Skip to content

Commit 4f6d6f0

Browse files
authored
Merge pull request #11515 from Kordyjan/paramnames
Output names of function parameters
2 parents 55da939 + e63752b commit 4f6d6f0

File tree

10 files changed

+72
-11
lines changed

10 files changed

+72
-11
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,14 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
335335
emitAssocs(av, assocs, BCodeHelpers.this)(this)
336336
}
337337

338+
/*
339+
* must-single-thread
340+
*/
341+
def emitParamNames(jmethod: asm.MethodVisitor, params: List[Symbol]) =
342+
for param <- params do
343+
var access = asm.Opcodes.ACC_FINAL
344+
jmethod.visitParameter(param.name.mangledString, access)
345+
338346
/*
339347
* must-single-thread
340348
*/

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
615615
/*
616616
* must-single-thread
617617
*/
618-
def initJMethod(flags: Int, paramAnnotations: List[List[Annotation]]): Unit = {
618+
def initJMethod(flags: Int, params: List[Symbol]): Unit = {
619619

620620
val jgensig = getGenericSignature(methSymbol, claszSymbol)
621621
val (excs, others) = methSymbol.annotations.partition(_.symbol eq defn.ThrowsAnnot)
@@ -637,7 +637,8 @@ trait BCodeSkelBuilder extends BCodeHelpers {
637637
// TODO param names: (m.params map (p => javaName(p.sym)))
638638

639639
emitAnnotations(mnode, others)
640-
emitParamAnnotations(mnode, paramAnnotations)
640+
emitParamNames(mnode, params)
641+
emitParamAnnotations(mnode, params.map(_.annotations))
641642

642643
} // end of method initJMethod
643644

@@ -749,7 +750,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
749750
.addFlagIf(isNative, asm.Opcodes.ACC_NATIVE) // native methods of objects are generated in mirror classes
750751

751752
// TODO needed? for(ann <- m.symbol.annotations) { ann.symbol.initialize }
752-
initJMethod(flags, params.map(p => p.symbol.annotations))
753+
initJMethod(flags, params.map(_.symbol))
753754

754755

755756
if (!isAbstractMethod && !isNative) {

compiler/src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ object StdNames {
257257
final val DeprecatedATTR: N = "Deprecated"
258258
final val ExceptionsATTR: N = "Exceptions"
259259
final val InnerClassesATTR: N = "InnerClasses"
260+
final val MethodParametersATTR: N = "MethodParameters"
260261
final val LineNumberTableATTR: N = "LineNumberTable"
261262
final val LocalVariableTableATTR: N = "LocalVariableTable"
262263
final val RuntimeVisibleAnnotationATTR: N = "RuntimeVisibleAnnotations" // RetentionPolicy.RUNTIME

compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ class ClassfileParser(
657657
var constant: Constant = null
658658
var exceptions: List[NameOrString] = Nil
659659
var annotations: List[Annotation] = Nil
660+
var namedParams: Map[Int, TermName] = Map.empty
660661
def complete(tp: Type, isVarargs: Boolean = false)(using Context): Type = {
661662
val updatedType =
662663
if sig == null then tp
@@ -680,7 +681,14 @@ class ClassfileParser(
680681
sym.addAnnotation(ThrowsAnnotation(cls.asClass))
681682
}
682683

683-
cook.apply(newType)
684+
def fillInParamNames(t: Type): Type = t match
685+
case mt @ MethodType(oldp) if namedParams.nonEmpty =>
686+
mt.derivedLambdaType(List.tabulate(oldp.size)(n => namedParams.getOrElse(n, oldp(n))))
687+
case pt: PolyType if namedParams.nonEmpty =>
688+
pt.derivedLambdaType(pt.paramNames, pt.paramInfos, fillInParamNames(pt.resultType))
689+
case _ => t
690+
691+
cook.apply(fillInParamNames(newType))
684692
}
685693
}
686694

@@ -714,6 +722,14 @@ class ClassfileParser(
714722
if (c ne null) res.constant = c
715723
else report.warning(s"Invalid constant in attribute of ${sym.showLocated} while parsing ${classfile}")
716724

725+
case tpnme.MethodParametersATTR =>
726+
val paramCount = in.nextByte
727+
for i <- 0 until paramCount do
728+
val name = pool.getName(in.nextChar)
729+
val flags = in.nextChar
730+
if (flags & JAVA_ACC_SYNTHETIC) == 0 then
731+
res.namedParams += (i -> name.name)
732+
717733
case tpnme.AnnotationDefaultATTR =>
718734
sym.addAnnotation(Annotation(defn.AnnotationDefaultAnnot, Nil))
719735

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class CompilationTests {
4242
compileFilesInDir("tests/pos-custom-args/erased", defaultOptions.and("-Yerased-terms")),
4343
compileFilesInDir("tests/pos", defaultOptions.and("-Ycheck-init")),
4444
compileFilesInDir("tests/pos-deep-subtype", allowDeepSubtypes),
45+
compileDir("tests/pos-special/java-param-names", defaultOptions.withJavacOnlyOptions("-parameters")),
4546
compileFile(
4647
// succeeds despite -Xfatal-warnings because of -nowarn
4748
"tests/neg-custom-args/fatal-warnings/xfatalWarnings.scala",

compiler/test/dotty/tools/vulpix/TestFlags.scala

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,23 @@ import java.io.{File => JFile}
55
final case class TestFlags(
66
defaultClassPath: String,
77
runClassPath: String, // class path that is used when running `run` tests (not compiling)
8-
options: Array[String]) {
8+
options: Array[String],
9+
javacOptions: Array[String]) {
910

1011
def and(flags: String*): TestFlags =
11-
TestFlags(defaultClassPath, runClassPath, options ++ flags)
12+
TestFlags(defaultClassPath, runClassPath, options ++ flags, javacOptions)
1213

1314
def without(flags: String*): TestFlags =
14-
TestFlags(defaultClassPath, runClassPath, options diff flags)
15+
TestFlags(defaultClassPath, runClassPath, options diff flags, javacOptions)
1516

1617
def withClasspath(classPath: String): TestFlags =
17-
TestFlags(s"$defaultClassPath${JFile.pathSeparator}$classPath", runClassPath, options)
18+
TestFlags(s"$defaultClassPath${JFile.pathSeparator}$classPath", runClassPath, options, javacOptions)
1819

1920
def withRunClasspath(classPath: String): TestFlags =
20-
TestFlags(defaultClassPath, s"$runClassPath${JFile.pathSeparator}$classPath", options)
21+
TestFlags(defaultClassPath, s"$runClassPath${JFile.pathSeparator}$classPath", options, javacOptions)
22+
23+
def withJavacOnlyOptions(flags: String*): TestFlags =
24+
TestFlags(defaultClassPath, runClassPath, options, javacOptions ++ flags)
2125

2226
def all: Array[String] = Array("-classpath", defaultClassPath) ++ options
2327

@@ -43,10 +47,10 @@ final case class TestFlags(
4347
val flags = all
4448
val cp = flags.dropWhile(_ != "-classpath").take(2)
4549
val output = flags.dropWhile(_ != "-d").take(2)
46-
cp ++ output
50+
cp ++ output ++ javacOptions
4751
}
4852
}
4953

5054
object TestFlags {
51-
def apply(classPath: String, flags: Array[String]): TestFlags = TestFlags(classPath, classPath, flags)
55+
def apply(classPath: String, flags: Array[String]): TestFlags = TestFlags(classPath, classPath, flags, Array.empty)
5256
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class Foo_1 {
2+
public Foo_1(int number, String text) {}
3+
public void bar(String barText, int barNumber) {}
4+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@main def Test =
2+
new Foo_1(number = 6, text = "param-name").bar(barNumber = 8, barText = "some-method")

tests/run/i11486/Old_1.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
case class TestedOld(foo: Int, bar: String, baz: Double):
2+
def target(abc: TestedOld, efg: TestedOld) = ()
3+
def symbolic(`def`: Int, *** : Int, `unary_!`: Int) = ()

tests/run/i11486/Test_2.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import java.lang.reflect.Executable
2+
3+
case class Tested(foo: Int, bar: String, baz: Double):
4+
def target(abc: Tested, efg: Tested) = ()
5+
def symbolic(`def`: Int, *** : Int, `unary_!`: Int) = ()
6+
7+
def run(cls: Class[_]) =
8+
extension(m: Executable) def parameters: List[String] = m.getParameters.toList.map(_.getName)
9+
10+
val ctorParams = cls.getConstructors.head.parameters
11+
assert(ctorParams == List("foo", "bar", "baz"))
12+
13+
val targetParams = cls.getMethods.toList.find(_.getName == "target").get.parameters
14+
assert(targetParams == List("abc", "efg"))
15+
16+
val symbolicParams = cls.getMethods.toList.find(_.getName == "symbolic").get.parameters
17+
assert(symbolicParams == List("def", "$times$times$times", "unary_$bang"))
18+
19+
@main def Test =
20+
run(classOf[TestedOld])
21+
run(classOf[Tested])

0 commit comments

Comments
 (0)