summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-01-14 14:30:57 -0800
committerPaul Phillips <paulp@improving.org>2013-01-14 15:18:52 -0800
commit61f70e48cecddf27fba162c165dfaf712c84278c (patch)
tree5927d6f00e043dc95e7609ba38e3d57484ebffd5 /src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
parentebdc0ff73b533d2b625a919d0bb57dbe94430c02 (diff)
downloadscala-61f70e48cecddf27fba162c165dfaf712c84278c.tar.gz
scala-61f70e48cecddf27fba162c165dfaf712c84278c.tar.bz2
scala-61f70e48cecddf27fba162c165dfaf712c84278c.zip
SI-6375, warn on lost annotation.
Annotations on abstract vals which are not meta-annotated were silently discarded. Still discarded, only less silently. I warned on as many "lost annotation" situations as I was reasonably able to cover without false positives.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala35
1 files changed, 33 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index d74d5ecfbe..438c783810 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -126,7 +126,7 @@ trait MethodSynthesis {
/** There are two key methods in here.
*
- * 1) Enter methods such as enterGetterSetterare called
+ * 1) Enter methods such as enterGetterSetter are called
* from Namer with a tree which may generate further trees such as accessors or
* implicit wrappers. Some setup is performed. In general this creates symbols
* and enters them into the scope of the owner.
@@ -171,14 +171,45 @@ trait MethodSynthesis {
enterBeans(tree)
}
+ /** This is called for those ValDefs which addDerivedTrees ignores, but
+ * which might have a warnable annotation situation.
+ */
+ private def warnForDroppedAnnotations(tree: Tree) {
+ val annotations = tree.symbol.initialize.annotations
+ val targetClass = defaultAnnotationTarget(tree)
+ val retained = deriveAnnotations(annotations, targetClass, keepClean = true)
+
+ annotations filterNot (retained contains _) foreach (ann => issueAnnotationWarning(ann, targetClass))
+ }
+ private def issueAnnotationWarning(ann: AnnotationInfo, defaultTarget: Symbol) {
+ global.reporter.warning(ann.pos,
+ s"Annotation is unused - it can be retained with a meta-annotation such as @($ann @${defaultTarget.name})")
+ }
+
def addDerivedTrees(typer: Typer, stat: Tree): List[Tree] = stat match {
case vd @ ValDef(mods, name, tpt, rhs) if !noFinishGetterSetter(vd) =>
// If we don't save the annotations, they seem to wander off.
val annotations = stat.symbol.initialize.annotations
- ( allValDefDerived(vd)
+ val trees = (
+ allValDefDerived(vd)
map (acc => atPos(vd.pos.focus)(acc derive annotations))
filterNot (_ eq EmptyTree)
)
+ // Verify each annotation landed safely somewhere, else warn.
+ // Filtering when isParamAccessor is a necessary simplification
+ // because there's a bunch of unwritten annotation code involving
+ // the propagation of annotations - constructor parameter annotations
+ // may need to make their way to parameters of the constructor as
+ // well as fields of the class, etc.
+ if (!mods.isParamAccessor) annotations foreach (ann =>
+ if (!trees.exists(_.symbol hasAnnotation ann.symbol))
+ issueAnnotationWarning(ann, GetterTargetClass)
+ )
+
+ trees
+ case vd: ValDef =>
+ warnForDroppedAnnotations(vd)
+ vd :: Nil
case cd @ ClassDef(mods, _, _, _) if mods.isImplicit =>
val annotations = stat.symbol.initialize.annotations
// TODO: need to shuffle annotations between wrapper and class.