Skip to content

Commit

Permalink
Processing JavaType types
Browse files Browse the repository at this point in the history
Processing JavaType types instead of J types.  This allows for types to be processed via dynamic type binding
  • Loading branch information
jimbethancourt committed Nov 22, 2024
1 parent 807337c commit c1ff015
Show file tree
Hide file tree
Showing 16 changed files with 192 additions and 110 deletions.
Original file line number Diff line number Diff line change
@@ -1,72 +1,151 @@
package org.hjug.parser;

import lombok.extern.slf4j.Slf4j;
import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultDirectedWeightedGraph;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.*;

@Slf4j
public class JavaVariableVisitor<P> extends JavaIsoVisitor<P> {

Graph<String, DefaultWeightedEdge> classReferencesGraph =
new DefaultDirectedWeightedGraph<>(DefaultWeightedEdge.class);

/**
* Variable type is B
* Owning type is A
*
* <p>
* class A {
* B b1, b2;
* B b1, b2;
* }
*/
@Override
public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, P p) {
J.VariableDeclarations variableDeclarations = super.visitVariableDeclarations(multiVariable, p);

// TODO: getAllAnnotations() is deprecated - need to get Cursor and call
// AnnotationService.getAllAnnotations(cursor)
System.out.println("*************************");
System.out.println(variableDeclarations);
System.out.println("*************************");

JavaType owner =
variableDeclarations.getVariables().get(0).getVariableType().getOwner();
String ownerFqn = "";

if (owner instanceof JavaType.Method) {
JavaType.Method m = (JavaType.Method) owner;
// System.out.println("Method owner: " + m.getDeclaringType().getFullyQualifiedName());
ownerFqn = m.getDeclaringType().getFullyQualifiedName();
} else if (owner instanceof JavaType.Class) {
JavaType.Class c = (JavaType.Class) owner;
// System.out.println("Method owner: " + c.getFullyQualifiedName());
ownerFqn = c.getFullyQualifiedName();
}

TypeTree typeTree = variableDeclarations.getTypeExpression();

// skip class definition to prevent all types from self-referencing
if (typeTree instanceof J.Identifier) {
return variableDeclarations;
}

JavaType javaType;
if (null != typeTree) {
javaType = typeTree.getType();
} else {
return variableDeclarations;
}

// TODO: getAllAnnotations() is deprecated - need to call
// AnnotationService.getAllAnnotations() but not sure which one yet
// but I'm not sure how to get a cursor
// All types, including primitives can be annotated
System.out.println("Type annotations: " + variableDeclarations.getAllAnnotations());
for (J.Annotation annotation : variableDeclarations.getAllAnnotations()) {
JavaType.Class type = (JavaType.Class) annotation.getType();
if (null != type) {
String annotationFqn = type.getFullyQualifiedName();
System.out.println("Variable Annotation FQN: " + annotationFqn);
addType(ownerFqn, annotationFqn);
}
}

// skip primitive variable declarations
if (variableDeclarations.getTypeExpression() instanceof J.Primitive) {
if (javaType instanceof JavaType.Primitive) {
return variableDeclarations;
} else if (variableDeclarations.getTypeExpression() instanceof J.ParameterizedType) {
}

processType(javaType, ownerFqn);

return variableDeclarations;
}

// processType methods are mutually recursive
void processType(JavaType javaType, String ownerFqn) {
if (javaType instanceof JavaType.Class) {
processType((JavaType.Class) javaType, ownerFqn);
} else if (javaType instanceof JavaType.Parameterized) {
// A<E> --> A
// get Variable type
System.out.println("Parametrized Variable type: "
+ ((J.ParameterizedType) variableDeclarations.getTypeExpression())
.getClazz()
.getType());

// A<E> --> E
// gets variable's type parameters
System.out.println("Type parameters: "
+ ((J.ParameterizedType) variableDeclarations.getTypeExpression()).getTypeParameters());
} else if (variableDeclarations.getTypeExpression() instanceof J.ArrayType) {
// D[] --> D
System.out.println(
"Array Element type: " + ((J.ArrayType) variableDeclarations.getTypeExpression()).getElementType());

} else if (variableDeclarations.getTypeExpression() instanceof J.Identifier) {
// G --> G
System.out.println("Identifier type: " + (variableDeclarations.getTypeExpression()).getType());
processType((JavaType.Parameterized) javaType, ownerFqn);
} else if (javaType instanceof JavaType.GenericTypeVariable) {
// T t;
processType((JavaType.GenericTypeVariable) javaType, ownerFqn);
} else if (javaType instanceof JavaType.Array) {
processType((JavaType.Array) javaType, ownerFqn);
}
}

// *should* always have get(0)
System.out.println( "Varible Owner: " +
variableDeclarations.getVariables().get(0).getVariableType().getOwner());
private void processType(JavaType.Parameterized parameterized, String ownerFqn) {
// List<A<E>> --> A
processAnnotations(parameterized, ownerFqn);
System.out.println("Parameterized type FQN : " + parameterized.getFullyQualifiedName());
addType(ownerFqn, parameterized.getFullyQualifiedName());

System.out.println( "Varible Owner Class: " +
variableDeclarations.getVariables().get(0).getVariableType().getOwner().getClass());
System.out.println("Nested Parameterized type parameters: " + parameterized.getTypeParameters());
for (JavaType parameter : parameterized.getTypeParameters()) {
processType(parameter, ownerFqn);
}
}

/* for (J.VariableDeclarations.NamedVariable variable : variableDeclarations.getVariables()) {
System.out.println(
"Varible VariableType Owner: " + variable.getVariableType().getOwner());
System.out.println("Varible type: " + variable.getType());
System.out.println("Varible name: " + variable.getName());
}*/
private void processType(JavaType.Array arrayType, String ownerFqn) {
// D[] --> D
System.out.println("Array Element type: " + arrayType.getElemType());
processType(arrayType.getElemType(), ownerFqn);
}

System.out.println("*************************");
System.out.println(variableDeclarations.toString());
System.out.println("*************************");
private void processType(JavaType.GenericTypeVariable typeVariable, String ownerFqn) {
System.out.println("Type parameter type name: " + typeVariable.getName());

return variableDeclarations;
for (JavaType bound : typeVariable.getBounds()) {
processType(bound, ownerFqn);
}
}

private void processType(JavaType.Class classType, String ownerFqn) {
processAnnotations(classType, ownerFqn);
System.out.println("Class type FQN: " + classType.getFullyQualifiedName());
addType(ownerFqn, classType.getFullyQualifiedName());
}

void processAnnotations(JavaType.FullyQualified fullyQualified, String ownerFqn) {
if (!fullyQualified.getAnnotations().isEmpty()) {
for (JavaType.FullyQualified annotation : fullyQualified.getAnnotations()) {
String annotationFqn = annotation.getFullyQualifiedName();
System.out.println("Extra Annotation FQN: " + annotationFqn);
addType(ownerFqn, annotationFqn);
}
}
}

void addType(String ownerFqn, String typeFqn) {
classReferencesGraph.addVertex(ownerFqn);
classReferencesGraph.addVertex(typeFqn);

if (!classReferencesGraph.containsEdge(ownerFqn, typeFqn)) {
classReferencesGraph.addEdge(ownerFqn, typeFqn);
} else {
DefaultWeightedEdge edge = classReferencesGraph.getEdge(ownerFqn, typeFqn);
classReferencesGraph.setEdgeWeight(edge, classReferencesGraph.getEdgeWeight(edge) + 1);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ void visitClasses() throws IOException {

// return fqdns;
}

class Inner {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.hjug.javaVariableVisitorTestClasses;

import java.util.Map;
import java.util.List;

public class A<T> {

public A(B cB, C cC){}

@MyAnnotation
@MyOtherAnnotation
int intVar, intVar2;
@MyAnnotation
@MyOtherAnnotation
C rawC;
B<B> b, b3;
C<B.InnerB, C> c;
D[] ds;

@MyAnnotation
B<C>[] arrayOfGenericBsWithCTypeParam;
@MyAnnotation
B<C[]> bWithArrayOfCs;
List<A<B>> listWithNestedGenric;
Map<A,B> map;
List<? extends List<? extends Number>> listOfListsOfNumbers;

C doSomething(B<C> paramB) {
List<B<E>> list3;
A<E> a2;
B<C> b2;
C<A,B> c2;
return new C();
}

class InnerClass{
class InnerInner{
class MegaInner{
D d;
}
}
}
static class StaticInnerClass{}
}

class NonPublic {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.hjug.javaVariableVisitorTestClasses;

public class B<T> {

static class InnerB{}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.hjug.javaVariableVisitorTestClasses;

public class C<T,U> {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.hjug.javaVariableVisitorTestClasses;

public class D {
// A a;
// C c;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.hjug.javaVariableVisitorTestClasses;

public interface E {
void foo(A a);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.hjug.javaVariableVisitorTestClasses;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package org.hjug.javaVariableVisitorTestClasses;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

0 comments on commit c1ff015

Please sign in to comment.