Added Occurance Finder for ANTLR
diff --git a/java/languages.antlr/build.xml b/java/languages.antlr/build.xml
index 047f473..914e8b7 100644
--- a/java/languages.antlr/build.xml
+++ b/java/languages.antlr/build.xml
@@ -46,6 +46,7 @@
<java classname="org.antlr.v4.Tool" classpathref="antlr4.tool">
<arg value="-o"/><arg value="${antlr.outdir}"/>
<!--arg value="-package"/><arg value="org.antlr.parser.antlr4"/-->
+ <!--arg value="-visitor"/-->
<arg value="${antlr.outdir}/ANTLRv4Lexer.g4"/>
<arg value="${antlr.outdir}/ANTLRv4Parser.g4"/>
</java>
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 be2000c..43e4245 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
@@ -20,7 +20,6 @@
import javax.swing.text.AbstractDocument;
import javax.swing.text.Document;
-import org.netbeans.api.editor.document.LineDocument;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenHierarchy;
import org.netbeans.api.lexer.TokenSequence;
@@ -44,7 +43,7 @@
Token<?> token = ts.token();
String ref = String.valueOf(token.text());
AntlrParserResult.Reference aref = result.references.get(ref);
- return aref != null ? new DeclarationLocation(aref.source, aref.defOffset) : DeclarationLocation.NONE;
+ return aref != null ? new DeclarationLocation(aref.source, aref.defOffset.getStart()) : DeclarationLocation.NONE;
}
@Override
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrLanguage.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrLanguage.java
index 9c43263..5c7256e 100644
--- a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrLanguage.java
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrLanguage.java
@@ -20,7 +20,7 @@
import org.netbeans.api.lexer.Language;
import org.netbeans.modules.csl.api.DeclarationFinder;
-import org.netbeans.modules.csl.api.SemanticAnalyzer;
+import org.netbeans.modules.csl.api.OccurrencesFinder;
import org.netbeans.modules.csl.api.StructureScanner;
import org.netbeans.modules.csl.spi.DefaultLanguageConfig;
import org.netbeans.modules.csl.spi.LanguageRegistration;
@@ -68,6 +68,15 @@
return true;
}
+ @Override
+ public OccurrencesFinder getOccurrencesFinder() {
+ return new AntlrOccurancesFinder();
+ }
+
+ @Override
+ public boolean hasOccurrencesFinder() {
+ return true;
+ }
@Override
public String getPreferredExtension() {
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrLexer.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrLexer.java
index 5d34618..6c2f8ee 100644
--- a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrLexer.java
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrLexer.java
@@ -45,6 +45,7 @@
if (info.state() != null) {
((LexerState) info.state()).restore(lexer);
}
+ input.markToken();
}
private org.antlr.v4.runtime.Token preFetchedToken = null;
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
new file mode 100644
index 0000000..3e2d362
--- /dev/null
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrOccurancesFinder.java
@@ -0,0 +1,104 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.netbeans.api.lexer.Token;
+import org.netbeans.api.lexer.TokenHierarchy;
+import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.modules.csl.api.ColoringAttributes;
+import org.netbeans.modules.csl.api.OccurrencesFinder;
+import org.netbeans.modules.csl.api.OffsetRange;
+import org.netbeans.modules.parsing.spi.Scheduler;
+import org.netbeans.modules.parsing.spi.SchedulerEvent;
+
+/**
+ *
+ * @author lkishalmi
+ */
+public class AntlrOccurancesFinder extends OccurrencesFinder<AntlrParserResult> {
+
+ private int caretPosition;
+ private boolean cancelled;
+ private final Map<OffsetRange, ColoringAttributes> occurrences = new HashMap<>();
+
+ @Override
+ public void setCaretPosition(int position) {
+ caretPosition = position;
+ }
+
+ @Override
+ public Map<OffsetRange, ColoringAttributes> getOccurrences() {
+ return occurrences;
+ }
+
+ @Override
+ public void run(AntlrParserResult result, SchedulerEvent event) {
+ occurrences.clear();
+ if (checkAndResetCancel()) {
+ return;
+ }
+ computeOccurrences(result);
+ }
+
+ @Override
+ public int getPriority() {
+ return 200;
+ }
+
+ @Override
+ public Class<? extends Scheduler> getSchedulerClass() {
+ return Scheduler.CURSOR_SENSITIVE_TASK_SCHEDULER;
+ }
+
+ @Override
+ public void cancel() {
+ this.cancelled = true;
+ }
+
+
+ private boolean checkAndResetCancel() {
+ if (cancelled) {
+ cancelled = false;
+ return true;
+ }
+ return false;
+ }
+
+ private void computeOccurrences(AntlrParserResult result) {
+ TokenHierarchy<?> tokenHierarchy = result.getSnapshot().getTokenHierarchy();
+ TokenSequence<?> ts = tokenHierarchy.tokenSequence();
+ ts.move(caretPosition);
+ if (ts.movePrevious()) {
+ ts.moveNext();
+ Token<?> token = ts.token();
+ if (token.id() == AntlrTokenId.RULE || token.id() == AntlrTokenId.TOKEN) {
+ String refName = String.valueOf(token.text());
+ AntlrParserResult.Reference ref = result.references.get(refName);
+ if (ref != 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 d6a317c..decdf6a 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
@@ -34,6 +34,7 @@
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.Token;
@@ -72,6 +73,10 @@
while (!parsingQueue.isEmpty()) {
parsingQueue.removeFirst().grammarSpec();
}
+ // Second phase scan
+ ANTLRv4Parser secondPhase = createParser(getSnapshot());
+ secondPhase.addParseListener(createOccurancesListener());
+ secondPhase.grammarSpec();
finished.set(true);
return this;
}
@@ -81,12 +86,16 @@
addParseTask(src.createSnapshot(), true);
}
- private void addParseTask(Snapshot snapshot, boolean imported) {
- FileObject fo = snapshot.getSource().getFileObject();
+ private ANTLRv4Parser createParser(Snapshot snapshot) {
CharStream cs = CharStreams.fromString(String.valueOf(snapshot.getText()));
ANTLRv4Lexer lexer = new org.antlr.parser.antlr4.ANTLRv4Lexer(cs);
CommonTokenStream tokens = new CommonTokenStream(lexer);
- ANTLRv4Parser parser = new ANTLRv4Parser(tokens);
+ return new ANTLRv4Parser(tokens);
+ }
+
+ private void addParseTask(Snapshot snapshot, boolean imported) {
+ FileObject fo = snapshot.getSource().getFileObject();
+ ANTLRv4Parser parser = createParser(snapshot);
if (!imported) {
@@ -117,9 +126,10 @@
static class Reference {
final String name;
final FileObject source;
- final int defOffset;
+ final OffsetRange defOffset;
+ final List<OffsetRange> occurances = new ArrayList<>();
- public Reference(String name, FileObject source, int defOffset) {
+ public Reference(String name, FileObject source, OffsetRange defOffset) {
this.name = name;
this.source = source;
this.defOffset = defOffset;
@@ -146,14 +156,16 @@
@Override
public void exitParserRuleSpec(ANTLRv4Parser.ParserRuleSpecContext ctx) {
Token token = ctx.RULE_REF().getSymbol();
- Reference ref = new Reference(token.getText(), source, token.getStartIndex());
+ OffsetRange range = new OffsetRange(token.getStartIndex(), token.getStopIndex() + 1);
+ Reference ref = new Reference(token.getText(), source, range);
references.put(ref.name, ref);
}
@Override
public void exitLexerRuleSpec(ANTLRv4Parser.LexerRuleSpecContext ctx) {
Token token = ctx.TOKEN_REF().getSymbol();
- Reference ref = new Reference(token.getText(), source, token.getStartIndex());
+ OffsetRange range = new OffsetRange(token.getStartIndex(), token.getStopIndex() + 1);
+ Reference ref = new Reference(token.getText(), source, range);
references.put(ref.name, ref);
}
@@ -262,4 +274,34 @@
};
}
+
+ ANTLRv4ParserListener createOccurancesListener() {
+ return new ANTLRv4ParserBaseListener() {
+
+ private void addOccurance(Token token) {
+ String refName = token.getText();
+ System.out.println(refName);
+ Reference ref = references.get(refName);
+ if (ref != null) {
+ ref.occurances.add(new OffsetRange(token.getStartIndex(), token.getStopIndex() + 1));
+ }
+ }
+
+ @Override
+ public void exitTerminal(ANTLRv4Parser.TerminalContext ctx) {
+ if (ctx.TOKEN_REF() != null) {
+ addOccurance(ctx.TOKEN_REF().getSymbol());
+ }
+ }
+
+ @Override
+ public void exitRuleref(ANTLRv4Parser.RulerefContext ctx) {
+ if (ctx.RULE_REF() != null) {
+ addOccurance(ctx.RULE_REF().getSymbol());
+ }
+ }
+
+ };
+ }
+
}