You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by sk...@apache.org on 2021/07/20 08:46:40 UTC
[netbeans] branch master updated: Added Check regular expression
window and hint. Modified Malformed Regexp Hint.
This is an automated email from the ASF dual-hosted git repository.
skygo 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 0eff92f Added Check regular expression window and hint. Modified Malformed Regexp Hint.
new ea9ebc6 Merge pull request #2953 from mishrasandeep/netbeans-5561
0eff92f is described below
commit 0eff92f3770931017f6557cd1d84cd71b6fbe9ea
Author: mishrasandeep <sa...@oracle.com>
AuthorDate: Thu May 13 10:40:12 2021 +0530
Added Check regular expression window and hint. Modified Malformed Regexp Hint.
---
java/java.hints/licenseinfo.xml | 3 +
java/java.hints/nbproject/project.xml | 9 +
.../modules/java/hints/bugs/Bundle.properties | 8 -
.../netbeans/modules/java/hints/bugs/Regexp.java | 172 -----------
.../modules/java/hints/jdk/Bundle.properties | 9 +
.../modules/java/hints/jdk/CheckRegex.java | 235 ++++++++++++++
.../java/hints/jdk/CheckRegexTopComponent.form | 198 ++++++++++++
.../java/hints/jdk/CheckRegexTopComponent.java | 341 +++++++++++++++++++++
.../netbeans/modules/java/hints/jdk/Regexp.java | 185 +++++++++++
.../modules/java/hints/resources/half-match.png | Bin 0 -> 654 bytes
.../modules/java/hints/resources/match.png | Bin 0 -> 495 bytes
.../modules/java/hints/resources/no-match.png | Bin 0 -> 339 bytes
.../modules/java/hints/jdk/CheckRegexTest.java | 54 ++++
.../java/hints/{bugs => jdk}/RegexpTest.java | 6 +-
14 files changed, 1037 insertions(+), 183 deletions(-)
diff --git a/java/java.hints/licenseinfo.xml b/java/java.hints/licenseinfo.xml
index f12e06e..5f02fc5 100644
--- a/java/java.hints/licenseinfo.xml
+++ b/java/java.hints/licenseinfo.xml
@@ -27,6 +27,9 @@
<file>src/org/netbeans/modules/java/hints/analyzer/ui/warning-glyph.gif</file>
<file>src/org/netbeans/modules/java/hints/analyzer/ui/suggestion.png</file>
<file>src/org/netbeans/modules/java/hints/analyzer/ui/refactoringpreview.png</file>
+ <file>src/org/netbeans/modules/java/hints/resources/match.png</file>
+ <file>src/org/netbeans/modules/java/hints/resources/half-match.png</file>
+ <file>src/org/netbeans/modules/java/hints/resources/no-match.png</file>
<license ref="Apache-2.0-ASF" />
<comment type="COMMENT_UNSUPPORTED" />
</fileset>
diff --git a/java/java.hints/nbproject/project.xml b/java/java.hints/nbproject/project.xml
index a94078f..ce13a87 100644
--- a/java/java.hints/nbproject/project.xml
+++ b/java/java.hints/nbproject/project.xml
@@ -358,6 +358,15 @@
</run-dependency>
</dependency>
<dependency>
+ <code-name-base>org.netbeans.modules.settings</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>1.61</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
<code-name-base>org.netbeans.spi.editor.hints</code-name-base>
<build-prerequisite/>
<compile-dependency/>
diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Bundle.properties b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Bundle.properties
index e225ec7..aca26e7 100644
--- a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Bundle.properties
+++ b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Bundle.properties
@@ -21,18 +21,10 @@ DN_AnnotationsNotRuntime_isAnnotation={0} does not have runtime Retention, the r
DN_AnnotationsNotRuntime_getAnnotation={0} does not have runtime Retention, the result will always be null
# {0} - the name of the annotation
DN_AnnotationsNotRuntime_instanceof={0} does not have runtime Retention, the condition will always be false
-#{0}: PatternSyntaxException.getDescription()
-#{1}: PatternSyntaxException.getMessage()
-#{2}: PatternSyntaxException.getPattern()
-#{3}: PatternSyntaxException.getIndex()
-DN_RegExp=Invalid regular expression: {0}
DN_org.netbeans.modules.java.hints.bugs.AnnotationsNotRuntime=Annotations without runtime Retention
DESC_org.netbeans.modules.java.hints.bugs.AnnotationsNotRuntime=Warns about reflective access to annotations with CLASS or SOURCE retentions
-DN_org.netbeans.modules.java.hints.bugs.Regexp=Malformed regular expression
-DESC_org.netbeans.modules.java.hints.bugs.Regexp=Warns about malformed regular expressions
-
DN_org.netbeans.modules.java.hints.bugs.Tiny.stringReplaceAllDot=String.replaceAll(".", )
DESC_org.netbeans.modules.java.hints.bugs.Tiny.stringReplaceAllDot=Finds occurrences of calls to String.replaceAll(".", $target), which would replace all characters of the source string with $target.
ERR_string-replace-all-dot=Call to String.replaceAll(".", $target) is probably undesired
diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Regexp.java b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Regexp.java
deleted file mode 100644
index 4be2cd9..0000000
--- a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Regexp.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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.bugs;
-
-import com.sun.source.tree.BinaryTree;
-import com.sun.source.tree.IdentifierTree;
-import com.sun.source.tree.LiteralTree;
-import com.sun.source.tree.MemberSelectTree;
-import com.sun.source.tree.MethodInvocationTree;
-import com.sun.source.tree.Tree.Kind;
-import com.sun.source.util.TreePath;
-import org.netbeans.api.java.source.support.ErrorAwareTreePathScanner;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.VariableElement;
-import org.netbeans.spi.java.hints.ConstraintVariableType;
-import org.netbeans.spi.java.hints.Hint;
-import org.netbeans.spi.java.hints.TriggerPattern;
-import org.netbeans.spi.java.hints.TriggerPatterns;
-import org.netbeans.spi.java.hints.HintContext;
-import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
-import org.netbeans.spi.editor.hints.ErrorDescription;
-import org.netbeans.spi.java.hints.Hint.Options;
-import org.openide.util.NbBundle;
-
-/**
- *
- * @author lahvac
- */
-@Hint(displayName = "#DN_org.netbeans.modules.java.hints.bugs.Regexp", description = "#DESC_org.netbeans.modules.java.hints.bugs.Regexp", category="bugs", suppressWarnings={"MalformedRegexp", "", "MalformedRegex"}, options=Options.QUERY)
-public class Regexp {
-
- @TriggerPatterns({
- @TriggerPattern(value="java.util.regex.Pattern.compile($pattern)",
- constraints={
- @ConstraintVariableType(variable="$pattern", type="java.lang.String")
- }),
- @TriggerPattern(value="java.util.regex.Pattern.compile($pattern, $flags)",
- constraints={
- @ConstraintVariableType(variable="$pattern", type="java.lang.String"),
- @ConstraintVariableType(variable="$flags", type="int")
- }),
- @TriggerPattern(value="java.util.regex.Pattern.matches($pattern, $text)",
- constraints={
- @ConstraintVariableType(variable="$pattern", type="java.lang.String"),
- @ConstraintVariableType(variable="$text", type="java.lang.CharSequence")
- }),
- @TriggerPattern(value="$str.split($pattern)",
- constraints={
- @ConstraintVariableType(variable="$str", type="java.lang.String"),
- @ConstraintVariableType(variable="$pattern", type="java.lang.String")
- }),
- @TriggerPattern(value="$str.split($pattern, $limit)",
- constraints={
- @ConstraintVariableType(variable="$str", type="java.lang.String"),
- @ConstraintVariableType(variable="$pattern", type="java.lang.String"),
- @ConstraintVariableType(variable="$limit", type="int")
- }),
- @TriggerPattern(value="$str.matches($pattern)",
- constraints={
- @ConstraintVariableType(variable="$str", type="java.lang.String"),
- @ConstraintVariableType(variable="$pattern", type="java.lang.String")
- }),
- @TriggerPattern(value="$str.replaceFirst($pattern, $repl)",
- constraints={
- @ConstraintVariableType(variable="$str", type="java.lang.String"),
- @ConstraintVariableType(variable="$pattern", type="java.lang.String"),
- @ConstraintVariableType(variable="$repl", type="java.lang.String")
- }),
- @TriggerPattern(value="$str.replaceAll($pattern, $repl)",
- constraints={
- @ConstraintVariableType(variable="$str", type="java.lang.String"),
- @ConstraintVariableType(variable="$pattern", type="java.lang.String"),
- @ConstraintVariableType(variable="$repl", type="java.lang.String")
- })
- })
- public static ErrorDescription hint(final HintContext ctx) {
- final StringBuilder regexp = new StringBuilder();
- final boolean[] accept = {true};
- TreePath pattern = ctx.getVariables().get("$pattern");
- new ErrorAwareTreePathScanner<Void, Void>() {
- @Override
- public Void visitLiteral(LiteralTree node, Void p) {
- if (node.getValue() instanceof String) {
- regexp.append(node.getValue());
- return null;
- }
- accept[0] = false;
- return null;
- }
- @Override
- public Void visitIdentifier(IdentifierTree node, Void p) {
- Element el = ctx.getInfo().getTrees().getElement(getCurrentPath());
-
- if (el != null && el.getKind() == ElementKind.FIELD) {
- VariableElement ve = (VariableElement) el;
-
- if (ve.getConstantValue() instanceof String) {
- regexp.append(ve.getConstantValue());
- return null;
- }
- }
- accept[0] = false;
- return null;
- }
- @Override
- public Void visitMemberSelect(MemberSelectTree node, Void p) {
- Element el = ctx.getInfo().getTrees().getElement(getCurrentPath());
-
- if (el != null && el.getKind() == ElementKind.FIELD) {
- VariableElement ve = (VariableElement) el;
-
- if (ve.getConstantValue() instanceof String) {
- regexp.append(ve.getConstantValue());
- return null;
- }
- }
- accept[0] = false;
- return null;
- }
- @Override
- public Void visitBinary(BinaryTree node, Void p) {
- if (node.getKind() != Kind.PLUS) {
- return super.visitBinary(node, p);
- }
- accept[0] = false;
- return null;
- }
- @Override
- public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
- accept[0] = false;
- return null;
- }
- }.scan(pattern, null);
-
- if (!accept[0] || regexp.length() == 0) {
- return null;
- }
-
- try {
- Pattern.compile(regexp.toString());
- return null;
- } catch (PatternSyntaxException pse) {
- String displayName = NbBundle.getMessage(Regexp.class, "DN_RegExp", new Object[] {
- pse.getDescription(),
- pse.getMessage(),
- pse.getPattern(),
- pse.getIndex(),
- });
- return ErrorDescriptionFactory.forTree(ctx, pattern, displayName);
- }
- }
-}
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 d595271..2298007 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
@@ -111,3 +111,12 @@ DESC_AnnoProcessor_ObsoleteSupportedSource=If the project's source level is grea
another useless warning during compilation. <p/>\
It is recommended to return at least the current project's source level. \
For future compatibility, consider to return <b>SourceVersion.latest()</b>; most Processors are not affected by future language changes.
+CheckRegexTopComponent.regexLabel.text=Re&gular Expression:
+CheckRegexTopComponent.exampleLabel.text=E&xample:
+CheckRegexTopComponent.strictCheckBox.text=Str&ict Check
+
+#{0}: PatternSyntaxException.getDescription()
+#{1}: PatternSyntaxException.getMessage()
+#{2}: PatternSyntaxException.getPattern()
+#{3}: PatternSyntaxException.getIndex()
+DN_RegExp=Invalid regular expression: {0}
diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegex.java b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegex.java
new file mode 100644
index 0000000..5d6179d
--- /dev/null
+++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegex.java
@@ -0,0 +1,235 @@
+/*
+ * 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 com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.BlockTree;
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.ExpressionStatementTree;
+import com.sun.source.tree.ExpressionTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.LiteralTree;
+import com.sun.source.tree.StatementTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.Tree.Kind;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.tree.JCTree.JCBlock;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import java.util.List;
+import javax.lang.model.element.Name;
+import javax.swing.SwingUtilities;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.java.hints.ConstraintVariableType;
+import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.java.hints.Hint;
+import org.netbeans.spi.java.hints.HintContext;
+import org.netbeans.spi.java.hints.JavaFix;
+import org.netbeans.spi.java.hints.TriggerPattern;
+import org.netbeans.spi.java.hints.TriggerPatterns;
+import org.openide.util.NbBundle.Messages;
+
+@Hint(displayName = "#DN_CheckRegex", description = "#DESC_CheckRegex", category = "general")
+@Messages({
+ "DN_CheckRegex=Check Regular Expression",
+ "DESC_CheckRegex=Check Regular Expression"
+})
+public class CheckRegex {
+
+ @TriggerPatterns({
+ @TriggerPattern(value = "java.util.regex.Pattern.compile($pattern)",
+ constraints = {
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String")
+ }),
+ @TriggerPattern(value = "java.util.regex.Pattern.compile($pattern, $flags)",
+ constraints = {
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$flags", type = "int")
+ }),
+ @TriggerPattern(value = "java.util.regex.Pattern.matches($pattern, $text)",
+ constraints = {
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$text", type = "java.lang.CharSequence")
+ }),
+ @TriggerPattern(value = "$str.split($pattern)",
+ constraints = {
+ @ConstraintVariableType(variable = "$str", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String")
+ }),
+ @TriggerPattern(value = "$str.split($pattern, $limit)",
+ constraints = {
+ @ConstraintVariableType(variable = "$str", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$limit", type = "int")
+ }),
+ @TriggerPattern(value = "$str.matches($pattern)",
+ constraints = {
+ @ConstraintVariableType(variable = "$str", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String")
+ }),
+ @TriggerPattern(value = "$str.replaceFirst($pattern, $repl)",
+ constraints = {
+ @ConstraintVariableType(variable = "$str", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$repl", type = "java.lang.String")
+ }),
+ @TriggerPattern(value = "$str.replaceAll($pattern, $repl)",
+ constraints = {
+ @ConstraintVariableType(variable = "$str", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$repl", type = "java.lang.String")
+ })
+ })
+ @CheckForNull
+ @Messages({"ERR_CheckRegex=Check regular expression",
+ "# {0} - invalidRegex",
+ "ERR_InvalidRegex=Invalid regular expression: {0}"})
+ public static ErrorDescription computeWarning(HintContext ctx) {
+
+ String originalString = null;
+ Tree leaf = ctx.getVariables().get("$pattern").getLeaf(); // NOI18N
+
+ if (leaf.getKind() == Kind.STRING_LITERAL) {
+ originalString = (String) ((LiteralTree) leaf).getValue();
+ } else if (leaf.getKind() == Kind.IDENTIFIER) {
+ originalString = identifierSearch(leaf, ctx);
+ }
+
+ return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.ERR_CheckRegex(), new FixImpl(ctx.getInfo(), ctx.getPath(), originalString).toEditorFix());
+ }
+
+ @CheckForNull
+ public static String identifierSearch(Tree leaf, HintContext ctx) {
+ String originalString = null;
+ Name name = ((IdentifierTree) leaf).getName();
+ TreePath tp = ctx.getPath().getParentPath();
+
+ Tree statement = tp.getLeaf();
+ BlockTree bt = null;
+ while (originalString == null && tp != null) {
+ if (tp.getLeaf() instanceof JCBlock) {
+ originalString = identifierBlockSearch(tp.getLeaf(), name, statement, bt);
+ bt = (BlockTree) tp.getLeaf();
+ } else if (tp.getLeaf() instanceof JCClassDecl) {
+ originalString = identifierClassSearch(tp.getLeaf(), name);
+ }
+ tp = tp.getParentPath();
+ }
+ return originalString;
+ }
+
+ @CheckForNull
+ private static String identifierBlockSearch(Tree leaf, Name name, Tree statement, BlockTree blocktree) {
+ String res = null;
+ try {
+ BlockTree bt = (BlockTree) leaf;
+ List<? extends StatementTree> statements = bt.getStatements();
+ for (int i = 0; i < statements.size(); i++) {
+ StatementTree st = statements.get(i);
+ if (st.equals(statement)) {
+ return res;
+ }
+ if (st.equals(blocktree)) {
+ return res;
+ }
+ if (st instanceof VariableTree) {
+ VariableTree vt = (VariableTree) st;
+ if (vt.getType().toString().equalsIgnoreCase("String") && vt.getName().equals(name)) { // NOI18N
+ LiteralTree lt = (LiteralTree) vt.getInitializer();
+ res = (String) lt.getValue();
+ }
+ } else if (st instanceof ExpressionStatementTree) {
+ ExpressionStatementTree est = (ExpressionStatementTree) st;
+ ExpressionTree et = est.getExpression();
+ if (et instanceof AssignmentTree) {
+ AssignmentTree at = (AssignmentTree) et;
+ if (at.getVariable().toString().equals(name.toString())) {
+ res = (String) ((LiteralTree) ((AssignmentTree) est.getExpression()).getExpression()).getValue();
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ return res;
+ }
+
+ @CheckForNull
+ private static String identifierClassSearch(Tree leaf, Name name) {
+ String res = null;
+ try {
+ ClassTree ct = (ClassTree) leaf;
+ List<? extends Tree> members = ct.getMembers();
+ for (int i = 0; i < members.size(); i++) {
+ Tree t = members.get(i);
+ if (t instanceof VariableTree) {
+ VariableTree vt = (VariableTree) t;
+ if (vt.getType().toString().equalsIgnoreCase("String") && vt.getName().equals(name)) { // NOI18N
+ LiteralTree lt = (LiteralTree) vt.getInitializer();
+ res = lt != null ? (String) lt.getValue() : null;
+ }
+ } else if (t instanceof ExpressionStatementTree) {
+ ExpressionStatementTree est = (ExpressionStatementTree) t;
+ ExpressionTree et = est.getExpression();
+ if (et instanceof AssignmentTree) {
+ AssignmentTree at = (AssignmentTree) et;
+ if (at.getVariable().toString().equals(name.toString())) {
+ res = (String) ((LiteralTree) ((AssignmentTree) est.getExpression()).getExpression()).getValue();
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ return res;
+ }
+
+ private static final class FixImpl extends JavaFix {
+
+ private final String origString;
+
+ private FixImpl(CompilationInfo info, TreePath path, String origString) {
+ super(info, path);
+ this.origString = origString;
+ }
+
+ @Override
+ protected String getText() {
+ return Bundle.DESC_CheckRegex();
+ }
+
+ @Override
+ protected void performRewrite(TransformationContext tc) throws Exception {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ CheckRegexTopComponent win = CheckRegexTopComponent.findInstance();
+ win.open();
+ win.requestActive();
+ win.setData(origString);
+ }
+ });
+ }
+
+ }
+}
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
new file mode 100644
index 0000000..56e5790
--- /dev/null
+++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegexTopComponent.form
@@ -0,0 +1,198 @@
+<?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.9" 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="regexLabel" alignment="0" min="-2" max="-2" attributes="0"/>
+ <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"/>
+ <Component id="errorLabel" min="-2" max="-2" attributes="0"/>
+ </Group>
+ <Component id="exampleLayeredPane" alignment="0" min="-2" max="-2" attributes="0"/>
+ </Group>
+ <EmptySpace pref="266" 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 max="32767" attributes="0"/>
+ <Component id="regexLabel" min="-2" max="-2" attributes="0"/>
+ <EmptySpace 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"/>
+ <Component id="exampleLayeredPane" 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="CheckRegexTopComponent.regexLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
+ </Property>
+ </Properties>
+ </Component>
+ <Container class="javax.swing.JScrollPane" name="regexScrollPane">
+ <Properties>
+ <Property name="verticalScrollBarPolicy" type="int" value="21"/>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[164, 74]"/>
+ </Property>
+ </Properties>
+ <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="regexTextArea">
+ <Properties>
+ <Property name="columns" type="int" value="20"/>
+ <Property name="rows" type="int" value="5"/>
+ <Property name="focusAccelerator" type="char" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+ <Connection code="'g'" type="code"/>
+ </Property>
+ </Properties>
+ <Events>
+ <EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="regexTextAreaKeyReleased"/>
+ </Events>
+ </Component>
+ </SubComponents>
+ </Container>
+ <Component class="javax.swing.JLabel" name="exampleLabel">
+ <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.exampleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
+ </Property>
+ </Properties>
+ </Component>
+ <Container class="javax.swing.JLayeredPane" name="exampleLayeredPane">
+
+ <Layout>
+ <DimensionLayout dim="0">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" alignment="1" attributes="0">
+ <EmptySpace pref="297" max="32767" attributes="0"/>
+ <Component id="iconLabel" min="-2" pref="17" max="-2" attributes="0"/>
+ <EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
+ <Component id="strictCheckBox" min="-2" max="-2" attributes="0"/>
+ </Group>
+ <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
+ <Group type="102" alignment="0" attributes="0">
+ <Component id="exampleScrollPane" min="-2" pref="320" max="-2" attributes="0"/>
+ <EmptySpace min="0" pref="15" max="32767" attributes="0"/>
+ </Group>
+ </Group>
+ </Group>
+ </DimensionLayout>
+ <DimensionLayout dim="1">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" alignment="0" attributes="0">
+ <EmptySpace min="-2" pref="21" max="-2" attributes="0"/>
+ <Group type="103" groupAlignment="0" attributes="0">
+ <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"/>
+ </Group>
+ <Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
+ <Group type="102" alignment="0" attributes="0">
+ <Component id="exampleScrollPane" min="-2" pref="44" max="-2" attributes="0"/>
+ <EmptySpace min="0" pref="6" max="32767" attributes="0"/>
+ </Group>
+ </Group>
+ </Group>
+ </DimensionLayout>
+ </Layout>
+ <SubComponents>
+ <Component class="javax.swing.JLabel" name="iconLabel">
+ </Component>
+ <Container class="javax.swing.JScrollPane" name="exampleScrollPane">
+ <Properties>
+ <Property name="verticalScrollBarPolicy" type="int" value="21"/>
+ <Property name="opaque" type="boolean" value="false"/>
+ </Properties>
+ <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"/>
+ <Property name="focusAccelerator" type="char" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+ <Connection code="'x'" type="code"/>
+ </Property>
+ </Properties>
+ <Events>
+ <EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="exampleTextAreaKeyReleased"/>
+ </Events>
+ </Component>
+ </SubComponents>
+ </Container>
+ <Component class="javax.swing.JCheckBox" name="strictCheckBox">
+ <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.strictCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
+ </Property>
+ </Properties>
+ <Events>
+ <EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="strictCheckBoxItemStateChanged"/>
+ </Events>
+ </Component>
+ </SubComponents>
+ </Container>
+ <Component class="javax.swing.JLabel" name="errorLabel">
+ </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
new file mode 100644
index 0000000..98652b0
--- /dev/null
+++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/CheckRegexTopComponent.java
@@ -0,0 +1,341 @@
+/*
+ * 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.Color;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultHighlighter;
+import javax.swing.text.Highlighter;
+import org.netbeans.api.settings.ConvertAsProperties;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+import org.openide.windows.TopComponent;
+import org.openide.util.NbBundle.Messages;
+import org.openide.windows.Mode;
+import org.openide.windows.WindowManager;
+
+/**
+ * Top component which displays something.
+ */
+@ConvertAsProperties(
+ dtd = "-//org.netbeans.modules.java.hints.jdk//CheckRegex//EN",
+ autostore = false
+)
+@TopComponent.Description(
+ preferredID = "CheckRegexTopComponent",
+ persistenceType = TopComponent.PERSISTENCE_ALWAYS
+)
+@TopComponent.Registration(mode = "output", openAtStartup = false, position = 13000)
+@ActionID(category = "Window", id = "org.netbeans.modules.java.hints.jdk.CheckRegexTopComponent")
+@ActionReferences({
+ @ActionReference(name = "Check Regex", path = "Menu/Window", position = 950),
+ @ActionReference(path = "Shortcuts", name = "C-8")})
+@TopComponent.OpenActionRegistration(
+ displayName = "#CTL_CheckRegexAction",
+ preferredID = "CheckRegexTopComponent"
+)
+@Messages({
+ "CTL_CheckRegexAction=Check Regex",
+ "CTL_CheckRegexTopComponent=Check Regular Expression",
+ "HINT_CheckRegexTopComponent=This is a Check Regex window"
+})
+public final class CheckRegexTopComponent extends TopComponent {
+
+ private static CheckRegexTopComponent instance;
+ private static final String PREFERRED_ID = "CheckRegexTopComponent";
+ private static boolean isStrictMatch;
+
+ public CheckRegexTopComponent() {
+ initComponents();
+ setName(Bundle.CTL_CheckRegexTopComponent());
+ setToolTipText(Bundle.HINT_CheckRegexTopComponent());
+ isStrictMatch = false;
+ }
+
+ /**
+ * 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();
+ regexScrollPane = new javax.swing.JScrollPane();
+ regexTextArea = new javax.swing.JTextArea();
+ exampleLabel = new javax.swing.JLabel();
+ exampleLayeredPane = new javax.swing.JLayeredPane();
+ iconLabel = new javax.swing.JLabel();
+ exampleScrollPane = new javax.swing.JScrollPane();
+ exampleTextArea = new javax.swing.JTextArea();
+ strictCheckBox = new javax.swing.JCheckBox();
+ errorLabel = new javax.swing.JLabel();
+
+ org.openide.awt.Mnemonics.setLocalizedText(regexLabel, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.regexLabel.text")); // NOI18N
+
+ regexScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
+ regexScrollPane.setPreferredSize(new java.awt.Dimension(164, 74));
+
+ regexTextArea.setColumns(20);
+ regexTextArea.setRows(5);
+ regexTextArea.setFocusAccelerator('g');
+ regexTextArea.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyReleased(java.awt.event.KeyEvent evt) {
+ regexTextAreaKeyReleased(evt);
+ }
+ });
+ regexScrollPane.setViewportView(regexTextArea);
+
+ org.openide.awt.Mnemonics.setLocalizedText(exampleLabel, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.exampleLabel.text")); // NOI18N
+
+ exampleScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
+ exampleScrollPane.setOpaque(false);
+
+ exampleTextArea.setColumns(20);
+ exampleTextArea.setRows(5);
+ exampleTextArea.setFocusAccelerator('x');
+ exampleTextArea.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyReleased(java.awt.event.KeyEvent evt) {
+ exampleTextAreaKeyReleased(evt);
+ }
+ });
+ exampleScrollPane.setViewportView(exampleTextArea);
+
+ org.openide.awt.Mnemonics.setLocalizedText(strictCheckBox, org.openide.util.NbBundle.getMessage(CheckRegexTopComponent.class, "CheckRegexTopComponent.strictCheckBox.text")); // NOI18N
+ strictCheckBox.addItemListener(new java.awt.event.ItemListener() {
+ public void itemStateChanged(java.awt.event.ItemEvent evt) {
+ strictCheckBoxItemStateChanged(evt);
+ }
+ });
+
+ exampleLayeredPane.setLayer(iconLabel, javax.swing.JLayeredPane.DEFAULT_LAYER);
+ exampleLayeredPane.setLayer(exampleScrollPane, javax.swing.JLayeredPane.DEFAULT_LAYER);
+ exampleLayeredPane.setLayer(strictCheckBox, javax.swing.JLayeredPane.DEFAULT_LAYER);
+
+ javax.swing.GroupLayout exampleLayeredPaneLayout = new javax.swing.GroupLayout(exampleLayeredPane);
+ exampleLayeredPane.setLayout(exampleLayeredPaneLayout);
+ exampleLayeredPaneLayout.setHorizontalGroup(
+ exampleLayeredPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, exampleLayeredPaneLayout.createSequentialGroup()
+ .addContainerGap(297, Short.MAX_VALUE)
+ .addComponent(iconLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 17, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(12, 12, 12)
+ .addComponent(strictCheckBox))
+ .addGroup(exampleLayeredPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(exampleLayeredPaneLayout.createSequentialGroup()
+ .addComponent(exampleScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 15, Short.MAX_VALUE)))
+ );
+ exampleLayeredPaneLayout.setVerticalGroup(
+ exampleLayeredPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(exampleLayeredPaneLayout.createSequentialGroup()
+ .addGap(21, 21, 21)
+ .addGroup(exampleLayeredPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(strictCheckBox)
+ .addComponent(iconLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(exampleLayeredPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(exampleLayeredPaneLayout.createSequentialGroup()
+ .addComponent(exampleScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 44, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 6, Short.MAX_VALUE)))
+ );
+
+ 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(regexLabel)
+ .addComponent(exampleLabel)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(regexScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 320, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(errorLabel))
+ .addComponent(exampleLayeredPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(266, Short.MAX_VALUE))
+ );
+ 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)
+ .addComponent(regexLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(regexScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(errorLabel))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .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())
+ );
+ }// </editor-fold>//GEN-END:initComponents
+
+ private void exampleTextAreaKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_exampleTextAreaKeyReleased
+ if (exampleTextArea.getSelectedText() == null) {
+ matchPattern();
+ }
+ }//GEN-LAST:event_exampleTextAreaKeyReleased
+
+ private void regexTextAreaKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_regexTextAreaKeyReleased
+ matchPattern();
+ }//GEN-LAST:event_regexTextAreaKeyReleased
+
+ private void strictCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_strictCheckBoxItemStateChanged
+ isStrictMatch = !isStrictMatch;
+ matchPattern();
+ }//GEN-LAST:event_strictCheckBoxItemStateChanged
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ 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.JLabel iconLabel;
+ private javax.swing.JLabel regexLabel;
+ private javax.swing.JScrollPane regexScrollPane;
+ private javax.swing.JTextArea regexTextArea;
+ private javax.swing.JCheckBox strictCheckBox;
+ // End of variables declaration//GEN-END:variables
+ @Override
+ public void componentOpened() {
+ // TODO add custom code on component opening
+ }
+
+ @Override
+ public void componentClosed() {
+ // TODO add custom code on component closing
+ }
+
+ void writeProperties(java.util.Properties p) {
+ // better to version settings since initial version as advocated at
+ // http://wiki.apidesign.org/wiki/PropertyFiles
+ p.setProperty("version", "1.0"); // NOI18N
+ // TODO store your settings
+ }
+
+ void readProperties(java.util.Properties p) {
+ String version = p.getProperty("version"); // NOI18N
+ // TODO read your settings according to their version
+ }
+
+ public static synchronized CheckRegexTopComponent getDefault() {
+ if (instance == null) {
+ instance = new CheckRegexTopComponent();
+ }
+ Mode outputMode = WindowManager.getDefault().findMode("output"); // NOI18N
+ if (outputMode != null) {
+ outputMode.dockInto(instance);
+ }
+ return instance;
+ }
+
+ public static synchronized CheckRegexTopComponent findInstance() {
+ TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
+ if (win == null) {
+ Logger.getLogger(CheckRegexTopComponent.class.getName()).warning(
+ "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); // NOI18N
+ return getDefault();
+ }
+ if (win instanceof CheckRegexTopComponent) {
+ return (CheckRegexTopComponent) win;
+ }
+ Logger.getLogger(CheckRegexTopComponent.class.getName()).warning(
+ "There seem to be multiple components with the '" + PREFERRED_ID
+ + "' ID. That is a potential source of errors and unexpected behavior."); // NOI18N
+ return getDefault();
+ }
+
+ void setData(String origString) {
+ regexTextArea.setText(origString);
+ matchPattern();
+ }
+
+ @NbBundle.Messages({
+ "CheckRegexTopComponent.tooltip.match.regex=The Example Matches the Regular Expression",
+ "CheckRegexTopComponent.tooltip.need.more.input=Need more input to match",
+ "CheckRegexTopComponent.tooltip.not.match=The example does not match the Regular Expression.",
+ "# {0} - matchCount",
+ "CheckRegexTopComponent.tooltop.sub.match={0} substring(s) match the Regular Expression",
+ "# {0} - invalidRegex",
+ "CheckRegexTopComponent.label.error=Invalid regular expression: {0}"
+ })
+ private void matchPattern() {
+
+ Highlighter highlighter = exampleTextArea.getHighlighter();
+ highlighter.removeAllHighlights();
+
+ errorLabel.setText("");
+ iconLabel.setIcon(null);
+
+ if (regexTextArea.getText().length() == 0 || exampleTextArea.getText().length() == 0) {
+ return;
+ }
+ Pattern p;
+ try {
+ p = Pattern.compile(regexTextArea.getText());
+ } catch (PatternSyntaxException pse) {
+ errorLabel.setText(Bundle.CheckRegexTopComponent_label_error(pse.getDescription()));
+ return;
+ }
+ Matcher m = p.matcher(exampleTextArea.getText());
+
+ if (m.matches()) {
+ iconLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/java/hints/resources/match.png"))); // NOI18N
+ exampleTextArea.setToolTipText(Bundle.CheckRegexTopComponent_tooltip_match_regex());
+ } else if (m.hitEnd()) {
+ iconLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/java/hints/resources/half-match.png"))); // NOI18N
+ exampleTextArea.setToolTipText(Bundle.CheckRegexTopComponent_tooltip_need_more_input());
+ } else if (isStrictMatch) {
+ iconLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/java/hints/resources/no-match.png"))); // NOI18N
+ exampleTextArea.setToolTipText(Bundle.CheckRegexTopComponent_tooltip_not_match());
+ } else {
+ m.reset();
+ long count = 0;
+ try {
+ while (m.find()) {
+ int start = m.start();
+ int end = m.end();
+ DefaultHighlighter.DefaultHighlightPainter defaultHighlightPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.GREEN);
+ highlighter.addHighlight(start, end, defaultHighlightPainter);
+ count++;
+ }
+ if (count > 0) {
+ iconLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/java/hints/resources/match.png"))); // NOI18N
+ exampleTextArea.setToolTipText(Bundle.CheckRegexTopComponent_tooltop_sub_match(count));
+ } else {
+ iconLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/java/hints/resources/no-match.png"))); // NOI18N
+ exampleTextArea.setToolTipText(Bundle.CheckRegexTopComponent_tooltip_not_match());
+ }
+ } catch (BadLocationException e) {
+ Exceptions.printStackTrace(e);
+ }
+ }
+ }
+}
diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/Regexp.java b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/Regexp.java
new file mode 100644
index 0000000..4810d43
--- /dev/null
+++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/Regexp.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.jdk;
+
+import com.sun.source.tree.BinaryTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.LiteralTree;
+import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.Tree.Kind;
+import com.sun.source.util.TreePath;
+import org.netbeans.api.java.source.support.ErrorAwareTreePathScanner;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.VariableElement;
+import org.netbeans.spi.java.hints.ConstraintVariableType;
+import org.netbeans.spi.java.hints.Hint;
+import org.netbeans.spi.java.hints.TriggerPattern;
+import org.netbeans.spi.java.hints.TriggerPatterns;
+import org.netbeans.spi.java.hints.HintContext;
+import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.Severity;
+import org.netbeans.spi.java.hints.Hint.Options;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author lahvac
+ */
+@Hint(displayName = "#DN_org.netbeans.modules.java.hints.jdk.Regexp", description = "#DESC_org.netbeans.modules.java.hints.jdk.Regexp", category = "bugs", severity = Severity.ERROR, suppressWarnings = {"MalformedRegexp", "", "MalformedRegex"}, options = Options.QUERY)
+@NbBundle.Messages({"DN_org.netbeans.modules.java.hints.jdk.Regexp=Malformed regular expression",
+ "DESC_org.netbeans.modules.java.hints.jdk.Regexp=Warns about malformed regular expressions"})
+public class Regexp {
+
+ @TriggerPatterns({
+ @TriggerPattern(value = "java.util.regex.Pattern.compile($pattern)",
+ constraints = {
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String")
+ }),
+ @TriggerPattern(value = "java.util.regex.Pattern.compile($pattern, $flags)",
+ constraints = {
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$flags", type = "int")
+ }),
+ @TriggerPattern(value = "java.util.regex.Pattern.matches($pattern, $text)",
+ constraints = {
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$text", type = "java.lang.CharSequence")
+ }),
+ @TriggerPattern(value = "$str.split($pattern)",
+ constraints = {
+ @ConstraintVariableType(variable = "$str", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String")
+ }),
+ @TriggerPattern(value = "$str.split($pattern, $limit)",
+ constraints = {
+ @ConstraintVariableType(variable = "$str", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$limit", type = "int")
+ }),
+ @TriggerPattern(value = "$str.matches($pattern)",
+ constraints = {
+ @ConstraintVariableType(variable = "$str", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String")
+ }),
+ @TriggerPattern(value = "$str.replaceFirst($pattern, $repl)",
+ constraints = {
+ @ConstraintVariableType(variable = "$str", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$repl", type = "java.lang.String")
+ }),
+ @TriggerPattern(value = "$str.replaceAll($pattern, $repl)",
+ constraints = {
+ @ConstraintVariableType(variable = "$str", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$pattern", type = "java.lang.String"),
+ @ConstraintVariableType(variable = "$repl", type = "java.lang.String")
+ })
+ })
+ public static ErrorDescription hint(final HintContext ctx) {
+ final StringBuilder regexp = new StringBuilder();
+ final boolean[] accept = {true};
+ Tree leaf = ctx.getVariables().get("$pattern").getLeaf(); // NOI18N
+ if (leaf.getKind() == Kind.STRING_LITERAL) {
+ TreePath pattern = ctx.getVariables().get("$pattern"); // NOI18N
+ new ErrorAwareTreePathScanner<Void, Void>() {
+ @Override
+ public Void visitLiteral(LiteralTree node, Void p) {
+ if (node.getValue() instanceof String) {
+ regexp.append(node.getValue());
+ return null;
+ }
+ accept[0] = false;
+ return null;
+ }
+
+ @Override
+ public Void visitIdentifier(IdentifierTree node, Void p) {
+ Element el = ctx.getInfo().getTrees().getElement(getCurrentPath());
+
+ if (el != null && el.getKind() == ElementKind.FIELD) {
+ VariableElement ve = (VariableElement) el;
+
+ if (ve.getConstantValue() instanceof String) {
+ regexp.append(ve.getConstantValue());
+ return null;
+ }
+ }
+ accept[0] = false;
+ return null;
+ }
+
+ @Override
+ public Void visitMemberSelect(MemberSelectTree node, Void p) {
+ Element el = ctx.getInfo().getTrees().getElement(getCurrentPath());
+
+ if (el != null && el.getKind() == ElementKind.FIELD) {
+ VariableElement ve = (VariableElement) el;
+
+ if (ve.getConstantValue() instanceof String) {
+ regexp.append(ve.getConstantValue());
+ return null;
+ }
+ }
+ accept[0] = false;
+ return null;
+ }
+
+ @Override
+ public Void visitBinary(BinaryTree node, Void p) {
+ if (node.getKind() != Kind.PLUS) {
+ return super.visitBinary(node, p);
+ }
+ accept[0] = false;
+ return null;
+ }
+
+ @Override
+ public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
+ accept[0] = false;
+ return null;
+ }
+ }.scan(pattern, null);
+
+ if (!accept[0] || regexp.length() == 0) {
+ return null;
+ }
+ } else if (leaf.getKind() == Kind.IDENTIFIER) {
+ String val = CheckRegex.identifierSearch(leaf, ctx);
+ if (val != null) {
+ regexp.append(val);
+ }
+ }
+ try {
+ Pattern.compile(regexp.toString());
+ return null;
+ } catch (PatternSyntaxException pse) {
+ String displayName = NbBundle.getMessage(Regexp.class, "DN_RegExp", new Object[]{ // NOI18N
+ pse.getDescription(),
+ pse.getMessage(),
+ pse.getPattern(),
+ pse.getIndex(),});
+ return ErrorDescriptionFactory.forTree(ctx, leaf, displayName);
+ }
+ }
+}
diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/resources/half-match.png b/java/java.hints/src/org/netbeans/modules/java/hints/resources/half-match.png
new file mode 100644
index 0000000..9b0460e
Binary files /dev/null and b/java/java.hints/src/org/netbeans/modules/java/hints/resources/half-match.png differ
diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/resources/match.png b/java/java.hints/src/org/netbeans/modules/java/hints/resources/match.png
new file mode 100644
index 0000000..d37e7ec
Binary files /dev/null and b/java/java.hints/src/org/netbeans/modules/java/hints/resources/match.png differ
diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/resources/no-match.png b/java/java.hints/src/org/netbeans/modules/java/hints/resources/no-match.png
new file mode 100644
index 0000000..44c59b1
Binary files /dev/null and b/java/java.hints/src/org/netbeans/modules/java/hints/resources/no-match.png differ
diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/CheckRegexTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/CheckRegexTest.java
new file mode 100644
index 0000000..22eb381
--- /dev/null
+++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/CheckRegexTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.junit.Test;
+import org.netbeans.modules.java.hints.test.api.HintTest;
+
+public class CheckRegexTest {
+
+ @Test
+ public void testWarningProduced() throws Exception {
+ HintTest.create()
+ .input("package test;\n"
+ + "import java.util.regex.Pattern;\n"
+ + "public class Test {\n"
+ + " public static void main(String[] args) {\n"
+ + " Pattern pattern = Pattern.compile(\"a(b|c|d)\");\n"
+ + " }\n"
+ + "}\n")
+ .run(CheckRegex.class)
+ .assertWarnings("4:34-4:41:verifier:" + Bundle.ERR_CheckRegex());
+ }
+
+ @Test
+ public void testWarningProduced2() throws Exception {
+ HintTest.create()
+ .input("package test;\n"
+ + "import java.util.regex.Pattern;\n"
+ + "public class Test {\n"
+ + " public static void main(String[] args) {\n"
+ + " boolean matches = Pattern.matches(\"\\\\d\", \"abc\");\n"
+ + " }\n"
+ + "}\n")
+ .run(CheckRegex.class)
+ .assertWarnings("4:34-4:41:verifier:" + Bundle.ERR_CheckRegex());
+ }
+
+}
diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/RegexpTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/RegexpTest.java
similarity index 91%
rename from java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/RegexpTest.java
rename to java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/RegexpTest.java
index e3f5267..3bb0688 100644
--- a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/RegexpTest.java
+++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/RegexpTest.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.netbeans.modules.java.hints.bugs;
+package org.netbeans.modules.java.hints.jdk;
import org.netbeans.junit.NbTestCase;
import org.netbeans.modules.java.hints.test.api.HintTest;
@@ -41,6 +41,6 @@ public class RegexpTest extends NbTestCase {
" }\n" +
"}\n")
.run(Regexp.class)
- .assertWarnings("3:40-3:43:verifier:Invalid regular expression");
+ .assertWarnings("3:40-3:43:error:Invalid regular expression: Unclosed group");
}
-}
\ No newline at end of file
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists