diff options
Diffstat (limited to 'test')
39 files changed, 733 insertions, 49 deletions
diff --git a/test/files/neg/case-collision2.flags b/test/files/neg/case-collision2.flags index 5bfa9da5c5..bea46902c9 100644 --- a/test/files/neg/case-collision2.flags +++ b/test/files/neg/case-collision2.flags @@ -1 +1 @@ --Ynooptimize -Ybackend:GenBCode -Xfatal-warnings +-Ybackend:GenBCode -Xfatal-warnings diff --git a/test/files/neg/inlineMaxSize.check b/test/files/neg/inlineMaxSize.check new file mode 100644 index 0000000000..d218a8b6e2 --- /dev/null +++ b/test/files/neg/inlineMaxSize.check @@ -0,0 +1,9 @@ +inlineMaxSize.scala:7: warning: C::i()I is annotated @inline but could not be inlined: +The size of the callsite method C::j()I +would exceed the JVM method size limit after inlining C::i()I. + + @inline final def j = i + i + ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found +one error found diff --git a/test/files/neg/inlineMaxSize.flags b/test/files/neg/inlineMaxSize.flags new file mode 100644 index 0000000000..9c6b811622 --- /dev/null +++ b/test/files/neg/inlineMaxSize.flags @@ -0,0 +1 @@ +-Ybackend:GenBCode -Ydelambdafy:method -Yopt:l:classpath -Yopt-warnings -Xfatal-warnings
\ No newline at end of file diff --git a/test/files/neg/inlineMaxSize.scala b/test/files/neg/inlineMaxSize.scala new file mode 100644 index 0000000000..16dc0d9538 --- /dev/null +++ b/test/files/neg/inlineMaxSize.scala @@ -0,0 +1,8 @@ +// not a JUnit test because of https://github.com/scala-opt/scala/issues/23 +class C { + @inline final def f = 0 + @inline final def g = f + f + f + f + f + f + f + f + f + f + @inline final def h = g + g + g + g + g + g + g + g + g + g + @inline final def i = h + h + h + h + h + h + h + h + h + h + @inline final def j = i + i +} diff --git a/test/files/neg/t0899.check b/test/files/neg/t0899.check index 8b71be8e0c..28cb06ae5a 100644 --- a/test/files/neg/t0899.check +++ b/test/files/neg/t0899.check @@ -1,10 +1,10 @@ -t0899.scala:9: error: super may be not be used on value o +t0899.scala:9: error: super may not be used on value o override val o = "Ha! " + super.o ^ -t0899.scala:11: error: super may be not be used on variable v +t0899.scala:11: error: super may not be used on variable v super.v = "aa" ^ -t0899.scala:12: error: super may be not be used on variable v +t0899.scala:12: error: super may not be used on variable v println(super.v) ^ three errors found diff --git a/test/files/neg/t562.check b/test/files/neg/t562.check index 8c3823642a..95be075af1 100644 --- a/test/files/neg/t562.check +++ b/test/files/neg/t562.check @@ -1,4 +1,4 @@ -t562.scala:10: error: super may be not be used on value y +t562.scala:10: error: super may not be used on value y override val y = super.y; ^ one error found diff --git a/test/files/pos/t3368.flags b/test/files/pos/t3368.flags new file mode 100644 index 0000000000..cb20509902 --- /dev/null +++ b/test/files/pos/t3368.flags @@ -0,0 +1 @@ +-Ystop-after:parser diff --git a/test/files/pos/t3368.scala b/test/files/pos/t3368.scala new file mode 100644 index 0000000000..c8e861a899 --- /dev/null +++ b/test/files/pos/t3368.scala @@ -0,0 +1,5 @@ + +trait X { + // error: in XML literal: name expected, but char '!' cannot start a name + def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]> +} diff --git a/test/files/pos/t8359-closelim-crash.flags b/test/files/pos/t8359-closelim-crash.flags new file mode 100644 index 0000000000..49d036a887 --- /dev/null +++ b/test/files/pos/t8359-closelim-crash.flags @@ -0,0 +1 @@ +-optimize diff --git a/test/files/pos/t8359-closelim-crash.scala b/test/files/pos/t8359-closelim-crash.scala new file mode 100644 index 0000000000..1413694d10 --- /dev/null +++ b/test/files/pos/t8359-closelim-crash.scala @@ -0,0 +1,23 @@ +package test + +// This is a minimization of code that crashed the compiler during bootstrapping +// in the first iteration of https://github.com/scala/scala/pull/4373, the PR +// that adjusted the order of free and declared params in LambdaLift. + +// Was: +// java.lang.AssertionError: assertion failed: +// Record Record(<$anon: Function1>,Map(value a$1 -> Deref(LocalVar(value b)))) does not contain a field value b$1 +// at scala.tools.nsc.Global.assert(Global.scala:262) +// at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:113) +// at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:122) +// at scala.tools.nsc.backend.opt.ClosureElimination$ClosureElim$$anonfun$analyzeMethod$1$$anonfun$apply$2.replaceFieldAccess$1(ClosureElimination.scala:124) +class Typer { + def bar(a: Boolean, b: Boolean): Unit = { + @inline + def baz(): Unit = { + ((_: Any) => (Typer.this, a, b)).apply("") + } + ((_: Any) => baz()).apply("") + } +} + diff --git a/test/files/pos/t9239/Declaration.scala b/test/files/pos/t9239/Declaration.scala new file mode 100644 index 0000000000..452dcc1e77 --- /dev/null +++ b/test/files/pos/t9239/Declaration.scala @@ -0,0 +1,3 @@ +class Foo[A] +trait Bar[A] extends Foo[A] +class Baz[A] extends Bar[A] diff --git a/test/files/pos/t9239/Usage.java b/test/files/pos/t9239/Usage.java new file mode 100644 index 0000000000..d1e3fb0c3e --- /dev/null +++ b/test/files/pos/t9239/Usage.java @@ -0,0 +1,15 @@ +/** + * Used to fail with: + * + * Usage.java:5: error: incompatible types: Baz<String> cannot be converted to Foo<String> + * foo(f); + * ^ + */ +public class Usage { + public Usage() { + Baz<String> f = null; + foo(f); + } + + public void foo(Foo<String> f) { }; +} diff --git a/test/files/run/t3368.check b/test/files/run/t3368.check new file mode 100644 index 0000000000..1d9dd677f6 --- /dev/null +++ b/test/files/run/t3368.check @@ -0,0 +1,46 @@ +[[syntax trees at end of parser]] // newSource1.scala +package <empty> { + abstract trait X extends scala.AnyRef { + def $init$() = { + () + }; + def x = { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye")); + $buf.$amp$plus(new _root_.scala.xml.PCData("red & black")); + $buf + } + }; + abstract trait Y extends scala.AnyRef { + def $init$() = { + () + }; + def y = { + { + new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({ + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("starthi & bye")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("world")); + $buf.$amp$plus({ + { + new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true) + } + }); + $buf.$amp$plus(new _root_.scala.xml.Text("stuffred & black")); + $buf + }: _*)) + } + } + } +} + diff --git a/test/files/run/t3368.scala b/test/files/run/t3368.scala new file mode 100644 index 0000000000..15acba5099 --- /dev/null +++ b/test/files/run/t3368.scala @@ -0,0 +1,18 @@ + +import scala.tools.partest.ParserTest + + +object Test extends ParserTest { + + override def code = """ + trait X { + // error: in XML literal: name expected, but char '!' cannot start a name + def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]> + } + trait Y { + def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a> + } + """ + + override def extraSettings = s"${super.extraSettings} -Xxml:coalescing" +} diff --git a/test/files/run/t5699.scala b/test/files/run/t5699.scala index ec3b1d26b4..409bcd250c 100755 --- a/test/files/run/t5699.scala +++ b/test/files/run/t5699.scala @@ -1,21 +1,13 @@ -import scala.tools.partest.DirectTest +import scala.tools.partest.ParserTest import scala.reflect.internal.util.BatchSourceFile -object Test extends DirectTest { +object Test extends ParserTest { // Java code override def code = """ |public @interface MyAnnotation { String value(); } """.stripMargin - override def extraSettings: String = "-usejavacp -Ystop-after:typer -Xprint:parser" - - override def show(): Unit = { - // redirect err to out, for logging - val prevErr = System.err - System.setErr(System.out) - compile() - System.setErr(prevErr) - } + override def extraSettings: String = "-usejavacp -Ystop-after:namer -Xprint:parser" override def newSources(sourceCodes: String*) = { assert(sourceCodes.size == 1) diff --git a/test/files/run/t7407.flags b/test/files/run/t7407.flags index be4ef0798a..ffc65f4b81 100644 --- a/test/files/run/t7407.flags +++ b/test/files/run/t7407.flags @@ -1 +1 @@ --Ynooptimise -Yopt:l:none -Ybackend:GenBCode +-Yopt:l:none -Ybackend:GenBCode diff --git a/test/files/run/t7407b.flags b/test/files/run/t7407b.flags index c8547a27dc..c30091d3de 100644 --- a/test/files/run/t7407b.flags +++ b/test/files/run/t7407b.flags @@ -1 +1 @@ --Ynooptimise -Ybackend:GenBCode +-Ybackend:GenBCode diff --git a/test/files/run/t7741a/GroovyInterface$1Dump.java b/test/files/run/t7741a/GroovyInterface$1Dump.java new file mode 100644 index 0000000000..0c0eab3f1b --- /dev/null +++ b/test/files/run/t7741a/GroovyInterface$1Dump.java @@ -0,0 +1,222 @@ +import java.util.*; +import scala.tools.asm.*; + +// generated with +// git clone alewando/scala_groovy_interop +// SCALA_HOME=... GROOVY_HOME=... ant +// cd /code/scala2 +// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1' +// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1' +public class GroovyInterface$1Dump implements Opcodes { + + public static byte[] dump () throws Exception { + + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(V1_5, ACC_SUPER + ACC_SYNTHETIC, "GroovyInterface$1", null, "java/lang/Object", new String[] {}); + + cw.visitInnerClass("GroovyInterface$1", "GroovyInterface", "1", ACC_SYNTHETIC); + + { + fv = cw.visitField(ACC_STATIC + ACC_SYNTHETIC, "$class$GroovyInterface", "Ljava/lang/Class;", null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$staticClassInfo", "Lorg/codehaus/groovy/reflection/ClassInfo;", null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(ACC_PUBLIC + ACC_STATIC + ACC_TRANSIENT + ACC_SYNTHETIC, "__$stMC", "Z", null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(ACC_PRIVATE + ACC_TRANSIENT + ACC_SYNTHETIC, "metaClass", "Lgroovy/lang/MetaClass;", null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$callSiteArray", "Ljava/lang/ref/SoftReference;", null, null); + fv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); + mv.visitMethodInsn(INVOKESTATIC, "GroovyInterface$1", "$getCallSiteArray", "()[Lorg/codehaus/groovy/runtime/callsite/CallSite;", false); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitVarInsn(ASTORE, 2); + mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(SWAP); + mv.visitFieldInsn(PUTFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;"); + mv.visitVarInsn(ALOAD, 2); + mv.visitInsn(POP); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PROTECTED + ACC_SYNTHETIC, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); + mv.visitLdcInsn(Type.getType("LGroovyInterface$1;")); + Label l0 = new Label(); + mv.visitJumpInsn(IF_ACMPEQ, l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/ScriptBytecodeAdapter", "initMetaClass", "(Ljava/lang/Object;)Lgroovy/lang/MetaClass;", false); + mv.visitInsn(ARETURN); + mv.visitLabel(l0); + mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$staticClassInfo", "Lorg/codehaus/groovy/reflection/ClassInfo;"); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + Label l1 = new Label(); + mv.visitJumpInsn(IFNONNULL, l1); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false); + mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/reflection/ClassInfo", "getClassInfo", "(Ljava/lang/Class;)Lorg/codehaus/groovy/reflection/ClassInfo;", false); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 1); + mv.visitFieldInsn(PUTSTATIC, "GroovyInterface$1", "$staticClassInfo", "Lorg/codehaus/groovy/reflection/ClassInfo;"); + mv.visitLabel(l1); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEVIRTUAL, "org/codehaus/groovy/reflection/ClassInfo", "getMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitInsn(ARETURN); + mv.visitMaxs(2, 2); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "getMetaClass", "()Lgroovy/lang/MetaClass;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;"); + mv.visitInsn(DUP); + Label l0 = new Label(); + mv.visitJumpInsn(IFNULL, l0); + mv.visitInsn(ARETURN); + mv.visitLabel(l0); + mv.visitInsn(POP); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitFieldInsn(PUTFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;"); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;"); + mv.visitInsn(ARETURN); + mv.visitMaxs(2, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "setMetaClass", "(Lgroovy/lang/MetaClass;)V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitFieldInsn(PUTFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;"); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 2); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "invokeMethod", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "getMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "invokeMethod", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", true); + mv.visitInsn(ARETURN); + mv.visitMaxs(4, 3); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "getProperty", "(Ljava/lang/String;)Ljava/lang/Object;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "getMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "getProperty", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", true); + mv.visitInsn(ARETURN); + mv.visitMaxs(3, 2); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "setProperty", "(Ljava/lang/String;Ljava/lang/Object;)V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "getMetaClass", "()Lgroovy/lang/MetaClass;", false); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "setProperty", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", true); + mv.visitInsn(RETURN); + mv.visitMaxs(4, 3); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); + mv.visitCode(); + mv.visitLdcInsn(Type.getType("LGroovyInterface;")); + mv.visitVarInsn(ASTORE, 0); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(PUTSTATIC, "GroovyInterface$1", "$class$GroovyInterface", "Ljava/lang/Class;"); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(POP); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$createCallSiteArray", "()Lorg/codehaus/groovy/runtime/callsite/CallSiteArray;", null, null); + mv.visitCode(); + mv.visitLdcInsn(new Integer(0)); + mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); + mv.visitVarInsn(ASTORE, 0); + mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/callsite/CallSiteArray"); + mv.visitInsn(DUP); + mv.visitLdcInsn(Type.getType("LGroovyInterface$1;")); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/callsite/CallSiteArray", "<init>", "(Ljava/lang/Class;[Ljava/lang/String;)V", false); + mv.visitInsn(ARETURN); + mv.visitMaxs(4, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC + ACC_SYNTHETIC, "$getCallSiteArray", "()[Lorg/codehaus/groovy/runtime/callsite/CallSite;", null, null); + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$callSiteArray", "Ljava/lang/ref/SoftReference;"); + Label l0 = new Label(); + mv.visitJumpInsn(IFNULL, l0); + mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$callSiteArray", "Ljava/lang/ref/SoftReference;"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ref/SoftReference", "get", "()Ljava/lang/Object;", false); + mv.visitTypeInsn(CHECKCAST, "org/codehaus/groovy/runtime/callsite/CallSiteArray"); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 0); + Label l1 = new Label(); + mv.visitJumpInsn(IFNONNULL, l1); + mv.visitLabel(l0); + mv.visitMethodInsn(INVOKESTATIC, "GroovyInterface$1", "$createCallSiteArray", "()Lorg/codehaus/groovy/runtime/callsite/CallSiteArray;", false); + mv.visitVarInsn(ASTORE, 0); + mv.visitTypeInsn(NEW, "java/lang/ref/SoftReference"); + mv.visitInsn(DUP); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/ref/SoftReference", "<init>", "(Ljava/lang/Object;)V", false); + mv.visitFieldInsn(PUTSTATIC, "GroovyInterface$1", "$callSiteArray", "Ljava/lang/ref/SoftReference;"); + mv.visitLabel(l1); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, "org/codehaus/groovy/runtime/callsite/CallSiteArray", "array", "[Lorg/codehaus/groovy/runtime/callsite/CallSite;"); + mv.visitInsn(ARETURN); + mv.visitMaxs(3, 1); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } +} diff --git a/test/files/run/t7741a/GroovyInterfaceDump.java b/test/files/run/t7741a/GroovyInterfaceDump.java new file mode 100644 index 0000000000..87c09e272f --- /dev/null +++ b/test/files/run/t7741a/GroovyInterfaceDump.java @@ -0,0 +1,51 @@ +import java.util.*; +import scala.tools.asm.*; + +// generated with +// git clone alewando/scala_groovy_interop +// SCALA_HOME=... GROOVY_HOME=... ant +// cd /code/scala2 +// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1' +// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1' +public class GroovyInterfaceDump implements Opcodes { + + public static byte[] dump () throws Exception { + + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(V1_5, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, "GroovyInterface", null, "java/lang/Object", null); + + cw.visitInnerClass("GroovyInterface$1", "GroovyInterface", "1", ACC_SYNTHETIC); + + cw.visitInnerClass("GroovyInterface$__clinit__closure1", null, null, 0); + + { + fv = cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "closure", "Ljava/lang/Object;", null, null); + fv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); + mv.visitCode(); + mv.visitTypeInsn(NEW, "GroovyInterface$__clinit__closure1"); + mv.visitInsn(DUP); + mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$class$GroovyInterface", "Ljava/lang/Class;"); + mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$class$GroovyInterface", "Ljava/lang/Class;"); + mv.visitMethodInsn(INVOKESPECIAL, "GroovyInterface$__clinit__closure1", "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V", false); + mv.visitVarInsn(ASTORE, 0); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(PUTSTATIC, "GroovyInterface", "closure", "Ljava/lang/Object;"); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(POP); + mv.visitInsn(RETURN); + mv.visitMaxs(4, 1); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } +} + diff --git a/test/files/run/t7741a/Test.scala b/test/files/run/t7741a/Test.scala new file mode 100644 index 0000000000..a75cb6c9eb --- /dev/null +++ b/test/files/run/t7741a/Test.scala @@ -0,0 +1,47 @@ +import java.io.{ByteArrayInputStream, FileOutputStream, BufferedOutputStream} +import java.util + +import java.io.File + +import scala.tools.partest.DirectTest + +object Test extends DirectTest { + + def code = "" + + override def show(): Unit = { + + val class1: Array[Byte] = GroovyInterfaceDump.dump() + val class2: Array[Byte] = GroovyInterface$1Dump.dump() + def writeFile(contents: Array[Byte], f: java.io.File): Unit = { + val out = new BufferedOutputStream(new FileOutputStream(f)) + try { + out.write(contents) + } finally out.close() + } + + val outdir = testOutput.jfile + + // interface GroovyInterface { + // + // // This is the line that causes scalac to choke. + // // It results in a GroovyInterface$1 class, which is a non-static inner class but it's constructor does not + // // include the implicit parameter that is the immediate enclosing instance. + // // See http://jira.codehaus.org/browse/GROOVY-7312 + // // + // // Scalac error: + // // [scalac] error: error while loading 1, class file '..../scala_groovy_interop/classes/com/example/groovy/GroovyInterface$1.class' is broken + // // [scalac] (class java.util.NoSuchElementException/head of empty list) + // final static def closure = { x -> "banana" } + // + // } + writeFile(GroovyInterfaceDump.dump(), new File(outdir, "GroovyInterface.class")) + writeFile(GroovyInterface$1Dump.dump(), new File(outdir, "GroovyInterface$1.class")) + compileCode("object Test { def foo(g: GroovyInterface) = g.toString }") + } + + def compileCode(code: String) = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code) + } +} diff --git a/test/files/run/t7741b.check b/test/files/run/t7741b.check new file mode 100644 index 0000000000..a19e54aa3a --- /dev/null +++ b/test/files/run/t7741b.check @@ -0,0 +1,3 @@ +1. Don't refer to Inner +2. Refering to Inner +pos: NoPosition Class file for HasInner$Inner not found ERROR diff --git a/test/files/run/t7741b/HasInner.java b/test/files/run/t7741b/HasInner.java new file mode 100644 index 0000000000..a1d0d0d81a --- /dev/null +++ b/test/files/run/t7741b/HasInner.java @@ -0,0 +1,3 @@ +class HasInner { + class Inner {} +} diff --git a/test/files/run/t7741b/Test.scala b/test/files/run/t7741b/Test.scala new file mode 100644 index 0000000000..569ae6b679 --- /dev/null +++ b/test/files/run/t7741b/Test.scala @@ -0,0 +1,29 @@ +import java.io.File + +import scala.tools.partest.StoreReporterDirectTest + +object Test extends StoreReporterDirectTest { + + def code = "" + + override def show(): Unit = { + deleteClass("HasInner$Inner") + println("1. Don't refer to Inner") + compileCode("class Test { def test(x: HasInner) = x }") + assert(filteredInfos.isEmpty, filteredInfos) + println("2. Refering to Inner") + compileCode("class Test { def test(x: HasInner#Inner) = x }") + println(filteredInfos.mkString("\n")) + } + + def deleteClass(name: String) { + val classFile = new File(testOutput.path, name + ".class") + assert(classFile.exists) + assert(classFile.delete()) + } + + def compileCode(code: String) = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code) + } +} diff --git a/test/files/run/t8845.flags b/test/files/run/t8845.flags index aada25f80d..c30091d3de 100644 --- a/test/files/run/t8845.flags +++ b/test/files/run/t8845.flags @@ -1 +1 @@ --Ybackend:GenBCode -Ynooptimize +-Ybackend:GenBCode diff --git a/test/files/run/t8925.flags b/test/files/run/t8925.flags index be4ef0798a..ffc65f4b81 100644 --- a/test/files/run/t8925.flags +++ b/test/files/run/t8925.flags @@ -1 +1 @@ --Ynooptimise -Yopt:l:none -Ybackend:GenBCode +-Yopt:l:none -Ybackend:GenBCode diff --git a/test/files/run/t9252.check b/test/files/run/t9252.check new file mode 100644 index 0000000000..b00d748f7f --- /dev/null +++ b/test/files/run/t9252.check @@ -0,0 +1 @@ +class [Lscala.runtime.BoxedUnit; diff --git a/test/files/run/t9252.scala b/test/files/run/t9252.scala new file mode 100644 index 0000000000..da698948e1 --- /dev/null +++ b/test/files/run/t9252.scala @@ -0,0 +1,5 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + println(rootMirror.runtimeClass(typeOf[Array[Unit]])) +}
\ No newline at end of file diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala index 5d5215d887..d0ffd06b01 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala @@ -8,7 +8,6 @@ import scala.reflect.io.VirtualDirectory import scala.tools.asm.Opcodes import scala.tools.asm.tree.{ClassNode, MethodNode} import scala.tools.cmd.CommandLineParser -import scala.tools.nsc.backend.jvm.opt.LocalOpt import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.reporters.StoreReporter import scala.tools.nsc.settings.MutableSettings @@ -157,12 +156,6 @@ object CodeGenTools { assertTrue(h.start == insVec(startIndex) && h.end == insVec(endIndex) && h.handler == insVec(handlerIndex)) } - val localOpt = { - val settings = new MutableSettings(msg => throw new IllegalArgumentException(msg)) - settings.processArguments(List("-Yopt:l:method"), processAll = true) - new LocalOpt(settings) - } - import scala.language.implicitConversions implicit def aliveInstruction(ins: Instruction): (Instruction, Boolean) = (ins, true) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala index 7b0504fec0..cb01f3d164 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala @@ -40,7 +40,7 @@ class EmptyExceptionHandlersTest extends ClearAfterClass { Op(RETURN) ) assertTrue(convertMethod(asmMethod).handlers.length == 1) - localOpt.removeEmptyExceptionHandlers(asmMethod) + LocalOptImpls.removeEmptyExceptionHandlers(asmMethod) assertTrue(convertMethod(asmMethod).handlers.isEmpty) } @@ -61,7 +61,7 @@ class EmptyExceptionHandlersTest extends ClearAfterClass { Op(RETURN) ) assertTrue(convertMethod(asmMethod).handlers.length == 1) - localOpt.removeEmptyExceptionHandlers(asmMethod) + LocalOptImpls.removeEmptyExceptionHandlers(asmMethod) assertTrue(convertMethod(asmMethod).handlers.isEmpty) } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala index 8c0168826e..7283e20745 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala @@ -42,14 +42,14 @@ class EmptyLabelsAndLineNumbersTest { ) val method = genMethod()(ops.map(_._1): _*) - assertTrue(localOpt.removeEmptyLineNumbers(method)) + assertTrue(LocalOptImpls.removeEmptyLineNumbers(method)) assertSameCode(instructionsFromMethod(method), ops.filter(_._2).map(_._1)) } @Test def badlyLocatedLineNumbers(): Unit = { def t(ops: Instruction*) = - assertThrows[AssertionError](localOpt.removeEmptyLineNumbers(genMethod()(ops: _*))) + assertThrows[AssertionError](LocalOptImpls.removeEmptyLineNumbers(genMethod()(ops: _*))) // line numbers have to be right after their referenced label node t(LineNumber(0, Label(1)), Label(1)) @@ -88,7 +88,7 @@ class EmptyLabelsAndLineNumbersTest { ) val method = genMethod(handlers = handler)(ops(2, 3, 8, 8, 9, 11).map(_._1): _*) - assertTrue(localOpt.removeEmptyLabelNodes(method)) + assertTrue(LocalOptImpls.removeEmptyLabelNodes(method)) val m = convertMethod(method) assertSameCode(m.instructions, ops(1, 1, 7, 7, 7, 10).filter(_._2).map(_._1)) assertTrue(m.handlers match { diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala index fedc074a15..029caa995c 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala @@ -143,4 +143,52 @@ class InlineWarningTest extends ClearAfterClass { compileClasses(newCompiler(extraArgs = InlineWarningTest.argsNoWarn + " -Yopt-warnings:no-inline-mixed"))(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)}) assert(c == 2, c) } + + @Test + def cannotInlinePrivateCallIntoDifferentClass(): Unit = { + val code = + """class M { + | @inline final def f = { + | @noinline def nested = 0 + | nested + | } + | + | def t = f // ok + |} + | + |class N { + | def t(a: M) = a.f // not possible + |} + """.stripMargin + + val warn = + """M::f()I is annotated @inline but could not be inlined: + |The callee M::f()I contains the instruction INVOKESPECIAL M.nested$1 ()I + |that would cause an IllegalAccessError when inlined into class N""".stripMargin + + var c = 0 + compile(code, allowMessage = i => { c += 1; i.msg contains warn }) + assert(c == 1, c) + } + + @Test + def cannotMixStrictfp(): Unit = { + val code = + """import annotation.strictfp + |class C { + | @strictfp @inline final def f = 0 + | @strictfp def t1 = f + | def t2 = f + |} + """.stripMargin + + val warn = + """C::f()I is annotated @inline but could not be inlined: + |The callsite method C::t2()I + |does not have the same strictfp mode as the callee C::f()I.""".stripMargin + + var c = 0 + compile(code, allowMessage = i => { c += 1; i.msg contains warn }) + assert(c == 1, c) + } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 39fb28570e..17724aecb1 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -152,7 +152,7 @@ class InlinerTest extends ClearAfterClass { assertSameCode(convertMethod(g).instructions.dropNonOp.take(4), expectedInlined) - localOpt.methodOptimizations(g, "C") + compiler.genBCode.bTypes.localOpt.methodOptimizations(g, "C") assertSameCode(convertMethod(g).instructions.dropNonOp, expectedInlined ++ List(VarOp(ASTORE, 2), VarOp(ALOAD, 2), Op(ATHROW))) } @@ -950,4 +950,29 @@ class InlinerTest extends ClearAfterClass { assertInvoke(getSingleMethod(t, "t3"), "B", "<init>") assertInvoke(getSingleMethod(t, "t4"), "B", "<init>") } + + @Test + def dontInlineNative(): Unit = { + val code = + """class C { + | def t = System.arraycopy(null, 0, null, 0, 0) + |} + """.stripMargin + val List(c) = compileClasses(newCompiler(extraArgs = InlinerTest.args + " -Yopt-inline-heuristics:everything"))(code) + assertInvoke(getSingleMethod(c, "t"), "java/lang/System", "arraycopy") + } + + @Test + def inlineMayRenderCodeDead(): Unit = { + val code = + """class C { + | @inline final def f: String = throw new Error("") + | @inline final def g: String = "a" + f + "b" // after inlining f, need to run DCE, because the rest of g becomes dead. + | def t = g // the inliner requires no dead code when inlining g (uses an Analyzer). + |} + """.stripMargin + + val List(c) = compile(code) + assertInvoke(getSingleMethod(c, "t"), "java/lang/Error", "<init>") + } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala index 360fa1d23d..a685ae7dd5 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala @@ -26,7 +26,7 @@ class SimplifyJumpsTest { Op(RETURN) ) val method = genMethod()(ops: _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), Op(RETURN) :: ops.tail) } @@ -45,7 +45,7 @@ class SimplifyJumpsTest { Jump(GOTO, Label(2)) :: // replaced by ATHROW rest: _* ) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), Op(ACONST_NULL) :: Op(ATHROW) :: rest) } @@ -66,11 +66,11 @@ class SimplifyJumpsTest { Op(RETURN) ) val method = genMethod(handlers = handler)(initialInstrs: _*) - assertFalse(localOpt.simplifyJumps(method)) + assertFalse(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), initialInstrs) val optMethod = genMethod()(initialInstrs: _*) // no handler - assertTrue(localOpt.simplifyJumps(optMethod)) + assertTrue(LocalOptImpls.simplifyJumps(optMethod)) assertSameCode(instructionsFromMethod(optMethod).take(3), List(Label(1), Op(ACONST_NULL), Op(ATHROW))) } @@ -91,7 +91,7 @@ class SimplifyJumpsTest { Op(IRETURN) ) val method = genMethod()(begin ::: rest: _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode( instructionsFromMethod(method), List(VarOp(ILOAD, 1), Jump(IFLT, Label(3))) ::: rest.tail ) @@ -99,7 +99,7 @@ class SimplifyJumpsTest { // no label allowed between begin and rest. if there's another label, then there could be a // branch that label. eliminating the GOTO would change the behavior. val nonOptMethod = genMethod()(begin ::: Label(22) :: rest: _*) - assertFalse(localOpt.simplifyJumps(nonOptMethod)) + assertFalse(LocalOptImpls.simplifyJumps(nonOptMethod)) } @Test @@ -116,7 +116,7 @@ class SimplifyJumpsTest { // ensures that the goto is safely removed. ASM supports removing while iterating, but not the // next element of the current. Here, the current is the IFGE, the next is the GOTO. val method = genMethod()(code(Jump(IFGE, Label(2)), Jump(GOTO, Label(3))): _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), code(Jump(IFLT, Label(3)))) } @@ -131,7 +131,7 @@ class SimplifyJumpsTest { Op(IRETURN) ) val method = genMethod()(ops: _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), ops.tail) } @@ -157,7 +157,7 @@ class SimplifyJumpsTest { Op(IRETURN) ) val method = genMethod()(ops(1, 2, 3): _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), ops(3, 3, 3)) } @@ -181,7 +181,7 @@ class SimplifyJumpsTest { ) val method = genMethod()(ops(2): _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), ops(3)) } @@ -202,7 +202,7 @@ class SimplifyJumpsTest { ) val method = genMethod()(ops(Jump(IFGE, Label(1))): _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), ops(Op(POP))) } @@ -215,7 +215,7 @@ class SimplifyJumpsTest { Jump(GOTO, Label(1)) ) val method = genMethod()(ops(List(Jump(IF_ICMPGE, Label(1)))): _*) - assertTrue(localOpt.simplifyJumps(method)) + assertTrue(LocalOptImpls.simplifyJumps(method)) assertSameCode(instructionsFromMethod(method), ops(List(Op(POP), Op(POP)))) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala index da9853148b..902af7b7fa 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala @@ -44,7 +44,7 @@ class UnreachableCodeTest extends ClearAfterClass { def assertEliminateDead(code: (Instruction, Boolean)*): Unit = { val method = genMethod()(code.map(_._1): _*) - localOpt.removeUnreachableCodeImpl(method, "C") + LocalOptImpls.removeUnreachableCodeImpl(method, "C") val nonEliminated = instructionsFromMethod(method) val expectedLive = code.filter(_._2).map(_._1).toList assertSameCode(nonEliminated, expectedLive) diff --git a/test/pending/run/delambdafy-lambdametafactory.scala b/test/pending/run/delambdafy-lambdametafactory.scala new file mode 100644 index 0000000000..daea8a39fe --- /dev/null +++ b/test/pending/run/delambdafy-lambdametafactory.scala @@ -0,0 +1,50 @@ +// +// Tests that the static accessor method for lambda bodies +// (generated under -Ydelambdafy:method) are compatible with +// Java 8's LambdaMetafactory. +// +import java.lang.invoke._ + +class C { + def test1: Unit = { + (x: String) => x.reverse + } + def test2: Unit = { + val capture1 = "capture1" + (x: String) => capture1 + " " + x.reverse + } + def test3: Unit = { + (x: String) => C.this + " " + x.reverse + } +} +trait T { + def test4: Unit = { + (x: String) => x.reverse + } +} + +// A functional interface. Function1 contains abstract methods that are filled in by mixin +trait Function1ish[A, B] { + def apply(a: A): B +} + +object Test { + def lambdaFactory[A, B](hostClass: Class[_], instantiatedParam: Class[A], instantiatedRet: Class[B], accessorName: String, + capturedParams: Array[(Class[_], AnyRef)] = Array()) = { + val caller = MethodHandles.lookup + val methodType = MethodType.methodType(classOf[AnyRef], Array[Class[_]](classOf[AnyRef])) + val instantiatedMethodType = MethodType.methodType(instantiatedRet, Array[Class[_]](instantiatedParam)) + val (capturedParamTypes, captured) = capturedParams.unzip + val targetMethodType = MethodType.methodType(instantiatedRet, capturedParamTypes :+ instantiatedParam) + val invokedType = MethodType.methodType(classOf[Function1ish[_, _]], capturedParamTypes) + val target = caller.findStatic(hostClass, accessorName, targetMethodType) + val site = LambdaMetafactory.metafactory(caller, "apply", invokedType, methodType, target, instantiatedMethodType) + site.getTarget.invokeWithArguments(captured: _*).asInstanceOf[Function1ish[A, B]] + } + def main(args: Array[String]) { + println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$1").apply("abc")) + println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$2", Array(classOf[String] -> "capture1")).apply("abc")) + println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$3", Array(classOf[C] -> new C)).apply("abc")) + println(lambdaFactory(Class.forName("T$class"), classOf[String], classOf[String], "accessor$4", Array(classOf[T] -> new T{})).apply("abc")) + } +} diff --git a/test/scaladoc/run/t5795.check b/test/scaladoc/run/t5795.check new file mode 100644 index 0000000000..d08ab619ed --- /dev/null +++ b/test/scaladoc/run/t5795.check @@ -0,0 +1,4 @@ +newSource:16: warning: Could not find any member to link for "Exception". + /** + ^ +Done. diff --git a/test/scaladoc/run/t5795.scala b/test/scaladoc/run/t5795.scala new file mode 100644 index 0000000000..767e4f1a72 --- /dev/null +++ b/test/scaladoc/run/t5795.scala @@ -0,0 +1,63 @@ +import scala.tools.nsc.doc.model._ +import scala.tools.partest.ScaladocModelTest + +object Test extends ScaladocModelTest { + + override def code = """ +/** + * Only the 'deprecated' tag should stay. + * + * @author + * @since + * @todo + * @note + * @see + * @version + * @deprecated + * @example + * @constructor + */ +object Test { + /** + * Only the 'throws' tag should stay. + * @param foo + * @param bar + * @param baz + * @return + * @throws Exception + * @tparam T + */ + def foo[T](foo: Any, bar: Any, baz: Any): Int = 1 +} + """ + + def scaladocSettings = "" + + def test(b: Boolean, text: => String): Unit = if (!b) println(text) + + def testModel(root: Package) = { + import access._ + val obj = root._object("Test") + val c = obj.comment.get + + test(c.authors.isEmpty, s"expected no authors, found: ${c.authors}") + test(!c.since.isDefined, s"expected no since tag, found: ${c.since}") + test(c.todo.isEmpty, s"expected no todos, found: ${c.todo}") + test(c.note.isEmpty, s"expected no note, found: ${c.note}") + test(c.see.isEmpty, s"expected no see, found: ${c.see}") + test(!c.version.isDefined, s"expected no version tag, found: ${c.version}") + // deprecated stays + test(c.deprecated.isDefined, s"expected deprecated tag, found none") + test(c.example.isEmpty, s"expected no example, found: ${c.example}") + test(!c.constructor.isDefined, s"expected no constructor tag, found: ${c.constructor}") + + val method = obj._method("foo") + val mc = method.comment.get + + test(mc.valueParams.isEmpty, s"expected empty value params, found: ${mc.valueParams}") + test(mc.typeParams.isEmpty, s"expected empty type params, found: ${mc.typeParams}") + test(!mc.result.isDefined, s"expected no result tag, found: ${mc.result}") + // throws stay + test(!mc.throws.isEmpty, s"expected an exception tag, found: ${mc.throws}") + } +} diff --git a/test/scaladoc/scalacheck/CommentFactoryTest.scala b/test/scaladoc/scalacheck/CommentFactoryTest.scala index ff64a25602..d30b78087c 100644 --- a/test/scaladoc/scalacheck/CommentFactoryTest.scala +++ b/test/scaladoc/scalacheck/CommentFactoryTest.scala @@ -24,8 +24,11 @@ class Factory(val g: Global, val s: doc.Settings) } } + def getComment(s: String): Comment = + parse(s, "", scala.tools.nsc.util.NoPosition, null) + def parseComment(s: String): Option[Inline] = - strip(parse(s, "", scala.tools.nsc.util.NoPosition, null)) + strip(getComment(s)) def createBody(s: String) = parse(s, "", scala.tools.nsc.util.NoPosition, null).body @@ -166,4 +169,19 @@ object Test extends Properties("CommentFactory") { } } + property("Empty parameter text should be empty") = { + // used to fail with + // body == Body(List(Paragraph(Chain(List(Summary(Text('\n'))))))) + factory.getComment( + """ +/** + * @deprecated + */ + """).deprecated match { + case Some(Body(l)) if l.isEmpty => true + case other => + println(other) + false + } + } } diff --git a/test/scaladoc/scalacheck/HtmlFactoryTest.scala b/test/scaladoc/scalacheck/HtmlFactoryTest.scala index 51633be440..6a6b1f8901 100644 --- a/test/scaladoc/scalacheck/HtmlFactoryTest.scala +++ b/test/scaladoc/scalacheck/HtmlFactoryTest.scala @@ -685,7 +685,7 @@ object Test extends Properties("HtmlFactory") { case node: scala.xml.Node => { val s = node.toString s.contains("<h6>Author:</h6>") && - s.contains("<p>The Only Author\n</p>") + s.contains("<p>The Only Author</p>") } case _ => false } @@ -699,7 +699,7 @@ object Test extends Properties("HtmlFactory") { val s = node.toString s.contains("<h6>Authors:</h6>") && s.contains("<p>The First Author</p>") && - s.contains("<p>The Second Author\n</p>") + s.contains("<p>The Second Author</p>") } case _ => false } |