Commits

Anonymous committed de8f6fe

demo branch preparing for the actual demo

Comments (0)

Files changed (8)

analysis/src/j1/tutorial/javac/analysis/rules/CollectionRemove.java

-package j1.tutorial.javac.analysis.rules;
-
-import com.sun.source.tree.CompilationUnitTree;
-import com.sun.source.tree.MemberSelectTree;
-import com.sun.source.tree.MethodInvocationTree;
-import com.sun.source.tree.Tree.Kind;
-import com.sun.source.util.TreePath;
-import com.sun.source.util.TreePathScanner;
-import j1.tutorial.javac.analysis.api.AnalysisContext;
-import j1.tutorial.javac.analysis.api.Rule;
-import j1.tutorial.javac.analysis.api.Utilities;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.type.WildcardType;
-import org.openide.util.lookup.ServiceProvider;
-
-@ServiceProvider(service=Rule.class)
-public class CollectionRemove implements Rule {
-
-    @Override
-    public void analyseFile(final AnalysisContext ctx, final CompilationUnitTree file) {
-        final ExecutableElement checkAgainst = Utilities.resolveMethod(ctx, "java.util.Collection.add(java.lang.Object)");
-        final ExecutableElement collectionRemove = Utilities.resolveMethod(ctx, "java.util.Collection.remove(java.lang.Object)");
-        new TreePathScanner<Void, Void>() {
-            @Override public Void visitMethodInvocation(MethodInvocationTree mit, Void p) {
-                TypeMirror site = null;
-                
-                if (mit.getMethodSelect().getKind() == Kind.MEMBER_SELECT) { //XXX: IDENTIFIER/implicit this
-                    site = ctx.getTrees().getTypeMirror(new TreePath(new TreePath(getCurrentPath(), mit.getMethodSelect()), ((MemberSelectTree) mit.getMethodSelect()).getExpression()));
-                }
-                
-                Element actualMethod = ctx.getTrees().getElement(getCurrentPath());
-                
-                if (   actualMethod != null
-                    && actualMethod.getKind() == ElementKind.METHOD
-                    && site != null
-                    && site.getKind() == TypeKind.DECLARED
-                    && ctx.getElementUtils().overrides((ExecutableElement) actualMethod, collectionRemove, (TypeElement) ((DeclaredType) site).asElement())) {
-                    TypeMirror actualMethodType = ctx.getTypeUtils().asMemberOf((DeclaredType) site, checkAgainst);
-                    TypeMirror expectedType = ((ExecutableType) actualMethodType).getParameterTypes().get(0);
-                    
-                    if (expectedType.getKind() == TypeKind.WILDCARD) {
-                        expectedType = ((WildcardType) expectedType).getExtendsBound();
-                        if (expectedType == null) {
-                            expectedType = ctx.getElementUtils().getTypeElement("java.lang.Object").asType();
-                        }
-                    }
-                    
-                    TypeMirror actualType = ctx.getTrees().getTypeMirror(new TreePath(getCurrentPath(), mit.getArguments().get(0)));
-                    
-                    if (!ctx.getTypeUtils().isAssignable(actualType, expectedType)) {
-                        ctx.getTrees().printMessage(javax.tools.Diagnostic.Kind.WARNING, "Suspicious parameter type: " + actualType + ", should be assignable to: " + expectedType, mit.getArguments().get(0), file);
-                    }
-                }
-                
-                return super.visitMethodInvocation(mit, p);
-            }
-        }.scan(file, null);
-    }
-    
-}

analysis/src/j1/tutorial/javac/analysis/rules/FinalRule.java

