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());
+                }
+            }
+
+        };
+    }
+
 }