Implementation of Goto Declaration and Completion using Indexer
diff --git a/java/languages.antlr/nbproject/project.xml b/java/languages.antlr/nbproject/project.xml
index 7de043e..22c1f1e 100644
--- a/java/languages.antlr/nbproject/project.xml
+++ b/java/languages.antlr/nbproject/project.xml
@@ -123,6 +123,23 @@
</run-dependency>
</dependency>
<dependency>
+ <code-name-base>org.netbeans.modules.parsing.indexing</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>9.27</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.modules.projectapi</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>1.89</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
<compile-dependency/>
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrCompletionProvider.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrCompletionProvider.java
index 32986af..97e199e 100644
--- a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrCompletionProvider.java
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrCompletionProvider.java
@@ -19,8 +19,10 @@
package org.netbeans.modules.languages.antlr;
import java.util.Collections;
-import java.util.Map;
+import java.util.List;
+import java.util.Locale;
import java.util.prefs.Preferences;
+import java.util.stream.Collectors;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import org.netbeans.api.editor.mimelookup.MimeLookup;
@@ -39,6 +41,9 @@
import org.netbeans.modules.parsing.api.Source;
import org.netbeans.modules.parsing.api.UserTask;
import org.netbeans.modules.parsing.spi.ParseException;
+import org.netbeans.modules.parsing.spi.indexing.support.IndexResult;
+import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
+import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind;
import org.netbeans.spi.editor.completion.CompletionItem;
import org.netbeans.spi.editor.completion.CompletionProvider;
import org.netbeans.spi.editor.completion.CompletionResultSet;
@@ -46,8 +51,13 @@
import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery;
import org.netbeans.spi.editor.completion.support.AsyncCompletionTask;
import org.netbeans.spi.editor.completion.support.CompletionUtilities;
+import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
+import static org.netbeans.modules.languages.antlr.AntlrIndexer.FIELD_CASE_INSENSITIVE_DECLARATION;
+import static org.netbeans.modules.languages.antlr.AntlrIndexer.FIELD_DECLARATION;
+import static org.netbeans.modules.languages.antlr.AntlrIndexer.transitiveImports;
+
/**
*
* @author Laszlo Kishalmi
@@ -103,19 +113,45 @@
@Override
public void run(ResultIterator resultIterator) throws Exception {
AntlrParserResult result = (AntlrParserResult) resultIterator.getParserResult(caretOffset);
- boolean isCaseSensitive = isCaseSensitive();
String prefix = getPrefix(result, caretOffset, true);
- if (prefix != null) {
- String mprefix = isCaseSensitive ? prefix : prefix.toUpperCase();
- Map<String, AntlrParserResult.Reference> refs = result.references;
- for (String ref : refs.keySet()) {
- String mref = isCaseSensitive ? ref : ref.toUpperCase();
- boolean match = mref.startsWith(mprefix);
- if (match) {
- CompletionItem item = CompletionUtilities.newCompletionItemBuilder(ref)
+ FileObject fo = source.getFileObject();
+ if (prefix != null && fo != null) {
+ String prefix_ci = prefix.toLowerCase(Locale.ENGLISH);
+ QuerySupport qs = AntlrIndexer.getQuerySupport(fo);
+ QuerySupport.Query.Factory qf = qs.getQueryFactory();
+ List<FileObject> candidates = transitiveImports(qs, fo);
+ QuerySupport.Query query = qf.and(
+ // Only consider the file itself or imported files
+ qf.or(
+ candidates.stream()
+ .map(fo2 -> qs.getQueryFactory().file(fo2))
+ .collect(Collectors.toList())
+ .toArray(new QuerySupport.Query[0])
+ ),
+ qf.field(
+ isCaseSensitive() ? FIELD_DECLARATION : FIELD_CASE_INSENSITIVE_DECLARATION,
+ isCaseSensitive() ? prefix : prefix_ci,
+ isCaseSensitive() ? Kind.PREFIX : Kind.CASE_INSENSITIVE_PREFIX
+ )
+ );
+
+ for (IndexResult ir : query.execute(FIELD_DECLARATION)) {
+ for (String value : ir.getValues(FIELD_DECLARATION)) {
+ if (isCaseSensitive()) {
+ if (!value.startsWith(prefix)) {
+ continue;
+ }
+ } else {
+ if(! value.toLowerCase(Locale.ENGLISH).startsWith(prefix_ci)) {
+ continue;
+ }
+ }
+ String[] values = value.split("\\\\");
+ CompletionItem item = CompletionUtilities
+ .newCompletionItemBuilder(values[0])
.startOffset(caretOffset - prefix.length())
- .leftHtmlText(ref)
- .sortText(ref)
+ .leftHtmlText(values[0])
+ .sortText(values[0])
.build();
resultSet.addItem(item);
}
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 0ffc09f..a142964 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
@@ -18,15 +18,28 @@
*/
package org.netbeans.modules.languages.antlr;
-import java.util.Map;
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
import javax.swing.text.AbstractDocument;
import javax.swing.text.Document;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenHierarchy;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.modules.csl.api.DeclarationFinder;
+import org.netbeans.modules.csl.api.ElementHandle;
+import org.netbeans.modules.csl.api.HtmlFormatter;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.csl.spi.ParserResult;
+import org.netbeans.modules.parsing.spi.indexing.support.IndexResult;
+import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
+import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Query;
+import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Query.Factory;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+
+import static org.netbeans.modules.languages.antlr.AntlrIndexer.FIELD_DECLARATION;
+import static org.netbeans.modules.languages.antlr.AntlrIndexer.transitiveImports;
/**
*
@@ -36,16 +49,13 @@
@Override
public DeclarationLocation findDeclaration(ParserResult info, int caretOffset) {
- AntlrParserResult result = (AntlrParserResult) info;
TokenSequence<?> ts = info.getSnapshot().getTokenHierarchy().tokenSequence();
ts.move(caretOffset);
ts.movePrevious();
ts.moveNext();
Token<?> token = ts.token();
String ref = String.valueOf(token.text());
- Map<String, AntlrParserResult.Reference> refs = result.references;
- AntlrParserResult.Reference aref = refs.get(ref);
- return aref != null ? new DeclarationLocation(aref.source, aref.defOffset.getStart()) : DeclarationLocation.NONE;
+ return getDeclarationLocation(info.getSnapshot().getSource().getFileObject(), ref);
}
@Override
@@ -72,4 +82,89 @@
}
}
+ public static DeclarationLocation getDeclarationLocation(FileObject sourceFile, String name) {
+ try {
+ QuerySupport qs = AntlrIndexer.getQuerySupport(sourceFile);
+ Factory qf = qs.getQueryFactory();
+ String targetDefinition = name + AntlrIndexer.SEPARATOR;
+ List<FileObject> candidates = transitiveImports(qs, sourceFile);
+ Query query = qf.and(
+ // Only consider the file itself or imported files
+ qf.or(
+ candidates.stream()
+ .map(fo -> qs.getQueryFactory().file(fo))
+ .collect(Collectors.toList())
+ .toArray(new Query[0])
+ ),
+ qf.field(FIELD_DECLARATION, targetDefinition, QuerySupport.Kind.PREFIX)
+ );
+
+ DeclarationFinder.DeclarationLocation dl = null;
+ for(IndexResult ir: query.execute(FIELD_DECLARATION)) {
+ for (String value : ir.getValues(FIELD_DECLARATION)) {
+ if (!value.startsWith(targetDefinition)) {
+ continue;
+ }
+ String[] values = value.split("\\\\");
+ int start = Integer.parseInt(values[1]);
+ int end = Integer.parseInt(values[2]);
+ AntlrStructureItem asi = new AntlrStructureItem.RuleStructureItem(name, ir.getFile(), start, end);
+ DeclarationLocation dln = new DeclarationFinder.DeclarationLocation(ir.getFile(), start, asi);
+ if (dl == null) {
+ dl = dln;
+ }
+ // If multiple declaration locations are possible (antlr4
+ // allows redefinition), the original location must be part
+ // of the alternative locations.
+ //
+ // The sortIdx describes the "depth" of the inheritence tree
+ // until the location is found. Nearer imports are preferred
+ dl.addAlternative(new AlternativeLocationImpl(dln, candidates.indexOf(ir.getFile())));
+ }
+ }
+ if(dl == null) {
+ dl = DeclarationFinder.DeclarationLocation.NONE;
+ }
+ return dl;
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ return DeclarationFinder.DeclarationLocation.NONE;
+ }
+ }
+
+ private static class AlternativeLocationImpl implements AlternativeLocation {
+
+ private final DeclarationLocation location;
+ private final int sortIdx;
+
+ public AlternativeLocationImpl(DeclarationLocation location, int sortIdx) {
+ this.location = location;
+ this.sortIdx = sortIdx;
+ }
+
+ @Override
+ public ElementHandle getElement() {
+ return getLocation().getElement();
+ }
+
+ @Override
+ public String getDisplayHtml(HtmlFormatter formatter) {
+ return getLocation().toString();
+ }
+
+ @Override
+ public DeclarationFinder.DeclarationLocation getLocation() {
+ return location;
+ }
+
+ @Override
+ public int compareTo(DeclarationFinder.AlternativeLocation o) {
+ if(o instanceof AlternativeLocationImpl) {
+ return sortIdx - ((AlternativeLocationImpl) o).sortIdx;
+ } else {
+ return 0;
+ }
+ }
+
+ }
}
diff --git a/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrIndexer.java b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrIndexer.java
new file mode 100644
index 0000000..bd87004
--- /dev/null
+++ b/java/languages.antlr/src/org/netbeans/modules/languages/antlr/AntlrIndexer.java
@@ -0,0 +1,245 @@
+/*
+ * 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.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.editor.mimelookup.MimeRegistrations;
+import org.netbeans.modules.languages.antlr.v3.Antlr3Language;
+import org.netbeans.modules.languages.antlr.v4.Antlr4Language;
+import org.netbeans.modules.languages.antlr.v4.Antlr4ParserResult;
+import org.netbeans.modules.parsing.api.Snapshot;
+import org.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.modules.parsing.spi.indexing.Context;
+import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexer;
+import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory;
+import org.netbeans.modules.parsing.spi.indexing.Indexable;
+import org.netbeans.modules.parsing.spi.indexing.support.IndexDocument;
+import org.netbeans.modules.parsing.spi.indexing.support.IndexingSupport;
+import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+
+public class AntlrIndexer extends EmbeddingIndexer {
+
+ // Used to split
+ public static final String SEPARATOR = "\\";
+ public static final String FIELD_IMPORT = "import";
+ public static final String FIELD_DECLARATION = "declaration";
+ public static final String FIELD_CASE_INSENSITIVE_DECLARATION = "ci-declaration";
+ public static final String FIELD_OCCURRENCE = "occurrence";
+ public static final String FIELD_CASE_INSENSITIVE_OCCURRENCE = "ci-occurrence";
+
+ private static final Logger LOG = Logger.getLogger(AntlrIndexer.class.getName());
+
+ @Override
+ protected void index(Indexable indexable, Parser.Result parserResult, Context context) {
+ IndexingSupport support;
+ try {
+ support = IndexingSupport.getInstance(context);
+ } catch (IOException ex) {
+ LOG.log(Level.WARNING, null, ex);
+ return;
+ }
+
+ IndexDocument id = support.createDocument(indexable);
+
+ if (parserResult instanceof AntlrParserResult) {
+ Map<String, AntlrParserResult.Reference> refs = ((AntlrParserResult) parserResult).references;
+ refs.values().stream().forEach(r -> {
+ String declarationValue = r.name + SEPARATOR + r.defOffset.getStart() + SEPARATOR + r.defOffset.getEnd();
+ id.addPair(FIELD_DECLARATION, declarationValue, true, true);
+ id.addPair(FIELD_CASE_INSENSITIVE_DECLARATION, ci(declarationValue), true, true);
+ if(r.occurances != null) {
+ r.occurances.stream().forEach(c2 -> {
+ String occurrenceValue = r.name + SEPARATOR + c2.getStart() + SEPARATOR + c2.getEnd();
+ id.addPair(FIELD_OCCURRENCE, occurrenceValue, true, true);
+ id.addPair(FIELD_CASE_INSENSITIVE_OCCURRENCE, ci(declarationValue), true, true);
+ });
+ }
+ });
+ }
+
+ if (parserResult instanceof Antlr4ParserResult) {
+ ((Antlr4ParserResult) parserResult).getImports()
+ .forEach(s -> {
+ id.addPair(FIELD_IMPORT, s, true, true);
+ });
+ }
+
+ support.addDocument(id);
+ }
+
+ @MimeRegistrations({
+ @MimeRegistration(
+ mimeType = Antlr3Language.MIME_TYPE,
+ service = EmbeddingIndexerFactory.class
+ ),
+ @MimeRegistration(
+ mimeType = Antlr4Language.MIME_TYPE,
+ service = EmbeddingIndexerFactory.class
+ )
+ })
+ public static final class Factory extends EmbeddingIndexerFactory {
+
+ public static final String NAME = "antlr"; // NOI18N
+ public static final int VERSION = 4;
+ private static final int PRIORITY = 100;
+
+ @Override
+ public EmbeddingIndexer createIndexer(final Indexable indexable, final Snapshot snapshot) {
+ if (isIndexable(indexable, snapshot)) {
+ return new AntlrIndexer();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getIndexerName() {
+ return NAME;
+ }
+
+ @Override
+ public int getIndexVersion() {
+ return VERSION;
+ }
+
+ private boolean isIndexable(Indexable indexable, Snapshot snapshot) {
+ return Antlr3Language.MIME_TYPE.equals(snapshot.getMimeType())
+ || Antlr4Language.MIME_TYPE.equals(snapshot.getMimeType());
+ }
+
+ @Override
+ public void filesDeleted(Iterable<? extends Indexable> deleted, Context context) {
+ try {
+ IndexingSupport is = IndexingSupport.getInstance(context);
+ for (Indexable i : deleted) {
+ is.removeDocuments(i);
+ }
+ } catch (IOException ioe) {
+ LOG.log(Level.WARNING, null, ioe);
+ }
+ }
+
+ @Override
+ public void rootsRemoved(final Iterable<? extends URL> removedRoots) {
+ }
+
+ @Override
+ public void filesDirty(Iterable<? extends Indexable> dirty, Context context) {
+ try {
+ IndexingSupport is = IndexingSupport.getInstance(context);
+ for (Indexable i : dirty) {
+ is.markDirtyDocuments(i);
+ }
+ } catch (IOException ioe) {
+ LOG.log(Level.WARNING, null, ioe);
+ }
+ }
+
+ @Override
+ public int getPriority() {
+ return PRIORITY;
+ }
+ }
+
+
+ /**
+ * Find all imports of the specified file (including transitive ones).
+ *
+ * @param qs
+ * @param sourceFile
+ * @return
+ */
+ public static List<FileObject> transitiveImports(QuerySupport qs, FileObject sourceFile) {
+ List<FileObject> result = new ArrayList<>();
+ LinkedList<FileObject> toScan = new LinkedList<>();
+ Set<String> seen = new HashSet<>();
+ result.add(sourceFile);
+ toScan.add(sourceFile);
+ seen.add(sourceFile.getName());
+ while(! toScan.isEmpty()) {
+ FileObject target = toScan.poll();
+ try {
+ qs.getQueryFactory()
+ .file(target)
+ .execute(AntlrIndexer.FIELD_IMPORT)
+ .forEach(c -> {
+ for(String value: c.getValues(AntlrIndexer.FIELD_IMPORT)) {
+ if(! seen.contains(value)) {
+ seen.add(value);
+ }
+ FileObject foAntlr;
+ if(Antlr3Language.MIME_TYPE.equals(sourceFile.getMIMEType())) {
+ foAntlr = sourceFile.getParent().getFileObject(value, "g");
+ } else {
+ foAntlr = sourceFile.getParent().getFileObject(value, "g4");
+ }
+ if(foAntlr.canRead()) {
+ toScan.add(foAntlr);
+ result.add(foAntlr);
+ }
+ }
+ });
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ return result;
+ }
+
+ private static QuerySupport getQuerySupport(final Collection<FileObject> roots) {
+ try {
+ return QuerySupport.forRoots(
+ AntlrIndexer.Factory.NAME,
+ AntlrIndexer.Factory.VERSION,
+ roots.toArray(new FileObject[0]));
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ return null;
+ }
+
+ public static QuerySupport getQuerySupport(final FileObject source) {
+ return getQuerySupport(QuerySupport.findRoots(source,
+ null,
+ null,
+ Collections.<String>emptySet()));
+ }
+
+ /**
+ * Create string representation for case insensitive search
+ */
+ private static String ci(String declarationValue) {
+ return declarationValue.toLowerCase(Locale.ENGLISH);
+ }
+}
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 bced56f..e98d7cc 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
@@ -19,14 +19,10 @@
package org.netbeans.modules.languages.antlr;
import java.util.ArrayList;
-import java.util.Deque;
-import java.util.HashSet;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
-import java.util.concurrent.atomic.AtomicBoolean;
import org.antlr.v4.runtime.ANTLRErrorListener;
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.Parser;
@@ -40,7 +36,6 @@
import org.netbeans.modules.csl.spi.DefaultError;
import org.netbeans.modules.csl.spi.ParserResult;
import org.netbeans.modules.parsing.api.Snapshot;
-import org.netbeans.modules.parsing.api.Source;
import org.openide.filesystems.FileObject;
/**
@@ -55,54 +50,26 @@
public final List<OffsetRange> folds = new ArrayList<>();
public final List<AntlrStructureItem> structure = new ArrayList<>();
- final Set<FileObject> queued = new HashSet<>();
- final Deque<T> parsingQueue = new LinkedList<>();
-
- final AtomicBoolean finished = new AtomicBoolean();
+ volatile boolean finished = false;
public AntlrParserResult(Snapshot snapshot) {
super(snapshot);
- addParseTask(snapshot, false);
}
-
public AntlrParserResult get() {
- while (!parsingQueue.isEmpty()) {
- evaluateParser(parsingQueue.removeFirst());
- }
- // Second phase scan
- T secondPhase = createParser(getSnapshot());
- secondPhase.addParseListener(createOccurancesListener());
- evaluateParser(secondPhase);
- finished.set(true);
- return this;
- }
-
- protected final void addParseTask(FileObject fo) {
- Source src = Source.create(fo);
- addParseTask(src.createSnapshot(), true);
- }
-
-
- protected final void addParseTask(Snapshot snapshot, boolean imported) {
- // TODO: In a more decent implementation we should not try to parse
- // other files. Parser results in other files should be put
- // and retrieved by the Indexer infrastructure, which is yet to be
- // implemented.
- FileObject fo = snapshot.getSource().getFileObject();
- if (queued.add(fo)) {
- T parser = createParser(snapshot);
-
-
- if (!imported) {
- parser.addErrorListener(createErrorListener(fo));
- parser.addParseListener(createFoldListener());
- }
+ if (! finished) {
+ FileObject fo = getSnapshot().getSource().getFileObject();
+ T parser = createParser(getSnapshot());
+ parser.addErrorListener(createErrorListener(fo));
+ parser.addParseListener(createFoldListener());
parser.addParseListener(createReferenceListener(fo));
parser.addParseListener(createImportListener(fo));
parser.addParseListener(createStructureListener(fo));
- parsingQueue.add(parser);
+ parser.addParseListener(createOccurancesListener());
+ evaluateParser(parser);
+ finished = true;
}
+ return this;
}
@Override
@@ -117,7 +84,7 @@
@Override
protected boolean processingFinished() {
- return finished.get();
+ return finished;
}
public static class Reference {
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 c8d927f..9cd8325 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
@@ -19,6 +19,7 @@
package org.netbeans.modules.languages.antlr.v4;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.antlr.parser.antlr4.ANTLRv4Lexer;
import org.antlr.parser.antlr4.ANTLRv4Parser;
@@ -40,6 +41,8 @@
*/
public final class Antlr4ParserResult extends AntlrParserResult<ANTLRv4Parser> {
+ private List<String> imports = new ArrayList<>();
+
public Antlr4ParserResult(Snapshot snapshot) {
super(snapshot);
}
@@ -85,10 +88,7 @@
protected ParseTreeListener createImportListener(FileObject source) {
return new ANTLRv4ParserBaseListener() {
private void addImport(String importedGrammar) {
- FileObject importedFo = source.getParent().getFileObject(importedGrammar + ".g4"); //NOI18N
- if (importedFo != null) {
- addParseTask(importedFo);
- }
+ imports.add(importedGrammar);
}
@Override
@@ -235,6 +235,7 @@
};
}
-
-
+ public List<String> getImports() {
+ return Collections.unmodifiableList(imports);
+ }
}