-package j1.tutorial.javac.analysis.rules;
-
-import j1.tutorial.javac.analysis.api.Utilities;
-import java.util.Set;
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Processor;
-import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.tools.Diagnostic.Kind;
-import org.openide.util.lookup.ServiceProvider;
-
-@ServiceProvider(service=Processor.class)
-@SupportedAnnotationTypes("*")
-public class FinalRule extends AbstractProcessor {
-
-    @Override
-    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
-        for (Element toProcess : roundEnv.getRootElements()) {
-            if (!toProcess.getKind().isClass() && !toProcess.getKind().isInterface()) {
-                continue;
-            }
-            TypeElement typeElement = (TypeElement) toProcess;
-            for (TypeMirror superInterface : typeElement.getInterfaces()) {
-                if (superInterface.getKind() != TypeKind.DECLARED) continue;
-                TypeElement intf = (TypeElement) ((DeclaredType) superInterface).asElement();
-                AnnotationMirror friendAnnotation = Utilities.findAppliedAnnotation(processingEnv, intf, "j1.tutorial.javac.analysis.api.Final"); //TODO: string?
-
-                if (friendAnnotation != null) {
-                    boolean accepted = false;
-
-                    for (TypeMirror friend : Utilities.getAttributeValue(processingEnv, friendAnnotation, "implementors", TypeMirror[].class)) {
-                        if (typeElement.getQualifiedName().contentEquals(Utilities.toFQN(friend))) {
-                            accepted = true;
-                            break;
-                        }
-                    }
-
-                    if (!accepted) {
-                        processingEnv.getMessager().printMessage(Kind.ERROR, "Cannot implement: " + intf.getQualifiedName().toString() + ", not its listed implementor", typeElement);
-                    }
-                }
-            }
-        }
-        
-        return false;
-    }
-
-    @Override
-    public SourceVersion getSupportedSourceVersion() {
-        return SourceVersion.latest();
-    }
-
-}

analysis/src/j1/tutorial/javac/analysis/rules/FriendRule.java

-package j1.tutorial.javac.analysis.rules;
-
-import com.sun.source.tree.ClassTree;
-import com.sun.source.tree.CompilationUnitTree;
-import com.sun.source.tree.IdentifierTree;
-import com.sun.source.tree.MemberSelectTree;
-import com.sun.source.tree.Tree;
-import com.sun.source.util.TreePathScanner;
-import j1.tutorial.javac.analysis.api.AnalysisContext;
-import j1.tutorial.javac.analysis.api.Rule;
-import j1.tutorial.javac.analysis.api.Utilities;
-import java.util.HashSet;
-import java.util.Set;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-import javax.tools.Diagnostic.Kind;
-import org.openide.util.lookup.ServiceProvider;
-
-@ServiceProvider(service=Rule.class)
-public class FriendRule implements Rule {
-
-    @Override
-    public void analyseFile(final AnalysisContext ctx, final CompilationUnitTree file) {
-        new TreePathScanner<Void, Void>() {
-            private final Set<String> enclosingClasses = new HashSet<>();
-            @Override public Void visitClass(ClassTree node, Void p) {
-                TypeElement clazz = (TypeElement) ctx.getTrees().getElement(getCurrentPath());
-                String fqn = clazz.getQualifiedName().toString();
-                
-                enclosingClasses.add(fqn);
-                try {
-                    return super.visitClass(node, p);
-                } finally {
-                    enclosingClasses.remove(fqn);
-                }
-            }
-            @Override public Void visitIdentifier(IdentifierTree node, Void p) {
-                handleElement(ctx.getTrees().getElement(getCurrentPath()), node);
-                return super.visitIdentifier(node, p);
-            }
-            @Override public Void visitMemberSelect(MemberSelectTree node, Void p) {
-                handleElement(ctx.getTrees().getElement(getCurrentPath()), node);
-                return super.visitMemberSelect(node, p);
-            }
-            private void handleElement(Element element, Tree node) {
-                if (element == null) return ;
-                
-                AnnotationMirror friendAnnotation = Utilities.findAppliedAnnotation(ctx, element, "j1.tutorial.javac.analysis.api.Friend"); //TODO: string?
-
-                if (friendAnnotation != null) {
-                    boolean accepted = false;
-
-                    for (TypeMirror friend : Utilities.getAttributeValue(ctx, friendAnnotation, "friends", TypeMirror[].class)) {
-                        if (enclosingClasses.contains(Utilities.toFQN(friend))) {
-                            accepted = true;
-                            break;
-                        }
-                    }
-
-                    if (!accepted) {
-                        ctx.getTrees().printMessage(Kind.ERROR, "Cannot use: " + element.toString()/*XXX: better toString*/ + ", not its friend", node, file);
-                    }
-                }
-            }
-        }.scan(file, null);
-    }
-    
-}

analysis/src/j1/tutorial/javac/analysis/rules/RegExpRule.java

