@@ -7,7 +7,7 @@ import Contexts._, Symbols._, Types._, Names._, StdNames._, NameOps._, Scopes._,
7
7
import SymDenotations ._ , unpickleScala2 .Scala2Unpickler ._ , Constants ._ , Annotations ._ , util .Positions ._
8
8
import NameKinds .{ModuleClassName , DefaultGetterName }
9
9
import ast .tpd ._
10
- import java .io .{ File , IOException }
10
+ import java .io .{ ByteArrayInputStream , DataInputStream , File , IOException }
11
11
import java .lang .Integer .toHexString
12
12
import scala .collection .{ mutable , immutable }
13
13
import scala .collection .mutable .{ ListBuffer , ArrayBuffer }
@@ -194,13 +194,21 @@ class ClassfileParser(
194
194
val name = pool.getName(in.nextChar)
195
195
val isConstructor = name eq nme.CONSTRUCTOR
196
196
197
- /** Strip leading outer param from constructor.
198
- * Todo: Also strip trailing access tag for private inner constructors?
197
+ /** Strip leading outer param from constructor and trailing access tag for
198
+ * private inner constructors.
199
199
*/
200
- def stripOuterParamFromConstructor () = innerClasses.get(currentClassName) match {
200
+ def normalizeConstructorParams () = innerClasses.get(currentClassName) match {
201
201
case Some (entry) if ! isStatic(entry.jflags) =>
202
202
val mt @ MethodTpe (paramNames, paramTypes, resultType) = denot.info
203
- denot.info = mt.derivedLambdaType(paramNames.tail, paramTypes.tail, resultType)
203
+ var normalizedParamNames = paramNames.tail
204
+ var normalizedParamTypes = paramTypes.tail
205
+ if ((jflags & JAVA_ACC_SYNTHETIC ) != 0 ) {
206
+ // SI-7455 strip trailing dummy argument ("access constructor tag") from synthetic constructors which
207
+ // are added when an inner class needs to access a private constructor.
208
+ normalizedParamNames = paramNames.dropRight(1 )
209
+ normalizedParamTypes = paramTypes.dropRight(1 )
210
+ }
211
+ denot.info = mt.derivedLambdaType(normalizedParamNames, normalizedParamTypes, resultType)
204
212
case _ =>
205
213
}
206
214
@@ -216,7 +224,7 @@ class ClassfileParser(
216
224
217
225
denot.info = pool.getType(in.nextChar)
218
226
if (isEnum) denot.info = ConstantType (Constant (sym))
219
- if (isConstructor) stripOuterParamFromConstructor ()
227
+ if (isConstructor) normalizeConstructorParams ()
220
228
setPrivateWithin(denot, jflags)
221
229
denot.info = translateTempPoly(parseAttributes(sym, denot.info))
222
230
if (isConstructor) normalizeConstructorInfo()
@@ -227,8 +235,12 @@ class ClassfileParser(
227
235
// seal java enums
228
236
if (isEnum) {
229
237
val enumClass = sym.owner.linkedClass
230
- if (! (enumClass is Flags .Sealed )) enumClass.setFlag(Flags .AbstractSealed )
231
- enumClass.addAnnotation(Annotation .makeChild(sym))
238
+ if (! enumClass.exists)
239
+ ctx.warning(s " no linked class for java enum $sym in ${sym.owner}. A referencing class file might be missing an InnerClasses entry. " )
240
+ else {
241
+ if (! (enumClass is Flags .Sealed )) enumClass.setFlag(Flags .AbstractSealed )
242
+ enumClass.addAnnotation(Annotation .makeChild(sym))
243
+ }
232
244
}
233
245
} finally {
234
246
in.bp = oldbp
@@ -923,12 +935,16 @@ class ClassfileParser(
923
935
case null =>
924
936
val start = starts(index)
925
937
if (in.buf(start).toInt != CONSTANT_UTF8 ) errorBadTag(start)
926
- val name = termName(in.buf, start + 3 , in.getChar(start + 1 ))
938
+ val len = in.getChar(start + 1 ).toInt
939
+ val name = termName(fromMUTF8(in.buf, start + 1 , len + 2 ))
927
940
values(index) = name
928
941
name
929
942
}
930
943
}
931
944
945
+ private def fromMUTF8 (bytes : Array [Byte ], offset : Int , len : Int ): String =
946
+ new DataInputStream (new ByteArrayInputStream (bytes, offset, len)).readUTF
947
+
932
948
/** Return the name found at given index in the constant pool, with '/' replaced by '.'. */
933
949
def getExternalName (index : Int ): SimpleTermName = {
934
950
if (index <= 0 || len <= index)
0 commit comments