private static Collection<String> suggestKeywords(PsiElement position) { TextRange posRange = position.getTextRange(); CupFile posFile = (CupFile) position.getContainingFile(); TextRange range = new TextRange(0, posRange.getStartOffset()); String text = range.isEmpty() ? CompletionInitializationContext.DUMMY_IDENTIFIER : range.substring(posFile.getText()); int completionOffset = posRange.getStartOffset() - range.getStartOffset(); // = posRange.getStartOffset() ... PsiFile file = PsiFileFactory.getInstance(posFile.getProject()).createFileFromText("a.cup", CupLanguage.INSTANCE, text, true, false); GeneratedParserUtilBase.CompletionState state = new GeneratedParserUtilBase.CompletionState(completionOffset) { @Nullable @Override public String convertItem(Object o) { if (o == CupTypes.IDENTIFIER) { return null; } return o.toString(); } }; file.putUserData(GeneratedParserUtilBase.COMPLETION_STATE_KEY, state); TreeUtil.ensureParsed(file.getNode()); return state.items; }
@Override public ASTNode findChildByRole(int role) { LOG.assertTrue(ChildRole.isUnique(role)); switch(role){ default: return null; case ChildRole.BREAK_KEYWORD: return findChildByType(BREAK_KEYWORD); case ChildRole.LABEL: return findChildByType(IDENTIFIER); case ChildRole.CLOSING_SEMICOLON: return TreeUtil.findChildBackward(this, SEMICOLON); } }
@Override public ASTNode findChildByRole(int role) { LOG.assertTrue(ChildRole.isUnique(role)); switch(role){ default: return null; case ChildRole.RETURN_KEYWORD: return findChildByType(RETURN_KEYWORD); case ChildRole.RETURN_VALUE: return findChildByType(EXPRESSION_BIT_SET); case ChildRole.CLOSING_SEMICOLON: return TreeUtil.findChildBackward(this, SEMICOLON); } }
@Override public ASTNode findChildByRole(int role){ LOG.assertTrue(ChildRole.isUnique(role)); switch(role){ default: return null; case ChildRole.IMPORT_KEYWORD: return getFirstChildNode(); case ChildRole.IMPORT_ON_DEMAND_DOT: return findChildByType(JavaTokenType.DOT); case ChildRole.IMPORT_ON_DEMAND_ASTERISK: return findChildByType(JavaTokenType.ASTERISK); case ChildRole.CLOSING_SEMICOLON: return TreeUtil.findChildBackward(this, JavaTokenType.SEMICOLON); } }
@Override public ASTNode findChildByRole(int role) { LOG.assertTrue(ChildRole.isUnique(role)); switch(role){ default: return null; case ChildRole.THROW_KEYWORD: return findChildByType(THROW_KEYWORD); case ChildRole.EXCEPTION: return findChildByType(EXPRESSION_BIT_SET); case ChildRole.CLOSING_SEMICOLON: return TreeUtil.findChildBackward(this, SEMICOLON); } }
private static int stripAnnotationsFromModifierList(@NotNull PsiElement element) { TextRange textRange = element.getTextRange(); if (textRange == null) return 0; PsiAnnotation lastAnnotation = null; for (PsiElement child : element.getChildren()) { if (child instanceof PsiAnnotation) lastAnnotation = (PsiAnnotation)child; } if (lastAnnotation == null) { return textRange.getStartOffset(); } ASTNode node = lastAnnotation.getNode(); if (node != null) { do { node = TreeUtil.nextLeaf(node); } while (node != null && ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(node.getElementType())); } if (node != null) return node.getTextRange().getStartOffset(); return textRange.getStartOffset(); }
@Nullable private static PsiFile getContainingFileByTree(@NotNull final PsiElement changeScope) { // there could be pseudo physical trees (JSPX/JSP/etc.) which must not translate // any changes to document and not to fire any PSI events final PsiFile psiFile; final ASTNode node = changeScope.getNode(); if (node == null) { psiFile = changeScope.getContainingFile(); } else { final FileElement fileElement = TreeUtil.getFileElement((TreeElement)node); // assert fileElement != null : "Can't find file element for node: " + node; // Hack. the containing tree can be invalidated if updating supplementary trees like HTML in JSP. if (fileElement == null) return null; psiFile = (PsiFile)fileElement.getPsi(); } return psiFile.getNode() != null ? psiFile : null; }
private static int getMatchingLength(@NotNull FileElement treeElement, @NotNull CharSequence text, boolean fromStart) { int patternIndex = fromStart ? 0 : text.length() - 1; int finalPatternIndex = fromStart ? text.length() - 1 : 0; int direction = fromStart ? 1 : -1; ASTNode leaf = fromStart ? TreeUtil.findFirstLeaf(treeElement, false) : TreeUtil.findLastLeaf(treeElement, false); int result = 0; while (leaf != null && (fromStart ? patternIndex <= finalPatternIndex : patternIndex >= finalPatternIndex)) { if (!(leaf instanceof ForeignLeafPsiElement)) { CharSequence chars = leaf.getChars(); if (chars.length() > 0) { int matchingLength = getLeafMatchingLength(chars, text, patternIndex, finalPatternIndex, direction); result += matchingLength; if (matchingLength != chars.length()) { break; } patternIndex += (fromStart ? matchingLength : -matchingLength); } } leaf = fromStart ? TreeUtil.nextLeaf(leaf, false) : TreeUtil.prevLeaf(leaf, false); } return result; }
private static void markToReformatBeforeOrInsertWhitespace(final ASTNode left, @NotNull final ASTNode right) { final Language leftLang = left != null ? PsiUtilCore.getNotAnyLanguage(left) : null; final Language rightLang = PsiUtilCore.getNotAnyLanguage(right); ASTNode generatedWhitespace = null; if (leftLang != null && leftLang.isKindOf(rightLang)) { generatedWhitespace = LanguageTokenSeparatorGenerators.INSTANCE.forLanguage(leftLang).generateWhitespaceBetweenTokens(left, right); } else if (rightLang.isKindOf(leftLang)) { generatedWhitespace = LanguageTokenSeparatorGenerators.INSTANCE.forLanguage(rightLang).generateWhitespaceBetweenTokens(left, right); } if (generatedWhitespace != null) { final TreeUtil.CommonParentState parentState = new TreeUtil.CommonParentState(); TreeUtil.prevLeaf((TreeElement)right, parentState); parentState.nextLeafBranchStart.getTreeParent().addChild(generatedWhitespace, parentState.nextLeafBranchStart); } else { markToReformatBefore(right, true); } }
private static boolean hasLineBreakAfterIgnoringComments(@NotNull ASTNode node) { for (ASTNode next = TreeUtil.nextLeaf(node); next != null; next = TreeUtil.nextLeaf(next)) { if (isWhitespace(next)) { if (next.textContains('\n')) { return true; } } else if (next.getElementType() == PyTokenTypes.END_OF_LINE_COMMENT) { return true; } else { break; } } return false; }
public static int calcBaseIndent(ASTNode chameleon) { final ASTNode prevLeaf = TreeUtil.prevLeaf(chameleon, true); if (prevLeaf == null) { return 0; } final CharSequence text = prevLeaf.getChars(); int offset = text.length(); int answer = 0; while (--offset > 0) { final char c = text.charAt(offset); if (c == '\n') { break; } if (c != ' ' && c != '\t') { answer = 0; break; } answer++; } return answer; }
public void _testPerformance1() throws Exception { final String text = loadFile("pallada.xml"); long time = System.currentTimeMillis(); final PsiFile file = createFile("test.xml", text); transformAllChildren(file.getNode()); System.out.println("Old parsing took " + (System.currentTimeMillis() - time) + "ms"); int index = 0; while (index++ < 10) { newParsing(text); } LeafElement firstLeaf = TreeUtil.findFirstLeaf(file.getNode()); index = 0; do { index++; } while ((firstLeaf = TreeUtil.nextLeaf(firstLeaf, null)) != null); System.out.println("For " + index + " lexems"); }
public void _testPerformance2() throws Exception { final String text = loadFile("performance2.xml"); long time = System.currentTimeMillis(); final PsiFile file = createFile("test.xml", text); transformAllChildren(file.getNode()); System.out.println("Old parsing took " + (System.currentTimeMillis() - time) + "ms"); int index = 0; while (index++ < 10) { newParsing(text); } LeafElement firstLeaf = TreeUtil.findFirstLeaf(file.getNode()); index = 0; do { index++; } while ((firstLeaf = TreeUtil.nextLeaf(firstLeaf, null)) != null); System.out.println("For " + index + " lexems"); }
@Override public void deleteChildInternal(@NotNull ASTNode child) { PsiElement element = child.getPsi(); if (element instanceof GrExpression || element instanceof GrNamedArgument) { ASTNode prev = TreeUtil.skipElementsBack(child.getTreePrev(), TokenSets.WHITE_SPACES_OR_COMMENTS); if (prev != null && prev.getElementType() == GroovyTokenTypes.mCOMMA) { final ASTNode pprev = prev.getTreePrev(); if (pprev != null && PsiImplUtil.isWhiteSpaceOrNls(pprev)) { super.deleteChildInternal(pprev); } super.deleteChildInternal(prev); } else { ASTNode next = TreeUtil.skipElements(child.getTreeNext(), TokenSets.WHITE_SPACES_OR_COMMENTS); if (next != null && next.getElementType() == GroovyTokenTypes.mCOMMA) { final ASTNode nnext = next.getTreeNext(); if (nnext != null && PsiImplUtil.isWhiteSpaceOrNls(nnext)) { super.deleteChildInternal(nnext); } super.deleteChildInternal(next); } } } super.deleteChildInternal(child); }
public void deleteChildInternal(@NotNull ASTNode child) { PsiElement element = child.getPsi(); if (element instanceof GrExpression || element instanceof GrNamedArgument) { ASTNode prev = TreeUtil.skipElementsBack(child.getTreePrev(), TokenSets.WHITE_SPACES_OR_COMMENTS); if (prev != null && prev.getElementType() == mCOMMA) { final ASTNode pprev = prev.getTreePrev(); if (pprev != null && TokenSets.WHITE_SPACES_SET.contains(pprev.getElementType())) { super.deleteChildInternal(pprev); } super.deleteChildInternal(prev); } else { ASTNode next = TreeUtil.skipElements(child.getTreeNext(), TokenSets.WHITE_SPACES_OR_COMMENTS); if (next != null && next.getElementType() == mCOMMA) { final ASTNode nnext = next.getTreeNext(); if (nnext != null && TokenSets.WHITE_SPACES_SET.contains(nnext.getElementType())) { super.deleteChildInternal(nnext); } super.deleteChildInternal(next); } } } super.deleteChildInternal(child); }
@SuppressWarnings("unchecked") private static void addRuleRefFoldingDescriptors(List<FoldingDescriptor> descriptors, PsiElement root) { for (RuleSpecNode specNode : PsiTreeUtil.findChildrenOfType(root, RuleSpecNode.class)) { GrammarElementRefNode refNode = PsiTreeUtil.findChildOfAnyType(specNode, GrammarElementRefNode.class); if (refNode == null) continue; PsiElement nextSibling = refNode.getNextSibling(); if (nextSibling == null) continue; int startOffset = nextSibling.getTextOffset(); ASTNode backward = TreeUtil.findChildBackward(specNode.getNode(), SEMICOLON); if (backward == null) continue; int endOffset = backward.getTextRange().getEndOffset(); if (startOffset >= endOffset) continue; descriptors.add(new FoldingDescriptor(specNode, new TextRange(startOffset, endOffset))); } }
@Nullable private static PsiFile getContainingFileByTree(@Nonnull final PsiElement changeScope) { // there could be pseudo physical trees (JSPX/JSP/etc.) which must not translate // any changes to document and not to fire any PSI events final PsiFile psiFile; final ASTNode node = changeScope.getNode(); if (node == null) { psiFile = changeScope.getContainingFile(); } else { final FileElement fileElement = TreeUtil.getFileElement((TreeElement)node); // assert fileElement != null : "Can't find file element for node: " + node; // Hack. the containing tree can be invalidated if updating supplementary trees like HTML in JSP. if (fileElement == null) return null; psiFile = (PsiFile)fileElement.getPsi(); } return psiFile.getNode() != null ? psiFile : null; }
private static void markToReformatBeforeOrInsertWhitespace(final ASTNode left, @Nonnull final ASTNode right) { final Language leftLang = left != null ? PsiUtilCore.getNotAnyLanguage(left) : null; final Language rightLang = PsiUtilCore.getNotAnyLanguage(right); ASTNode generatedWhitespace = null; if (leftLang != null && leftLang.isKindOf(rightLang)) { generatedWhitespace = LanguageTokenSeparatorGenerators.INSTANCE.forLanguage(leftLang).generateWhitespaceBetweenTokens(left, right); } else if (rightLang.isKindOf(leftLang)) { generatedWhitespace = LanguageTokenSeparatorGenerators.INSTANCE.forLanguage(rightLang).generateWhitespaceBetweenTokens(left, right); } if (generatedWhitespace != null) { final TreeUtil.CommonParentState parentState = new TreeUtil.CommonParentState(); TreeUtil.prevLeaf((TreeElement)right, parentState); parentState.nextLeafBranchStart.getTreeParent().addChild(generatedWhitespace, parentState.nextLeafBranchStart); } else { markToReformatBefore(right, true); } }
private static int getMatchingLength(@Nonnull FileElement treeElement, @Nonnull CharSequence text, boolean fromStart) { int patternIndex = fromStart ? 0 : text.length() - 1; int finalPatternIndex = fromStart ? text.length() - 1 : 0; int direction = fromStart ? 1 : -1; ASTNode leaf = fromStart ? TreeUtil.findFirstLeaf(treeElement, false) : TreeUtil.findLastLeaf(treeElement, false); int result = 0; while (leaf != null && (fromStart ? patternIndex <= finalPatternIndex : patternIndex >= finalPatternIndex)) { if (!(leaf instanceof ForeignLeafPsiElement)) { CharSequence chars = leaf.getChars(); if (chars.length() > 0) { int matchingLength = getLeafMatchingLength(chars, text, patternIndex, finalPatternIndex, direction); result += matchingLength; if (matchingLength != chars.length()) { break; } patternIndex += fromStart ? matchingLength : -matchingLength; } } leaf = fromStart ? TreeUtil.nextLeaf(leaf, false) : TreeUtil.prevLeaf(leaf, false); } return result; }
@Override public final ASTNode findChildByRole(final int role) { LOG.assertTrue(ChildRole.isUnique(role)); switch(role) { case ChildRole.REFERENCE_NAME: return TreeUtil.findChildBackward(this, JavaTokenType.IDENTIFIER); case ChildRole.REFERENCE_PARAMETER_LIST: { TreeElement lastChild = getLastChildNode(); return lastChild.getElementType() == JavaElementType.REFERENCE_PARAMETER_LIST ? lastChild : null; } case ChildRole.QUALIFIER: return findChildByType(JavaElementType.JAVA_CODE_REFERENCE); case ChildRole.DOT: return findChildByType(JavaTokenType.DOT); } return null; }
@Override public ASTNode findChildByRole(int role) { LOG.assertTrue(ChildRole.isUnique(role)); switch(role){ default: return null; case ChildRole.MODIFIER_LIST: return findChildByType(MODIFIER_LIST); case ChildRole.TYPE: return findChildByType(TYPE); case ChildRole.NAME: return findChildByType(JavaTokenType.IDENTIFIER); case ChildRole.INITIALIZER_EQ: return findChildByType(JavaTokenType.EQ); case ChildRole.INITIALIZER: return findChildByType(ElementType.EXPRESSION_BIT_SET); case ChildRole.CLOSING_SEMICOLON: return TreeUtil.findChildBackward(this, JavaTokenType.SEMICOLON); } }
@Override public ASTNode findChildByRole(int role) { LOG.assertTrue(ChildRole.isUnique(role)); switch(role) { default: return null; case ChildRole.PACKAGE_KEYWORD: return findChildByType(JavaTokenType.PACKAGE_KEYWORD); case ChildRole.PACKAGE_REFERENCE: return findChildByType(JavaElementType.JAVA_CODE_REFERENCE); case ChildRole.CLOSING_SEMICOLON: return TreeUtil.findChildBackward(this, JavaTokenType.SEMICOLON); case ChildRole.MODIFIER_LIST: return findChildByType(JavaElementType.MODIFIER_LIST); } }
public static boolean canStickChildrenTogether(final ASTNode child1, final ASTNode child2) { if(child1 == null || child2 == null) { return true; } if(isWS(child1) || isWS(child2)) { return true; } ASTNode token1 = TreeUtil.findLastLeaf(child1); ASTNode token2 = TreeUtil.findFirstLeaf(child2); LOG.assertTrue(token1 != null); LOG.assertTrue(token2 != null); return !(token1.getElementType() instanceof IJavaElementType) || !(token2.getElementType() instanceof IJavaElementType) || canStickJavaTokens(token1, token2); }
@Override protected String replaceWithPsiInLeaf(TextRange textRange, String whiteSpace, ASTNode leafElement) { if (!myCanModifyAllWhiteSpaces) { if (AppleScriptPsiImplUtil.isWhiteSpaceOrNls(leafElement)) return null; } IElementType elementTypeToUse = TokenType.WHITE_SPACE; ASTNode prevNode = TreeUtil.prevLeaf(leafElement); if (prevNode != null && AppleScriptPsiImplUtil.isWhiteSpaceOrNls(prevNode)) { elementTypeToUse = prevNode.getElementType(); } FormatterUtil.replaceWhiteSpace(whiteSpace, leafElement, elementTypeToUse, textRange); return whiteSpace; }
@Override public void handleElement(Lexer lexer) { if (seenContentType && seenScript && !seenAttribute) { @NonNls String mimeType = TreeUtil.getTokenText(lexer); scriptType = caseInsensitive ? mimeType.toLowerCase(Locale.US) : mimeType; } if (seenStylesheetType && seenStyle && !seenAttribute) { @NonNls String rel = TreeUtil.getTokenText(lexer).trim(); styleType = caseInsensitive ? rel.toLowerCase(Locale.US) : rel; } }
@Override public ASTNode findChildByRole(int role){ LOG.assertTrue(ChildRole.isUnique(role)); switch(role){ default: return null; case ChildRole.DO_KEYWORD: return findChildByType(DO_KEYWORD); case ChildRole.LOOP_BODY: return PsiImplUtil.findStatementChild(this); case ChildRole.WHILE_KEYWORD: return findChildByType(WHILE_KEYWORD); case ChildRole.LPARENTH: return findChildByType(LPARENTH); case ChildRole.CONDITION: return findChildByType(EXPRESSION_BIT_SET); case ChildRole.RPARENTH: return findChildByType(RPARENTH); case ChildRole.CLOSING_SEMICOLON: return TreeUtil.findChildBackward(this, SEMICOLON); } }
@Override public ASTNode findChildByRole(int role) { LOG.assertTrue(ChildRole.isUnique(role)); switch(role){ default: return null; case ChildRole.EXPRESSION_LIST: return findChildByType(EXPRESSION_LIST); case ChildRole.CLOSING_SEMICOLON: return TreeUtil.findChildBackward(this, SEMICOLON); } }