diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Namers.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index cb6e29650f..8e4e0d317e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -533,6 +533,7 @@ trait Namers requires Analyzer { var result = tp; if (sym hasFlag IMPLICIT) { val p = provided(tp); + //Console.println("check contractive: "+sym+" "+p+"/"+required(tp)) for (val r <- required(tp)) { if (!isContainedIn(r, p) || (r =:= p)) { context.error(sym.pos, "implicit " + sym + " is not contractive," + @@ -549,6 +550,10 @@ trait Namers requires Analyzer { makePolyType(typer.reenterTypeParams(tparams), typer.typedType(rhs).tpe); def typeSig(tree: Tree): Type = { + tree match { + case md: MemberDef => attributes(md) + case _ => + } val result = try { val sym: Symbol = tree.symbol @@ -644,6 +649,66 @@ trait Namers requires Analyzer { deSkolemize(result) } + /** + * @param defn ... + */ + protected def attributes(defn: MemberDef): Unit = { + var attrError: Boolean = false; + def error(pos: PositionType, msg: String): Null = { + context.error(pos, msg) + attrError = true + null + } + def getConstant(tree: Tree): Constant = tree match { + case Literal(value) => value + case arg => error(arg.pos, "attribute argument needs to be a constant; found: "+arg) + } + val attrInfos = + for (val t @ Attribute(constr, elements) <- defn.mods.attributes) yield { + typer.typed(constr, EXPRmode | CONSTmode, AttributeClass.tpe) match { + case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => + val constrArgs = args map getConstant + val attrScope = tpt.tpe.decls. + filter(sym => sym.isMethod && !sym.isConstructor && sym.hasFlag(JAVA)); + val names = new collection.mutable.HashSet[Symbol] + names ++= attrScope.elements.filter(.isMethod) + if (args.length == 1) { + names.retain(sym => sym.name != nme.value) + } + val nvPairs = elements map { + case Assign(ntree @ Ident(name), rhs) => { + val sym = attrScope.lookup(name); + if (sym == NoSymbol) { + error(ntree.pos, "unknown attribute element name: " + name) + } else if (!names.contains(sym)) { + error(ntree.pos, "duplicate value for element " + name) + } else { + names -= sym + Pair(sym.name, getConstant(typer.typed(rhs, EXPRmode | CONSTmode, sym.tpe.resultType))) + } + } + } + for (val name <- names) { + if (!name.attributes.contains(Triple(AnnotationDefaultAttr.tpe, List(), List()))) { + error(t.pos, "attribute " + tpt.tpe.symbol.fullNameString + " is missing element " + name.name) + } + } + if (tpt.tpe.symbol.hasFlag(JAVA) && settings.target.value == "jvm-1.4") { + context.unit.warning (t.pos, "Java annotation will not be emitted in classfile unless you use the '-target:jvm-1.5' option") + } + Triple(tpt.tpe, constrArgs, nvPairs) + } + } + if (!attrError) { + val attributed = + if (defn.symbol.isModule) defn.symbol.moduleClass else defn.symbol + if (!attrInfos.isEmpty) { + attributed.attributes = attrInfos + } + } +// defn.mods setAttr List(); + } + /** Check that symbol's definition is well-formed. This means: * - no conflicting modifiers * - `abstract' modifier only for classes |