@Override public PsiNameValuePairStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { String name = null; String value = null; List<LighterASTNode> children = tree.getChildren(node); for (LighterASTNode child : children) { if (child.getTokenType() == JavaTokenType.IDENTIFIER) { name = RecordUtil.intern(tree.getCharTable(), child); } else if (child.getTokenType() == JavaElementType.LITERAL_EXPRESSION) { value = RecordUtil.intern(tree.getCharTable(), tree.getChildren(child).get(0)); value = StringUtil.unquoteString(value); } } return new PsiNameValuePairStubImpl(parentStub, StringRef.fromString(name), StringRef.fromString(value)); }
@Override public PsiImportStatementStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { boolean isOnDemand = false; String refText = null; for (LighterASTNode child : tree.getChildren(node)) { IElementType type = child.getTokenType(); if (type == JavaElementType.JAVA_CODE_REFERENCE || type == JavaElementType.IMPORT_STATIC_REFERENCE) { refText = JavaSourceUtil.getReferenceText(tree, child); } else if (type == JavaTokenType.ASTERISK) { isOnDemand = true; } } byte flags = PsiImportStatementStubImpl.packFlags(isOnDemand, node.getTokenType() == JavaElementType.IMPORT_STATIC_STATEMENT); return new PsiImportStatementStubImpl(parentStub, refText, flags); }
public static boolean isDeprecatedByAnnotation(@NotNull LighterAST tree, @NotNull LighterASTNode modList) { for (final LighterASTNode child : tree.getChildren(modList)) { if (child.getTokenType() == JavaElementType.ANNOTATION) { final LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, child, JavaElementType.JAVA_CODE_REFERENCE); if (ref != null) { final LighterASTNode id = LightTreeUtil.firstChildOfType(tree, ref, JavaTokenType.IDENTIFIER); if (id != null) { final String name = intern(tree.getCharTable(), id); if (DEPRECATED_ANNOTATION_NAME.equals(name)) return true; } } } } return false; }
@NotNull @Override protected StubElement createStubForFile(@NotNull PsiFile file, @NotNull LighterAST tree) { if (!(file instanceof PsiJavaFile)) { return super.createStubForFile(file, tree); } String refText = ""; LighterASTNode pkg = LightTreeUtil.firstChildOfType(tree, tree.getRoot(), JavaElementType.PACKAGE_STATEMENT); if (pkg != null) { LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, pkg, JavaElementType.JAVA_CODE_REFERENCE); if (ref != null) { refText = JavaSourceUtil.getReferenceText(tree, ref); } } return new PsiJavaFileStubImpl((PsiJavaFile)file, StringRef.fromString(refText), false); }
public static void toBuffer(@NotNull LighterAST tree, @NotNull LighterASTNode node, @NotNull StringBuilder buffer, @Nullable TokenSet skipTypes) { if (skipTypes != null && skipTypes.contains(node.getTokenType())) { return; } if (node instanceof LighterASTTokenNode) { buffer.append(((LighterASTTokenNode)node).getText()); return; } if (node instanceof LighterLazyParseableNode) { buffer.append(((LighterLazyParseableNode)node).getText()); return; } List<LighterASTNode> children = tree.getChildren(node); for (int i = 0, size = children.size(); i < size; ++i) { toBuffer(tree, children.get(i), buffer, skipTypes); } tree.disposeChildren(children); }
@Override public PsiNameValuePairStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { String name = null; String value = null; List<LighterASTNode> children = tree.getChildren(node); for (LighterASTNode child : children) { if (child.getTokenType() == JavaTokenType.IDENTIFIER) { name = RecordUtil.intern(tree.getCharTable(), child); } else if (child.getTokenType() == JavaElementType.LITERAL_EXPRESSION) { value = RecordUtil.intern(tree.getCharTable(), tree.getChildren(child).get(0)); value = StringUtil.stripQuotesAroundValue(value); } } return new PsiNameValuePairStubImpl(parentStub, StringRef.fromString(name), StringRef.fromString(value)); }
@Override public PsiImportStatementStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { boolean isOnDemand = false; String refText = null; for (LighterASTNode child : tree.getChildren(node)) { IElementType type = child.getTokenType(); if (type == JavaElementType.JAVA_CODE_REFERENCE || type == JavaElementType.IMPORT_STATIC_REFERENCE) { refText = SourceUtil.getReferenceText(tree, child); } else if (type == JavaTokenType.ASTERISK) { isOnDemand = true; } } byte flags = PsiImportStatementStubImpl.packFlags(isOnDemand, node.getTokenType() == JavaElementType.IMPORT_STATIC_STATEMENT); return new PsiImportStatementStubImpl(parentStub, refText, flags); }
@NotNull @Override protected StubElement createStubForFile(@NotNull PsiFile file, @NotNull LighterAST tree) { if (!(file instanceof PsiJavaFile)) { return super.createStubForFile(file, tree); } String refText = ""; LighterASTNode pkg = LightTreeUtil.firstChildOfType(tree, tree.getRoot(), JavaElementType.PACKAGE_STATEMENT); if (pkg != null) { LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, pkg, JavaElementType.JAVA_CODE_REFERENCE); if (ref != null) { refText = SourceUtil.getReferenceText(tree, ref); } } return new PsiJavaFileStubImpl((PsiJavaFile)file, StringRef.fromString(refText), false); }
public static void toBuffer(@NotNull LighterAST tree, @NotNull LighterASTNode node, @NotNull StringBuilder buffer, @Nullable TokenSet skipTypes) { if (skipTypes != null && skipTypes.contains(node.getTokenType())) return; if (node instanceof LighterASTTokenNode) { buffer.append(((LighterASTTokenNode)node).getText()); return; } if (node instanceof LighterLazyParseableNode) { buffer.append(((LighterLazyParseableNode)node).getText()); return; } List<LighterASTNode> children = tree.getChildren(node); for (int i = 0, size = children.size(); i < size; ++i) { toBuffer(tree, children.get(i), buffer, skipTypes); } }
public static void toBuffer(@Nonnull LighterAST tree, @Nonnull LighterASTNode node, @Nonnull StringBuilder buffer, @Nullable TokenSet skipTypes) { if (skipTypes != null && skipTypes.contains(node.getTokenType())) { return; } if (node instanceof LighterASTTokenNode) { buffer.append(((LighterASTTokenNode)node).getText()); return; } if (node instanceof LighterLazyParseableNode) { buffer.append(((LighterLazyParseableNode)node).getText()); return; } List<LighterASTNode> children = tree.getChildren(node); for (int i = 0, size = children.size(); i < size; ++i) { toBuffer(tree, children.get(i), buffer, skipTypes); } }
private static void formatParameter(@NotNull LighterAST tree, @NotNull LighterASTNode parameter, StringBuilder buf) { final List<LighterASTNode> children = tree.getChildren(parameter); for(LighterASTNode node : children) { final IElementType tokenType = node.getTokenType(); if(tokenType == JavaElementType.TYPE) { formatType(tree, node, buf); buf.append(' '); } else if(tokenType == JavaTokenType.IDENTIFIER) { buf.append(RecordUtil.intern(tree.getCharTable(), node)); } } }
private static void formatTypeParameters(LighterAST tree, LighterASTNode typeParameters, StringBuilder buf) { final List<LighterASTNode> children = LightTreeUtil.getChildrenOfType(tree, typeParameters, JavaElementType.TYPE); if(children.isEmpty()) { return; } buf.append('<'); for(int i = 0; i < children.size(); i++) { LighterASTNode child = children.get(i); formatType(tree, child, buf); if(i != children.size() - 1) { buf.append(", "); } } buf.append('>'); }
@Override public PsiImportStatementStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { boolean isOnDemand = false; String refText = null; for(LighterASTNode child : tree.getChildren(node)) { IElementType type = child.getTokenType(); if(type == JavaElementType.JAVA_CODE_REFERENCE || type == JavaElementType.IMPORT_STATIC_REFERENCE) { refText = JavaSourceUtil.getReferenceText(tree, child); } else if(type == JavaTokenType.ASTERISK) { isOnDemand = true; } } byte flags = PsiImportStatementStubImpl.packFlags(isOnDemand, node.getTokenType() == JavaElementType.IMPORT_STATIC_STATEMENT); return new PsiImportStatementStubImpl(parentStub, refText, flags); }
@Override public PsiPackageAccessibilityStatementStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { String refText = null; List<String> to = ContainerUtil.newSmartList(); for(LighterASTNode child : tree.getChildren(node)) { IElementType type = child.getTokenType(); if(type == JavaElementType.JAVA_CODE_REFERENCE) { refText = JavaSourceUtil.getReferenceText(tree, child); } else if(type == JavaElementType.MODULE_REFERENCE) { to.add(JavaSourceUtil.getReferenceText(tree, child)); } } return new PsiPackageAccessibilityStatementStubImpl(parentStub, this, refText, to); }
public static boolean isDeprecatedByAnnotation(@NotNull LighterAST tree, @NotNull LighterASTNode modList) { for(final LighterASTNode child : tree.getChildren(modList)) { if(child.getTokenType() == JavaElementType.ANNOTATION) { final LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, child, JavaElementType.JAVA_CODE_REFERENCE); if(ref != null) { final LighterASTNode id = LightTreeUtil.firstChildOfType(tree, ref, JavaTokenType.IDENTIFIER); if(id != null) { final String name = intern(tree.getCharTable(), id); if(DEPRECATED_ANNOTATION_NAME.equals(name)) { return true; } } } } } return false; }
public static boolean isDeprecatedByDocComment(@NotNull LighterAST tree, @NotNull LighterASTNode comment) { String text = LightTreeUtil.toFilteredString(tree, comment, null); if(text.contains(DEPRECATED_TAG)) { JavaDocLexer lexer = new JavaDocLexer(LanguageLevel.HIGHEST); lexer.start(text); IElementType token; while((token = lexer.getTokenType()) != null) { if(token == JavaDocTokenType.DOC_TAG_NAME && DEPRECATED_TAG.equals(lexer.getTokenText())) { return true; } lexer.advance(); } } return false; }
@NotNull @Override protected StubElement createStubForFile(@NotNull PsiFile file, @NotNull LighterAST tree) { if(!(file instanceof PsiJavaFile)) { return super.createStubForFile(file, tree); } String refText = ""; LighterASTNode pkg = LightTreeUtil.firstChildOfType(tree, tree.getRoot(), JavaElementType.PACKAGE_STATEMENT); if(pkg != null) { LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, pkg, JavaElementType.JAVA_CODE_REFERENCE); if(ref != null) { refText = JavaSourceUtil.getReferenceText(tree, ref); } } return new PsiJavaFileStubImpl((PsiJavaFile) file, refText, null, false); }
@Nullable private static MethodData calcData(LighterAST tree, LighterASTNode method) { LighterASTNode body = LightTreeUtil.firstChildOfType(tree, method, JavaElementType.CODE_BLOCK); if(body == null) { return null; } List<LighterASTNode> statements = ContractInferenceInterpreter.getStatements(body, tree); List<PreContract> contracts = new ContractInferenceInterpreter(tree, method, body).inferContracts(statements); NullityInference.NullityInferenceVisitor nullityVisitor = new NullityInference.NullityInferenceVisitor(tree, body); PurityInference.PurityInferenceVisitor purityVisitor = new PurityInference.PurityInferenceVisitor(tree, body); for(LighterASTNode statement : statements) { walkMethodBody(tree, statement, it -> { nullityVisitor.visitNode(it); purityVisitor.visitNode(it); }); } return createData(body, contracts, nullityVisitor.getResult(), purityVisitor.getResult()); }
private static void walkMethodBody(LighterAST tree, LighterASTNode root, Consumer<LighterASTNode> processor) { new RecursiveLighterASTNodeWalkingVisitor(tree) { @Override public void visitNode(@NotNull LighterASTNode element) { IElementType type = element.getTokenType(); if(type == JavaElementType.CLASS || type == JavaElementType.FIELD || type == JavaElementType.METHOD || type == JavaElementType.ANNOTATION_METHOD || type == JavaElementType .LAMBDA_EXPRESSION) { return; } processor.accept(element); super.visitNode(element); } }.visitNode(root); }
@NotNull private static Set<LighterASTNode> findCallsWithNulls(LighterAST lighterAst, int[] nullOffsets) { Set<LighterASTNode> calls = new HashSet<>(); for(int offset : nullOffsets) { LighterASTNode leaf = LightTreeUtil.findLeafElementAt(lighterAst, offset); LighterASTNode literal = leaf == null ? null : lighterAst.getParent(leaf); if(isNullLiteral(lighterAst, literal)) { LighterASTNode exprList = lighterAst.getParent(literal); if(exprList != null && exprList.getTokenType() == EXPRESSION_LIST) { ContainerUtil.addIfNotNull(calls, LightTreeUtil.getParentOfType(lighterAst, exprList, CALL_TYPES, ElementType.MEMBER_BIT_SET)); } } } return calls; }
@Nullable private static IntArrayList getNullParameterIndices(LighterAST lighterAst, @NotNull LighterASTNode methodCall) { final LighterASTNode node = LightTreeUtil.firstChildOfType(lighterAst, methodCall, EXPRESSION_LIST); if(node == null) { return null; } final List<LighterASTNode> parameters = JavaLightTreeUtil.getExpressionChildren(lighterAst, node); IntArrayList indices = new IntArrayList(1); for(int idx = 0; idx < parameters.size(); idx++) { if(isNullLiteral(lighterAst, parameters.get(idx))) { indices.add(idx); } } return indices; }
@Nullable private static String getMethodName(LighterAST lighterAst, @NotNull LighterASTNode call, IElementType elementType) { if(elementType == NEW_EXPRESSION || elementType == ANONYMOUS_CLASS) { final List<LighterASTNode> refs = LightTreeUtil.getChildrenOfType(lighterAst, call, JAVA_CODE_REFERENCE); if(refs.isEmpty()) { return null; } final LighterASTNode lastRef = refs.get(refs.size() - 1); return JavaLightTreeUtil.getNameIdentifierText(lighterAst, lastRef); } LOG.assertTrue(elementType == METHOD_CALL_EXPRESSION); final LighterASTNode methodReference = lighterAst.getChildren(call).get(0); if(methodReference.getTokenType() == REFERENCE_EXPRESSION) { return JavaLightTreeUtil.getNameIdentifierText(lighterAst, methodReference); } return null; }
@Override public PsiFieldStub createStub(final LighterAST tree, final LighterASTNode node, final StubElement parentStub) { final TypeInfo typeInfo = TypeInfo.create(tree, node, parentStub); boolean isDeprecatedByComment = false; boolean hasDeprecatedAnnotation = false; boolean hasDocComment = false; String name = null; String initializer = null; boolean expectingInit = false; for (final LighterASTNode child : tree.getChildren(node)) { final IElementType type = child.getTokenType(); if (type == JavaDocElementType.DOC_COMMENT) { hasDocComment = true; isDeprecatedByComment = RecordUtil.isDeprecatedByDocComment(tree, child); } else if (type == JavaElementType.MODIFIER_LIST) { hasDeprecatedAnnotation = RecordUtil.isDeprecatedByAnnotation(tree, child); } else if (type == JavaTokenType.IDENTIFIER) { name = RecordUtil.intern(tree.getCharTable(), child); } else if (type == JavaTokenType.EQ) { expectingInit = true; } else if (expectingInit && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) && type != JavaTokenType.SEMICOLON) { initializer = encodeInitializer(tree, child); break; } } final boolean isEnumConst = node.getTokenType() == JavaElementType.ENUM_CONSTANT; final byte flags = PsiFieldStubImpl.packFlags(isEnumConst, isDeprecatedByComment, hasDeprecatedAnnotation, hasDocComment); return new PsiFieldStubImpl(parentStub, name, typeInfo, initializer, flags); }
private static String encodeInitializer(final LighterAST tree, final LighterASTNode initializer) { final IElementType type = initializer.getTokenType(); if (type == JavaElementType.NEW_EXPRESSION || type == JavaElementType.METHOD_CALL_EXPRESSION) { return PsiFieldStub.INITIALIZER_NOT_STORED; } if (initializer.getEndOffset() - initializer.getStartOffset() > INITIALIZER_LENGTH_LIMIT) { return PsiFieldStub.INITIALIZER_TOO_LONG; } return LightTreeUtil.toFilteredString(tree, initializer, null); }
private static String[] getTexts(LighterAST tree, LighterASTNode node) { List<LighterASTNode> refs = LightTreeUtil.getChildrenOfType(tree, node, JavaElementType.JAVA_CODE_REFERENCE); String[] texts = ArrayUtil.newStringArray(refs.size()); for (int i = 0; i < refs.size(); i++) { texts[i] = LightTreeUtil.toFilteredString(tree, refs.get(i), null); } return texts; }
@Override public PsiParameterStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { TypeInfo typeInfo = TypeInfo.create(tree, node, parentStub); LighterASTNode id = LightTreeUtil.requiredChildOfType(tree, node, JavaTokenType.IDENTIFIER); String name = RecordUtil.intern(tree.getCharTable(), id); return new PsiParameterStubImpl(parentStub, name, typeInfo, typeInfo.isEllipsis); }
@Override protected boolean skipChildProcessingWhenBuildingStubs(@NotNull LighterAST tree, @NotNull LighterASTNode parent, @NotNull LighterASTNode node) { IElementType parentType = parent.getTokenType(); IElementType nodeType = node.getTokenType(); if (checkByTypes(parentType, nodeType)) return true; if (nodeType == JavaElementType.CODE_BLOCK) { CodeBlockVisitor visitor = new CodeBlockVisitor(); ((LighterLazyParseableNode)node).accept(visitor); return visitor.result; } return false; }
@NotNull public static List<LighterASTNode> getChildrenOfType(@NotNull LighterAST tree, @NotNull LighterASTNode node, @NotNull IElementType type) { List<LighterASTNode> result = null; List<LighterASTNode> children = tree.getChildren(node); for (int i = 0, size = children.size(); i < size; ++i) { LighterASTNode child = children.get(i); if (child.getTokenType() == type) { if (result == null) result = new SmartList<LighterASTNode>(); result.add(child); } } return result != null ? result: Collections.<LighterASTNode>emptyList(); }
@NotNull public static List<LighterASTNode> getChildrenOfType(@NotNull LighterAST tree, @NotNull LighterASTNode node, @NotNull TokenSet types) { List<LighterASTNode> result = null; List<LighterASTNode> children = tree.getChildren(node); for (int i = 0, size = children.size(); i < size; ++i) { LighterASTNode child = children.get(i); if (types.contains(child.getTokenType())) { if (result == null) result = new SmartList<LighterASTNode>(); result.add(child); } } return result != null ? result: Collections.<LighterASTNode>emptyList(); }
@NotNull public static String toFilteredString(@NotNull LighterAST tree, @NotNull LighterASTNode node, @Nullable TokenSet skipTypes) { int length = node.getEndOffset() - node.getStartOffset(); if (length < 0) { length = 0; Logger.getInstance(LightTreeUtil.class).error("tree=" + tree + " node=" + node); } StringBuilder buffer = new StringBuilder(length); toBuffer(tree, node, buffer, skipTypes); return buffer.toString(); }
protected RecursiveLighterASTNodeWalkingVisitor(@NotNull final LighterAST ast) { this.ast = ast; myWalkingState = new WalkingState<IndexedLighterASTNode>(new LighterASTGuide()) { @Override public void elementFinished(@NotNull IndexedLighterASTNode element) { RecursiveLighterASTNodeWalkingVisitor.this.elementFinished(element.node); if (parentStack.peek() == element) { // getFirstChild returned nothing. otherwise getFirstChild() was not called, i.e. super.visitNode() was not called i.e. just ignore IndexedLighterASTNode[] children = childrenStack.pop(); List<LighterASTNode> list = children.length == 0 ? Collections.<LighterASTNode>emptyList() : ContainerUtil.map(children, new Function<IndexedLighterASTNode, LighterASTNode>() { @Override public LighterASTNode fun(IndexedLighterASTNode node) { return node.node; } }); ast.disposeChildren(list); parentStack.pop(); } } @Override public void visit(@NotNull IndexedLighterASTNode iNode) { LighterASTNode element = iNode.node; RecursiveLighterASTNodeWalkingVisitor visitor = RecursiveLighterASTNodeWalkingVisitor.this; if (element instanceof LighterLazyParseableNode) { visitor.visitLazyParseableNode((LighterLazyParseableNode)element); } else if (element instanceof LighterASTTokenNode) { visitor.visitTokenNode((LighterASTTokenNode)element); } else { visitor.visitNode(element); } } }; }
public @NotNull LighterAST getLighterASTForPsiDependentIndex() { LighterAST lighterAST = getUserData(IndexingDataKeys.LIGHTER_AST_NODE_KEY); if (lighterAST == null) { lighterAST = getPsiFileForPsiDependentIndex().getNode().getLighterAST(); assert lighterAST != null; putUserData(IndexingDataKeys.LIGHTER_AST_NODE_KEY, lighterAST); } return lighterAST; }
@Override public PsiFieldStub createStub(final LighterAST tree, final LighterASTNode node, final StubElement parentStub) { final TypeInfo typeInfo = TypeInfo.create(tree, node, parentStub); boolean isDeprecatedByComment = false; boolean hasDeprecatedAnnotation = false; String name = null; String initializer = null; boolean expectingInit = false; for (final LighterASTNode child : tree.getChildren(node)) { final IElementType type = child.getTokenType(); if (type == JavaDocElementType.DOC_COMMENT) { isDeprecatedByComment = RecordUtil.isDeprecatedByDocComment(tree, child); } else if (type == JavaElementType.MODIFIER_LIST) { hasDeprecatedAnnotation = RecordUtil.isDeprecatedByAnnotation(tree, child); } else if (type == JavaTokenType.IDENTIFIER) { name = RecordUtil.intern(tree.getCharTable(), child); } else if (type == JavaTokenType.EQ) { expectingInit = true; } else if (expectingInit && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) && type != JavaTokenType.SEMICOLON) { initializer = encodeInitializer(tree, child); break; } } final boolean isEnumConst = node.getTokenType() == JavaElementType.ENUM_CONSTANT; final byte flags = PsiFieldStubImpl.packFlags(isEnumConst, isDeprecatedByComment, hasDeprecatedAnnotation); return new PsiFieldStubImpl(parentStub, name, typeInfo, initializer, flags); }
@Override public PsiParameterStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { TypeInfo typeInfo = TypeInfo.create(tree, node, parentStub); LighterASTNode id = LightTreeUtil.requiredChildOfType(tree, node, ID_TYPES); String name = RecordUtil.intern(tree.getCharTable(), id); return new PsiParameterStubImpl(parentStub, name, typeInfo, typeInfo.isEllipsis); }
@Override protected boolean skipChildProcessingWhenBuildingStubs(@NotNull LighterAST tree, @NotNull LighterASTNode parent, @NotNull LighterASTNode node) { IElementType parentType = parent.getTokenType(); IElementType nodeType = node.getTokenType(); if (checkByTypes(parentType, nodeType)) return true; if (nodeType == JavaElementType.CODE_BLOCK && node instanceof LighterLazyParseableNode) { CodeBlockVisitor visitor = new CodeBlockVisitor(); ((LighterLazyParseableNode)node).accept(visitor); return visitor.result; } return false; }
@Nullable public static LighterASTNode firstChildOfType(@NotNull LighterAST tree, @NotNull LighterASTNode node, @NotNull IElementType type) { List<LighterASTNode> children = tree.getChildren(node); for (int i = 0, size = children.size(); i < size; ++i) { LighterASTNode child = children.get(i); if (child.getTokenType() == type) return child; } return null; }