Skip to content

Commit fb74930

Browse files
committed
Fix for issue #166: build path access rules applied to types throughout
1 parent 0f6be28 commit fb74930

File tree

3 files changed

+163
-41
lines changed

3 files changed

+163
-41
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/builder/BuildAccessRulesTests.java

+134-13
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
package org.eclipse.jdt.core.groovy.tests.builder;
1717

18+
import java.util.ArrayList;
19+
import java.util.List;
20+
1821
import junit.framework.Test;
1922

2023
import org.codehaus.groovy.eclipse.core.builder.GroovyClasspathContainer;
@@ -64,25 +67,143 @@ protected void setUp() throws Exception {
6467
env.createFolder(src);
6568
}
6669

67-
//
70+
private void assertAccessRestriction(String source, String... types) {
71+
IPath foo = env.addGroovyClass(src, "Foo", source);
72+
fullBuild();
73+
74+
// read back contents in case of line delimeters change or package statement addition or ...
75+
source = env.readTextFile(foo);
76+
77+
List<String> problems = new ArrayList<String>();
78+
for (String type : types) {
79+
int offset = -1;
80+
while ((offset = source.indexOf(type.trim(), offset + 1)) != -1) {
81+
problems.add("Problem : Access restriction: The type '" + type.trim() + "' is not API (restriction on required library '##')" +
82+
" [ resource : </Project/src/Foo.groovy> range : <" + offset + "," + (offset + type.length()) + "> category : <150> severity : <2>]");
83+
}
84+
}
85+
86+
expectingProblemsFor(foo, problems);
87+
}
88+
89+
//--------------------------------------------------------------------------
90+
91+
public void testAccessForImport() {
92+
String source = "import java.beans.BeanDescriptor";
93+
94+
assertAccessRestriction(source, "BeanDescriptor");
95+
}
6896

6997
public void testAccessForExtends() {
70-
env.addGroovyClass(src, "Foo",
71-
"import java.beans.*\n" +
72-
"class Foo extends BeanDescriptor {}");
73-
fullBuild();
98+
String source = "import java.beans.*\n" +
99+
"class Foo extends BeanDescriptor {}";
74100

75-
expectingProblemsFor(src.append("Foo.groovy"), "Problem : Access restriction: The type 'BeanDescriptor' is not API" +
76-
" (restriction on required library '##') [ resource : </Project/src/Foo.groovy> range : <38,52> category : <150> severity : <2>]");
101+
assertAccessRestriction(source, "BeanDescriptor");
77102
}
78103

