Skip to content

Commit

Permalink
moditect#7 Find more references (Annotations, Type Parameters) WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
nilshartmann committed Jan 2, 2019
1 parent e65f5e5 commit 051ac2a
Show file tree
Hide file tree
Showing 16 changed files with 312 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
@@ -0,0 +1,73 @@
package org.moditect.deptective.plugintest.deps;

import static com.google.testing.compile.CompilationSubject.assertThat;

import org.junit.Test;
import org.moditect.deptective.plugintest.PluginTestBase;
import org.moditect.deptective.plugintest.deps.model.Model;
import org.moditect.deptective.plugintest.deps.service.Service;
import org.moditect.deptective.plugintest.deps.ui.InvalidAnnotation;
import org.moditect.deptective.plugintest.deps.ui.InvalidAnnotationParameter;
import org.moditect.deptective.plugintest.deps.ui.InvalidGenericUIView;
import org.moditect.deptective.plugintest.deps.ui.InvalidGenericView;
import org.moditect.deptective.plugintest.deps.ui.InvalidTypeView;
import org.moditect.deptective.plugintest.deps.ui.InvalidView;

import com.google.testing.compile.Compilation;
import com.google.testing.compile.Compiler;

public class DependenciesTest extends PluginTestBase {

protected Compilation compileWithModelAndService(Class<?> testClass) {
Compilation compilation = Compiler.javac().withOptions("-Xplugin:Deptective", getConfigFileOption())
.compile(forTestClass(Model.class), forTestClass(Service.class), forTestClass(testClass));

return compilation;
}

@Test
public void shouldDetectInvalidRefrencesInMethodParameters() {
Compilation compilation = compileWithModelAndService(InvalidView.class);
assertThat(compilation).failed();
assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.deps.ui does not read org.moditect.deptective.plugintest.deps.model"
);
}

@Test
public void shouldDetectInvalidRefrencesInTypeArguments() {
Compilation compilation = compileWithModelAndService(InvalidGenericView.class);
assertThat(compilation).failed();
assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.deps.ui does not read org.moditect.deptective.plugintest.deps.model"
);

compilation = compileWithModelAndService(InvalidGenericUIView.class);
assertThat(compilation).failed();
assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.deps.ui does not read org.moditect.deptective.plugintest.deps.model"
);

compilation = compileWithModelAndService(InvalidTypeView.class);
assertThat(compilation).failed();
assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.deps.ui does not read org.moditect.deptective.plugintest.deps.model"
);
}


@Test
public void shouldDetectInvalidRefrencesInAnnotations() {
// Compilation compilation = compileWithModelAndService(InvalidAnnotation.class);
// assertThat(compilation).failed();
// assertThat(compilation).hadErrorContaining(
// "package org.moditect.deptective.plugintest.deps.ui does not read org.moditect.deptective.plugintest.deps.model"
// );

Compilation compilation = compileWithModelAndService(InvalidAnnotationParameter.class);
assertThat(compilation).failed();
assertThat(compilation).hadErrorContaining(
"package org.moditect.deptective.plugintest.deps.ui does not read org.moditect.deptective.plugintest.deps.model"
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.moditect.deptective.plugintest.deps.model;

public class Model {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.moditect.deptective.plugintest.deps.model;

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 ModelAnnotation {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.moditect.deptective.plugintest.deps.service;

public class Service {

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

public class GenericUI<T> {

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

public class GenericView<T> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.moditect.deptective.plugintest.deps.ui;

import org.moditect.deptective.plugintest.deps.model.ModelAnnotation;

@ModelAnnotation
public class InvalidAnnotation {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.moditect.deptective.plugintest.deps.ui;

@UIAnnotation(uiClass=org.moditect.deptective.plugintest.deps.model.Model.class)
public class InvalidAnnotationParameter {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.moditect.deptective.plugintest.deps.ui;

import org.moditect.deptective.plugintest.deps.model.Model;

// Access to GenericUI is allowed,
// Access to Mdeol via GenericUI NOT
public class InvalidGenericUIView extends GenericView<GenericUI<Model>>{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.moditect.deptective.plugintest.deps.ui;

import org.moditect.deptective.plugintest.deps.model.Model;

public class InvalidGenericView extends GenericView<Model>{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.moditect.deptective.plugintest.deps.ui;


public class InvalidModel extends org.moditect.deptective.plugintest.deps.model.Model{


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.moditect.deptective.plugintest.deps.ui;

import org.moditect.deptective.plugintest.deps.model.Model;

// Acess to Model forbidden
public class InvalidTypeView<T extends Model> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.moditect.deptective.plugintest.deps.ui;

import org.moditect.deptective.plugintest.deps.model.Model;

public class InvalidView {

public void invalidModelUsage(Model m) {
//
}



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

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 UIAnnotation {
Class<?> uiClass() default String.class;
}
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 051ac2a

Please sign in to comment.