Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OC-31 support compilestatic #267

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clover-groovy/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@
<configuration>
<skipTests>${func.test.skip}</skipTests>
<includes>
<include>**/GroovyUtilsTest.*</include>
<include>**/*TestSuite.*</include>
</includes>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.ConstructorNode
import org.codehaus.groovy.ast.DynamicVariable
import org.codehaus.groovy.ast.FieldNode
import org.codehaus.groovy.ast.GenericsType
import org.codehaus.groovy.ast.GroovyClassVisitor
import org.codehaus.groovy.ast.InnerClassNode
import org.codehaus.groovy.ast.MethodNode
Expand Down Expand Up @@ -56,7 +57,8 @@ class NodePrinter {
"ConstructorNode - $it.name (${joinParameterTypes(it.parameters)})"
},
"org.codehaus.groovy.ast.MethodNode" : { MethodNode it ->
"MethodNode - $it.name (${joinParameterTypes(it.parameters)}) : $it.returnType - synthetic=$it.synthetic"
"MethodNode - $it.name (${printParameterTypes(it.parameters)}) : return=${printClassNode(it.returnType)} - synthetic=$it.synthetic - generics=${printGenericsTypes(it.genericsTypes)}"
//- descriptor=${it.typeDescriptor.toString()}
},
"org.codehaus.groovy.ast.FieldNode" : { FieldNode it ->
"FieldNode - $it.name : $it.type"
Expand Down Expand Up @@ -166,11 +168,95 @@ class NodePrinter {
}

static String joinParameterTypes(Parameter[] parameters) {
Arrays.asList(parameters).stream()
.map(typeToString)
.collect(Collectors.joining(", "))
if (parameters == null) {
return "<null>"
} else {
return Arrays.asList(parameters).stream()
.map(typeToString)
.collect(Collectors.joining(", "))
}
}

static String printParameterType(Parameter param) {
return "Parameter { " +
"type : $param.type," +
"name : $param.name, " +
"originType : $param.originType, " +
"dynamicTyped : $param.dynamicTyped, " +
// "closureShare : $param.closureShare, " +
"defaultValue : $param.defaultValue, " +
// "hasDefaultValue : $param.hasDefaultValue, " +
"inStaticContext : $param.inStaticContext, " +
"modifiers : $param.modifiers " +
"} "
}

static String printParameterTypes(Parameter[] parameters) {
if (parameters == null) {
return "<null>"
} else {
return Arrays.asList(parameters).stream()
.map(parameterToString)
.collect(Collectors.joining(", "))
}
}

static String printGenericsTypes(GenericsType[] genericsTypes) {
if (genericsTypes == null) {
return "<null>"
} else {
return Arrays.asList(genericsTypes).stream()
.map(genericsTypeToString)
.collect(Collectors.joining(", "))
}
}

static String printGenericsType(GenericsType g) {
return "GenericsType { " +
"name : $g.name, " +
"type : $g.type, " +
"lowerBound : $g.lowerBound, " +
"upperBounds : $g.upperBounds, " +
"placeholder : $g.placeholder, " +
"resolved : $g.resolved, " +
"wildcard : $g.wildcard" +
"}"
}

static String printClassNode(ClassNode cn) {
return "ClassNode { " +
"name : $cn.name," +
"modifiers : $cn.modifiers," +
"interfaces : $cn.interfaces," +
"mixins : $cn.mixins," +
"superClass : $cn.superClass," +
"typeAnnotations : $cn.typeAnnotations," +
"componentType : $cn.componentType," +
"genericsTypes : $cn.genericsTypes," +

// "usesGenerics : $cn.usesGenerics," +
// "redirect : $cn.redirect," +
"}"
}

static class GenericsTypeToString implements Function<GenericsType, String> {
@Override
String apply(GenericsType type) {
return printGenericsType(type)
}
}

static GenericsTypeToString genericsTypeToString = new GenericsTypeToString();

static class ParameterToString implements Function<Parameter, String> {
@Override
String apply(Parameter parameter) {
return printParameterType(parameter)
}
}

static ParameterToString parameterToString = new ParameterToString()

static class TypeToString implements Function<Parameter, String> {
@Override
String apply(Parameter parameter) {
Expand Down
48 changes: 35 additions & 13 deletions clover-groovy/src/main/java/org/openclover/groovy/instr/Grover.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.GenericsType;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.Parameter;
Expand Down Expand Up @@ -621,12 +622,19 @@ private ClassNode createSimpleSnifferClassNode() {
}

private void addExprEval(ClassNode clazz) {
//def exprEval(def expr, Integer index) {
//<T> T exprEval(T expr, Integer index) {
// RECORDERCLASS.R.inc(index)
// return expr
//}
final Parameter expr = new Parameter(ClassHelper.DYNAMIC_TYPE, "expr");
final Parameter index = new Parameter(ClassHelper.Integer_TYPE, "index");
final ClassNode typeTClass = ClassHelper.make("T");
typeTClass.setGenericsPlaceHolder(true);
typeTClass.setRedirect(ClassHelper.OBJECT_TYPE);
final GenericsType typeT = new GenericsType(typeTClass);
typeT.setPlaceholder(true);
typeTClass.setGenericsTypes(new GenericsType[]{ typeT });

final Parameter expr = new Parameter(typeTClass, "expr");
final Parameter index = new Parameter(ClassHelper.int_TYPE, "index");
final VariableScope methodScope = new VariableScope();
final Statement methodCode = new BlockStatement(
new Statement[]{
Expand All @@ -639,22 +647,33 @@ private void addExprEval(ClassNode clazz) {
},
methodScope);

clazz.addMethod(
CloverNames.namespace("exprEval"), ACC_STATIC | ACC_PUBLIC,
ClassHelper.DYNAMIC_TYPE,
final MethodNode methodNode = new MethodNode(
CloverNames.namespace("exprEval"),
ACC_STATIC | ACC_PUBLIC,
typeTClass,
new Parameter[]{expr, index},
new ClassNode[]{},
methodCode);
methodNode.setGenericsTypes(new GenericsType[]{ typeT });

clazz.addMethod(methodNode);
}

private void addEvalElvis(ClassNode clazz) {
//def elvisEval(def expr, Integer index) {
//<T> T elvisEval(T expr, int index) {
// boolean isTrue = expr as Boolean
// if (isTrue) { RECORDERCLASS.R.inc(index) } else { RECORDERCLASS.R.inc(index + 1) }
// return expr
//}
final Parameter expr = new Parameter(ClassHelper.DYNAMIC_TYPE, "expr");
final Parameter index = new Parameter(ClassHelper.Integer_TYPE, "index");
final ClassNode typeTClass = ClassHelper.make("T");
typeTClass.setGenericsPlaceHolder(true);
typeTClass.setRedirect(ClassHelper.OBJECT_TYPE);
final GenericsType typeT = new GenericsType(typeTClass);
typeT.setPlaceholder(true);
typeTClass.setGenericsTypes(new GenericsType[]{ typeT });

final Parameter expr = new Parameter(typeTClass, "expr");
final Parameter index = new Parameter(ClassHelper.int_TYPE, "index");
final VariableScope methodScope = new VariableScope();
final Statement methodCode = new BlockStatement(
new Statement[]{
Expand Down Expand Up @@ -690,16 +709,19 @@ private void addEvalElvis(ClassNode clazz) {
methodScope
);

clazz.addMethod(
CloverNames.namespace("elvisEval"), ACC_STATIC | ACC_PUBLIC,
ClassHelper.DYNAMIC_TYPE,
final MethodNode methodNode = new MethodNode(CloverNames.namespace("elvisEval2"),
ACC_STATIC | ACC_PUBLIC,
typeTClass,
new Parameter[]{expr, index},
new ClassNode[]{},
methodCode);
methodNode.setGenericsTypes(new GenericsType[]{ typeT });

clazz.addMethod(methodNode);
}

private void addEvalTestException(ClassNode clazz) {
//def evalTestException(Throwable exception, def expected) {
//int evalTestException(Throwable exception, def expected) {
// boolean isExpected = false
// for (ex in expected) {
// isExpected = isExpected || (exception != null && ex.isAssignableFrom(exception.getClass()))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.openclover.groovy.instr

import groovy.transform.CompileStatic

@CompileStatic
class GroovyElvisOperatorTest extends TestBase {
GroovyElvisOperatorTest(String testName) {
super(testName)
}

GroovyElvisOperatorTest(String methodName, String specificName, File groovyAllJar, List<File> additionalGroovyJars) {
super(methodName, specificName, groovyAllJar, additionalGroovyJars)
}

void testElvisOperatorWithCompileStatic() {
elvisOperatorAndCompileStatic(true)
}

void testElvisOperatorWithoutCompileStatic() {
elvisOperatorAndCompileStatic(false)
}

private void elvisOperatorAndCompileStatic(boolean withCompileStatic) {
instrumentAndCompileWithGrover(
[
"Elvis.groovy":
(withCompileStatic ? "@groovy.transform.CompileStatic " : "") +
"""class Elvis {
void testElvisWithDefType() {
def a = 1, b = 2
def c = a ?: b * b
}
void testElvisWithPrimitiveType() {
int a = 1, b = 2
int c = a ?: b * b
}
void testElvisWithNormalType() {
String a = "1", b = "2"
String c = a ?: b + b
}
void testElvisWithGenericType() {
List<String> l = new ArrayList<String>();
List<String> l2 = l ?: l
}
}
"""
])
//
// assertRegistry db, { Clover2Registry reg ->
// assertPackage reg.model.project, isDefaultPackage, { PackageInfo p ->
// assertFile p, named("C.groovy"), { FullFileInfo f ->
// assertClass f, { ClassInfo it -> it.name == "C" }, { FullClassInfo c ->
// assertMethod(c, and(simplyNamed("testSafeEvalWithField")), { MethodInfo m ->
// assertBranch(m, at(10, 43, 10, 44), complexity(1))
// }) &&
//
// assertMethod(c, and(simplyNamed("testSafeEvalWithClosure")), { MethodInfo m ->
// assertBranch(m, at(13, 48, 13, 67), complexity(1))
// }) &&
//
// assertMethod(c, and(simplyNamed("testSafeEvalWithMethod")), { MethodInfo m ->
// assertBranch(m, at(16, 48, 16, 53), complexity(1))
// }) &&
//
// assertMethod(c, and(simplyNamed("testSafeEvalWithProperty")), { MethodInfo m ->
// assertBranch(m, at(20, 48, 20, 49), complexity(1))
// })
// }
// }
// }
// }
}
}
Loading
Loading