-package j1.tutorial.javac.analysis.rules;
-
-import com.sun.source.tree.BinaryTree;
-import com.sun.source.tree.CompilationUnitTree;
-import com.sun.source.tree.ExpressionTree;
-import com.sun.source.tree.LiteralTree;
-import com.sun.source.tree.MethodInvocationTree;
-import com.sun.source.tree.VariableTree;
-import com.sun.source.util.TreePath;
-import com.sun.source.util.TreePathScanner;
-import j1.tutorial.javac.analysis.api.AnalysisContext;
-import j1.tutorial.javac.analysis.api.Rule;
-import j1.tutorial.javac.analysis.api.Utilities;
-import java.util.Iterator;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.VariableElement;
-import javax.tools.Diagnostic;
-import org.openide.util.lookup.ServiceProvider;
-
-@ServiceProvider(service=Rule.class)
-public class RegExpRule implements Rule {
-
-    @Override
-    public void analyseFile(final AnalysisContext ctx, final CompilationUnitTree file) {
-        new TreePathScanner<Void, Void>() {
-            @Override public Void visitVariable(VariableTree vt, Void p) {
-                Element el = ctx.getTrees().getElement(getCurrentPath());
-                
-                if (vt.getInitializer() != null && el != null) {
-                    String constant = getConstant(ctx, new TreePath(getCurrentPath(), vt.getInitializer()));
-
-                    maybeVerifyRegExp(el, constant, vt.getInitializer());
-                }
-                return super.visitVariable(vt, p);
-            }
-            @Override public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
-                Element method = ctx.getTrees().getElement(getCurrentPath());
-                
-                if (method != null && method.getKind() == ElementKind.METHOD) {
-                    Iterator<? extends VariableElement> paramVars = ((ExecutableElement) method).getParameters().iterator();
-                    Iterator<? extends ExpressionTree> paramTree = node.getArguments().iterator();
-                    
-                    while (paramVars.hasNext() && paramTree.hasNext()) {
-                        VariableElement var = paramVars.next();
-                        ExpressionTree tree = paramTree.next();
-                        
-                        String constant = getConstant(ctx, new TreePath(getCurrentPath(), tree));
-                        maybeVerifyRegExp(var, constant, tree);
-                    }
-                }
-                
-                return super.visitMethodInvocation(node, p);
-            }
-
-            private void maybeVerifyRegExp(Element var, String constant, ExpressionTree tree) {
-                if (Utilities.findAttachedAnnotation(ctx, var, "j1.tutorial.javac.analysis.api.RegExp") != null && constant != null) {
-                    try {
-                        Pattern.compile(constant);
-                    } catch (PatternSyntaxException ex) {
-                        ctx.getTrees().printMessage(Diagnostic.Kind.ERROR, ex.getDescription(), tree, file);
-                    }
-                }
-            }
-        }.scan(file, null);
-    }
-    
-    private String getConstant(final AnalysisContext ctx, final TreePath path) {
-        switch (path.getLeaf().getKind()) {
-            case STRING_LITERAL: return (String) ((LiteralTree) path.getLeaf()).getValue();
-            case PLUS: {
-                BinaryTree binary = (BinaryTree) path.getLeaf();
-                String left = getConstant(ctx, new TreePath(path, binary.getLeftOperand()));
-                String right = getConstant(ctx, new TreePath(path, binary.getRightOperand()));
-                
-                if (left != null && right != null) return left + right;
-                else return null;
-            }
-            case IDENTIFIER:
-            case MEMBER_SELECT: {
-                Element el = ctx.getTrees().getElement(path);
-                
-                if (el != null && el.getKind() == ElementKind.FIELD && ((VariableElement) el).getConstantValue() instanceof String) {
-                    return (String) ((VariableElement) el).getConstantValue();
-                }
-                
-                return null;
-            }
-        }
-        
-        return null;
-    }
-    
-}

analysis/test/j1/tutorial/javac/analysis/rules/CollectionRemoveNGTest.java

+/*
 package j1.tutorial.javac.analysis.rules;
 
 import j1.tutorial.javac.analysis.api.RuleTest;
 //                .assertWarnings();
 //    }
 }
+*/

analysis/test/j1/tutorial/javac/analysis/rules/FinalRuleNGTest.java

+/*
 package j1.tutorial.javac.analysis.rules;
 
 import j1.tutorial.javac.analysis.api.RuleTest;
     }
     
 }
+*/

analysis/test/j1/tutorial/javac/analysis/rules/FriendRuleNGTest.java

+/*
 package j1.tutorial.javac.analysis.rules;
 
 import j1.tutorial.javac.analysis.api.RuleTest;
                 .assertWarnings("/test/Test.java:41-52:Cannot use: call(), not its friend");
     }
 }
+*/

analysis/test/j1/tutorial/javac/analysis/rules/RegExpRuleNGTest.java

+/*
 package j1.tutorial.javac.analysis.rules;
 
 import j1.tutorial.javac.analysis.api.RuleTest;
     //TODO: much more tests
     
 }
+*/