Skip to content

Commit

Permalink
GROOVY-6328
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Oct 28, 2021
1 parent 79530b5 commit 7b3fac3
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2020 the original author or authors.
* Copyright 2009-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,7 +15,9 @@
*/
package org.eclipse.jdt.core.groovy.tests.builder;

import static org.eclipse.jdt.groovy.core.tests.GroovyBundle.isAtLeastGroovy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

import java.util.Arrays;

Expand Down Expand Up @@ -67,12 +69,12 @@ public void testStaticTypeCheckingDSL1() throws Exception {
" storeType(var, robotClass)\n" +
" handled = true\n" +
" }\n" +
"}");
"}\n");
env.addGroovyClass(projPath.append("src"), "Robot",
"@groovy.transform.TypeChecked(extensions = 'RobotMove.groovy')\n" +
"void operate() {\n" +
" robot.move \"left\"\n" +
"}");
"}\n");
//@formatter:on

env.fullBuild(projPath);
Expand All @@ -97,7 +99,7 @@ public void testStaticTypeCheckingDSL2() throws Exception {
" storeType(var, robotClass)\n" +
" handled = true\n" +
" }\n" +
"}");
"}\n");
env.addGroovyClass(projPath.append("src"), "RobotScript",
"import groovy.transform.TypeChecked\n" +
"class Robot {\n" +
Expand All @@ -107,11 +109,52 @@ public void testStaticTypeCheckingDSL2() throws Exception {
"@TypeChecked(extensions = 'RobotMove.groovy')\n" +
"void operate() {\n" +
" robot.move \"left\"\n" +
"}");
"}\n");
//@formatter:on

env.fullBuild(projPath);
Problem[] problems = env.getProblemsFor(projPath);
assertEquals("Should have found no problems in:\n" + Arrays.toString(problems), 0, problems.length);
}

@Test // GROOVY-6328
public void testStaticTypeCheckingDSL3() throws Exception { assumeTrue(isAtLeastGroovy(40));
Activator.getInstancePreferences().putBoolean(Activator.GROOVY_SCRIPT_FILTERS_ENABLED, true);
Activator.getInstancePreferences().put(Activator.GROOVY_SCRIPT_FILTERS, "src/*Checker.groovy,y");

IPath projPath = createGenericProject();
//@formatter:off
env.addGroovyClass(projPath.append("src"), "TypeChecker",
"onMethodSelection { expr, node ->\n" +
" context.enclosingBinaryExpression.putNodeMetaData('notified', true)\n" +
"}\n");
//@formatter:on

for (String methods : new String[] {"", "void setS(String s) {this.s = s}"}) {
env.addGroovyClass(projPath.append("src"), "TestScript",
"import static org.codehaus.groovy.control.CompilePhase.INSTRUCTION_SELECTION\n" +
"class C {\n" +
" String s\n" +
" " + methods + "\n" +
"}\n" +
"C make(@DelegatesTo(value=C.class, strategy=Closure.DELEGATE_FIRST) Closure closure) {\n" +
" new C().tap(closure)\n" +
"}\n" +
"@groovy.transform.ASTTest(phase=INSTRUCTION_SELECTION, value={\n" +
" def assignment = lookup.call('here')[0].expression\n" +
" assert assignment.getNodeMetaData('notified')\n" +
"})\n" +
"@groovy.transform.TypeChecked(extensions='TypeChecker.groovy')\n" +
"void test() {\n" +
" def c = make {\n" +
" here: s = 'foo'\n" + // expecting onMethodSelection for setter
" }\n" +
"}\n");
//@formatter:on

env.fullBuild(projPath);
Problem[] problems = env.getProblemsFor(projPath);
assertEquals("Should have found no problems in:\n" + Arrays.toString(problems), 0, problems.length);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1636,11 +1636,12 @@ protected boolean existsProperty(final PropertyExpression pexp, final boolean re
}
}
}
foundGetterOrSetter = (foundGetterOrSetter || !setters.isEmpty() || getter != null);

if (property != null && storeProperty(property, pexp, receiverType, visitor, receiver.getData())) return true;
if (property != null && storeProperty(property, pexp, receiverType, visitor, receiver.getData(), !readMode)) return true;

if (field != null && storeField(field, pexp, receiverType, visitor, receiver.getData(), !readMode)) return true;

foundGetterOrSetter = (foundGetterOrSetter || !setters.isEmpty() || getter != null);
}

// GROOVY-5568: the property may be defined by DGM
Expand Down Expand Up @@ -1854,16 +1855,29 @@ private boolean storeField(final FieldNode field, final PropertyExpression expre
return true;
}

private boolean storeProperty(final PropertyNode property, final PropertyExpression expressionToStoreOn, final ClassNode receiver, final ClassCodeVisitorSupport visitor, final String delegationData) {
private boolean storeProperty(final PropertyNode property, final PropertyExpression expression, final ClassNode receiver, final ClassCodeVisitorSupport visitor, final String delegationData, final boolean lhsOfAssignment) {
if (visitor != null) visitor.visitProperty(property);
storeWithResolve(property.getOriginType(), receiver, property.getDeclaringClass(), property.isStatic(), expressionToStoreOn);
ClassNode propertyType = property.getOriginType();

storeWithResolve(propertyType, receiver, property.getDeclaringClass(), property.isStatic(), expression);

if (delegationData != null) {
expressionToStoreOn.putNodeMetaData(IMPLICIT_RECEIVER, delegationData);
expression.putNodeMetaData(IMPLICIT_RECEIVER, delegationData);
}
if (Modifier.isFinal(property.getModifiers())) {
expressionToStoreOn.putNodeMetaData(READONLY_PROPERTY, Boolean.TRUE);
expression.putNodeMetaData(READONLY_PROPERTY, Boolean.TRUE);
if (!lhsOfAssignment) {
MethodNode implicitGetter = new MethodNode(property.getGetterNameOrDefault(), Opcodes.ACC_PUBLIC, propertyType, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
implicitGetter.setDeclaringClass(property.getDeclaringClass());
extension.onMethodSelection(expression, implicitGetter);
}
} else {
expressionToStoreOn.removeNodeMetaData(READONLY_PROPERTY);
expression.removeNodeMetaData(READONLY_PROPERTY);
if (lhsOfAssignment) {
MethodNode implicitSetter = new MethodNode(property.getSetterNameOrDefault(), Opcodes.ACC_PUBLIC, VOID_TYPE, new Parameter[] {new Parameter(propertyType, "value")}, ClassNode.EMPTY_ARRAY, null);
implicitSetter.setDeclaringClass(property.getDeclaringClass());
extension.onMethodSelection(expression, implicitSetter);
}
}
return true;
}
Expand Down

0 comments on commit 7b3fac3

Please sign in to comment.