/** * Suggest replacing {@code input} with a qualified reference to a locally declared field with a * similar or the same name as the {@code input} expression. * * @param input a MEMBER_SELECT or IDENTIFIER expression which should be replaced. * @param validFieldPredicate Predicate used to decide which locally declared fields are * appropriate candidates for replacement (e.g.: is the appropriate type) */ public static ImmutableList<Fix> fixesByReplacingExpressionWithLocallyDeclaredField( ExpressionTree input, Predicate<JCVariableDecl> validFieldPredicate, VisitorState state) { Preconditions.checkState(input.getKind() == IDENTIFIER || input.getKind() == MEMBER_SELECT); ImmutableMultimap<Integer, JCVariableDecl> potentialReplacements = ASTHelpers.findEnclosingNode(state.getPath(), JCClassDecl.class).getMembers().stream() .filter(JCVariableDecl.class::isInstance) .map(JCVariableDecl.class::cast) .filter(validFieldPredicate) .collect(collectByEditDistanceTo(simpleNameOfIdentifierOrMemberAccess(input))); return buildValidReplacements( potentialReplacements, var -> SuggestedFix.replace(input, "this." + var.sym)); }
/** * Performs a best-effort search for the AST node of a field declaration. * * <p>It will only find fields declared in a lexically enclosing scope of the current location. * Since double-checked locking should always be used on a private field, this should be * reasonably effective. */ @Nullable private static JCTree findFieldDeclaration(TreePath path, VarSymbol var) { for (TreePath curr = path; curr != null; curr = curr.getParentPath()) { Tree leaf = curr.getLeaf(); if (!(leaf instanceof JCClassDecl)) { continue; } for (JCTree tree : ((JCClassDecl) leaf).getMembers()) { if (Objects.equals(var, ASTHelpers.getSymbol(tree))) { return tree; } } } return null; } }
/** Tokenizes as little of the {@code tree} as possible to ensure we grab all the annotations. */ private static ImmutableList<ErrorProneToken> annotationTokens( Tree tree, VisitorState state, int annotationEnd) { int endPos; if (tree instanceof JCMethodDecl) { JCMethodDecl methodTree = (JCMethodDecl) tree; endPos = methodTree.getBody() == null ? state.getEndPosition(methodTree) : methodTree.getBody().getStartPosition(); } else if (tree instanceof JCVariableDecl) { endPos = ((JCVariableDecl) tree).getType().getStartPosition(); } else if (tree instanceof JCClassDecl) { JCClassDecl classTree = (JCClassDecl) tree; endPos = classTree.getMembers().isEmpty() ? state.getEndPosition(classTree) : classTree.getMembers().get(0).getStartPosition(); } else { throw new AssertionError(); } return ErrorProneTokens.getTokens( state.getSourceCode().subSequence(annotationEnd, endPos).toString(), state.context); }
members = ((JCClassDecl) path.getLeaf()).getMembers(); } else { members = ((JCBlock) path.getLeaf()).getStatements();
@Override public boolean isInnerType( String topLevel, String relativeInner ) { if( isAnonymous( relativeInner ) ) { return true; } Model model = getModel( topLevel ); if( model == null ) { return false; } JCTree.JCClassDecl classDecl = getClassDecl( model ); if( classDecl == null ) { return false; } for( JCTree m: classDecl.getMembers() ) { if( m instanceof JCTree.JCClassDecl ) { return isInnerClass( (JCTree.JCClassDecl)m, relativeInner ); } } return false; }
@Override public boolean isInnerType( String topLevel, String relativeInner ) { if( isAnonymous( relativeInner ) ) { return true; } Model model = getModel( topLevel ); if( model == null ) { return false; } JCTree.JCClassDecl classDecl = getClassDecl( model ); if( classDecl == null ) { return false; } for( JCTree m: classDecl.getMembers() ) { if( m instanceof JCTree.JCClassDecl ) { return isInnerClass( (JCTree.JCClassDecl)m, relativeInner ); } } return false; }
/** Tokenizes as little of the {@code tree} as possible to ensure we grab all the annotations. */ private static ImmutableList<ErrorProneToken> annotationTokens( Tree tree, VisitorState state, int annotationEnd) { int endPos; if (tree instanceof JCMethodDecl) { JCMethodDecl methodTree = (JCMethodDecl) tree; endPos = methodTree.getBody() == null ? state.getEndPosition(methodTree) : methodTree.getBody().getStartPosition(); } else if (tree instanceof JCVariableDecl) { endPos = ((JCVariableDecl) tree).getType().getStartPosition(); } else if (tree instanceof JCClassDecl) { JCClassDecl classTree = (JCClassDecl) tree; endPos = classTree.getMembers().isEmpty() ? state.getEndPosition(classTree) : classTree.getMembers().get(0).getStartPosition(); } else { throw new AssertionError(); } return ErrorProneTokens.getTokens( state.getSourceCode().subSequence(annotationEnd, endPos).toString(), state.context); }
/** * Performs a best-effort search for the AST node of a field declaration. * * <p>It will only find fields declared in a lexically enclosing scope of the current location. * Since double-checked locking should always be used on a private field, this should be * reasonably effective. */ @Nullable private static JCTree findFieldDeclaration(TreePath path, VarSymbol var) { for (TreePath curr = path; curr != null; curr = curr.getParentPath()) { Tree leaf = curr.getLeaf(); if (!(leaf instanceof JCClassDecl)) { continue; } for (JCTree tree : ((JCClassDecl) leaf).getMembers()) { if (Objects.equals(var, ASTHelpers.getSymbol(tree))) { return tree; } } } return null; } }
@Override public Description matchMethod(MethodTree method, VisitorState state) { if (!CAN_BE_A_BINDS_METHOD.matches(method, state)) { return NO_MATCH; } JCClassDecl enclosingClass = ASTHelpers.findEnclosingNode(state.getPath(), JCClassDecl.class); // Dagger 1 modules don't support @Binds. if (!IS_DAGGER_2_MODULE.matches(enclosingClass, state)) { return NO_MATCH; } if (enclosingClass.getExtendsClause() != null) { return fixByDelegating(); } for (Tree member : enclosingClass.getMembers()) { if (member.getKind().equals(Tree.Kind.METHOD) && !getSymbol(member).isConstructor()) { MethodTree siblingMethod = (MethodTree) member; Set<Modifier> siblingFlags = siblingMethod.getModifiers().getFlags(); if (!(siblingFlags.contains(Modifier.STATIC) || siblingFlags.contains(Modifier.ABSTRACT)) && !CAN_BE_A_BINDS_METHOD.matches(siblingMethod, state)) { return fixByDelegating(); } } } return fixByModifyingMethod(state, enclosingClass, method); }
/** * Suggest replacing {@code input} with a qualified reference to a locally declared field with a * similar or the same name as the {@code input} expression. * * @param input a MEMBER_SELECT or IDENTIFIER expression which should be replaced. * @param validFieldPredicate Predicate used to decide which locally declared fields are * appropriate candidates for replacement (e.g.: is the appropriate type) */ public static ImmutableList<Fix> fixesByReplacingExpressionWithLocallyDeclaredField( ExpressionTree input, Predicate<JCVariableDecl> validFieldPredicate, VisitorState state) { Preconditions.checkState(input.getKind() == IDENTIFIER || input.getKind() == MEMBER_SELECT); ImmutableMultimap<Integer, JCVariableDecl> potentialReplacements = ASTHelpers.findEnclosingNode(state.getPath(), JCClassDecl.class).getMembers().stream() .filter(JCVariableDecl.class::isInstance) .map(JCVariableDecl.class::cast) .filter(validFieldPredicate) .collect(collectByEditDistanceTo(simpleNameOfIdentifierOrMemberAccess(input))); return buildValidReplacements( potentialReplacements, var -> SuggestedFix.replace(input, "this." + var.sym)); }
public JCTree getTree(Element element) { Symbol symbol = (Symbol) element; TypeSymbol enclosing = symbol.enclClass(); Env<AttrContext> env = enter.getEnv(enclosing); if (env == null) return null; JCClassDecl classNode = env.enclClass; if (classNode != null) { if (TreeInfo.symbolFor(classNode) == element) return classNode; for (JCTree node : classNode.getMembers()) if (TreeInfo.symbolFor(node) == element) return node; } return null; }
public JCTree getTree(Element element) { Symbol symbol = (Symbol) element; TypeSymbol enclosing = symbol.enclClass(); Env<AttrContext> env = enter.getEnv(enclosing); if (env == null) return null; JCClassDecl classNode = env.enclClass; if (classNode != null) { if (TreeInfo.symbolFor(classNode) == element) return classNode; for (JCTree node : classNode.getMembers()) if (TreeInfo.symbolFor(node) == element) return node; } return null; }
public JCTree getTree(Element element) { Symbol symbol = (Symbol) element; TypeSymbol enclosing = symbol.enclClass(); Env<AttrContext> env = enter.getEnv(enclosing); if (env == null) return null; JCClassDecl classNode = env.enclClass; if (classNode != null) { if (TreeInfo.symbolFor(classNode) == element) return classNode; for (JCTree node : classNode.getMembers()) if (TreeInfo.symbolFor(node) == element) return node; } return null; }
public JCTree getTree(Element element) { Symbol symbol = (Symbol) element; TypeSymbol enclosing = symbol.enclClass(); Env<AttrContext> env = enter.getEnv(enclosing); if (env == null) return null; JCClassDecl classNode = env.enclClass; if (classNode != null) { if (TreeInfo.symbolFor(classNode) == element) return classNode; for (JCTree node : classNode.getMembers()) if (TreeInfo.symbolFor(node) == element) return node; } return null; }
boolean initializationBlockFound = false; if (newClass.def != null) { for (JCTree m : newClass.def.getMembers()) { if (m instanceof JCBlock) { initializationBlockFound = true; for (JCTree m : newClass.def.getMembers()) { if (m instanceof JCBlock) { for (JCTree s : ((JCBlock) m).stats) {
private void printStaticInitializer(JCBlock block) { if (getScope().isEnumScope()) { // static blocks are initialized in the enum wrapper class return; } if (getScope().isDeclareClassScope()) { // static init block are erased in declare class return; } int static_i = 0; for (JCTree m : ((JCClassDecl) getParent()).getMembers()) { if (m instanceof JCBlock) { if (((JCBlock) m).isStatic()) { if (block == m) { print("static __static_initializer_" + static_i + "() "); print("{"); println().startIndent(); printBlockStatements(block.stats); endIndent().printIndent(); print("}"); break; } static_i++; } } } }
private void printFieldInitializations() { JCClassDecl clazz = getParent(JCClassDecl.class); for (JCTree t : clazz.getMembers()) { if (t instanceof JCVariableDecl && !getScope().fieldsWithInitializers.contains(t)) { JCVariableDecl field = (JCVariableDecl) t; if (!field.sym.isStatic() && !context.hasAnnotationType(field.sym, JSweetConfig.ANNOTATION_ERASED)) { String name = getIdentifier(field.sym); if (context.getFieldNameMapping(field.sym) != null) { name = context.getFieldNameMapping(field.sym); } printIndent().print("if(").print("this.").print(name).print("===undefined) ").print("this.") .print(name).print(" = ").print(Util.getTypeInitialValue(field.type)).print(";").println(); } } } for (JCVariableDecl field : getScope().fieldsWithInitializers) { if (context.hasAnnotationType(field.sym, JSweetConfig.ANNOTATION_ERASED)) { continue; } String name = getIdentifier(field.sym); if (context.getFieldNameMapping(field.sym) != null) { name = context.getFieldNameMapping(field.sym); } printIndent().print("this.").print(name).print(" = "); if (!substituteAssignedExpression(field.type, field.init)) { print(field.init); } print(";").println(); } }
/** * Tells if the given type declaration contains some method declarations. */ public static boolean containsMethods(JCClassDecl classDeclaration) { for (JCTree member : classDeclaration.getMembers()) { if (member instanceof JCMethodDecl) { JCMethodDecl method = (JCMethodDecl) member; if (method.pos == classDeclaration.pos) { continue; } return true; // if (method.body != null) { // return true; // } } else if (member instanceof JCVariableDecl) { if (((JCVariableDecl) member).mods.getFlags().contains(Modifier.STATIC)) { return true; } } } return false; }
members = ((JCClassDecl) path.getLeaf()).getMembers(); } else { members = ((JCBlock) path.getLeaf()).getStatements();
@Override public Description matchMethod(MethodTree method, VisitorState state) { if (!CAN_BE_A_BINDS_METHOD.matches(method, state)) { return NO_MATCH; } JCClassDecl enclosingClass = ASTHelpers.findEnclosingNode(state.getPath(), JCClassDecl.class); // Dagger 1 modules don't support @Binds. if (!IS_DAGGER_2_MODULE.matches(enclosingClass, state)) { return NO_MATCH; } if (enclosingClass.getExtendsClause() != null) { return fixByDelegating(); } for (Tree member : enclosingClass.getMembers()) { if (member.getKind().equals(Tree.Kind.METHOD) && !getSymbol(member).isConstructor()) { MethodTree siblingMethod = (MethodTree) member; Set<Modifier> siblingFlags = siblingMethod.getModifiers().getFlags(); if (!(siblingFlags.contains(Modifier.STATIC) || siblingFlags.contains(Modifier.ABSTRACT)) && !CAN_BE_A_BINDS_METHOD.matches(siblingMethod, state)) { return fixByDelegating(); } } } return fixByModifyingMethod(state, enclosingClass, method); }