This is an automated email from the ASF dual-hosted git repository. akhileshsingh pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push: new 8e7f1ca057 Added java regex flags for text matching and Example generator from r… (#3252) 8e7f1ca057 is described below commit 8e7f1ca0575403699765eb95edba526ad7fe845f Author: Sandeep Mishra <72914639+mishrasand...@users.noreply.github.com> AuthorDate: Mon May 9 12:32:25 2022 +0530 Added java regex flags for text matching and Example generator from r… (#3252) * Added java regex flags for text matching and Example generator from regex --- java/java.hints/nbproject/project.xml | 8 + .../modules/java/hints/jdk/Bundle.properties | 27 ++ .../java/hints/jdk/CheckRegexTopComponent.form | 228 +++++++++- .../java/hints/jdk/CheckRegexTopComponent.java | 305 ++++++++++++- .../java/hints/jdk/RegexExampleVisualPanel1.form | 131 ++++++ .../java/hints/jdk/RegexExampleVisualPanel1.java | 163 +++++++ .../java/hints/regex/parser/ExampleGenerator.java | 185 ++++++++ .../java/hints/regex/parser/RegExParser.java | 503 +++++++++++++++++++++ .../java/hints/regex/parser/RegexConstructs.java | 495 ++++++++++++++++++++ .../hints/regex/parser/ExampleGeneratorTest.java | 129 ++++++ 10 files changed, 2160 insertions(+), 14 deletions(-) diff --git a/java/java.hints/nbproject/project.xml b/java/java.hints/nbproject/project.xml index b21b337343..e3d88fab5c 100644 --- a/java/java.hints/nbproject/project.xml +++ b/java/java.hints/nbproject/project.xml @@ -78,6 +78,14 @@ <specification-version>1.40</specification-version> </run-dependency> </dependency> + <dependency> + <code-name-base>org.netbeans.api.templates</code-name-base> + <build-prerequisite/> + <compile-dependency/> + <run-dependency> + <specification-version>1.21</specification-version> + </run-dependency> + </dependency> <dependency> <code-name-base>org.netbeans.libs.javacapi</code-name-base> <build-prerequisite/> diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/Bundle.properties b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/Bundle.properties index 2298007fee..706e2338d7 100644 --- a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/Bundle.properties +++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/Bundle.properties @@ -120,3 +120,30 @@ CheckRegexTopComponent.strictCheckBox.text=Str&ict Check #{2}: PatternSyntaxException.getPattern() #{3}: PatternSyntaxException.getIndex() DN_RegExp=Invalid regular expression: {0} +CheckRegexTopComponent.flagsButton.text=Regex Flags +CheckRegexTopComponent.dotAllMenuItem.text=DOTALL +CheckRegexTopComponent.caseInsensitiveMenuItem.text=CASE_INSENSITIVE +CheckRegexTopComponent.unicodeCaseMenuItem.text=UNICODE_CASE +CheckRegexTopComponent.unicodeCharacterClassMenuItem.text=UNICODE_CHARACTER_CLASS +CheckRegexTopComponent.commentsMenuItem.text=COMMENTS +CheckRegexTopComponent.literalMenuItem.text=LITERAL +CheckRegexTopComponent.multilineMenuItem.text=MULTILINE +CheckRegexTopComponent.commentsMenuItem.toolTipText=Permits whitespace and comments in pattern +CheckRegexTopComponent.multilineMenuItem.toolTipText=^ and $ match just after or just before a line terminator +CheckRegexTopComponent.unicodeCaseMenuItem.toolTipText=Enables Unicode-aware case folding +CheckRegexTopComponent.caseInsensitiveMenuItem.toolTipText=Enables case-insensitive matching +CheckRegexTopComponent.dotAllMenuItem.toolTipText=. matches any character, including a line terminator +CheckRegexTopComponent.unicodeCharacterClassMenuItem.toolTipText=Enables the Unicode version of Predefined character classes and POSIX character classes +CheckRegexTopComponent.literalMenuItem.toolTipText=Enables literal parsing of the pattern +CheckRegexTopComponent.unixLinesMenuItem.text=UNIX_LINES +CheckRegexTopComponent.canonEqMenuItem.text=CANON_EQ +CheckRegexTopComponent.unixLinesMenuItem.toolTipText=Only the '\\n' line terminator is recognized in the behavior of ., ^, and $ +CheckRegexTopComponent.canonEqMenuItem.toolTipText=Enables canonical equivalence= +CheckRegexTopComponent.examplesButton.text=Generate Examples +CheckRegexTopComponent.regexLabel1.text=Re&gular Expression: +RegexExampleVisualPanel1.regExLabel.text=Regular Expression: +RegexExampleVisualPanel1.numberField.text=10 +RegexExampleVisualPanel1.NoLabel.text=No.: +RegexExampleVisualPanel1.regenerateButton.text=Regenerate +RegexExampleVisualPanel1.REGEX_EXAMPLES=Regex Examples +RegexExampleVisualPanel1.exampleTextArea.invalidText=Input valid number diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegexTopComponent.form b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegexTopComponent.form index 56e5790705..83a197126b 100644 --- a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegexTopComponent.form +++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegexTopComponent.form @@ -22,6 +22,191 @@ --> <Form version="1.9" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <NonVisualComponents> + <Container class="javax.swing.JPopupMenu" name="flagsPopupMenu"> + + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout"> + <Property name="useNullLayout" type="boolean" value="true"/> + </Layout> + <SubComponents> + <MenuItem class="javax.swing.JCheckBoxMenuItem" name="multilineMenuItem"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.multilineMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.multilineMenuItem.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="multilineMenuItemActionPerformed"/> + </Events> + </MenuItem> + <MenuItem class="javax.swing.JCheckBoxMenuItem" name="literalMenuItem"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.literalMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.literalMenuItem.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="literalMenuItemActionPerformed"/> + </Events> + </MenuItem> + <MenuItem class="javax.swing.JCheckBoxMenuItem" name="dotAllMenuItem"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.dotAllMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.dotAllMenuItem.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="dotAllMenuItemActionPerformed"/> + </Events> + </MenuItem> + <MenuItem class="javax.swing.JCheckBoxMenuItem" name="caseInsensitiveMenuItem"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.caseInsensitiveMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.caseInsensitiveMenuItem.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="caseInsensitiveMenuItemActionPerformed"/> + </Events> + </MenuItem> + <MenuItem class="javax.swing.JCheckBoxMenuItem" name="commentsMenuItem"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.commentsMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.commentsMenuItem.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="commentsMenuItemActionPerformed"/> + </Events> + </MenuItem> + <MenuItem class="javax.swing.JCheckBoxMenuItem" name="unixLinesMenuItem"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.unixLinesMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.unixLinesMenuItem.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unixLinesMenuItemActionPerformed"/> + </Events> + </MenuItem> + <MenuItem class="javax.swing.JCheckBoxMenuItem" name="canonEqMenuItem"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.canonEqMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.canonEqMenuItem.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="canonEqMenuItemActionPerformed"/> + </Events> + </MenuItem> + <MenuItem class="javax.swing.JCheckBoxMenuItem" name="unicodeCaseMenuItem"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.unicodeCaseMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.unicodeCaseMenuItem.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unicodeCaseMenuItemActionPerformed"/> + </Events> + </MenuItem> + <MenuItem class="javax.swing.JCheckBoxMenuItem" name="unicodeCharacterClassMenuItem"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.unicodeCharacterClassMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.unicodeCharacterClassMenuItem.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unicodeCharacterClassMenuItemActionPerformed"/> + </Events> + </MenuItem> + </SubComponents> + </Container> + <Container class="javax.swing.JFrame" name="examplesFrame"> + <Properties> + <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor"> + <Color id="Default Cursor"/> + </Property> + <Property name="locationByPlatform" type="boolean" value="true"/> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jScrollPane1" min="-2" pref="306" max="-2" attributes="0"/> + <Component id="regexLabel1" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace pref="15" max="32767" attributes="0"/> + <Component id="regexLabel1" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jScrollPane1" min="-2" pref="235" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JScrollPane" name="jScrollPane1"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTextArea" name="jTextArea1"> + <Properties> + <Property name="columns" type="int" value="20"/> + <Property name="rows" type="int" value="5"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JLabel" name="regexLabel1"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.regexLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + </NonVisualComponents> <AuxValues> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> @@ -44,30 +229,41 @@ <Component id="exampleLabel" alignment="0" min="-2" max="-2" attributes="0"/> <Group type="102" alignment="0" attributes="0"> <Component id="regexScrollPane" min="-2" pref="320" max="-2" attributes="0"/> - <EmptySpace type="unrelated" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="62" max="-2" attributes="0"/> <Component id="errorLabel" min="-2" max="-2" attributes="0"/> </Group> <Component id="exampleLayeredPane" alignment="0" min="-2" max="-2" attributes="0"/> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="1" max="-2" attributes="0"/> + <Component id="flagsButton" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="examplesButton" min="-2" max="-2" attributes="0"/> + </Group> </Group> - <EmptySpace pref="266" max="32767" attributes="0"/> + <EmptySpace min="-2" pref="266" max="-2" attributes="0"/> </Group> </Group> </DimensionLayout> <DimensionLayout dim="1"> <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" alignment="1" attributes="0"> - <EmptySpace max="32767" attributes="0"/> + <EmptySpace min="-2" max="-2" attributes="0"/> <Component id="regexLabel" min="-2" max="-2" attributes="0"/> - <EmptySpace max="-2" attributes="0"/> + <EmptySpace min="-2" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> <Component id="regexScrollPane" min="-2" pref="42" max="-2" attributes="0"/> <Component id="errorLabel" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace type="unrelated" max="-2" attributes="0"/> <Component id="exampleLabel" min="-2" max="-2" attributes="0"/> - <EmptySpace max="-2" attributes="0"/> + <EmptySpace min="-2" max="-2" attributes="0"/> <Component id="exampleLayeredPane" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="flagsButton" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="examplesButton" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="32767" attributes="0"/> </Group> </Group> </DimensionLayout> @@ -141,7 +337,7 @@ <Component id="strictCheckBox" min="-2" max="-2" attributes="0"/> <Component id="iconLabel" min="-2" pref="18" max="-2" attributes="0"/> </Group> - <EmptySpace max="32767" attributes="0"/> + <EmptySpace pref="9" max="32767" attributes="0"/> </Group> <Group type="103" rootIndex="1" groupAlignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0"> @@ -194,5 +390,25 @@ </Container> <Component class="javax.swing.JLabel" name="errorLabel"> </Component> + <Component class="javax.swing.JButton" name="flagsButton"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.flagsButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="flagsButtonActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="examplesButton"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="CheckRegexTopComponent.examplesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="examplesButtonActionPerformed"/> + </Events> + </Component> </SubComponents> </Form> diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegexTopComponent.java b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegexTopComponent.java index 98652b0d6b..7c034254ae 100644 --- a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegexTopComponent.java +++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegexTopComponent.java @@ -19,6 +19,7 @@ package org.netbeans.modules.java.hints.jdk; import java.awt.Color; +import java.util.ArrayList; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -67,7 +68,8 @@ public final class CheckRegexTopComponent extends TopComponent { private static CheckRegexTopComponent instance; private static final String PREFERRED_ID = "CheckRegexTopComponent"; private static boolean isStrictMatch; - + private static int Flags = 0; + public CheckRegexTopComponent() { initComponents(); setName(Bundle.CTL_CheckRegexTopComponent()); @@ -83,6 +85,20 @@ public final class CheckRegexTopComponent extends TopComponent { // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { + flagsPopupMenu = new javax.swing.JPopupMenu(); + multilineMenuItem = new javax.swing.JCheckBoxMenuItem(); + literalMenuItem = new javax.swing.JCheckBoxMenuItem(); + dotAllMenuItem = new javax.swing.JCheckBoxMenuItem(); + caseInsensitiveMenuItem = new javax.swing.JCheckBoxMenuItem(); + commentsMenuItem = new javax.swing.JCheckBoxMenuItem(); + unixLinesMenuItem = new javax.swing.JCheckBoxMenuItem(); + canonEqMenuItem = new javax.swing.JCheckBoxMenuItem(); + unicodeCaseMenuItem = new javax.swing.JCheckBoxMenuItem(); + unicodeCharacterClassMenuItem = new javax.swing.JCheckBoxMenuItem(); + examplesFrame = new javax.swing.JFrame(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + regexLabel1 = new javax.swing.JLabel(); regexLabel = new javax.swing.JLabel(); regexScrollPane = new javax.swing.JScrollPane(); regexTextArea = new javax.swing.JTextArea(); @@ -93,6 +109,119 @@ public final class CheckRegexTopComponent extends TopComponent { exampleTextArea = new javax.swing.JTextArea(); strictCheckBox = new javax.swing.JCheckBox(); errorLabel = new javax.swing.JLabel(); + flagsButton = new javax.swing.JButton(); + examplesButton = new javax.swing.JButton(); + + org.openide.awt.Mnemonics.setLocalizedText(multilineMenuItem, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.multilineMenuItem.text")); // NOI18N + multilineMenuItem.setToolTipText(org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.multilineMenuItem.toolTipText")); // NOI18N + multilineMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + multilineMenuItemActionPerformed(evt); + } + }); + flagsPopupMenu.add(multilineMenuItem); + + org.openide.awt.Mnemonics.setLocalizedText(literalMenuItem, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.literalMenuItem.text")); // NOI18N + literalMenuItem.setToolTipText(org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.literalMenuItem.toolTipText")); // NOI18N + literalMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + literalMenuItemActionPerformed(evt); + } + }); + flagsPopupMenu.add(literalMenuItem); + + org.openide.awt.Mnemonics.setLocalizedText(dotAllMenuItem, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.dotAllMenuItem.text")); // NOI18N + dotAllMenuItem.setToolTipText(org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.dotAllMenuItem.toolTipText")); // NOI18N + dotAllMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + dotAllMenuItemActionPerformed(evt); + } + }); + flagsPopupMenu.add(dotAllMenuItem); + + org.openide.awt.Mnemonics.setLocalizedText(caseInsensitiveMenuItem, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.caseInsensitiveMenuItem.text")); // NOI18N + caseInsensitiveMenuItem.setToolTipText(org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.caseInsensitiveMenuItem.toolTipText")); // NOI18N + caseInsensitiveMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + caseInsensitiveMenuItemActionPerformed(evt); + } + }); + flagsPopupMenu.add(caseInsensitiveMenuItem); + + org.openide.awt.Mnemonics.setLocalizedText(commentsMenuItem, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.commentsMenuItem.text")); // NOI18N + commentsMenuItem.setToolTipText(org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.commentsMenuItem.toolTipText")); // NOI18N + commentsMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + commentsMenuItemActionPerformed(evt); + } + }); + flagsPopupMenu.add(commentsMenuItem); + + org.openide.awt.Mnemonics.setLocalizedText(unixLinesMenuItem, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.unixLinesMenuItem.text")); // NOI18N + unixLinesMenuItem.setToolTipText(org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.unixLinesMenuItem.toolTipText")); // NOI18N + unixLinesMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + unixLinesMenuItemActionPerformed(evt); + } + }); + flagsPopupMenu.add(unixLinesMenuItem); + + org.openide.awt.Mnemonics.setLocalizedText(canonEqMenuItem, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.canonEqMenuItem.text")); // NOI18N + canonEqMenuItem.setToolTipText(org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.canonEqMenuItem.toolTipText")); // NOI18N + canonEqMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + canonEqMenuItemActionPerformed(evt); + } + }); + flagsPopupMenu.add(canonEqMenuItem); + + org.openide.awt.Mnemonics.setLocalizedText(unicodeCaseMenuItem, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.unicodeCaseMenuItem.text")); // NOI18N + unicodeCaseMenuItem.setToolTipText(org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.unicodeCaseMenuItem.toolTipText")); // NOI18N + unicodeCaseMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + unicodeCaseMenuItemActionPerformed(evt); + } + }); + flagsPopupMenu.add(unicodeCaseMenuItem); + + org.openide.awt.Mnemonics.setLocalizedText(unicodeCharacterClassMenuItem, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.unicodeCharacterClassMenuItem.text")); // NOI18N + unicodeCharacterClassMenuItem.setToolTipText(org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.unicodeCharacterClassMenuItem.toolTipText")); // NOI18N + unicodeCharacterClassMenuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + unicodeCharacterClassMenuItemActionPerformed(evt); + } + }); + flagsPopupMenu.add(unicodeCharacterClassMenuItem); + + examplesFrame.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); + examplesFrame.setLocationByPlatform(true); + + jTextArea1.setColumns(20); + jTextArea1.setRows(5); + jScrollPane1.setViewportView(jTextArea1); + + org.openide.awt.Mnemonics.setLocalizedText(regexLabel1, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.regexLabel1.text")); // NOI18N + + javax.swing.GroupLayout examplesFrameLayout = new javax.swing.GroupLayout(examplesFrame.getContentPane()); + examplesFrame.getContentPane().setLayout(examplesFrameLayout); + examplesFrameLayout.setHorizontalGroup( + examplesFrameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(examplesFrameLayout.createSequentialGroup() + .addContainerGap() + .addGroup(examplesFrameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 306, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(regexLabel1)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + examplesFrameLayout.setVerticalGroup( + examplesFrameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, examplesFrameLayout.createSequentialGroup() + .addContainerGap(15, Short.MAX_VALUE) + .addComponent(regexLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 235, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); org.openide.awt.Mnemonics.setLocalizedText(regexLabel, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.regexLabel.text")); // NOI18N @@ -163,6 +292,20 @@ public final class CheckRegexTopComponent extends TopComponent { .addGap(0, 6, Short.MAX_VALUE))) ); + org.openide.awt.Mnemonics.setLocalizedText(flagsButton, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.flagsButton.text")); // NOI18N + flagsButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + flagsButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(examplesButton, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.examplesButton.text")); // NOI18N + examplesButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + examplesButtonActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -174,15 +317,20 @@ public final class CheckRegexTopComponent extends TopComponent { .addComponent(exampleLabel) .addGroup(layout.createSequentialGroup() .addComponent(regexScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGap(62, 62, 62) .addComponent(errorLabel)) - .addComponent(exampleLayeredPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap(266, Short.MAX_VALUE)) + .addComponent(exampleLayeredPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addGap(1, 1, 1) + .addComponent(flagsButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(examplesButton))) + .addGap(266, 266, 266)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap() .addComponent(regexLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -192,7 +340,11 @@ public final class CheckRegexTopComponent extends TopComponent { .addComponent(exampleLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(exampleLayeredPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap()) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(flagsButton) + .addComponent(examplesButton)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// </editor-fold>//GEN-END:initComponents @@ -211,17 +363,144 @@ public final class CheckRegexTopComponent extends TopComponent { matchPattern(); }//GEN-LAST:event_strictCheckBoxItemStateChanged + private void flagsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_flagsButtonActionPerformed + if(flagsPopupMenu.isVisible()){ + flagsPopupMenu.setVisible(false); + }else{ + flagsPopupMenu.show(flagsButton, 0, (int) (0 - flagsPopupMenu.getPreferredSize().getHeight())); + } + }//GEN-LAST:event_flagsButtonActionPerformed + + private void caseInsensitiveMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_caseInsensitiveMenuItemActionPerformed + if(caseInsensitiveMenuItem.isSelected()){ + Flags |= Pattern.CASE_INSENSITIVE; + }else{ + Flags &= ~Pattern.CASE_INSENSITIVE; + } + flagsPopupMenu.show(flagsButton, 0, 0 - flagsPopupMenu.getHeight()); + matchPattern(); + }//GEN-LAST:event_caseInsensitiveMenuItemActionPerformed + + private void multilineMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_multilineMenuItemActionPerformed + if(multilineMenuItem.isSelected()){ + Flags |= Pattern.MULTILINE; + }else{ + Flags &= ~Pattern.MULTILINE; + } + flagsPopupMenu.show(flagsButton, 0, 0 - flagsPopupMenu.getHeight()); + matchPattern(); + }//GEN-LAST:event_multilineMenuItemActionPerformed + + private void dotAllMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dotAllMenuItemActionPerformed + if(dotAllMenuItem.isSelected()){ + Flags |= Pattern.DOTALL; + }else{ + Flags &= ~Pattern.DOTALL; + } + flagsPopupMenu.show(flagsButton, 0, 0 - flagsPopupMenu.getHeight()); + matchPattern(); + }//GEN-LAST:event_dotAllMenuItemActionPerformed + + private void unicodeCaseMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unicodeCaseMenuItemActionPerformed + if(unicodeCaseMenuItem.isSelected()){ + Flags |= Pattern.UNICODE_CASE; + }else{ + Flags &= ~Pattern.UNICODE_CASE; + } + flagsPopupMenu.show(flagsButton, 0, 0 - flagsPopupMenu.getHeight()); + matchPattern(); + }//GEN-LAST:event_unicodeCaseMenuItemActionPerformed + + private void unicodeCharacterClassMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unicodeCharacterClassMenuItemActionPerformed + if(unicodeCharacterClassMenuItem.isSelected()){ + Flags |= Pattern.UNICODE_CHARACTER_CLASS; + }else{ + Flags &= ~Pattern.UNICODE_CHARACTER_CLASS; + } + flagsPopupMenu.show(flagsButton, 0, 0 - flagsPopupMenu.getHeight()); + matchPattern(); + }//GEN-LAST:event_unicodeCharacterClassMenuItemActionPerformed + + private void commentsMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_commentsMenuItemActionPerformed + if(commentsMenuItem.isSelected()){ + Flags |= Pattern.COMMENTS; + }else{ + Flags &= ~Pattern.COMMENTS; + } + flagsPopupMenu.show(flagsButton, 0, 0 - flagsPopupMenu.getHeight()); + matchPattern(); + }//GEN-LAST:event_commentsMenuItemActionPerformed + + private void literalMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_literalMenuItemActionPerformed + if(literalMenuItem.isSelected()){ + Flags |= Pattern.LITERAL; + }else{ + Flags &= ~Pattern.LITERAL; + } + flagsPopupMenu.show(flagsButton, 0, 0 - flagsPopupMenu.getHeight()); + matchPattern(); + }//GEN-LAST:event_literalMenuItemActionPerformed + + private void unixLinesMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unixLinesMenuItemActionPerformed + if(unixLinesMenuItem.isSelected()){ + Flags |= Pattern.UNIX_LINES; + }else{ + Flags &= ~Pattern.UNIX_LINES; + } + flagsPopupMenu.show(flagsButton, 0, 0 - flagsPopupMenu.getHeight()); + matchPattern(); + }//GEN-LAST:event_unixLinesMenuItemActionPerformed + + private void canonEqMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_canonEqMenuItemActionPerformed + if(canonEqMenuItem.isSelected()){ + Flags |= Pattern.CANON_EQ; + }else{ + Flags &= ~Pattern.CANON_EQ; + } + flagsPopupMenu.show(flagsButton, 0, 0 - flagsPopupMenu.getHeight()); + matchPattern(); + }//GEN-LAST:event_canonEqMenuItemActionPerformed + + private void examplesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_examplesButtonActionPerformed + + Pattern p; + try { + p = Pattern.compile(regexTextArea.getText()); + } catch (PatternSyntaxException pse) { + errorLabel.setText(Bundle.CheckRegexTopComponent_label_error(pse.getDescription())); + return; + } + RegexExampleAction regexExampleAction = new RegexExampleAction(); + regexExampleAction.actionPerformed(evt); + }//GEN-LAST:event_examplesButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBoxMenuItem canonEqMenuItem; + private javax.swing.JCheckBoxMenuItem caseInsensitiveMenuItem; + private javax.swing.JCheckBoxMenuItem commentsMenuItem; + private javax.swing.JCheckBoxMenuItem dotAllMenuItem; private javax.swing.JLabel errorLabel; private javax.swing.JLabel exampleLabel; private javax.swing.JLayeredPane exampleLayeredPane; private javax.swing.JScrollPane exampleScrollPane; private javax.swing.JTextArea exampleTextArea; + private javax.swing.JButton examplesButton; + private javax.swing.JFrame examplesFrame; + private javax.swing.JButton flagsButton; + private javax.swing.JPopupMenu flagsPopupMenu; private javax.swing.JLabel iconLabel; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JCheckBoxMenuItem literalMenuItem; + private javax.swing.JCheckBoxMenuItem multilineMenuItem; private javax.swing.JLabel regexLabel; + private javax.swing.JLabel regexLabel1; private javax.swing.JScrollPane regexScrollPane; private javax.swing.JTextArea regexTextArea; private javax.swing.JCheckBox strictCheckBox; + private javax.swing.JCheckBoxMenuItem unicodeCaseMenuItem; + private javax.swing.JCheckBoxMenuItem unicodeCharacterClassMenuItem; + private javax.swing.JCheckBoxMenuItem unixLinesMenuItem; // End of variables declaration//GEN-END:variables @Override public void componentOpened() { @@ -299,7 +578,7 @@ public final class CheckRegexTopComponent extends TopComponent { } Pattern p; try { - p = Pattern.compile(regexTextArea.getText()); + p = Pattern.compile(regexTextArea.getText(), Flags); } catch (PatternSyntaxException pse) { errorLabel.setText(Bundle.CheckRegexTopComponent_label_error(pse.getDescription())); return; @@ -322,7 +601,12 @@ public final class CheckRegexTopComponent extends TopComponent { while (m.find()) { int start = m.start(); int end = m.end(); - DefaultHighlighter.DefaultHighlightPainter defaultHighlightPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.GREEN); + DefaultHighlighter.DefaultHighlightPainter defaultHighlightPainter; + if(count%2 == 0){ + defaultHighlightPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.GREEN); + }else{ + defaultHighlightPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW); + } highlighter.addHighlight(start, end, defaultHighlightPainter); count++; } @@ -338,4 +622,9 @@ public final class CheckRegexTopComponent extends TopComponent { } } } + + public String getExpression(){ + return regexTextArea.getText(); + } + } diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/RegexExampleVisualPanel1.form b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/RegexExampleVisualPanel1.form new file mode 100644 index 0000000000..8b207b0f8a --- /dev/null +++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/RegexExampleVisualPanel1.form @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!-- + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +--> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="exampleScrollPane" pref="380" max="32767" attributes="0"/> + <Group type="102" attributes="0"> + <Component id="regExLabel" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="expressionLabel" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + <Component id="NoLabel" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="numberField" min="-2" pref="42" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="regenerateButton" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="32767" attributes="0"/> + </Group> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="regExLabel" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="expressionLabel" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="numberField" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="NoLabel" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Component id="exampleScrollPane" min="-2" pref="207" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="regenerateButton" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="regExLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="RegexExampleVisualPanel1.regExLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Container class="javax.swing.JScrollPane" name="exampleScrollPane"> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTextArea" name="exampleTextArea"> + <Properties> + <Property name="columns" type="int" value="20"/> + <Property name="rows" type="int" value="5"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JLabel" name="expressionLabel"> + </Component> + <Component class="javax.swing.JTextField" name="numberField"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="RegexExampleVisualPanel1.numberField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="NoLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="RegexExampleVisualPanel1.NoLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="regenerateButton"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="org/netbeans/modules/java/hints/jdk/Bundle.properties" key="RegexExampleVisualPanel1.regenerateButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="regenerateButtonActionPerformed"/> + </Events> + </Component> + </SubComponents> +</Form> diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/RegexExampleVisualPanel1.java b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/RegexExampleVisualPanel1.java new file mode 100644 index 0000000000..d661631911 --- /dev/null +++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/RegexExampleVisualPanel1.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.hints.jdk; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import javax.swing.JPanel; +import org.netbeans.modules.java.hints.regex.parser.ExampleGenerator; +import org.netbeans.modules.java.hints.regex.parser.RegExParser; +import org.netbeans.modules.java.hints.regex.parser.RegexConstructs.RegEx; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.util.NbBundle; + +public final class RegexExampleVisualPanel1 extends JPanel { + + private final String expression; + /** + * Creates new form RegexExampleVisualPanel1 + */ + public RegexExampleVisualPanel1() { + initComponents(); + this.expression = CheckRegexTopComponent.findInstance().getExpression(); + expressionLabel.setText(expression); + exampleTextArea.setText(getExamples()); + } + + @Override + public String getName() { + return NbBundle.getMessage(RegexExampleVisualPanel1.class, "RegexExampleVisualPanel1.REGEX_EXAMPLES"); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + regExLabel = new javax.swing.JLabel(); + exampleScrollPane = new javax.swing.JScrollPane(); + exampleTextArea = new javax.swing.JTextArea(); + expressionLabel = new javax.swing.JLabel(); + numberField = new javax.swing.JTextField(); + NoLabel = new javax.swing.JLabel(); + regenerateButton = new javax.swing.JButton(); + + org.openide.awt.Mnemonics.setLocalizedText(regExLabel, org.openide.util.NbBundle.getMessage(RegexExampleVisualPanel1.class, "RegexExampleVisualPanel1.regExLabel.text")); // NOI18N + + exampleTextArea.setColumns(20); + exampleTextArea.setRows(5); + exampleScrollPane.setViewportView(exampleTextArea); + + numberField.setText(org.openide.util.NbBundle.getMessage(RegexExampleVisualPanel1.class, "RegexExampleVisualPanel1.numberField.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(NoLabel, org.openide.util.NbBundle.getMessage(RegexExampleVisualPanel1.class, "RegexExampleVisualPanel1.NoLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(regenerateButton, org.openide.util.NbBundle.getMessage(RegexExampleVisualPanel1.class, "RegexExampleVisualPanel1.regenerateButton.text")); // NOI18N + regenerateButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + regenerateButtonActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(exampleScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(regExLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(expressionLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(NoLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(numberField, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(regenerateButton) + .addGap(0, 0, Short.MAX_VALUE))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(regExLabel) + .addComponent(expressionLabel) + .addComponent(numberField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(NoLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(exampleScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 207, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(regenerateButton) + .addContainerGap()) + ); + }// </editor-fold>//GEN-END:initComponents + + private void regenerateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_regenerateButtonActionPerformed + exampleTextArea.setText(getExamples()); + }//GEN-LAST:event_regenerateButtonActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel NoLabel; + private javax.swing.JScrollPane exampleScrollPane; + private javax.swing.JTextArea exampleTextArea; + private javax.swing.JLabel expressionLabel; + private javax.swing.JTextField numberField; + private javax.swing.JLabel regExLabel; + private javax.swing.JButton regenerateButton; + // End of variables declaration//GEN-END:variables + + private String getExamples() { + RegExParser r = new RegExParser(expression); + RegEx p = r.parse(); + ExampleGenerator eg = new ExampleGenerator(p); + int noFieldVal = 0; + try{ + noFieldVal = Integer.parseInt(numberField.getText()); + }catch(NumberFormatException e){ + return NbBundle.getMessage(RegexExampleVisualPanel1.class, "RegexExampleVisualPanel1.exampleTextArea.invalidText"); + } + ArrayList<String> generate = eg.generate(noFieldVal); + StringBuilder sb = new StringBuilder(); + generate.forEach(example -> { + sb.append(example + "\n"); + }); + return sb.toString(); + } +} + +final class RegexExampleAction implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { + DialogDescriptor dd = new DialogDescriptor(new RegexExampleVisualPanel1(), NbBundle.getMessage(RegexExampleVisualPanel1.class, "RegexExampleVisualPanel1.REGEX_EXAMPLES")); + dd.setOptions(new Object[0]); + DialogDisplayer.getDefault().notify(dd); + } + +} diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/regex/parser/ExampleGenerator.java b/java/java.hints/src/org/netbeans/modules/java/hints/regex/parser/ExampleGenerator.java new file mode 100644 index 0000000000..2234ab74d3 --- /dev/null +++ b/java/java.hints/src/org/netbeans/modules/java/hints/regex/parser/ExampleGenerator.java @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.hints.regex.parser; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import org.netbeans.modules.java.hints.regex.parser.RegexConstructs.*; + +/** + * + * @author sandeemi + */ +public class ExampleGenerator { + + private final RegEx regEx; + private Random rnd; + + private boolean DOT_ALL = false; + + public ExampleGenerator(RegEx regEx) { + this.rnd = new Random(); + this.regEx = regEx; + } + + public void setDOT_ALL(boolean DOT_ALL) { + this.DOT_ALL = DOT_ALL; + } + + public ArrayList<String> generate(int n) { + + ArrayList<String> result = new ArrayList<>(); + + for (int i = 0; i < n; i++) { + StringBuilder sb = new StringBuilder(); + buildExample(regEx, sb); + result.add(sb.toString()); + } + + return result; + } + + private void buildExample(RegEx regex, StringBuilder sb) { + + if (regex instanceof Blank) { + return; + } + + if (regex instanceof Primitive) { + sb.append(((Primitive) regex).getCh()); + return; + } + + if (regex instanceof Repetition) { + int nextInt = rnd.nextInt(10); + RegEx internal = ((Repetition) regex).getInternal(); + + for (int i = 0; i < nextInt; i++) { + buildExample(internal, sb); + } + + return; + } + + if (regex instanceof OneOrMore) { + int nextInt = rnd.nextInt(10) + 1; + + RegEx internal = ((OneOrMore) regex).getInternal(); + + for (int i = 0; i < nextInt; i++) { + buildExample(internal, sb); + } + + return; + } + + if (regex instanceof Group) { + if (regex instanceof SpecialConstructGroup) { + GroupType groupType = ((SpecialConstructGroup) regex).getGroupType(); + if (groupType.isNegative() || groupType.isPositive()) { + return; + } + } + RegEx internal = ((Group) regex).getInternal(); + buildExample(internal, sb); + + return; + } + if (regex instanceof Optional) { + boolean nextBool = rnd.nextBoolean(); + + RegEx internal = ((Optional) regex).getInternal(); + + if (nextBool) { + buildExample(internal, sb); + } + + return; + } + + if (regex instanceof GreedyBound) { + + RegEx internal = ((GreedyBound) regex).getInternal(); + int min = ((GreedyBound) regex).getMin(); + boolean maxPresent = ((GreedyBound) regex).isMaxPresent(); + int max = ((GreedyBound) regex).getMax(); + + int nextInt; + + if (maxPresent) { + nextInt = rnd.nextInt(max - min + 1) + min; + } else { + nextInt = rnd.nextInt(10) + min; + } + + for (int i = 0; i < nextInt; i++) { + buildExample(internal, sb); + } + + return; + } + + if (regex instanceof AnyChar) { + int nextInt = rnd.nextInt(126 - 32) + 32; + sb.append((char) nextInt); + return; + } + + if (regex instanceof CharClass) { + + CharClass charClass = (CharClass) regex; + List<Character> charClassList = charClass.isNegation() ? charClass.getNegationList() : charClass.getAllChar(); + + int n = charClassList.size(); + sb.append(charClassList.get(rnd.nextInt(n))); + + return; + } + + if (regex instanceof Range) { + char from = ((Range) regex).getFrom(); + char to = ((Range) regex).getTo(); + + int length = to - from; + + sb.append((char) (from + rnd.nextInt(length + 1))); + + return; + } + + if (regex instanceof Choice) { + ArrayList<RegEx> choices = ((Choice) regex).getChoice(); + + int n = choices.size(); + + buildExample(choices.get(rnd.nextInt(n)), sb); + + return; + } + + if (regex instanceof Concat) { + ArrayList<RegEx> concatNodes = ((Concat) regex).getConcat(); + concatNodes.forEach((RegEx nodes) -> { + buildExample(nodes, sb); + }); + + } + } +} diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/regex/parser/RegExParser.java b/java/java.hints/src/org/netbeans/modules/java/hints/regex/parser/RegExParser.java new file mode 100644 index 0000000000..d139e1116a --- /dev/null +++ b/java/java.hints/src/org/netbeans/modules/java/hints/regex/parser/RegExParser.java @@ -0,0 +1,503 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.hints.regex.parser; + +import java.util.ArrayList; +import java.util.HashMap; +import org.netbeans.modules.java.hints.regex.parser.RegexConstructs.*; + +/** + * + * @author sandeemi + */ +public class RegExParser { + + private final String input; + private int pos; + private int groupNo; + private HashMap<Integer, RegEx> groupMap; + private HashMap<String, RegEx> namedGroupMap; + + private static final char OR = '|'; + private static final char AND = '&'; + private static final char NOT = '^'; + private static final char DASH = '-'; + private static final char DOT = '.'; + private static final char ESCAPE = '\\'; + private static final char COMMA = ','; + private static final char EQUAL = '='; + private static final char EXCLM = '!'; + private static final char COLON = ':'; + + private static final char OPT = '?'; + private static final char STAR = '*'; + private static final char PLUS = '+'; + private static final char PAR_OP = '('; + private static final char PAR_CL = ')'; + private static final char CLASS_OP = '['; + private static final char CLASS_CL = ']'; + private static final char BRAC_OP = '{'; + private static final char BRAC_CL = '}'; + private static final char NAMED_OP = '<'; + private static final char NAMED_CL = '>'; + private static final char QUOT_OP = 'Q'; + private static final char QUOT_CL = 'E'; + + private static final char[] DIGIT = "0123456789".toCharArray(); + private static final char[] BOUNDRY_MATCHERS = "bBAGzZ".toCharArray(); + private static final char[] OPEN_LOOP = new char[]{OPT, STAR, PLUS, BRAC_OP}; + + public RegExParser(String input) { + this.input = input; + this.pos = 0; + this.groupNo = 0; + this.groupMap = new HashMap<>(); + this.namedGroupMap = new HashMap<>(); + } + + public RegEx parse() { + if (input == null) { + return null; + } else if (input.isEmpty()) { + return new Blank(); + } else { + return regex(); + } + } + + /*Recursive descent parsing internals*/ + private char peek() { + return input.charAt(pos); + } + + private void eat(char c) { + if (peek() == c) { + pos++; + } else { + throw new RuntimeException("Expected: " + c + "; got: " + peek()); + } + } + + private char next() { + char c = peek(); + eat(c); + return c; + } + + private char nextChar() { + return input.charAt(pos + 1); + } + + private boolean nextIn(char[] arr) { + if (more()) { + char c = peek(); + for (char a : arr) { + if (c == a) { + return true; + } + } + } + return false; + } + + private boolean more() { + return pos < input.length(); + } + + /*Regular expression term types*/ + private RegEx regex() { + RegEx term = term(); + + while (more() && peek() == OR) { + eat('|'); + term = Choice.subChoices(term, term()); + } + return term; + } + + private RegEx term() { + RegEx factor = new Blank(); + + while (more() && peek() != PAR_CL && peek() != '|') { + RegEx nextFactor = factor(); + factor = new Sequence(factor, nextFactor); + } + + factor = flatten(factor); + + return factor; + } + + private RegEx factor() { + + RegEx base = base(); + + while (more() && nextIn(OPEN_LOOP)) { + switch (peek()) { + case PLUS: + base = new OneOrMore(base); + eat(PLUS); + if (more() && peek() == OPT) { + eat(OPT); + } else if (more() && peek() == PLUS) { + eat(PLUS); + } + break; + case STAR: + base = new Repetition(base); + eat(STAR); + if (more() && peek() == OPT) { + eat(OPT); + } else if (more() && peek() == PLUS) { + eat(PLUS); + } + break; + case OPT: + base = new Optional(base); + eat(OPT); + // TODO: case for z?+Z + if (more() && peek() == OPT) { + eat(OPT); + } else if (more() && peek() == PLUS) { + eat(PLUS); + } + break; + case BRAC_OP: + base = greedyBound(base); + break; + } + } + + return base; + } + + private RegEx base() { + + switch (peek()) { + case CLASS_OP: + eat(CLASS_OP); + RegEx c = charClass(false); + eat(CLASS_CL); + return c; + case PAR_OP: + return handleParenthesis(); + case '\\': + return handleEscape(); + case DOT: + eat(DOT); + return new AnyChar(); + case '^': + eat('^'); + return new Blank(); + case '$': + eat('$'); + return new Blank(); + default: + return new Primitive(next()); + } + } + + private RegEx handleParenthesis() { + eat(PAR_OP); + groupNo++; + RegEx r = null; + if (peek() == OPT) { + next(); + StringBuilder name = new StringBuilder(); + switch (peek()) { + case NAMED_OP: + next(); + switch (peek()) { + case EQUAL: + next(); + r = new SpecialConstructGroup(GroupType.POSITIVE_LOOKBEHIND, regex()); + break; + case EXCLM: + next(); + r = new SpecialConstructGroup(GroupType.NEGATIVE_LOOKBEHIND, regex()); + break; + default: + while (peek() != NAMED_CL) { + name.append(next()); + } + next(); + r = new NamedGroup(groupNo, name.toString(), regex(), this); + break; + } + break; + case EQUAL: + next(); + r = new SpecialConstructGroup(GroupType.POSITIVE_LOOKAHEAD, regex()); + break; + case EXCLM: + next(); + r = new SpecialConstructGroup(GroupType.NEGATIVE_LOOKAHEAD, regex()); + break; + case COLON: + next(); + groupNo--; + r = new SpecialConstructGroup(GroupType.NON_CAPTURE_GROUP, regex()); + break; + + } + } else { + r = new CapturingGroup(groupNo, regex(), this); + } + eat(PAR_CL); + return r; + } + + private RegEx handleEscape() throws NumberFormatException, RuntimeException { + eat('\\'); + if (nextIn(BOUNDRY_MATCHERS)) { + next(); + return new Blank(); + } + if (nextIn(DIGIT)) { + String number = ""; + int n = getGroupMap().size(); + while (more() && nextIn(DIGIT)) { + int parseInt = Integer.parseInt(String.valueOf(number + peek())); + if (parseInt <= n) { + number += next(); + } else { + break; + } + } + int num = Integer.parseInt(String.valueOf(number)); + + return getGroupMap().get(num); + } + char esc = next(); + if (esc == QUOT_OP) { + return handleQuotations(); + } + if (esc == 'p' && peek() == BRAC_OP) { + StringBuilder s = new StringBuilder(); + eat(BRAC_OP); + while (peek() != BRAC_CL) { + s.append(next()); + } + eat(BRAC_CL); + return handlePosix(s.toString()); + } + if (esc == 'k' && peek() == NAMED_OP) { + StringBuilder s = new StringBuilder(); + next(); + while (peek() != NAMED_CL) { + s.append(next()); + } + next(); + return getNamedGroupMap().get(s.toString()); + } + if (SpecialChar.sChars.containsKey(esc)) { + return SpecialChar.sChars.get(esc); + } + return new Primitive(esc); + } + + private RegEx handleQuotations() throws RuntimeException { + ArrayList<RegEx> quotations = new ArrayList<>(); + while (!(peek() == ESCAPE && nextChar() == QUOT_CL)) { + char quot = next(); + quotations.add(new Primitive(quot)); + } + eat(ESCAPE); + eat(QUOT_CL); + if (nextIn(OPEN_LOOP)) { + throw new RuntimeException(this.input + " token not Quantifiable at " + (pos - 1)); + } + return new Concat(quotations); + } + + private RegEx charClass(boolean isIntersection) { + CharClass charClass; + if (peek() == NOT) { + eat(NOT); + charClass = new CharClass(true, isIntersection); + } else { + charClass = new CharClass(false, isIntersection); + } + if (peek() == CLASS_CL || peek() == DASH) { + charClass.addToClass(new Primitive(peek())); + next(); + } + while (peek() != CLASS_CL) { + if (nextChar() == DASH) { + char from = peek(); + eat(from); + next(); + if (peek() == CLASS_CL) { + charClass.addToClass(new Primitive(DASH)); + } else { + char to = peek(); + eat(to); + charClass.addToClass(new Range(from, to)); + } + } else if (peek() == CLASS_OP) { + eat(CLASS_OP); + RegEx c = charClass(false); + eat(CLASS_CL); + charClass.addToClass(c); + } else if (peek() == AND) { + next(); + if (peek() == AND) { + next(); + if (peek() == CLASS_OP) { + eat(CLASS_OP); + RegEx c = charClass(true); + eat(CLASS_CL); + charClass.addToClass(c); + } + } else { + charClass.addToClass(new Primitive(AND)); + } + }else if(peek() == ESCAPE && SpecialChar.sChars.containsKey(nextChar())) { + next(); + charClass.addToClass(SpecialChar.sChars.get(peek())); + next(); + }else{ + charClass.addToClass(new Primitive(next())); + } + } + return charClass; + } + + private RegEx greedyBound(RegEx base) { + GreedyBound gr = new GreedyBound(base); + eat(BRAC_OP); + String number = ""; + while (peek() != BRAC_CL && peek() != COMMA) { + number += next(); + } + int min = Integer.parseInt(String.valueOf(number)); + gr.setMin(min); + + int max; + if (peek() == COMMA) { + eat(COMMA); + if (nextIn(DIGIT)) { + number = ""; + while (peek() != BRAC_CL) { + number += next(); + } + gr.setMaxPresent(true); + max = Integer.parseInt(String.valueOf(number)); + gr.setMax(max); + } else { + gr.setMaxPresent(false); + } + } else if (peek() == BRAC_CL) { + gr.setMaxPresent(true); + gr.setMax(min); + } + + eat(BRAC_CL); + return gr; + } + + private RegEx flatten(RegEx factor) { + ArrayList<RegEx> flattenedList = new ArrayList<>(); + Sequence factorCopy = (Sequence) factor; + + while (factorCopy.firstSeq != null && (factorCopy.firstSeq instanceof Sequence)) { + flattenedList.add(0, factorCopy.secondSeq); + factorCopy = (Sequence) factorCopy.firstSeq; + } + + flattenedList.add(0, factorCopy.secondSeq); + + if (flattenedList.size() == 1) { + return flattenedList.get(0); + } + + return new Concat(flattenedList); + } + + private Posix handlePosix(String posix) { + Posix posixClass; + + posixClass = new Posix(posix, false, false); + switch (posix) { + case "Lower": + posixClass.addToClass(new Range('a', 'z')); + break; + case "Upper": + posixClass.addToClass(new Range('A', 'Z')); + break; + case "ASCII": + posixClass.addToClass(new Range((char) 0x00, (char) 0x7F)); + break; + case "Alpha": + posixClass.addToClass(handlePosix("Lower"), handlePosix("Upper")); + break; + case "Digit": + posixClass.addToClass(new Range('0', '9')); + break; + case "Alnum": + posixClass.addToClass(handlePosix("Alpha"), handlePosix("Digit")); + break; + case "Punct": + String punctuations = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; + for (int i = 0; i < punctuations.length(); i++) { + posixClass.addToClass(new Primitive(punctuations.charAt(i))); + } + break; + case "Graph": + posixClass.addToClass(handlePosix("Alnum"), handlePosix("Punct")); + break; + case "Print": + posixClass.addToClass(handlePosix("Graph"), new Primitive((char) 0x20)); + break; + case "Blank": + posixClass.addToClass(new Primitive(' '), new Primitive('\t')); + break; + case "Cntrl": + posixClass.addToClass(new Range((char) 0x00, (char) 0x1F), new Primitive((char) 0x7F)); + break; + case "XDigit": + posixClass.addToClass(new Range('0', '9'), new Range('a', 'f'), new Range('A', 'F')); + break; + case "Space": + posixClass.addToClass(new Primitive(' '), new Primitive('\t'), new Primitive('\n'), new Primitive((char) 0x0B), new Primitive('\f'), new Primitive('\r')); + break; + default: + break; + } + + return posixClass; + } + + public HashMap<String, RegEx> getNamedGroupMap() { + return namedGroupMap; + } + + public void setNamedGroupMap(HashMap<String, RegEx> namedGroupMap) { + this.namedGroupMap = namedGroupMap; + } + + public HashMap<Integer, RegEx> getGroupMap() { + return groupMap; + } + + public void setGroupMap(HashMap<Integer, RegEx> groupMap) { + this.groupMap = groupMap; + } + +} diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/regex/parser/RegexConstructs.java b/java/java.hints/src/org/netbeans/modules/java/hints/regex/parser/RegexConstructs.java new file mode 100644 index 0000000000..4498121337 --- /dev/null +++ b/java/java.hints/src/org/netbeans/modules/java/hints/regex/parser/RegexConstructs.java @@ -0,0 +1,495 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.hints.regex.parser; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +/** + * + * @author SANDEEMI + */ +public class RegexConstructs { + + public static abstract class RegEx { + + } + + public static class AnyChar extends RegEx { + + } + + public static class Blank extends RegEx { + + } + + public static class CharClass extends RegEx { + + private final boolean isNegation; + private final boolean isIntersection; + private final List<RegEx> charClassList; + private final List<Character> allChars; + private final List<Character> negationChars; + + public CharClass(boolean isNegation, boolean isIntersection) { + this.isNegation = isNegation; + this.isIntersection = isIntersection; + this.charClassList = new ArrayList<>(); + allChars = new ArrayList<>(); + negationChars = new ArrayList<>(); + for (int c = 32; c <= 126; c++) { + negationChars.add((char) c); + } + } + + public void addToClass(RegEx... nextChar) { + for (RegEx next : nextChar) { + this.charClassList.add(next); + if (next instanceof Primitive) { + allChars.add((Character) ((Primitive) next).getCh()); + negationChars.remove((Character) ((Primitive) next).getCh()); + } else if (next instanceof Range) { + char from = ((Range) next).getFrom(); + char to = ((Range) next).getTo(); + for (char c = from; c <= to; c++) { + allChars.add((Character) c); + negationChars.remove((Character) c); + } + } else if (next instanceof CharClass) { + CharClass charClass = (CharClass) next; + if (charClass.isIntersection) { + handleIntersection(charClass); + } else { + handleUnion(charClass); + } + } + } + } + + private void handleUnion(CharClass charClass) { + List<Character> allCharInt; + if (charClass.isNegation()) { + allCharInt = charClass.getNegationList(); + } else { + allCharInt = charClass.getAllChar(); + } + ListIterator<Character> listIterator = allCharInt.listIterator(); + while (listIterator.hasNext()) { + Character c = listIterator.next(); + if (!allChars.contains(c)) { + allChars.add(c); + negationChars.remove(c); + } + } + } + + private void handleIntersection(CharClass charClass) { + + List<Character> allCharInt; + if (charClass.isNegation()) { + allCharInt = charClass.getNegationList(); + } else { + allCharInt = charClass.getAllChar(); + } + ListIterator<Character> listIterator = allChars.listIterator(); + while (listIterator.hasNext()) { + Character c = listIterator.next(); + if (!allCharInt.contains(c)) { + listIterator.remove(); + negationChars.add(c); + } + } + } + + public boolean isNegation() { + return isNegation; + } + + public List<RegEx> getCharClassList() { + return charClassList; + } + + public List<Character> getAllChar() { + return allChars; + } + + public List<Character> getNegationList() { + return negationChars; + } + } + + public static class CapturingGroup extends Group { + + private int groupNo; + + public CapturingGroup(int groupNo, RegEx regex, RegExParser regExParser) { + super(regex); + this.groupNo = groupNo; + regExParser.getGroupMap().put(groupNo, regex); + } + + public int getGroupNo() { + return groupNo; + } + + public void setGroupNo(int groupNo) { + this.groupNo = groupNo; + } + } + + public static class Choice extends RegEx { + + private ArrayList<RegEx> choice; + + public Choice(ArrayList<RegEx> choice) { + this.choice = choice; + } + + public static Choice subChoices(RegEx... regex) { + ArrayList<RegEx> alternatives = new ArrayList<>(); + for (RegEx r : regex) { + if (r instanceof Choice) { + alternatives.addAll(((Choice) r).getChoice()); + } else { + alternatives.add(r); + } + } + + return new Choice(alternatives); + } + + public ArrayList<RegEx> getChoice() { + return choice; + } + + public void setChoice(ArrayList<RegEx> choice) { + this.choice = choice; + } + } + + public static class Concat extends RegEx { + + private ArrayList<RegEx> concat; + + public ArrayList<RegEx> getConcat() { + return concat; + } + + public void setConcat(ArrayList<RegEx> concat) { + this.concat = concat; + } + + public Concat(ArrayList<RegEx> seq) { + this.concat = seq; + } + } + + public static class GreedyBound extends RegEx { + + private final RegEx internal; + private int min; + private boolean maxPresent; + private int max; + + public boolean isMaxPresent() { + return maxPresent; + } + + public void setMaxPresent(boolean maxPresent) { + this.maxPresent = maxPresent; + } + + public GreedyBound(RegEx base) { + this.internal = base; + } + + public int getMin() { + return min; + } + + public void setMin(int min) { + this.min = min; + } + + public int getMax() { + return max; + } + + public void setMax(int max) { + this.max = max; + } + + public RegEx getInternal() { + return internal; + } + + } + + public static class Group extends RegEx { + + private RegEx internal; + + public Group(RegEx regex) { + this.internal = regex; + } + + public RegEx getInternal() { + return internal; + } + + public void setInternal(RegEx internal) { + this.internal = internal; + } + + } + + public static enum GroupType { + POSITIVE_LOOKAHEAD, + NEGATIVE_LOOKAHEAD, + POSITIVE_LOOKBEHIND, + NEGATIVE_LOOKBEHIND, + CAPTURE_GROUP, + NON_CAPTURE_GROUP; + + public boolean isNegative() { + return this == NEGATIVE_LOOKAHEAD || this == NEGATIVE_LOOKBEHIND; + } + + public boolean isPositive() { + return this == POSITIVE_LOOKAHEAD || this == POSITIVE_LOOKBEHIND; + } + } + + public static class NamedGroup extends CapturingGroup { + + private String groupName; + + public NamedGroup(int groupNo, String groupName, RegEx regex, RegExParser regExParser) { + super(groupNo, regex, regExParser); + this.groupName = groupName; + regExParser.getNamedGroupMap().put(groupName, regex); + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + } + + public static class OneOrMore extends RegEx { + + private RegEx internal; + + public OneOrMore(RegEx base) { + this.internal = base; + } + + public RegEx getInternal() { + return internal; + } + } + + public static class Optional extends RegEx { + + private RegEx internal; + + public Optional(RegEx base) { + this.internal = base; + } + + public RegEx getInternal() { + return internal; + } + + } + + public static class Posix extends CharClass { + + private String posixName; + + public Posix(String posixName, boolean isNegation, boolean isIntersection) { + super(isNegation, isIntersection); + this.posixName = posixName; + } + + public String getPosixName() { + return posixName; + } + + } + + public static class Primitive extends RegEx { + + private char ch; + + public Primitive(char esc) { + this.ch = esc; + } + + public char getCh() { + return ch; + } + } + + public static class Range extends RegEx { + + private char from; + private char to; + + public Range(char from, char to) { + this.from = from; + this.to = to; + } + + public char getFrom() { + return from; + } + + public char getTo() { + return to; + } + + } + + public static class Repetition extends RegEx { + + private RegEx internal; + + public Repetition(RegEx internal) { + this.internal = internal; + } + + public RegEx getInternal() { + return internal; + } + + } + + public static class Sequence extends RegEx { + + public final RegEx firstSeq; + public final RegEx secondSeq; + + public Sequence(RegEx first, RegEx second) { + this.firstSeq = first; + this.secondSeq = second; + } + + } + + public static class SpecialChar { + + public static Map<Character, RegEx> sChars = buildHashMap('t', new Primitive('\t'), + 'n', new Primitive('\n'), + 'r', new Primitive('\r'), + 'f', new Primitive('\f'), + '\\', new Primitive('\\'), + 's', buildWhiteSpaceEscape(false), + 'd', buildDigitEscape(false), + 'w', buildAlphaNumericEscape(false), + 'S', buildWhiteSpaceEscape(true), + 'D', buildDigitEscape(true), + 'W', buildAlphaNumericEscape(true) + ); + + public static RegEx buildWhiteSpaceEscape(boolean negation) { + + CharClass charClass = new CharClass(negation, false); + + charClass.addToClass(new Primitive('\t'), + new Primitive('\n'), + new Primitive('\f'), + new Primitive('\r'), + new Primitive(' ')); + return charClass; + } + + public static RegEx buildDigitEscape(boolean negation) { + CharClass charClass = new CharClass(negation, false); + charClass.addToClass(new Range('0', '9')); + return charClass; + } + + public static RegEx buildAlphaNumericEscape(boolean negation) { + CharClass charClass = new CharClass(false, false); + charClass.addToClass(new Range('1', '9'), + new Range('a', 'z'), + new Range('A', 'Z'), + new Primitive('_')); + + return charClass; + } + + public static HashMap<Character, RegEx> buildHashMap(Object... data) { + HashMap<Character, RegEx> result = new HashMap<Character, RegEx>(); + + if (data.length % 2 != 0) { + throw new IllegalArgumentException("Odd number of arguments"); + } + + Character key = null; + Integer step = -1; + + for (Object value : data) { + step++; + switch (step % 2) { + case 0: + if (value == null) { + throw new IllegalArgumentException("Null key value"); + } + key = (Character) value; + continue; + case 1: + result.put(key, (RegEx) value); + break; + } + } + + return result; + } + + } + + public static class SpecialConstructGroup extends Group { + + private GroupType groupType; + + public GroupType getGroupType() { + return groupType; + } + + public void setGroupType(GroupType groupType) { + this.groupType = groupType; + } + + public SpecialConstructGroup(GroupType groupType, RegEx regex) { + super(regex); + this.groupType = groupType; + } + + } + +} diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/regex/parser/ExampleGeneratorTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/regex/parser/ExampleGeneratorTest.java new file mode 100644 index 0000000000..ca5e938824 --- /dev/null +++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/regex/parser/ExampleGeneratorTest.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.hints.regex.parser; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; +import org.netbeans.modules.java.hints.regex.parser.RegexConstructs.RegEx; + +/** + * + * @author SANDEEMI + */ +public class ExampleGeneratorTest { + + public ExampleGeneratorTest() { + } + + @BeforeClass + public static void setUpClass() { + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of generate method, of class ExampleGenerator. + */ + @Test + public void testGenerate() throws IOException { + + int n = 50; + + List<String> regexps = Arrays.asList("z*", + "z+", + "z?", + "z{1}", + "z{1,2}", + "z{1,}", + "z?+t", + "a|b", + "ab", + "[^a-z]", + "\\d\\w\\s", + "\n\r\f\\\\", + "a|(b|c|d)|e", + "z*[1-9d-f](ab|bc|cd)\\d+", + "a*|b{2,4}", + "[\\s]", + "\\d+(\\.\\d\\d)?", + "rege(x(es)?|xps?)", + "[2-9]|[12]\\d|3[0-6]", + "([0-2][1-9]|3[01])-(0[1-9]|1[12])-(\\d{4})", + "[a-z_1-9]|\\Qabcd!@#$%^&*()1234[]?'\\E|(ab)+.", + "[a-z[q-s]]", + "[a-z1-9&&[^a-z]]", + "\\p{Lower}\\p{Punct}\\p{Graph}", + "^[a-z0-9_-]{3,15}$", + "(ab(cd(ef)))\\2\\3{2}\\1", + "(?<new>ab)(ba)\\k<new>{2}\\2\\1+", + "(ab{2,8}[^abcd])", + "ab(?!ef)", + "(ab(cd(?:ef(gh))))\\3", + "(?<!ab)cd", + "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$", + "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$", + "([^\\s]+(\\.(jpg|png|gif|bmp))$)", + "(1[012]|[1-9]):[0-5][0-9](\\s)?(am|pm)", + "([01]?[0-9]|2[0-3]):[0-5][0-9]", + "(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/((19|20)\\d\\d)", + "<(\"[^\"]*\"|'[^']*'|[^'\">])*>", + "<a([^>]+)>(.+?)</a>", + "\\s*href\\s*=\\s*(\"([^\"]*\")|'[^']*'|([^'\">\\s]+));"); + + for (String regex : regexps) { + if (regex.charAt(0) != '#') { + Pattern pat = Pattern.compile(regex, 0); + Matcher m; + RegExParser r = new RegExParser(regex); + RegEx p = r.parse(); + assertNotNull(p); + + ExampleGenerator eg = new ExampleGenerator(p); + ArrayList<String> generate = eg.generate(n); + assertNotNull(generate); + assertEquals(generate.size(), n); + + for (String examples : generate) { + m = pat.matcher(examples); + assertTrue(m.matches()); + } + } + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists