Permalink
Browse files

SI-6372 cleans up the API of Attachments

Previously Attachments allowed multiple attachments that
correspond to the same attachment type.

This created a potential for confusion, given that Attachments.get
only searched for the first attachment of a given type.

Hence I made Attachments.add overwrite previously existing attachments
of a given type and renamed it to Attachments.update, so that the name
suits the intention better.
  • Loading branch information...
xeno-by committed Sep 14, 2012
1 parent ed913c2 commit 210f8c8f108aaf650a5be640c4db0d2336193f33
@@ -143,7 +143,7 @@ trait GenSymbols {
// produces valid Scala code (with vals in a block depending only on lexically preceding vals)
val reification = reificode(sym)
import reification.{name, binding}
val tree = reification.tree addAttachment ReifyBindingAttachment(binding)
val tree = reification.tree updateAttachment ReifyBindingAttachment(binding)
state.symtab += (sym, name, tree)
}
fromSymtab
@@ -46,8 +46,8 @@ trait SymbolTables {
def symRef(sym: Symbol): Tree =
symtab.get(sym) match {
case Some(FreeDef(_, name, binding, _, _)) => Ident(name) addAttachment binding
case Some(SymDef(_, name, _, _)) => Ident(name) addAttachment ReifyBindingAttachment(Ident(sym))
case Some(FreeDef(_, name, binding, _, _)) => Ident(name) updateAttachment binding
case Some(SymDef(_, name, _, _)) => Ident(name) updateAttachment ReifyBindingAttachment(Ident(sym))
case None => EmptyTree
}
@@ -86,7 +86,7 @@ trait SymbolTables {
newTermName(fresh.newName(name))
}
val bindingAttachment = reification.attachments.get[ReifyBindingAttachment].get
add(ValDef(NoMods, freshName(name0), TypeTree(), reification) addAttachment bindingAttachment)
add(ValDef(NoMods, freshName(name0), TypeTree(), reification) updateAttachment bindingAttachment)
}
private def add(sym: Symbol, name: TermName): SymbolTable = {
@@ -203,7 +203,7 @@ trait SymbolTables {
result ++= cumulativeAliases.distinct filter (alias => alias._1 == sym && alias._2 != currtab.symName(sym)) map (alias => {
val canonicalName = currtab.symName(sym)
val aliasName = alias._2
ValDef(NoMods, aliasName, TypeTree(), Ident(canonicalName)) addAttachment ReifyAliasAttachment(sym, aliasName)
ValDef(NoMods, aliasName, TypeTree(), Ident(canonicalName)) updateAttachment ReifyAliasAttachment(sym, aliasName)
})
result.toList
})
@@ -1029,7 +1029,7 @@ self =>
val tok = in.token
val name = ident()
t = atPos(start) {
if (tok == BACKQUOTED_IDENT) Ident(name) addAttachment BackquotedIdentifierAttachment
if (tok == BACKQUOTED_IDENT) Ident(name) updateAttachment BackquotedIdentifierAttachment
else Ident(name)
}
if (in.token == DOT) {
@@ -1082,7 +1082,7 @@ abstract class Erasure extends AddInterfaces
// println("inject derived: "+arg+" "+tpt.tpe)
val List(arg) = args
val attachment = new TypeRefAttachment(tree.tpe.asInstanceOf[TypeRef])
InjectDerivedValue(arg) addAttachment attachment
InjectDerivedValue(arg) updateAttachment attachment
case _ =>
preEraseNormalApply(tree)
}
@@ -713,7 +713,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
if (isNullaryInvocation(expandee)) expectedTpe = expectedTpe.finalResultType
var typechecked = typecheck("macro def return type", expanded, expectedTpe)
typechecked = typecheck("expected type", typechecked, pt)
typechecked addAttachment MacroExpansionAttachment(expandee)
typechecked updateAttachment MacroExpansionAttachment(expandee)
} finally {
popMacroContext()
}
@@ -762,7 +762,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
case (false, true) =>
macroLogLite("macro expansion is delayed: %s".format(expandee))
delayed += expandee -> undetparams
expandee addAttachment MacroRuntimeAttachment(delayed = true, typerContext = typer.context, macroContext = Some(macroArgs(typer, expandee).c))
expandee updateAttachment MacroRuntimeAttachment(delayed = true, typerContext = typer.context, macroContext = Some(macroArgs(typer, expandee).c))
Delay(expandee)
case (false, false) =>
import typer.TyperErrorGen._
@@ -637,15 +637,15 @@ trait Namers extends MethodSynthesis {
MaxParametersCaseClassError(tree)
val m = ensureCompanionObject(tree, caseModuleDef)
m.moduleClass.addAttachment(new ClassForCaseCompanionAttachment(tree))
m.moduleClass.updateAttachment(new ClassForCaseCompanionAttachment(tree))
}
val hasDefault = impl.body exists {
case DefDef(_, nme.CONSTRUCTOR, _, vparamss, _, _) => mexists(vparamss)(_.mods.hasDefault)
case _ => false
}
if (hasDefault) {
val m = ensureCompanionObject(tree)
m.addAttachment(new ConstructorDefaultsAttachment(tree, null))
m.updateAttachment(new ConstructorDefaultsAttachment(tree, null))
}
val owner = tree.symbol.owner
if (settings.lint.value && owner.isPackageObjectClass && !mods.isImplicit) {
@@ -1172,7 +1172,7 @@ trait Namers extends MethodSynthesis {
// symbol will be re-entered in the scope but the default parameter will not.
val att = meth.attachments.get[DefaultsOfLocalMethodAttachment] match {
case Some(att) => att.defaultGetters += default
case None => meth.addAttachment(new DefaultsOfLocalMethodAttachment(default))
case None => meth.updateAttachment(new DefaultsOfLocalMethodAttachment(default))
}
}
} else if (baseHasDefault) {
@@ -2482,7 +2482,7 @@ trait Typers extends Modes with Adaptations with Tags {
match_ setType B1.tpe
// the default uses applyOrElse's first parameter since the scrut's type has been widened
val body = methodBodyTyper.virtualizedMatch(match_ addAttachment DefaultOverrideMatchAttachment(REF(default) APPLY (REF(x))), mode, B1.tpe)
val body = methodBodyTyper.virtualizedMatch(match_ updateAttachment DefaultOverrideMatchAttachment(REF(default) APPLY (REF(x))), mode, B1.tpe)
DefDef(methodSym, body)
}
@@ -2500,7 +2500,7 @@ trait Typers extends Modes with Adaptations with Tags {
methodSym setInfoAndEnter MethodType(paramSyms, BooleanClass.tpe)
val match_ = methodBodyTyper.typedMatch(gen.mkUnchecked(selector), casesTrue, mode, BooleanClass.tpe)
val body = methodBodyTyper.virtualizedMatch(match_ addAttachment DefaultOverrideMatchAttachment(FALSE_typed), mode, BooleanClass.tpe)
val body = methodBodyTyper.virtualizedMatch(match_ updateAttachment DefaultOverrideMatchAttachment(FALSE_typed), mode, BooleanClass.tpe)
DefDef(methodSym, body)
}
@@ -2622,7 +2622,7 @@ trait Typers extends Modes with Adaptations with Tags {
// todo. investigate whether something can be done about this
val att = templ.attachments.get[CompoundTypeTreeOriginalAttachment].getOrElse(CompoundTypeTreeOriginalAttachment(Nil, Nil))
templ.removeAttachment[CompoundTypeTreeOriginalAttachment]
templ addAttachment att.copy(stats = stats1)
templ updateAttachment att.copy(stats = stats1)
for (stat <- stats1 if stat.isDef) {
val member = stat.symbol
if (!(context.owner.ancestors forall
@@ -4947,7 +4947,7 @@ trait Typers extends Modes with Adaptations with Tags {
//Console.println("Owner: " + context.enclClass.owner + " " + context.enclClass.owner.id)
val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls, templ.pos)
newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ)
templ addAttachment CompoundTypeTreeOriginalAttachment(parents1, Nil) // stats are set elsewhere
templ updateAttachment CompoundTypeTreeOriginalAttachment(parents1, Nil) // stats are set elsewhere
tree setType self
}
}
@@ -20,15 +20,18 @@ abstract class Attachments { self =>
/** Gets the underlying payload */
def all: Set[Any] = Set.empty
private def matchesTag[T: ClassTag](datum: Any) =
classTag[T].runtimeClass == datum.getClass
def get[T: ClassTag]: Option[T] =
(all find (_.getClass == classTag[T].runtimeClass)).asInstanceOf[Option[T]]
(all filter matchesTag[T]).headOption.asInstanceOf[Option[T]]
/** Creates a copy of this attachment with its payload updated */
def add(attachment: Any): Attachments { type Pos = self.Pos } =
new NonemptyAttachments(this.pos, all + attachment)
def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } =
new NonemptyAttachments(this.pos, remove[T].all + attachment)
def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = {
val newAll = all filterNot (_.getClass == classTag[T].runtimeClass)
val newAll = all filterNot matchesTag[T]
if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }]
else new NonemptyAttachments(this.pos, newAll)
}
@@ -10,7 +10,7 @@ trait StdAttachments {
trait Attachable {
protected var rawatt: base.Attachments { type Pos = Position } = NoPosition
def attachments = rawatt
def addAttachment(attachment: Any): this.type = { rawatt = rawatt.add(attachment); this }
def updateAttachment[T: ClassTag](attachment: T): this.type = { rawatt = rawatt.update(attachment); this }
def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this }
// cannot be final due to SynchronizedSymbols
@@ -1600,7 +1600,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
setInfo (this.info cloneInfo clone)
setAnnotations this.annotations
)
this.attachments.all.foreach(clone.addAttachment)
this.attachments.all.foreach(clone.updateAttachment)
if (clone.thisSym != clone)
clone.typeOfThis = (clone.typeOfThis cloneInfo clone)
@@ -10,7 +10,7 @@ abstract class Universe extends scala.reflect.api.Universe {
def attachments: base.Attachments { type Pos = Position }
/** ... */
def addAttachment(attachment: Any): AttachableApi.this.type
def updateAttachment[T: ClassTag](attachment: T): AttachableApi.this.type
/** ... */
def removeAttachment[T: ClassTag]: AttachableApi.this.type

0 comments on commit 210f8c8

Please sign in to comment.