Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
moditect#7 Find more references (Annotations, Type Parameters) WIP
Browse files Browse the repository at this point in the history
nilshartmann committed Jan 2, 2019

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent e65f5e5 commit e6cdbb9
Showing 10 changed files with 313 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -21,12 +21,18 @@
import org.moditect.deptective.internal.model.Package;
import org.moditect.deptective.internal.model.PackageDependencies;

import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.TypeParameterTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TreePathScanner;
import com.sun.tools.javac.api.BasicJavacTask;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;

@@ -64,25 +70,100 @@ public Void visitCompilationUnit(CompilationUnitTree tree, Void p) {

return super.visitCompilationUnit(tree, p);
}

@Override



// @Override
// public Void visitImport(ImportTree node, Void p) {
// System.out.println("QI: " + node.getQualifiedIdentifier().getKind() + " -> " + node.getQualifiedIdentifier());
// node.getQualifiedIdentifier().accept(new TreeScanner<Void, Void>() {
// @Override
// public Void visitMemberSelect(MemberSelectTree n, Void p) {
// return super.visitMemberSelect(n, p);
// }
// }, null);
//
// checkPackageAccess(node, getQualifiedName(node.getQualifiedIdentifier()));
// return super.visitImport(node, p);
// }

@Override
public Void visitVariable(VariableTree node, Void p) {
com.sun.tools.javac.tree.JCTree jcTree = (com.sun.tools.javac.tree.JCTree)node;
com.sun.tools.javac.tree.JCTree jcTree = (com.sun.tools.javac.tree.JCTree)node;

PackageElement pakkage = elements.getPackageOf(jcTree.type.asElement());
String qualifiedName = pakkage.getQualifiedName().toString();

if (!packageDependencies.isWhitelisted(qualifiedName)) {
if (!qualifiedName.isEmpty() && !packageOfCurrentCompilationUnit.reads(qualifiedName)) {
if (reportingPolicy == ReportingPolicy.ERROR) {
log.error(jcTree.pos, DeptectiveMessages.ILLEGAL_PACKAGE_DEPENDENCY, packageOfCurrentCompilationUnit, qualifiedName);
}
else {
log.strictWarning(jcTree, DeptectiveMessages.ILLEGAL_PACKAGE_DEPENDENCY, packageOfCurrentCompilationUnit, qualifiedName);
}
}
}
checkPackageAccess(node, qualifiedName);

return super.visitVariable(node, p);
}

@Override
public Void visitTypeParameter(TypeParameterTree node, Void p) {
node.getBounds().forEach(s -> {
checkPackageAccess(s, getQualifiedName(s));
});

return super.visitTypeParameter(node, p);
}

@Override
public Void visitParameterizedType(ParameterizedTypeTree node, Void p) {
node.getTypeArguments().forEach(s -> {
checkPackageAccess(s, getQualifiedName(s));
});
return super.visitParameterizedType(node, p);
}

@Override
public Void visitAnnotation(AnnotationTree node, Void p) {
checkPackageAccess(node.getAnnotationType(), getQualifiedName(node));

// node.getArguments().forEach(expr -> {
//
// System.out.println("expr" + expr + "(" + expr.getClass().getName() + ")");
// if (expr instanceof AssignmentTree) {
// AssignmentTree assignmentTree = (AssignmentTree)expr;
// System.out.println("expr" + expr);
// System.out.println("qn => " + getQualifiedName(assignmentTree.getExpression()));
// checkPackageAccess(assignmentTree.getExpression(), getQualifiedName(assignmentTree.getExpression()));
// }
// });
return super.visitAnnotation(node, p);
}

protected String getQualifiedName(Tree tree) {
com.sun.tools.javac.tree.JCTree jcTree = (com.sun.tools.javac.tree.JCTree)tree;
Type type = jcTree.type;
if (type == null) {
throw new IllegalArgumentException("Could not determine type for tree object " + tree + " (" + tree.getClass()+")");
}
System.out.println("TX: " + type.asElement());
PackageElement pakkage = elements.getPackageOf(type.asElement());
return pakkage.getQualifiedName().toString();
}

protected void checkPackageAccess(Tree node, String qualifiedName) {
com.sun.tools.javac.tree.JCTree jcTree = (com.sun.tools.javac.tree.JCTree)node;

if (packageDependencies.isWhitelisted(qualifiedName)) {
return;
}

if (packageOfCurrentCompilationUnit.getName().equals(qualifiedName)) {
return;
}

if (qualifiedName.isEmpty() || packageOfCurrentCompilationUnit.reads(qualifiedName)) {
return;
}


if (reportingPolicy == ReportingPolicy.ERROR) {
log.error(jcTree.pos, DeptectiveMessages.ILLEGAL_PACKAGE_DEPENDENCY, packageOfCurrentCompilationUnit, qualifiedName);
}
else {
log.strictWarning(jcTree, DeptectiveMessages.ILLEGAL_PACKAGE_DEPENDENCY, packageOfCurrentCompilationUnit, qualifiedName);
}
}
}
Original file line number Diff line number Diff line change
@@ -32,51 +32,123 @@
import com.google.testing.compile.Compiler;

