use of com.sun.tools.javac.code.Scope in project ceylon-compiler by ceylon.
the class HashCollisionTest method createClass.
/**
* Create a class symbol, init the members scope, and add it to owner's scope.
*/
ClassSymbol createClass(Name name, Symbol owner) {
ClassSymbol sym = new ClassSymbol(0, name, owner);
sym.members_field = new Scope(sym);
if (owner != symtab.unnamedPackage)
owner.members().enter(sym);
return sym;
}
use of com.sun.tools.javac.code.Scope in project error-prone by google.
the class FindIdentifiers method findAllIdents.
/**
* Finds the set of all bare variable identifiers in scope at the current location. Identifiers
* are ordered by ascending distance/scope count from the current location to match shadowing
* rules. That is, if two variables with the same simple names appear in the set, the one that
* appears first in iteration order is the one you get if you use the bare name in the source
* code.
*
* <p>We do not report variables that would require a qualfied access. We also do not handle
* wildcard imports.
*/
public static LinkedHashSet<VarSymbol> findAllIdents(VisitorState state) {
ImmutableSet.Builder<VarSymbol> result = new ImmutableSet.Builder<>();
Tree prev = state.getPath().getLeaf();
for (Tree curr : state.getPath().getParentPath()) {
switch(curr.getKind()) {
case BLOCK:
for (StatementTree stmt : ((BlockTree) curr).getStatements()) {
if (stmt.equals(prev)) {
break;
}
addIfVariable(stmt, result);
}
break;
case METHOD:
for (VariableTree param : ((MethodTree) curr).getParameters()) {
result.add(ASTHelpers.getSymbol(param));
}
break;
case CATCH:
result.add(ASTHelpers.getSymbol(((CatchTree) curr).getParameter()));
break;
case CLASS:
case INTERFACE:
case ENUM:
case ANNOTATION_TYPE:
// field is referred to by qualified name, but we don't support that.
for (Tree member : ((ClassTree) curr).getMembers()) {
if (member.equals(prev)) {
break;
}
addIfVariable(member, result);
}
// Collect inherited fields.
Type classType = ASTHelpers.getType(curr);
com.sun.tools.javac.util.List<Type> superTypes = state.getTypes().closure(classType).tail;
for (Type type : superTypes) {
Scope scope = type.tsym.members();
ImmutableList.Builder<VarSymbol> varsList = new ImmutableList.Builder<VarSymbol>();
for (Symbol var : scope.getSymbols(VarSymbol.class::isInstance)) {
varsList.add((VarSymbol) var);
}
result.addAll(varsList.build().reverse());
}
break;
case FOR_LOOP:
addAllIfVariable(((ForLoopTree) curr).getInitializer(), result);
break;
case ENHANCED_FOR_LOOP:
result.add(ASTHelpers.getSymbol(((EnhancedForLoopTree) curr).getVariable()));
break;
case TRY:
TryTree tryTree = (TryTree) curr;
boolean inResources = false;
for (Tree resource : tryTree.getResources()) {
if (resource.equals(prev)) {
inResources = true;
break;
}
}
if (inResources) {
// Case 1: we're in one of the resource declarations
for (Tree resource : tryTree.getResources()) {
if (resource.equals(prev)) {
break;
}
addIfVariable(resource, result);
}
} else if (tryTree.getBlock().equals(prev)) {
// Case 2: We're in the block (not a catch or finally)
addAllIfVariable(tryTree.getResources(), result);
}
break;
case COMPILATION_UNIT:
for (ImportTree importTree : ((CompilationUnitTree) curr).getImports()) {
if (importTree.isStatic() && importTree.getQualifiedIdentifier().getKind() == Kind.MEMBER_SELECT) {
MemberSelectTree memberSelectTree = (MemberSelectTree) importTree.getQualifiedIdentifier();
Scope scope = state.getTypes().membersClosure(ASTHelpers.getType(memberSelectTree.getExpression()), /*skipInterface*/
false);
for (Symbol var : scope.getSymbols(sym -> sym instanceof VarSymbol && sym.getSimpleName().equals(memberSelectTree.getIdentifier()))) {
result.add((VarSymbol) var);
}
}
}
break;
default:
// other node types don't introduce variables
break;
}
prev = curr;
}
// TODO(eaftan): switch out collector for ImmutableSet.toImmutableSet()
return result.build().stream().filter(var -> isVisible(var, state.getPath())).collect(Collectors.toCollection(LinkedHashSet::new));
}
use of com.sun.tools.javac.code.Scope in project error-prone by google.
the class ASTHelpers method enumValues.
/** @return all values of the given enum type, in declaration order. */
public static LinkedHashSet<String> enumValues(TypeSymbol enumType) {
if (enumType.getKind() != ElementKind.ENUM) {
throw new IllegalStateException();
}
Scope scope = enumType.members();
Deque<String> values = new ArrayDeque<>();
for (Symbol sym : scope.getSymbols()) {
if (sym instanceof VarSymbol) {
VarSymbol var = (VarSymbol) sym;
if ((var.flags() & Flags.ENUM) != 0) {
/**
* Javac gives us the members backwards, apparently. It's worth making an effort to
* preserve declaration order because it's useful for diagnostics (e.g. in
* {@link MissingCasesInEnumSwitch}).
*/
values.push(sym.name.toString());
}
}
}
return new LinkedHashSet<>(values);
}
use of com.sun.tools.javac.code.Scope in project ceylon-compiler by ceylon.
the class HashCollisionTest method run.
void run() throws Exception {
// set up basic environment for test
Context context = new Context();
// required by ClassReader which is required by Symtab
JavacFileManager.preRegister(context);
// Name.Table impls tied to an instance of Names
names = Names.instance(context);
symtab = Symtab.instance(context);
// determine hashMask for an empty scope
// any owner will do
Scope emptyScope = new Scope(symtab.unnamedPackage);
Field sHashMask = Scope.class.getDeclaredField("hashMask");
sHashMask.setAccessible(true);
scopeHashMask = sHashMask.getInt(emptyScope);
log("scopeHashMask: " + scopeHashMask);
// 1. determine the Name.hashCode of "Entry", and therefore the index of
// Entry in an empty scope. i.e. name.hashCode() & Scope.hashMask
Name entry = names.fromString("Entry");
// 2. create names of the form *$Entry until we find a name with a
// hashcode which yields the same index as Entry in an empty scope.
// Since Name.hashCode is a function of position (and not content) it
// should work to create successively longer names until one with the
// desired characteristics is found.
Name outerName;
Name innerName;
StringBuilder sb = new StringBuilder("C");
int i = 0;
do {
sb.append(Integer.toString(i % 10));
innerName = names.fromString(sb + "$Entry");
} while (!clash(entry, innerName) && (++i) < MAX_TRIES);
if (clash(entry, innerName)) {
log("Detected expected hash collision for " + entry + " and " + innerName + " after " + i + " tries");
} else {
throw new Exception("No potential collision found after " + i + " tries");
}
outerName = names.fromString(sb.toString());
/*
* Now we can set up the scenario.
*/
// 3. Create a nested class named Entry
ClassSymbol cc = createClass(names.fromString("C"), symtab.unnamedPackage);
ClassSymbol ce = createClass(entry, cc);
// 4. Create a package containing a nested class using the name from 2
PackageSymbol p = new PackageSymbol(names.fromString("p"), symtab.rootPackage);
p.members_field = new Scope(p);
ClassSymbol inner = createClass(innerName, p);
// we'll need this later when we "rename" cn
ClassSymbol outer = createClass(outerName, p);
// 5. Create a star-import scope
log("createStarImportScope");
// if StarImportScope exists, use it, otherwise, for testing legacy code,
// fall back on ImportScope
Scope starImportScope;
Method importAll;
PackageSymbol pkg = new PackageSymbol(names.fromString("pkg"), symtab.rootPackage);
try {
Class<?> c = Class.forName("com.sun.tools.javac.code.Scope$StarImportScope");
Constructor ctor = c.getDeclaredConstructor(new Class[] { Symbol.class });
importAll = c.getDeclaredMethod("importAll", new Class[] { Scope.class });
starImportScope = (Scope) ctor.newInstance(new Object[] { pkg });
} catch (ClassNotFoundException e) {
starImportScope = new ImportScope(pkg);
importAll = null;
}
dump("initial", starImportScope);
// 6. Insert the contents of the package from 4.
Scope p_members = p.members();
if (importAll != null) {
importAll.invoke(starImportScope, p_members);
} else {
Scope fromScope = p_members;
Scope toScope = starImportScope;
// before the use of StarImportScope.importAll.
for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) {
if (e.sym.kind == TYP && !toScope.includes(e.sym))
toScope.enter(e.sym, fromScope);
}
}
dump("imported p", starImportScope);
// 7. Insert the class from 3.
starImportScope.enter(ce, cc.members_field);
dump("imported ce", starImportScope);
/*
* Set the trap.
*/
// 8. Rename the nested class to Entry. so that there is a bogus entry in the star-import scope
p.members_field.remove(inner);
inner.name = entry;
inner.owner = outer;
outer.members_field.enter(inner);
// 9. Lookup Entry
Scope.Entry e = starImportScope.lookup(entry);
dump("final", starImportScope);
if (e.sym == null)
throw new Exception("symbol not found: " + entry);
}
use of com.sun.tools.javac.code.Scope in project ceylon-compiler by ceylon.
the class Attr method visitNewClass.
public void visitNewClass(JCNewClass tree) {
Type owntype = types.createErrorType(tree.type);
// The local environment of a class creation is
// a new environment nested in the current one.
Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
// The anonymous inner class definition of the new expression,
// if one is defined by it.
JCClassDecl cdef = tree.def;
// If enclosing class is given, attribute it, and
// complete class name to be fully qualified
// Class field following new
JCExpression clazz = tree.clazz;
// Identifier in class field
JCExpression clazzid = (clazz.getTag() == JCTree.TYPEAPPLY) ? ((JCTypeApply) clazz).clazz : clazz;
// The same in fully qualified form
JCExpression clazzid1 = clazzid;
if (tree.encl != null) {
// We are seeing a qualified new, of the form
// <expr>.new C <...> (...) ...
// In this case, we let clazz stand for the name of the
// allocated class C prefixed with the type of the qualifier
// expression, so that we can
// resolve it with standard techniques later. I.e., if
// <expr> has type T, then <expr>.new C <...> (...)
// yields a clazz T.C.
Type encltype = chk.checkRefType(tree.encl.pos(), attribExpr(tree.encl, env));
clazzid1 = make.at(clazz.pos).Select(make.Type(encltype), ((JCIdent) clazzid).name);
if (clazz.getTag() == JCTree.TYPEAPPLY)
clazz = make.at(tree.pos).TypeApply(clazzid1, ((JCTypeApply) clazz).arguments);
else
clazz = clazzid1;
}
// Attribute clazz expression and store
// symbol + type back into the attributed tree.
Type clazztype = attribType(clazz, env);
Pair<Scope, Scope> mapping = getSyntheticScopeMapping(clazztype);
clazztype = chk.checkDiamond(tree, clazztype);
chk.validate(clazz, localEnv);
if (tree.encl != null) {
// We have to work in this case to store
// symbol + type back into the attributed tree.
tree.clazz.type = clazztype;
TreeInfo.setSymbol(clazzid, TreeInfo.symbol(clazzid1));
clazzid.type = ((JCIdent) clazzid).sym.type;
if (!clazztype.isErroneous()) {
if (cdef != null && clazztype.tsym.isInterface()) {
log.error(tree.encl.pos(), "anon.class.impl.intf.no.qual.for.new");
} else if (clazztype.tsym.isStatic()) {
log.error(tree.encl.pos(), "qualified.new.of.static.class", clazztype.tsym);
}
}
} else if (!clazztype.tsym.isInterface() && clazztype.getEnclosingType().tag == CLASS) {
// Check for the existence of an apropos outer instance
rs.resolveImplicitThis(tree.pos(), env, clazztype);
}
// Attribute constructor arguments.
List<Type> argtypes = attribArgs(tree.args, localEnv);
List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv);
if (TreeInfo.isDiamond(tree) && !clazztype.isErroneous()) {
clazztype = attribDiamond(localEnv, tree, clazztype, mapping, argtypes, typeargtypes);
clazz.type = clazztype;
} else if (allowDiamondFinder && tree.def == null && !clazztype.isErroneous() && clazztype.getTypeArguments().nonEmpty() && findDiamonds) {
boolean prevDeferDiags = log.deferDiagnostics;
Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
Type inferred = null;
try {
//disable diamond-related diagnostics
log.deferDiagnostics = true;
log.deferredDiagnostics = ListBuffer.lb();
inferred = attribDiamond(localEnv, tree, clazztype, mapping, argtypes, typeargtypes);
} finally {
log.deferDiagnostics = prevDeferDiags;
log.deferredDiagnostics = prevDeferredDiags;
}
if (inferred != null && !inferred.isErroneous() && inferred.tag == CLASS && types.isAssignable(inferred, pt.tag == NONE ? clazztype : pt, Warner.noWarnings)) {
String key = types.isSameType(clazztype, inferred) ? "diamond.redundant.args" : "diamond.redundant.args.1";
log.warning(tree.clazz.pos(), key, clazztype, inferred);
}
}
// If we have made no mistakes in the class type...
if (clazztype.tag == CLASS) {
// Enums may not be instantiated except implicitly
if (allowEnums && (clazztype.tsym.flags_field & Flags.ENUM) != 0 && (env.tree.getTag() != JCTree.VARDEF || (((JCVariableDecl) env.tree).mods.flags & Flags.ENUM) == 0 || ((JCVariableDecl) env.tree).init != tree))
log.error(tree.pos(), "enum.cant.be.instantiated");
// Check that class is not abstract
if (cdef == null && (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
log.error(tree.pos(), "abstract.cant.be.instantiated", clazztype.tsym);
} else if (cdef != null && clazztype.tsym.isInterface()) {
// anonymous classes implementing an interface
if (!argtypes.isEmpty())
log.error(tree.args.head.pos(), "anon.class.impl.intf.no.args");
if (!typeargtypes.isEmpty())
log.error(tree.typeargs.head.pos(), "anon.class.impl.intf.no.typeargs");
// Error recovery: pretend no arguments were supplied.
argtypes = List.nil();
typeargtypes = List.nil();
} else // Resolve the called constructor under the assumption
// that we are referring to a superclass instance of the
// current instance (JLS ???).
{
//the following code alters some of the fields in the current
//AttrContext - hence, the current context must be dup'ed in
//order to avoid downstream failures
Env<AttrContext> rsEnv = localEnv.dup(tree);
rsEnv.info.selectSuper = cdef != null;
rsEnv.info.varArgs = false;
tree.constructor = rs.resolveConstructor(tree.pos(), rsEnv, clazztype, argtypes, typeargtypes);
tree.constructorType = tree.constructor.type.isErroneous() ? syms.errType : checkMethod(clazztype, tree.constructor, rsEnv, tree.args, argtypes, typeargtypes, rsEnv.info.varArgs);
if (rsEnv.info.varArgs)
Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null);
}
if (cdef != null) {
// }
if (Resolve.isStatic(env))
cdef.mods.flags |= STATIC;
if (clazztype.tsym.isInterface()) {
cdef.implementing = List.of(clazz);
} else {
cdef.extending = clazz;
}
attribStat(cdef, localEnv);
// and delete it from the new expression
if (tree.encl != null && !clazztype.tsym.isInterface()) {
tree.args = tree.args.prepend(makeNullCheck(tree.encl));
argtypes = argtypes.prepend(tree.encl.type);
tree.encl = null;
}
// Reassign clazztype and recompute constructor.
clazztype = cdef.sym.type;
boolean useVarargs = tree.varargsElement != null;
Symbol sym = rs.resolveConstructor(tree.pos(), localEnv, clazztype, argtypes, typeargtypes, true, useVarargs);
Assert.check(sym.kind < AMBIGUOUS || tree.constructor.type.isErroneous());
tree.constructor = sym;
if (tree.constructor.kind > ERRONEOUS) {
tree.constructorType = syms.errType;
} else {
tree.constructorType = checkMethod(clazztype, tree.constructor, localEnv, tree.args, argtypes, typeargtypes, useVarargs);
}
}
if (tree.constructor != null && tree.constructor.kind == MTH)
owntype = clazztype;
}
result = check(tree, owntype, VAL, pkind, pt);
chk.validate(tree.typeargs, localEnv);
}
Aggregations