79104
public void testAccessForImplements() {
80-
env.addGroovyClass(src, "Foo",
81-
"import java.beans.*\n" +
82-
"abstract class Foo implements BeanInfo {}");
83-
fullBuild();
105+
String source = "import java.beans.*\n" +
106+
"abstract class Foo implements BeanInfo {}";
107+
108+
assertAccessRestriction(source, "BeanInfo "); // interface has +1 sloc...
109+
}
110+
111+
public void testAccessForExtendsGenerics() {
112+
String source = "import java.beans.*\n" +
113+
"class Foo extends ArrayList<BeanDescriptor> {}";
114+
115+
assertAccessRestriction(source, "BeanDescriptor");
116+
}
117+
118+
public void testAccessForImplementsGenerics() {
119+
String source = "import java.beans.*\n" +
120+
"abstract class Foo implements List<BeanInfo> {}";
121+
122+
assertAccessRestriction(source, "BeanInfo");
123+
}
124+
125+
public void testAccessForField() {
126+
String source = "import java.beans.*\n" +
127+
"class Foo { private BeanInfo info }";
128+
129+
assertAccessRestriction(source, "BeanInfo");
130+
}
131+
132+
public void testAccessForProperty() {
133+
String source = "import java.beans.*\n" +
134+
"class Foo { BeanInfo info }";
135+
136+
assertAccessRestriction(source, "BeanInfo");
137+
}
138+
139+
public void testAccessForFieldGenerics() {
140+
String source = "import java.beans.*\n" +
141+
"class Foo { private List<BeanInfo> info }";
142+
143+
assertAccessRestriction(source, "BeanInfo");
144+
}
145+
146+
public void testAccessForPropertyGenerics() {
147+
String source = "import java.beans.*\n" +
148+
"class Foo { List<BeanInfo> info }";
149+
150+
assertAccessRestriction(source, "BeanInfo");
151+
}
152+
153+
public void testAccessForLazyProperty() {
154+
String source = "import java.beans.*\n" +
155+
"abstract class Foo {\n" +
156+
" @Lazy BeanInfo info = init()\n" +
157+
" abstract def init()\n" +
158+
"}";
159+
160+
assertAccessRestriction(source, "BeanInfo");
161+
}
162+
163+
public void testAccessForMethodParameter() {
164+
String source = "import java.beans.*\n" +
165+
"class Foo {\n" +
166+
" def meth(BeanInfo info) { }\n" +
167+
"}";
168+
169+
assertAccessRestriction(source, "BeanInfo");
170+
}
171+
172+
public void testAccessForMethodReturnType() {
173+
String source = "import java.beans.*\n" +
174+
"class Foo {\n" +
175+
" BeanInfo meth() { }\n" +
176+
"}";
177+
178+
assertAccessRestriction(source, "BeanInfo");
179+
}
180+
181+
public void testAccessForMethodParameterGenerics() {
182+
String source = "import java.beans.*\n" +
183+
"class Foo {\n" +
184+
" def meth(List<BeanInfo> info) { }\n" +
185+
" }";
186+
187+
assertAccessRestriction(source, "BeanInfo");
188+
}
189+
190+
public void testAccessForMethodReturnTypeGenerics() {
191+
String source = "import java.beans.*\n" +
192+
"class Foo {\n" +
193+
" List<BeanInfo> meth() { }\n" +
194+
"}";
195+
196+
assertAccessRestriction(source, "BeanInfo");
197+
}
198+
199+
public void testAccessForLocalVariable() {
200+
String source = "import java.beans.*\n" +
201+
"class Foo {\n" +
202+
" def meth() {\n" +
203+
" BeanInfo info = null\n" +
204+
" }\n" +
205+
"}";
84206

85-
expectingProblemsFor(src.append("Foo.groovy"), "Problem : Access restriction: The type 'BeanInfo' is not API" +
86-
" (restriction on required library '##') [ resource : </Project/src/Foo.groovy> range : <50,59> category : <150> severity : <2>]");
207+
assertAccessRestriction(source, "BeanInfo");
87208
}
88209
}

base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/internal/compiler/ast/JDTClassNode.java

+10-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2016 the original author or authors.
2+
* Copyright 2009-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -68,18 +68,16 @@
6868
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
6969

7070
/**
71-
* Groovy can use these to ask questions of JDT bindings. They are only built as required (as groovy references to java files are
72-
* resolved). They remain uninitialized until groovy starts digging into them - at that time the details are filled in (eg.
73-
* members).
74-
*
75-
* @author Andy Clement
71+
* Groovy can use these to ask questions of JDT bindings. They are only built as
72+
* required (as groovy references to java files are resolved). They remain
73+
* uninitialized until groovy starts digging into them - at that time the details
74+
* are filled in (eg. members).
7675
*/
7776
public class JDTClassNode extends ClassNode implements JDTNode {
7877

7978
private static final Parameter[] NO_PARAMETERS = new Parameter[0];
8079

81-
// arbitrary choice of first eight. Maintaining these as a constant array prevents 10000 strings called 'arg0' consuming
82-
// memory
80+
// arbitrary choice of first eight; maintaining these as a constant array prevents 10000 strings called 'arg0' consuming memory
8381
private final static String[] argNames = new String[] { "arg0", "arg1", "arg2", "arg3", "arg4", "arg5", "arg6", "arg7" };
8482

8583
// The binding which this JDTClassNode represents
@@ -402,25 +400,17 @@ private Parameter makeParameter(TypeBinding parameterType, int paramNumber) {
402400
}
403401

404402
/**
405-
*
406-
* @param type
407-
* @param cl erasure of type
408-
* @return
403+
* @param t type
404+
* @param c erasure of type
409405
*/
410406
private ClassNode makeClassNode(TypeBinding t, TypeBinding c) {
411-
// was:
412-
// return resolver.convertToClassNode(type);
413-
ClassNode back = null;
414-
// This line would check the compile unit
415-
// if (cu != null) back = cu.getClass(c.getName());
416-
if (back == null)
417-
back = resolver.convertToClassNode(c);// ClassHelper.make(c);
407+
ClassNode back = resolver.convertToClassNode(c);
418408
if (!((t instanceof BinaryTypeBinding) || (t instanceof SourceTypeBinding))) {
419409
ClassNode front = JDTClassNodeBuilder.build(this.resolver, t);
420410
front.setRedirect(back);
421411
return front;
422412
}
423-
return back;// .getPlainNodeReference();
413+
return back;
424414
}
425415

426416
public GenericsType[] getGenericsTypes() {
@@ -455,7 +445,6 @@ private ConstructorNode constructorBindingToConstructorNode(MethodBinding method
455445
}
456446
}
457447
ctorNode = new ConstructorNode(modifiers, parameters, thrownExceptions, null);
458-
459448
ctorNode.setGenericsTypes(generics);
460449
return ctorNode;
461450
}
@@ -503,8 +492,6 @@ private FieldNode fieldBindingToFieldNode(FieldBinding fieldBinding, TypeDeclara
503492
return fNode;
504493
}
505494

