summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]build.xml1023
-rw-r--r--src/compiler/scala/reflect/macros/runtime/Reifiers.scala6
-rw-r--r--src/compiler/scala/reflect/reify/Phases.scala2
-rw-r--r--src/compiler/scala/reflect/reify/Reifier.scala4
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reshape.scala8
-rw-r--r--src/compiler/scala/reflect/reify/utils/Extractors.scala65
-rw-r--r--src/compiler/scala/tools/nsc/CompileClient.scala4
-rw-r--r--src/compiler/scala/tools/nsc/Driver.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala42
-rw-r--r--src/compiler/scala/tools/nsc/Main.scala2
-rw-r--r--src/compiler/scala/tools/nsc/MainTokenMetric.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala8
-rw-r--r--src/compiler/scala/tools/nsc/ast/Positions.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/Printers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala6
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodes.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala19
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Printers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Repository.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala36
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala13
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala8
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugins.scala2
-rw-r--r--src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala17
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala767
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala190
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala18
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala64
-rw-r--r--src/compiler/scala/tools/nsc/transform/LazyVals.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala26
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala48
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala14
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala35
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Logic.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala18
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Adaptations.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Checkable.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala30
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala25
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala18
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala238
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala15
-rw-r--r--src/compiler/scala/tools/nsc/util/SimpleTracer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/util/TreeSet.scala20
-rw-r--r--src/compiler/scala/tools/reflect/MacroImplementations.scala3
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala16
-rw-r--r--src/compiler/scala/tools/util/PathResolver.scala4
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Global.scala2
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Main.scala2
-rw-r--r--src/interactive/scala/tools/nsc/interactive/REPL.scala4
-rw-r--r--src/interactive/scala/tools/nsc/interactive/tests/InteractiveTest.scala12
-rw-r--r--src/interactive/scala/tools/nsc/interactive/tests/Tester.scala4
-rw-r--r--src/interactive/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala4
-rw-r--r--src/interactive/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala2
-rw-r--r--src/library/scala/collection/Iterator.scala54
-rw-r--r--src/library/scala/collection/parallel/package.scala7
-rwxr-xr-xsrc/library/scala/reflect/NameTransformer.scala9
-rw-r--r--src/library/scala/reflect/package.scala14
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala8
-rw-r--r--src/partest/scala/tools/partest/DirectTest.scala5
-rw-r--r--src/partest/scala/tools/partest/IcodeTest.scala4
-rw-r--r--src/partest/scala/tools/partest/PartestDefaults.scala9
-rw-r--r--src/partest/scala/tools/partest/PartestTask.scala341
-rw-r--r--src/partest/scala/tools/partest/TestKinds.scala67
-rw-r--r--src/partest/scala/tools/partest/TestState.scala54
-rw-r--r--src/partest/scala/tools/partest/nest/AntRunner.scala25
-rw-r--r--src/partest/scala/tools/partest/nest/CompileManager.scala182
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleFileManager.scala33
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleRunner.scala321
-rw-r--r--src/partest/scala/tools/partest/nest/Diff.java873
-rw-r--r--src/partest/scala/tools/partest/nest/DiffPrint.java606
-rw-r--r--src/partest/scala/tools/partest/nest/DirectCompiler.scala105
-rw-r--r--src/partest/scala/tools/partest/nest/DirectRunner.scala52
-rw-r--r--src/partest/scala/tools/partest/nest/FileManager.scala88
-rw-r--r--src/partest/scala/tools/partest/nest/NestUI.scala111
-rw-r--r--src/partest/scala/tools/partest/nest/PathSettings.scala3
-rw-r--r--src/partest/scala/tools/partest/nest/ReflectiveRunner.scala7
-rw-r--r--src/partest/scala/tools/partest/nest/Runner.scala628
-rw-r--r--src/partest/scala/tools/partest/nest/RunnerManager.scala690
-rw-r--r--src/partest/scala/tools/partest/nest/SBTRunner.scala29
-rw-r--r--src/partest/scala/tools/partest/nest/StreamCapture.scala53
-rw-r--r--src/partest/scala/tools/partest/nest/TestFile.scala80
-rw-r--r--src/partest/scala/tools/partest/package.scala151
-rw-r--r--src/reflect/scala/reflect/api/Annotations.scala31
-rw-r--r--src/reflect/scala/reflect/api/Constants.scala6
-rw-r--r--src/reflect/scala/reflect/api/FlagSets.scala6
-rw-r--r--src/reflect/scala/reflect/api/ImplicitTags.scala200
-rw-r--r--src/reflect/scala/reflect/api/Names.scala18
-rw-r--r--src/reflect/scala/reflect/api/Positions.scala7
-rw-r--r--src/reflect/scala/reflect/api/Printers.scala2
-rw-r--r--src/reflect/scala/reflect/api/Scopes.scala14
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala48
-rw-r--r--src/reflect/scala/reflect/api/Trees.scala324
-rw-r--r--src/reflect/scala/reflect/api/Types.scala2
-rw-r--r--src/reflect/scala/reflect/api/Universe.scala3
-rw-r--r--src/reflect/scala/reflect/internal/ClassfileConstants.scala5
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala4
-rw-r--r--src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala77
-rw-r--r--src/reflect/scala/reflect/internal/JMethodOrConstructor.scala45
-rw-r--r--src/reflect/scala/reflect/internal/JavaAccFlags.scala83
-rw-r--r--src/reflect/scala/reflect/internal/Kinds.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala50
-rw-r--r--src/reflect/scala/reflect/internal/Positions.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala31
-rw-r--r--src/reflect/scala/reflect/internal/PrivateWithin.scala33
-rw-r--r--src/reflect/scala/reflect/internal/Scopes.scala48
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala119
-rw-r--r--src/reflect/scala/reflect/internal/SymbolTable.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala108
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala8
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala70
-rw-r--r--src/reflect/scala/reflect/internal/settings/MutableSettings.scala5
-rw-r--r--src/reflect/scala/reflect/internal/tpe/GlbLubs.scala2
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeComparers.scala261
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala2
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala2
-rw-r--r--src/reflect/scala/reflect/internal/transform/UnCurry.scala9
-rw-r--r--src/reflect/scala/reflect/internal/util/Collections.scala13
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala207
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverse.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/SymbolTable.scala4
-rw-r--r--src/repl/scala/tools/nsc/MainGenericRunner.scala4
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala4
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala2
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Power.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/DocFactory.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/Uncompilable.scala4
-rwxr-xr-xsrc/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala18
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala6
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DiagramStats.scala4
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala8
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala4
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala2
-rw-r--r--starr.number1
-rwxr-xr-xtest/build-partest.xml24
-rw-r--r--test/files/jvm/t7253.check1
-rw-r--r--test/files/jvm/t7253/Base_1.scala5
-rw-r--r--test/files/jvm/t7253/JavaClient_1.java9
-rw-r--r--test/files/jvm/t7253/ScalaClient_1.scala9
-rw-r--r--test/files/jvm/t7253/test.scala28
-rw-r--r--test/files/neg/choices.check2
-rw-r--r--test/files/neg/choices.flags2
-rw-r--r--test/files/neg/javac-error.check10
-rw-r--r--test/files/neg/javac-error.flags1
-rw-r--r--test/files/neg/javac-error/J.java5
-rw-r--r--test/files/neg/javac-error/SUT_5.scala5
-rw-r--r--test/files/neg/t3631.check4
-rw-r--r--test/files/neg/t5580b.check6
-rw-r--r--test/files/neg/t5580b.scala (renamed from test/files/pos/t5580b.scala)6
-rw-r--r--test/files/neg/t7110.check6
-rw-r--r--test/files/neg/t7110.flags1
-rw-r--r--test/files/neg/t7110.scala6
-rw-r--r--test/files/neg/t7251.check4
-rw-r--r--test/files/neg/t7251/A_1.scala10
-rw-r--r--test/files/neg/t7251/B_2.scala7
-rw-r--r--test/files/neg/t7259.check7
-rw-r--r--test/files/neg/t7259.scala9
-rw-r--r--test/files/neg/t7285.check15
-rw-r--r--test/files/neg/t7285.flags1
-rw-r--r--test/files/neg/t7285.scala55
-rw-r--r--test/files/neg/t7290.check12
-rw-r--r--test/files/neg/t7290.flags1
-rw-r--r--test/files/neg/t7290.scala10
-rw-r--r--test/files/neg/t7299.check7
-rw-r--r--test/files/neg/t7299.scala6
-rw-r--r--test/files/pos/t3120/J1.java4
-rw-r--r--test/files/pos/t3120/J2.java4
-rw-r--r--test/files/pos/t3120/Q.java3
-rw-r--r--test/files/pos/t3120/Test.scala3
-rw-r--r--test/files/pos/t3631.scala (renamed from test/files/neg/t3631.scala)0
-rw-r--r--test/files/pos/t6210.flags1
-rw-r--r--test/files/pos/t6210.scala21
-rw-r--r--test/files/pos/t6921.scala11
-rw-r--r--test/files/pos/t7232.flags1
-rw-r--r--test/files/pos/t7232/Foo.java9
-rw-r--r--test/files/pos/t7232/List.java4
-rw-r--r--test/files/pos/t7232/Test.scala5
-rw-r--r--test/files/pos/t7232b.flags1
-rw-r--r--test/files/pos/t7232b/Foo.java8
-rw-r--r--test/files/pos/t7232b/List.java5
-rw-r--r--test/files/pos/t7232b/Test.scala5
-rw-r--r--test/files/pos/t7232c.flags1
-rw-r--r--test/files/pos/t7232c/Foo.java10
-rw-r--r--test/files/pos/t7232c/Test.scala4
-rw-r--r--test/files/pos/t7232d.flags1
-rw-r--r--test/files/pos/t7232d/Entry.java4
-rw-r--r--test/files/pos/t7232d/Foo.java8
-rw-r--r--test/files/pos/t7232d/Test.scala4
-rw-r--r--test/files/pos/t7233.scala14
-rw-r--r--test/files/pos/t7233b.scala8
-rw-r--r--test/files/pos/t7239.scala38
-rw-r--r--test/files/pos/t7285a.flags1
-rw-r--r--test/files/pos/t7285a.scala83
-rw-r--r--test/files/pos/t7296.scala6
-rwxr-xr-xtest/files/presentation/doc/doc.scala7
-rwxr-xr-xtest/files/presentation/doc/src/p/Base.scala2
-rw-r--r--test/files/run/blame_eye_triple_eee-double.check (renamed from test/files/run/blame_eye_triple_eee.check)0
-rw-r--r--test/files/run/blame_eye_triple_eee-double.flags (renamed from test/files/run/blame_eye_triple_eee.flags)0
-rw-r--r--test/files/run/blame_eye_triple_eee-double.scala (renamed from test/files/run/blame_eye_triple_eee.scala)0
-rw-r--r--test/files/run/blame_eye_triple_eee-float.check9
-rw-r--r--test/files/run/blame_eye_triple_eee-float.flags1
-rw-r--r--test/files/run/blame_eye_triple_eee-float.scala61
-rw-r--r--test/files/run/case-class-23.check2
-rw-r--r--test/files/run/case-class-23.scala33
-rw-r--r--test/files/run/classfile-format-51.scala126
-rw-r--r--test/files/run/existentials3-new.check6
-rw-r--r--test/files/run/inline-ex-handlers.check919
-rw-r--r--test/files/run/iterator-concat.check4
-rw-r--r--test/files/run/iterator-concat.scala15
-rw-r--r--test/files/run/outertest.scala47
-rw-r--r--test/files/run/reify_this.scala6
-rw-r--r--test/files/run/t3994.scala20
-rwxr-xr-xtest/files/run/t5699.check11
-rwxr-xr-xtest/files/run/t5699.scala24
-rw-r--r--test/files/run/t6028.check14
-rw-r--r--test/files/run/t6146b.check11
-rw-r--r--test/files/run/t6146b.scala3
-rw-r--r--test/files/run/t6168/Context.java34
-rw-r--r--test/files/run/t6168/JavaTest.java8
-rw-r--r--test/files/run/t6168/SomeClass.java14
-rw-r--r--test/files/run/t6168/SomeClass2.java12
-rw-r--r--test/files/run/t6168/main.scala15
-rw-r--r--test/files/run/t6168b/Context.java34
-rw-r--r--test/files/run/t6168b/JavaTest.java6
-rw-r--r--test/files/run/t6168b/SomeClass.java11
-rw-r--r--test/files/run/t6168b/main.scala8
-rw-r--r--test/files/run/t6223.scala4
-rw-r--r--test/files/run/t6387.check1
-rw-r--r--test/files/run/t6387.scala16
-rw-r--r--test/files/run/t6715.scala15
-rw-r--r--test/files/run/t6725-1.check2
-rw-r--r--test/files/run/t6725-1.scala5
-rw-r--r--test/files/run/t6725-2.check8
-rw-r--r--test/files/run/t6725-2.scala6
-rw-r--r--test/files/run/t6793.scala9
-rw-r--r--test/files/run/t6793b.scala11
-rw-r--r--test/files/run/t6793c.scala11
-rw-r--r--test/files/run/t6900.scala36
-rw-r--r--test/files/run/t7240.check0
-rw-r--r--test/files/run/t7240/Macros_1.scala48
-rw-r--r--test/files/run/t7240/Test_2.scala3
-rw-r--r--test/files/run/t7242.scala71
-rwxr-xr-xtest/files/run/t7246.check1
-rwxr-xr-xtest/files/run/t7246/Outer.java4
-rwxr-xr-xtest/files/run/t7246/Test.scala16
-rwxr-xr-xtest/files/run/t7246b.check2
-rwxr-xr-xtest/files/run/t7246b/Base.scala7
-rwxr-xr-xtest/files/run/t7246b/Outer.java4
-rwxr-xr-xtest/files/run/t7246b/Test.scala14
-rw-r--r--test/files/run/t7249.check1
-rw-r--r--test/files/run/t7249.scala7
-rw-r--r--test/files/run/t7290.scala9
-rw-r--r--test/files/run/t7300.check2
-rw-r--r--test/files/run/t7300.scala11
-rw-r--r--test/files/run/test-cpp.check146
-rw-r--r--test/files/scalap/abstractClass.check (renamed from test/files/scalap/abstractClass/result.test)0
-rw-r--r--test/files/scalap/abstractClass.scala (renamed from test/files/scalap/abstractClass/A.scala)0
-rw-r--r--test/files/scalap/abstractMethod.check (renamed from test/files/scalap/abstractMethod/result.test)0
-rw-r--r--test/files/scalap/abstractMethod.scala (renamed from test/files/scalap/abstractMethod/A.scala)0
-rw-r--r--test/files/scalap/caseClass.check (renamed from test/files/scalap/caseClass/result.test)0
-rw-r--r--test/files/scalap/caseClass.scala (renamed from test/files/scalap/caseClass/A.scala)0
-rw-r--r--test/files/scalap/caseObject.check (renamed from test/files/scalap/caseObject/result.test)0
-rw-r--r--test/files/scalap/caseObject.scala (renamed from test/files/scalap/caseObject/A.scala)0
-rw-r--r--test/files/scalap/cbnParam.check (renamed from test/files/scalap/cbnParam/result.test)0
-rw-r--r--test/files/scalap/cbnParam.scala (renamed from test/files/scalap/cbnParam/A.scala)0
-rw-r--r--test/files/scalap/classPrivate.check (renamed from test/files/scalap/classPrivate/result.test)0
-rw-r--r--test/files/scalap/classPrivate.scala (renamed from test/files/scalap/classPrivate/A.scala)0
-rw-r--r--test/files/scalap/classWithExistential.check (renamed from test/files/scalap/classWithExistential/result.test)0
-rw-r--r--test/files/scalap/classWithExistential.scala (renamed from test/files/scalap/classWithExistential/A.scala)0
-rw-r--r--test/files/scalap/classWithSelfAnnotation.check (renamed from test/files/scalap/classWithSelfAnnotation/result.test)0
-rw-r--r--test/files/scalap/classWithSelfAnnotation.scala (renamed from test/files/scalap/classWithSelfAnnotation/A.scala)0
-rw-r--r--test/files/scalap/covariantParam.check (renamed from test/files/scalap/covariantParam/result.test)0
-rw-r--r--test/files/scalap/covariantParam.scala (renamed from test/files/scalap/covariantParam/A.scala)0
-rw-r--r--test/files/scalap/defaultParameter.check (renamed from test/files/scalap/defaultParameter/result.test)0
-rw-r--r--test/files/scalap/defaultParameter.scala (renamed from test/files/scalap/defaultParameter/A.scala)0
-rw-r--r--test/files/scalap/implicitParam.check (renamed from test/files/scalap/implicitParam/result.test)0
-rw-r--r--test/files/scalap/implicitParam.scala (renamed from test/files/scalap/implicitParam/A.scala)0
-rw-r--r--test/files/scalap/packageObject.check (renamed from test/files/scalap/packageObject/result.test)0
-rw-r--r--test/files/scalap/packageObject.scala (renamed from test/files/scalap/packageObject/A.scala)0
-rw-r--r--test/files/scalap/paramClauses.check (renamed from test/files/scalap/paramClauses/result.test)0
-rw-r--r--test/files/scalap/paramClauses.scala (renamed from test/files/scalap/paramClauses/A.scala)0
-rw-r--r--test/files/scalap/paramNames.check (renamed from test/files/scalap/paramNames/result.test)0
-rw-r--r--test/files/scalap/paramNames.scala (renamed from test/files/scalap/paramNames/A.scala)0
-rw-r--r--test/files/scalap/sequenceParam.check (renamed from test/files/scalap/sequenceParam/result.test)0
-rw-r--r--test/files/scalap/sequenceParam.scala (renamed from test/files/scalap/sequenceParam/A.scala)0
-rw-r--r--test/files/scalap/simpleClass.check (renamed from test/files/scalap/simpleClass/result.test)0
-rw-r--r--test/files/scalap/simpleClass.scala (renamed from test/files/scalap/simpleClass/A.scala)0
-rw-r--r--test/files/scalap/traitObject.check (renamed from test/files/scalap/traitObject/result.test)0
-rw-r--r--test/files/scalap/traitObject.scala (renamed from test/files/scalap/traitObject/A.scala)0
-rw-r--r--test/files/scalap/typeAnnotations.check (renamed from test/files/scalap/typeAnnotations/result.test)0
-rw-r--r--test/files/scalap/typeAnnotations.scala (renamed from test/files/scalap/typeAnnotations/A.scala)0
-rw-r--r--test/files/scalap/valAndVar.check (renamed from test/files/scalap/valAndVar/result.test)0
-rw-r--r--test/files/scalap/valAndVar.scala (renamed from test/files/scalap/valAndVar/A.scala)0
-rw-r--r--test/files/scalap/wildcardType.check (renamed from test/files/scalap/wildcardType/result.test)0
-rw-r--r--test/files/scalap/wildcardType.scala (renamed from test/files/scalap/wildcardType/A.scala)0
-rwxr-xr-xtest/partest20
-rw-r--r--test/scaladoc/run/SI-6580.check11
-rw-r--r--test/scaladoc/run/SI-6580.scala32
-rw-r--r--test/scaladoc/run/SI-6715.check1
-rw-r--r--test/scaladoc/run/SI-6715.scala15
339 files changed, 5934 insertions, 6187 deletions
diff --git a/build.xml b/build.xml
index 9c98c34b32..e1c19fd909 100644..100755
--- a/build.xml
+++ b/build.xml
@@ -1,10 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="sabbus" default="build" xmlns:artifact="urn:maven-artifact-ant">
+ <include file="test/build-partest.xml" as="partest"/>
+
<description>
SuperSabbus for Scala core, builds the scala library and compiler. It can also package it as a simple distribution, tests it for stable bootstrapping and against the Scala test suite.
</description>
+<!-- HINTS
+
+ - for faster builds, have a build.properties in the same directory as build.xml that says:
+ locker.skip=1
+ starr.use.released=1
+
+-->
+
<!-- USAGE FROM JENKINS SCRIPTS IS (CURRENTLY) AS FOLLOWS:
ant $antArgs $scalacArgs $targets
@@ -16,7 +26,20 @@ scalacArgs examples:
"-Dscalac.args=\"-Yrangepos\" -Dpartest.scalac_opts=\"-Yrangepos\""
targets exercised:
- build-opt nightly test.suite test.continuations.suite test.scaladoc locker.done
+ locker.done build-opt nightly test.suite test.continuations.suite test.scaladoc
+-->
+
+<!-- To use Zinc with the ant build:
+ - install zinc and symlink the installed zinc script to ${basedir}/tools/zinc (${basedir} is where build.xml and the rest of your checkout resides)
+ - make sure to set ZINC_OPTS to match ANT_OPTS!
+-->
+
+<!--
+TODO:
+ - detect zinc anywhere on PATH
+ - automatically set ZINC_OPTS
+ - skip locker (and test.stability) by default to speed up PR validation, still do full build & testing during nightly
+ - (rework the build to pack locker and build using that when using zinc)
-->
@@ -44,8 +67,8 @@ targets exercised:
<target name="distpack-maven" depends="dist.done, docs.done">
<ant antfile="${src.dir}/build/pack.xml" target="pack-maven.done" inheritall="yes" inheritrefs="yes"/></target>
- <target name="distpack-opt" description="Builds an optimised distribution."> <optimize name="distpack"/></target>
- <target name="distpack-maven-opt" description="Builds an optimised maven distribution."><optimize name="distpack-maven"/></target>
+ <target name="distpack-opt" description="Builds an optimised distribution."> <optimized name="distpack"/></target>
+ <target name="distpack-maven-opt" description="Builds an optimised maven distribution."><optimized name="distpack-maven"/></target>
<target name="all.done" depends="dist.done, test.done"/>
@@ -57,8 +80,8 @@ targets exercised:
<target name="nightly.checkall">
<antcall target="nightly-nopt"> <param name="partest.scalac_opts" value="-Ycheck:all"/></antcall></target>
- <target name="clean" depends="locker.clean" description="Removes binaries of compiler and library. Distributions are untouched."/>
- <target name="docsclean" depends="docs.clean" description="Removes generated documentation. Distributions are untouched."/>
+ <target name="clean" depends="quick.clean" description="Removes binaries of compiler and library. Locker and distributions are untouched."/>
+ <target name="docsclean" depends="docs.clean" description="Removes generated documentation. Distributions are untouched."/>
<target name="distclean" depends="dist.clean" description="Removes all distributions. Binaries and documentation are untouched."/>
<macrodef name="optimized" >
@@ -74,63 +97,68 @@ targets exercised:
<property environment="env"/>
<!-- Prevents system classpath from being used -->
- <property name="build.sysclasspath" value="ignore"/>
+ <property name="build.sysclasspath" value="ignore"/>
<!-- Defines the repository layout -->
- <property name="docs.dir" value="${basedir}/docs"/>
- <property name="lib.dir" value="${basedir}/lib"/>
- <property name="src.dir" value="${basedir}/src"/>
- <property name="partest.dir" value="${basedir}/test"/>
+ <property name="docs.dir" value="${basedir}/docs"/>
+ <property name="lib.dir" value="${basedir}/lib"/>
+ <property name="src.dir" value="${basedir}/src"/>
+ <property name="partest.dir" value="${basedir}/test"/>
- <property name="lib-ant.dir" value="${lib.dir}/ant"/>
+ <property name="lib-ant.dir" value="${lib.dir}/ant"/>
<!-- For developers: any jars placed in this dir will be added to the classpath
of all targets and copied into quick/pack/etc builds. -->
- <property name="lib-extra.dir" value="${lib.dir}/extra"/>
+ <property name="lib-extra.dir" value="${lib.dir}/extra"/>
<!-- Loads custom properties definitions -->
<property file="${basedir}/build.properties"/>
+
<!-- Generating version number -->
<property file="${basedir}/build.number"/>
+ <!-- read starr.version -->
+ <property file="${basedir}/starr.number"/>
+
<!-- Sets location of pre-compiled libraries -->
- <property name="library.starr.jar" value="${lib.dir}/scala-library.jar"/>
- <property name="reflect.starr.jar" value="${lib.dir}/scala-reflect.jar"/>
- <property name="compiler.starr.jar" value="${lib.dir}/scala-compiler.jar"/>
- <property name="jline.jar" value="${lib.dir}/jline.jar"/>
- <property name="ant.jar" value="${ant.home}/lib/ant.jar"/>
- <property name="scalacheck.jar" value="${lib.dir}/scalacheck.jar"/>
+ <property name="library.starr.jar" value="${lib.dir}/scala-library.jar"/>
+ <property name="reflect.starr.jar" value="${lib.dir}/scala-reflect.jar"/>
+ <property name="compiler.starr.jar" value="${lib.dir}/scala-compiler.jar"/>
+ <property name="jline.jar" value="${lib.dir}/jline.jar"/>
+ <property name="ant.jar" value="${ant.home}/lib/ant.jar"/>
+ <property name="scalacheck.jar" value="${lib.dir}/scalacheck.jar"/>
<!-- Sets location of build folders -->
- <property name="build.dir" value="${basedir}/build"/>
- <property name="build-asm.dir" value="${build.dir}/asm"/>
- <property name="build-locker.dir" value="${build.dir}/locker"/>
- <property name="build-palo.dir" value="${build.dir}/palo"/>
- <property name="build-quick.dir" value="${build.dir}/quick"/>
- <property name="build-pack.dir" value="${build.dir}/pack"/>
- <property name="build-osgi.dir" value="${build.dir}/osgi"/>
- <property name="build-strap.dir" value="${build.dir}/strap"/>
- <property name="build-docs.dir" value="${build.dir}/scaladoc"/>
- <property name="build-libs.dir" value="${build.dir}/libs"/>
- <property name="build-sbt.dir" value="${build.dir}/sbt-interface"/>
-
- <property name="test.osgi.src" value="${partest.dir}/osgi/src"/>
- <property name="test.osgi.classes" value="${build-osgi.dir}/classes"/>
-
- <property name="dists.dir" value="${basedir}/dists"/>
-
- <property name="copyright.string" value="Copyright 2002-2013, LAMP/EPFL"/>
- <property name="partest.version.number" value="0.9.2"/>
+ <property name="build.dir" value="${basedir}/build"/>
+ <property name="build-libs.dir" value="${build.dir}/libs"/>
+ <property name="build-asm.dir" value="${build.dir}/asm"/>
+ <property name="build-forkjoin.dir" value="${build-libs.dir}"/>
+ <property name="build-locker.dir" value="${build.dir}/locker"/>
+ <property name="build-palo.dir" value="${build.dir}/palo"/>
+ <property name="build-quick.dir" value="${build.dir}/quick"/>
+ <property name="build-pack.dir" value="${build.dir}/pack"/>
+ <property name="build-osgi.dir" value="${build.dir}/osgi"/>
+ <property name="build-strap.dir" value="${build.dir}/strap"/>
+ <property name="build-docs.dir" value="${build.dir}/scaladoc"/>
+ <property name="build-sbt.dir" value="${build.dir}/sbt-interface"/>
+
+ <property name="test.osgi.src" value="${partest.dir}/osgi/src"/>
+ <property name="test.osgi.classes" value="${build-osgi.dir}/classes"/>
+
+ <property name="dists.dir" value="${basedir}/dists"/>
+
+ <property name="copyright.string" value="Copyright 2002-2013, LAMP/EPFL"/>
+ <property name="partest.version.number" value="0.9.3"/>
<!-- These are NOT the flags used to run SuperSabbus, but the ones written
into the script runners created with scala.tools.ant.ScalaTool -->
- <property name="java.flags" value="-Xmx256M -Xms32M"/>
- <property name="jvm.opts" value=""/>
+ <property name="java.flags" value="-Xmx256M -Xms32M"/>
+ <property name="jvm.opts" value=""/>
<!-- if ANT_OPTS is already set by the environment, it will be unaltered,
but if it is unset it will take this default value. -->
- <property name="env.ANT_OPTS" value="-Xms1536M -Xmx1536M -Xss1M -XX:MaxPermSize=192M -XX:+UseParallelGC" />
+ <property name="env.ANT_OPTS" value="-Xms1536M -Xmx1536M -Xss1M -XX:MaxPermSize=192M -XX:+UseParallelGC" />
- <property name="scalacfork.jvmargs" value="${env.ANT_OPTS} ${jvm.opts}"/>
+ <property name="scalacfork.jvmargs" value="${env.ANT_OPTS} ${jvm.opts}"/>
<!-- ===========================================================================
INITIALIZATION
@@ -167,11 +195,15 @@ targets exercised:
<path id="maven-ant-tasks.classpath" path="${lib-ant.dir}/maven-ant-tasks-2.1.1.jar" />
<typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath" />
+ <!-- Resolve maven dependencies -->
+
<!-- work around http://jira.codehaus.org/browse/MANTTASKS-203:
java.lang.ClassCastException: org.codehaus.plexus.DefaultPlexusContainer cannot be cast to org.codehaus.plexus.PlexusContainer
on repeated use of artifact:dependencies
-->
<if><not><isset property="maven-deps-done"></isset></not><then>
+ <mkdir dir="${user.home}/.m2/repository"/>
+ <!-- This task has an issue where if the user directory does not exist, so we create it above. UGH. -->
<artifact:dependencies pathId="extra.tasks.classpath" filesetId="extra.tasks.fileset">
<dependency groupId="biz.aQute" artifactId="bnd" version="1.50.0"/>
</artifact:dependencies>
@@ -190,25 +222,32 @@ targets exercised:
<dependency groupId="org.apache.felix" artifactId="org.apache.felix.framework" version="3.2.2"/>
</artifact:dependencies>
+ <artifact:dependencies pathId="partest.extras.classpath" filesetId="partest.extras.fileset" versionsId="partest.extras.versions">
+ <dependency groupId="com.googlecode.java-diff-utils" artifactId="diffutils" version="1.3.0"/>
+ </artifact:dependencies>
+
<!-- BND support -->
<typedef resource="aQute/bnd/ant/taskdef.properties" classpathref="extra.tasks.classpath" />
- <!-- Resolve maven dependencies -->
- <mkdir dir="${user.home}/.m2/repository"/>
- <!-- This task has an issue where if the user directory does not exist, so we create it above. UGH. -->
- <artifact:dependencies pathId="dependency.classpath" filesetId="dependency.fileset">
- <!--<dependency groupId="com.typesafe" artifactId="config" version="0.4.0"/>-->
- </artifact:dependencies>
-
- <if><isset property="starr.version"/><then>
+ <!-- Download STARR via maven if `starr.use.released` is set,
+ and `starr.version` is specified (see the starr.number properties file).
+ Want to slow down STARR changes, using only released versions. -->
+ <if><isset property="starr.use.released"/><then>
+ <echo message="Using Scala ${starr.version} for STARR."/>
<artifact:dependencies pathId="starr.core.path">
<dependency groupId="org.scala-lang" artifactId="scala-library" version="${starr.version}"/>
<dependency groupId="org.scala-lang" artifactId="scala-reflect" version="${starr.version}"/>
<dependency groupId="org.scala-lang" artifactId="scala-compiler" version="${starr.version}"/>
- </artifact:dependencies>
- </then></if>
+ </artifact:dependencies></then>
+ <else>
+ <path id="starr.core.path">
+ <pathelement location="${library.starr.jar}"/>
+ <pathelement location="${reflect.starr.jar}"/>
+ <pathelement location="${compiler.starr.jar}"/>
+ </path></else>
+ </if>
- <property name="maven-deps-done" value="yep!"/>
+ <property name="maven-deps-done" value="yep!"/>
</then></if>
@@ -226,30 +265,34 @@ targets exercised:
- `version.suffix == maven.version.suffix == ""`
-->
<if><not><equals arg1="${version.bnum}" arg2="0"/></not><then>
- <property name="version.suffix" value="-${version.bnum}"/>
+ <property name="version.suffix" value="-${version.bnum}"/>
</then></if>
<if><or><not><isset property="version.suffix"/></not><equals arg1="${version.suffix}" arg2=""/></or><then>
<if><isset property="build.release"/><then>
- <property name="maven.version.suffix" value=""/>
- <property name="version.suffix" value="${maven.version.suffix}"/>
+ <property name="maven.version.suffix" value=""/>
+ <property name="version.suffix" value="${maven.version.suffix}"/>
<if><equals arg1="${maven.version.suffix}" arg2=""/><then>
<property name="osgi.version.suffix" value="-VFINAL"/></then>
<else>
<property name="osgi.version.suffix" value="${maven.version.suffix}"/></else></if></then></if></then>
<else> <!-- version.suffix set and not empty -->
- <property name="maven.version.suffix" value="${version.suffix}"/>
- <property name="osgi.version.suffix" value="${version.suffix}"/></else></if>
+ <property name="maven.version.suffix" value="${version.suffix}"/>
+ <property name="osgi.version.suffix" value="${version.suffix}"/></else></if>
+
+ <!-- if a maven version suffix was set (or inferred), assume we're building a release -->
+ <if><isset property="maven.version.suffix"/><then>
+ <property name="build.release" value="1"/></then></if>
<!-- not building a release and no version.suffix specified -->
- <property name="maven.version.suffix" value="-SNAPSHOT"/>
+ <property name="maven.version.suffix" value="-SNAPSHOT"/>
<if><equals arg1="${maven.version.suffix}" arg2="-SNAPSHOT"/><then>
- <property name="osgi.version.suffix" value=""/>
- <property name="version.suffix" value=""/></then>
+ <property name="osgi.version.suffix" value=""/>
+ <property name="version.suffix" value=""/></then>
<else>
- <property name="osgi.version.suffix" value="${maven.version.suffix}"/>
- <property name="version.suffix" value="${maven.version.suffix}"/></else></if>
+ <property name="osgi.version.suffix" value="${maven.version.suffix}"/>
+ <property name="version.suffix" value="${maven.version.suffix}"/></else></if>
<exec osfamily="unix" executable="tools/get-scala-commit-sha" outputproperty="git.commit.sha" failifexecutionfails="false" />
@@ -266,8 +309,8 @@ targets exercised:
</exec>
<!-- some default in case something went wrong getting the revision -->
- <property name="git.commit.sha" value="unknown"/>
- <property name="git.commit.date" value="unknown"/>
+ <property name="git.commit.sha" value="unknown"/>
+ <property name="git.commit.date" value="unknown"/>
<!-- We use the git describe to determine the OSGi modifier for our build. -->
<property name="maven.version.number"
@@ -276,9 +319,9 @@ targets exercised:
value="${version.major}.${version.minor}.${version.patch}.v${git.commit.date}${osgi.version.suffix}-${git.commit.sha}"/>
<if><isset property="build.release"/><then>
- <property name="version.number" value="${maven.version.number}"/>
+ <property name="version.number" value="${maven.version.number}"/>
</then><else>
- <property name="version.number" value="${version.major}.${version.minor}.${version.patch}${version.suffix}-${git.commit.date}-${git.commit.sha}"/>
+ <property name="version.number" value="${version.major}.${version.minor}.${version.patch}${version.suffix}-${git.commit.date}-${git.commit.sha}"/>
</else></if>
<condition property="has.java6">
@@ -304,27 +347,27 @@ targets exercised:
</then></if>
<!-- Allow this to be overridden simply -->
- <property name="sbt.latest.version" value="0.12.2"/>
+ <property name="sbt.latest.version" value="0.12.2"/>
- <property name="sbt.src.dir" value="${build-sbt.dir}/${sbt.latest.version}/src"/>
- <property name="sbt.lib.dir" value="${build-sbt.dir}/${sbt.latest.version}/lib"/>
+ <property name="sbt.src.dir" value="${build-sbt.dir}/${sbt.latest.version}/src"/>
+ <property name="sbt.lib.dir" value="${build-sbt.dir}/${sbt.latest.version}/lib"/>
- <property name="sbt.interface.jar" value="${sbt.lib.dir}/interface.jar"/>
- <property name="sbt.interface.url" value="http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-sbt/interface/${sbt.latest.version}/jars/interface.jar"/>
+ <property name="sbt.interface.jar" value="${sbt.lib.dir}/interface.jar"/>
+ <property name="sbt.interface.url" value="http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-sbt/interface/${sbt.latest.version}/jars/interface.jar"/>
<property name="sbt.interface.src.jar" value="${sbt.src.dir}/compiler-interface-src.jar"/>
<property name="sbt.interface.src.url" value="http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-sbt/compiler-interface/${sbt.latest.version}/jars/compiler-interface-src.jar"/>
<!-- Additional command line arguments for scalac. They are added to all build targets -->
- <property name="scalac.args" value=""/>
- <property name="javac.args" value=""/>
+ <property name="scalac.args" value=""/>
+ <property name="javac.args" value=""/>
- <property name="scalac.args.always" value="" />
- <property name="scalac.args.optimise" value=""/> <!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
- <property name="scalac.args.all" value="${scalac.args.always} ${scalac.args} ${scalac.args.optimise}"/>
- <property name="scalac.args.locker" value="${scalac.args.all}"/>
- <property name="scalac.args.quick" value="${scalac.args.all}"/>
- <property name="scalac.args.strap" value="${scalac.args.quick}"/>
+ <property name="scalac.args.always" value="" />
+ <property name="scalac.args.optimise" value=""/> <!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
+ <property name="scalac.args.all" value="${scalac.args.always} ${scalac.args} ${scalac.args.optimise}"/>
+ <property name="scalac.args.locker" value="${scalac.args.all}"/>
+ <property name="scalac.args.quick" value="${scalac.args.all}"/>
+ <property name="scalac.args.strap" value="${scalac.args.quick}"/>
<!-- This is the start time for the distribution -->
<tstamp prefix="time">
@@ -333,8 +376,8 @@ targets exercised:
</tstamp>
<!-- some default in case something went wrong getting the revision -->
- <property name="version.number" value="-unknown-"/>
- <property name="init.avail" value="yes"/>
+ <property name="version.number" value="-unknown-"/>
+ <property name="init.avail" value="yes"/>
<!-- Local libs (developer use.) -->
<mkdir dir="${lib-extra.dir}"/>
@@ -347,7 +390,6 @@ targets exercised:
<fileset dir="${lib-extra.dir}">
<include name="**/*.jar"/>
</fileset>
- <path refid="dependency.classpath"/>
</path>
<!-- And print-out what we are building -->
@@ -387,7 +429,9 @@ targets exercised:
<fail unless="version.suffixes.consistent" message="Version suffixes inconsistent!"/>
<path id="forkjoin.classpath" path="${build-libs.dir}/classes/forkjoin"/>
- <path id="asm.classpath" path="${build-asm.dir}/classes/"/>
+ <path id="asm.classpath" path="${build-asm.dir}/classes"/>
+ <property name="forkjoin-classes" refid="forkjoin.classpath"/>
+ <property name="asm-classes" refid="asm.classpath"/>
<!-- Compilers to use for the various stages.
@@ -399,24 +443,10 @@ targets exercised:
<path refid="aux.libs"/>
</path>
- <!-- Download STARR via maven if `starr.version` is specified.
- Want to slow down STARR changes, using only released versions. -->
- <if><isset property="starr.version"/><then>
- <property name="strr" refid="starr.compiler.path"/>
- <echo message="Using Scala ${starr.version} for STARR."/>
- <!-- <echo message="STARR classpath: ${strr}"/> -->
- </then><else>
- <path id="starr.core.path">
- <pathelement location="${library.starr.jar}"/>
- <pathelement location="${reflect.starr.jar}"/>
- <pathelement location="${compiler.starr.jar}"/>
- </path>
- </else></if>
-
- <!-- Skip locker with -Dlocker.skip=YESSIR. Uses STARR instead. -->
+ <!-- To skip locker, use -Dlocker.skip=1 -->
<if><isset property="locker.skip"/><then>
- <echo message="Skipping locker! Using STARR instead."/>
- <path id="locker.compiler.path"><path refid="starr.compiler.path"/></path>
+ <echo message="Using STARR to build the quick stage (skipping locker)."/>
+ <path id="locker.compiler.path" refid="starr.compiler.path"/>
<property name="locker.locked" value="locker skipped"/></then>
<else>
<path id="locker.compiler.path"><path refid="locker.compiler.build.path"/></path></else></if>
@@ -440,6 +470,11 @@ targets exercised:
<path refid="aux.libs"/>
</path>
+ <path id="locker.actors.build.path">
+ <path refid="locker.library.build.path"/>
+ <pathelement location="${build-locker.dir}/classes/actors"/>
+ </path>
+
<path id="locker.reflect.build.path">
<path refid="locker.library.build.path"/>
<pathelement location="${build-locker.dir}/classes/reflect"/>
@@ -458,7 +493,10 @@ targets exercised:
<path refid="aux.libs"/>
</path>
- <path id="quick.actors.build.path"><path refid="quick.library.build.path"/></path>
+ <path id="quick.actors.build.path">
+ <path refid="quick.library.build.path"/>
+ <pathelement location="${build-quick.dir}/classes/actors"/>
+ </path>
<path id="quick.reflect.build.path">
<path refid="quick.library.build.path"/>
@@ -479,6 +517,7 @@ targets exercised:
<path id="quick.swing.build.path">
<path refid="quick.library.build.path"/>
+ <path refid="quick.actors.build.path"/>
<pathelement location="${build-quick.dir}/classes/swing"/>
</path>
@@ -489,6 +528,7 @@ targets exercised:
<path id="quick.scalacheck.build.path">
<pathelement location="${build-quick.dir}/classes/library"/>
+ <pathelement location="${build-quick.dir}/classes/actors"/>
<pathelement location="${build-quick.dir}/classes/scalacheck"/>
</path>
@@ -500,6 +540,7 @@ targets exercised:
<path id="quick.partest.build.path">
<path refid="quick.scalap.build.path"/>
+ <path refid="partest.extras.classpath"/>
<pathelement location="${build-quick.dir}/classes/repl"/>
<pathelement location="${scalacheck.jar}"/>
</path>
@@ -518,11 +559,13 @@ targets exercised:
<path id="quick.bin.tool.path">
<path refid="quick.repl.build.path"/>
+ <path refid="quick.actors.build.path"/>
<pathelement location="${build-quick.dir}/classes/scalap"/>
<pathelement location="${build-quick.dir}/classes/continuations-library"/>
</path>
<!-- PACK -->
+ <!-- also used for docs.* targets TODO: use separate paths for those -->
<path id="pack.compiler.path">
<pathelement location="${build-pack.dir}/lib/scala-library.jar"/>
<pathelement location="${build-pack.dir}/lib/scala-reflect.jar"/>
@@ -531,6 +574,7 @@ targets exercised:
<pathelement location="${build-pack.dir}/lib/scalap.jar"/>
<pathelement location="${build-pack.dir}/lib/scala-actors.jar"/>
<pathelement location="${ant.jar}"/>
+ <path refid="partest.extras.classpath"/>
<path refid="aux.libs"/>
</path>
@@ -543,6 +587,42 @@ targets exercised:
<path refid="aux.libs"/>
</path>
+ <path id="pack.library.files">
+ <fileset dir="${build-quick.dir}/classes/library"/>
+ <fileset dir="${build-quick.dir}/classes/continuations-library"/>
+ <fileset dir="${forkjoin-classes}"/>
+ </path>
+
+ <path id="pack.actors.files">
+ <fileset dir="${build-quick.dir}/classes/actors"/>
+ </path>
+
+ <path id="pack.compiler.files">
+ <fileset dir="${build-quick.dir}/classes/compiler"/>
+ <fileset dir="${build-quick.dir}/classes/repl"/>
+ <fileset dir="${build-quick.dir}/classes/scaladoc"/>
+ <fileset dir="${build-quick.dir}/classes/interactive"/>
+ <fileset dir="${asm-classes}"/>
+ </path>
+
+ <path id="pack.swing.files"> <fileset dir="${build-quick.dir}/classes/swing"/> </path>
+ <path id="pack.reflect.files"> <fileset dir="${build-quick.dir}/classes/reflect"/> </path>
+ <path id="pack.plugins.files"> <fileset dir="${build-quick.dir}/classes/continuations-plugin"/> </path>
+ <path id="pack.scalacheck.files"> <fileset dir="${build-quick.dir}/classes/scalacheck"/> </path>
+ <path id="pack.scalap.files"> <fileset dir="${build-quick.dir}/classes/scalap"/>
+ <fileset file="${src.dir}/scalap/decoder.properties"/> </path>
+
+ <path id="pack.partest.files">
+ <fileset dir="${build-quick.dir}/classes/partest">
+ <exclude name="scala/tools/partest/javaagent/**"/>
+ </fileset>
+ </path>
+
+ <path id="pack.partest-javaagent.files">
+ <fileset dir="${build-quick.dir}/classes/partest">
+ <include name="scala/tools/partest/javaagent/**"/>
+ </fileset>
+ </path>
<!-- STRAP -->
<path id="strap.library.build.path">
@@ -550,7 +630,6 @@ targets exercised:
<path refid="forkjoin.classpath"/>
<path refid="aux.libs"/>
</path>
- <path id="strap.actors.build.path"><path refid="strap.library.build.path"/></path>
<path id="strap.reflect.build.path">
<path refid="strap.library.build.path"/>
@@ -579,9 +658,18 @@ targets exercised:
<path id="partest.classpath">
<path refid="pack.compiler.path"/>
+ <path refid="partest.extras.classpath"/>
+ </path>
+
+ <!-- obsolete? -->
+ <!-- TODO - segregate swing tests (there can't be many) -->
+ <!--
+ <path id="partest.build.path">
+ <path refid="pack.compiler.path"/>
<fileset dir="${partest.dir}/files/lib" includes="*.jar" />
- <pathelement location="${pack.dir}/lib/scala-swing.jar"/> <!-- TODO - segregate swing tests (there can't be many) -->
+ <pathelement location="${pack.dir}/lib/scala-swing.jar"/>
</path>
+ -->
<path id="test.osgi.compiler.build.path">
<pathelement location="${test.osgi.classes}"/>
@@ -660,53 +748,39 @@ targets exercised:
<delete dir="${build-@{build}.dir}" includeemptydirs="yes" quiet="yes" failonerror="no"/>
</sequential>
</macrodef>
-
<!-- ===========================================================================
- LOCAL DEPENDENCY (Adapted ASM)
+ LOCAL DEPENDENCIES
============================================================================ -->
- <target name="asm.done" depends="init">
- <available file="${build-asm.dir}/asm.complete" property="asm.available"/>
- <if><not><isset property="asm.available"/></not><then>
- <stopwatch name="asm.lib.timer"/>
- <mkdir dir="${build-asm.dir}/classes/"/>
- <javac
- srcdir="${src.dir}/asm"
- destdir="${build-asm.dir}/classes"
- classpath="${build-asm.dir}/classes"
- includes="**/*.java"
- target="1.6" source="1.5">
- <compilerarg line="${javac.args} -XDignore.symbol.file"/>
- </javac>
- <stopwatch name="asm.lib.timer" action="total"/>
- <touch file="${build-asm.dir}/asm.complete" verbose="no"/>
- </then></if>
- </target>
+ <macrodef name="simple-javac" >
+ <attribute name="project"/> <!-- project: asm/forkjoin -->
+ <attribute name="args" default=""/>
+ <attribute name="jar" default="yes"/>
+ <sequential>
+ <uptodate property="@{project}.available" targetfile="${build-libs.dir}/@{project}.complete">
+ <srcfiles dir="${src.dir}/@{project}"/></uptodate>
+ <if><not><isset property="@{project}.available"/></not><then>
+ <stopwatch name="@{project}.timer"/>
+ <mkdir dir="${@{project}-classes}"/>
+ <javac
+ srcdir="${src.dir}/@{project}"
+ destdir="${@{project}-classes}"
+ classpath="${@{project}-classes}"
+ includes="**/*.java"
+ target="1.6" source="1.5"
+ compiler="javac1.6">
+ <compilerarg line="${javac.args} @{args}"/>
+ </javac>
+ <if><equals arg1="@{jar}" arg2="yes"/><then>
+ <jar whenmanifestonly="fail" destfile="${build-libs.dir}/@{project}.jar" basedir="${@{project}-classes}"/></then></if>
+ <stopwatch name="@{project}.timer" action="total"/>
+ <mkdir dir="${build-libs.dir}"/>
+ <touch file="${build-libs.dir}/@{project}.complete" verbose="no"/>
+ </then></if>
+ </sequential>
+ </macrodef>
-<!-- ===========================================================================
- LOCAL DEPENDENCY (FORKJOIN)
-============================================================================ -->
- <target name="forkjoin.done" depends="init">
- <uptodate property="forkjoin.available" targetfile="${build-libs.dir}/forkjoin.complete">
- <srcfiles dir="${src.dir}/forkjoin"/></uptodate>
- <if><not><isset property="forkjoin.available"/></not><then>
- <stopwatch name="forkjoin.lib.timer"/>
- <mkdir dir="${build-libs.dir}/classes/forkjoin"/>
- <javac
- fork="yes"
- compiler="javac1.6"
- srcdir="${src.dir}/forkjoin"
- destdir="${build-libs.dir}/classes/forkjoin"
- classpath="${build-libs.dir}/classes/forkjoin"
- includes="**/*.java"
- debug="true"
- target="1.6" source="1.5">
- <compilerarg line="${javac.args} -XDignore.symbol.file"/>
- </javac>
- <jar whenmanifestonly="fail" destfile="${build-libs.dir}/forkjoin.jar" basedir="${build-libs.dir}/classes/forkjoin"/>
- <stopwatch name="forkjoin.lib.timer" action="total"/>
- <touch file="${build-libs.dir}/forkjoin.complete" verbose="no"/>
- </then></if>
- </target>
+ <target name="asm.done" depends="init"> <simple-javac project="asm" jar="no"/> </target>
+ <target name="forkjoin.done" depends="init"> <simple-javac project="forkjoin" args="-XDignore.symbol.file"/></target>
<!-- ===========================================================================
STAGED COMPILATION MACROS
@@ -731,6 +805,49 @@ targets exercised:
</sequential>
</macrodef>
+ <!-- Zinc assumes a one-to-one correspondence of output folder to set of source files.
+ When compiling different sets of source files in multiple compilations to the same output directory,
+ Zinc thinks source files that appeared in an earlier compilation but are absent in the current one,
+ were deleted and thus deletes the corresponding output files.
+
+ Note that zinc also requires each arg to scalac to be prefixed by -S.
+ -->
+ <macrodef name="zinc">
+ <attribute name="compilerpathref" />
+ <attribute name="destdir" />
+ <attribute name="srcdir" />
+ <attribute name="srcpath" default="NOT SET"/> <!-- needed to compile the library, "NOT SET" is just a convention to denote an optional attribute -->
+ <attribute name="buildpathref" />
+ <attribute name="params" default="" />
+ <attribute name="java-excludes" default=""/>
+
+ <sequential>
+ <local name="sources"/>
+ <pathconvert pathsep=" " property="sources">
+ <fileset dir="@{srcdir}">
+ <include name="**/*.java"/>
+ <include name="**/*.scala"/>
+ <exclude name="@{java-excludes}"/>
+ </fileset>
+ </pathconvert>
+ <local name="args"/>
+ <local name="sargs"/>
+ <if><not><equals arg1="@{srcpath}" arg2="NOT SET"/></not><then>
+ <property name="args" value="@{params} -sourcepath @{srcpath}"/>
+ </then></if>
+ <property name="args" value="@{params}"/> <!-- default -->
+
+ <!-- HACK: prefix scalac args by -S -->
+ <script language="javascript">
+ project.setProperty("sargs", project.getProperty("args").trim().replaceAll(" ", " -S"));
+ </script>
+
+ <exec osfamily="unix" executable="tools/zinc" failifexecutionfails="true" failonerror="true">
+ <arg line="-nailed -compile-order JavaThenScala -scala-path ${ant.refid:@{compilerpathref}} -d @{destdir} -classpath ${toString:@{buildpathref}} ${sargs} ${sources}"/>
+ </exec>
+ </sequential>
+ </macrodef>
+
<macrodef name="staged-scalac" >
<attribute name="with"/> <!-- will use path `@{with}.compiler.path` to locate scalac -->
<attribute name="stage"/> <!-- current stage (locker, quick, strap) -->
@@ -739,33 +856,46 @@ targets exercised:
<attribute name="args" default=""/> <!-- additional args -->
<attribute name="destproject" default="@{project}"/> <!-- overrides the output directory; used when building multiple projects into the same directory-->
<attribute name="srcdir" default="@{project}"/>
- <element name="args" implicit="true" optional="true"/>
+ <attribute name="java-excludes" default=""/>
<sequential>
+ <!-- TODO: detect zinc anywhere on PATH
+ use zinc for the quick stage if it's available;
+ would use it for locker but something is iffy in sbt: get a class cast error on global phase -->
+ <if><and> <available file="tools/zinc"/>
+ <equals arg1="@{stage}" arg2="quick"/>
+ <not><equals arg1="@{project}" arg2="plugins"/></not> <!-- doesn't work in zinc because it requires the quick compiler, which isn't jarred up-->
+ </and><then>
+ <zinc taskname="Z.@{stage}.@{project}"
+ compilerpathref="@{with}.compiler.path"
+ destdir="${build-@{stage}.dir}/classes/@{destproject}"
+ srcdir="${src.dir}/@{srcdir}"
+ srcpath="@{srcpath}"
+ buildpathref="@{stage}.@{project}.build.path"
+ params="${scalac.args.@{stage}} @{args}"
+ java-excludes="@{java-excludes}"/></then>
+ <else>
<if><equals arg1="@{srcpath}" arg2="NOT SET"/><then>
<scalacfork taskname="@{stage}.@{project}"
- destdir="${build-@{stage}.dir}/classes/@{destproject}"
+ jvmargs="${scalacfork.jvmargs}"
compilerpathref="@{with}.compiler.path"
- params="${scalac.args.@{stage}} @{args}"
+ destdir="${build-@{stage}.dir}/classes/@{destproject}"
srcdir="${src.dir}/@{srcdir}"
- jvmargs="${scalacfork.jvmargs}">
+ params="${scalac.args.@{stage}} @{args}">
<include name="**/*.scala"/>
- <compilationpath refid="@{stage}.@{project}.build.path"/>
- <args/>
- </scalacfork></then>
+ <compilationpath refid="@{stage}.@{project}.build.path"/></scalacfork></then>
<else>
<scalacfork taskname="@{stage}.@{project}"
- destdir="${build-@{stage}.dir}/classes/@{destproject}"
+ jvmargs="${scalacfork.jvmargs}"
compilerpathref="@{with}.compiler.path"
- srcpath="@{srcpath}"
- params="${scalac.args.@{stage}} @{args}"
+ destdir="${build-@{stage}.dir}/classes/@{destproject}"
srcdir="${src.dir}/@{srcdir}"
- jvmargs="${scalacfork.jvmargs}">
+ srcpath="@{srcpath}"
+ params="${scalac.args.@{stage}} @{args}">
<include name="**/*.scala"/>
- <compilationpath refid="@{stage}.@{project}.build.path"/>
- <args/>
- </scalacfork></else>
+ <compilationpath refid="@{stage}.@{project}.build.path"/></scalacfork></else>
</if>
+ </else></if>
</sequential>
</macrodef>
@@ -793,20 +923,17 @@ targets exercised:
<attribute name="srcpath" default="NOT SET"/> <!-- needed to compile the library -->
<attribute name="args" default=""/> <!-- additional args -->
<attribute name="includes" default="comp.includes"/>
+ <attribute name="java-excludes" default=""/>
<attribute name="version" default=""/> <!-- non-empty for partest and scaladoc: use @{version}.version.number in property file-->
- <element name="pre" optional="true"/>
- <element name="post" optional="true"/>
-
<sequential>
<staged-uptodate stage="@{stage}" project="@{project}">
<check><srcfiles dir="${src.dir}/@{project}"/></check>
<do>
<stopwatch name="@{stage}.@{project}.timer"/>
<mkdir dir="${build-@{stage}.dir}/classes/@{project}"/>
- <pre/>
- <staged-scalac with="@{with}" stage="@{stage}" project="@{project}" srcpath="@{srcpath}" args="@{args}"/>
- <post/>
+ <staged-javac stage="@{stage}" project="@{project}" excludes="@{java-excludes}"/> <!-- always compile with javac for simplicity and regularity; it's cheap -->
+ <staged-scalac with="@{with}" stage="@{stage}" project="@{project}" srcpath="@{srcpath}" args="@{args}" java-excludes="@{java-excludes}"/>
<if><equals arg1="@{version}" arg2=""/><then>
<propertyfile file = "${build-@{stage}.dir}/classes/@{project}/@{project}.properties">
<entry key = "version.number" value="${version.number}"/>
@@ -871,15 +998,33 @@ targets exercised:
<attribute name="project"/>
<attribute name="targetdir" default="lib"/>
<attribute name="targetjar" default="scala-@{project}.jar"/>
- <element name="do" implicit="true"/>
+ <attribute name="destfile" default="${build-pack.dir}/@{targetdir}/@{targetjar}"/>
+ <attribute name="manifest" default=""/>
+ <element name="pre" optional="true"/>
+ <element name="jar-opts" optional="true"/>
<sequential>
- <uptodate property="pack.@{project}.available"
- targetfile="${build-pack.dir}/@{targetdir}/@{targetjar}"
- srcfile="${build-quick.dir}/@{project}.complete"/>
+ <uptodate property="pack.@{project}.available" targetfile="@{destfile}">
+ <srcresources>
+ <resources refid="pack.@{project}.files"/>
+ <!-- <path><pathelement location="${build-quick.dir}/@{project}.complete"/></path> -->
+ </srcresources>
+ </uptodate>
<if><not><isset property="pack.@{project}.available"/></not><then>
<mkdir dir="${build-pack.dir}/@{targetdir}"/>
- <do/>
+ <pre/>
+
+ <if><not><equals arg1="@{manifest}" arg2=""/></not><then>
+ <jar whenmanifestonly="fail" destfile="@{destfile}" manifest="@{manifest}"> <!-- update="true" makes no difference on my machine, so starting from scratch-->
+ <jar-opts/>
+ <path refid="pack.@{project}.files"/>
+ </jar></then>
+ <else>
+ <jar whenmanifestonly="fail" destfile="@{destfile}">
+ <jar-opts/>
+ <path refid="pack.@{project}.files"/>
+ </jar>
+ </else></if>
</then></if>
</sequential>
</macrodef>
@@ -897,7 +1042,8 @@ targets exercised:
<do>
<stopwatch name="docs.@{project}.timer"/>
<mkdir dir="${build-docs.dir}/@{project}"/>
- <if><equals arg1="@{classpathref}" arg2="NOT SET"/><then>
+ <if><equals arg1="@{docroot}" arg2="NOT SET"/><then>
+ <!-- TODO: introduce docs.@{project}.build.path for classpathref -->
<scaladoc
destdir="${build-docs.dir}/@{project}"
doctitle="@{title}"
@@ -940,16 +1086,20 @@ targets exercised:
<!-- ===========================================================================
LOCAL REFERENCE BUILD (LOCKER)
============================================================================ -->
- <target name="locker.start" depends="asm.done, forkjoin.done">
+ <target name="locker.start" depends="asm.done, forkjoin.done">
<condition property="locker.locked"><available file="${build-locker.dir}/locker.locked"/></condition></target>
- <target name="locker.lib" depends="locker.start" unless="locker.locked">
- <staged-build with="starr" stage="locker" project="library" srcpath="${src.dir}/library" includes="lib.includes">
- <pre><staged-javac stage="locker" project="library" args="-XDignore.symbol.file"/></pre></staged-build></target>
- <!-- TODO: args="-XDignore.symbol.file" necessary?? -->
+ <target name="locker.lib" depends="locker.start" unless="locker.locked">
+ <staged-build with="starr" stage="locker" project="library" srcpath="${src.dir}/library" includes="lib.includes"/></target>
+
+ <target name="locker.actors" depends="locker.lib" unless="locker.locked">
+ <staged-build with="starr" stage="locker" project="actors"/> </target>
- <target name="locker.reflect" depends="locker.lib" unless="locker.locked"> <staged-build with="starr" stage="locker" project="reflect"/></target>
- <target name="locker.comp" depends="locker.reflect" unless="locker.locked"> <staged-build with="starr" stage="locker" project="compiler"/></target>
+ <target name="locker.reflect" depends="locker.lib" unless="locker.locked">
+ <staged-build with="starr" stage="locker" project="reflect"/></target>
+
+ <target name="locker.comp" depends="locker.reflect" unless="locker.locked">
+ <staged-build with="starr" stage="locker" project="compiler"/></target>
<target name="locker.done" depends="locker.comp">
<mkdir dir="${build-locker.dir}"/>
@@ -961,62 +1111,43 @@ targets exercised:
<!-- ===========================================================================
QUICK BUILD (QUICK)
============================================================================ -->
- <target name="quick.start" depends="locker.done"/>
+ <target name="quick.start" depends="locker.done"/>
- <target name="quick.lib" depends="quick.start">
- <staged-build with="locker" stage="quick" project="library" srcpath="${src.dir}/library" includes="lib.rootdoc.includes">
- <pre>
- <staged-javac stage="quick" project="library" args="-XDignore.symbol.file"/> <!-- TODO: args="-XDignore.symbol.file" necessary?? -->
- <staged-javac stage="quick" project="actors" destproject="library"/>
- </pre>
- <post>
- <staged-scalac with="locker" stage="quick" project="actors" destproject="library"/>
- </post>
- </staged-build>
- </target>
+ <target name="quick.lib" depends="quick.start">
+ <staged-build with="locker" stage="quick" project="library" srcpath="${src.dir}/library" includes="lib.rootdoc.includes"/></target>
- <target name="quick.reflect" depends="quick.lib"> <staged-build with="locker" stage="quick" project="reflect"/> </target>
+ <target name="quick.actors" depends="quick.lib">
+ <staged-build with="locker" stage="quick" project="actors"/> </target>
- <target name="quick.comp" depends="quick.reflect">
- <staged-build with="locker" stage="quick" project="compiler"/>
- </target>
+ <target name="quick.reflect" depends="quick.lib">
+ <staged-build with="locker" stage="quick" project="reflect"/> </target>
- <target name="quick.repl" depends="quick.comp">
- <staged-build with="locker" stage="quick" project="repl">
- <pre>
- <staged-javac stage="quick" project="repl"/>
- </pre>
- </staged-build>
- </target>
+ <target name="quick.comp" depends="quick.reflect">
+ <staged-build with="locker" stage="quick" project="compiler"/> </target>
- <target name="quick.scalacheck" depends="quick.lib">
- <staged-build with="locker" stage="quick" project="scalacheck" args="-nowarn"/>
- </target>
+ <target name="quick.repl" depends="quick.comp">
+ <staged-build with="locker" stage="quick" project="repl"/> </target>
- <target name="quick.scalap" depends="quick.repl">
- <staged-build with="locker" stage="quick" project="scalap"/>
- </target>
+ <target name="quick.scalacheck" depends="quick.actors, quick.lib">
+ <staged-build with="locker" stage="quick" project="scalacheck" args="-nowarn"/> </target>
- <target name="quick.partest" depends="quick.scalap, quick.repl, asm.done">
- <staged-build with="locker" stage="quick" project="partest" version="partest">
- <pre><staged-javac stage="quick" project="partest"/></pre>
- </staged-build>
- </target>
+ <target name="quick.scalap" depends="quick.repl">
+ <staged-build with="locker" stage="quick" project="scalap"/> </target>
+
+ <target name="quick.partest" depends="quick.scalap, quick.repl, asm.done">
+ <staged-build with="locker" stage="quick" project="partest" version="partest"/> </target>
<target name="quick.scaladoc" depends="quick.comp, quick.partest">
- <staged-build with="locker" stage="quick" project="scaladoc" version="scaladoc"/>
- </target>
+ <staged-build with="locker" stage="quick" project="scaladoc" version="scaladoc"/> </target>
<target name="quick.interactive" depends="quick.comp, quick.scaladoc">
- <staged-build with="locker" stage="quick" project="interactive"/>
- </target>
+ <staged-build with="locker" stage="quick" project="interactive"/> </target>
- <target name="quick.swing" depends="quick.lib" if="has.java6">
- <staged-build with="locker" stage="quick" project="swing"/>
- </target>
+ <target name="quick.swing" depends="quick.actors, quick.lib" if="has.java6">
+ <staged-build with="locker" stage="quick" project="swing"/> </target>
- <target name="quick.plugins" depends="quick.comp">
- <staged-uptodate stage="quick" project="plugins">
+ <target name="quick.plugins" depends="quick.comp">
+ <staged-uptodate stage="quick" project="plugins">
<check><srcfiles dir="${src.dir}/continuations"/></check>
<do>
<stopwatch name="quick.plugins.timer"/>
@@ -1033,158 +1164,99 @@ targets exercised:
<!-- might split off library part into its own ant target -->
<mkdir dir="${build-quick.dir}/classes/continuations-library"/>
- <!-- have to compile with quick compiler here! -->
+ <!-- TODO: must build with quick to avoid
+ [quick.plugins] error: java.lang.NoClassDefFoundError: scala/tools/nsc/transform/patmat/PatternMatching
+ [quick.plugins] at scala.tools.selectivecps.SelectiveCPSTransform.newTransformer(SelectiveCPSTransform.scala:29)
+
+ WHY OH WHY!? scala/tools/nsc/transform/patmat/PatternMatching should be on locker.compiler.path
+ -->
<staged-scalac with="quick" stage="quick" project="plugins"
srcdir="continuations/library" destproject="continuations-library"
- args="-Xplugin-require:continuations -P:continuations:enable">
- <compilerarg value="-Xpluginsdir"/>
- <compilerarg file="${build-quick.dir}/misc/scala-devel/plugins"/>
- </staged-scalac>
+ args="-Xplugin-require:continuations -P:continuations:enable -Xpluginsdir ${build-quick.dir}/misc/scala-devel/plugins"/>
<stopwatch name="quick.plugins.timer" action="total"/>
</do>
</staged-uptodate>
</target>
- <target name="quick.bin" depends="init">
+ <target name="quick.bin" depends="quick.lib, quick.reflect, quick.comp, quick.repl, quick.scalacheck, quick.scalap, quick.interactive, quick.swing, quick.plugins, quick.partest, quick.scaladoc">
<staged-bin stage="quick" classpathref="quick.bin.tool.path"/>
</target>
- <target name="quick.done" depends="quick.lib, quick.reflect, quick.comp, quick.repl, quick.scalacheck, quick.scalap, quick.interactive, quick.swing, quick.plugins, quick.partest, quick.scaladoc, quick.bin"/>
+ <target name="quick.done" depends="quick.bin"/>
<target name="quick-opt" description="Optimized version of quick.done."> <optimized name="quick.done"/></target>
<!-- ===========================================================================
PACKED QUICK BUILD (PACK)
============================================================================ -->
- <target name="pack.lib" depends="quick.lib, quick.plugins, forkjoin.done">
- <staged-pack project="library">
- <!-- First copy maven dependencies -->
- <copy todir="${build-pack.dir}/lib">
- <fileset refid="dependency.fileset" />
- <mapper type="flatten" />
- </copy>
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-library.jar">
- <fileset dir="${build-quick.dir}/classes/library">
- <exclude name="scala/swing/**"/>
- <exclude name="scala/actors/**"/>
- </fileset>
- <fileset dir="${build-quick.dir}/classes/continuations-library"/>
- <fileset dir="${build-libs.dir}/classes/forkjoin"/>
- </jar>
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-actors.jar">
- <fileset dir="${build-quick.dir}/classes/library">
- <include name="scala/actors/**"/>
- </fileset>
- </jar>
- </staged-pack>
- </target>
-
- <target name="pack.swing" depends="quick.swing" if="has.java6">
- <staged-pack project="swing’">
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-swing.jar" basedir="${build-quick.dir}/classes/swing"/>
- </staged-pack>
- </target>
-
- <target name="pack.reflect" depends="quick.reflect">
- <staged-pack project="reflect’">
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-reflect.jar" basedir="${build-quick.dir}/classes/reflect"/>
- </staged-pack>
- </target>
-
- <target name="pack.comp" depends="quick.comp, quick.scaladoc, quick.interactive, quick.repl, asm.done">
- <staged-pack project="compiler">
- <mkdir dir="${build-pack.dir}/META-INF"/>
- <copy file="META-INF/MANIFEST.MF" toDir="${build-pack.dir}/META-INF"/>
- <manifest file="${build-pack.dir}/META-INF/MANIFEST.MF" mode="update">
- <attribute name="Bundle-Version" value="${version.number}"/>
- <attribute name="Class-Path" value="scala-reflect.jar scala-library.jar"/>
- </manifest>
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-compiler.jar" manifest="${build-pack.dir}/META-INF/MANIFEST.MF">
+ <target name="pack.lib" depends="quick.lib, quick.plugins, forkjoin.done">
+ <staged-pack project="library"/></target>
+
+ <target name="pack.actors" depends="quick.lib"> <staged-pack project="actors"/> </target>
+ <target name="pack.swing" if="has.java6" depends="quick.swing"> <staged-pack project="swing"/> </target>
+ <target name="pack.reflect" depends="quick.reflect"> <staged-pack project="reflect"/> </target>
+
+ <target name="pack.comp" depends="quick.comp, quick.scaladoc, quick.interactive, quick.repl, asm.done">
+ <staged-pack project="compiler" manifest="${build-pack.dir}/META-INF/MANIFEST.MF">
+ <pre> <!-- TODO the files copied here do not influence actuality of this target (nor does the manifest) -->
+ <copy file="${jline.jar}" toDir="${build-pack.dir}/lib"/>
+ <copy todir="${build-pack.dir}/lib">
+ <fileset dir="${lib-extra.dir}">
+ <include name="**/*.jar"/>
+ </fileset>
+ </copy>
+ <mkdir dir="${build-pack.dir}/META-INF"/>
+ <copy file="${basedir}/META-INF/MANIFEST.MF" toDir="${build-pack.dir}/META-INF"/>
+ <manifest file="${build-pack.dir}/META-INF/MANIFEST.MF" mode="update">
+ <attribute name="Bundle-Version" value="${version.number}"/>
+ <attribute name="Class-Path" value="scala-reflect.jar scala-library.jar"/>
+ </manifest>
+ </pre>
+ <jar-opts>
<service type="javax.script.ScriptEngineFactory" provider="scala.tools.nsc.interpreter.IMain$Factory"/>
- <fileset dir="${build-quick.dir}/classes/compiler"/>
- <fileset dir="${build-quick.dir}/classes/scaladoc"/>
- <fileset dir="${build-quick.dir}/classes/interactive"/>
- <fileset dir="${build-quick.dir}/classes/repl"/>
- <fileset dir="${build-asm.dir}/classes"/>
- </jar>
- <copy file="${jline.jar}" toDir="${build-pack.dir}/lib"/>
- <copy todir="${build-pack.dir}/lib">
- <fileset dir="${lib-extra.dir}">
- <include name="**/*.jar"/>
- </fileset>
- </copy>
+ </jar-opts>
</staged-pack>
</target>
- <target name="pack.plugins" depends="quick.plugins">
- <staged-pack project="plugins" targetdir="misc/scala-devel/plugins" targetjar="continuations.jar">
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/misc/scala-devel/plugins/continuations.jar" basedir="${build-quick.dir}/classes/continuations-plugin"/>
- </staged-pack>
- </target>
-
- <target name="pack.scalacheck" depends="quick.scalacheck">
- <uptodate property="pack.scalacheck.available"
- targetfile="${build-pack.dir}/lib/scalacheck.jar">
- <srcfiles dir="${build-quick.dir}/classes/scalacheck"/></uptodate>
- <if><not><isset property="pack.scalacheck.available"/></not><then>
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scalacheck.jar" basedir="${build-quick.dir}/classes/scalacheck"/>
- </then></if>
- </target>
+ <target name="pack.plugins" depends="quick.plugins"> <staged-pack project="plugins" targetdir="misc/scala-devel/plugins" targetjar="continuations.jar"/> </target>
+ <target name="pack.scalacheck" depends="quick.scalacheck"> <staged-pack project="scalacheck" targetjar="scalacheck.jar"/> </target>
<target name="pack.partest" depends="quick.partest">
- <staged-pack project="partest">
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-partest.jar">
- <fileset dir="${build-quick.dir}/classes/partest">
- <exclude name="scala/tools/partest/javaagent/**"/>
- </fileset>
- </jar>
- <jar whenmanifestonly="fail" destfile = "${build-pack.dir}/lib/scala-partest-javaagent.jar"
- manifest = "${src.dir}/partest/scala/tools/partest/javaagent/MANIFEST.MF">
- <fileset dir = "${build-quick.dir}/classes/partest">
- <include name = "scala/tools/partest/javaagent/**"/>
- </fileset>
- </jar>
- </staged-pack>
+ <staged-pack project="partest"/>
+ <!-- TODO the manifest should influence actuality of this target -->
+ <staged-pack project="partest-javaagent" manifest="${src.dir}/partest/scala/tools/partest/javaagent/MANIFEST.MF"/>
</target>
- <target name="pack.scalap" depends="quick.scalap">
- <staged-pack project="plugins" targetjar="scalap.jar">
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scalap.jar">
- <fileset dir="${build-quick.dir}/classes/scalap"/>
- <fileset file="${src.dir}/scalap/decoder.properties"/>
- </jar>
- </staged-pack>
- </target>
+ <target name="pack.scalap" depends="quick.scalap"> <staged-pack project="scalap" targetjar="scalap.jar"/> </target>
- <target name="pack.bin" depends="pack.comp, pack.lib, pack.partest, pack.plugins, pack.reflect, pack.scalacheck, pack.scalap, pack.swing">
+ <target name="pack.bin" depends="pack.comp, pack.lib, pack.actors, pack.partest, pack.plugins, pack.reflect, pack.scalacheck, pack.scalap, pack.swing">
<staged-bin stage="pack"/>
</target>
- <target name="pack.done" depends="pack.bin">
+ <!-- depend on quick.done so quick.bin is run when pack.done is -->
+ <target name="pack.done" depends="quick.done, pack.bin">
+ <!-- copy dependencies to build/pack/lib, it only takes a second so don't bother with uptodate checks -->
+ <copy todir="${build-pack.dir}/lib">
+ <resources refid="partest.extras.fileset"/>
+ <mapper classpathref="maven-ant-tasks.classpath" classname="org.apache.maven.artifact.ant.VersionMapper"
+ from="${partest.extras.versions}" to="flatten"/>
+ </copy>
+
<taskdef resource="scala/tools/ant/antlib.xml" classpathref="pack.compiler.path"/>
- <taskdef resource="scala/tools/partest/antlib.xml" classpathref="pack.compiler.path"/>
+ <taskdef resource="scala/tools/partest/antlib.xml" classpathref="partest.classpath"/>
</target>
<!-- ===========================================================================
BOOTSTRAPPING BUILD (STRAP)
============================================================================ -->
- <target name="strap.lib" depends="quick.done">
- <staged-build with="quick" stage="strap" project="library" srcpath="${src.dir}/library" includes="lib.rootdoc.includes">
- <pre>
- <staged-javac stage="strap" project="library" args="-XDignore.symbol.file"/> <!-- TODO: args="-XDignore.symbol.file" necessary?? -->
- <staged-javac stage="strap" project="actors" destproject="library"/>
- </pre>
- <post>
- <staged-scalac with="quick" stage="strap" project="actors" destproject="library"/>
- </post>
- </staged-build>
+ <target name="strap.done" depends="pack.done">
+ <staged-build with="pack" stage="strap" project="library" srcpath="${src.dir}/library" includes="lib.rootdoc.includes"/>
+ <staged-build with="pack" stage="strap" project="reflect"/>
+ <staged-build with="pack" stage="strap" project="compiler"/>
</target>
- <target name="strap.reflect" depends="strap.lib"> <staged-build with="pack" stage="strap" project="reflect"/> </target>
- <target name="strap.comp" depends="strap.reflect"> <staged-build with="pack" stage="strap" project="compiler"/> </target>
- <target name="strap.done" depends="strap.comp"/>
<target name="strap-opt" description="Optimized version of strap.done."> <optimized name="strap.done"/></target>
@@ -1195,13 +1267,13 @@ targets exercised:
<mkdir dir="${build-palo.dir}/lib"/>
<jar whenmanifestonly="fail" destfile="${build-palo.dir}/lib/scala-library.jar">
<fileset dir="${build-locker.dir}/classes/library"/>
- <fileset dir="${build-libs.dir}/classes/forkjoin"/>
+ <fileset dir="${forkjoin-classes}"/>
</jar>
<jar whenmanifestonly="fail" destfile="${build-palo.dir}/lib/scala-reflect.jar" manifest="${basedir}/META-INF/MANIFEST.MF"
basedir="${build-locker.dir}/classes/reflect"/>
<jar whenmanifestonly="fail" destfile="${build-palo.dir}/lib/scala-compiler.jar" manifest="${basedir}/META-INF/MANIFEST.MF">
<fileset dir="${build-locker.dir}/classes/compiler"/>
- <fileset dir="${build-asm.dir}/classes/"/>
+ <fileset dir="${asm-classes}"/>
</jar>
<copy file="${jline.jar}" toDir="${build-palo.dir}/lib"/>
</target>
@@ -1279,7 +1351,7 @@ targets exercised:
TEST SUITE
============================================================================ -->
<!-- bootstrapping stability: compare {quick,strap}/(lib|reflect|comp) -->
- <target name="test.stability" depends="quick.lib, quick.reflect, quick.comp, strap.lib, strap.reflect, strap.comp">
+ <target name="test.stability" depends="strap.done">
<exec osfamily="unix" vmlauncher="false" executable="${basedir}/tools/stability-test.sh" failonerror="true" />
<!-- I think doing it this way means it will auto-pass on windows... that's the idea. If not, something like this. -->
<!-- <exec osfamily="windows" executable="foo" failonerror="false" failifexecutionfails="false" /> -->
@@ -1361,121 +1433,109 @@ targets exercised:
<stopwatch name="quick.sbt-interface.timer" action="total"/>
</target>
- <property name="partest.srcdir" value="files" /> <!-- TODO: make targets for `pending` and other subdirs -->
+ <!-- See test/build-partest.xml for the macro(s) being used here. -->
- <target name="test.run" depends="pack.done">
- <partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
- timeout="1200000"
- srcdir="${partest.srcdir}"
- scalacopts="${scalac.args.optimise}">
-
- <compilationpath refid="partest.classpath"/>
- <runtests dir="${partest.dir}/${partest.srcdir}/run" includes="*.scala"/>
- <jvmtests dir="${partest.dir}/${partest.srcdir}/jvm" includes="*.scala"/>
- </partest>
+ <target name="test.suite" depends="pack.done">
+ <testSuite/>
</target>
- <target name="test.suite" depends="pack.done">
- <partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
- timeout="2400000"
- srcdir="${partest.srcdir}"
- scalacopts="${scalac.args.optimise}">
- <compilationpath refid="partest.classpath"/>
- <postests dir="${partest.dir}/${partest.srcdir}/pos" includes="*.scala"/>
- <negtests dir="${partest.dir}/${partest.srcdir}/neg" includes="*.scala"/>
- <runtests dir="${partest.dir}/${partest.srcdir}/run" includes="*.scala"/>
- <jvmtests dir="${partest.dir}/${partest.srcdir}/jvm" includes="*.scala"/>
- <residenttests dir="${partest.dir}/${partest.srcdir}/res" includes="*.res"/>
- <scalaptests dir="${partest.dir}/${partest.srcdir}/scalap" includes="**/*.scala"/>
- <scalachecktests dir="${partest.dir}/${partest.srcdir}/scalacheck">
- <include name="*.scala"/>
- </scalachecktests>
- <specializedtests dir="${partest.dir}/${partest.srcdir}/specialized">
- <include name="*.scala"/>
- </specializedtests>
- <instrumentedtests dir="${partest.dir}/${partest.srcdir}/instrumented">
- <include name="*.scala"/>
- </instrumentedtests>
- </partest>
+ <target name="test.suite.color" depends="pack.done">
+ <testSuite colors="8"/>
+ </target>
+
+ <target name="test.run" depends="pack.done">
+ <testSuite kinds="run jvm"/>
</target>
<target name="test.continuations.suite" depends="pack.done">
- <partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
- timeout="2400000"
- srcdir="${partest.srcdir}"
- scalacopts="${scalac.args.optimise} -Xplugin-require:continuations -P:continuations:enable">
- <compilerarg value="-Xpluginsdir"/>
- <compilerarg file="${build-quick.dir}/misc/scala-devel/plugins"/>
- <compilationpath refid="partest.classpath"/>
- <negtests dir="${partest.dir}/${partest.srcdir}/continuations-neg" includes="*.scala"/>
- <runtests dir="${partest.dir}/${partest.srcdir}/continuations-run" includes="*.scala"/>
- </partest>
+ <testSuite kinds="continuations-neg continuations-run"
+ scalacOpts="${scalac.args.optimise} -Xpluginsdir ${build-quick.dir}/misc/scala-devel/plugins -Xplugin-require:continuations -P:continuations:enable"
+ />
</target>
<target name="test.scaladoc" depends="pack.done">
- <partest erroronfailed="yes" scalacopts="${scalac.args.optimise}" showlog="yes">
- <compilationpath refid="partest.classpath"/>
- <runtests dir="${partest.dir}/scaladoc/run" includes="*.scala" />
- <scalachecktests dir="${partest.dir}/scaladoc/scalacheck" includes="*.scala" />
- </partest>
+ <testSuite kinds="run scalacheck" srcdir="scaladoc"/>
</target>
<target name="test.interactive" depends="pack.done">
- <partest erroronfailed="yes" scalacopts="${scalac.args.optimise}" showlog="yes">
- <compilationpath refid="partest.classpath"/>
- <presentationtests dir="${partest.dir}/${partest.srcdir}/presentation">
- <include name="*/*.scala"/>
- </presentationtests>
- </partest>
+ <testSuite kinds="presentation"/>
</target>
-<!-- currently disabled: test.ant, test.bc, test.positions, test.classload -->
- <target name="test.done" depends="test.osgi, test.sbt, test.interactive, test.continuations.suite, test.suite, test.scaladoc, test.stability"/>
-
+ <!-- for use in PR validation, where stability is rarely broken, so we're going to use starr for locker,
+ and skip test.stability (which requires locker == quick) -->
+ <target name="test.core" depends="test.osgi, test.sbt, test.bc, test.interactive, test.continuations.suite, test.scaladoc, test.suite"/>
+ <target name="test.done" depends="test.core, test.stability"/>
<!-- ===========================================================================
BINARY COMPATIBILITY TESTING
============================================================================ -->
<target name="bc.init" depends="init" unless="maven-deps-done-mima">
+ <property name="bc-reference-version" value="2.11.0"/>
+
<property name="bc-build.dir" value="${build.dir}/bc"/>
<!-- Obtain mima -->
<mkdir dir="${bc-build.dir}"/>
<!-- Pull down MIMA -->
<artifact:dependencies pathId="mima.classpath">
- <dependency groupId="com.typesafe" artifactId="mima-reporter_2.9.2" version="0.1.4"/>
+ <dependency groupId="com.typesafe" artifactId="mima-reporter_2.9.2" version="0.1.5"/>
</artifact:dependencies>
<artifact:dependencies pathId="old.bc.classpath">
- <dependency groupId="org.scala-lang" artifactId="scala-library" version="2.10.0-RC2"/>
- <dependency groupId="org.scala-lang" artifactId="scala-reflect" version="2.10.0-RC2"/>
+ <dependency groupId="org.scala-lang" artifactId="scala-swing" version="${bc-reference-version}"/>
+ <dependency groupId="org.scala-lang" artifactId="scala-library" version="${bc-reference-version}"/>
+ <dependency groupId="org.scala-lang" artifactId="scala-reflect" version="${bc-reference-version}"/>
</artifact:dependencies>
<property name="maven-deps-done-mima" value="true"/>
</target>
- <target name="test.bc" depends="bc.init, pack.lib">
- <java
- fork="true"
- failonerror="true"
- classname="com.typesafe.tools.mima.cli.Main">
- <arg value="--prev"/>
- <arg value="${org.scala-lang:scala-library:jar}"/>
- <arg value="--curr"/>
- <arg value="${build-pack.dir}/lib/scala-library.jar"/>
- <classpath>
- <path refid="mima.classpath"/>
- </classpath>
- </java>
- <java
- fork="true"
- failonerror="true"
- classname="com.typesafe.tools.mima.cli.Main">
- <arg value="--prev"/>
- <arg value="${org.scala-lang:scala-reflect:jar}"/>
- <arg value="--curr"/>
- <arg value="${build-pack.dir}/lib/scala-reflect.jar"/>
- <classpath>
- <path refid="mima.classpath"/>
- </classpath>
- </java>
+ <macrodef name="bc.run-mima">
+ <attribute name="jar-name"/>
+ <attribute name="prev"/>
+ <attribute name="curr"/>
+ <attribute name="direction"/>
+ <sequential>
+ <echo message="Checking @{direction} binary compatibility for @{jar-name} (against ${bc-reference-version})"/>
+ <java taskname="mima"
+ fork="true"
+ failonerror="true"
+ classname="com.typesafe.tools.mima.cli.Main">
+ <arg value="--prev"/>
+ <arg value="@{prev}"/>
+ <arg value="--curr"/>
+ <arg value="@{curr}"/>
+ <arg value="--filters"/>
+ <arg value="${basedir}/bincompat-@{direction}.whitelist.conf"/>
+ <arg value="--generate-filters"/>
+ <classpath>
+ <path refid="mima.classpath"/>
+ </classpath>
+ </java>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="bc.check">
+ <attribute name="jar-name"/>
+ <sequential>
+ <bc.run-mima
+ jar-name="@{jar-name}"
+ prev="${org.scala-lang:@{jar-name}:jar}"
+ curr="${build-pack.dir}/lib/@{jar-name}.jar"
+ direction="backward"/>
+ <bc.run-mima
+ jar-name="@{jar-name}"
+ prev="${build-pack.dir}/lib/@{jar-name}.jar"
+ curr="${org.scala-lang:@{jar-name}:jar}"
+ direction="forward"/>
+ </sequential>
+ </macrodef>
+
+ <target name="test.bc-opt" description="Optimized version of test.bc."> <optimized name="test.bc"/></target>
+
+ <!-- Enable after the release of the 2.11.0 or a prior RC that estabilishes the new baseline. -->
+ <target name="test.bc"></target>
+ <target name="test.bc.disabled" depends="bc.init, pack.lib, pack.reflect, pack.swing">
+ <bc.check jar-name="scala-library"/>
+ <bc.check jar-name="scala-reflect"/>
+ <bc.check jar-name="scala-swing"/>
</target>
<!-- ===========================================================================
@@ -1509,6 +1569,7 @@ targets exercised:
<include name="swing/**"/>
<include name="actors/**"/>
<include name="reflect/**"/>
+ <include name="continuations/library/**"/>
</srcfiles></check>
<do>
<stopwatch name="docs.lib.timer"/>
@@ -1656,6 +1717,13 @@ targets exercised:
<include name="scalap.jar"/>
</fileset>
</copy>
+
+ <copy todir="${dist.dir}/lib">
+ <resources refid="partest.extras.fileset"/>
+ <mapper classpathref="maven-ant-tasks.classpath" classname="org.apache.maven.artifact.ant.VersionMapper"
+ from="${partest.extras.versions}" to="flatten"/>
+ </copy>
+
<mkdir dir="${dist.dir}/bin"/>
<!-- TODO - Stop being inefficient and don't copy OSGi bundles overtop other jars. -->
<copy-bundle name="scala-library"/>
@@ -1804,7 +1872,7 @@ targets exercised:
</target>
<target name="replacestarr-opt" description="Replaces the Starr compiler and library by fresh, optimised ones built from current sources and tests them.">
- <optimize name="replacestarr"/></target>
+ <optimized name="replacestarr"/></target>
<!-- Ant on Windows is not able to delete jar files that are referenced in any <path>.
See ticket 1290 on trac. -->
@@ -1821,13 +1889,13 @@ targets exercised:
</target>
<target name="replacestarrwin-opt" description="Creates a new Starr on Windows. Manually execute 'ant locker.clean build' first!">
- <optimize name="replacestarrwin"/></target>
+ <optimized name="replacestarrwin"/></target>
<target name="replacelocker" description="Replaces the Locker compiler and library by fresh ones built from current sources."
depends="palo.clean, locker.unlock, palo.done"/>
<target name="replacelocker-opt" description="Replaces the Locker compiler and library by fresh, optimised ones built from current sources.">
- <optimize name="replacelocker"/></target>
+ <optimized name="replacelocker"/></target>
<target name="buildlocker" description="Does the same for locker as build does for quick." depends="locker.unlock, palo.bin"/>
<target name="unlocklocker" description="Same as buildlocker." depends="buildlocker"/> <!-- REMOVE -->
@@ -1846,105 +1914,6 @@ targets exercised:
<target name="fastlocker" description="Buildlocker without extra fuss" depends="fastlocker.comp"/>
-
-<!-- ===========================================================================
- TODO: FIX OR REMOVE
-============================================================================ -->
-
- <!-- not called by test target -->
- <target name="test.classload" depends="pack.done">
- <!-- TODO - Add actors + reflect to this -->
- <classloadVerify classpath="${build-pack.dir}/lib/scala-library.jar" />
- </target>
-
- <!-- not called by test target -->
- <target name="test.ant" depends="pack.done">
- <partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
- srcdir="${partest.srcdir}"
- scalacopts="${scalac.args.optimise}">
- <compilationpath refid="partest.classpath"/>
- <anttests dir="${partest.dir}/${partest.srcdir}/ant" includes="*build.xml"/>
- </partest>
- </target>
-
- <!-- not called by test target -->
- <target name="test.positions" depends="quick.comp">
- <antcall target="test.positions.tests.sub" inheritRefs="true">
- <param name="test.tests.srcs" value="${partest.dir}/files/positions"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/compiler"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/library"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/actors"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/dbc"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/swing"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/partest"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/scalap"/>
- </antcall>
- <antcall target="test.positions.tests.sub" inheritRefs="true">
- <param name="test.tests.srcs" value="${partest.dir}/files/pos"/>
- </antcall>
- <antcall target="test.positions.tests.sub" inheritRefs="true">
- <param name="test.tests.srcs" value="${partest.dir}/files/run"/>
- </antcall>
- <antcall target="test.positions.tests.sub" inheritRefs="true">
- <param name="test.tests.srcs" value="${partest.dir}/files/neg"/>
- </antcall>
- </target>
-
- <target name="test.positions.sub">
- <echo message="Validating positions for: ${test.srcs}"/>
- <if>
- <isfileselected file="${test.srcs}">
- <type type="dir"/>
- </isfileselected>
- <then>
- <property name="srcdir" value="${test.srcs}"/>
- <property name="srcs" value="**/*.scala"/>
- </then>
- <else>
- <dirname property="srcdir" file="${test.srcs}"/>
- <basename property="srcs" file="${test.srcs}"/>
- </else>
- </if>
- <scalacfork
- destdir=""
- compilerpathref="locker.compiler.path"
- srcpath="${srcdir}"
- params="-Xprint-pos -Yide-debug"
- srcdir="${srcdir}"
- jvmargs="${scalacfork.jvmargs}">
- <include name="${srcs}"/>
- <compilationpath refid="test.positions.sub.build.path"/>
- </scalacfork>
- </target>
-
- <target name="test.positions.tests.sub">
- <foreach target="test.positions.sub"
- inheritAll="true"
- inheritRefs="true"
- param="test.srcs">
- <path>
- <fileset dir="${test.tests.srcs}" includes="*.scala"/>
- <dirset dir="${test.tests.srcs}">
- <include name="*"/>
- </dirset>
- </path>
- </foreach>
- </target>
-
<!-- ===========================================================================
VISUALIZATION
============================================================================ -->
diff --git a/src/compiler/scala/reflect/macros/runtime/Reifiers.scala b/src/compiler/scala/reflect/macros/runtime/Reifiers.scala
index 8bb388be8f..7ec3457c6a 100644
--- a/src/compiler/scala/reflect/macros/runtime/Reifiers.scala
+++ b/src/compiler/scala/reflect/macros/runtime/Reifiers.scala
@@ -60,15 +60,15 @@ trait Reifiers {
def logFreeVars(symtab: SymbolTable): Unit =
// logging free vars only when they are untyped prevents avalanches of duplicate messages
symtab.syms map (sym => symtab.symDef(sym)) foreach {
- case FreeTermDef(_, _, binding, _, origin) if universe.settings.logFreeTerms.value && binding.tpe == null =>
+ case FreeTermDef(_, _, binding, _, origin) if universe.settings.logFreeTerms && binding.tpe == null =>
reporter.echo(position, "free term: %s %s".format(showRaw(binding), origin))
- case FreeTypeDef(_, _, binding, _, origin) if universe.settings.logFreeTypes.value && binding.tpe == null =>
+ case FreeTypeDef(_, _, binding, _, origin) if universe.settings.logFreeTypes && binding.tpe == null =>
reporter.echo(position, "free type: %s %s".format(showRaw(binding), origin))
case _ =>
// do nothing
}
- if (universe.settings.logFreeTerms.value || universe.settings.logFreeTypes.value)
+ if (universe.settings.logFreeTerms || universe.settings.logFreeTypes)
reification match {
case ReifiedTree(_, _, symtab, _, _, _, _) => logFreeVars(symtab)
case ReifiedType(_, _, symtab, _, _, _) => logFreeVars(symtab)
diff --git a/src/compiler/scala/reflect/reify/Phases.scala b/src/compiler/scala/reflect/reify/Phases.scala
index d43532090c..4572caeb36 100644
--- a/src/compiler/scala/reflect/reify/Phases.scala
+++ b/src/compiler/scala/reflect/reify/Phases.scala
@@ -25,7 +25,7 @@ trait Phases extends Reshape
if (reifyDebug) println("[reshape phase]")
tree = reshape.transform(tree)
if (reifyDebug) println("[interlude]")
- if (reifyDebug) println("reifee = " + (if (settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString))
+ if (reifyDebug) println("reifee = " + (if (settings.Xshowtrees || settings.XshowtreesCompact || settings.XshowtreesStringified) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString))
if (reifyDebug) println("[calculate phase]")
calculate.traverse(tree)
diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala
index 9cf069fe98..11857e2172 100644
--- a/src/compiler/scala/reflect/reify/Reifier.scala
+++ b/src/compiler/scala/reflect/reify/Reifier.scala
@@ -57,7 +57,7 @@ abstract class Reifier extends States
val result = reifee match {
case tree: Tree =>
- reifyTrace("reifying = ")(if (settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)
+ reifyTrace("reifying = ")(if (settings.Xshowtrees || settings.XshowtreesCompact || settings.XshowtreesStringified) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)
reifyTrace("reifee is located at: ")(tree.pos)
reifyTrace("universe = ")(universe)
reifyTrace("mirror = ")(mirror)
@@ -140,4 +140,4 @@ abstract class Reifier extends States
throw new UnexpectedReificationException(defaultErrorPosition, "reification crashed", ex)
}
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala
index bb5cb53d7d..bc2dbeed3e 100644
--- a/src/compiler/scala/reflect/reify/phases/Reshape.scala
+++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala
@@ -254,7 +254,7 @@ trait Reshape {
case _ => rhs // unit or trait case
}
val DefDef(mods0, name0, _, _, tpt0, rhs0) = ddef
- val name1 = nme.dropLocalSuffix(name0)
+ val name1 = name0.dropLocal
val Modifiers(flags0, privateWithin0, annotations0) = mods0
val flags1 = (flags0 & GetterFlags) & ~(STABLE | ACCESSOR | METHOD)
val mods1 = Modifiers(flags1, privateWithin0, annotations0) setPositions mods0.positions
@@ -273,7 +273,9 @@ trait Reshape {
if (defdef.name.startsWith(prefix)) {
val name = defdef.name.toString.substring(prefix.length)
def uncapitalize(s: String) = if (s.length == 0) "" else { val chars = s.toCharArray; chars(0) = chars(0).toLower; new String(chars) }
- def findValDef(name: String) = (symdefs.values collect { case vdef: ValDef if nme.dropLocalSuffix(vdef.name).toString == name => vdef }).headOption
+ def findValDef(name: String) = symdefs.values collectFirst {
+ case vdef: ValDef if vdef.name.dropLocal string_== name => vdef
+ }
val valdef = findValDef(name).orElse(findValDef(uncapitalize(name))).orNull
if (valdef != null) accessors(valdef) = accessors.getOrElse(valdef, Nil) :+ defdef
}
@@ -297,7 +299,7 @@ trait Reshape {
mods
}
val mods2 = toPreTyperModifiers(mods1, vdef.symbol)
- val name1 = nme.dropLocalSuffix(name)
+ val name1 = name.dropLocal
val vdef1 = ValDef(mods2, name1.toTermName, tpt, rhs)
if (reifyDebug) println("resetting visibility of field: %s => %s".format(vdef, vdef1))
Some(vdef1) // no copyAttrs here, because new ValDef and old symbols are now out of sync
diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala
index d57188bf6e..7338df1f72 100644
--- a/src/compiler/scala/reflect/reify/utils/Extractors.scala
+++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala
@@ -164,51 +164,30 @@ trait Extractors {
}
}
- object FreeDef {
- def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
- case FreeTermDef(uref, name, binding, flags, origin) =>
- Some((uref, name, binding, flags, origin))
- case FreeTypeDef(uref, name, binding, flags, origin) =>
- Some((uref, name, binding, flags, origin))
- case _ =>
- None
- }
- }
-
- object FreeTermDef {
- def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
- case
- ValDef(_, name, _, Apply(
- Select(Select(uref1 @ Ident(_), build1), newFreeTerm),
- List(
- _,
- _,
- Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))),
- Literal(Constant(origin: String)))))
- if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newFreeTerm == nme.newFreeTerm &&
- uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits =>
- Some((uref1, name, reifyBinding(tree), flags, origin))
- case _ =>
- None
- }
- }
-
- object FreeTypeDef {
- def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
- case
- ValDef(_, name, _, Apply(
- Select(Select(uref1 @ Ident(_), build1), newFreeType),
- List(
- _,
- Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))),
- Literal(Constant(origin: String)))))
- if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newFreeType == nme.newFreeType &&
- uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits =>
- Some((uref1, name, reifyBinding(tree), flags, origin))
- case _ =>
- None
+ sealed abstract class FreeDefExtractor(acceptTerms: Boolean, acceptTypes: Boolean) {
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = {
+ def acceptFreeTermFactory(name: Name) = {
+ (acceptTerms && name == nme.newFreeTerm) ||
+ (acceptTypes && name == nme.newFreeType)
+ }
+ tree match {
+ case
+ ValDef(_, name, _, Apply(
+ Select(Select(uref1 @ Ident(_), build1), freeTermFactory),
+ _ :+
+ Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))) :+
+ Literal(Constant(origin: String))))
+ if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && acceptFreeTermFactory(freeTermFactory) &&
+ uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits =>
+ Some((uref1, name, reifyBinding(tree), flags, origin))
+ case _ =>
+ None
+ }
}
}
+ object FreeDef extends FreeDefExtractor(acceptTerms = true, acceptTypes = true)
+ object FreeTermDef extends FreeDefExtractor(acceptTerms = true, acceptTypes = false)
+ object FreeTypeDef extends FreeDefExtractor(acceptTerms = false, acceptTypes = true)
object FreeRef {
def unapply(tree: Tree): Option[(Tree, TermName)] = tree match {
diff --git a/src/compiler/scala/tools/nsc/CompileClient.scala b/src/compiler/scala/tools/nsc/CompileClient.scala
index c756a1b0d9..64f6758e73 100644
--- a/src/compiler/scala/tools/nsc/CompileClient.scala
+++ b/src/compiler/scala/tools/nsc/CompileClient.scala
@@ -26,12 +26,12 @@ class StandardCompileClient extends HasCompileSocket with CompileOutputCommon {
val settings = new FscSettings(Console.println)
val command = new OfflineCompilerCommand(args.toList, settings)
val shutdown = settings.shutdown.value
- val extraVmArgs = if (settings.preferIPv4.value) List("-D%s=true".format(preferIPv4Stack.key)) else Nil
+ val extraVmArgs = if (settings.preferIPv4) List("-D%s=true".format(preferIPv4Stack.key)) else Nil
val vmArgs = settings.jvmargs.unparse ++ settings.defines.unparse ++ extraVmArgs
val fscArgs = args.toList ++ command.extraFscArgs
- if (settings.version.value) {
+ if (settings.version) {
Console println versionMsg
return true
}
diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala
index fc247600f6..fbfed6110f 100644
--- a/src/compiler/scala/tools/nsc/Driver.scala
+++ b/src/compiler/scala/tools/nsc/Driver.scala
@@ -41,7 +41,7 @@ abstract class Driver {
command = new CompilerCommand(args.toList, ss)
settings = command.settings
- if (settings.version.value) {
+ if (settings.version) {
reporter.echo(versionMsg)
} else if (processSettingsHook()) {
val compiler = newCompiler()
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index c53d6cd11e..8b78ddd59d 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -221,7 +221,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def inform(msg: String) = reporter.echo(msg)
override def globalError(msg: String) = reporter.error(NoPosition, msg)
override def warning(msg: String) =
- if (settings.fatalWarnings.value) globalError(msg)
+ if (settings.fatalWarnings) globalError(msg)
else reporter.warning(NoPosition, msg)
// Getting in front of Predef's asserts to supplement with more info.
@@ -252,7 +252,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
}
@inline final def ifDebug(body: => Unit) {
- if (settings.debug.value)
+ if (settings.debug)
body
}
/** This is for WARNINGS which should reach the ears of scala developers
@@ -262,7 +262,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
* to make them visually distinct.
*/
@inline final override def devWarning(msg: => String) {
- if (settings.developer.value || settings.debug.value)
+ if (settings.developer || settings.debug)
warning("!!! " + msg)
else
log("!!! " + msg) // such warnings always at least logged
@@ -272,7 +272,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
msg + " in " + (currentTime - start) + "ms"
def informComplete(msg: String): Unit = reporter.withoutTruncating(inform(msg))
- def informProgress(msg: String) = if (settings.verbose.value) inform("[" + msg + "]")
+ def informProgress(msg: String) = if (settings.verbose) inform("[" + msg + "]")
def informTime(msg: String, start: Long) = informProgress(elapsedMessage(msg, start))
def logError(msg: String, t: Throwable): Unit = ()
@@ -287,7 +287,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
}
@inline final override def debuglog(msg: => String) {
- if (settings.debug.value)
+ if (settings.debug)
log(msg)
}
@@ -332,7 +332,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
}
}
- if (settings.verbose.value || settings.Ylogcp.value) {
+ if (settings.verbose || settings.Ylogcp) {
// Uses the "do not truncate" inform
informComplete("[search path for source files: " + classPath.sourcepaths.mkString(",") + "]")
informComplete("[search path for class files: " + classPath.asClasspathString + "]")
@@ -402,7 +402,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
if ((unit ne null) && unit.exists)
lastSeenSourceFile = unit.source
- if (settings.debug.value && (settings.verbose.value || currentRun.size < 5))
+ if (settings.debug && (settings.verbose || currentRun.size < 5))
inform("[running phase " + name + " on " + unit + "]")
val unit0 = currentUnit
@@ -736,7 +736,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val maxName = (0 /: phaseNames)(_ max _.length)
val width = maxName min Limit
val maxDesc = MaxCol - (width + 6) // descriptions not novels
- val fmt = if (settings.verbose.value) s"%${maxName}s %2s %s%n"
+ val fmt = if (settings.verbose) s"%${maxName}s %2s %s%n"
else s"%${width}.${width}s %2s %.${maxDesc}s%n"
val line1 = fmt.format("phase name", "id", "description")
@@ -1097,7 +1097,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val info3: List[String] = (
( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) )
++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) )
- ++ ( if (!settings.debug.value) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) )
+ ++ ( if (!settings.debug) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) )
++ ( List(errorMessage) )
)
@@ -1113,7 +1113,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def echoPhaseSummary(ph: Phase) = {
/* Only output a summary message under debug if we aren't echoing each file. */
- if (settings.debug.value && !(settings.verbose.value || currentRun.size < 5))
+ if (settings.debug && !(settings.verbose || currentRun.size < 5))
inform("[running phase " + ph.name + " on " + currentRun.size + " compilation units]")
}
@@ -1121,10 +1121,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
class ConditionalWarning(what: String, option: Settings#BooleanSetting) {
val warnings = mutable.LinkedHashMap[Position, String]()
def warn(pos: Position, msg: String) =
- if (option.value) reporter.warning(pos, msg)
+ if (option) reporter.warning(pos, msg)
else if (!(warnings contains pos)) warnings += ((pos, msg))
def summarize() =
- if (warnings.nonEmpty && (option.isDefault || settings.fatalWarnings.value))
+ if (warnings.nonEmpty && (option.isDefault || settings.fatalWarnings))
warning("there were %d %s warning(s); re-run with %s for details".format(warnings.size, what, option.name))
}
@@ -1240,7 +1240,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def resetProjectClasses(root: Symbol): Unit = try {
def unlink(sym: Symbol) =
if (sym != NoSymbol) root.info.decls.unlink(sym)
- if (settings.verbose.value) inform("[reset] recursing in "+root)
+ if (settings.verbose) inform("[reset] recursing in "+root)
val toReload = mutable.Set[String]()
for (sym <- root.info.decls) {
if (sym.isInitialized && clearOnNextRun(sym))
@@ -1260,7 +1260,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
for (fullname <- toReload)
classPath.findClass(fullname) match {
case Some(classRep) =>
- if (settings.verbose.value) inform("[reset] reinit "+fullname)
+ if (settings.verbose) inform("[reset] reinit "+fullname)
loaders.initializeFromClassPath(root, classRep)
case _ =>
}
@@ -1453,7 +1453,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
}
def reportCompileErrors() {
- if (!reporter.hasErrors && reporter.hasWarnings && settings.fatalWarnings.value)
+ if (!reporter.hasErrors && reporter.hasWarnings && settings.fatalWarnings)
globalError("No warnings can be incurred under -Xfatal-warnings.")
if (reporter.hasErrors) {
@@ -1492,7 +1492,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def compileUnits(units: List[CompilationUnit], fromPhase: Phase) {
try compileUnitsInternal(units, fromPhase)
catch { case ex: Throwable =>
- val shown = if (settings.verbose.value)
+ val shown = if (settings.verbose)
stackTraceString(ex)
else
stackTraceHeadString(ex) // note that error stacktraces do not print in fsc
@@ -1526,14 +1526,14 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
if (shouldWriteIcode) {
// Write *.icode files when -Xprint-icode or -Xprint:<some-optimiz-phase> was given.
writeICode()
- } else if ((settings.Xprint containsPhase globalPhase) || settings.printLate.value && runIsAt(cleanupPhase)) {
+ } else if ((settings.Xprint containsPhase globalPhase) || settings.printLate && runIsAt(cleanupPhase)) {
// print trees
- if (settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value) nodePrinters.printAll()
+ if (settings.Xshowtrees || settings.XshowtreesCompact || settings.XshowtreesStringified) nodePrinters.printAll()
else printAllUnits()
}
// print the symbols presently attached to AST nodes
- if (settings.Yshowsyms.value)
+ if (settings.Yshowsyms)
trackerFactory.snapshot()
// print members
@@ -1552,7 +1552,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
runCheckers()
// output collected statistics
- if (settings.Ystatistics.value)
+ if (settings.Ystatistics)
statistics.print(phase)
advancePhase()
@@ -1697,7 +1697,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
informProgress("wrote " + file)
} catch {
case ex: IOException =>
- if (settings.debug.value) ex.printStackTrace()
+ if (settings.debug) ex.printStackTrace()
globalError("could not write file " + file)
}
})
diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala
index 00c6c37dfd..9f6f483ad8 100644
--- a/src/compiler/scala/tools/nsc/Main.scala
+++ b/src/compiler/scala/tools/nsc/Main.scala
@@ -17,7 +17,7 @@ class MainClass extends Driver with EvalLoop {
override def newCompiler(): Global = Global(settings, reporter)
override def doCompile(compiler: Global) {
- if (settings.resident.value) resident(compiler)
+ if (settings.resident) resident(compiler)
else super.doCompile(compiler)
}
}
diff --git a/src/compiler/scala/tools/nsc/MainTokenMetric.scala b/src/compiler/scala/tools/nsc/MainTokenMetric.scala
index 584805b37e..e2893204e0 100644
--- a/src/compiler/scala/tools/nsc/MainTokenMetric.scala
+++ b/src/compiler/scala/tools/nsc/MainTokenMetric.scala
@@ -42,7 +42,7 @@ object MainTokenMetric {
tokenMetric(compiler, command.files)
} catch {
case ex @ FatalError(msg) =>
- if (command.settings.debug.value)
+ if (command.settings.debug)
ex.printStackTrace()
reporter.error(null, "fatal error: " + msg)
}
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index 821e88e52e..5f8bc71449 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -95,7 +95,7 @@ class ScriptRunner extends HasCompileSocket {
settings.outdir.value = compiledPath.path
- if (settings.nc.value) {
+ if (settings.nc) {
/* Setting settings.script.value informs the compiler this is not a
* self contained compilation unit.
*/
@@ -114,7 +114,7 @@ class ScriptRunner extends HasCompileSocket {
* not take place until there are no non-daemon threads running. Tickets #1955, #2006.
*/
util.waitingForThreads {
- if (settings.save.value) {
+ if (settings.save) {
val jarFile = jarFileFor(scriptFile)
def jarOK = jarFile.canRead && (jarFile isFresher File(scriptFile))
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
index 602366a201..caab299635 100644
--- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
@@ -32,7 +32,7 @@ abstract class NodePrinters {
}
trait DefaultPrintAST extends PrintAST {
- val printPos = settings.Xprintpos.value || settings.Yposdebug.value
+ val printPos = settings.Xprintpos || settings.Yposdebug
def showNameAndPos(tree: NameTree) = showPosition(tree) + showName(tree.name)
def showDefTreeName(tree: DefTree) = showName(tree.name)
@@ -100,9 +100,9 @@ abstract class NodePrinters {
def stringify(tree: Tree): String = {
buf.clear()
- if (settings.XshowtreesStringified.value) buf.append(tree.toString + EOL)
- if (settings.XshowtreesCompact.value) {
- buf.append(showRaw(tree, printIds = settings.uniqid.value, printTypes = settings.printtypes.value))
+ if (settings.XshowtreesStringified) buf.append(tree.toString + EOL)
+ if (settings.XshowtreesCompact) {
+ buf.append(showRaw(tree, printIds = settings.uniqid, printTypes = settings.printtypes))
} else {
level = 0
traverse(tree)
diff --git a/src/compiler/scala/tools/nsc/ast/Positions.scala b/src/compiler/scala/tools/nsc/ast/Positions.scala
index 66d75969e9..beab801edf 100644
--- a/src/compiler/scala/tools/nsc/ast/Positions.scala
+++ b/src/compiler/scala/tools/nsc/ast/Positions.scala
@@ -25,6 +25,6 @@ trait Positions extends scala.reflect.internal.Positions {
}
override protected[this] lazy val posAssigner: PosAssigner =
- if (settings.Yrangepos.value && settings.debug.value || settings.Yposdebug.value) new ValidatingPosAssigner
+ if (settings.Yrangepos && settings.debug || settings.Yposdebug) new ValidatingPosAssigner
else new DefaultPosAssigner
}
diff --git a/src/compiler/scala/tools/nsc/ast/Printers.scala b/src/compiler/scala/tools/nsc/ast/Printers.scala
index 7fefb2ce0c..72538bac08 100644
--- a/src/compiler/scala/tools/nsc/ast/Printers.scala
+++ b/src/compiler/scala/tools/nsc/ast/Printers.scala
@@ -200,15 +200,15 @@ trait Printers extends scala.reflect.internal.Printers { this: Global =>
override def printTree(tree: Tree) { print(safe(tree)) }
}
- def asString(t: Tree): String = render(t, newStandardTreePrinter, settings.printtypes.value, settings.uniqid.value, settings.Yshowsymkinds.value)
- def asCompactString(t: Tree): String = render(t, newCompactTreePrinter, settings.printtypes.value, settings.uniqid.value, settings.Yshowsymkinds.value)
+ def asString(t: Tree): String = render(t, newStandardTreePrinter, settings.printtypes, settings.uniqid, settings.Yshowsymkinds)
+ def asCompactString(t: Tree): String = render(t, newCompactTreePrinter, settings.printtypes, settings.uniqid, settings.Yshowsymkinds)
def asCompactDebugString(t: Tree): String = render(t, newCompactTreePrinter, true, true, true)
def newStandardTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer)
def newCompactTreePrinter(writer: PrintWriter): CompactTreePrinter = new CompactTreePrinter(writer)
override def newTreePrinter(writer: PrintWriter): TreePrinter =
- if (settings.Ycompacttrees.value) newCompactTreePrinter(writer)
+ if (settings.Ycompacttrees) newCompactTreePrinter(writer)
else newStandardTreePrinter(writer)
override def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream))
override def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter))
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 68e198d071..7671912651 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -2085,7 +2085,7 @@ self =>
val name = ident()
var bynamemod = 0
val tpt =
- if (settings.YmethodInfer.value && !owner.isTypeName && in.token != COLON) {
+ if (settings.YmethodInfer && !owner.isTypeName && in.token != COLON) {
TypeTree()
} else { // XX-METHOD-INFER
accept(COLON)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index b485e862fd..eb31f7a66e 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -446,7 +446,7 @@ trait Scanners extends ScannersCommon {
* there a realistic situation where one would need it?
*/
if (isDigit(ch)) {
- if (settings.future.value) syntaxError("Non-zero numbers may not have a leading zero.")
+ if (settings.future) syntaxError("Non-zero numbers may not have a leading zero.")
else deprecationWarning("Treating numbers with a leading zero as octal is deprecated.")
}
base = 8
@@ -990,7 +990,7 @@ trait Scanners extends ScannersCommon {
/* As of scala 2.11, it isn't a number unless c here is a digit, so
* settings.future.value excludes the rest of the logic.
*/
- if (settings.future.value && !isDigit(c))
+ if (settings.future && !isDigit(c))
return setStrVal()
val isDefinitelyNumber = (c: @switch) match {
@@ -1217,7 +1217,7 @@ trait Scanners extends ScannersCommon {
*/
class SourceFileScanner(val source: SourceFile) extends Scanner {
val buf = source.content
- override val decodeUni: Boolean = !settings.nouescape.value
+ override val decodeUni: Boolean = !settings.nouescape
// suppress warnings, throw exception on errors
def deprecationWarning(off: Offset, msg: String): Unit = ()
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
index 7cf5a07291..80d70e6428 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
@@ -32,7 +32,7 @@ abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParse
else newUnitParser(unit).smartParse()
}
- if (settings.Yrangepos.value && !reporter.hasErrors)
+ if (settings.Yrangepos && !reporter.hasErrors)
validatePositions(unit.body)
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
index 89682e91d2..94fbba8066 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
@@ -331,7 +331,7 @@ trait BasicBlocks {
assert(!closed || ignore, this)
if (ignore) {
- if (settings.debug.value) {
+ if (settings.debug) {
/* Trying to pin down what it's likely to see after a block has been
* put into ignore mode so we hear about it if there's a problem.
*/
@@ -405,11 +405,11 @@ trait BasicBlocks {
* is discovered to be unreachable.
*/
def killIf(cond: Boolean) {
- if (!settings.YdisableUnreachablePrevention.value && cond) {
+ if (!settings.YdisableUnreachablePrevention && cond) {
debuglog(s"Killing block $this")
assert(instructionList.isEmpty, s"Killing a non empty block $this")
// only checked under debug because fetching predecessor list is moderately expensive
- if (settings.debug.value)
+ if (settings.debug)
assert(predecessors.isEmpty, s"Killing block $this which is referred to from ${predecessors.mkString}")
close()
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 8ba75fbb46..31028e64d3 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -39,7 +39,7 @@ abstract class GenICode extends SubComponent {
override def newPhase(prev: Phase) = new ICodePhase(prev)
@inline private def debugassert(cond: => Boolean, msg: => Any) {
- if (settings.debug.value)
+ if (settings.debug)
assert(cond, msg)
}
@@ -129,7 +129,7 @@ abstract class GenICode extends SubComponent {
case Return(_) => ()
case EmptyTree =>
globalError("Concrete method has no definition: " + tree + (
- if (settings.debug.value) "(found: " + m.symbol.owner.info.decls.toList.mkString(", ") + ")"
+ if (settings.debug) "(found: " + m.symbol.owner.info.decls.toList.mkString(", ") + ")"
else "")
)
case _ => if (ctx1.bb.isEmpty)
@@ -710,7 +710,7 @@ abstract class GenICode extends SubComponent {
debuglog("BOX : " + fun.symbol.fullName)
val ctx1 = genLoad(expr, ctx, toTypeKind(expr.tpe))
val nativeKind = toTypeKind(expr.tpe)
- if (settings.Xdce.value) {
+ if (settings.Xdce) {
// we store this boxed value to a local, even if not really needed.
// boxing optimization might use it, and dead code elimination will
// take care of unnecessary stores
@@ -1483,7 +1483,7 @@ abstract class GenICode extends SubComponent {
if (mustUseAnyComparator) {
// when -optimise is on we call the @inline-version of equals, found in ScalaRunTime
val equalsMethod =
- if (!settings.optimise.value) {
+ if (!settings.optimise) {
def default = platform.externalEquals
platform match {
case x: JavaPlatform =>
@@ -1507,7 +1507,7 @@ abstract class GenICode extends SubComponent {
val ctx2 = genLoad(r, ctx1, ObjectReference)
val branchesReachable = !ctx2.bb.ignore
ctx2.bb.emitOnly(
- CALL_METHOD(equalsMethod, if (settings.optimise.value) Dynamic else Static(onInstance = false)),
+ CALL_METHOD(equalsMethod, if (settings.optimise) Dynamic else Static(onInstance = false)),
CZJUMP(thenCtx.bb, elseCtx.bb, NE, BOOL)
)
branchesReachable
@@ -2032,7 +2032,7 @@ abstract class GenICode extends SubComponent {
// Generate the catch-all exception handler that deals with uncaught exceptions coming
// from the try or exception handlers. It catches the exception, runs the finally code, then rethrows
// the exception
- if (settings.YdisableUnreachablePrevention.value || !outerCtx.bb.ignore) {
+ if (settings.YdisableUnreachablePrevention || !outerCtx.bb.ignore) {
if (finalizer != EmptyTree) {
val exh = outerCtx.newExceptionHandler(NoSymbol, finalizer.pos) // finalizer covers exception handlers
this.addActiveHandler(exh) // .. and body aswell
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
index b7b07a579f..0cdf629ce1 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
@@ -94,7 +94,7 @@ abstract class ICodeCheckers {
}
def checkICodes(): Unit = {
- if (settings.verbose.value)
+ if (settings.verbose)
println("[[consistency check at the beginning of phase " + globalPhase.name + "]]")
classes.values foreach check
}
@@ -444,7 +444,7 @@ abstract class ICodeCheckers {
def checkBool(cond: Boolean, msg: String) =
if (!cond) icodeError(msg)
- if (settings.debug.value) {
+ if (settings.debug) {
log("PC: " + instr)
log("stack: " + stack)
log("================")
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
index e2d387c65d..3f2141782a 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
@@ -35,7 +35,7 @@ abstract class ICodes extends AnyRef
/** Debugging flag */
def shouldCheckIcode = settings.check contains global.genicode.phaseName
- def checkerDebug(msg: String) = if (shouldCheckIcode && global.settings.debug.value) println(msg)
+ def checkerDebug(msg: String) = if (shouldCheckIcode && global.settings.debug) println(msg)
/** The ICode linearizer. */
val linearizer: Linearizer = settings.Xlinearizer.value match {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
index e471f4256b..c1cda2c863 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
@@ -61,7 +61,7 @@ trait Members {
startBlock = newBlock()
def removeBlock(b: BasicBlock) {
- if (settings.debug.value) {
+ if (settings.debug) {
// only do this sanity check when debug is turned on because it's moderately expensive
val referers = blocks filter (_.successors contains b)
assert(referers.isEmpty, s"Trying to removing block $b (with preds ${b.predecessors.mkString}) but it is still refered to from block(s) ${referers.mkString}")
@@ -172,6 +172,7 @@ trait Members {
var returnType: TypeKind = _
var recursive: Boolean = false
var bytecodeHasEHs = false // set by ICodeReader only, used by Inliner to prevent inlining (SI-6188)
+ var bytecodeHasInvokeDynamic = false // set by ICodeReader only, used by Inliner to prevent inlining until we have proper invoke dynamic support
/** local variables and method parameters */
var locals: List[Local] = Nil
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
index d8aac8e9db..ff118be3c4 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
@@ -394,6 +394,25 @@ trait Opcodes { self: ICodes =>
override def category = mthdsCat
}
+
+ /**
+ * A place holder entry that allows us to parse class files with invoke dynamic
+ * instructions. Because the compiler doesn't yet really understand the
+ * behavior of invokeDynamic, this op acts as a poison pill. Any attempt to analyze
+ * this instruction will cause a failure. The only optimization that
+ * should ever look at non-Scala generated icode is the inliner, and it
+ * has been modified to not examine any method with invokeDynamic
+ * instructions. So if this poison pill ever causes problems then
+ * there's been a serious misunderstanding
+ */
+ // TODO do the real thing
+ case class INVOKE_DYNAMIC(poolEntry: Char) extends Instruction {
+ private def error = sys.error("INVOKE_DYNAMIC is not fully implemented and should not be analyzed")
+ override def consumed = error
+ override def produced = error
+ override def producedTypes = error
+ override def category = error
+ }
case class BOX(boxType: TypeKind) extends Instruction {
assert(boxType.isValueType && (boxType ne UNIT)) // documentation
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala
index 5b47e3cfff..1fe33f78e7 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala
@@ -110,7 +110,7 @@ trait Printers { self: ICodes =>
print(bb.label)
if (bb.loopHeader) print("[loop header]")
print(": ")
- if (settings.debug.value) print("pred: " + bb.predecessors + " succs: " + bb.successors + " flags: " + bb.flagsString)
+ if (settings.debug) print("pred: " + bb.predecessors + " succs: " + bb.successors + " flags: " + bb.flagsString)
indent(); println()
bb.toList foreach printInstruction
undent(); println()
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Repository.scala b/src/compiler/scala/tools/nsc/backend/icode/Repository.scala
index e92e61c957..10d57df4a3 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Repository.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Repository.scala
@@ -39,7 +39,7 @@ trait Repository {
} catch {
case e: Throwable => // possible exceptions are MissingRequirementError, IOException and TypeError -> no better common supertype
log("Failed to load %s. [%s]".format(sym.fullName, e.getMessage))
- if (settings.debug.value) { e.printStackTrace }
+ if (settings.debug) { e.printStackTrace }
false
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
index 152a11ab1a..338a07c872 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -199,7 +199,7 @@ abstract class CopyPropagation {
override def run() {
forwardAnalysis(blockTransfer)
- if (settings.debug.value) {
+ if (settings.debug) {
linearizer.linearize(method).foreach(b => if (b != method.startBlock)
assert(in(b) != lattice.bottom,
"Block " + b + " in " + this.method + " has input equal to bottom -- not visited?"))
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
index 14b57f287f..60f7857d0c 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
@@ -74,7 +74,7 @@ abstract class Liveness {
override def run() {
backwardAnalysis(blockTransfer)
- if (settings.debug.value) {
+ if (settings.debug) {
linearizer.linearize(method).foreach(b => if (b != method.startBlock)
assert(lattice.bottom != in(b),
"Block " + b + " in " + this.method + " has input equal to bottom -- not visited?"))
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala
index 2d29e6b14f..26b7bc50d8 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala
@@ -51,7 +51,7 @@ abstract class ReachingDefinitions {
// it'd be nice not to call zip with mismatched sequences because
// it makes it harder to spot the real problems.
val result = (a.stack, b.stack).zipped map (_ ++ _)
- if (settings.debug.value && (a.stack.length != b.stack.length))
+ if (settings.debug && (a.stack.length != b.stack.length))
devWarning(s"Mismatched stacks in ReachingDefinitions#lub2: ${a.stack}, ${b.stack}, returning $result")
result
}
@@ -141,7 +141,7 @@ abstract class ReachingDefinitions {
override def run() {
forwardAnalysis(blockTransfer)
- if (settings.debug.value) {
+ if (settings.debug) {
linearizer.linearize(method).foreach(b => if (b != method.startBlock)
assert(lattice.bottom != in(b),
"Block " + b + " in " + this.method + " has input equal to bottom -- not visited? " + in(b)
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
index 227c1064ea..57380db7e7 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -136,7 +136,7 @@ abstract class TypeFlowAnalysis {
// icodes.lubs0 = 0
forwardAnalysis(blockTransfer)
timer.stop
- if (settings.debug.value) {
+ if (settings.debug) {
linearizer.linearize(method).foreach(b => if (b != method.startBlock)
assert(visited.contains(b),
"Block " + b + " in " + this.method + " has input equal to bottom -- not visited? .." + visited))
@@ -167,7 +167,7 @@ abstract class TypeFlowAnalysis {
val bindings = out.vars
val stack = out.stack
- if (settings.debug.value) {
+ if (settings.debug) {
// Console.println("[before] Stack: " + stack);
// Console.println(i);
}
@@ -367,7 +367,7 @@ abstract class TypeFlowAnalysis {
preCandidates += rc._2.bb
}
- if (settings.debug.value) {
+ if (settings.debug) {
for(b <- callerLin; if (b != method.startBlock) && preCandidates(b)) {
assert(visited.contains(b),
"Block " + b + " in " + this.method + " has input equal to bottom -- not visited? .." + visited)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 2aa874b567..66a58870cc 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -86,10 +86,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
override def run() {
- if (settings.debug.value)
+ if (settings.debug)
inform("[running phase " + name + " on icode]")
- if (settings.Xdce.value)
+ if (settings.Xdce)
for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym)) {
log(s"Optimizer eliminated ${sym.fullNameString}")
icodes.classes -= sym
@@ -290,7 +290,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
def inameToSymbol(iname: String): Symbol = {
val name = global.newTypeName(iname)
val res0 =
- if (nme.isModuleName(name)) rootMirror.getModule(nme.stripModuleSuffix(name))
+ if (nme.isModuleName(name)) rootMirror.getModule(name.dropModule)
else rootMirror.getClassByName(name.replace('/', '.')) // TODO fails for inner classes (but this hasn't been tested).
assert(res0 != NoSymbol)
val res = jsymbol(res0)
@@ -804,7 +804,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
// without it. This is particularly bad because the availability of
// generic information could disappear as a consequence of a seemingly
// unrelated change.
- settings.Ynogenericsig.value
+ settings.Ynogenericsig
|| sym.isArtifact
|| sym.isLiftedMethod
|| sym.isBridge
@@ -834,7 +834,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
catch { case _: Throwable => false }
}
- if (settings.Xverify.value) {
+ if (settings.Xverify) {
// Run the signature parser to catch bogus signatures.
val isValidSignature = wrap {
// Alternative: scala.tools.reflect.SigParser (frontend to sun.reflect.generics.parser.SignatureParser)
@@ -1362,7 +1362,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
for (constructor <- c.lookupStaticCtor) {
addStaticInit(Some(constructor))
}
- val skipStaticForwarders = (c.symbol.isInterface || settings.noForwarders.value)
+ val skipStaticForwarders = (c.symbol.isInterface || settings.noForwarders)
if (!skipStaticForwarders) {
val lmoc = c.symbol.companionModule
// add static forwarders if there are no name conflicts; see bugs #363 and #1735
@@ -2251,16 +2251,16 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
// info calls so that types are up to date; erasure may add lateINTERFACE to traits
hostSymbol.info ; methodOwner.info
- def isInterfaceCall(sym: Symbol) = (
- sym.isInterface && methodOwner != ObjectClass
+ def needsInterfaceCall(sym: Symbol) = (
+ sym.isInterface
|| sym.isJavaDefined && sym.isNonBottomSubClass(ClassfileAnnotationClass)
)
// whether to reference the type of the receiver or
- // the type of the method owner (if not an interface!)
+ // the type of the method owner
val useMethodOwner = (
style != Dynamic
- || !isInterfaceCall(hostSymbol) && isAccessibleFrom(methodOwner, siteSymbol)
|| hostSymbol.isBottomClass
+ || methodOwner == ObjectClass
)
val receiver = if (useMethodOwner) methodOwner else hostSymbol
val jowner = javaName(receiver)
@@ -2283,11 +2283,11 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
}
style match {
- case Static(true) => dbg("invokespecial"); jcode.invokespecial (jowner, jname, jtype)
- case Static(false) => dbg("invokestatic"); jcode.invokestatic (jowner, jname, jtype)
- case Dynamic if isInterfaceCall(receiver) => dbg("invokinterface"); jcode.invokeinterface(jowner, jname, jtype)
- case Dynamic => dbg("invokevirtual"); jcode.invokevirtual (jowner, jname, jtype)
- case SuperCall(_) =>
+ case Static(true) => dbg("invokespecial"); jcode.invokespecial (jowner, jname, jtype)
+ case Static(false) => dbg("invokestatic"); jcode.invokestatic (jowner, jname, jtype)
+ case Dynamic if needsInterfaceCall(receiver) => dbg("invokinterface"); jcode.invokeinterface(jowner, jname, jtype)
+ case Dynamic => dbg("invokevirtual"); jcode.invokevirtual (jowner, jname, jtype)
+ case SuperCall(_) =>
dbg("invokespecial")
jcode.invokespecial(jowner, jname, jtype)
initModule()
@@ -3220,7 +3220,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
val detour = computeDetour
rephraseGotos(detour)
- if (settings.debug.value) {
+ if (settings.debug) {
val (remappings, cycles) = detour partition {case (source, target) => source != target}
for ((source, target) <- remappings) {
debuglog(s"Will elide jump only block $source because it can be jumped around to get to $target.")
@@ -3273,7 +3273,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
}
// remove the unusued exception handler references
- if (settings.debug.value)
+ if (settings.debug)
for (exh <- unusedExceptionHandlers) debuglog(s"eliding exception handler $exh because it does not cover any reachable blocks")
m.exh = m.exh filterNot unusedExceptionHandlers
@@ -3287,7 +3287,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
def normalize(m: IMethod) {
if(!m.hasCode) { return }
collapseJumpOnlyBlocks(m)
- if (settings.optimise.value)
+ if (settings.optimise)
elimUnreachableBlocks(m)
icodes checkValid m
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
index 8f439fc800..aaf2c55dcd 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
@@ -82,7 +82,7 @@ abstract class ClosureElimination extends SubComponent {
*
*/
class ClosureElim {
- def analyzeClass(cls: IClass): Unit = if (settings.Xcloselim.value) {
+ def analyzeClass(cls: IClass): Unit = if (settings.Xcloselim) {
log(s"Analyzing ${cls.methods.size} methods in $cls.")
cls.methods foreach { m =>
analyzeMethod(m)
diff --git a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala
index 7187bacb06..ff93206ffd 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala
@@ -41,7 +41,7 @@ abstract class ConstantOptimization extends SubComponent {
def name = phaseName
override def apply(c: IClass) {
- if (settings.YconstOptimization.value) {
+ if (settings.YconstOptimization) {
val analyzer = new ConstantOptimizer
analyzer optimizeClass c
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 7042d7a042..1026e95fac 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -33,7 +33,7 @@ abstract class DeadCodeElimination extends SubComponent {
val dce = new DeadCode()
override def apply(c: IClass) {
- if (settings.Xdce.value)
+ if (settings.Xdce)
dce.analyzeClass(c)
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
index dcf0590951..cecabda171 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
@@ -88,7 +88,7 @@ abstract class InlineExceptionHandlers extends SubComponent {
/** Apply exception handler inlining to a class */
override def apply(c: IClass): Unit =
- if (settings.inlineHandlers.value) {
+ if (settings.inlineHandlers) {
val startTime = System.currentTimeMillis
currentClass = c
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index 38040d921f..a6eedbd07e 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -265,7 +265,7 @@ abstract class Inliners extends SubComponent {
}
def analyzeClass(cls: IClass): Unit =
- if (settings.inline.value) {
+ if (settings.inline) {
inlineLog("class", s"${cls.symbol.decodedName}", s"analyzing ${cls.methods.size} methods in $cls")
this.currentIClazz = cls
@@ -319,7 +319,7 @@ abstract class Inliners extends SubComponent {
* */
def analyzeMethod(m: IMethod): Unit = {
// m.normalize
- if (settings.debug.value)
+ if (settings.debug)
inlineLog("caller", ownedName(m.symbol), "in " + m.symbol.owner.fullName)
val sizeBeforeInlining = m.code.blockCount
@@ -382,8 +382,8 @@ abstract class Inliners extends SubComponent {
val shouldWarn = hasInline(i.method)
def warnNoInline(reason: String): Boolean = {
- def msg = "Could not inline required method %s because %s.".format(i.method.originalName.decode, reason)
- if (settings.debug.value)
+ def msg = "Could not inline required method %s because %s.".format(i.method.unexpandedName.decode, reason)
+ if (settings.debug)
inlineLog("fail", i.method.fullName, reason)
if (shouldWarn)
warn(i.pos, msg)
@@ -565,7 +565,7 @@ abstract class Inliners extends SubComponent {
while (retry && count < MAX_INLINE_RETRY)
for(inlFail <- tfa.warnIfInlineFails) {
- warn(inlFail.pos, "At the end of the day, could not inline @inline-marked method " + inlFail.method.originalName.decode)
+ warn(inlFail.pos, "At the end of the day, could not inline @inline-marked method " + inlFail.method.unexpandedName.decode)
}
m.normalize()
@@ -935,7 +935,7 @@ abstract class Inliners extends SubComponent {
// add exception handlers of the callee
caller addHandlers (inc.handlers map translateExh)
assert(pending.isEmpty, "Pending NEW elements: " + pending)
- if (settings.debug.value) icodes.checkValid(caller.m)
+ if (settings.debug) icodes.checkValid(caller.m)
}
def isStampedForInlining(stackLength: Int): InlineSafetyInfo = {
@@ -958,6 +958,7 @@ abstract class Inliners extends SubComponent {
if(isInlineForbidden) { rs ::= "is annotated @noinline" }
if(inc.isSynchronized) { rs ::= "is synchronized method" }
if(inc.m.bytecodeHasEHs) { rs ::= "bytecode contains exception handlers / finally clause" } // SI-6188
+ if(inc.m.bytecodeHasInvokeDynamic) { rs ::= "bytecode contains invoke dynamic" }
if(rs.isEmpty) null else rs.mkString("", ", and ", "")
}
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index cf40fe90fa..f1b1d1a9a7 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -755,13 +755,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
val pos = in.currentPos
val name = identForType()
val (statics, body) = typeBody(AT, name)
- def getValueMethodType(tree: Tree) = tree match {
- case DefDef(_, nme.value, _, _, tpt, _) => Some(tpt.duplicate)
- case _ => None
- }
- var templ = makeTemplate(annotationParents, body)
- for (stat <- templ.body; tpt <- getValueMethodType(stat))
- templ = makeTemplate(annotationParents, makeConstructor(List(tpt)) :: templ.body)
+ val templ = makeTemplate(annotationParents, body)
addCompanionObject(statics, atPos(pos) {
ClassDef(mods, name, List(), templ)
})
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
index 71b97e86a6..a591482392 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
@@ -62,7 +62,7 @@ trait Plugins {
def withPlug = plug :: pick(tail, plugNames + plug.name, phaseNames ++ plugPhaseNames)
lazy val commonPhases = phaseNames intersect plugPhaseNames
- def note(msg: String): Unit = if (settings.verbose.value) inform(msg format plug.name)
+ def note(msg: String): Unit = if (settings.verbose) inform(msg format plug.name)
def fail(msg: String) = { note(msg) ; withoutPlug }
if (plugNames contains plug.name)
diff --git a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
index 44670ea578..a67c207820 100644
--- a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
@@ -43,7 +43,7 @@ abstract class AbstractReporter extends Reporter {
if (!hidden || isPromptSet) {
severity.count += 1
display(pos, msg, severity)
- } else if (settings.debug.value) {
+ } else if (settings.debug) {
severity.count += 1
display(pos, "[ suppressed ] " + msg, severity)
}
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 61ac07d18f..250feb69bf 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -31,7 +31,7 @@ abstract class SymbolLoaders {
}
protected def signalError(root: Symbol, ex: Throwable) {
- if (settings.debug.value) ex.printStackTrace()
+ if (settings.debug) ex.printStackTrace()
globalError(ex.getMessage() match {
case null => "i/o error while loading " + root.name
case msg => "error while loading " + root.name + ", " + msg
@@ -104,8 +104,15 @@ abstract class SymbolLoaders {
val clazz = enterClass(root, name, completer)
val module = enterModule(root, name, completer)
if (!clazz.isAnonymousClass) {
- assert(clazz.companionModule == module, module)
- assert(module.companionClass == clazz, clazz)
+ // Diagnostic for SI-7147
+ def msg: String = {
+ def symLocation(sym: Symbol) = if (sym == null) "null" else s"${clazz.fullLocationString} (from ${clazz.associatedFile})"
+ sm"""Inconsistent class/module symbol pair for `$name` loaded from ${symLocation(root)}.
+ |clazz = ${symLocation(clazz)}; clazz.companionModule = ${clazz.companionModule}
+ |module = ${symLocation(module)}; module.companionClass = ${module.companionClass}"""
+ }
+ assert(clazz.companionModule == module, msg)
+ assert(module.companionClass == clazz, msg)
}
}
@@ -136,10 +143,10 @@ abstract class SymbolLoaders {
((classRep.binary, classRep.source) : @unchecked) match {
case (Some(bin), Some(src))
if platform.needCompile(bin, src) && !binaryOnly(owner, classRep.name) =>
- if (settings.verbose.value) inform("[symloader] picked up newer source file for " + src.path)
+ if (settings.verbose) inform("[symloader] picked up newer source file for " + src.path)
global.loaders.enterToplevelsFromSource(owner, classRep.name, src)
case (None, Some(src)) =>
- if (settings.verbose.value) inform("[symloader] no class, picked up source file for " + src.path)
+ if (settings.verbose) inform("[symloader] no class, picked up source file for " + src.path)
global.loaders.enterToplevelsFromSource(owner, classRep.name, src)
case (Some(bin), _) =>
global.loaders.enterClassAndModule(owner, classRep.name, platform.newClassLoader(bin))
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala
index 035244e421..daaa625164 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala
@@ -127,7 +127,7 @@ trait SymbolTrackers {
else " (" + Flags.flagsToString(masked) + ")"
}
def symString(sym: Symbol) = (
- if (settings.debug.value && sym.hasCompleteInfo) {
+ if (settings.debug && sym.hasCompleteInfo) {
val s = sym.defString take 240
if (s.length == 240) s + "..." else s
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index d26a61f187..a8a47205dd 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -12,9 +12,11 @@ import java.lang.Integer.toHexString
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.{ ListBuffer, ArrayBuffer }
import scala.annotation.switch
+import scala.reflect.internal.{ JavaAccFlags }
import scala.reflect.internal.pickling.{PickleBuffer, ByteCodecs}
import scala.tools.nsc.io.AbstractFile
+
/** This abstract class implements a class file parser.
*
* @author Martin Odersky
@@ -23,6 +25,7 @@ import scala.tools.nsc.io.AbstractFile
abstract class ClassfileParser {
val global: Global
import global._
+ import definitions._
import scala.reflect.internal.ClassfileConstants._
import Flags._
@@ -40,21 +43,41 @@ abstract class ClassfileParser {
protected var classTParams = Map[Name,Symbol]()
protected var srcfile0 : Option[AbstractFile] = None
protected def moduleClass: Symbol = staticModule.moduleClass
+ private var sawPrivateConstructor = false
+
+ private def ownerForFlags(jflags: JavaAccFlags) = if (jflags.isStatic) moduleClass else clazz
def srcfile = srcfile0
- private def currentIsTopLevel = currentClass.toString.indexOf('$') < 0
+ private def optimized = global.settings.optimise.value
+ private def currentIsTopLevel = !(currentClass.decodedName containsChar '$')
+
+ // u1, u2, and u4 are what these data types are called in the JVM spec.
+ // They are an unsigned byte, unsigned char, and unsigned int respectively.
+ // We bitmask u1 into an Int to make sure it's 0-255 (and u1 isn't used
+ // for much beyond tags) but leave u2 alone as it's already unsigned.
+ protected final def u1(): Int = in.nextByte & 0xFF
+ protected final def u2(): Char = in.nextChar
+ protected final def u4(): Int = in.nextInt
+
+ private def readInnerClassFlags() = readClassFlags()
+ private def readClassFlags() = JavaAccFlags classFlags u2
+ private def readMethodFlags() = JavaAccFlags methodFlags u2
+ private def readFieldFlags() = JavaAccFlags fieldFlags u2
+ private def readTypeName() = readName().toTypeName
+ private def readName() = pool getName u2
+ private def readType() = pool getType u2
private object unpickler extends scala.reflect.internal.pickling.UnPickler {
val global: ClassfileParser.this.global.type = ClassfileParser.this.global
}
private def handleMissing(e: MissingRequirementError) = {
- if (settings.debug.value) e.printStackTrace
+ if (settings.debug) e.printStackTrace
throw new IOException("Missing dependency '" + e.req + "', required by " + in.file)
}
private def handleError(e: Exception) = {
- if (settings.debug.value) e.printStackTrace()
+ if (settings.debug) e.printStackTrace()
throw new IOException("class file '%s' is broken\n(%s/%s)".format(
in.file,
e.getClass,
@@ -106,65 +129,60 @@ abstract class ClassfileParser {
}
private def parseHeader() {
- val magic = in.nextInt
+ val magic = u4
if (magic != JAVA_MAGIC)
- throw new IOException("class file '" + in.file + "' "
- + "has wrong magic number 0x" + toHexString(magic)
- + ", should be 0x" + toHexString(JAVA_MAGIC))
- val minorVersion = in.nextChar.toInt
- val majorVersion = in.nextChar.toInt
- if ((majorVersion < JAVA_MAJOR_VERSION) ||
- ((majorVersion == JAVA_MAJOR_VERSION) &&
- (minorVersion < JAVA_MINOR_VERSION)))
- throw new IOException("class file '" + in.file + "' "
- + "has unknown version "
- + majorVersion + "." + minorVersion
- + ", should be at least "
- + JAVA_MAJOR_VERSION + "." + JAVA_MINOR_VERSION)
+ abort(s"class file ${in.file} has wrong magic number 0x${toHexString(magic)}")
+
+ val minor, major = u2
+ if (major < JAVA_MAJOR_VERSION || major == JAVA_MAJOR_VERSION && minor < JAVA_MINOR_VERSION)
+ abort(s"class file ${in.file} has unknown version $major.$minor, should be at least $JAVA_MAJOR_VERSION.$JAVA_MINOR_VERSION")
}
class ConstantPool {
- private val len = in.nextChar
- private val starts = new Array[Int](len)
- private val values = new Array[AnyRef](len)
+ private val len = u2
+ private val starts = new Array[Int](len)
+ private val values = new Array[AnyRef](len)
private val internalized = new Array[Name](len)
{ var i = 1
while (i < starts.length) {
starts(i) = in.bp
i += 1
- (in.nextByte.toInt: @switch) match {
- case CONSTANT_UTF8 | CONSTANT_UNICODE =>
- in.skip(in.nextChar)
- case CONSTANT_CLASS | CONSTANT_STRING =>
- in.skip(2)
- case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF
- | CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT =>
- in.skip(4)
- case CONSTANT_LONG | CONSTANT_DOUBLE =>
- in.skip(8)
- i += 1
- case _ =>
- errorBadTag(in.bp - 1)
+ (u1.toInt: @switch) match {
+ case CONSTANT_UTF8 | CONSTANT_UNICODE => in skip u2
+ case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE => in skip 2
+ case CONSTANT_METHODHANDLE => in skip 3
+ case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF => in skip 4
+ case CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT => in skip 4
+ case CONSTANT_INVOKEDYNAMIC => in skip 4
+ case CONSTANT_LONG | CONSTANT_DOUBLE => in skip 8 ; i += 1
+ case _ => errorBadTag(in.bp - 1)
}
}
}
- /** Return the name found at given index. */
- def getName(index: Int): Name = {
- if (index <= 0 || len <= index)
- errorBadIndex(index)
+ def recordAtIndex[T <: AnyRef](value: T, idx: Int): T = {
+ values(idx) = value
+ value
+ }
- values(index) match {
+ def firstExpecting(index: Int, expected: Int): Int = {
+ val start = starts(index)
+ val first = in.buf(start).toInt
+ if (first == expected) start + 1
+ else this errorBadTag start
+ }
+
+ /** Return the name found at given index. */
+ def getName(index: Int): Name = (
+ if (index <= 0 || len <= index) errorBadIndex(index)
+ else values(index) match {
case name: Name => name
- case null =>
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start)
- val name = newTermName(in.buf, start + 3, in.getChar(start + 1))
- values(index) = name
- name
+ case _ =>
+ val start = firstExpecting(index, CONSTANT_UTF8)
+ recordAtIndex(newTermName(in.buf, start + 2, in.getChar(start)), index)
}
- }
+ )
/** Return the name found at given index in the constant pool, with '/' replaced by '.'. */
def getExternalName(index: Int): Name = {
@@ -179,28 +197,23 @@ abstract class ClassfileParser {
def getClassSymbol(index: Int): Symbol = {
if (index <= 0 || len <= index) errorBadIndex(index)
- var c = values(index).asInstanceOf[Symbol]
- if (c eq null) {
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
- val name = getExternalName(in.getChar(start + 1))
- if (nme.isModuleName(name))
- c = rootMirror.getModuleByName(nme.stripModuleSuffix(name))
- else
- c = classNameToSymbol(name)
-
- values(index) = c
+ values(index) match {
+ case sym: Symbol => sym
+ case _ =>
+ val result = getClassName(index) match {
+ case name if nme.isModuleName(name) => rootMirror getModuleByName name.dropModule
+ case name => classNameToSymbol(name)
+ }
+ recordAtIndex(result, index)
}
- c
}
/** Return the external name of the class info structure found at 'index'.
* Use 'getClassSymbol' if the class is sure to be a top-level class.
*/
def getClassName(index: Int): Name = {
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
- getExternalName(in.getChar(start + 1))
+ val start = firstExpecting(index, CONSTANT_CLASS)
+ getExternalName(in getChar start)
}
/** Return the symbol of the class member at `index`.
@@ -238,7 +251,7 @@ abstract class ClassfileParser {
if (f == NoSymbol)
f = rootMirror.getModuleByName(name dropRight 1)
} else {
- val origName = nme.originalName(name)
+ val origName = nme.unexpandedName(name)
val owner = if (static) ownerTpe.typeSymbol.linkedClassOfClass else ownerTpe.typeSymbol
// println("\t" + owner.info.member(name).tpe.widen + " =:= " + tpe)
f = owner.info.findMember(origName, 0, 0, stableOnly = false).suchThat(_.tpe.widen =:= tpe)
@@ -276,94 +289,66 @@ abstract class ClassfileParser {
*/
private def getNameAndType(index: Int, ownerTpe: Type): (Name, Type) = {
if (index <= 0 || len <= index) errorBadIndex(index)
- var p = values(index).asInstanceOf[(Name, Type)]
- if (p eq null) {
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_NAMEANDTYPE) errorBadTag(start)
- val name = getName(in.getChar(start + 1).toInt)
- // create a dummy symbol for method types
- val dummySym = ownerTpe.typeSymbol.newMethod(name.toTermName, ownerTpe.typeSymbol.pos)
- var tpe = getType(dummySym, in.getChar(start + 3).toInt)
-
- // fix the return type, which is blindly set to the class currently parsed
- if (name == nme.CONSTRUCTOR)
- tpe match {
- case MethodType(formals, restpe) =>
- tpe = MethodType(formals, ownerTpe)
+ (values(index): @unchecked) match {
+ case p: ((Name, Type)) => p
+ case _ =>
+ val start = firstExpecting(index, CONSTANT_NAMEANDTYPE)
+ val name = getName(in.getChar(start).toInt)
+ // create a dummy symbol for method types
+ val dummy = ownerTpe.typeSymbol.newMethod(name.toTermName, ownerTpe.typeSymbol.pos)
+ val tpe = getType(dummy, in.getChar(start + 2).toInt)
+ // fix the return type, which is blindly set to the class currently parsed
+ val restpe = tpe match {
+ case MethodType(formals, _) if name == nme.CONSTRUCTOR => MethodType(formals, ownerTpe)
+ case _ => tpe
}
-
- p = (name, tpe)
+ ((name, restpe))
}
- p
}
/** Return the type of a class constant entry. Since
* arrays are considered to be class types, they might
* appear as entries in 'newarray' or 'cast' opcodes.
*/
- def getClassOrArrayType(index: Int): Type = {
+ def getClassOrArrayType(index: Int): Type = (
if (index <= 0 || len <= index) errorBadIndex(index)
- val value = values(index)
- var c: Type = null
- if (value eq null) {
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
- val name = getExternalName(in.getChar(start + 1))
- if (name.charAt(0) == ARRAY_TAG) {
- c = sigToType(null, name)
- values(index) = c
- } else {
- val sym = classNameToSymbol(name)
- /*if (name.endsWith("$")) definitions.getModule(name.subName(0, name.length - 1))
- else if (name.endsWith("$class")) definitions.getModule(name)
- else definitions.getClass(name)*/
- values(index) = sym
- c = sym.tpe
- }
- } else c = value match {
- case tp: Type => tp
- case cls: Symbol => cls.tpe
+ else values(index) match {
+ case tp: Type => tp
+ case cls: Symbol => cls.tpe_*
+ case _ =>
+ val name = getClassName(index)
+ name charAt 0 match {
+ case ARRAY_TAG => recordAtIndex(sigToType(null, name), index)
+ case _ => recordAtIndex(classNameToSymbol(name), index).tpe_*
+ }
}
- c
- }
-
- def getType(index: Int): Type = getType(null, index)
-
- def getType(sym: Symbol, index: Int): Type =
- sigToType(sym, getExternalName(index))
+ )
- def getSuperClass(index: Int): Symbol =
- if (index == 0) definitions.AnyClass else getClassSymbol(index)
+ def getType(index: Int): Type = getType(null, index)
+ def getType(sym: Symbol, index: Int): Type = sigToType(sym, getExternalName(index))
+ def getSuperClass(index: Int): Symbol = if (index == 0) AnyClass else getClassSymbol(index)
- def getConstant(index: Int): Constant = {
+ private def createConstant(index: Int): Constant = {
+ val start = starts(index)
+ Constant((in.buf(start).toInt: @switch) match {
+ case CONSTANT_STRING => getName(in.getChar(start + 1).toInt).toString
+ case CONSTANT_INTEGER => in.getInt(start + 1)
+ case CONSTANT_FLOAT => in.getFloat(start + 1)
+ case CONSTANT_LONG => in.getLong(start + 1)
+ case CONSTANT_DOUBLE => in.getDouble(start + 1)
+ case CONSTANT_CLASS => getClassOrArrayType(index).typeSymbol.tpe_* // !!! Is this necessary or desirable?
+ case _ => errorBadTag(start)
+ })
+ }
+ def getConstant(index: Int): Constant = (
if (index <= 0 || len <= index) errorBadIndex(index)
- var value = values(index)
- if (value eq null) {
- val start = starts(index)
- value = (in.buf(start).toInt: @switch) match {
- case CONSTANT_STRING =>
- Constant(getName(in.getChar(start + 1).toInt).toString)
- case CONSTANT_INTEGER =>
- Constant(in.getInt(start + 1))
- case CONSTANT_FLOAT =>
- Constant(in.getFloat(start + 1))
- case CONSTANT_LONG =>
- Constant(in.getLong(start + 1))
- case CONSTANT_DOUBLE =>
- Constant(in.getDouble(start + 1))
- case CONSTANT_CLASS =>
- getClassOrArrayType(index).typeSymbol
- case _ =>
- errorBadTag(start)
- }
- values(index) = value
+ else values(index) match {
+ case const: Constant => const
+ case sym: Symbol => Constant(sym.tpe_*)
+ case tpe: Type => Constant(tpe)
+ case _ => recordAtIndex(createConstant(index), index)
}
- value match {
- case ct: Constant => ct
- case cls: Symbol => Constant(cls.tpe_*)
- case arr: Type => Constant(arr)
- }
- }
+ )
private def getSubArray(bytes: Array[Byte]): Array[Byte] = {
val decodedLength = ByteCodecs.decode(bytes)
@@ -372,46 +357,41 @@ abstract class ClassfileParser {
arr
}
- def getBytes(index: Int): Array[Byte] = {
+ def getBytes(index: Int): Array[Byte] = (
if (index <= 0 || len <= index) errorBadIndex(index)
- var value = values(index).asInstanceOf[Array[Byte]]
- if (value eq null) {
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start)
- val len = in.getChar(start + 1)
- val bytes = new Array[Byte](len)
- System.arraycopy(in.buf, start + 3, bytes, 0, len)
- value = getSubArray(bytes)
- values(index) = value
+ else values(index) match {
+ case xs: Array[Byte] => xs
+ case _ =>
+ val start = firstExpecting(index, CONSTANT_UTF8)
+ val len = in getChar start
+ val bytes = new Array[Byte](len)
+ System.arraycopy(in.buf, start + 2, bytes, 0, len)
+ recordAtIndex(getSubArray(bytes), index)
}
- value
- }
+ )
def getBytes(indices: List[Int]): Array[Byte] = {
- assert(!indices.isEmpty, indices)
- var value = values(indices.head).asInstanceOf[Array[Byte]]
- if (value eq null) {
- val bytesBuffer = ArrayBuffer.empty[Byte]
- for (index <- indices) {
- if (index <= 0 || ConstantPool.this.len <= index) errorBadIndex(index)
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start)
- val len = in.getChar(start + 1)
- bytesBuffer ++= in.buf.view(start + 3, start + 3 + len)
- }
- value = getSubArray(bytesBuffer.toArray)
- values(indices.head) = value
+ val head = indices.head
+ values(head) match {
+ case xs: Array[Byte] => xs
+ case _ =>
+ val arr: Array[Byte] = indices.toArray flatMap { index =>
+ if (index <= 0 || ConstantPool.this.len <= index) errorBadIndex(index)
+ val start = firstExpecting(index, CONSTANT_UTF8)
+ val len = in getChar start
+ in.buf drop start + 2 take len
+ }
+ recordAtIndex(getSubArray(arr), head)
}
- value
}
/** Throws an exception signaling a bad constant index. */
private def errorBadIndex(index: Int) =
- throw new RuntimeException("bad constant pool index: " + index + " at pos: " + in.bp)
+ abort(s"bad constant pool index: $index at pos: ${in.bp}")
/** Throws an exception signaling a bad tag at given address. */
private def errorBadTag(start: Int) =
- throw new RuntimeException("bad constant pool tag " + in.buf(start) + " at byte " + start)
+ abort("bad constant pool tag ${in.buf(start)} at byte $start")
}
/** Try to force the chain of enclosing classes for the given name. Otherwise
@@ -435,89 +415,82 @@ abstract class ClassfileParser {
sym
}
- /** Return the class symbol of the given name. */
- def classNameToSymbol(name: Name): Symbol = {
- def loadClassSymbol(name: Name): Symbol = {
- val file = global.classPath findSourceFile ("" +name) getOrElse {
- // SI-5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented
- // therefore, it will rummage through the classpath triggering errors whenever it encounters package objects
- // that are not in their correct place (see bug for details)
- if (!settings.isScaladoc)
- warning("Class " + name + " not found - continuing with a stub.")
- return NoSymbol.newClass(name.toTypeName)
- }
- val completer = new global.loaders.ClassfileLoader(file)
- var owner: Symbol = rootMirror.RootClass
- var sym: Symbol = NoSymbol
- var ss: Name = null
- var start = 0
- var end = name indexOf '.'
-
- while (end > 0) {
- ss = name.subName(start, end)
- sym = owner.info.decls lookup ss
- if (sym == NoSymbol) {
- sym = owner.newPackage(ss.toTermName) setInfo completer
- sym.moduleClass setInfo completer
- owner.info.decls enter sym
- }
- owner = sym.moduleClass
- start = end + 1
- end = name.indexOf('.', start)
- }
- ss = name.subName(0, start)
- owner.info.decls lookup ss orElse {
- sym = owner.newClass(ss.toTypeName) setInfoAndEnter completer
- debuglog("loaded "+sym+" from file "+file)
- sym
+ private def loadClassSymbol(name: Name): Symbol = {
+ val file = global.classPath findSourceFile ("" +name) getOrElse {
+ // SI-5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented
+ // therefore, it will rummage through the classpath triggering errors whenever it encounters package objects
+ // that are not in their correct place (see bug for details)
+ if (!settings.isScaladoc)
+ warning(s"Class $name not found - continuing with a stub.")
+ return NoSymbol.newClass(name.toTypeName)
+ }
+ val completer = new global.loaders.ClassfileLoader(file)
+ var owner: Symbol = rootMirror.RootClass
+ var sym: Symbol = NoSymbol
+ var ss: Name = null
+ var start = 0
+ var end = name indexOf '.'
+
+ while (end > 0) {
+ ss = name.subName(start, end)
+ sym = owner.info.decls lookup ss
+ if (sym == NoSymbol) {
+ sym = owner.newPackage(ss.toTermName) setInfo completer
+ sym.moduleClass setInfo completer
+ owner.info.decls enter sym
}
+ owner = sym.moduleClass
+ start = end + 1
+ end = name.indexOf('.', start)
}
-
- def lookupClass(name: Name) = try {
- if (name.pos('.') == name.length)
- definitions.getMember(rootMirror.EmptyPackageClass, name.toTypeName)
- else
- rootMirror.getClassByName(name) // see tickets #2464, #3756
- } catch {
- case _: FatalError => loadClassSymbol(name)
- }
-
- innerClasses.get(name) match {
- case Some(entry) =>
- //println("found inner class " + name)
- val res = innerClasses.classSymbol(entry.externalName)
- //println("\trouted to: " + res)
- res
- case None =>
- //if (name.toString.contains("$")) println("No inner class: " + name + innerClasses + " while parsing " + in.file.name)
- lookupClass(name)
+ ss = name.subName(0, start)
+ owner.info.decls lookup ss orElse {
+ sym = owner.newClass(ss.toTypeName) setInfoAndEnter completer
+ debuglog("loaded "+sym+" from file "+file)
+ sym
}
}
- var sawPrivateConstructor = false
+ /** FIXME - we shouldn't be doing ad hoc lookups in the empty package.
+ * The method called "getClassByName" should either return the class or not.
+ */
+ private def lookupClass(name: Name) = (
+ if (name containsChar '.')
+ rootMirror getClassByName name // see tickets #2464, #3756
+ else
+ definitions.getMember(rootMirror.EmptyPackageClass, name.toTypeName)
+ )
+
+ /** Return the class symbol of the given name. */
+ def classNameToSymbol(name: Name): Symbol = {
+ if (innerClasses contains name)
+ innerClasses innerSymbol name
+ else
+ try lookupClass(name)
+ catch { case _: FatalError => loadClassSymbol(name) }
+ }
def parseClass() {
- val jflags = in.nextChar
- val isAnnotation = hasAnnotation(jflags)
- val sflags = toScalaClassFlags(jflags)
- val nameIdx = in.nextChar
- currentClass = pool.getClassName(nameIdx)
+ val jflags = readClassFlags()
+ val sflags = jflags.toScalaFlags
+ val nameIdx = u2
+ currentClass = pool.getClassName(nameIdx)
/* Parse parents for Java classes. For Scala, return AnyRef, since the real type will be unpickled.
* Updates the read pointer of 'in'. */
def parseParents: List[Type] = {
if (isScala) {
- in.nextChar // skip superclass
- val ifaces = in.nextChar
- in.bp += ifaces * 2 // .. and iface count interfaces
- List(definitions.AnyRefClass.tpe) // dummy superclass, will be replaced by pickled information
+ u2 // skip superclass
+ val ifaces = u2
+ in.bp += ifaces * 2 // .. and iface count interfaces
+ List(AnyRefClass.tpe) // dummy superclass, will be replaced by pickled information
}
else raiseLoaderLevel {
- val superType = if (isAnnotation) { in.nextChar; definitions.AnnotationClass.tpe }
- else pool.getSuperClass(in.nextChar).tpe_*
- val ifaceCount = in.nextChar
- var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(in.nextChar).tpe_*
- if (isAnnotation) ifaces = definitions.ClassfileAnnotationClass.tpe :: ifaces
+ val superType = if (jflags.isAnnotation) { u2; AnnotationClass.tpe }
+ else pool.getSuperClass(u2).tpe_*
+ val ifaceCount = u2
+ var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(u2).tpe_*
+ if (jflags.isAnnotation) ifaces ::= ClassfileAnnotationClass.tpe
superType :: ifaces
}
}
@@ -547,21 +520,20 @@ abstract class ClassfileParser {
skipMembers() // methods
if (!isScala) {
clazz setFlag sflags
- importPrivateWithinFromJavaFlags(clazz, jflags)
- importPrivateWithinFromJavaFlags(staticModule, jflags)
- clazz.setInfo(classInfo)
+ propagatePackageBoundary(jflags, clazz, staticModule)
+ clazz setInfo classInfo
moduleClass setInfo staticInfo
- staticModule.setInfo(moduleClass.tpe)
- staticModule.setFlag(JAVA)
- staticModule.moduleClass.setFlag(JAVA)
+ staticModule setInfo moduleClass.tpe
+ staticModule setFlag JAVA
+ staticModule.moduleClass setFlag JAVA
// attributes now depend on having infos set already
parseAttributes(clazz, classInfo)
def queueLoad() {
in.bp = curbp
- 0 until in.nextChar foreach (_ => parseField())
+ 0 until u2 foreach (_ => parseField())
sawPrivateConstructor = false
- 0 until in.nextChar foreach (_ => parseMethod())
+ 0 until u2 foreach (_ => parseMethod())
val needsConstructor = (
!sawPrivateConstructor
&& !(instanceScope containsName nme.CONSTRUCTOR)
@@ -597,26 +569,28 @@ abstract class ClassfileParser {
}
def parseField() {
- val jflags = in.nextChar
- val sflags = toScalaFieldFlags(jflags)
- if ((sflags & PRIVATE) != 0L && !global.settings.optimise.value) {
+ val jflags = readFieldFlags()
+ val sflags = jflags.toScalaFlags
+
+ if ((sflags & PRIVATE) != 0L && !optimized) {
in.skip(4); skipAttributes()
} else {
- val name = pool.getName(in.nextChar)
- val info = pool.getType(in.nextChar)
- val sym = getOwner(jflags).newValue(name.toTermName, NoPosition, sflags)
- val isEnum = (jflags & JAVA_ACC_ENUM) != 0
+ val name = readName()
+ val info = readType()
+ val sym = ownerForFlags(jflags).newValue(name.toTermName, NoPosition, sflags)
+ // Note: the info may be overrwritten later with a generic signature
+ // parsed from SignatureATTR
sym setInfo {
- if (isEnum) ConstantType(Constant(sym))
+ if (jflags.isEnum) ConstantType(Constant(sym))
else info
}
- importPrivateWithinFromJavaFlags(sym, jflags)
+ propagatePackageBoundary(jflags, sym)
parseAttributes(sym, info)
- getScope(jflags).enter(sym)
+ getScope(jflags) enter sym
// sealed java enums
- if (isEnum) {
+ if (jflags.isEnum) {
val enumClass = sym.owner.linkedClassOfClass
if (!enumClass.isSealed)
enumClass setFlag (SEALED | ABSTRACT)
@@ -627,26 +601,27 @@ abstract class ClassfileParser {
}
def parseMethod() {
- val jflags = in.nextChar.toInt
- val sflags = toScalaMethodFlags(jflags)
- if (isPrivate(jflags) && !global.settings.optimise.value) {
- val name = pool.getName(in.nextChar)
+ val jflags = readMethodFlags()
+ val sflags = jflags.toScalaFlags
+ if (jflags.isPrivate && !optimized) {
+ val name = readName()
if (name == nme.CONSTRUCTOR)
sawPrivateConstructor = true
in.skip(2); skipAttributes()
- } else {
- if ((sflags & PRIVATE) != 0L && global.settings.optimise.value) {
+ }
+ else {
+ if ((sflags & PRIVATE) != 0L && optimized) {
in.skip(4); skipAttributes()
} else {
- val name = pool.getName(in.nextChar)
- val sym = getOwner(jflags).newMethod(name.toTermName, NoPosition, sflags)
- var info = pool.getType(sym, (in.nextChar))
+ val name = readName()
+ val sym = ownerForFlags(jflags).newMethod(name.toTermName, NoPosition, sflags)
+ var info = pool.getType(sym, u2)
if (name == nme.CONSTRUCTOR)
info match {
case MethodType(params, restpe) =>
// if this is a non-static inner class, remove the explicit outer parameter
- val newParams = innerClasses.get(currentClass) match {
- case Some(entry) if !isScalaRaw && !isStatic(entry.jflags) =>
+ val newParams = innerClasses getEntry currentClass match {
+ case Some(entry) if !isScalaRaw && !entry.jflags.isStatic =>
/* About `clazz.owner.isPackage` below: SI-5957
* For every nested java class A$B, there are two symbols in the scala compiler.
* 1. created by SymbolLoader, because of the existence of the A$B.class file, owner: package
@@ -661,13 +636,15 @@ abstract class ClassfileParser {
}
info = MethodType(newParams, clazz.tpe)
}
- sym.setInfo(info)
- importPrivateWithinFromJavaFlags(sym, jflags)
+ // Note: the info may be overrwritten later with a generic signature
+ // parsed from SignatureATTR
+ sym setInfo info
+ propagatePackageBoundary(jflags, sym)
parseAttributes(sym, info)
- if ((jflags & JAVA_ACC_VARARGS) != 0) {
- sym.setInfo(arrayToRepeated(sym.info))
- }
- getScope(jflags).enter(sym)
+ if (jflags.isVarargs)
+ sym modifyInfo arrayToRepeated
+
+ getScope(jflags) enter sym
}
}
}
@@ -687,15 +664,15 @@ abstract class ClassfileParser {
def sig2type(tparams: immutable.Map[Name,Symbol], skiptvs: Boolean): Type = {
val tag = sig.charAt(index); index += 1
tag match {
- case BYTE_TAG => definitions.ByteClass.tpe
- case CHAR_TAG => definitions.CharClass.tpe
- case DOUBLE_TAG => definitions.DoubleClass.tpe
- case FLOAT_TAG => definitions.FloatClass.tpe
- case INT_TAG => definitions.IntClass.tpe
- case LONG_TAG => definitions.LongClass.tpe
- case SHORT_TAG => definitions.ShortClass.tpe
- case VOID_TAG => definitions.UnitClass.tpe
- case BOOL_TAG => definitions.BooleanClass.tpe
+ case BYTE_TAG => ByteClass.tpe
+ case CHAR_TAG => CharClass.tpe
+ case DOUBLE_TAG => DoubleClass.tpe
+ case FLOAT_TAG => FloatClass.tpe
+ case INT_TAG => IntClass.tpe
+ case LONG_TAG => LongClass.tpe
+ case SHORT_TAG => ShortClass.tpe
+ case VOID_TAG => UnitClass.tpe
+ case BOOL_TAG => BooleanClass.tpe
case 'L' =>
def processInner(tp: Type): Type = tp match {
case TypeRef(pre, sym, args) if (!sym.isStatic) =>
@@ -720,7 +697,7 @@ abstract class ClassfileParser {
val tp = sig2type(tparams, skiptvs)
// sig2type seems to return AnyClass regardless of the situation:
// we don't want Any as a LOWER bound.
- if (tp.typeSymbol == definitions.AnyClass) TypeBounds.empty
+ if (tp.typeSymbol == AnyClass) TypeBounds.empty
else TypeBounds.lower(tp)
case '*' => TypeBounds.empty
}
@@ -741,9 +718,9 @@ abstract class ClassfileParser {
// or we'll create a boatload of needless existentials.
else if (classSym.isMonomorphicType || classSym.unsafeTypeParams.isEmpty) tp
// raw type - existentially quantify all type parameters
- else logResult(s"raw type from $classSym")(definitions.unsafeClassExistentialType(classSym))
+ else logResult(s"raw type from $classSym")(unsafeClassExistentialType(classSym))
case tp =>
- assert(sig.charAt(index) != '<', tp)
+ assert(sig.charAt(index) != '<', s"sig=$sig, index=$index, tp=$tp")
tp
}
@@ -754,7 +731,9 @@ abstract class ClassfileParser {
accept('.')
val name = subName(c => c == ';' || c == '<' || c == '.').toTypeName
val clazz = tpe.member(name)
- tpe = processClassType(processInner(clazz.tpe))
+ val dummyArgs = Nil // the actual arguments are added in processClassType
+ val inner = typeRef(pre = tpe, sym = clazz, args = dummyArgs)
+ tpe = processClassType(inner)
}
accept(';')
tpe
@@ -767,11 +746,11 @@ abstract class ClassfileParser {
// NOTE that the comparison to Object only works for abstract types bounded by classes that are strict subclasses of Object
// if the bound is exactly Object, it will have been converted to Any, and the comparison will fail
// see also RestrictJavaArraysMap (when compiling java sources directly)
- if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe)) {
- elemtp = intersectionType(List(elemtp, definitions.ObjectClass.tpe))
+ if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< ObjectClass.tpe)) {
+ elemtp = intersectionType(List(elemtp, ObjectClass.tpe))
}
- definitions.arrayType(elemtp)
+ arrayType(elemtp)
case '(' =>
// we need a method symbol. given in line 486 by calling getType(methodSym, ..)
assert(sym ne null, sig)
@@ -789,7 +768,7 @@ abstract class ClassfileParser {
case 'T' =>
val n = subName(';'.==).toTypeName
index += 1
- if (skiptvs) definitions.AnyClass.tpe
+ if (skiptvs) AnyClass.tpe
else tparams(n).typeConstructor
}
} // sig2type(tparams, skiptvs)
@@ -842,27 +821,23 @@ abstract class ClassfileParser {
GenPolyType(ownTypeParams, tpe)
} // sigToType
- class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType with FlagAgnosticCompleter {
- override def complete(sym: Symbol) { throw new AssertionError("cyclic type dereferencing") }
- }
-
def parseAttributes(sym: Symbol, symtype: Type) {
def convertTo(c: Constant, pt: Type): Constant = {
- if (pt.typeSymbol == definitions.BooleanClass && c.tag == IntTag)
+ if (pt.typeSymbol == BooleanClass && c.tag == IntTag)
Constant(c.value != 0)
else
c convertTo pt
}
def parseAttribute() {
- val attrName = pool.getName(in.nextChar).toTypeName
- val attrLen = in.nextInt
+ val attrName = readTypeName()
+ val attrLen = u4
attrName match {
case tpnme.SignatureATTR =>
if (!isScala && !isScalaRaw) {
- val sig = pool.getExternalName(in.nextChar)
+ val sig = pool.getExternalName(u2)
val newType = sigToType(sym, sig)
sym.setInfo(newType)
- if (settings.debug.value && settings.verbose.value)
+ if (settings.debug && settings.verbose)
println("" + sym + "; signature = " + sig + " type = " + newType)
}
else in.skip(attrLen)
@@ -874,10 +849,10 @@ abstract class ClassfileParser {
in.skip(attrLen)
case tpnme.DeprecatedATTR =>
val arg = Literal(Constant("see corresponding Javadoc for more information."))
- sym.addAnnotation(definitions.DeprecatedAttr, arg, Literal(Constant("")))
+ sym.addAnnotation(DeprecatedAttr, arg, Literal(Constant("")))
in.skip(attrLen)
case tpnme.ConstantValueATTR =>
- val c = pool.getConstant(in.nextChar)
+ val c = pool.getConstant(u2)
val c1 = convertTo(c, symtype)
if (c1 ne null) sym.setInfo(ConstantType(c1))
else println("failure to convert " + c + " to " + symtype); //debug
@@ -891,7 +866,7 @@ abstract class ClassfileParser {
isScalaRaw = true
// Attribute on methods of java annotation classes when that method has a default
case tpnme.AnnotationDefaultATTR =>
- sym.addAnnotation(definitions.AnnotationDefaultAttr)
+ sym.addAnnotation(AnnotationDefaultAttr)
in.skip(attrLen)
// Java annotations on classes / methods / fields with RetentionPolicy.RUNTIME
case tpnme.RuntimeAnnotationATTR =>
@@ -921,7 +896,7 @@ abstract class ClassfileParser {
parseExceptions(attrLen)
case tpnme.SourceFileATTR =>
- val srcfileLeaf = pool.getName(in.nextChar).toString.trim
+ val srcfileLeaf = readName().toString.trim
val srcpath = sym.enclosingPackage match {
case NoSymbol => srcfileLeaf
case rootMirror.EmptyPackage => srcfileLeaf
@@ -934,8 +909,8 @@ abstract class ClassfileParser {
}
def parseAnnotArg: Option[ClassfileAnnotArg] = {
- val tag = in.nextByte.toChar
- val index = in.nextChar
+ val tag = u1
+ val index = u2
tag match {
case STRING_TAG =>
Some(LiteralAnnotArg(Constant(pool.getName(index).toString)))
@@ -946,7 +921,7 @@ abstract class ClassfileParser {
Some(LiteralAnnotArg(Constant(pool.getType(index))))
case ENUM_TAG =>
val t = pool.getType(index)
- val n = pool.getName(in.nextChar)
+ val n = readName()
val s = t.typeSymbol.companionModule.info.decls.lookup(n)
assert(s != NoSymbol, t)
Some(LiteralAnnotArg(Constant(s)))
@@ -966,20 +941,20 @@ abstract class ClassfileParser {
}
def parseScalaSigBytes: Option[ScalaSigBytes] = {
- val tag = in.nextByte.toChar
+ val tag = u1
assert(tag == STRING_TAG, tag)
- Some(ScalaSigBytes(pool getBytes in.nextChar))
+ Some(ScalaSigBytes(pool getBytes u2))
}
def parseScalaLongSigBytes: Option[ScalaSigBytes] = {
- val tag = in.nextByte.toChar
+ val tag = u1
assert(tag == ARRAY_TAG, tag)
- val stringCount = in.nextChar
+ val stringCount = u2
val entries =
for (i <- 0 until stringCount) yield {
- val stag = in.nextByte.toChar
+ val stag = u1
assert(stag == STRING_TAG, stag)
- in.nextChar.toInt
+ u2.toInt
}
Some(ScalaSigBytes(pool.getBytes(entries.toList)))
}
@@ -989,20 +964,20 @@ abstract class ClassfileParser {
*/
def parseAnnotation(attrNameIndex: Char): Option[AnnotationInfo] = try {
val attrType = pool.getType(attrNameIndex)
- val nargs = in.nextChar
+ val nargs = u2
val nvpairs = new ListBuffer[(Name, ClassfileAnnotArg)]
var hasError = false
for (i <- 0 until nargs) {
- val name = pool.getName(in.nextChar)
+ val name = readName()
// The "bytes: String" argument of the ScalaSignature attribute is parsed specially so that it is
// available as an array of bytes (the pickled Scala signature) instead of as a string. The pickled signature
// is encoded as a string because of limitations in the Java class file format.
- if ((attrType == definitions.ScalaSignatureAnnotation.tpe) && (name == nme.bytes))
+ if ((attrType == ScalaSignatureAnnotation.tpe) && (name == nme.bytes))
parseScalaSigBytes match {
case Some(c) => nvpairs += ((name, c))
case None => hasError = true
}
- else if ((attrType == definitions.ScalaLongSignatureAnnotation.tpe) && (name == nme.bytes))
+ else if ((attrType == ScalaLongSignatureAnnotation.tpe) && (name == nme.bytes))
parseScalaLongSigBytes match {
case Some(c) => nvpairs += ((name, c))
case None => hasError = true
@@ -1025,7 +1000,7 @@ abstract class ClassfileParser {
// with a `FatalError` exception, handled above. Here you'd end up after a NPE (for example),
// and that should never be swallowed silently.
warning("Caught: " + ex + " while parsing annotations in " + in.file)
- if (settings.debug.value) ex.printStackTrace()
+ if (settings.debug) ex.printStackTrace()
None // ignore malformed annotations
}
@@ -1035,10 +1010,10 @@ abstract class ClassfileParser {
* thrown by a method.
*/
def parseExceptions(len: Int) {
- val nClasses = in.nextChar
+ val nClasses = u2
for (n <- 0 until nClasses) {
// FIXME: this performs an equivalent of getExceptionTypes instead of getGenericExceptionTypes (SI-7065)
- val cls = pool.getClassSymbol(in.nextChar.toInt)
+ val cls = pool.getClassSymbol(u2)
// we call initialize due to the fact that we call Symbol.isMonomorphicType in addThrowsAnnotation
// and that method requires Symbol to be forced to give the right answers, see SI-7107 for details
cls.initialize
@@ -1049,13 +1024,13 @@ abstract class ClassfileParser {
/* Parse a sequence of annotations and attaches them to the
* current symbol sym, except for the ScalaSignature annotation that it returns, if it is available. */
def parseAnnotations(len: Int): Option[AnnotationInfo] = {
- val nAttr = in.nextChar
+ val nAttr = u2
var scalaSigAnnot: Option[AnnotationInfo] = None
for (n <- 0 until nAttr)
- parseAnnotation(in.nextChar) match {
- case Some(scalaSig) if (scalaSig.atp == definitions.ScalaSignatureAnnotation.tpe) =>
+ parseAnnotation(u2) match {
+ case Some(scalaSig) if (scalaSig.atp == ScalaSignatureAnnotation.tpe) =>
scalaSigAnnot = Some(scalaSig)
- case Some(scalaSig) if (scalaSig.atp == definitions.ScalaLongSignatureAnnotation.tpe) =>
+ case Some(scalaSig) if (scalaSig.atp == ScalaLongSignatureAnnotation.tpe) =>
scalaSigAnnot = Some(scalaSig)
case Some(annot) =>
sym.addAnnotation(annot)
@@ -1065,7 +1040,7 @@ abstract class ClassfileParser {
}
// begin parseAttributes
- for (i <- 0 until in.nextChar) parseAttribute()
+ for (i <- 0 until u2) parseAttribute()
}
/** Enter own inner classes in the right scope. It needs the scopes to be set up,
@@ -1075,11 +1050,12 @@ abstract class ClassfileParser {
def className(name: Name): Name =
name.subName(name.lastPos('.') + 1, name.length)
- def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile, jflags: Int) {
+ def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile) {
+ def jflags = entry.jflags
val completer = new global.loaders.ClassfileLoader(file)
val name = entry.originalName
- val sflags = toScalaClassFlags(jflags)
- val owner = getOwner(jflags)
+ val sflags = jflags.toScalaFlags
+ val owner = ownerForFlags(jflags)
val scope = getScope(jflags)
val innerClass = owner.newClass(name.toTypeName, NoPosition, sflags) setInfo completer
val innerModule = owner.newModule(name.toTermName, NoPosition, sflags) setInfo completer
@@ -1102,13 +1078,13 @@ abstract class ClassfileParser {
unlinkIfPresent(cName.toTypeName)
}
- for (entry <- innerClasses.values) {
+ for (entry <- innerClasses.entries) {
// create a new class member for immediate inner classes
if (entry.outerName == currentClass) {
val file = global.classPath.findSourceFile(entry.externalName.toString) getOrElse {
throw new AssertionError(entry.externalName)
}
- enterClassAndModule(entry, file, entry.jflags)
+ enterClassAndModule(entry, file)
}
}
}
@@ -1121,10 +1097,10 @@ abstract class ClassfileParser {
skipSuperclasses()
skipMembers() // fields
skipMembers() // methods
- val attrs = in.nextChar
+ val attrs = u2
for (i <- 0 until attrs) {
- val attrName = pool.getName(in.nextChar).toTypeName
- val attrLen = in.nextInt
+ val attrName = readTypeName()
+ val attrLen = u4
attrName match {
case tpnme.SignatureATTR =>
in.skip(attrLen)
@@ -1138,16 +1114,12 @@ abstract class ClassfileParser {
case tpnme.ScalaATTR =>
isScalaRaw = true
case tpnme.InnerClassesATTR if !isScala =>
- val entries = in.nextChar.toInt
+ val entries = u2
for (i <- 0 until entries) {
- val innerIndex = in.nextChar.toInt
- val outerIndex = in.nextChar.toInt
- val nameIndex = in.nextChar.toInt
- val jflags = in.nextChar.toInt
- if (innerIndex != 0 && outerIndex != 0 && nameIndex != 0) {
- val entry = InnerClassEntry(innerIndex, outerIndex, nameIndex, jflags)
- innerClasses += (pool.getClassName(innerIndex) -> entry)
- }
+ val innerIndex, outerIndex, nameIndex = u2
+ val jflags = readInnerClassFlags()
+ if (innerIndex != 0 && outerIndex != 0 && nameIndex != 0)
+ innerClasses add InnerClassEntry(innerIndex, outerIndex, nameIndex, jflags)
}
case _ =>
in.skip(attrLen)
@@ -1157,65 +1129,67 @@ abstract class ClassfileParser {
}
/** An entry in the InnerClasses attribute of this class file. */
- case class InnerClassEntry(external: Int, outer: Int, name: Int, jflags: Int) {
+ case class InnerClassEntry(external: Int, outer: Int, name: Int, jflags: JavaAccFlags) {
def externalName = pool getClassName external
def outerName = pool getClassName outer
def originalName = pool getName name
-
- override def toString =
- originalName + " in " + outerName + "(" + externalName +")"
+ def isModule = originalName.isTermName
+ def scope = if (jflags.isStatic) staticScope else instanceScope
+ def enclosing = if (jflags.isStatic) enclModule else enclClass
+
+ // The name of the outer class, without its trailing $ if it has one.
+ private def strippedOuter = nme stripModuleSuffix outerName
+ private def isInner = innerClasses contains strippedOuter
+ private def enclClass = if (isInner) innerClasses innerSymbol strippedOuter else classNameToSymbol(strippedOuter)
+ private def enclModule = enclClass.companionModule
}
- object innerClasses extends mutable.HashMap[Name, InnerClassEntry] {
- /** Return the class symbol for `externalName`. It looks it up in its outer class.
- * Forces all outer class symbols to be completed.
- *
- * If the given name is not an inner class, it returns the symbol found in `definitions`.
- */
- def classSymbol(externalName: Name): Symbol = {
- /* Return the symbol of `innerName`, having the given `externalName`. */
- def innerSymbol(externalName: Name, innerName: Name, static: Boolean): Symbol = {
- def getMember(sym: Symbol, name: Name): Symbol =
- if (static)
- if (sym == clazz) staticScope.lookup(name)
- else sym.companionModule.info.member(name)
- else
- if (sym == clazz) instanceScope.lookup(name)
- else sym.info.member(name)
-
- innerClasses.get(externalName) match {
- case Some(entry) =>
- val outerName = nme.stripModuleSuffix(entry.outerName)
- val sym = classSymbol(outerName)
- val s =
- // if loading during initialization of `definitions` typerPhase is not yet set.
- // in that case we simply load the member at the current phase
- if (currentRun.typerPhase != null)
- enteringTyper(getMember(sym, innerName.toTypeName))
- else
- getMember(sym, innerName.toTypeName)
-
- assert(s ne NoSymbol,
- "" + ((externalName, outerName, innerName, sym.fullLocationString)) + " / " +
- " while parsing " + ((in.file, busy)) +
- sym + "." + innerName + " linkedModule: " + sym.companionModule + sym.companionModule.info.members
- )
- s
-
- case None =>
- classNameToSymbol(externalName)
- }
- }
-
- get(externalName) match {
- case Some(entry) =>
- innerSymbol(entry.externalName, entry.originalName, isStatic(entry.jflags))
- case None =>
- classNameToSymbol(externalName)
- }
+ /** Return the class symbol for the given name. It looks it up in its outer class.
+ * Forces all outer class symbols to be completed.
+ *
+ * If the given name is not an inner class, it returns the symbol found in `definitions`.
+ */
+ object innerClasses {
+ private val inners = mutable.HashMap[Name, InnerClassEntry]()
+
+ def contains(name: Name) = inners contains name
+ def getEntry(name: Name) = inners get name
+ def entries = inners.values
+
+ def add(entry: InnerClassEntry): Unit = {
+ inners get entry.externalName foreach (existing =>
+ debugwarn(s"Overwriting inner class entry! Was $existing, now $entry")
+ )
+ inners(entry.externalName) = entry
+ }
+ def innerSymbol(externalName: Name): Symbol = this getEntry externalName match {
+ case Some(entry) => innerSymbol(entry)
+ case _ => NoSymbol
+ }
+ // if loading during initialization of `definitions` typerPhase is not yet set.
+ // in that case we simply load the member at the current phase
+ @inline private def enteringTyperIfPossible(body: => Symbol): Symbol =
+ if (currentRun.typerPhase eq null) body else enteringTyper(body)
+
+ private def innerSymbol(entry: InnerClassEntry): Symbol = {
+ val name = entry.originalName.toTypeName
+ val enclosing = entry.enclosing
+ def getMember = (
+ if (enclosing == clazz) entry.scope lookup name
+ else enclosing.info member name
+ )
+ enteringTyperIfPossible(getMember)
+ /** There used to be an assertion that this result is not NoSymbol; changing it to an error
+ * revealed it had been going off all the time, but has been swallowed by a catch t: Throwable
+ * in Repository.scala. Since it has been accomplishing nothing except misleading anyone who
+ * thought it wasn't triggering, I removed it entirely.
+ */
}
}
+ class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType with FlagAgnosticCompleter {
+ override def complete(sym: Symbol) { throw new AssertionError("cyclic type dereferencing") }
+ }
class LazyAliasType(alias: Symbol) extends LazyType with FlagAgnosticCompleter {
override def complete(sym: Symbol) {
sym setInfo createFromClonedSymbols(alias.initialize.typeParams, alias.tpe)(typeFun)
@@ -1223,16 +1197,16 @@ abstract class ClassfileParser {
}
def skipAttributes() {
- var attrCount: Int = in.nextChar
+ var attrCount: Int = u2
while (attrCount > 0) {
in skip 2
- in skip in.nextInt
+ in skip u4
attrCount -= 1
}
}
def skipMembers() {
- var memberCount: Int = in.nextChar
+ var memberCount: Int = u2
while (memberCount > 0) {
in skip 6
skipAttributes()
@@ -1242,17 +1216,10 @@ abstract class ClassfileParser {
def skipSuperclasses() {
in.skip(2) // superclass
- val ifaces = in.nextChar
+ val ifaces = u2
in.skip(2 * ifaces)
}
- protected def getOwner(flags: Int): Symbol =
- if (isStatic(flags)) moduleClass else clazz
-
- protected def getScope(flags: Int): Scope =
- if (isStatic(flags)) staticScope else instanceScope
-
- private def isPrivate(flags: Int) = (flags & JAVA_ACC_PRIVATE) != 0
- private def isStatic(flags: Int) = (flags & JAVA_ACC_STATIC) != 0
- private def hasAnnotation(flags: Int) = (flags & JAVA_ACC_ANNOTATION) != 0
+ protected def getScope(flags: JavaAccFlags): Scope =
+ if (flags.isStatic) staticScope else instanceScope
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 86f034223d..50487ad123 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -10,6 +10,7 @@ package classfile
import scala.collection.{ mutable, immutable }
import mutable.ListBuffer
import ClassfileConstants._
+import scala.reflect.internal.JavaAccFlags
/** ICode reader from Java bytecode.
*
@@ -45,26 +46,19 @@ abstract class ICodeReader extends ClassfileParser {
(staticCode, instanceCode)
}
- /** If we're parsing a scala module, the owner of members is always
- * the module symbol.
- */
- override def getOwner(jflags: Int): Symbol =
- if (isScalaModule) this.staticModule
- else super.getOwner(jflags)
-
override def parseClass() {
this.instanceCode = new IClass(clazz)
this.staticCode = new IClass(staticModule)
- in.nextChar
- pool getClassSymbol in.nextChar
+ u2
+ pool getClassSymbol u2
parseInnerClasses()
in.skip(2) // super class
- in.skip(2 * in.nextChar) // interfaces
- val fieldCount = in.nextChar
+ in.skip(2 * u2) // interfaces
+ val fieldCount = u2
for (i <- 0 until fieldCount) parseField()
- val methodCount = in.nextChar
+ val methodCount = u2
for (i <- 0 until methodCount) parseMethod()
instanceCode.methods = instanceCode.methods.reverse
staticCode.methods = staticCode.methods.reverse
@@ -76,25 +70,31 @@ abstract class ICodeReader extends ClassfileParser {
skipAttributes()
}
- private def parseMember(field: Boolean): (Int, Symbol) = {
- val jflags = in.nextChar
- val name = pool getName in.nextChar
- val owner = getOwner(jflags)
- val dummySym = owner.newMethod(name.toTermName, owner.pos, toScalaMethodFlags(jflags))
+ private def parseMember(field: Boolean): (JavaAccFlags, Symbol) = {
+ val jflags = JavaAccFlags(u2)
+ val name = pool getName u2
+ /** If we're parsing a scala module, the owner of members is always
+ * the module symbol.
+ */
+ val owner = (
+ if (isScalaModule) staticModule
+ else if (jflags.isStatic) moduleClass
+ else clazz
+ )
+ val dummySym = owner.newMethod(name.toTermName, owner.pos, jflags.toScalaFlags)
try {
- val ch = in.nextChar
+ val ch = u2
val tpe = pool.getType(dummySym, ch)
if ("<clinit>" == name.toString)
(jflags, NoSymbol)
else {
- val owner = getOwner(jflags)
var sym = owner.info.findMember(name, 0, 0, stableOnly = false).suchThat(old => sameType(old.tpe, tpe))
if (sym == NoSymbol)
sym = owner.info.findMember(newTermName(name + nme.LOCAL_SUFFIX_STRING), 0, 0, stableOnly = false).suchThat(_.tpe =:= tpe)
if (sym == NoSymbol) {
- sym = if (field) owner.newValue(name.toTermName, owner.pos, toScalaFieldFlags(jflags)) else dummySym
+ sym = if (field) owner.newValue(name.toTermName, owner.pos, jflags.toScalaFlags) else dummySym
sym setInfoAndEnter tpe
log(s"ICodeReader could not locate ${name.decode} in $owner. Created ${sym.defString}.")
}
@@ -126,9 +126,9 @@ abstract class ICodeReader extends ClassfileParser {
this.method = new IMethod(sym)
this.method.returnType = toTypeKind(sym.tpe.resultType)
getCode(jflags).addMethod(this.method)
- if ((jflags & JAVA_ACC_NATIVE) != 0)
+ if (jflags.isNative)
this.method.native = true
- val attributeCount = in.nextChar
+ val attributeCount = u2
for (i <- 0 until attributeCount) parseAttribute()
} else {
debuglog("Skipping non-existent method.")
@@ -142,8 +142,8 @@ abstract class ICodeReader extends ClassfileParser {
}
def parseAttribute() {
- val attrName = pool.getName(in.nextChar).toTypeName
- val attrLen = in.nextInt
+ val attrName = pool.getName(u2).toTypeName
+ val attrLen = u4
attrName match {
case tpnme.CodeATTR =>
parseByteCode()
@@ -164,7 +164,7 @@ abstract class ICodeReader extends ClassfileParser {
rootMirror.getClassByName(name)
}
else if (nme.isModuleName(name)) {
- val strippedName = nme.stripModuleSuffix(name)
+ val strippedName = name.dropModule
forceMangledName(newTermName(strippedName.decode), module = true) orElse rootMirror.getModuleByName(strippedName)
}
else {
@@ -187,9 +187,9 @@ abstract class ICodeReader extends ClassfileParser {
/** Parse java bytecode into ICode */
def parseByteCode() {
- maxStack = in.nextChar
- maxLocals = in.nextChar
- val codeLength = in.nextInt
+ maxStack = u2
+ maxLocals = u2
+ val codeLength = u4
val code = new LinearCode
def parseInstruction() {
@@ -200,7 +200,7 @@ abstract class ICodeReader extends ClassfileParser {
/* Parse 16 bit jump target. */
def parseJumpTarget = {
size += 2
- val offset = in.nextChar.toShort
+ val offset = u2.toShort
val target = pc + offset
assert(target >= 0 && target < codeLength, "Illegal jump target: " + target)
target
@@ -209,14 +209,13 @@ abstract class ICodeReader extends ClassfileParser {
/* Parse 32 bit jump target. */
def parseJumpTargetW: Int = {
size += 4
- val offset = in.nextInt
+ val offset = u4
val target = pc + offset
assert(target >= 0 && target < codeLength, "Illegal jump target: " + target + "pc: " + pc + " offset: " + offset)
target
}
- val instr = toUnsignedByte(in.nextByte)
- instr match {
+ u1 match {
case JVM.nop => parseInstruction()
case JVM.aconst_null => code emit CONSTANT(Constant(null))
case JVM.iconst_m1 => code emit CONSTANT(Constant(-1))
@@ -235,17 +234,17 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.dconst_0 => code emit CONSTANT(Constant(0.0))
case JVM.dconst_1 => code emit CONSTANT(Constant(1.0))
- case JVM.bipush => code.emit(CONSTANT(Constant(in.nextByte))); size += 1
- case JVM.sipush => code.emit(CONSTANT(Constant(in.nextChar))); size += 2
- case JVM.ldc => code.emit(CONSTANT(pool.getConstant(toUnsignedByte(in.nextByte)))); size += 1
- case JVM.ldc_w => code.emit(CONSTANT(pool.getConstant(in.nextChar))); size += 2
- case JVM.ldc2_w => code.emit(CONSTANT(pool.getConstant(in.nextChar))); size += 2
- case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, INT))); size += 1
- case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, LONG))); size += 1
- case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, FLOAT))); size += 1
- case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, DOUBLE))); size += 1
+ case JVM.bipush => code.emit(CONSTANT(Constant(u1))); size += 1
+ case JVM.sipush => code.emit(CONSTANT(Constant(u2))); size += 2
+ case JVM.ldc => code.emit(CONSTANT(pool.getConstant(u1))); size += 1
+ case JVM.ldc_w => code.emit(CONSTANT(pool.getConstant(u2))); size += 2
+ case JVM.ldc2_w => code.emit(CONSTANT(pool.getConstant(u2))); size += 2
+ case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(u1, INT))); size += 1
+ case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(u1, LONG))); size += 1
+ case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(u1, FLOAT))); size += 1
+ case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(u1, DOUBLE))); size += 1
case JVM.aload =>
- val local = in.nextByte.toInt; size += 1
+ val local = u1.toInt; size += 1
if (local == 0 && !method.isStatic)
code.emit(THIS(method.symbol.owner))
else
@@ -285,11 +284,11 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.caload => code.emit(LOAD_ARRAY_ITEM(CHAR))
case JVM.saload => code.emit(LOAD_ARRAY_ITEM(SHORT))
- case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, INT))); size += 1
- case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, LONG))); size += 1
- case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, FLOAT))); size += 1
- case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, DOUBLE))); size += 1
- case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, ObjectReference))); size += 1
+ case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(u1, INT))); size += 1
+ case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(u1, LONG))); size += 1
+ case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(u1, FLOAT))); size += 1
+ case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(u1, DOUBLE))); size += 1
+ case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(u1, ObjectReference))); size += 1
case JVM.istore_0 => code.emit(STORE_LOCAL(code.getLocal(0, INT)))
case JVM.istore_1 => code.emit(STORE_LOCAL(code.getLocal(1, INT)))
case JVM.istore_2 => code.emit(STORE_LOCAL(code.getLocal(2, INT)))
@@ -373,9 +372,9 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.lxor => code.emit(CALL_PRIMITIVE(Logical(XOR, LONG)))
case JVM.iinc =>
size += 2
- val local = code.getLocal(in.nextByte, INT)
+ val local = code.getLocal(u1, INT)
code.emit(LOAD_LOCAL(local))
- code.emit(CONSTANT(Constant(in.nextByte)))
+ code.emit(CONSTANT(Constant(u1)))
code.emit(CALL_PRIMITIVE(Arithmetic(ADD, INT)))
code.emit(STORE_LOCAL(local))
@@ -425,14 +424,14 @@ abstract class ICodeReader extends ClassfileParser {
size += padding
in.bp += padding
assert((pc + size % 4) != 0, pc)
-/* var byte1 = in.nextByte; size += 1;
- while (byte1 == 0) { byte1 = in.nextByte; size += 1; }
- val default = byte1 << 24 | in.nextByte << 16 | in.nextByte << 8 | in.nextByte;
+/* var byte1 = u1; size += 1;
+ while (byte1 == 0) { byte1 = u1; size += 1; }
+ val default = byte1 << 24 | u1 << 16 | u1 << 8 | u1;
size = size + 3
*/
- val default = pc + in.nextInt; size += 4
- val low = in.nextInt
- val high = in.nextInt
+ val default = pc + u4; size += 4
+ val low = u4
+ val high = u4
size += 8
assert(low <= high, "Value low not <= high for tableswitch.")
@@ -445,13 +444,13 @@ abstract class ICodeReader extends ClassfileParser {
size += padding
in.bp += padding
assert((pc + size % 4) != 0, pc)
- val default = pc + in.nextInt; size += 4
- val npairs = in.nextInt; size += 4
+ val default = pc + u4; size += 4
+ val npairs = u4; size += 4
var tags: List[List[Int]] = Nil
var targets: List[Int] = Nil
var i = 0
while (i < npairs) {
- tags = List(in.nextInt) :: tags; size += 4
+ tags = List(u4) :: tags; size += 4
targets = parseJumpTargetW :: targets; // parseJumpTargetW updates 'size' itself
i += 1
}
@@ -466,47 +465,54 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.return_ => code.emit(RETURN(UNIT))
case JVM.getstatic =>
- val field = pool.getMemberSymbol(in.nextChar, static = true); size += 2
+ val field = pool.getMemberSymbol(u2, static = true); size += 2
if (field.hasModuleFlag)
code emit LOAD_MODULE(field)
else
code emit LOAD_FIELD(field, isStatic = true)
case JVM.putstatic =>
- val field = pool.getMemberSymbol(in.nextChar, static = true); size += 2
+ val field = pool.getMemberSymbol(u2, static = true); size += 2
code.emit(STORE_FIELD(field, isStatic = true))
case JVM.getfield =>
- val field = pool.getMemberSymbol(in.nextChar, static = false); size += 2
+ val field = pool.getMemberSymbol(u2, static = false); size += 2
code.emit(LOAD_FIELD(field, isStatic = false))
case JVM.putfield =>
- val field = pool.getMemberSymbol(in.nextChar, static = false); size += 2
+ val field = pool.getMemberSymbol(u2, static = false); size += 2
code.emit(STORE_FIELD(field, isStatic = false))
case JVM.invokevirtual =>
- val m = pool.getMemberSymbol(in.nextChar, static = false); size += 2
+ val m = pool.getMemberSymbol(u2, static = false); size += 2
code.emit(CALL_METHOD(m, Dynamic))
case JVM.invokeinterface =>
- val m = pool.getMemberSymbol(in.nextChar, static = false); size += 4
+ val m = pool.getMemberSymbol(u2, static = false); size += 4
in.skip(2)
code.emit(CALL_METHOD(m, Dynamic))
case JVM.invokespecial =>
- val m = pool.getMemberSymbol(in.nextChar, static = false); size += 2
+ val m = pool.getMemberSymbol(u2, static = false); size += 2
val style = if (m.name == nme.CONSTRUCTOR || m.isPrivate) Static(onInstance = true)
else SuperCall(m.owner.name)
code.emit(CALL_METHOD(m, style))
case JVM.invokestatic =>
- val m = pool.getMemberSymbol(in.nextChar, static = true); size += 2
+ val m = pool.getMemberSymbol(u2, static = true); size += 2
if (isBox(m))
code.emit(BOX(toTypeKind(m.info.paramTypes.head)))
else if (isUnbox(m))
code.emit(UNBOX(toTypeKind(m.info.resultType)))
else
code.emit(CALL_METHOD(m, Static(onInstance = false)))
+ case JVM.invokedynamic =>
+ // TODO, this is just a place holder. A real implementation must parse the class constant entry
+ debuglog("Found JVM invokedynamic instructionm, inserting place holder ICode INVOKE_DYNAMIC.")
+ containsInvokeDynamic = true
+ val poolEntry = in.nextChar
+ in.skip(2)
+ code.emit(INVOKE_DYNAMIC(poolEntry))
case JVM.new_ =>
- code.emit(NEW(REFERENCE(pool.getClassSymbol(in.nextChar))))
+ code.emit(NEW(REFERENCE(pool.getClassSymbol(u2))))
size += 2
case JVM.newarray =>
- val kind = in.nextByte match {
+ val kind = u1 match {
case T_BOOLEAN => BOOL
case T_CHAR => CHAR
case T_FLOAT => FLOAT
@@ -520,35 +526,35 @@ abstract class ICodeReader extends ClassfileParser {
code.emit(CREATE_ARRAY(kind, 1))
case JVM.anewarray =>
- val tpe = pool.getClassOrArrayType(in.nextChar); size += 2
+ val tpe = pool.getClassOrArrayType(u2); size += 2
code.emit(CREATE_ARRAY(toTypeKind(tpe), 1))
case JVM.arraylength => code.emit(CALL_PRIMITIVE(ArrayLength(ObjectReference))); // the kind does not matter
case JVM.athrow => code.emit(THROW(definitions.ThrowableClass))
case JVM.checkcast =>
- code.emit(CHECK_CAST(toTypeKind(pool.getClassOrArrayType(in.nextChar)))); size += 2
+ code.emit(CHECK_CAST(toTypeKind(pool.getClassOrArrayType(u2)))); size += 2
case JVM.instanceof =>
- code.emit(IS_INSTANCE(toTypeKind(pool.getClassOrArrayType(in.nextChar)))); size += 2
+ code.emit(IS_INSTANCE(toTypeKind(pool.getClassOrArrayType(u2)))); size += 2
case JVM.monitorenter => code.emit(MONITOR_ENTER())
case JVM.monitorexit => code.emit(MONITOR_EXIT())
case JVM.wide =>
size += 1
- toUnsignedByte(in.nextByte) match {
- case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, INT))); size += 2
- case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, LONG))); size += 2
- case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, FLOAT))); size += 2
- case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, DOUBLE))); size += 2
- case JVM.aload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, ObjectReference))); size += 2
- case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, INT))); size += 2
- case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, LONG))); size += 2
- case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, FLOAT))); size += 2
- case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, DOUBLE))); size += 2
- case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, ObjectReference))); size += 2
+ u1 match {
+ case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(u2, INT))); size += 2
+ case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(u2, LONG))); size += 2
+ case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(u2, FLOAT))); size += 2
+ case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(u2, DOUBLE))); size += 2
+ case JVM.aload => code.emit(LOAD_LOCAL(code.getLocal(u2, ObjectReference))); size += 2
+ case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(u2, INT))); size += 2
+ case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(u2, LONG))); size += 2
+ case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(u2, FLOAT))); size += 2
+ case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(u2, DOUBLE))); size += 2
+ case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(u2, ObjectReference))); size += 2
case JVM.ret => sys.error("Cannot handle jsr/ret")
case JVM.iinc =>
size += 4
- val local = code.getLocal(in.nextChar, INT)
- code.emit(CONSTANT(Constant(in.nextChar)))
+ val local = code.getLocal(u2, INT)
+ code.emit(CONSTANT(Constant(u2)))
code.emit(CALL_PRIMITIVE(Arithmetic(ADD, INT)))
code.emit(STORE_LOCAL(local))
case _ => sys.error("Invalid 'wide' operand")
@@ -556,8 +562,8 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.multianewarray =>
size += 3
- val tpe = toTypeKind(pool getClassOrArrayType in.nextChar)
- val dim = in.nextByte
+ val tpe = toTypeKind(pool getClassOrArrayType u2)
+ val dim = u1
// assert(dim == 1, "Cannot handle multidimensional arrays yet.")
code emit CREATE_ARRAY(tpe, dim)
@@ -583,14 +589,14 @@ abstract class ICodeReader extends ClassfileParser {
pc = 0
while (pc < codeLength) parseInstruction()
- val exceptionEntries = in.nextChar.toInt
+ val exceptionEntries = u2.toInt
code.containsEHs = (exceptionEntries != 0)
var i = 0
while (i < exceptionEntries) {
// skip start end PC
in.skip(4)
// read the handler PC
- code.jmpTargets += in.nextChar
+ code.jmpTargets += u2
// skip the exception type
in.skip(2)
i += 1
@@ -626,10 +632,8 @@ abstract class ICodeReader extends ClassfileParser {
/** Return the icode class that should include members with the given flags.
* There are two possible classes, the static part and the instance part.
*/
- def getCode(flags: Int): IClass =
- if (isScalaModule) staticCode
- else if ((flags & JAVA_ACC_STATIC) != 0) staticCode
- else instanceCode
+ def getCode(flags: JavaAccFlags): IClass =
+ if (isScalaModule || flags.isStatic) staticCode else instanceCode
class LinearCode {
val instrs: ListBuffer[(Int, Instruction)] = new ListBuffer
@@ -639,6 +643,7 @@ abstract class ICodeReader extends ClassfileParser {
var containsDUPX = false
var containsNEW = false
var containsEHs = false
+ var containsInvokeDynamic = false
def emit(i: Instruction) {
instrs += ((pc, i))
@@ -657,6 +662,7 @@ abstract class ICodeReader extends ClassfileParser {
val code = new Code(method)
method.setCode(code)
method.bytecodeHasEHs = containsEHs
+ method.bytecodeHasInvokeDynamic = containsInvokeDynamic
var bb = code.startBlock
def makeBasicBlocks: mutable.Map[Int, BasicBlock] =
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 9217bbeeb8..94880c4b2e 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -239,7 +239,7 @@ abstract class Pickler extends SubComponent {
putSymbols(tparams)
case AnnotatedType(annotations, underlying, selfsym) =>
putType(underlying)
- if (settings.selfInAnnots.value) putSymbol(selfsym)
+ if (settings.selfInAnnots) putSymbol(selfsym)
putAnnotations(annotations filter (_.isStatic))
case _ =>
throw new FatalError("bad type: " + tp + "(" + tp.getClass + ")")
@@ -643,7 +643,7 @@ abstract class Pickler extends SubComponent {
annotations filter (_.isStatic) match {
case Nil => writeBody(tp) // write the underlying type if there are no annotations
case staticAnnots =>
- if (settings.selfInAnnots.value && selfsym != NoSymbol)
+ if (settings.selfInAnnots && selfsym != NoSymbol)
writeRef(selfsym)
writeRef(tp)
writeRefs(staticAnnots)
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index 3b9cee2d88..ac18e5ba4f 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -85,7 +85,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
def transformApplyDynamic(ad: ApplyDynamic) = {
val qual0 = ad.qual
val params = ad.args
- if (settings.logReflectiveCalls.value)
+ if (settings.logReflectiveCalls)
unit.echo(ad.pos, "method invocation uses reflection")
val typedPos = typedWithPos(ad.pos) _
@@ -473,7 +473,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
/* For testing purposes, the dynamic application's condition
* can be printed-out in great detail. Remove? */
- if (settings.debug.value) {
+ if (settings.debug) {
def paramsToString(xs: Any*) = xs map (_.toString) mkString ", "
val mstr = ad.symbol.tpe match {
case MethodType(mparams, resType) =>
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index 768c9b6989..06367009b6 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -94,8 +94,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
val paramAccessors = clazz.constrParamAccessors
// The constructor parameter corresponding to an accessor
- def parameter(acc: Symbol): Symbol =
- parameterNamed(nme.getterName(acc.originalName.toTermName))
+ def parameter(acc: Symbol): Symbol = parameterNamed(acc.unexpandedName.getterName)
// The constructor parameter with given name. This means the parameter
// has given name, or starts with given name, and continues with a `$` afterwards.
@@ -191,8 +190,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
stat match {
case ValDef(mods, name, _, _) if (mods hasFlag PRESUPER) =>
// stat is the constructor-local definition of the field value
- val fields = presupers filter (
- vdef => nme.localToGetter(vdef.name) == name)
+ val fields = presupers filter (_.getterName == name)
assert(fields.length == 1)
val to = fields.head.symbol
if (!to.tpe.isInstanceOf[ConstantType])
@@ -314,10 +312,8 @@ abstract class Constructors extends Transform with ast.TreeDSL {
def specializedAssignFor(sym: Symbol): Option[Tree] =
specializedStats find {
- case Assign(sel @ Select(This(_), _), rhs) =>
- ( (sel.symbol hasFlag SPECIALIZED)
- && (nme.unspecializedName(nme.localToGetter(sel.symbol.name.toTermName)) == nme.localToGetter(sym.name.toTermName))
- )
+ case Assign(sel @ Select(This(_), _), _) =>
+ sel.symbol.isSpecialized && (nme.unspecializedName(sel.symbol.getterName) == sym.getterName)
case _ => false
}
@@ -432,8 +428,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
}
def addGetter(sym: Symbol): Symbol = {
- val getr = addAccessor(
- sym, nme.getterName(sym.name.toTermName), getterFlags(sym.flags))
+ val getr = addAccessor(sym, sym.getterName, getterFlags(sym.flags))
getr setInfo MethodType(List(), sym.tpe)
defBuf += localTyper.typedPos(sym.pos)(DefDef(getr, Select(This(clazz), sym)))
getr
@@ -441,8 +436,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
def addSetter(sym: Symbol): Symbol = {
sym setFlag MUTABLE
- val setr = addAccessor(
- sym, nme.getterToSetter(nme.getterName(sym.name.toTermName)), setterFlags(sym.flags))
+ val setr = addAccessor(sym, sym.setterName, setterFlags(sym.flags))
setr setInfo MethodType(setr.newSyntheticValueParams(List(sym.tpe)), UnitClass.tpe)
defBuf += localTyper.typed {
//util.trace("adding setter def for "+setr) {
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 857c01c49a..ac79c60254 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -66,8 +66,8 @@ abstract class Erasure extends AddInterfaces
}
}
- override protected def verifyJavaErasure = settings.Xverify.value || settings.debug.value
- def needsJavaSig(tp: Type) = !settings.Ynogenericsig.value && NeedsSigCollector.collect(tp)
+ override protected def verifyJavaErasure = settings.Xverify || settings.debug
+ def needsJavaSig(tp: Type) = !settings.Ynogenericsig && NeedsSigCollector.collect(tp)
// only refer to type params that will actually make it into the sig, this excludes:
// * higher-order type parameters
@@ -418,7 +418,7 @@ abstract class Erasure extends AddInterfaces
|both have erased type ${exitingPostErasure(bridge.tpe)}""")
}
for (bc <- root.baseClasses) {
- if (settings.debug.value)
+ if (settings.debug)
exitingPostErasure(println(
sm"""check bridge overrides in $bc
|${bc.info.nonPrivateDecl(bridge.name)}
@@ -648,7 +648,7 @@ abstract class Erasure extends AddInterfaces
* @return the adapted tree
*/
private def adaptToType(tree: Tree, pt: Type): Tree = {
- if (settings.debug.value && pt != WildcardType)
+ if (settings.debug && pt != WildcardType)
log("adapting " + tree + ":" + tree.tpe + " : " + tree.tpe.parents + " to " + pt)//debug
if (tree.tpe <:< pt)
tree
@@ -730,7 +730,7 @@ abstract class Erasure extends AddInterfaces
else if (tree.symbol == Any_isInstanceOf)
adaptMember(atPos(tree.pos)(Select(qual, Object_isInstanceOf)))
else if (tree.symbol.owner == AnyClass)
- adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, name))))
+ adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, tree.symbol.name))))
else {
var qual1 = typedQualifier(qual)
if ((isPrimitiveValueType(qual1.tpe) && !isPrimitiveValueMember(tree.symbol)) ||
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 124dd6c995..367825c251 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -41,26 +41,24 @@ abstract class ExplicitOuter extends InfoTransform
private def isInner(clazz: Symbol) =
!clazz.isPackageClass && !clazz.outerClass.isStaticOwner
- private def haveSameOuter(parent: Type, clazz: Symbol) = parent match {
- case TypeRef(pre, sym, _) =>
- val owner = clazz.owner
+ private def haveSameOuter(parent: Type, clazz: Symbol) = {
+ val owner = clazz.owner
+ val parentSym = parent.typeSymbol
- //println(s"have same outer $parent $clazz $sym ${sym.owner} $owner $pre")
-
- sym.isClass && owner.isClass &&
- (owner isSubClass sym.owner) &&
- owner.thisType =:= pre
-
- case _ => false
+ parentSym.isClass && owner.isClass &&
+ (owner isSubClass parentSym.owner) &&
+ owner.thisType =:= parent.prefix
}
/** Does given clazz define an outer field? */
def hasOuterField(clazz: Symbol) = {
- val parents = clazz.info.parents
+ val parent = clazz.info.firstParent
- isInner(clazz) && !clazz.isTrait && {
- parents.isEmpty || !haveSameOuter(parents.head, clazz)
- }
+ // space optimization: inherit the $outer pointer from the parent class if
+ // we know that it will point to the correct instance.
+ def canReuseParentOuterField = !parent.typeSymbol.isJavaDefined && haveSameOuter(parent, clazz)
+
+ isInner(clazz) && !clazz.isTrait && !canReuseParentOuterField
}
private def outerField(clazz: Symbol): Symbol = {
@@ -100,6 +98,29 @@ abstract class ExplicitOuter extends InfoTransform
sym setInfo clazz.outerClass.thisType
}
+ /**
+ * Will the outer accessor of the `clazz` subsume the outer accessor of
+ * `mixin`?
+ *
+ * This arises when an inner object mixes in its companion trait.
+ *
+ * {{{
+ * class C {
+ * trait T { C.this } // C$T$$$outer$ : C
+ * object T extends T { C.this } // C$T$$$outer$ : C.this.type
+ * }
+ * }}}
+ *
+ * See SI-7242.
+ }}
+ */
+ private def skipMixinOuterAccessor(clazz: Symbol, mixin: Symbol) = {
+ // Reliant on the current scheme for name expansion, the expanded name
+ // of the outer accessors in a trait and its companion object are the same.
+ // If the assumption is one day falsified, run/t7424.scala will let us know.
+ clazz.fullName == mixin.fullName
+ }
+
/** <p>
* The type transformation method:
* </p>
@@ -162,10 +183,14 @@ abstract class ExplicitOuter extends InfoTransform
for (mc <- clazz.mixinClasses) {
val mixinOuterAcc: Symbol = exitingExplicitOuter(outerAccessor(mc))
if (mixinOuterAcc != NoSymbol) {
- if (decls1 eq decls) decls1 = decls.cloneScope
- val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED)
- newAcc setInfo (clazz.thisType memberType mixinOuterAcc)
- decls1 enter newAcc
+ if (skipMixinOuterAccessor(clazz, mc))
+ debuglog(s"Reusing outer accessor symbol of $clazz for the mixin outer accessor of $mc")
+ else {
+ if (decls1 eq decls) decls1 = decls.cloneScope
+ val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED)
+ newAcc setInfo (clazz.thisType memberType mixinOuterAcc)
+ decls1 enter newAcc
+ }
}
}
}
@@ -370,6 +395,7 @@ abstract class ExplicitOuter extends InfoTransform
val outerAcc = outerAccessor(mixinClass) overridingSymbol currentClass
def mixinPrefix = (currentClass.thisType baseType mixinClass).prefix
assert(outerAcc != NoSymbol, "No outer accessor for inner mixin " + mixinClass + " in " + currentClass)
+ assert(outerAcc.alternatives.size == 1, s"Multiple outer accessors match inner mixin $mixinClass in $currentClass : ${outerAcc.alternatives.map(_.defString)}")
// I added the mixinPrefix.typeArgs.nonEmpty condition to address the
// crash in SI-4970. I feel quite sure this can be improved.
val path = (
@@ -404,7 +430,7 @@ abstract class ExplicitOuter extends InfoTransform
}
if (!currentClass.isTrait)
for (mc <- currentClass.mixinClasses)
- if (outerAccessor(mc) != NoSymbol)
+ if (outerAccessor(mc) != NoSymbol && !skipMixinOuterAccessor(currentClass, mc))
newDefs += mixinOuterAccessorDef(mc)
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
index e6c9afb042..69a93b482c 100644
--- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala
+++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
@@ -183,7 +183,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
if (bmps.isEmpty) rhs else rhs match {
case Block(assign, l @ LabelDef(name, params, _))
- if name.toString == ("_" + methSym.name) && isMatch(params) =>
+ if (name string_== "_" + methSym.name) && isMatch(params) =>
Block(assign, deriveLabelDef(l)(rhs => typed(prependStats(bmps, rhs))))
case _ => prependStats(bmps, rhs)
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index e0b30ab9f9..35df63b246 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -86,7 +86,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
* Note: The `checkinit` option does not check if transient fields are initialized.
*/
private def needsInitFlag(sym: Symbol) = (
- settings.checkInit.value
+ settings.checkInit
&& sym.isGetter
&& !sym.isInitializedToDefault
&& !sym.hasFlag(PARAMACCESSOR | SPECIALIZED | LAZY)
@@ -125,7 +125,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
debuglog("starting rebindsuper " + base + " " + member + ":" + member.tpe +
" " + mixinClass + " " + base.info.baseClasses + "/" + bcs)
while (!bcs.isEmpty && sym == NoSymbol) {
- if (settings.debug.value) {
+ if (settings.debug) {
val other = bcs.head.info.nonPrivateDecl(member.name)
debuglog("rebindsuper " + bcs.head + " " + other + " " + other.tpe +
" " + other.isDeferred)
@@ -185,11 +185,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
newSym updateInfo (mixinMember.info cloneInfo newSym)
}
- def needsExpandedSetterName(field: Symbol) = !field.isLazy && (
- if (field.isMethod) field.hasStableFlag
- else !field.isMutable
- )
-
/** Add getters and setters for all non-module fields of an implementation
* class to its interface unless they are already present. This is done
* only once per class. The mixedin flag is used to remember whether late
@@ -207,19 +202,19 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// println("creating new getter for "+ field +" : "+ field.info +" at "+ field.locationString+(field hasFlag MUTABLE))
val newFlags = field.flags & ~PrivateLocal | ACCESSOR | lateDEFERRED | ( if (field.isMutable) 0 else STABLE )
// TODO preserve pre-erasure info?
- clazz.newMethod(nme.getterName(field.name.toTermName), field.pos, newFlags) setInfo MethodType(Nil, field.info)
+ clazz.newMethod(field.getterName, field.pos, newFlags) setInfo MethodType(Nil, field.info)
}
/* Create a new setter. Setters are never private or local. They are
* always accessors and deferred. */
def newSetter(field: Symbol): Symbol = {
//println("creating new setter for "+field+field.locationString+(field hasFlag MUTABLE))
- val setterName = nme.getterToSetter(nme.getterName(field.name.toTermName))
+ val setterName = field.setterName
val newFlags = field.flags & ~PrivateLocal | ACCESSOR | lateDEFERRED
val setter = clazz.newMethod(setterName, field.pos, newFlags)
// TODO preserve pre-erasure info?
setter setInfo MethodType(setter.newSyntheticValueParams(List(field.info)), UnitClass.tpe)
- if (needsExpandedSetterName(field))
+ if (field.needsExpandedSetterName)
setter.name = nme.expandedSetterName(setter.name, clazz)
setter
@@ -237,7 +232,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
val getter = member.getter(clazz)
if (getter == NoSymbol) addMember(clazz, newGetter(member))
if (!member.tpe.isInstanceOf[ConstantType] && !member.isLazy) {
- val setter = member.setter(clazz, needsExpandedSetterName(member))
+ val setter = member.setter(clazz)
if (setter == NoSymbol) addMember(clazz, newSetter(member))
}
}
@@ -315,7 +310,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// carries over the current entry in the type history)
val sym = enteringErasure {
// so we have a type history entry before erasure
- clazz.newValue(nme.getterToLocal(mixinMember.name.toTermName), mixinMember.pos).setInfo(mixinMember.tpe.resultType)
+ clazz.newValue(mixinMember.localName, mixinMember.pos).setInfo(mixinMember.tpe.resultType)
}
sym updateInfo mixinMember.tpe.resultType // info at current phase
@@ -924,7 +919,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
else if (sym.isConstructor) {
deriveDefDef(stat)(addInitBits(clazz, _))
}
- else if (settings.checkInit.value && !clazz.isTrait && sym.isSetter) {
+ else if (settings.checkInit && !clazz.isTrait && sym.isSetter) {
val getter = sym.getter(clazz)
if (needsInitFlag(getter) && fieldOffset.isDefinedAt(getter))
deriveDefDef(stat)(rhs => Block(List(rhs, localTyper.typed(mkSetFlag(clazz, fieldOffset(getter), getter, bitmapKind(getter)))), UNIT))
@@ -1236,10 +1231,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
case Assign(Apply(lhs @ Select(qual, _), List()), rhs) =>
// assign to fields in some implementation class via an abstract
// setter in the interface.
- def setter = lhs.symbol.setter(
- toInterface(lhs.symbol.owner.tpe).typeSymbol,
- needsExpandedSetterName(lhs.symbol)
- ) setPos lhs.pos
+ def setter = lhs.symbol.setter(toInterface(lhs.symbol.owner.tpe).typeSymbol) setPos lhs.pos
typedPos(tree.pos)((qual DOT setter)(rhs))
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 15fe9f0a24..8e008edde2 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -79,7 +79,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
/** For a given class and concrete type arguments, give its specialized class */
- val specializedClass: mutable.Map[(Symbol, TypeEnv), Symbol] = new mutable.LinkedHashMap
+ val specializedClass = perRunCaches.newMap[(Symbol, TypeEnv), Symbol]
/** Map a method symbol to a list of its specialized overloads in the same class. */
private val overloads = perRunCaches.newMap[Symbol, List[Overload]]() withDefaultValue Nil
@@ -322,20 +322,20 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Specialize name for the two list of types. The first one denotes
* specialization on method type parameters, the second on outer environment.
*/
- private def specializedName(name: Name, types1: List[Type], types2: List[Type]): TermName = {
- if (nme.INITIALIZER == name || (types1.isEmpty && types2.isEmpty))
+ private def specializedName(name: Name, types1: List[Type], types2: List[Type]): TermName = (
+ if (name == nme.CONSTRUCTOR || (types1.isEmpty && types2.isEmpty))
name.toTermName
else if (nme.isSetterName(name))
- nme.getterToSetter(specializedName(nme.setterToGetter(name.toTermName), types1, types2))
+ specializedName(name.getterName, types1, types2).setterName
else if (nme.isLocalName(name))
- nme.getterToLocal(specializedName(nme.localToGetter(name.toTermName), types1, types2))
+ specializedName(name.getterName, types1, types2).localName
else {
val (base, cs, ms) = nme.splitSpecializedName(name)
newTermName(base.toString + "$"
+ "m" + ms + types1.map(t => definitions.abbrvTag(t.typeSymbol)).mkString("", "", "")
+ "c" + cs + types2.map(t => definitions.abbrvTag(t.typeSymbol)).mkString("", "", "$sp"))
}
- }
+ )
lazy val specializableTypes = ScalaValueClasses map (_.tpe) sorted
@@ -714,7 +714,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// debuglog("m: " + m + " isLocal: " + nme.isLocalName(m.name) + " specVal: " + specVal.name + " isLocal: " + nme.isLocalName(specVal.name))
if (nme.isLocalName(m.name)) {
- val specGetter = mkAccessor(specVal, nme.localToGetter(specVal.name.toTermName)) setInfo MethodType(Nil, specVal.info)
+ val specGetter = mkAccessor(specVal, specVal.getterName) setInfo MethodType(Nil, specVal.info)
val origGetter = overrideIn(sClass, m.getter(clazz))
info(origGetter) = Forward(specGetter)
enterMember(specGetter)
@@ -729,7 +729,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
if (specVal.isVariable && m.setter(clazz) != NoSymbol) {
- val specSetter = mkAccessor(specVal, nme.getterToSetter(specGetter.name))
+ val specSetter = mkAccessor(specVal, specGetter.setterName)
.resetFlag(STABLE)
specSetter.setInfo(MethodType(specSetter.newSyntheticValueParams(List(specVal.info)),
UnitClass.tpe))
@@ -1156,7 +1156,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* If it is a 'no-specialization' run, it is applied only to loaded symbols.
*/
override def transformInfo(sym: Symbol, tpe: Type): Type = {
- if (settings.nospecialization.value && currentRun.compiles(sym)) tpe
+ if (settings.nospecialization && currentRun.compiles(sym)) tpe
else tpe.resultType match {
case cinfo @ ClassInfoType(parents, decls, clazz) if !unspecializableClass(cinfo) =>
val tparams = tpe.typeParams
@@ -1752,21 +1752,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Create specialized class definitions */
def implSpecClasses(trees: List[Tree]): List[Tree] = {
- val buf = new mutable.ListBuffer[Tree]
- for (tree <- trees)
- tree match {
- case ClassDef(_, _, _, impl) =>
- tree.symbol.info // force specialization
- for (((sym1, env), specCls) <- specializedClass if sym1 == tree.symbol) {
- val parents = specCls.info.parents.map(TypeTree)
- buf +=
- ClassDef(specCls, atPos(impl.pos)(Template(parents, emptyValDef, List()))
- .setSymbol(specCls.newLocalDummy(sym1.pos))) setPos tree.pos
- debuglog("created synthetic class: " + specCls + " of " + sym1 + " in " + pp(env))
- }
- case _ =>
- }
- buf.toList
+ trees flatMap {
+ case tree @ ClassDef(_, _, _, impl) =>
+ tree.symbol.info // force specialization
+ for (((sym1, env), specCls) <- specializedClass if sym1 == tree.symbol) yield {
+ debuglog("created synthetic class: " + specCls + " of " + sym1 + " in " + pp(env))
+ val parents = specCls.info.parents.map(TypeTree)
+ ClassDef(specCls, atPos(impl.pos)(Template(parents, emptyValDef, List()))
+ .setSymbol(specCls.newLocalDummy(sym1.pos))) setPos tree.pos
+ }
+ case _ => Nil
+ } sortBy (_.name.decoded)
}
}
@@ -1805,7 +1801,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
def initializesSpecializedField(f: Symbol) = (
(f.name endsWith nme.SPECIALIZED_SUFFIX)
- && clazz.info.member(nme.originalName(f.name)).isPublic
+ && clazz.info.member(f.unexpandedName).isPublic
&& clazz.info.decl(f.name).suchThat(_.isGetter) != NoSymbol
)
@@ -1836,7 +1832,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
class SpecializationTransformer(unit: CompilationUnit) extends Transformer {
informProgress("specializing " + unit)
override def transform(tree: Tree) = {
- val resultTree = if (settings.nospecialization.value) tree
+ val resultTree = if (settings.nospecialization) tree
else exitingSpecialize(specializeCalls(unit).transform(tree))
// Remove the final modifier and @inline annotation from anything in the
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index 92ed7fc555..313f968e93 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -217,7 +217,10 @@ abstract class TailCalls extends Transform {
debuglog("Rewriting tail recursive call: " + fun.pos.lineContent.trim)
accessed += ctx.label
- typedPos(fun.pos)(Apply(Ident(ctx.label), noTailTransform(recv) :: transformArgs))
+ typedPos(fun.pos) {
+ val args = mapWithIndex(transformArgs)((arg, i) => mkAttributedCastHack(arg, ctx.label.info.params(i + 1).tpe))
+ Apply(Ident(ctx.label), noTailTransform(recv) :: args)
+ }
}
if (!ctx.isEligible) fail("it is neither private nor final so can be overridden")
@@ -276,7 +279,7 @@ abstract class TailCalls extends Transform {
typedPos(tree.pos)(Block(
List(ValDef(newThis, This(currentClass))),
- LabelDef(newCtx.label, newThis :: vpSyms, newRHS)
+ LabelDef(newCtx.label, newThis :: vpSyms, mkAttributedCastHack(newRHS, newCtx.label.tpe.resultType))
))
}
else {
@@ -373,6 +376,13 @@ abstract class TailCalls extends Transform {
super.transform(tree)
}
}
+
+ // Workaround for SI-6900. Uncurry installs an InfoTransformer and a tree Transformer.
+ // These leave us with conflicting view on method signatures; the parameter symbols in
+ // the MethodType can be clones of the ones originally found on the parameter ValDef, and
+ // consequently appearing in the typechecked RHS of the method.
+ private def mkAttributedCastHack(tree: Tree, tpe: Type) =
+ gen.mkAttributedCast(tree, tpe)
}
// collect the LabelDefs (generated by the pattern matcher) in a DefDef that are in tail position
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 8fd1df7cea..2f5cb23abb 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -347,10 +347,14 @@ abstract class UnCurry extends InfoTransform
}
else {
log(s"Argument '$arg' at line ${arg.pos.safeLine} is $formal from ${fun.fullName}")
+ def canUseDirectly(recv: Tree) = (
+ recv.tpe.typeSymbol.isSubClass(FunctionClass(0))
+ && treeInfo.isExprSafeToInline(recv)
+ )
arg match {
// don't add a thunk for by-name argument if argument already is an application of
// a Function0. We can then remove the application and use the existing Function0.
- case Apply(Select(recv, nme.apply), Nil) if recv.tpe.typeSymbol isSubClass FunctionClass(0) =>
+ case Apply(Select(recv, nme.apply), Nil) if canUseDirectly(recv) =>
recv
case _ =>
newFunction0(arg)
@@ -424,7 +428,7 @@ abstract class UnCurry extends InfoTransform
val result = (
// TODO - settings.noassertions.value temporarily retained to avoid
// breakage until a reasonable interface is settled upon.
- if ((sym ne null) && (sym.elisionLevel.exists (_ < settings.elidebelow.value || settings.noassertions.value)))
+ if ((sym ne null) && (sym.elisionLevel.exists (_ < settings.elidebelow.value || settings.noassertions)))
replaceElidableTree(tree)
else translateSynchronized(tree) match {
case dd @ DefDef(mods, name, tparams, _, tpt, rhs) =>
@@ -628,7 +632,8 @@ abstract class UnCurry extends InfoTransform
*
* This transformation erases the dependent method types by:
* - Widening the formal parameter type to existentially abstract
- * over the prior parameters (using `packSymbols`)
+ * over the prior parameters (using `packSymbols`). This transformation
+ * is performed in the the `InfoTransform`er [[scala.reflect.internal.transform.UnCurry]].
* - Inserting casts in the method body to cast to the original,
* precise type.
*
@@ -656,15 +661,14 @@ abstract class UnCurry extends InfoTransform
*/
def erase(dd: DefDef): (List[List[ValDef]], Tree) = {
import dd.{ vparamss, rhs }
- val vparamSyms = vparamss flatMap (_ map (_.symbol))
-
val paramTransforms: List[ParamTransform] =
- vparamss.flatten.map { p =>
- val declaredType = p.symbol.info
- // existentially abstract over value parameters
- val packedType = typer.packSymbols(vparamSyms, declaredType)
- if (packedType =:= declaredType) Identity(p)
+ map2(vparamss.flatten, dd.symbol.info.paramss.flatten) { (p, infoParam) =>
+ val packedType = infoParam.info
+ if (packedType =:= p.symbol.info) Identity(p)
else {
+ // The Uncurry info transformer existentially abstracted over value parameters
+ // from the previous parameter lists.
+
// Change the type of the param symbol
p.symbol updateInfo packedType
@@ -676,8 +680,8 @@ abstract class UnCurry extends InfoTransform
// the method body to refer to this, rather than the parameter.
val tempVal: ValDef = {
val tempValName = unit freshTermName (p.name + "$")
- val newSym = dd.symbol.newTermSymbol(tempValName, p.pos, SYNTHETIC).setInfo(declaredType)
- atPos(p.pos)(ValDef(newSym, gen.mkAttributedCast(Ident(p.symbol), declaredType)))
+ val newSym = dd.symbol.newTermSymbol(tempValName, p.pos, SYNTHETIC).setInfo(p.symbol.info)
+ atPos(p.pos)(ValDef(newSym, gen.mkAttributedCast(Ident(p.symbol), p.symbol.info)))
}
Packed(newParam, tempVal)
}
@@ -695,13 +699,6 @@ abstract class UnCurry extends InfoTransform
Block(tempVals, rhsSubstituted)
}
- // update the type of the method after uncurry.
- dd.symbol updateInfo {
- val GenPolyType(tparams, tp) = dd.symbol.info
- logResult(s"erased dependent param types for ${dd.symbol.info}") {
- GenPolyType(tparams, MethodType(allParams map (_.symbol), tp.finalResultType))
- }
- }
(allParams :: Nil, rhs1)
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
index 0371df3b10..92b7700c04 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
@@ -573,6 +573,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
assert(tp.isInstanceOf[SingletonType])
val toString = tp match {
case ConstantType(c) => c.escapedStringValue
+ case _ if tp.typeSymbol.isModuleClass => tp.typeSymbol.name.toString
case _ => tp.toString
}
Const.unique(tp, new ValueConst(tp, tp.widen, toString))
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
index 125e9a3b65..31b04d0bd6 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
@@ -15,9 +15,9 @@ import scala.reflect.internal.util.Position
/** Optimize and analyze matches based on their TreeMaker-representation.
*
* The patmat translation doesn't rely on this, so it could be disabled in principle.
- *
- * TODO: split out match analysis
+ * - well, not quite: the backend crashes if we emit duplicates in switches (e.g. SI-7290)
*/
+// TODO: split out match analysis
trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
import global._
import global.definitions._
@@ -435,7 +435,7 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
case SwitchableTreeMaker(pattern) :: GuardAndBodyTreeMakers(guard, body) =>
Some(CaseDef(pattern, guard, body))
// alternatives
- case AlternativesTreeMaker(_, altss, _) :: GuardAndBodyTreeMakers(guard, body) if alternativesSupported =>
+ case AlternativesTreeMaker(_, altss, pos) :: GuardAndBodyTreeMakers(guard, body) if alternativesSupported =>
val switchableAlts = altss map {
case SwitchableTreeMaker(pattern) :: Nil =>
Some(pattern)
@@ -445,7 +445,17 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
// succeed if they were all switchable
sequence(switchableAlts) map { switchableAlts =>
- CaseDef(Alternative(switchableAlts), guard, body)
+ def extractConst(t: Tree) = t match {
+ case Literal(const) => const
+ case _ => t
+ }
+ // SI-7290 Discard duplicate alternatives that would crash the backend
+ val distinctAlts = distinctBy(switchableAlts)(extractConst)
+ if (distinctAlts.size < switchableAlts.size) {
+ val duplicated = switchableAlts.groupBy(extractConst).flatMap(_._2.drop(1).take(1)) // report the first duplicated
+ global.currentUnit.warning(pos, s"Pattern contains duplicate alternatives: ${duplicated.mkString(", ")}")
+ }
+ CaseDef(Alternative(distinctAlts), guard, body)
}
case _ =>
// debug.patmat("can't emit switch for "+ makers)
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
index 76268f3ecd..4dff445fe8 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
@@ -522,7 +522,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
debug.patmat("combining cases: "+ (casesNoSubstOnly.map(_.mkString(" >> ")).mkString("{", "\n", "}")))
val (suppression, requireSwitch): (Suppression, Boolean) =
- if (settings.XnoPatmatAnalysis.value) (Suppression.NoSuppression, false)
+ if (settings.XnoPatmatAnalysis) (Suppression.NoSuppression, false)
else scrut match {
case Typed(tree, tpt) =>
val suppressExhaustive = tpt.tpe hasAnnotation UncheckedClass
diff --git a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala
index 62c584e97b..567d5d0ecd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala
@@ -66,9 +66,9 @@ trait Adaptations {
)
}
- if (settings.noAdaptedArgs.value)
+ if (settings.noAdaptedArgs)
adaptWarning("No automatic adaptation here: use explicit parentheses.")
- else if (settings.warnAdaptedArgs.value)
+ else if (settings.warnAdaptedArgs)
adaptWarning(
if (args.isEmpty) "Adapting argument list by inserting (): " + (
if (isLeakyTarget) "leaky (Object-receiving) target makes this especially dangerous."
@@ -77,7 +77,7 @@ trait Adaptations {
else "Adapting argument list by creating a " + args.size + "-tuple: this may not be what you want."
)
- !settings.noAdaptedArgs.value
+ !settings.noAdaptedArgs
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 36121f2653..02e1eb6f00 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -97,9 +97,9 @@ trait Analyzer extends AnyRef
try {
val typer = newTyper(rootContext(unit))
unit.body = typer.typed(unit.body)
- if (global.settings.Yrangepos.value && !global.reporter.hasErrors) global.validatePositions(unit.body)
+ if (global.settings.Yrangepos && !global.reporter.hasErrors) global.validatePositions(unit.body)
for (workItem <- unit.toCheck) workItem()
- if (settings.lint.value)
+ if (settings.lint)
typer checkUnused unit
}
finally {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
index 026f5f7bc8..0686b28079 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
@@ -203,7 +203,7 @@ trait Checkable {
private def isEffectivelyFinal(sym: Symbol): Boolean = (
// initialization important
sym.initialize.isEffectivelyFinal || (
- settings.future.value && isTupleSymbol(sym) // SI-7294 step into the future and treat TupleN as final.
+ settings.future && isTupleSymbol(sym) // SI-7294 step into the future and treat TupleN as final.
)
)
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 8723046728..89fc55bc2c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -919,7 +919,7 @@ trait ContextErrors {
def NotWithinBounds(tree: Tree, prefix: String, targs: List[Type],
tparams: List[Symbol], kindErrors: List[String]) =
issueNormalTypeError(tree,
- NotWithinBoundsErrorMessage(prefix, targs, tparams, settings.explaintypes.value))
+ NotWithinBoundsErrorMessage(prefix, targs, tparams, settings.explaintypes))
//substExpr
def PolymorphicExpressionInstantiationError(tree: Tree, undetparams: List[Symbol], pt: Type) =
@@ -1058,9 +1058,6 @@ trait ContextErrors {
issueSymbolTypeError(currentSym, prevSym.name + " is already defined as " + s2 + s3 + where)
}
- def MaxParametersCaseClassError(tree: Tree) =
- issueNormalTypeError(tree, "Implementation restriction: case classes cannot have more than " + definitions.MaxFunctionArity + " parameters.")
-
def MissingParameterOrValTypeError(vparam: Tree) =
issueNormalTypeError(vparam, "missing parameter type")
@@ -1364,7 +1361,7 @@ trait ContextErrors {
}
def MacroImplTargMismatchError(atargs: List[Type], atparams: List[Symbol]) =
- compatibilityError(typer.infer.InferErrorGen.NotWithinBoundsErrorMessage("", atargs, atparams, macroDebugVerbose || settings.explaintypes.value))
+ compatibilityError(typer.infer.InferErrorGen.NotWithinBoundsErrorMessage("", atargs, atparams, macroDebugVerbose || settings.explaintypes))
def MacroImplTparamInstantiationError(atparams: List[Symbol], ex: NoInstance) =
compatibilityError(
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 9d5a9c819c..e89a860e0f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -79,9 +79,9 @@ trait Contexts { self: Analyzer =>
protected def rootImports(unit: CompilationUnit): List[Symbol] = {
assert(definitions.isDefinitionsInitialized, "definitions uninitialized")
- if (settings.noimports.value) Nil
+ if (settings.noimports) Nil
else if (unit.isJava) RootImports.javaList
- else if (settings.nopredef.value || treeInfo.noPredefImportForUnit(unit.body)) RootImports.javaAndScalaList
+ else if (settings.nopredef || treeInfo.noPredefImportForUnit(unit.body)) RootImports.javaAndScalaList
else RootImports.completeList
}
@@ -322,7 +322,7 @@ trait Contexts { self: Analyzer =>
def makeNewImport(imp: Import): Context = {
val impInfo = new ImportInfo(imp, depth)
- if (settings.lint.value && imp.pos.isDefined) // pos.isDefined excludes java.lang/scala/Predef imports
+ if (settings.lint && imp.pos.isDefined) // pos.isDefined excludes java.lang/scala/Predef imports
allImportInfos(unit) ::= impInfo
make(unit, imp, owner, scope, impInfo :: imports)
@@ -406,7 +406,7 @@ trait Contexts { self: Analyzer =>
unit.error(pos, if (checking) "\n**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg)
@inline private def issueCommon(err: AbsTypeError)(pf: PartialFunction[AbsTypeError, Unit]) {
- if (settings.Yissuedebug.value) {
+ if (settings.Yissuedebug) {
log("issue error: " + err.errMsg)
(new Exception).printStackTrace()
}
@@ -912,7 +912,25 @@ trait Contexts { self: Analyzer =>
def lookupImport(imp: ImportInfo, requireExplicit: Boolean) =
importedAccessibleSymbol(imp, name, requireExplicit) filter qualifies
- while (!impSym.exists && imports.nonEmpty && imp1.depth > symbolDepth) {
+ // Java: A single-type-import declaration d in a compilation unit c of package p
+ // that imports a type named n shadows, throughout c, the declarations of:
+ //
+ // 1) any top level type named n declared in another compilation unit of p
+ //
+ // A type-import-on-demand declaration never causes any other declaration to be shadowed.
+ //
+ // Scala: Bindings of different kinds have a precedence defined on them:
+ //
+ // 1) Definitions and declarations that are local, inherited, or made available by a
+ // package clause in the same compilation unit where the definition occurs have
+ // highest precedence.
+ // 2) Explicit imports have next highest precedence.
+ def depthOk(imp: ImportInfo) = (
+ imp.depth > symbolDepth
+ || (unit.isJava && imp.isExplicitImport(name) && imp.depth == symbolDepth)
+ )
+
+ while (!impSym.exists && imports.nonEmpty && depthOk(imports.head)) {
impSym = lookupImport(imp1, requireExplicit = false)
if (!impSym.exists)
imports = imports.tail
@@ -1047,7 +1065,7 @@ trait Contexts { self: Analyzer =>
if (result == NoSymbol)
selectors = selectors.tail
}
- if (settings.lint.value && selectors.nonEmpty && result != NoSymbol && pos != NoPosition)
+ if (settings.lint && selectors.nonEmpty && result != NoSymbol && pos != NoPosition)
recordUsage(current, result)
// Harden against the fallout from bugs like SI-6745
diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
index 282dd8a99d..7092f00bff 100644
--- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -98,6 +98,7 @@ trait EtaExpansion { self: Analyzer =>
case TypeApply(fn, args) =>
treeCopy.TypeApply(tree, liftoutPrefix(fn), args).clearType()
case Select(qual, name) =>
+ val name = tree.symbol.name // account for renamed imports, SI-7233
treeCopy.Select(tree, liftout(qual, byName = false), name).clearType() setSymbol NoSymbol
case Ident(name) =>
tree
@@ -114,7 +115,7 @@ trait EtaExpansion { self: Analyzer =>
val origTpe = sym.tpe
val isRepeated = definitions.isRepeatedParamType(origTpe)
// SI-4176 Don't leak A* in eta-expanded function types. See t4176b.scala
- val droppedStarTpe = if (settings.etaExpandKeepsStar.value) origTpe else dropIllegalStarTypes(origTpe)
+ val droppedStarTpe = if (settings.etaExpandKeepsStar) origTpe else dropIllegalStarTypes(origTpe)
val valDef = ValDef(Modifiers(SYNTHETIC | PARAM), sym.name.toTermName, TypeTree(droppedStarTpe), EmptyTree)
(valDef, isRepeated)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 8f52088b19..85e31347be 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -298,7 +298,7 @@ trait Implicits {
def pos = if (pos0 != NoPosition) pos0 else tree.pos
def failure(what: Any, reason: String, pos: Position = this.pos): SearchResult = {
- if (settings.XlogImplicits.value)
+ if (settings.XlogImplicits)
reporter.echo(pos, what+" is not a valid implicit value for "+pt+" because:\n"+reason)
SearchFailure
}
@@ -1118,7 +1118,7 @@ trait Implicits {
)
// todo. migrate hardcoded materialization in Implicits to corresponding implicit macros
val materializer = atPos(pos.focus)(gen.mkMethodCall(TagMaterializers(tagClass), List(tp), if (prefix != EmptyTree) List(prefix) else List()))
- if (settings.XlogImplicits.value) reporter.echo(pos, "materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer))
+ if (settings.XlogImplicits) reporter.echo(pos, "materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer))
if (context.macrosEnabled) success(materializer)
// don't call `failure` here. if macros are disabled, we just fail silently
// otherwise -Xlog-implicits will spam the long with zillions of "macros are disabled"
@@ -1141,7 +1141,7 @@ trait Implicits {
if (args contains EmptyTree) EmptyTree
else typedPos(tree.pos.focus) {
val mani = gen.mkManifestFactoryCall(full, constructor, tparg, args.toList)
- if (settings.debug.value) println("generated manifest: "+mani) // DEBUG
+ if (settings.debug) println("generated manifest: "+mani) // DEBUG
mani
}
@@ -1316,7 +1316,7 @@ trait Implicits {
}
}
- if (result.isFailure && settings.debug.value)
+ if (result.isFailure && settings.debug)
log("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+implicitsOfExpectedType)
result
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 495ac1c086..8d7830897d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -131,7 +131,7 @@ trait Infer extends Checkable {
else if (optionArgs.nonEmpty)
if (nbSubPats == 1) {
val productArity = productArgs.size
- if (productArity > 1 && settings.lint.value)
+ if (productArity > 1 && settings.lint)
global.currentUnit.warning(pos, s"extractor pattern binds a single value to a Product${productArity} of type ${optionArgs.head}")
optionArgs
}
@@ -338,7 +338,7 @@ trait Infer extends Checkable {
sym1 = sym
if (sym1 == NoSymbol) {
- if (settings.debug.value) {
+ if (settings.debug) {
Console.println(context)
Console.println(tree)
Console.println("" + pre + " " + sym.owner + " " + context.owner + " " + context.outer.enclClass.owner + " " + sym.owner.thisType + (pre =:= sym.owner.thisType))
@@ -378,7 +378,7 @@ trait Infer extends Checkable {
try pre.memberType(sym1)
catch {
case ex: MalformedType =>
- if (settings.debug.value) ex.printStackTrace
+ if (settings.debug) ex.printStackTrace
val sym2 = underlyingSymbol(sym1)
val itype = pre.memberType(sym2)
ErrorUtils.issueTypeError(
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index 5999a64b36..50383a1e78 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -471,7 +471,7 @@ trait MethodSynthesis {
}
}
case class Setter(tree: ValDef) extends DerivedSetter {
- def name = nme.getterToSetter(tree.name)
+ def name = tree.setterName
def category = SetterTargetClass
def flagsMask = SetterFlags
def flagsExtra = ACCESSOR
@@ -479,7 +479,7 @@ trait MethodSynthesis {
override def derivedSym = basisSym.setter(enclClass)
}
case class Field(tree: ValDef) extends DerivedFromValDef {
- def name = nme.getterToLocal(tree.name)
+ def name = tree.localName
def category = FieldTargetClass
def flagsMask = FieldFlags
def flagsExtra = PrivateLocal
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index e966cc9060..de3010c371 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -184,7 +184,7 @@ trait Namers extends MethodSynthesis {
(newS.owner.isTypeParameter || newS.owner.isAbstractType)
// FIXME: name comparisons not successful, are these underscores
// sometimes nme.WILDCARD and sometimes tpnme.WILDCARD?
- && (newS.name.toString == nme.WILDCARD.toString)
+ && (newS.name string_== nme.WILDCARD)
)
)
@@ -323,7 +323,7 @@ trait Namers extends MethodSynthesis {
}
}
private def createFieldSymbol(tree: ValDef): TermSymbol =
- owner.newValue(nme.getterToLocal(tree.name), tree.pos, tree.mods.flags & FieldFlags | PrivateLocal)
+ owner.newValue(tree.localName, tree.pos, tree.mods.flags & FieldFlags | PrivateLocal)
private def createImportSymbol(tree: Tree) =
NoSymbol.newImport(tree.pos) setInfo completerOf(tree)
@@ -523,14 +523,20 @@ trait Namers extends MethodSynthesis {
if (from != nme.WILDCARD && base != ErrorType) {
if (isValid(from)) {
// for Java code importing Scala objects
- if (!nme.isModuleName(from) || isValid(nme.stripModuleSuffix(from))) {
+ if (!nme.isModuleName(from) || isValid(from.dropModule)) {
typer.TyperErrorGen.NotAMemberError(tree, expr, from)
}
}
// Setting the position at the import means that if there is
// more than one hidden name, the second will not be warned.
// So it is the position of the actual hidden name.
- checkNotRedundant(tree.pos withPoint fromPos, from, to)
+ //
+ // Note: java imports have precence over definitions in the same package
+ // so don't warn for them. There is a corresponding special treatment
+ // in the shadowing rules in typedIdent to (SI-7232). In any case,
+ // we shouldn't be emitting warnings for .java source files.
+ if (!context.unit.isJava)
+ checkNotRedundant(tree.pos withPoint fromPos, from, to)
}
}
@@ -654,9 +660,6 @@ trait Namers extends MethodSynthesis {
tree.symbol setInfo completerOf(tree)
if (mods.isCase) {
- if (primaryConstructorArity > MaxFunctionArity)
- MaxParametersCaseClassError(tree)
-
val m = ensureCompanionObject(tree, caseModuleDef)
m.moduleClass.updateAttachment(new ClassForCaseCompanionAttachment(tree))
}
@@ -669,7 +672,7 @@ trait Namers extends MethodSynthesis {
m.updateAttachment(new ConstructorDefaultsAttachment(tree, null))
}
val owner = tree.symbol.owner
- if (settings.lint.value && owner.isPackageObjectClass && !mods.isImplicit) {
+ if (settings.lint && owner.isPackageObjectClass && !mods.isImplicit) {
context.unit.warning(tree.pos,
"it is not recommended to define classes/objects inside of package objects.\n" +
"If possible, define " + tree.symbol + " in " + owner.skipPackageObject + " instead."
@@ -705,7 +708,7 @@ trait Namers extends MethodSynthesis {
// check that lower bound is not an F-bound
// but carefully: class Foo[T <: Bar[_ >: T]] should be allowed
for (tp1 @ TypeRef(_, sym, _) <- lo) {
- if (settings.breakCycles.value) {
+ if (settings.breakCycles) {
if (!sym.maybeInitialize) {
log(s"Cycle inspecting $lo for possible f-bounds: ${sym.fullLocationString}")
return sym
@@ -1373,7 +1376,9 @@ trait Namers extends MethodSynthesis {
if (!cdef.symbol.hasAbstractFlag)
namer.enterSyntheticSym(caseModuleApplyMeth(cdef))
- namer.enterSyntheticSym(caseModuleUnapplyMeth(cdef))
+ val primaryConstructorArity = treeInfo.firstConstructorArgs(cdef.impl.body).size
+ if (primaryConstructorArity <= MaxTupleArity)
+ namer.enterSyntheticSym(caseModuleUnapplyMeth(cdef))
}
def addCopyMethod(cdef: ClassDef, namer: Namer) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index d5ecb687b0..6921f8ce27 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -499,7 +499,7 @@ trait NamesDefaults { self: Analyzer =>
// disable conforms as a view...
val errsBefore = reporter.ERROR.count
try typer.silent { tpr =>
- val res = tpr.typed(arg, subst(paramtpe))
+ val res = tpr.typed(arg.duplicate, subst(paramtpe))
// better warning for SI-5044: if `silent` was not actually silent give a hint to the user
// [H]: the reason why `silent` is not silent is because the cyclic reference exception is
// thrown in a context completely different from `context` here. The exception happens while
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 40428272cf..efd4fd804f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -142,7 +142,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
}
// This has become noisy with implicit classes.
- if (settings.lint.value && settings.developer.value) {
+ if (settings.lint && settings.developer) {
clazz.info.decls filter (x => x.isImplicit && x.typeParams.nonEmpty) foreach { sym =>
val alts = clazz.info.decl(sym.name).alternatives
if (alts.size > 1)
@@ -307,7 +307,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
infoStringWithLocation(other),
infoStringWithLocation(member)
)
- else if (settings.debug.value)
+ else if (settings.debug)
analyzer.foundReqMsg(member.tpe, other.tpe)
else ""
@@ -407,7 +407,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
else if (member.isAnyOverride && (other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.isLazy) {
// !?! this is not covered by the spec. We need to resolve this either by changing the spec or removing the test here.
// !!! is there a !?! convention? I'm !!!ing this to make sure it turns up on my searches.
- if (!settings.overrideVars.value)
+ if (!settings.overrideVars)
overrideError("cannot override a mutable variable")
}
else if (member.isAnyOverride &&
@@ -431,7 +431,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
} else {
checkOverrideTypes()
checkOverrideDeprecated()
- if (settings.warnNullaryOverride.value) {
+ if (settings.warnNullaryOverride) {
if (other.paramss.isEmpty && !member.paramss.isEmpty) {
unit.warning(member.pos, "non-nullary method overrides nullary method")
}
@@ -920,7 +920,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
def apply(tp: Type) = mapOver(tp).normalize
}
- def checkImplicitViewOptionApply(pos: Position, fn: Tree, args: List[Tree]): Unit = if (settings.lint.value) (fn, args) match {
+ def checkImplicitViewOptionApply(pos: Position, fn: Tree, args: List[Tree]): Unit = if (settings.lint) (fn, args) match {
case (tap@TypeApply(fun, targs), List(view: ApplyImplicitView)) if fun.symbol == Option_apply =>
unit.warning(pos, s"Suspicious application of an implicit view (${view.fun}) in the argument to Option.apply.") // SI-6567
case _ =>
@@ -1199,7 +1199,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
catch {
case ex: TypeError =>
unit.error(tree0.pos, ex.getMessage())
- if (settings.explaintypes.value) {
+ if (settings.explaintypes) {
val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, argtps).bounds)
(argtps, bounds).zipped map ((targ, bound) => explainTypes(bound.lo, targ))
(argtps, bounds).zipped map ((targ, bound) => explainTypes(targ, bound.hi))
@@ -1537,9 +1537,9 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
case ValDef(_, _, _, _) | DefDef(_, _, _, _, _, _) =>
checkDeprecatedOvers(tree)
checkInfiniteLoop(tree.asInstanceOf[ValOrDefDef])
- if (settings.warnNullaryUnit.value)
+ if (settings.warnNullaryUnit)
checkNullaryMethodReturnType(sym)
- if (settings.warnInaccessible.value) {
+ if (settings.warnInaccessible) {
if (!sym.isConstructor && !sym.isEffectivelyFinal && !sym.isSynthetic)
checkAccessibilityOfReferencedTypes(tree)
}
@@ -1642,7 +1642,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
result
} catch {
case ex: TypeError =>
- if (settings.debug.value) ex.printStackTrace()
+ if (settings.debug) ex.printStackTrace()
unit.error(tree.pos, ex.getMessage())
tree
} finally {
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index c967fed0b9..e22dc73b53 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -91,7 +91,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
if (!found.isErroneous && !req.isErroneous) {
val msg = analyzer.ErrorUtils.typeErrorMsg(found, req, typer.infer.isPossiblyMissingArgs(found, req))
typer.context.error(pos, analyzer.withAddendum(pos)(msg))
- if (settings.explaintypes.value)
+ if (settings.explaintypes)
explainTypes(found, req)
}
}
@@ -241,7 +241,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
// also exists in a superclass, because they may be surprised
// to find out that a constructor parameter will shadow a
// field. See SI-4762.
- if (settings.lint.value) {
+ if (settings.lint) {
if (sym.isPrivateLocal && sym.paramss.isEmpty) {
qual.symbol.ancestors foreach { parent =>
parent.info.decls filterNot (x => x.isPrivate || x.hasLocalFlag) foreach { m2 =>
@@ -256,9 +256,16 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
}
- // direct calls to aliases of param accessors to the superclass in order to avoid
+
+ def isAccessibleFromSuper(sym: Symbol) = {
+ val pre = SuperType(sym.owner.tpe, qual.tpe)
+ localTyper.context.isAccessible(sym, pre, superAccess = true)
+ }
+
+ // Direct calls to aliases of param accessors to the superclass in order to avoid
// duplicating fields.
- if (sym.isParamAccessor && sym.alias != NoSymbol) {
+ // ... but, only if accessible (SI-6793)
+ if (sym.isParamAccessor && sym.alias != NoSymbol && isAccessibleFromSuper(sym.alias)) {
val result = (localTyper.typedPos(tree.pos) {
Select(Super(qual, tpnme.EMPTY) setPos qual.pos, sym.alias)
}).asInstanceOf[Select]
@@ -296,7 +303,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case Super(_, mix) =>
if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) {
- if (!settings.overrideVars.value)
+ if (!settings.overrideVars)
unit.error(tree.pos, "super may be not be used on " + sym.accessedOrSelf)
} else if (isDisallowed(sym)) {
unit.error(tree.pos, "super not allowed here: use this." + name.decode + " instead")
@@ -388,7 +395,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
assert(clazz != NoSymbol, sym)
debuglog("Decided for host class: " + clazz)
- val accName = nme.protName(sym.originalName)
+ val accName = nme.protName(sym.unexpandedName)
val hasArgs = sym.tpe.paramSectionCount > 0
val memberType = refChecks.toScalaRepeatedParam(sym.tpe) // fix for #2413
@@ -406,7 +413,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
val protAcc = clazz.info.decl(accName).suchThat(s => s == NoSymbol || s.tpe =:= accType(s)) orElse {
- val newAcc = clazz.newMethod(nme.protName(sym.originalName), tree.pos, newFlags = ARTIFACT)
+ val newAcc = clazz.newMethod(nme.protName(sym.unexpandedName), tree.pos, newFlags = ARTIFACT)
newAcc setInfoAndEnter accType(newAcc)
val code = DefDef(newAcc, {
@@ -466,7 +473,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
assert(clazz != NoSymbol, field)
debuglog("Decided for host class: " + clazz)
- val accName = nme.protSetterName(field.originalName)
+ val accName = nme.protSetterName(field.unexpandedName)
val protectedAccessor = clazz.info decl accName orElse {
val protAcc = clazz.newMethod(accName, field.pos, newFlags = ARTIFACT)
val paramTypes = List(clazz.typeOfThis, field.tpe)
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 5dc422bc1a..c531caa2e8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -93,7 +93,7 @@ trait SyntheticMethods extends ast.TreeDSL {
// like Tags and Arrays which are not robust and infer things
// which they shouldn't.
val accessorLub = (
- if (settings.Xexperimental.value) {
+ if (settings.Xexperimental) {
global.weakLub(accessors map (_.tpe.finalResultType))._1 match {
case RefinedType(parents, decls) if !decls.isEmpty => intersectionType(parents)
case tp => tp
@@ -336,7 +336,7 @@ trait SyntheticMethods extends ast.TreeDSL {
def shouldGenerate(m: Symbol) = {
!hasOverridingImplementation(m) || {
clazz.isDerivedValueClass && (m == Any_hashCode || m == Any_equals) && {
- if (settings.lint.value) {
+ if (settings.lint) {
(clazz.info nonPrivateMember m.name) filter (m => (m.owner != AnyClass) && (m.owner != clazz) && !m.isDeferred) andAlso { m =>
currentUnit.warning(clazz.pos, s"Implementation of ${m.name} inherited from ${m.owner} overridden in $clazz to enforce value class semantics")
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index dc11c5fe96..1c8d37ef39 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -69,7 +69,7 @@ abstract class TreeCheckers extends Analyzer {
// new symbols
if (newSyms.nonEmpty) {
informFn(newSyms.size + " new symbols.")
- val toPrint = if (settings.debug.value) sortedNewSyms mkString " " else ""
+ val toPrint = if (settings.debug) sortedNewSyms mkString " " else ""
newSyms.clear()
if (toPrint != "")
@@ -120,7 +120,7 @@ abstract class TreeCheckers extends Analyzer {
def errorFn(msg: Any): Unit = {hasError = true; println("[check: %s] %s".format(phase.prev, msg))}
def errorFn(pos: Position, msg: Any): Unit = errorFn(posstr(pos) + ": " + msg)
def informFn(msg: Any) {
- if (settings.verbose.value || settings.debug.value)
+ if (settings.verbose || settings.debug)
println("[check: %s] %s".format(phase.prev, msg))
}
@@ -137,7 +137,7 @@ abstract class TreeCheckers extends Analyzer {
}
def checkTrees() {
- if (settings.verbose.value)
+ if (settings.verbose)
Console.println("[consistency check at the beginning of phase " + phase + "]")
currentRun.units foreach (x => wrap(x)(check(x)))
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index 46740cd03c..5f45fead91 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -545,7 +545,7 @@ trait TypeDiagnostics {
// Error suppression will squash some of these warnings unless we circumvent it.
// It is presumed if you are using a -Y option you would really like to hear
// the warnings you've requested.
- if (settings.warnDeadCode.value && context.unit.exists && treeOK(tree) && exprOK)
+ if (settings.warnDeadCode && context.unit.exists && treeOK(tree) && exprOK)
context.warning(tree.pos, "dead code following this construct", force = true)
tree
}
@@ -585,7 +585,7 @@ trait TypeDiagnostics {
// but it seems that throwErrors excludes some of the errors that should actually be
// buffered, causing TypeErrors to fly around again. This needs some more investigation.
if (!context0.reportErrors) throw ex
- if (settings.debug.value) ex.printStackTrace()
+ if (settings.debug) ex.printStackTrace()
ex match {
case CyclicReference(sym, info: TypeCompleter) =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala b/src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala
index 65a3fedbd2..eb05486dca 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala
@@ -50,7 +50,7 @@ trait StructuredTypeStrings extends DestructureTypes {
else block(level, grouping)(name, nodes)
}
private def shortClass(x: Any) = {
- if (settings.debug.value) {
+ if (settings.debug) {
val name = (x.getClass.getName split '.').last
val str = if (TypeStrings.isAnonClass(x.getClass)) name else (name split '$').last
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 0e57145343..692c24fd20 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -944,6 +944,57 @@ trait Typers extends Adaptations with Tags {
// due to wrapClassTagUnapply, but when we support parameterized extractors, it will become
// more common place)
val extractor = overloadedExtractorOfObject orElse unapplyMember(tree.tpe)
+ def convertToCaseConstructor(clazz: Symbol): TypeTree = {
+ // convert synthetic unapply of case class to case class constructor
+ val prefix = tree.tpe.prefix
+ val tree1 = TypeTree(clazz.primaryConstructor.tpe.asSeenFrom(prefix, clazz.owner))
+ .setOriginal(tree)
+
+ val skolems = new mutable.ListBuffer[TypeSymbol]
+ object variantToSkolem extends TypeMap(trackVariance = true) {
+ def apply(tp: Type) = mapOver(tp) match {
+ // !!! FIXME - skipping this when variance.isInvariant allows unsoundness, see SI-5189
+ case TypeRef(NoPrefix, tpSym, Nil) if !variance.isInvariant && tpSym.isTypeParameterOrSkolem && tpSym.owner.isTerm =>
+ // must initialize or tpSym.tpe might see random type params!!
+ // without this, we'll get very weird types inferred in test/scaladoc/run/SI-5933.scala
+ // TODO: why is that??
+ tpSym.initialize
+ val bounds = if (variance.isPositive) TypeBounds.upper(tpSym.tpe) else TypeBounds.lower(tpSym.tpe)
+ // origin must be the type param so we can deskolemize
+ val skolem = context.owner.newGADTSkolem(unit.freshTypeName("?"+tpSym.name), tpSym, bounds)
+ // println("mapping "+ tpSym +" to "+ skolem + " : "+ bounds +" -- pt= "+ pt +" in "+ context.owner +" at "+ context.tree )
+ skolems += skolem
+ skolem.tpe
+ case tp1 => tp1
+ }
+ }
+
+ // have to open up the existential and put the skolems in scope
+ // can't simply package up pt in an ExistentialType, because that takes us back to square one (List[_ <: T] == List[T] due to covariance)
+ val ptSafe = variantToSkolem(pt) // TODO: pt.skolemizeExistential(context.owner, tree) ?
+ val freeVars = skolems.toList
+
+ // use "tree" for the context, not context.tree: don't make another CaseDef context,
+ // as instantiateTypeVar's bounds would end up there
+ val ctorContext = context.makeNewScope(tree, context.owner)
+ freeVars foreach ctorContext.scope.enter
+ newTyper(ctorContext).infer.inferConstructorInstance(tree1, clazz.typeParams, ptSafe)
+
+ // simplify types without losing safety,
+ // so that we get rid of unnecessary type slack, and so that error messages don't unnecessarily refer to skolems
+ val extrapolate = new ExistentialExtrapolation(freeVars) extrapolate (_: Type)
+ val extrapolated = tree1.tpe match {
+ case MethodType(ctorArgs, res) => // ctorArgs are actually in a covariant position, since this is the type of the subpatterns of the pattern represented by this Apply node
+ ctorArgs foreach (p => p.info = extrapolate(p.info)) // no need to clone, this is OUR method type
+ copyMethodType(tree1.tpe, ctorArgs, extrapolate(res))
+ case tp => tp
+ }
+
+ // once the containing CaseDef has been type checked (see typedCase),
+ // tree1's remaining type-slack skolems will be deskolemized (to the method type parameter skolems)
+ tree1 setType extrapolated
+ }
+
if (extractor != NoSymbol) {
// if we did some ad-hoc overloading resolution, update the tree's symbol
// do not update the symbol if the tree's symbol's type does not define an unapply member
@@ -959,59 +1010,16 @@ trait Typers extends Adaptations with Tags {
val clazz = unapplyParameterType(unapply)
if (unapply.isCase && clazz.isCase) {
- // convert synthetic unapply of case class to case class constructor
- val prefix = tree.tpe.prefix
- val tree1 = TypeTree(clazz.primaryConstructor.tpe.asSeenFrom(prefix, clazz.owner))
- .setOriginal(tree)
-
- val skolems = new mutable.ListBuffer[TypeSymbol]
- object variantToSkolem extends TypeMap(trackVariance = true) {
- def apply(tp: Type) = mapOver(tp) match {
- // !!! FIXME - skipping this when variance.isInvariant allows unsoundness, see SI-5189
- case TypeRef(NoPrefix, tpSym, Nil) if !variance.isInvariant && tpSym.isTypeParameterOrSkolem && tpSym.owner.isTerm =>
- // must initialize or tpSym.tpe might see random type params!!
- // without this, we'll get very weird types inferred in test/scaladoc/run/SI-5933.scala
- // TODO: why is that??
- tpSym.initialize
- val bounds = if (variance.isPositive) TypeBounds.upper(tpSym.tpe) else TypeBounds.lower(tpSym.tpe)
- // origin must be the type param so we can deskolemize
- val skolem = context.owner.newGADTSkolem(unit.freshTypeName("?"+tpSym.name), tpSym, bounds)
- // println("mapping "+ tpSym +" to "+ skolem + " : "+ bounds +" -- pt= "+ pt +" in "+ context.owner +" at "+ context.tree )
- skolems += skolem
- skolem.tpe
- case tp1 => tp1
- }
- }
-
- // have to open up the existential and put the skolems in scope
- // can't simply package up pt in an ExistentialType, because that takes us back to square one (List[_ <: T] == List[T] due to covariance)
- val ptSafe = variantToSkolem(pt) // TODO: pt.skolemizeExistential(context.owner, tree) ?
- val freeVars = skolems.toList
-
- // use "tree" for the context, not context.tree: don't make another CaseDef context,
- // as instantiateTypeVar's bounds would end up there
- val ctorContext = context.makeNewScope(tree, context.owner)
- freeVars foreach ctorContext.scope.enter
- newTyper(ctorContext).infer.inferConstructorInstance(tree1, clazz.typeParams, ptSafe)
-
- // simplify types without losing safety,
- // so that we get rid of unnecessary type slack, and so that error messages don't unnecessarily refer to skolems
- val extrapolate = new ExistentialExtrapolation(freeVars) extrapolate (_: Type)
- val extrapolated = tree1.tpe match {
- case MethodType(ctorArgs, res) => // ctorArgs are actually in a covariant position, since this is the type of the subpatterns of the pattern represented by this Apply node
- ctorArgs foreach (p => p.info = extrapolate(p.info)) // no need to clone, this is OUR method type
- copyMethodType(tree1.tpe, ctorArgs, extrapolate(res))
- case tp => tp
- }
-
- // once the containing CaseDef has been type checked (see typedCase),
- // tree1's remaining type-slack skolems will be deskolemized (to the method type parameter skolems)
- tree1 setType extrapolated
+ convertToCaseConstructor(clazz)
} else {
tree
}
} else {
- CaseClassConstructorError(tree)
+ val clazz = tree.tpe.typeSymbol.linkedClassOfClass
+ if (clazz.isCase)
+ convertToCaseConstructor(clazz)
+ else
+ CaseClassConstructorError(tree)
}
}
@@ -1133,14 +1141,14 @@ trait Typers extends Adaptations with Tags {
// note: was if (pt.typeSymbol == UnitClass) but this leads to a potentially
// infinite expansion if pt is constant type ()
if (sym == UnitClass) { // (12)
- if (settings.warnValueDiscard.value)
+ if (settings.warnValueDiscard)
context.unit.warning(tree.pos, "discarded non-Unit value")
return typedPos(tree.pos, mode, pt) {
Block(List(tree), Literal(Constant(())))
}
}
else if (isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt)) {
- if (settings.warnNumericWiden.value)
+ if (settings.warnNumericWiden)
context.unit.warning(tree.pos, "implicit numeric widening")
return typedPos(tree.pos, mode, pt) {
Select(tree, "to" + sym.name)
@@ -1159,7 +1167,7 @@ trait Typers extends Adaptations with Tags {
val coercion = inferView(tree, tree.tpe, pt, reportAmbiguous = true)
if (coercion != EmptyTree) {
def msg = "inferred view from " + tree.tpe + " to " + pt + " = " + coercion + ":" + coercion.tpe
- if (settings.logImplicitConv.value)
+ if (settings.logImplicitConv)
unit.echo(tree.pos, msg)
debuglog(msg)
@@ -1170,9 +1178,9 @@ trait Typers extends Adaptations with Tags {
}
}
}
- if (settings.debug.value) {
+ if (settings.debug) {
log("error tree = " + tree)
- if (settings.explaintypes.value) explainTypes(tree.tpe, pt)
+ if (settings.explaintypes) explainTypes(tree.tpe, pt)
}
val found = tree.tpe
@@ -1286,7 +1294,7 @@ trait Typers extends Adaptations with Tags {
inferView(qual, qual.tpe, searchTemplate, reportAmbiguous, saveErrors) match {
case EmptyTree => qual
case coercion =>
- if (settings.logImplicitConv.value)
+ if (settings.logImplicitConv)
unit.echo(qual.pos,
"applied implicit conversion from %s to %s = %s".format(
qual.tpe, searchTemplate, coercion.symbol.defString))
@@ -1324,8 +1332,7 @@ trait Typers extends Adaptations with Tags {
def adaptToMemberWithArgs(tree: Tree, qual: Tree, name: Name, mode: Mode, reportAmbiguous: Boolean, saveErrors: Boolean): Tree = {
def onError(reportError: => Tree): Tree = context.tree match {
case Apply(tree1, args) if (tree1 eq tree) && args.nonEmpty =>
- ( silent (_.typedArgs(args, mode))
- map (_.asInstanceOf[List[Tree]])
+ ( silent (_.typedArgs(args.map(_.duplicate), mode))
filter (xs => !(xs exists (_.isErrorTyped)))
map (xs => adaptToArguments(qual, name, xs, WildcardType, reportAmbiguous, saveErrors))
orElse ( _ => reportError)
@@ -1745,12 +1752,12 @@ trait Typers extends Adaptations with Tags {
if (!(selfType <:< parent.tpe.typeOfThis) &&
!phase.erasedTypes &&
!context.owner.isSynthetic && // don't check synthetic concrete classes for virtuals (part of DEVIRTUALIZE)
- !settings.noSelfCheck.value && // setting to suppress this very check
+ !settings.noSelfCheck && // setting to suppress this very check
!selfType.isErroneous &&
!parent.tpe.isErroneous)
{
pending += ParentSelfTypeConformanceError(parent, selfType)
- if (settings.explaintypes.value) explainTypes(selfType, parent.tpe.typeOfThis)
+ if (settings.explaintypes) explainTypes(selfType, parent.tpe.typeOfThis)
}
if (parents exists (p => p != parent && p.tpe.typeSymbol == psym && !psym.isError))
@@ -2300,7 +2307,7 @@ trait Typers extends Adaptations with Tags {
tdef.symbol.annotations.map(_.completeInfo())
// @specialized should not be pickled when compiling with -no-specialize
- if (settings.nospecialization.value && currentRun.compiles(tdef.symbol)) {
+ if (settings.nospecialization && currentRun.compiles(tdef.symbol)) {
tdef.symbol.removeAnnotation(definitions.SpecializedClass)
tdef.symbol.deSkolemize.removeAnnotation(definitions.SpecializedClass)
}
@@ -2492,7 +2499,7 @@ trait Typers extends Adaptations with Tags {
// TODO: add fallback __match sentinel to predef
val matchStrategy: Tree =
- if (!(newPatternMatching && settings.Xexperimental.value && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen
+ if (!(newPatternMatching && settings.Xexperimental && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen
else newTyper(context.makeImplicit(reportAmbiguousErrors = false)).silent(_.typed(Ident(vpmName._match), EXPRmode, WildcardType), reportAmbiguousErrors = false) orElse (_ => null)
if (matchStrategy ne null) // virtualize
@@ -3558,7 +3565,7 @@ trait Typers extends Adaptations with Tags {
// If there are dummy type arguments in typeFun part, it suggests we
// must type the actual constructor call, not only the select. The value
// arguments are how the type arguments will be inferred.
- if (targs.isEmpty && typedFun0.exists(t => isDummyAppliedType(t.tpe)))
+ if (targs.isEmpty && typedFun0.exists(t => t.tpe != null && isDummyAppliedType(t.tpe)))
logResult(s"Retyped $typedFun0 to find type args")(typed(argss.foldLeft(fun0)(Apply(_, _))))
else
typedFun0
@@ -3671,77 +3678,9 @@ trait Typers extends Adaptations with Tags {
})
}
- def isRawParameter(sym: Symbol) = // is it a type parameter leaked by a raw type?
- sym.isTypeParameter && sym.owner.isJavaDefined
-
- /** If we map a set of hidden symbols to their existential bounds, we
- * have a problem: the bounds may themselves contain references to the
- * hidden symbols. So this recursively calls existentialBound until
- * the typeSymbol is not amongst the symbols being hidden.
- */
- def existentialBoundsExcludingHidden(hidden: List[Symbol]): Map[Symbol, Type] = {
- def safeBound(t: Type): Type =
- if (hidden contains t.typeSymbol) safeBound(t.typeSymbol.existentialBound.bounds.hi) else t
-
- def hiBound(s: Symbol): Type = safeBound(s.existentialBound.bounds.hi) match {
- case tp @ RefinedType(parents, decls) =>
- val parents1 = parents mapConserve safeBound
- if (parents eq parents1) tp
- else copyRefinedType(tp, parents1, decls)
- case tp => tp
- }
-
- // Hanging onto lower bound in case anything interesting
- // happens with it.
- mapFrom(hidden)(s => s.existentialBound match {
- case TypeBounds(lo, hi) => TypeBounds(lo, hiBound(s))
- case _ => hiBound(s)
- })
- }
-
- /** Given a set `rawSyms` of term- and type-symbols, and a type
- * `tp`, produce a set of fresh type parameters and a type so that
- * it can be abstracted to an existential type. Every type symbol
- * `T` in `rawSyms` is mapped to a clone. Every term symbol `x` of
- * type `T` in `rawSyms` is given an associated type symbol of the
- * following form:
- *
- * type x.type <: T with Singleton
- *
- * The name of the type parameter is `x.type`, to produce nice
- * diagnostics. The Singleton parent ensures that the type
- * parameter is still seen as a stable type. Type symbols in
- * rawSyms are fully replaced by the new symbols. Term symbols are
- * also replaced, except for term symbols of an Ident tree, where
- * only the type of the Ident is changed.
- */
- protected def existentialTransform[T](rawSyms: List[Symbol], tp: Type)(creator: (List[Symbol], Type) => T): T = {
- val allBounds = existentialBoundsExcludingHidden(rawSyms)
- val typeParams: List[Symbol] = rawSyms map { sym =>
- val name = sym.name match {
- case x: TypeName => x
- case x => tpnme.singletonName(x)
- }
- val bound = allBounds(sym)
- val sowner = if (isRawParameter(sym)) context.owner else sym.owner
- val quantified = sowner.newExistential(name, sym.pos)
-
- quantified setInfo bound.cloneInfo(quantified)
- }
- // Higher-kinded existentials are not yet supported, but this is
- // tpeHK for when they are: "if a type constructor is expected/allowed,
- // tpeHK must be called instead of tpe."
- val typeParamTypes = typeParams map (_.tpeHK)
- def doSubst(info: Type) = info.subst(rawSyms, typeParamTypes)
-
- creator(typeParams map (_ modifyInfo doSubst), doSubst(tp))
- }
-
/** Compute an existential type from raw hidden symbols `syms` and type `tp`
*/
- def packSymbols(hidden: List[Symbol], tp: Type): Type =
- if (hidden.isEmpty) tp
- else existentialTransform(hidden, tp)(existentialAbstraction)
+ def packSymbols(hidden: List[Symbol], tp: Type): Type = global.packSymbols(hidden, tp, Some(context0.owner))
def isReferencedFrom(ctx: Context, sym: Symbol): Boolean =
ctx.owner.isTerm &&
@@ -4085,7 +4024,7 @@ trait Typers extends Adaptations with Tags {
if (ann.tpe == null) {
// an annotated type
val selfsym =
- if (!settings.selfInAnnots.value)
+ if (!settings.selfInAnnots)
NoSymbol
else
arg1.tpe.selfsym orElse {
@@ -4211,7 +4150,7 @@ trait Typers extends Adaptations with Tags {
if (treeInfo.mayBeVarGetter(varsym)) {
lhs1 match {
case treeInfo.Applied(Select(qual, name), _, _) =>
- val sel = Select(qual, nme.getterToSetter(name.toTermName)) setPos lhs.pos
+ val sel = Select(qual, name.setterName) setPos lhs.pos
val app = Apply(sel, List(rhs)) setPos tree.pos
return typed(app, mode, pt)
@@ -4372,6 +4311,12 @@ trait Typers extends Adaptations with Tags {
treeCopy.New(tree, tpt1).setType(tp)
}
+ def functionTypeWildcard(tree: Tree, arity: Int): Type = {
+ val tp = functionType(List.fill(arity)(WildcardType), WildcardType)
+ if (tp == NoType) MaxFunctionArityError(tree)
+ tp
+ }
+
def typedEta(expr1: Tree): Tree = expr1.tpe match {
case TypeRef(_, ByNameParamClass, _) =>
val expr2 = Function(List(), expr1) setPos expr1.pos
@@ -4383,10 +4328,10 @@ trait Typers extends Adaptations with Tags {
typed1(expr2, mode, pt)
case PolyType(_, MethodType(formals, _)) =>
if (isFunctionType(pt)) expr1
- else adapt(expr1, mode, functionType(formals map (t => WildcardType), WildcardType))
+ else adapt(expr1, mode, functionTypeWildcard(expr1, formals.length))
case MethodType(formals, _) =>
if (isFunctionType(pt)) expr1
- else adapt(expr1, mode, functionType(formals map (t => WildcardType), WildcardType))
+ else adapt(expr1, mode, functionTypeWildcard(expr1, formals.length))
case ErrorType =>
expr1
case _ =>
@@ -4658,7 +4603,7 @@ trait Typers extends Adaptations with Tags {
if (isPastTyper) t.tpe match {
case OverloadedType(pre, alts) =>
if (alts forall (s => (s.owner == ObjectClass) || (s.owner == AnyClass) || isPrimitiveValueClass(s.owner))) ()
- else if (settings.debug.value) printCaller(
+ else if (settings.debug) printCaller(
s"""|Select received overloaded type during $phase, but typer is over.
|If this type reaches the backend, we are likely doomed to crash.
|$t has these overloads:
@@ -4692,11 +4637,13 @@ trait Typers extends Adaptations with Tags {
def handleMissing: Tree = {
def errorTree = missingSelectErrorTree(tree, qual, name)
def asTypeSelection = (
- if (context.owner.enclosingTopLevelClass.isJavaDefined && name.isTypeName) {
+ if (context.unit.isJava && name.isTypeName) {
+ // SI-3120 Java uses the same syntax, A.B, to express selection from the
+ // value A and from the type A. We have to try both.
atPos(tree.pos)(gen.convertToSelectFromType(qual, name)) match {
case EmptyTree => None
case tree1 => Some(typed1(tree1, mode, pt))
- }
+ }
}
else None
)
@@ -4826,7 +4773,7 @@ trait Typers extends Adaptations with Tags {
*/
def typedIdent(tree: Tree, name: Name): Tree = {
// setting to enable unqualified idents in empty package (used by the repl)
- def inEmptyPackage = if (settings.exposeEmptyPackage.value) lookupInEmpty(name) else NoSymbol
+ def inEmptyPackage = if (settings.exposeEmptyPackage) lookupInEmpty(name) else NoSymbol
def issue(err: AbsTypeError) = {
// Avoiding some spurious error messages: see SI-2388.
@@ -4947,7 +4894,7 @@ trait Typers extends Adaptations with Tags {
AppliedTypeNoParametersError(tree, tpt1.tpe)
} else {
//Console.println("\{tpt1}:\{tpt1.symbol}:\{tpt1.symbol.info}")
- if (settings.debug.value) Console.println(tpt1+":"+tpt1.symbol+":"+tpt1.symbol.info)//debug
+ if (settings.debug) Console.println(tpt1+":"+tpt1.symbol+":"+tpt1.symbol.info)//debug
AppliedTypeWrongNumberOfArgsError(tree, tpt1, tparams)
}
}
@@ -4993,6 +4940,13 @@ trait Typers extends Adaptations with Tags {
}
def typedTry(tree: Try) = {
+ tree match {
+ case Try(_, Nil, EmptyTree) =>
+ if (!isPastTyper) context.warning(tree.pos,
+ "A try without a catch or finally is equivalent to putting its body in a block; no exceptions are handled.")
+ case _ =>
+ }
+
var block1 = typed(tree.block, pt)
var catches1 = typedCases(tree.catches, ThrowableClass.tpe, pt)
@@ -5143,7 +5097,7 @@ trait Typers extends Adaptations with Tags {
def typedLiteral(tree: Literal) = {
val value = tree.value
// Warn about likely interpolated strings which are missing their interpolators
- if (settings.lint.value) value match {
+ if (settings.lint) value match {
case Constant(s: String) =>
def names = InterpolatorIdentRegex findAllIn s map (n => newTermName(n stripPrefix "$"))
val shouldWarn = (
@@ -5325,7 +5279,7 @@ trait Typers extends Adaptations with Tags {
reportTypeError(context, tree.pos, ex)
setError(tree)
case ex: Exception =>
- if (settings.debug.value) // @M causes cyclic reference error
+ if (settings.debug) // @M causes cyclic reference error
Console.println("exception when typing "+tree+", pt = "+ptPlugins)
if (context != null && context.unit.exists && tree != null)
logError("AT: " + (tree.pos).dbgString, ex)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index 589e5ce6fd..d55dce70c7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -115,11 +115,16 @@ trait Unapplies extends ast.TreeDSL
/** The module corresponding to a case class; overrides toString to show the module's name
*/
def caseModuleDef(cdef: ClassDef): ModuleDef = {
- // > MaxFunctionArity is caught in Namers, but for nice error reporting instead of
- // an abrupt crash we trim the list here.
- def primaries = constrParamss(cdef).head take MaxFunctionArity map (_.tpt)
- def inheritFromFun = !cdef.mods.hasAbstractFlag && cdef.tparams.isEmpty && constrParamss(cdef).length == 1
- def createFun = gen.scalaFunctionConstr(primaries, toIdent(cdef), abstractFun = true)
+ val params = constrParamss(cdef)
+ def inheritFromFun = !cdef.mods.hasAbstractFlag && cdef.tparams.isEmpty && (params match {
+ case List(ps) if ps.length <= MaxFunctionArity => true
+ case _ => false
+ })
+ def createFun = {
+ def primaries = params.head map (_.tpt)
+ gen.scalaFunctionConstr(primaries, toIdent(cdef), abstractFun = true)
+ }
+
def parents = if (inheritFromFun) List(createFun) else Nil
def toString = DefDef(
Modifiers(OVERRIDE | FINAL | SYNTHETIC),
diff --git a/src/compiler/scala/tools/nsc/util/SimpleTracer.scala b/src/compiler/scala/tools/nsc/util/SimpleTracer.scala
index 6997dbd402..4e1cf02a6e 100644
--- a/src/compiler/scala/tools/nsc/util/SimpleTracer.scala
+++ b/src/compiler/scala/tools/nsc/util/SimpleTracer.scala
@@ -10,7 +10,7 @@ import java.io.PrintStream
* @param enabled: A condition that must be true for trace info to be produced.
*/
class SimpleTracer(out: PrintStream, enabled: Boolean = true) {
- def apply[T](msg: String)(value: T): T = {
+ def apply[T](msg: => String)(value: T): T = {
if (enabled) out.println(msg+value)
value
}
diff --git a/src/compiler/scala/tools/nsc/util/TreeSet.scala b/src/compiler/scala/tools/nsc/util/TreeSet.scala
index 3cdbcc5110..d2e9238e8f 100644
--- a/src/compiler/scala/tools/nsc/util/TreeSet.scala
+++ b/src/compiler/scala/tools/nsc/util/TreeSet.scala
@@ -40,12 +40,22 @@ class TreeSet[T >: Null <: AnyRef](less: (T, T) => Boolean) extends Set[T] {
tree = add(tree)
}
- def iterator = {
- def elems(t: Tree): Iterator[T] = {
- if (t eq null) Iterator.empty
- else elems(t.l) ++ (Iterator single t.elem) ++ elems(t.r)
+ def iterator = toList.iterator
+
+ override def foreach[U](f: T => U) {
+ def loop(t: Tree) {
+ if (t ne null) {
+ loop(t.l)
+ f(t.elem)
+ loop(t.r)
+ }
}
- elems(tree)
+ loop(tree)
+ }
+ override def toList = {
+ val xs = scala.collection.mutable.ListBuffer[T]()
+ foreach(xs += _)
+ xs.toList
}
override def toString(): String = {
diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/reflect/MacroImplementations.scala
index 002a3fce82..4e8f02084d 100644
--- a/src/compiler/scala/tools/reflect/MacroImplementations.scala
+++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala
@@ -117,7 +117,8 @@ abstract class MacroImplementations {
if (!strIsEmpty) {
val len = str.length
while (idx < len) {
- if (str(idx) == '%') {
+ def notPercentN = str(idx) != '%' || (idx + 1 < len && str(idx + 1) != 'n')
+ if (str(idx) == '%' && notPercentN) {
bldr append (str substring (start, idx)) append "%%"
start = idx + 1
}
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
index 3e227ce8aa..f6ed5f8f1c 100644
--- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
+++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
@@ -250,7 +250,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
throwIfErrors()
val className = mdef.symbol.fullName
- if (settings.debug.value) println("generated: "+className)
+ if (settings.debug) println("generated: "+className)
def moduleFileName(className: String) = className + "$"
val jclazz = jClass.forName(moduleFileName(className), true, classLoader)
val jmeth = jclazz.getDeclaredMethods.find(_.getName == wrapperMethodName).get
@@ -349,11 +349,11 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
lazy val exporter = importer.reverse
def typeCheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = compiler.withCleanupCaches {
- if (compiler.settings.verbose.value) println("importing "+tree+", expectedType = "+expectedType)
+ if (compiler.settings.verbose) println("importing "+tree+", expectedType = "+expectedType)
val ctree: compiler.Tree = importer.importTree(tree)
val cexpectedType: compiler.Type = importer.importType(expectedType)
- if (compiler.settings.verbose.value) println("typing "+ctree+", expectedType = "+expectedType)
+ if (compiler.settings.verbose) println("typing "+ctree+", expectedType = "+expectedType)
val ttree: compiler.Tree = compiler.typeCheck(ctree, cexpectedType, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled)
val uttree = exporter.importTree(ttree)
uttree
@@ -369,12 +369,12 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
}
private def inferImplicit(tree: u.Tree, pt: u.Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: u.Position): u.Tree = compiler.withCleanupCaches {
- if (compiler.settings.verbose.value) println(s"importing pt=$pt, tree=$tree, pos=$pos")
+ if (compiler.settings.verbose) println(s"importing pt=$pt, tree=$tree, pos=$pos")
val ctree: compiler.Tree = importer.importTree(tree)
val cpt: compiler.Type = importer.importType(pt)
val cpos: compiler.Position = importer.importPosition(pos)
- if (compiler.settings.verbose.value) println("inferring implicit %s of type %s, macros = %s".format(if (isView) "view" else "value", pt, !withMacrosDisabled))
+ if (compiler.settings.verbose) println("inferring implicit %s of type %s, macros = %s".format(if (isView) "view" else "value", pt, !withMacrosDisabled))
val itree: compiler.Tree = compiler.inferImplicit(ctree, cpt, isView = isView, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = cpos)
val uitree = exporter.importTree(itree)
uitree
@@ -395,17 +395,17 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
}
def parse(code: String): u.Tree = {
- if (compiler.settings.verbose.value) println("parsing "+code)
+ if (compiler.settings.verbose) println("parsing "+code)
val ctree: compiler.Tree = compiler.parse(code)
val utree = exporter.importTree(ctree)
utree
}
def compile(tree: u.Tree): () => Any = {
- if (compiler.settings.verbose.value) println("importing "+tree)
+ if (compiler.settings.verbose) println("importing "+tree)
val ctree: compiler.Tree = importer.importTree(tree)
- if (compiler.settings.verbose.value) println("compiling "+ctree)
+ if (compiler.settings.verbose) println("compiling "+ctree)
compiler.compile(ctree)
}
diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala
index d8e545e6b1..8d65c40a01 100644
--- a/src/compiler/scala/tools/util/PathResolver.scala
+++ b/src/compiler/scala/tools/util/PathResolver.scala
@@ -146,7 +146,7 @@ object PathResolver {
import PathResolver.{ Defaults, Environment, ppcp }
class PathResolver(settings: Settings, context: JavaContext) {
- def this(settings: Settings) = this(settings, if (settings.inline.value) new JavaContext else DefaultJavaContext)
+ def this(settings: Settings) = this(settings, if (settings.inline) new JavaContext else DefaultJavaContext)
private def cmdLineOrElse(name: String, alt: String) = {
(commandLineFor(name) match {
@@ -240,7 +240,7 @@ class PathResolver(settings: Settings, context: JavaContext) {
lazy val result = {
val cp = new JavaClassPath(containers.toIndexedSeq, context)
- if (settings.Ylogcp.value) {
+ if (settings.Ylogcp) {
Console.println("Classpath built from " + settings.toConciseString)
Console.println("Defaults: " + PathResolver.Defaults)
Console.println("Calculated: " + Calculated)
diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala
index 099a882f10..dbdb2d02b6 100644
--- a/src/interactive/scala/tools/nsc/interactive/Global.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Global.scala
@@ -547,7 +547,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
for (s <- allSources; if !ignoredFiles(s.file); unit <- getUnit(s)) {
try {
if (!unit.isUpToDate)
- if (unit.problems.isEmpty || !settings.YpresentationStrict.value)
+ if (unit.problems.isEmpty || !settings.YpresentationStrict)
typeCheck(unit)
else debugLog("%s has syntax errors. Skipped typechecking".format(unit))
else debugLog("already up to date: "+unit)
diff --git a/src/interactive/scala/tools/nsc/interactive/Main.scala b/src/interactive/scala/tools/nsc/interactive/Main.scala
index 3b4a36f62d..c838606f02 100644
--- a/src/interactive/scala/tools/nsc/interactive/Main.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Main.scala
@@ -12,7 +12,7 @@ package interactive
*/
object Main extends nsc.MainClass {
override def processSettingsHook(): Boolean = {
- if (this.settings.Yidedebug.value) {
+ if (this.settings.Yidedebug) {
this.settings.Xprintpos.value = true
this.settings.Yrangepos.value = true
val compiler = new interactive.Global(this.settings, this.reporter)
diff --git a/src/interactive/scala/tools/nsc/interactive/REPL.scala b/src/interactive/scala/tools/nsc/interactive/REPL.scala
index 04c06b9357..432400ecd2 100644
--- a/src/interactive/scala/tools/nsc/interactive/REPL.scala
+++ b/src/interactive/scala/tools/nsc/interactive/REPL.scala
@@ -32,7 +32,7 @@ object REPL {
val settings = new Settings(replError)
reporter = new ConsoleReporter(settings)
val command = new CompilerCommand(args.toList, settings)
- if (command.settings.version.value)
+ if (command.settings.version)
reporter.echo(versionMsg)
else {
try {
@@ -50,7 +50,7 @@ object REPL {
}
} catch {
case ex @ FatalError(msg) =>
- if (true || command.settings.debug.value) // !!!
+ if (true || command.settings.debug) // !!!
ex.printStackTrace()
reporter.error(null, "fatal error: " + msg)
}
diff --git a/src/interactive/scala/tools/nsc/interactive/tests/InteractiveTest.scala b/src/interactive/scala/tools/nsc/interactive/tests/InteractiveTest.scala
index a4a2de9b51..f30d896fb7 100644
--- a/src/interactive/scala/tools/nsc/interactive/tests/InteractiveTest.scala
+++ b/src/interactive/scala/tools/nsc/interactive/tests/InteractiveTest.scala
@@ -74,7 +74,7 @@ abstract class InteractiveTest
/** Test's entry point */
def main(args: Array[String]) {
try execute()
- finally shutdown()
+ finally askShutdown()
}
protected def execute(): Unit = {
@@ -110,14 +110,4 @@ abstract class InteractiveTest
tester.run()
}
****/
-
- /** shutdown the presentation compiler. */
- protected def shutdown() {
- askShutdown()
-
- // this is actually needed to force exit on test completion.
- // Note: May be a bug on either the testing framework or (less likely)
- // the presentation compiler
- sys.exit(0)
- }
}
diff --git a/src/interactive/scala/tools/nsc/interactive/tests/Tester.scala b/src/interactive/scala/tools/nsc/interactive/tests/Tester.scala
index 9382d5890f..8a47c1df37 100644
--- a/src/interactive/scala/tools/nsc/interactive/tests/Tester.scala
+++ b/src/interactive/scala/tools/nsc/interactive/tests/Tester.scala
@@ -17,7 +17,7 @@ class Tester(ntests: Int, inputs: Array[SourceFile], settings: Settings) {
val compiler = new Global(settings, reporter)
def askAndListen[T, U](msg: String, arg: T, op: (T, Response[U]) => Unit) {
- if (settings.verbose.value) print(msg+" "+arg+": ")
+ if (settings.verbose) print(msg+" "+arg+": ")
val TIMEOUT = 10 // ms
val limit = System.currentTimeMillis() + randomDelayMillis
val res = new Response[U]
@@ -28,7 +28,7 @@ class Tester(ntests: Int, inputs: Array[SourceFile], settings: Settings) {
} else res.get(TIMEOUT) match {
case Some(Left(t)) =>
/**/
- if (settings.verbose.value) println(t)
+ if (settings.verbose) println(t)
case Some(Right(ex)) =>
ex.printStackTrace()
println(ex)
diff --git a/src/interactive/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala b/src/interactive/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala
index 9085eb56e6..c0ad245091 100644
--- a/src/interactive/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala
+++ b/src/interactive/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala
@@ -17,7 +17,7 @@ private[tests] trait CoreTestDefs
with AskCompletionAt {
def memberPrinter(member: compiler.Member): String =
- "[accessible: %5s] ".format(member.accessible) + "`" + (member.sym.toString() + member.tpe.toString()).trim() + "`"
+ "[accessible: %5s] ".format(member.accessible) + "`" + (member.sym.toString.trim + member.tpe.toString()).trim + "`"
override def runTest() {
askAllSources(CompletionMarker) { pos =>
@@ -29,7 +29,7 @@ private[tests] trait CoreTestDefs
// universal check file that we can provide for this to work
reporter.println("retrieved %d members".format(members.size))
compiler ask { () =>
- val filtered = members.filterNot(member => member.sym.name.toString == "getClass" || member.sym.isConstructor)
+ val filtered = members.filterNot(member => (member.sym.name string_== "getClass") || member.sym.isConstructor)
reporter.println(filtered.map(memberPrinter).sortBy(_.toString()).mkString("\n"))
}
}
diff --git a/src/interactive/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala b/src/interactive/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala
index 676feeba8a..40cfc111a1 100644
--- a/src/interactive/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala
+++ b/src/interactive/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala
@@ -11,7 +11,7 @@ private[tests] object SourcesCollector {
* With the default `filter` only .scala and .java files are collected.
* */
def apply(base: Path, filter: SourceFilter): Array[SourceFile] = {
- assert(base.isDirectory)
+ assert(base.isDirectory, base + " is not a directory")
base.walk.filter(filter).map(source).toList.toArray.sortBy(_.file.name)
}
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala
index c85a4fb6e7..72a23a0dd0 100644
--- a/src/library/scala/collection/Iterator.scala
+++ b/src/library/scala/collection/Iterator.scala
@@ -161,6 +161,41 @@ object Iterator {
def hasNext = true
def next = elem
}
+
+ /** Avoid stack overflows when applying ++ to lots of iterators by
+ * flattening the unevaluated iterators out into a vector of closures.
+ */
+ private[scala] final class ConcatIterator[+A](initial: Vector[() => Iterator[A]]) extends Iterator[A] {
+ // current set to null when all iterators are exhausted
+ private[this] var current: Iterator[A] = Iterator.empty
+ private[this] var queue: Vector[() => Iterator[A]] = initial
+ // Advance current to the next non-empty iterator
+ private[this] def advance(): Boolean = {
+ if (queue.isEmpty) {
+ current = null
+ false
+ }
+ else {
+ current = queue.head()
+ queue = queue.tail
+ current.hasNext || advance()
+ }
+ }
+ def hasNext = (current ne null) && (current.hasNext || advance())
+ def next() = if (hasNext) current.next else Iterator.empty.next
+
+ override def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] =
+ new ConcatIterator(queue :+ (() => that.toIterator))
+ }
+
+ private[scala] final class JoinIterator[+A](lhs: Iterator[A], that: => GenTraversableOnce[A]) extends Iterator[A] {
+ private[this] lazy val rhs: Iterator[A] = that.toIterator
+ def hasNext = lhs.hasNext || rhs.hasNext
+ def next = if (lhs.hasNext) lhs.next else rhs.next
+
+ override def ++[B >: A](that: => GenTraversableOnce[B]) =
+ new ConcatIterator(Vector(() => this, () => that.toIterator))
+ }
}
import Iterator.empty
@@ -338,24 +373,7 @@ trait Iterator[+A] extends TraversableOnce[A] {
* @usecase def ++(that: => Iterator[A]): Iterator[A]
* @inheritdoc
*/
- def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = new AbstractIterator[B] {
- // optimize a little bit to prevent n log n behavior.
- private var cur : Iterator[B] = self
- private var selfExhausted : Boolean = false
- // since that is by-name, make sure it's only referenced once -
- // if "val it = that" is inside the block, then hasNext on an empty
- // iterator will continually reevaluate it. (ticket #3269)
- lazy val it = that.toIterator
- // the eq check is to avoid an infinite loop on "x ++ x"
- def hasNext = cur.hasNext || (!selfExhausted && {
- it.hasNext && {
- cur = it
- selfExhausted = true
- true
- }
- })
- def next() = { hasNext; cur.next() }
- }
+ def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = new Iterator.JoinIterator(self, that)
/** Creates a new iterator by applying a function to all values produced by this iterator
* and concatenating the results.
diff --git a/src/library/scala/collection/parallel/package.scala b/src/library/scala/collection/parallel/package.scala
index d91f70da75..66fbad7643 100644
--- a/src/library/scala/collection/parallel/package.scala
+++ b/src/library/scala/collection/parallel/package.scala
@@ -41,12 +41,7 @@ package object parallel {
private[parallel] def outofbounds(idx: Int) = throw new IndexOutOfBoundsException(idx.toString)
- private[parallel] def getTaskSupport: TaskSupport =
- if (scala.util.Properties.isJavaAtLeast("1.6")) {
- val vendor = scala.util.Properties.javaVmVendor
- if ((vendor contains "Oracle") || (vendor contains "Sun") || (vendor contains "Apple")) new ForkJoinTaskSupport
- else new ThreadPoolTaskSupport
- } else new ThreadPoolTaskSupport
+ private[parallel] def getTaskSupport: TaskSupport = new ForkJoinTaskSupport
val defaultTaskSupport: TaskSupport = getTaskSupport
diff --git a/src/library/scala/reflect/NameTransformer.scala b/src/library/scala/reflect/NameTransformer.scala
index 8a1cce6b02..6192971c74 100755
--- a/src/library/scala/reflect/NameTransformer.scala
+++ b/src/library/scala/reflect/NameTransformer.scala
@@ -15,9 +15,12 @@ package reflect
object NameTransformer {
// XXX Short term: providing a way to alter these without having to recompile
// the compiler before recompiling the compiler.
- val MODULE_SUFFIX_STRING = sys.props.getOrElse("SCALA_MODULE_SUFFIX_STRING", "$")
- val NAME_JOIN_STRING = sys.props.getOrElse("SCALA_NAME_JOIN_STRING", "$")
- val MODULE_INSTANCE_NAME = "MODULE$"
+ val MODULE_SUFFIX_STRING = sys.props.getOrElse("SCALA_MODULE_SUFFIX_STRING", "$")
+ val NAME_JOIN_STRING = sys.props.getOrElse("SCALA_NAME_JOIN_STRING", "$")
+ val MODULE_INSTANCE_NAME = "MODULE$"
+ val LOCAL_SUFFIX_STRING = " "
+ val SETTER_SUFFIX_STRING = "_$eq"
+ val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$"
private val nops = 128
private val ncodes = 26 * 26
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index 10e6d7d9a4..97d7da3f2d 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -1,5 +1,7 @@
package scala
+import java.lang.reflect.{ AccessibleObject => jAccessibleObject }
+
package object reflect {
// in the new scheme of things ClassManifests are aliased to ClassTags
@@ -42,6 +44,18 @@ package object reflect {
def classTag[T](implicit ctag: ClassTag[T]) = ctag
+ /** Make a java reflection object accessible, if it is not already
+ * and it is possible to do so. If a SecurityException is thrown in the
+ * attempt, it is caught and discarded.
+ */
+ def ensureAccessible[T <: jAccessibleObject](m: T): T = {
+ if (!m.isAccessible) {
+ try m setAccessible true
+ catch { case _: SecurityException => } // does nothing
+ }
+ m
+ }
+
// anchor for the class tag materialization macro emitted during tag materialization in Implicits.scala
// implementation is hardwired into `scala.reflect.reify.Taggers`
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index 753dd0205e..ea1f392e2b 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -158,13 +158,7 @@ object ScalaRunTime {
// Java bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4071957
// More background at ticket #2318.
- def ensureAccessible(m: JMethod): JMethod = {
- if (!m.isAccessible) {
- try m setAccessible true
- catch { case _: SecurityException => () }
- }
- m
- }
+ def ensureAccessible(m: JMethod): JMethod = scala.reflect.ensureAccessible(m)
def checkInitialized[T <: AnyRef](x: T): T =
if (x == null) throw new UninitializedError else x
diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala
index 3f61062073..46e9621b31 100644
--- a/src/partest/scala/tools/partest/DirectTest.scala
+++ b/src/partest/scala/tools/partest/DirectTest.scala
@@ -6,7 +6,6 @@
package scala.tools.partest
import scala.tools.nsc._
-import io.Directory
import util.{BatchSourceFile, CommandLineParser}
import reporters.{Reporter, ConsoleReporter}
@@ -21,8 +20,8 @@ abstract class DirectTest extends App {
def show(): Unit
// the test file or dir, and output directory
- def testPath = io.File(sys.props("partest.test-path"))
- def testOutput = io.Directory(sys.props("partest.output"))
+ def testPath = SFile(sys.props("partest.test-path"))
+ def testOutput = Directory(sys.props("partest.output"))
// override to add additional settings with strings
def extraSettings: String = ""
diff --git a/src/partest/scala/tools/partest/IcodeTest.scala b/src/partest/scala/tools/partest/IcodeTest.scala
index f5333cc5f9..b12ec0de61 100644
--- a/src/partest/scala/tools/partest/IcodeTest.scala
+++ b/src/partest/scala/tools/partest/IcodeTest.scala
@@ -5,9 +5,7 @@
package scala.tools.partest
-import scala.tools.nsc._
-import nest.FileUtil._
-import io.Directory
+import scala.tools.partest.nest.FileUtil.compareContents
/** A trait for testing icode. All you need is this in a
* partest source file:
diff --git a/src/partest/scala/tools/partest/PartestDefaults.scala b/src/partest/scala/tools/partest/PartestDefaults.scala
index 5d98a8be81..16f1a6933f 100644
--- a/src/partest/scala/tools/partest/PartestDefaults.scala
+++ b/src/partest/scala/tools/partest/PartestDefaults.scala
@@ -1,13 +1,10 @@
package scala.tools
package partest
-import nsc.io.{ File, Path, Directory }
-import scala.tools.util.PathResolver
-import nsc.Properties.{ propOrElse, propOrNone, propOrEmpty }
-import java.lang.Runtime.getRuntime
+import scala.tools.nsc.Properties.{ propOrElse, propOrNone, propOrEmpty }
+import java.lang.Runtime.{ getRuntime => runtime }
object PartestDefaults {
- import nsc.Properties._
def testRootName = propOrNone("partest.root")
def srcDirName = propOrElse("partest.srcdir", "files")
@@ -23,7 +20,7 @@ object PartestDefaults {
def testBuild = propOrNone("partest.build")
def errorCount = propOrElse("partest.errors", "0").toInt
- def numThreads = propOrNone("partest.threads") map (_.toInt) getOrElse getRuntime.availableProcessors
+ def numThreads = propOrNone("partest.threads") map (_.toInt) getOrElse runtime.availableProcessors
def timeout = "1200000"
}
diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala
index 13207b16fd..b5b09a753a 100644
--- a/src/partest/scala/tools/partest/PartestTask.scala
+++ b/src/partest/scala/tools/partest/PartestTask.scala
@@ -10,14 +10,10 @@ package scala.tools
package partest
import scala.util.Properties.setProp
-import scala.tools.nsc.io.{ Directory, Path => SPath }
-import nsc.util.ClassPath
-import util.PathResolver
import scala.tools.ant.sabbus.CompilationPathProperty
-import java.io.File
import java.lang.reflect.Method
import org.apache.tools.ant.Task
-import org.apache.tools.ant.types.{Path, Reference, FileSet}
+import org.apache.tools.ant.types.{ Reference, FileSet}
import org.apache.tools.ant.types.Commandline.Argument
/** An Ant task to execute the Scala test suite (NSC).
@@ -26,92 +22,42 @@ import org.apache.tools.ant.types.Commandline.Argument
* - `srcdir`,
* - `classpath`,
* - `classpathref`,
- * - `showlog`,
- * - `showdiff`,
* - `erroronfailed`,
* - `javacmd`,
* - `javaccmd`,
* - `scalacopts`,
- * - `timeout`,
* - `debug`,
* - `junitreportdir`.
*
* It also takes the following parameters as nested elements:
* - `compilationpath`.
- * - `postests`,
- * - `negtests`,
- * - `runtests`,
- * - `jvmtests`,
- * - `residenttests`,
- * - `shootouttests`,
- * - `scalaptests`,
- * - `scalachecktests`,
- * - `specializedtests`,
- * - `instrumentedtests`,
- * - `presentationtests`,
- * - `scripttests`.
*
* @author Philippe Haller
*/
class PartestTask extends Task with CompilationPathProperty {
-
- def addConfiguredPosTests(input: FileSet) {
- posFiles = Some(input)
- }
-
- def addConfiguredNegTests(input: FileSet) {
- negFiles = Some(input)
- }
-
- def addConfiguredRunTests(input: FileSet) {
- runFiles = Some(input)
- }
-
- def addConfiguredJvmTests(input: FileSet) {
- jvmFiles = Some(input)
- }
-
- def addConfiguredResidentTests(input: FileSet) {
- residentFiles = Some(input)
- }
-
- def addConfiguredScalacheckTests(input: FileSet) {
- scalacheckFiles = Some(input)
- }
-
- def addConfiguredScriptTests(input: FileSet) {
- scriptFiles = Some(input)
- }
-
- def addConfiguredShootoutTests(input: FileSet) {
- shootoutFiles = Some(input)
- }
-
- def addConfiguredScalapTests(input: FileSet) {
- scalapFiles = Some(input)
- }
-
- def addConfiguredSpecializedTests(input: FileSet) {
- specializedFiles = Some(input)
- }
-
- def addConfiguredInstrumentedTests(input: FileSet) {
- instrumentedFiles = Some(input)
- }
-
- def addConfiguredPresentationTests(input: FileSet) {
- presentationFiles = Some(input)
- }
-
- def addConfiguredAntTests(input: FileSet) {
- antFiles = Some(input)
- }
-
+ type Path = org.apache.tools.ant.types.Path
+
+ private var kinds: List[String] = Nil
+ private var classpath: Option[Path] = None
+ private var debug = false
+ private var errorOnFailed: Boolean = true
+ private var jUnitReportDir: Option[File] = None
+ private var javaccmd: Option[File] = None
+ private var javacmd: Option[File] = Option(sys.props("java.home")) map (x => new File(x, "bin/java"))
+ private var scalacArgs: Option[Seq[Argument]] = None
+ private var srcDir: Option[String] = None
+ private var colors: Int = 0
def setSrcDir(input: String) {
srcDir = Some(input)
}
+ def setColors(input: String) {
+ try colors = input.toInt catch { case _: NumberFormatException => () }
+ if (colors > 0)
+ sys.props("partest.colors") = colors.toString
+ }
+
def setClasspath(input: Path) {
if (classpath.isEmpty)
classpath = Some(input)
@@ -127,15 +73,6 @@ class PartestTask extends Task with CompilationPathProperty {
def setClasspathref(input: Reference) {
createClasspath().setRefid(input)
}
-
- def setShowLog(input: Boolean) {
- showLog = input
- }
-
- def setShowDiff(input: Boolean) {
- showDiff = input
- }
-
def setErrorOnFailed(input: Boolean) {
errorOnFailed = input
}
@@ -144,6 +81,10 @@ class PartestTask extends Task with CompilationPathProperty {
javacmd = Some(input)
}
+ def setKinds(input: String) {
+ kinds = words(input)
+ }
+
def setJavacCmd(input: File) {
javaccmd = Some(input)
}
@@ -159,10 +100,6 @@ class PartestTask extends Task with CompilationPathProperty {
a
}
- def setTimeout(delay: String) {
- timeout = Some(delay)
- }
-
def setDebug(input: Boolean) {
debug = input
}
@@ -171,172 +108,35 @@ class PartestTask extends Task with CompilationPathProperty {
jUnitReportDir = Some(input)
}
- private var classpath: Option[Path] = None
- private var srcDir: Option[String] = None
- private var javacmd: Option[File] = None
- private var javaccmd: Option[File] = None
- private var showDiff: Boolean = false
- private var showLog: Boolean = false
- private var posFiles: Option[FileSet] = None
- private var negFiles: Option[FileSet] = None
- private var runFiles: Option[FileSet] = None
- private var jvmFiles: Option[FileSet] = None
- private var residentFiles: Option[FileSet] = None
- private var scalacheckFiles: Option[FileSet] = None
- private var scriptFiles: Option[FileSet] = None
- private var shootoutFiles: Option[FileSet] = None
- private var scalapFiles: Option[FileSet] = None
- private var specializedFiles: Option[FileSet] = None
- private var instrumentedFiles: Option[FileSet] = None
- private var presentationFiles: Option[FileSet] = None
- private var antFiles: Option[FileSet] = None
- private var errorOnFailed: Boolean = false
- private var scalacArgs: Option[Seq[Argument]] = None
- private var timeout: Option[String] = None
- private var jUnitReportDir: Option[File] = None
- private var debug = false
-
- def fileSetToDir(fs: FileSet) = Directory(fs getDir getProject)
- def fileSetToArray(fs: FileSet): Array[SPath] = {
- val root = fileSetToDir(fs)
- (fs getDirectoryScanner getProject).getIncludedFiles map (root / _)
- }
-
- private def getFiles(fileSet: Option[FileSet]): Array[File] = fileSet match {
- case None => Array()
- case Some(fs) => fileSetToArray(fs) filterNot (_ hasExtension "log") map (_.jfile)
- }
-
- private def getFilesAndDirs(fileSet: Option[FileSet]): Array[File] = fileSet match {
- case None => Array()
- case Some(fs) =>
- def shouldExclude(name: String) = (name endsWith ".obj") || (name startsWith ".")
- // println("----> " + fileSet)
-
- val fileTests = getFiles(Some(fs)) filterNot (x => shouldExclude(x.getName))
- val dirResult = getDirs(Some(fs)) filterNot (x => shouldExclude(x.getName))
- // println("dirs: " + dirResult.toList)
- // println("files: " + fileTests.toList)
-
- dirResult ++ fileTests
- }
-
- private def getDirs(fileSet: Option[FileSet]): Array[File] = fileSet match {
- case None => Array()
- case Some(fs) =>
- def shouldExclude(name: String) = (name endsWith ".obj") || (name startsWith ".")
-
- val dirTests: Iterator[SPath] = fileSetToDir(fs).dirs filterNot (x => shouldExclude(x.name))
- val dirResult = dirTests.toList.toArray map (_.jfile)
-
- dirResult
- }
-
-
- private def getPosFiles = getFilesAndDirs(posFiles)
- private def getNegFiles = getFilesAndDirs(negFiles)
- private def getRunFiles = getFilesAndDirs(runFiles)
- private def getJvmFiles = getFilesAndDirs(jvmFiles)
- private def getResidentFiles = getFiles(residentFiles)
- private def getScalacheckFiles = getFilesAndDirs(scalacheckFiles)
- private def getScriptFiles = getFiles(scriptFiles)
- private def getShootoutFiles = getFiles(shootoutFiles)
- private def getScalapFiles = getFiles(scalapFiles)
- private def getSpecializedFiles = getFiles(specializedFiles)
- private def getInstrumentedFiles = getFilesAndDirs(instrumentedFiles)
- private def getPresentationFiles = getDirs(presentationFiles)
- private def getAntFiles = getFiles(antFiles)
-
override def execute() {
- val opts = getProject().getProperties() get "env.PARTEST_OPTS"
- if (opts != null && opts.toString != "")
- opts.toString.split(" ") foreach { propDef =>
- log("setting system property " + propDef)
- val kv = propDef split "="
- val key = kv(0) substring 2
- val value = kv(1)
- setProp(key, value)
- }
-
- if (isPartestDebug || debug) {
- setProp("partest.debug", "true")
- nest.NestUI._verbose = true
+ if (debug || sys.props.contains("partest.debug")) {
+ nest.NestUI.setDebug()
}
srcDir foreach (x => setProp("partest.srcdir", x))
val classpath = this.compilationPath getOrElse sys.error("Mandatory attribute 'compilationPath' is not set.")
-
- val scalaLibrary = {
- (classpath.list map { fs => new File(fs) }) find { f =>
- f.getName match {
- case "scala-library.jar" => true
- case "library" if (f.getParentFile.getName == "classes") => true
- case _ => false
- }
- }
- } getOrElse sys.error("Provided classpath does not contain a Scala library.")
-
- val scalaReflect = {
- (classpath.list map { fs => new File(fs) }) find { f =>
- f.getName match {
- case "scala-reflect.jar" => true
- case "reflect" if (f.getParentFile.getName == "classes") => true
- case _ => false
- }
- }
- } getOrElse sys.error("Provided classpath does not contain a Scala reflection library.")
-
- val scalaCompiler = {
- (classpath.list map { fs => new File(fs) }) find { f =>
- f.getName match {
- case "scala-compiler.jar" => true
- case "compiler" if (f.getParentFile.getName == "classes") => true
- case _ => false
- }
- }
- } getOrElse sys.error("Provided classpath does not contain a Scala compiler.")
-
- val scalaPartest = {
- (classpath.list map { fs => new File(fs) }) find { f =>
- f.getName match {
- case "scala-partest.jar" => true
- case "partest" if (f.getParentFile.getName == "classes") => true
- case _ => false
- }
- }
- } getOrElse sys.error("Provided classpath does not contain a Scala partest.")
-
- val scalaActors = {
- (classpath.list map { fs => new File(fs) }) find { f =>
- f.getName match {
- case "scala-actors.jar" => true
- case "actors" if (f.getParentFile.getName == "classes") => true
- case _ => false
- }
- }
- } getOrElse sys.error("Provided classpath does not contain a Scala actors.")
+ val cpfiles = classpath.list map { fs => new File(fs) } toList
+ def findCp(name: String) = cpfiles find (f =>
+ (f.getName == s"scala-$name.jar")
+ || (f.absolutePathSegments endsWith Seq("classes", name))
+ ) getOrElse sys.error(s"Provided classpath does not contain a Scala $name element.")
+
+ val scalaLibrary = findCp("library")
+ val scalaReflect = findCp("reflect")
+ val scalaCompiler = findCp("compiler")
+ val scalaPartest = findCp("partest")
+ val scalaActors = findCp("actors")
def scalacArgsFlat: Option[Seq[String]] = scalacArgs map (_ flatMap { a =>
val parts = a.getParts
- if(parts eq null) Seq[String]() else parts.toSeq
+ if (parts eq null) Nil else parts.toSeq
})
val antRunner = new scala.tools.partest.nest.AntRunner
val antFileManager = antRunner.fileManager
- // this is a workaround for https://issues.scala-lang.org/browse/SI-5433
- // when that bug is fixed, this paragraph of code can be safely removed
- // we hack into the classloader that will become parent classloader for scalac
- // this way we ensure that reflective macro lookup will pick correct Code.lift
- val loader = getClass.getClassLoader.asInstanceOf[org.apache.tools.ant.AntClassLoader]
- val path = new org.apache.tools.ant.types.Path(getProject())
- val newClassPath = ClassPath.join(nest.PathSettings.srcCodeLib.toString, loader.getClasspath)
- path.setPath(newClassPath)
- loader.setClassPath(path)
-
- antFileManager.showDiff = showDiff
- antFileManager.showLog = showLog
+ // antFileManager.failed = runFailed
antFileManager.CLASSPATH = ClassPath.join(classpath.list: _*)
antFileManager.LATEST_LIB = scalaLibrary.getAbsolutePath
antFileManager.LATEST_REFLECT = scalaReflect.getAbsolutePath
@@ -347,53 +147,35 @@ class PartestTask extends Task with CompilationPathProperty {
javacmd foreach (x => antFileManager.JAVACMD = x.getAbsolutePath)
javaccmd foreach (x => antFileManager.JAVAC_CMD = x.getAbsolutePath)
scalacArgsFlat foreach (antFileManager.SCALAC_OPTS ++= _)
- timeout foreach (antFileManager.timeout = _)
-
- type TFSet = (Array[File], String, String)
- val testFileSets = List(
- (getPosFiles, "pos", "Compiling files that are expected to build"),
- (getNegFiles, "neg", "Compiling files that are expected to fail"),
- (getRunFiles, "run", "Compiling and running files"),
- (getJvmFiles, "jvm", "Compiling and running files"),
- (getResidentFiles, "res", "Running resident compiler scenarii"),
- (getScalacheckFiles, "scalacheck", "Running scalacheck tests"),
- (getScriptFiles, "script", "Running script files"),
- (getShootoutFiles, "shootout", "Running shootout tests"),
- (getScalapFiles, "scalap", "Running scalap tests"),
- (getSpecializedFiles, "specialized", "Running specialized files"),
- (getInstrumentedFiles, "instrumented", "Running instrumented files"),
- (getPresentationFiles, "presentation", "Running presentation compiler test files"),
- (getAntFiles, "ant", "Running ant task tests")
- )
-
- def runSet(set: TFSet): (Int, Int, Iterable[String]) = {
- val (files, name, msg) = set
+
+ def runSet(kind: String, files: Array[File]): (Int, Int, List[String]) = {
if (files.isEmpty) (0, 0, List())
else {
- log(msg)
- val results: Iterable[(String, TestState)] = antRunner.reflectiveRunTestsForFiles(files, name)
- val (succs, fails) = resultsToStatistics(results)
+ log(s"Running ${files.length} tests in '$kind' at $now")
+ // log(s"Tests: ${files.toList}")
+ val results = antRunner.reflectiveRunTestsForFiles(files, kind)
+ val (passed, failed) = results partition (_.isOk)
+ val numPassed = passed.size
+ val numFailed = failed.size
+ def failedMessages = failed map (_.longStatus)
- val failed: Iterable[String] = results collect {
- case (path, TestState.Fail) => path + " [FAILED]"
- case (path, TestState.Timeout) => path + " [TIMOUT]"
- }
+ log(s"Completed '$kind' at $now")
// create JUnit Report xml files if directory was specified
jUnitReportDir foreach { d =>
d.mkdir
- val report = testReport(name, results, succs, fails)
- scala.xml.XML.save(d.getAbsolutePath+"/"+name+".xml", report)
+ val report = testReport(kind, results, numPassed, numFailed)
+ scala.xml.XML.save(d.getAbsolutePath+"/"+kind+".xml", report)
}
- (succs, fails, failed)
+ (numPassed, numFailed, failedMessages)
}
}
- val _results = testFileSets map runSet
- val allSuccesses = _results map (_._1) sum
- val allFailures = _results map (_._2) sum
+ val _results = kinds map (k => runSet(k, TestKinds testsFor k map (_.jfile) toArray))
+ val allSuccesses = _results map (_._1) sum
+ val allFailures = _results map (_._2) sum
val allFailedPaths = _results flatMap (_._3)
def f = if (errorOnFailed && allFailures > 0) (sys error _) else log(_: String)
@@ -408,20 +190,17 @@ class PartestTask extends Task with CompilationPathProperty {
f(msg)
}
- private def oneResult(res: (String, TestState)) =
- <testcase name={res._1}>{
- res._2 match {
- case TestState.Ok => scala.xml.NodeSeq.Empty
- case TestState.Fail => <failure message="Test failed"/>
- case TestState.Timeout => <failure message="Test timed out"/>
- }
+ private def oneResult(res: TestState) =
+ <testcase name={res.testIdent}>{
+ if (res.isOk) scala.xml.NodeSeq.Empty
+ else <failure message="Test failed"/>
}</testcase>
- private def testReport(kind: String, results: Iterable[(String, TestState)], succs: Int, fails: Int) =
+ private def testReport(kind: String, results: Iterable[TestState], succs: Int, fails: Int) =
<testsuite name={kind} tests={(succs + fails).toString} failures={fails.toString}>
<properties/>
{
- results.map(oneResult(_))
+ results map oneResult
}
</testsuite>
}
diff --git a/src/partest/scala/tools/partest/TestKinds.scala b/src/partest/scala/tools/partest/TestKinds.scala
new file mode 100644
index 0000000000..ec682690ca
--- /dev/null
+++ b/src/partest/scala/tools/partest/TestKinds.scala
@@ -0,0 +1,67 @@
+package scala.tools
+package partest
+
+import nest.PathSettings.srcDir
+
+object TestKinds {
+ val standardKinds = "pos neg run jvm res buildmanager scalacheck scalap specialized instrumented presentation ant" split "\\s+" toList
+ val standardArgs = standardKinds map ("--" + _)
+
+ def denotesTestFile(p: Path) = p.isFile && p.hasExtension("scala", "res", "xml")
+ def denotesTestDir(p: Path) = kindOf(p) match {
+ case "res" => false
+ case _ => p.isDirectory && p.extension == ""
+ }
+ def denotesTestPath(p: Path) = denotesTestDir(p) || denotesTestFile(p)
+
+ // TODO
+ def isTestForPartest(p: Path) = (
+ (p.name == "intentional-failure.scala")
+ || (p.path contains "test-for-partest")
+ )
+
+ def kindOf(p: Path) = {
+ p.toAbsolute.segments takeRight 2 head
+
+ // (srcDir relativize p.toCanonical).segments match {
+ // case (".." :: "scaladoc" :: xs) => xs.head
+ // case xs => xs.head
+ // }
+ }
+ def logOf(p: Path) = {
+ p.parent / s"${p.stripExtension}-${kindOf(p)}.log"
+ // p.parent / s"${p.stripExtension}.log"
+ }
+
+ // true if a test path matches the --grep expression.
+ private def pathMatchesExpr(path: Path, expr: String) = {
+ // Matches the expression if any source file contains the expr,
+ // or if the checkfile contains it, or if the filename contains
+ // it (the last is case-insensitive.)
+ def matches(p: Path) = (
+ (p.path.toLowerCase contains expr.toLowerCase)
+ || (p.fileContents contains expr)
+ )
+ def candidates = {
+ (path changeExtension "check") +: {
+ if (path.isFile) List(path)
+ else path.toDirectory.deepList() filter (_.isJavaOrScala) toList
+ }
+ }
+
+ (candidates exists matches)
+ }
+
+ def groupedTests(paths: List[Path]): List[(String, List[Path])] =
+ (paths.distinct groupBy kindOf).toList sortBy (standardKinds indexOf _._1)
+
+ /** Includes tests for testing partest. */
+ private def allTestsForKind(kind: String): List[Path] =
+ (srcDir / kind toDirectory).list.toList filter denotesTestPath
+
+ def testsForPartest: List[Path] = standardKinds flatMap allTestsForKind filter isTestForPartest
+ def testsFor(kind: String): List[Path] = allTestsForKind(kind) filterNot isTestForPartest
+ def grepFor(expr: String): List[Path] = standardTests filter (t => pathMatchesExpr(t, expr))
+ def standardTests: List[Path] = standardKinds flatMap testsFor
+ def failedTests: List[Path] = standardTests filter (p => logOf(p).isFile)
+}
diff --git a/src/partest/scala/tools/partest/TestState.scala b/src/partest/scala/tools/partest/TestState.scala
new file mode 100644
index 0000000000..ce8e72f616
--- /dev/null
+++ b/src/partest/scala/tools/partest/TestState.scala
@@ -0,0 +1,54 @@
+package scala.tools.partest
+
+import scala.tools.nsc.FatalError
+import scala.tools.nsc.util.stackTraceString
+
+sealed abstract class TestState {
+ def testFile: File
+ def what: String
+ def reason: String
+ def transcript: List[String]
+
+ def isOk = false
+ def isSkipped = false
+ def testIdent = testFile.testIdent
+ def transcriptString = transcript.mkString("\n")
+
+ def identAndReason = testIdent + reasonString
+ def status = s"$what - $identAndReason"
+ def longStatus = status + transcriptString
+ def reasonString = if (reason == "") "" else s" [$reason]"
+
+ override def toString = status
+}
+
+object TestState {
+ case class Uninitialized(testFile: File) extends TestState {
+ def what = "uninitialized"
+ def reason = what
+ def transcript = Nil
+ }
+ case class Pass(testFile: File) extends TestState {
+ final override def isOk = true
+ def what = "pass"
+ def transcript: List[String] = Nil
+ def reason = ""
+ }
+ case class Skip(testFile: File, reason: String) extends TestState {
+ override def isOk = true
+ final override def isSkipped = true
+ def transcript: List[String] = Nil
+ def what = "skip"
+ }
+ case class Fail(testFile: File, reason: String, transcript: List[String]) extends TestState {
+ def what = "fail"
+ }
+ case class Crash(testFile: File, caught: Throwable, transcript: List[String]) extends TestState {
+ def what = "crash"
+ def reason = s"caught $caught_s - ${caught.getMessage}"
+
+ private def caught_s = (caught.getClass.getName split '.').last
+ private def stack_s = stackTraceString(caught)
+ override def transcriptString = nljoin(super.transcriptString, caught_s)
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/AntRunner.scala b/src/partest/scala/tools/partest/nest/AntRunner.scala
index 93045b8c1d..1d3b79171b 100644
--- a/src/partest/scala/tools/partest/nest/AntRunner.scala
+++ b/src/partest/scala/tools/partest/nest/AntRunner.scala
@@ -10,24 +10,21 @@
package scala.tools.partest
package nest
-import java.io.File
-import scala.tools.nsc.io.{ Directory }
-
class AntRunner extends DirectRunner {
val fileManager = new FileManager {
- var JAVACMD: String = "java"
- var JAVAC_CMD: String = "javac"
- var CLASSPATH: String = _
- var LATEST_LIB: String = _
- var LATEST_REFLECT: String = _
- var LATEST_COMP: String = _
- var LATEST_PARTEST: String = _
- var LATEST_ACTORS: String = _
- val testRootPath: String = "test"
- val testRootDir: Directory = Directory(testRootPath)
+ var JAVACMD: String = "java"
+ var JAVAC_CMD: String = "javac"
+ var CLASSPATH: String = _
+ var LATEST_LIB: String = _
+ var LATEST_REFLECT: String = _
+ var LATEST_COMP: String = _
+ var LATEST_PARTEST: String = _
+ var LATEST_ACTORS: String = _
+ val testRootPath: String = "test"
+ val testRootDir: Directory = Directory(testRootPath)
}
- def reflectiveRunTestsForFiles(kindFiles: Array[File], kind: String) =
+ def reflectiveRunTestsForFiles(kindFiles: Array[File], kind: String): List[TestState] =
runTestsForFiles(kindFiles.toList, kind)
}
diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala
deleted file mode 100644
index a8694cc0d6..0000000000
--- a/src/partest/scala/tools/partest/nest/CompileManager.scala
+++ /dev/null
@@ -1,182 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2013 LAMP/EPFL
- * @author Philipp Haller
- */
-
-// $Id$
-
-package scala.tools.partest
-package nest
-
-import scala.tools.nsc.{ Global, Settings, CompilerCommand, FatalError, io }
-import scala.reflect.io.{ Directory, File => SFile, FileOperationException }
-import scala.tools.nsc.reporters.{ Reporter, ConsoleReporter }
-import scala.tools.nsc.util.{ ClassPath, FakePos }
-import scala.tools.nsc.Properties.{ setProp, propOrEmpty }
-import scala.tools.util.PathResolver
-import io.Path
-import java.io.{ File, BufferedReader, PrintWriter, FileReader, Writer, FileWriter, StringWriter }
-import File.pathSeparator
-
-sealed abstract class CompilationOutcome {
- def merge(other: CompilationOutcome): CompilationOutcome
- def isPositive = this eq CompileSuccess
- def isNegative = this eq CompileFailed
-}
-case object CompileSuccess extends CompilationOutcome {
- def merge(other: CompilationOutcome) = other
-}
-case object CompileFailed extends CompilationOutcome {
- def merge(other: CompilationOutcome) = if (other eq CompileSuccess) this else other
-}
-case object CompilerCrashed extends CompilationOutcome {
- def merge(other: CompilationOutcome) = this
-}
-
-class ExtConsoleReporter(settings: Settings, val writer: PrintWriter) extends ConsoleReporter(settings, Console.in, writer) {
- shortname = true
-}
-
-class TestSettings(cp: String, error: String => Unit) extends Settings(error) {
- def this(cp: String) = this(cp, _ => ())
-
- nowarnings.value = false
- encoding.value = "UTF-8"
- classpath.value = cp
-}
-
-abstract class SimpleCompiler {
- def compile(out: Option[File], files: List[File], kind: String, log: File): CompilationOutcome
-}
-
-class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
- def newGlobal(settings: Settings, reporter: Reporter): Global =
- Global(settings, reporter)
-
- def newGlobal(settings: Settings, logWriter: FileWriter): Global =
- newGlobal(settings, new ExtConsoleReporter(settings, new PrintWriter(logWriter)))
-
- def newSettings(): TestSettings = new TestSettings(fileManager.LATEST_LIB)
- def newSettings(outdir: String): TestSettings = {
- val cp = ClassPath.join(fileManager.LATEST_LIB, outdir)
- val s = new TestSettings(cp)
- s.outdir.value = outdir
-
- s
- }
-
- implicit class Copier(f: SFile) {
- // But what if f is bigger than CHUNK?!
- def copyTo(dest: Path) {
- dest.toFile writeAll f.slurp
- }
- }
-
- // plugin path can be relative to test root, or cwd is out
- private def updatePluginPath(options: String, out: Option[File], srcdir: Directory): String = {
- val dir = fileManager.testRootDir
- def pathOrCwd(p: String) =
- if (p == "." && out.isDefined) {
- val plugxml = "scalac-plugin.xml"
- val pout = Path(out.get)
- val pd = (srcdir / plugxml).toFile
- if (pd.exists) pd copyTo (pout / plugxml)
- pout
- } else Path(p)
- def absolutize(path: String) = pathOrCwd(path) match {
- case x if x.isAbsolute => x.path
- case x => (dir / x).toAbsolute.path
- }
-
- val (opt1, opt2) = (options split "\\s").toList partition (_ startsWith "-Xplugin:")
- val plugins = opt1 map (_ stripPrefix "-Xplugin:") flatMap (_ split pathSeparator) map absolutize
- val pluginOption = if (opt1.isEmpty) Nil else List("-Xplugin:" + (plugins mkString pathSeparator))
-
- (opt2 ::: pluginOption) mkString " "
- }
-
- def compile(out: Option[File], files: List[File], kind: String, log: File): CompilationOutcome = {
- val testSettings = out match {
- case Some(f) => newSettings(f.getAbsolutePath)
- case _ => newSettings()
- }
- val logWriter = new FileWriter(log)
-
- // this api has no notion of srcdir, so fake it
- val fstFile = SFile(files(0))
- val srcdir = fstFile.parent
-
- // check whether there is a ".flags" file
- def convertFlags(f: SFile) = updatePluginPath(f.slurp(), out, srcdir)
- val logFile = basename(log.getName)
- val flagsFileName = "%s.flags" format (logFile.substring(0, logFile.lastIndexOf("-")))
- val argString = (SFile(log).parent / flagsFileName) ifFile (convertFlags) getOrElse ""
-
- // slurp local flags (e.g., "A_1.flags")
- def isInGroup(num: Int) = fstFile.stripExtension endsWith ("_" + num)
- val inGroup = (1 to 9) flatMap (group => if (isInGroup(group)) List(group) else List())
- val localFlagsList = if (inGroup.nonEmpty) {
- val localArgString = (srcdir / (fstFile.stripExtension + ".flags")) ifFile (convertFlags) getOrElse ""
- localArgString.split(' ').toList.filter(_.length > 0)
- } else List()
-
- val allOpts = fileManager.SCALAC_OPTS.toList ::: argString.split(' ').toList.filter(_.length > 0) ::: localFlagsList
- val args = allOpts.toList
-
- NestUI.verbose("scalac options: "+allOpts)
-
- val command = new CompilerCommand(args, testSettings)
- val global = newGlobal(command.settings, logWriter)
- val testRep: ExtConsoleReporter = global.reporter.asInstanceOf[ExtConsoleReporter]
-
- val testFileFn: (File, FileManager) => TestFile = kind match {
- case "pos" => PosTestFile.apply
- case "neg" => NegTestFile.apply
- case "run" => RunTestFile.apply
- case "jvm" => JvmTestFile.apply
- case "shootout" => ShootoutTestFile.apply
- case "scalap" => ScalapTestFile.apply
- case "scalacheck" => ScalaCheckTestFile.apply
- case "specialized" => SpecializedTestFile.apply
- case "instrumented" => InstrumentedTestFile.apply
- case "presentation" => PresentationTestFile.apply
- case "ant" => AntTestFile.apply
- }
- val test: TestFile = testFileFn(files.head, fileManager)
- if (!test.defineSettings(command.settings, out.isEmpty)) {
- testRep.error(FakePos("partest"), test.flags match {
- case Some(flags) => "bad flags: " + flags
- case _ => "bad settings: " + command.settings
- })
- }
-
- val toCompile = files map (_.getPath)
-
- try {
- NestUI.verbose("compiling "+toCompile)
- NestUI.verbose("with classpath: "+global.classPath.toString)
- NestUI.verbose("and java classpath: "+ propOrEmpty("java.class.path"))
- try {
- if (command.shouldStopWithInfo) logWriter append (command getInfoMessage global)
- else new global.Run compile toCompile
- } catch {
- case FatalError(msg) =>
- testRep.error(null, "fatal error: " + msg)
- return CompilerCrashed
- }
-
- testRep.printSummary()
- testRep.writer.close()
- }
- finally logWriter.close()
-
- if (testRep.hasErrors || command.shouldStopWithInfo) CompileFailed
- else CompileSuccess
- }
-}
-
-class CompileManager(val fileManager: FileManager) {
- private def newCompiler = new DirectCompiler(fileManager)
- def attemptCompile(outdir: Option[File], sources: List[File], kind: String, log: File): CompilationOutcome =
- newCompiler.compile(outdir, sources, kind, log)
-}
diff --git a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
index 0ec3f60bf5..b436675d3a 100644
--- a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
+++ b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
@@ -3,20 +3,15 @@
* @author Philipp Haller
*/
-// $Id$
+
package scala.tools.partest
package nest
-import java.io.{ File, FilenameFilter, IOException, StringWriter }
+import java.io.{ FilenameFilter, IOException }
import java.net.URI
import scala.util.Properties.{ propOrElse, scalaCmd, scalacCmd }
-import scala.tools.util.PathResolver
import scala.tools.nsc.{ io, util }
-import util.{ ClassPath }
-import io.{ Path, Directory }
-import File.pathSeparator
-import ClassPath.{ join }
import PathResolver.{ Environment, Defaults }
class ConsoleFileManager extends FileManager {
@@ -55,7 +50,7 @@ class ConsoleFileManager extends FileManager {
var JAVAC_CMD = PartestDefaults.javacCmd
- NestUI.verbose("CLASSPATH: "+CLASSPATH)
+ vlog("CLASSPATH: "+CLASSPATH)
if (!srcDir.isDirectory) {
NestUI.failure("Source directory \"" + srcDir.path + "\" not found")
@@ -70,14 +65,14 @@ class ConsoleFileManager extends FileManager {
}
def findLatest() {
- NestUI.verbose("test parent: "+testParent)
+ vlog("test parent: "+testParent)
- def prefixFileWith(parent: File, relPath: String) = (io.File(parent) / relPath).toCanonical
+ def prefixFileWith(parent: File, relPath: String) = (SFile(parent) / relPath).toCanonical
def prefixFile(relPath: String) = (testParent / relPath).toCanonical
if (!testClasses.isEmpty) {
testClassesDir = Path(testClasses.get).toCanonical.toDirectory
- NestUI.verbose("Running with classes in "+testClassesDir)
+ vlog("Running with classes in "+testClassesDir)
latestLibFile = testClassesDir / "library"
latestActorsFile = testClassesDir / "library" / "actors"
@@ -87,7 +82,7 @@ class ConsoleFileManager extends FileManager {
}
else if (testBuild.isDefined) {
val dir = Path(testBuild.get)
- NestUI.verbose("Running on "+dir)
+ vlog("Running on "+dir)
latestLibFile = dir / "lib/scala-library.jar"
latestActorsFile = dir / "lib/scala-actors.jar"
latestReflectFile = dir / "lib/scala-reflect.jar"
@@ -96,7 +91,7 @@ class ConsoleFileManager extends FileManager {
}
else {
def setupQuick() {
- NestUI.verbose("Running build/quick")
+ vlog("Running build/quick")
latestLibFile = prefixFile("build/quick/classes/library")
latestActorsFile = prefixFile("build/quick/classes/library/actors")
latestReflectFile = prefixFile("build/quick/classes/reflect")
@@ -105,7 +100,7 @@ class ConsoleFileManager extends FileManager {
}
def setupInst() {
- NestUI.verbose("Running dist (installed)")
+ vlog("Running dist (installed)")
val p = testParent.getParentFile
latestLibFile = prefixFileWith(p, "lib/scala-library.jar")
latestActorsFile = prefixFileWith(p, "lib/scala-actors.jar")
@@ -115,7 +110,7 @@ class ConsoleFileManager extends FileManager {
}
def setupDist() {
- NestUI.verbose("Running dists/latest")
+ vlog("Running dists/latest")
latestLibFile = prefixFile("dists/latest/lib/scala-library.jar")
latestActorsFile = prefixFile("dists/latest/lib/scala-actors.jar")
latestReflectFile = prefixFile("dists/latest/lib/scala-reflect.jar")
@@ -124,7 +119,7 @@ class ConsoleFileManager extends FileManager {
}
def setupPack() {
- NestUI.verbose("Running build/pack")
+ vlog("Running build/pack")
latestLibFile = prefixFile("build/pack/lib/scala-library.jar")
latestActorsFile = prefixFile("build/pack/lib/scala-actors.jar")
latestReflectFile = prefixFile("build/pack/lib/scala-reflect.jar")
@@ -170,11 +165,13 @@ class ConsoleFileManager extends FileManager {
var latestReflectFile: File = _
var latestCompFile: File = _
var latestPartestFile: File = _
- def latestScalapFile: File = (latestLibFile.parent / "scalap.jar").jfile
+ //def latestScalapFile: File = (latestLibFile.parent / "scalap.jar").jfile
+ //def latestScalapFile: File = new File(latestLibFile.getParentFile, "scalap.jar")
var testClassesDir: Directory = _
// initialize above fields
findLatest()
+ /*
def getFiles(kind: String, cond: Path => Boolean): List[File] = {
def ignoreDir(p: Path) = List("svn", "obj") exists (p hasExtension _)
@@ -187,4 +184,6 @@ class ConsoleFileManager extends FileManager {
( if (failed) files filter (x => logFileExists(x, kind)) else files ) map (_.jfile)
}
+ */
+ var latestFjbgFile: File = _
}
diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
index fd4d52f603..ddd42f5601 100644
--- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
+++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
@@ -3,83 +3,110 @@
* @author Philipp Haller
*/
-// $Id$
-
-package scala.tools.partest
+package scala.tools
+package partest
package nest
-import java.io.{File, PrintStream, FileOutputStream, BufferedReader,
- InputStreamReader, StringWriter, PrintWriter}
import utils.Properties._
import scala.tools.nsc.Properties.{ versionMsg, setProp }
import scala.tools.nsc.util.CommandLineParser
-import scala.tools.nsc.io
-import io.{ Path }
import scala.collection.{ mutable, immutable }
+import PathSettings.srcDir
+import TestKinds._
class ConsoleRunner extends DirectRunner {
- import PathSettings.{ srcDir, testRoot }
-
- case class TestSet(kind: String, filter: Path => Boolean, msg: String)
- private def stdFilter(p: Path) = p.isDirectory || (p hasExtension "scala")
- private def antFilter(p: Path) = p.isFile && (p endsWith "build.xml")
-
- val testSets = {
- List(
- TestSet("pos", stdFilter, "Testing compiler (on files whose compilation should succeed)"),
- TestSet("neg", stdFilter, "Testing compiler (on files whose compilation should fail)"),
- TestSet("run", stdFilter, "Testing interpreter and backend"),
- TestSet("jvm", stdFilter, "Testing JVM backend"),
- TestSet("res", x => x.isFile && (x hasExtension "res"), "Testing resident compiler"),
- TestSet("shootout", stdFilter, "Testing shootout tests"),
- TestSet("script", stdFilter, "Testing script tests"),
- TestSet("scalacheck", stdFilter, "Testing ScalaCheck tests"),
- TestSet("scalap", _.isDirectory, "Run scalap decompiler tests"),
- TestSet("specialized", stdFilter, "Testing specialized tests"),
- TestSet("instrumented", stdFilter, "Testing instrumented tests"),
- TestSet("presentation", _.isDirectory, "Testing presentation compiler tests."),
- TestSet("ant", antFilter, "Run Ant task tests.")
- )
- }
+ import NestUI._
+ import NestUI.color._
+
+ // So we can ctrl-C a test run and still hear all
+ // the buffered failure info.
+ scala.sys addShutdownHook issueSummaryReport()
var fileManager: ConsoleFileManager = _
- private var testFiles: List[File] = List()
- private val errors = PartestDefaults.errorCount
- private val testSetKinds = testSets map (_.kind)
- private val testSetArgs = testSets map ("--" + _.kind)
- private val testSetArgMap = testSetArgs zip testSets toMap
+ private var totalTests = 0
+ private val passedTests = mutable.ListBuffer[TestState]()
+ private val failedTests = mutable.ListBuffer[TestState]()
+
+ def comment(s: String) = echo(magenta("# " + s))
+ def levyJudgment() = {
+ if (totalTests == 0) echoMixed("No tests to run.")
+ else if (elapsedMillis == 0) echoMixed("Test Run ABORTED")
+ else if (isSuccess) echoPassed("Test Run PASSED")
+ else echoFailed("Test Run FAILED")
+ }
+
+ def passFailString(passed: Int, failed: Int, skipped: Int): String = {
+ val total = passed + failed + skipped
+ val isSuccess = failed == 0
+ def p0 = s"$passed/$total"
+ def p = ( if (isSuccess) bold(green(p0)) else p0 ) + " passed"
+ def f = if (failed == 0) "" else bold(red("" + failed)) + " failed"
+ def s = if (skipped == 0) "" else bold(yellow("" + skipped)) + " skipped"
+
+ oempty(p, f, s) mkString ", "
+ }
+
+ private var summarizing = false
+ private var elapsedMillis = 0L
+ private var expectedFailures = 0
+ private def isSuccess = failedTests.size == expectedFailures
+
+ def issueSummaryReport() {
+ // Don't run twice
+ if (!summarizing) {
+ summarizing = true
+
+ val passed0 = passedTests.toList
+ val failed0 = failedTests.toList
+ val passed = passed0.size
+ val failed = failed0.size
+ val skipped = totalTests - (passed + failed)
+ val passFail = passFailString(passed, failed, skipped)
+ val elapsed = if (elapsedMillis > 0) " (elapsed time: " + elapsedString(elapsedMillis) + ")" else ""
+ val message = passFail + elapsed
+
+ if (failed0.nonEmpty) {
+ echo(bold(cyan("##### Transcripts from failed tests #####\n")))
+ failed0 foreach { state =>
+ comment("partest " + state.testFile)
+ echo(state.transcriptString + "\n")
+ }
+ }
- private def printVersion() { NestUI outline (versionMsg + "\n") }
+ echo(message)
+ levyJudgment()
+ }
+ }
private val unaryArgs = List(
- "--pack", "--all", "--verbose", "--show-diff", "--show-log",
+ "--pack", "--all",
+ "--terse", "--verbose", "--show-diff", "--show-log", "--self-test",
"--failed", "--update-check", "--version", "--ansi", "--debug", "--help"
- ) ::: testSetArgs
+ ) ::: standardArgs
private val binaryArgs = List(
"--grep", "--srcpath", "--buildpath", "--classpath"
)
- // true if a test path matches the --grep expression.
- private def pathMatchesExpr(path: Path, expr: String) = {
- def pred(p: Path) = file2String(p.toFile) contains expr
- def greppable(f: Path) = f.isFile && (f hasExtension ("scala", "java"))
- def any(d: Path) = d.toDirectory.deepList() exists (f => greppable(f) && pred(f))
-
- (path.isFile && pred(path)) ||
- (path.isDirectory && any(path)) ||
- (pred(path changeExtension "check"))
- }
-
def main(argstr: String) {
val parsed = CommandLineParser(argstr) withUnaryArgs unaryArgs withBinaryArgs binaryArgs
- val args = onlyValidTestPaths(parsed.residualArgs)
- /* Early return on no args, version, or invalid args */
- if (argstr == "") return NestUI.usage()
- if (parsed isSet "--version") return printVersion
- if (parsed isSet "--help") return NestUI.usage()
+ if (parsed isSet "--debug") NestUI.setDebug()
+ if (parsed isSet "--verbose") NestUI.setVerbose()
+ if (parsed isSet "--terse") NestUI.setTerse()
+
+ // Early return on no args, version, or invalid args
+ if (parsed isSet "--version") return echo(versionMsg)
+ if ((argstr == "") || (parsed isSet "--help")) return NestUI.usage()
+
+ val (individualTests, invalid) = parsed.residualArgs map (p => Path(p)) partition denotesTestPath
+ if (invalid.nonEmpty) {
+ if (isPartestVerbose)
+ invalid foreach (p => echoWarning(s"Discarding invalid test path " + p))
+ else if (!isPartestTerse)
+ echoWarning(s"Discarding ${invalid.size} invalid test paths")
+ }
parsed get "--srcpath" foreach (x => setProp("partest.srcdir", x))
@@ -89,144 +116,102 @@ class ConsoleRunner extends DirectRunner {
else if (parsed isSet "--pack") new ConsoleFileManager("build/pack")
else new ConsoleFileManager // auto detection, see ConsoleFileManager.findLatest
- NestUI._verbose = parsed isSet "--verbose"
- fileManager.showDiff = true
- // parsed isSet "--show-diff"
fileManager.updateCheck = parsed isSet "--update-check"
- fileManager.showLog = parsed isSet "--show-log"
fileManager.failed = parsed isSet "--failed"
- if (parsed isSet "--ansi") NestUI initialize NestUI.MANY
- if (parsed isSet "--timeout") fileManager.timeout = parsed("--timeout")
- if (parsed isSet "--debug") setProp("partest.debug", "true")
+ val partestTests = (
+ if (parsed isSet "--self-test") TestKinds.testsForPartest
+ else Nil
+ )
- def addTestFile(file: File) = {
- if (!file.exists)
- NestUI.failure("Test file '%s' not found, skipping.\n" format file)
- else {
- NestUI.verbose("adding test file " + file)
- testFiles +:= file
- }
- }
+ val grepExpr = parsed get "--grep" getOrElse ""
// If --grep is given we suck in every file it matches.
-
- val grepOption = parsed get "--grep"
- val grepPaths = grepOption.toList flatMap { expr =>
- val subjectDirs = testSetKinds map (srcDir / _ toDirectory)
- val testPaths = subjectDirs flatMap (_.list filter stdFilter)
- val paths = testPaths filter (p => pathMatchesExpr(p, expr))
-
+ var grepMessage = ""
+ val greppedTests = if (grepExpr == "") Nil else {
+ val paths = grepFor(grepExpr)
if (paths.isEmpty)
- NestUI.failure("--grep string '%s' matched no tests." format expr)
+ echoWarning(s"grep string '$grepExpr' matched no tests.\n")
- paths map (_.jfile)
+ paths.sortBy(_.toString)
}
- val grepMessage = grepOption map (x => "Argument '%s' matched %d test(s)".format(x, grepPaths.size)) getOrElse ""
-
- grepPaths foreach addTestFile
- args foreach (x => addTestFile(new File(x)))
- // If no file arguments were given, we assume --all
- val enabledTestSets: List[TestSet] = {
- val enabledArgs = testSetArgs filter parsed.isSet
-
- if (args.isEmpty && !(parsed isSet "--grep") && (enabledArgs.isEmpty || (parsed isSet "--all"))) testSets
- else enabledArgs map testSetArgMap
- }
+ val isRerun = parsed isSet "--failed"
+ val rerunTests = if (isRerun) TestKinds.failedTests else Nil
+ def miscTests = partestTests ++ individualTests ++ greppedTests ++ rerunTests
+ val givenKinds = standardArgs filter parsed.isSet
+ val kinds = (
+ if (parsed isSet "--all") standardKinds
+ else if (givenKinds.nonEmpty) givenKinds map (_ stripPrefix "--")
+ else if (invalid.isEmpty && miscTests.isEmpty && !isRerun) standardKinds // If no kinds, --grep, or individual tests were given, assume --all
+ else Nil
+ )
+ val kindsTests = kinds flatMap testsFor
val dir =
if (fileManager.testClasses.isDefined) fileManager.testClassesDir
else fileManager.testBuildFile getOrElse {
fileManager.latestCompFile.getParentFile.getParentFile.getAbsoluteFile
}
- val vmBin = javaHome + File.separator + "bin"
- val vmName = "%s (build %s, %s)".format(javaVmName, javaVmVersion, javaVmInfo)
- val vmOpts = fileManager.JAVA_OPTS
-
- NestUI.verbose("enabled test sets: " + (enabledTestSets map (_.kind) mkString " "))
-
- List(
- "Scala compiler classes in: " + dir,
- "Scala version is: " + versionMsg,
- "Scalac options are: " + fileManager.SCALAC_OPTS,
- "Java binaries in: " + vmBin,
- "Java runtime is: " + vmName,
- "Java options are: " + vmOpts,
- "Source directory is: " + srcDir,
- ""
- ) foreach (x => NestUI verbose (x + "\n"))
-
- NestUI.verbose("available processors: " + Runtime.getRuntime().availableProcessors())
-
- // Dragged down here so it isn't buried under the banner.
- if (grepMessage != "")
- NestUI.normal(grepMessage + "\n")
-
- val ((successes, failures), elapsedMillis) = timed(testCheckAll(enabledTestSets))
- val total = successes + failures
-
- val elapsedSecs = elapsedMillis/1000
- val elapsedMins = elapsedSecs/60
- val elapsedHrs = elapsedMins/60
- val dispMins = elapsedMins - elapsedHrs * 60
- val dispSecs = elapsedSecs - elapsedMins * 60
-
- val dispElapsed = {
- def form(num: Long) = if (num < 10) "0"+num else ""+num
- form(elapsedHrs)+":"+form(dispMins)+":"+form(dispSecs)
+ def testContributors = {
+ List(
+ if (partestTests.isEmpty) "" else "partest self-tests",
+ if (rerunTests.isEmpty) "" else "previously failed tests",
+ if (kindsTests.isEmpty) "" else s"${kinds.size} named test categories",
+ if (greppedTests.isEmpty) "" else s"${greppedTests.size} tests matching '$grepExpr'",
+ if (individualTests.isEmpty) "" else "specified tests"
+ ) filterNot (_ == "") mkString ", "
}
- if (failures == 0)
- NestUI.success("All of "+total+" tests were successful (elapsed time: "+dispElapsed+")\n")
- else
- NestUI.failure(failures+" of "+total+" tests failed (elapsed time: "+dispElapsed+")\n")
+ def banner = {
+ val vmBin = javaHome + fileSeparator + "bin"
+ val vmName = "%s (build %s, %s)".format(javaVmName, javaVmVersion, javaVmInfo)
+ val vmOpts = fileManager.JAVA_OPTS
+
+ s"""|Scala compiler classes in: $dir
+ |Scala version is: $versionMsg
+ |Scalac options are: ${fileManager.SCALAC_OPTS mkString " "}
+ |Java binaries in: $vmBin
+ |Java runtime is: $vmName
+ |Java options are: $vmOpts
+ |Source directory is: $srcDir
+ |Available processors: ${Runtime.getRuntime().availableProcessors()}
+ |Java Classpath: ${sys.props("java.class.path")}
+ """.stripMargin
+ }
- System exit ( if (failures == errors) 0 else 1 )
- }
+ chatty(banner)
- def runTests(testSet: TestSet): (Int, Int) = {
- val TestSet(kind, filter, msg) = testSet
+ val allTests = (miscTests ++ (kinds flatMap testsFor)).distinct
+ val grouped = (allTests groupBy kindOf).toList sortBy (x => standardKinds indexOf x._1)
- fileManager.getFiles(kind, filter) match {
- case Nil => NestUI.verbose("test dir empty\n") ; (0, 0)
- case files =>
- NestUI.verbose("test files: "+files)
- NestUI.outline("\n"+msg+"\n")
- resultsToStatistics(runTestsForFiles(files, kind))
+ totalTests = allTests.size
+ expectedFailures = propOrNone("partest.errors") match {
+ case Some(num) => num.toInt
+ case _ => 0
}
- }
-
- /**
- * @return (success count, failure count)
- */
- def testCheckAll(enabledSets: List[TestSet]): (Int, Int) = {
- def kindOf(f: File) = {
- (srcDir relativize Path(f).toCanonical).segments match {
- case (".." :: "scaladoc" :: xs) => xs.head
- case xs => xs.head
+ val expectedFailureMessage = if (expectedFailures == 0) "" else s" (expecting $expectedFailures to fail)"
+ echo(s"Selected $totalTests tests drawn from $testContributors$expectedFailureMessage\n")
+
+ val (_, millis) = timed {
+ for ((kind, paths) <- grouped) {
+ val num = paths.size
+ val ss = if (num == 1) "" else "s"
+ comment(s"starting $num test$ss in $kind")
+ val results = runTestsForFiles(paths map (_.jfile), kind)
+ val (passed, failed) = results partition (_.isOk)
+
+ passedTests ++= passed
+ failedTests ++= failed
+ if (failed.nonEmpty) {
+ comment(passFailString(passed.size, failed.size, 0) + " in " + kind)
+ }
+ echo("")
}
}
-
- val (valid, invalid) = testFiles partition (x => testSetKinds contains kindOf(x))
- invalid foreach (x => NestUI.failure(
- "Invalid test file '%s', skipping.\n".format(x) +
- "(Test kind '%s' not in known set '%s')".format(kindOf(x), testSetKinds))
- )
-
- val grouped = (valid groupBy kindOf).toList sortBy (x => testSetKinds indexOf x._1)
- val runTestsFileLists =
- for ((kind, files) <- grouped) yield {
- NestUI.outline("\nTesting individual files\n")
- resultsToStatistics(runTestsForFiles(files, kind))
- }
-
- if (enabledSets.nonEmpty)
- NestUI.verbose("Run sets: "+enabledSets)
-
- val results = runTestsFileLists ::: (enabledSets map runTests)
-
- (results map (_._1) sum, results map (_._2) sum)
+ this.elapsedMillis = millis
+ issueSummaryReport()
+ System exit ( if (isSuccess) 0 else 1 )
}
}
diff --git a/src/partest/scala/tools/partest/nest/Diff.java b/src/partest/scala/tools/partest/nest/Diff.java
deleted file mode 100644
index f69fc6858b..0000000000
--- a/src/partest/scala/tools/partest/nest/Diff.java
+++ /dev/null
@@ -1,873 +0,0 @@
-
-package scala.tools.partest.nest;
-
-import java.util.Hashtable;
-
-/** A class to compare IndexedSeqs of objects. The result of comparison
- is a list of <code>change</code> objects which form an
- edit script. The objects compared are traditionally lines
- of text from two files. Comparison options such as "ignore
- whitespace" are implemented by modifying the <code>equals</code>
- and <code>hashcode</code> methods for the objects compared.
-<p>
- The basic algorithm is described in: </br>
- "An O(ND) Difference Algorithm and its Variations", Eugene Myers,
- Algorithmica Vol. 1 No. 2, 1986, p 251.
-<p>
- This class outputs different results from GNU diff 1.15 on some
- inputs. Our results are actually better (smaller change list, smaller
- total size of changes), but it would be nice to know why. Perhaps
- there is a memory overwrite bug in GNU diff 1.15.
-
- @author Stuart D. Gathman, translated from GNU diff 1.15
- Copyright (C) 2000 Business Management Systems, Inc.
-<p>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-<p>
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-<p>
- You should have received a copy of the <a href=COPYING.txt>
- GNU General Public License</a>
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-public class Diff {
-
- /** Prepare to find differences between two arrays. Each element of
- the arrays is translated to an "equivalence number" based on
- the result of <code>equals</code>. The original Object arrays
- are no longer needed for computing the differences. They will
- be needed again later to print the results of the comparison as
- an edit script, if desired.
- */
- public Diff(Object[] a,Object[] b) {
- Hashtable<Object, Integer> h = new Hashtable<Object, Integer>(a.length + b.length);
- filevec[0] = new file_data(a,h);
- filevec[1] = new file_data(b,h);
- }
-
- /** 1 more than the maximum equivalence value used for this or its
- sibling file. */
- private int equiv_max = 1;
-
- /** When set to true, the comparison uses a heuristic to speed it up.
- With this heuristic, for files with a constant small density
- of changes, the algorithm is linear in the file size. */
- public boolean heuristic = false;
-
- /** When set to true, the algorithm returns a guarranteed minimal
- set of changes. This makes things slower, sometimes much slower. */
- public boolean no_discards = false;
-
- private int[] xvec, yvec; /* IndexedSeqs being compared. */
- private int[] fdiag; /* IndexedSeq, indexed by diagonal, containing
- the X coordinate of the point furthest
- along the given diagonal in the forward
- search of the edit matrix. */
- private int[] bdiag; /* IndexedSeq, indexed by diagonal, containing
- the X coordinate of the point furthest
- along the given diagonal in the backward
- search of the edit matrix. */
- private int fdiagoff, bdiagoff;
- private final file_data[] filevec = new file_data[2];
- private int cost;
-
- /** Find the midpoint of the shortest edit script for a specified
- portion of the two files.
-
- We scan from the beginnings of the files, and simultaneously from the ends,
- doing a breadth-first search through the space of edit-sequence.
- When the two searches meet, we have found the midpoint of the shortest
- edit sequence.
-
- The value returned is the number of the diagonal on which the midpoint lies.
- The diagonal number equals the number of inserted lines minus the number
- of deleted lines (counting only lines before the midpoint).
- The edit cost is stored into COST; this is the total number of
- lines inserted or deleted (counting only lines before the midpoint).
-
- This function assumes that the first lines of the specified portions
- of the two files do not match, and likewise that the last lines do not
- match. The caller must trim matching lines from the beginning and end
- of the portions it is going to specify.
-
- Note that if we return the "wrong" diagonal value, or if
- the value of bdiag at that diagonal is "wrong",
- the worst this can do is cause suboptimal diff output.
- It cannot cause incorrect diff output. */
-
- private int diag (int xoff, int xlim, int yoff, int ylim) {
- final int[] fd = fdiag; // Give the compiler a chance.
- final int[] bd = bdiag; // Additional help for the compiler.
- final int[] xv = xvec; // Still more help for the compiler.
- final int[] yv = yvec; // And more and more . . .
- final int dmin = xoff - ylim; // Minimum valid diagonal.
- final int dmax = xlim - yoff; // Maximum valid diagonal.
- final int fmid = xoff - yoff; // Center diagonal of top-down search.
- final int bmid = xlim - ylim; // Center diagonal of bottom-up search.
- int fmin = fmid, fmax = fmid; // Limits of top-down search.
- int bmin = bmid, bmax = bmid; // Limits of bottom-up search.
- /* True if southeast corner is on an odd
- diagonal with respect to the northwest. */
- final boolean odd = (fmid - bmid & 1) != 0;
-
- fd[fdiagoff + fmid] = xoff;
- bd[bdiagoff + bmid] = xlim;
-
- for (int c = 1;; ++c)
- {
- int d; /* Active diagonal. */
- boolean big_snake = false;
-
- /* Extend the top-down search by an edit step in each diagonal. */
- if (fmin > dmin)
- fd[fdiagoff + --fmin - 1] = -1;
- else
- ++fmin;
- if (fmax < dmax)
- fd[fdiagoff + ++fmax + 1] = -1;
- else
- --fmax;
- for (d = fmax; d >= fmin; d -= 2)
- {
- int x, y, oldx, tlo = fd[fdiagoff + d - 1], thi = fd[fdiagoff + d + 1];
-
- if (tlo >= thi)
- x = tlo + 1;
- else
- x = thi;
- oldx = x;
- y = x - d;
- while (x < xlim && y < ylim && xv[x] == yv[y]) {
- ++x; ++y;
- }
- if (x - oldx > 20)
- big_snake = true;
- fd[fdiagoff + d] = x;
- if (odd && bmin <= d && d <= bmax && bd[bdiagoff + d] <= fd[fdiagoff + d])
- {
- cost = 2 * c - 1;
- return d;
- }
- }
-
- /* Similar extend the bottom-up search. */
- if (bmin > dmin)
- bd[bdiagoff + --bmin - 1] = Integer.MAX_VALUE;
- else
- ++bmin;
- if (bmax < dmax)
- bd[bdiagoff + ++bmax + 1] = Integer.MAX_VALUE;
- else
- --bmax;
- for (d = bmax; d >= bmin; d -= 2)
- {
- int x, y, oldx, tlo = bd[bdiagoff + d - 1], thi = bd[bdiagoff + d + 1];
-
- if (tlo < thi)
- x = tlo;
- else
- x = thi - 1;
- oldx = x;
- y = x - d;
- while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) {
- --x; --y;
- }
- if (oldx - x > 20)
- big_snake = true;
- bd[bdiagoff + d] = x;
- if (!odd && fmin <= d && d <= fmax && bd[bdiagoff + d] <= fd[fdiagoff + d])
- {
- cost = 2 * c;
- return d;
- }
- }
-
- /* Heuristic: check occasionally for a diagonal that has made
- lots of progress compared with the edit distance.
- If we have any such, find the one that has made the most
- progress and return it as if it had succeeded.
-
- With this heuristic, for files with a constant small density
- of changes, the algorithm is linear in the file size. */
-
- if (c > 200 && big_snake && heuristic)
- {
- int best = 0;
- int bestpos = -1;
-
- for (d = fmax; d >= fmin; d -= 2)
- {
- int dd = d - fmid;
- if ((fd[fdiagoff + d] - xoff)*2 - dd > 12 * (c + (dd > 0 ? dd : -dd)))
- {
- if (fd[fdiagoff + d] * 2 - dd > best
- && fd[fdiagoff + d] - xoff > 20
- && fd[fdiagoff + d] - d - yoff > 20)
- {
- int k;
- int x = fd[fdiagoff + d];
-
- /* We have a good enough best diagonal;
- now insist that it end with a significant snake. */
- for (k = 1; k <= 20; k++)
- if (xvec[x - k] != yvec[x - d - k])
- break;
-
- if (k == 21)
- {
- best = fd[fdiagoff + d] * 2 - dd;
- bestpos = d;
- }
- }
- }
- }
- if (best > 0)
- {
- cost = 2 * c - 1;
- return bestpos;
- }
-
- best = 0;
- for (d = bmax; d >= bmin; d -= 2)
- {
- int dd = d - bmid;
- if ((xlim - bd[bdiagoff + d])*2 + dd > 12 * (c + (dd > 0 ? dd : -dd)))
- {
- if ((xlim - bd[bdiagoff + d]) * 2 + dd > best
- && xlim - bd[bdiagoff + d] > 20
- && ylim - (bd[bdiagoff + d] - d) > 20)
- {
- /* We have a good enough best diagonal;
- now insist that it end with a significant snake. */
- int k;
- int x = bd[bdiagoff + d];
-
- for (k = 0; k < 20; k++)
- if (xvec[x + k] != yvec[x - d + k])
- break;
- if (k == 20)
- {
- best = (xlim - bd[bdiagoff + d]) * 2 + dd;
- bestpos = d;
- }
- }
- }
- }
- if (best > 0)
- {
- cost = 2 * c - 1;
- return bestpos;
- }
- }
- }
- }
-
- /** Compare in detail contiguous subsequences of the two files
- which are known, as a whole, to match each other.
-
- The results are recorded in the IndexedSeqs filevec[N].changed_flag, by
- storing a 1 in the element for each line that is an insertion or deletion.
-
- The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1.
-
- Note that XLIM, YLIM are exclusive bounds.
- All line numbers are origin-0 and discarded lines are not counted. */
-
- private void compareseq (int xoff, int xlim, int yoff, int ylim) {
- /* Slide down the bottom initial diagonal. */
- while (xoff < xlim && yoff < ylim && xvec[xoff] == yvec[yoff]) {
- ++xoff; ++yoff;
- }
- /* Slide up the top initial diagonal. */
- while (xlim > xoff && ylim > yoff && xvec[xlim - 1] == yvec[ylim - 1]) {
- --xlim; --ylim;
- }
-
- /* Handle simple cases. */
- if (xoff == xlim)
- while (yoff < ylim)
- filevec[1].changed_flag[1+filevec[1].realindexes[yoff++]] = true;
- else if (yoff == ylim)
- while (xoff < xlim)
- filevec[0].changed_flag[1+filevec[0].realindexes[xoff++]] = true;
- else
- {
- /* Find a point of correspondence in the middle of the files. */
-
- int d = diag (xoff, xlim, yoff, ylim);
- int c = cost;
- int f = fdiag[fdiagoff + d];
- int b = bdiag[bdiagoff + d];
-
- if (c == 1)
- {
- /* This should be impossible, because it implies that
- one of the two subsequences is empty,
- and that case was handled above without calling `diag'.
- Let's verify that this is true. */
- throw new IllegalArgumentException("Empty subsequence");
- }
- else
- {
- /* Use that point to split this problem into two subproblems. */
- compareseq (xoff, b, yoff, b - d);
- /* This used to use f instead of b,
- but that is incorrect!
- It is not necessarily the case that diagonal d
- has a snake from b to f. */
- compareseq (b, xlim, b - d, ylim);
- }
- }
- }
-
- /** Discard lines from one file that have no matches in the other file.
- */
-
- private void discard_confusing_lines() {
- filevec[0].discard_confusing_lines(filevec[1]);
- filevec[1].discard_confusing_lines(filevec[0]);
- }
-
- private boolean inhibit = false;
-
- /** Adjust inserts/deletes of blank lines to join changes
- as much as possible.
- */
-
- private void shift_boundaries() {
- if (inhibit)
- return;
- filevec[0].shift_boundaries(filevec[1]);
- filevec[1].shift_boundaries(filevec[0]);
- }
-
- public interface ScriptBuilder {
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script.
- @param changed0 true for lines in first file which do not match 2nd
- @param len0 number of lines in first file
- @param changed1 true for lines in 2nd file which do not match 1st
- @param len1 number of lines in 2nd file
- @return a linked list of changes - or null
- */
- public change build_script(
- boolean[] changed0,int len0,
- boolean[] changed1,int len1
- );
- }
-
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script in reverse order. */
-
- static class ReverseScript implements ScriptBuilder {
- public change build_script(
- final boolean[] changed0,int len0,
- final boolean[] changed1,int len1)
- {
- change script = null;
- int i0 = 0, i1 = 0;
- while (i0 < len0 || i1 < len1) {
- if (changed0[1+i0] || changed1[1+i1]) {
- int line0 = i0, line1 = i1;
-
- /* Find # lines changed here in each file. */
- while (changed0[1+i0]) ++i0;
- while (changed1[1+i1]) ++i1;
-
- /* Record this change. */
- script = new change(line0, line1, i0 - line0, i1 - line1, script);
- }
-
- /* We have reached lines in the two files that match each other. */
- i0++; i1++;
- }
-
- return script;
- }
- }
-
- static class ForwardScript implements ScriptBuilder {
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script in forward order. */
- public change build_script(
- final boolean[] changed0,int len0,
- final boolean[] changed1,int len1)
- {
- change script = null;
- int i0 = len0, i1 = len1;
-
- while (i0 >= 0 || i1 >= 0)
- {
- if (changed0[i0] || changed1[i1])
- {
- int line0 = i0, line1 = i1;
-
- /* Find # lines changed here in each file. */
- while (changed0[i0]) --i0;
- while (changed1[i1]) --i1;
-
- /* Record this change. */
- script = new change(i0, i1, line0 - i0, line1 - i1, script);
- }
-
- /* We have reached lines in the two files that match each other. */
- i0--; i1--;
- }
-
- return script;
- }
- }
-
- /** Standard ScriptBuilders. */
- public final static ScriptBuilder
- forwardScript = new ForwardScript(),
- reverseScript = new ReverseScript();
-
- /* Report the differences of two files. DEPTH is the current directory
- depth. */
- public final change diff_2(final boolean reverse) {
- return diff(reverse ? reverseScript : forwardScript);
- }
-
- /** Get the results of comparison as an edit script. The script
- is described by a list of changes. The standard ScriptBuilder
- implementations provide for forward and reverse edit scripts.
- Alternate implementations could, for instance, list common elements
- instead of differences.
- @param bld an object to build the script from change flags
- @return the head of a list of changes
- */
- public change diff(final ScriptBuilder bld) {
-
- /* Some lines are obviously insertions or deletions
- because they don't match anything. Detect them now,
- and avoid even thinking about them in the main comparison algorithm. */
-
- discard_confusing_lines ();
-
- /* Now do the main comparison algorithm, considering just the
- undiscarded lines. */
-
- xvec = filevec[0].undiscarded;
- yvec = filevec[1].undiscarded;
-
- int diags =
- filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines + 3;
- fdiag = new int[diags];
- fdiagoff = filevec[1].nondiscarded_lines + 1;
- bdiag = new int[diags];
- bdiagoff = filevec[1].nondiscarded_lines + 1;
-
- compareseq (0, filevec[0].nondiscarded_lines,
- 0, filevec[1].nondiscarded_lines);
- fdiag = null;
- bdiag = null;
-
- /* Modify the results slightly to make them prettier
- in cases where that can validly be done. */
-
- shift_boundaries ();
-
- /* Get the results of comparison in the form of a chain
- of `struct change's -- an edit script. */
- return bld.build_script(
- filevec[0].changed_flag,
- filevec[0].buffered_lines,
- filevec[1].changed_flag,
- filevec[1].buffered_lines
- );
-
- }
-
- /** The result of comparison is an "edit script": a chain of change objects.
- Each change represents one place where some lines are deleted
- and some are inserted.
-
- LINE0 and LINE1 are the first affected lines in the two files (origin 0).
- DELETED is the number of lines deleted here from file 0.
- INSERTED is the number of lines inserted here in file 1.
-
- If DELETED is 0 then LINE0 is the number of the line before
- which the insertion was done; vice versa for INSERTED and LINE1. */
-
- public static class change {
- /** Previous or next edit command. */
- public change link;
- /** # lines of file 1 changed here. */
- public final int inserted;
- /** # lines of file 0 changed here. */
- public final int deleted;
- /** Line number of 1st deleted line. */
- public final int line0;
- /** Line number of 1st inserted line. */
- public final int line1;
-
- /** Cons an additional entry onto the front of an edit script OLD.
- LINE0 and LINE1 are the first affected lines in the two files (origin 0).
- DELETED is the number of lines deleted here from file 0.
- INSERTED is the number of lines inserted here in file 1.
-
- If DELETED is 0 then LINE0 is the number of the line before
- which the insertion was done; vice versa for INSERTED and LINE1. */
- public change(int line0, int line1, int deleted, int inserted, change old) {
- this.line0 = line0;
- this.line1 = line1;
- this.inserted = inserted;
- this.deleted = deleted;
- this.link = old;
- //System.err.println(line0+","+line1+","+inserted+","+deleted);
- }
- }
-
- /** Data on one input file being compared.
- */
-
- class file_data {
-
- /** Allocate changed array for the results of comparison. */
- void clear() {
- /* Allocate a flag for each line of each file, saying whether that line
- is an insertion or deletion.
- Allocate an extra element, always zero, at each end of each IndexedSeq.
- */
- changed_flag = new boolean[buffered_lines + 2];
- }
-
- /** Return equiv_count[I] as the number of lines in this file
- that fall in equivalence class I.
- @return the array of equivalence class counts.
- */
- int[] equivCount() {
- int[] equiv_count = new int[equiv_max];
- for (int i = 0; i < buffered_lines; ++i)
- ++equiv_count[equivs[i]];
- return equiv_count;
- }
-
- /** Discard lines that have no matches in another file.
-
- A line which is discarded will not be considered by the actual
- comparison algorithm; it will be as if that line were not in the file.
- The file's `realindexes' table maps virtual line numbers
- (which don't count the discarded lines) into real line numbers;
- this is how the actual comparison algorithm produces results
- that are comprehensible when the discarded lines are counted.
-<p>
- When we discard a line, we also mark it as a deletion or insertion
- so that it will be printed in the output.
- @param f the other file
- */
- void discard_confusing_lines(file_data f) {
- clear();
- /* Set up table of which lines are going to be discarded. */
- final byte[] discarded = discardable(f.equivCount());
-
- /* Don't really discard the provisional lines except when they occur
- in a run of discardables, with nonprovisionals at the beginning
- and end. */
- filterDiscards(discarded);
-
- /* Actually discard the lines. */
- discard(discarded);
- }
-
- /** Mark to be discarded each line that matches no line of another file.
- If a line matches many lines, mark it as provisionally discardable.
- @see equivCount()
- @param counts The count of each equivalence number for the other file.
- @return 0=nondiscardable, 1=discardable or 2=provisionally discardable
- for each line
- */
-
- private byte[] discardable(final int[] counts) {
- final int end = buffered_lines;
- final byte[] discards = new byte[end];
- final int[] equivs = this.equivs;
- int many = 5;
- int tem = end / 64;
-
- /* Multiply MANY by approximate square root of number of lines.
- That is the threshold for provisionally discardable lines. */
- while ((tem = tem >> 2) > 0)
- many *= 2;
-
- for (int i = 0; i < end; i++)
- {
- int nmatch;
- if (equivs[i] == 0)
- continue;
- nmatch = counts[equivs[i]];
- if (nmatch == 0)
- discards[i] = 1;
- else if (nmatch > many)
- discards[i] = 2;
- }
- return discards;
- }
-
- /** Don't really discard the provisional lines except when they occur
- in a run of discardables, with nonprovisionals at the beginning
- and end. */
-
- private void filterDiscards(final byte[] discards) {
- final int end = buffered_lines;
-
- for (int i = 0; i < end; i++)
- {
- /* Cancel provisional discards not in middle of run of discards. */
- if (discards[i] == 2)
- discards[i] = 0;
- else if (discards[i] != 0)
- {
- /* We have found a nonprovisional discard. */
- int j;
- int length;
- int provisional = 0;
-
- /* Find end of this run of discardable lines.
- Count how many are provisionally discardable. */
- for (j = i; j < end; j++)
- {
- if (discards[j] == 0)
- break;
- if (discards[j] == 2)
- ++provisional;
- }
-
- /* Cancel provisional discards at end, and shrink the run. */
- while (j > i && discards[j - 1] == 2) {
- discards[--j] = 0; --provisional;
- }
-
- /* Now we have the length of a run of discardable lines
- whose first and last are not provisional. */
- length = j - i;
-
- /* If 1/4 of the lines in the run are provisional,
- cancel discarding of all provisional lines in the run. */
- if (provisional * 4 > length)
- {
- while (j > i)
- if (discards[--j] == 2)
- discards[j] = 0;
- }
- else
- {
- int consec;
- int minimum = 1;
- int tem = length / 4;
-
- /* MINIMUM is approximate square root of LENGTH/4.
- A subrun of two or more provisionals can stand
- when LENGTH is at least 16.
- A subrun of 4 or more can stand when LENGTH >= 64. */
- while ((tem = tem >> 2) > 0)
- minimum *= 2;
- minimum++;
-
- /* Cancel any subrun of MINIMUM or more provisionals
- within the larger run. */
- for (j = 0, consec = 0; j < length; j++)
- if (discards[i + j] != 2)
- consec = 0;
- else if (minimum == ++consec)
- /* Back up to start of subrun, to cancel it all. */
- j -= consec;
- else if (minimum < consec)
- discards[i + j] = 0;
-
- /* Scan from beginning of run
- until we find 3 or more nonprovisionals in a row
- or until the first nonprovisional at least 8 lines in.
- Until that point, cancel any provisionals. */
- for (j = 0, consec = 0; j < length; j++)
- {
- if (j >= 8 && discards[i + j] == 1)
- break;
- if (discards[i + j] == 2) {
- consec = 0; discards[i + j] = 0;
- }
- else if (discards[i + j] == 0)
- consec = 0;
- else
- consec++;
- if (consec == 3)
- break;
- }
-
- /* I advances to the last line of the run. */
- i += length - 1;
-
- /* Same thing, from end. */
- for (j = 0, consec = 0; j < length; j++)
- {
- if (j >= 8 && discards[i - j] == 1)
- break;
- if (discards[i - j] == 2) {
- consec = 0; discards[i - j] = 0;
- }
- else if (discards[i - j] == 0)
- consec = 0;
- else
- consec++;
- if (consec == 3)
- break;
- }
- }
- }
- }
- }
-
- /** Actually discard the lines.
- @param discards flags lines to be discarded
- */
- private void discard(final byte[] discards) {
- final int end = buffered_lines;
- int j = 0;
- for (int i = 0; i < end; ++i)
- if (no_discards || discards[i] == 0)
- {
- undiscarded[j] = equivs[i];
- realindexes[j++] = i;
- }
- else
- changed_flag[1+i] = true;
- nondiscarded_lines = j;
- }
-
- file_data(Object[] data, Hashtable<Object, Integer> h) {
- buffered_lines = data.length;
-
- equivs = new int[buffered_lines];
- undiscarded = new int[buffered_lines];
- realindexes = new int[buffered_lines];
-
- for (int i = 0; i < data.length; ++i) {
- Integer ir = h.get(data[i]);
- if (ir == null)
- h.put(data[i], new Integer(equivs[i] = equiv_max++));
- else
- equivs[i] = ir.intValue();
- }
- }
-
- /** Adjust inserts/deletes of blank lines to join changes
- as much as possible.
-
- We do something when a run of changed lines include a blank
- line at one end and have an excluded blank line at the other.
- We are free to choose which blank line is included.
- `compareseq' always chooses the one at the beginning,
- but usually it is cleaner to consider the following blank line
- to be the "change". The only exception is if the preceding blank line
- would join this change to other changes.
- @param f the file being compared against
- */
-
- void shift_boundaries(file_data f) {
- final boolean[] changed = changed_flag;
- final boolean[] other_changed = f.changed_flag;
- int i = 0;
- int j = 0;
- int i_end = buffered_lines;
- int preceding = -1;
- int other_preceding = -1;
-
- for (;;)
- {
- int start, end, other_start;
-
- /* Scan forwards to find beginning of another run of changes.
- Also keep track of the corresponding point in the other file. */
-
- while (i < i_end && !changed[1+i])
- {
- while (other_changed[1+j++])
- /* Non-corresponding lines in the other file
- will count as the preceding batch of changes. */
- other_preceding = j;
- i++;
- }
-
- if (i == i_end)
- break;
-
- start = i;
- other_start = j;
-
- for (;;)
- {
- /* Now find the end of this run of changes. */
-
- while (i < i_end && changed[1+i]) i++;
- end = i;
-
- /* If the first changed line matches the following unchanged one,
- and this run does not follow right after a previous run,
- and there are no lines deleted from the other file here,
- then classify the first changed line as unchanged
- and the following line as changed in its place. */
-
- /* You might ask, how could this run follow right after another?
- Only because the previous run was shifted here. */
-
- if (end != i_end
- && equivs[start] == equivs[end]
- && !other_changed[1+j]
- && end != i_end
- && !((preceding >= 0 && start == preceding)
- || (other_preceding >= 0
- && other_start == other_preceding)))
- {
- changed[1+end++] = true;
- changed[1+start++] = false;
- ++i;
- /* Since one line-that-matches is now before this run
- instead of after, we must advance in the other file
- to keep in synch. */
- ++j;
- }
- else
- break;
- }
-
- preceding = i;
- other_preceding = j;
- }
- }
-
- /** Number of elements (lines) in this file. */
- final int buffered_lines;
-
- /** IndexedSeq, indexed by line number, containing an equivalence code for
- each line. It is this IndexedSeq that is actually compared with that
- of another file to generate differences. */
- private final int[] equivs;
-
- /** IndexedSeq, like the previous one except that
- the elements for discarded lines have been squeezed out. */
- final int[] undiscarded;
-
- /** IndexedSeq mapping virtual line numbers (not counting discarded lines)
- to real ones (counting those lines). Both are origin-0. */
- final int[] realindexes;
-
- /** Total number of nondiscarded lines. */
- int nondiscarded_lines;
-
- /** Array, indexed by real origin-1 line number,
- containing true for a line that is an insertion or a deletion.
- The results of comparison are stored here. */
- boolean[] changed_flag;
-
- }
-}
diff --git a/src/partest/scala/tools/partest/nest/DiffPrint.java b/src/partest/scala/tools/partest/nest/DiffPrint.java
deleted file mode 100644
index 31f9a1bc79..0000000000
--- a/src/partest/scala/tools/partest/nest/DiffPrint.java
+++ /dev/null
@@ -1,606 +0,0 @@
-
-package scala.tools.partest.nest;
-
-import java.io.*;
-import java.util.Vector;
-import java.util.Date;
-//import com.objectspace.jgl.predicates.UnaryPredicate;
-
-interface UnaryPredicate {
- boolean execute(Object obj);
-}
-
-/** A simple framework for printing change lists produced by <code>Diff</code>.
- @see bmsi.util.Diff
- @author Stuart D. Gathman
- Copyright (C) 2000 Business Management Systems, Inc.
-<p>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-<p>
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-<p>
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-public class DiffPrint {
- /** A Base class for printing edit scripts produced by Diff.
- This class divides the change list into "hunks", and calls
- <code>print_hunk</code> for each hunk. Various utility methods
- are provided as well.
- */
- public static abstract class Base {
- protected Base(Object[] a,Object[] b, Writer w) {
- outfile = new PrintWriter(w);
- file0 = a;
- file1 = b;
- }
- /** Set to ignore certain kinds of lines when printing
- an edit script. For example, ignoring blank lines or comments.
- */
- protected UnaryPredicate ignore = null;
-
- /** Set to the lines of the files being compared.
- */
- protected Object[] file0, file1;
-
- /** Divide SCRIPT into pieces by calling HUNKFUN and
- print each piece with PRINTFUN.
- Both functions take one arg, an edit script.
-
- PRINTFUN takes a subscript which belongs together (with a null
- link at the end) and prints it. */
- public void print_script(Diff.change script) {
- Diff.change next = script;
-
- while (next != null)
- {
- Diff.change t, end;
-
- /* Find a set of changes that belong together. */
- t = next;
- end = hunkfun(next);
-
- /* Disconnect them from the rest of the changes,
- making them a hunk, and remember the rest for next iteration. */
- next = end.link;
- end.link = null;
- //if (DEBUG)
- // debug_script(t);
-
- /* Print this hunk. */
- print_hunk(t);
-
- /* Reconnect the script so it will all be freed properly. */
- end.link = next;
- }
- outfile.flush();
- }
-
- /** Called with the tail of the script
- and returns the last link that belongs together with the start
- of the tail. */
-
- protected Diff.change hunkfun(Diff.change hunk) {
- return hunk;
- }
-
- protected int first0, last0, first1, last1, deletes, inserts;
- protected PrintWriter outfile;
-
- /** Look at a hunk of edit script and report the range of lines in each file
- that it applies to. HUNK is the start of the hunk, which is a chain
- of `struct change'. The first and last line numbers of file 0 are stored
- in *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1.
- Note that these are internal line numbers that count from 0.
-
- If no lines from file 0 are deleted, then FIRST0 is LAST0+1.
-
- Also set *DELETES nonzero if any lines of file 0 are deleted
- and set *INSERTS nonzero if any lines of file 1 are inserted.
- If only ignorable lines are inserted or deleted, both are
- set to 0. */
-
- protected void analyze_hunk(Diff.change hunk) {
- int f0, l0 = 0, f1, l1 = 0, show_from = 0, show_to = 0;
- int i;
- Diff.change next;
- boolean nontrivial = (ignore == null);
-
- show_from = show_to = 0;
-
- f0 = hunk.line0;
- f1 = hunk.line1;
-
- for (next = hunk; next != null; next = next.link)
- {
- l0 = next.line0 + next.deleted - 1;
- l1 = next.line1 + next.inserted - 1;
- show_from += next.deleted;
- show_to += next.inserted;
- for (i = next.line0; i <= l0 && ! nontrivial; i++)
- if (!ignore.execute(file0[i]))
- nontrivial = true;
- for (i = next.line1; i <= l1 && ! nontrivial; i++)
- if (!ignore.execute(file1[i]))
- nontrivial = true;
- }
-
- first0 = f0;
- last0 = l0;
- first1 = f1;
- last1 = l1;
-
- /* If all inserted or deleted lines are ignorable,
- tell the caller to ignore this hunk. */
-
- if (!nontrivial)
- show_from = show_to = 0;
-
- deletes = show_from;
- inserts = show_to;
- }
-
- /** Print the script header which identifies the files compared. */
- protected void print_header(String filea, String fileb) { }
-
- protected abstract void print_hunk(Diff.change hunk);
-
- protected void print_1_line(String pre,Object linbuf) {
- outfile.println(pre + linbuf.toString());
- }
-
- /** Print a pair of line numbers with SEPCHAR, translated for file FILE.
- If the two numbers are identical, print just one number.
-
- Args A and B are internal line numbers.
- We print the translated (real) line numbers. */
-
- protected void print_number_range (char sepchar, int a, int b) {
- /* Note: we can have B < A in the case of a range of no lines.
- In this case, we should print the line number before the range,
- which is B. */
- if (++b > ++a)
- outfile.print("" + a + sepchar + b);
- else
- outfile.print(b);
- }
-
- public static char change_letter(int inserts, int deletes) {
- if (inserts == 0)
- return 'd';
- else if (deletes == 0)
- return 'a';
- else
- return 'c';
- }
- }
-
- /** Print a change list in the standard diff format.
- */
- public static class NormalPrint extends Base {
-
- public NormalPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- /** Print a hunk of a normal diff.
- This is a contiguous portion of a complete edit script,
- describing changes in consecutive lines. */
-
- protected void print_hunk (Diff.change hunk) {
-
- /* Determine range of line numbers involved in each file. */
- analyze_hunk(hunk);
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Print out the line number header for this hunk */
- print_number_range (',', first0, last0);
- outfile.print(change_letter(inserts, deletes));
- print_number_range (',', first1, last1);
- outfile.println();
-
- /* Print the lines that the first file has. */
- if (deletes != 0)
- for (int i = first0; i <= last0; i++)
- print_1_line ("< ", file0[i]);
-
- if (inserts != 0 && deletes != 0)
- outfile.println("---");
-
- /* Print the lines that the second file has. */
- if (inserts != 0)
- for (int i = first1; i <= last1; i++)
- print_1_line ("> ", file1[i]);
- }
- }
-
- /** Prints an edit script in a format suitable for input to <code>ed</code>.
- The edit script must be generated with the reverse option to
- be useful as actual <code>ed</code> input.
- */
- public static class EdPrint extends Base {
-
- public EdPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- /** Print a hunk of an ed diff */
- protected void print_hunk(Diff.change hunk) {
-
- /* Determine range of line numbers involved in each file. */
- analyze_hunk (hunk);
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Print out the line number header for this hunk */
- print_number_range (',', first0, last0);
- outfile.println(change_letter(inserts, deletes));
-
- /* Print new/changed lines from second file, if needed */
- if (inserts != 0)
- {
- boolean inserting = true;
- for (int i = first1; i <= last1; i++)
- {
- /* Resume the insert, if we stopped. */
- if (! inserting)
- outfile.println(i - first1 + first0 + "a");
- inserting = true;
-
- /* If the file's line is just a dot, it would confuse `ed'.
- So output it with a double dot, and set the flag LEADING_DOT
- so that we will output another ed-command later
- to change the double dot into a single dot. */
-
- if (".".equals(file1[i]))
- {
- outfile.println("..");
- outfile.println(".");
- /* Now change that double dot to the desired single dot. */
- outfile.println(i - first1 + first0 + 1 + "s/^\\.\\././");
- inserting = false;
- }
- else
- /* Line is not `.', so output it unmodified. */
- print_1_line ("", file1[i]);
- }
-
- /* End insert mode, if we are still in it. */
- if (inserting)
- outfile.println(".");
- }
- }
- }
-
- /** Prints an edit script in context diff format. This and its
- 'unified' variation is used for source code patches.
- */
- public static class ContextPrint extends Base {
-
- protected int context = 3;
-
- public ContextPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- protected void print_context_label (String mark, File inf, String label) {
- if (label != null)
- outfile.println(mark + ' ' + label);
- else if (inf.lastModified() > 0)
- // FIXME: use DateFormat to get precise format needed.
- outfile.println(
- mark + ' ' + inf.getPath() + '\t' + new Date(inf.lastModified())
- );
- else
- /* Don't pretend that standard input is ancient. */
- outfile.println(mark + ' ' + inf.getPath());
- }
-
- public void print_header(String filea,String fileb) {
- print_context_label ("***", new File(filea), filea);
- print_context_label ("---", new File(fileb), fileb);
- }
-
- /** If function_regexp defined, search for start of function. */
- private String find_function(Object[] lines, int start) {
- return null;
- }
-
- protected void print_function(Object[] file,int start) {
- String function = find_function (file0, first0);
- if (function != null) {
- outfile.print(" ");
- outfile.print(
- (function.length() < 40) ? function : function.substring(0,40)
- );
- }
- }
-
- protected void print_hunk(Diff.change hunk) {
-
- /* Determine range of line numbers involved in each file. */
-
- analyze_hunk (hunk);
-
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Include a context's width before and after. */
-
- first0 = Math.max(first0 - context, 0);
- first1 = Math.max(first1 - context, 0);
- last0 = Math.min(last0 + context, file0.length - 1);
- last1 = Math.min(last1 + context, file1.length - 1);
-
-
- outfile.print("***************");
-
- /* If we looked for and found a function this is part of,
- include its name in the header of the diff section. */
- print_function (file0, first0);
-
- outfile.println();
- outfile.print("*** ");
- print_number_range (',', first0, last0);
- outfile.println(" ****");
-
- if (deletes != 0) {
- Diff.change next = hunk;
-
- for (int i = first0; i <= last0; i++) {
- /* Skip past changes that apply (in file 0)
- only to lines before line I. */
-
- while (next != null && next.line0 + next.deleted <= i)
- next = next.link;
-
- /* Compute the marking for line I. */
-
- String prefix = " ";
- if (next != null && next.line0 <= i)
- /* The change NEXT covers this line.
- If lines were inserted here in file 1, this is "changed".
- Otherwise it is "deleted". */
- prefix = (next.inserted > 0) ? "!" : "-";
-
- print_1_line (prefix, file0[i]);
- }
- }
-
- outfile.print("--- ");
- print_number_range (',', first1, last1);
- outfile.println(" ----");
-
- if (inserts != 0) {
- Diff.change next = hunk;
-
- for (int i = first1; i <= last1; i++) {
- /* Skip past changes that apply (in file 1)
- only to lines before line I. */
-
- while (next != null && next.line1 + next.inserted <= i)
- next = next.link;
-
- /* Compute the marking for line I. */
-
- String prefix = " ";
- if (next != null && next.line1 <= i)
- /* The change NEXT covers this line.
- If lines were deleted here in file 0, this is "changed".
- Otherwise it is "inserted". */
- prefix = (next.deleted > 0) ? "!" : "+";
-
- print_1_line (prefix, file1[i]);
- }
- }
- }
- }
-
- /** Prints an edit script in context diff format. This and its
- 'unified' variation is used for source code patches.
- */
- public static class UnifiedPrint extends ContextPrint {
-
- public UnifiedPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- public void print_header(String filea,String fileb) {
- print_context_label ("---", new File(filea), filea);
- print_context_label ("+++", new File(fileb), fileb);
- }
-
- private void print_number_range (int a, int b) {
- //translate_range (file, a, b, &trans_a, &trans_b);
-
- /* Note: we can have B < A in the case of a range of no lines.
- In this case, we should print the line number before the range,
- which is B. */
- if (b < a)
- outfile.print(b + ",0");
- else
- super.print_number_range(',',a,b);
- }
-
- protected void print_hunk(Diff.change hunk) {
- /* Determine range of line numbers involved in each file. */
- analyze_hunk (hunk);
-
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Include a context's width before and after. */
-
- first0 = Math.max(first0 - context, 0);
- first1 = Math.max(first1 - context, 0);
- last0 = Math.min(last0 + context, file0.length - 1);
- last1 = Math.min(last1 + context, file1.length - 1);
-
-
-
- outfile.print("@@ -");
- print_number_range (first0, last0);
- outfile.print(" +");
- print_number_range (first1, last1);
- outfile.print(" @@");
-
- /* If we looked for and found a function this is part of,
- include its name in the header of the diff section. */
- print_function(file0,first0);
-
- outfile.println();
-
- Diff.change next = hunk;
- int i = first0;
- int j = first1;
-
- while (i <= last0 || j <= last1) {
-
- /* If the line isn't a difference, output the context from file 0. */
-
- if (next == null || i < next.line0) {
- outfile.print(' ');
- print_1_line ("", file0[i++]);
- j++;
- }
- else {
- /* For each difference, first output the deleted part. */
-
- int k = next.deleted;
- while (k-- > 0) {
- outfile.print('-');
- print_1_line ("", file0[i++]);
- }
-
- /* Then output the inserted part. */
-
- k = next.inserted;
- while (k-- > 0) {
- outfile.print('+');
- print_1_line ("", file1[j++]);
- }
-
- /* We're done with this hunk, so on to the next! */
-
- next = next.link;
- }
- }
- }
- }
-
-
- /** Read a text file into an array of String. This provides basic diff
- functionality. A more advanced diff utility will use specialized
- objects to represent the text lines, with options to, for example,
- convert sequences of whitespace to a single space for comparison
- purposes.
- */
- static String[] slurp(String file) throws IOException {
- BufferedReader rdr = new BufferedReader(new FileReader(file));
- Vector<String> s = new Vector<String>();
- for (;;) {
- String line = rdr.readLine();
- if (line == null) break;
- s.addElement(line);
- }
- String[] a = new String[s.size()];
- s.copyInto(a);
- return a;
- }
-
- public static void main(String[] argv) throws IOException {
- String filea = argv[argv.length - 2];
- String fileb = argv[argv.length - 1];
- String[] a = slurp(filea);
- String[] b = slurp(fileb);
- Diff d = new Diff(a,b);
- char style = 'n';
- for (int i = 0; i < argv.length - 2; ++i) {
- String f = argv[i];
- if (f.startsWith("-")) {
- for (int j = 1; j < f.length(); ++j) {
- switch (f.charAt(j)) {
- case 'e': // Ed style
- style = 'e'; break;
- case 'c': // Context diff
- style = 'c'; break;
- case 'u':
- style = 'u'; break;
- }
- }
- }
- }
- boolean reverse = style == 'e';
- Diff.change script = d.diff_2(reverse);
- if (script == null)
- System.err.println("No differences");
- else {
- Base p;
- Writer w = new OutputStreamWriter(System.out);
- switch (style) {
- case 'e':
- p = new EdPrint(a,b,w); break;
- case 'c':
- p = new ContextPrint(a,b,w); break;
- case 'u':
- p = new UnifiedPrint(a,b,w); break;
- default:
- p = new NormalPrint(a,b,w);
- }
- p.print_header(filea,fileb);
- p.print_script(script);
- }
- }
-
- public static void doDiff(String[] argv, Writer w) throws IOException {
- String filea = argv[argv.length - 2];
- String fileb = argv[argv.length - 1];
- String[] a = slurp(filea);
- String[] b = slurp(fileb);
- Diff d = new Diff(a,b);
- char style = 'n';
- for (int i = 0; i < argv.length - 2; ++i) {
- String f = argv[i];
- if (f.startsWith("-")) {
- for (int j = 1; j < f.length(); ++j) {
- switch (f.charAt(j)) {
- case 'e': // Ed style
- style = 'e'; break;
- case 'c': // Context diff
- style = 'c'; break;
- case 'u':
- style = 'u'; break;
- }
- }
- }
- }
- boolean reverse = style == 'e';
- Diff.change script = d.diff_2(reverse);
- if (script == null)
- w.write("No differences\n");
- else {
- Base p;
- switch (style) {
- case 'e':
- p = new EdPrint(a,b,w); break;
- case 'c':
- p = new ContextPrint(a,b,w); break;
- case 'u':
- p = new UnifiedPrint(a,b,w); break;
- default:
- p = new NormalPrint(a,b,w);
- }
- p.print_header(filea,fileb);
- p.print_script(script);
- }
- }
-
-}
diff --git a/src/partest/scala/tools/partest/nest/DirectCompiler.scala b/src/partest/scala/tools/partest/nest/DirectCompiler.scala
new file mode 100644
index 0000000000..650b6c35c8
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/DirectCompiler.scala
@@ -0,0 +1,105 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2013 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+package scala.tools.partest
+package nest
+
+import scala.tools.nsc.{ Global, Settings, CompilerCommand, FatalError }
+import scala.tools.nsc.reporters.{ Reporter, ConsoleReporter }
+import scala.tools.nsc.util.{ FakePos, stackTraceString }
+import scala.tools.nsc.Properties.{ setProp, propOrEmpty }
+import scala.reflect.io.AbstractFile
+import scala.reflect.internal.util.Position
+import java.io.{ BufferedReader, PrintWriter, FileReader, Writer, FileWriter }
+
+class ExtConsoleReporter(settings: Settings, val writer: PrintWriter) extends ConsoleReporter(settings, Console.in, writer) {
+ shortname = true
+ // override def error(pos: Position, msg: String): Unit
+}
+
+class TestSettings(cp: String, error: String => Unit) extends Settings(error) {
+ def this(cp: String) = this(cp, _ => ())
+
+ nowarnings.value = false
+ encoding.value = "UTF-8"
+ classpath.value = cp
+}
+
+class PartestGlobal(settings: Settings, reporter: Reporter) extends Global(settings, reporter) {
+ // override def abort(msg: String): Nothing
+ // override def globalError(msg: String): Unit
+ // override def supplementErrorMessage(msg: String): String
+}
+class DirectCompiler(val fileManager: FileManager) {
+ def newGlobal(settings: Settings, reporter: Reporter): PartestGlobal =
+ new PartestGlobal(settings, reporter)
+
+ def newGlobal(settings: Settings, logWriter: FileWriter): Global =
+ newGlobal(settings, new ExtConsoleReporter(settings, new PrintWriter(logWriter)))
+
+ def newSettings(): TestSettings = new TestSettings(fileManager.LATEST_LIB)
+ def newSettings(outdir: String): TestSettings = {
+ val cp = ClassPath.join(fileManager.LATEST_LIB, outdir)
+ val s = new TestSettings(cp)
+ s.outdir.value = outdir
+ s
+ }
+
+ def compile(runner: Runner, opts0: List[String], sources: List[File]): TestState = {
+ import runner._
+
+ val testSettings = new TestSettings(ClassPath.join(fileManager.LATEST_LIB, outDir.getPath))
+ val logWriter = new FileWriter(logFile)
+ val srcDir = if (testFile.isDirectory) testFile else Path(testFile).parent.jfile
+ val opts = fileManager.updatePluginPath(opts0, AbstractFile getDirectory outDir, AbstractFile getDirectory srcDir)
+ val command = new CompilerCommand(opts, testSettings)
+ val global = newGlobal(testSettings, logWriter)
+ val reporter = global.reporter.asInstanceOf[ExtConsoleReporter]
+ def errorCount = reporter.ERROR.count
+
+ def defineSettings(s: Settings) = {
+ s.outputDirs setSingleOutput outDir.getPath
+ // adding codelib.jar to the classpath
+ // codelib provides the possibility to override standard reify
+ // this shields the massive amount of reification tests from changes in the API
+ prependToClasspaths(s, codelib)
+ s.classpath append fileManager.CLASSPATH // adding this why?
+
+ // add the instrumented library version to classpath
+ if (kind == "specialized")
+ prependToClasspaths(s, speclib)
+
+ // check that option processing succeeded
+ opts0.isEmpty || command.ok
+ }
+
+ if (!defineSettings(testSettings))
+ if (opts0.isEmpty)
+ reporter.error(null, s"bad settings: $testSettings")
+ else
+ reporter.error(null, opts0.mkString("bad options: ", space, ""))
+
+ def ids = sources.map(_.testIdent) mkString space
+ vlog(s"% scalac $ids")
+
+ def execCompile() =
+ if (command.shouldStopWithInfo) {
+ logWriter append (command getInfoMessage global)
+ runner genFail "compilation stopped with info"
+ } else {
+ new global.Run compile sources.map(_.getPath)
+ if (!reporter.hasErrors) runner.genPass()
+ else {
+ reporter.printSummary()
+ reporter.writer.close()
+ runner.genFail(s"compilation failed with $errorCount errors")
+ }
+ }
+
+ try { execCompile() }
+ catch { case t: Throwable => reporter.error(null, t.getMessage) ; runner.genCrash(t) }
+ finally { logWriter.close() }
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/DirectRunner.scala b/src/partest/scala/tools/partest/nest/DirectRunner.scala
index 7e4c3b842c..49dd39c344 100644
--- a/src/partest/scala/tools/partest/nest/DirectRunner.scala
+++ b/src/partest/scala/tools/partest/nest/DirectRunner.scala
@@ -3,14 +3,12 @@
* @author Philipp Haller
*/
-// $Id$
-
package scala.tools.partest
package nest
import java.io.File
import scala.util.Properties.setProp
-import scala.tools.nsc.util.ScalaClassLoader
+import scala.tools.nsc.util.{ ScalaClassLoader, Exceptional }
import scala.tools.nsc.io.Path
import scala.collection.{ mutable, immutable }
import java.util.concurrent._
@@ -22,41 +20,33 @@ trait DirectRunner {
import PartestDefaults.numThreads
- def denotesTestFile(arg: String) = Path(arg).hasExtension("scala", "res", "xml")
- def denotesTestDir(arg: String) = Path(arg).ifDirectory(_.files.nonEmpty) exists (x => x)
- def denotesTestPath(arg: String) = denotesTestDir(arg) || denotesTestFile(arg)
-
- /** No duplicate, no empty directories, don't mess with this unless
- * you like partest hangs.
- */
- def onlyValidTestPaths[T](args: List[T]): List[T] = {
- args.distinct filter (arg => denotesTestPath("" + arg) || {
- NestUI.warning("Discarding invalid test path '%s'\n" format arg)
- false
- })
- }
- def runTestsForFiles(_kindFiles: List[File], kind: String): immutable.Map[String, TestState] = {
- System.setProperty("line.separator", "\n")
+ Thread.setDefaultUncaughtExceptionHandler(
+ new Thread.UncaughtExceptionHandler {
+ def uncaughtException(thread: Thread, t: Throwable) {
+ val t1 = Exceptional unwrap t
+ System.err.println(s"Uncaught exception on thread $thread: $t1")
+ t1.printStackTrace()
+ }
+ }
+ )
+ def runTestsForFiles(kindFiles: List[File], kind: String): List[TestState] = {
- val allUrls = PathSettings.scalaCheck.toURL :: fileManager.latestUrls
- val scalaCheckParentClassLoader = ScalaClassLoader.fromURLs(allUrls)
- val kindFiles = onlyValidTestPaths(_kindFiles)
- val pool = Executors.newFixedThreadPool(numThreads)
- val manager = new RunnerManager(kind, fileManager, TestRunParams(scalaCheckParentClassLoader))
- val futures = kindFiles map (f => (f, pool submit callable(manager runTest f))) toMap
+ NestUI.resetTestNumber()
- pool.shutdown()
+ val allUrls = PathSettings.scalaCheck.toURL :: fileManager.latestUrls
+ val parentClassLoader = ScalaClassLoader fromURLs allUrls
+ val pool = Executors newFixedThreadPool numThreads
+ val manager = new RunnerManager(kind, fileManager, TestRunParams(parentClassLoader))
+ val futures = kindFiles map (f => pool submit callable(manager runTest f))
+ pool.shutdown()
try if (!pool.awaitTermination(4, TimeUnit.HOURS))
- NestUI.warning("Thread pool timeout elapsed before all tests were complete!")
+ NestUI warning "Thread pool timeout elapsed before all tests were complete!"
catch { case t: InterruptedException =>
- NestUI.warning("Thread pool was interrupted")
+ NestUI warning "Thread pool was interrupted"
t.printStackTrace()
}
- for ((file, future) <- futures) yield {
- val state = if (future.isCancelled) TestState.Timeout else future.get
- (file.getAbsolutePath, state)
- }
+ futures map (_.get)
}
}
diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala
index a32c56e973..25371b7d54 100644
--- a/src/partest/scala/tools/partest/nest/FileManager.scala
+++ b/src/partest/scala/tools/partest/nest/FileManager.scala
@@ -12,39 +12,36 @@ import java.io.{File, FilenameFilter, IOException, StringWriter,
FileInputStream, FileOutputStream, BufferedReader,
FileReader, PrintWriter, FileWriter}
import java.net.URI
-import scala.tools.nsc.io.{ Path, Directory, File => SFile }
+import scala.reflect.io.AbstractFile
import scala.collection.mutable
trait FileUtil {
/**
- * Compares two files using a Java implementation of the GNU diff
- * available at http://www.bmsi.com/java/#diff.
+ * Compares two files using difflib to produce a unified diff.
*
* @param f1 the first file to be compared
* @param f2 the second file to be compared
- * @return the text difference between the compared files
+ * @return the unified diff of the compared files or the empty string if they're equal
*/
def compareFiles(f1: File, f2: File): String = {
- val diffWriter = new StringWriter
- val args = Array(f1.getAbsolutePath(), f2.getAbsolutePath())
-
- DiffPrint.doDiff(args, diffWriter)
- val res = diffWriter.toString
- if (res startsWith "No") "" else res
+ compareContents(io.Source.fromFile(f1).getLines.toSeq, io.Source.fromFile(f2).getLines.toSeq, f1.getName, f2.getName)
}
- def compareContents(lines1: Seq[String], lines2: Seq[String]): String = {
- val xs1 = lines1.toArray[AnyRef]
- val xs2 = lines2.toArray[AnyRef]
-
- val diff = new Diff(xs1, xs2)
- val change = diff.diff_2(false)
- val writer = new StringWriter
- val p = new DiffPrint.NormalPrint(xs1, xs2, writer)
-
- p.print_script(change)
- val res = writer.toString
- if (res startsWith "No ") ""
- else res
+
+ /**
+ * Compares two lists of lines using difflib to produce a unified diff.
+ *
+ * @param origLines the first seq of lines to be compared
+ * @param newLines the second seq of lines to be compared
+ * @param origName file name to be used in unified diff for `origLines`
+ * @param newName file name to be used in unified diff for `newLines`
+ * @return the unified diff of the `origLines` and `newLines` or the empty string if they're equal
+ */
+ def compareContents(origLines: Seq[String], newLines: Seq[String], origName: String = "a", newName: String = "b"): String = {
+ import collection.JavaConverters._
+
+ val diff = difflib.DiffUtils.diff(origLines.asJava, newLines.asJava)
+ if (diff.getDeltas.isEmpty) ""
+ else difflib.DiffUtils.generateUnifiedDiff(origName, newName, origLines.asJava, diff, 1).asScala.mkString("\n")
}
}
object FileUtil extends FileUtil { }
@@ -65,16 +62,19 @@ trait FileManager extends FileUtil {
var LATEST_ACTORS: String
protected def relativeToLibrary(what: String): String = {
- if (LATEST_LIB endsWith ".jar") {
- (SFile(LATEST_LIB).parent / s"scala-$what.jar").toAbsolute.path
- }
- else {
+ def jarname = if (what startsWith "scala") s"$what.jar" else s"scala-$what.jar"
+ if (LATEST_LIB endsWith ".jar")
+ (SFile(LATEST_LIB).parent / jarname).toAbsolute.path
+ else
(SFile(LATEST_LIB).parent.parent / "classes" / what).toAbsolute.path
- }
}
def latestScaladoc = relativeToLibrary("scaladoc")
def latestInteractive = relativeToLibrary("interactive")
- def latestPaths = List(LATEST_LIB, LATEST_REFLECT, LATEST_COMP, LATEST_PARTEST, LATEST_ACTORS, latestScaladoc, latestInteractive)
+ def latestScalapFile = relativeToLibrary("scalap")
+ def latestPaths = List(
+ LATEST_LIB, LATEST_REFLECT, LATEST_COMP, LATEST_PARTEST, LATEST_ACTORS,
+ latestScalapFile, latestScaladoc, latestInteractive
+ )
def latestFiles = latestPaths map (p => new java.io.File(p))
def latestUrls = latestFiles map (_.toURI.toURL)
@@ -131,4 +131,34 @@ trait FileManager extends FileUtil {
f.printlnAll(f.lines.toList map replace: _*)
}
+
+ /** Massage args to merge plugins and fix paths.
+ * Plugin path can be relative to test root, or cwd is out.
+ * While we're at it, mix in the baseline options, too.
+ * That's how ant passes in the plugins dir.
+ */
+ def updatePluginPath(args: List[String], out: AbstractFile, srcdir: AbstractFile): List[String] = {
+ val dir = testRootDir
+ // The given path, or the output dir if ".", or a temp dir if output is virtual (since plugin loading doesn't like virtual)
+ def pathOrCwd(p: String) =
+ if (p == ".") {
+ val plugxml = "scalac-plugin.xml"
+ val pout = if (out.isVirtual) Directory.makeTemp() else Path(out.path)
+ val srcpath = Path(srcdir.path)
+ val pd = (srcpath / plugxml).toFile
+ if (pd.exists) pd copyTo (pout / plugxml)
+ pout
+ } else Path(p)
+ def absolutize(path: String) = pathOrCwd(path) match {
+ case x if x.isAbsolute => x.path
+ case x => (dir / x).toAbsolute.path
+ }
+
+ val xprefix = "-Xplugin:"
+ val (xplugs, others) = args partition (_ startsWith xprefix)
+ val Xplugin = if (xplugs.isEmpty) Nil else List(xprefix +
+ (xplugs map (_ stripPrefix xprefix) flatMap (_ split pathSeparator) map absolutize mkString pathSeparator)
+ )
+ SCALAC_OPTS.toList ::: others ::: Xplugin
+ }
}
diff --git a/src/partest/scala/tools/partest/nest/NestUI.scala b/src/partest/scala/tools/partest/nest/NestUI.scala
index df90b22448..2e203bfd91 100644
--- a/src/partest/scala/tools/partest/nest/NestUI.scala
+++ b/src/partest/scala/tools/partest/nest/NestUI.scala
@@ -3,14 +3,37 @@
* @author Philipp Haller
*/
-// $Id$
-
package scala.tools.partest
package nest
import java.io.PrintWriter
+class Colors(enabled: => Boolean) {
+ import Console._
+
+ val bold = colored(BOLD)
+ val yellow = colored(YELLOW)
+ val green = colored(GREEN)
+ val blue = colored(BLUE)
+ val red = colored(RED)
+ val red_b = colored(RED_B)
+ val green_b = colored(GREEN_B)
+ val cyan = colored(CYAN)
+ val magenta = colored(MAGENTA)
+
+ private def colored(code: String): String => String =
+ s => if (enabled) code + s + RESET else s
+}
+
object NestUI {
+ private val testNum = new java.util.concurrent.atomic.AtomicInteger(1)
+ // @volatile private var testNumber = 1
+ private def testNumber = "%3d" format testNum.getAndIncrement()
+ def resetTestNumber() = testNum set 1
+
+ var colorEnabled = sys.props contains "partest.colors"
+ val color = new Colors(colorEnabled)
+ import color._
val NONE = 0
val SOME = 1
@@ -22,11 +45,57 @@ object NestUI {
private var _warning = ""
private var _default = ""
+ private var dotCount = 0
+ private val DotWidth = 72
+
+ def leftFlush() {
+ if (dotCount != 0) {
+ normal("\n")
+ dotCount = 0
+ }
+ }
+
+ def statusLine(state: TestState) = {
+ import state._
+ val word = bold(
+ if (isSkipped) yellow("--")
+ else if (isOk) green("ok")
+ else red("!!")
+ )
+ word + f" $testNumber%3s - $testIdent%-40s$reasonString"
+ }
+
+ def reportTest(state: TestState) = {
+ if (isTerse && state.isOk) {
+ if (dotCount >= DotWidth) {
+ outline("\n.")
+ dotCount = 1
+ }
+ else {
+ outline(".")
+ dotCount += 1
+ }
+ }
+ else echo(statusLine(state))
+ }
+
+ def echo(message: String): Unit = synchronized {
+ leftFlush()
+ print(message + "\n")
+ }
+ def chatty(msg: String) = if (isVerbose) echo(msg)
+
+ def echoSkipped(msg: String) = echo(yellow(msg))
+ def echoPassed(msg: String) = echo(bold(green(msg)))
+ def echoFailed(msg: String) = echo(bold(red(msg)))
+ def echoMixed(msg: String) = echo(bold(yellow(msg)))
+ def echoWarning(msg: String) = echo(bold(red(msg)))
+
def initialize(number: Int) = number match {
case MANY =>
_outline = Console.BOLD + Console.BLACK
_success = Console.BOLD + Console.GREEN
- _failure = Console.BOLD + Console.RED
+ _failure = Console.BOLD + Console.RED
_warning = Console.BOLD + Console.YELLOW
_default = Console.RESET
case SOME =>
@@ -61,10 +130,7 @@ object NestUI {
}
def usage() {
- println("Usage: NestRunner [<options>] [<testfile> ..] [<resfile>]")
- println(" <testfile>: list of files ending in '.scala'")
- println(" <resfile>: a file not ending in '.scala'")
- println(" <options>:")
+ println("Usage: NestRunner [options] [test test ...]")
println
println(" Test categories:")
println(" --all run all tests")
@@ -74,16 +140,12 @@ object NestUI {
println(" --jvm run JVM backend tests")
println(" --res run resident compiler tests")
println(" --scalacheck run ScalaCheck tests")
- println(" --script run script runner tests")
- println(" --shootout run shootout tests")
println(" --instrumented run instrumented tests")
println(" --presentation run presentation compiler tests")
- println(" --grep <expr> run all tests whose source file contains <expr>")
println
println(" Other options:")
println(" --pack pick compiler/reflect/library in build/pack, and run all tests")
- println(" --show-log show log")
- println(" --show-diff show diff between log and check file")
+ println(" --grep <expr> run all tests whose source file contains <expr>")
println(" --failed run only those tests that failed during the last run")
println(" --update-check instead of failing tests with output change, update checkfile. (Use with care!)")
println(" --verbose show progress information")
@@ -100,11 +162,28 @@ object NestUI {
}
var _verbose = false
+ var _debug = false
+ var _terse = false
+ def isVerbose = _verbose
+ def isDebug = _debug
+ def isTerse = _terse
+
+ def setVerbose() {
+ _verbose = true
+ }
+ def setDebug() {
+ _debug = true
+ }
+ def setTerse() {
+ _terse = true
+ }
def verbose(msg: String) {
- if (_verbose) {
- outline("debug: ")
- println(msg)
- }
+ if (isVerbose)
+ System.err.println(msg)
+ }
+ def debug(msg: String) {
+ if (isDebug)
+ System.err.println(msg)
}
}
diff --git a/src/partest/scala/tools/partest/nest/PathSettings.scala b/src/partest/scala/tools/partest/nest/PathSettings.scala
index 02651c527b..7c005b4f61 100644
--- a/src/partest/scala/tools/partest/nest/PathSettings.scala
+++ b/src/partest/scala/tools/partest/nest/PathSettings.scala
@@ -71,6 +71,9 @@ object PathSettings {
findJar(buildPackLibDir.files ++ srcLibDir.files, "scalacheck") getOrElse {
sys.error("No scalacheck jar found in '%s' or '%s'".format(buildPackLibDir, srcLibDir))
}
+
+ lazy val diffUtils: File =
+ findJar(buildPackLibDir.files, "diffutils") getOrElse sys.error(s"No diffutils.jar found in '$buildPackLibDir'.")
}
class PathSettings() {
diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
index 05cae7b238..9780e82cd9 100644
--- a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
+++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
@@ -51,10 +51,13 @@ class ReflectiveRunner {
new ConsoleFileManager
// this is a workaround for https://issues.scala-lang.org/browse/SI-5433
- // when that bug is fixed, the addition of PathSettings.srcCodeLib can be removed
+ // when that bug is fixed, the addition of PathSettings.srcCodeLib can be removed
// we hack into the classloader that will become parent classloader for scalac
// this way we ensure that reflective macro lookup will pick correct Code.lift
- val sepUrls = PathSettings.srcCodeLib.toURI.toURL :: fileManager.latestUrls
+ // it's also used to inject diffutils into the classpath when running partest from the test/partest script
+ val srcCodeLibAndDiff = List(PathSettings.srcCodeLib, PathSettings.diffUtils)
+ val sepUrls = srcCodeLibAndDiff.map(_.toURI.toURL) ::: fileManager.latestUrls
+ // this seems to be the core classloader that determines which classes can be found when running partest from the test/partest script
val sepLoader = new URLClassLoader(sepUrls.toArray, null)
if (isPartestDebug)
diff --git a/src/partest/scala/tools/partest/nest/Runner.scala b/src/partest/scala/tools/partest/nest/Runner.scala
new file mode 100644
index 0000000000..fc56818bfc
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/Runner.scala
@@ -0,0 +1,628 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2013 LAMP/EPFL
+ * @author Paul Phillips
+ */
+package scala.tools.partest
+package nest
+
+import java.io.{ Console => _, _ }
+import java.net.URL
+import scala.tools.nsc.Properties.{ jdkHome, javaHome, propOrElse, propOrEmpty }
+import scala.util.Properties.{ envOrElse, isWin }
+import scala.tools.nsc.{ Settings, CompilerCommand, Global }
+import scala.tools.nsc.io.{ AbstractFile, PlainFile, Path, Directory, File => SFile }
+import scala.tools.nsc.reporters.ConsoleReporter
+import scala.tools.nsc.util.{ ClassPath, FakePos, ScalaClassLoader, stackTraceString }
+import ClassPath.{ join, split }
+import scala.tools.scalap.scalax.rules.scalasig.ByteCode
+import scala.collection.{ mutable, immutable }
+import scala.sys.process.Process
+import java.util.concurrent.{ Executors, TimeUnit, TimeoutException }
+import PartestDefaults.{ javaCmd, javacCmd }
+import scala.tools.scalap.Main.decompileScala
+
+trait PartestRunSettings {
+ def gitPath: Path
+ def reportPath: Path
+ def logPath: Path
+
+ def testPaths: List[Path]
+
+ def gitDiffOptions: List[String]
+ def extraScalacOptions: List[String]
+ def extraJavaOptions: List[String]
+}
+
+class TestTranscript {
+ import NestUI.color._
+ private val buf = mutable.ListBuffer[String]()
+ private def pass(s: String) = bold(green("% ")) + s
+ private def fail(s: String) = bold(red("% ")) + s
+
+ def add(action: String): this.type = { buf += action ; this }
+ def append(text: String) { val s = buf.last ; buf.trimEnd(1) ; buf += (s + text) }
+
+ // Colorize prompts according to pass/fail
+ def fail: List[String] = buf.toList match {
+ case Nil => Nil
+ case xs => (xs.init map pass) :+ fail(xs.last)
+ }
+}
+
+class Runner(val testFile: File, fileManager: FileManager) {
+ import fileManager._
+
+ // Override to true to have the outcome of this test displayed
+ // whether it passes or not; in general only failures are reported,
+ // except for a . per passing test to show progress.
+ def isEnumeratedTest = false
+
+ def testRunParams: TestRunParams = ???
+
+ private var _lastState: TestState = null
+ private var _transcript = new TestTranscript
+
+ def lastState = if (_lastState == null) TestState.Uninitialized(testFile) else _lastState
+ def setLastState(s: TestState) = _lastState = s
+ def transcript: List[String] = _transcript.fail ++ logFile.fileLines
+ def pushTranscript(msg: String) = _transcript add msg
+
+ val parentFile = testFile.getParentFile
+ val kind = parentFile.getName
+ val fileBase = basename(testFile.getName)
+ val logFile = new File(parentFile, s"$fileBase-$kind.log")
+ val outFile = logFile changeExtension "obj"
+ val checkFile = testFile changeExtension "check"
+ val flagsFile = testFile changeExtension "flags"
+ val testIdent = testFile.testIdent // e.g. pos/t1234
+
+ lazy val outDir = { outFile.mkdirs() ; outFile }
+
+ type RanOneTest = (Boolean, LogContext)
+
+ def showCrashInfo(t: Throwable) {
+ System.err.println("Crashed running test $testIdent: " + t)
+ if (!isPartestTerse)
+ System.err.println(stackTraceString(t))
+ }
+ protected def crashHandler: PartialFunction[Throwable, TestState] = {
+ case t: InterruptedException =>
+ genTimeout()
+ case t: Throwable =>
+ showCrashInfo(t)
+ logFile.appendAll(stackTraceString(t))
+ genCrash(t)
+ }
+
+ def genPass() = TestState.Pass(testFile)
+ def genFail(reason: String) = TestState.Fail(testFile, reason, _transcript.fail)
+ def genTimeout() = TestState.Fail(testFile, "timed out", _transcript.fail)
+ def genCrash(caught: Throwable) = TestState.Crash(testFile, caught, _transcript.fail)
+
+ def speclib = PathSettings.srcSpecLib.toString // specialization lib
+ def codelib = PathSettings.srcCodeLib.toString // reify lib
+
+ // Prepend to a classpath, but without incurring duplicate entries
+ def prependTo(classpath: String, path: String): String = {
+ val segments = ClassPath split classpath
+
+ if (segments startsWith path) classpath
+ else ClassPath.join(path :: segments distinct: _*)
+ }
+
+ def prependToJavaClasspath(path: String) {
+ val jcp = sys.props.getOrElse("java.class.path", "")
+ prependTo(jcp, path) match {
+ case `jcp` =>
+ case cp => sys.props("java.class.path") = cp
+ }
+ }
+ def prependToClasspaths(s: Settings, path: String) {
+ prependToJavaClasspath(path)
+ val scp = s.classpath.value
+ prependTo(scp, path) match {
+ case `scp` =>
+ case cp => s.classpath.value = cp
+ }
+ }
+
+ private def workerError(msg: String): Unit = System.err.println("Error: " + msg)
+
+ def javac(files: List[File]): TestState = {
+ // compile using command-line javac compiler
+ val args = Seq(
+ javacCmd,
+ "-d",
+ outDir.getAbsolutePath,
+ "-classpath",
+ join(outDir.toString, CLASSPATH)
+ ) ++ files.map(_.getAbsolutePath)
+
+ pushTranscript(args mkString " ")
+ val captured = StreamCapture(runCommand(args, logFile))
+ if (captured.result) genPass() else {
+ logFile appendAll captured.stderr
+ genFail("java compilation failed")
+ }
+ }
+
+ def testPrompt = kind match {
+ case "res" => "nsc> "
+ case _ => "% "
+ }
+
+ def nextTestAction[T](body: => T)(failFn: PartialFunction[T, TestState]): T = {
+ val result = body
+ setLastState( if (failFn isDefinedAt result) failFn(result) else genPass() )
+ result
+ }
+ def nextTestActionExpectTrue[T](reason: String, body: => Boolean): Boolean = {
+ nextTestAction(body) { case false => genFail(reason) }
+ }
+
+ private def assembleTestCommand(outDir: File, logFile: File): List[String] = {
+ // check whether there is a ".javaopts" file
+ val argsFile = testFile changeExtension "javaopts"
+ val argString = file2String(argsFile)
+ if (argString != "")
+ NestUI.verbose("Found javaopts file '%s', using options: '%s'".format(argsFile, argString))
+
+ val testFullPath = testFile.getAbsolutePath
+
+ // Note! As this currently functions, JAVA_OPTS must precede argString
+ // because when an option is repeated to java only the last one wins.
+ // That means until now all the .javaopts files were being ignored because
+ // they all attempt to change options which are also defined in
+ // partest.java_opts, leading to debug output like:
+ //
+ // debug: Found javaopts file 'files/shootout/message.scala-2.javaopts', using options: '-Xss32k'
+ // debug: java -Xss32k -Xss2m -Xms256M -Xmx1024M -classpath [...]
+ val extras = if (isPartestDebug) List("-Dpartest.debug=true") else Nil
+ val propertyOptions = List(
+ "-Dfile.encoding=UTF-8",
+ "-Djava.library.path="+logFile.getParentFile.getAbsolutePath,
+ "-Dpartest.output="+outDir.getAbsolutePath,
+ "-Dpartest.lib="+LATEST_LIB,
+ "-Dpartest.reflect="+LATEST_REFLECT,
+ "-Dpartest.cwd="+outDir.getParent,
+ "-Dpartest.test-path="+testFullPath,
+ "-Dpartest.testname="+fileBase,
+ "-Djavacmd="+javaCmd,
+ "-Djavaccmd="+javacCmd,
+ "-Duser.language=en",
+ "-Duser.country=US"
+ ) ++ extras
+
+ val classpath = if (extraClasspath != "") join(extraClasspath, CLASSPATH) else CLASSPATH
+
+ javaCmd +: (
+ (JAVA_OPTS.split(' ') ++ extraJavaOptions.split(' ') ++ argString.split(' ')).map(_.trim).filter(_ != "").toList ++ Seq(
+ "-classpath",
+ join(outDir.toString, classpath)
+ ) ++ propertyOptions ++ Seq(
+ "scala.tools.nsc.MainGenericRunner",
+ "-usejavacp",
+ "Test",
+ "jvm"
+ )
+ )
+ }
+
+ /** Runs command redirecting standard out and
+ * error out to output file.
+ */
+ private def runCommand(args: Seq[String], outFile: File): Boolean = {
+ (Process(args) #> outFile !) == 0
+ }
+
+ private def execTest(outDir: File, logFile: File): Boolean = {
+ val cmd = assembleTestCommand(outDir, logFile)
+
+ pushTranscript(cmd.mkString(" \\\n ") + " > " + logFile.getName)
+ nextTestActionExpectTrue("non-zero exit code", runCommand(cmd, logFile)) || {
+ _transcript append logFile.fileContents
+ false
+ }
+ }
+
+ override def toString = s"""Test($testIdent, lastState = $lastState)"""
+
+ def newTestWriters() = {
+ val swr = new StringWriter
+ val wr = new PrintWriter(swr, true)
+ // diff = ""
+
+ ((swr, wr))
+ }
+
+ def fail(what: Any) = {
+ NestUI.verbose("scalac: compilation of "+what+" failed\n")
+ false
+ }
+
+ /** Filter the diff for conditional blocks.
+ * The check file can contain lines of the form:
+ * `#partest java7`
+ * where the line contains a conventional flag name.
+ * In the diff output, these lines have the form:
+ * `> #partest java7`
+ * Blocks which don't apply are filtered out,
+ * and what remains is the desired diff.
+ * Line edit commands such as `0a1,6` don't count
+ * as diff, so return a nonempty diff only if
+ * material diff output was seen.
+ * Filtering the diff output (instead of every check
+ * file) means that we only post-process a test that
+ * might be failing, in the normal case.
+ */
+ def diffilter(d: String) = {
+ import scala.util.Properties.javaVersion
+ val prefix = "#partest"
+ val margin = "> "
+ val leader = margin + prefix
+ // use lines in block so labeled? Default to sure, go ahead.
+ def retainOn(f: String) = f match {
+ case "java7" => javaVersion startsWith "1.7"
+ case "java6" => javaVersion startsWith "1.6"
+ case _ => true
+ }
+ if (d contains prefix) {
+ val sb = new StringBuilder
+ var retain = true // use the current line
+ var material = false // saw a line of diff
+ for (line <- d.lines)
+ if (line startsWith leader) {
+ val rest = (line stripPrefix leader).trim
+ retain = retainOn(rest)
+ } else if (retain) {
+ if (line startsWith margin) material = true
+ sb ++= line
+ sb ++= EOL
+ }
+ if (material) sb.toString else ""
+ } else d
+ }
+
+ def currentDiff = (
+ if (checkFile.canRead) diffilter(compareFiles(logFile, checkFile))
+ else compareContents(augmentString(file2String(logFile)).lines.toList, Nil)
+ )
+
+ val gitRunner = List("/usr/local/bin/git", "/usr/bin/git") map (f => new java.io.File(f)) find (_.canRead)
+ val gitDiffOptions = "--ignore-space-at-eol --no-index " + propOrEmpty("partest.git_diff_options")
+ // --color=always --word-diff
+
+ def gitDiff(f1: File, f2: File): Option[String] = {
+ try gitRunner map { git =>
+ val cmd = s"$git diff $gitDiffOptions $f1 $f2"
+ val diff = Process(cmd).lines_!.drop(4).map(_ + "\n").mkString
+
+ "\n" + diff
+ }
+ catch { case t: Exception => None }
+ }
+
+ /** This does something about absolute paths and file separator
+ * chars before diffing.
+ */
+ def normalizeLog() {
+ // squashing // in paths also munges line comments, so save this innovation for another time.
+ // (There are line comments in the "stub implementations" error output.)
+ //val slashes = """[/\\]+""".r
+ //def squashSlashes(s: String) = slashes replaceAllIn (s, "/")
+ def squashSlashes(s: String) = s replace ('\\', '/')
+ val base = squashSlashes(parentFile.getAbsolutePath + File.separator)
+ val quoted = """\Q%s\E""" format base
+ val baseless = (if (isWin) "(?i)" + quoted else quoted).r
+ def canonicalize(s: String) = baseless replaceAllIn (squashSlashes(s), "")
+ logFile mapInPlace canonicalize
+ }
+
+ def diffIsOk: Boolean = {
+ val diff = currentDiff
+ val ok: Boolean = (diff == "") || {
+ fileManager.updateCheck && {
+ NestUI.verbose("Updating checkfile " + checkFile)
+ checkFile writeAll file2String(logFile)
+ true
+ }
+ }
+ pushTranscript(s"diff $logFile $checkFile")
+ nextTestAction(ok) {
+ case false =>
+ // Get a word-highlighted diff from git if we can find it
+ val bestDiff = if (ok) "" else {
+ if (checkFile.canRead)
+ gitDiff(logFile, checkFile) getOrElse {
+ s"diff $logFile $checkFile\n$diff"
+ }
+ else diff
+ }
+ _transcript append bestDiff
+ genFail("output differs")
+ // TestState.fail("output differs", "output differs",
+ // genFail("output differs")
+ // TestState.Fail("output differs", bestDiff)
+ }
+ }
+
+ /** 1. Creates log file and output directory.
+ * 2. Runs script function, providing log file and output directory as arguments.
+ */
+ def runInContext(body: => Boolean): (Boolean, LogContext) = {
+ val (swr, wr) = newTestWriters()
+ val succeeded = body
+ (succeeded, LogContext(logFile, swr, wr))
+ }
+
+ /** Grouped files in group order, and lex order within each group. */
+ def groupedFiles(dir: File): List[List[File]] = {
+ val testFiles = dir.listFiles.toList filter (_.isJavaOrScala)
+ val grouped = testFiles groupBy (_.group)
+ grouped.keys.toList.sorted map (k => grouped(k) sortBy (_.getName))
+ }
+
+ def newCompiler = new DirectCompiler(fileManager)
+
+ def attemptCompile(sources: List[File]): TestState = {
+ val state = newCompiler.compile(this, flagsForCompilation(sources), sources)
+ if (!state.isOk)
+ _transcript append ("\n" + file2String(logFile))
+
+ state
+ }
+
+ // snort or scarf all the contributing flags files
+ def flagsForCompilation(sources: List[File]): List[String] = {
+ def argsplitter(s: String) = words(s) filter (_.nonEmpty)
+ val perTest = argsplitter(flagsFile.fileContents)
+ val perGroup = if (testFile.isDirectory) {
+ sources flatMap { f => SFile(Path(f) changeExtension "flags").safeSlurp map argsplitter getOrElse Nil }
+ } else Nil
+ perTest ++ perGroup
+ }
+
+ abstract class CompileRound {
+ def fs: List[File]
+ def result: TestState
+ def description: String
+
+ def fsString = fs map (_.toString stripPrefix parentFile.toString + "/") mkString " "
+ def isOk = result.isOk
+ def mkScalacString(): String = {
+ val flags = file2String(flagsFile) match {
+ case "" => ""
+ case s => " " + s
+ }
+ s"""scalac $fsString"""
+ }
+ override def toString = description + ( if (result.isOk) "" else "\n" + result.status )
+ }
+ case class OnlyJava(fs: List[File]) extends CompileRound {
+ def description = s"""javac $fsString"""
+ lazy val result = { pushTranscript(description) ; javac(fs) }
+ }
+ case class OnlyScala(fs: List[File]) extends CompileRound {
+ def description = mkScalacString()
+ lazy val result = { pushTranscript(description) ; attemptCompile(fs) }
+ }
+ case class ScalaAndJava(fs: List[File]) extends CompileRound {
+ def description = mkScalacString()
+ lazy val result = { pushTranscript(description) ; attemptCompile(fs) }
+ }
+
+ def compilationRounds(file: File): List[CompileRound] = {
+ val grouped = if (file.isDirectory) groupedFiles(file) else List(List(file))
+
+ (grouped map mixedCompileGroup).flatten
+ }
+ def mixedCompileGroup(allFiles: List[File]): List[CompileRound] = {
+ val (scalaFiles, javaFiles) = allFiles partition (_.isScala)
+ val isMixed = javaFiles.nonEmpty && scalaFiles.nonEmpty
+ val round1 = if (scalaFiles.isEmpty) None else Some(ScalaAndJava(allFiles))
+ val round2 = if (javaFiles.isEmpty) None else Some(OnlyJava(javaFiles))
+ val round3 = if (!isMixed) None else Some(OnlyScala(scalaFiles))
+
+ List(round1, round2, round3).flatten
+ }
+
+ def runNegTest() = runInContext {
+ val rounds = compilationRounds(testFile)
+
+ if (rounds forall (x => nextTestActionExpectTrue("compilation failed", x.isOk)))
+ nextTestActionExpectTrue("expected compilation failure", false)
+ else {
+ normalizeLog // put errors in a normal form
+ diffIsOk
+ }
+ }
+
+ def runTestCommon(andAlso: => Boolean): (Boolean, LogContext) = runInContext {
+ compilationRounds(testFile).forall(x => nextTestActionExpectTrue("compilation failed", x.isOk)) && andAlso
+ }
+
+ // Apache Ant 1.6 or newer
+ def ant(args: Seq[String], output: File): Boolean = {
+ val antDir = Directory(envOrElse("ANT_HOME", "/opt/ant/"))
+ val antLibDir = Directory(antDir / "lib")
+ val antLauncherPath = SFile(antLibDir / "ant-launcher.jar").path
+ val antOptions =
+ if (NestUI._verbose) List("-verbose", "-noinput")
+ else List("-noinput")
+ val cmd = javaCmd +: (
+ JAVA_OPTS.split(' ').map(_.trim).filter(_ != "") ++ Seq(
+ "-classpath",
+ antLauncherPath,
+ "org.apache.tools.ant.launch.Launcher"
+ ) ++ antOptions ++ args
+ )
+
+ runCommand(cmd, output)
+ }
+
+ def runAntTest(): (Boolean, LogContext) = {
+ val (swr, wr) = newTestWriters()
+
+ val succeeded = try {
+ val binary = "-Dbinary="+(
+ if (fileManager.LATEST_LIB endsWith "build/quick/classes/library") "quick"
+ else if (fileManager.LATEST_LIB endsWith "build/pack/lib/scala-library.jar") "pack"
+ else if (fileManager.LATEST_LIB endsWith "dists/latest/lib/scala-library.jar/") "latest"
+ else "installed"
+ )
+ val args = Array(binary, "-logfile", logFile.getPath, "-file", testFile.getPath)
+ NestUI.verbose("ant "+args.mkString(" "))
+
+ pushTranscript(s"ant ${args.mkString(" ")}")
+ nextTestActionExpectTrue("ant failed", ant(args, logFile)) && diffIsOk
+ }
+ catch { // *catch-all*
+ case e: Exception =>
+ NestUI.warning("caught "+e)
+ false
+ }
+
+ (succeeded, LogContext(logFile, swr, wr))
+ }
+
+ def extraClasspath = kind match {
+ case "specialized" => PathSettings.srcSpecLib.toString
+ case _ => ""
+ }
+ def extraJavaOptions = kind match {
+ case "instrumented" => "-javaagent:"+PathSettings.instrumentationAgentLib
+ case _ => ""
+ }
+
+ def runScalacheckTest() = runTestCommon {
+ NestUI.verbose("compilation of "+testFile+" succeeded\n")
+
+ val outURL = outDir.getAbsoluteFile.toURI.toURL
+ val logWriter = new PrintStream(new FileOutputStream(logFile), true)
+
+ Output.withRedirected(logWriter) {
+ // this classloader is test specific: its parent contains library classes and others
+ ScalaClassLoader.fromURLs(List(outURL), testRunParams.scalaCheckParentClassLoader).run("Test", Nil)
+ }
+
+ NestUI.verbose(file2String(logFile))
+ // obviously this must be improved upon
+ val lines = SFile(logFile).lines map (_.trim) filterNot (_ == "") toBuffer;
+ lines.forall(x => !x.startsWith("!")) || {
+ NestUI.normal("ScalaCheck test failed. Output:\n")
+ lines foreach (x => NestUI.normal(x + "\n"))
+ false
+ }
+ }
+
+ def runResidentTest() = {
+ // simulate resident compiler loop
+ val prompt = "\nnsc> "
+ val (swr, wr) = newTestWriters()
+
+ NestUI.verbose(this+" running test "+fileBase)
+ val dir = parentFile
+ val resFile = new File(dir, fileBase + ".res")
+
+ // run compiler in resident mode
+ // $SCALAC -d "$os_dstbase".obj -Xresident -sourcepath . "$@"
+ val sourcedir = logFile.getParentFile.getAbsoluteFile
+ val sourcepath = sourcedir.getAbsolutePath+File.separator
+ NestUI.verbose("sourcepath: "+sourcepath)
+
+ val argList = List(
+ "-d", outDir.getAbsoluteFile.getPath,
+ "-Xresident",
+ "-sourcepath", sourcepath)
+
+ // configure input/output files
+ val logOut = new FileOutputStream(logFile)
+ val logWriter = new PrintStream(logOut, true)
+ val resReader = new BufferedReader(new FileReader(resFile))
+ val logConsoleWriter = new PrintWriter(new OutputStreamWriter(logOut), true)
+
+ // create compiler
+ val settings = new Settings(workerError)
+ settings.sourcepath.value = sourcepath
+ settings.classpath.value = fileManager.CLASSPATH
+ val reporter = new ConsoleReporter(settings, scala.Console.in, logConsoleWriter)
+ val command = new CompilerCommand(argList, settings)
+ object compiler extends Global(command.settings, reporter)
+
+ def resCompile(line: String): Boolean = {
+ // NestUI.verbose("compiling "+line)
+ val cmdArgs = (line split ' ').toList map (fs => new File(dir, fs).getAbsolutePath)
+ // NestUI.verbose("cmdArgs: "+cmdArgs)
+ val sett = new Settings(workerError)
+ sett.sourcepath.value = sourcepath
+ val command = new CompilerCommand(cmdArgs, sett)
+ // "scalac " + command.files.mkString(" ")
+ pushTranscript("scalac " + command.files.mkString(" "))
+ nextTestActionExpectTrue(
+ "compilation failed",
+ command.ok && {
+ (new compiler.Run) compile command.files
+ !reporter.hasErrors
+ }
+ )
+ }
+ def loop(): Boolean = {
+ logWriter.print(prompt)
+ resReader.readLine() match {
+ case null | "" => logWriter.close() ; true
+ case line => resCompile(line) && loop()
+ }
+ }
+ // res/t687.res depends on ignoring its compilation failure
+ // and just looking at the diff, so I made them all do that
+ // because this is long enough.
+ if (!Output.withRedirected(logWriter)(try loop() finally resReader.close()))
+ setLastState(genPass())
+
+ normalizeLog // put errors in a normal form
+ (diffIsOk, LogContext(logFile, swr, wr))
+ }
+
+ def run(): TestState = {
+ if (kind == "neg" || (kind endsWith "-neg")) runNegTest()
+ else kind match {
+ case "pos" => runTestCommon(true)
+ case "ant" => runAntTest()
+ case "scalacheck" => runScalacheckTest()
+ case "res" => runResidentTest()
+ case "scalap" => runScalapTest()
+ case "script" => runScriptTest()
+ case _ => runTestCommon(execTest(outDir, logFile) && diffIsOk)
+ }
+
+ lastState
+ }
+
+ def runScalapTest() = runTestCommon {
+ val isPackageObject = testFile.getName startsWith "package"
+ val className = testFile.getName.stripSuffix(".scala").capitalize + (if (!isPackageObject) "" else ".package")
+ val loader = ScalaClassLoader.fromURLs(List(outDir.toURI.toURL), this.getClass.getClassLoader)
+ val byteCode = ByteCode forClass (loader loadClass className)
+ val result = decompileScala(byteCode.bytes, isPackageObject)
+
+ logFile writeAll result
+ diffIsOk
+ }
+ def runScriptTest() = {
+ import scala.sys.process._
+ val (swr, wr) = newTestWriters()
+
+ val args = file2String(testFile changeExtension "args")
+ val cmdFile = if (isWin) testFile changeExtension "bat" else testFile
+ val succeeded = (((cmdFile + " " + args) #> logFile !) == 0) && diffIsOk
+
+ (succeeded, LogContext(logFile, swr, wr))
+ }
+
+ def cleanup() {
+ if (lastState.isOk)
+ logFile.delete()
+ if (!isPartestDebug)
+ Directory(outDir).deleteRecursively()
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala
index 8f28277a6c..1c689714c7 100644
--- a/src/partest/scala/tools/partest/nest/RunnerManager.scala
+++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala
@@ -8,8 +8,6 @@ package nest
import java.io._
import java.net.URL
-import java.util.{ Timer, TimerTask }
-
import scala.tools.nsc.Properties.{ jdkHome, javaHome, propOrElse }
import scala.util.Properties.{ envOrElse, isWin }
import scala.tools.nsc.{ Settings, CompilerCommand, Global }
@@ -22,6 +20,7 @@ import scala.collection.{ mutable, immutable }
import scala.sys.process._
import java.util.concurrent.{ Executors, TimeUnit, TimeoutException }
import PartestDefaults.{ javaCmd, javacCmd }
+import scala.tools.scalap.Main.decompileScala
class LogContext(val file: File, val writers: Option[(StringWriter, PrintWriter)])
@@ -75,689 +74,22 @@ object Output {
class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunParams) {
import fileManager._
-
- val compileMgr = new CompileManager(fileManager)
fileManager.CLASSPATH += File.pathSeparator + PathSettings.scalaCheck
-
- private def compareFiles(f1: File, f2: File): String =
- try fileManager.compareFiles(f1, f2)
- catch { case t: Exception => t.toString }
-
- /** This does something about absolute paths and file separator
- * chars before diffing.
- */
- private def replaceSlashes(dir: File, s: String): String = {
- val base = (dir.getAbsolutePath + File.separator).replace('\\', '/')
- var regex = """\Q%s\E""" format base
- if (isWin) regex = "(?i)" + regex
- s.replace('\\', '/').replaceAll(regex, "")
- }
-
- private def workerError(msg: String): Unit = System.err.println("Error: " + msg)
-
- private def printInfoStart(file: File, printer: PrintWriter) {
- NestUI.outline("testing: ", printer)
- val filesdir = file.getAbsoluteFile.getParentFile.getParentFile
- val testdir = filesdir.getParentFile
- val totalWidth = 56
- val name = {
- // 1. try with [...]/files/run/test.scala
- val name = file.getAbsolutePath drop testdir.getAbsolutePath.length
- if (name.length <= totalWidth) name
- // 2. try with [...]/run/test.scala
- else file.getAbsolutePath drop filesdir.getAbsolutePath.length
- }
- NestUI.normal("[...]%s%s".format(name, " " * (totalWidth - name.length)), printer)
- }
-
- private def printInfoEnd(success: Boolean, printer: PrintWriter) {
- NestUI.normal("[", printer)
- if (success) NestUI.success(" OK ", printer)
- else NestUI.failure("FAILED", printer)
- NestUI.normal("]\n", printer)
- }
-
- private def printInfoTimeout(printer: PrintWriter) {
- NestUI.normal("[", printer)
- NestUI.failure("TIMOUT", printer)
- NestUI.normal("]\n", printer)
- }
-
- private def javac(outDir: File, files: List[File], output: File): CompilationOutcome = {
- // compile using command-line javac compiler
- val args = Seq(
- javacCmd,
- "-d",
- outDir.getAbsolutePath,
- "-classpath",
- join(outDir.toString, CLASSPATH)
- ) ++ files.map("" + _)
-
- try if (runCommand(args, output)) CompileSuccess else CompileFailed
- catch exHandler(output, "javac command failed:\n" + args.map(" " + _ + "\n").mkString + "\n", CompilerCrashed)
- }
-
- /** Runs command redirecting standard out and error out to output file.
- * Overloaded to accept a sequence of arguments.
- */
- private def runCommand(args: Seq[String], outFile: File): Boolean = {
- NestUI.verbose("running command:\n"+args.map(" " + _ + "\n").mkString)
- runCommandImpl(Process(args), outFile)
- }
-
- /** Runs command redirecting standard out and error out to output file.
- * Overloaded to accept a single string = concatenated command + arguments.
- */
- private def runCommand(command: String, outFile: File): Boolean = {
- NestUI.verbose("running command:"+command)
- runCommandImpl(Process(command), outFile)
- }
-
- private def runCommandImpl(process: => ProcessBuilder, outFile: File): Boolean = {
- val exitCode = (process #> outFile !)
- // normalize line endings
- // System.getProperty("line.separator") should be "\n" here
- // so reading a file and writing it back should convert all CRLFs to LFs
- SFile(outFile).printlnAll(SFile(outFile).lines.toList: _*)
- exitCode == 0
- }
-
- @inline private def isJava(f: File) = SFile(f) hasExtension "java"
- @inline private def isScala(f: File) = SFile(f) hasExtension "scala"
- @inline private def isJavaOrScala(f: File) = isJava(f) || isScala(f)
-
- private def outputLogFile(logFile: File) {
- val lines = SFile(logFile).lines
- if (lines.nonEmpty) {
- NestUI.normal("Log file '" + logFile + "': \n")
- lines foreach (x => NestUI.normal(x + "\n"))
- }
- }
- private def logStackTrace(logFile: File, t: Throwable, msg: String): Boolean = {
- SFile(logFile).writeAll(msg, stackTraceString(t))
- outputLogFile(logFile) // if running the test threw an exception, output log file
- false
- }
-
- private def exHandler[T](logFile: File, msg: String, value: T): PartialFunction[Throwable, T] = {
- case e: Exception => logStackTrace(logFile, e, msg) ; value
- }
-
- class Runner(testFile: File) {
- var testDiff: String = ""
- var passed: Option[Boolean] = None
-
- val fileBase = basename(testFile.getName)
- val logFile = fileManager.getLogFile(testFile, kind)
- val parent = testFile.getParentFile
- val outDir = new File(parent, "%s-%s.obj".format(fileBase, kind))
- def toDelete = if (isPartestDebug) Nil else List(
- if (passed exists (x => x)) Some(logFile) else None,
- if (outDir.isDirectory) Some(outDir) else None
- ).flatten
-
- private def createOutputDir(): File = {
- outDir.mkdirs()
- outDir
- }
-
- private def execTest(outDir: File, logFile: File, classpathPrefix: String = "", javaOpts: String = ""): Boolean = {
- // check whether there is a ".javaopts" file
- val argsFile = new File(logFile.getParentFile, fileBase + ".javaopts")
- val argString = file2String(argsFile)
- if (argString != "")
- NestUI.verbose("Found javaopts file '%s', using options: '%s'".format(argsFile, argString))
-
- val testFullPath = {
- val d = new File(logFile.getParentFile, fileBase)
- if (d.isDirectory) d.getAbsolutePath
- else {
- val f = new File(logFile.getParentFile, fileBase + ".scala")
- if (f.isFile) f.getAbsolutePath
- else ""
- }
- }
-
- // Note! As this currently functions, JAVA_OPTS must precede argString
- // because when an option is repeated to java only the last one wins.
- // That means until now all the .javaopts files were being ignored because
- // they all attempt to change options which are also defined in
- // partest.java_opts, leading to debug output like:
- //
- // debug: Found javaopts file 'files/shootout/message.scala-2.javaopts', using options: '-Xss32k'
- // debug: java -Xss32k -Xss2m -Xms256M -Xmx1024M -classpath [...]
- val extras = if (isPartestDebug) List("-Dpartest.debug=true") else Nil
- val propertyOptions = List(
- "-Dfile.encoding=UTF-8",
- "-Djava.library.path="+logFile.getParentFile.getAbsolutePath,
- "-Dpartest.output="+outDir.getAbsolutePath,
- "-Dpartest.lib="+LATEST_LIB,
- "-Dpartest.reflect="+LATEST_REFLECT,
- "-Dpartest.comp="+LATEST_COMP,
- "-Dpartest.cwd="+outDir.getParent,
- "-Dpartest.test-path="+testFullPath,
- "-Dpartest.testname="+fileBase,
- "-Djavacmd="+javaCmd,
- "-Djavaccmd="+javacCmd,
- "-Duser.language=en",
- "-Duser.country=US"
- ) ++ extras
-
- val classpath = if (classpathPrefix != "") join(classpathPrefix, CLASSPATH) else CLASSPATH
- val cmd = javaCmd +: (
- (JAVA_OPTS.split(' ') ++ javaOpts.split(' ') ++ argString.split(' ')).map(_.trim).filter(_ != "") ++ Seq(
- "-classpath",
- join(outDir.toString, classpath)
- ) ++ propertyOptions ++ Seq(
- "scala.tools.nsc.MainGenericRunner",
- "-usejavacp",
- "Test",
- "jvm"
- )
- )
-
- runCommand(cmd, logFile)
- }
-
- private def getCheckFilePath(dir: File, suffix: String) = {
- def chkFile(s: String) = (Directory(dir) / "%s%s.check".format(fileBase, s)).toFile
-
- if (chkFile("").isFile || suffix == "") chkFile("")
- else chkFile("-" + suffix)
- }
-
- private def compareOutput(dir: File, logFile: File): String = {
- val checkFile = getCheckFilePath(dir, kind)
- val diff =
- if (checkFile.canRead) compareFiles(logFile, checkFile.jfile)
- else file2String(logFile)
-
- // if check file exists, compare with log file
- if (diff != "" && fileManager.updateCheck) {
- NestUI.verbose("Updating checkfile " + checkFile.jfile)
- val toWrite = if (checkFile.exists) checkFile else getCheckFilePath(dir, "")
- toWrite writeAll file2String(logFile)
- ""
- }
- else diff
- }
-
- def newTestWriters() = {
- val swr = new StringWriter
- val wr = new PrintWriter(swr, true)
-
- ((swr, wr))
- }
-
- def diffCheck(testFile: File, diff: String) = {
- testDiff = diff
- testDiff == ""
- }
-
- /** 1. Creates log file and output directory.
- * 2. Runs script function, providing log file and output directory as arguments.
- */
- def runInContext(file: File, script: (File, File) => Boolean): (Boolean, LogContext) = {
- val (swr, wr) = newTestWriters()
- printInfoStart(file, wr)
-
- NestUI.verbose(this+" running test "+fileBase)
- val outDir = createOutputDir()
- NestUI.verbose("output directory: "+outDir)
-
- // run test-specific code
- val succeeded = try {
- if (isPartestDebug) {
- val (result, millis) = timed(script(logFile, outDir))
- fileManager.recordTestTiming(file.getPath, millis)
- result
- }
- else script(logFile, outDir)
- }
- catch exHandler(logFile, "", false)
-
- (succeeded, LogContext(logFile, swr, wr))
- }
-
- def groupedFiles(dir: File): List[List[File]] = {
- val testFiles = dir.listFiles.toList filter isJavaOrScala
-
- def isInGroup(f: File, num: Int) = SFile(f).stripExtension endsWith ("_" + num)
- val groups = (0 to 9).toList map (num => (testFiles filter (f => isInGroup(f, num))).sorted)
- val noGroupSuffix = (testFiles filterNot (groups.flatten contains)).sorted
-
- noGroupSuffix :: groups filterNot (_.isEmpty)
- }
-
- def compileFilesIn(dir: File, logFile: File, outDir: File): CompilationOutcome = {
- def compileGroup(g: List[File]): CompilationOutcome = {
- val (scalaFiles, javaFiles) = g partition isScala
- val allFiles = javaFiles ++ scalaFiles
-
- /* The test can contain both java and scala files, each of which should be compiled with the corresponding
- * compiler. Since the source files can reference each other both ways (java referencing scala classes and
- * vice versa, the partest compilation routine attempts to reach a "bytecode fixpoint" between the two
- * compilers -- that's when bytecode generated by each compiler implements the signatures expected by the other.
- *
- * In theory this property can't be guaranteed, as neither compiler can know what signatures the other
- * compiler expects and how to implement them. (see SI-1240 for the full story)
- *
- * In practice, this happens in 3 steps:
- * STEP1: Feed all the files to scalac if there are also non-Scala sources.
- * It will parse java files and obtain their expected signatures and generate bytecode for scala files
- * STEP2: Feed the java files to javac if there are any.
- * It will generate the bytecode for the java files and link to the scalac-generated bytecode for scala
- * STEP3: (Re-)compile the scala sources so they link to the correct
- * java signatures, in case the signatures deduced by scalac from the source files were wrong. Since the
- * bytecode for java is already in place, we only feed the scala files to scalac so it will take the
- * java signatures from the existing javac-generated bytecode.
- * Note that no artifacts are deleted before this step.
- */
- List(1, 2, 3).foldLeft(CompileSuccess: CompilationOutcome) {
- case (CompileSuccess, 1) if scalaFiles.nonEmpty && javaFiles.nonEmpty =>
- compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile)
- case (CompileSuccess, 2) if javaFiles.nonEmpty =>
- javac(outDir, javaFiles, logFile)
- case (CompileSuccess, 3) if scalaFiles.nonEmpty =>
- // TODO: Do we actually need this? SI-1240 is known to require this, but we don't know if other tests
- // require it: https://groups.google.com/forum/?fromgroups#!topic/scala-internals/rFDKAcOKciU
- compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile)
-
- case (outcome, _) => outcome
- }
- }
- groupedFiles(dir).foldLeft(CompileSuccess: CompilationOutcome) {
- case (CompileSuccess, files) => compileGroup(files)
- case (outcome, _) => outcome
- }
- }
-
- def runTestCommon(file: File, expectFailure: Boolean)(
- onSuccess: (File, File) => Boolean,
- onFail: (File, File) => Unit = (_, _) => ()): (Boolean, LogContext) =
- {
- runInContext(file, (logFile: File, outDir: File) => {
- val outcome = (
- if (file.isDirectory) compileFilesIn(file, logFile, outDir)
- else compileMgr.attemptCompile(None, List(file), kind, logFile)
- )
- val result = (
- if (expectFailure) outcome.isNegative
- else outcome.isPositive
- )
-
- if (result) onSuccess(logFile, outDir)
- else { onFail(logFile, outDir) ; false }
- })
- }
-
- def runJvmTest(file: File): (Boolean, LogContext) =
- runTestCommon(file, expectFailure = false)((logFile, outDir) => {
- val dir = file.getParentFile
-
- // adding codelib.jar to the classpath
- // codelib provides the possibility to override standard reify
- // this shields the massive amount of reification tests from changes in the API
- execTest(outDir, logFile, PathSettings.srcCodeLib.toString) && {
- // cannot replace paths here since this also inverts slashes
- // which affects a bunch of tests
- //fileManager.mapFile(logFile, replaceSlashes(dir, _))
- diffCheck(file, compareOutput(dir, logFile))
- }
- })
-
- // Apache Ant 1.6 or newer
- def ant(args: Seq[String], output: File): Boolean = {
- val antDir = Directory(envOrElse("ANT_HOME", "/opt/ant/"))
- val antLibDir = Directory(antDir / "lib")
- val antLauncherPath = SFile(antLibDir / "ant-launcher.jar").path
- val antOptions =
- if (NestUI._verbose) List("-verbose", "-noinput")
- else List("-noinput")
- val cmd = javaCmd +: (
- JAVA_OPTS.split(' ').map(_.trim).filter(_ != "") ++ Seq(
- "-classpath",
- antLauncherPath,
- "org.apache.tools.ant.launch.Launcher"
- ) ++ antOptions ++ args
- )
-
- try runCommand(cmd, output)
- catch exHandler(output, "ant command '" + cmd + "' failed:\n", false)
- }
-
- def runAntTest(file: File): (Boolean, LogContext) = {
- val (swr, wr) = newTestWriters()
- printInfoStart(file, wr)
-
- NestUI.verbose(this+" running test "+fileBase)
-
- val succeeded = try {
- val binary = "-Dbinary="+(
- if (fileManager.LATEST_LIB endsWith "build/quick/classes/library") "quick"
- else if (fileManager.LATEST_LIB endsWith "build/pack/lib/scala-library.jar") "pack"
- else if (fileManager.LATEST_LIB endsWith "dists/latest/lib/scala-library.jar/") "latest"
- else "installed"
- )
- val args = Array(binary, "-logfile", logFile.path, "-file", file.path)
- NestUI.verbose("ant "+args.mkString(" "))
- ant(args, logFile) && diffCheck(file, compareOutput(file.getParentFile, logFile))
- }
- catch { // *catch-all*
- case e: Exception =>
- NestUI.verbose("caught "+e)
- false
- }
-
- (succeeded, LogContext(logFile, swr, wr))
- }
-
- def runSpecializedTest(file: File): (Boolean, LogContext) =
- runTestCommon(file, expectFailure = false)((logFile, outDir) => {
- val dir = file.getParentFile
-
- // adding the instrumented library to the classpath
- ( execTest(outDir, logFile, PathSettings.srcSpecLib.toString) &&
- diffCheck(file, compareOutput(dir, logFile))
- )
- })
-
- def runInstrumentedTest(file: File): (Boolean, LogContext) =
- runTestCommon(file, expectFailure = false)((logFile, outDir) => {
- val dir = file.getParentFile
-
- // adding the javagent option with path to instrumentation agent
- execTest(outDir, logFile, javaOpts = "-javaagent:"+PathSettings.instrumentationAgentLib) &&
- diffCheck(file, compareOutput(dir, logFile))
- })
-
- def processSingleFile(file: File): (Boolean, LogContext) = kind match {
- case "scalacheck" =>
- val succFn: (File, File) => Boolean = { (logFile, outDir) =>
- NestUI.verbose("compilation of "+file+" succeeded\n")
-
- val outURL = outDir.getAbsoluteFile.toURI.toURL
- val logWriter = new PrintStream(new FileOutputStream(logFile), true)
-
- Output.withRedirected(logWriter) {
- // this classloader is test specific: its parent contains library classes and others
- ScalaClassLoader.fromURLs(List(outURL), params.scalaCheckParentClassLoader).run("Test", Nil)
- }
-
- NestUI.verbose(file2String(logFile))
- // obviously this must be improved upon
- val lines = SFile(logFile).lines map (_.trim) filterNot (_ == "") toBuffer;
- lines.forall(x => !x.startsWith("!")) || {
- NestUI.normal("ScalaCheck test failed. Output:\n")
- lines foreach (x => NestUI.normal(x + "\n"))
- false
- }
- }
- runTestCommon(file, expectFailure = false)(
- succFn,
- (logFile, outDir) => outputLogFile(logFile)
- )
-
- case "pos" =>
- runTestCommon(file, expectFailure = false)(
- (logFile, outDir) => true,
- (_, _) => ()
- )
-
- case "neg" =>
- runTestCommon(file, expectFailure = true)((logFile, outDir) => {
- // compare log file to check file
- val dir = file.getParentFile
-
- // diff is contents of logFile
- fileManager.mapFile(logFile, replaceSlashes(dir, _))
- diffCheck(file, compareOutput(dir, logFile))
- })
-
- case "run" | "jvm" =>
- runJvmTest(file)
-
- case "specialized" =>
- runSpecializedTest(file)
-
- case "instrumented" =>
- runInstrumentedTest(file)
-
- case "presentation" =>
- runJvmTest(file) // for the moment, it's exactly the same as for a run test
-
- case "ant" =>
- runAntTest(file)
-
- case "res" => {
- // simulate resident compiler loop
- val prompt = "\nnsc> "
-
- val (swr, wr) = newTestWriters()
- printInfoStart(file, wr)
-
- NestUI.verbose(this+" running test "+fileBase)
- val dir = file.getParentFile
- val outDir = createOutputDir()
- val resFile = new File(dir, fileBase + ".res")
- NestUI.verbose("outDir: "+outDir)
- NestUI.verbose("logFile: "+logFile)
- //NestUI.verbose("logFileErr: "+logFileErr)
- NestUI.verbose("resFile: "+resFile)
-
- // run compiler in resident mode
- // $SCALAC -d "$os_dstbase".obj -Xresident -sourcepath . "$@"
- val sourcedir = logFile.getParentFile.getAbsoluteFile
- val sourcepath = sourcedir.getAbsolutePath+File.separator
- NestUI.verbose("sourcepath: "+sourcepath)
-
- val argList = List(
- "-d", outDir.getAbsoluteFile.getPath,
- "-Xresident",
- "-sourcepath", sourcepath)
-
- // configure input/output files
- val logOut = new FileOutputStream(logFile)
- val logWriter = new PrintStream(logOut, true)
- val resReader = new BufferedReader(new FileReader(resFile))
- val logConsoleWriter = new PrintWriter(new OutputStreamWriter(logOut), true)
-
- // create compiler
- val settings = new Settings(workerError)
- settings.sourcepath.value = sourcepath
- settings.classpath.value = fileManager.CLASSPATH
- val reporter = new ConsoleReporter(settings, scala.Console.in, logConsoleWriter)
- val command = new CompilerCommand(argList, settings)
- object compiler extends Global(command.settings, reporter)
-
- val resCompile = (line: String) => {
- NestUI.verbose("compiling "+line)
- val cmdArgs = (line split ' ').toList map (fs => new File(dir, fs).getAbsolutePath)
- NestUI.verbose("cmdArgs: "+cmdArgs)
- val sett = new Settings(workerError)
- sett.sourcepath.value = sourcepath
- val command = new CompilerCommand(cmdArgs, sett)
- command.ok && {
- (new compiler.Run) compile command.files
- !reporter.hasErrors
- }
- }
-
- def loop(action: String => Boolean): Boolean = {
- logWriter.print(prompt)
- resReader.readLine() match {
- case null | "" => logWriter.flush() ; true
- case line => action(line) && loop(action)
- }
- }
-
- Output.withRedirected(logWriter) {
- try loop(resCompile)
- finally resReader.close()
- }
- fileManager.mapFile(logFile, replaceSlashes(dir, _))
-
- (diffCheck(file, compareOutput(dir, logFile)), LogContext(logFile, swr, wr))
- }
-
- case "shootout" =>
- val (swr, wr) = newTestWriters()
- printInfoStart(file, wr)
-
- NestUI.verbose(this+" running test "+fileBase)
- val outDir = createOutputDir()
-
- // 2. define file {outDir}/test.scala that contains code to compile/run
- val testFile = new File(outDir, "test.scala")
- NestUI.verbose("outDir: "+outDir)
- NestUI.verbose("logFile: "+logFile)
- NestUI.verbose("testFile: "+testFile)
-
- // 3. cat {test}.scala.runner {test}.scala > testFile
- val runnerFile = new File(parent, fileBase+".scala.runner")
- val bodyFile = new File(parent, fileBase+".scala")
- SFile(testFile).writeAll(
- file2String(runnerFile),
- file2String(bodyFile)
- )
-
- // 4. compile testFile
- val ok = compileMgr.attemptCompile(None, List(testFile), kind, logFile) eq CompileSuccess
- NestUI.verbose("compilation of " + testFile + (if (ok) "succeeded" else "failed"))
- val result = ok && {
- execTest(outDir, logFile) && {
- NestUI.verbose(this+" finished running "+fileBase)
- diffCheck(file, compareOutput(parent, logFile))
- }
- }
-
- (result, LogContext(logFile, swr, wr))
-
- case "scalap" =>
- runInContext(file, (logFile: File, outDir: File) => {
- val sourceDir = Directory(if (file.isFile) file.getParent else file)
- val sources = sourceDir.files filter (_ hasExtension "scala") map (_.jfile) toList
- val results = sourceDir.files filter (_.name == "result.test") map (_.jfile) toList
-
- if (sources.length != 1 || results.length != 1) {
- NestUI.warning("Misconfigured scalap test directory: " + sourceDir + " \n")
- false
- }
- else {
- val resFile = results.head
- // 2. Compile source file
-
- if (!compileMgr.attemptCompile(Some(outDir), sources, kind, logFile).isPositive) {
- NestUI.normal("compilerMgr failed to compile %s to %s".format(sources mkString ", ", outDir))
- false
- }
- else {
- // 3. Decompile file and compare results
- val isPackageObject = sourceDir.name startsWith "package"
- val className = sourceDir.name.capitalize + (if (!isPackageObject) "" else ".package")
- val url = outDir.toURI.toURL
- val loader = ScalaClassLoader.fromURLs(List(url), this.getClass.getClassLoader)
- val clazz = loader.loadClass(className)
-
- val byteCode = ByteCode.forClass(clazz)
- val result = scala.tools.scalap.Main.decompileScala(byteCode.bytes, isPackageObject)
-
- SFile(logFile) writeAll result
- diffCheck(file, compareFiles(logFile, resFile))
- }
- }
- })
-
- case "script" =>
- val (swr, wr) = newTestWriters()
- printInfoStart(file, wr)
-
- NestUI.verbose(this+" running test "+fileBase)
-
- // check whether there is an args file
- val argsFile = new File(file.getParentFile, fileBase+".args")
- NestUI.verbose("argsFile: "+argsFile)
- val argString = file2String(argsFile)
- val succeeded = try {
- val cmdString =
- if (isWin) {
- val batchFile = new File(file.getParentFile, fileBase+".bat")
- NestUI.verbose("batchFile: "+batchFile)
- batchFile.getAbsolutePath
- }
- else file.getAbsolutePath
-
- val ok = runCommand(cmdString+argString, logFile)
- ( ok && diffCheck(file, compareOutput(file.getParentFile, logFile)) )
- }
- catch { case e: Exception => NestUI.verbose("caught "+e) ; false }
-
- (succeeded, LogContext(logFile, swr, wr))
- }
-
- private def crashContext(t: Throwable): LogContext = {
- try {
- logStackTrace(logFile, t, "Possible compiler crash during test of: " + testFile + "\n")
- LogContext(logFile)
- }
- catch { case t: Throwable => LogContext(null) }
- }
-
- def run(): (Boolean, LogContext) = {
- val result = try processSingleFile(testFile) catch { case t: Throwable => (false, crashContext(t)) }
- passed = Some(result._1)
- result
- }
-
- def reportResult(writers: Option[(StringWriter, PrintWriter)]) {
- writers foreach { case (swr, wr) =>
- if (passed.isEmpty) printInfoTimeout(wr)
- else printInfoEnd(passed.get, wr)
- wr.flush()
- swr.flush()
- NestUI.normal(swr.toString)
-
- if (passed exists (x => !x)) {
- if (fileManager.showDiff || isPartestDebug)
- NestUI.normal(testDiff)
- if (fileManager.showLog)
- showLog(logFile)
- }
- }
- toDelete foreach (_.deleteRecursively())
- }
- }
+ fileManager.CLASSPATH += File.pathSeparator + PathSettings.diffUtils // needed to put diffutils on test/partest's classpath
def runTest(testFile: File): TestState = {
- val runner = new Runner(testFile)
+ val runner = new Runner(testFile, fileManager) {
+ override def testRunParams = params
+ }
// when option "--failed" is provided execute test only if log
// is present (which means it failed before)
if (fileManager.failed && !runner.logFile.canRead)
- return TestState.Ok
-
- val (success, ctx) = runner.run()
- val state = if (success) TestState.Ok else TestState.Fail
-
- runner.reportResult(ctx.writers)
- state
- }
-
- private def filesToSet(pre: String, fs: List[String]): Set[AbstractFile] =
- fs flatMap (s => Option(AbstractFile getFile (pre + s))) toSet
-
- private def copyTestFiles(testDir: File, destDir: File) {
- val invalidExts = List("changes", "svn", "obj")
- testDir.listFiles.toList filter (
- f => (isJavaOrScala(f) && f.isFile) ||
- (f.isDirectory && !(invalidExts.contains(SFile(f).extension)))) foreach
- { f => fileManager.copyFile(f, destDir) }
- }
-
- private def showLog(logFile: File) {
- file2String(logFile) match {
- case "" if logFile.canRead => ()
- case "" => NestUI.failure("Couldn't open log file: " + logFile + "\n")
- case s => NestUI.normal(s)
+ runner.genPass()
+ else {
+ val (state, elapsed) = timed(runner.run())
+ NestUI.reportTest(state)
+ runner.cleanup()
+ state
}
}
}
diff --git a/src/partest/scala/tools/partest/nest/SBTRunner.scala b/src/partest/scala/tools/partest/nest/SBTRunner.scala
index 20f9c701d5..1cf3aa858f 100644
--- a/src/partest/scala/tools/partest/nest/SBTRunner.scala
+++ b/src/partest/scala/tools/partest/nest/SBTRunner.scala
@@ -1,3 +1,6 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2013 LAMP/EPFL
+ */
package scala.tools.partest
package nest
@@ -21,7 +24,7 @@ object SBTRunner extends DirectRunner {
val testRootDir: Directory = Directory(testRootPath)
}
- def reflectiveRunTestsForFiles(kindFiles: Array[File], kind: String):java.util.Map[String, TestState] = {
+ def reflectiveRunTestsForFiles(kindFiles: Array[File], kind: String): java.util.List[TestState] = {
def failedOnlyIfRequired(files:List[File]):List[File]={
if (fileManager.failed) files filter (x => fileManager.logFileExists(x, kind)) else files
}
@@ -33,7 +36,7 @@ object SBTRunner extends DirectRunner {
scalacOptions: Seq[String] = Seq(),
justFailedTests: Boolean = false)
- def mainReflect(args: Array[String]): java.util.Map[String, String] = {
+ def mainReflect(args: Array[String]): java.util.List[TestState] = {
setProp("partest.debug", "true")
val Argument = new scala.util.matching.Regex("-(.*)")
@@ -46,7 +49,7 @@ object SBTRunner extends DirectRunner {
case x => sys.error("Unknown command line options: " + x)
}
val config = parseArgs(args, CommandLineOptions())
- fileManager.SCALAC_OPTS ++= config.scalacOptions
+ fileManager.SCALAC_OPTS = config.scalacOptions
fileManager.CLASSPATH = config.classpath getOrElse sys.error("No classpath set")
def findClasspath(jar: String, name: String): Option[String] = {
@@ -67,22 +70,14 @@ object SBTRunner extends DirectRunner {
// TODO - Make this a flag?
//fileManager.updateCheck = true
// Now run and report...
- val runs = config.tests.filterNot(_._2.isEmpty)
- (for {
- (testType, files) <- runs
- (path, result) <- reflectiveRunTestsForFiles(files,testType).asScala
- } yield (path, fixResult(result))).seq.asJava
- }
- def fixResult(result: TestState): String = result match {
- case TestState.Ok => "OK"
- case TestState.Fail => "FAIL"
- case TestState.Timeout => "TIMEOUT"
+ val runs = config.tests.filterNot(_._2.isEmpty)
+ val result = runs.toList flatMap { case (kind, files) => reflectiveRunTestsForFiles(files, kind).asScala }
+
+ result.asJava
}
+
def main(args: Array[String]): Unit = {
- val failures = (
- for ((path, result) <- mainReflect(args).asScala ; if result != TestState.Ok) yield
- path + ( if (result == TestState.Fail) " [FAILED]" else " [TIMEOUT]" )
- )
+ val failures = mainReflect(args).asScala collect { case s if !s.isOk => s.longStatus }
// Re-list all failures so we can go figure out what went wrong.
failures foreach System.err.println
if(!failures.isEmpty) sys.exit(1)
diff --git a/src/partest/scala/tools/partest/nest/StreamCapture.scala b/src/partest/scala/tools/partest/nest/StreamCapture.scala
new file mode 100644
index 0000000000..dc155b1787
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/StreamCapture.scala
@@ -0,0 +1,53 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2013 LAMP/EPFL
+ * @author Paul Phillips
+ */
+package scala.tools.partest
+package nest
+
+import java.io.{ Console => _, _ }
+
+object StreamCapture {
+ case class Captured[T](stdout: String, stderr: String, result: T) {
+ override def toString = s"""
+ |result: $result
+ |[stdout]
+ |$stdout
+ |[stderr]
+ |$stderr""".stripMargin.trim
+ }
+
+ private def mkStream = {
+ val swr = new StringWriter
+ val wr = new PrintWriter(swr, true)
+ val ostream = new PrintStream(new OutputStream { def write(b: Int): Unit = wr write b }, true) // autoFlush = true
+
+ (ostream, () => { ostream.close() ; swr.toString })
+ }
+
+ def savingSystem[T](body: => T): T = {
+ val savedOut = System.out
+ val savedErr = System.err
+ try body
+ finally {
+ System setErr savedErr
+ System setOut savedOut
+ }
+ }
+
+ def apply[T](body: => T): Captured[T] = {
+ val (outstream, stdoutFn) = mkStream
+ val (errstream, stderrFn) = mkStream
+
+ val result = savingSystem {
+ System setOut outstream
+ System setErr errstream
+ Console.withOut(outstream) {
+ Console.withErr(errstream) {
+ body
+ }
+ }
+ }
+ Captured(stdoutFn(), stderrFn(), result)
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/TestFile.scala b/src/partest/scala/tools/partest/nest/TestFile.scala
deleted file mode 100644
index 880c6e431b..0000000000
--- a/src/partest/scala/tools/partest/nest/TestFile.scala
+++ /dev/null
@@ -1,80 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2013 LAMP/EPFL
- * @author Philipp Haller
- */
-
-// $Id$
-
-package scala.tools.partest
-package nest
-
-import java.io.{ File => JFile }
-import scala.tools.nsc.Settings
-import scala.tools.nsc.util.ClassPath
-import scala.tools.nsc.io._
-import scala.util.Properties.{ propIsSet, propOrElse, setProp }
-
-trait TestFileCommon {
- def file: JFile
- def kind: String
-
- val dir = file.toAbsolute.parent
- val fileBase = file.stripExtension
- val flags = dir / (fileBase + ".flags") ifFile (f => f.slurp().trim)
-
- lazy val objectDir = dir / (fileBase + "-" + kind + ".obj") createDirectory true
- def setOutDirTo = objectDir
-}
-
-abstract class TestFile(val kind: String) extends TestFileCommon {
- def file: JFile
- def fileManager: FileManager
-
- def defineSettings(settings: Settings, setOutDir: Boolean) = {
- settings.classpath append dir.path
- if (setOutDir)
- settings.outputDirs setSingleOutput setOutDirTo.path
-
- // adding codelib.jar to the classpath
- // codelib provides the possibility to override standard reify
- // this shields the massive amount of reification tests from changes in the API
- settings.classpath prepend PathSettings.srcCodeLib.toString
- if (propIsSet("java.class.path")) setProp("java.class.path", PathSettings.srcCodeLib.toString + ";" + propOrElse("java.class.path", ""))
-
- // have to catch bad flags somewhere
- (flags forall (f => settings.processArgumentString(f)._1)) && {
- settings.classpath append fileManager.CLASSPATH
- true
- }
- }
-
- override def toString(): String = "%s %s".format(kind, file)
-}
-
-case class PosTestFile(file: JFile, fileManager: FileManager) extends TestFile("pos")
-case class NegTestFile(file: JFile, fileManager: FileManager) extends TestFile("neg")
-case class RunTestFile(file: JFile, fileManager: FileManager) extends TestFile("run")
-case class ScalaCheckTestFile(file: JFile, fileManager: FileManager) extends TestFile("scalacheck")
-case class JvmTestFile(file: JFile, fileManager: FileManager) extends TestFile("jvm")
-case class ShootoutTestFile(file: JFile, fileManager: FileManager) extends TestFile("shootout") {
- override def setOutDirTo = file.parent
-}
-case class ScalapTestFile(file: JFile, fileManager: FileManager) extends TestFile("scalap") {
- override def setOutDirTo = file.parent
-}
-case class SpecializedTestFile(file: JFile, fileManager: FileManager) extends TestFile("specialized") {
- override def defineSettings(settings: Settings, setOutDir: Boolean): Boolean = {
- super.defineSettings(settings, setOutDir) && {
- // add the instrumented library version to classpath
- settings.classpath prepend PathSettings.srcSpecLib.toString
- // @partest maintainer: if we use a custom Scala build (specified via --classpath)
- // then the classes provided by it will come earlier than instrumented.jar in the resulting classpath
- // this entire classpath business needs a thorough solution
- if (propIsSet("java.class.path")) setProp("java.class.path", PathSettings.srcSpecLib.toString + ";" + propOrElse("java.class.path", ""))
- true
- }
- }
-}
-case class PresentationTestFile(file: JFile, fileManager: FileManager) extends TestFile("presentation")
-case class AntTestFile(file: JFile, fileManager: FileManager) extends TestFile("ant")
-case class InstrumentedTestFile(file: JFile, fileManager: FileManager) extends TestFile("instrumented")
diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala
index 2b2ce2e435..9e21b0f6ba 100644
--- a/src/partest/scala/tools/partest/package.scala
+++ b/src/partest/scala/tools/partest/package.scala
@@ -4,31 +4,102 @@
package scala.tools
-import java.io.{ FileNotFoundException, File => JFile }
-import nsc.io.{ Path, Directory, File => SFile }
-import scala.tools.util.PathResolver
-import nsc.Properties.{ propOrElse, propOrNone, propOrEmpty }
import scala.sys.process.javaVmArguments
import java.util.concurrent.Callable
+import scala.tools.partest.nest.NestUI
+import scala.tools.nsc.util.{ ScalaClassLoader, Exceptional }
-package partest {
- class TestState { }
- object TestState {
- val Ok = new TestState
- val Fail = new TestState
- val Timeout = new TestState
+package object partest {
+ type File = java.io.File
+ type SFile = scala.reflect.io.File
+ type Directory = scala.reflect.io.Directory
+ type Path = scala.reflect.io.Path
+ type PathResolver = scala.tools.util.PathResolver
+ type ClassPath[T] = scala.tools.nsc.util.ClassPath[T]
+ type StringWriter = java.io.StringWriter
+
+ val SFile = scala.reflect.io.File
+ val Directory = scala.reflect.io.Directory
+ val Path = scala.reflect.io.Path
+ val PathResolver = scala.tools.util.PathResolver
+ val ClassPath = scala.tools.nsc.util.ClassPath
+
+ val space = "\u0020"
+ val EOL = scala.compat.Platform.EOL
+ def onull(s: String) = if (s == null) "" else s
+ def oempty(xs: String*) = xs filterNot (x => x == null || x == "")
+ def ojoin(xs: String*): String = oempty(xs: _*) mkString space
+ def nljoin(xs: String*): String = oempty(xs: _*) mkString EOL
+
+ def setUncaughtHandler() = {
+ Thread.setDefaultUncaughtExceptionHandler(
+ new Thread.UncaughtExceptionHandler {
+ def uncaughtException(thread: Thread, t: Throwable) {
+ val t1 = Exceptional unwrap t
+ System.err.println(s"Uncaught exception on thread $thread: $t1")
+ t1.printStackTrace()
+ }
+ }
+ )
}
-}
-package object partest {
- import nest.NestUI
+ /** Sources have a numerical group, specified by name_7 and so on. */
+ private val GroupPattern = """.*_(\d+)""".r
+
+ implicit class FileOps(val f: File) {
+ private def sf = SFile(f)
+
+ def testIdent = {
+ f.toString split """[/\\]+""" takeRight 2 mkString "/" // e.g. pos/t1234
+ }
+
+ def mapInPlace(mapFn: String => String): Unit =
+ writeAll(fileLines.map(x => mapFn(x) + "\n"): _*)
+
+ def appendAll(strings: String*): Unit = sf.appendAll(strings: _*)
+ def writeAll(strings: String*): Unit = sf.writeAll(strings: _*)
+ def absolutePathSegments: List[String] = f.getAbsolutePath split """[/\\]+""" toList
+
+ def isJava = f.isFile && (sf hasExtension "java")
+ def isScala = f.isFile && (sf hasExtension "scala")
+ def isJavaOrScala = isJava || isScala
+
+ def extension = sf.extension
+ def hasExtension(ext: String) = sf hasExtension ext
+ def changeExtension(ext: String): File = (sf changeExtension ext).jfile
+
+ /** The group number for this source file, or -1 for no group. */
+ def group: Int =
+ sf.stripExtension match {
+ case GroupPattern(g) if g.toInt >= 0 => g.toInt
+ case _ => -1
+ }
+
+ def fileContents: String = try sf.slurp() catch { case _: java.io.FileNotFoundException => "" }
+ def fileLines: List[String] = augmentString(fileContents).lines.toList
+ }
+
+ implicit class PathOps(p: Path) extends FileOps(p.jfile) { }
+
+ implicit class Copier(val f: SFile) extends AnyVal {
+ def copyTo(dest: Path): Unit = dest.toFile writeAll f.slurp(scala.io.Codec.UTF8)
+ }
- implicit private[partest] def temporaryPath2File(x: Path): JFile = x.jfile
- implicit private[partest] def temporaryFile2Path(x: JFile): Path = Path(x)
+ implicit def temporaryPath2File(x: Path): File = x.jfile
+ implicit def stringPathToJavaFile(path: String): File = new File(path)
implicit lazy val postfixOps = scala.language.postfixOps
implicit lazy val implicitConversions = scala.language.implicitConversions
+ def fileSeparator = java.io.File.separator
+ def pathSeparator = java.io.File.pathSeparator
+
+ def pathToTestIdent(path: Path) = path.jfile.testIdent
+
+ def canonicalizeSlashes(line: String) = line.replaceAll("""[/\\]+""", "/")
+
+ def words(s: String): List[String] = (s.trim split "\\s+").toList
+
def timed[T](body: => T): (T, Long) = {
val t1 = System.currentTimeMillis
val result = body
@@ -39,15 +110,40 @@ package object partest {
def callable[T](body: => T): Callable[T] = new Callable[T] { override def call() = body }
- def file2String(f: JFile) =
- try SFile(f).slurp(scala.io.Codec.UTF8)
- catch { case _: FileNotFoundException => "" }
+ def file2String(f: File): String = f.fileContents
def basename(name: String): String = Path(name).stripExtension
- def resultsToStatistics(results: Iterable[(_, TestState)]): (Int, Int) = {
- val (files, failures) = results map (_._2 == TestState.Ok) partition (_ == true)
- (files.size, failures.size)
+ /** In order to allow for spaces in flags/options, this
+ * parses .flags, .javaopts, javacopts etc files as follows:
+ * If it is exactly one line, it is split (naively) on spaces.
+ * If it contains more than one line, each line is its own
+ * token, spaces and all.
+ */
+ def readOptionsFile(file: File): List[String] = {
+ file.fileLines match {
+ case x :: Nil => words(x)
+ case xs => xs map (_.trim)
+ }
+ }
+
+ def findProgram(name: String): Option[File] = {
+ val pathDirs = sys.env("PATH") match {
+ case null => List("/usr/local/bin", "/usr/bin", "/bin")
+ case path => path split "[:;]" filterNot (_ == "") toList
+ }
+ pathDirs.iterator map (d => new File(d, name)) find (_.canExecute)
+ }
+
+ def now = (new java.util.Date).toString
+ def elapsedString(millis: Long): String = {
+ val elapsedSecs = millis/1000
+ val elapsedMins = elapsedSecs/60
+ val elapsedHrs = elapsedMins/60
+ val dispMins = elapsedMins - elapsedHrs * 60
+ val dispSecs = elapsedSecs - elapsedMins * 60
+
+ "%02d:%02d:%02d".format(elapsedHrs, dispMins, dispSecs)
}
def vmArgString = javaVmArguments.mkString(
@@ -62,13 +158,10 @@ package object partest {
}
def showAllJVMInfo() {
- NestUI.verbose(vmArgString)
- NestUI.verbose(allPropertiesString)
+ vlog(vmArgString)
+ vlog(allPropertiesString)
}
- def isPartestDebug: Boolean =
- propOrEmpty("partest.debug") == "true"
-
import scala.language.experimental.macros
/**
@@ -117,4 +210,10 @@ package object partest {
a.tree))))),
a.tree))
}
+
+ def isPartestTerse = NestUI.isTerse
+ def isPartestDebug = NestUI.isDebug
+ def isPartestVerbose = NestUI.isVerbose
+
+ def vlog(msg: => String) = if (isPartestVerbose) System.err.println(msg)
}
diff --git a/src/reflect/scala/reflect/api/Annotations.scala b/src/reflect/scala/reflect/api/Annotations.scala
index 09eaf7afb4..f87e10c792 100644
--- a/src/reflect/scala/reflect/api/Annotations.scala
+++ b/src/reflect/scala/reflect/api/Annotations.scala
@@ -45,12 +45,6 @@ trait Annotations { self: Universe =>
*/
type Annotation >: Null <: AnyRef with AnnotationApi
- /** A tag that preserves the identity of the `Annotation` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val AnnotationTag: ClassTag[Annotation]
-
/** The constructor/extractor for `Annotation` instances.
* @group Extractors
*/
@@ -90,11 +84,6 @@ trait Annotations { self: Universe =>
*/
type JavaArgument >: Null <: AnyRef
- /** A tag that preserves the identity of the `JavaArgument` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val JavaArgumentTag: ClassTag[JavaArgument]
/** A literal argument to a Java annotation as `"Use X instead"` in `@Deprecated("Use X instead")`
* @template
@@ -102,12 +91,6 @@ trait Annotations { self: Universe =>
*/
type LiteralArgument >: Null <: AnyRef with JavaArgument with LiteralArgumentApi
- /** A tag that preserves the identity of the `LiteralArgument` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val LiteralArgumentTag: ClassTag[LiteralArgument]
-
/** The constructor/extractor for `LiteralArgument` instances.
* @group Extractors
*/
@@ -137,12 +120,6 @@ trait Annotations { self: Universe =>
*/
type ArrayArgument >: Null <: AnyRef with JavaArgument with ArrayArgumentApi
- /** A tag that preserves the identity of the `ArrayArgument` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ArrayArgumentTag: ClassTag[ArrayArgument]
-
/** The constructor/extractor for `ArrayArgument` instances.
* @group Extractors
*/
@@ -172,12 +149,6 @@ trait Annotations { self: Universe =>
*/
type NestedArgument >: Null <: AnyRef with JavaArgument with NestedArgumentApi
- /** A tag that preserves the identity of the `NestedArgument` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val NestedArgumentTag: ClassTag[NestedArgument]
-
/** The constructor/extractor for `NestedArgument` instances.
* @group Extractors
*/
@@ -200,4 +171,4 @@ trait Annotations { self: Universe =>
/** The underlying nested annotation. */
def annotation: Annotation
}
-} \ No newline at end of file
+}
diff --git a/src/reflect/scala/reflect/api/Constants.scala b/src/reflect/scala/reflect/api/Constants.scala
index f3d75c3c00..0b7dd5582a 100644
--- a/src/reflect/scala/reflect/api/Constants.scala
+++ b/src/reflect/scala/reflect/api/Constants.scala
@@ -183,12 +183,6 @@ trait Constants {
*/
type Constant >: Null <: AnyRef with ConstantApi
- /** A tag that preserves the identity of the `Constant` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ConstantTag: ClassTag[Constant]
-
/** The constructor/extractor for `Constant` instances.
* @group Extractors
*/
diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala
index 4357aec9c9..712236cce1 100644
--- a/src/reflect/scala/reflect/api/FlagSets.scala
+++ b/src/reflect/scala/reflect/api/FlagSets.scala
@@ -61,12 +61,6 @@ trait FlagSets { self: Universe =>
*/
type FlagSet
- /** A tag that preserves the identity of the `FlagSet` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val FlagSetTag: ClassTag[FlagSet]
-
/** The API of `FlagSet` instances.
* The main source of information about flag sets is the [[scala.reflect.api.FlagSets]] page.
* @group Flags
diff --git a/src/reflect/scala/reflect/api/ImplicitTags.scala b/src/reflect/scala/reflect/api/ImplicitTags.scala
index 3f377d6cff..fdc1d9017b 100644
--- a/src/reflect/scala/reflect/api/ImplicitTags.scala
+++ b/src/reflect/scala/reflect/api/ImplicitTags.scala
@@ -1,108 +1,116 @@
package scala.reflect
package api
+/** Tags which preserve the identity of abstract types in the face of erasure.
+ * Can be used for pattern matching, instance tests, serialization and the like.
+ * @group Tags
+ */
trait ImplicitTags {
- self: Types =>
+ self: Universe =>
- /** A tag that preserves the identity of the `Type` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeTagg: ClassTag[Type]
-
- /** A tag that preserves the identity of the `SingletonType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SingletonTypeTag: ClassTag[SingletonType]
-
- /** A tag that preserves the identity of the `ThisType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ThisTypeTag: ClassTag[ThisType]
-
- /** A tag that preserves the identity of the `SingleType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SingleTypeTag: ClassTag[SingleType]
-
- /** A tag that preserves the identity of the `SuperType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SuperTypeTag: ClassTag[SuperType]
-
- /** A tag that preserves the identity of the `ConstantType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ConstantTypeTag: ClassTag[ConstantType]
-
- /** A tag that preserves the identity of the `TypeRef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeRefTag: ClassTag[TypeRef]
-
- /** A tag that preserves the identity of the `CompoundType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val CompoundTypeTag: ClassTag[CompoundType]
-
- /** A tag that preserves the identity of the `RefinedType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val RefinedTypeTag: ClassTag[RefinedType]
-
- /** A tag that preserves the identity of the `ClassInfoType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
+ // Tags for Types.
+ implicit val AnnotatedTypeTag: ClassTag[AnnotatedType]
+ implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType]
implicit val ClassInfoTypeTag: ClassTag[ClassInfoType]
-
- /** A tag that preserves the identity of the `MethodType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
+ implicit val CompoundTypeTag: ClassTag[CompoundType]
+ implicit val ConstantTypeTag: ClassTag[ConstantType]
+ implicit val ExistentialTypeTag: ClassTag[ExistentialType]
implicit val MethodTypeTag: ClassTag[MethodType]
-
- /** A tag that preserves the identity of the `NullaryMethodType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
implicit val NullaryMethodTypeTag: ClassTag[NullaryMethodType]
-
- /** A tag that preserves the identity of the `PolyType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
implicit val PolyTypeTag: ClassTag[PolyType]
-
- /** A tag that preserves the identity of the `ExistentialType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ExistentialTypeTag: ClassTag[ExistentialType]
-
- /** A tag that preserves the identity of the `AnnotatedType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val AnnotatedTypeTag: ClassTag[AnnotatedType]
-
- /** A tag that preserves the identity of the `TypeBounds` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
+ implicit val RefinedTypeTag: ClassTag[RefinedType]
+ implicit val SingleTypeTag: ClassTag[SingleType]
+ implicit val SingletonTypeTag: ClassTag[SingletonType]
+ implicit val SuperTypeTag: ClassTag[SuperType]
+ implicit val ThisTypeTag: ClassTag[ThisType]
implicit val TypeBoundsTag: ClassTag[TypeBounds]
+ implicit val TypeRefTag: ClassTag[TypeRef]
+ implicit val TypeTagg: ClassTag[Type]
- /** A tag that preserves the identity of the `BoundedWildcardType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType]
+ // Tags for Names.
+ implicit val NameTag: ClassTag[Name]
+ implicit val TermNameTag: ClassTag[TermName]
+ implicit val TypeNameTag: ClassTag[TypeName]
+
+ // Tags for Scopes.
+ implicit val ScopeTag: ClassTag[Scope]
+ implicit val MemberScopeTag: ClassTag[MemberScope]
+
+ // Tags for Annotations.
+ implicit val AnnotationTag: ClassTag[Annotation]
+ implicit val JavaArgumentTag: ClassTag[JavaArgument]
+ implicit val LiteralArgumentTag: ClassTag[LiteralArgument]
+ implicit val ArrayArgumentTag: ClassTag[ArrayArgument]
+ implicit val NestedArgumentTag: ClassTag[NestedArgument]
+
+ // Tags for Symbols.
+ implicit val TermSymbolTag: ClassTag[TermSymbol]
+ implicit val MethodSymbolTag: ClassTag[MethodSymbol]
+ implicit val SymbolTag: ClassTag[Symbol]
+ implicit val TypeSymbolTag: ClassTag[TypeSymbol]
+ implicit val ModuleSymbolTag: ClassTag[ModuleSymbol]
+ implicit val ClassSymbolTag: ClassTag[ClassSymbol]
+ implicit val FreeTermSymbolTag: ClassTag[FreeTermSymbol]
+ implicit val FreeTypeSymbolTag: ClassTag[FreeTypeSymbol]
+
+ // Tags for misc Tree relatives.
+ implicit val PositionTag: ClassTag[Position]
+ implicit val ConstantTag: ClassTag[Constant]
+ implicit val FlagSetTag: ClassTag[FlagSet]
+ implicit val ModifiersTag: ClassTag[Modifiers]
+
+ // Tags for Trees. WTF.
+ implicit val AlternativeTag: ClassTag[Alternative]
+ implicit val AnnotatedTag: ClassTag[Annotated]
+ implicit val AppliedTypeTreeTag: ClassTag[AppliedTypeTree]
+ implicit val ApplyTag: ClassTag[Apply]
+ implicit val AssignOrNamedArgTag: ClassTag[AssignOrNamedArg]
+ implicit val AssignTag: ClassTag[Assign]
+ implicit val BindTag: ClassTag[Bind]
+ implicit val BlockTag: ClassTag[Block]
+ implicit val CaseDefTag: ClassTag[CaseDef]
+ implicit val ClassDefTag: ClassTag[ClassDef]
+ implicit val CompoundTypeTreeTag: ClassTag[CompoundTypeTree]
+ implicit val DefDefTag: ClassTag[DefDef]
+ implicit val DefTreeTag: ClassTag[DefTree]
+ implicit val ExistentialTypeTreeTag: ClassTag[ExistentialTypeTree]
+ implicit val FunctionTag: ClassTag[Function]
+ implicit val GenericApplyTag: ClassTag[GenericApply]
+ implicit val IdentTag: ClassTag[Ident]
+ implicit val IfTag: ClassTag[If]
+ implicit val ImplDefTag: ClassTag[ImplDef]
+ implicit val ImportSelectorTag: ClassTag[ImportSelector]
+ implicit val ImportTag: ClassTag[Import]
+ implicit val LabelDefTag: ClassTag[LabelDef]
+ implicit val LiteralTag: ClassTag[Literal]
+ implicit val MatchTag: ClassTag[Match]
+ implicit val MemberDefTag: ClassTag[MemberDef]
+ implicit val ModuleDefTag: ClassTag[ModuleDef]
+ implicit val NameTreeTag: ClassTag[NameTree]
+ implicit val NewTag: ClassTag[New]
+ implicit val PackageDefTag: ClassTag[PackageDef]
+ implicit val RefTreeTag: ClassTag[RefTree]
+ implicit val ReferenceToBoxedTag: ClassTag[ReferenceToBoxed]
+ implicit val ReturnTag: ClassTag[Return]
+ implicit val SelectFromTypeTreeTag: ClassTag[SelectFromTypeTree]
+ implicit val SelectTag: ClassTag[Select]
+ implicit val SingletonTypeTreeTag: ClassTag[SingletonTypeTree]
+ implicit val StarTag: ClassTag[Star]
+ implicit val SuperTag: ClassTag[Super]
+ implicit val SymTreeTag: ClassTag[SymTree]
+ implicit val TemplateTag: ClassTag[Template]
+ implicit val TermTreeTag: ClassTag[TermTree]
+ implicit val ThisTag: ClassTag[This]
+ implicit val ThrowTag: ClassTag[Throw]
+ implicit val TreeTag: ClassTag[Tree]
+ implicit val TryTag: ClassTag[Try]
+ implicit val TypTreeTag: ClassTag[TypTree]
+ implicit val TypeApplyTag: ClassTag[TypeApply]
+ implicit val TypeBoundsTreeTag: ClassTag[TypeBoundsTree]
+ implicit val TypeDefTag: ClassTag[TypeDef]
+ implicit val TypeTreeTag: ClassTag[TypeTree]
+ implicit val TypedTag: ClassTag[Typed]
+ implicit val UnApplyTag: ClassTag[UnApply]
+ implicit val ValDefTag: ClassTag[ValDef]
+ implicit val ValOrDefDefTag: ClassTag[ValOrDefDef]
}
diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala
index 6290b88d33..e7840a13fb 100644
--- a/src/reflect/scala/reflect/api/Names.scala
+++ b/src/reflect/scala/reflect/api/Names.scala
@@ -43,34 +43,16 @@ trait Names {
*/
type Name >: Null <: NameApi
- /** A tag that preserves the identity of the `Name` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val NameTag: ClassTag[Name]
-
/** The abstract type of names representing terms.
* @group Names
*/
type TypeName >: Null <: Name
- /** A tag that preserves the identity of the `TypeName` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeNameTag: ClassTag[TypeName]
-
/** The abstract type of names representing types.
* @group Names
*/
type TermName >: Null <: Name
- /** A tag that preserves the identity of the `TermName` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TermNameTag: ClassTag[TermName]
-
/** The API of Name instances.
* @group API
*/
diff --git a/src/reflect/scala/reflect/api/Positions.scala b/src/reflect/scala/reflect/api/Positions.scala
index 87f00fdb88..6edf8e13e4 100644
--- a/src/reflect/scala/reflect/api/Positions.scala
+++ b/src/reflect/scala/reflect/api/Positions.scala
@@ -19,13 +19,6 @@ trait Positions {
* @group Positions
*/
type Position >: Null <: scala.reflect.api.Position { type Pos = Position }
-
- /** A tag that preserves the identity of the `Position` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val PositionTag: ClassTag[Position]
-
/** A special "missing" position.
* @group Positions
*/
diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala
index d9e05e77c1..162fe1296b 100644
--- a/src/reflect/scala/reflect/api/Printers.scala
+++ b/src/reflect/scala/reflect/api/Printers.scala
@@ -163,6 +163,8 @@ trait Printers { self: Universe =>
import scala.language.implicitConversions
implicit def booleanToBooleanFlag(value: Boolean): BooleanFlag = BooleanFlag(Some(value))
implicit def optionToBooleanFlag(value: Option[Boolean]): BooleanFlag = BooleanFlag(value)
+ import scala.reflect.internal.settings.MutableSettings
+ implicit def settingToBooleanFlag(setting: MutableSettings#BooleanSetting): BooleanFlag = BooleanFlag(Some(setting.value))
}
/** @group Printers */
diff --git a/src/reflect/scala/reflect/api/Scopes.scala b/src/reflect/scala/reflect/api/Scopes.scala
index 7f9799393c..4bab6b6a04 100644
--- a/src/reflect/scala/reflect/api/Scopes.scala
+++ b/src/reflect/scala/reflect/api/Scopes.scala
@@ -33,12 +33,6 @@ trait Scopes { self: Universe =>
*/
trait ScopeApi extends Iterable[Symbol]
- /** A tag that preserves the identity of the `Scope` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ScopeTag: ClassTag[Scope]
-
/** Create a new scope with the given initial elements.
* @group Scopes
*/
@@ -61,10 +55,4 @@ trait Scopes { self: Universe =>
*/
def sorted: List[Symbol]
}
-
- /** A tag that preserves the identity of the `MemberScope` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val MemberScopeTag: ClassTag[MemberScope]
-} \ No newline at end of file
+}
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index dbad3dd478..7225919de5 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -61,12 +61,6 @@ trait Symbols { self: Universe =>
*/
type Symbol >: Null <: SymbolApi
- /** A tag that preserves the identity of the `Symbol` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SymbolTag: ClassTag[Symbol]
-
/** The type of type symbols representing type, class, and trait declarations,
* as well as type parameters.
* @group Symbols
@@ -74,12 +68,6 @@ trait Symbols { self: Universe =>
*/
type TypeSymbol >: Null <: Symbol with TypeSymbolApi
- /** A tag that preserves the identity of the `TypeSymbol` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeSymbolTag: ClassTag[TypeSymbol]
-
/** The type of term symbols representing val, var, def, and object declarations as
* well as packages and value parameters.
* @group Symbols
@@ -87,72 +75,36 @@ trait Symbols { self: Universe =>
*/
type TermSymbol >: Null <: Symbol with TermSymbolApi
- /** A tag that preserves the identity of the `TermSymbol` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TermSymbolTag: ClassTag[TermSymbol]
-
/** The type of method symbols representing def declarations.
* @group Symbols
* @template
*/
type MethodSymbol >: Null <: TermSymbol with MethodSymbolApi
- /** A tag that preserves the identity of the `MethodSymbol` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val MethodSymbolTag: ClassTag[MethodSymbol]
-
/** The type of module symbols representing object declarations.
* @group Symbols
* @template
*/
type ModuleSymbol >: Null <: TermSymbol with ModuleSymbolApi
- /** A tag that preserves the identity of the `ModuleSymbol` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ModuleSymbolTag: ClassTag[ModuleSymbol]
-
/** The type of class symbols representing class and trait definitions.
* @group Symbols
* @template
*/
type ClassSymbol >: Null <: TypeSymbol with ClassSymbolApi
- /** A tag that preserves the identity of the `ClassSymbol` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ClassSymbolTag: ClassTag[ClassSymbol]
-
/** The type of free terms introduced by reification.
* @group Symbols
* @template
*/
type FreeTermSymbol >: Null <: TermSymbol with FreeTermSymbolApi
- /** A tag that preserves the identity of the `FreeTermSymbol` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val FreeTermSymbolTag: ClassTag[FreeTermSymbol]
-
/** The type of free types introduced by reification.
* @group Symbols
* @template
*/
type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolApi
- /** A tag that preserves the identity of the `FreeTypeSymbol` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val FreeTypeSymbolTag: ClassTag[FreeTypeSymbol]
-
/** A special "missing" symbol. Commonly used in the API to denote a default or empty value.
* @group Symbols
* @template
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala
index 18985fe83d..99b5ef87f8 100644
--- a/src/reflect/scala/reflect/api/Trees.scala
+++ b/src/reflect/scala/reflect/api/Trees.scala
@@ -60,12 +60,6 @@ trait Trees { self: Universe =>
*/
type Tree >: Null <: TreeApi
- /** A tag that preserves the identity of the `Tree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TreeTag: ClassTag[Tree]
-
/** The API that all trees support.
* The main source of information about trees is the [[scala.reflect.api.Trees]] page.
* @group API
@@ -230,12 +224,6 @@ trait Trees { self: Universe =>
*/
type TermTree >: Null <: AnyRef with Tree with TermTreeApi
- /** A tag that preserves the identity of the `TermTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TermTreeTag: ClassTag[TermTree]
-
/** The API that all term trees support
* @group API
*/
@@ -249,12 +237,6 @@ trait Trees { self: Universe =>
*/
type TypTree >: Null <: AnyRef with Tree with TypTreeApi
- /** A tag that preserves the identity of the `TypTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypTreeTag: ClassTag[TypTree]
-
/** The API that all typ trees support
* @group API
*/
@@ -267,12 +249,6 @@ trait Trees { self: Universe =>
*/
type SymTree >: Null <: AnyRef with Tree with SymTreeApi
- /** A tag that preserves the identity of the `SymTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SymTreeTag: ClassTag[SymTree]
-
/** The API that all sym trees support
* @group API
*/
@@ -287,12 +263,6 @@ trait Trees { self: Universe =>
*/
type NameTree >: Null <: AnyRef with Tree with NameTreeApi
- /** A tag that preserves the identity of the `NameTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val NameTreeTag: ClassTag[NameTree]
-
/** The API that all name trees support
* @group API
*/
@@ -311,12 +281,6 @@ trait Trees { self: Universe =>
*/
type RefTree >: Null <: SymTree with NameTree with RefTreeApi
- /** A tag that preserves the identity of the `RefTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val RefTreeTag: ClassTag[RefTree]
-
/** The API that all ref trees support
* @group API
*/
@@ -337,12 +301,6 @@ trait Trees { self: Universe =>
*/
type DefTree >: Null <: SymTree with NameTree with DefTreeApi
- /** A tag that preserves the identity of the `DefTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val DefTreeTag: ClassTag[DefTree]
-
/** The API that all def trees support
* @group API
*/
@@ -358,12 +316,6 @@ trait Trees { self: Universe =>
*/
type MemberDef >: Null <: DefTree with MemberDefApi
- /** A tag that preserves the identity of the `MemberDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val MemberDefTag: ClassTag[MemberDef]
-
/** The API that all member defs support
* @group API
*/
@@ -378,12 +330,6 @@ trait Trees { self: Universe =>
*/
type PackageDef >: Null <: MemberDef with PackageDefApi
- /** A tag that preserves the identity of the `PackageDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val PackageDefTag: ClassTag[PackageDef]
-
/** The constructor/extractor for `PackageDef` instances.
* @group Extractors
*/
@@ -417,12 +363,6 @@ trait Trees { self: Universe =>
*/
type ImplDef >: Null <: MemberDef with ImplDefApi
- /** A tag that preserves the identity of the `ImplDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ImplDefTag: ClassTag[ImplDef]
-
/** The API that all impl defs support
* @group API
*/
@@ -437,12 +377,6 @@ trait Trees { self: Universe =>
*/
type ClassDef >: Null <: ImplDef with ClassDefApi
- /** A tag that preserves the identity of the `ClassDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ClassDefTag: ClassTag[ClassDef]
-
/** The constructor/extractor for `ClassDef` instances.
* @group Extractors
*/
@@ -488,12 +422,6 @@ trait Trees { self: Universe =>
*/
type ModuleDef >: Null <: ImplDef with ModuleDefApi
- /** A tag that preserves the identity of the `ModuleDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ModuleDefTag: ClassTag[ModuleDef]
-
/** The constructor/extractor for `ModuleDef` instances.
* @group Extractors
*/
@@ -534,12 +462,6 @@ trait Trees { self: Universe =>
*/
type ValOrDefDef >: Null <: MemberDef with ValOrDefDefApi
- /** A tag that preserves the identity of the `ValOrDefDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ValOrDefDefTag: ClassTag[ValOrDefDef]
-
/** The API that all val defs and def defs support
* @group API
*/
@@ -571,12 +493,6 @@ trait Trees { self: Universe =>
*/
type ValDef >: Null <: ValOrDefDef with ValDefApi
- /** A tag that preserves the identity of the `ValDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ValDefTag: ClassTag[ValDef]
-
/** The constructor/extractor for `ValDef` instances.
* @group Extractors
*/
@@ -626,12 +542,6 @@ trait Trees { self: Universe =>
*/
type DefDef >: Null <: ValOrDefDef with DefDefApi
- /** A tag that preserves the identity of the `DefDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val DefDefTag: ClassTag[DefDef]
-
/** The constructor/extractor for `DefDef` instances.
* @group Extractors
*/
@@ -681,12 +591,6 @@ trait Trees { self: Universe =>
*/
type TypeDef >: Null <: MemberDef with TypeDefApi
- /** A tag that preserves the identity of the `TypeDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeDefTag: ClassTag[TypeDef]
-
/** The constructor/extractor for `TypeDef` instances.
* @group Extractors
*/
@@ -746,12 +650,6 @@ trait Trees { self: Universe =>
*/
type LabelDef >: Null <: DefTree with TermTree with LabelDefApi
- /** A tag that preserves the identity of the `LabelDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val LabelDefTag: ClassTag[LabelDef]
-
/** The constructor/extractor for `LabelDef` instances.
* @group Extractors
*/
@@ -808,12 +706,6 @@ trait Trees { self: Universe =>
*/
type ImportSelector >: Null <: AnyRef with ImportSelectorApi
- /** A tag that preserves the identity of the `ImportSelector` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ImportSelectorTag: ClassTag[ImportSelector]
-
/** The constructor/extractor for `ImportSelector` instances.
* @group Extractors
*/
@@ -860,12 +752,6 @@ trait Trees { self: Universe =>
*/
type Import >: Null <: SymTree with ImportApi
- /** A tag that preserves the identity of the `Import` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ImportTag: ClassTag[Import]
-
/** The constructor/extractor for `Import` instances.
* @group Extractors
*/
@@ -918,12 +804,6 @@ trait Trees { self: Universe =>
*/
type Template >: Null <: SymTree with TemplateApi
- /** A tag that preserves the identity of the `Template` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TemplateTag: ClassTag[Template]
-
/** The constructor/extractor for `Template` instances.
* @group Extractors
*/
@@ -976,12 +856,6 @@ trait Trees { self: Universe =>
*/
type Block >: Null <: TermTree with BlockApi
- /** A tag that preserves the identity of the `Block` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val BlockTag: ClassTag[Block]
-
/** The constructor/extractor for `Block` instances.
* @group Extractors
*/
@@ -1021,12 +895,6 @@ trait Trees { self: Universe =>
*/
type CaseDef >: Null <: AnyRef with Tree with CaseDefApi
- /** A tag that preserves the identity of the `CaseDef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val CaseDefTag: ClassTag[CaseDef]
-
/** The constructor/extractor for `CaseDef` instances.
* @group Extractors
*/
@@ -1074,12 +942,6 @@ trait Trees { self: Universe =>
*/
type Alternative >: Null <: TermTree with AlternativeApi
- /** A tag that preserves the identity of the `Alternative` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val AlternativeTag: ClassTag[Alternative]
-
/** The constructor/extractor for `Alternative` instances.
* @group Extractors
*/
@@ -1112,12 +974,6 @@ trait Trees { self: Universe =>
*/
type Star >: Null <: TermTree with StarApi
- /** A tag that preserves the identity of the `Star` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val StarTag: ClassTag[Star]
-
/** The constructor/extractor for `Star` instances.
* @group Extractors
*/
@@ -1153,12 +1009,6 @@ trait Trees { self: Universe =>
*/
type Bind >: Null <: DefTree with BindApi
- /** A tag that preserves the identity of the `Bind` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val BindTag: ClassTag[Bind]
-
/** The constructor/extractor for `Bind` instances.
* @group Extractors
*/
@@ -1222,12 +1072,6 @@ trait Trees { self: Universe =>
*/
type UnApply >: Null <: TermTree with UnApplyApi
- /** A tag that preserves the identity of the `UnApply` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val UnApplyTag: ClassTag[UnApply]
-
/** The constructor/extractor for `UnApply` instances.
* @group Extractors
*/
@@ -1264,12 +1108,6 @@ trait Trees { self: Universe =>
*/
type Function >: Null <: TermTree with SymTree with FunctionApi
- /** A tag that preserves the identity of the `Function` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val FunctionTag: ClassTag[Function]
-
/** The constructor/extractor for `Function` instances.
* @group Extractors
*/
@@ -1308,12 +1146,6 @@ trait Trees { self: Universe =>
*/
type Assign >: Null <: TermTree with AssignApi
- /** A tag that preserves the identity of the `Assign` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val AssignTag: ClassTag[Assign]
-
/** The constructor/extractor for `Assign` instances.
* @group Extractors
*/
@@ -1350,12 +1182,6 @@ trait Trees { self: Universe =>
*/
type AssignOrNamedArg >: Null <: TermTree with AssignOrNamedArgApi
- /** A tag that preserves the identity of the `AssignOrNamedArg` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val AssignOrNamedArgTag: ClassTag[AssignOrNamedArg]
-
/** The constructor/extractor for `AssignOrNamedArg` instances.
* @group Extractors
*/
@@ -1397,12 +1223,6 @@ trait Trees { self: Universe =>
*/
type If >: Null <: TermTree with IfApi
- /** A tag that preserves the identity of the `If` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val IfTag: ClassTag[If]
-
/** The constructor/extractor for `If` instances.
* @group Extractors
*/
@@ -1454,12 +1274,6 @@ trait Trees { self: Universe =>
*/
type Match >: Null <: TermTree with MatchApi
- /** A tag that preserves the identity of the `Match` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val MatchTag: ClassTag[Match]
-
/** The constructor/extractor for `Match` instances.
* @group Extractors
*/
@@ -1495,12 +1309,6 @@ trait Trees { self: Universe =>
*/
type Return >: Null <: TermTree with SymTree with ReturnApi
- /** A tag that preserves the identity of the `Return` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ReturnTag: ClassTag[Return]
-
/** The constructor/extractor for `Return` instances.
* @group Extractors
*/
@@ -1533,12 +1341,6 @@ trait Trees { self: Universe =>
*/
type Try >: Null <: TermTree with TryApi
- /** A tag that preserves the identity of the `Try` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TryTag: ClassTag[Try]
-
/** The constructor/extractor for `Try` instances.
* @group Extractors
*/
@@ -1577,12 +1379,6 @@ trait Trees { self: Universe =>
*/
type Throw >: Null <: TermTree with ThrowApi
- /** A tag that preserves the identity of the `Throw` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ThrowTag: ClassTag[Throw]
-
/** The constructor/extractor for `Throw` instances.
* @group Extractors
*/
@@ -1613,12 +1409,6 @@ trait Trees { self: Universe =>
*/
type New >: Null <: TermTree with NewApi
- /** A tag that preserves the identity of the `New` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val NewTag: ClassTag[New]
-
/** The constructor/extractor for `New` instances.
* @group Extractors
*/
@@ -1669,12 +1459,6 @@ trait Trees { self: Universe =>
*/
type Typed >: Null <: TermTree with TypedApi
- /** A tag that preserves the identity of the `Typed` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypedTag: ClassTag[Typed]
-
/** The constructor/extractor for `Typed` instances.
* @group Extractors
*/
@@ -1708,12 +1492,6 @@ trait Trees { self: Universe =>
*/
type GenericApply >: Null <: TermTree with GenericApplyApi
- /** A tag that preserves the identity of the `GenericApply` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val GenericApplyTag: ClassTag[GenericApply]
-
/** The API that all applies support
* @group API
*/
@@ -1735,12 +1513,6 @@ trait Trees { self: Universe =>
*/
type TypeApply >: Null <: GenericApply with TypeApplyApi
- /** A tag that preserves the identity of the `TypeApply` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeApplyTag: ClassTag[TypeApply]
-
/** The constructor/extractor for `TypeApply` instances.
* @group Extractors
*/
@@ -1779,12 +1551,6 @@ trait Trees { self: Universe =>
*/
type Apply >: Null <: GenericApply with ApplyApi
- /** A tag that preserves the identity of the `Apply` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ApplyTag: ClassTag[Apply]
-
/** The constructor/extractor for `Apply` instances.
* @group Extractors
*/
@@ -1822,12 +1588,6 @@ trait Trees { self: Universe =>
*/
type Super >: Null <: TermTree with SuperApi
- /** A tag that preserves the identity of the `Super` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SuperTag: ClassTag[Super]
-
/** The constructor/extractor for `Super` instances.
* @group Extractors
*/
@@ -1874,12 +1634,6 @@ trait Trees { self: Universe =>
*/
type This >: Null <: TermTree with SymTree with ThisApi
- /** A tag that preserves the identity of the `This` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ThisTag: ClassTag[This]
-
/** The constructor/extractor for `This` instances.
* @group Extractors
*/
@@ -1915,12 +1669,6 @@ trait Trees { self: Universe =>
*/
type Select >: Null <: RefTree with SelectApi
- /** A tag that preserves the identity of the `Select` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SelectTag: ClassTag[Select]
-
/** The constructor/extractor for `Select` instances.
* @group Extractors
*/
@@ -1960,12 +1708,6 @@ trait Trees { self: Universe =>
*/
type Ident >: Null <: RefTree with IdentApi
- /** A tag that preserves the identity of the `Ident` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val IdentTag: ClassTag[Ident]
-
/** The constructor/extractor for `Ident` instances.
* @group Extractors
*/
@@ -2005,12 +1747,6 @@ trait Trees { self: Universe =>
*/
type ReferenceToBoxed >: Null <: TermTree with ReferenceToBoxedApi
- /** A tag that preserves the identity of the `ReferenceToBoxed` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ReferenceToBoxedTag: ClassTag[ReferenceToBoxed]
-
/** The constructor/extractor for `ReferenceToBoxed` instances.
* @group Extractors
*/
@@ -2055,12 +1791,6 @@ trait Trees { self: Universe =>
*/
type Literal >: Null <: TermTree with LiteralApi
- /** A tag that preserves the identity of the `Literal` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val LiteralTag: ClassTag[Literal]
-
/** The constructor/extractor for `Literal` instances.
* @group Extractors
*/
@@ -2094,12 +1824,6 @@ trait Trees { self: Universe =>
*/
type Annotated >: Null <: AnyRef with Tree with AnnotatedApi
- /** A tag that preserves the identity of the `Annotated` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val AnnotatedTag: ClassTag[Annotated]
-
/** The constructor/extractor for `Annotated` instances.
* @group Extractors
*/
@@ -2134,12 +1858,6 @@ trait Trees { self: Universe =>
*/
type SingletonTypeTree >: Null <: TypTree with SingletonTypeTreeApi
- /** A tag that preserves the identity of the `SingletonTypeTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SingletonTypeTreeTag: ClassTag[SingletonTypeTree]
-
/** The constructor/extractor for `SingletonTypeTree` instances.
* @group Extractors
*/
@@ -2170,12 +1888,6 @@ trait Trees { self: Universe =>
*/
type SelectFromTypeTree >: Null <: TypTree with RefTree with SelectFromTypeTreeApi
- /** A tag that preserves the identity of the `SelectFromTypeTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SelectFromTypeTreeTag: ClassTag[SelectFromTypeTree]
-
/** The constructor/extractor for `SelectFromTypeTree` instances.
* @group Extractors
*/
@@ -2217,12 +1929,6 @@ trait Trees { self: Universe =>
*/
type CompoundTypeTree >: Null <: TypTree with CompoundTypeTreeApi
- /** A tag that preserves the identity of the `CompoundTypeTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val CompoundTypeTreeTag: ClassTag[CompoundTypeTree]
-
/** The constructor/extractor for `CompoundTypeTree` instances.
* @group Extractors
*/
@@ -2253,12 +1959,6 @@ trait Trees { self: Universe =>
*/
type AppliedTypeTree >: Null <: TypTree with AppliedTypeTreeApi
- /** A tag that preserves the identity of the `AppliedTypeTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val AppliedTypeTreeTag: ClassTag[AppliedTypeTree]
-
/** The constructor/extractor for `AppliedTypeTree` instances.
* @group Extractors
*/
@@ -2301,12 +2001,6 @@ trait Trees { self: Universe =>
*/
type TypeBoundsTree >: Null <: TypTree with TypeBoundsTreeApi
- /** A tag that preserves the identity of the `TypeBoundsTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeBoundsTreeTag: ClassTag[TypeBoundsTree]
-
/** The constructor/extractor for `TypeBoundsTree` instances.
* @group Extractors
*/
@@ -2344,12 +2038,6 @@ trait Trees { self: Universe =>
*/
type ExistentialTypeTree >: Null <: TypTree with ExistentialTypeTreeApi
- /** A tag that preserves the identity of the `ExistentialTypeTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ExistentialTypeTreeTag: ClassTag[ExistentialTypeTree]
-
/** The constructor/extractor for `ExistentialTypeTree` instances.
* @group Extractors
*/
@@ -2387,12 +2075,6 @@ trait Trees { self: Universe =>
*/
type TypeTree >: Null <: TypTree with TypeTreeApi
- /** A tag that preserves the identity of the `TypeTree` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeTreeTag: ClassTag[TypeTree]
-
/** The constructor/extractor for `TypeTree` instances.
* @group Extractors
*/
@@ -2990,12 +2672,6 @@ trait Trees { self: Universe =>
*/
type Modifiers >: Null <: AnyRef with ModifiersApi
- /** A tag that preserves the identity of the `Modifiers` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Traversal
- */
- implicit val ModifiersTag: ClassTag[Modifiers]
-
/** The API that all Modifiers support
* @group API
*/
diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala
index e5140f23e5..1152f97350 100644
--- a/src/reflect/scala/reflect/api/Types.scala
+++ b/src/reflect/scala/reflect/api/Types.scala
@@ -50,7 +50,7 @@ package api
*
* @contentDiagram hideNodes "*Api"
*/
-trait Types extends ImplicitTags {
+trait Types {
self: Universe =>
/** The type of Scala types, and also Scala type signatures.
diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala
index 4928b8bb38..16e533cf7b 100644
--- a/src/reflect/scala/reflect/api/Universe.scala
+++ b/src/reflect/scala/reflect/api/Universe.scala
@@ -68,6 +68,7 @@ abstract class Universe extends Symbols
with Exprs
with TypeTags
with TagInterop
+ with ImplicitTags
with StandardDefinitions
with StandardNames
with BuildUtils
@@ -93,4 +94,4 @@ abstract class Universe extends Symbols
// implementation is hardwired to `scala.reflect.reify.Taggers`
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
def reify[T](expr: T): Expr[T] = ??? // macro
-} \ No newline at end of file
+}
diff --git a/src/reflect/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
index 78f7438429..faf61e5205 100644
--- a/src/reflect/scala/reflect/internal/ClassfileConstants.scala
+++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
@@ -72,6 +72,9 @@ object ClassfileConstants {
final val CONSTANT_METHODREF = 10
final val CONSTANT_INTFMETHODREF = 11
final val CONSTANT_NAMEANDTYPE = 12
+ final val CONSTANT_METHODHANDLE = 15
+ final val CONSTANT_METHODTYPE = 16
+ final val CONSTANT_INVOKEDYNAMIC = 18
// tags describing the type of a literal in attribute values
final val BYTE_TAG = 'B'
@@ -306,7 +309,7 @@ object ClassfileConstants {
final val invokespecial = 0xb7
final val invokestatic = 0xb8
final val invokeinterface = 0xb9
- final val xxxunusedxxxx = 0xba
+ final val invokedynamic = 0xba
final val new_ = 0xbb
final val newarray = 0xbc
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 55954196f6..5392daf674 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -244,8 +244,8 @@ trait Definitions extends api.StandardDefinitions {
(sym eq NoSymbol)
|| sym.isConstructor
|| sym.isPrivateLocal
- || isUniversalMember(sym)
)
+ def isUnimportableUnlessRenamed(sym: Symbol) = isUnimportable(sym) || isUniversalMember(sym)
def isImportable(sym: Symbol) = !isUnimportable(sym)
/** Is this type equivalent to Any, AnyVal, or AnyRef? */
@@ -973,7 +973,7 @@ trait Definitions extends api.StandardDefinitions {
getMemberIfDefined(owner, name) orElse {
if (phase.flatClasses && name.isTypeName && !owner.isPackageObjectOrClass) {
val pkg = owner.owner
- val flatname = nme.flattenedName(owner.name, name)
+ val flatname = tpnme.flattenedName(owner.name, name)
getMember(pkg, flatname)
}
else fatalMissingSymbol(owner, name)
diff --git a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala
index 281a32caf6..34bd400186 100644
--- a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala
+++ b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala
@@ -31,4 +31,81 @@ trait ExistentialsAndSkolems {
}
(new Deskolemizer).typeSkolems
}
+
+ def isRawParameter(sym: Symbol) = // is it a type parameter leaked by a raw type?
+ sym.isTypeParameter && sym.owner.isJavaDefined
+
+ /** If we map a set of hidden symbols to their existential bounds, we
+ * have a problem: the bounds may themselves contain references to the
+ * hidden symbols. So this recursively calls existentialBound until
+ * the typeSymbol is not amongst the symbols being hidden.
+ */
+ private def existentialBoundsExcludingHidden(hidden: List[Symbol]): Map[Symbol, Type] = {
+ def safeBound(t: Type): Type =
+ if (hidden contains t.typeSymbol) safeBound(t.typeSymbol.existentialBound.bounds.hi) else t
+
+ def hiBound(s: Symbol): Type = safeBound(s.existentialBound.bounds.hi) match {
+ case tp @ RefinedType(parents, decls) =>
+ val parents1 = parents mapConserve safeBound
+ if (parents eq parents1) tp
+ else copyRefinedType(tp, parents1, decls)
+ case tp => tp
+ }
+
+ // Hanging onto lower bound in case anything interesting
+ // happens with it.
+ mapFrom(hidden)(s => s.existentialBound match {
+ case TypeBounds(lo, hi) => TypeBounds(lo, hiBound(s))
+ case _ => hiBound(s)
+ })
+ }
+
+ /** Given a set `rawSyms` of term- and type-symbols, and a type
+ * `tp`, produce a set of fresh type parameters and a type so that
+ * it can be abstracted to an existential type. Every type symbol
+ * `T` in `rawSyms` is mapped to a clone. Every term symbol `x` of
+ * type `T` in `rawSyms` is given an associated type symbol of the
+ * following form:
+ *
+ * type x.type <: T with Singleton
+ *
+ * The name of the type parameter is `x.type`, to produce nice
+ * diagnostics. The Singleton parent ensures that the type
+ * parameter is still seen as a stable type. Type symbols in
+ * rawSyms are fully replaced by the new symbols. Term symbols are
+ * also replaced, except for term symbols of an Ident tree, where
+ * only the type of the Ident is changed.
+ */
+ final def existentialTransform[T](rawSyms: List[Symbol], tp: Type, rawOwner: Option[Symbol] = None)(creator: (List[Symbol], Type) => T): T = {
+ val allBounds = existentialBoundsExcludingHidden(rawSyms)
+ val typeParams: List[Symbol] = rawSyms map { sym =>
+ val name = sym.name match {
+ case x: TypeName => x
+ case x => tpnme.singletonName(x)
+ }
+ def rawOwner0 = rawOwner.getOrElse(abort(s"no owner provided for existential transform over raw parameter: $sym"))
+ val bound = allBounds(sym)
+ val sowner = if (isRawParameter(sym)) rawOwner0 else sym.owner
+ val quantified = sowner.newExistential(name, sym.pos)
+
+ quantified setInfo bound.cloneInfo(quantified)
+ }
+ // Higher-kinded existentials are not yet supported, but this is
+ // tpeHK for when they are: "if a type constructor is expected/allowed,
+ // tpeHK must be called instead of tpe."
+ val typeParamTypes = typeParams map (_.tpeHK)
+ def doSubst(info: Type) = info.subst(rawSyms, typeParamTypes)
+
+ creator(typeParams map (_ modifyInfo doSubst), doSubst(tp))
+ }
+
+ /**
+ * Compute an existential type from hidden symbols `hidden` and type `tp`.
+ * @param hidden The symbols that will be existentially abstracted
+ * @param hidden The original type
+ * @param rawOwner The owner for Java raw types.
+ */
+ final def packSymbols(hidden: List[Symbol], tp: Type, rawOwner: Option[Symbol] = None): Type =
+ if (hidden.isEmpty) tp
+ else existentialTransform(hidden, tp, rawOwner)(existentialAbstraction)
}
diff --git a/src/reflect/scala/reflect/internal/JMethodOrConstructor.scala b/src/reflect/scala/reflect/internal/JMethodOrConstructor.scala
new file mode 100644
index 0000000000..3d1d1bf451
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/JMethodOrConstructor.scala
@@ -0,0 +1,45 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ * @author Paul Phillips
+ */
+package scala.reflect
+package internal
+
+import java.lang.{ Class => jClass }
+import java.lang.annotation.{ Annotation => jAnnotation }
+import java.lang.reflect.{
+ Member => jMember, Constructor => jConstructor, Method => jMethod,
+ AnnotatedElement => jAnnotatedElement, Type => jType,
+ TypeVariable => jTypeVariable
+}
+
+/** This class tries to abstract over some of the duplication
+ * in java.lang.reflect.{ Method, Constructor }.
+ */
+class JMethodOrConstructor(val member: jMember with jAnnotatedElement) {
+ def isVarArgs: Boolean = member match {
+ case m: jMethod => m.isVarArgs
+ case m: jConstructor[_] => m.isVarArgs
+ }
+ def typeParams: Array[_ <: jTypeVariable[_]] = member match {
+ case m: jMethod => m.getTypeParameters
+ case m: jConstructor[_] => m.getTypeParameters
+ }
+ def paramTypes: Array[jType] = member match {
+ case m: jMethod => m.getGenericParameterTypes
+ case m: jConstructor[_] => m.getGenericParameterTypes
+ }
+ def paramAnnotations: Array[Array[jAnnotation]] = member match {
+ case m: jMethod => m.getParameterAnnotations
+ case m: jConstructor[_] => m.getParameterAnnotations
+ }
+ def resultType: jType = member match {
+ case m: jMethod => m.getGenericReturnType
+ case m: jConstructor[_] => classOf[Unit]
+ }
+}
+
+object JMethodOrConstructor {
+ implicit def liftMethodToJmoc(m: jMethod): JMethodOrConstructor = new JMethodOrConstructor(m)
+ implicit def liftConstructorToJmoc(m: jConstructor[_]): JMethodOrConstructor = new JMethodOrConstructor(m)
+}
diff --git a/src/reflect/scala/reflect/internal/JavaAccFlags.scala b/src/reflect/scala/reflect/internal/JavaAccFlags.scala
new file mode 100644
index 0000000000..4be1f828d3
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/JavaAccFlags.scala
@@ -0,0 +1,83 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ * @author Paul Phillips
+ */
+package scala.reflect
+package internal
+
+import java.lang.{ Class => jClass }
+import java.lang.reflect.{ Member => jMember, Constructor => jConstructor, Field => jField, Method => jMethod }
+import JavaAccFlags._
+import ClassfileConstants._
+
+/** A value class which encodes the access_flags (JVMS 4.1)
+ * for a field, method, or class. The low 16 bits are the same
+ * as those returned by java.lang.reflect.Member#getModifiers
+ * and found in the bytecode.
+ *
+ * The high bits encode whether the access flags are directly
+ * associated with a class, constructor, field, or method.
+ */
+final class JavaAccFlags private (val coded: Int) extends AnyVal {
+ private def has(mask: Int) = (flags & mask) != 0
+ private def flagCarrierId = coded >>> 16
+ private def flags = coded & 0xFFFF
+
+ def isAbstract = has(JAVA_ACC_ABSTRACT)
+ def isAnnotation = has(JAVA_ACC_ANNOTATION)
+ def isBridge = has(JAVA_ACC_BRIDGE)
+ def isEnum = has(JAVA_ACC_ENUM)
+ def isFinal = has(JAVA_ACC_FINAL)
+ def isInterface = has(JAVA_ACC_INTERFACE)
+ def isNative = has(JAVA_ACC_NATIVE)
+ def isPrivate = has(JAVA_ACC_PRIVATE)
+ def isProtected = has(JAVA_ACC_PROTECTED)
+ def isPublic = has(JAVA_ACC_PUBLIC)
+ def isStatic = has(JAVA_ACC_STATIC)
+ def isStrictFp = has(JAVA_ACC_STRICT)
+ def isSuper = has(JAVA_ACC_SUPER)
+ def isSynchronized = has(JAVA_ACC_SYNCHRONIZED)
+ def isSynthetic = has(JAVA_ACC_SYNTHETIC)
+ def isTransient = has(JAVA_ACC_TRANSIENT)
+ def isVarargs = has(JAVA_ACC_VARARGS)
+ def isVolatile = has(JAVA_ACC_VOLATILE)
+
+ /** Do these flags describe a member which has either protected or package access?
+ * Such access in java is encoded in scala as protected[foo] or private[foo], where
+ * `foo` is the defining package.
+ */
+ def hasPackageAccessBoundary = !has(JAVA_ACC_PRIVATE | JAVA_ACC_PUBLIC) // equivalently, allows protected or package level access
+ def isPackageProtected = !has(JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)
+
+ def toJavaFlags: Int = flags
+ def toScalaFlags: Long = flagCarrierId match {
+ case Method | Constructor => FlagTranslation methodFlags flags
+ case Class => FlagTranslation classFlags flags
+ case _ => FlagTranslation fieldFlags flags
+ }
+}
+
+object JavaAccFlags {
+ private val Unknown = 0
+ private val Class = 1
+ private val Field = 2
+ private val Method = 3
+ private val Constructor = 4
+
+ private def create(flagCarrier: Int, access_flags: Int): JavaAccFlags =
+ new JavaAccFlags((flagCarrier << 16) | (access_flags & 0xFFFF))
+
+ def classFlags(flags: Int): JavaAccFlags = create(Class, flags)
+ def methodFlags(flags: Int): JavaAccFlags = create(Method, flags)
+ def fieldFlags(flags: Int): JavaAccFlags = create(Field, flags)
+ def constructorFlags(flags: Int): JavaAccFlags = create(Constructor, flags)
+
+ def apply(access_flags: Int): JavaAccFlags = create(Unknown, access_flags)
+ def apply(clazz: jClass[_]): JavaAccFlags = classFlags(clazz.getModifiers)
+ def apply(member: jMember): JavaAccFlags = member match {
+ case x: jConstructor[_] => constructorFlags(x.getModifiers)
+ case x: jMethod => methodFlags(x.getModifiers)
+ case x: jField => fieldFlags(x.getModifiers)
+ case _ => apply(member.getModifiers)
+ }
+}
diff --git a/src/reflect/scala/reflect/internal/Kinds.scala b/src/reflect/scala/reflect/internal/Kinds.scala
index cc8dd16d69..3c49aef05a 100644
--- a/src/reflect/scala/reflect/internal/Kinds.scala
+++ b/src/reflect/scala/reflect/internal/Kinds.scala
@@ -145,7 +145,7 @@ trait Kinds {
kindErrors = f(kindErrors)
}
- if (settings.debug.value) {
+ if (settings.debug) {
log("checkKindBoundsHK expected: "+ param +" with params "+ hkparams +" by definition in "+ paramowner)
log("checkKindBoundsHK supplied: "+ arg +" with params "+ hkargs +" from "+ owner)
log("checkKindBoundsHK under params: "+ underHKParams +" with args "+ withHKArgs)
@@ -201,7 +201,7 @@ trait Kinds {
else NoKindErrors
}
- if (settings.debug.value && (tparams.nonEmpty || targs.nonEmpty)) log(
+ if (settings.debug && (tparams.nonEmpty || targs.nonEmpty)) log(
"checkKindBounds0(" + tparams + ", " + targs + ", " + pre + ", "
+ owner + ", " + explainErrors + ")"
)
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index 63178d0b39..81d7619f22 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -46,7 +46,7 @@ trait Mirrors extends api.Mirrors {
val result = if (path.isTermName) sym.suchThat(_ hasFlag MODULE) else sym
if (result != NoSymbol) result
else {
- if (settings.debug.value) { log(sym.info); log(sym.info.members) }//debug
+ if (settings.debug) { log(sym.info); log(sym.info.members) }//debug
thisMirror.missingHook(owner, name) orElse {
MissingRequirementError.notFound((if (path.isTermName) "object " else "class ")+path+" in "+thisMirror)
}
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index f8598dca7a..b8141d25f5 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -177,6 +177,12 @@ trait Names extends api.Names {
/** @return the hash value of this name */
final override def hashCode(): Int = index
+ /** @return true if the string value of this name is equal
+ * to the string value of the given name or String.
+ */
+ def string_==(that: Name): Boolean = (that ne null) && (toString == that.toString)
+ def string_==(that: String): Boolean = (that ne null) && (toString == that)
+
/****
* This has been quite useful to find places where people are comparing
* a TermName and a TypeName, or a Name and a String.
@@ -210,7 +216,7 @@ trait Names extends api.Names {
/** @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)
- /** @return the index of first occurrence of char c in this name, length if not found */
+ /** @return the index of first occurrence of s in this name, length if not found */
final def pos(s: String): Int = pos(s, 0)
/** Returns the index of the first occurrence of character c in
@@ -319,15 +325,18 @@ 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 indexOf(ch: Char) = {
- val idx = pos(ch)
- if (idx == length) -1 else idx
- }
- def indexOf(ch: Char, fromIndex: Int) = {
- val idx = pos(ch, fromIndex)
- if (idx == length) -1 else idx
- }
- def lastIndexOf(ch: Char) = lastPos(ch)
+ /** Rewrite the confusing failure indication via result == length to
+ * the normal failure indication via result == -1.
+ */
+ private def fixIndexOf(idx: Int): Int = if (idx == length) -1 else idx
+
+ def indexOf(ch: Char) = fixIndexOf(pos(ch))
+ def indexOf(ch: Char, fromIndex: Int) = fixIndexOf(pos(ch, fromIndex))
+ def indexOf(s: String) = fixIndexOf(pos(s))
+
+ /** The lastPos methods already return -1 on failure. */
+ def lastIndexOf(ch: Char): Int = lastPos(ch)
+ def lastIndexOf(s: String): Int = toString lastIndexOf s
/** Replace all occurrences of `from` by `to` in
* name; result is always a term name.
@@ -392,9 +401,24 @@ trait Names extends api.Names {
* reap the benefits because an (unused) $outer pointer so it is not single-field.
*/
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]
+ import NameTransformer._
+ def stripSuffix(suffix: String): T = stripSuffix(suffix: TermName)
+ def stripSuffix(suffix: Name): T = if (name endsWith suffix) dropRight(suffix.length) else name
+ def take(n: Int): T = name.subName(0, n).asInstanceOf[T]
+ def drop(n: Int): T = name.subName(n, name.length).asInstanceOf[T]
+ def dropRight(n: Int): T = name.subName(0, name.length - n).asInstanceOf[T]
+ def dropLocal: TermName = name.toTermName stripSuffix LOCAL_SUFFIX_STRING
+ def dropSetter: TermName = name.toTermName stripSuffix SETTER_SUFFIX_STRING
+ def dropModule: T = this stripSuffix MODULE_SUFFIX_STRING
+ def localName: TermName = getterName append LOCAL_SUFFIX_STRING
+ def setterName: TermName = getterName append SETTER_SUFFIX_STRING
+ def getterName: TermName = dropTraitSetterSeparator.dropSetter.dropLocal
+
+ private def dropTraitSetterSeparator: TermName =
+ name indexOf TRAIT_SETTER_SEPARATOR_STRING match {
+ case -1 => name.toTermName
+ case idx => name.toTermName drop idx drop TRAIT_SETTER_SEPARATOR_STRING.length
+ }
}
implicit val NameTag = ClassTag[Name](classOf[Name])
diff --git a/src/reflect/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala
index cc32a0363f..3cf4f4a1df 100644
--- a/src/reflect/scala/reflect/internal/Positions.scala
+++ b/src/reflect/scala/reflect/internal/Positions.scala
@@ -107,7 +107,7 @@ trait Positions extends api.Positions { self: SymbolTable =>
def validate(tree: Tree, encltree: Tree): Unit = {
if (!tree.isEmpty && tree.canHaveAttrs) {
- if (settings.Yposdebug.value && (settings.verbose.value || settings.Yrangepos.value))
+ if (settings.Yposdebug && (settings.verbose || settings.Yrangepos))
println("[%10s] %s".format("validate", treeStatus(tree, encltree)))
if (!tree.pos.isDefined)
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index 28837c4ae8..5b80889225 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -29,18 +29,19 @@ trait Printers extends api.Printers { self: SymbolTable =>
def quotedName(name: String): String = quotedName(newTermName(name), decode = false)
private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = {
- val sym = tree.symbol
- if (sym.name.toString == nme.ERROR.toString) {
- "<" + quotedName(name, decoded) + ": error>"
- } else if (sym != null && sym != NoSymbol) {
- val prefix = if (sym.isMixinConstructor) "/*%s*/".format(quotedName(sym.owner.name, decoded)) else ""
- var suffix = ""
- if (settings.uniqid.value) suffix += ("#" + sym.id)
- if (settings.Yshowsymkinds.value) suffix += ("#" + sym.abbreviatedKindString)
- prefix + quotedName(tree.symbol.decodedName) + suffix
- } else {
- quotedName(name, decoded)
- }
+ val sym = tree.symbol
+ def qname = quotedName(name.dropLocal, decoded)
+ def qowner = quotedName(sym.owner.name.dropLocal, decoded)
+ def qsymbol = quotedName(sym.nameString)
+
+ if (sym.name.toTermName == nme.ERROR)
+ s"<$qname: error>"
+ else if (sym == null || sym == NoSymbol)
+ qname
+ else if (sym.isMixinConstructor)
+ s"/*$qowner*/$qsymbol"
+ else
+ qsymbol
}
def decodedSymName(tree: Tree, name: Name) = symNameInternal(tree, name, decoded = true)
@@ -168,7 +169,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
)
def printFlags(flags: Long, privateWithin: String) {
- val mask: Long = if (settings.debug.value) -1L else PrintableFlags
+ val mask: Long = if (settings.debug) -1L else PrintableFlags
val s = flagsToString(flags & mask, privateWithin)
if (s != "") print(s + " ")
}
@@ -375,7 +376,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
if (!qual.isEmpty) print(symName(tree, qual) + ".")
print("this")
- case Select(qual @ New(tpe), name) if (!settings.debug.value) =>
+ case Select(qual @ New(tpe), name) if !settings.debug =>
print(qual)
case Select(qualifier, name) =>
@@ -546,7 +547,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
print("pendingSuperCall")
case tree: Tree =>
val hasSymbolField = tree.hasSymbolField && tree.symbol != NoSymbol
- val isError = hasSymbolField && tree.symbol.name.toString == nme.ERROR.toString
+ val isError = hasSymbolField && (tree.symbol.name string_== nme.ERROR)
printProduct(
tree,
preamble = _ => {
diff --git a/src/reflect/scala/reflect/internal/PrivateWithin.scala b/src/reflect/scala/reflect/internal/PrivateWithin.scala
index 9b99b94b41..5646ac82ae 100644
--- a/src/reflect/scala/reflect/internal/PrivateWithin.scala
+++ b/src/reflect/scala/reflect/internal/PrivateWithin.scala
@@ -1,23 +1,26 @@
package scala.reflect
package internal
-import ClassfileConstants._
+import java.lang.{ Class => jClass }
+import java.lang.reflect.{ Member => jMember }
trait PrivateWithin {
self: SymbolTable =>
- def importPrivateWithinFromJavaFlags(sym: Symbol, jflags: Int): Symbol = {
- if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)) == 0)
- // See ticket #1687 for an example of when topLevelClass is NoSymbol: it
- // apparently occurs when processing v45.3 bytecode.
- if (sym.enclosingTopLevelClass != NoSymbol)
- sym.privateWithin = sym.enclosingTopLevelClass.owner
-
- // protected in java means package protected. #3946
- if ((jflags & JAVA_ACC_PROTECTED) != 0)
- if (sym.enclosingTopLevelClass != NoSymbol)
- sym.privateWithin = sym.enclosingTopLevelClass.owner
-
- sym
+ def propagatePackageBoundary(c: jClass[_], syms: Symbol*): Unit =
+ propagatePackageBoundary(JavaAccFlags(c), syms: _*)
+ def propagatePackageBoundary(m: jMember, syms: Symbol*): Unit =
+ propagatePackageBoundary(JavaAccFlags(m), syms: _*)
+ def propagatePackageBoundary(jflags: JavaAccFlags, syms: Symbol*) {
+ if (jflags.hasPackageAccessBoundary)
+ syms foreach setPackageAccessBoundary
}
-} \ No newline at end of file
+
+ // protected in java means package protected. #3946
+ // See ticket #1687 for an example of when the enclosing top level class is NoSymbol;
+ // it apparently occurs when processing v45.3 bytecode.
+ def setPackageAccessBoundary(sym: Symbol): Symbol = (
+ if (sym.enclosingTopLevelClass eq NoSymbol) sym
+ else sym setPrivateWithin sym.enclosingTopLevelClass.owner
+ )
+}
diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala
index 850c497d4b..371eddbc4f 100644
--- a/src/reflect/scala/reflect/internal/Scopes.scala
+++ b/src/reflect/scala/reflect/internal/Scopes.scala
@@ -6,6 +6,8 @@
package scala.reflect
package internal
+import scala.annotation.tailrec
+
trait Scopes extends api.Scopes { self: SymbolTable =>
/** An ADT to represent the results of symbol name lookups.
@@ -65,6 +67,11 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
/** a cache for all elements, to be used by symbol iterator.
*/
private var elemsCache: List[Symbol] = null
+ private var cachedSize = -1
+ private def flushElemsCache() {
+ elemsCache = null
+ cachedSize = -1
+ }
/** size and mask of hash tables
* todo: make hashtables grow?
@@ -86,6 +93,12 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
/** the number of entries in this scope */
override def size: Int = {
+ if (cachedSize < 0)
+ cachedSize = directSize
+
+ cachedSize
+ }
+ private def directSize: Int = {
var s = 0
var e = elems
while (e ne null) {
@@ -98,7 +111,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
/** enter a scope entry
*/
protected def enterEntry(e: ScopeEntry) {
- elemsCache = null
+ flushElemsCache()
if (hashtable ne null)
enterInHash(e)
else if (size >= MIN_HASH)
@@ -192,7 +205,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
e1.tail = e.tail
}
}
- elemsCache = null
+ flushElemsCache()
}
/** remove symbol */
@@ -304,16 +317,43 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
e
}
+ /** TODO - we can test this more efficiently than checking isSubScope
+ * in both directions. However the size test might be enough to quickly
+ * rule out most failures.
+ */
+ def isSameScope(other: Scope) = (
+ (size == other.size) // optimization - size is cached
+ && (this isSubScope other)
+ && (other isSubScope this)
+ )
+
+ def isSubScope(other: Scope) = {
+ def scopeContainsSym(sym: Symbol): Boolean = {
+ @tailrec def entryContainsSym(e: ScopeEntry): Boolean = e match {
+ case null => false
+ case _ =>
+ val comparableInfo = sym.info.substThis(sym.owner, e.sym.owner)
+ (e.sym.info =:= comparableInfo) || entryContainsSym(lookupNextEntry(e))
+ }
+ entryContainsSym(this lookupEntry sym.name)
+ }
+ other.toList forall scopeContainsSym
+ }
+
/** Return all symbols as a list in the order they were entered in this scope.
*/
override def toList: List[Symbol] = {
if (elemsCache eq null) {
- elemsCache = Nil
+ var symbols: List[Symbol] = Nil
+ var count = 0
var e = elems
while ((e ne null) && e.owner == this) {
- elemsCache = e.sym :: elemsCache
+ count += 1
+ symbols ::= e.sym
e = e.next
}
+ elemsCache = symbols
+ cachedSize = count
}
elemsCache
}
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index a894bd649c..ae2cf09c2e 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -86,8 +86,12 @@ trait StdNames {
def flattenedName(segments: Name*): NameType =
compactify(segments mkString NAME_JOIN_STRING)
- val MODULE_SUFFIX_STRING: String = NameTransformer.MODULE_SUFFIX_STRING
- val NAME_JOIN_STRING: String = NameTransformer.NAME_JOIN_STRING
+ val NAME_JOIN_STRING: String = NameTransformer.NAME_JOIN_STRING
+ val MODULE_SUFFIX_STRING: String = NameTransformer.MODULE_SUFFIX_STRING
+ val SETTER_SUFFIX_STRING: String = NameTransformer.SETTER_SUFFIX_STRING
+ val LOCAL_SUFFIX_STRING: String = NameTransformer.LOCAL_SUFFIX_STRING
+ val TRAIT_SETTER_SEPARATOR_STRING: String = NameTransformer.TRAIT_SETTER_SEPARATOR_STRING
+
val SINGLETON_SUFFIX: String = ".type"
val ANON_CLASS_NAME: NameType = "$anon"
@@ -265,7 +269,7 @@ trait StdNames {
val BITMAP_PREFIX = "bitmap$"
val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$"
val DEFAULT_GETTER_STRING = "$default$"
- val DEFAULT_GETTER_INIT_STRING = "$lessinit$greater" // CONSTRUCTOR.encoded, less is more
+ val DEFAULT_GETTER_INIT_STRING = NameTransformer.encode("<init>") + DEFAULT_GETTER_STRING
val DO_WHILE_PREFIX = "doWhile$"
val EVIDENCE_PARAM_PREFIX = "evidence$"
val EXCEPTION_RESULT_PREFIX = "exceptionResult"
@@ -275,7 +279,6 @@ trait StdNames {
val PROTECTED_PREFIX = "protected$"
val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set"
val SUPER_PREFIX_STRING = "super$"
- val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$"
val WHILE_PREFIX = "while$"
// Compiler internal names
@@ -284,10 +287,8 @@ trait StdNames {
val DEFAULT_CASE: NameType = "defaultCase$"
val EQEQ_LOCAL_VAR: NameType = "eqEqTemp$"
val FAKE_LOCAL_THIS: NameType = "this$"
- val INITIALIZER: NameType = CONSTRUCTOR // Is this buying us something?
val LAZY_LOCAL: NameType = "$lzy"
val LAZY_SLOW_SUFFIX: NameType = "$lzycompute"
- val LOCAL_SUFFIX_STRING = " "
val UNIVERSE_BUILD_PREFIX: NameType = "$u.build."
val UNIVERSE_PREFIX: NameType = "$u."
val UNIVERSE_SHORT: NameType = "$u"
@@ -301,21 +302,16 @@ trait StdNames {
val MIXIN_CONSTRUCTOR: NameType = "$init$"
val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
val OUTER: NameType = "$outer"
- val OUTER_LOCAL: NameType = OUTER + LOCAL_SUFFIX_STRING // "$outer ", note the space
+ val OUTER_LOCAL: NameType = OUTER.localName
val OUTER_SYNTH: NameType = "<outer>" // emitted by virtual pattern matcher, replaced by outer accessor in explicitouter
val ROOTPKG: NameType = "_root_"
val SELECTOR_DUMMY: NameType = "<unapply-selector>"
val SELF: NameType = "$this"
- val SETTER_SUFFIX: NameType = encode("_=")
+ val SETTER_SUFFIX: NameType = NameTransformer.SETTER_SUFFIX_STRING
val SPECIALIZED_INSTANCE: NameType = "specInstance$"
val STAR: NameType = "*"
val THIS: NameType = "_$this"
- @deprecated("Use SPECIALIZED_SUFFIX", "2.10.0")
- def SPECIALIZED_SUFFIX_STRING = SPECIALIZED_SUFFIX.toString
- @deprecated("Use SPECIALIZED_SUFFIX", "2.10.0")
- def SPECIALIZED_SUFFIX_NAME: TermName = SPECIALIZED_SUFFIX.toTermName
-
def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR
def isExceptionResultName(name: Name) = name startsWith EXCEPTION_RESULT_PREFIX
def isImplClassName(name: Name) = name endsWith IMPL_CLASS_SUFFIX
@@ -345,31 +341,52 @@ trait StdNames {
name.endChar == '=' && name.startChar != '=' && isOperatorPart(name.startChar)
}
- /** The expanded name of `name` relative to this class `base` with given `separator`
- */
- def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName =
+ private def expandedNameInternal(name: TermName, base: Symbol, separator: String): TermName =
newTermNameCached(base.fullName('$') + separator + name)
+ /** The expanded name of `name` relative to this class `base`
+ */
+ def expandedName(name: TermName, base: Symbol) = expandedNameInternal(name, base, EXPAND_SEPARATOR_STRING)
+
/** The expanded setter name of `name` relative to this class `base`
*/
- def expandedSetterName(name: TermName, base: Symbol): TermName =
- expandedName(name, base, separator = TRAIT_SETTER_SEPARATOR_STRING)
+ def expandedSetterName(name: TermName, base: Symbol) = expandedNameInternal(name, base, TRAIT_SETTER_SEPARATOR_STRING)
- /** If `name` is an expandedName name, the original name.
- * Otherwise `name` itself.
- */
- def originalName(name: Name): Name = {
- var i = name.length
- while (i >= 2 && !(name.charAt(i - 1) == '$' && name.charAt(i - 2) == '$')) i -= 1
- if (i >= 2) {
- while (i >= 3 && name.charAt(i - 3) == '$') i -= 1
- name.subName(i, name.length)
- } else name
+ /** If `name` is an expandedName name, the original (unexpanded) name.
+ * Otherwise `name` itself.
+ * Look backward from the end of the string for "$$", and take the
+ * part of the string after that; but if the string is "$$$" or longer,
+ * be sure to retain the extra dollars.
+ */
+ def unexpandedName(name: Name): Name = name lastIndexOf "$$" match {
+ case 0 | -1 => name
+ case idx0 =>
+ // Sketchville - We've found $$ but if it's part of $$$ or $$$$
+ // or something we need to keep the bonus dollars, so e.g. foo$$$outer
+ // has an original name of $outer.
+ var idx = idx0
+ while (idx > 0 && name.charAt(idx - 1) == '$')
+ idx -= 1
+ name drop idx + 2
}
+ @deprecated("Use SPECIALIZED_SUFFIX", "2.10.0")
+ def SPECIALIZED_SUFFIX_STRING = SPECIALIZED_SUFFIX.toString
+ @deprecated("Use SPECIALIZED_SUFFIX", "2.10.0")
+ def SPECIALIZED_SUFFIX_NAME: TermName = SPECIALIZED_SUFFIX.toTermName
+
+ @deprecated("Use unexpandedName", "2.11.0") def originalName(name: Name): Name = unexpandedName(name)
+ @deprecated("Use Name#dropModule", "2.11.0") def stripModuleSuffix(name: Name): Name = name.dropModule
+ @deprecated("Use Name#dropLocal", "2.11.0") def localToGetter(name: TermName): TermName = name.dropLocal
+ @deprecated("Use Name#dropLocal", "2.11.0") def dropLocalSuffix(name: Name): TermName = name.dropLocal
+ @deprecated("Use Name#localName", "2.11.0") def getterToLocal(name: TermName): TermName = name.localName
+ @deprecated("Use Name#setterName", "2.11.0") def getterToSetter(name: TermName): TermName = name.setterName
+ @deprecated("Use Name#getterName", "2.11.0") def getterName(name: TermName): TermName = name.getterName
+ @deprecated("Use Name#getterName", "2.11.0") def setterToGetter(name: TermName): TermName = name.getterName
+
def unspecializedName(name: Name): Name = (
if (name endsWith SPECIALIZED_SUFFIX)
- name.subName(0, name.lastIndexOf('m') - 1)
+ name.subName(0, name.lastIndexOf('m') - 1)
else name
)
@@ -394,39 +411,23 @@ trait StdNames {
} else
(name, "", "")
- def getterName(name: TermName): TermName = if (isLocalName(name)) localToGetter(name) else name
- def getterToLocal(name: TermName): TermName = name append LOCAL_SUFFIX_STRING
- def getterToSetter(name: TermName): TermName = name append SETTER_SUFFIX
- def localToGetter(name: TermName): TermName = name dropRight LOCAL_SUFFIX_STRING.length
-
- def dropLocalSuffix(name: Name): Name = if (name endsWith ' ') name dropRight 1 else name
-
- def setterToGetter(name: TermName): TermName = {
- val p = name.pos(TRAIT_SETTER_SEPARATOR_STRING)
- if (p < name.length)
- setterToGetter(name drop (p + TRAIT_SETTER_SEPARATOR_STRING.length))
- else
- name.subName(0, name.length - SETTER_SUFFIX.length)
- }
-
// Nominally, name$default$N, encoded for <init>
- def defaultGetterName(name: Name, pos: Int): TermName = {
- val prefix = if (isConstructorName(name)) DEFAULT_GETTER_INIT_STRING else name
- newTermName(prefix + DEFAULT_GETTER_STRING + pos)
- }
+ def defaultGetterName(name: Name, pos: Int): TermName = (
+ if (isConstructorName(name))
+ DEFAULT_GETTER_INIT_STRING + pos
+ else
+ name + DEFAULT_GETTER_STRING + pos
+ )
// Nominally, name from name$default$N, CONSTRUCTOR for <init>
- def defaultGetterToMethod(name: Name): TermName = {
- val p = name.pos(DEFAULT_GETTER_STRING)
- if (p < name.length) {
- val q = name.toTermName.subName(0, p)
- // i.e., if (q.decoded == CONSTRUCTOR.toString) CONSTRUCTOR else q
- if (q.toString == DEFAULT_GETTER_INIT_STRING) CONSTRUCTOR else q
- } else name.toTermName
- }
-
- def stripModuleSuffix(name: Name): Name = (
- if (isModuleName(name)) name dropRight MODULE_SUFFIX_STRING.length else name
+ def defaultGetterToMethod(name: Name): TermName = (
+ if (name startsWith DEFAULT_GETTER_INIT_STRING)
+ nme.CONSTRUCTOR
+ else name indexOf DEFAULT_GETTER_STRING match {
+ case -1 => name.toTermName
+ case idx => name.toTermName take idx
+ }
)
+
def localDummyName(clazz: Symbol): TermName = newTermName(LOCALDUMMY_PREFIX + clazz.name + ">")
def superName(name: Name): TermName = newTermName(SUPER_PREFIX_STRING + name)
diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala
index 03ec59f0fe..336c2748c6 100644
--- a/src/reflect/scala/reflect/internal/SymbolTable.scala
+++ b/src/reflect/scala/reflect/internal/SymbolTable.scala
@@ -60,8 +60,8 @@ abstract class SymbolTable extends macros.Universe
def debugwarn(msg: => String): Unit = devWarning(msg)
/** Override with final implementation for inlining. */
- def debuglog(msg: => String): Unit = if (settings.debug.value) log(msg)
- def devWarning(msg: => String): Unit = if (settings.debug.value) Console.err.println(msg)
+ def debuglog(msg: => String): Unit = if (settings.debug) log(msg)
+ def devWarning(msg: => String): Unit = if (settings.debug) Console.err.println(msg)
def throwableAsString(t: Throwable): String = "" + t
/** Prints a stack trace if -Ydebug or equivalent was given, otherwise does nothing. */
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index c881de7830..8ef2805529 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -190,7 +190,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def varianceString: String = variance.symbolicString
override def flagMask =
- if (settings.debug.value && !isAbstractType) AllFlags
+ if (settings.debug && !isAbstractType) AllFlags
else if (owner.isRefinementClass) ExplicitFlags & ~OVERRIDE
else ExplicitFlags
@@ -202,7 +202,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def shortSymbolClass = shortClassOfInstance(this)
def symbolCreationString: String = (
"%s%25s | %-40s | %s".format(
- if (settings.uniqid.value) "%06d | ".format(id) else "",
+ if (settings.uniqid) "%06d | ".format(id) else "",
shortSymbolClass,
name.decode + " in " + owner,
rawFlagString
@@ -761,16 +761,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def compileTimeOnlyMessage = getAnnotation(CompileTimeOnlyAttr) flatMap (_ stringArg 0)
/** Is this symbol an accessor method for outer? */
- final def isOuterAccessor = {
- hasFlag(STABLE | ARTIFACT) &&
- originalName == nme.OUTER
- }
+ final def isOuterAccessor = hasFlag(STABLE | ARTIFACT) && (unexpandedName == nme.OUTER)
/** Is this symbol an accessor method for outer? */
- final def isOuterField = {
- hasFlag(ARTIFACT) &&
- originalName == nme.OUTER_LOCAL
- }
+ final def isOuterField = isArtifact && (unexpandedName == nme.OUTER_LOCAL)
/** Does this symbol denote a stable value? */
def isStable = false
@@ -834,7 +828,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Is this symbol effectively final? I.e, it cannot be overridden */
final def isEffectivelyFinal: Boolean = (
(this hasFlag FINAL | PACKAGE)
- || isModuleOrModuleClass && (isTopLevel || !settings.overrideObjects.value)
+ || isModuleOrModuleClass && (isTopLevel || !settings.overrideObjects)
|| isTerm && (
isPrivate
|| isLocal
@@ -995,10 +989,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// ------ name attribute --------------------------------------------------------------
- /** If this symbol has an expanded name, its original name, otherwise its name itself.
- * @see expandName
+ @deprecated("Use unexpandedName", "2.11.0") def originalName: Name = unexpandedName
+
+ /** If this symbol has an expanded name, its original (unexpanded) name,
+ * otherwise the name itself.
*/
- def originalName: Name = nme.originalName(nme.dropLocalSuffix(name))
+ def unexpandedName: Name = nme.unexpandedName(name)
/** The name of the symbol before decoding, e.g. `\$eq\$eq` instead of `==`.
*/
@@ -1006,7 +1002,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** The decoded name of the symbol, e.g. `==` instead of `\$eq\$eq`.
*/
- def decodedName: String = nme.dropLocalSuffix(name).decode
+ def decodedName: String = name.decode
private def addModuleSuffix(n: Name): Name =
if (needsModuleSuffix) n append nme.MODULE_SUFFIX_STRING else n
@@ -1025,7 +1021,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
)
/** These should be moved somewhere like JavaPlatform.
*/
- def javaSimpleName: Name = addModuleSuffix(nme.dropLocalSuffix(simpleName))
+ def javaSimpleName: Name = addModuleSuffix(simpleName.dropLocal)
def javaBinaryName: Name = addModuleSuffix(fullNameInternal('/'))
def javaClassName: String = addModuleSuffix(fullNameInternal('.')).toString
@@ -1046,7 +1042,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else ((effectiveOwner.enclClass.fullNameAsName(separator) append separator): Name) append name
)
- def fullNameAsName(separator: Char): Name = nme.dropLocalSuffix(fullNameInternal(separator))
+ def fullNameAsName(separator: Char): Name = fullNameInternal(separator).dropLocal
/** The encoded full path name of this symbol, where outer names and inner names
* are separated by periods.
@@ -1823,7 +1819,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
//
// The slightly more principled approach of using the paramss of the
// primary constructor leads to cycles in, for example, pos/t5084.scala.
- val primaryNames = constrParamAccessors.map(acc => nme.dropLocalSuffix(acc.name))
+ val primaryNames = constrParamAccessors map (_.name.dropLocal)
caseFieldAccessorsUnsorted.sortBy { acc =>
primaryNames indexWhere { orig =>
(acc.name == orig) || (acc.name startsWith (orig append "$"))
@@ -1842,7 +1838,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** The symbol accessed by this accessor function, but with given owner type. */
final def accessed(ownerTp: Type): Symbol = {
assert(hasAccessorFlag, this)
- ownerTp decl nme.getterToLocal(getterName.toTermName)
+ ownerTp decl localName
}
/** The module corresponding to this module class (note that this
@@ -2199,22 +2195,23 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** The getter of this value or setter definition in class `base`, or NoSymbol if
* none exists.
*/
- final def getter(base: Symbol): Symbol = base.info.decl(getterName) filter (_.hasAccessorFlag)
+ final def getter(base: Symbol): Symbol =
+ base.info decl getterName filter (_.hasAccessorFlag)
- def getterName: TermName = (
- if (isSetter) nme.setterToGetter(name.toTermName)
- else if (nme.isLocalName(name)) nme.localToGetter(name.toTermName)
- else name.toTermName
- )
+ def getterName: TermName = name.getterName
+ def setterName: TermName = name.setterName
+ def localName: TermName = name.localName
/** The setter of this value or getter definition, or NoSymbol if none exists */
- final def setter(base: Symbol): Symbol = setter(base, hasExpandedName = false)
+ final def setter(base: Symbol, hasExpandedName: Boolean = needsExpandedSetterName): Symbol =
+ base.info decl setterNameInBase(base, hasExpandedName) filter (_.hasAccessorFlag)
- final def setter(base: Symbol, hasExpandedName: Boolean): Symbol = {
- var sname = nme.getterToSetter(nme.getterName(name.toTermName))
- if (hasExpandedName) sname = nme.expandedSetterName(sname, base)
- base.info.decl(sname) filter (_.hasAccessorFlag)
- }
+ def needsExpandedSetterName = (
+ if (isMethod) hasStableFlag && !isLazy
+ else hasNoFlags(LAZY | MUTABLE)
+ )
+ def setterNameInBase(base: Symbol, expanded: Boolean): TermName =
+ if (expanded) nme.expandedSetterName(setterName, base) else setterName
/** If this is a derived value class, return its unbox method
* or NoSymbol if it does not exist.
@@ -2391,12 +2388,13 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* If settings.uniqid, adds id.
* If settings.Yshowsymkinds, adds abbreviated symbol kind.
*/
- def nameString: String = (
- if (!settings.uniqid.value && !settings.Yshowsymkinds.value) "" + originalName.decode
- else if (settings.uniqid.value && !settings.Yshowsymkinds.value) originalName.decode + "#" + id
- else if (!settings.uniqid.value && settings.Yshowsymkinds.value) originalName.decode + "#" + abbreviatedKindString
- else originalName.decode + "#" + id + "#" + abbreviatedKindString
- )
+ def nameString: String = {
+ val name_s = if (settings.debug.value) "" + unexpandedName else unexpandedName.dropLocal.decode
+ val id_s = if (settings.uniqid.value) "#" + id else ""
+ val kind_s = if (settings.Yshowsymkinds.value) "#" + abbreviatedKindString else ""
+
+ name_s + id_s + kind_s
+ }
def fullNameString: String = {
def recur(sym: Symbol): String = {
@@ -2623,20 +2621,32 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** change name by appending $$<fully-qualified-name-of-class `base`>
- * Do the same for any accessed symbols or setters/getters
+ * Do the same for any accessed symbols or setters/getters.
+ * If the accessor to be renamed is overriding a base symbol, enter
+ * a cloned symbol with the original name but without ACCESSOR flag.
*/
override def expandName(base: Symbol) {
- if (!hasFlag(EXPANDEDNAME)) {
- setFlag(EXPANDEDNAME)
- if (hasAccessorFlag && !isDeferred) {
- accessed.expandName(base)
- }
- else if (hasGetter) {
- getter(owner).expandName(base)
- setter(owner).expandName(base)
- }
- name = nme.expandedName(name.toTermName, base)
+ def expand(sym: Symbol) {
+ if ((sym eq NoSymbol) || (sym hasFlag EXPANDEDNAME)) () // skip
+ else sym setFlag EXPANDEDNAME setName nme.expandedName(sym.name.toTermName, base)
+ }
+ def cloneAndExpand(accessor: Symbol) {
+ val clone = accessor.cloneSymbol(accessor.owner, (accessor.flags | ARTIFACT) & ~ACCESSOR)
+ expand(accessor)
+ log(s"Expanded overriding accessor to $accessor, but cloned $clone to preserve override")
+ accessor.owner.info.decls enter clone
+ }
+ def expandAccessor(accessor: Symbol) {
+ if (accessor.isOverridingSymbol) cloneAndExpand(accessor) else expand(accessor)
+ }
+ if (hasAccessorFlag && !isDeferred) {
+ expand(accessed)
+ }
+ else if (hasGetter) {
+ expandAccessor(getter(owner))
+ expandAccessor(setter(owner))
}
+ expand(this)
}
}
implicit val TermSymbolTag = ClassTag[TermSymbol](classOf[TermSymbol])
@@ -3065,7 +3075,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if (Statistics.canEnable) Statistics.incCounter(nameCount)
if (needsFlatClasses) {
if (flatname eq null)
- flatname = nme.flattenedName(rawowner.name, rawname).toTypeName
+ flatname = tpnme.flattenedName(rawowner.name, rawname)
flatname
}
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index e96fcc90df..b1f58814c7 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -188,7 +188,7 @@ abstract class TreeInfo {
def isVariableOrGetter(tree: Tree) = {
def sym = tree.symbol
def isVar = sym.isVariable
- def isGetter = mayBeVarGetter(sym) && sym.owner.info.member(nme.getterToSetter(sym.name.toTermName)) != NoSymbol
+ def isGetter = mayBeVarGetter(sym) && sym.owner.info.member(sym.setterName) != NoSymbol
tree match {
case Ident(_) => isVar
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index c00337e578..7467ccc6b9 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -242,6 +242,9 @@ trait Trees extends api.Trees { self: SymbolTable =>
trait NameTree extends Tree with NameTreeApi {
def name: Name
+ def getterName: TermName = name.getterName
+ def setterName: TermName = name.setterName
+ def localName: TermName = name.localName
}
trait RefTree extends SymTree with NameTree with RefTreeApi {
@@ -1488,6 +1491,11 @@ trait Trees extends api.Trees { self: SymbolTable =>
/** Substitute symbols in `from` with symbols in `to`. Returns a new
* tree using the new symbols and whose Ident and Select nodes are
* name-consistent with the new symbols.
+ *
+ * Note: This is currently a destructive operation on the original Tree.
+ * Trees currently assigned a symbol in `from` will be assigned the new symbols
+ * without copying, and trees that define symbols with an `info` that refer
+ * a symbol in `from` will have a new type assigned.
*/
class TreeSymSubstituter(from: List[Symbol], to: List[Symbol]) extends Transformer {
val symSubst = new SubstSymMap(from, to)
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index d7ff4faa5d..25b05ae6b3 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -871,7 +871,7 @@ trait Types
def baseTypeSeqDepth: Int = 1
/** The list of all baseclasses of this type (including its own typeSymbol)
- * in reverse linearization order, starting with the class itself and ending
+ * in linearization order, starting with the class itself and ending
* in class Any.
*/
def baseClasses: List[Symbol] = List()
@@ -1306,7 +1306,7 @@ trait Types
override def isVolatile = false
override def isHigherKinded = sym.isRefinementClass && underlying.isHigherKinded
override def prefixString =
- if (settings.debug.value) sym.nameString + ".this."
+ if (settings.debug) sym.nameString + ".this."
else if (sym.isAnonOrRefinementClass) "this."
else if (sym.isOmittablePrefix) ""
else if (sym.isModuleClass) sym.fullNameString + "."
@@ -1522,7 +1522,7 @@ trait Types
typeSymbol.isAnonOrRefinementClass && (decls exists symbolIsPossibleInRefinement)
override def safeToString: String = parentsString(parents) + (
- (if (settings.debug.value || parents.isEmpty || (decls.elems ne null))
+ (if (settings.debug || parents.isEmpty || (decls.elems ne null))
fullyInitializeScope(decls).mkString("{", "; ", "}") else "")
)
}
@@ -1622,7 +1622,7 @@ trait Types
object baseClassesCycleMonitor {
private var open: List[Symbol] = Nil
@inline private def cycleLog(msg: => String) {
- if (settings.debug.value)
+ if (settings.debug)
Console.err.println(msg)
}
def size = open.size
@@ -1868,7 +1868,7 @@ trait Types
tp match {
case tr @ TypeRef(_, sym, args) if args.nonEmpty =>
val tparams = tr.initializedTypeParams
- if (settings.debug.value && !sameLength(tparams, args))
+ if (settings.debug && !sameLength(tparams, args))
devWarning(s"Mismatched zip in computeRefs(): ${sym.info.typeParams}, $args")
foreach2(tparams, args) { (tparam1, arg) =>
@@ -1934,7 +1934,7 @@ trait Types
override def kind = "ClassInfoType"
override def safeToString =
- if (settings.debug.value || decls.size > 1)
+ if (settings.debug || decls.size > 1)
formattedToString
else
super.safeToString
@@ -1943,7 +1943,7 @@ trait Types
*/
def formattedToString: String =
parents.mkString("\n with ") + (
- if (settings.debug.value || parents.isEmpty || (decls.elems ne null))
+ if (settings.debug || parents.isEmpty || (decls.elems ne null))
fullyInitializeScope(decls).mkString(" {\n ", "\n ", "\n}")
else ""
)
@@ -2352,7 +2352,7 @@ trait Types
// ensure that symbol is not a local copy with a name coincidence
private def needsPreString = (
- settings.debug.value
+ settings.debug
|| !shorthands(sym.fullName)
|| (sym.ownersIterator exists (s => !s.isClass))
)
@@ -2403,12 +2403,12 @@ trait Types
""
}
override def safeToString = {
- val custom = if (settings.debug.value) "" else customToString
+ val custom = if (settings.debug) "" else customToString
if (custom != "") custom
else finishPrefix(preString + sym.nameString + argsString)
}
override def prefixString = "" + (
- if (settings.debug.value)
+ if (settings.debug)
super.prefixString
else if (sym.isOmittablePrefix)
""
@@ -2422,20 +2422,28 @@ trait Types
override def kind = "TypeRef"
}
+ // No longer defined as anonymous classes in `object TypeRef` to avoid an unnecessary outer pointer.
+ private final class AliasArgsTypeRef(pre: Type, sym: Symbol, args: List[Type]) extends ArgsTypeRef(pre, sym, args) with AliasTypeRef
+ private final class AbstractArgsTypeRef(pre: Type, sym: Symbol, args: List[Type]) extends ArgsTypeRef(pre, sym, args) with AbstractTypeRef
+ private final class ClassArgsTypeRef(pre: Type, sym: Symbol, args: List[Type]) extends ArgsTypeRef(pre, sym, args) with ClassTypeRef
+ private final class AliasNoArgsTypeRef(pre: Type, sym: Symbol) extends NoArgsTypeRef(pre, sym) with AliasTypeRef
+ private final class AbstractNoArgsTypeRef(pre: Type, sym: Symbol) extends NoArgsTypeRef(pre, sym) with AbstractTypeRef
+ private final class ClassNoArgsTypeRef(pre: Type, sym: Symbol) extends NoArgsTypeRef(pre, sym) with ClassTypeRef
+
object TypeRef extends TypeRefExtractor {
def apply(pre: Type, sym: Symbol, args: List[Type]): Type = unique({
if (args.nonEmpty) {
- if (sym.isAliasType) new ArgsTypeRef(pre, sym, args) with AliasTypeRef
- else if (sym.isAbstractType) new ArgsTypeRef(pre, sym, args) with AbstractTypeRef
- else new ArgsTypeRef(pre, sym, args) with ClassTypeRef
+ if (sym.isAliasType) new AliasArgsTypeRef(pre, sym, args)
+ else if (sym.isAbstractType) new AbstractArgsTypeRef(pre, sym, args)
+ else new ClassArgsTypeRef(pre, sym, args)
}
else {
- if (sym.isAliasType) new NoArgsTypeRef(pre, sym) with AliasTypeRef
- else if (sym.isAbstractType) new NoArgsTypeRef(pre, sym) with AbstractTypeRef
+ if (sym.isAliasType) new AliasNoArgsTypeRef(pre, sym)
+ else if (sym.isAbstractType) new AbstractNoArgsTypeRef(pre, sym)
else if (sym.isRefinementClass) new RefinementTypeRef(pre, sym)
else if (sym.isPackageClass) new PackageTypeRef(pre, sym)
else if (sym.isModuleClass) new ModuleTypeRef(pre, sym)
- else new NoArgsTypeRef(pre, sym) with ClassTypeRef
+ else new ClassNoArgsTypeRef(pre, sym)
}
})
}
@@ -2714,10 +2722,10 @@ trait Types
override def safeToString: String = {
def clauses = {
val str = quantified map (_.existentialToString) mkString (" forSome { ", "; ", " }")
- if (settings.explaintypes.value) "(" + str + ")" else str
+ if (settings.explaintypes) "(" + str + ")" else str
}
underlying match {
- case TypeRef(pre, sym, args) if !settings.debug.value && isRepresentableWithWildcards =>
+ case TypeRef(pre, sym, args) if !settings.debug && isRepresentableWithWildcards =>
"" + TypeRef(pre, sym, Nil) + wildcardArgsString(quantified.toSet, args).mkString("[", ", ", "]")
case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) =>
"(" + underlying + ")" + clauses
@@ -3220,7 +3228,7 @@ trait Types
if (sym.owner.isTerm && (sym.owner != encl)) Some(sym.owner) else None
).flatten map (s => s.decodedName + tparamsOfSym(s)) mkString "#"
}
- private def levelString = if (settings.explaintypes.value) level else ""
+ private def levelString = if (settings.explaintypes) level else ""
override def safeToString = (
if ((constr eq null) || (constr.inst eq null)) "TVar<" + originName + "=null>"
else if (constr.inst ne NoType) "=?" + constr.inst
@@ -3752,10 +3760,11 @@ trait Types
if (tp.isTrivial) tp
else if (tp.prefix.typeSymbol isNonBottomSubClass owner) {
val widened = tp match {
- case _: ConstantType => tp // Java enum constants: don't widen to the enum type!
- case _ => tp.widen // C.X.type widens to C.this.X.type, otherwise `tp asSeenFrom (pre, C)` has no effect.
+ case _: ConstantType => tp // Java enum constants: don't widen to the enum type!
+ case _ => tp.widen // C.X.type widens to C.this.X.type, otherwise `tp asSeenFrom (pre, C)` has no effect.
}
- widened asSeenFrom (pre, tp.typeSymbol.owner)
+ val memType = widened asSeenFrom (pre, tp.typeSymbol.owner)
+ if (tp eq widened) memType else memType.narrow
}
else loop(tp.prefix) memberType tp.typeSymbol
@@ -3783,7 +3792,7 @@ trait Types
* the maximum depth `bd` of all types in the base type sequences of these types.
*/
private def lubDepthAdjust(td: Int, bd: Int): Int =
- if (settings.XfullLubs.value) bd
+ if (settings.XfullLubs) bd
else if (bd <= 3) bd
else if (bd <= 5) td max (bd - 1)
else if (bd <= 7) td max (bd - 2)
@@ -3875,9 +3884,14 @@ trait Types
}
}
- def normalizePlus(tp: Type) =
+ def normalizePlus(tp: Type) = (
if (isRawType(tp)) rawToExistential(tp)
- else tp.normalize
+ else tp.normalize match {
+ // Unify the two representations of module classes
+ case st @ SingleType(_, sym) if sym.isModule => st.underlying.normalize
+ case _ => tp.normalize
+ }
+ )
/*
todo: change to:
@@ -4399,7 +4413,7 @@ trait Types
/** An exception for cyclic references from which we can recover */
case class RecoverableCyclicReference(sym: Symbol)
extends TypeError("illegal cyclic reference involving " + sym) {
- if (settings.debug.value) printStackTrace()
+ if (settings.debug) printStackTrace()
}
class NoCommonType(tps: List[Type]) extends Throwable(
@@ -4425,12 +4439,12 @@ trait Types
/** If option `explaintypes` is set, print a subtype trace for `found <:< required`. */
def explainTypes(found: Type, required: Type) {
- if (settings.explaintypes.value) withTypesExplained(found <:< required)
+ if (settings.explaintypes) withTypesExplained(found <:< required)
}
/** If option `explaintypes` is set, print a subtype trace for `op(found, required)`. */
def explainTypes(op: (Type, Type) => Any, found: Type, required: Type) {
- if (settings.explaintypes.value) withTypesExplained(op(found, required))
+ if (settings.explaintypes) withTypesExplained(op(found, required))
}
/** Execute `op` while printing a trace of the operations on types executed. */
diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
index e7a1ea9311..68f9fc8e83 100644
--- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
+++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
@@ -49,3 +49,8 @@ abstract class MutableSettings extends AbsSettings {
def XfullLubs: BooleanSetting
def breakCycles: BooleanSetting
}
+object MutableSettings {
+ import scala.language.implicitConversions
+ /** Support the common use case, `if (settings.debug) println("Hello, martin.")` */
+ @inline implicit def reflectSettingToBoolean(s: MutableSettings#BooleanSetting): Boolean = s.value
+}
diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
index 5bdc5f8a73..921d2e3d66 100644
--- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
+++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
@@ -366,7 +366,7 @@ private[internal] trait GlbLubs {
// parameters are not handled correctly.
val ok = ts forall { t =>
isSubType(t, lubRefined, depth) || {
- if (settings.debug.value || printLubs) {
+ if (settings.debug || printLubs) {
Console.println(
"Malformed lub: " + lubRefined + "\n" +
"Argument " + t + " does not conform. Falling back to " + lubBase
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
index e9d3ffbf56..da8e64ea16 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
@@ -52,14 +52,17 @@ trait TypeComparers {
private def isSubPre(pre1: Type, pre2: Type, sym: Symbol) =
if ((pre1 ne pre2) && (pre1 ne NoPrefix) && (pre2 ne NoPrefix) && pre1 <:< pre2) {
- if (settings.debug.value) println(s"new isSubPre $sym: $pre1 <:< $pre2")
+ if (settings.debug) println(s"new isSubPre $sym: $pre1 <:< $pre2")
true
} else
false
- private def equalSymsAndPrefixes(sym1: Symbol, pre1: Type, sym2: Symbol, pre2: Type): Boolean =
- if (sym1 == sym2) sym1.hasPackageFlag || sym1.owner.hasPackageFlag || phase.erasedTypes || pre1 =:= pre2
- else (sym1.name == sym2.name) && isUnifiable(pre1, pre2)
+ private def equalSymsAndPrefixes(sym1: Symbol, pre1: Type, sym2: Symbol, pre2: Type): Boolean = (
+ if (sym1 == sym2)
+ sym1.hasPackageFlag || sym1.owner.hasPackageFlag || phase.erasedTypes || pre1 =:= pre2
+ else
+ (sym1.name == sym2.name) && isUnifiable(pre1, pre2)
+ )
def isDifferentType(tp1: Type, tp2: Type): Boolean = try {
@@ -126,7 +129,13 @@ trait TypeComparers {
tp2.typeSymbol.isPackageClass
else if (tp2 eq NoPrefix) // !! I do not see how this would be warranted by the spec
tp1.typeSymbol.isPackageClass
+ else if (tp1.isInstanceOf[AnnotatedType] || tp2.isInstanceOf[AnnotatedType])
+ annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && (tp1.withoutAnnotations =:= tp2.withoutAnnotations)
else {
+ // We flush out any AnnotatedTypes before calling isSameType2 because
+ // unlike most other subclasses of Type, we have to allow for equivalence of any
+ // combination of { tp1, tp2 } { is, is not } an AnnotatedType - this because the
+ // logic of "annotationsConform" is arbitrary and unknown.
isSameType2(tp1, tp2) || {
val tp1n = normalizePlus(tp1)
val tp2n = normalizePlus(tp2)
@@ -135,165 +144,99 @@ trait TypeComparers {
}
}
- def isSameType2(tp1: Type, tp2: Type): Boolean = {
- tp1 match {
- case tr1: TypeRef =>
- tp2 match {
- case tr2: TypeRef =>
- return (equalSymsAndPrefixes(tr1.sym, tr1.pre, tr2.sym, tr2.pre) &&
- ((tp1.isHigherKinded && tp2.isHigherKinded && tp1.normalize =:= tp2.normalize) ||
- isSameTypes(tr1.args, tr2.args))) ||
- ((tr1.pre, tr2.pre) match {
- case (tv @ TypeVar(_,_), _) => tv.registerTypeSelection(tr1.sym, tr2)
- case (_, tv @ TypeVar(_,_)) => tv.registerTypeSelection(tr2.sym, tr1)
- case _ => false
- })
- case _: SingleType =>
- return isSameType2(tp2, tp1) // put singleton type on the left, caught below
- case _ =>
- }
- case tt1: ThisType =>
- tp2 match {
- case tt2: ThisType =>
- if (tt1.sym == tt2.sym) return true
- case _ =>
- }
- case st1: SingleType =>
- tp2 match {
- case st2: SingleType =>
- if (equalSymsAndPrefixes(st1.sym, st1.pre, st2.sym, st2.pre)) return true
- case TypeRef(pre2, sym2, Nil) =>
- if (sym2.isModuleClass && equalSymsAndPrefixes(st1.sym, st1.pre, sym2.sourceModule, pre2)) return true
- case _ =>
- }
- case ct1: ConstantType =>
- tp2 match {
- case ct2: ConstantType =>
- return (ct1.value == ct2.value)
- case _ =>
- }
- case rt1: RefinedType =>
- tp2 match {
- case rt2: RefinedType => //
- def isSubScope(s1: Scope, s2: Scope): Boolean = s2.toList.forall {
- sym2 =>
- var e1 = s1.lookupEntry(sym2.name)
- (e1 ne null) && {
- val substSym = sym2.info.substThis(sym2.owner, e1.sym.owner)
- var isEqual = false
- while (!isEqual && (e1 ne null)) {
- isEqual = e1.sym.info =:= substSym
- e1 = s1.lookupNextEntry(e1)
- }
- isEqual
- }
- }
- //Console.println("is same? " + tp1 + " " + tp2 + " " + tp1.typeSymbol.owner + " " + tp2.typeSymbol.owner)//DEBUG
- return isSameTypes(rt1.parents, rt2.parents) && {
- val decls1 = rt1.decls
- val decls2 = rt2.decls
- isSubScope(decls1, decls2) && isSubScope(decls2, decls1)
- }
- case _ =>
- }
- case mt1: MethodType =>
- tp2 match {
- case mt2: MethodType =>
- return isSameTypes(mt1.paramTypes, mt2.paramTypes) &&
- mt1.resultType =:= mt2.resultType.substSym(mt2.params, mt1.params) &&
- mt1.isImplicit == mt2.isImplicit
- // note: no case NullaryMethodType(restpe) => return mt1.params.isEmpty && mt1.resultType =:= restpe
- case _ =>
- }
- case NullaryMethodType(restpe1) =>
- tp2 match {
- // note: no case mt2: MethodType => return mt2.params.isEmpty && restpe =:= mt2.resultType
- case NullaryMethodType(restpe2) =>
- return restpe1 =:= restpe2
- case _ =>
- }
- case PolyType(tparams1, res1) =>
- tp2 match {
- case PolyType(tparams2, res2) =>
- // assert((tparams1 map (_.typeParams.length)) == (tparams2 map (_.typeParams.length)))
- // @M looks like it might suffer from same problem as #2210
- return (
- (sameLength(tparams1, tparams2)) && // corresponds does not check length of two sequences before checking the predicate
- (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) &&
- res1 =:= res2.substSym(tparams2, tparams1)
- )
- case _ =>
- }
- case ExistentialType(tparams1, res1) =>
- tp2 match {
- case ExistentialType(tparams2, res2) =>
- // @M looks like it might suffer from same problem as #2210
- return (
- // corresponds does not check length of two sequences before checking the predicate -- faster & needed to avoid crasher in #2956
- sameLength(tparams1, tparams2) &&
- (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) &&
- res1 =:= res2.substSym(tparams2, tparams1)
- )
- case _ =>
- }
- case TypeBounds(lo1, hi1) =>
- tp2 match {
- case TypeBounds(lo2, hi2) =>
- return lo1 =:= lo2 && hi1 =:= hi2
- case _ =>
- }
- case BoundedWildcardType(bounds) =>
- return bounds containsType tp2
- case _ =>
- }
- tp2 match {
- case BoundedWildcardType(bounds) =>
- return bounds containsType tp1
- case _ =>
- }
- tp1 match {
- case tv @ TypeVar(_,_) =>
- return tv.registerTypeEquality(tp2, typeVarLHS = true)
- case _ =>
- }
- tp2 match {
- case tv @ TypeVar(_,_) =>
- return tv.registerTypeEquality(tp1, typeVarLHS = false)
- case _ =>
+ private def isSameHKTypes(tp1: Type, tp2: Type) = (
+ tp1.isHigherKinded
+ && tp2.isHigherKinded
+ && (tp1.normalize =:= tp2.normalize)
+ )
+ private def isSameTypeRef(tr1: TypeRef, tr2: TypeRef) = (
+ equalSymsAndPrefixes(tr1.sym, tr1.pre, tr2.sym, tr2.pre)
+ && (isSameHKTypes(tr1, tr2) || isSameTypes(tr1.args, tr2.args))
+ )
+
+ private def isSameSingletonType(tp1: SingletonType, tp2: SingletonType): Boolean = {
+ // We don't use dealiasWiden here because we are looking for the SAME type,
+ // and widening leads to a less specific type. The logic is along the lines of
+ // dealiasAndFollowUnderlyingAsLongAsTheTypeIsEquivalent. This method is only
+ // called after a surface comparison has failed, so if chaseDealiasedUnderlying
+ // does not produce a type other than tp1 and tp2, return false.
+ @tailrec def chaseDealiasedUnderlying(tp: Type): Type = tp.underlying.dealias match {
+ case next: SingletonType if tp ne next => chaseDealiasedUnderlying(next)
+ case _ => tp
}
- tp1 match {
- case _: AnnotatedType =>
- return annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations
- case _ =>
+ val origin1 = chaseDealiasedUnderlying(tp1)
+ val origin2 = chaseDealiasedUnderlying(tp2)
+ ((origin1 ne tp1) || (origin2 ne tp2)) && (origin1 =:= origin2)
+ }
+
+ private def isSameMethodType(mt1: MethodType, mt2: MethodType) = (
+ isSameTypes(mt1.paramTypes, mt2.paramTypes)
+ && (mt1.resultType =:= mt2.resultType.substSym(mt2.params, mt1.params))
+ && (mt1.isImplicit == mt2.isImplicit)
+ )
+
+ private def equalTypeParamsAndResult(tparams1: List[Symbol], res1: Type, tparams2: List[Symbol], res2: Type) = {
+ def subst(info: Type) = info.substSym(tparams2, tparams1)
+ // corresponds does not check length of two sequences before checking the predicate,
+ // but SubstMap assumes it has been checked (SI-2956)
+ ( sameLength(tparams1, tparams2)
+ && (tparams1 corresponds tparams2)((p1, p2) => p1.info =:= subst(p2.info))
+ && (res1 =:= subst(res2))
+ )
+ }
+
+ def isSameType2(tp1: Type, tp2: Type): Boolean = {
+ /** Here we highlight those unfortunate type-like constructs which
+ * are hidden bundles of mutable state, cruising the type system picking
+ * up any type constraints naive enough to get into their hot rods.
+ */
+ def mutateNonTypeConstructs(lhs: Type, rhs: Type) = lhs match {
+ case BoundedWildcardType(bounds) => bounds containsType rhs
+ case tv @ TypeVar(_, _) => tv.registerTypeEquality(rhs, typeVarLHS = lhs eq tp1)
+ case TypeRef(tv @ TypeVar(_, _), sym, _) => tv.registerTypeSelection(sym, rhs)
+ case _ => false
}
- tp2 match {
- case _: AnnotatedType =>
- return annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations
- case _ =>
+ /* SingletonType receives this additional scrutiny because there are
+ * a variety of Types which must be treated as equivalent even if they
+ * arrive in different guises. For instance, object Foo in the following
+ * might appear in (at least) the four given below.
+ *
+ * package pkg { object Foo ; type Bar = Foo.type }
+ *
+ * ModuleClassTypeRef(pkg.type, Foo: ModuleClassSymbol, Nil)
+ * ThisType(Foo: ModuleClassSymbol)
+ * SingleType(pkg.type, Foo: ModuleSymbol)
+ * AliasTypeRef(NoPrefix, sym: AliasSymbol, Nil) where sym.info is one of the above
+ */
+ def sameSingletonType = tp1 match {
+ case tp1: SingletonType => tp2 match {
+ case tp2: SingletonType => isSameSingletonType(tp1, tp2)
+ case _ => false
+ }
+ case _ => false
}
- tp1 match {
- case _: SingletonType =>
- tp2 match {
- case _: SingletonType =>
- def chaseDealiasedUnderlying(tp: Type): Type = {
- var origin = tp
- var next = origin.underlying.dealias
- while (next.isInstanceOf[SingletonType]) {
- assert(origin ne next, origin)
- origin = next
- next = origin.underlying.dealias
- }
- origin
- }
- val origin1 = chaseDealiasedUnderlying(tp1)
- val origin2 = chaseDealiasedUnderlying(tp2)
- ((origin1 ne tp1) || (origin2 ne tp2)) && (origin1 =:= origin2)
- case _ =>
- false
- }
- case _ =>
- false
+ /** Those false cases certainly are ugly. There's a proposed SIP to deuglify it.
+ * https://docs.google.com/a/improving.org/document/d/1onPrzSqyDpHScc9PS_hpxJwa3FlPtthxw-bAuuEe8uA
+ */
+ def sameTypeAndSameCaseClass = tp1 match {
+ case tp1: TypeRef => tp2 match { case tp2: TypeRef => isSameTypeRef(tp1, tp2) ; case _ => false }
+ case tp1: MethodType => tp2 match { case tp2: MethodType => isSameMethodType(tp1, tp2) ; case _ => false }
+ case RefinedType(ps1, decls1) => tp2 match { case RefinedType(ps2, decls2) => isSameTypes(ps1, ps2) && (decls1 isSameScope decls2) ; case _ => false }
+ case SingleType(pre1, sym1) => tp2 match { case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1, pre1, sym2, pre2) ; case _ => false }
+ case PolyType(ps1, res1) => tp2 match { case PolyType(ps2, res2) => equalTypeParamsAndResult(ps1, res1, ps2, res2) ; case _ => false }
+ case ExistentialType(qs1, res1) => tp2 match { case ExistentialType(qs2, res2) => equalTypeParamsAndResult(qs1, res1, qs2, res2) ; case _ => false }
+ case ThisType(sym1) => tp2 match { case ThisType(sym2) => sym1 == sym2 ; case _ => false }
+ case ConstantType(c1) => tp2 match { case ConstantType(c2) => c1 == c2 ; case _ => false }
+ case NullaryMethodType(res1) => tp2 match { case NullaryMethodType(res2) => res1 =:= res2 ; case _ => false }
+ case TypeBounds(lo1, hi1) => tp2 match { case TypeBounds(lo2, hi2) => lo1 =:= lo2 && hi1 =:= hi2 ; case _ => false }
+ case _ => false
}
+
+ ( sameTypeAndSameCaseClass
+ || sameSingletonType
+ || mutateNonTypeConstructs(tp1, tp2)
+ || mutateNonTypeConstructs(tp2, tp1)
+ )
}
def isSubType(tp1: Type, tp2: Type): Boolean = isSubType(tp1, tp2, AnyDepth)
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
index a002b01f70..b0feb0a7fb 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
@@ -66,7 +66,7 @@ private[internal] trait TypeConstraints {
def clear() {
lock()
try {
- if (settings.debug.value)
+ if (settings.debug)
self.log("Clearing " + log.size + " entries from the undoLog.")
log = Nil
} finally unlock()
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala b/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala
index 263b0f5a3e..c86383e9e3 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala
@@ -14,7 +14,7 @@ private[internal] trait TypeToStrings {
protected def typeToString(tpe: Type): String =
if (tostringRecursions >= maxTostringRecursions) {
devWarning("Exceeded recursion depth attempting to print " + util.shortClassOfInstance(tpe))
- if (settings.debug.value)
+ if (settings.debug)
(new Throwable).printStackTrace
"..."
diff --git a/src/reflect/scala/reflect/internal/transform/UnCurry.scala b/src/reflect/scala/reflect/internal/transform/UnCurry.scala
index 32d3171b26..1f7638a621 100644
--- a/src/reflect/scala/reflect/internal/transform/UnCurry.scala
+++ b/src/reflect/scala/reflect/internal/transform/UnCurry.scala
@@ -25,7 +25,14 @@ trait UnCurry {
val tp = expandAlias(tp0)
tp match {
case MethodType(params, MethodType(params1, restpe)) =>
- apply(MethodType(params ::: params1, restpe))
+ // This transformation is described in UnCurryTransformer.dependentParamTypeErasure
+ val packSymbolsMap = new TypeMap {
+ // Wrapping in a TypeMap to reuse the code that opts for a fast path if the function is an identity.
+ def apply(tp: Type): Type = packSymbols(params, tp)
+ }
+ val existentiallyAbstractedParam1s = packSymbolsMap.mapOver(params1)
+ val substitutedResult = restpe.substSym(params1, existentiallyAbstractedParam1s)
+ apply(MethodType(params ::: existentiallyAbstractedParam1s, substitutedResult))
case MethodType(params, ExistentialType(tparams, restpe @ MethodType(_, _))) =>
abort("unexpected curried method types with intervening existential")
case MethodType(h :: t, restpe) if h.isImplicit =>
diff --git a/src/reflect/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala
index 63b7f73386..d6fca9d186 100644
--- a/src/reflect/scala/reflect/internal/util/Collections.scala
+++ b/src/reflect/scala/reflect/internal/util/Collections.scala
@@ -76,6 +76,19 @@ trait Collections {
lb.toList
}
+ final def distinctBy[A, B](xs: List[A])(f: A => B): List[A] = {
+ val buf = new ListBuffer[A]
+ val seen = mutable.Set[B]()
+ xs foreach { x =>
+ val y = f(x)
+ if (!seen(y)) {
+ buf += x
+ seen += y
+ }
+ }
+ buf.toList
+ }
+
@tailrec final def flattensToEmpty(xss: Seq[Seq[_]]): Boolean = {
xss.isEmpty || xss.head.isEmpty && flattensToEmpty(xss.tail)
}
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 2e38caaf5d..3211bb7919 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -6,12 +6,14 @@ import scala.collection.mutable.WeakHashMap
import java.lang.{Class => jClass, Package => jPackage}
import java.lang.reflect.{
- Method => jMethod, Constructor => jConstructor, Modifier => jModifier, Field => jField,
+ Method => jMethod, Constructor => jConstructor, Field => jField,
Member => jMember, Type => jType, TypeVariable => jTypeVariable, Array => jArray,
+ AccessibleObject => jAccessibleObject,
GenericDeclaration, GenericArrayType, ParameterizedType, WildcardType, AnnotatedElement }
import java.lang.annotation.{Annotation => jAnnotation}
import java.io.IOException
-import internal.MissingRequirementError
+import scala.reflect.internal.{ MissingRequirementError, JavaAccFlags, JMethodOrConstructor }
+import JavaAccFlags._
import internal.pickling.ByteCodecs
import internal.ClassfileConstants._
import internal.pickling.UnPickler
@@ -88,12 +90,12 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
// ----------- Caching ------------------------------------------------------------------
- private val classCache = new TwoWayCache[jClass[_], ClassSymbol]
- private val packageCache = new TwoWayCache[Package, ModuleSymbol]
- private val methodCache = new TwoWayCache[jMethod, MethodSymbol]
+ private val classCache = new TwoWayCache[jClass[_], ClassSymbol]
+ private val packageCache = new TwoWayCache[Package, ModuleSymbol]
+ private val methodCache = new TwoWayCache[jMethod, MethodSymbol]
private val constructorCache = new TwoWayCache[jConstructor[_], MethodSymbol]
- private val fieldCache = new TwoWayCache[jField, TermSymbol]
- private val tparamCache = new TwoWayCache[jTypeVariable[_ <: GenericDeclaration], TypeSymbol]
+ private val fieldCache = new TwoWayCache[jField, TermSymbol]
+ private val tparamCache = new TwoWayCache[jTypeVariable[_ <: GenericDeclaration], TypeSymbol]
private[runtime] def toScala[J: HasJavaClass, S](cache: TwoWayCache[J, S], key: J)(body: (JavaMirror, J) => S): S =
cache.toScala(key){
@@ -101,38 +103,36 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
body(mirrorDefining(jclazz), key)
}
- private implicit val classHasJavaClass: HasJavaClass[jClass[_]] =
- new HasJavaClass(identity)
- private implicit val methHasJavaClass: HasJavaClass[jMethod]
- = new HasJavaClass(_.getDeclaringClass)
- private implicit val fieldHasJavaClass: HasJavaClass[jField] =
- new HasJavaClass(_.getDeclaringClass)
- private implicit val constrHasJavaClass: HasJavaClass[jConstructor[_]] =
- new HasJavaClass(_.getDeclaringClass)
+ private implicit val classHasJavaClass: HasJavaClass[jClass[_]] = new HasJavaClass(identity)
+ private implicit val methHasJavaClass: HasJavaClass[jMethod] = new HasJavaClass(_.getDeclaringClass)
+ private implicit val fieldHasJavaClass: HasJavaClass[jField] = new HasJavaClass(_.getDeclaringClass)
+ private implicit val constrHasJavaClass: HasJavaClass[jConstructor[_]] = new HasJavaClass(_.getDeclaringClass)
private implicit val tparamHasJavaClass: HasJavaClass[jTypeVariable[_ <: GenericDeclaration]] =
new HasJavaClass ( (tparam: jTypeVariable[_ <: GenericDeclaration]) => {
tparam.getGenericDeclaration match {
- case jclazz: jClass[_] => jclazz
- case jmeth: jMethod => jmeth.getDeclaringClass
+ case jclazz: jClass[_] => jclazz
+ case jmeth: jMethod => jmeth.getDeclaringClass
case jconstr: jConstructor[_] => jconstr.getDeclaringClass
}
})
// ----------- Implementations of mirror operations and classes -------------------
- private def ErrorInnerClass(sym: Symbol) = throw new ScalaReflectionException(s"$sym is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror")
- private def ErrorInnerModule(sym: Symbol) = throw new ScalaReflectionException(s"$sym is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror")
- private def ErrorStaticClass(sym: Symbol) = throw new ScalaReflectionException(s"$sym is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror")
- private def ErrorStaticModule(sym: Symbol) = throw new ScalaReflectionException(s"$sym is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror")
- private def ErrorNotMember(sym: Symbol, owner: Symbol) = throw new ScalaReflectionException(s"expected a member of $owner, you provided ${sym.kindString} ${sym.fullName}")
- private def ErrorNotField(sym: Symbol) = throw new ScalaReflectionException(s"expected a field or an accessor method symbol, you provided $sym")
- private def ErrorNonExistentField(sym: Symbol) = throw new ScalaReflectionException(
+ private def abort(msg: String) = throw new ScalaReflectionException(msg)
+
+ private def ErrorInnerClass(sym: Symbol) = abort(s"$sym is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror")
+ private def ErrorInnerModule(sym: Symbol) = abort(s"$sym is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror")
+ private def ErrorStaticClass(sym: Symbol) = abort(s"$sym is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror")
+ private def ErrorStaticModule(sym: Symbol) = abort(s"$sym is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror")
+ private def ErrorNotMember(sym: Symbol, owner: Symbol) = abort(s"expected a member of $owner, you provided ${sym.kindString} ${sym.fullName}")
+ private def ErrorNotField(sym: Symbol) = abort(s"expected a field or an accessor method symbol, you provided $sym")
+ private def ErrorSetImmutableField(sym: Symbol) = abort(s"cannot set an immutable field ${sym.name}")
+ private def ErrorNotConstructor(sym: Symbol, owner: Symbol) = abort(s"expected a constructor of $owner, you provided $sym")
+ private def ErrorFree(member: Symbol, freeType: Symbol) = abort(s"cannot reflect ${member.kindString} ${member.name}, because it's a member of a weak type ${freeType.name}")
+ private def ErrorNonExistentField(sym: Symbol) = abort(
sm"""Scala field ${sym.name} isn't represented as a Java field, neither it has a Java accessor method
|note that private parameters of class constructors don't get mapped onto fields and/or accessors,
|unless they are used outside of their declaring constructors.""")
- private def ErrorSetImmutableField(sym: Symbol) = throw new ScalaReflectionException(s"cannot set an immutable field ${sym.name}")
- private def ErrorNotConstructor(sym: Symbol, owner: Symbol) = throw new ScalaReflectionException(s"expected a constructor of $owner, you provided $sym")
- private def ErrorFree(member: Symbol, freeType: Symbol) = throw new ScalaReflectionException(s"cannot reflect ${member.kindString} ${member.name}, because it's a member of a weak type ${freeType.name}")
/** Helper functions for extracting typed values from a (Class[_], Any)
* representing an annotation argument.
@@ -210,7 +210,6 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
case _ => body
}
}
-
private def checkMemberOf(sym: Symbol, owner: ClassSymbol) {
if (sym.owner == AnyClass || sym.owner == AnyRefClass || sym.owner == ObjectClass) {
// do nothing
@@ -236,16 +235,12 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
if (staticClazz.isPrimitive) staticClazz else dynamicClazz
}
- private class JavaInstanceMirror[T: ClassTag](val instance: T)
- extends InstanceMirror {
+ private class JavaInstanceMirror[T: ClassTag](val instance: T) extends InstanceMirror {
def symbol = thisMirror.classSymbol(preciseClass(instance))
def reflectField(field: TermSymbol): FieldMirror = {
checkMemberOf(field, symbol)
if ((field.isMethod && !field.isAccessor) || field.isModule) ErrorNotField(field)
- val name =
- if (field.isGetter) nme.getterToLocal(field.name)
- else if (field.isSetter) nme.getterToLocal(nme.setterToGetter(field.name))
- else field.name
+ val name = if (field.isAccessor) field.localName else field.name
val field1 = (field.owner.info decl name).asTerm
try fieldToJava(field1)
catch {
@@ -272,12 +267,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private class JavaFieldMirror(val receiver: Any, val symbol: TermSymbol)
extends FieldMirror {
- lazy val jfield = {
- val jfield = fieldToJava(symbol)
- if (!jfield.isAccessible) jfield.setAccessible(true)
- jfield
- }
- def get = jfield.get(receiver)
+ lazy val jfield = ensureAccessible(fieldToJava(symbol))
+ def get = jfield get receiver
def set(value: Any) = {
if (!symbol.isMutable) ErrorSetImmutableField(symbol)
jfield.set(receiver, value)
@@ -313,7 +304,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
// the "symbol == Any_getClass || symbol == Object_getClass" test doesn't cut it
// because both AnyVal and its primitive descendants define their own getClass methods
- private def isGetClass(meth: MethodSymbol) = meth.name.toString == "getClass" && meth.paramss.flatten.isEmpty
+ private def isGetClass(meth: MethodSymbol) = (meth.name string_== "getClass") && meth.paramss.flatten.isEmpty
private def isStringConcat(meth: MethodSymbol) = meth == String_+ || (meth.owner.isPrimitiveValueClass && meth.returnType =:= StringClass.toType)
lazy val bytecodelessMethodOwners = Set[Symbol](AnyClass, AnyValClass, AnyRefClass, ObjectClass, ArrayClass) ++ ScalaPrimitiveValueClasses
lazy val bytecodefulObjectMethods = Set[Symbol](Object_clone, Object_equals, Object_finalize, Object_hashCode, Object_toString,
@@ -341,15 +332,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
}
}
}
-
- private abstract class JavaMethodMirror(val symbol: MethodSymbol)
- extends MethodMirror {
- lazy val jmeth = {
- val jmeth = methodToJava(symbol)
- if (!jmeth.isAccessible) jmeth.setAccessible(true)
- jmeth
- }
-
+ private abstract class JavaMethodMirror(val symbol: MethodSymbol) extends MethodMirror {
+ lazy val jmeth = ensureAccessible(methodToJava(symbol))
def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*)
def jinvoke(jmeth: jMethod, receiver: Any, args: Seq[Any]): Any = {
@@ -421,13 +405,13 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
if (!perfectMatch && !varargMatch) {
val n_arguments = if (isVarArgsList(params)) s"${params.length - 1} or more" else s"${params.length}"
val s_arguments = if (params.length == 1 && !isVarArgsList(params)) "argument" else "arguments"
- throw new ScalaReflectionException(s"${showMethodSig(symbol)} takes $n_arguments $s_arguments")
+ abort(s"${showMethodSig(symbol)} takes $n_arguments $s_arguments")
}
def objReceiver = receiver.asInstanceOf[AnyRef]
def objArg0 = args(0).asInstanceOf[AnyRef]
def objArgs = args.asInstanceOf[Seq[AnyRef]]
- def fail(msg: String) = throw new ScalaReflectionException(msg + ", it cannot be invoked with mirrors")
+ def fail(msg: String) = abort(msg + ", it cannot be invoked with mirrors")
def invokePrimitiveMethod = {
val jmeths = classOf[BoxesRunTime].getDeclaredMethods.filter(_.getName == nme.primitiveMethodName(symbol.name).toString)
@@ -467,14 +451,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
extends MethodMirror {
def bind(newReceiver: Any) = new JavaConstructorMirror(newReceiver.asInstanceOf[AnyRef], symbol)
override val receiver = outer
- lazy val jconstr = {
- val jconstr = constructorToJava(symbol)
- if (!jconstr.isAccessible) jconstr.setAccessible(true)
- jconstr
- }
+ lazy val jconstr = ensureAccessible(constructorToJava(symbol))
def apply(args: Any*): Any = {
if (symbol.owner == ArrayClass)
- throw new ScalaReflectionException("Cannot instantiate arrays with mirrors. Consider using `scala.reflect.ClassTag(<class of element>).newArray(<length>)` instead")
+ abort("Cannot instantiate arrays with mirrors. Consider using `scala.reflect.ClassTag(<class of element>).newArray(<length>)` instead")
val effectiveArgs =
if (outer == null) args.asInstanceOf[Seq[AnyRef]]
@@ -535,7 +515,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
}
def javaClass(path: String): jClass[_] =
- Class.forName(path, true, classLoader)
+ jClass.forName(path, true, classLoader)
/** Does `path` correspond to a Java class with that fully qualified name in the current class loader? */
def tryJavaClass(path: String): Option[jClass[_]] = (
@@ -565,7 +545,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
def markAbsent(tpe: Type) = setAllInfos(clazz, module, tpe)
def handleError(ex: Exception) = {
markAbsent(ErrorType)
- if (settings.debug.value) ex.printStackTrace()
+ if (settings.debug) ex.printStackTrace()
val msg = ex.getMessage()
MissingRequirementError.signal(
(if (msg eq null) "reflection error while loading " + clazz.name
@@ -658,13 +638,22 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
sym setAnnotations (jann.getAnnotations map JavaAnnotationProxy).toList
// SI-7065: we're not using getGenericExceptionTypes here to be consistent with ClassfileParser
val jexTpes = jann match {
- case jm: jMethod => jm.getExceptionTypes.toList
+ case jm: jMethod => jm.getExceptionTypes.toList
case jconstr: jConstructor[_] => jconstr.getExceptionTypes.toList
- case _ => Nil
+ case _ => Nil
}
jexTpes foreach (jexTpe => sym.addThrowsAnnotation(classSymbol(jexTpe)))
}
+ private implicit class jClassOps(val clazz: jClass[_]) {
+ def javaFlags: JavaAccFlags = JavaAccFlags(clazz)
+ def scalaFlags: Long = javaFlags.toScalaFlags
+ }
+ private implicit class jMemberOps(val member: jMember) {
+ def javaFlags: JavaAccFlags = JavaAccFlags(member)
+ def scalaFlags: Long = javaFlags.toScalaFlags
+ }
+
/**
* A completer that fills in the types of a Scala class and its companion object
* by copying corresponding type info from a Java class. This completer is used
@@ -684,14 +673,14 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
override def load(sym: Symbol): Unit = {
debugInfo("completing from Java " + sym + "/" + clazz.fullName)//debug
assert(sym == clazz || (module != NoSymbol && (sym == module || sym == module.moduleClass)), sym)
- val flags = toScalaClassFlags(jclazz.getModifiers)
+ val flags = jclazz.scalaFlags
clazz setFlag (flags | JAVA)
if (module != NoSymbol) {
module setFlag (flags & PRIVATE | JAVA)
module.moduleClass setFlag (flags & PRIVATE | JAVA)
}
- relatedSymbols foreach (importPrivateWithinFromJavaFlags(_, jclazz.getModifiers))
+ propagatePackageBoundary(jclazz, relatedSymbols: _*)
copyAnnotations(clazz, jclazz)
// to do: annotations to set also for module?
@@ -723,28 +712,21 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass)
}
- def enter(sym: Symbol, mods: Int) =
- (if (jModifier.isStatic(mods)) module.moduleClass else clazz).info.decls enter sym
+ def enter(sym: Symbol, mods: JavaAccFlags) =
+ ( if (mods.isStatic) module.moduleClass else clazz ).info.decls enter sym
for (jinner <- jclazz.getDeclaredClasses)
jclassAsScala(jinner) // inner class is entered as a side-effect
// no need to call enter explicitly
- pendingLoadActions = { () =>
-
- for (jfield <- jclazz.getDeclaredFields)
- enter(jfieldAsScala(jfield), jfield.getModifiers)
-
- for (jmeth <- jclazz.getDeclaredMethods)
- enter(jmethodAsScala(jmeth), jmeth.getModifiers)
-
- for (jconstr <- jclazz.getConstructors)
- enter(jconstrAsScala(jconstr), jconstr.getModifiers)
-
- } :: pendingLoadActions
+ pendingLoadActions ::= { () =>
+ jclazz.getDeclaredFields foreach (f => enter(jfieldAsScala(f), f.javaFlags))
+ jclazz.getDeclaredMethods foreach (m => enter(jmethodAsScala(m), m.javaFlags))
+ jclazz.getConstructors foreach (c => enter(jconstrAsScala(c), c.javaFlags))
+ }
if (parentsLevel == 0) {
- while (!pendingLoadActions.isEmpty) {
+ while (pendingLoadActions.nonEmpty) {
val item = pendingLoadActions.head
pendingLoadActions = pendingLoadActions.tail
item()
@@ -763,8 +745,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
* If Java modifiers `mods` contain STATIC, return the module class
* of the companion module of `clazz`, otherwise the class `clazz` itself.
*/
- private def followStatic(clazz: Symbol, mods: Int) =
- if (jModifier.isStatic(mods)) clazz.companionModule.moduleClass else clazz
+ private def followStatic(clazz: Symbol, mods: JavaAccFlags) =
+ if (mods.isStatic) clazz.companionModule.moduleClass else clazz
/** Methods which need to be treated with care
* because they either are getSimpleName or call getSimpleName:
@@ -800,7 +782,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
if (jclazz.isMemberClass) {
val jEnclosingClass = jclazz.getEnclosingClass
val sEnclosingClass = classToScala(jEnclosingClass)
- followStatic(sEnclosingClass, jclazz.getModifiers)
+ followStatic(sEnclosingClass, jclazz.javaFlags)
} else if (jclazz.isLocalClass0) {
val jEnclosingMethod = jclazz.getEnclosingMethod
if (jEnclosingMethod != null) {
@@ -828,7 +810,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
* The Scala owner of the Scala symbol corresponding to the Java member `jmember`
*/
private def sOwner(jmember: jMember): Symbol = {
- followStatic(classToScala(jmember.getDeclaringClass), jmember.getModifiers)
+ followStatic(classToScala(jmember.getDeclaringClass), jmember.javaFlags)
}
/**
@@ -844,9 +826,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
* that start with the given name are searched instead.
*/
private def lookup(clazz: Symbol, jname: String): Symbol = {
- def approximateMatch(sym: Symbol, jstr: String): Boolean =
- (sym.name.toString == jstr) ||
- sym.isPrivate && nme.expandedName(sym.name.toTermName, sym.owner).toString == jstr
+ def approximateMatch(sym: Symbol, jstr: String): Boolean = (
+ (sym.name string_== jstr)
+ || sym.isPrivate && (nme.expandedName(sym.name.toTermName, sym.owner) string_== jstr)
+ )
clazz.info.decl(newTermName(jname)) orElse {
(clazz.info.decls.iterator filter (approximateMatch(_, jname))).toList match {
@@ -868,7 +851,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def methodToScala1(jmeth: jMethod): MethodSymbol = {
val jOwner = jmeth.getDeclaringClass
val preOwner = classToScala(jOwner)
- val owner = followStatic(preOwner, jmeth.getModifiers)
+ val owner = followStatic(preOwner, jmeth.javaFlags)
(lookup(owner, jmeth.getName) suchThat (erasesTo(_, jmeth)) orElse jmethodAsScala(jmeth))
.asMethod
}
@@ -882,7 +865,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
toScala(constructorCache, jconstr)(_ constructorToScala1 _)
private def constructorToScala1(jconstr: jConstructor[_]): MethodSymbol = {
- val owner = followStatic(classToScala(jconstr.getDeclaringClass), jconstr.getModifiers)
+ val owner = followStatic(classToScala(jconstr.getDeclaringClass), jconstr.javaFlags)
(lookup(owner, jconstr.getName) suchThat (erasesTo(_, jconstr)) orElse jconstrAsScala(jconstr))
.asMethod
}
@@ -1008,7 +991,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def typeParamToScala1(jparam: jTypeVariable[_ <: GenericDeclaration]): TypeSymbol = {
val owner = genericDeclarationToScala(jparam.getGenericDeclaration)
owner.info match {
- case PolyType(tparams, _) => tparams.find(_.name.toString == jparam.getName).get.asType
+ case PolyType(tparams, _) => tparams.find(_.name string_== jparam.getName).get.asType
}
}
@@ -1020,6 +1003,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
case jmeth: jMethod => methodToScala(jmeth)
case jconstr: jConstructor[_] => constructorToScala(jconstr)
}
+ def reflectMemberToScala(m: jMember): Symbol = m match {
+ case x: GenericDeclaration => genericDeclarationToScala(x)
+ case x: jField => jfieldAsScala(x)
+ }
/**
* Given some Java type arguments, a corresponding list of Scala types, plus potentially
@@ -1094,10 +1081,11 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def jfieldAsScala1(jfield: jField): TermSymbol = {
val field = sOwner(jfield)
- .newValue(newTermName(jfield.getName), NoPosition, toScalaFieldFlags(jfield.getModifiers))
+ .newValue(newTermName(jfield.getName), NoPosition, jfield.scalaFlags)
.setInfo(typeToScala(jfield.getGenericType))
- fieldCache enter (jfield, field)
- importPrivateWithinFromJavaFlags(field, jfield.getModifiers)
+
+ fieldCache.enter(jfield, field)
+ propagatePackageBoundary(jfield, field)
copyAnnotations(field, jfield)
field
}
@@ -1117,16 +1105,19 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def jmethodAsScala1(jmeth: jMethod): MethodSymbol = {
val clazz = sOwner(jmeth)
- val meth = clazz.newMethod(newTermName(jmeth.getName), NoPosition, toScalaMethodFlags(jmeth.getModifiers))
+ val meth = clazz.newMethod(newTermName(jmeth.getName), NoPosition, jmeth.scalaFlags)
methodCache enter (jmeth, meth)
val tparams = jmeth.getTypeParameters.toList map createTypeParameter
val paramtpes = jmeth.getGenericParameterTypes.toList map typeToScala
val resulttpe = typeToScala(jmeth.getGenericReturnType)
setMethType(meth, tparams, paramtpes, resulttpe)
- importPrivateWithinFromJavaFlags(meth, jmeth.getModifiers)
+ propagatePackageBoundary(jmeth.javaFlags, meth)
copyAnnotations(meth, jmeth)
- if ((jmeth.getModifiers & JAVA_ACC_VARARGS) != 0) meth.setInfo(arrayToRepeated(meth.info))
- meth
+
+ if (jmeth.javaFlags.isVarargs)
+ meth modifyInfo arrayToRepeated
+ else
+ meth
}
/**
@@ -1141,13 +1132,13 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def jconstrAsScala1(jconstr: jConstructor[_]): MethodSymbol = {
// [Martin] Note: I know there's a lot of duplication wrt jmethodAsScala, but don't think it's worth it to factor this out.
val clazz = sOwner(jconstr)
- val constr = clazz.newConstructor(NoPosition, toScalaMethodFlags(jconstr.getModifiers))
+ val constr = clazz.newConstructor(NoPosition, jconstr.scalaFlags)
constructorCache enter (jconstr, constr)
val tparams = jconstr.getTypeParameters.toList map createTypeParameter
val paramtpes = jconstr.getGenericParameterTypes.toList map typeToScala
setMethType(constr, tparams, paramtpes, clazz.tpe_*)
constr setInfo GenPolyType(tparams, MethodType(clazz.newSyntheticValueParams(paramtpes), clazz.tpe))
- importPrivateWithinFromJavaFlags(constr, jconstr.getModifiers)
+ propagatePackageBoundary(jconstr.javaFlags, constr)
copyAnnotations(constr, jconstr)
constr
}
@@ -1172,13 +1163,15 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
else if (clazz.isTopLevel)
javaClass(clazz.javaClassName)
else if (clazz.owner.isClass) {
- val childOfClass = !clazz.owner.isModuleClass
- val childOfTopLevel = clazz.owner.isTopLevel
+ val childOfClass = !clazz.owner.isModuleClass
+ val childOfTopLevel = clazz.owner.isTopLevel
val childOfTopLevelObject = clazz.owner.isModuleClass && childOfTopLevel
// suggested in https://issues.scala-lang.org/browse/SI-4023?focusedCommentId=54759#comment-54759
var ownerClazz = classToJava(clazz.owner.asClass)
- if (childOfTopLevelObject) ownerClazz = Class.forName(ownerClazz.getName stripSuffix "$", true, ownerClazz.getClassLoader)
+ if (childOfTopLevelObject)
+ ownerClazz = jClass.forName(ownerClazz.getName stripSuffix "$", true, ownerClazz.getClassLoader)
+
val ownerChildren = ownerClazz.getDeclaredClasses
var fullNameOfJavaClass = ownerClazz.getName
@@ -1202,7 +1195,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
*/
def fieldToJava(fld: TermSymbol): jField = fieldCache.toJava(fld) {
val jclazz = classToJava(fld.owner.asClass)
- val jname = nme.dropLocalSuffix(fld.name).toString
+ val jname = fld.name.dropLocal.toString
try jclazz getDeclaredField jname
catch {
case ex: NoSuchFieldException => jclazz getDeclaredField expandedName(fld)
@@ -1215,7 +1208,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
def methodToJava(meth: MethodSymbol): jMethod = methodCache.toJava(meth) {
val jclazz = classToJava(meth.owner.asClass)
val paramClasses = transformedType(meth).paramTypes map typeToJavaClass
- val jname = nme.dropLocalSuffix(meth.name).toString
+ val jname = meth.name.dropLocal.toString
try jclazz getDeclaredMethod (jname, paramClasses: _*)
catch {
case ex: NoSuchMethodException =>
@@ -1243,11 +1236,11 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
* Pre: Scala type is already transformed to Java level.
*/
def typeToJavaClass(tpe: Type): jClass[_] = tpe match {
- case ExistentialType(_, rtpe) => typeToJavaClass(rtpe)
- case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe))
- case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClass)
+ case ExistentialType(_, rtpe) => typeToJavaClass(rtpe)
+ case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe))
+ case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClass)
case tpe @ TypeRef(_, sym: AliasTypeSymbol, _) => typeToJavaClass(tpe.dealias)
- case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found")
+ case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found")
}
}
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
index a130013398..4d90afcdc3 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
@@ -14,7 +14,7 @@ class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.S
lazy val settings = new Settings
private val isLogging = sys.props contains "scala.debug.reflect"
- def log(msg: => AnyRef): Unit = if (isLogging) Console.err.println("[reflect] " + msg)
+ def log(msg: => AnyRef): Unit = if (isLogging) Console.err.println("[reflect] " + msg)
type TreeCopier = InternalTreeCopierOps
def newStrictTreeCopier: TreeCopier = new StrictTreeCopier
diff --git a/src/reflect/scala/reflect/runtime/SymbolTable.scala b/src/reflect/scala/reflect/runtime/SymbolTable.scala
index 5c08e9a508..ade7a4a21a 100644
--- a/src/reflect/scala/reflect/runtime/SymbolTable.scala
+++ b/src/reflect/scala/reflect/runtime/SymbolTable.scala
@@ -11,10 +11,10 @@ import scala.reflect.internal.Flags._
private[scala] trait SymbolTable extends internal.SymbolTable with JavaMirrors with SymbolLoaders with SynchronizedOps {
def info(msg: => String) =
- if (settings.verbose.value) println("[reflect-compiler] "+msg)
+ if (settings.verbose) println("[reflect-compiler] "+msg)
def debugInfo(msg: => String) =
- if (settings.debug.value) info(msg)
+ if (settings.debug) info(msg)
/** Declares that this is a runtime reflection universe.
*
diff --git a/src/repl/scala/tools/nsc/MainGenericRunner.scala b/src/repl/scala/tools/nsc/MainGenericRunner.scala
index 7195424cf9..9e87b6ba55 100644
--- a/src/repl/scala/tools/nsc/MainGenericRunner.scala
+++ b/src/repl/scala/tools/nsc/MainGenericRunner.scala
@@ -17,7 +17,7 @@ object JarRunner extends CommonRunner {
val jarURLs = ClassPath expandManifestPath jarPath
val urls = if (jarURLs.isEmpty) File(jarPath).toURL +: settings.classpathURLs else jarURLs
- if (settings.Ylogcp.value) {
+ if (settings.Ylogcp) {
Console.err.println("Running jar with these URLs as the classpath:")
urls foreach println
}
@@ -46,7 +46,7 @@ class MainGenericRunner {
def sampleCompiler = new Global(settings) // def so its not created unless needed
if (!command.ok) return errorFn("\n" + command.shortUsageMsg)
- else if (settings.version.value) return errorFn("Scala code runner %s -- %s".format(versionString, copyrightString))
+ else if (settings.version) return errorFn("Scala code runner %s -- %s".format(versionString, copyrightString))
else if (command.shouldStopWithInfo) return errorFn(command getInfoMessage sampleCompiler)
def isE = !settings.execute.isDefault
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 599a061984..df28e428ce 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -628,10 +628,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
* with SimpleReader.
*/
def chooseReader(settings: Settings): InteractiveReader = {
- if (settings.Xnojline.value || Properties.isEmacsShell)
+ if (settings.Xnojline || Properties.isEmacsShell)
SimpleReader()
else try new JLineReader(
- if (settings.noCompletion.value) NoCompletion
+ if (settings.noCompletion) NoCompletion
else new JLineCompletion(intp)
)
catch {
diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index d2b6cdd7f0..4ba81b634a 100644
--- a/src/repl/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -397,7 +397,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
}
private[nsc] def replwarn(msg: => String) {
- if (!settings.nowarnings.value)
+ if (!settings.nowarnings)
printMessage(msg)
}
diff --git a/src/repl/scala/tools/nsc/interpreter/Power.scala b/src/repl/scala/tools/nsc/interpreter/Power.scala
index e517a16b32..da6d271a68 100644
--- a/src/repl/scala/tools/nsc/interpreter/Power.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Power.scala
@@ -70,7 +70,7 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
pass += 1
val (repeats, unseen) = todo partition seen
unseenHistory += unseen.size
- if (settings.verbose.value) {
+ if (settings.verbose) {
println("%3d %s accumulated, %s discarded. This pass: %s unseen, %s repeats".format(
pass, keep.size, discarded, unseen.size, repeats.size))
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala b/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala
index b4d2adaad4..4607684c0d 100644
--- a/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala
@@ -126,7 +126,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
}
private[doc] def docdbg(msg: String) {
- if (settings.Ydocdebug.value)
+ if (settings.Ydocdebug)
println(msg)
}
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala b/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala
index 5ad50445a8..bf6d6ffed7 100644
--- a/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala
@@ -91,7 +91,7 @@ trait ScaladocAnalyzer extends Analyzer {
typedStats(trees, NoSymbol)
useCase.defined = context.scope.toList filterNot (useCase.aliases contains _)
- if (settings.debug.value)
+ if (settings.debug)
useCase.defined foreach (sym => println("defined use cases: %s:%s".format(sym, sym.tpe)))
useCase.defined
diff --git a/src/scaladoc/scala/tools/nsc/doc/Uncompilable.scala b/src/scaladoc/scala/tools/nsc/doc/Uncompilable.scala
index 9447e36610..ea45ca1a56 100644
--- a/src/scaladoc/scala/tools/nsc/doc/Uncompilable.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/Uncompilable.scala
@@ -28,7 +28,7 @@ trait Uncompilable {
lazy val pairs = files flatMap { f =>
val comments = docPairs(f.slurp())
- if (settings.verbose.value)
+ if (settings.verbose)
inform("Found %d doc comments in parse-only file %s: %s".format(comments.size, f, comments.map(_._1).mkString(", ")))
comments
@@ -37,7 +37,7 @@ trait Uncompilable {
def symbols = pairs map (_._1)
def templates = symbols filter (x => x.isClass || x.isTrait || x == AnyRefClass/* which is now a type alias */) toSet
def comments = {
- if (settings.debug.value || settings.verbose.value)
+ if (settings.debug || settings.verbose)
inform("Found %d uncompilable files: %s".format(files.size, files mkString ", "))
if (pairs.isEmpty)
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala b/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
index 2a07547de2..ac5fec80b3 100755
--- a/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
@@ -73,16 +73,20 @@ object EntityLink {
def unapply(el: EntityLink): Option[(Inline, LinkTo)] = Some((el.title, el.link))
}
final case class HtmlTag(data: String) extends Inline {
- def canClose(open: HtmlTag) = {
- open.data.stripPrefix("<") == data.stripPrefix("</")
+ private val Pattern = """(?ms)\A<(/?)(.*?)[\s>].*\z""".r
+ private val (isEnd, tagName) = data match {
+ case Pattern(s1, s2) =>
+ (! s1.isEmpty, Some(s2.toLowerCase))
+ case _ =>
+ (false, None)
}
- def close = {
- if (data.indexOf("</") == -1)
- Some(HtmlTag("</" + data.stripPrefix("<")))
- else
- None
+ def canClose(open: HtmlTag) = {
+ isEnd && tagName == open.tagName
}
+
+ private val TagsNotToClose = Set("br", "img")
+ def close = tagName collect { case name if !TagsNotToClose(name) => HtmlTag(s"</$name>") }
}
/** The summary of a comment, usually its first sentence. There must be exactly one summary per body. */
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala b/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala
index 229e26d699..9edd5afa13 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala
@@ -60,7 +60,7 @@ abstract class HtmlPage extends Page { thisPage =>
w.write(xml.Xhtml.toXhtml(html))
}
- if (site.universe.settings.docRawOutput.value)
+ if (site.universe.settings.docRawOutput)
writeFile(site, ".raw") {
// we're only interested in the body, as this will go into the diff
_.write(body.text)
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala b/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala
index 5781e680dd..348ea97c5b 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala
@@ -6,6 +6,7 @@
package scala.tools.nsc.doc.html
import scala.xml.NodeSeq
+import scala.annotation.tailrec
/** Highlight the syntax of Scala code appearing in a `{{{` wiki block
* (see method `HtmlPage.blockToHtml`).
@@ -209,9 +210,9 @@ private[html] object SyntaxHigh {
out.toString
}
- def parse(pre: String, i: Int): Int = {
+ @tailrec def parse(pre: String, i: Int): Unit = {
out append pre
- if (i == buf.length) return i
+ if (i == buf.length) return
buf(i) match {
case '\n' =>
parse("\n", i+1)
@@ -277,7 +278,6 @@ private[html] object SyntaxHigh {
} else
parse(buf(i).toChar.toString, i+1)
}
- i
}
parse("", 0)
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DiagramStats.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DiagramStats.scala
index ec00cace75..ab8e9e2756 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DiagramStats.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DiagramStats.scala
@@ -42,7 +42,7 @@ object DiagramStats {
private[this] var fixedImages = 0
def printStats(settings: Settings) = {
- if (settings.docDiagramsDebug.value) {
+ if (settings.docDiagramsDebug) {
settings.printMsg("\nDiagram generation running time breakdown:\n")
filterTrack.printStats(settings.printMsg)
modelTrack.printStats(settings.printMsg)
@@ -63,4 +63,4 @@ object DiagramStats {
def addBrokenImage(): Unit = brokenImages += 1
def addFixedImage(): Unit = fixedImages += 1
-} \ No newline at end of file
+}
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
index 837d9e6f21..7d146b4a5f 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
@@ -329,7 +329,7 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
NodeSeq.Empty
} catch {
case exc: Exception =>
- if (settings.docDiagramsDebug.value) {
+ if (settings.docDiagramsDebug) {
settings.printMsg("\n\n**********************************************************************")
settings.printMsg("Encountered an error while generating page for " + template.qualifiedName)
settings.printMsg(dotInput.toString.split("\n").mkString("\nDot input:\n\t","\n\t",""))
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala
index 895cc84f39..cc228082c1 100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -272,7 +272,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
assert(!(docTemplatesCache isDefinedAt sym), sym)
docTemplatesCache += (sym -> this)
- if (settings.verbose.value)
+ if (settings.verbose)
inform("Creating doc template for " + sym)
override def toRoot: List[DocTemplateImpl] = this :: inTpl.toRoot
@@ -350,7 +350,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
// the implicit conversions are generated eagerly, but the members generated by implicit conversions are added
// lazily, on completeModel
val conversions: List[ImplicitConversionImpl] =
- if (settings.docImplicits.value) makeImplicitConversions(sym, this) else Nil
+ if (settings.docImplicits) makeImplicitConversions(sym, this) else Nil
// members as given by the compiler
lazy val memberSyms = sym.info.members.filter(s => membersShouldDocument(s, this)).toList
@@ -924,7 +924,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def ownerTpl(sym: Symbol): Symbol =
if (sym.isClass || sym.isModule || sym == NoSymbol) sym else ownerTpl(sym.owner)
val tpe =
- if (thisFactory.settings.useStupidTypes.value) aType else {
+ if (thisFactory.settings.useStupidTypes) aType else {
def ownerTpl(sym: Symbol): Symbol =
if (sym.isClass || sym.isModule || sym == NoSymbol) sym else ownerTpl(sym.owner)
val fixedSym = if (inTpl.sym.isModule) inTpl.sym.moduleClass else inTpl.sym
@@ -1036,7 +1036,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
// whether or not to create a page for an {abstract,alias} type
def typeShouldDocument(bSym: Symbol, inTpl: DocTemplateImpl) =
- (settings.docExpandAllTypes.value && (bSym.sourceFile != null)) ||
+ (settings.docExpandAllTypes && (bSym.sourceFile != null)) ||
(bSym.isAliasType || bSym.isAbstractType) &&
{ val rawComment = global.expandedDocComment(bSym, inTpl.sym)
rawComment.contains("@template") || rawComment.contains("@documentable") }
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
index 71b0a00e0a..1f87f935f2 100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
@@ -241,7 +241,7 @@ trait ModelFactoryImplicitSupport {
available match {
case Some(true) =>
Nil
- case Some(false) if (!settings.docImplicitsShowAll.value) =>
+ case Some(false) if !settings.docImplicitsShowAll =>
// if -implicits-show-all is not set, we get rid of impossible conversions (such as Numeric[String])
throw new ImplicitNotFound(implType)
case _ =>
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
index 99e9059d79..d5048dcfa3 100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
@@ -140,7 +140,7 @@ trait ModelFactoryTypeSupport {
}
val prefix =
- if (!settings.docNoPrefixes.value && needsPrefix && (bSym != AnyRefClass /* which we normalize */)) {
+ if (!settings.docNoPrefixes && needsPrefix && (bSym != AnyRefClass /* which we normalize */)) {
if (!owner.isRefinementClass) {
val qName = makeQualifiedName(owner, Some(inTpl.sym))
if (qName != "") qName + "." else ""
@@ -308,7 +308,7 @@ trait ModelFactoryTypeSupport {
// SI-4360: Entity caching depends on both the type AND the template it's in, as the prefixes might change for the
// same type based on the template the type is shown in.
- if (settings.docNoPrefixes.value)
+ if (settings.docNoPrefixes)
typeCache.getOrElseUpdate(aType, createTypeEntity)
else createTypeEntity
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala
index 6395446d3b..44d8886e4e 100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala
@@ -248,7 +248,7 @@ trait DiagramDirectiveParser {
hideNodesFilter = hideNodesFilter0,
hideEdgesFilter = hideEdgesFilter0)
- if (settings.docDiagramsDebug.value && result != NoDiagramAtAll && result != FullDiagram)
+ if (settings.docDiagramsDebug && result != NoDiagramAtAll && result != FullDiagram)
settings.printMsg(template.kind + " " + template.qualifiedName + " filter: " + result)
tFilter += System.currentTimeMillis
diff --git a/starr.number b/starr.number
new file mode 100644
index 0000000000..89659fcbf3
--- /dev/null
+++ b/starr.number
@@ -0,0 +1 @@
+starr.version=2.11.0-M2 \ No newline at end of file
diff --git a/test/build-partest.xml b/test/build-partest.xml
new file mode 100755
index 0000000000..44502ffa61
--- /dev/null
+++ b/test/build-partest.xml
@@ -0,0 +1,24 @@
+<project name="partest" basedir=".">
+ <dirname property="partest.basedir" file="${ant.file.partest}"/>
+ <property file="${partest.basedir}/included.properties"/>
+
+ <macrodef name="testSuite">
+ <attribute name="dir" default="${partest.basedir}/test"/>
+ <attribute name="srcdir" default="files"/> <!-- TODO: make targets for `pending` and other subdirs -->
+ <attribute name="colors" default="${partest.colors}"/>
+ <attribute name="scalacOpts" default="${scalac.args.optimise}"/>
+ <attribute name="kinds" default="pos neg run jvm res scalap scalacheck specialized instrumented presentation"/>
+ <sequential>
+ <property name="partest.dir" value="@{dir}" />
+ <partest srcdir="@{srcdir}"
+ kinds="@{kinds}"
+ colors="@{colors}"
+ scalacOpts="@{scalacOpts}"
+ compilationpathref="partest.classpath">
+ <compilationpath>
+ <fileset dir="${partest.dir}/files/lib" includes="*.jar" />
+ </compilationpath>
+ </partest>
+ </sequential>
+ </macrodef>
+</project>
diff --git a/test/files/jvm/t7253.check b/test/files/jvm/t7253.check
new file mode 100644
index 0000000000..43f53aba12
--- /dev/null
+++ b/test/files/jvm/t7253.check
@@ -0,0 +1 @@
+bytecode identical
diff --git a/test/files/jvm/t7253/Base_1.scala b/test/files/jvm/t7253/Base_1.scala
new file mode 100644
index 0000000000..a531ebb69d
--- /dev/null
+++ b/test/files/jvm/t7253/Base_1.scala
@@ -0,0 +1,5 @@
+trait A { def f(): Int }
+trait B1 extends A
+abstract class B2 extends A
+class B3 extends A { def f(): Int = 1 }
+class B4 extends B3
diff --git a/test/files/jvm/t7253/JavaClient_1.java b/test/files/jvm/t7253/JavaClient_1.java
new file mode 100644
index 0000000000..43475de2f5
--- /dev/null
+++ b/test/files/jvm/t7253/JavaClient_1.java
@@ -0,0 +1,9 @@
+public class JavaClient_1 {
+ int foo() {
+ ((A) null).f();
+ ((B1) null).f();
+ ((B2) null).f();
+ ((B3) null).f();
+ return ((B4) null).f();
+ }
+}
diff --git a/test/files/jvm/t7253/ScalaClient_1.scala b/test/files/jvm/t7253/ScalaClient_1.scala
new file mode 100644
index 0000000000..d244b326a8
--- /dev/null
+++ b/test/files/jvm/t7253/ScalaClient_1.scala
@@ -0,0 +1,9 @@
+class ScalaClient_1 {
+ def foo() = {
+ (null: A).f()
+ (null: B1).f()
+ (null: B2).f()
+ (null: B3).f()
+ (null: B4).f()
+ }
+}
diff --git a/test/files/jvm/t7253/test.scala b/test/files/jvm/t7253/test.scala
new file mode 100644
index 0000000000..7fe08e8813
--- /dev/null
+++ b/test/files/jvm/t7253/test.scala
@@ -0,0 +1,28 @@
+import scala.tools.partest.BytecodeTest
+
+import scala.tools.nsc.util.JavaClassPath
+import java.io.InputStream
+import scala.tools.asm
+import asm.ClassReader
+import asm.tree.{ClassNode, InsnList}
+import scala.collection.JavaConverters._
+
+object Test extends BytecodeTest {
+ import instructions._
+
+ def show: Unit = {
+ val instrBaseSeqs = Seq("ScalaClient_1", "JavaClient_1") map (name => instructions.fromMethod(getMethod(loadClassNode(name), "foo")))
+ val instrSeqs = instrBaseSeqs map (_ filter isInvoke)
+ cmpInstructions(instrSeqs(0), instrSeqs(1))
+ }
+
+ def cmpInstructions(isa: List[Instruction], isb: List[Instruction]) = {
+ if (isa == isb) println("bytecode identical")
+ else diffInstructions(isa, isb)
+ }
+
+ def isInvoke(node: Instruction): Boolean = {
+ val opcode = node.opcode
+ (opcode == "INVOKEVIRTUAL") || (opcode == "INVOKEINTERFACE")
+ }
+}
diff --git a/test/files/neg/choices.check b/test/files/neg/choices.check
index 3e63f9999d..b114394e96 100644
--- a/test/files/neg/choices.check
+++ b/test/files/neg/choices.check
@@ -1,2 +1,2 @@
-partest error: bad flags: -Ylinearizer
+error: bad options: -Yresolve-term-conflict
one error found
diff --git a/test/files/neg/choices.flags b/test/files/neg/choices.flags
index 5464a18c5d..9718467d4c 100644
--- a/test/files/neg/choices.flags
+++ b/test/files/neg/choices.flags
@@ -1 +1 @@
--Ylinearizer \ No newline at end of file
+-Yresolve-term-conflict
diff --git a/test/files/neg/javac-error.check b/test/files/neg/javac-error.check
new file mode 100644
index 0000000000..e7d1ccc1a1
--- /dev/null
+++ b/test/files/neg/javac-error.check
@@ -0,0 +1,10 @@
+#partest java6
+javac-error/J.java:2: method does not override or implement a method from a supertype
+ @Override public void foo() { }
+ ^
+1 error
+#partest java7
+javac-error/J.java:2: error: method does not override or implement a method from a supertype
+ @Override public void foo() { }
+ ^
+1 error
diff --git a/test/files/neg/javac-error.flags b/test/files/neg/javac-error.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/files/neg/javac-error.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/neg/javac-error/J.java b/test/files/neg/javac-error/J.java
new file mode 100644
index 0000000000..83f50c9ae2
--- /dev/null
+++ b/test/files/neg/javac-error/J.java
@@ -0,0 +1,5 @@
+public class J {
+ @Override public void foo() { }
+
+ public void bar() { foo(); }
+}
diff --git a/test/files/neg/javac-error/SUT_5.scala b/test/files/neg/javac-error/SUT_5.scala
new file mode 100644
index 0000000000..0a996352c0
--- /dev/null
+++ b/test/files/neg/javac-error/SUT_5.scala
@@ -0,0 +1,5 @@
+
+/** The System Under Test.
+ * We bail on the earlier round that generates the first error.
+ */
+class SUT extends J
diff --git a/test/files/neg/t3631.check b/test/files/neg/t3631.check
deleted file mode 100644
index 6d8feca1ed..0000000000
--- a/test/files/neg/t3631.check
+++ /dev/null
@@ -1,4 +0,0 @@
-t3631.scala:3: error: Implementation restriction: case classes cannot have more than 22 parameters.
-case class X23(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int) { }
- ^
-one error found
diff --git a/test/files/neg/t5580b.check b/test/files/neg/t5580b.check
new file mode 100644
index 0000000000..45fde46ff9
--- /dev/null
+++ b/test/files/neg/t5580b.check
@@ -0,0 +1,6 @@
+t5580b.scala:11: error: polymorphic expression cannot be instantiated to expected type;
+ found : [A]scala.collection.mutable.Set[A]
+ required: scala.collection.mutable.Map[bar,scala.collection.mutable.Set[bar]]
+ if (map.get(tmp).isEmpty) map.put(tmp,collection.mutable.Set())
+ ^
+one error found
diff --git a/test/files/pos/t5580b.scala b/test/files/neg/t5580b.scala
index d5a4a0a2b2..2161da4584 100644
--- a/test/files/pos/t5580b.scala
+++ b/test/files/neg/t5580b.scala
@@ -1,9 +1,3 @@
-/** It's a pos test because it does indeed compile,
- * not so much because I'm glad it does. Testing
- * that error messages created and discarded during
- * implicit search don't blow it up.
- */
-
import scala.collection.mutable.WeakHashMap
import scala.collection.JavaConversions._
diff --git a/test/files/neg/t7110.check b/test/files/neg/t7110.check
new file mode 100644
index 0000000000..e484dc4325
--- /dev/null
+++ b/test/files/neg/t7110.check
@@ -0,0 +1,6 @@
+t7110.scala:2: warning: A try without a catch or finally is equivalent to putting its body in a block; no exceptions are handled.
+ try { ??? } // warn
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+one warning found
+one error found
diff --git a/test/files/neg/t7110.flags b/test/files/neg/t7110.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/t7110.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t7110.scala b/test/files/neg/t7110.scala
new file mode 100644
index 0000000000..79ac325216
--- /dev/null
+++ b/test/files/neg/t7110.scala
@@ -0,0 +1,6 @@
+object Test {
+ try { ??? } // warn
+
+ try { ??? } finally ??? // no warn
+ try { ??? } catch { case _: Throwable => } // no warn
+}
diff --git a/test/files/neg/t7251.check b/test/files/neg/t7251.check
new file mode 100644
index 0000000000..8df8984d63
--- /dev/null
+++ b/test/files/neg/t7251.check
@@ -0,0 +1,4 @@
+B_2.scala:5: error: object s.Outer$Triple$ is not a value
+ println( s.Outer$Triple$ )
+ ^
+one error found
diff --git a/test/files/neg/t7251/A_1.scala b/test/files/neg/t7251/A_1.scala
new file mode 100644
index 0000000000..d05373ed28
--- /dev/null
+++ b/test/files/neg/t7251/A_1.scala
@@ -0,0 +1,10 @@
+package s
+
+object Outer {
+ type Triple[+A, +B, +C] = Tuple3[A, B, C]
+ object Triple {
+ def apply[A, B, C](x: A, y: B, z: C) = Tuple3(x, y, z)
+ def unapply[A, B, C](x: Tuple3[A, B, C]): Option[Tuple3[A, B, C]] = Some(x)
+ }
+}
+
diff --git a/test/files/neg/t7251/B_2.scala b/test/files/neg/t7251/B_2.scala
new file mode 100644
index 0000000000..eb59b30902
--- /dev/null
+++ b/test/files/neg/t7251/B_2.scala
@@ -0,0 +1,7 @@
+package s
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ println( s.Outer$Triple$ )
+ }
+}
diff --git a/test/files/neg/t7259.check b/test/files/neg/t7259.check
new file mode 100644
index 0000000000..0ad627fc3b
--- /dev/null
+++ b/test/files/neg/t7259.check
@@ -0,0 +1,7 @@
+t7259.scala:1: error: not found: type xxxxx
+@xxxxx // error: not found: type xxxx
+ ^
+t7259.scala:8: error: type xxxxx is not a member of package annotation
+@annotation.xxxxx // error: not found: type scala
+ ^
+two errors found
diff --git a/test/files/neg/t7259.scala b/test/files/neg/t7259.scala
new file mode 100644
index 0000000000..0fdfe18822
--- /dev/null
+++ b/test/files/neg/t7259.scala
@@ -0,0 +1,9 @@
+@xxxxx // error: not found: type xxxx
+class Ok
+
+//
+// This had the wrong error message in 2.9 and 2.10.
+//
+
+@annotation.xxxxx // error: not found: type scala
+class WrongErrorMessage
diff --git a/test/files/neg/t7285.check b/test/files/neg/t7285.check
new file mode 100644
index 0000000000..a38772bead
--- /dev/null
+++ b/test/files/neg/t7285.check
@@ -0,0 +1,15 @@
+t7285.scala:15: warning: match may not be exhaustive.
+It would fail on the following input: (Up, Down)
+ (d1, d2) match {
+ ^
+t7285.scala:33: warning: match may not be exhaustive.
+It would fail on the following input: Down
+ (d1) match {
+ ^
+t7285.scala:51: warning: match may not be exhaustive.
+It would fail on the following input: (Up, Down)
+ (d1, d2) match {
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+three warnings found
+one error found
diff --git a/test/files/neg/t7285.flags b/test/files/neg/t7285.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/t7285.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t7285.scala b/test/files/neg/t7285.scala
new file mode 100644
index 0000000000..14121d92b1
--- /dev/null
+++ b/test/files/neg/t7285.scala
@@ -0,0 +1,55 @@
+sealed abstract class Base
+
+
+object Test1 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Up) => true
+ }
+ }
+}
+
+object Test2 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1) match {
+ case Test2.Base.Up => false
+ }
+ }
+}
+
+
+object Test4 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base
+
+ case object Up extends Base
+ }
+
+ import Test4.Base._
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Test4.Base.Up) => true
+ }
+}
diff --git a/test/files/neg/t7290.check b/test/files/neg/t7290.check
new file mode 100644
index 0000000000..ad2d0e25b0
--- /dev/null
+++ b/test/files/neg/t7290.check
@@ -0,0 +1,12 @@
+t7290.scala:4: warning: Pattern contains duplicate alternatives: 0
+ case 0 | 0 => 0
+ ^
+t7290.scala:5: warning: Pattern contains duplicate alternatives: 2, 3
+ case 2 | 2 | 2 | 3 | 2 | 3 => 0
+ ^
+t7290.scala:6: warning: Pattern contains duplicate alternatives: 4
+ case 4 | (_ @ 4) => 0
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+three warnings found
+one error found
diff --git a/test/files/neg/t7290.flags b/test/files/neg/t7290.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/t7290.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t7290.scala b/test/files/neg/t7290.scala
new file mode 100644
index 0000000000..b9db7f7e8a
--- /dev/null
+++ b/test/files/neg/t7290.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+ val y = (0: Int) match {
+ case 1 => 1
+ case 0 | 0 => 0
+ case 2 | 2 | 2 | 3 | 2 | 3 => 0
+ case 4 | (_ @ 4) => 0
+ case _ => -1
+ }
+ assert(y == 0, y)
+}
diff --git a/test/files/neg/t7299.check b/test/files/neg/t7299.check
new file mode 100644
index 0000000000..74340c4841
--- /dev/null
+++ b/test/files/neg/t7299.check
@@ -0,0 +1,7 @@
+t7299.scala:4: error: implementation restricts functions to 22 parameters
+ val eta1 = f _
+ ^
+t7299.scala:5: error: implementation restricts functions to 22 parameters
+ val eta2 = g[Any] _
+ ^
+two errors found
diff --git a/test/files/neg/t7299.scala b/test/files/neg/t7299.scala
new file mode 100644
index 0000000000..f3aae5ce5d
--- /dev/null
+++ b/test/files/neg/t7299.scala
@@ -0,0 +1,6 @@
+object Test {
+ def f(a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int) = 0
+ def g[A](a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int) = 0
+ val eta1 = f _
+ val eta2 = g[Any] _
+}
diff --git a/test/files/pos/t3120/J1.java b/test/files/pos/t3120/J1.java
new file mode 100644
index 0000000000..12b23c1c98
--- /dev/null
+++ b/test/files/pos/t3120/J1.java
@@ -0,0 +1,4 @@
+class J1 {
+ public class Inner1 { }
+ public static class Inner2 { }
+}
diff --git a/test/files/pos/t3120/J2.java b/test/files/pos/t3120/J2.java
new file mode 100644
index 0000000000..db6e859020
--- /dev/null
+++ b/test/files/pos/t3120/J2.java
@@ -0,0 +1,4 @@
+public class J2 {
+ public void f1(J1.Inner1 p) { }
+ public void f2(J1.Inner2 p) { }
+}
diff --git a/test/files/pos/t3120/Q.java b/test/files/pos/t3120/Q.java
new file mode 100644
index 0000000000..fe2269308a
--- /dev/null
+++ b/test/files/pos/t3120/Q.java
@@ -0,0 +1,3 @@
+public class Q {
+ public static void passInner(J1.Inner1 myInner) {}
+}
diff --git a/test/files/pos/t3120/Test.scala b/test/files/pos/t3120/Test.scala
new file mode 100644
index 0000000000..c02146fba1
--- /dev/null
+++ b/test/files/pos/t3120/Test.scala
@@ -0,0 +1,3 @@
+object Test {
+ Q.passInner(null)
+}
diff --git a/test/files/neg/t3631.scala b/test/files/pos/t3631.scala
index bcf91619ee..bcf91619ee 100644
--- a/test/files/neg/t3631.scala
+++ b/test/files/pos/t3631.scala
diff --git a/test/files/pos/t6210.flags b/test/files/pos/t6210.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/t6210.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t6210.scala b/test/files/pos/t6210.scala
new file mode 100644
index 0000000000..1ce8493872
--- /dev/null
+++ b/test/files/pos/t6210.scala
@@ -0,0 +1,21 @@
+abstract sealed trait AST
+abstract sealed trait AExpr extends AST
+case class AAssign(name: String, v: AExpr) extends AExpr
+case class AConstBool(v: Boolean) extends AExpr
+
+trait Ty {}
+case class TInt() extends Ty
+case class TBool() extends Ty
+
+object Foo {
+ def checkExpr(ast: AExpr): Ty = {
+ var astTy:Ty = ast match {
+ case AAssign(nm: String, v:AExpr) => TBool()
+
+ case AConstBool(v: Boolean) => TBool()
+
+ case _ => throw new Exception(s"Unhandled case check(ast: ${ast.getClass})")
+ }
+ astTy
+ }
+}
diff --git a/test/files/pos/t6921.scala b/test/files/pos/t6921.scala
new file mode 100644
index 0000000000..36e70e5d2c
--- /dev/null
+++ b/test/files/pos/t6921.scala
@@ -0,0 +1,11 @@
+class Message(messageType: String, reason: Option[String])
+
+class ReproForSI6921 {
+
+ private[this] var reason = ""
+
+ def decideElection = {
+ val explanation = None
+ new Message("", reason = explanation)
+ }
+}
diff --git a/test/files/pos/t7232.flags b/test/files/pos/t7232.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/t7232.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t7232/Foo.java b/test/files/pos/t7232/Foo.java
new file mode 100644
index 0000000000..3478301b30
--- /dev/null
+++ b/test/files/pos/t7232/Foo.java
@@ -0,0 +1,9 @@
+package pack;
+
+import java.util.List;
+
+public class Foo {
+ public static java.util.List okay() { throw new Error(); }
+
+ public static List wrong() { throw new Error(); }
+}
diff --git a/test/files/pos/t7232/List.java b/test/files/pos/t7232/List.java
new file mode 100644
index 0000000000..e42c63aa67
--- /dev/null
+++ b/test/files/pos/t7232/List.java
@@ -0,0 +1,4 @@
+package pack;
+
+public class List {
+}
diff --git a/test/files/pos/t7232/Test.scala b/test/files/pos/t7232/Test.scala
new file mode 100644
index 0000000000..49c3c12aed
--- /dev/null
+++ b/test/files/pos/t7232/Test.scala
@@ -0,0 +1,5 @@
+object Test {
+ import pack._
+ Foo.okay().size()
+ Foo.wrong().size()
+}
diff --git a/test/files/pos/t7232b.flags b/test/files/pos/t7232b.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/t7232b.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t7232b/Foo.java b/test/files/pos/t7232b/Foo.java
new file mode 100644
index 0000000000..94f08d545e
--- /dev/null
+++ b/test/files/pos/t7232b/Foo.java
@@ -0,0 +1,8 @@
+package pack;
+
+import java.util.*;
+
+public class Foo {
+ // should be pack.List.
+ public static List list() { throw new Error(); }
+}
diff --git a/test/files/pos/t7232b/List.java b/test/files/pos/t7232b/List.java
new file mode 100644
index 0000000000..ce977152b9
--- /dev/null
+++ b/test/files/pos/t7232b/List.java
@@ -0,0 +1,5 @@
+package pack;
+
+public class List {
+ public void packList() {}
+}
diff --git a/test/files/pos/t7232b/Test.scala b/test/files/pos/t7232b/Test.scala
new file mode 100644
index 0000000000..6377e26bec
--- /dev/null
+++ b/test/files/pos/t7232b/Test.scala
@@ -0,0 +1,5 @@
+object Test {
+ import pack._
+
+ Foo.list().packList()
+}
diff --git a/test/files/pos/t7232c.flags b/test/files/pos/t7232c.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/t7232c.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t7232c/Foo.java b/test/files/pos/t7232c/Foo.java
new file mode 100644
index 0000000000..bbda09a2da
--- /dev/null
+++ b/test/files/pos/t7232c/Foo.java
@@ -0,0 +1,10 @@
+package pack;
+
+import java.util.List;
+
+public class Foo {
+ public static class List {
+ public void isInnerList() {}
+ }
+ public static List innerList() { throw new Error(); }
+}
diff --git a/test/files/pos/t7232c/Test.scala b/test/files/pos/t7232c/Test.scala
new file mode 100644
index 0000000000..aa7c710948
--- /dev/null
+++ b/test/files/pos/t7232c/Test.scala
@@ -0,0 +1,4 @@
+object Test {
+ import pack._
+ Foo.innerList().isInnerList()
+}
diff --git a/test/files/pos/t7232d.flags b/test/files/pos/t7232d.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/t7232d.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t7232d/Entry.java b/test/files/pos/t7232d/Entry.java
new file mode 100644
index 0000000000..0cfb6fb25b
--- /dev/null
+++ b/test/files/pos/t7232d/Entry.java
@@ -0,0 +1,4 @@
+package pack;
+
+public class Entry {
+}
diff --git a/test/files/pos/t7232d/Foo.java b/test/files/pos/t7232d/Foo.java
new file mode 100644
index 0000000000..df7114a0f0
--- /dev/null
+++ b/test/files/pos/t7232d/Foo.java
@@ -0,0 +1,8 @@
+package pack;
+
+import java.util.Map.Entry;
+
+public class Foo {
+ public static Entry mapEntry() { throw new Error(); }
+ public static void javaTest() { mapEntry().getKey(); }
+}
diff --git a/test/files/pos/t7232d/Test.scala b/test/files/pos/t7232d/Test.scala
new file mode 100644
index 0000000000..89a8063b3c
--- /dev/null
+++ b/test/files/pos/t7232d/Test.scala
@@ -0,0 +1,4 @@
+object Test {
+ import pack._
+ Foo.mapEntry().getKey()
+}
diff --git a/test/files/pos/t7233.scala b/test/files/pos/t7233.scala
new file mode 100644
index 0000000000..ae15c08c35
--- /dev/null
+++ b/test/files/pos/t7233.scala
@@ -0,0 +1,14 @@
+object Foo {
+ def bar(i: Int) = i
+
+ def ol(i: Int) = i
+ def ol(i: String) = i
+}
+object Test {
+ import Foo.{ bar => quux, toString => bar, ol => olRenamed}
+
+ val f1 = quux _
+ val f1Typed: (Int => Int) = f1
+
+ val f2: String => String = olRenamed _
+}
diff --git a/test/files/pos/t7233b.scala b/test/files/pos/t7233b.scala
new file mode 100644
index 0000000000..927c7fcfd1
--- /dev/null
+++ b/test/files/pos/t7233b.scala
@@ -0,0 +1,8 @@
+object Test {
+ // crash
+ def foo(a: Any) = { import a.{toString => toS}; toS }
+
+ // okay
+ def ok1(a: String) = { import a.{isInstanceOf => iio}; iio[String] }
+ def ok2(a: Int) = { import a.{toInt => ti}; ti }
+}
diff --git a/test/files/pos/t7239.scala b/test/files/pos/t7239.scala
new file mode 100644
index 0000000000..16e9d00f17
--- /dev/null
+++ b/test/files/pos/t7239.scala
@@ -0,0 +1,38 @@
+object Test {
+ def BrokenMethod(): HasFilter[(Int, String)] = ???
+
+ trait HasFilter[B] {
+ def filter(p: B => Boolean) = ???
+ }
+
+ trait HasWithFilter {
+ def withFilter = ???
+ }
+
+ object addWithFilter {
+ trait NoImplicit
+ implicit def enrich(v: Any)
+ (implicit F0: NoImplicit): HasWithFilter = ???
+ }
+
+ BrokenMethod().withFilter(_ => true) // okay
+ BrokenMethod().filter(_ => true) // okay
+
+ locally {
+ import addWithFilter._
+ BrokenMethod().withFilter((_: (Int, String)) => true) // okay
+ }
+
+ locally {
+ import addWithFilter._
+ // adaptToMemberWithArgs sets the type of the tree `x`
+ // to ErrorType (while in silent mode, so the error is not
+ // reported. Later, when the fallback from `withFilter`
+ // to `filter` is attempted, the closure is taken to have
+ // have the type `<error> => Boolean`, which conforms to
+ // `(B => Boolean)`. Only later during pickling does the
+ // defensive check for erroneous types in the tree pick up
+ // the problem.
+ BrokenMethod().withFilter(x => true) // erroneous or inaccessible type.
+ }
+}
diff --git a/test/files/pos/t7285a.flags b/test/files/pos/t7285a.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/t7285a.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t7285a.scala b/test/files/pos/t7285a.scala
new file mode 100644
index 0000000000..34e79c741b
--- /dev/null
+++ b/test/files/pos/t7285a.scala
@@ -0,0 +1,83 @@
+sealed abstract class Base
+
+object Test {
+ case object Up extends Base
+
+ def foo(d1: Base) =
+ d1 match {
+ case Up =>
+ }
+
+ // Sealed subtype: ModuleTypeRef <empty>.this.Test.Up.type
+ // Pattern: UniqueThisType Test.this.type
+}
+
+
+object Test1 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Up) => true
+ case (Up, Down) => false
+ }
+ }
+}
+
+object Test2 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1) match {
+ case Up | Down => false
+ }
+ }
+}
+
+object Test3 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base
+
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Down, Down) => false
+ }
+ }
+}
+
+object Test4 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ }
+ import Test4.Base._
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Test4.Base.Up) => true
+ case (Up, Down) => false
+ }
+}
diff --git a/test/files/pos/t7296.scala b/test/files/pos/t7296.scala
new file mode 100644
index 0000000000..0c078d3657
--- /dev/null
+++ b/test/files/pos/t7296.scala
@@ -0,0 +1,6 @@
+object Test {
+ type A = Int
+ // Emits the implementation restriction but then proceeds to crash
+ // when creating the Foo.unapply.
+ case class Foo(a: A, b: A, c: A, d: A, e: A, f: A, g: A, h: A, i: A, j: A, k: A, l: A, m: A, n: A, o: A, p: A, q: A, r: A, s: A, t: A, u: A, v: A, w: A, x: A, y: A, Z: A)
+}
diff --git a/test/files/presentation/doc/doc.scala b/test/files/presentation/doc/doc.scala
index 7a2eb9a588..916b7832f4 100755
--- a/test/files/presentation/doc/doc.scala
+++ b/test/files/presentation/doc/doc.scala
@@ -127,16 +127,17 @@ object Test extends InteractiveTest {
val baseSource = findSource("Base.scala")
val derivedSource = findSource("Derived.scala")
def existsText(where: Any, text: String): Boolean = where match {
- case `text` => true
+ case s: String => s contains text
case s: Seq[_] => s exists (existsText(_, text))
case p: Product => p.productIterator exists (existsText(_, text))
+ case c: Comment => existsText(c.body, text)
}
val (derived, base) = compiler.ask { () =>
val derived = definitions.RootPackage.info.decl(newTermName("p")).info.decl(newTypeName("Derived"))
(derived, derived.ancestors(0))
}
val cmt1 = getComment(derived, derivedSource, (base, baseSource)::(derived, derivedSource)::Nil)
- if (!existsText(cmt1, "Derived comment."))
+ if (!existsText(cmt1, "This is Derived comment"))
println("Unexpected Derived class comment:"+cmt1)
val (fooDerived, fooBase) = compiler.ask { () =>
@@ -145,7 +146,7 @@ object Test extends InteractiveTest {
}
val cmt2 = getComment(fooDerived, derivedSource, (fooBase, baseSource)::(fooDerived, derivedSource)::Nil)
- if (!existsText(cmt2, "Base method has documentation."))
+ if (!existsText(cmt2, "Base method has documentation"))
println("Unexpected foo method comment:"+cmt2)
}
}
diff --git a/test/files/presentation/doc/src/p/Base.scala b/test/files/presentation/doc/src/p/Base.scala
index 9031de3e3e..d91632b6f6 100755
--- a/test/files/presentation/doc/src/p/Base.scala
+++ b/test/files/presentation/doc/src/p/Base.scala
@@ -1,7 +1,7 @@
package p
/**
- * @define BaseComment $BaseVar comment.
+ * @define BaseComment This is $BaseVar comment.
*/
trait Base {
/**
diff --git a/test/files/run/blame_eye_triple_eee.check b/test/files/run/blame_eye_triple_eee-double.check
index 5e46d91a8f..5e46d91a8f 100644
--- a/test/files/run/blame_eye_triple_eee.check
+++ b/test/files/run/blame_eye_triple_eee-double.check
diff --git a/test/files/run/blame_eye_triple_eee.flags b/test/files/run/blame_eye_triple_eee-double.flags
index c9b68d70dc..c9b68d70dc 100644
--- a/test/files/run/blame_eye_triple_eee.flags
+++ b/test/files/run/blame_eye_triple_eee-double.flags
diff --git a/test/files/run/blame_eye_triple_eee.scala b/test/files/run/blame_eye_triple_eee-double.scala
index 1640aead40..1640aead40 100644
--- a/test/files/run/blame_eye_triple_eee.scala
+++ b/test/files/run/blame_eye_triple_eee-double.scala
diff --git a/test/files/run/blame_eye_triple_eee-float.check b/test/files/run/blame_eye_triple_eee-float.check
new file mode 100644
index 0000000000..5e46d91a8f
--- /dev/null
+++ b/test/files/run/blame_eye_triple_eee-float.check
@@ -0,0 +1,9 @@
+if (NaN == NaN) is good
+if (x == x) is good
+if (x == NaN) is good
+if (NaN != NaN) is good
+if (x != x) is good
+if (NaN != x) is good
+x matching was good
+NaN matching was good
+loop with NaN was goood
diff --git a/test/files/run/blame_eye_triple_eee-float.flags b/test/files/run/blame_eye_triple_eee-float.flags
new file mode 100644
index 0000000000..c9b68d70dc
--- /dev/null
+++ b/test/files/run/blame_eye_triple_eee-float.flags
@@ -0,0 +1 @@
+-optimise
diff --git a/test/files/run/blame_eye_triple_eee-float.scala b/test/files/run/blame_eye_triple_eee-float.scala
new file mode 100644
index 0000000000..4deb9f3d60
--- /dev/null
+++ b/test/files/run/blame_eye_triple_eee-float.scala
@@ -0,0 +1,61 @@
+object Test extends App {
+ import Float.NaN
+
+ // NaN must not equal NaN no matter what optimizations are applied
+ // All the following will seem redundant, but to an optimizer
+ // they can appear different
+
+ val x = NaN
+
+ if (NaN == NaN)
+ println("if (NaN == NaN) is broken")
+ else
+ println("if (NaN == NaN) is good")
+
+ if (x == x)
+ println("if (x == x) is broken")
+ else
+ println("if (x == x) is good")
+
+ if (x == NaN)
+ println("if (x == NaN) is broken")
+ else
+ println("if (x == NaN) is good")
+
+ if (NaN != NaN)
+ println("if (NaN != NaN) is good")
+ else
+ println("if (NaN != NaN) broken")
+
+ if (x != x)
+ println("if (x != x) is good")
+ else
+ println("if (x != x) broken")
+
+ if (NaN != x)
+ println("if (NaN != x) is good")
+ else
+ println("if (NaN != x) is broken")
+
+ x match {
+ case 0.0f => println("x matched 0!")
+ case NaN => println("x matched NaN!")
+ case _ => println("x matching was good")
+ }
+
+ NaN match {
+ case 0.0f => println("NaN matched 0!")
+ case NaN => println("NaN matched NaN!")
+ case _ => println("NaN matching was good")
+ }
+
+ var z = 0.0f
+ var i = 0
+ while (i < 10) {
+ if (i % 2 == 0) z = NaN
+ else z = NaN
+ i += 1
+ }
+ if (z.isNaN && i == 10) println("loop with NaN was goood")
+ else println("loop with NaN was broken")
+}
diff --git a/test/files/run/case-class-23.check b/test/files/run/case-class-23.check
new file mode 100644
index 0000000000..888ed2c9eb
--- /dev/null
+++ b/test/files/run/case-class-23.check
@@ -0,0 +1,2 @@
+23
+(1,23)
diff --git a/test/files/run/case-class-23.scala b/test/files/run/case-class-23.scala
new file mode 100644
index 0000000000..92b719574a
--- /dev/null
+++ b/test/files/run/case-class-23.scala
@@ -0,0 +1,33 @@
+case class TwentyThree(
+ _1: Int,
+ _2: Int,
+ _3: Int,
+ _4: Int,
+ _5: Int,
+ _6: Int,
+ _7: Int,
+ _8: Int,
+ _9: Int,
+ _10: Int,
+ _11: Int,
+ _12: Int,
+ _13: Int,
+ _14: Int,
+ _15: Int,
+ _16: Int,
+ _17: Int,
+ _18: Int,
+ _19: Int,
+ _20: Int,
+ _21: Int,
+ _22: Int,
+ _23: Int
+)
+
+object Test extends App {
+ val x = new TwentyThree(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23)
+ println(x._23)
+ assert(x.copy(_1 = 1) == x)
+ val TwentyThree(a, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, b) = x
+ println((a, b))
+}
diff --git a/test/files/run/classfile-format-51.scala b/test/files/run/classfile-format-51.scala
new file mode 100644
index 0000000000..9b1e612f4f
--- /dev/null
+++ b/test/files/run/classfile-format-51.scala
@@ -0,0 +1,126 @@
+import java.io.{File, FileOutputStream}
+
+import scala.tools.nsc.settings.ScalaVersion
+import scala.tools.partest._
+import scala.tools.asm
+import asm.{AnnotationVisitor, ClassWriter, FieldVisitor, Handle, MethodVisitor, Opcodes}
+import Opcodes._
+
+// This test ensures that we can read JDK 7 (classfile format 51) files, including those
+// with invokeDynamic instructions and associated constant pool entries
+// to do that it first uses ASM to generate a class called DynamicInvoker. Then
+// it runs a normal compile on the source in the 'code' field that refers to
+// DynamicInvoker. Any failure will be dumped to std out.
+//
+// By it's nature the test can only work on JDK 7+ because under JDK 6 some of the
+// classes referred to by DynamicInvoker won't be available and DynamicInvoker won't
+// verify. So the test includes a version check that short-circuites the whole test
+// on JDK 6
+object Test extends DirectTest {
+ override def extraSettings: String = "-optimise -usejavacp -d " + testOutput.path + " -cp " + testOutput.path
+
+ def generateClass() {
+ val invokerClassName = "DynamicInvoker"
+ val bootstrapMethodName = "bootstrap"
+ val bootStrapMethodType = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
+ val targetMethodName = "target"
+ val targetMethodType = "()Ljava/lang/String;"
+
+ val cw = new ClassWriter(0)
+ cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, invokerClassName, null, "java/lang/Object", null)
+
+ val constructor = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null)
+ constructor.visitCode()
+ constructor.visitVarInsn(ALOAD, 0)
+ constructor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V")
+ constructor.visitInsn(RETURN)
+ constructor.visitMaxs(1, 1)
+ constructor.visitEnd()
+
+ val target = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, targetMethodName, targetMethodType, null, null)
+ target.visitCode()
+ target.visitLdcInsn("hello")
+ target.visitInsn(ARETURN)
+ target.visitMaxs(1, 1)
+ target.visitEnd()
+
+ val bootstrap = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, bootstrapMethodName, bootStrapMethodType, null, null)
+ bootstrap.visitCode()
+// val lookup = MethodHandles.lookup();
+ bootstrap.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;")
+ bootstrap.visitVarInsn(ASTORE, 3) // lookup
+
+// val clazz = lookup.lookupClass();
+ bootstrap.visitVarInsn(ALOAD, 3) // lookup
+ bootstrap.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "lookupClass", "()Ljava/lang/Class;")
+ bootstrap.visitVarInsn(ASTORE, 4) // clazz
+
+// val methodType = MethodType.fromMethodDescriptorString("()Ljava/lang/String, clazz.getClassLoader()")
+ bootstrap.visitLdcInsn("()Ljava/lang/String;")
+ bootstrap.visitVarInsn(ALOAD, 4) // CLAZZ
+ bootstrap.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getClassLoader", "()Ljava/lang/ClassLoader;")
+ bootstrap.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodType", "fromMethodDescriptorString", "(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/invoke/MethodType;")
+ bootstrap.visitVarInsn(ASTORE, 5) // methodType
+
+// val methodHandle = lookup.findStatic(thisClass, "target", methodType)
+ bootstrap.visitVarInsn(ALOAD, 3) // lookup
+ bootstrap.visitVarInsn(ALOAD, 4) // clazz
+ bootstrap.visitLdcInsn("target")
+ bootstrap.visitVarInsn(ALOAD, 5) // methodType
+ bootstrap.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "findStatic", "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;")
+ bootstrap.visitVarInsn(ASTORE, 6) // methodHandle
+
+// new ConstantCallSite(methodHandle)
+ bootstrap.visitTypeInsn(NEW, "java/lang/invoke/ConstantCallSite")
+ bootstrap.visitInsn(DUP)
+ bootstrap.visitVarInsn(ALOAD, 6) // methodHandle
+ bootstrap.visitMethodInsn(INVOKESPECIAL, "java/lang/invoke/ConstantCallSite", "<init>", "(Ljava/lang/invoke/MethodHandle;)V")
+ bootstrap.visitInsn(ARETURN)
+ bootstrap.visitMaxs(4,7)
+ bootstrap.visitEnd()
+
+ val test = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "test", s"()Ljava/lang/String;", null, null)
+ test.visitCode()
+ val bootstrapHandle = new Handle(H_INVOKESTATIC, invokerClassName, bootstrapMethodName, bootStrapMethodType)
+ test.visitInvokeDynamicInsn("invoke", targetMethodType, bootstrapHandle)
+ test.visitInsn(ARETURN)
+ test.visitMaxs(1, 1)
+ test.visitEnd()
+
+ cw.visitEnd()
+ val bytes = cw.toByteArray()
+
+ val fos = new FileOutputStream(new File(s"${testOutput.path}/$invokerClassName.class"))
+ try
+ fos write bytes
+ finally
+ fos.close()
+
+ }
+
+ def code =
+"""
+object Driver {
+ val invoker = new DynamicInvoker()
+ println(invoker.test())
+}
+"""
+
+ override def show(): Unit = {
+ // redirect err to out, for logging
+ val prevErr = System.err
+ System.setErr(System.out)
+ try {
+ // this test is only valid under JDK 1.7+
+ // cheat a little by using 'ScalaVersion' because it can parse java versions just as well
+ val requiredJavaVersion = ScalaVersion("1.7")
+ val executingJavaVersion = ScalaVersion(System.getProperty("java.specification.version"))
+ if (executingJavaVersion >= requiredJavaVersion) {
+ generateClass()
+ compile()
+ }
+ }
+ finally
+ System.setErr(prevErr)
+ }
+}
diff --git a/test/files/run/existentials3-new.check b/test/files/run/existentials3-new.check
index 8f7dd701ac..c0233d2267 100644
--- a/test/files/run/existentials3-new.check
+++ b/test/files/run/existentials3-new.check
@@ -12,9 +12,9 @@ List[Seq[Int]], t=TypeRef, s=class List
List[Seq[U forSome { type U <: Int }]], t=TypeRef, s=class List
Bar.type, t=TypeRef, s=type Bar.type
Bar, t=TypeRef, s=type Bar
-Test.ToS, t=RefinedType, s=g3
-Test.ToS, t=RefinedType, s=g4
-Test.ToS, t=RefinedType, s=g5
+Test.ToS, t=RefinedType, s=g3
+Test.ToS, t=RefinedType, s=g4
+Test.ToS, t=RefinedType, s=g5
() => Test.ToS, t=TypeRef, s=trait Function0
() => Test.ToS, t=TypeRef, s=trait Function0
$anon, t=TypeRef, s=type $anon
diff --git a/test/files/run/inline-ex-handlers.check b/test/files/run/inline-ex-handlers.check
index abcc8bf42d..7c885d2cc9 100644
--- a/test/files/run/inline-ex-handlers.check
+++ b/test/files/run/inline-ex-handlers.check
@@ -1,427 +1,492 @@
-172c172
-< locals: value x$1, value x1
----
-> locals: value x$1, value x1, variable boxed1
-174c174
-< blocks: [1,2,3,4]
----
-> blocks: [1,3,4]
-186a187,188
-> 92 STORE_LOCAL(variable boxed1)
-> 92 LOAD_LOCAL(variable boxed1)
-195,197d196
-< 92 JUMP 2
-<
-< 2:
-247c246
-< blocks: [1,2,3,4,5,6,7,8,11,12,13,14,15,16,17,18]
----
-> blocks: [1,2,3,4,5,6,8,11,12,13,14,15,16,17,18]
-258,260d256
-< 92 JUMP 7
-<
-< 7:
-391c387
-< locals: value args, variable result, value ex6, value x4, value x5, value message, value x
----
-> locals: value args, variable result, value ex6, value x4, value x5, value x
-393c389
-< blocks: [1,2,3,4,5,8,10,11,13]
----
-> blocks: [1,2,3,5,8,10,11,13,14]
-417c413,422
-< 103 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 14
->
-> 14:
-> 101 LOAD_LOCAL(value ex6)
-> 101 STORE_LOCAL(value x4)
-> 101 SCOPE_ENTER value x4
-> 106 LOAD_LOCAL(value x4)
-> 106 IS_INSTANCE REF(class MyException)
-> 106 CZJUMP (BOOL)NE ? 5 : 8
-430,432d434
-< 101 JUMP 4
-<
-< 4:
-442,445d443
-< 106 LOAD_LOCAL(value x5)
-< 106 CALL_METHOD MyException.message (dynamic)
-< 106 STORE_LOCAL(value message)
-< 106 SCOPE_ENTER value message
-447c445,446
-< 106 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 106 CALL_METHOD MyException.message (dynamic)
-519c518
-< blocks: [1,2,3,4,6,7,9,10]
----
-> blocks: [1,3,4,6,7,9,10,11,12,13]
-548c547,552
-< 306 THROW(MyException)
----
-> ? JUMP 11
->
-> 11:
-> ? LOAD_LOCAL(variable monitor4)
-> 305 MONITOR_EXIT
-> ? JUMP 12
-554c558
-< ? THROW(Throwable)
----
-> ? JUMP 12
-560c564,571
-< ? THROW(Throwable)
----
-> ? STORE_LOCAL(value t)
-> ? JUMP 13
->
-> 12:
-> ? LOAD_LOCAL(variable monitor3)
-> 304 MONITOR_EXIT
-> ? STORE_LOCAL(value t)
-> ? JUMP 13
-574c585
-< 310 JUMP 2
----
-> 300 RETURN(UNIT)
-576c587,596
-< 2:
----
-> 13:
-> 310 LOAD_MODULE object Predef
-> 310 CALL_PRIMITIVE(StartConcat)
-> 310 CONSTANT("Caught crash: ")
-> 310 CALL_PRIMITIVE(StringConcat(REF(class String)))
-> 310 LOAD_LOCAL(value t)
-> 310 CALL_METHOD java.lang.Throwable.toString (dynamic)
-> 310 CALL_PRIMITIVE(StringConcat(REF(class String)))
-> 310 CALL_PRIMITIVE(EndConcat)
-> 310 CALL_METHOD scala.Predef.println (dynamic)
-584c604
-< catch (Throwable) in ArrayBuffer(7, 9, 10) starting at: 6
----
-> catch (Throwable) in ArrayBuffer(7, 9, 10, 11) starting at: 6
-587c607
-< catch (Throwable) in ArrayBuffer(4, 6, 7, 9, 10) starting at: 3
----
-> catch (Throwable) in ArrayBuffer(4, 6, 7, 9, 10, 11, 12) starting at: 3
-619c639
-< blocks: [1,3,4,5,6,8,9]
----
-> blocks: [1,3,4,5,6,8,9,10,11]
-643c663,669
-< 78 THROW(IllegalArgumentException)
----
-> ? STORE_LOCAL(value e)
-> ? JUMP 10
->
-> 10:
-> 81 LOAD_LOCAL(value e)
-> ? STORE_LOCAL(variable exc1)
-> ? JUMP 11
-669c695,696
-< 81 THROW(Exception)
----
-> ? STORE_LOCAL(variable exc1)
-> ? JUMP 11
-685a713,725
-> 11:
-> 83 LOAD_MODULE object Predef
-> 83 CONSTANT("finally")
-> 83 CALL_METHOD scala.Predef.println (dynamic)
-> 84 LOAD_LOCAL(variable result)
-> 84 CONSTANT(1)
-> 84 CALL_PRIMITIVE(Arithmetic(SUB,INT))
-> 84 CONSTANT(2)
-> 84 CALL_PRIMITIVE(Arithmetic(DIV,INT))
-> 84 STORE_LOCAL(variable result)
-> 84 LOAD_LOCAL(variable exc1)
-> 84 THROW(Throwable)
->
-691c731
-< catch (<none>) in ArrayBuffer(4, 5, 6, 8) starting at: 3
----
-> catch (<none>) in ArrayBuffer(4, 5, 6, 8, 10) starting at: 3
-715c755
-< locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value message, value x, value ex6, value x4, value x5, value message, value x
----
-> locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value x, value ex6, value x4, value x5, value x
-717c757
-< blocks: [1,3,4,5,6,9,13,14,15,18,20,21,23,24]
----
-> blocks: [1,3,4,5,6,9,13,14,15,18,20,21,23,24,25,26,27]
-741c781,788
-< 172 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 25
->
-> 25:
-> 170 LOAD_LOCAL(value ex6)
-> 170 STORE_LOCAL(value x4)
-> 170 SCOPE_ENTER value x4
-> 170 JUMP 14
-781,784d827
-< 175 LOAD_LOCAL(value x5)
-< 175 CALL_METHOD MyException.message (dynamic)
-< 175 STORE_LOCAL(value message)
-< 175 SCOPE_ENTER value message
-786c829,830
-< 176 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 176 CALL_METHOD MyException.message (dynamic)
-790c834,835
-< 177 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 177 CALL_METHOD MyException.message (dynamic)
-792c837,838
-< 177 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 26
-796c842,843
-< 170 THROW(Throwable)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 26
-805a853,858
-> 26:
-> 169 LOAD_LOCAL(value ex6)
-> 169 STORE_LOCAL(value x4)
-> 169 SCOPE_ENTER value x4
-> 169 JUMP 5
->
-816,819d868
-< 180 LOAD_LOCAL(value x5)
-< 180 CALL_METHOD MyException.message (dynamic)
-< 180 STORE_LOCAL(value message)
-< 180 SCOPE_ENTER value message
-821c870,871
-< 181 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 181 CALL_METHOD MyException.message (dynamic)
-825c875,876
-< 182 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 182 CALL_METHOD MyException.message (dynamic)
-827c878,879
-< 182 THROW(MyException)
----
-> ? STORE_LOCAL(variable exc2)
-> ? JUMP 27
-831c883,884
-< 169 THROW(Throwable)
----
-> ? STORE_LOCAL(variable exc2)
-> ? JUMP 27
-847a901,913
-> 27:
-> 184 LOAD_MODULE object Predef
-> 184 CONSTANT("finally")
-> 184 CALL_METHOD scala.Predef.println (dynamic)
-> 185 LOAD_LOCAL(variable result)
-> 185 CONSTANT(1)
-> 185 CALL_PRIMITIVE(Arithmetic(SUB,INT))
-> 185 CONSTANT(2)
-> 185 CALL_PRIMITIVE(Arithmetic(DIV,INT))
-> 185 STORE_LOCAL(variable result)
-> 185 LOAD_LOCAL(variable exc2)
-> 185 THROW(Throwable)
->
-853c919
-< catch (Throwable) in ArrayBuffer(13, 14, 15, 18, 20, 21, 23) starting at: 4
----
-> catch (Throwable) in ArrayBuffer(13, 14, 15, 18, 20, 21, 23, 25) starting at: 4
-856c922
-< catch (<none>) in ArrayBuffer(4, 5, 6, 9, 13, 14, 15, 18, 20, 21, 23) starting at: 3
----
-> catch (<none>) in ArrayBuffer(4, 5, 6, 9, 13, 14, 15, 18, 20, 21, 23, 25, 26) starting at: 3
-880c946
-< locals: value args, variable result, value e, value ex6, value x4, value x5, value message, value x
----
-> locals: value args, variable result, value e, value ex6, value x4, value x5, value x
-882c948
-< blocks: [1,2,3,6,7,8,11,13,14,16]
----
-> blocks: [1,2,3,6,7,8,11,13,14,16,17]
-906c972,979
-< 124 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 17
->
-> 17:
-> 122 LOAD_LOCAL(value ex6)
-> 122 STORE_LOCAL(value x4)
-> 122 SCOPE_ENTER value x4
-> 122 JUMP 7
-931,934d1003
-< 127 LOAD_LOCAL(value x5)
-< 127 CALL_METHOD MyException.message (dynamic)
-< 127 STORE_LOCAL(value message)
-< 127 SCOPE_ENTER value message
-936c1005,1006
-< 127 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 127 CALL_METHOD MyException.message (dynamic)
-965c1035
-< catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16) starting at: 3
----
-> catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16, 17) starting at: 3
-989c1059
-< locals: value args, variable result, value ex6, value x4, value x5, value message, value x, value e
----
-> locals: value args, variable result, value ex6, value x4, value x5, value x, value e
-991c1061
-< blocks: [1,2,3,4,5,8,12,13,14,16]
----
-> blocks: [1,2,3,5,8,12,13,14,16,17]
-1015c1085,1094
-< 148 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 17
->
-> 17:
-> 145 LOAD_LOCAL(value ex6)
-> 145 STORE_LOCAL(value x4)
-> 145 SCOPE_ENTER value x4
-> 154 LOAD_LOCAL(value x4)
-> 154 IS_INSTANCE REF(class MyException)
-> 154 CZJUMP (BOOL)NE ? 5 : 8
-1036,1038d1114
-< 145 JUMP 4
-<
-< 4:
-1048,1051d1123
-< 154 LOAD_LOCAL(value x5)
-< 154 CALL_METHOD MyException.message (dynamic)
-< 154 STORE_LOCAL(value message)
-< 154 SCOPE_ENTER value message
-1053c1125,1126
-< 154 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 154 CALL_METHOD MyException.message (dynamic)
-1270c1343
-< blocks: [1,2,3,4,5,7]
----
-> blocks: [1,2,3,4,5,7,8]
-1294c1367,1374
-< 38 THROW(IllegalArgumentException)
----
-> ? STORE_LOCAL(value e)
-> ? JUMP 8
->
-> 8:
-> 42 LOAD_MODULE object Predef
-> 42 CONSTANT("IllegalArgumentException")
-> 42 CALL_METHOD scala.Predef.println (dynamic)
-> 42 JUMP 2
-1341c1421
-< locals: value args, variable result, value ex6, value x4, value x5, value message, value x
----
-> locals: value args, variable result, value ex6, value x4, value x5, value x
-1343c1423
-< blocks: [1,2,3,4,5,8,10,11,13,14,16]
----
-> blocks: [1,2,3,5,8,10,11,13,14,16,17]
-1367c1447,1448
-< 203 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 17
-1387c1468,1477
-< 209 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 17
->
-> 17:
-> 200 LOAD_LOCAL(value ex6)
-> 200 STORE_LOCAL(value x4)
-> 200 SCOPE_ENTER value x4
-> 212 LOAD_LOCAL(value x4)
-> 212 IS_INSTANCE REF(class MyException)
-> 212 CZJUMP (BOOL)NE ? 5 : 8
-1400,1402d1489
-< 200 JUMP 4
-<
-< 4:
-1412,1415d1498
-< 212 LOAD_LOCAL(value x5)
-< 212 CALL_METHOD MyException.message (dynamic)
-< 212 STORE_LOCAL(value message)
-< 212 SCOPE_ENTER value message
-1417c1500,1501
-< 213 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 213 CALL_METHOD MyException.message (dynamic)
-1461c1545
-< blocks: [1,2,3,4,5,7]
----
-> blocks: [1,2,3,4,5,7,8]
-1485c1569,1570
-< 58 THROW(IllegalArgumentException)
----
-> ? STORE_LOCAL(value e)
-> ? JUMP 8
-1486a1572,1577
-> 8:
-> 62 LOAD_MODULE object Predef
-> 62 CONSTANT("RuntimeException")
-> 62 CALL_METHOD scala.Predef.println (dynamic)
-> 62 JUMP 2
->
-1534c1625
-< blocks: [1,3,4]
----
-> blocks: [1,3,4,5]
-1554c1645,1650
-< 229 THROW(MyException)
----
-> ? JUMP 5
->
-> 5:
-> ? LOAD_LOCAL(variable monitor1)
-> 228 MONITOR_EXIT
-> 228 THROW(Throwable)
-1560c1656
-< ? THROW(Throwable)
----
-> 228 THROW(Throwable)
-1588c1684
-< locals: value args, variable result, variable monitor2, variable monitorResult1
----
-> locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1
-1590c1686
-< blocks: [1,3,4]
----
-> blocks: [1,3,4,5]
-1613c1709,1717
-< 245 THROW(MyException)
----
-> ? STORE_LOCAL(value exception$1)
-> ? DROP ConcatClass
-> ? LOAD_LOCAL(value exception$1)
-> ? JUMP 5
->
-> 5:
-> ? LOAD_LOCAL(variable monitor2)
-> 244 MONITOR_EXIT
-> 244 THROW(Throwable)
-1619c1723
-< ? THROW(Throwable)
----
-> 244 THROW(Throwable)
-
+--- a
++++ b
+@@ -171,5 +171,5 @@
+ def productElement(x$1: Int (INT)): Object {
+- locals: value x$1, value x1
++ locals: value x$1, value x1, variable boxed1
+ startBlock: 1
+- blocks: [1,2,3,4]
++ blocks: [1,3,4]
+
+@@ -186,2 +186,4 @@
+ 92 LOAD_LOCAL(value x$1)
++ 92 STORE_LOCAL(variable boxed1)
++ 92 LOAD_LOCAL(variable boxed1)
+ 92 BOX INT
+@@ -194,5 +196,2 @@
+ 92 CALL_METHOD MyException.message (dynamic)
+- 92 JUMP 2
+-
+- 2:
+ 92 RETURN(REF(class Object))
+@@ -246,3 +245,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,5,6,7,8,11,12,13,14,15,16,17,18]
++ blocks: [1,2,3,4,5,6,8,11,12,13,14,15,16,17,18]
+
+@@ -257,5 +256,2 @@
+ 92 SCOPE_ENTER value x1
+- 92 JUMP 7
+-
+- 7:
+ 92 LOAD_LOCAL(value x1)
+@@ -390,5 +386,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,2,3,4,5,8,10,11,13]
++ blocks: [1,2,3,5,8,10,11,13,14]
+
+@@ -416,4 +412,13 @@
+ 103 CALL_METHOD MyException.<init> (static-instance)
+- 103 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 14
+
++ 14:
++ 101 LOAD_LOCAL(value ex6)
++ 101 STORE_LOCAL(value x4)
++ 101 SCOPE_ENTER value x4
++ 106 LOAD_LOCAL(value x4)
++ 106 IS_INSTANCE REF(class MyException)
++ 106 CZJUMP (BOOL)NE ? 5 : 8
++
+ 13:
+@@ -429,5 +434,2 @@
+ 101 SCOPE_ENTER value x4
+- 101 JUMP 4
+-
+- 4:
+ 106 LOAD_LOCAL(value x4)
+@@ -441,8 +443,5 @@
+ 106 SCOPE_ENTER value x5
+- 106 LOAD_LOCAL(value x5)
+- 106 CALL_METHOD MyException.message (dynamic)
+- 106 STORE_LOCAL(value message)
+- 106 SCOPE_ENTER value message
+ 106 LOAD_MODULE object Predef
+- 106 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 106 CALL_METHOD MyException.message (dynamic)
+ 106 CALL_METHOD scala.Predef.println (dynamic)
+@@ -518,3 +517,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,6,7,9,10]
++ blocks: [1,3,4,6,7,9,10,11,12,13]
+
+@@ -547,4 +546,9 @@
+ 306 CALL_METHOD MyException.<init> (static-instance)
+- 306 THROW(MyException)
++ ? JUMP 11
+
++ 11:
++ ? LOAD_LOCAL(variable monitor4)
++ 305 MONITOR_EXIT
++ ? JUMP 12
++
+ 9:
+@@ -553,3 +557,3 @@
+ 305 MONITOR_EXIT
+- ? THROW(Throwable)
++ ? JUMP 12
+
+@@ -559,4 +563,11 @@
+ 304 MONITOR_EXIT
+- ? THROW(Throwable)
++ ? STORE_LOCAL(value t)
++ ? JUMP 13
+
++ 12:
++ ? LOAD_LOCAL(variable monitor3)
++ 304 MONITOR_EXIT
++ ? STORE_LOCAL(value t)
++ ? JUMP 13
++
+ 3:
+@@ -573,5 +584,14 @@
+ 310 CALL_METHOD scala.Predef.println (dynamic)
+- 310 JUMP 2
++ 300 RETURN(UNIT)
+
+- 2:
++ 13:
++ 310 LOAD_MODULE object Predef
++ 310 CALL_PRIMITIVE(StartConcat)
++ 310 CONSTANT("Caught crash: ")
++ 310 CALL_PRIMITIVE(StringConcat(REF(class String)))
++ 310 LOAD_LOCAL(value t)
++ 310 CALL_METHOD java.lang.Throwable.toString (dynamic)
++ 310 CALL_PRIMITIVE(StringConcat(REF(class String)))
++ 310 CALL_PRIMITIVE(EndConcat)
++ 310 CALL_METHOD scala.Predef.println (dynamic)
+ 300 RETURN(UNIT)
+@@ -583,6 +603,6 @@
+ with finalizer: null
+- catch (Throwable) in ArrayBuffer(7, 9, 10) starting at: 6
++ catch (Throwable) in ArrayBuffer(7, 9, 10, 11) starting at: 6
+ consisting of blocks: List(6)
+ with finalizer: null
+- catch (Throwable) in ArrayBuffer(4, 6, 7, 9, 10) starting at: 3
++ catch (Throwable) in ArrayBuffer(4, 6, 7, 9, 10, 11, 12) starting at: 3
+ consisting of blocks: List(3)
+@@ -618,3 +638,3 @@
+ startBlock: 1
+- blocks: [1,3,4,5,6,8,9]
++ blocks: [1,3,4,5,6,8,9,10,11]
+
+@@ -642,4 +662,10 @@
+ 78 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance)
+- 78 THROW(IllegalArgumentException)
++ ? STORE_LOCAL(value e)
++ ? JUMP 10
+
++ 10:
++ 81 LOAD_LOCAL(value e)
++ ? STORE_LOCAL(variable exc1)
++ ? JUMP 11
++
+ 8:
+@@ -668,3 +694,4 @@
+ 81 LOAD_LOCAL(value e)
+- 81 THROW(Exception)
++ ? STORE_LOCAL(variable exc1)
++ ? JUMP 11
+
+@@ -685,2 +712,15 @@
+
++ 11:
++ 83 LOAD_MODULE object Predef
++ 83 CONSTANT("finally")
++ 83 CALL_METHOD scala.Predef.println (dynamic)
++ 84 LOAD_LOCAL(variable result)
++ 84 CONSTANT(1)
++ 84 CALL_PRIMITIVE(Arithmetic(SUB,INT))
++ 84 CONSTANT(2)
++ 84 CALL_PRIMITIVE(Arithmetic(DIV,INT))
++ 84 STORE_LOCAL(variable result)
++ 84 LOAD_LOCAL(variable exc1)
++ 84 THROW(Throwable)
++
+ }
+@@ -690,3 +730,3 @@
+ with finalizer: null
+- catch (<none>) in ArrayBuffer(4, 5, 6, 8) starting at: 3
++ catch (<none>) in ArrayBuffer(4, 5, 6, 8, 10) starting at: 3
+ consisting of blocks: List(3)
+@@ -714,5 +754,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value message, value x, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value x, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,3,4,5,6,9,13,14,15,18,20,21,23,24]
++ blocks: [1,3,4,5,6,9,13,14,15,18,20,21,23,24,25,26,27]
+
+@@ -740,4 +780,11 @@
+ 172 CALL_METHOD MyException.<init> (static-instance)
+- 172 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 25
+
++ 25:
++ 170 LOAD_LOCAL(value ex6)
++ 170 STORE_LOCAL(value x4)
++ 170 SCOPE_ENTER value x4
++ 170 JUMP 14
++
+ 23:
+@@ -780,8 +827,5 @@
+ 175 SCOPE_ENTER value x5
+- 175 LOAD_LOCAL(value x5)
+- 175 CALL_METHOD MyException.message (dynamic)
+- 175 STORE_LOCAL(value message)
+- 175 SCOPE_ENTER value message
+ 176 LOAD_MODULE object Predef
+- 176 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 176 CALL_METHOD MyException.message (dynamic)
+ 176 CALL_METHOD scala.Predef.println (dynamic)
+@@ -789,5 +833,7 @@
+ 177 DUP(REF(class MyException))
+- 177 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 177 CALL_METHOD MyException.message (dynamic)
+ 177 CALL_METHOD MyException.<init> (static-instance)
+- 177 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 26
+
+@@ -795,3 +841,4 @@
+ 170 LOAD_LOCAL(value ex6)
+- 170 THROW(Throwable)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 26
+
+@@ -805,2 +852,8 @@
+
++ 26:
++ 169 LOAD_LOCAL(value ex6)
++ 169 STORE_LOCAL(value x4)
++ 169 SCOPE_ENTER value x4
++ 169 JUMP 5
++
+ 5:
+@@ -815,8 +868,5 @@
+ 180 SCOPE_ENTER value x5
+- 180 LOAD_LOCAL(value x5)
+- 180 CALL_METHOD MyException.message (dynamic)
+- 180 STORE_LOCAL(value message)
+- 180 SCOPE_ENTER value message
+ 181 LOAD_MODULE object Predef
+- 181 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 181 CALL_METHOD MyException.message (dynamic)
+ 181 CALL_METHOD scala.Predef.println (dynamic)
+@@ -824,5 +874,7 @@
+ 182 DUP(REF(class MyException))
+- 182 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 182 CALL_METHOD MyException.message (dynamic)
+ 182 CALL_METHOD MyException.<init> (static-instance)
+- 182 THROW(MyException)
++ ? STORE_LOCAL(variable exc2)
++ ? JUMP 27
+
+@@ -830,3 +882,4 @@
+ 169 LOAD_LOCAL(value ex6)
+- 169 THROW(Throwable)
++ ? STORE_LOCAL(variable exc2)
++ ? JUMP 27
+
+@@ -847,2 +900,15 @@
+
++ 27:
++ 184 LOAD_MODULE object Predef
++ 184 CONSTANT("finally")
++ 184 CALL_METHOD scala.Predef.println (dynamic)
++ 185 LOAD_LOCAL(variable result)
++ 185 CONSTANT(1)
++ 185 CALL_PRIMITIVE(Arithmetic(SUB,INT))
++ 185 CONSTANT(2)
++ 185 CALL_PRIMITIVE(Arithmetic(DIV,INT))
++ 185 STORE_LOCAL(variable result)
++ 185 LOAD_LOCAL(variable exc2)
++ 185 THROW(Throwable)
++
+ }
+@@ -852,6 +918,6 @@
+ with finalizer: null
+- catch (Throwable) in ArrayBuffer(13, 14, 15, 18, 20, 21, 23) starting at: 4
++ catch (Throwable) in ArrayBuffer(13, 14, 15, 18, 20, 21, 23, 25) starting at: 4
+ consisting of blocks: List(9, 8, 6, 5, 4)
+ with finalizer: null
+- catch (<none>) in ArrayBuffer(4, 5, 6, 9, 13, 14, 15, 18, 20, 21, 23) starting at: 3
++ catch (<none>) in ArrayBuffer(4, 5, 6, 9, 13, 14, 15, 18, 20, 21, 23, 25, 26) starting at: 3
+ consisting of blocks: List(3)
+@@ -879,5 +945,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value e, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value e, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,2,3,6,7,8,11,13,14,16]
++ blocks: [1,2,3,6,7,8,11,13,14,16,17]
+
+@@ -905,4 +971,11 @@
+ 124 CALL_METHOD MyException.<init> (static-instance)
+- 124 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
++ 17:
++ 122 LOAD_LOCAL(value ex6)
++ 122 STORE_LOCAL(value x4)
++ 122 SCOPE_ENTER value x4
++ 122 JUMP 7
++
+ 16:
+@@ -930,8 +1003,5 @@
+ 127 SCOPE_ENTER value x5
+- 127 LOAD_LOCAL(value x5)
+- 127 CALL_METHOD MyException.message (dynamic)
+- 127 STORE_LOCAL(value message)
+- 127 SCOPE_ENTER value message
+ 127 LOAD_MODULE object Predef
+- 127 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 127 CALL_METHOD MyException.message (dynamic)
+ 127 CALL_METHOD scala.Predef.println (dynamic)
+@@ -964,3 +1034,3 @@
+ with finalizer: null
+- catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16) starting at: 3
++ catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16, 17) starting at: 3
+ consisting of blocks: List(3)
+@@ -988,5 +1058,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, value x4, value x5, value message, value x, value e
++ locals: value args, variable result, value ex6, value x4, value x5, value x, value e
+ startBlock: 1
+- blocks: [1,2,3,4,5,8,12,13,14,16]
++ blocks: [1,2,3,5,8,12,13,14,16,17]
+
+@@ -1014,4 +1084,13 @@
+ 148 CALL_METHOD MyException.<init> (static-instance)
+- 148 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
++ 17:
++ 145 LOAD_LOCAL(value ex6)
++ 145 STORE_LOCAL(value x4)
++ 145 SCOPE_ENTER value x4
++ 154 LOAD_LOCAL(value x4)
++ 154 IS_INSTANCE REF(class MyException)
++ 154 CZJUMP (BOOL)NE ? 5 : 8
++
+ 16:
+@@ -1035,5 +1114,2 @@
+ 145 SCOPE_ENTER value x4
+- 145 JUMP 4
+-
+- 4:
+ 154 LOAD_LOCAL(value x4)
+@@ -1047,8 +1123,5 @@
+ 154 SCOPE_ENTER value x5
+- 154 LOAD_LOCAL(value x5)
+- 154 CALL_METHOD MyException.message (dynamic)
+- 154 STORE_LOCAL(value message)
+- 154 SCOPE_ENTER value message
+ 154 LOAD_MODULE object Predef
+- 154 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 154 CALL_METHOD MyException.message (dynamic)
+ 154 CALL_METHOD scala.Predef.println (dynamic)
+@@ -1269,3 +1342,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,5,7]
++ blocks: [1,2,3,4,5,7,8]
+
+@@ -1293,4 +1366,11 @@
+ 38 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance)
+- 38 THROW(IllegalArgumentException)
++ ? STORE_LOCAL(value e)
++ ? JUMP 8
+
++ 8:
++ 42 LOAD_MODULE object Predef
++ 42 CONSTANT("IllegalArgumentException")
++ 42 CALL_METHOD scala.Predef.println (dynamic)
++ 42 JUMP 2
++
+ 7:
+@@ -1340,5 +1420,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,2,3,4,5,8,10,11,13,14,16]
++ blocks: [1,2,3,5,8,10,11,13,14,16,17]
+
+@@ -1366,3 +1446,4 @@
+ 203 CALL_METHOD MyException.<init> (static-instance)
+- 203 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
+@@ -1386,4 +1467,13 @@
+ 209 CALL_METHOD MyException.<init> (static-instance)
+- 209 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
++ 17:
++ 200 LOAD_LOCAL(value ex6)
++ 200 STORE_LOCAL(value x4)
++ 200 SCOPE_ENTER value x4
++ 212 LOAD_LOCAL(value x4)
++ 212 IS_INSTANCE REF(class MyException)
++ 212 CZJUMP (BOOL)NE ? 5 : 8
++
+ 16:
+@@ -1399,5 +1489,2 @@
+ 200 SCOPE_ENTER value x4
+- 200 JUMP 4
+-
+- 4:
+ 212 LOAD_LOCAL(value x4)
+@@ -1411,8 +1498,5 @@
+ 212 SCOPE_ENTER value x5
+- 212 LOAD_LOCAL(value x5)
+- 212 CALL_METHOD MyException.message (dynamic)
+- 212 STORE_LOCAL(value message)
+- 212 SCOPE_ENTER value message
+ 213 LOAD_MODULE object Predef
+- 213 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 213 CALL_METHOD MyException.message (dynamic)
+ 213 CALL_METHOD scala.Predef.println (dynamic)
+@@ -1460,3 +1544,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,5,7]
++ blocks: [1,2,3,4,5,7,8]
+
+@@ -1484,4 +1568,11 @@
+ 58 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance)
+- 58 THROW(IllegalArgumentException)
++ ? STORE_LOCAL(value e)
++ ? JUMP 8
+
++ 8:
++ 62 LOAD_MODULE object Predef
++ 62 CONSTANT("RuntimeException")
++ 62 CALL_METHOD scala.Predef.println (dynamic)
++ 62 JUMP 2
++
+ 7:
+@@ -1533,3 +1624,3 @@
+ startBlock: 1
+- blocks: [1,3,4]
++ blocks: [1,3,4,5]
+
+@@ -1553,4 +1644,9 @@
+ 229 CALL_METHOD MyException.<init> (static-instance)
+- 229 THROW(MyException)
++ ? JUMP 5
+
++ 5:
++ ? LOAD_LOCAL(variable monitor1)
++ 228 MONITOR_EXIT
++ 228 THROW(Throwable)
++
+ 3:
+@@ -1559,3 +1655,3 @@
+ 228 MONITOR_EXIT
+- ? THROW(Throwable)
++ 228 THROW(Throwable)
+
+@@ -1587,5 +1683,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, variable monitor2, variable monitorResult1
++ locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1
+ startBlock: 1
+- blocks: [1,3,4]
++ blocks: [1,3,4,5]
+
+@@ -1612,4 +1708,12 @@
+ 245 CALL_METHOD MyException.<init> (static-instance)
+- 245 THROW(MyException)
++ ? STORE_LOCAL(value exception$1)
++ ? DROP ConcatClass
++ ? LOAD_LOCAL(value exception$1)
++ ? JUMP 5
+
++ 5:
++ ? LOAD_LOCAL(variable monitor2)
++ 244 MONITOR_EXIT
++ 244 THROW(Throwable)
++
+ 3:
+@@ -1618,3 +1722,3 @@
+ 244 MONITOR_EXIT
+- ? THROW(Throwable)
++ 244 THROW(Throwable)
+
diff --git a/test/files/run/iterator-concat.check b/test/files/run/iterator-concat.check
new file mode 100644
index 0000000000..23835b07ae
--- /dev/null
+++ b/test/files/run/iterator-concat.check
@@ -0,0 +1,4 @@
+100
+1000
+10000
+100000
diff --git a/test/files/run/iterator-concat.scala b/test/files/run/iterator-concat.scala
new file mode 100644
index 0000000000..f11363410f
--- /dev/null
+++ b/test/files/run/iterator-concat.scala
@@ -0,0 +1,15 @@
+object Test {
+ // Create `size` Function0s, each of which evaluates to an Iterator
+ // which produces 1. Then fold them over ++ to get a single iterator,
+ // which should sum to "size".
+ def mk(size: Int): Iterator[Int] = {
+ val closures = (1 to size).toList.map(x => (() => Iterator(1)))
+ closures.foldLeft(Iterator.empty: Iterator[Int])((res, f) => res ++ f())
+ }
+ def main(args: Array[String]): Unit = {
+ println(mk(100).sum)
+ println(mk(1000).sum)
+ println(mk(10000).sum)
+ println(mk(100000).sum)
+ }
+}
diff --git a/test/files/run/outertest.scala b/test/files/run/outertest.scala
index 3cc96afa5b..fa0443f669 100644
--- a/test/files/run/outertest.scala
+++ b/test/files/run/outertest.scala
@@ -1,26 +1,57 @@
// A test for the case where the outer field of class B#J should be eliminated.
-// You can verify this by running a javap on B.J
+
+import reflect.ClassTag
+
abstract class A {
+ abstract class I
- abstract class I {
+ val foo = this
+}
+class B extends A {
+ class J extends I {
+ val bar = foo
}
- val foo = "foo"
+ type II = I
+ class K extends II {
+ val bar = foo
+ }
+ class L extends (I @annotation.tailrec) {
+ val bar = foo
+ }
}
-class B extends A {
- class J extends I {
+class C extends A {
+ val c: C = this
+
+ class M extends c.I {
val bar = foo
}
-
}
-object Test extends App {
+object Test extends App {
val b = new B
- assert((new b.J).bar == b.foo)
+ val c0 = new C
+ val c = new { override val c = c0 } with C
+
+ assert((new b.J).bar eq b)
+ assert((new b.K).bar eq b)
+ assert((new b.L).bar eq b)
+ assert((new c.M).bar eq c)
+
+ def checkOuterFields[C: ClassTag](expected: Int) {
+ val cls = implicitly[ClassTag[C]].runtimeClass
+ val outerFields = cls.getDeclaredFields().filter(_.getName.contains("$outer"))
+ assert(outerFields.size == expected, outerFields.map(_.getName))
+ }
+ checkOuterFields[A#I](1) // the base class must have the $outer pointer
+ checkOuterFields[B#J](0) // reuse parent class' $outer pointer
+ checkOuterFields[B#K](0) // ... through an alias
+ checkOuterFields[B#L](0) // ... through the annotated type
+ checkOuterFields[C#M](1) // different prefix, can't share.
}
diff --git a/test/files/run/reify_this.scala b/test/files/run/reify_this.scala
index ecbf394bba..c385da6360 100644
--- a/test/files/run/reify_this.scala
+++ b/test/files/run/reify_this.scala
@@ -1,11 +1,11 @@
import scala.reflect.runtime.universe._
import scala.tools.reflect.Eval
-trait Eval {
+trait Transvaal {
def eval(tree: Expr[_]) = tree.eval
}
-object Test extends App with Eval {
+object Test extends App with Transvaal {
// select a value from package
eval(reify{println("foo")})
eval(reify{println((new Object).toString == (new Object).toString)})
@@ -17,4 +17,4 @@ object Test extends App with Eval {
// select a value from module
val x = 2
eval(reify{println(x)})
-} \ No newline at end of file
+}
diff --git a/test/files/run/t3994.scala b/test/files/run/t3994.scala
new file mode 100644
index 0000000000..0ee1d9d966
--- /dev/null
+++ b/test/files/run/t3994.scala
@@ -0,0 +1,20 @@
+trait T {
+ trait Default { def foo = this }
+ object Default extends Default
+}
+
+class Crash { // if you change this to a `trait` it keeps failing, though if it is an `object` it compiles just fine!
+ class Element
+
+ /* declare this as a class, and the crash goes away */
+ trait ElementOrdering extends Ordering[Element] {
+ def compare(a: Element, b: Element): Int = 0
+ }
+
+ implicit object ElementOrdering extends ElementOrdering
+}
+
+object Test extends App {
+ (new T {}).Default
+ (new Crash).ElementOrdering
+}
diff --git a/test/files/run/t5699.check b/test/files/run/t5699.check
new file mode 100755
index 0000000000..df19644ae6
--- /dev/null
+++ b/test/files/run/t5699.check
@@ -0,0 +1,11 @@
+[[syntax trees at end of parser]] // annodef.java
+package <empty> {
+ object MyAnnotation extends {
+ def <init>() = _
+ };
+ class MyAnnotation extends scala.annotation.Annotation with _root_.java.lang.annotation.Annotation with scala.annotation.ClassfileAnnotation {
+ def <init>() = _;
+ def value(): String
+ }
+}
+
diff --git a/test/files/run/t5699.scala b/test/files/run/t5699.scala
new file mode 100755
index 0000000000..5cef67e3b1
--- /dev/null
+++ b/test/files/run/t5699.scala
@@ -0,0 +1,24 @@
+import scala.tools.partest.DirectTest
+import scala.tools.nsc.util.BatchSourceFile
+
+object Test extends DirectTest {
+ // 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 newSources(sourceCodes: String*) = {
+ assert(sourceCodes.size == 1)
+ List(new BatchSourceFile("annodef.java", sourceCodes(0)))
+ }
+}
diff --git a/test/files/run/t6028.check b/test/files/run/t6028.check
index 67c30e35c6..2ec639fce2 100644
--- a/test/files/run/t6028.check
+++ b/test/files/run/t6028.check
@@ -1,7 +1,7 @@
[[syntax trees at end of lambdalift]] // newSource1
package <empty> {
class T extends Object {
- <paramaccessor> val T$$classParam: Int = _;
+ <paramaccessor> val classParam: Int = _;
def <init>(classParam: Int): T = {
T.super.<init>();
()
@@ -30,15 +30,15 @@ package <empty> {
()
};
final def apply(): Int = $anonfun$foo$1.this.apply$mcI$sp();
- <specialized> def apply$mcI$sp(): Int = $anonfun$foo$1.this.$outer.T$$classParam.+($anonfun$foo$1.this.$outer.field()).+($anonfun$foo$1.this.methodParam$1).+($anonfun$foo$1.this.methodLocal$1);
+ <specialized> def apply$mcI$sp(): Int = $anonfun$foo$1.this.$outer.classParam.+($anonfun$foo$1.this.$outer.field()).+($anonfun$foo$1.this.methodParam$1).+($anonfun$foo$1.this.methodLocal$1);
<synthetic> <paramaccessor> <artifact> private[this] val $outer: T = _;
- <synthetic> <stable> <artifact> def T$$anonfun$$$outer(): T = $anonfun$foo$1.this.$outer;
+ <synthetic> <stable> <artifact> def $outer(): T = $anonfun$foo$1.this.$outer;
final <bridge> <artifact> def apply(): Object = scala.Int.box($anonfun$foo$1.this.apply());
<synthetic> <paramaccessor> private[this] val methodParam$1: Int = _;
<synthetic> <paramaccessor> private[this] val methodLocal$1: Int = _
};
abstract trait MethodLocalTrait$1 extends Object {
- <synthetic> <stable> <artifact> def T$MethodLocalTrait$$$outer(): T
+ <synthetic> <stable> <artifact> def $outer(): T
};
object MethodLocalObject$2 extends Object with T#MethodLocalTrait$1 {
def <init>($outer: T, barParam$1: Int): T#MethodLocalObject$2.type = {
@@ -47,8 +47,8 @@ package <empty> {
()
};
<synthetic> <paramaccessor> <artifact> private[this] val $outer: T = _;
- <synthetic> <stable> <artifact> def T$MethodLocalObject$$$outer(): T = MethodLocalObject$2.this.$outer;
- <synthetic> <stable> <artifact> def T$MethodLocalTrait$$$outer(): T = MethodLocalObject$2.this.$outer
+ <synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer;
+ <synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer
};
final <stable> private[this] def MethodLocalObject$1(barParam$1: Int, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = {
MethodLocalObject$module$1.elem = new T#MethodLocalObject$2.type(T.this, barParam$1);
@@ -70,7 +70,7 @@ package <empty> {
$anonfun$tryy$1.this.tryyLocal$1.elem = $anonfun$tryy$1.this.tryyParam$1
} finally ();
<synthetic> <paramaccessor> <artifact> private[this] val $outer: T = _;
- <synthetic> <stable> <artifact> def T$$anonfun$$$outer(): T = $anonfun$tryy$1.this.$outer;
+ <synthetic> <stable> <artifact> def $outer(): T = $anonfun$tryy$1.this.$outer;
final <bridge> <artifact> def apply(): Object = {
$anonfun$tryy$1.this.apply();
scala.runtime.BoxedUnit.UNIT
diff --git a/test/files/run/t6146b.check b/test/files/run/t6146b.check
index b664d1152a..49ff70697e 100644
--- a/test/files/run/t6146b.check
+++ b/test/files/run/t6146b.check
@@ -37,8 +37,15 @@ memType: (sub: u.Type, scrut: u.Type)u.Type
scala>
-scala> memType(S1, fTpe)
-res0: u.Type = O.X.S1.type
+scala> val mt1 = memType(S1, fTpe)
+mt1: u.Type = O.X.S1.type
+
+scala> global.typeDeconstruct.show(mt1)
+res0: String =
+TypeRef(
+ pre = SingleType(pre = ThisType(object O), object X)
+ TypeSymbol(class S1 extends C.this.F[T])
+)
scala> memType(S2, fTpe)
res1: u.Type = O.S2
diff --git a/test/files/run/t6146b.scala b/test/files/run/t6146b.scala
index adcd40d2ee..e63709aa9d 100644
--- a/test/files/run/t6146b.scala
+++ b/test/files/run/t6146b.scala
@@ -31,7 +31,8 @@ val fTpe = typeOf[O.type].decl(newTermName("foo")).paramss.head.head.tpe
def memType(sub: Type, scrut: Type): Type =
nestedMemberType(sub.typeSymbol, scrut.prefix, scrut.typeSymbol.owner)
-memType(S1, fTpe)
+val mt1 = memType(S1, fTpe)
+global.typeDeconstruct.show(mt1)
memType(S2, fTpe)
memType(S3, fTpe)
memType(S4, fTpe)
diff --git a/test/files/run/t6168/Context.java b/test/files/run/t6168/Context.java
new file mode 100644
index 0000000000..e527844563
--- /dev/null
+++ b/test/files/run/t6168/Context.java
@@ -0,0 +1,34 @@
+public class Context<ParentType> {
+ private ParentType parent;
+
+ public Context() {}
+
+ public ParentType getParent() {
+ return parent;
+ }
+
+ public void setParent(ParentType parent) {
+ this.parent = parent;
+ }
+
+ public Field<Integer> intField() {
+ return new Field<Integer>() {
+ @Override
+ public Integer get() {
+ return 0;
+ }
+
+ @Override
+ public ParentType set(Integer t) {
+ return parent;
+ }
+ };
+ }
+
+ public abstract class Field<T> { //Note this is a path dependent type
+
+ public abstract T get();
+
+ public abstract ParentType set(T t);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6168/JavaTest.java b/test/files/run/t6168/JavaTest.java
new file mode 100644
index 0000000000..94ae91661d
--- /dev/null
+++ b/test/files/run/t6168/JavaTest.java
@@ -0,0 +1,8 @@
+public class JavaTest {
+ public static void main(String[] args) {
+ SomeClass a = new SomeClass();
+ SomeClass2 a2 = new SomeClass2();
+ SomeClass b = a.f.set(23).f.set(23);
+ SomeClass2 b2 = a2.f.set(23).f.set(23);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6168/SomeClass.java b/test/files/run/t6168/SomeClass.java
new file mode 100644
index 0000000000..6f76b829bb
--- /dev/null
+++ b/test/files/run/t6168/SomeClass.java
@@ -0,0 +1,14 @@
+public class SomeClass {
+ private final Context<SomeClass> context = new Context<SomeClass>();
+ {
+ context.setParent(this);
+ }
+
+ public final Context<SomeClass>.Field<Integer> f = context.intField();
+
+ public SomeClass() {
+ f.set(23).f.set(23);
+ }
+}
+
+
diff --git a/test/files/run/t6168/SomeClass2.java b/test/files/run/t6168/SomeClass2.java
new file mode 100644
index 0000000000..b2c7a7540b
--- /dev/null
+++ b/test/files/run/t6168/SomeClass2.java
@@ -0,0 +1,12 @@
+public class SomeClass2 {
+ private final Context<SomeClass2> context = new Context<SomeClass2>();
+ {
+ context.setParent(this);
+ }
+
+ public final Context<SomeClass2>.Field<Integer> f = context.intField();
+
+ public SomeClass2() {
+ f.set(23).f.set(23);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6168/main.scala b/test/files/run/t6168/main.scala
new file mode 100644
index 0000000000..c7ad37830b
--- /dev/null
+++ b/test/files/run/t6168/main.scala
@@ -0,0 +1,15 @@
+
+
+object Test extends App {
+ JavaTest.main(null)
+
+ var a1 : SomeClass = new SomeClass
+ var a2 : SomeClass2 = new SomeClass2
+ //import language.implicitConversions
+ //implicit def setParentType2SomeClass(x:Any) = x.asInstanceOf[SomeClass]
+ //implicit def setParentType2SomeClass2(x:Any) = x.asInstanceOf[SomeClass2]
+ //var b : SomeClass = a.f.set(23).asInstanceOf[SomeClass].f.set(23).asInstanceOf[SomeClass]
+ //var b2 : SomeClass2 = a2.f.set(23).asInstanceOf[SomeClass2].f.set(23).asInstanceOf[SomeClass2]
+ var b1 : SomeClass = a1.f.set(23).f.set(23)
+ var b2 : SomeClass2 = a2.f.set(23).f.set(23)
+}
diff --git a/test/files/run/t6168b/Context.java b/test/files/run/t6168b/Context.java
new file mode 100644
index 0000000000..b3ea22126f
--- /dev/null
+++ b/test/files/run/t6168b/Context.java
@@ -0,0 +1,34 @@
+public class Context<ParentType> {
+ private ParentType parent;
+
+ public Context() {}
+
+ public ParentType getParent() {
+ return parent;
+ }
+
+ public void setParent(ParentType parent) {
+ this.parent = parent;
+ }
+
+ public Field<Integer> intField() {
+ return new Field<Integer>() {
+ @Override
+ public Integer get() {
+ return 0;
+ }
+
+ @Override
+ public ParentType set(Integer t) {
+ return parent;
+ }
+ };
+ }
+
+ public static abstract class Field<T> {
+
+ public abstract T get();
+
+ public abstract Object set(T t);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6168b/JavaTest.java b/test/files/run/t6168b/JavaTest.java
new file mode 100644
index 0000000000..a09fa0382d
--- /dev/null
+++ b/test/files/run/t6168b/JavaTest.java
@@ -0,0 +1,6 @@
+public class JavaTest {
+ public static void main(String[] args) {
+ SomeClass a = new SomeClass();
+ Object b = a.f.set(23);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6168b/SomeClass.java b/test/files/run/t6168b/SomeClass.java
new file mode 100644
index 0000000000..566c55e1c5
--- /dev/null
+++ b/test/files/run/t6168b/SomeClass.java
@@ -0,0 +1,11 @@
+public class SomeClass {
+ private final Context<SomeClass> context = new Context<SomeClass>();
+ {
+ context.setParent(this);
+ }
+
+ public final Context.Field<Integer> f = context.intField();
+
+}
+
+
diff --git a/test/files/run/t6168b/main.scala b/test/files/run/t6168b/main.scala
new file mode 100644
index 0000000000..187e9fe85e
--- /dev/null
+++ b/test/files/run/t6168b/main.scala
@@ -0,0 +1,8 @@
+
+
+object Test extends App {
+ JavaTest.main(null)
+
+ var a1 : SomeClass = new SomeClass
+ var b1 : Object = a1.f.set(23)
+}
diff --git a/test/files/run/t6223.scala b/test/files/run/t6223.scala
index fb176e32e6..0996ea1c45 100644
--- a/test/files/run/t6223.scala
+++ b/test/files/run/t6223.scala
@@ -5,7 +5,7 @@ class Foo[@specialized(Int) A](a:A) {
object Test {
def main(args:Array[String]) {
val f = new Foo(333)
- val ms = f.getClass().getDeclaredMethods().sortBy(_.getName)
- ms.foreach(m => println(m.getName))
+ val ms = f.getClass().getDeclaredMethods().map(_.getName).sorted
+ ms.foreach(println)
}
}
diff --git a/test/files/run/t6387.check b/test/files/run/t6387.check
new file mode 100644
index 0000000000..83b33d238d
--- /dev/null
+++ b/test/files/run/t6387.check
@@ -0,0 +1 @@
+1000
diff --git a/test/files/run/t6387.scala b/test/files/run/t6387.scala
new file mode 100644
index 0000000000..bbebb5f511
--- /dev/null
+++ b/test/files/run/t6387.scala
@@ -0,0 +1,16 @@
+trait A {
+ def foo: Long
+}
+
+object Test {
+ def a(): A = new A {
+ var foo: Long = 1000L
+
+ val test = () => {
+ foo = 28
+ }
+ }
+ def main(args: Array[String]) {
+ println(a().foo)
+ }
+}
diff --git a/test/files/run/t6715.scala b/test/files/run/t6715.scala
new file mode 100644
index 0000000000..07ff34218a
--- /dev/null
+++ b/test/files/run/t6715.scala
@@ -0,0 +1,15 @@
+import scala.reflect.runtime.universe._
+
+class A {
+ def $$ = 1
+ def $times = 1
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val memberSet: Set[String] = typeOf[A].members.map{ _.toString }.toSet
+ assert(memberSet contains "method *")
+ assert(memberSet contains "method $$")
+ assert(! (memberSet contains "method"))
+ }
+}
diff --git a/test/files/run/t6725-1.check b/test/files/run/t6725-1.check
new file mode 100644
index 0000000000..6ed281c757
--- /dev/null
+++ b/test/files/run/t6725-1.check
@@ -0,0 +1,2 @@
+1
+1
diff --git a/test/files/run/t6725-1.scala b/test/files/run/t6725-1.scala
new file mode 100644
index 0000000000..a167ef8aa3
--- /dev/null
+++ b/test/files/run/t6725-1.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ val a = 1
+ val s = f"$a%s%n$a%s"
+ println(s)
+} \ No newline at end of file
diff --git a/test/files/run/t6725-2.check b/test/files/run/t6725-2.check
new file mode 100644
index 0000000000..3496917ad5
--- /dev/null
+++ b/test/files/run/t6725-2.check
@@ -0,0 +1,8 @@
+
+
+aaaa
+
+
+aaaa
+aaaa
+aaaa
diff --git a/test/files/run/t6725-2.scala b/test/files/run/t6725-2.scala
new file mode 100644
index 0000000000..e033cf5ea8
--- /dev/null
+++ b/test/files/run/t6725-2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ println(f"%n")
+ println(f"aaaa%n")
+ println(f"%naaaa")
+ println(f"aaaa%naaaa")
+} \ No newline at end of file
diff --git a/test/files/run/t6793.scala b/test/files/run/t6793.scala
new file mode 100644
index 0000000000..0b1f1619af
--- /dev/null
+++ b/test/files/run/t6793.scala
@@ -0,0 +1,9 @@
+package a { class C1(private[a] val v0: String) }
+package b { class C2(v1: String) extends a.C1(v1) { def foo = v1 } }
+
+object Test extends App {
+ new b.C2("x")
+
+ val c2Fields = classOf[b.C2].getDeclaredFields
+ assert(c2Fields.size == 1, c2Fields.map(_.getName).toList)
+}
diff --git a/test/files/run/t6793b.scala b/test/files/run/t6793b.scala
new file mode 100644
index 0000000000..cb3f2fb2fa
--- /dev/null
+++ b/test/files/run/t6793b.scala
@@ -0,0 +1,11 @@
+package a {
+ class C1(val v0: String)
+ class C2(v1: String) extends a.C1(v1) { def foo = v1 }
+}
+
+object Test extends App {
+ new a.C2("x")
+
+ val c2Fields = classOf[a.C2].getDeclaredFields
+ assert(c2Fields.isEmpty, c2Fields.map(_.getName).mkString(", "))
+}
diff --git a/test/files/run/t6793c.scala b/test/files/run/t6793c.scala
new file mode 100644
index 0000000000..e28c7c81a1
--- /dev/null
+++ b/test/files/run/t6793c.scala
@@ -0,0 +1,11 @@
+package a {
+ class C1(private[a] val v0: String)
+ class C2(v1: String) extends a.C1(v1) { def foo = v1 }
+}
+
+object Test extends App {
+ new a.C2("x").foo
+
+ val c2Fields = classOf[a.C2].getDeclaredFields
+ assert(c2Fields.isEmpty, c2Fields.map(_.getName).toList)
+}
diff --git a/test/files/run/t6900.scala b/test/files/run/t6900.scala
new file mode 100644
index 0000000000..a29d388129
--- /dev/null
+++ b/test/files/run/t6900.scala
@@ -0,0 +1,36 @@
+import annotation.tailrec
+
+trait Universe {
+ type T <: AnyRef
+}
+
+final class Bug {
+ var i = 1
+ def stop() = { i -= 1; i < 0 }
+ // the alias bypasses the fast path in erasures InfoTransformer
+ // predicated on `TypeMap.noChangeToSymbols`
+ type Alias = Any
+
+ @tailrec
+ // So we get two symbols for `universe`, the original on the ValDef
+ // and a clone in the MethodType of `f`.
+ def f(universe: Universe, l: Alias): universe.T = {
+ if (stop()) null.asInstanceOf[universe.T] else f(universe, null)
+ }
+
+ @tailrec
+ def g(universe: Universe)(l: Alias): universe.T = {
+ if (stop()) null.asInstanceOf[universe.T] else g(universe)(l)
+ }
+
+ @tailrec
+ def h(universe: Universe)(l: List[universe.T]): List[universe.T] = {
+ if (stop()) Nil else h(universe)(l)
+ }
+}
+
+object Test extends App {
+ assert(new Bug().f(null, null) == null)
+ assert(new Bug().g(null)(null) == null)
+ assert(new Bug().h(null)(null) == Nil)
+} \ No newline at end of file
diff --git a/test/files/run/t7240.check b/test/files/run/t7240.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/t7240.check
diff --git a/test/files/run/t7240/Macros_1.scala b/test/files/run/t7240/Macros_1.scala
new file mode 100644
index 0000000000..6465e18760
--- /dev/null
+++ b/test/files/run/t7240/Macros_1.scala
@@ -0,0 +1,48 @@
+package bakery
+
+import scala.language.experimental.macros
+import scala.reflect.macros.Context
+
+trait FailureCake {
+ implicit def liftAnyFails[T: Manifest]: Any = ???
+
+ // This works
+ // implicit def liftAny[T]: Any = ???
+}
+
+object Bakery {
+
+ def failure: Any = macro failureImpl
+ def failureImpl(c: Context): c.Expr[Any] = {
+ import c.universe._
+
+ def dslTrait(dslName: String) = {
+ val names = dslName.split("\\.").toList.reverse
+ assert(names.length >= 1, "DSL trait name must be in the valid format. DSL trait name is " + dslName)
+
+ val tpeName = newTypeName(names.head)
+ names.tail.reverse match {
+ case head :: tail ⇒
+ Select(tail.foldLeft[Tree](Ident(newTermName(head)))((tree, name) ⇒ Select(tree, newTermName(name))), tpeName)
+ case Nil ⇒
+ Ident(tpeName)
+ }
+ }
+
+ def composeDSL(transformedBody: Tree) =
+ ClassDef(Modifiers(), newTypeName("eval"), List(), Template(
+ List(dslTrait("bakery.FailureCake")),
+ emptyValDef,
+ List(
+ DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(),
+ Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))),
+ DefDef(Modifiers(), newTermName("main"), List(), List(List()), Ident(newTypeName("Any")), transformedBody))))
+
+ def constructor = Apply(Select(New(Ident(newTypeName("eval"))), nme.CONSTRUCTOR), List())
+
+ c.eval(c.Expr[Any](
+ c.resetAllAttrs(Block(composeDSL(Literal(Constant(1))), constructor))))
+
+ c.Expr[Any](Literal(Constant(1)))
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t7240/Test_2.scala b/test/files/run/t7240/Test_2.scala
new file mode 100644
index 0000000000..2450bdabf9
--- /dev/null
+++ b/test/files/run/t7240/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ bakery.Bakery.failure
+} \ No newline at end of file
diff --git a/test/files/run/t7242.scala b/test/files/run/t7242.scala
new file mode 100644
index 0000000000..c995336144
--- /dev/null
+++ b/test/files/run/t7242.scala
@@ -0,0 +1,71 @@
+class CrashTest {
+ def foo = ()
+ trait CrashTestTable {
+ def cols = foo
+ }
+ // This was leading to a class between the mixed in
+ // outer accessor and the outer accessor of this object.
+ object CrashTestTable extends CrashTestTable {
+ foo
+ cols
+ }
+}
+
+class CrashTest1 {
+ def foo = ()
+ class CrashTestTable {
+ def cols = foo
+ }
+ object CrashTestTable extends CrashTestTable {
+ foo
+ cols
+ }
+}
+
+class CrashTest2 {
+ def foo = ()
+ trait CrashTestTable {
+ def cols = foo
+ }
+ object Obj extends CrashTestTable {
+ foo
+ cols
+ }
+}
+
+class CrashTest3 {
+ def foo = ()
+
+ def meth() {
+ trait CrashTestTable {
+ def cols = foo
+ }
+ object Obj extends CrashTestTable {
+ foo
+ cols
+ }
+ Obj
+ }
+}
+
+object Test extends App {
+ {
+ val c = new CrashTest
+ c.CrashTestTable
+ }
+
+ {
+ val c = new CrashTest1
+ c.CrashTestTable
+ }
+
+ {
+ val c = new CrashTest2
+ c.Obj
+ }
+
+ {
+ val c = new CrashTest3
+ c.meth()
+ }
+}
diff --git a/test/files/run/t7246.check b/test/files/run/t7246.check
new file mode 100755
index 0000000000..ce01362503
--- /dev/null
+++ b/test/files/run/t7246.check
@@ -0,0 +1 @@
+hello
diff --git a/test/files/run/t7246/Outer.java b/test/files/run/t7246/Outer.java
new file mode 100755
index 0000000000..163276fb3b
--- /dev/null
+++ b/test/files/run/t7246/Outer.java
@@ -0,0 +1,4 @@
+public class Outer {
+ public class Inner {
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t7246/Test.scala b/test/files/run/t7246/Test.scala
new file mode 100755
index 0000000000..9f23ca8f3a
--- /dev/null
+++ b/test/files/run/t7246/Test.scala
@@ -0,0 +1,16 @@
+object Test extends App {
+
+ val so = new SubOuter
+ val si = new so.SubInner
+ println(si.bar)
+}
+
+class SubOuter extends Outer {
+
+ val foo = "hello"
+
+ class SubInner extends Inner {
+ def bar = foo
+ }
+
+} \ No newline at end of file
diff --git a/test/files/run/t7246b.check b/test/files/run/t7246b.check
new file mode 100755
index 0000000000..5073bd8617
--- /dev/null
+++ b/test/files/run/t7246b.check
@@ -0,0 +1,2 @@
+base
+sub
diff --git a/test/files/run/t7246b/Base.scala b/test/files/run/t7246b/Base.scala
new file mode 100755
index 0000000000..4e71d3313d
--- /dev/null
+++ b/test/files/run/t7246b/Base.scala
@@ -0,0 +1,7 @@
+class Base {
+ val baseOuter = "base"
+
+ class BaseInner {
+ val baseInner = baseOuter
+ }
+}
diff --git a/test/files/run/t7246b/Outer.java b/test/files/run/t7246b/Outer.java
new file mode 100755
index 0000000000..53a79316ef
--- /dev/null
+++ b/test/files/run/t7246b/Outer.java
@@ -0,0 +1,4 @@
+public class Outer extends Base {
+ public class Inner extends BaseInner {
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t7246b/Test.scala b/test/files/run/t7246b/Test.scala
new file mode 100755
index 0000000000..f0982ea8d0
--- /dev/null
+++ b/test/files/run/t7246b/Test.scala
@@ -0,0 +1,14 @@
+object Test extends App {
+
+ val so = new SubOuter
+ val si = new so.SubInner
+ println(si.baseInner)
+ println(si.subInner)
+}
+
+class SubOuter extends Outer {
+ val subOuter = "sub"
+ class SubInner extends Inner {
+ def subInner = subOuter
+ }
+}
diff --git a/test/files/run/t7249.check b/test/files/run/t7249.check
new file mode 100644
index 0000000000..7777e0a5a2
--- /dev/null
+++ b/test/files/run/t7249.check
@@ -0,0 +1 @@
+Yup!
diff --git a/test/files/run/t7249.scala b/test/files/run/t7249.scala
new file mode 100644
index 0000000000..375df5c3ad
--- /dev/null
+++ b/test/files/run/t7249.scala
@@ -0,0 +1,7 @@
+object Test extends App {
+ def bnToLambda(s: => String): () => String = () => s
+ var x: () => String = () => sys.error("Nope")
+ val y = bnToLambda { x() }
+ x = () => "Yup!"
+ println(y())
+}
diff --git a/test/files/run/t7290.scala b/test/files/run/t7290.scala
new file mode 100644
index 0000000000..01f7e8f68e
--- /dev/null
+++ b/test/files/run/t7290.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ val y = (0: Int) match {
+ case 1 => 1
+ case 0 | 0 => 0
+ case 2 | 2 | 2 | 3 | 2 | 3 => 0
+ case _ => -1
+ }
+ assert(y == 0, y)
+}
diff --git a/test/files/run/t7300.check b/test/files/run/t7300.check
new file mode 100644
index 0000000000..51993f072d
--- /dev/null
+++ b/test/files/run/t7300.check
@@ -0,0 +1,2 @@
+2
+2
diff --git a/test/files/run/t7300.scala b/test/files/run/t7300.scala
new file mode 100644
index 0000000000..ec841690df
--- /dev/null
+++ b/test/files/run/t7300.scala
@@ -0,0 +1,11 @@
+object Test extends App {
+ // single line comment in multi line comment
+ /*//*/ val x = 1 */*/
+ val x = 2
+ println(x)
+
+ // single line comment in nested multi line comment
+ /*/*//*/ val y = 1 */*/*/
+ val y = 2
+ println(y)
+}
diff --git a/test/files/run/test-cpp.check b/test/files/run/test-cpp.check
index bfea438c60..13f4c64be3 100644
--- a/test/files/run/test-cpp.check
+++ b/test/files/run/test-cpp.check
@@ -1,65 +1,81 @@
-37c37
-< locals: value args, value x, value y
----
-> locals: value args
-42,43d41
-< 52 CONSTANT(2)
-< 52 STORE_LOCAL(value x)
-45,46d42
-< 53 LOAD_LOCAL(value x)
-< 53 STORE_LOCAL(value y)
-49c45
-< 54 LOAD_LOCAL(value y)
----
-> 54 CONSTANT(2)
-92c88
-< locals: value args, value x, value y
----
-> locals: value args, value x
-101,102d96
-< 82 LOAD_LOCAL(value x)
-< 82 STORE_LOCAL(value y)
-105c99
-< 83 LOAD_LOCAL(value y)
----
-> 83 LOAD_LOCAL(value x)
-135c129
-< locals: value args, value x, value y
----
-> locals: value args
-140,141d133
-< 66 THIS(TestAliasChainDerefThis)
-< 66 STORE_LOCAL(value x)
-143,144d134
-< 67 LOAD_LOCAL(value x)
-< 67 STORE_LOCAL(value y)
-147c137
-< 68 LOAD_LOCAL(value y)
----
-> 68 THIS(Object)
-176c166
-< locals: value x, value y
----
-> locals: value x
-181,182d170
-< 29 LOAD_LOCAL(value x)
-< 29 STORE_LOCAL(value y)
-185c173
-< 30 LOAD_LOCAL(value y)
----
-> 30 LOAD_LOCAL(value x)
-223,224d210
-< 97 LOAD_LOCAL(variable x)
-< 97 STORE_LOCAL(variable y)
-227c213
-< 98 LOAD_LOCAL(variable y)
----
-> 98 LOAD_LOCAL(variable x)
-233,234d218
-< 101 LOAD_LOCAL(variable y)
-< 101 STORE_LOCAL(variable x)
-236c220
-< 102 LOAD_LOCAL(variable x)
----
-> 102 LOAD_LOCAL(variable y)
-
+--- a
++++ b
+@@ -36,3 +36,3 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, value x, value y
++ locals: value args
+ startBlock: 1
+@@ -41,10 +41,6 @@
+ 1:
+- 52 CONSTANT(2)
+- 52 STORE_LOCAL(value x)
+ 52 SCOPE_ENTER value x
+- 53 LOAD_LOCAL(value x)
+- 53 STORE_LOCAL(value y)
+ 53 SCOPE_ENTER value y
+ 54 LOAD_MODULE object Predef
+- 54 LOAD_LOCAL(value y)
++ 54 CONSTANT(2)
+ 54 BOX INT
+@@ -91,3 +87,3 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, value x, value y
++ locals: value args, value x
+ startBlock: 1
+@@ -100,7 +96,5 @@
+ 81 SCOPE_ENTER value x
+- 82 LOAD_LOCAL(value x)
+- 82 STORE_LOCAL(value y)
+ 82 SCOPE_ENTER value y
+ 83 LOAD_MODULE object Predef
+- 83 LOAD_LOCAL(value y)
++ 83 LOAD_LOCAL(value x)
+ 83 BOX INT
+@@ -134,3 +128,3 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, value x, value y
++ locals: value args
+ startBlock: 1
+@@ -139,10 +133,6 @@
+ 1:
+- 66 THIS(TestAliasChainDerefThis)
+- 66 STORE_LOCAL(value x)
+ 66 SCOPE_ENTER value x
+- 67 LOAD_LOCAL(value x)
+- 67 STORE_LOCAL(value y)
+ 67 SCOPE_ENTER value y
+ 68 LOAD_MODULE object Predef
+- 68 LOAD_LOCAL(value y)
++ 68 THIS(Object)
+ 68 CALL_METHOD scala.Predef.println (dynamic)
+@@ -175,3 +165,3 @@
+ def test(x: Int (INT)): Unit {
+- locals: value x, value y
++ locals: value x
+ startBlock: 1
+@@ -180,7 +170,5 @@
+ 1:
+- 29 LOAD_LOCAL(value x)
+- 29 STORE_LOCAL(value y)
+ 29 SCOPE_ENTER value y
+ 30 LOAD_MODULE object Predef
+- 30 LOAD_LOCAL(value y)
++ 30 LOAD_LOCAL(value x)
+ 30 BOX INT
+@@ -222,7 +210,5 @@
+ 96 SCOPE_ENTER variable x
+- 97 LOAD_LOCAL(variable x)
+- 97 STORE_LOCAL(variable y)
+ 97 SCOPE_ENTER variable y
+ 98 LOAD_MODULE object Predef
+- 98 LOAD_LOCAL(variable y)
++ 98 LOAD_LOCAL(variable x)
+ 98 BOX INT
+@@ -232,6 +218,4 @@
+ 100 STORE_LOCAL(variable y)
+- 101 LOAD_LOCAL(variable y)
+- 101 STORE_LOCAL(variable x)
+ 102 LOAD_MODULE object Predef
+- 102 LOAD_LOCAL(variable x)
++ 102 LOAD_LOCAL(variable y)
+ 102 BOX INT
diff --git a/test/files/scalap/abstractClass/result.test b/test/files/scalap/abstractClass.check
index ef1daac23d..ef1daac23d 100644
--- a/test/files/scalap/abstractClass/result.test
+++ b/test/files/scalap/abstractClass.check
diff --git a/test/files/scalap/abstractClass/A.scala b/test/files/scalap/abstractClass.scala
index 19a528d5a1..19a528d5a1 100644
--- a/test/files/scalap/abstractClass/A.scala
+++ b/test/files/scalap/abstractClass.scala
diff --git a/test/files/scalap/abstractMethod/result.test b/test/files/scalap/abstractMethod.check
index 40fa02d408..40fa02d408 100644
--- a/test/files/scalap/abstractMethod/result.test
+++ b/test/files/scalap/abstractMethod.check
diff --git a/test/files/scalap/abstractMethod/A.scala b/test/files/scalap/abstractMethod.scala
index 4bedb377b3..4bedb377b3 100644
--- a/test/files/scalap/abstractMethod/A.scala
+++ b/test/files/scalap/abstractMethod.scala
diff --git a/test/files/scalap/caseClass/result.test b/test/files/scalap/caseClass.check
index 7d7aa4fd8f..7d7aa4fd8f 100644
--- a/test/files/scalap/caseClass/result.test
+++ b/test/files/scalap/caseClass.check
diff --git a/test/files/scalap/caseClass/A.scala b/test/files/scalap/caseClass.scala
index 95f9984519..95f9984519 100644
--- a/test/files/scalap/caseClass/A.scala
+++ b/test/files/scalap/caseClass.scala
diff --git a/test/files/scalap/caseObject/result.test b/test/files/scalap/caseObject.check
index 867a4b2162..867a4b2162 100644
--- a/test/files/scalap/caseObject/result.test
+++ b/test/files/scalap/caseObject.check
diff --git a/test/files/scalap/caseObject/A.scala b/test/files/scalap/caseObject.scala
index 6a3ff10d75..6a3ff10d75 100644
--- a/test/files/scalap/caseObject/A.scala
+++ b/test/files/scalap/caseObject.scala
diff --git a/test/files/scalap/cbnParam/result.test b/test/files/scalap/cbnParam.check
index 52ecb6ae66..52ecb6ae66 100644
--- a/test/files/scalap/cbnParam/result.test
+++ b/test/files/scalap/cbnParam.check
diff --git a/test/files/scalap/cbnParam/A.scala b/test/files/scalap/cbnParam.scala
index 2f366df64a..2f366df64a 100644
--- a/test/files/scalap/cbnParam/A.scala
+++ b/test/files/scalap/cbnParam.scala
diff --git a/test/files/scalap/classPrivate/result.test b/test/files/scalap/classPrivate.check
index ab2d40cdaf..ab2d40cdaf 100644
--- a/test/files/scalap/classPrivate/result.test
+++ b/test/files/scalap/classPrivate.check
diff --git a/test/files/scalap/classPrivate/A.scala b/test/files/scalap/classPrivate.scala
index 9f1bd34a6a..9f1bd34a6a 100644
--- a/test/files/scalap/classPrivate/A.scala
+++ b/test/files/scalap/classPrivate.scala
diff --git a/test/files/scalap/classWithExistential/result.test b/test/files/scalap/classWithExistential.check
index caee3fd6de..caee3fd6de 100644
--- a/test/files/scalap/classWithExistential/result.test
+++ b/test/files/scalap/classWithExistential.check
diff --git a/test/files/scalap/classWithExistential/A.scala b/test/files/scalap/classWithExistential.scala
index 4a5213f963..4a5213f963 100644
--- a/test/files/scalap/classWithExistential/A.scala
+++ b/test/files/scalap/classWithExistential.scala
diff --git a/test/files/scalap/classWithSelfAnnotation/result.test b/test/files/scalap/classWithSelfAnnotation.check
index 82bbd9e8df..82bbd9e8df 100644
--- a/test/files/scalap/classWithSelfAnnotation/result.test
+++ b/test/files/scalap/classWithSelfAnnotation.check
diff --git a/test/files/scalap/classWithSelfAnnotation/A.scala b/test/files/scalap/classWithSelfAnnotation.scala
index 9e0398622a..9e0398622a 100644
--- a/test/files/scalap/classWithSelfAnnotation/A.scala
+++ b/test/files/scalap/classWithSelfAnnotation.scala
diff --git a/test/files/scalap/covariantParam/result.test b/test/files/scalap/covariantParam.check
index f7a3c98966..f7a3c98966 100644
--- a/test/files/scalap/covariantParam/result.test
+++ b/test/files/scalap/covariantParam.check
diff --git a/test/files/scalap/covariantParam/A.scala b/test/files/scalap/covariantParam.scala
index 5b2c24d6fa..5b2c24d6fa 100644
--- a/test/files/scalap/covariantParam/A.scala
+++ b/test/files/scalap/covariantParam.scala
diff --git a/test/files/scalap/defaultParameter/result.test b/test/files/scalap/defaultParameter.check
index 0c775ea7b5..0c775ea7b5 100644
--- a/test/files/scalap/defaultParameter/result.test
+++ b/test/files/scalap/defaultParameter.check
diff --git a/test/files/scalap/defaultParameter/A.scala b/test/files/scalap/defaultParameter.scala
index d3514952f4..d3514952f4 100644
--- a/test/files/scalap/defaultParameter/A.scala
+++ b/test/files/scalap/defaultParameter.scala
diff --git a/test/files/scalap/implicitParam/result.test b/test/files/scalap/implicitParam.check
index a2cfd6092d..a2cfd6092d 100644
--- a/test/files/scalap/implicitParam/result.test
+++ b/test/files/scalap/implicitParam.check
diff --git a/test/files/scalap/implicitParam/A.scala b/test/files/scalap/implicitParam.scala
index 80657218d9..80657218d9 100644
--- a/test/files/scalap/implicitParam/A.scala
+++ b/test/files/scalap/implicitParam.scala
diff --git a/test/files/scalap/packageObject/result.test b/test/files/scalap/packageObject.check
index 5732d92958..5732d92958 100644
--- a/test/files/scalap/packageObject/result.test
+++ b/test/files/scalap/packageObject.check
diff --git a/test/files/scalap/packageObject/A.scala b/test/files/scalap/packageObject.scala
index 7e429c9935..7e429c9935 100644
--- a/test/files/scalap/packageObject/A.scala
+++ b/test/files/scalap/packageObject.scala
diff --git a/test/files/scalap/paramClauses/result.test b/test/files/scalap/paramClauses.check
index 3a141e8faf..3a141e8faf 100644
--- a/test/files/scalap/paramClauses/result.test
+++ b/test/files/scalap/paramClauses.check
diff --git a/test/files/scalap/paramClauses/A.scala b/test/files/scalap/paramClauses.scala
index f9d1917402..f9d1917402 100644
--- a/test/files/scalap/paramClauses/A.scala
+++ b/test/files/scalap/paramClauses.scala
diff --git a/test/files/scalap/paramNames/result.test b/test/files/scalap/paramNames.check
index 85e37f858d..85e37f858d 100644
--- a/test/files/scalap/paramNames/result.test
+++ b/test/files/scalap/paramNames.check
diff --git a/test/files/scalap/paramNames/A.scala b/test/files/scalap/paramNames.scala
index 7ba9ff0feb..7ba9ff0feb 100644
--- a/test/files/scalap/paramNames/A.scala
+++ b/test/files/scalap/paramNames.scala
diff --git a/test/files/scalap/sequenceParam/result.test b/test/files/scalap/sequenceParam.check
index 142d92fea3..142d92fea3 100644
--- a/test/files/scalap/sequenceParam/result.test
+++ b/test/files/scalap/sequenceParam.check
diff --git a/test/files/scalap/sequenceParam/A.scala b/test/files/scalap/sequenceParam.scala
index 86e13340b9..86e13340b9 100644
--- a/test/files/scalap/sequenceParam/A.scala
+++ b/test/files/scalap/sequenceParam.scala
diff --git a/test/files/scalap/simpleClass/result.test b/test/files/scalap/simpleClass.check
index 4fdf25d1cf..4fdf25d1cf 100644
--- a/test/files/scalap/simpleClass/result.test
+++ b/test/files/scalap/simpleClass.check
diff --git a/test/files/scalap/simpleClass/A.scala b/test/files/scalap/simpleClass.scala
index fa82e62680..fa82e62680 100644
--- a/test/files/scalap/simpleClass/A.scala
+++ b/test/files/scalap/simpleClass.scala
diff --git a/test/files/scalap/traitObject/result.test b/test/files/scalap/traitObject.check
index 104ba14f1a..104ba14f1a 100644
--- a/test/files/scalap/traitObject/result.test
+++ b/test/files/scalap/traitObject.check
diff --git a/test/files/scalap/traitObject/A.scala b/test/files/scalap/traitObject.scala
index d5f43181c1..d5f43181c1 100644
--- a/test/files/scalap/traitObject/A.scala
+++ b/test/files/scalap/traitObject.scala
diff --git a/test/files/scalap/typeAnnotations/result.test b/test/files/scalap/typeAnnotations.check
index 407b0235c6..407b0235c6 100644
--- a/test/files/scalap/typeAnnotations/result.test
+++ b/test/files/scalap/typeAnnotations.check
diff --git a/test/files/scalap/typeAnnotations/A.scala b/test/files/scalap/typeAnnotations.scala
index ff2445edc9..ff2445edc9 100644
--- a/test/files/scalap/typeAnnotations/A.scala
+++ b/test/files/scalap/typeAnnotations.scala
diff --git a/test/files/scalap/valAndVar/result.test b/test/files/scalap/valAndVar.check
index e940da9801..e940da9801 100644
--- a/test/files/scalap/valAndVar/result.test
+++ b/test/files/scalap/valAndVar.check
diff --git a/test/files/scalap/valAndVar/A.scala b/test/files/scalap/valAndVar.scala
index 2d89348401..2d89348401 100644
--- a/test/files/scalap/valAndVar/A.scala
+++ b/test/files/scalap/valAndVar.scala
diff --git a/test/files/scalap/wildcardType/result.test b/test/files/scalap/wildcardType.check
index e43261db32..e43261db32 100644
--- a/test/files/scalap/wildcardType/result.test
+++ b/test/files/scalap/wildcardType.check
diff --git a/test/files/scalap/wildcardType/A.scala b/test/files/scalap/wildcardType.scala
index 4bb0d14de5..4bb0d14de5 100644
--- a/test/files/scalap/wildcardType/A.scala
+++ b/test/files/scalap/wildcardType.scala
diff --git a/test/partest b/test/partest
index 9b0ab02fdc..8243316cca 100755
--- a/test/partest
+++ b/test/partest
@@ -1,7 +1,8 @@
-#!/bin/sh
+#!/usr/bin/env bash
+#
##############################################################################
-# Scala test runner 2.8.0
+# Scala test runner 2.10.0
##############################################################################
# (c) 2002-2013 LAMP/EPFL
#
@@ -10,6 +11,16 @@
# PARTICULAR PURPOSE.
##############################################################################
+# Use tput to detect color-capable terminal.
+term_colors=$(tput colors 2>/dev/null)
+if [[ $? == 0 ]] && [[ $term_colors -gt 2 ]]; then
+ git_diff_options="--color=always --word-diff"
+ color_opts="-Dpartest.colors=$term_colors"
+else
+ unset color_opts
+ git_diff_options="--nocolor"
+fi
+
cygwin=false;
darwin=false;
case "`uname`" in
@@ -53,8 +64,8 @@ if [ -z "$EXT_CLASSPATH" ] ; then
fi
done
elif [ -f "$SCALA_HOME/build/pack/lib/scala-partest.jar" ] ; then
- for lib in `echo "partest library reflect compiler"`; do
- ext="$SCALA_HOME/build/pack/lib/scala-$lib.jar"
+ for lib in `echo "scala-partest scala-library scala-reflect scala-compiler diffutils"`; do
+ ext="$SCALA_HOME/build/pack/lib/$lib.jar"
if [ -z "$EXT_CLASSPATH" ] ; then
EXT_CLASSPATH="$ext"
else
@@ -98,6 +109,7 @@ fi
"${JAVACMD:=java}" \
$JAVA_OPTS -cp "$EXT_CLASSPATH" \
${partestDebugStr} \
+ "$color_opts" \
-Dscala.home="${SCALA_HOME}" \
-Dpartest.javacmd="${JAVACMD}" \
-Dpartest.java_opts="${JAVA_OPTS}" \
diff --git a/test/scaladoc/run/SI-6580.check b/test/scaladoc/run/SI-6580.check
new file mode 100644
index 0000000000..2fb6ec3258
--- /dev/null
+++ b/test/scaladoc/run/SI-6580.check
@@ -0,0 +1,11 @@
+Chain(List(Chain(List(Text(Here z(1) is defined as follows:), Text(
+), HtmlTag(<br>), Text(
+), Text( ), HtmlTag(<img src='http://example.com/fig1.png'>), Text(
+), HtmlTag(<br>), Text(
+), Text(plus z(1) times), Text(
+), HtmlTag(<br>), Text(
+), Text( ), HtmlTag(<img src='http://example.com/fig2.png'>), Text(
+), HtmlTag(<br>), Text(
+), Text(equals QL of something
+)))))
+Done.
diff --git a/test/scaladoc/run/SI-6580.scala b/test/scaladoc/run/SI-6580.scala
new file mode 100644
index 0000000000..c544138f44
--- /dev/null
+++ b/test/scaladoc/run/SI-6580.scala
@@ -0,0 +1,32 @@
+import scala.tools.nsc.doc
+import scala.tools.nsc.doc.model._
+import scala.tools.nsc.doc.html.page.{Index, ReferenceIndex}
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+ override def scaladocSettings = ""
+ override def code = """
+
+ object Test {
+ /** Here z(1) is defined as follows:
+ * <br>
+ * <img src='http://example.com/fig1.png'>
+ * <br>
+ * plus z(1) times
+ * <br>
+ * <img src='http://example.com/fig2.png'>
+ * <br>
+ * equals QL of something
+ */
+ def f = 1
+ }
+
+ """
+
+ def testModel(rootPackage: Package) {
+ import access._
+
+ val f = rootPackage._object("Test")._method("f")
+ println(f.comment.get.short)
+ }
+}
diff --git a/test/scaladoc/run/SI-6715.check b/test/scaladoc/run/SI-6715.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-6715.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-6715.scala b/test/scaladoc/run/SI-6715.scala
new file mode 100644
index 0000000000..92d3376234
--- /dev/null
+++ b/test/scaladoc/run/SI-6715.scala
@@ -0,0 +1,15 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+ def scaladocSettings = ""
+
+ override def code = "object A { def $$ = 123 }"
+
+ def testModel(rootPackage: Package) = {
+ import access._
+
+ val method = rootPackage._object("A")._method("$$")
+ assert(method != null)
+ }
+}