/* * Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC * All rights reserved. * * The source code of this document is proprietary work, and is not licensed for * distribution. For information about licensing, contact Sam Harwell at: * sam@tunnelvisionlabs.com */ package org.antlr.works.editor.grammar.fold; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.antlr.netbeans.editor.text.DocumentSnapshot; import org.antlr.netbeans.editor.text.OffsetRegion; import org.antlr.netbeans.editor.text.SnapshotPositionRegion; import org.antlr.netbeans.parsing.spi.ParserData; import org.antlr.runtime.CommonToken; import org.antlr.runtime.Token; import org.antlr.runtime.tree.CommonTree; import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.runtime.misc.IntervalSet; import org.antlr.v4.tool.ast.GrammarAST; import org.antlr.v4.tool.ast.GrammarRootAST; import org.antlr.works.editor.antlr3.fold.AbstractAntlrFoldScanner; import org.antlr.works.editor.grammar.parser.CompiledModel; import org.antlr.works.editor.grammar.parser.CompiledModelV4; /** * * @author Sam Harwell */ public class GrammarFoldScannerV4 extends AbstractAntlrFoldScanner<CompiledModel> { @Override protected List<FoldInfo> calculateFolds(ParserData<CompiledModel> baseResult) { CompiledModelV4 result4 = (CompiledModelV4)baseResult.getData(); if (result4 == null) { return Collections.emptyList(); } DocumentSnapshot snapshot = result4.getSnapshot(); final List<FoldInfo> folds = new ArrayList<>(); GrammarRootAST parseResult = result4.getResult().getResult(); if (parseResult != null) { IntervalSet foldTypes = new IntervalSet(); foldTypes.add(ANTLRParser.MODE); foldTypes.add(ANTLRParser.RULE); foldTypes.add(ANTLRParser.TOKENS_SPEC); foldTypes.add(ANTLRParser.OPTIONS); // foldTypes.add(ANTLRParser.AT); List<GrammarAST> foldNodes = parseResult.getNodesWithType(foldTypes); for (GrammarAST child : foldNodes) { // imported grammars merge trees from multiple files. only consider // trees from the current file for folding. if (child.g != parseResult.g) { continue; } String blockHint; switch (child.getType()) { case ANTLRParser.MODE: blockHint = "mode " + child.getChild(0).getText(); break; case ANTLRParser.RULE: blockHint = child.getChild(0).getText() + "..."; break; case ANTLRParser.TOKENS_SPEC: blockHint = "tokens {...}"; break; case ANTLRParser.OPTIONS: blockHint = "options {...}"; break; // case ANTLRParser.AT: // if (child.getChildCount() == 2) { // blockHint = "@" + child.getChild(0) + " {...}"; // } else if (child.getChildCount() == 3) { // blockHint = "@" + child.getChild(0) + "::" + child.getChild(1).getText() + " {...}"; // } // break; default: continue; } if (blockHint == null || blockHint.isEmpty()) { continue; } FoldInfo fold = createFold(child, blockHint, snapshot, result4.getResult().getTokens()); if (fold != null) { folds.add(fold); } } for (CommonToken token : result4.getResult().getTokens()) { switch (token.getType()) { case ANTLRParser.DOC_COMMENT: case ANTLRParser.COMMENT: case ANTLRParser.ACTION: int startLine = snapshot.findLineNumber(token.getStartIndex()); int stopLine = snapshot.findLineNumber(token.getStopIndex()); if (startLine >= stopLine) { continue; } String blockHint = null; if (token.getType() == ANTLRParser.DOC_COMMENT) { blockHint = "/** ... */"; } else if (token.getType() == ANTLRParser.COMMENT) { blockHint = "/* ... */"; } else if (token.getType() == ANTLRParser.ACTION) { blockHint = "{}"; } else { throw new IllegalStateException(); } SnapshotPositionRegion region = new SnapshotPositionRegion(snapshot, OffsetRegion.fromBounds(token.getStartIndex(), token.getStopIndex() + 1)); FoldInfo info = new FoldInfo(region, blockHint); folds.add(info); break; default: break; } } } return folds; } @Override protected CommonToken getStartToken(CommonTree child, DocumentSnapshot snapshot, CommonToken[] tokens) { CommonToken startToken = super.getStartToken(child, snapshot, tokens); if (startToken.getType() == ANTLRParser.DOC_COMMENT) { for (int index = child.getTokenStartIndex(); index <= child.getTokenStopIndex(); index++) { startToken = tokens[index]; if (startToken.getType() != ANTLRParser.DOC_COMMENT && startToken.getChannel() == Token.DEFAULT_CHANNEL) { break; } } } return startToken; } }