506-
// FIXASC Need to override anything else from the supertype?
507-
508495
@Override
509496
public boolean isReallyResolved() {
510497
return true;

base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/internal/compiler/ast/JDTResolver.java

+19-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2016 the original author or authors.
2+
* Copyright 2009-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -37,7 +37,9 @@
3737
import org.codehaus.jdt.groovy.internal.compiler.ast.GroovyParser.GrapeAwareGroovyClassLoader;
3838
import org.eclipse.jdt.core.compiler.CharOperation;
3939
import org.eclipse.jdt.groovy.core.util.ReflectionUtils;
40+
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
4041
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
42+
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
4143
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
4244
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
4345

@@ -154,6 +156,16 @@ protected boolean resolveFromModule(ClassNode type, boolean testModuleImports) {
154156
if (DEBUG) {
155157
log("resolveFromModule", type, foundit);
156158
}
159+
if (foundit) {
160+
if (type.redirect() instanceof JDTClassNode && ((JDTClassNode) type.redirect()).getJdtBinding().hasRestrictedAccess()) {
161+
TypeBinding binding = ((JDTClassNode) type.redirect()).getJdtBinding();
162+
AccessRestriction restriction = activeScope.environment().getAccessRestriction(binding.erasure());
163+
if (restriction != null) {
164+
SingleTypeReference ref = new SingleTypeReference(type.getNameWithoutPackage().toCharArray(), ((long) type.getStart() << 32 | (long) type.getEnd() - 1));
165+
activeScope.problemReporter().forbiddenReference(binding, ref, restriction.classpathEntryType, restriction.classpathEntryName, restriction.getProblemId());
166+
}
167+
}
168+
}
157169
return foundit;
158170
}
159171

@@ -435,11 +447,12 @@ private JDTClassNode checkForExisting(TypeBinding jdtBinding) {
435447
}
436448

437449
/**
438-
* Creates a Groovy ClassNode that represents the JDT TypeBinding. Build the basic structure, mark it as 'in progress' and then
439-
* continue with initialization. This allows self referential generic declarations.
450+
* Creates a Groovy ClassNode that represents the JDT TypeBinding. Steps
451+
* include building the basic structure, marking node as 'in progress' and
452+
* continuing with initialization. This allows self-referential generics.
440453
*
441454
* @param jdtBinding the JDT binding for which to create a ClassNode
442-
* @return the new ClassNode, of type JDTClassNode
455+
* @return a {@link JDTClassNode}
443456
*/
444457
private ClassNode createJDTClassNode(TypeBinding jdtBinding) {
445458
JDTClassNodeBuilder cnb = new JDTClassNodeBuilder(this);
@@ -449,7 +462,8 @@ private ClassNode createJDTClassNode(TypeBinding jdtBinding) {
449462
assert !inProgress.containsKey(jdtBinding);
450463
inProgress.put(jdtBinding, jdtNode);
451464

452-
jdtNode.setupGenerics(); // for a BinaryTypeBinding this fixes up those generics
465+
// fix up generics for BinaryTypeBinding
466+
jdtNode.setupGenerics();
453467

454468
assert nodeCache.get(jdtBinding) == null : "not unique";
455469
nodeCache.put(jdtBinding, jdtNode);

0 commit comments

Comments
 (0)