From 724b0dc71f1f8f91b995d01e9e027789f54ecdfe Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 6 Jul 2012 12:48:52 -0700 Subject: Implicits to encourage more Name-dropping. This creates implicits in cakes across the land from: String => TermName String => TypeName And also from: Name => NameOps[Name] // lower priority TermName => NameOps[TermName] TypeName => NameOps[TypeName] What this is all about, using "drop" as a motivating example, is that these should all work: "abc" drop 1 // "bc": String ("abc": TermName) drop 1 // "bc": TermName ("abc": TypeName) drop 1 // "bc": TypeName (("abc": TypeName): Name) drop 1 // "bc": Name But this should not: ("bc": Name) // ambiguity error This requires drop not being directly on Name; peer implicits from String => TermName and String => TypeName; implicit classes to install drop on TermName and TypeName; and a lower priority implicit class to allow ops on Names. Review by @xeno.by . --- .../scala/reflect/reify/utils/NodePrinters.scala | 2 +- .../tools/nsc/interactive/ScratchPadMaker.scala | 2 +- .../scala/tools/nsc/symtab/clr/TypeParser.scala | 18 ++++++++--------- .../scala/tools/nsc/typechecker/Typers.scala | 2 +- src/library/scala/reflect/base/Names.scala | 3 +++ src/reflect/scala/reflect/internal/Names.scala | 23 ++++++++++++++++------ src/reflect/scala/reflect/internal/StdNames.scala | 7 ++++++- .../scala/reflect/runtime/JavaMirrors.scala | 2 +- test/files/neg/reflection-names-neg.check | 10 ++++++++++ test/files/neg/reflection-names-neg.scala | 6 ++++++ test/files/run/reflection-names.check | 4 ++++ test/files/run/reflection-names.scala | 15 ++++++++++++++ 12 files changed, 73 insertions(+), 21 deletions(-) create mode 100644 test/files/neg/reflection-names-neg.check create mode 100644 test/files/neg/reflection-names-neg.scala create mode 100644 test/files/run/reflection-names.check create mode 100644 test/files/run/reflection-names.scala diff --git a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala index 7214da597e..6394e1eac2 100644 --- a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala +++ b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala @@ -42,7 +42,7 @@ trait NodePrinters { val buf = new collection.mutable.ListBuffer[String] val annotations = m.group(3) - if (buf.nonEmpty || annotations.nonEmpty) + if (buf.nonEmpty || annotations != "") buf.append("List(" + annotations + ")") val privateWithin = "" + m.group(2) diff --git a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala index a3f6726b44..c79248e1c1 100644 --- a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala +++ b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala @@ -92,7 +92,7 @@ trait ScratchPadMaker { self: Global => case PackageDef(_, _) => super.traverse(tree) case ModuleDef(_, name, Template(_, _, body)) => - if (objectName.length == 0 /* objectName.isEmpty does not compile on Java 5 due to ambiguous implicit conversions: augmentString, stringToTermName */) + if (objectName.length == 0) objectName = tree.symbol.fullName body foreach traverseStat applyPendingPatches(skipped) diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala index e54ecdd590..c5092aa057 100644 --- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala @@ -35,8 +35,6 @@ abstract class TypeParser { protected var busy: Boolean = false // lock to detect recursive reads - private implicit def stringToTermName(s: String): TermName = newTermName(s) - private object unpickler extends UnPickler { val global: TypeParser.this.global.type = TypeParser.this.global } @@ -260,8 +258,8 @@ abstract class TypeParser { || ntype.IsInterface /* TODO why shouldn't nested ifaces be type-parsed too? */ ) { val loader = new loaders.MsilFileLoader(new MsilFile(ntype)) - val nclazz = statics.newClass(ntype.Name.toTypeName) - val nmodule = statics.newModule(ntype.Name) + val nclazz = statics.newClass(ntype.Name) + val nmodule = statics.newModule(ntype.Name) nclazz.setInfo(loader) nmodule.setInfo(loader) staticDefs.enter(nclazz) @@ -311,7 +309,7 @@ abstract class TypeParser { assert(prop.PropertyType == getter.ReturnType); val gparams: Array[ParameterInfo] = getter.GetParameters(); gparamsLength = gparams.length; - val name: Name = if (gparamsLength == 0) prop.Name else nme.apply; + val name: TermName = if (gparamsLength == 0) prop.Name else nme.apply; val flags = translateAttributes(getter); val owner: Symbol = if (getter.IsStatic) statics else clazz; val methodSym = owner.newMethod(name, NoPosition, flags) @@ -333,7 +331,7 @@ abstract class TypeParser { if(getter != null) assert(sparams.length == gparamsLength + 1, "" + getter + "; " + setter); - val name: Name = if (gparamsLength == 0) nme.getterToSetter(prop.Name) + val name: TermName = if (gparamsLength == 0) nme.getterToSetter(prop.Name) else nme.update; val flags = translateAttributes(setter); val mtype = methodType(setter, definitions.UnitClass.tpe); @@ -494,13 +492,13 @@ abstract class TypeParser { else clrTypes.methods(methodSym) = method.asInstanceOf[MethodInfo]; } - private def createMethod(name: Name, flags: Long, args: Array[MSILType], retType: MSILType, method: MethodInfo, statik: Boolean): Symbol = { + private def createMethod(name: TermName, flags: Long, args: Array[MSILType], retType: MSILType, method: MethodInfo, statik: Boolean): Symbol = { val mtype = methodType(args, getCLSType(retType)) assert(mtype != null) createMethod(name, flags, mtype, method, statik) } - private def createMethod(name: Name, flags: Long, mtype: Symbol => Type, method: MethodInfo, statik: Boolean): Symbol = { + private def createMethod(name: TermName, flags: Long, mtype: Symbol => Type, method: MethodInfo, statik: Boolean): Symbol = { val methodSym: Symbol = (if (statik) statics else clazz).newMethod(name) methodSym.setFlag(flags).setInfo(mtype(methodSym)) (if (statik) staticDefs else instanceDefs).enter(methodSym) @@ -541,7 +539,7 @@ abstract class TypeParser { s = createMethod(nme.MINUS, flags, args, typ, clrTypes.DELEGATE_REMOVE, false); } - private def getName(method: MethodBase): Name = { + private def getName(method: MethodBase): TermName = { def operatorOverload(name : String, paramsArity : Int) : Option[Name] = paramsArity match { case 1 => name match { @@ -653,7 +651,7 @@ abstract class TypeParser { private def getClassType(typ: MSILType): Type = { assert(typ != null); - val res = rootMirror.getClassByName(typ.FullName.replace('+', '.')).tpe; + val res = rootMirror.getClassByName(typ.FullName.replace('+', '.') : TypeName).tpe; //if (res.isError()) // global.reporter.error("unknown class reference " + type.FullName); res diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index ccd346e72d..c675167139 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4283,7 +4283,7 @@ trait Typers extends Modes with Adaptations with Tags { } def convertToAssignment(fun: Tree, qual: Tree, name: Name, args: List[Tree]): Tree = { - val prefix = name stripSuffix nme.EQL + val prefix = name.toTermName stripSuffix nme.EQL def mkAssign(vble: Tree): Tree = Assign( vble, diff --git a/src/library/scala/reflect/base/Names.scala b/src/library/scala/reflect/base/Names.scala index edf2ba7dc9..280a6ce8a2 100644 --- a/src/library/scala/reflect/base/Names.scala +++ b/src/library/scala/reflect/base/Names.scala @@ -11,6 +11,9 @@ package base * `name1 == name2` implies `name1 eq name2`. */ trait Names { + /** Intentionally no implicit from String => Name. */ + implicit def stringToTermName(s: String): TermName = newTermName(s) + implicit def stringToTypeName(s: String): TypeName = newTypeName(s) /** The abstract type of names */ type Name >: Null <: NameBase diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala index 18671871ae..3c0848f77f 100644 --- a/src/reflect/scala/reflect/internal/Names.scala +++ b/src/reflect/scala/reflect/internal/Names.scala @@ -10,12 +10,18 @@ import scala.io.Codec import java.security.MessageDigest import language.implicitConversions +trait LowPriorityNames { + self: Names => + + implicit def nameToNameOps(name: Name): NameOps[Name] = new NameOps[Name](name) +} + /** The class Names ... * * @author Martin Odersky * @version 1.0, 05/02/2005 */ -trait Names extends api.Names { +trait Names extends api.Names with LowPriorityNames { implicit def promoteTermNamesAsNecessary(name: Name): TermName = name.toTermName // Operations ------------------------------------------------------------- @@ -356,11 +362,6 @@ trait Names extends api.Names { final def endsWith(char: Char): Boolean = len > 0 && endChar == char final def endsWith(name: String): Boolean = endsWith(newTermName(name)) - def dropRight(n: Int): ThisNameType = subName(0, len - n) - def drop(n: Int): ThisNameType = subName(n, len) - def stripSuffix(suffix: Name): ThisNameType = - if (this endsWith suffix) dropRight(suffix.length) else thisName - def indexOf(ch: Char) = { val idx = pos(ch) if (idx == length) -1 else idx @@ -429,6 +430,16 @@ trait Names extends api.Names { def debugString = { val s = decode ; if (isTypeName) s + "!" else s } } + implicit def TermNameOps(name: TermName): NameOps[TermName] = new NameOps(name) + implicit def TypeNameOps(name: TypeName): NameOps[TypeName] = new NameOps(name) + + final class NameOps[T <: Name](name: T) { + def stripSuffix(suffix: Name): T = if (name endsWith suffix) dropRight(suffix.length) else name + def dropRight(n: Int): T = name.subName(0, name.length - n).asInstanceOf[T] + def drop(n: Int): T = name.subName(n, name.length).asInstanceOf[T] + def nonEmpty: Boolean = name.length > 0 + } + implicit val NameTag = ClassTag[Name](classOf[Name]) /** A name that contains no operator chars nor dollar signs. diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 72a99589d5..4070ad83c6 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -84,6 +84,9 @@ trait StdNames { abstract class CommonNames extends NamesApi { type NameType >: Null <: Name + // Masking some implicits so as to allow our targeted => NameType. + protected val stringToTermName = null + protected val stringToTypeName = null protected implicit def createNameType(name: String): NameType def flattenedName(segments: Name*): NameType = @@ -963,7 +966,7 @@ trait StdNames { case -1 => if (name == "") scala.Nil else scala.List(mkName(name, assumeTerm)) // otherwise, we can tell based on whether '#' or '.' is the following char. case idx => - val (simple, div, rest) = (name take idx, name charAt idx, newTermName(name) drop (idx + 1)) + val (simple, div, rest) = (name take idx, name charAt idx, name drop idx + 1) mkName(simple, div == '.') :: segments(rest, assumeTerm) } } @@ -1038,6 +1041,8 @@ trait StdNames { } abstract class SymbolNames { + protected val stringToTermName = null + protected val stringToTypeName = null protected implicit def createNameType(s: String): TypeName = newTypeNameCached(s) val BeanProperty : TypeName diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 41955170bd..e147046410 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -658,7 +658,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym val ownerModule: ModuleSymbol = if (split > 0) packageNameToScala(fullname take split) else this.RootPackage val owner = ownerModule.moduleClass - val name = newTermName(fullname drop (split + 1)) + val name = (fullname: TermName) drop split + 1 val opkg = owner.info decl name if (opkg.isPackage) opkg.asModuleSymbol diff --git a/test/files/neg/reflection-names-neg.check b/test/files/neg/reflection-names-neg.check new file mode 100644 index 0000000000..a56a19e7fd --- /dev/null +++ b/test/files/neg/reflection-names-neg.check @@ -0,0 +1,10 @@ +reflection-names-neg.scala:5: error: type mismatch; + found : String("abc") + required: reflect.runtime.universe.Name +Note that implicit conversions are not applicable because they are ambiguous: + both method stringToTermName in trait Names of type (s: String)reflect.runtime.universe.TermName + and method stringToTypeName in trait Names of type (s: String)reflect.runtime.universe.TypeName + are possible conversion functions from String("abc") to reflect.runtime.universe.Name + val x2 = ("abc": Name) drop 1 // error + ^ +one error found diff --git a/test/files/neg/reflection-names-neg.scala b/test/files/neg/reflection-names-neg.scala new file mode 100644 index 0000000000..7283d16db9 --- /dev/null +++ b/test/files/neg/reflection-names-neg.scala @@ -0,0 +1,6 @@ +import scala.reflect.runtime.universe._ + +object Test { + val x1 = "abc" drop 1 // "bc": String + val x2 = ("abc": Name) drop 1 // error +} diff --git a/test/files/run/reflection-names.check b/test/files/run/reflection-names.check new file mode 100644 index 0000000000..f8cb78cc67 --- /dev/null +++ b/test/files/run/reflection-names.check @@ -0,0 +1,4 @@ +(java.lang.String,bc) +(scala.reflect.internal.Names$TermName_R,bc) +(scala.reflect.internal.Names$TypeName_R,bc) +(scala.reflect.internal.Names$TypeName_R,bc) diff --git a/test/files/run/reflection-names.scala b/test/files/run/reflection-names.scala new file mode 100644 index 0000000000..2433c84813 --- /dev/null +++ b/test/files/run/reflection-names.scala @@ -0,0 +1,15 @@ +import scala.tools.nsc._ + +object Test { + val global = new Global(new Settings()) + import global._ + + val x1 = "abc" drop 1 // "bc": String + val x2 = ("abc": TermName) drop 1 // "bc": TermName + val x3 = ("abc": TypeName) drop 1 // "bc": TypeName + val x4 = (("abc": TypeName): Name) drop 1 // "bc": Name + + def main(args: Array[String]): Unit = { + List(x1, x2, x3, x4) foreach (x => println(x.getClass.getName, x)) + } +} -- cgit v1.2.3 From b355fb2c7f622c2d263c43864469b862ef0bc768 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 13 Jul 2012 12:09:16 -0700 Subject: Avoid conflict with String's apply. This brought to light that Name extends (Int => Char), and that small convenience was not paying for itself. I updated the places taking advantage of it to use Name#charAt. --- src/compiler/scala/tools/nsc/ast/DocComments.scala | 2 +- .../scala/tools/nsc/ast/parser/Parsers.scala | 2 +- .../scala/tools/nsc/javac/JavaScanners.scala | 4 +-- .../nsc/symtab/classfile/ClassfileParser.scala | 32 +++++++++++----------- .../tools/nsc/typechecker/MethodSynthesis.scala | 2 +- src/reflect/scala/reflect/internal/Names.scala | 10 +++---- src/reflect/scala/reflect/internal/StdNames.scala | 8 +++--- src/reflect/scala/reflect/internal/TreeInfo.scala | 2 +- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala index 316faba6e2..b545140c4a 100755 --- a/src/compiler/scala/tools/nsc/ast/DocComments.scala +++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala @@ -522,7 +522,7 @@ trait DocComments { self: Global => val substAliases = new TypeMap { def apply(tp: Type) = mapOver(tp) match { - case tp1 @ TypeRef(pre, sym, args) if (sym.name.length > 1 && sym.name(0) == '$') => + case tp1 @ TypeRef(pre, sym, args) if (sym.name.length > 1 && sym.name.startChar == '$') => subst(sym, aliases, aliasExpansions) match { case TypeRef(pre1, sym1, _) => typeRef(pre1, sym1, args) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 3232bde3b4..e0c9631246 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -763,7 +763,7 @@ self => def precedence(operator: Name): Int = if (operator eq nme.ERROR) -1 else { - val firstCh = operator(0) + val firstCh = operator.startChar if (isScalaLetter(firstCh)) 1 else if (nme.isOpAssignmentName(operator)) 0 else firstCh match { diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala index 73b5a752b4..a37fdc3ed1 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala @@ -778,7 +778,7 @@ trait JavaScanners extends ast.parser.ScannersCommon { */ def intVal(negated: Boolean): Long = { if (token == CHARLIT && !negated) { - if (name.length > 0) name(0) else 0 + if (name.length > 0) name.charAt(0) else 0 } else { var value: Long = 0 val divider = if (base == 10) 1 else 2 @@ -787,7 +787,7 @@ trait JavaScanners extends ast.parser.ScannersCommon { var i = 0 val len = name.length while (i < len) { - val d = digit2int(name(i), base) + val d = digit2int(name.charAt(i), base) if (d < 0) { syntaxError("malformed integer number") return 0 diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index e6499c05a6..86f9d38203 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -307,7 +307,7 @@ abstract class ClassfileParser { val start = starts(index) if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start) val name = getExternalName(in.getChar(start + 1)) - if (name(0) == ARRAY_TAG) { + if (name.charAt(0) == ARRAY_TAG) { c = sigToType(null, name) values(index) = c } else { @@ -667,16 +667,16 @@ abstract class ClassfileParser { var index = 0 val end = sig.length def accept(ch: Char) { - assert(sig(index) == ch, (sig(index), ch)) + assert(sig.charAt(index) == ch, (sig.charAt(index), ch)) index += 1 } def subName(isDelimiter: Char => Boolean): Name = { val start = index - while (!isDelimiter(sig(index))) { index += 1 } + while (!isDelimiter(sig.charAt(index))) { index += 1 } sig.subName(start, index) } def sig2type(tparams: immutable.Map[Name,Symbol], skiptvs: Boolean): Type = { - val tag = sig(index); index += 1 + val tag = sig.charAt(index); index += 1 tag match { case BYTE_TAG => definitions.ByteClass.tpe case CHAR_TAG => definitions.CharClass.tpe @@ -697,12 +697,12 @@ abstract class ClassfileParser { def processClassType(tp: Type): Type = tp match { case TypeRef(pre, classSym, args) => val existentials = new ListBuffer[Symbol]() - if (sig(index) == '<') { + if (sig.charAt(index) == '<') { accept('<') val xs = new ListBuffer[Type]() var i = 0 - while (sig(index) != '>') { - sig(index) match { + while (sig.charAt(index) != '>') { + sig.charAt(index) match { case variance @ ('+' | '-' | '*') => index += 1 val bounds = variance match { @@ -738,14 +738,14 @@ abstract class ClassfileParser { res } case tp => - assert(sig(index) != '<', tp) + assert(sig.charAt(index) != '<', tp) tp } val classSym = classNameToSymbol(subName(c => c == ';' || c == '<')) assert(!classSym.isOverloaded, classSym.alternatives) var tpe = processClassType(processInner(classSym.tpe)) - while (sig(index) == '.') { + while (sig.charAt(index) == '.') { accept('.') val name = subName(c => c == ';' || c == '<' || c == '.').toTypeName val clazz = tpe.member(name) @@ -754,7 +754,7 @@ abstract class ClassfileParser { accept(';') tpe case ARRAY_TAG => - while ('0' <= sig(index) && sig(index) <= '9') index += 1 + while ('0' <= sig.charAt(index) && sig.charAt(index) <= '9') index += 1 var elemtp = sig2type(tparams, skiptvs) // make unbounded Array[T] where T is a type variable into Array[T with Object] // (this is necessary because such arrays have a representation which is incompatible @@ -771,7 +771,7 @@ abstract class ClassfileParser { // we need a method symbol. given in line 486 by calling getType(methodSym, ..) assert(sym ne null, sig) val paramtypes = new ListBuffer[Type]() - while (sig(index) != ')') { + while (sig.charAt(index) != ')') { paramtypes += objToAny(sig2type(tparams, skiptvs)) } index += 1 @@ -791,9 +791,9 @@ abstract class ClassfileParser { def sig2typeBounds(tparams: immutable.Map[Name, Symbol], skiptvs: Boolean): Type = { val ts = new ListBuffer[Type] - while (sig(index) == ':') { + while (sig.charAt(index) == ':') { index += 1 - if (sig(index) != ':') // guard against empty class bound + if (sig.charAt(index) != ':') // guard against empty class bound ts += objToAny(sig2type(tparams, skiptvs)) } TypeBounds.upper(intersectionType(ts.toList, sym)) @@ -801,11 +801,11 @@ abstract class ClassfileParser { var tparams = classTParams val newTParams = new ListBuffer[Symbol]() - if (sig(index) == '<') { + if (sig.charAt(index) == '<') { assert(sym != null, sig) index += 1 val start = index - while (sig(index) != '>') { + while (sig.charAt(index) != '>') { val tpname = subName(':'.==).toTypeName val s = sym.newTypeParameter(tpname) tparams = tparams + (tpname -> s) @@ -813,7 +813,7 @@ abstract class ClassfileParser { newTParams += s } index = start - while (sig(index) != '>') { + while (sig.charAt(index) != '>') { val tpname = subName(':'.==).toTypeName val s = tparams(tpname) s.setInfo(sig2typeBounds(tparams, false)) diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index 95d0369707..7bd5f4caeb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -540,7 +540,7 @@ trait MethodSynthesis { val ValDef(mods, name, _, _) = tree val beans = beanAccessorsFromNames(tree) if (beans.nonEmpty) { - if (!name(0).isLetter) + if (!name.charAt(0).isLetter) BeanPropertyAnnotationFieldWithoutLetterError(tree) else if (mods.isPrivate) // avoids name clashes with private fields in traits BeanPropertyAnnotationPrivateFieldError(tree) diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala index 3c0848f77f..20da38fd63 100644 --- a/src/reflect/scala/reflect/internal/Names.scala +++ b/src/reflect/scala/reflect/internal/Names.scala @@ -145,7 +145,7 @@ trait Names extends api.Names with LowPriorityNames { * or Strings as Names. Give names the key functions the absence of which * make people want Strings all the time. */ - sealed abstract class Name(protected val index: Int, protected val len: Int) extends NameApi with Function1[Int, Char] { + sealed abstract class Name(protected val index: Int, protected val len: Int) extends NameApi { type ThisNameType >: Null <: Name protected[this] def thisName: ThisNameType @@ -226,7 +226,7 @@ trait Names extends api.Names with LowPriorityNames { } /** @return the i'th Char of this name */ - final def apply(i: Int): Char = chrs(index + i) + final def charAt(i: Int): Char = chrs(index + i) /** @return the index of first occurrence of char c in this name, length if not found */ final def pos(c: Char): Int = pos(c, 0) @@ -355,8 +355,8 @@ trait Names extends api.Names with LowPriorityNames { /** Some thoroughly self-explanatory convenience functions. They * assume that what they're being asked to do is known to be valid. */ - final def startChar: Char = apply(0) - final def endChar: Char = apply(len - 1) + final def startChar: Char = this charAt 0 + final def endChar: Char = this charAt len - 1 final def startsWith(char: Char): Boolean = len > 0 && startChar == char final def startsWith(name: String): Boolean = startsWith(newTermName(name)) final def endsWith(char: Char): Boolean = len > 0 && endChar == char @@ -380,7 +380,7 @@ trait Names extends api.Names with LowPriorityNames { val cs = new Array[Char](len) var i = 0 while (i < len) { - val ch = this(i) + val ch = charAt(i) cs(i) = if (ch == from) to else ch i += 1 } diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 51dd309a61..165e04863c 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -374,9 +374,9 @@ trait StdNames { */ def originalName(name: Name): Name = { var i = name.length - while (i >= 2 && !(name(i - 1) == '$' && name(i - 2) == '$')) i -= 1 + while (i >= 2 && !(name.charAt(i - 1) == '$' && name.charAt(i - 2) == '$')) i -= 1 if (i >= 2) { - while (i >= 3 && name(i - 3) == '$') i -= 1 + while (i >= 3 && name.charAt(i - 3) == '$') i -= 1 name.subName(i, name.length) } else name } @@ -455,10 +455,10 @@ trait StdNames { // Otherwise return the argument. def stripAnonNumberSuffix(name: Name): Name = { var pos = name.length - while (pos > 0 && name(pos - 1).isDigit) + while (pos > 0 && name.charAt(pos - 1).isDigit) pos -= 1 - if (pos <= 0 || pos == name.length || name(pos - 1) != '$') name + if (pos <= 0 || pos == name.length || name.charAt(pos - 1) != '$') name else name.subName(0, pos - 1) } diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 698d219634..745065b024 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -316,7 +316,7 @@ abstract class TreeInfo { /** Is name a variable name? */ def isVariableName(name: Name): Boolean = { - val first = name(0) + val first = name.startChar ((first.isLower && first.isLetter) || first == '_') && !reserved(name) } -- cgit v1.2.3