From 1673a2a3e251b632eacc96bc068651eaa9b21e22 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Sat, 9 Jan 2010 18:22:58 -0500 Subject: [PATCH] Remove use of reflection for compatibility in Analyzer --- compile/api/SameAPI.scala | 220 ++++++++++++++++----------- compile/interface/Analyzer.scala | 31 ++-- compile/interface/CachedMethod.scala | 27 ---- notes | 3 + 4 files changed, 150 insertions(+), 131 deletions(-) delete mode 100644 compile/interface/CachedMethod.scala diff --git a/compile/api/SameAPI.scala b/compile/api/SameAPI.scala index 73937a7a5..4c428bb8f 100644 --- a/compile/api/SameAPI.scala +++ b/compile/api/SameAPI.scala @@ -21,38 +21,68 @@ object SameAPI } private class SameAPI { - def debug(flag: Boolean, msg: => String): Boolean = + abstract class Result(val referencesMap: immutable.Map[Int, Int], val parameterMap: immutable.Map[Int, Int]) extends NotNull { - if(!flag) println(msg) + def &&(o: => Result): Result + def value: Boolean + } + final object False extends Result(Map.empty, Map.empty) + { + def &&(o: => Result): Result = this + def value = false + } + final class True(references: immutable.Map[Int, Int], parameters: immutable.Map[Int, Int]) extends Result(references, parameters) + { + def value = true + def &&(o: => Result): Result = o match { case False => o; case t: True => newTrue(t) } + private def newTrue(t: True): True = + { + def equalIntersection(a: Map[Int, Int], b: Map[Int, Int]) = + { + val sameKeys = a.keySet ** b.keySet + assume(sameKeys.forall(key => a(key) == b(key))) + } + equalIntersection(referencesMap, t.referencesMap) + equalIntersection(parameterMap, t.parameterMap) + new True(referencesMap ++ t.referencesMap, parameterMap ++ t.parameterMap) + } + } + implicit def b2b(b: Boolean): Result = if(b) new True(Map.empty, Map.empty) else False + + def debug(flag: Result, msg: => String): Result = + { + if(!flag.value) println(msg) flag } - private val parameterMap = new mutable.HashMap[Int, Int] - private val referencesMap = new mutable.HashMap[Int, Int] + def printMaps(b: Result) = println(mapStrings(b)) + def mapStrings(b: Result) = + { + "parameter map:\n\t" + + b.parameterMap.mkString("\n\t") + + "\nreference map:\n\t" + + b.referencesMap.mkString("\n\t") + } + def check(a: Source, b: Source): Boolean = + { + val initialResult = + samePackages(a, b) && + debug(sameDefinitions(a, b), "Definitions differed") + initialResult.value && + debug(sameReferences(initialResult.referencesMap, initialResult.parameterMap), "References differed: \n" + mapStrings(initialResult)).value + } - private def mapID(map: mutable.Map[Int, Int], key: Int, value: Int): Boolean = - equalOrEmpty(map.put(key, value), value) - private def equalOrEmpty[T](o: Option[T], nonemptyValue: T): Boolean = - o match { case Some(v) => v == nonemptyValue; case None => true } + def sameReferences(referencesMap: Map[Int,Int], parameterMap: Map[Int,Int]): Boolean = + referencesMap.forall { case (a, b) => parameterMap(a) == b } - def check(a: Source, b: Source) = - samePackages(a, b) && - debug(sameDefinitions(a, b), "Definitions differed") && - debug(sameReferences, "References differed") - - def sameReferences: Boolean = - referencesMap.forall(tupled(sameReference)) - def sameReference(a: Int, b: Int): Boolean = - parameterMap(a) == b - - def samePackages(a: Source, b: Source): Boolean = + def samePackages(a: Source, b: Source): Result = sameStrings(packages(a), packages(b)) def packages(s: Source): Set[String] = Set() ++ s.packages.map(_.name) - def sameDefinitions(a: Source, b: Source): Boolean = + def sameDefinitions(a: Source, b: Source): Result = sameDefinitions(a.definitions, b.definitions) - def sameDefinitions(a: Seq[Definition], b: Seq[Definition]): Boolean = + def sameDefinitions(a: Seq[Definition], b: Seq[Definition]): Result = { val (avalues, atypes) = separateDefinitions(a) val (bvalues, btypes) = separateDefinitions(b) @@ -61,23 +91,33 @@ private class SameAPI } def separateDefinitions(s: Seq[Definition]): (Seq[Definition], Seq[Definition]) = s.toArray.partition(isValueDefinition) - def sameDefinitions(a: scala.collection.Map[String, List[Definition]], b: scala.collection.Map[String, List[Definition]]): Boolean = - debug(sameStrings(a.keySet, b.keySet), "\tDefinition strings differed") && zippedEntries(a,b).forall(tupled(sameNamedDefinitions)) + def sameDefinitions(a: scala.collection.Map[String, List[Definition]], b: scala.collection.Map[String, List[Definition]]): Result = + debug(sameStrings(a.keySet, b.keySet), "\tDefinition strings differed") && forall(zippedEntries(a,b))(tupled(sameNamedDefinitions)) - def sameNamedDefinitions(a: List[Definition], b: List[Definition]): Boolean = + def sameNamedDefinitions(a: List[Definition], b: List[Definition]): Result = { - def sameDefs(a: List[Definition], b: List[Definition]): Boolean = + println("Comparing " + a.size + " defs against " + b.size + " defs") + def sameDefs(a: List[Definition], b: List[Definition], v: Result): Result = + { + println("\t " + a.size + " to " + b.size + "") a match { - case xdef :: tail => - b.find(bdef => sameDefinitionContent(xdef, bdef)) match - { - case Some(bdef) => sameDefs(tail, b - bdef) - case None => debug(false, "Definition not in new API: \n" + xdef.name ) - } - case Nil => true + case adef :: atail => + def sameDef(seen: List[Definition], remaining: List[Definition]): Result = + remaining match + { + case Nil => debug(false, "Definition different in new API: \n" + adef.name ) + case bdef :: btail => + val eq = v && sameDefinitionContent(adef, bdef) + if(eq.value) printMaps(eq) + if(eq.value) sameDefs(atail, seen ::: btail, eq) else sameDef(bdef :: seen, btail) + } + sameDef(Nil, b) + case Nil => v } - debug((a.length == b.length), "\t\tLength differed for " + a.headOption.map(_.name).getOrElse("empty")) && sameDefs(a, b) + } + //if(a.length > 1) println("Comparing\n" + a.mkString("\n\t") + "\nagainst\n" + b.mkString("\n\t") + "\n\n") + debug((a.length == b.length), "\t\tLength differed for " + a.headOption.map(_.name).getOrElse("empty")) && sameDefs(a, b, true) } def isValueDefinition(d: Definition): Boolean = @@ -98,14 +138,14 @@ private class SameAPI } // doesn't check name - def sameDefinitionContent(a: Definition, b: Definition): Boolean = + def sameDefinitionContent(a: Definition, b: Definition): Result = //a.name == b.name && debug(sameAccess(a.access, b.access), "Access differed") && debug(sameModifiers(a.modifiers, b.modifiers), "Modifiers differed") && debug(sameAnnotations(a.annotations, b.annotations), "Annotations differed") && debug(sameDefinitionSpecificAPI(a, b), "Definition-specific differed") - def sameAccess(a: Access, b: Access): Boolean = + def sameAccess(a: Access, b: Access): Result = (a, b) match { case (_: Public, _: Public) => true @@ -114,9 +154,9 @@ private class SameAPI case (qa: Pkg, qb: Pkg) => sameQualifier(qa, qb) case _ => debug(false, "Different access categories") } - def sameQualifier(a: Qualified, b: Qualified): Boolean = + def sameQualifier(a: Qualified, b: Qualified): Result = sameQualifier(a.qualifier, b.qualifier) - def sameQualifier(a: Qualifier, b: Qualifier): Boolean = + def sameQualifier(a: Qualifier, b: Qualifier): Result = (a, b) match { case (_: Unqualified, _: Unqualified) => true @@ -125,7 +165,7 @@ private class SameAPI case _ => debug(false, "Different qualifier categories: " + a.getClass.getName + " -- " +b.getClass.getName) } - def sameModifiers(a: Modifiers, b: Modifiers): Boolean = + def sameModifiers(a: Modifiers, b: Modifiers): Result = bitSet(a) == bitSet(b) def bitSet(m: Modifiers): immutable.BitSet = @@ -142,20 +182,20 @@ private class SameAPI setIf(bs, isSynthetic, 7) bs.toImmutable } - def setIf(bs: mutable.BitSet, flag: Boolean, i: Int): Unit = - if(flag) bs += i + def setIf(bs: mutable.BitSet, flag: Result, i: Int): Unit = + if(flag.value) bs += i - def sameAnnotations(a: Seq[Annotation], b: Seq[Annotation]): Boolean = + def sameAnnotations(a: Seq[Annotation], b: Seq[Annotation]): Result = sameSeq(a, b)(sameAnnotation) - def sameAnnotation(a: Annotation, b: Annotation): Boolean = + def sameAnnotation(a: Annotation, b: Annotation): Result = debug(sameSimpleType(a.base, b.base), "Annotation base type differed") && debug(sameAnnotationArguments(a.arguments, b.arguments), "Annotation arguments differed (" + a + ") and (" + b + ")") - def sameAnnotationArguments(a: Seq[AnnotationArgument], b: Seq[AnnotationArgument]): Boolean = + def sameAnnotationArguments(a: Seq[AnnotationArgument], b: Seq[AnnotationArgument]): Result = argumentMap(a) == argumentMap(b) def argumentMap(a: Seq[AnnotationArgument]): Map[String,String] = Map() ++ a.map(arg => (arg.name, arg.value)) - def sameDefinitionSpecificAPI(a: Definition, b: Definition): Boolean = + def sameDefinitionSpecificAPI(a: Definition, b: Definition): Result = (a, b) match { case (fa: FieldLike, fb: FieldLike) => sameFieldSpecificAPI(fa, fb) @@ -163,11 +203,11 @@ private class SameAPI case _ => false } - def sameParameterizedDefinition(a: ParameterizedDefinition, b: ParameterizedDefinition): Boolean = + def sameParameterizedDefinition(a: ParameterizedDefinition, b: ParameterizedDefinition): Result = debug(sameTypeParameters(a.typeParameters, b.typeParameters), "Different type parameters for " + a.name) && sameParameterizedSpecificAPI(a, b) - def sameParameterizedSpecificAPI(a: ParameterizedDefinition, b: ParameterizedDefinition): Boolean = + def sameParameterizedSpecificAPI(a: ParameterizedDefinition, b: ParameterizedDefinition): Result = (a, b) match { case (da: Def, db: Def) => sameDefSpecificAPI(da, db) @@ -177,19 +217,19 @@ private class SameAPI case _ => false } - def sameDefSpecificAPI(a: Def, b: Def): Boolean = + def sameDefSpecificAPI(a: Def, b: Def): Result = debug(sameValueParameters(a.valueParameters, b.valueParameters), "Different def value parameters for " + a.name) && debug(sameType(a.returnType, b.returnType), "Different def return type for " + a.name) - def sameAliasSpecificAPI(a: TypeAlias, b: TypeAlias): Boolean = + def sameAliasSpecificAPI(a: TypeAlias, b: TypeAlias): Result = debug(sameType(a.tpe, b.tpe), "Different alias type for " + a.name) - def sameDeclarationSpecificAPI(a: TypeDeclaration, b: TypeDeclaration): Boolean = + def sameDeclarationSpecificAPI(a: TypeDeclaration, b: TypeDeclaration): Result = debug(sameType(a.lowerBound, b.lowerBound), "Different lower bound for declaration " + a.name) && debug(sameType(a.upperBound, b.upperBound), "Different upper bound for declaration " + a.name) - def sameFieldSpecificAPI(a: FieldLike, b: FieldLike): Boolean = + def sameFieldSpecificAPI(a: FieldLike, b: FieldLike): Result = debug(sameFieldCategory(a, b), "Different field categories (" + a.name + "=" + a.getClass.getName + " -- " +a.name + "=" + a.getClass.getName + ")")&& debug(sameType(a.tpe, b.tpe), "Different field type for " + a.name) - def sameFieldCategory(a: FieldLike, b: FieldLike): Boolean = + def sameFieldCategory(a: FieldLike, b: FieldLike): Result = (a,b) match { case (_: Val, _: Val) => true @@ -197,72 +237,73 @@ private class SameAPI case _=> false } - def sameClassLikeSpecificAPI(a: ClassLike, b: ClassLike): Boolean = + def sameClassLikeSpecificAPI(a: ClassLike, b: ClassLike): Result = sameDefinitionType(a.definitionType, b.definitionType) && sameType(a.selfType, b.selfType) && sameStructure(a.structure, b.structure) - def sameValueParameters(a: Seq[ParameterList], b: Seq[ParameterList]): Boolean = + def sameValueParameters(a: Seq[ParameterList], b: Seq[ParameterList]): Result = sameSeq(a, b)(sameParameterList) - def sameParameterList(a: ParameterList, b: ParameterList): Boolean = - (a.isImplicit == b.isImplicit) && + def sameParameterList(a: ParameterList, b: ParameterList): Result = + ((a.isImplicit == b.isImplicit): Result) && sameParameters(a.parameters, b.parameters) - def sameParameters(a: Seq[MethodParameter], b: Seq[MethodParameter]): Boolean = + def sameParameters(a: Seq[MethodParameter], b: Seq[MethodParameter]): Result = sameSeq(a, b)(sameMethodParameter) - def sameMethodParameter(a: MethodParameter, b: MethodParameter): Boolean = - (a.name == b.name) && + def sameMethodParameter(a: MethodParameter, b: MethodParameter): Result = + ((a.name == b.name): Result) && sameType(a.tpe, b.tpe) && (a.hasDefault == b.hasDefault) && sameParameterModifier(a.modifier, b.modifier) def sameParameterModifier(a: ParameterModifier, b: ParameterModifier) = a == b - def sameDefinitionType(a: DefinitionType, b: DefinitionType): Boolean = + def sameDefinitionType(a: DefinitionType, b: DefinitionType): Result = a == b - def sameVariance(a: Variance, b: Variance): Boolean = + def sameVariance(a: Variance, b: Variance): Result = a == b - def sameTypeParameters(a: Seq[TypeParameter], b: Seq[TypeParameter]): Boolean = + def sameTypeParameters(a: Seq[TypeParameter], b: Seq[TypeParameter]): Result = debug(sameSeq(a, b)(sameTypeParameter), "Different type parameters") - def sameTypeParameter(a: TypeParameter, b: TypeParameter): Boolean = + def sameTypeParameter(a: TypeParameter, b: TypeParameter): Result = sameTypeParameters(a.typeParameters, b.typeParameters) && debug(sameVariance(a.variance, b.variance), "Different variance") && debug(sameType(a.lowerBound, b.lowerBound), "Different lower bound") && debug(sameType(a.upperBound, b.upperBound), "Different upper bound") && debug(mapSameParameters(a, b), "Different type parameter bindings") - def mapSameParameters(a: TypeParameter, b: TypeParameter): Boolean = - mapID(parameterMap, a.id, b.id) + def mapSameParameters(a: TypeParameter, b: TypeParameter): Result = + mapParameters(a.id, b.id) + def mapParameters(a: Int, b: Int) = new True(Map.empty, Map( a -> b )) - def sameType(a: Type, b: Type): Boolean = + def sameType(a: Type, b: Type): Result = (a, b) match { - case (sa: SimpleType, sb: SimpleType) => debug(sameSimpleType(sa, sb), "Different simple type") - case (aa: Annotated, ab: Annotated) => debug(sameAnnotatedType(aa, ab), "Different annotated type") + case (sa: SimpleType, sb: SimpleType) => debug(sameSimpleType(sa, sb), "Different simple types: " + sa + " and " + {Thread.dumpStack; sb}) + case (aa: Annotated, ab: Annotated) => debug(sameAnnotatedType(aa, ab), "Different annotated types") case (sa: Structure, sb: Structure) => debug(sameStructure(sa, sb), "Different structure type") case (ea: Existential, eb: Existential) => debug(sameExistentialType(ea, eb), "Different existential type") case (pa: Polymorphic, pb: Polymorphic) => debug(samePolymorphicType(pa, pb), "Different polymorphic type") case _ => false } - def sameExistentialType(a: Existential, b: Existential): Boolean = + def sameExistentialType(a: Existential, b: Existential): Result = sameTypeParameters(a.clause, b.clause) && sameType(a.baseType, b.baseType) - def samePolymorphicType(a: Polymorphic, b: Polymorphic): Boolean = + def samePolymorphicType(a: Polymorphic, b: Polymorphic): Result = sameTypeParameters(a.parameters, b.parameters) && sameType(a.baseType, b.baseType) - def sameAnnotatedType(a: Annotated, b: Annotated): Boolean = + def sameAnnotatedType(a: Annotated, b: Annotated): Result = sameSimpleType(a.baseType, b.baseType) && sameAnnotations(a.annotations, b.annotations) - def sameStructure(a: Structure, b: Structure): Boolean = + def sameStructure(a: Structure, b: Structure): Result = sameSeq(a.parents, b.parents)(sameType) && sameMembers(a.declarations, b.declarations) && sameMembers(a.inherited, b.inherited) - def sameMembers(a: Seq[Definition], b: Seq[Definition]): Boolean = + def sameMembers(a: Seq[Definition], b: Seq[Definition]): Result = sameDefinitions(a, b) - def sameSimpleType(a: SimpleType, b: SimpleType): Boolean = + def sameSimpleType(a: SimpleType, b: SimpleType): Result = (a, b) match { case (pa: Projection, pb: Projection) => debug(sameProjection(pa, pb), "Different projection") @@ -273,22 +314,23 @@ private class SameAPI case _ => debug(false, "Different category of simple type (" + a.getClass.getName + " and " + b.getClass.getName + ") for (" + a + " and " + b + ")") } - def sameParameterized(a: Parameterized, b: Parameterized): Boolean = + def sameParameterized(a: Parameterized, b: Parameterized): Result = sameSimpleType(a.baseType, b.baseType) && sameSeq(a.typeArguments, b.typeArguments)(sameType) - def sameParameterRef(a: ParameterRef, b: ParameterRef): Boolean = - mapID(referencesMap, a.id, b.id) - def sameSingleton(a: Singleton, b: Singleton): Boolean = + def sameParameterRef(a: ParameterRef, b: ParameterRef): Result = + mapReferences(a.id, b.id) + def mapReferences(a: Int, b: Int) = new True(Map( a -> b ), Map.empty) + def sameSingleton(a: Singleton, b: Singleton): Result = samePath(a.path, b.path) - def sameProjection(a: Projection, b: Projection): Boolean = + def sameProjection(a: Projection, b: Projection): Result = sameSimpleType(a.prefix, b.prefix) && (a.id == b.id) - def samePath(a: Path, b: Path): Boolean = + def samePath(a: Path, b: Path): Result = samePathComponents(a.components, b.components) - def samePathComponents(a: Seq[PathComponent], b: Seq[PathComponent]): Boolean = + def samePathComponents(a: Seq[PathComponent], b: Seq[PathComponent]): Result = sameSeq(a, b)(samePathComponent) - def samePathComponent(a: PathComponent, b: PathComponent): Boolean = + def samePathComponent(a: PathComponent, b: PathComponent): Result = (a, b) match { case (_: This, _: This) => true @@ -296,21 +338,25 @@ private class SameAPI case (ia: Id, ib: Id) => samePathId(ia, ib) case _ => false } - def samePathSuper(a: Super, b: Super): Boolean = + def samePathSuper(a: Super, b: Super): Result = samePath(a.qualifier, b.qualifier) - def samePathId(a: Id, b: Id): Boolean = + def samePathId(a: Id, b: Id): Result = a.id == b.id // precondition: a.keySet == b.keySet protected def zippedEntries[A,B](a: scala.collection.Map[A,B], b: scala.collection.Map[A,B]): Iterable[(B,B)] = for( (key, avalue) <- a) yield (avalue, b(key)) - def sameStrings(a: scala.collection.Set[String], b: scala.collection.Set[String]) = + def sameStrings(a: scala.collection.Set[String], b: scala.collection.Set[String]): Result = a == b - def sameSeq[T](a: Seq[T], b: Seq[T])(eq: (T,T) => Boolean): Boolean = + final def sameSeq[T](a: Seq[T], b: Seq[T])(eq: (T,T) => Result): Result = sameArray(a.toArray, b.toArray)(eq) - private def sameArray[T](a: Array[T], b: Array[T])(eq: (T,T) => Boolean): Boolean = - (a.length == b.length) && a.zip(b).forall(tupled(eq)) + final def sameArray[T](a: Array[T], b: Array[T])(eq: (T,T) => Result): Result = + ((a.length == b.length): Result) && forall(a.zip(b))(tupled(eq)) + final def forall[T](a: Iterable[T])(f: T => Result): Result = forallList(a.toList, true)(f) + final def forallList[T](a: List[T], v: Result)(f: T => Result): Result = + if(v.value) ( a match { case Nil => v; case x :: xs => forallList(xs, v && f(x) )(f) } ) + else v def defaultEquals[T <: AnyRef] = (a: T, b: T) => a == b } \ No newline at end of file diff --git a/compile/interface/Analyzer.scala b/compile/interface/Analyzer.scala index 900897593..0232dc9eb 100644 --- a/compile/interface/Analyzer.scala +++ b/compile/interface/Analyzer.scala @@ -114,7 +114,7 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends private def classFile(sym: Symbol): Option[AbstractFile] = { import scala.tools.nsc.symtab.Flags - val name = sym.fullNameString(File.separatorChar) + (if (sym.hasFlag(Flags.MODULE)) "$" else "") + val name = sym.fullNameString(finder.classSeparator) + (if (sym.hasFlag(Flags.MODULE)) "$" else "") finder.findClass(name) orElse { if(isTopLevelModule(sym)) { @@ -186,32 +186,29 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends private lazy val finder = try { new LegacyFinder } catch { case _ => new NewFinder } private trait ClassFinder { + def classSeparator: Char def findClass(name: String): Option[AbstractFile] } private class NewFinder extends ClassFinder { - private val findClass0 = reflect[Option[AnyRef]]("findClass", classOf[String]) - findClass0.force(classPath) // force discovery, so that an exception is thrown if method doesn't exist - private val extractClass0 = reflect[Option[AbstractFile]]("binary") - private def translate(name: String): String = name.replace(File.separatorChar, '.') // 2.8 uses '.', 2.7 uses '/' + class Compat27 { def findClass(name: String) = this; def flatMap(f: Compat27 => AnyRef) = Predef.error("Should never be called"); def binary = None } + implicit def compat27(any: AnyRef): Compat27 = new Compat27 + + def classSeparator = '.' // 2.8 uses . when searching for classes def findClass(name: String): Option[AbstractFile] = - findClass0(classPath, translate(name)).flatMap {a => extractClass0(a) } + classPath.findClass(name).flatMap(_.binary.asInstanceOf[Option[AbstractFile]]) } private class LegacyFinder extends ClassFinder { - private val root = { val m = reflect[AnyRef]("root"); m(classPath) } - private val find0 = reflect[AnyRef]("find", classOf[String], classOf[Boolean]) - find0.force(root) // force discovery, so that an exception is thrown if method doesn't exist - private val classFile = reflect[AbstractFile]("classFile") + class Compat28 { def root: Compat28 = invalid; def find(n: String, b: Boolean) = this; def classFile = invalid; def invalid = Predef.error("Should never be called") } + implicit def compat28(any: AnyRef): Compat28 = new Compat28 + + def classSeparator = File.separatorChar // 2.7 uses / or \ when searching for classes + private val root = classPath.root def findClass(name: String): Option[AbstractFile] = { - val entry = find0(root, name, boolean2Boolean(false)) - if (entry eq null) - None - else - Some( classFile(entry) ) + val entry = root.find(name, false) + if(entry eq null) None else Some(entry.classFile) } } - import scala.reflect.Manifest - private def reflect[T](name: String, tpes: Class[_]*)(implicit mf: Manifest[T]) = new CachedMethod(name, tpes : _*)(mf) } \ No newline at end of file diff --git a/compile/interface/CachedMethod.scala b/compile/interface/CachedMethod.scala deleted file mode 100644 index 943968fec..000000000 --- a/compile/interface/CachedMethod.scala +++ /dev/null @@ -1,27 +0,0 @@ -package xsbt - -import java.lang.ref.WeakReference -import java.lang.reflect.Method -import scala.reflect.Manifest - -// replacement for structural type cache, which doesn't use weak references -// assumes type of target doesn't change -// not thread safe -private final class CachedMethod[T](name: String, tpes: Class[_]*)(mf: Manifest[T]) extends NotNull -{ - private var method = new WeakReference[Method](null) - private def getMethod(on: AnyRef): Method = - { - val m = on.getClass.getMethod(name, tpes : _*) - method = new WeakReference(m) - m - } - def force(on: AnyRef) { getMethod(on) } - def apply(on: AnyRef, args: AnyRef*): T = - { - val cached = method.get - val m = if(cached ne null) cached else getMethod(on) - val result = m.invoke(on, args : _*) - mf.erasure.cast(result).asInstanceOf[T] - } -} \ No newline at end of file diff --git a/notes b/notes index 4873309c4..71f0e44eb 100644 --- a/notes +++ b/notes @@ -1,6 +1,7 @@ DONE -fix caching issue for compiler interface -fix test ClassLoader +-implement