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; }
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('>'); }
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()); }
@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; }
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 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 public PsiProvidesStatementStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, node, JavaElementType.JAVA_CODE_REFERENCE); String refText = ref != null ? JavaSourceUtil.getReferenceText(tree, ref) : null; return new PsiProvidesStatementStubImpl(parentStub, refText); }
@Override public PsiUsesStatementStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, node, JavaElementType.JAVA_CODE_REFERENCE); String refText = ref != null ? JavaSourceUtil.getReferenceText(tree, ref) : null; return new PsiUsesStatementStubImpl(parentStub, refText); }
@Override public PsiRequiresStatementStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, node, JavaElementType.MODULE_REFERENCE); String refText = ref != null ? JavaSourceUtil.getReferenceText(tree, ref) : null; return new PsiRequiresStatementStubImpl(parentStub, refText); }
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); }
@NotNull @Override protected String getPresentableText(@NotNull LighterAST tree, @NotNull LighterASTNode funExpr) { LighterASTNode parameterList = ObjectUtils.notNull(LightTreeUtil.firstChildOfType(tree, funExpr, JavaStubElementTypes.PARAMETER_LIST)); return getLambdaPresentableText(tree, parameterList); }
@NotNull private static String[] getTexts(@NotNull LighterAST tree, @NotNull 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, false); }
@Nullable @Contract("_,null->null") public static List<LighterASTNode> getArgList(@NotNull LighterAST tree, @Nullable LighterASTNode call) { LighterASTNode anonClass = LightTreeUtil.firstChildOfType(tree, call, ANONYMOUS_CLASS); LighterASTNode exprList = LightTreeUtil.firstChildOfType(tree, anonClass != null ? anonClass : call, EXPRESSION_LIST); return exprList == null ? null : getExpressionChildren(tree, exprList); }
@Nullable @Contract("_,null->null") public static String getNameIdentifierText(@NotNull LighterAST tree, @Nullable LighterASTNode idOwner) { LighterASTNode id = LightTreeUtil.firstChildOfType(tree, idOwner, JavaTokenType.IDENTIFIER); return id != null ? RecordUtil.intern(tree.getCharTable(), id) : null; }
@Override public PsiMethodStub createStub(final LighterAST tree, final LighterASTNode node, final StubElement parentStub) { String name = null; boolean isConstructor = true; boolean isVarArgs = false; boolean isDeprecatedByComment = false; boolean hasDeprecatedAnnotation = false; boolean hasDocComment = false; String defValueText = null; boolean expectingDef = 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 == JavaElementType.TYPE) { isConstructor = false; } else if (type == JavaTokenType.IDENTIFIER) { name = RecordUtil.intern(tree.getCharTable(), child); } else if (type == JavaElementType.PARAMETER_LIST) { final List<LighterASTNode> params = LightTreeUtil.getChildrenOfType(tree, child, JavaElementType.PARAMETER); if (!params.isEmpty()) { final LighterASTNode pType = LightTreeUtil.firstChildOfType(tree, params.get(params.size() - 1), JavaElementType.TYPE); if (pType != null) { isVarArgs = (LightTreeUtil.firstChildOfType(tree, pType, JavaTokenType.ELLIPSIS) != null); } } } else if (type == JavaTokenType.DEFAULT_KEYWORD) { expectingDef = true; } else if (expectingDef && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) && type != JavaTokenType.SEMICOLON && type != JavaElementType.CODE_BLOCK) { defValueText = LightTreeUtil.toFilteredString(tree, child, null); break; } } TypeInfo typeInfo = isConstructor ? TypeInfo.createConstructorType() : TypeInfo.create(tree, node, parentStub); boolean isAnno = (node.getTokenType() == JavaElementType.ANNOTATION_METHOD); byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnno, isVarArgs, isDeprecatedByComment, hasDeprecatedAnnotation, hasDocComment); return new PsiMethodStubImpl(parentStub, name, typeInfo, flags, defValueText); }
@Override public PsiAnnotationStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { String text = LightTreeUtil.toFilteredString(tree, node, null); return new PsiAnnotationStubImpl(parentStub, text); }
@Override public PsiTypeParameterStub createStub(final LighterAST tree, final LighterASTNode node, final StubElement parentStub) { final LighterASTNode id = LightTreeUtil.requiredChildOfType(tree, node, JavaTokenType.IDENTIFIER); final String name = RecordUtil.intern(tree.getCharTable(), id); return new PsiTypeParameterStubImpl(parentStub, StringRef.fromString(name)); }
public static boolean isDeprecatedByDocComment(@NotNull LighterAST tree, @NotNull LighterASTNode comment) { // todo[r.sh] parse doc comments, implement tree lookup String text = LightTreeUtil.toFilteredString(tree, comment, null); return text.contains(DEPRECATED_TAG); }
public static int packModifierList(@NotNull LighterAST tree, @NotNull LighterASTNode modList, @NotNull StubElement parent) { int packed = 0; final LighterASTNode modListOwner = tree.getParent(modList); if (modListOwner != null && modListOwner.getTokenType() == parent.getStubType()) { final StubElement grandParent = parent.getParentStub(); if (parent instanceof PsiClassStub) { if (grandParent instanceof PsiClassStub && ((PsiClassStub)grandParent).isInterface()) { packed |= ModifierFlags.PUBLIC_MASK; packed |= ModifierFlags.STATIC_MASK; } if (((PsiClassStub)parent).isInterface()) { packed |= ModifierFlags.ABSTRACT_MASK; if (grandParent instanceof PsiClassStub) { packed |= ModifierFlags.STATIC_MASK; } } else if (((PsiClassStub)parent).isEnum()) { if (!(grandParent instanceof PsiFileStub)) { packed |= ModifierFlags.STATIC_MASK; } boolean isFinal = true; final List<LighterASTNode> enumConstants = LightTreeUtil.getChildrenOfType(tree, modListOwner, JavaElementType.ENUM_CONSTANT); for (final LighterASTNode constant : enumConstants) { if (LightTreeUtil.firstChildOfType(tree, constant, JavaElementType.ENUM_CONSTANT_INITIALIZER) != null) { isFinal = false; break; } } if (isFinal) { packed |= ModifierFlags.FINAL_MASK; } final List<LighterASTNode> methods = LightTreeUtil.getChildrenOfType(tree, modListOwner, JavaElementType.METHOD); for (final LighterASTNode method : methods) { final LighterASTNode mods = LightTreeUtil.requiredChildOfType(tree, method, JavaElementType.MODIFIER_LIST); if (LightTreeUtil.firstChildOfType(tree, mods, JavaTokenType.ABSTRACT_KEYWORD) != null) { packed |= ModifierFlags.ABSTRACT_MASK; break; } } } } else if (parent instanceof PsiMethodStub) { if (grandParent instanceof PsiClassStub && ((PsiClassStub)grandParent).isInterface()) { packed |= ModifierFlags.PUBLIC_MASK; packed |= ModifierFlags.ABSTRACT_MASK; } } else if (parent instanceof PsiFieldStub) { if (parent.getStubType() == JavaElementType.ENUM_CONSTANT || grandParent instanceof PsiClassStub && ((PsiClassStub)grandParent).isInterface()) { packed |= ModifierFlags.PUBLIC_MASK; packed |= ModifierFlags.STATIC_MASK; packed |= ModifierFlags.FINAL_MASK; } } } for (final LighterASTNode child : tree.getChildren(modList)) { final int flag = ModifierFlags.KEYWORD_TO_MODIFIER_FLAG_MAP.get(child.getTokenType()); if (flag != 0) { packed |= flag; } } if ((packed & ModifierFlags.DEFENDER_MASK) != 0) { packed &= ~ModifierFlags.ABSTRACT_MASK; } if ((packed & (ModifierFlags.PRIVATE_MASK | ModifierFlags.PROTECTED_MASK | ModifierFlags.PUBLIC_MASK)) == 0) { packed |= ModifierFlags.PACKAGE_LOCAL_MASK; } return packed; }
@Override public PropertyStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { LighterASTNode keyNode = LightTreeUtil.firstChildOfType(tree, node, PropertiesTokenTypes.KEY_CHARACTERS); String key = intern(tree.getCharTable(), keyNode); return new PropertyStubImpl(parentStub, key); }
@Override public PsiMethodStub createStub(final LighterAST tree, final LighterASTNode node, final StubElement parentStub) { String name = null; boolean isConstructor = true; boolean isVarArgs = false; boolean isDeprecatedByComment = false; boolean hasDeprecatedAnnotation = false; String defValueText = null; boolean expectingDef = 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 == JavaElementType.TYPE) { isConstructor = false; } else if (type == JavaTokenType.IDENTIFIER) { name = RecordUtil.intern(tree.getCharTable(), child); } else if (type == JavaElementType.PARAMETER_LIST) { final List<LighterASTNode> params = LightTreeUtil.getChildrenOfType(tree, child, JavaElementType.PARAMETER); if (params.size() > 0) { final LighterASTNode pType = LightTreeUtil.firstChildOfType(tree, params.get(params.size() - 1), JavaElementType.TYPE); if (pType != null) { isVarArgs = (LightTreeUtil.firstChildOfType(tree, pType, JavaTokenType.ELLIPSIS) != null); } } } else if (type == JavaTokenType.DEFAULT_KEYWORD) { expectingDef = true; } else if (expectingDef && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) && type != JavaTokenType.SEMICOLON && type != JavaElementType.CODE_BLOCK) { defValueText = LightTreeUtil.toFilteredString(tree, child, null); break; } } TypeInfo typeInfo = isConstructor ? TypeInfo.createConstructorType() : TypeInfo.create(tree, node, parentStub); boolean isAnno = (node.getTokenType() == JavaElementType.ANNOTATION_METHOD); byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnno, isVarArgs, isDeprecatedByComment, hasDeprecatedAnnotation); return new PsiMethodStubImpl(parentStub, StringRef.fromString(name), typeInfo, flags, StringRef.fromString(defValueText)); }
@Override public PsiMethodStub createStub(final LighterAST tree, final LighterASTNode node, final StubElement parentStub) { String name = null; boolean isConstructor = true; boolean isVarArgs = false; boolean isDeprecatedByComment = false; boolean hasDeprecatedAnnotation = false; boolean hasDocComment = false; String defValueText = null; boolean expectingDef = 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 == JavaElementType.TYPE) { isConstructor = false; } else if(type == JavaTokenType.IDENTIFIER) { name = RecordUtil.intern(tree.getCharTable(), child); } else if(type == JavaElementType.PARAMETER_LIST) { final List<LighterASTNode> params = LightTreeUtil.getChildrenOfType(tree, child, JavaElementType.PARAMETER); if(!params.isEmpty()) { final LighterASTNode pType = LightTreeUtil.firstChildOfType(tree, params.get(params.size() - 1), JavaElementType.TYPE); if(pType != null) { isVarArgs = (LightTreeUtil.firstChildOfType(tree, pType, JavaTokenType.ELLIPSIS) != null); } } } else if(type == JavaTokenType.DEFAULT_KEYWORD) { expectingDef = true; } else if(expectingDef && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) && type != JavaTokenType.SEMICOLON && type != JavaElementType.CODE_BLOCK) { defValueText = LightTreeUtil.toFilteredString(tree, child, null); break; } } TypeInfo typeInfo = isConstructor ? TypeInfo.createConstructorType() : TypeInfo.create(tree, node, parentStub); boolean isAnno = (node.getTokenType() == JavaElementType.ANNOTATION_METHOD); byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnno, isVarArgs, isDeprecatedByComment, hasDeprecatedAnnotation, hasDocComment); return new PsiMethodStubImpl(parentStub, name, typeInfo, flags, defValueText); }
@Override public PsiJavaModuleStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { LighterASTNode ref = LightTreeUtil.requiredChildOfType(tree, node, JavaElementType.MODULE_REFERENCE); return new PsiJavaModuleStubImpl(parentStub, JavaSourceUtil.getReferenceText(tree, ref)); }