diff options
author | Paul Phillips <paulp@improving.org> | 2012-05-04 17:44:28 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-05-04 18:24:16 -0700 |
commit | 0fb12fa0620c5f9999e309a4de7831549b283c24 (patch) | |
tree | 94a01f56b6ea8ed2dd2fdba0a8f9105e67f9d290 /src/compiler/scala/reflect/internal/Symbols.scala | |
parent | ecbf89552666ebba974188ef3c98b5f4855d0cea (diff) | |
download | scala-0fb12fa0620c5f9999e309a4de7831549b283c24.tar.gz scala-0fb12fa0620c5f9999e309a4de7831549b283c24.tar.bz2 scala-0fb12fa0620c5f9999e309a4de7831549b283c24.zip |
Updated Symbol to record classfile origin.
This change should be transparent to anything using sourceFile,
unless it was drinking from the inheritance well too deeply. Rather
than squander the already allocated field for every ClassSymbol not
being compiled from source, I'm now populating it with the file
representing the class. This will make a broad range of things easier,
like debugging, issuing useful error messages, symbol invalidation,
signature verification, you name it.
def sourceFile - still returns only source code files
def binaryFile - returns only class files
def associatedFile - returns whatever is there, if anything
Performance: I may be mistaken, but I believe this is a zero-impact
change. No new fields are allocated; fields which were null now hold
a useful reference. The reference is to a file instance which was
already being allocated and already long-lived.
Compare error messages:
// Version 1
% scalac a.scala
error: type _$1 is defined twice
// Version 2
% scalac a.scala
error: type _$1 is defined twice
conflicting symbols both originated in file './foo/package.class'
Note: this may be due to a bug in the compiler involving wildcards in package objects
one error found
Bonus for people who read commit logs. Try this in the repl
after starting power mode.
ListClass.info.members groupBy (_.associatedFile) foreach {
case (k, vs) => println("%s\n %s\n".format(k, vs map (_.defString) mkString "\n "))
}
Diffstat (limited to 'src/compiler/scala/reflect/internal/Symbols.scala')
-rw-r--r-- | src/compiler/scala/reflect/internal/Symbols.scala | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 78cec02c0a..2a5b759f94 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -2036,13 +2036,27 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isExpandedModuleClass: Boolean = name(name.length - 1) == '$' */ - def sourceFile: AbstractFileType = - if (isModule) moduleClass.sourceFile - else enclosingTopLevelClass.sourceFile - def sourceFile_=(f: AbstractFileType) { - abort("sourceFile_= inapplicable for " + this) - } + /** Desire to re-use the field in ClassSymbol which stores the source + * file to also store the classfile, but without changing the behavior + * of sourceFile (which is expected at least in the IDE only to + * return actual source code.) So sourceFile has classfiles filtered out. + */ + private def sourceFileOnly(file: AbstractFileType): AbstractFileType = + if ((file eq null) || (file.path endsWith ".class")) null else file + + private def binaryFileOnly(file: AbstractFileType): AbstractFileType = + if ((file eq null) || !(file.path endsWith ".class")) null else file + + final def binaryFile: AbstractFileType = binaryFileOnly(associatedFile) + final def sourceFile: AbstractFileType = sourceFileOnly(associatedFile) + + /** Overridden in ModuleSymbols to delegate to the module class. */ + def associatedFile: AbstractFileType = enclosingTopLevelClass.associatedFile + def associatedFile_=(f: AbstractFileType) { abort("associatedFile_= inapplicable for " + this) } + + @deprecated("Use associatedFile_= instead", "2.10.0") + def sourceFile_=(f: AbstractFileType): Unit = associatedFile_=(f) /** If this is a sealed class, its known direct subclasses. * Otherwise, the empty set. @@ -2423,6 +2437,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => def distinguishingFlag = MODULE private var flatname: TermName = null + override def associatedFile = moduleClass.associatedFile + override def associatedFile_=(f: AbstractFileType) { moduleClass.associatedFile = f } + override def isModule = true override def moduleClass = referenced override def companionClass = @@ -2718,9 +2735,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => extends TypeSymbol(initOwner, initPos, initName) with ClassSymbolApi { type TypeOfClonedSymbol = ClassSymbol - private[this] var flatname: TypeName = _ - private[this] var source: AbstractFileType = _ - private[this] var thissym: Symbol = this + private[this] var flatname: TypeName = _ + private[this] var _associatedFile: AbstractFileType = _ + private[this] var thissym: Symbol = this private[this] var thisTypeCache: Type = _ private[this] var thisTypePeriod = NoPeriod @@ -2819,10 +2836,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (c.isOverloaded) c.alternatives.head else c } - override def sourceFile = - if (owner.isPackageClass) source - else super.sourceFile - override def sourceFile_=(f: AbstractFileType) { source = f } + override def associatedFile = if (owner.isPackageClass) _associatedFile else super.associatedFile + override def associatedFile_=(f: AbstractFileType) { _associatedFile = f } override def reset(completer: Type): this.type = { super.reset(completer) @@ -2867,6 +2882,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => clone.typeOfThis = typeOfThis clone.thisSym setName thisSym.name } + if (_associatedFile ne null) + clone.associatedFile = _associatedFile + clone } @@ -3021,7 +3039,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def enclosingTopLevelClass: Symbol = this override def enclosingPackageClass: Symbol = this override def enclMethod: Symbol = this - override def sourceFile: AbstractFileType = null + override def associatedFile = null override def ownerChain: List[Symbol] = List() override def ownersIterator: Iterator[Symbol] = Iterator.empty override def alternatives: List[Symbol] = List() |