public class BasicPluginTest extends PluginTestBase {

private Compilation compile() {
Compilation compilation = Compiler.javac()
.withOptions(
"-Xplugin:Deptective",
getConfigFileOption()
)
.compile(
forTestClass(BarCtorCall.class),
forTestClass(BarField.class),
forTestClass(BarLocalVar.class),
forTestClass(BarLoopVar.class),
forTestClass(BarParameter.class),
forTestClass(BarRetVal.class),
forTestClass(BarTypeArg.class),
forTestClass(Foo.class)
);

@Test
public void shouldDetectDisallowedPackageDependence() {
Compilation compilation = Compiler.javac()
.withOptions(
"-Xplugin:Deptective",
getConfigFileOption()
)
.compile(
forTestClass(BarCtorCall.class),
forTestClass(BarField.class),
forTestClass(BarLocalVar.class),
forTestClass(BarLoopVar.class),
forTestClass(BarParameter.class),
forTestClass(BarRetVal.class),
forTestClass(BarTypeArg.class),
forTestClass(Foo.class)
);

assertThat(compilation).failed();

return compilation;
}

// TODO https://github.com/moditect/deptective/issues/7
// @Test
// public void shouldDetectInvalidConstructorParameters() {
// Compilation compilation = compile();
// assertThat(compilation).failed();
//
// // TODO https://github.com/moditect/deptective/issues/7
// assertThat(compilation).hadErrorContaining(
// "package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.barctorcall"
// );
// }

@Test
public void shouldDetectInvalidFieldReferences() {
Compilation compilation = compile();
assertThat(compilation).failed();

assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.barfield"
);
}

@Test
public void shouldDetectInvalidLocalVariableReferences() {
Compilation compilation = compile();
assertThat(compilation).failed();

assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.barlocalvar"
);
}

@Test
public void shouldDetectInvalidLoopVariableReferences() {
Compilation compilation = compile();
assertThat(compilation).failed();

assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.barloopvar"
);
}

@Test
public void shouldDetectInvalidMethodParameterReferences() {
Compilation compilation = compile();
assertThat(compilation).failed();

assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.barparameter"
);
}

@Test
public void shouldDetectInvalidAnnotationReferences() {
Compilation compilation = compile();
assertThat(compilation).failed();

assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.barclazzan"
);
assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.barfieldan"
);
}

// @Test
// public void shouldDetectInvalidReturnValueReferences() {
// Compilation compilation = compile();
// assertThat(compilation).failed();
//
// // TODO https://github.com/moditect/deptective/issues/7
// assertThat(compilation).hadErrorContaining(
// "package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.barretval"
// );
//
// }

@Test
public void shouldDetectInvalidTypeArguments() {
Compilation compilation = compile();
assertThat(compilation).failed();

// TODO https://github.com/moditect/deptective/issues/7
// assertThat(compilation).hadErrorContaining(
// "package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.barretval"
// );
// assertThat(compilation).hadErrorContaining(
// "package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.bartypearg"
// );
// in type argument
assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.bartypearg"
);

// in class definition type argument bound
assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.bargen"
);

// in 'extends' class definition type argument
assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.basic.foo does not read org.moditect.deptective.plugintest.basic.bargentype"
);
}

@Test
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.moditect.deptective.plugintest.basic.barclazzan;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.MODULE;
import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.TYPE_PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER,
TYPE_USE, MODULE })
public @interface BarClazzAnnotation {
Class<?> classParameter() default String.class;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.moditect.deptective.plugintest.basic.barfieldan;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.MODULE;
import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.TYPE_PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER,
TYPE_USE, MODULE })
public @interface BarFieldAnnotation {
Class<?> classParameter() default String.class;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.moditect.deptective.plugintest.basic.bargen;

public class BarGeneric {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.moditect.deptective.plugintest.basic.bargentype;

public class BarGenType {

}
Original file line number Diff line number Diff line change
@@ -18,16 +18,23 @@
import java.util.ArrayList;
import java.util.List;

import org.moditect.deptective.plugintest.basic.barclazzan.BarClazzAnnotation;
import org.moditect.deptective.plugintest.basic.barctorcall.BarCtorCall;
import org.moditect.deptective.plugintest.basic.barfield.BarField;
import org.moditect.deptective.plugintest.basic.barfieldan.BarFieldAnnotation;
import org.moditect.deptective.plugintest.basic.bargen.BarGeneric;
import org.moditect.deptective.plugintest.basic.bargentype.BarGenType;
import org.moditect.deptective.plugintest.basic.barlocalvar.BarLocalVar;
import org.moditect.deptective.plugintest.basic.barloopvar.BarLoopVar;
import org.moditect.deptective.plugintest.basic.barparameter.BarParameter;
import org.moditect.deptective.plugintest.basic.barretval.BarRetVal;
import org.moditect.deptective.plugintest.basic.bartypearg.BarTypeArg;

@FooAnnotation
@BarClazzAnnotation
public class Foo {

@BarFieldAnnotation
private String s;
private final BarField bar = new BarField();

@@ -46,6 +53,12 @@ public BarRetVal doSomething(BarParameter bar) {

return null;
}

static class InvalidFooGeneric<T extends BarGeneric> {}

static class InvalidFooImplementation extends FooContainer<BarGenType> {}




}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.moditect.deptective.plugintest.basic.foo;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.MODULE;
import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.TYPE_PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER,
TYPE_USE, MODULE })
public @interface FooAnnotation {
Class<?> classParameter() default String.class;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.moditect.deptective.plugintest.basic.foo;

public class FooContainer<T> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"packages" : [
{
"name" : "org.moditect.deptective.plugintest.deps.model"
},
{
"name" : "org.moditect.deptective.plugintest.deps.service",
"reads" : [
"org.moditect.deptective.plugintest.deps.model"
]
},
{
"name" : "org.moditect.deptective.plugintest.deps.ui",
"reads" : [
"org.moditect.deptective.plugintest.deps.service"
]
}
]
}

0 comments on commit e6cdbb9

Please sign in to comment.