diff options
Diffstat (limited to 'src/dotty/tools/dotc/transform/CheckStatic.scala')
-rw-r--r-- | src/dotty/tools/dotc/transform/CheckStatic.scala | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/transform/CheckStatic.scala b/src/dotty/tools/dotc/transform/CheckStatic.scala new file mode 100644 index 000000000..264c20eb2 --- /dev/null +++ b/src/dotty/tools/dotc/transform/CheckStatic.scala @@ -0,0 +1,83 @@ +package dotty.tools.dotc +package transform + +import core._ +import Names._ +import StdNames.nme +import Types._ +import dotty.tools.dotc.transform.TreeTransforms.{AnnotationTransformer, TransformerInfo, MiniPhaseTransform, TreeTransformer} +import ast.Trees._ +import Flags._ +import Contexts.Context +import Symbols._ +import Constants._ +import Denotations._, SymDenotations._ +import Decorators.StringInterpolators +import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.core.Annotations.ConcreteAnnotation +import scala.collection.mutable +import DenotTransformers._ +import Names.Name +import NameOps._ +import Decorators._ +import TypeUtils._ + +/** A transformer that check that requirements of Static fields\methods are implemented: + * 1. Only objects can have members annotated with `@static` + * 2. The fields annotated with `@static` should preceed any non-`@static` fields. + * This ensures that we do not introduce surprises for users in initialization order. + * 3. If a member `foo` of an `object C` is annotated with `@static`, + * the companion class `C` is not allowed to define term members with name `foo`. + * 4. If a member `foo` of an `object C` is annotated with `@static`, the companion class `C` + * is not allowed to inherit classes that define a term member with name `foo`. + * 5. Only `@static` methods and vals are supported in companions of traits. + * Java8 supports those, but not vars, and JavaScript does not have interfaces at all. + */ +class CheckStatic extends MiniPhaseTransform { thisTransformer => + import ast.tpd._ + + override def phaseName = "elimRepeated" + + + def check(tree: tpd.DefTree)(implicit ctx: Context) = { + + } + + override def transformTemplate(tree: tpd.Template)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + val defns = tree.body.collect{case t: ValOrDefDef => t} + var hadNonStaticField = false + for(defn <- defns) { + if (defn.symbol.hasAnnotation(ctx.definitions.ScalaStaticAnnot)) { + if(!ctx.owner.is(Module)) { + ctx.error("@static fields are only allowed inside objects", defn.pos) + } + + if (defn.isInstanceOf[ValDef] && hadNonStaticField) { + ctx.error("@static fields should preceed non-static ones", defn.pos) + } + + val companion = ctx.owner.companionClass + if (!companion.exists) { + ctx.error("object that conatin @static members should have companion class", defn.pos) + } + + val clashes = companion.asClass.membersNamed(defn.name) + if (clashes.exists) { + ctx.error("companion classes cannot define members with same name as @static member", defn.pos) + } + + if (defn.symbol.is(Flags.Mutable) && companion.is(Flags.Trait)) { + ctx.error("Companions of traits cannot define mutable @static fields") + } + } else hadNonStaticField = hadNonStaticField || defn.isInstanceOf[ValDef] + + } + tree + } + + override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { + if (tree.symbol.hasAnnotation(defn.ScalaStaticAnnot)) + ref(tree.symbol) + else tree + } +} |