use of org.eclipse.ceylon.langtools.tools.javac.code.Scope in project ceylon by eclipse.
the class Enter method visitClassDef.
@Override
public void visitClassDef(JCClassDecl tree) {
Symbol owner = env.info.scope.owner;
Scope enclScope = enterScope(env);
ClassSymbol c;
if (owner.kind == PCK) {
// We are seeing a toplevel class.
PackageSymbol packge = (PackageSymbol) owner;
for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner) q.flags_field |= EXISTS;
c = reader.enterClass(tree.name, packge);
packge.members().enterIfAbsent(c);
if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env) && !sourceLanguage.isCeylon()) {
log.error(tree.pos(), "class.public.should.be.in.file", tree.name);
}
} else {
if (!tree.name.isEmpty() && !chk.checkUniqueClassName(tree.pos(), tree.name, enclScope)) {
result = null;
return;
}
if (owner.kind == TYP) {
// We are seeing a member class.
c = reader.enterClass(tree.name, (TypeSymbol) owner);
if ((owner.flags_field & INTERFACE) != 0) {
tree.mods.flags |= PUBLIC | STATIC;
}
} else {
// We are seeing a local class.
c = reader.defineClass(tree.name, owner);
c.flatname = chk.localClassName(c);
if (!c.name.isEmpty())
chk.checkTransparentClass(tree.pos(), c, env.info.scope);
}
}
tree.sym = c;
// Enter class into `compiled' table and enclosing scope.
if (chk.compiled.get(c.flatname) != null) {
duplicateClass(tree.pos(), c);
result = types.createErrorType(tree.name, (TypeSymbol) owner, Type.noType);
tree.sym = (ClassSymbol) result.tsym;
return;
}
chk.compiled.put(c.flatname, c);
// CEYLON(stef): don't add anonymous classes to the environment
if (tree.name.length() != 0)
enclScope.enter(c);
// Set up an environment for class block and store in `typeEnvs'
// table, to be retrieved later in memberEnter and attribution.
Env<AttrContext> localEnv = classEnv(tree, env);
typeEnvs.put(c, localEnv);
// Fill out class fields.
c.completer = memberEnter;
c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
c.sourcefile = env.toplevel.sourcefile;
c.members_field = new Scope(c);
// determine the enclosing type
if (sourceLanguage.isCeylon()) {
// (This would be an illegal access to "this before super").
if (env.info.isSelfCall && (isNewAnonymousClass(env.tree) || isNewLetClass(env.tree))) {
c.flags_field |= CEYLON_NOOUTERTHIS;
}
}
ClassType ct = (ClassType) c.type;
// Ceylon: make sure everything is reset if we Enter twice for bootstrap
ct.interfaces_field = null;
ct.allparams_field = null;
ct.supertype_field = null;
ct.all_interfaces_field = null;
// End Ceylon
if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
// We are seeing a local or inner class.
// Set outer_field of this class to closest enclosing class
// which contains this class in a non-static context
// (its "enclosing instance class"), provided such a class exists.
Symbol owner1 = owner;
// Ceylon: make sure we skip outer classes if required
boolean skip = c.skipOuterClass();
while (skip || ((owner1.kind & (VAR | MTH)) != 0 && (owner1.flags_field & STATIC) == 0)) {
// Ceylon: we only take new outer class skip orders from types, never from methods/vars
if (owner1.kind == TYP)
skip = owner1.skipOuterClass();
owner1 = owner1.owner;
}
if (owner1.kind == TYP) {
ct.setEnclosingType(owner1.type);
}
}
// Enter type parameters.
ct.typarams_field = classEnter(tree.typarams, localEnv);
// completed later.
if (!c.isLocal() && uncompleted != null)
uncompleted.append(c);
// System.err.println("entering " + c.fullname + " in " + c.owner);//DEBUG
// Recursively enter all member classes.
classEnter(tree.defs, localEnv);
result = c.type;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Scope in project ceylon by eclipse.
the class Types method firstUnimplementedAbstractImpl.
// where:
private MethodSymbol firstUnimplementedAbstractImpl(ClassSymbol impl, ClassSymbol c) {
MethodSymbol undef = null;
// since they cannot have abstract members.
if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) {
Scope s = c.members();
for (Scope.Entry e = s.elems; undef == null && e != null; e = e.sibling) {
if (e.sym.kind == MTH && (e.sym.flags() & (ABSTRACT | IPROXY | DEFAULT)) == ABSTRACT) {
MethodSymbol absmeth = (MethodSymbol) e.sym;
MethodSymbol implmeth = absmeth.implementation(impl, this, true);
if (implmeth == null || implmeth == absmeth) {
// look for default implementations
if (allowDefaultMethods) {
MethodSymbol prov = interfaceCandidates(impl.type, absmeth).head;
if (prov != null && prov.overrides(absmeth, impl, this, true)) {
implmeth = prov;
}
}
}
if (implmeth == null || implmeth == absmeth) {
undef = absmeth;
} else if (sourceLanguage.isCeylon())
implmeth.flags_field |= CEYLON_METHOD_OVERRIDE_CHECKED;
}
}
if (undef == null) {
Type st = supertype(c.type);
if (st.hasTag(CLASS))
undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol) st.tsym);
}
for (List<Type> l = interfaces(c.type); undef == null && l.nonEmpty(); l = l.tail) {
undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol) l.head.tsym);
}
}
return undef;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Scope in project ceylon by eclipse.
the class Types method makeFunctionalInterfaceClass.
/**
* Create a symbol for a class that implements a given functional interface
* and overrides its functional descriptor. This routine is used for two
* main purposes: (i) checking well-formedness of a functional interface;
* (ii) perform functional interface bridge calculation.
*/
public ClassSymbol makeFunctionalInterfaceClass(Env<AttrContext> env, Name name, List<Type> targets, long cflags) {
if (targets.isEmpty()) {
return null;
}
Symbol descSym = findDescriptorSymbol(targets.head.tsym);
Type descType = findDescriptorType(targets.head);
ClassSymbol csym = new ClassSymbol(cflags, name, env.enclClass.sym.outermostClass());
csym.completer = null;
csym.members_field = new Scope(csym);
MethodSymbol instDescSym = new MethodSymbol(descSym.flags(), descSym.name, descType, csym);
csym.members_field.enter(instDescSym);
Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym);
ctype.supertype_field = syms.objectType;
ctype.interfaces_field = targets;
csym.type = ctype;
csym.sourcefile = ((ClassSymbol) csym.owner).sourcefile;
return csym;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Scope in project ceylon by eclipse.
the class Enter method visitTopLevel.
@Override
public void visitTopLevel(JCCompilationUnit tree) {
JavaFileObject prev = log.useSource(tree.sourcefile);
boolean addEnv = false;
boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE);
if (tree.pid != null) {
tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid));
if (tree.packageAnnotations.nonEmpty() || pkginfoOpt == PkgInfo.ALWAYS) {
if (isPkgInfo) {
addEnv = true;
} else if (tree.packageAnnotations.nonEmpty()) {
log.error(tree.packageAnnotations.head.pos(), "pkg.annotations.sb.in.package-info.java");
}
}
} else {
tree.packge = syms.unnamedPackage;
}
// Find all classes in package.
tree.packge.complete();
Env<AttrContext> topEnv = topLevelEnv(tree);
// Save environment of package-info.java file.
if (isPkgInfo) {
Env<AttrContext> env0 = typeEnvs.get(tree.packge);
if (env0 == null) {
typeEnvs.put(tree.packge, topEnv);
} else {
JCCompilationUnit tree0 = env0.toplevel;
if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
log.warning(tree.pid != null ? tree.pid.pos() : null, "pkg-info.already.seen", tree.packge);
if (addEnv || (tree0.packageAnnotations.isEmpty())) {
typeEnvs.put(tree.packge, topEnv);
}
}
}
for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner) q.flags_field |= EXISTS;
Name name = names.package_info;
ClassSymbol c = reader.enterClass(name, tree.packge);
c.flatname = names.fromString(tree.packge + "." + name);
c.sourcefile = tree.sourcefile;
c.completer = null;
c.members_field = new Scope(c);
tree.packge.package_info = c;
}
classEnter(tree.defs, topEnv);
if (addEnv) {
todo.append(topEnv);
}
log.useSource(prev);
result = null;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Scope in project ceylon by eclipse.
the class Types method makeIntersectionType.
/**
* Make an intersection type from non-empty list of types. The list should be ordered according to
* {@link TypeSymbol#precedes(TypeSymbol, Types)}. This does not cause symbol completion as
* an extra parameter indicates as to whether all bounds are interfaces - in which case the
* supertype is implicitly assumed to be 'Object'.
*
* @param bounds the types from which the intersection type is formed
* @param allInterfaces are all bounds interface types?
*/
public IntersectionClassType makeIntersectionType(List<Type> bounds, boolean allInterfaces) {
Assert.check(bounds.nonEmpty());
Type firstExplicitBound = bounds.head;
if (allInterfaces) {
bounds = bounds.prepend(syms.objectType);
}
ClassSymbol bc = new ClassSymbol(ABSTRACT | PUBLIC | SYNTHETIC | COMPOUND | ACYCLIC, Type.moreInfo ? names.fromString(bounds.toString()) : names.empty, null, syms.noSymbol);
IntersectionClassType intersectionType = new IntersectionClassType(bounds, bc, allInterfaces);
bc.type = intersectionType;
bc.erasure_field = (bounds.head.hasTag(TYPEVAR)) ? // error condition, recover
syms.objectType : erasure(firstExplicitBound);
bc.members_field = new Scope(bc);
return intersectionType;
}
Aggregations