提交 8a4a34f1 编写于 作者: M mfang

Merge

/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -241,12 +241,16 @@ public class Scope {
listeners = listeners.prepend(sl);
}
/** Remove symbol from this scope. Used when an inner class
* attribute tells us that the class isn't a package member.
/** Remove symbol from this scope.
*/
public void remove(Symbol sym) {
public void remove(final Symbol sym) {
Assert.check(shared == 0);
Entry e = lookup(sym.name);
Entry e = lookup(sym.name, new Filter<Symbol>() {
@Override
public boolean accepts(Symbol candidate) {
return candidate == sym;
}
});
if (e.scope == null) return;
// remove e from table and shadowed list;
......
......@@ -2694,74 +2694,98 @@ public class Types {
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="compute transitive closure of all members in given site">
class MembersClosureCache extends SimpleVisitor<CompoundScope, Boolean> {
class MembersClosureCache extends SimpleVisitor<Scope.CompoundScope, Void> {
private WeakHashMap<TypeSymbol, Entry> _map =
new WeakHashMap<TypeSymbol, Entry>();
private Map<TypeSymbol, CompoundScope> _map = new HashMap<>();
class Entry {
final boolean skipInterfaces;
final CompoundScope compoundScope;
Set<TypeSymbol> seenTypes = new HashSet<>();
class MembersScope extends CompoundScope {
CompoundScope scope;
public MembersScope(CompoundScope scope) {
super(scope.owner);
this.scope = scope;
}
Filter<Symbol> combine(final Filter<Symbol> sf) {
return new Filter<Symbol>() {
@Override
public boolean accepts(Symbol s) {
return !s.owner.isInterface() && (sf == null || sf.accepts(s));
}
};
}
public Entry(boolean skipInterfaces, CompoundScope compoundScope) {
this.skipInterfaces = skipInterfaces;
this.compoundScope = compoundScope;
@Override
public Iterable<Symbol> getElements(Filter<Symbol> sf) {
return scope.getElements(combine(sf));
}
@Override
public Iterable<Symbol> getElementsByName(Name name, Filter<Symbol> sf) {
return scope.getElementsByName(name, combine(sf));
}
boolean matches(boolean skipInterfaces) {
return this.skipInterfaces == skipInterfaces;
@Override
public int getMark() {
return scope.getMark();
}
}
List<TypeSymbol> seenTypes = List.nil();
CompoundScope nilScope;
/** members closure visitor methods **/
public CompoundScope visitType(Type t, Boolean skipInterface) {
return null;
public CompoundScope visitType(Type t, Void _unused) {
if (nilScope == null) {
nilScope = new CompoundScope(syms.noSymbol);
}
return nilScope;
}
@Override
public CompoundScope visitClassType(ClassType t, Boolean skipInterface) {
if (seenTypes.contains(t.tsym)) {
public CompoundScope visitClassType(ClassType t, Void _unused) {
if (!seenTypes.add(t.tsym)) {
//this is possible when an interface is implemented in multiple
//superclasses, or when a classs hierarchy is circular - in such
//superclasses, or when a class hierarchy is circular - in such
//cases we don't need to recurse (empty scope is returned)
return new CompoundScope(t.tsym);
}
try {
seenTypes = seenTypes.prepend(t.tsym);
seenTypes.add(t.tsym);
ClassSymbol csym = (ClassSymbol)t.tsym;
Entry e = _map.get(csym);
if (e == null || !e.matches(skipInterface)) {
CompoundScope membersClosure = new CompoundScope(csym);
if (!skipInterface) {
for (Type i : interfaces(t)) {
membersClosure.addSubScope(visit(i, skipInterface));
}
CompoundScope membersClosure = _map.get(csym);
if (membersClosure == null) {
membersClosure = new CompoundScope(csym);
for (Type i : interfaces(t)) {
membersClosure.addSubScope(visit(i, null));
}
membersClosure.addSubScope(visit(supertype(t), skipInterface));
membersClosure.addSubScope(visit(supertype(t), null));
membersClosure.addSubScope(csym.members());
e = new Entry(skipInterface, membersClosure);
_map.put(csym, e);
_map.put(csym, membersClosure);
}
return e.compoundScope;
return membersClosure;
}
finally {
seenTypes = seenTypes.tail;
seenTypes.remove(t.tsym);
}
}
@Override
public CompoundScope visitTypeVar(TypeVar t, Boolean skipInterface) {
return visit(t.getUpperBound(), skipInterface);
public CompoundScope visitTypeVar(TypeVar t, Void _unused) {
return visit(t.getUpperBound(), null);
}
}
private MembersClosureCache membersCache = new MembersClosureCache();
public CompoundScope membersClosure(Type site, boolean skipInterface) {
return membersCache.visit(site, skipInterface);
CompoundScope cs = membersCache.visit(site, null);
if (cs == null)
Assert.error("type " + site);
return skipInterface ? membersCache.new MembersScope(cs) : cs;
}
// </editor-fold>
......
......@@ -825,9 +825,18 @@ public class Attr extends JCTree.Visitor {
}
public void visitClassDef(JCClassDecl tree) {
// Local classes have not been entered yet, so we need to do it now:
if ((env.info.scope.owner.kind & (VAR | MTH)) != 0)
// Local and anonymous classes have not been entered yet, so we need to
// do it now.
if ((env.info.scope.owner.kind & (VAR | MTH)) != 0) {
enter.classEnter(tree, env);
} else {
// If this class declaration is part of a class level annotation,
// as in @MyAnno(new Object() {}) class MyClass {}, enter it in
// order to simplify later steps and allow for sensible error
// messages.
if (env.tree.hasTag(NEWCLASS) && TreeInfo.isInAnnotation(env, tree))
enter.classEnter(tree, env);
}
ClassSymbol c = tree.sym;
if (c == null) {
......
......@@ -1256,6 +1256,9 @@ public class DeferredAttr extends JCTree.Visitor {
return isSimpleReceiver(((JCAnnotatedType)rec).underlyingType);
case APPLY:
return true;
case NEWCLASS:
JCNewClass nc = (JCNewClass) rec;
return nc.encl == null && nc.def == null && !TreeInfo.isDiamond(nc);
default:
return false;
}
......@@ -1310,17 +1313,24 @@ public class DeferredAttr extends JCTree.Visitor {
Type site;
if (rec != null) {
if (rec.hasTag(APPLY)) {
Symbol recSym = quicklyResolveMethod(env, (JCMethodInvocation) rec);
if (recSym == null)
return null;
Symbol resolvedReturnType =
analyzeCandidateMethods(recSym, syms.errSymbol, returnSymbolAnalyzer);
if (resolvedReturnType == null)
return null;
site = resolvedReturnType.type;
} else {
site = attribSpeculative(rec, env, attr.unknownTypeExprInfo).type;
switch (rec.getTag()) {
case APPLY:
Symbol recSym = quicklyResolveMethod(env, (JCMethodInvocation) rec);
if (recSym == null)
return null;
Symbol resolvedReturnType =
analyzeCandidateMethods(recSym, syms.errSymbol, returnSymbolAnalyzer);
if (resolvedReturnType == null)
return null;
site = resolvedReturnType.type;
break;
case NEWCLASS:
JCNewClass nc = (JCNewClass) rec;
site = attribSpeculative(nc.clazz, env, attr.unknownTypeExprInfo).type;
break;
default:
site = attribSpeculative(rec, env, attr.unknownTypeExprInfo).type;
break;
}
} else {
site = env.enclClass.sym.type;
......
......@@ -271,7 +271,7 @@ public class Resolve {
* the one of its outer environment
*/
protected static boolean isStatic(Env<AttrContext> env) {
return env.info.staticLevel > env.outer.info.staticLevel;
return env.outer != null && env.info.staticLevel > env.outer.info.staticLevel;
}
/** An environment is an "initializer" if it is a constructor or
......
......@@ -28,6 +28,7 @@ package com.sun.tools.javac.tree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
......@@ -351,6 +352,18 @@ public class TreeInfo {
return (lit.typetag == BOT);
}
/** Return true iff this tree is a child of some annotation. */
public static boolean isInAnnotation(Env<?> env, JCTree tree) {
TreePath tp = TreePath.getPath(env.toplevel, tree);
if (tp != null) {
for (Tree t : tp) {
if (t.getKind() == Tree.Kind.ANNOTATION)
return true;
}
}
return false;
}
public static String getCommentText(Env<?> env, JCTree tree) {
DocCommentTable docComments = (tree.hasTag(JCTree.Tag.TOPLEVEL))
? ((JCCompilationUnit) tree).docComments
......
/*
* @test /nodynamiccopyright/
* @bug 8028389
* @summary javac should output a proper error message when given something
* like new Object(){} as annotation argument.
*
* @compile/fail/ref=AnonSubclass.out -XDrawDiagnostics AnonSubclass.java
*/
@AnonSubclass(new Object(){})
@interface AnonSubclass {
String value();
}
AnonSubclass.java:10:15: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.anonymous.class: java.lang.Object, java.lang.String)
1 error
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
@interface AnonSubclassOnPkg {
String value();
}
/*
* @test /nodynamiccopyright/
* @bug 8028389
* @summary javac should output a proper error message when given something
* like new Object(){} as annotation argument.
*
* @compile AnonSubclassOnPkg.java
* @compile/fail/ref=package-info.out -XDrawDiagnostics package-info.java
*/
@AnonSubclassOnPkg(new Object(){})
package pkg;
package-info.java:11:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.anonymous.class: java.lang.Object, java.lang.String)
1 error
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8079613
* @summary Ensure that compiler ascertains a class of patently non-poly expressions as such
* @run main/timeout=10 DeeplyChainedNonPolyExpressionTest
*/
public class DeeplyChainedNonPolyExpressionTest {
static class JSO {
JSO put(String s, Object y) {
return null;
}
JSO put(java.lang.String x, java.util.Collection<String> y) {
return null;
}
JSO put(java.lang.String x, int y) {
return null;
}
JSO put(java.lang.String x, long y) {
return null;
}
JSO put(java.lang.String x, double y) {
return null;
}
JSO put(java.lang.String x, java.util.Map<String, String> y) {
return null;
}
JSO put(java.lang.String x, boolean y) {
return null;
}
}
static class JSA {
JSA put(Object o) {
return null;
}
JSA put(int i, Object x) {
return null;
}
JSA put(boolean x) {
return null;
}
JSA put(int x) {
return null;
}
JSA put(int i, int x) {
return null;
}
JSA put(int x, boolean y) {
return null;
}
JSA put(int i, long x) {
return null;
}
JSA put(long x) {
return null;
}
JSA put(java.util.Collection<String> x) {
return null;
}
JSA put(int i, java.util.Collection<String> x) {
return null;
}
JSA put(int i, java.util.Map<String, String> x) {
return null;
}
JSA put(java.util.Map<String, String> x) {
return null;
}
JSA put(int i, double x) {
return null;
}
JSA put(double x) {
return null;
}
}
public static void main(String [] args) {
}
public static void foo() {
new JSO()
.put("s", new JSA())
.put("s", new JSA())
.put("s", new JSO()
.put("s", new JSO()
.put("s", new JSA().put("s"))
.put("s", new JSA())
.put("s", new JSO()
.put("s", new JSO()
.put("s", new JSA().put("s").put("s"))
.put("s", new JSA())
.put("s", new JSO()
.put("s", new JSO()
.put("s", new JSA().put("s").put("s").put("s")
.put("s").put("s").put("s")
.put("s").put("s"))
.put("s", new JSA())
.put("s", new JSO()
.put("s", new JSO()
.put("s", new JSA().put("s"))
.put("s", new JSA())
)
)
)
)
)
.put("s", new JSO()
.put("s", new JSA().put("s"))
.put("s", new JSA())
.put("s", new JSO()
.put("s", new JSO()
.put("s", new JSA().put("s").put("s"))
.put("s", new JSA())
.put("s", new JSO()
.put("s", new JSO()
.put("s", new JSA().put("s").put("s").put("s")
.put("s").put("s").put("s")
.put("s").put("s"))
.put("s", new JSA())
.put("s", new JSO()
.put("s", new JSO()
.put("s", new JSA().put("s"))
.put("s", new JSA()))
)
)
)
)
)
)
)
)
);
}
}
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8080842
* @summary Ensure Scope impl can cope with remove() when a field and method share the name.
* @run main RemoveSymbolTest
*/
import java.util.Iterator;
import java.util.LinkedList;
public class RemoveSymbolTest<W> implements Iterable<W> {
static class Widget {
private String name;
Widget(String s) { name = s; }
@Override public String toString() { return name; }
}
private LinkedList<W> data;
// Instantiate an Iterable instance using a Lambda expression.
// Causes ClassFormatError if a local variable of type Widget is named after one of the methods.
private final Iterable<W> myIterator1 = () -> new Iterator<W>() {
private W hasNext = null;
private int index = 0;
@Override public boolean hasNext() { return index < data.size(); }
@Override public W next() { return data.get(index++); }
};
// Instantiate an Iterable instance using an anonymous class.
// Always works fine regardless of the name of the local variable.
private final Iterable<W> myIterator2 =
new Iterable<W>() {
@Override
public Iterator<W> iterator() {
return new Iterator<W>() {
private W hasNext = null;
private int index = 0;
@Override public boolean hasNext() { return index < data.size(); }
@Override public W next() { return data.get(index++); }
};
}
};
public RemoveSymbolTest() { data = new LinkedList<>(); }
public void add(W e) { data.add(e); }
@Override public String toString() { return data.toString(); }
@Override public Iterator<W> iterator() { return myIterator1.iterator(); }
public static void main(String[] args) {
RemoveSymbolTest<Widget> widgets = new RemoveSymbolTest<>();
widgets.add(new Widget("W1"));
widgets.add(new Widget("W2"));
widgets.add(new Widget("W3"));
System.out.println(".foreach() call: ");
widgets.forEach(w -> System.out.println(w + " "));
}
}
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8080842
* @summary Ensure Scope impl can cope with remove() when a field and method share the name.
*/
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Scope.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.file.JavacFileManager;
public class RemoveSymbolUnitTest {
Context context;
Names names;
Symtab symtab;
public static void main(String... args) throws Exception {
new RemoveSymbolUnitTest().run();
}
public void run() {
context = new Context();
JavacFileManager.preRegister(context); // required by ClassReader which is required by Symtab
names = Names.instance(context);
symtab = Symtab.instance(context);
Name hasNext = names.fromString("hasNext");
ClassSymbol clazz = new ClassSymbol(0,
names.fromString("X"),
Type.noType,
symtab.unnamedPackage);
VarSymbol v = new VarSymbol(0, hasNext, Type.noType, clazz);
MethodSymbol m = new MethodSymbol(0, hasNext, Type.noType, clazz);
// Try enter and remove in different shuffled combinations.
// working with fresh scope each time.
Scope cs = new Scope(clazz);
cs.enter(v);
cs.enter(m);
cs.remove(v);
Symbol s = cs.lookup(hasNext).sym;
if (s != m)
throw new AssertionError("Wrong symbol");
cs = new Scope(clazz);
cs.enter(m);
cs.enter(v);
cs.remove(v);
s = cs.lookup(hasNext).sym;
if (s != m)
throw new AssertionError("Wrong symbol");
cs = new Scope(clazz);
cs.enter(v);
cs.enter(m);
cs.remove(m);
s = cs.lookup(hasNext).sym;
if (s != v)
throw new AssertionError("Wrong symbol");
cs = new Scope(clazz);
cs.enter(m);
cs.enter(v);
cs.remove(m);
s = cs.lookup(hasNext).sym;
if (s != v)
throw new AssertionError("Wrong symbol");
}
}
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8039262
* @summary Ensure that using Types.membersClosure does not increase the number of listeners on the
* class's members Scope.
*/
import com.sun.tools.javac.code.Scope;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Names;
import java.lang.reflect.Field;
import java.util.Collection;
public class ScopeListenerTest {
public static void main(String[] args) throws Exception {
new ScopeListenerTest().run();
}
void run() throws Exception {
Context context = new Context();
JavacFileManager.preRegister(context);
Types types = Types.instance(context);
Symtab syms = Symtab.instance(context);
Names names = Names.instance(context);
types.membersClosure(syms.stringType, true);
types.membersClosure(syms.stringType, false);
Field listenersField = Scope.class.getDeclaredField("listeners");
listenersField.setAccessible(true);
int listenerCount =
((Collection) listenersField.get(syms.stringType.tsym.members())).size();
for (int i = 0; i < 100; i++) {
types.membersClosure(syms.stringType, true);
types.membersClosure(syms.stringType, false);
}
int newListenerCount
= ((Collection) listenersField.get(syms.stringType.tsym.members())).size();
if (listenerCount != newListenerCount) {
throw new AssertionError("Orig listener count: " + listenerCount +
"; new listener count: " + newListenerCount);
}
for (Symbol s : types.membersClosure(syms.stringType, true).getElements())
;
for (Symbol s : types.membersClosure(syms.stringType, false).getElementsByName(names.fromString("substring")))
;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册