Implement "Find Usages"
diff --git a/java/languages.antlr/nbproject/project.xml b/java/languages.antlr/nbproject/project.xml
index 7de043e..0088942 100644
--- a/java/languages.antlr/nbproject/project.xml
+++ b/java/languages.antlr/nbproject/project.xml
@@ -61,6 +61,15 @@
</run-dependency>
</dependency>
<dependency>
+ <code-name-base>org.netbeans.modules.editor</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>3</release-version>
+ <specification-version>1.105</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
<code-name-base>org.netbeans.modules.editor.completion</code-name-base>
<build-prerequisite/>
<compile-dependency/>
@@ -123,6 +132,14 @@
</run-dependency>
</dependency>
<dependency>
+ <code-name-base>org.netbeans.modules.refactoring.api</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>1.65</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
<compile-dependency/>
@@ -155,6 +172,14 @@
</run-dependency>
</dependency>
<dependency>
+ <code-name-base>org.openide.text</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>6.86</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
<code-name-base>org.openide.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrDeclarationFinder.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrDeclarationFinder.java
index 793dc94..45e5028 100644
--- a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrDeclarationFinder.java
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrDeclarationFinder.java
@@ -87,10 +87,9 @@
AntlrParserResult result = AntlrLocalIndex.getParserResult(fo);
- Map<String, Reference> refs = result.references;
+ Reference ref = ((Map<String, Reference>) result.references).get(name);
- if(refs.containsKey(name)) {
- Reference ref = refs.get(name);
+ if(ref != null && ref.defOffset != null) {
AntlrStructureItem asi = new AntlrStructureItem.RuleStructureItem(name, fo, ref.defOffset.getStart(), ref.defOffset.getEnd());
DeclarationLocation dln = new DeclarationFinder.DeclarationLocation(fo, ref.defOffset.getStart(), asi);
if (resultDL == DeclarationLocation.NONE) {
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrOccurancesFinder.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrOccurancesFinder.java
index ec2e24b..c9ac3e0 100644
--- a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrOccurancesFinder.java
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrOccurancesFinder.java
@@ -94,7 +94,9 @@
Map<String, AntlrParserResult.Reference> refs = result.references;
AntlrParserResult.Reference ref = refs.get(refName);
if (ref != null) {
- occurrences.put(ref.defOffset, ColoringAttributes.MARK_OCCURRENCES);
+ if(ref.defOffset != null) {
+ occurrences.put(ref.defOffset, ColoringAttributes.MARK_OCCURRENCES);
+ }
for (OffsetRange occurance : ref.occurances) {
occurrences.put(occurance, ColoringAttributes.MARK_OCCURRENCES);
}
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrParserResult.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrParserResult.java
index e98d7cc..8afc040 100644
--- a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrParserResult.java
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrParserResult.java
@@ -89,8 +89,8 @@
public static class Reference {
public final String name;
- public final FileObject source;
- public final OffsetRange defOffset;
+ public FileObject source;
+ public OffsetRange defOffset;
public final List<OffsetRange> occurances = new ArrayList<>();
public Reference(String name, FileObject source, OffsetRange defOffset) {
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/Refactoring.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/Refactoring.java
new file mode 100644
index 0000000..11210cd
--- /dev/null
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/Refactoring.java
@@ -0,0 +1,261 @@
+/*
+ * 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.languages.antlr.refactoring;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Position;
+import javax.swing.text.StyledDocument;
+import org.netbeans.api.editor.document.LineDocument;
+import org.netbeans.api.editor.document.LineDocumentUtils;
+import org.netbeans.modules.csl.api.OffsetRange;
+import org.netbeans.modules.languages.antlr.AntlrLocalIndex;
+import org.netbeans.modules.languages.antlr.AntlrParserResult;
+import org.netbeans.modules.languages.antlr.AntlrParserResult.Reference;
+import org.netbeans.modules.languages.antlr.v4.Antlr4Language;
+import org.netbeans.modules.languages.antlr.v4.Antlr4ParserResult;
+import org.netbeans.modules.refactoring.api.AbstractRefactoring;
+import org.netbeans.modules.refactoring.api.Problem;
+import org.netbeans.modules.refactoring.api.WhereUsedQuery;
+import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
+import org.netbeans.modules.refactoring.spi.RefactoringPlugin;
+import org.netbeans.modules.refactoring.spi.RefactoringPluginFactory;
+import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
+import org.openide.cookies.EditorCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.text.CloneableEditorSupport;
+import org.openide.text.PositionBounds;
+import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ *
+ * @author lahvac
+ */
+@NbBundle.Messages("TXT_Canceled=Canceled")
+public class Refactoring {
+
+ private static final class WhereUsedRefactoringPlugin implements RefactoringPlugin {
+
+ private final WhereUsedQuery query;
+ private final SymbolInformation symbolInformation;
+ private final AtomicBoolean cancel = new AtomicBoolean();
+
+ public WhereUsedRefactoringPlugin(WhereUsedQuery query, SymbolInformation symbolInformation) {
+ this.query = query;
+ this.symbolInformation = symbolInformation;
+ }
+
+ @Override
+ public Problem preCheck() {
+ return null;
+ }
+
+ @Override
+ public Problem checkParameters() {
+ return null;
+ }
+
+ @Override
+ public Problem fastCheckParameters() {
+ return null;
+ }
+
+ @Override
+ public void cancelRequest() {
+ cancel.set(true);
+ }
+
+ @Override
+ public Problem prepare(RefactoringElementsBag refactoringElements) {
+ try {
+ String name = this.symbolInformation.getName();
+ FileObject sourceFO = this.symbolInformation.getSourceFile();
+ Map<FileObject,Set<FileObject>> imports = new HashMap<>();
+
+ if (Antlr4Language.MIME_TYPE.equals(sourceFO.getMIMEType())) {
+ FileObject parent = sourceFO.getParent();
+ for(FileObject cf: parent.getChildren()) {
+ if (cancel.get()) {
+ throw new CancellationException();
+ }
+
+ Antlr4ParserResult result = (Antlr4ParserResult) AntlrLocalIndex.getParserResult(cf);
+
+ result.getImports().forEach(s -> {
+ FileObject referencedFO = parent.getFileObject(s, "g4");
+ if(referencedFO != null) {
+ imports.computeIfAbsent(cf, cd2 -> new HashSet<>())
+ .add(referencedFO);
+ }
+ });
+ }
+ }
+
+ List<FileObject> toScan = new ArrayList<>();
+ Set<FileObject> scannedFileObjects = new HashSet<>();
+
+ toScan.add(sourceFO);
+
+ while(! toScan.isEmpty()) {
+ if (cancel.get()) {
+ throw new CancellationException();
+ }
+
+ FileObject fo = toScan.remove(0);
+ if(scannedFileObjects.contains(fo)) {
+ continue;
+ }
+ scannedFileObjects.add(fo);
+
+ AntlrParserResult<?> result = (AntlrParserResult) AntlrLocalIndex.getParserResult(fo);
+
+ Reference ref = result.references.get(name);
+
+ TreeSet<OffsetRange> ranges = new TreeSet<>();
+
+ if(ref != null) {
+ if(ref.defOffset != null) {
+ ranges.add(ref.defOffset);
+ }
+ ranges.addAll(ref.occurances);
+ }
+
+ for(OffsetRange or : ranges) {
+ PositionBounds bounds;
+ try {
+ CloneableEditorSupport es = fo.getLookup().lookup(CloneableEditorSupport.class);
+ EditorCookie ec = fo.getLookup().lookup(EditorCookie.class);
+ StyledDocument doc = ec.openDocument();
+ LineDocument ldoc = (LineDocument) doc;
+
+ int rowStart = LineDocumentUtils.getLineStart(ldoc, or.getStart());
+ int rowEnd = LineDocumentUtils.getLineEnd(ldoc, or.getEnd());
+
+ bounds = new PositionBounds(
+ es.createPositionRef(or.getStart(), Position.Bias.Forward),
+ es.createPositionRef(or.getEnd(), Position.Bias.Forward)
+ );
+
+ String lineText = doc.getText(rowStart, rowEnd - rowStart);
+ String annotatedLine =
+ lineText.substring(0, or.getStart() - rowStart)
+ + "<strong>"
+ + lineText.substring(or.getStart() - rowStart, or.getEnd() - rowStart)
+ + "</strong>"
+ + lineText.substring(or.getEnd() - rowStart);
+ refactoringElements.add(query, new AntlrRefactoringElementImpl(annotatedLine, fo, bounds));
+ } catch (BadLocationException | IOException ex) {
+ Exceptions.printStackTrace(ex);
+ bounds = null;
+ }
+ }
+
+ toScan.addAll(imports.getOrDefault(fo, Collections.emptySet()));
+
+ for(Entry<FileObject,Set<FileObject>> e: imports.entrySet()) {
+ if(e.getValue().contains(fo)) {
+ toScan.add(e.getKey());
+ }
+ }
+ }
+
+ return null;
+ } catch (CancellationException ex) {
+ return new Problem(false, Bundle.TXT_Canceled());
+ }
+ }
+
+ }
+
+ @ServiceProvider(service=RefactoringPluginFactory.class)
+ public static class FactoryImpl implements RefactoringPluginFactory {
+
+ @Override
+ public RefactoringPlugin createInstance(AbstractRefactoring refactoring) {
+ if (refactoring instanceof WhereUsedQuery) {
+ WhereUsedQuery q = (WhereUsedQuery) refactoring;
+ SymbolInformation symbolInformation = q.getRefactoringSource().lookup(SymbolInformation.class);
+ if (symbolInformation != null) {
+ return new WhereUsedRefactoringPlugin(q, symbolInformation);
+ }
+ }
+ return null;
+ }
+
+ }
+
+ public static class AntlrRefactoringElementImpl extends SimpleRefactoringElementImplementation {
+
+ private final String annotatedLine;
+ private final FileObject file;
+ private final PositionBounds bounds;
+
+ public AntlrRefactoringElementImpl(String annotatedLine, FileObject file, PositionBounds bounds) {
+ this.annotatedLine = annotatedLine;
+ this.file = file;
+ this.bounds = bounds;
+ }
+
+ @Override
+ public String getText() {
+ return "Element usage";
+ }
+
+ @Override
+ public String getDisplayText() {
+ return annotatedLine;
+ }
+
+ @Override
+ public void performChange() {
+ // Currently the AntlrRefactoringElementImpl is only used for the
+ // WhereUsedRefactoring, which is not doing changes
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Lookup getLookup() {
+ return Lookup.EMPTY;
+ }
+
+ @Override
+ public FileObject getParentFile() {
+ return file;
+ }
+
+ @Override
+ public PositionBounds getPosition() {
+ return bounds;
+ }
+ }
+}
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/RefactoringActionsProvider.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/RefactoringActionsProvider.java
new file mode 100644
index 0000000..52da319
--- /dev/null
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/RefactoringActionsProvider.java
@@ -0,0 +1,113 @@
+/*
+ * 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.languages.antlr.refactoring;
+
+import javax.swing.Action;
+import javax.swing.JEditorPane;
+import javax.swing.SwingUtilities;
+import javax.swing.text.AbstractDocument;
+import javax.swing.text.Document;
+import org.netbeans.api.lexer.TokenHierarchy;
+import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.modules.editor.NbEditorUtilities;
+import org.netbeans.modules.languages.antlr.v3.Antlr3Language;
+import org.netbeans.modules.languages.antlr.v4.Antlr4Language;
+import org.netbeans.modules.refactoring.spi.ui.ActionsImplementationProvider;
+import org.netbeans.modules.refactoring.spi.ui.UI;
+import org.openide.cookies.*;
+import org.openide.filesystems.FileObject;
+import org.openide.text.CloneableEditorSupport;
+import org.openide.text.NbDocument;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
+import org.openide.windows.TopComponent;
+
+
+@NbBundle.Messages({"WARN_CannotPerformHere=Cannot perform rename here."})
+@org.openide.util.lookup.ServiceProvider(service=org.netbeans.modules.refactoring.spi.ui.ActionsImplementationProvider.class, position=150)
+public class RefactoringActionsProvider extends ActionsImplementationProvider{
+
+ @Override
+ @Messages("NM_Unknown=Unknown")
+ public void doFindUsages(Lookup lookup) {
+ Runnable start = () -> {
+ EditorCookie ec = lookup.lookup(EditorCookie.class);
+
+ if (isFromEditor(ec)) {
+ JEditorPane c = ec.getOpenedPanes()[0];
+ Document doc = c.getDocument();
+ AbstractDocument abstractDoc = (doc instanceof AbstractDocument) ? ((AbstractDocument) doc) : null;
+ FileObject file = NbEditorUtilities.getFileObject(doc);
+ int caretPos = c.getCaretPosition();
+
+ String name = Bundle.NM_Unknown();
+
+ if (abstractDoc != null) {
+ abstractDoc.readLock();
+ }
+ try {
+ TokenSequence<?> ts = TokenHierarchy.get(doc).tokenSequence();
+ if (ts != null) {
+ ts.move(caretPos);
+ if (ts.moveNext()) {
+ name = ts.token().text().toString();
+ }
+ }
+ } finally {
+ if (abstractDoc != null) {
+ abstractDoc.readUnlock();
+ }
+ }
+
+ SymbolInformation si = new SymbolInformation(file, name);
+ UI.openRefactoringUI(new WhereUsedRefactoringUIImpl(si),
+ TopComponent.getRegistry().getActivated());
+ }
+ };
+ SwingUtilities.invokeLater(start);
+ }
+
+ static String getActionName(Action action) {
+ String arg = (String) action.getValue(Action.NAME);
+ arg = arg.replace("&", ""); // NOI18N
+ return arg.replace("...", ""); // NOI18N
+ }
+
+ @Override
+ public boolean canFindUsages(Lookup lookup) {
+ EditorCookie ec = lookup.lookup(EditorCookie.class);
+ Document doc = ec.getDocument();
+ FileObject file = NbEditorUtilities.getFileObject(doc);
+ return Antlr3Language.MIME_TYPE.equals(file.getMIMEType())
+ || Antlr4Language.MIME_TYPE.equals(file.getMIMEType());
+ }
+
+ public static boolean isFromEditor(EditorCookie ec) {
+ if (ec != null && NbDocument.findRecentEditorPane(ec) != null) {
+ TopComponent activetc = TopComponent.getRegistry().getActivated();
+ if (activetc instanceof CloneableEditorSupport.Pane) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/SymbolInformation.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/SymbolInformation.java
new file mode 100644
index 0000000..ef39741
--- /dev/null
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/SymbolInformation.java
@@ -0,0 +1,67 @@
+/*
+ * 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.languages.antlr.refactoring;
+
+import java.util.Objects;
+import org.openide.filesystems.FileObject;
+
+public class SymbolInformation {
+ private final FileObject sourceFile;
+ private final String name;
+
+ public SymbolInformation(FileObject sourceFile, String name) {
+ this.sourceFile = sourceFile;
+ this.name = name;
+ }
+
+ public FileObject getSourceFile() {
+ return sourceFile;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 53 * hash + Objects.hashCode(this.sourceFile);
+ hash = 53 * hash + Objects.hashCode(this.name);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final SymbolInformation other = (SymbolInformation) obj;
+ if (!Objects.equals(this.name, other.name)) {
+ return false;
+ }
+ return Objects.equals(this.sourceFile, other.sourceFile);
+ }
+
+}
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/WhereUsedRefactoringUIImpl.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/WhereUsedRefactoringUIImpl.java
new file mode 100644
index 0000000..d219c15
--- /dev/null
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/refactoring/WhereUsedRefactoringUIImpl.java
@@ -0,0 +1,88 @@
+/*
+ * 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.languages.antlr.refactoring;
+
+import javax.swing.event.ChangeListener;
+import org.netbeans.modules.refactoring.api.AbstractRefactoring;
+import org.netbeans.modules.refactoring.api.Problem;
+import org.netbeans.modules.refactoring.api.WhereUsedQuery;
+import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel;
+import org.netbeans.modules.refactoring.spi.ui.RefactoringUI;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle.Messages;
+import org.openide.util.lookup.Lookups;
+
+
+public class WhereUsedRefactoringUIImpl implements RefactoringUI {
+ private final SymbolInformation symbolInformation;
+
+ public WhereUsedRefactoringUIImpl(SymbolInformation symbolInformation) {
+ this.symbolInformation = symbolInformation;
+ }
+
+ @Override
+ public String getName() {
+ return symbolInformation.getName();
+ }
+
+ @Override
+ @Messages({
+ "# {0} - identifier",
+ "DESC_Usages=Usages of {0}"
+ })
+ public String getDescription() {
+ return Bundle.DESC_Usages(symbolInformation.getName());
+ }
+
+ @Override
+ public boolean isQuery() {
+ return true;
+ }
+
+ @Override
+ public CustomRefactoringPanel getPanel(ChangeListener parent) {
+ return null;
+ }
+
+ @Override
+ public Problem setParameters() {
+ return null;
+ }
+
+ @Override
+ public Problem checkParameters() {
+ return null;
+ }
+
+ @Override
+ public boolean hasParameters() {
+ return false;
+ }
+
+ @Override
+ public AbstractRefactoring getRefactoring() {
+ return new WhereUsedQuery(Lookups.fixed(symbolInformation));
+ }
+
+ @Override
+ public HelpCtx getHelpCtx() {
+ return HelpCtx.DEFAULT_HELP;
+ }
+
+}
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v3/Antlr3Language.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v3/Antlr3Language.java
index d5d7f1a..419e91c 100644
--- a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v3/Antlr3Language.java
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v3/Antlr3Language.java
@@ -112,7 +112,12 @@
path = "Loaders/text/x-antlr3/Actions",
id = @ActionID(category = "System", id = "org.openide.actions.PropertiesAction"),
position = 1500
- )
+ ),
+ @ActionReference(
+ path = "Editors/text/x-antlr3/Popup",
+ id = @ActionID(category = "Refactoring", id = "org.netbeans.modules.refactoring.api.ui.WhereUsedAction"),
+ position = 1600
+ ),
})
@LanguageRegistration(mimeType = Antlr3Language.MIME_TYPE, useMultiview = true)
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v3/Antlr3ParserResult.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v3/Antlr3ParserResult.java
index 138f37d..a773a30 100644
--- a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v3/Antlr3ParserResult.java
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v3/Antlr3ParserResult.java
@@ -63,8 +63,13 @@
public void exitRule_(ANTLRv3Parser.Rule_Context ctx) {
Token token = ctx.id_().getStart();
OffsetRange range = new OffsetRange(token.getStartIndex(), token.getStopIndex() + 1);
- Reference ref = new Reference(token.getText(), source, range);
- references.put(ref.name, ref);
+ String name = token.getText();
+ if (references.containsKey(name)) {
+ references.get(name).defOffset = range;
+ } else {
+ Reference ref = new Reference(name, source, range);
+ references.put(ref.name, ref);
+ }
}
};
@@ -139,6 +144,10 @@
private void addOccurance(Token token) {
String refName = token.getText();
Reference ref = references.get(refName);
+ if (ref == null) {
+ ref = new Reference(refName, getSnapshot().getSource().getFileObject(), null);
+ references.put(ref.name, ref);
+ }
if (ref != null) {
ref.occurances.add(new OffsetRange(token.getStartIndex(), token.getStopIndex() + 1));
}
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v4/Antlr4Language.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v4/Antlr4Language.java
index f31e2b3..70739c6 100644
--- a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v4/Antlr4Language.java
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v4/Antlr4Language.java
@@ -108,7 +108,12 @@
path = "Loaders/text/x-antlr4/Actions",
id = @ActionID(category = "System", id = "org.openide.actions.PropertiesAction"),
position = 1500
- )
+ ),
+ @ActionReference(
+ path = "Editors/text/x-antlr4/Popup",
+ id = @ActionID(category = "Refactoring", id = "org.netbeans.modules.refactoring.api.ui.WhereUsedAction"),
+ position = 1600
+ ),
})
@LanguageRegistration(mimeType = Antlr4Language.MIME_TYPE, useMultiview = true)
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v4/Antlr4ParserResult.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v4/Antlr4ParserResult.java
index 9cd8325..ebcf7aa 100644
--- a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v4/Antlr4ParserResult.java
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/v4/Antlr4ParserResult.java
@@ -66,17 +66,24 @@
@Override
public void exitParserRuleSpec(ANTLRv4Parser.ParserRuleSpecContext ctx) {
Token token = ctx.RULE_REF().getSymbol();
- OffsetRange range = new OffsetRange(token.getStartIndex(), token.getStopIndex() + 1);
- Reference ref = new Reference(token.getText(), source, range);
- references.put(ref.name, ref);
+ addReference(token);
}
@Override
public void exitLexerRuleSpec(ANTLRv4Parser.LexerRuleSpecContext ctx) {
Token token = ctx.TOKEN_REF().getSymbol();
+ addReference(token);
+ }
+
+ public void addReference(Token token) {
OffsetRange range = new OffsetRange(token.getStartIndex(), token.getStopIndex() + 1);
- Reference ref = new Reference(token.getText(), source, range);
- references.put(ref.name, ref);
+ String name = token.getText();
+ if(references.containsKey(name)) {
+ references.get(name).defOffset = range;
+ } else {
+ Reference ref = new Reference(name, source, range);
+ references.put(ref.name, ref);
+ }
}
};
@@ -213,6 +220,10 @@
private void addOccurance(Token token) {
String refName = token.getText();
Reference ref = references.get(refName);
+ if (ref == null) {
+ ref = new Reference(refName, getSnapshot().getSource().getFileObject(), null);
+ references.put(ref.name, ref);
+ }
if (ref != null) {
ref.occurances.add(new OffsetRange(token.getStartIndex(), token.getStopIndex() + 1));
}