From 72ef612ad21830cd302e7f8ba8a8fdeb2c9b214e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Mon, 12 Nov 2018 18:46:49 +0100 Subject: [PATCH 01/22] fix exception 'UnmappableCharacterException' in dottydoc on Windows --- doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala index 826445ea1636..3987039687dd 100644 --- a/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala +++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala @@ -408,7 +408,7 @@ case class Site( } private def toSourceFile(f: JFile): SourceFile = - SourceFile(AbstractFile.getFile(new File(f.toPath)), Source.fromFile(f).toArray) + SourceFile(AbstractFile.getFile(new File(f.toPath)), Source.fromFile(f, "UTF-8").toArray) private def collectFiles(dir: JFile, includes: String => Boolean): Array[JFile] = dir From 0f94c25cdafb5ed8e7329ef886cf30e7c1929c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Mon, 12 Nov 2018 19:10:04 +0100 Subject: [PATCH 02/22] add batch scripts to build Dotty distro on Windows --- bin/common.bat | 60 ++++++ bin/dotc.bat | 164 +++++++++++++++++ bin/dotd.bat | 104 +++++++++++ bin/dotr.bat | 108 +++++++++++ project/scripts/build.bat | 377 ++++++++++++++++++++++++++++++++++++++ setenv.bat | 218 ++++++++++++++++++++++ 6 files changed, 1031 insertions(+) create mode 100644 bin/common.bat create mode 100644 bin/dotc.bat create mode 100644 bin/dotd.bat create mode 100644 bin/dotr.bat create mode 100644 project/scripts/build.bat create mode 100644 setenv.bat diff --git a/bin/common.bat b/bin/common.bat new file mode 100644 index 000000000000..4c9b9c10f7ca --- /dev/null +++ b/bin/common.bat @@ -0,0 +1,60 @@ +if defined JAVACMD ( + set _JAVACMD=%JAVACMD% + if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JAVACMD +) else if defined JAVA_HOME ( + set _JAVACMD=%JAVA_HOME%\bin\java.exe + if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JAVA_HOME +) else if defined JDK_HOME ( + set _JAVACMD=%JDK_HOME%\bin\java.exe + if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JDK_HOME +) else ( + where /q java.exe + if !ERRORLEVEL!==0 ( + for /f "delims=" %%i in ('where /f java.exe') do set _JAVA_BIN_DIR=%%~dpsi + rem we ignore Oracle path for java executable + if "!_JAVA_BIN_DIR!"=="!_JAVA_BIN_DIR:javapath=!" set _JAVACMD=!_JAVA_BIN_DIR!\java.exe + ) + if not defined _JAVACMD ( + set _PATH=C:\Progra~1\Java + for /f %%f in ('dir /ad /b "!_PATH!\jre*" 2^>NUL') do set _JAVA_HOME=!_PATH!\%%f + if not defined _JAVA_HOME ( + set _PATH=C:\opt + for /f %%f in ('dir /ad /b "!_PATH!\jdk*" 2^>NUL') do set _JAVA_HOME=!_PATH!\%%f\jre + ) + if defined _JAVA_HOME ( + if %_DEBUG%==1 echo [%_BASENAME%] Using default Java installation directory !_JAVA_HOME! + set _JAVACMD=!_JAVA_HOME!\bin\java.exe + ) + ) +) +if not exist "%_JAVACMD%" ( + if %_DEBUG%==1 echo [%_BASENAME%] Error: Java executable not found ^(%_JAVACMD%^) + set _EXITCODE=1 + goto :eof +) + +if defined DOTTY_HOME ( + set _LIB_DIR=%DOTTY_HOME%\lib +) else ( + if not defined _PROG_HOME ( + for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf + ) + set _LIB_DIR=!_PROG_HOME!\lib +) + +set _PSEP=; + +for /f %%f in ('dir /b "%_LIB_DIR%\*dotty-compiler*"') do set _DOTTY_COMP=%_LIB_DIR%\%%f +for /f %%f in ('dir /b "%_LIB_DIR%\*dotty-interfaces*"') do set _DOTTY_INTF=%_LIB_DIR%\%%f +for /f %%f in ('dir /b "%_LIB_DIR%\*dotty-library*"') do set _DOTTY_LIB=%_LIB_DIR%\%%f +for /f %%f in ('dir /b "%_LIB_DIR%\*scala-asm*"') do set _SCALA_ASM=%_LIB_DIR%\%%f +for /f %%f in ('dir /b "%_LIB_DIR%\*scala-library*"') do set _SCALA_LIB=%_LIB_DIR%\%%f +for /f %%f in ('dir /b "%_LIB_DIR%\*scala-xml*"') do set _SCALA_XML=%_LIB_DIR%\%%f +for /f %%f in ('dir /b "%_LIB_DIR%\*compiler-interface*"') do set _SBT_INTF=%_LIB_DIR%\%%f +for /f %%f in ('dir /b "%_LIB_DIR%\*jline-reader-3*"') do set _JLINE_READER=%_LIB_DIR%\%%f +for /f %%f in ('dir /b "%_LIB_DIR%\*jline-terminal-3*"') do set _JLINE_TERMINAL=%_LIB_DIR%\%%f +for /f %%f in ('dir /b "%_LIB_DIR%\*jline-terminal-jna-3*"') do set _JLINE_TERMINAL_JNA=%_LIB_DIR%\%%f +for /f %%f in ('dir /b "%_LIB_DIR%\*jna-4*"') do set _JNA=%_LIB_DIR%\%%f + +rem debug +set _DEBUG_STR=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 diff --git a/bin/dotc.bat b/bin/dotc.bat new file mode 100644 index 000000000000..83066abf861d --- /dev/null +++ b/bin/dotc.bat @@ -0,0 +1,164 @@ +@echo off +setlocal enabledelayedexpansion + +rem only for interactive debugging ! +set _DEBUG=0 + +rem ########################################################################## +rem ## Environment setup + +set _EXITCODE=0 + +set _BASENAME=%~n0 + +for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf + +call %_PROG_HOME%\bin\common.bat +if not %_EXITCODE%==0 goto end + +set _COMPILER_MAIN=dotty.tools.dotc.Main +set _DECOMPILER_MAIN=dotty.tools.dotc.decompiler.Main +set _REPL_MAIN=dotty.tools.repl.Main + +set _PROG_NAME=%_COMPILER_MAIN% + +call :args %* + +rem ########################################################################## +rem ## Main + +call :classpathArgs + +if defined JAVA_OPTS ( set _JAVA_OPTS=%JAVA_OPTS% +) else ( set _JAVA_OPTS=-Xmx768m -Xms768m +) +if %_DEBUG%==1 echo [%_BASENAME%] "%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% %_JVM_CP_ARGS% -Dscala.usejavacp=true %_PROG_NAME% %_SCALA_ARGS% %_RESIDUAL_ARGS% +"%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% %_JVM_CP_ARGS% ^ +-Dscala.usejavacp=true ^ +%_PROG_NAME% %_SCALA_ARGS% %_RESIDUAL_ARGS% +if not %ERRORLEVEL%==0 ( + if %_DEBUG%==1 echo [%_BASENAME%] Dotty compiler execution failed + set _EXITCODE=1 + goto end +) +goto end + +rem ########################################################################## +rem ## Subroutines + +:args +set _JAVA_DEBUG= +set _HELP= +set _VERBOSE= +set _QUIET= +set _COLORS= +set _SCALA_ARGS= +set _JAVA_ARGS= +set _RESIDUAL_ARGS= +:args_loop +if "%~1"=="" goto args_done +set _ARG=%~1 +if %_DEBUG%==1 echo [%_BASENAME%] _ARG=%_ARG% +if "%_ARG%"=="--" ( + rem for arg; do addResidual "$arg"; done; set -- ;; +) else if /i "%_ARG%"=="-h" ( + set _HELP=true + call :addScala "-help" +) else if /i "%_ARG%"=="-help" ( + set _HELP=true + call :addScala "-help" +) else if /i "%_ARG%"=="-v" ( + set _VERBOSE=true + call :addScala "-verbose" +) else if /i "%_ARG%"=="-verbose" ( + set _VERBOSE=true + call :addScala "-verbose" +) else if /i "%_ARG%"=="-debug" ( set _JAVA_DEBUG=%_DEBUG_STR% +) else if /i "%_ARG%"=="-q" ( set _QUIET=true +) else if /i "%_ARG%"=="-quiet" ( set _QUIET=true +rem Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 +) else if "%_ARG%"=="-=short" ( + call :addJava "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" +) else if /i "%_ARG%"=="-repl" ( set _PROG_NAME=%_REPL_MAIN% +) else if /i "%_ARG%"=="-compile" ( set _PROG_NAME=%_COMPILER_MAIN% +) else if /i "%_ARG%"=="-decompile" ( set _PROG_NAME=%_DECOMPILER_MAIN% +) else if /i "%_ARG%"=="print-tasty" ( + set _PROG_NAME=%_DECOMPILER_MAIN% + call :addScala "-print-tasty" +) else if /i "%_ARG%"=="-run" ( set _PROG_NAME=%_REPL_MAIN% +) else if /i "%_ARG%"=="-colors" ( set _COLORS=true +) else if /i "%_ARG%"=="-no-colors" ( set _COLORS= +) else if /i "%_ARG%"=="-with-compiler" ( set _JVM_CP_ARGS=%_PSEP%%_DOTTY_COMP% +rem break out -D and -J options and add them to JAVA_OPTS as well +rem so they reach the JVM in time to do some good. The -D options +rem will be available as system properties. +) else if "%_ARG:~0,2%"=="-D" ( + call :addJava "%_ARG%" + call :addScala "%_ARG%" +) else if "%_ARG:~0,2%"=="-J" ( + call :addJava "%_ARG%" + call :addScala "%_ARG%" +) else ( + call :addResidual "%_ARG%" +) +shift +goto args_loop +:args_done +if %_DEBUG%==1 ( + echo [%_BASENAME%] _VERBOSE=%_VERBOSE% + echo [%_BASENAME%] _PROG_NAME=%_PROG_NAME% +) +goto :eof + +rem output parameter: _SCALA_ARGS +:addScala +set _SCALA_ARGS=%_SCALA_ARGS% %~1 +if %_DEBUG%==1 echo [%_BASENAME%] _SCALA_ARGS=%_SCALA_ARGS% +goto :eof + +rem output parameter: _JAVA_ARGS +:addJava +set _JAVA_ARGS=%_JAVA_ARGS% %~1 +if %_DEBUG%==1 echo [%_BASENAME%] _JAVA_ARGS=%_JAVA_ARGS% +goto :eof + +rem output parameter: _RESIDUAL_ARGS +:addResidual +set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %~1 +if %_DEBUG%==1 echo [%_BASENAME%] _RESIDUAL_ARGS=%_RESIDUAL_ARGS% +goto :eof + +rem output parameter: _JVM_CP_ARGS +:classpathArgs +rem echo dotty-compiler: %_DOTTY_COMP% +rem echo dotty-interface: %_DOTTY_INTF% +rem echo dotty-library: %_DOTTY_LIB% +rem echo scala-asm: %_SCALA_ASM% +rem echo scala-lib: %_SCALA_LIB% +rem echo scala-xml: %_SCALA_XML% +rem echo sbt-intface: %_SBT_INTF% + +set __TOOLCHAIN=%_SCALA_LIB%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_SCALA_ASM%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_SBT_INTF%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_INTF%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_LIB%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_COMP%%_PSEP% + +rem # jline +set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_READER%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_TERMINAL%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_TERMINAL_JNA%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_JNA% + +set _JVM_CP_ARGS=-classpath %__TOOLCHAIN% +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% +exit /b %_EXITCODE% +endlocal + diff --git a/bin/dotd.bat b/bin/dotd.bat new file mode 100644 index 000000000000..860085fe4f72 --- /dev/null +++ b/bin/dotd.bat @@ -0,0 +1,104 @@ +@echo off +setlocal enabledelayedexpansion + +rem only for interactive debugging ! +set _DEBUG=0 + +rem ########################################################################## +rem ## Environment setup + +set _EXITCODE=0 + +set _BASENAME=%~n0 + +for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf + +call "%_PROG_HOME%\bin\common.bat" +if not %_EXITCODE%==0 goto end + +rem ########################################################################## +rem ## Main + +call :javaClassPath + +if %_DEBUG%==1 echo [%_BASENAME%] "%_JAVACMD%" -Dscala.usejavacp=true -classpath "%_CLASS_PATH%" dotty.tools.dottydoc.Main %* +"%_JAVACMD%" -Dscala.usejavacp=true -classpath "%_CLASS_PATH%" dotty.tools.dottydoc.Main %* +if not %ERRORLEVEL%==0 ( + if %_DEBUG%==1 echo [%_BASENAME%] Dottydoc execution failed + set _EXITCODE=1 + goto end +) +goto end + +rem ########################################################################## +rem ## Subroutines + +rem output parameter: _CLASS_PATH +:javaClassPath +set _LIB_DIR=%_PROG_HOME%\lib + +rem Set dotty-doc dep: +for /f %%f in ('dir /b "%_LIB_DIR%\*dotty-doc*"') do set _DOTTY_DOC_LIB=%_LIB_DIR%\%%f + +rem Set flexmark deps: +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-0*"') do set _FLEXMARK_LIBS=%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-anchorlink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-autolink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-emoji*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-gfm-strikethrough*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-gfm-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-gfm-tasklist*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-ins*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-superscript*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-wikilink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-yaml-front-matter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-formatter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-jira-converter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-util*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% + +rem Set jackson deps: +for /f %%f in ('dir /b "%_LIB_DIR%\*jackson-annotations*"') do set _JACKSON_LIBS=%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*jackson-core*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*jackson-databind*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*jackson-dataformat-yaml*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%_LIB_DIR%\%%f%_PSEP% + +rem Set liqp dep: +for /f %%f in ('dir /b "%_LIB_DIR%\*liqp*"') do set _LIQP_LIB=%_LIB_DIR%\%%f%_PSEP% + +rem Set ANTLR dep: +for /f %%f in ('dir /b "%_LIB_DIR%\*antlr-3*"') do set _ANTLR_LIB=%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /b "%_LIB_DIR%\*antlr-runtime-3*"') do set _ANTLR_RUNTIME_LIB=%_LIB_DIR%\%%f%_PSEP% + +rem Set autolink dep: +rem conflict with flexmark-ext-autolink-0.11 +for /f %%f in ('dir /b "%_LIB_DIR%\*autolink-0.6*"') do set _AUTOLINK_LIB=%_LIB_DIR%\%%f + +rem Set snakeyaml dep: +for /f %%f in ('dir /b "%_LIB_DIR%\*snakeyaml*"') do set _SNAKEYAML_LIB=%_LIB_DIR%\%%f%_PSEP% + +rem Set ST4 dep: +for /f %%f in ('dir /b "%_LIB_DIR%\*ST4*"') do set _ST4_LIB=%_LIB_DIR%\%%f%_PSEP% + +rem Set jsoup dep: +for /f %%f in ('dir /b "%_LIB_DIR%\*jsoup*"') do set _JSOUP_LIB=%_LIB_DIR%\%%f%_PSEP% + +set _CLASS_PATH=%_DOTTY_LIB%%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_DOC_LIB%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SBT_INTF% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_SCALA_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_FLEXMARK_LIBS% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_JACKSON_LIBS% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_LIQP_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_ANTLR_LIB%%_PSEP%%_ANTLR_RUNTIME_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_AUTOLINK_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_SNAKEYAML_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_ST4_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_JSOUP_LIB% +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% +exit /b %_EXITCODE% +endlocal diff --git a/bin/dotr.bat b/bin/dotr.bat new file mode 100644 index 000000000000..17d3438d87a3 --- /dev/null +++ b/bin/dotr.bat @@ -0,0 +1,108 @@ +@echo off +setlocal enabledelayedexpansion + +rem only for interactive debugging ! +set _DEBUG=0 + +rem ########################################################################## +rem ## Environment setup + +set _EXITCODE=0 + +set _BASENAME=%~n0 + +for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf + +call %_PROG_HOME%\bin\common.bat +if not %_EXITCODE%==0 goto end + +call :args %* + +rem ########################################################################## +rem ## Main + +set _CASE_1=0 +if %_EXECUTE_REPL%==1 set _CASE_1=1 +if %_EXECUTE_RUN%==0 if not defined _RESIDUAL_ARGS set _CASE_1=1 + +set _CASE_2=0 +if %_EXECUTE_RUN%==1 set _CASE_2=1 +if defined _RESIDUAL_ARGS set _CASE_2=1 + +rem if [ $execute_repl == true ] || ([ $execute_run == false ] && [ $options_indicator == 0 ]); then +if %_CASE_1%==1 ( + set _DOTC_ARGS= + if defined _CLASS_PATH set _DOTC_ARGS=-classpath "%_CLASS_PATH%" + set _DOTC_ARGS=!_DOTC_ARGS! %_JAVA_OPTIONS% -repl %_RESIDUAL_ARGS% + echo Starting dotty REPL... + if %_DEBUG%==1 echo [%_BASENAME%] %_PROG_HOME%\bin\dotc.bat !_DOTC_ARGS! + %_PROG_HOME%\bin\dotc.bat !_DOTC_ARGS! +rem elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then +) else if %_CASE_2%==1 ( + set _CP_ARG=%_DOTTY_LIB%%_PSEP%%_SCALA_LIB% + if defined _CLASS_PATH ( set _CP_ARG=!_CP_ARG!%_PSEP%%_CLASS_PATH% + ) else ( set _CP_ARG=!_CP_ARG!%_PSEP%. + ) + if %_CLASS_PATH_COUNT% gtr 1 ( + echo warning: multiple classpaths are found, dotr only use the last one. + ) + if %_WITH_COMPILER%==1 ( + set _CP_ARG=!_CP_ARG!%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SCALA_ASM% + ) + set _JAVA_ARGS=%_JAVA_DEBUG% -classpath "!_CP_ARG!" %_RESIDUAL_ARGS% + if %_DEBUG%==1 echo [%_BASENAME%] %_JAVACMD% !_JAVA_ARGS! + %_JAVACMD% !_JAVA_ARGS! +) else ( + echo warning: command option is not correct. +) + +goto end + +rem ########################################################################## +rem ## Subroutines + +:args +set _RESIDUAL_ARGS= +set _EXECUTE_REPL=0 +set _EXECUTE_RUN=0 +set _WITH_COMPILER=0 +set _JAVA_DEBUG= +set _CLASS_PATH_COUNT=0 +set _CLASS_PATH= +set _JVM_OPTIONS= +set _JAVA_OPTIONS= + +:args_loop +if "%1"=="" goto args_done +set "_ARG=%1" +if %_DEBUG%==1 echo [%_BASENAME%] _ARG=%_ARG% +if /i "%_ARG%"=="-repl" ( + set _EXECUTE_REPL=1 +) else if /i "%_ARG%"=="-run" ( + set _EXECUTE_RUN=1 +) else if /i "%_ARG%"=="-classpath" ( + set _CLASS_PATH=%2 + set /a _CLASS_PATH_COUNT+=1 + shift +) else if /i "%_ARG%"=="-with-compiler" ( + set _WITH_COMPILER=1 +) else if /i "%_ARG%"=="-d" ( + set _JAVA_DEBUG=%_DEBUG_STR% +) else if /i "%_ARG:~0,2%"=="-J" ( + set _JVM_OPTIONS=!_JVM_OPTIONS! %_ARG% + set _JAVA_OPTIONS=!_JAVA_OPTIONS! %_ARG% +) else ( + set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %_ARG% +) +shift +goto args_loop +:args_done +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% +exit /b %_EXITCODE% +endlocal diff --git a/project/scripts/build.bat b/project/scripts/build.bat new file mode 100644 index 000000000000..5d5ba7660f55 --- /dev/null +++ b/project/scripts/build.bat @@ -0,0 +1,377 @@ +@echo off +setlocal enabledelayedexpansion + +rem only for interactive debugging +set _DEBUG=1 + +rem ########################################################################## +rem ## Environment setup + +set _BASENAME=%~n0 + +set _EXITCODE=0 + +set _BOT_TOKEN=dotty-token + +rem set _DRONE_BUILD_EVENT=pull_request +set _DRONE_BUILD_EVENT= +set _DRONE_REMOTE_URL= +set _DRONE_BRANCH= + +for %%f in ("%~dp0..\..") do set _ROOT_DIR=%%~sf +set _BIN_DIR=%_ROOT_DIR%bin +set _TESTS_POS_DIR=%_ROOT_DIR%test\pos + +set _SOURCE=tests/pos/HelloWorld.scala +set _MAIN=HelloWorld +set _EXPECTED_OUTPUT=hello world + +call :args %* +if not %_EXITCODE%==0 ( goto end +) else if defined _HELP ( goto end +) + +set _OUT_DIR=%TEMP%\%_BASENAME%_out +if not exist "%_OUT_DIR%" mkdir "%_OUT_DIR%" + +set _OUT1_DIR=%TEMP%\%_BASENAME%_out1 +if not exist "%_OUT1_DIR%" mkdir "%_OUT1_DIR%" + +set _TMP_FILE=%TEMP%\%_BASENAME%_tmp.txt + +where /q git.exe +if not %ERRORLEVEL%==0 ( + echo Error: Git command not found ^(run setenv.bat^) 1>&2 + set _EXITCODE=1 + goto end +) +set _GIT_CMD=git.exe + +where /q sbt.bat +if not %ERRORLEVEL%==0 ( + echo Error: SBT command not found ^(run setenv.bat^) 1>&2 + set _EXITCODE=1 + goto end +) +rem full path of SBT command is required +for /f %%i in ('where sbt.bat') do set _SBT_CMD=%%i + +rem see file project/scripts/sbt +rem SBT uses the value of the JAVA_OPTS environment variable if defined, rather than the config. +set JAVA_OPTS=-Xmx4096m ^ +-XX:ReservedCodeCacheSize=1024m ^ +-XX:MaxMetaspaceSize=1024m + +set SBT_OPTS=-Ddotty.drone.mem=4096m ^ +-Dsbt.ivy.home=%USERPROFILE%\.ivy2\ ^ +-Dsbt.log.noformat=true + +rem ########################################################################## +rem ## Main + +if defined _CLEAN ( + if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" clean + call "%_SBT_CMD%" clean + goto end +) + +call :clone +if not %_EXITCODE%==0 goto end + +call :test +if not %_EXITCODE%==0 goto end + +if defined _BOOTSTRAP ( + call :test_bootstrapped + rem if not !_EXITCODE!==0 goto end + if not !_EXITCODE!==0 echo ###### Warning: _EXITCODE=!_EXITCODE! ####### 1>&2 +) +if defined _DOCUMENTATION ( + call :documentation + if not !_EXITCODE!==0 goto end +) +if defined _ARCHIVES ( + call :archives + if not !_EXITCODE!==0 goto end +) +goto end + +rem ########################################################################## +rem ## Subroutines + +rem input parameter: %* +rem output parameters: _VERBOSE, _DOCUMENTATION +:args +set _VERBOSE=0 +set _ARCHIVES= +set _BOOTSTRAP= +set _CLEAN= +set _DOCUMENTATION= +set __N=0 +:args_loop +set __ARG=%~1 +if not defined __ARG ( + goto args_done +) else if not "%__ARG:~0,1%"=="-" ( + set /a __N=+1 +) +if /i "%__ARG%"=="help" ( call :help & goto :eof +) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 +) else if /i "%__ARG:~0,4%"=="arch" ( set _ARCHIVES=1 +) else if /i "%__ARG:~0,4%"=="boot" ( set _BOOTSTRAP=1 +) else if /i "%__ARG%"=="clean" ( set _CLEAN=1 +) else if /i "%__ARG:~0,3%"=="doc" ( set _DOCUMENTATION=1 +) else ( + echo %_BASENAME%: Unknown subcommand %__ARG% + set _EXITCODE=1 + goto :eof +) +shift +goto :args_loop +:args_done +goto :eof + +:help +set _HELP=1 +echo Usage: setenv { options ^| subcommands } +echo Options: +echo -verbose display environment settings +echo Subcommands: +echo arch[ives] generate gz/zip archives +echo boot[strap] generate compiler bootstrap +echo clean clean project and leave +echo doc[umentation] generate documentation +echo help display this help message +goto :eof + +:clone +if "%_DRONE_BUILD_EVENT%"=="pull_request" if defined _DRONE_REMOTE_URL ( + %_GIT_CMD% config user.email "dotty.bot@epfl.ch" + %_GIT_CMD% config user.name "Dotty CI" + %_GIT_CMD% pull "%_DRONE_REMOTE_URL%" "%_DRONE_BRANCH%" +) +if %_DEBUG%==1 echo [%_BASENAME%] %_GIT_CMD% submodule update --init --recursive --jobs 3 +%_GIT_CMD% submodule update --init --recursive --jobs 3 +if not %ERRORLEVEL%==0 ( + echo Error: Failed to update Git submodules 1>&2 + set _EXITCODE=1 + goto :eof +) +goto :eof + +:clear_out +set __OUT_DIR=%~1 + +if exist "%__OUT_DIR%" ( + if %_DEBUG%==1 echo [%_BASENAME%] del /s /q "%__OUT_DIR%\*" 1^>NUL + del /s /q "%__OUT_DIR%\*" 1>NUL +) +goto :eof + +:grep +set __PATTERN=%~1 +set __FILE=%~2 + +findstr "%__PATTERN%" "%__FILE%" +if not %ERRORLEVEL%==0 ( + echo Error: Failed to find pattern "%__PATTERN%" in file %__FILE% 1>&2 + set _EXITCODE=1 + goto :eof +) +goto :eof + +rem ## see file project/scripts/cmdTests +:cmdTests +echo testing sbt dotc and dotr +if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotr -classpath %_OUT_DIR% %_MAIN%" ^> "%_TMP_FILE%" +call "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotr -classpath %_OUT_DIR% %_MAIN%" > "%_TMP_FILE%" +call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +rem # check that `sbt dotc` compiles and `sbt dotr` runs it +echo testing sbt dotc -from-tasty and dotr -classpath +call :clear_out "%_OUT_DIR%" +call "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotc -from-tasty -classpath %_OUT_DIR% -d %_OUT1_DIR% %_MAIN% ;dotr -classpath %_OUT1_DIR% %_MAIN%" > "%_TMP_FILE%" +call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +rem # check that `sbt dotc -decompile` runs +echo testing sbt dotc -decompile +call "%_SBT_CMD%" ";dotc -decompile -color:never -classpath %_OUT_DIR% %_MAIN%" > "%_TMP_FILE%" +call :grep "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +echo testing sbt dotr with no -classpath +call :clear_out "%_OUT_DIR%" +if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" ";dotc %_SOURCE% ; dotr %_MAIN%" ^> "%_TMP_FILE%" +call "%_SBT_CMD%" ";dotc %_SOURCE% ; dotr %_MAIN%" > "%_TMP_FILE%" +call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +echo testing loading tasty from .tasty file in jar +call :clear_out "%_OUT_DIR%" +call "%_SBT_CMD%" ";dotc -d %_OUT_DIR%\out.jar %_SOURCE%; dotc -decompile -classpath %_OUT_DIR%/out.jar -color:never %_MAIN%" > "%_TMP_FILE%" +call :grep "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +goto :eof + +:test +if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";clean ;compile ;test" +call "%_SBT_CMD%" ";clean ;compile ;test" +if not %ERRORLEVEL%==0 ( + echo Error: Failed to build Dotty 1>&2 + set _EXITCODE=1 + goto :eof +) + +rem ## see shell script project/scripts/cmdTests +call :cmdTests +if not %_EXITCODE%==0 goto :eof + +goto :eof + +:test_pattern +set __PATTERN=%~1 +set __FILE=%~2 + +set /p __PATTERN2=<"%__FILE%" +if not "%__PATTERN2%"=="%__PATTERN%" ( + echo Error: failed to find pattern "%__PATTERN%" in file %__FILE% 1>&2 + set _EXITCODE=1 + goto :eof +) +goto :eof + +rem ## see shell script project/scripts/bootstrapCmdTests +:bootstrapCmdTests +rem # check that benchmarks can run +if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" +call "%_SBT_CMD%" "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" + +rem # The above is here as it relies on the bootstrapped library. +call "%_SBT_CMD%" "dotty-bench-bootstrapped/jmh:run 1 1 tests/pos/alias.scala" +call "%_SBT_CMD%" "dotty-bench-bootstrapped/jmh:run 1 1 -with-compiler compiler/src/dotty/tools/dotc/core/Types.scala" + +echo testing scala.quoted.Expr.run from sbt dotr +call "%_SBT_CMD%" ";dotty-compiler-bootstrapped/dotc tests/run-with-compiler/quote-run.scala; dotty-compiler-bootstrapped/dotr -with-compiler Test" > "%_TMP_FILE%" +call :grep "val a: scala.Int = 3" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +rem # setup for `dotc`/`dotr` script tests +if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" dist-bootstrapped/pack +call "%_SBT_CMD%" dist-bootstrapped/pack + +rem # check that `dotc` compiles and `dotr` runs it +echo testing ./bin/dotc and ./bin/dotr +call :clear_out "%_OUT_DIR%" +call %_BIN_DIR%\dotc "%_SOURCE%" -d "%_OUT_DIR%" +call %_BIN_DIR%\dotr -classpath "%_OUT_DIR%" "%_MAIN%" > "%_TMP_FILE%" +call :test_pattern "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" + +rem # check that `dotc -from-tasty` compiles and `dotr` runs it +echo testing ./bin/dotc -from-tasty and dotr -classpath +call :clear_out "%_OUT1_DIR%" +call %_BIN_DIR%\dotc -from-tasty -classpath "%_OUT_DIR%" -d "%_OUT1_DIR%" "%_MAIN%" +call %_BIN_DIR%\dotr -classpath "%_OUT1_DIR%" "%_MAIN%" > "%_TMP_FILE%" +call :test_pattern "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" + +rem # echo ":quit" | ./dist-bootstrapped/target/pack/bin/dotr # not supported by CI + +echo testing ./bin/dotd +call :clear_out "%_OUT_DIR%" +call %_BIN_DIR%\dotd -project Hello -siteroot "%_OUT_DIR%" "%_SOURCE%" + +goto :eof + +:test_bootstrapped +if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" +call "%_SBT_CMD%" ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" +if not %ERRORLEVEL%==0 ( + echo Error: failed to bootstrap Dotty 1>&2 + set _EXITCODE=1 + goto :eof +) + +call :bootstrapCmdTests +if not %_EXITCODE%==0 goto :eof + +goto :eof + +:documentation +rem # make sure that _BOT_TOKEN is set +if not defined _BOT_TOKEN ( + echo Error: _BOT_TOKEN env unset, unable to push without password 1>&2 + set _EXITCODE=1 + goto :eof +) +for /f %%i in ('cd') do set _PWD=%%~si + +echo Working directory: %_PWD% + +call "%_SBT_CMD%" genDocs + +rem # make sure that the previous command actually succeeded +if not exist "%_PWD%\docs\_site\" ( + echo Error: output directory did not exist: %_PWD%\docs\_site 1>&2 + set _EXITCODE=1 + goto :eof +) + +goto :eof + +rem # save current head for commit message in gh-pages +rem for /f %%i in ('%_GIT_CMD% rev-parse HEAD 2^>NUL') do set _GIT_HEAD=%%i + +rem # set up remote and github credentials +rem %_GIT_CMD% remote add doc-remote "https://dotty-bot:%_BOT_TOKEN%@github.com/lampepfl/dotty-website.git" +rem %_GIT_CMD% config user.name "dotty-bot" +rem %_GIT_CMD% config user.email "dotty-bot@d-d.me" + +rem # check out correct branch +rem %_GIT_CMD% fetch doc-remote gh-pages +rem %_GIT_CMD% checkout gh-pages + +rem # move newly generated _site dir to $PWD +rem move %_PWD%\docs\_site . + +rem # remove everything BUT _site dir +rem del /f /q /s -rf !(_site) + +rem # copy new contents to $PWD +rem move _site\* . + +rem # remove now empty _site dir +rem del /f /q /s _site + +rem # add all contents of $PWD to commit +rem %_GIT_CMD% add -A +rem %_GIT_CMD% commit -m "Update gh-pages site for %_GIT_HEAD%" || echo "nothing new to commit" + +rem # push to doc-remote +rem %_GIT_CMD% push doc-remote || echo "couldn't push, since nothing was added" + +goto :eof + +:archives +if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" dist-bootstrapped/packArchive +call "%_SBT_CMD%" dist-bootstrapped/packArchive +rem output directory for gz/zip archives +set __TARGET_DIR=%_ROOT_DIR%\dist-bootstrapped\target +if not exist "%__TARGET_DIR%\" ( + echo Error: Directory target not found 1>&2 + set _EXITCODE=1 + goto :eof +) +if %_DEBUG%==1 ( + echo Output directory: %__TARGET_DIR%\ + dir /b /a-d "%__TARGET_DIR%" +) +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% +exit /b %_EXITCODE% diff --git a/setenv.bat b/setenv.bat new file mode 100644 index 000000000000..5651dc492512 --- /dev/null +++ b/setenv.bat @@ -0,0 +1,218 @@ +@echo off +setlocal enabledelayedexpansion + +rem only for interactive debugging +set _DEBUG=0 + +rem ########################################################################## +rem ## Environment setup + +set _BASENAME=%~n0 + +set _EXITCODE=0 + +call :args %* +if not %_EXITCODE%==0 goto end + +rem ########################################################################## +rem ## Main + +set _JDK_PATH= +set _SBT_PATH= +set _GIT_PATH= + +call :javac +if not %_EXITCODE%==0 goto end + +call :sbt +if not %_EXITCODE%==0 goto end + +call :git +if not %_EXITCODE%==0 goto end + +if "%~1"=="clean" call :clean + +goto end + +rem ########################################################################## +rem ## Subroutines + +rem input parameter: %* +:args +set _VERBOSE=0 +set __N=0 +:args_loop +set __ARG=%~1 +if not defined __ARG ( + goto args_done +) else if not "%__ARG:~0,1%"=="-" ( + set /a __N=!__N!+1 +) +if /i "%__ARG%"=="help" ( call :help & goto :eof +) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 +) else ( + echo %_BASENAME%: Unknown subcommand %__ARG% + set _EXITCODE=1 + goto :eof +) +shift +goto :args_loop +:args_done +goto :eof + +:help +echo Usage: setenv { options ^| subcommands } +echo Options: +echo -verbose display environment settings +echo Subcommands: +echo help display this help message +goto :eof + +:javac +where /q javac.exe +if %ERRORLEVEL%==0 goto :eof + +if defined JDK_HOME ( + set _JDK_HOME=%JDK_HOME% + if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JDK_HOME +) else ( + set _PATH=C:\Progra~1\Java + for /f "delims=" %%f in ('dir /ad /b "!_PATH!\jdk1.8*" 2^>NUL') do set _JDK_HOME=!_PATH!\%%f + if not defined _JDK_HOME ( + set _PATH=C:\opt + for /f %%f in ('dir /ad /b "!_PATH!\jdk1.8*" 2^>NUL') do set _JDK_HOME=!_PATH!\%%f + ) + if defined _JDK_HOME ( + if %_DEBUG%==1 echo [%_BASENAME%] Using default Java SDK installation directory !_JDK_HOME! + ) +) +if not exist "%_JDK_HOME%\bin\javac.exe" ( + if %_DEBUG%==1 echo [%_BASENAME%] javac executable not found ^(%_JDK_HOME%^) + set _EXITCODE=1 + goto :eof +) +rem variable _JDK_PATH is prepended to PATH, so path separator must appear as last character +set "_JDK_PATH=%_JDK_HOME%\bin;" +goto :eof + +:sbt +where /q sbt.bat +if %ERRORLEVEL%==0 goto :eof + +if defined SBT_HOME ( + set _SBT_HOME=%SBT_HOME% + if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable SBT_HOME +) else ( + set _PATH=C:\opt + for /f %%f in ('dir /ad /b "!_PATH!\sbt-1*" 2^>NUL') do set _SBT_HOME=!_PATH!\%%f + if defined _SBT_HOME ( + if %_DEBUG%==1 echo [%_BASENAME%] Using default sbt installation directory !_SBT_HOME! + ) +) +if not exist "%_SBT_HOME%\bin\sbt.bat" ( + if %_DEBUG%==1 echo [%_BASENAME%] sbt executable not found ^(%_SBT_HOME%^) + set _EXITCODE=1 + goto :eof +) +set "_SBT_PATH=;%_SBT_HOME%\bin" +goto :eof + +:git +where /q git.exe +if %ERRORLEVEL%==0 goto :eof + +if defined GIT_HOME ( + set _GIT_HOME=%GIT_HOME% + if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable GIT_HOME +) else ( + set __PATH=C:\opt + if exist "!__PATH!\Git\" ( set _GIT_HOME=!__PATH!\Git + ) else ( + for /f %%f in ('dir /ad /b "!__PATH!\Git*" 2^>NUL') do set _GIT_HOME=!__PATH!\%%f + if not defined _GIT_HOME ( + set __PATH=C:\Progra~1 + for /f %%f in ('dir /ad /b "!__PATH!\Git*" 2^>NUL') do set _GIT_HOME=!__PATH!\%%f + ) + ) + if defined _GIT_HOME ( + if %_DEBUG%==1 echo [%_BASENAME%] Using default Git installation directory !_GIT_HOME! + ) +) +if not exist "%_GIT_HOME%\bin\git.exe" ( + echo Git executable not found ^(%_GIT_HOME%^) + set _EXITCODE=1 + goto :eof +) +set "_GIT_PATH=;%_GIT_HOME%\bin;%_GIT_HOME%\usr\bin" +goto :eof + +:clean +for %%f in ("%~dp0") do set __ROOT_DIR=%%~sf +for /f %%i in ('dir /ad /b "%__ROOT_DIR%\" 2^>NUL') do ( + for /f %%j in ('dir /ad /b "%%i\target\scala-*" 2^>NUL') do ( + if %_DEBUG%==1 echo [%_BASENAME%] rmdir /s /q %__ROOT_DIR%%%i\target\%%j\classes 1^>NUL 2^>^&1 + rmdir /s /q %__ROOT_DIR%%%i\target\%%j\classes 1>NUL 2>&1 + ) +) +goto :eof + +rem output parameter: _SBT_VERSION +rem Note: SBT requires special handling to know its version (no comment) +:sbt_version +set _SBT_VERSION= +for /f %%i in ('where sbt.bat') do for %%f in ("%%~dpi..") do set __SBT_LAUNCHER=%%~sf\bin\sbt-launch.jar +for /f "tokens=1,*" %%i in ('java.exe -jar "%__SBT_LAUNCHER%" sbtVersion ^| findstr [0-9].[0-9]') do set _SBT_VERSION=%%j +for /f "tokens=1,*" %%i in ('java.exe -jar "%__SBT_LAUNCHER%" scalaVersion ^| findstr [0-9].[0-9]') do set _SBT_VERSION=%_SBT_VERSION%/%%j +goto :eof + +:print_env +set __VERBOSE=%1 +set __VERSIONS_LINE1= +set __VERSIONS_LINE2= +set __WHERE_ARGS= +where /q javac.exe +if %ERRORLEVEL%==0 ( + for /f "tokens=1,2,*" %%i in ('javac.exe -version 2^>^&1') do set "__VERSIONS_LINE1=%__VERSIONS_LINE1% javac %%j," + set __WHERE_ARGS=%__WHERE_ARGS% javac.exe +) +where /q java.exe +if %ERRORLEVEL%==0 ( + for /f "tokens=1,2,3,*" %%i in ('java.exe -version 2^>^&1 ^| findstr version 2^>^&1') do set "__VERSIONS_LINE1=%__VERSIONS_LINE1% java %%~k," + set __WHERE_ARGS=%__WHERE_ARGS% java.exe +) +call :sbt_version +if defined _SBT_VERSION ( + set __VERSIONS_LINE2=%__VERSIONS_LINE2% sbt %_SBT_VERSION%, + set __WHERE_ARGS=%__WHERE_ARGS% sbt.bat +) +where /q git.exe +if %ERRORLEVEL%==0 ( + for /f "tokens=1,2,*" %%i in ('git.exe --version') do set __VERSIONS_LINE2=%__VERSIONS_LINE2% git %%k, + set __WHERE_ARGS=%__WHERE_ARGS% git.exe +) +where /q diff.exe +if %ERRORLEVEL%==0 ( + for /f "tokens=1-3,*" %%i in ('diff.exe --version ^| findstr diff') do set __VERSIONS_LINE2=%__VERSIONS_LINE2% diff %%l + set __WHERE_ARGS=%__WHERE_ARGS% diff.exe +) +echo Tool versions: +echo %__VERSIONS_LINE1% +echo %__VERSIONS_LINE2% +if %__VERBOSE%==1 ( + rem if %_DEBUG%==1 echo [%_BASENAME%] where %__WHERE_ARGS% + echo Tool paths: + for /f "tokens=*" %%p in ('where %__WHERE_ARGS%') do echo %%p +) +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +endlocal & ( + if not defined JAVA_HOME set JAVA_HOME=%_JDK_HOME% + set "PATH=%_JDK_PATH%%PATH%%_SBT_PATH%%_GIT_PATH%;%~dp0project\scripts" + call :print_env %_VERBOSE% + if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% + for /f "delims==" %%i in ('set ^| findstr /b "_"') do set %%i= +) From 36f6108757b10521117088d37640f43dac4ee79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Tue, 13 Nov 2018 11:03:44 +0100 Subject: [PATCH 03/22] small improvements in batch scripts for Dotty 0.10 --- bin/common.bat | 27 ++++++++++++----------- bin/dotc.bat | 55 +++++++++++++++++++++++------------------------ bin/dotd.bat | 58 +++++++++++++++++++++++++------------------------- bin/dotr.bat | 24 ++++++++++----------- 4 files changed, 83 insertions(+), 81 deletions(-) diff --git a/bin/common.bat b/bin/common.bat index 4c9b9c10f7ca..fd26dbc009f8 100644 --- a/bin/common.bat +++ b/bin/common.bat @@ -1,3 +1,6 @@ +rem ########################################################################## +rem ## Code common to dotc.bat, dotd.bat and dotr.bat + if defined JAVACMD ( set _JAVACMD=%JAVACMD% if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JAVACMD @@ -28,7 +31,7 @@ if defined JAVACMD ( ) ) if not exist "%_JAVACMD%" ( - if %_DEBUG%==1 echo [%_BASENAME%] Error: Java executable not found ^(%_JAVACMD%^) + echo Error: Java executable not found ^(%_JAVACMD%^) 1>&2 set _EXITCODE=1 goto :eof ) @@ -44,17 +47,17 @@ if defined DOTTY_HOME ( set _PSEP=; -for /f %%f in ('dir /b "%_LIB_DIR%\*dotty-compiler*"') do set _DOTTY_COMP=%_LIB_DIR%\%%f -for /f %%f in ('dir /b "%_LIB_DIR%\*dotty-interfaces*"') do set _DOTTY_INTF=%_LIB_DIR%\%%f -for /f %%f in ('dir /b "%_LIB_DIR%\*dotty-library*"') do set _DOTTY_LIB=%_LIB_DIR%\%%f -for /f %%f in ('dir /b "%_LIB_DIR%\*scala-asm*"') do set _SCALA_ASM=%_LIB_DIR%\%%f -for /f %%f in ('dir /b "%_LIB_DIR%\*scala-library*"') do set _SCALA_LIB=%_LIB_DIR%\%%f -for /f %%f in ('dir /b "%_LIB_DIR%\*scala-xml*"') do set _SCALA_XML=%_LIB_DIR%\%%f -for /f %%f in ('dir /b "%_LIB_DIR%\*compiler-interface*"') do set _SBT_INTF=%_LIB_DIR%\%%f -for /f %%f in ('dir /b "%_LIB_DIR%\*jline-reader-3*"') do set _JLINE_READER=%_LIB_DIR%\%%f -for /f %%f in ('dir /b "%_LIB_DIR%\*jline-terminal-3*"') do set _JLINE_TERMINAL=%_LIB_DIR%\%%f -for /f %%f in ('dir /b "%_LIB_DIR%\*jline-terminal-jna-3*"') do set _JLINE_TERMINAL_JNA=%_LIB_DIR%\%%f -for /f %%f in ('dir /b "%_LIB_DIR%\*jna-4*"') do set _JNA=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-compiler*"') do set _DOTTY_COMP=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-interfaces*"') do set _DOTTY_INTF=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-library*"') do set _DOTTY_LIB=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-asm*"') do set _SCALA_ASM=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-library*"') do set _SCALA_LIB=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-xml*"') do set _SCALA_XML=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*compiler-interface*"') do set _SBT_INTF=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-reader-3*"') do set _JLINE_READER=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-terminal-3*"') do set _JLINE_TERMINAL=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-terminal-jna-3*"') do set _JLINE_TERMINAL_JNA=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jna-4*"') do set _JNA=%_LIB_DIR%\%%f rem debug set _DEBUG_STR=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 diff --git a/bin/dotc.bat b/bin/dotc.bat index 83066abf861d..30675e37f11c 100644 --- a/bin/dotc.bat +++ b/bin/dotc.bat @@ -55,59 +55,58 @@ set _COLORS= set _SCALA_ARGS= set _JAVA_ARGS= set _RESIDUAL_ARGS= + :args_loop if "%~1"=="" goto args_done -set _ARG=%~1 -if %_DEBUG%==1 echo [%_BASENAME%] _ARG=%_ARG% -if "%_ARG%"=="--" ( +set __ARG=%~1 +if %_DEBUG%==1 echo [%_BASENAME%] __ARG=%__ARG% +if "%__ARG%"=="--" ( rem for arg; do addResidual "$arg"; done; set -- ;; -) else if /i "%_ARG%"=="-h" ( +) else if /i "%__ARG%"=="-h" ( set _HELP=true call :addScala "-help" -) else if /i "%_ARG%"=="-help" ( +) else if /i "%__ARG%"=="-help" ( set _HELP=true call :addScala "-help" -) else if /i "%_ARG%"=="-v" ( +) else if /i "%__ARG%"=="-v" ( set _VERBOSE=true call :addScala "-verbose" -) else if /i "%_ARG%"=="-verbose" ( +) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=true call :addScala "-verbose" -) else if /i "%_ARG%"=="-debug" ( set _JAVA_DEBUG=%_DEBUG_STR% -) else if /i "%_ARG%"=="-q" ( set _QUIET=true -) else if /i "%_ARG%"=="-quiet" ( set _QUIET=true +) else if /i "%__ARG%"=="-debug" ( set _JAVA_DEBUG=%_DEBUG_STR% +) else if /i "%__ARG%"=="-q" ( set _QUIET=true +) else if /i "%__ARG%"=="-quiet" ( set _QUIET=true rem Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 -) else if "%_ARG%"=="-=short" ( +) else if "%__ARG%"=="-=short" ( call :addJava "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" -) else if /i "%_ARG%"=="-repl" ( set _PROG_NAME=%_REPL_MAIN% -) else if /i "%_ARG%"=="-compile" ( set _PROG_NAME=%_COMPILER_MAIN% -) else if /i "%_ARG%"=="-decompile" ( set _PROG_NAME=%_DECOMPILER_MAIN% -) else if /i "%_ARG%"=="print-tasty" ( +) else if /i "%__ARG%"=="-repl" ( set _PROG_NAME=%_REPL_MAIN% +) else if /i "%__ARG%"=="-compile" ( set _PROG_NAME=%_COMPILER_MAIN% +) else if /i "%__ARG%"=="-decompile" ( set _PROG_NAME=%_DECOMPILER_MAIN% +) else if /i "%__ARG%"=="print-tasty" ( set _PROG_NAME=%_DECOMPILER_MAIN% call :addScala "-print-tasty" -) else if /i "%_ARG%"=="-run" ( set _PROG_NAME=%_REPL_MAIN% -) else if /i "%_ARG%"=="-colors" ( set _COLORS=true -) else if /i "%_ARG%"=="-no-colors" ( set _COLORS= -) else if /i "%_ARG%"=="-with-compiler" ( set _JVM_CP_ARGS=%_PSEP%%_DOTTY_COMP% +) else if /i "%__ARG%"=="-run" ( set _PROG_NAME=%_REPL_MAIN% +) else if /i "%__ARG%"=="-colors" ( set _COLORS=true +) else if /i "%__ARG%"=="-no-colors" ( set _COLORS= +) else if /i "%__ARG%"=="-with-compiler" ( set _JVM_CP_ARGS=%_PSEP%%_DOTTY_COMP% rem break out -D and -J options and add them to JAVA_OPTS as well rem so they reach the JVM in time to do some good. The -D options rem will be available as system properties. ) else if "%_ARG:~0,2%"=="-D" ( - call :addJava "%_ARG%" - call :addScala "%_ARG%" + call :addJava "%__ARG%" + call :addScala "%__ARG%" ) else if "%_ARG:~0,2%"=="-J" ( - call :addJava "%_ARG%" - call :addScala "%_ARG%" + call :addJava "%__ARG%" + call :addScala "%__ARG%" ) else ( - call :addResidual "%_ARG%" + call :addResidual "%__ARG%" ) shift goto args_loop :args_done -if %_DEBUG%==1 ( - echo [%_BASENAME%] _VERBOSE=%_VERBOSE% - echo [%_BASENAME%] _PROG_NAME=%_PROG_NAME% -) +if %_DEBUG%==1 echo [%_BASENAME%] _VERBOSE=%_VERBOSE% +if %_DEBUG%==1 echo [%_BASENAME%] _PROG_NAME=%_PROG_NAME% goto :eof rem output parameter: _SCALA_ARGS diff --git a/bin/dotd.bat b/bin/dotd.bat index 860085fe4f72..2712062adbe7 100644 --- a/bin/dotd.bat +++ b/bin/dotd.bat @@ -13,7 +13,7 @@ set _BASENAME=%~n0 for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf -call "%_PROG_HOME%\bin\common.bat" +call %_PROG_HOME%\bin\common.bat if not %_EXITCODE%==0 goto end rem ########################################################################## @@ -35,53 +35,53 @@ rem ## Subroutines rem output parameter: _CLASS_PATH :javaClassPath -set _LIB_DIR=%_PROG_HOME%\lib +set __LIB_DIR=%_PROG_HOME%\lib rem Set dotty-doc dep: -for /f %%f in ('dir /b "%_LIB_DIR%\*dotty-doc*"') do set _DOTTY_DOC_LIB=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*dotty-doc*"') do set _DOTTY_DOC_LIB=%__LIB_DIR%\%%f rem Set flexmark deps: -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-0*"') do set _FLEXMARK_LIBS=%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-anchorlink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-autolink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-emoji*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-gfm-strikethrough*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-gfm-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-gfm-tasklist*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-ins*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-superscript*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-wikilink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-ext-yaml-front-matter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-formatter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-jira-converter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*flexmark-util*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-0*"') do set _FLEXMARK_LIBS=%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-anchorlink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-autolink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-emoji*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-strikethrough*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-tasklist*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-ins*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-superscript*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-wikilink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-yaml-front-matter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-formatter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-jira-converter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-util*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% rem Set jackson deps: -for /f %%f in ('dir /b "%_LIB_DIR%\*jackson-annotations*"') do set _JACKSON_LIBS=%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*jackson-core*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*jackson-databind*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*jackson-dataformat-yaml*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-annotations*"') do set _JACKSON_LIBS=%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-core*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-databind*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-dataformat-yaml*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% rem Set liqp dep: -for /f %%f in ('dir /b "%_LIB_DIR%\*liqp*"') do set _LIQP_LIB=%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*liqp*"') do set _LIQP_LIB=%__LIB_DIR%\%%f%_PSEP% rem Set ANTLR dep: -for /f %%f in ('dir /b "%_LIB_DIR%\*antlr-3*"') do set _ANTLR_LIB=%_LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /b "%_LIB_DIR%\*antlr-runtime-3*"') do set _ANTLR_RUNTIME_LIB=%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*antlr-3*"') do set _ANTLR_LIB=%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*antlr-runtime-3*"') do set _ANTLR_RUNTIME_LIB=%__LIB_DIR%\%%f%_PSEP% rem Set autolink dep: rem conflict with flexmark-ext-autolink-0.11 -for /f %%f in ('dir /b "%_LIB_DIR%\*autolink-0.6*"') do set _AUTOLINK_LIB=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*autolink-0.6*"') do set _AUTOLINK_LIB=%__LIB_DIR%\%%f rem Set snakeyaml dep: -for /f %%f in ('dir /b "%_LIB_DIR%\*snakeyaml*"') do set _SNAKEYAML_LIB=%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*snakeyaml*"') do set _SNAKEYAML_LIB=%__LIB_DIR%\%%f%_PSEP% rem Set ST4 dep: -for /f %%f in ('dir /b "%_LIB_DIR%\*ST4*"') do set _ST4_LIB=%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*ST4*"') do set _ST4_LIB=%__LIB_DIR%\%%f%_PSEP% rem Set jsoup dep: -for /f %%f in ('dir /b "%_LIB_DIR%\*jsoup*"') do set _JSOUP_LIB=%_LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jsoup*"') do set _JSOUP_LIB=%__LIB_DIR%\%%f%_PSEP% set _CLASS_PATH=%_DOTTY_LIB%%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_DOC_LIB%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SBT_INTF% set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_SCALA_LIB% diff --git a/bin/dotr.bat b/bin/dotr.bat index 17d3438d87a3..8384e7b5ab5d 100644 --- a/bin/dotr.bat +++ b/bin/dotr.bat @@ -44,7 +44,7 @@ rem elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then ) else ( set _CP_ARG=!_CP_ARG!%_PSEP%. ) if %_CLASS_PATH_COUNT% gtr 1 ( - echo warning: multiple classpaths are found, dotr only use the last one. + echo Warning: Multiple classpaths are found, dotr only use the last one. 1>&2 ) if %_WITH_COMPILER%==1 ( set _CP_ARG=!_CP_ARG!%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SCALA_ASM% @@ -53,7 +53,7 @@ rem elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then if %_DEBUG%==1 echo [%_BASENAME%] %_JAVACMD% !_JAVA_ARGS! %_JAVACMD% !_JAVA_ARGS! ) else ( - echo warning: command option is not correct. + echo Warning: Command option is not correct. 1>&2 ) goto end @@ -74,25 +74,25 @@ set _JAVA_OPTIONS= :args_loop if "%1"=="" goto args_done -set "_ARG=%1" -if %_DEBUG%==1 echo [%_BASENAME%] _ARG=%_ARG% -if /i "%_ARG%"=="-repl" ( +set "__ARG=%1" +if %_DEBUG%==1 echo [%_BASENAME%] __ARG=%__ARG% +if /i "%__ARG%"=="-repl" ( set _EXECUTE_REPL=1 -) else if /i "%_ARG%"=="-run" ( +) else if /i "%__ARG%"=="-run" ( set _EXECUTE_RUN=1 -) else if /i "%_ARG%"=="-classpath" ( +) else if /i "%__ARG%"=="-classpath" ( set _CLASS_PATH=%2 set /a _CLASS_PATH_COUNT+=1 shift -) else if /i "%_ARG%"=="-with-compiler" ( +) else if /i "%__ARG%"=="-with-compiler" ( set _WITH_COMPILER=1 -) else if /i "%_ARG%"=="-d" ( +) else if /i "%__ARG%"=="-d" ( set _JAVA_DEBUG=%_DEBUG_STR% ) else if /i "%_ARG:~0,2%"=="-J" ( - set _JVM_OPTIONS=!_JVM_OPTIONS! %_ARG% - set _JAVA_OPTIONS=!_JAVA_OPTIONS! %_ARG% + set _JVM_OPTIONS=!_JVM_OPTIONS! %__ARG% + set _JAVA_OPTIONS=!_JAVA_OPTIONS! %__ARG% ) else ( - set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %_ARG% + set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %__ARG% ) shift goto args_loop From 07178271fb8ad8685998247889e9048fb0746520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Tue, 13 Nov 2018 11:04:53 +0100 Subject: [PATCH 04/22] improved subcommands in build.bat --- project/scripts/build.bat | 107 ++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 32 deletions(-) diff --git a/project/scripts/build.bat b/project/scripts/build.bat index 5d5ba7660f55..7cab2507bf29 100644 --- a/project/scripts/build.bat +++ b/project/scripts/build.bat @@ -2,7 +2,7 @@ setlocal enabledelayedexpansion rem only for interactive debugging -set _DEBUG=1 +set _DEBUG=0 rem ########################################################################## rem ## Environment setup @@ -31,17 +31,20 @@ if not %_EXITCODE%==0 ( goto end ) else if defined _HELP ( goto end ) -set _OUT_DIR=%TEMP%\%_BASENAME%_out +if exist "C:\Temp\" ( set _TMP_DIR=C:\Temp +) else ( set _TMP_DIR=%TEMP% +) +set _OUT_DIR=%_TMP_DIR%\%_BASENAME%_out if not exist "%_OUT_DIR%" mkdir "%_OUT_DIR%" -set _OUT1_DIR=%TEMP%\%_BASENAME%_out1 +set _OUT1_DIR=%_TMP_DIR%\%_BASENAME%_out1 if not exist "%_OUT1_DIR%" mkdir "%_OUT1_DIR%" -set _TMP_FILE=%TEMP%\%_BASENAME%_tmp.txt +set _TMP_FILE=%_TMP_DIR%\%_BASENAME%_tmp.txt where /q git.exe if not %ERRORLEVEL%==0 ( - echo Error: Git command not found ^(run setenv.bat^) 1>&2 + echo Error: Git command not found ^(check your PATH variable^) 1>&2 set _EXITCODE=1 goto end ) @@ -49,11 +52,11 @@ set _GIT_CMD=git.exe where /q sbt.bat if not %ERRORLEVEL%==0 ( - echo Error: SBT command not found ^(run setenv.bat^) 1>&2 + echo Error: SBT command not found ^(check your PATH variable^) 1>&2 set _EXITCODE=1 goto end ) -rem full path of SBT command is required +rem full path is required for sbt to run successfully for /f %%i in ('where sbt.bat') do set _SBT_CMD=%%i rem see file project/scripts/sbt @@ -69,27 +72,40 @@ set SBT_OPTS=-Ddotty.drone.mem=4096m ^ rem ########################################################################## rem ## Main -if defined _CLEAN ( - if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" clean - call "%_SBT_CMD%" clean - goto end +if %_VERBOSE%==1 ( + for /f %%i in ('where git.exe') do set _GIT_CMD1=%%i + echo _GIT_CMD=!_GIT_CMD1! + echo _SBT_CMD=%_SBT_CMD% + echo JAVA_OPTS=%JAVA_OPTS% + echo SBT_OPTS=%SBT_OPTS% + echo. +) +if defined _CLEAN_ALL ( + call :clean_all + if not !_EXITCODE!==0 goto end +) +if defined _CLONE ( + call :clone + if not !_EXITCODE!==0 goto end +) +if defined _BUILD ( + call :test + if not !_EXITCODE!==0 goto end ) - -call :clone -if not %_EXITCODE%==0 goto end - -call :test -if not %_EXITCODE%==0 goto end - if defined _BOOTSTRAP ( call :test_bootstrapped rem if not !_EXITCODE!==0 goto end - if not !_EXITCODE!==0 echo ###### Warning: _EXITCODE=!_EXITCODE! ####### 1>&2 + if not !_EXITCODE!==0 ( + if defined _IGNORE ( echo ###### Warning: _EXITCODE=!_EXITCODE! ####### 1>&2 + ) else ( goto end + ) + ) ) if defined _DOCUMENTATION ( call :documentation if not !_EXITCODE!==0 goto end ) + if defined _ARCHIVES ( call :archives if not !_EXITCODE!==0 goto end @@ -105,7 +121,8 @@ rem output parameters: _VERBOSE, _DOCUMENTATION set _VERBOSE=0 set _ARCHIVES= set _BOOTSTRAP= -set _CLEAN= +set _BUILD= +set _CLEAN_ALL= set _DOCUMENTATION= set __N=0 :args_loop @@ -117,10 +134,16 @@ if not defined __ARG ( ) if /i "%__ARG%"=="help" ( call :help & goto :eof ) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 -) else if /i "%__ARG:~0,4%"=="arch" ( set _ARCHIVES=1 -) else if /i "%__ARG:~0,4%"=="boot" ( set _BOOTSTRAP=1 -) else if /i "%__ARG%"=="clean" ( set _CLEAN=1 -) else if /i "%__ARG:~0,3%"=="doc" ( set _DOCUMENTATION=1 +) else if /i "%__ARG:~0,4%"=="arch" ( + if not "%__ARG:~-5%"=="-only" set _BUILD=1 & set _BOOTSTRAP=1 + set _ARCHIVES=1 +) else if /i "%__ARG:~0,4%"=="boot" ( + if not "%__ARG:~-5%"=="-only" set _BUILD=1 + set _BOOTSTRAP=1 +) else if /i "%__ARG%"=="cleanall" ( set _CLEAN_ALL=1 +) else if /i "%__ARG:~0,3%"=="doc" ( + if not "%__ARG:~-5%"=="-only" set _BUILD=1 & set _BOOTSTRAP=1 + set _DOCUMENTATION=1 ) else ( echo %_BASENAME%: Unknown subcommand %__ARG% set _EXITCODE=1 @@ -135,13 +158,31 @@ goto :eof set _HELP=1 echo Usage: setenv { options ^| subcommands } echo Options: -echo -verbose display environment settings +echo -verbose display environment settings echo Subcommands: -echo arch[ives] generate gz/zip archives -echo boot[strap] generate compiler bootstrap -echo clean clean project and leave -echo doc[umentation] generate documentation -echo help display this help message +echo arch[ives] generate gz/zip archives (after bootstrap) +echo arch[ives]-only generate ONLY gz/zip archives +echo boot[strap] generate compiler bootstrap (after build) +echo boot[strap]-only generate ONLY compiler bootstrap +echo cleanall clean project (sbt+git) and quit +echo doc[umentation] generate documentation (after bootstrap) +echo doc[umentation]-only] generate ONLY documentation +echo help display this help message +goto :eof + +:clean_all +if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" clean +call "%_SBT_CMD%" clean +if not %ERRORLEVEL%==0 ( + set _EXITCODE=1 + goto :eof +) +if %_DEBUG%==1 echo [%_BASENAME%] %_GIT_CMD% clean -xdf +%_GIT_CMD% clean -xdf +if not %ERRORLEVEL%==0 ( + set _EXITCODE=1 + goto :eof +) goto :eof :clone @@ -172,6 +213,7 @@ goto :eof set __PATTERN=%~1 set __FILE=%~2 +if %_DEBUG%==1 echo [%_BASENAME%] findstr "%__PATTERN%" "%__FILE% findstr "%__PATTERN%" "%__FILE%" if not %ERRORLEVEL%==0 ( echo Error: Failed to find pattern "%__PATTERN%" in file %__FILE% 1>&2 @@ -217,8 +259,8 @@ if not %_EXITCODE%==0 goto :eof goto :eof :test -if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";clean ;compile ;test" -call "%_SBT_CMD%" ";clean ;compile ;test" +if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";compile ;test" +call "%_SBT_CMD%" ";compile ;test" if not %ERRORLEVEL%==0 ( echo Error: Failed to build Dotty 1>&2 set _EXITCODE=1 @@ -364,6 +406,7 @@ if not exist "%__TARGET_DIR%\" ( goto :eof ) if %_DEBUG%==1 ( + echo. echo Output directory: %__TARGET_DIR%\ dir /b /a-d "%__TARGET_DIR%" ) From 4e5738812601df0948482bc1ac1d80ea1fe09472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Tue, 13 Nov 2018 23:50:41 +0100 Subject: [PATCH 05/22] move batch scripts for distro to correct directory --- {bin => dist/bin}/common.bat | 0 {bin => dist/bin}/dotc.bat | 0 {bin => dist/bin}/dotd.bat | 0 {bin => dist/bin}/dotr.bat | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {bin => dist/bin}/common.bat (100%) rename {bin => dist/bin}/dotc.bat (100%) rename {bin => dist/bin}/dotd.bat (100%) rename {bin => dist/bin}/dotr.bat (100%) diff --git a/bin/common.bat b/dist/bin/common.bat similarity index 100% rename from bin/common.bat rename to dist/bin/common.bat diff --git a/bin/dotc.bat b/dist/bin/dotc.bat similarity index 100% rename from bin/dotc.bat rename to dist/bin/dotc.bat diff --git a/bin/dotd.bat b/dist/bin/dotd.bat similarity index 100% rename from bin/dotd.bat rename to dist/bin/dotd.bat diff --git a/bin/dotr.bat b/dist/bin/dotr.bat similarity index 100% rename from bin/dotr.bat rename to dist/bin/dotr.bat From 728cdff8f5ccb64e24ad4ba67b3ccf78b6af5a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Tue, 13 Nov 2018 23:52:38 +0100 Subject: [PATCH 06/22] fix goto label and help handling in batch scripts --- project/scripts/build.bat | 37 ++++++++++++++++--------------------- setenv.bat | 17 ++++++++--------- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/project/scripts/build.bat b/project/scripts/build.bat index 7cab2507bf29..1e504b747ec6 100644 --- a/project/scripts/build.bat +++ b/project/scripts/build.bat @@ -27,9 +27,8 @@ set _MAIN=HelloWorld set _EXPECTED_OUTPUT=hello world call :args %* -if not %_EXITCODE%==0 ( goto end -) else if defined _HELP ( goto end -) +if not %_EXITCODE%==0 goto end +if defined _HELP call :help & exit /b %_EXITCODE% if exist "C:\Temp\" ( set _TMP_DIR=C:\Temp ) else ( set _TMP_DIR=%TEMP% @@ -118,31 +117,28 @@ rem ## Subroutines rem input parameter: %* rem output parameters: _VERBOSE, _DOCUMENTATION :args -set _VERBOSE=0 set _ARCHIVES= set _BOOTSTRAP= set _BUILD= set _CLEAN_ALL= set _DOCUMENTATION= -set __N=0 +set _HELP= +set _VERBOSE=0 + :args_loop set __ARG=%~1 -if not defined __ARG ( - goto args_done -) else if not "%__ARG:~0,1%"=="-" ( - set /a __N=+1 -) -if /i "%__ARG%"=="help" ( call :help & goto :eof +if not defined __ARG goto args_done +if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof ) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 ) else if /i "%__ARG:~0,4%"=="arch" ( - if not "%__ARG:~-5%"=="-only" set _BUILD=1 & set _BOOTSTRAP=1 + if not "%__ARG:~-5%"=="-only" set _BUILD=1& set _BOOTSTRAP=1 set _ARCHIVES=1 ) else if /i "%__ARG:~0,4%"=="boot" ( if not "%__ARG:~-5%"=="-only" set _BUILD=1 set _BOOTSTRAP=1 ) else if /i "%__ARG%"=="cleanall" ( set _CLEAN_ALL=1 ) else if /i "%__ARG:~0,3%"=="doc" ( - if not "%__ARG:~-5%"=="-only" set _BUILD=1 & set _BOOTSTRAP=1 + if not "%__ARG:~-5%"=="-only" set _BUILD=1& set _BOOTSTRAP=1 set _DOCUMENTATION=1 ) else ( echo %_BASENAME%: Unknown subcommand %__ARG% @@ -150,13 +146,12 @@ if /i "%__ARG%"=="help" ( call :help & goto :eof goto :eof ) shift -goto :args_loop +goto args_loop :args_done goto :eof :help -set _HELP=1 -echo Usage: setenv { options ^| subcommands } +echo Usage: %_BASENAME% { options ^| subcommands } echo Options: echo -verbose display environment settings echo Subcommands: @@ -307,22 +302,22 @@ call "%_SBT_CMD%" dist-bootstrapped/pack rem # check that `dotc` compiles and `dotr` runs it echo testing ./bin/dotc and ./bin/dotr call :clear_out "%_OUT_DIR%" -call %_BIN_DIR%\dotc "%_SOURCE%" -d "%_OUT_DIR%" -call %_BIN_DIR%\dotr -classpath "%_OUT_DIR%" "%_MAIN%" > "%_TMP_FILE%" +call %_BIN_DIR%\dotc.bat "%_SOURCE%" -d "%_OUT_DIR%" +call %_BIN_DIR%\dotr.bat -classpath "%_OUT_DIR%" "%_MAIN%" > "%_TMP_FILE%" call :test_pattern "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" rem # check that `dotc -from-tasty` compiles and `dotr` runs it echo testing ./bin/dotc -from-tasty and dotr -classpath call :clear_out "%_OUT1_DIR%" -call %_BIN_DIR%\dotc -from-tasty -classpath "%_OUT_DIR%" -d "%_OUT1_DIR%" "%_MAIN%" -call %_BIN_DIR%\dotr -classpath "%_OUT1_DIR%" "%_MAIN%" > "%_TMP_FILE%" +call %_BIN_DIR%\dotc.bat -from-tasty -classpath "%_OUT_DIR%" -d "%_OUT1_DIR%" "%_MAIN%" +call %_BIN_DIR%\dotr.bat -classpath "%_OUT1_DIR%" "%_MAIN%" > "%_TMP_FILE%" call :test_pattern "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" rem # echo ":quit" | ./dist-bootstrapped/target/pack/bin/dotr # not supported by CI echo testing ./bin/dotd call :clear_out "%_OUT_DIR%" -call %_BIN_DIR%\dotd -project Hello -siteroot "%_OUT_DIR%" "%_SOURCE%" +call %_BIN_DIR%\dotd.bat -project Hello -siteroot "%_OUT_DIR%" "%_SOURCE%" goto :eof diff --git a/setenv.bat b/setenv.bat index 5651dc492512..917f1c39b8da 100644 --- a/setenv.bat +++ b/setenv.bat @@ -13,6 +13,7 @@ set _EXITCODE=0 call :args %* if not %_EXITCODE%==0 goto end +if defined _HELP call :help & exit /b %_EXITCODE% rem ########################################################################## rem ## Main @@ -38,17 +39,15 @@ rem ########################################################################## rem ## Subroutines rem input parameter: %* +rem output parameter: _HELP, _VERBOSE :args +set _HELP= set _VERBOSE=0 -set __N=0 + :args_loop set __ARG=%~1 -if not defined __ARG ( - goto args_done -) else if not "%__ARG:~0,1%"=="-" ( - set /a __N=!__N!+1 -) -if /i "%__ARG%"=="help" ( call :help & goto :eof +if not defined __ARG goto args_done +if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof ) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 ) else ( echo %_BASENAME%: Unknown subcommand %__ARG% @@ -56,12 +55,12 @@ if /i "%__ARG%"=="help" ( call :help & goto :eof goto :eof ) shift -goto :args_loop +goto args_loop :args_done goto :eof :help -echo Usage: setenv { options ^| subcommands } +echo Usage: %_BASENAME% { options ^| subcommands } echo Options: echo -verbose display environment settings echo Subcommands: From 52a47663d358264fbea5db05d107b3d05545865e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Tue, 13 Nov 2018 23:55:33 +0100 Subject: [PATCH 07/22] added batch scripts for sbt pack --- bin/common.bat | 127 +++++++++++++++++++++++++++++++++++++++++++++++++ bin/dotc.bat | 5 ++ bin/dotd.bat | 5 ++ bin/dotr.bat | 5 ++ 4 files changed, 142 insertions(+) create mode 100644 bin/common.bat create mode 100644 bin/dotc.bat create mode 100644 bin/dotd.bat create mode 100644 bin/dotr.bat diff --git a/bin/common.bat b/bin/common.bat new file mode 100644 index 000000000000..0ad054cce557 --- /dev/null +++ b/bin/common.bat @@ -0,0 +1,127 @@ +@echo off +setlocal + +rem # Wrapper for the published dotc/dotr script that check for file changes +rem # and use sbt to re build the compiler as needed. + +rem only for interactive debugging +set _DEBUG=1 + +rem ########################################################################## +rem ## Environment setup + +set _BASENAME=%~n0 + +set _EXITCODE=0 + +for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf + +rem # Marker file used to obtain the date of latest call to sbt-back +set _VERSION=%_ROOT_DIR%\dist-bootstrapped\target\pack\VERSION + +rem ########################################################################## +rem ## Main + +rem # Create the target if absent or if file changed in ROOT/compiler +rem new_files="$(find "$ROOT/compiler" \( -iname "*.scala" -o -iname "*.java" \) -newer "$version" 2> /dev/null)" +call :new_files "%_VERSION%" + +if exist "%_VERSION%" if %_NEW_FILES%==0 goto target +echo Building Dotty... +pushd %_ROOT% && sbt.bat "dist-bootstrapped/pack" + +:target +set _TARGET=%~1 +rem # Mutates %* by deleting the first element (%1) +shift + +if %_DEBUG%==1 echo [%_BASENAME%] call %_TARGET% %* +call %_TARGET% %* +popd +goto end + +rem ########################################################################## +rem ## Subroutines + +rem input parameter: %1=version file +rem Output parameter: _NEW_FILES +:new_files +set __VERSION_FILE=%~1 + +call :timestamp "%__VERSION_FILE%" +set __VERSION_TIMESTAMP=%_TIMESTAMP% +if %_DEBUG%==1 echo [%_BASENAME%] %__VERSION_TIMESTAMP% %__VERSION_FILE% + +set __JAVA_SOURCE_FILES= +for /f %%i in ('dir /s /b "%_ROOT_DIR%compiler\*.java" 2^>NUL') do ( + set __JAVA_SOURCE_FILES=!__JAVA_SOURCE_FILES! %%i +) +set __SCALA_SOURCE_FILES= +for /f %%i in ('dir /s /b "%_ROOT_DIR%compiler\*.scala" 2^>NUL') do ( + set __SCALA_SOURCE_FILES=!__SCALA_SOURCE_FILES! %%i +) + +call :compile_required "%__VERSION_TIMESTAMP%" "%__JAVA_SOURCE_FILES% %__SCALA_SOURCE_FILES%" +set _NEW_FILES=%_COMPILE_REQUIRED% + +goto :eof + +rem input parameter: 1=timestamp file 2=source files +rem output parameter: _COMPILE_REQUIRED +:compile_required +set __TIMESTAMP_FILE=%~1 +set __SOURCE_FILES=%~2 + +set __SOURCE_TIMESTAMP=00000000000000 +set __N=0 +for %%i in (%__SOURCE_FILES%) do ( + call :timestamp "%%i" + if %_DEBUG%==1 echo [%_BASENAME%] !_TIMESTAMP! %%i + call :newer !_TIMESTAMP! !__SOURCE_TIMESTAMP! + if !_NEWER!==1 set __SOURCE_TIMESTAMP=!_TIMESTAMP! + set /a __N=!__N!+1 +) +if exist "%__TIMESTAMP_FILE%" ( set /p __CLASS_TIMESTAMP=<%__TIMESTAMP_FILE% +) else ( set __CLASS_TIMESTAMP=00000000000000 +) +if %_DEBUG%==1 echo [%_BASENAME%] %__CLASS_TIMESTAMP% %__TIMESTAMP_FILE% + +call :newer %__SOURCE_TIMESTAMP% %__CLASS_TIMESTAMP% +set _COMPILE_REQUIRED=%_NEWER% +goto :eof + +rem output parameter: _NEWER +:newer +set __TIMESTAMP1=%~1 +set __TIMESTAMP2=%~2 + +set __TIMESTAMP1_DATE=%__TIMESTAMP1:~0,8% +set __TIMESTAMP1_TIME=%__TIMESTAMP1:~-6% + +set __TIMESTAMP2_DATE=%__TIMESTAMP2:~0,8% +set __TIMESTAMP2_TIME=%__TIMESTAMP2:~-6% + +if %__TIMESTAMP1_DATE% gtr %__TIMESTAMP2_DATE% ( set _NEWER=1 +) else if %__TIMESTAMP1_DATE% lss %__TIMESTAMP2_DATE% ( set _NEWER=0 +) else if %__TIMESTAMP1_TIME% gtr %__TIMESTAMP2_TIME% ( set _NEWER=1 +) else ( set _NEWER=0 +) +goto :eof + +rem input parameter: 1=file path +rem output parameter: _TIMESTAMP +:timestamp +set __FILE_PATH=%~1 + +set _TIMESTAMP=00000000000000 +for /f %%i in ('powershell -C "(Get-ChildItem '%__FILE_PATH%').LastWriteTime | Get-Date -uformat %%Y%%m%%d%%H%%M%%S"') do ( + set _TIMESTAMP=%%i +) +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +exit /b %_EXITCODE% +endlocal \ No newline at end of file diff --git a/bin/dotc.bat b/bin/dotc.bat new file mode 100644 index 000000000000..6cb1b20510dd --- /dev/null +++ b/bin/dotc.bat @@ -0,0 +1,5 @@ +@echo off + +for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf + +call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotc.bat" %* diff --git a/bin/dotd.bat b/bin/dotd.bat new file mode 100644 index 000000000000..5544e2bed952 --- /dev/null +++ b/bin/dotd.bat @@ -0,0 +1,5 @@ +@echo off + +for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf + +call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotd.bat" %* diff --git a/bin/dotr.bat b/bin/dotr.bat new file mode 100644 index 000000000000..3d62849591df --- /dev/null +++ b/bin/dotr.bat @@ -0,0 +1,5 @@ +@echo off + +for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf + +call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotr.bat" %* From 89437fb120ccec725e439b1199f616db061b4813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Wed, 14 Nov 2018 07:20:20 +0100 Subject: [PATCH 08/22] remove debug code --- bin/common.bat | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/bin/common.bat b/bin/common.bat index 0ad054cce557..264b3fedaa37 100644 --- a/bin/common.bat +++ b/bin/common.bat @@ -1,12 +1,9 @@ @echo off -setlocal +setlocal enabledelayedexpansion rem # Wrapper for the published dotc/dotr script that check for file changes rem # and use sbt to re build the compiler as needed. -rem only for interactive debugging -set _DEBUG=1 - rem ########################################################################## rem ## Environment setup @@ -23,21 +20,21 @@ rem ########################################################################## rem ## Main rem # Create the target if absent or if file changed in ROOT/compiler -rem new_files="$(find "$ROOT/compiler" \( -iname "*.scala" -o -iname "*.java" \) -newer "$version" 2> /dev/null)" call :new_files "%_VERSION%" if exist "%_VERSION%" if %_NEW_FILES%==0 goto target echo Building Dotty... -pushd %_ROOT% && sbt.bat "dist-bootstrapped/pack" +pushd %_ROOT% +sbt.bat "dist-bootstrapped/pack" +popd :target set _TARGET=%~1 rem # Mutates %* by deleting the first element (%1) shift -if %_DEBUG%==1 echo [%_BASENAME%] call %_TARGET% %* call %_TARGET% %* -popd + goto end rem ########################################################################## @@ -50,7 +47,6 @@ set __VERSION_FILE=%~1 call :timestamp "%__VERSION_FILE%" set __VERSION_TIMESTAMP=%_TIMESTAMP% -if %_DEBUG%==1 echo [%_BASENAME%] %__VERSION_TIMESTAMP% %__VERSION_FILE% set __JAVA_SOURCE_FILES= for /f %%i in ('dir /s /b "%_ROOT_DIR%compiler\*.java" 2^>NUL') do ( @@ -73,18 +69,14 @@ set __TIMESTAMP_FILE=%~1 set __SOURCE_FILES=%~2 set __SOURCE_TIMESTAMP=00000000000000 -set __N=0 for %%i in (%__SOURCE_FILES%) do ( call :timestamp "%%i" - if %_DEBUG%==1 echo [%_BASENAME%] !_TIMESTAMP! %%i call :newer !_TIMESTAMP! !__SOURCE_TIMESTAMP! if !_NEWER!==1 set __SOURCE_TIMESTAMP=!_TIMESTAMP! - set /a __N=!__N!+1 ) if exist "%__TIMESTAMP_FILE%" ( set /p __CLASS_TIMESTAMP=<%__TIMESTAMP_FILE% ) else ( set __CLASS_TIMESTAMP=00000000000000 ) -if %_DEBUG%==1 echo [%_BASENAME%] %__CLASS_TIMESTAMP% %__TIMESTAMP_FILE% call :newer %__SOURCE_TIMESTAMP% %__CLASS_TIMESTAMP% set _COMPILE_REQUIRED=%_NEWER% From 34551893ef1966f5050ba7a31fe4fffc5db58fea Mon Sep 17 00:00:00 2001 From: michelou Date: Wed, 14 Nov 2018 14:40:59 +0100 Subject: [PATCH 09/22] improved error messages in batch scripts --- project/scripts/build.bat | 64 ++++++++++++++++++++++----------------- setenv.bat | 20 +++--------- 2 files changed, 40 insertions(+), 44 deletions(-) diff --git a/project/scripts/build.bat b/project/scripts/build.bat index 1e504b747ec6..00572fcb36df 100644 --- a/project/scripts/build.bat +++ b/project/scripts/build.bat @@ -41,27 +41,10 @@ if not exist "%_OUT1_DIR%" mkdir "%_OUT1_DIR%" set _TMP_FILE=%_TMP_DIR%\%_BASENAME%_tmp.txt -where /q git.exe -if not %ERRORLEVEL%==0 ( - echo Error: Git command not found ^(check your PATH variable^) 1>&2 - set _EXITCODE=1 - goto end -) -set _GIT_CMD=git.exe - -where /q sbt.bat -if not %ERRORLEVEL%==0 ( - echo Error: SBT command not found ^(check your PATH variable^) 1>&2 - set _EXITCODE=1 - goto end -) -rem full path is required for sbt to run successfully -for /f %%i in ('where sbt.bat') do set _SBT_CMD=%%i - rem see file project/scripts/sbt rem SBT uses the value of the JAVA_OPTS environment variable if defined, rather than the config. -set JAVA_OPTS=-Xmx4096m ^ --XX:ReservedCodeCacheSize=1024m ^ +set JAVA_OPTS=-Xmx2048m ^ +-XX:ReservedCodeCacheSize=2048m ^ -XX:MaxMetaspaceSize=1024m set SBT_OPTS=-Ddotty.drone.mem=4096m ^ @@ -71,14 +54,9 @@ set SBT_OPTS=-Ddotty.drone.mem=4096m ^ rem ########################################################################## rem ## Main -if %_VERBOSE%==1 ( - for /f %%i in ('where git.exe') do set _GIT_CMD1=%%i - echo _GIT_CMD=!_GIT_CMD1! - echo _SBT_CMD=%_SBT_CMD% - echo JAVA_OPTS=%JAVA_OPTS% - echo SBT_OPTS=%SBT_OPTS% - echo. -) +call :init +if not %_EXITCODE%==0 goto end + if defined _CLEAN_ALL ( call :clean_all if not !_EXITCODE!==0 goto end @@ -141,7 +119,7 @@ if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof if not "%__ARG:~-5%"=="-only" set _BUILD=1& set _BOOTSTRAP=1 set _DOCUMENTATION=1 ) else ( - echo %_BASENAME%: Unknown subcommand %__ARG% + echo Error: Unknown subcommand %__ARG% set _EXITCODE=1 goto :eof ) @@ -165,7 +143,37 @@ echo doc[umentation]-only] generate ONLY documentation echo help display this help message goto :eof +rem output parameters: _GIT_CMD, _SBT_CMD +:init +where /q git.exe +if not %ERRORLEVEL%==0 ( + echo Error: Git command not found ^(check your PATH variable^) 1>&2 + set _EXITCODE=1 + goto end +) +set _GIT_CMD=git.exe + +where /q sbt.bat +if not %ERRORLEVEL%==0 ( + echo Error: SBT command not found ^(check your PATH variable^) 1>&2 + set _EXITCODE=1 + goto end +) +rem full path is required for sbt to run successfully +for /f %%i in ('where sbt.bat') do set _SBT_CMD=%%i + +if %_VERBOSE%==1 ( + for /f %%i in ('where git.exe') do set _GIT_CMD1=%%i + echo _GIT_CMD=!_GIT_CMD1! + echo _SBT_CMD=%_SBT_CMD% + echo JAVA_OPTS=%JAVA_OPTS% + echo SBT_OPTS=%SBT_OPTS% + echo. +) +goto :eof + :clean_all +echo run sbt clean and git clean -xdf if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" clean call "%_SBT_CMD%" clean if not %ERRORLEVEL%==0 ( diff --git a/setenv.bat b/setenv.bat index 917f1c39b8da..3e40b02725ac 100644 --- a/setenv.bat +++ b/setenv.bat @@ -31,8 +31,6 @@ if not %_EXITCODE%==0 goto end call :git if not %_EXITCODE%==0 goto end -if "%~1"=="clean" call :clean - goto end rem ########################################################################## @@ -50,7 +48,7 @@ if not defined __ARG goto args_done if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof ) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 ) else ( - echo %_BASENAME%: Unknown subcommand %__ARG% + echo Error: Unknown subcommand %__ARG% 1>&2 set _EXITCODE=1 goto :eof ) @@ -86,7 +84,7 @@ if defined JDK_HOME ( ) ) if not exist "%_JDK_HOME%\bin\javac.exe" ( - if %_DEBUG%==1 echo [%_BASENAME%] javac executable not found ^(%_JDK_HOME%^) + echo Error: javac executable not found ^(%_JDK_HOME%^) 1>&2 set _EXITCODE=1 goto :eof ) @@ -109,7 +107,7 @@ if defined SBT_HOME ( ) ) if not exist "%_SBT_HOME%\bin\sbt.bat" ( - if %_DEBUG%==1 echo [%_BASENAME%] sbt executable not found ^(%_SBT_HOME%^) + echo Error: sbt executable not found ^(%_SBT_HOME%^) 1>&2 set _EXITCODE=1 goto :eof ) @@ -138,23 +136,13 @@ if defined GIT_HOME ( ) ) if not exist "%_GIT_HOME%\bin\git.exe" ( - echo Git executable not found ^(%_GIT_HOME%^) + echo Error: Git executable not found ^(%_GIT_HOME%^) 1>&2 set _EXITCODE=1 goto :eof ) set "_GIT_PATH=;%_GIT_HOME%\bin;%_GIT_HOME%\usr\bin" goto :eof -:clean -for %%f in ("%~dp0") do set __ROOT_DIR=%%~sf -for /f %%i in ('dir /ad /b "%__ROOT_DIR%\" 2^>NUL') do ( - for /f %%j in ('dir /ad /b "%%i\target\scala-*" 2^>NUL') do ( - if %_DEBUG%==1 echo [%_BASENAME%] rmdir /s /q %__ROOT_DIR%%%i\target\%%j\classes 1^>NUL 2^>^&1 - rmdir /s /q %__ROOT_DIR%%%i\target\%%j\classes 1>NUL 2>&1 - ) -) -goto :eof - rem output parameter: _SBT_VERSION rem Note: SBT requires special handling to know its version (no comment) :sbt_version From 28b4c040b12adc05cba35d888b1686e5fbc0d366 Mon Sep 17 00:00:00 2001 From: michelou Date: Wed, 14 Nov 2018 17:33:19 +0100 Subject: [PATCH 10/22] reverted commits up to 72ef612 (PR #5430) --- bin/common.bat | 119 ----------- bin/dotc.bat | 5 - bin/dotd.bat | 5 - bin/dotr.bat | 5 - dist/bin/common.bat | 63 ------ dist/bin/dotc.bat | 163 --------------- dist/bin/dotd.bat | 104 ---------- dist/bin/dotr.bat | 108 ---------- project/scripts/build.bat | 423 -------------------------------------- setenv.bat | 205 ------------------ 10 files changed, 1200 deletions(-) delete mode 100644 bin/common.bat delete mode 100644 bin/dotc.bat delete mode 100644 bin/dotd.bat delete mode 100644 bin/dotr.bat delete mode 100644 dist/bin/common.bat delete mode 100644 dist/bin/dotc.bat delete mode 100644 dist/bin/dotd.bat delete mode 100644 dist/bin/dotr.bat delete mode 100644 project/scripts/build.bat delete mode 100644 setenv.bat diff --git a/bin/common.bat b/bin/common.bat deleted file mode 100644 index 264b3fedaa37..000000000000 --- a/bin/common.bat +++ /dev/null @@ -1,119 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem # Wrapper for the published dotc/dotr script that check for file changes -rem # and use sbt to re build the compiler as needed. - -rem ########################################################################## -rem ## Environment setup - -set _BASENAME=%~n0 - -set _EXITCODE=0 - -for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf - -rem # Marker file used to obtain the date of latest call to sbt-back -set _VERSION=%_ROOT_DIR%\dist-bootstrapped\target\pack\VERSION - -rem ########################################################################## -rem ## Main - -rem # Create the target if absent or if file changed in ROOT/compiler -call :new_files "%_VERSION%" - -if exist "%_VERSION%" if %_NEW_FILES%==0 goto target -echo Building Dotty... -pushd %_ROOT% -sbt.bat "dist-bootstrapped/pack" -popd - -:target -set _TARGET=%~1 -rem # Mutates %* by deleting the first element (%1) -shift - -call %_TARGET% %* - -goto end - -rem ########################################################################## -rem ## Subroutines - -rem input parameter: %1=version file -rem Output parameter: _NEW_FILES -:new_files -set __VERSION_FILE=%~1 - -call :timestamp "%__VERSION_FILE%" -set __VERSION_TIMESTAMP=%_TIMESTAMP% - -set __JAVA_SOURCE_FILES= -for /f %%i in ('dir /s /b "%_ROOT_DIR%compiler\*.java" 2^>NUL') do ( - set __JAVA_SOURCE_FILES=!__JAVA_SOURCE_FILES! %%i -) -set __SCALA_SOURCE_FILES= -for /f %%i in ('dir /s /b "%_ROOT_DIR%compiler\*.scala" 2^>NUL') do ( - set __SCALA_SOURCE_FILES=!__SCALA_SOURCE_FILES! %%i -) - -call :compile_required "%__VERSION_TIMESTAMP%" "%__JAVA_SOURCE_FILES% %__SCALA_SOURCE_FILES%" -set _NEW_FILES=%_COMPILE_REQUIRED% - -goto :eof - -rem input parameter: 1=timestamp file 2=source files -rem output parameter: _COMPILE_REQUIRED -:compile_required -set __TIMESTAMP_FILE=%~1 -set __SOURCE_FILES=%~2 - -set __SOURCE_TIMESTAMP=00000000000000 -for %%i in (%__SOURCE_FILES%) do ( - call :timestamp "%%i" - call :newer !_TIMESTAMP! !__SOURCE_TIMESTAMP! - if !_NEWER!==1 set __SOURCE_TIMESTAMP=!_TIMESTAMP! -) -if exist "%__TIMESTAMP_FILE%" ( set /p __CLASS_TIMESTAMP=<%__TIMESTAMP_FILE% -) else ( set __CLASS_TIMESTAMP=00000000000000 -) - -call :newer %__SOURCE_TIMESTAMP% %__CLASS_TIMESTAMP% -set _COMPILE_REQUIRED=%_NEWER% -goto :eof - -rem output parameter: _NEWER -:newer -set __TIMESTAMP1=%~1 -set __TIMESTAMP2=%~2 - -set __TIMESTAMP1_DATE=%__TIMESTAMP1:~0,8% -set __TIMESTAMP1_TIME=%__TIMESTAMP1:~-6% - -set __TIMESTAMP2_DATE=%__TIMESTAMP2:~0,8% -set __TIMESTAMP2_TIME=%__TIMESTAMP2:~-6% - -if %__TIMESTAMP1_DATE% gtr %__TIMESTAMP2_DATE% ( set _NEWER=1 -) else if %__TIMESTAMP1_DATE% lss %__TIMESTAMP2_DATE% ( set _NEWER=0 -) else if %__TIMESTAMP1_TIME% gtr %__TIMESTAMP2_TIME% ( set _NEWER=1 -) else ( set _NEWER=0 -) -goto :eof - -rem input parameter: 1=file path -rem output parameter: _TIMESTAMP -:timestamp -set __FILE_PATH=%~1 - -set _TIMESTAMP=00000000000000 -for /f %%i in ('powershell -C "(Get-ChildItem '%__FILE_PATH%').LastWriteTime | Get-Date -uformat %%Y%%m%%d%%H%%M%%S"') do ( - set _TIMESTAMP=%%i -) -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -exit /b %_EXITCODE% -endlocal \ No newline at end of file diff --git a/bin/dotc.bat b/bin/dotc.bat deleted file mode 100644 index 6cb1b20510dd..000000000000 --- a/bin/dotc.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off - -for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf - -call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotc.bat" %* diff --git a/bin/dotd.bat b/bin/dotd.bat deleted file mode 100644 index 5544e2bed952..000000000000 --- a/bin/dotd.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off - -for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf - -call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotd.bat" %* diff --git a/bin/dotr.bat b/bin/dotr.bat deleted file mode 100644 index 3d62849591df..000000000000 --- a/bin/dotr.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off - -for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf - -call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotr.bat" %* diff --git a/dist/bin/common.bat b/dist/bin/common.bat deleted file mode 100644 index fd26dbc009f8..000000000000 --- a/dist/bin/common.bat +++ /dev/null @@ -1,63 +0,0 @@ -rem ########################################################################## -rem ## Code common to dotc.bat, dotd.bat and dotr.bat - -if defined JAVACMD ( - set _JAVACMD=%JAVACMD% - if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JAVACMD -) else if defined JAVA_HOME ( - set _JAVACMD=%JAVA_HOME%\bin\java.exe - if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JAVA_HOME -) else if defined JDK_HOME ( - set _JAVACMD=%JDK_HOME%\bin\java.exe - if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JDK_HOME -) else ( - where /q java.exe - if !ERRORLEVEL!==0 ( - for /f "delims=" %%i in ('where /f java.exe') do set _JAVA_BIN_DIR=%%~dpsi - rem we ignore Oracle path for java executable - if "!_JAVA_BIN_DIR!"=="!_JAVA_BIN_DIR:javapath=!" set _JAVACMD=!_JAVA_BIN_DIR!\java.exe - ) - if not defined _JAVACMD ( - set _PATH=C:\Progra~1\Java - for /f %%f in ('dir /ad /b "!_PATH!\jre*" 2^>NUL') do set _JAVA_HOME=!_PATH!\%%f - if not defined _JAVA_HOME ( - set _PATH=C:\opt - for /f %%f in ('dir /ad /b "!_PATH!\jdk*" 2^>NUL') do set _JAVA_HOME=!_PATH!\%%f\jre - ) - if defined _JAVA_HOME ( - if %_DEBUG%==1 echo [%_BASENAME%] Using default Java installation directory !_JAVA_HOME! - set _JAVACMD=!_JAVA_HOME!\bin\java.exe - ) - ) -) -if not exist "%_JAVACMD%" ( - echo Error: Java executable not found ^(%_JAVACMD%^) 1>&2 - set _EXITCODE=1 - goto :eof -) - -if defined DOTTY_HOME ( - set _LIB_DIR=%DOTTY_HOME%\lib -) else ( - if not defined _PROG_HOME ( - for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf - ) - set _LIB_DIR=!_PROG_HOME!\lib -) - -set _PSEP=; - -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-compiler*"') do set _DOTTY_COMP=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-interfaces*"') do set _DOTTY_INTF=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-library*"') do set _DOTTY_LIB=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-asm*"') do set _SCALA_ASM=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-library*"') do set _SCALA_LIB=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-xml*"') do set _SCALA_XML=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*compiler-interface*"') do set _SBT_INTF=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-reader-3*"') do set _JLINE_READER=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-terminal-3*"') do set _JLINE_TERMINAL=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-terminal-jna-3*"') do set _JLINE_TERMINAL_JNA=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jna-4*"') do set _JNA=%_LIB_DIR%\%%f - -rem debug -set _DEBUG_STR=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 diff --git a/dist/bin/dotc.bat b/dist/bin/dotc.bat deleted file mode 100644 index 30675e37f11c..000000000000 --- a/dist/bin/dotc.bat +++ /dev/null @@ -1,163 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem only for interactive debugging ! -set _DEBUG=0 - -rem ########################################################################## -rem ## Environment setup - -set _EXITCODE=0 - -set _BASENAME=%~n0 - -for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf - -call %_PROG_HOME%\bin\common.bat -if not %_EXITCODE%==0 goto end - -set _COMPILER_MAIN=dotty.tools.dotc.Main -set _DECOMPILER_MAIN=dotty.tools.dotc.decompiler.Main -set _REPL_MAIN=dotty.tools.repl.Main - -set _PROG_NAME=%_COMPILER_MAIN% - -call :args %* - -rem ########################################################################## -rem ## Main - -call :classpathArgs - -if defined JAVA_OPTS ( set _JAVA_OPTS=%JAVA_OPTS% -) else ( set _JAVA_OPTS=-Xmx768m -Xms768m -) -if %_DEBUG%==1 echo [%_BASENAME%] "%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% %_JVM_CP_ARGS% -Dscala.usejavacp=true %_PROG_NAME% %_SCALA_ARGS% %_RESIDUAL_ARGS% -"%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% %_JVM_CP_ARGS% ^ --Dscala.usejavacp=true ^ -%_PROG_NAME% %_SCALA_ARGS% %_RESIDUAL_ARGS% -if not %ERRORLEVEL%==0 ( - if %_DEBUG%==1 echo [%_BASENAME%] Dotty compiler execution failed - set _EXITCODE=1 - goto end -) -goto end - -rem ########################################################################## -rem ## Subroutines - -:args -set _JAVA_DEBUG= -set _HELP= -set _VERBOSE= -set _QUIET= -set _COLORS= -set _SCALA_ARGS= -set _JAVA_ARGS= -set _RESIDUAL_ARGS= - -:args_loop -if "%~1"=="" goto args_done -set __ARG=%~1 -if %_DEBUG%==1 echo [%_BASENAME%] __ARG=%__ARG% -if "%__ARG%"=="--" ( - rem for arg; do addResidual "$arg"; done; set -- ;; -) else if /i "%__ARG%"=="-h" ( - set _HELP=true - call :addScala "-help" -) else if /i "%__ARG%"=="-help" ( - set _HELP=true - call :addScala "-help" -) else if /i "%__ARG%"=="-v" ( - set _VERBOSE=true - call :addScala "-verbose" -) else if /i "%__ARG%"=="-verbose" ( - set _VERBOSE=true - call :addScala "-verbose" -) else if /i "%__ARG%"=="-debug" ( set _JAVA_DEBUG=%_DEBUG_STR% -) else if /i "%__ARG%"=="-q" ( set _QUIET=true -) else if /i "%__ARG%"=="-quiet" ( set _QUIET=true -rem Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 -) else if "%__ARG%"=="-=short" ( - call :addJava "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" -) else if /i "%__ARG%"=="-repl" ( set _PROG_NAME=%_REPL_MAIN% -) else if /i "%__ARG%"=="-compile" ( set _PROG_NAME=%_COMPILER_MAIN% -) else if /i "%__ARG%"=="-decompile" ( set _PROG_NAME=%_DECOMPILER_MAIN% -) else if /i "%__ARG%"=="print-tasty" ( - set _PROG_NAME=%_DECOMPILER_MAIN% - call :addScala "-print-tasty" -) else if /i "%__ARG%"=="-run" ( set _PROG_NAME=%_REPL_MAIN% -) else if /i "%__ARG%"=="-colors" ( set _COLORS=true -) else if /i "%__ARG%"=="-no-colors" ( set _COLORS= -) else if /i "%__ARG%"=="-with-compiler" ( set _JVM_CP_ARGS=%_PSEP%%_DOTTY_COMP% -rem break out -D and -J options and add them to JAVA_OPTS as well -rem so they reach the JVM in time to do some good. The -D options -rem will be available as system properties. -) else if "%_ARG:~0,2%"=="-D" ( - call :addJava "%__ARG%" - call :addScala "%__ARG%" -) else if "%_ARG:~0,2%"=="-J" ( - call :addJava "%__ARG%" - call :addScala "%__ARG%" -) else ( - call :addResidual "%__ARG%" -) -shift -goto args_loop -:args_done -if %_DEBUG%==1 echo [%_BASENAME%] _VERBOSE=%_VERBOSE% -if %_DEBUG%==1 echo [%_BASENAME%] _PROG_NAME=%_PROG_NAME% -goto :eof - -rem output parameter: _SCALA_ARGS -:addScala -set _SCALA_ARGS=%_SCALA_ARGS% %~1 -if %_DEBUG%==1 echo [%_BASENAME%] _SCALA_ARGS=%_SCALA_ARGS% -goto :eof - -rem output parameter: _JAVA_ARGS -:addJava -set _JAVA_ARGS=%_JAVA_ARGS% %~1 -if %_DEBUG%==1 echo [%_BASENAME%] _JAVA_ARGS=%_JAVA_ARGS% -goto :eof - -rem output parameter: _RESIDUAL_ARGS -:addResidual -set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %~1 -if %_DEBUG%==1 echo [%_BASENAME%] _RESIDUAL_ARGS=%_RESIDUAL_ARGS% -goto :eof - -rem output parameter: _JVM_CP_ARGS -:classpathArgs -rem echo dotty-compiler: %_DOTTY_COMP% -rem echo dotty-interface: %_DOTTY_INTF% -rem echo dotty-library: %_DOTTY_LIB% -rem echo scala-asm: %_SCALA_ASM% -rem echo scala-lib: %_SCALA_LIB% -rem echo scala-xml: %_SCALA_XML% -rem echo sbt-intface: %_SBT_INTF% - -set __TOOLCHAIN=%_SCALA_LIB%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_SCALA_ASM%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_SBT_INTF%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_INTF%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_LIB%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_COMP%%_PSEP% - -rem # jline -set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_READER%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_TERMINAL%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_TERMINAL_JNA%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_JNA% - -set _JVM_CP_ARGS=-classpath %__TOOLCHAIN% -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% -exit /b %_EXITCODE% -endlocal - diff --git a/dist/bin/dotd.bat b/dist/bin/dotd.bat deleted file mode 100644 index 2712062adbe7..000000000000 --- a/dist/bin/dotd.bat +++ /dev/null @@ -1,104 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem only for interactive debugging ! -set _DEBUG=0 - -rem ########################################################################## -rem ## Environment setup - -set _EXITCODE=0 - -set _BASENAME=%~n0 - -for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf - -call %_PROG_HOME%\bin\common.bat -if not %_EXITCODE%==0 goto end - -rem ########################################################################## -rem ## Main - -call :javaClassPath - -if %_DEBUG%==1 echo [%_BASENAME%] "%_JAVACMD%" -Dscala.usejavacp=true -classpath "%_CLASS_PATH%" dotty.tools.dottydoc.Main %* -"%_JAVACMD%" -Dscala.usejavacp=true -classpath "%_CLASS_PATH%" dotty.tools.dottydoc.Main %* -if not %ERRORLEVEL%==0 ( - if %_DEBUG%==1 echo [%_BASENAME%] Dottydoc execution failed - set _EXITCODE=1 - goto end -) -goto end - -rem ########################################################################## -rem ## Subroutines - -rem output parameter: _CLASS_PATH -:javaClassPath -set __LIB_DIR=%_PROG_HOME%\lib - -rem Set dotty-doc dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*dotty-doc*"') do set _DOTTY_DOC_LIB=%__LIB_DIR%\%%f - -rem Set flexmark deps: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-0*"') do set _FLEXMARK_LIBS=%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-anchorlink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-autolink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-emoji*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-strikethrough*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-tasklist*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-ins*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-superscript*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-wikilink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-yaml-front-matter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-formatter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-jira-converter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-util*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% - -rem Set jackson deps: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-annotations*"') do set _JACKSON_LIBS=%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-core*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-databind*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-dataformat-yaml*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% - -rem Set liqp dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*liqp*"') do set _LIQP_LIB=%__LIB_DIR%\%%f%_PSEP% - -rem Set ANTLR dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*antlr-3*"') do set _ANTLR_LIB=%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*antlr-runtime-3*"') do set _ANTLR_RUNTIME_LIB=%__LIB_DIR%\%%f%_PSEP% - -rem Set autolink dep: -rem conflict with flexmark-ext-autolink-0.11 -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*autolink-0.6*"') do set _AUTOLINK_LIB=%__LIB_DIR%\%%f - -rem Set snakeyaml dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*snakeyaml*"') do set _SNAKEYAML_LIB=%__LIB_DIR%\%%f%_PSEP% - -rem Set ST4 dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*ST4*"') do set _ST4_LIB=%__LIB_DIR%\%%f%_PSEP% - -rem Set jsoup dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jsoup*"') do set _JSOUP_LIB=%__LIB_DIR%\%%f%_PSEP% - -set _CLASS_PATH=%_DOTTY_LIB%%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_DOC_LIB%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SBT_INTF% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_SCALA_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_FLEXMARK_LIBS% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_JACKSON_LIBS% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_LIQP_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_ANTLR_LIB%%_PSEP%%_ANTLR_RUNTIME_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_AUTOLINK_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_SNAKEYAML_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_ST4_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_JSOUP_LIB% -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% -exit /b %_EXITCODE% -endlocal diff --git a/dist/bin/dotr.bat b/dist/bin/dotr.bat deleted file mode 100644 index 8384e7b5ab5d..000000000000 --- a/dist/bin/dotr.bat +++ /dev/null @@ -1,108 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem only for interactive debugging ! -set _DEBUG=0 - -rem ########################################################################## -rem ## Environment setup - -set _EXITCODE=0 - -set _BASENAME=%~n0 - -for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf - -call %_PROG_HOME%\bin\common.bat -if not %_EXITCODE%==0 goto end - -call :args %* - -rem ########################################################################## -rem ## Main - -set _CASE_1=0 -if %_EXECUTE_REPL%==1 set _CASE_1=1 -if %_EXECUTE_RUN%==0 if not defined _RESIDUAL_ARGS set _CASE_1=1 - -set _CASE_2=0 -if %_EXECUTE_RUN%==1 set _CASE_2=1 -if defined _RESIDUAL_ARGS set _CASE_2=1 - -rem if [ $execute_repl == true ] || ([ $execute_run == false ] && [ $options_indicator == 0 ]); then -if %_CASE_1%==1 ( - set _DOTC_ARGS= - if defined _CLASS_PATH set _DOTC_ARGS=-classpath "%_CLASS_PATH%" - set _DOTC_ARGS=!_DOTC_ARGS! %_JAVA_OPTIONS% -repl %_RESIDUAL_ARGS% - echo Starting dotty REPL... - if %_DEBUG%==1 echo [%_BASENAME%] %_PROG_HOME%\bin\dotc.bat !_DOTC_ARGS! - %_PROG_HOME%\bin\dotc.bat !_DOTC_ARGS! -rem elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then -) else if %_CASE_2%==1 ( - set _CP_ARG=%_DOTTY_LIB%%_PSEP%%_SCALA_LIB% - if defined _CLASS_PATH ( set _CP_ARG=!_CP_ARG!%_PSEP%%_CLASS_PATH% - ) else ( set _CP_ARG=!_CP_ARG!%_PSEP%. - ) - if %_CLASS_PATH_COUNT% gtr 1 ( - echo Warning: Multiple classpaths are found, dotr only use the last one. 1>&2 - ) - if %_WITH_COMPILER%==1 ( - set _CP_ARG=!_CP_ARG!%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SCALA_ASM% - ) - set _JAVA_ARGS=%_JAVA_DEBUG% -classpath "!_CP_ARG!" %_RESIDUAL_ARGS% - if %_DEBUG%==1 echo [%_BASENAME%] %_JAVACMD% !_JAVA_ARGS! - %_JAVACMD% !_JAVA_ARGS! -) else ( - echo Warning: Command option is not correct. 1>&2 -) - -goto end - -rem ########################################################################## -rem ## Subroutines - -:args -set _RESIDUAL_ARGS= -set _EXECUTE_REPL=0 -set _EXECUTE_RUN=0 -set _WITH_COMPILER=0 -set _JAVA_DEBUG= -set _CLASS_PATH_COUNT=0 -set _CLASS_PATH= -set _JVM_OPTIONS= -set _JAVA_OPTIONS= - -:args_loop -if "%1"=="" goto args_done -set "__ARG=%1" -if %_DEBUG%==1 echo [%_BASENAME%] __ARG=%__ARG% -if /i "%__ARG%"=="-repl" ( - set _EXECUTE_REPL=1 -) else if /i "%__ARG%"=="-run" ( - set _EXECUTE_RUN=1 -) else if /i "%__ARG%"=="-classpath" ( - set _CLASS_PATH=%2 - set /a _CLASS_PATH_COUNT+=1 - shift -) else if /i "%__ARG%"=="-with-compiler" ( - set _WITH_COMPILER=1 -) else if /i "%__ARG%"=="-d" ( - set _JAVA_DEBUG=%_DEBUG_STR% -) else if /i "%_ARG:~0,2%"=="-J" ( - set _JVM_OPTIONS=!_JVM_OPTIONS! %__ARG% - set _JAVA_OPTIONS=!_JAVA_OPTIONS! %__ARG% -) else ( - set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %__ARG% -) -shift -goto args_loop -:args_done -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% -exit /b %_EXITCODE% -endlocal diff --git a/project/scripts/build.bat b/project/scripts/build.bat deleted file mode 100644 index 00572fcb36df..000000000000 --- a/project/scripts/build.bat +++ /dev/null @@ -1,423 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem only for interactive debugging -set _DEBUG=0 - -rem ########################################################################## -rem ## Environment setup - -set _BASENAME=%~n0 - -set _EXITCODE=0 - -set _BOT_TOKEN=dotty-token - -rem set _DRONE_BUILD_EVENT=pull_request -set _DRONE_BUILD_EVENT= -set _DRONE_REMOTE_URL= -set _DRONE_BRANCH= - -for %%f in ("%~dp0..\..") do set _ROOT_DIR=%%~sf -set _BIN_DIR=%_ROOT_DIR%bin -set _TESTS_POS_DIR=%_ROOT_DIR%test\pos - -set _SOURCE=tests/pos/HelloWorld.scala -set _MAIN=HelloWorld -set _EXPECTED_OUTPUT=hello world - -call :args %* -if not %_EXITCODE%==0 goto end -if defined _HELP call :help & exit /b %_EXITCODE% - -if exist "C:\Temp\" ( set _TMP_DIR=C:\Temp -) else ( set _TMP_DIR=%TEMP% -) -set _OUT_DIR=%_TMP_DIR%\%_BASENAME%_out -if not exist "%_OUT_DIR%" mkdir "%_OUT_DIR%" - -set _OUT1_DIR=%_TMP_DIR%\%_BASENAME%_out1 -if not exist "%_OUT1_DIR%" mkdir "%_OUT1_DIR%" - -set _TMP_FILE=%_TMP_DIR%\%_BASENAME%_tmp.txt - -rem see file project/scripts/sbt -rem SBT uses the value of the JAVA_OPTS environment variable if defined, rather than the config. -set JAVA_OPTS=-Xmx2048m ^ --XX:ReservedCodeCacheSize=2048m ^ --XX:MaxMetaspaceSize=1024m - -set SBT_OPTS=-Ddotty.drone.mem=4096m ^ --Dsbt.ivy.home=%USERPROFILE%\.ivy2\ ^ --Dsbt.log.noformat=true - -rem ########################################################################## -rem ## Main - -call :init -if not %_EXITCODE%==0 goto end - -if defined _CLEAN_ALL ( - call :clean_all - if not !_EXITCODE!==0 goto end -) -if defined _CLONE ( - call :clone - if not !_EXITCODE!==0 goto end -) -if defined _BUILD ( - call :test - if not !_EXITCODE!==0 goto end -) -if defined _BOOTSTRAP ( - call :test_bootstrapped - rem if not !_EXITCODE!==0 goto end - if not !_EXITCODE!==0 ( - if defined _IGNORE ( echo ###### Warning: _EXITCODE=!_EXITCODE! ####### 1>&2 - ) else ( goto end - ) - ) -) -if defined _DOCUMENTATION ( - call :documentation - if not !_EXITCODE!==0 goto end -) - -if defined _ARCHIVES ( - call :archives - if not !_EXITCODE!==0 goto end -) -goto end - -rem ########################################################################## -rem ## Subroutines - -rem input parameter: %* -rem output parameters: _VERBOSE, _DOCUMENTATION -:args -set _ARCHIVES= -set _BOOTSTRAP= -set _BUILD= -set _CLEAN_ALL= -set _DOCUMENTATION= -set _HELP= -set _VERBOSE=0 - -:args_loop -set __ARG=%~1 -if not defined __ARG goto args_done -if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof -) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 -) else if /i "%__ARG:~0,4%"=="arch" ( - if not "%__ARG:~-5%"=="-only" set _BUILD=1& set _BOOTSTRAP=1 - set _ARCHIVES=1 -) else if /i "%__ARG:~0,4%"=="boot" ( - if not "%__ARG:~-5%"=="-only" set _BUILD=1 - set _BOOTSTRAP=1 -) else if /i "%__ARG%"=="cleanall" ( set _CLEAN_ALL=1 -) else if /i "%__ARG:~0,3%"=="doc" ( - if not "%__ARG:~-5%"=="-only" set _BUILD=1& set _BOOTSTRAP=1 - set _DOCUMENTATION=1 -) else ( - echo Error: Unknown subcommand %__ARG% - set _EXITCODE=1 - goto :eof -) -shift -goto args_loop -:args_done -goto :eof - -:help -echo Usage: %_BASENAME% { options ^| subcommands } -echo Options: -echo -verbose display environment settings -echo Subcommands: -echo arch[ives] generate gz/zip archives (after bootstrap) -echo arch[ives]-only generate ONLY gz/zip archives -echo boot[strap] generate compiler bootstrap (after build) -echo boot[strap]-only generate ONLY compiler bootstrap -echo cleanall clean project (sbt+git) and quit -echo doc[umentation] generate documentation (after bootstrap) -echo doc[umentation]-only] generate ONLY documentation -echo help display this help message -goto :eof - -rem output parameters: _GIT_CMD, _SBT_CMD -:init -where /q git.exe -if not %ERRORLEVEL%==0 ( - echo Error: Git command not found ^(check your PATH variable^) 1>&2 - set _EXITCODE=1 - goto end -) -set _GIT_CMD=git.exe - -where /q sbt.bat -if not %ERRORLEVEL%==0 ( - echo Error: SBT command not found ^(check your PATH variable^) 1>&2 - set _EXITCODE=1 - goto end -) -rem full path is required for sbt to run successfully -for /f %%i in ('where sbt.bat') do set _SBT_CMD=%%i - -if %_VERBOSE%==1 ( - for /f %%i in ('where git.exe') do set _GIT_CMD1=%%i - echo _GIT_CMD=!_GIT_CMD1! - echo _SBT_CMD=%_SBT_CMD% - echo JAVA_OPTS=%JAVA_OPTS% - echo SBT_OPTS=%SBT_OPTS% - echo. -) -goto :eof - -:clean_all -echo run sbt clean and git clean -xdf -if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" clean -call "%_SBT_CMD%" clean -if not %ERRORLEVEL%==0 ( - set _EXITCODE=1 - goto :eof -) -if %_DEBUG%==1 echo [%_BASENAME%] %_GIT_CMD% clean -xdf -%_GIT_CMD% clean -xdf -if not %ERRORLEVEL%==0 ( - set _EXITCODE=1 - goto :eof -) -goto :eof - -:clone -if "%_DRONE_BUILD_EVENT%"=="pull_request" if defined _DRONE_REMOTE_URL ( - %_GIT_CMD% config user.email "dotty.bot@epfl.ch" - %_GIT_CMD% config user.name "Dotty CI" - %_GIT_CMD% pull "%_DRONE_REMOTE_URL%" "%_DRONE_BRANCH%" -) -if %_DEBUG%==1 echo [%_BASENAME%] %_GIT_CMD% submodule update --init --recursive --jobs 3 -%_GIT_CMD% submodule update --init --recursive --jobs 3 -if not %ERRORLEVEL%==0 ( - echo Error: Failed to update Git submodules 1>&2 - set _EXITCODE=1 - goto :eof -) -goto :eof - -:clear_out -set __OUT_DIR=%~1 - -if exist "%__OUT_DIR%" ( - if %_DEBUG%==1 echo [%_BASENAME%] del /s /q "%__OUT_DIR%\*" 1^>NUL - del /s /q "%__OUT_DIR%\*" 1>NUL -) -goto :eof - -:grep -set __PATTERN=%~1 -set __FILE=%~2 - -if %_DEBUG%==1 echo [%_BASENAME%] findstr "%__PATTERN%" "%__FILE% -findstr "%__PATTERN%" "%__FILE%" -if not %ERRORLEVEL%==0 ( - echo Error: Failed to find pattern "%__PATTERN%" in file %__FILE% 1>&2 - set _EXITCODE=1 - goto :eof -) -goto :eof - -rem ## see file project/scripts/cmdTests -:cmdTests -echo testing sbt dotc and dotr -if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotr -classpath %_OUT_DIR% %_MAIN%" ^> "%_TMP_FILE%" -call "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotr -classpath %_OUT_DIR% %_MAIN%" > "%_TMP_FILE%" -call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -rem # check that `sbt dotc` compiles and `sbt dotr` runs it -echo testing sbt dotc -from-tasty and dotr -classpath -call :clear_out "%_OUT_DIR%" -call "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotc -from-tasty -classpath %_OUT_DIR% -d %_OUT1_DIR% %_MAIN% ;dotr -classpath %_OUT1_DIR% %_MAIN%" > "%_TMP_FILE%" -call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -rem # check that `sbt dotc -decompile` runs -echo testing sbt dotc -decompile -call "%_SBT_CMD%" ";dotc -decompile -color:never -classpath %_OUT_DIR% %_MAIN%" > "%_TMP_FILE%" -call :grep "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -echo testing sbt dotr with no -classpath -call :clear_out "%_OUT_DIR%" -if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" ";dotc %_SOURCE% ; dotr %_MAIN%" ^> "%_TMP_FILE%" -call "%_SBT_CMD%" ";dotc %_SOURCE% ; dotr %_MAIN%" > "%_TMP_FILE%" -call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -echo testing loading tasty from .tasty file in jar -call :clear_out "%_OUT_DIR%" -call "%_SBT_CMD%" ";dotc -d %_OUT_DIR%\out.jar %_SOURCE%; dotc -decompile -classpath %_OUT_DIR%/out.jar -color:never %_MAIN%" > "%_TMP_FILE%" -call :grep "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -goto :eof - -:test -if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";compile ;test" -call "%_SBT_CMD%" ";compile ;test" -if not %ERRORLEVEL%==0 ( - echo Error: Failed to build Dotty 1>&2 - set _EXITCODE=1 - goto :eof -) - -rem ## see shell script project/scripts/cmdTests -call :cmdTests -if not %_EXITCODE%==0 goto :eof - -goto :eof - -:test_pattern -set __PATTERN=%~1 -set __FILE=%~2 - -set /p __PATTERN2=<"%__FILE%" -if not "%__PATTERN2%"=="%__PATTERN%" ( - echo Error: failed to find pattern "%__PATTERN%" in file %__FILE% 1>&2 - set _EXITCODE=1 - goto :eof -) -goto :eof - -rem ## see shell script project/scripts/bootstrapCmdTests -:bootstrapCmdTests -rem # check that benchmarks can run -if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" -call "%_SBT_CMD%" "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" - -rem # The above is here as it relies on the bootstrapped library. -call "%_SBT_CMD%" "dotty-bench-bootstrapped/jmh:run 1 1 tests/pos/alias.scala" -call "%_SBT_CMD%" "dotty-bench-bootstrapped/jmh:run 1 1 -with-compiler compiler/src/dotty/tools/dotc/core/Types.scala" - -echo testing scala.quoted.Expr.run from sbt dotr -call "%_SBT_CMD%" ";dotty-compiler-bootstrapped/dotc tests/run-with-compiler/quote-run.scala; dotty-compiler-bootstrapped/dotr -with-compiler Test" > "%_TMP_FILE%" -call :grep "val a: scala.Int = 3" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -rem # setup for `dotc`/`dotr` script tests -if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" dist-bootstrapped/pack -call "%_SBT_CMD%" dist-bootstrapped/pack - -rem # check that `dotc` compiles and `dotr` runs it -echo testing ./bin/dotc and ./bin/dotr -call :clear_out "%_OUT_DIR%" -call %_BIN_DIR%\dotc.bat "%_SOURCE%" -d "%_OUT_DIR%" -call %_BIN_DIR%\dotr.bat -classpath "%_OUT_DIR%" "%_MAIN%" > "%_TMP_FILE%" -call :test_pattern "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" - -rem # check that `dotc -from-tasty` compiles and `dotr` runs it -echo testing ./bin/dotc -from-tasty and dotr -classpath -call :clear_out "%_OUT1_DIR%" -call %_BIN_DIR%\dotc.bat -from-tasty -classpath "%_OUT_DIR%" -d "%_OUT1_DIR%" "%_MAIN%" -call %_BIN_DIR%\dotr.bat -classpath "%_OUT1_DIR%" "%_MAIN%" > "%_TMP_FILE%" -call :test_pattern "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" - -rem # echo ":quit" | ./dist-bootstrapped/target/pack/bin/dotr # not supported by CI - -echo testing ./bin/dotd -call :clear_out "%_OUT_DIR%" -call %_BIN_DIR%\dotd.bat -project Hello -siteroot "%_OUT_DIR%" "%_SOURCE%" - -goto :eof - -:test_bootstrapped -if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" -call "%_SBT_CMD%" ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" -if not %ERRORLEVEL%==0 ( - echo Error: failed to bootstrap Dotty 1>&2 - set _EXITCODE=1 - goto :eof -) - -call :bootstrapCmdTests -if not %_EXITCODE%==0 goto :eof - -goto :eof - -:documentation -rem # make sure that _BOT_TOKEN is set -if not defined _BOT_TOKEN ( - echo Error: _BOT_TOKEN env unset, unable to push without password 1>&2 - set _EXITCODE=1 - goto :eof -) -for /f %%i in ('cd') do set _PWD=%%~si - -echo Working directory: %_PWD% - -call "%_SBT_CMD%" genDocs - -rem # make sure that the previous command actually succeeded -if not exist "%_PWD%\docs\_site\" ( - echo Error: output directory did not exist: %_PWD%\docs\_site 1>&2 - set _EXITCODE=1 - goto :eof -) - -goto :eof - -rem # save current head for commit message in gh-pages -rem for /f %%i in ('%_GIT_CMD% rev-parse HEAD 2^>NUL') do set _GIT_HEAD=%%i - -rem # set up remote and github credentials -rem %_GIT_CMD% remote add doc-remote "https://dotty-bot:%_BOT_TOKEN%@github.com/lampepfl/dotty-website.git" -rem %_GIT_CMD% config user.name "dotty-bot" -rem %_GIT_CMD% config user.email "dotty-bot@d-d.me" - -rem # check out correct branch -rem %_GIT_CMD% fetch doc-remote gh-pages -rem %_GIT_CMD% checkout gh-pages - -rem # move newly generated _site dir to $PWD -rem move %_PWD%\docs\_site . - -rem # remove everything BUT _site dir -rem del /f /q /s -rf !(_site) - -rem # copy new contents to $PWD -rem move _site\* . - -rem # remove now empty _site dir -rem del /f /q /s _site - -rem # add all contents of $PWD to commit -rem %_GIT_CMD% add -A -rem %_GIT_CMD% commit -m "Update gh-pages site for %_GIT_HEAD%" || echo "nothing new to commit" - -rem # push to doc-remote -rem %_GIT_CMD% push doc-remote || echo "couldn't push, since nothing was added" - -goto :eof - -:archives -if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" dist-bootstrapped/packArchive -call "%_SBT_CMD%" dist-bootstrapped/packArchive -rem output directory for gz/zip archives -set __TARGET_DIR=%_ROOT_DIR%\dist-bootstrapped\target -if not exist "%__TARGET_DIR%\" ( - echo Error: Directory target not found 1>&2 - set _EXITCODE=1 - goto :eof -) -if %_DEBUG%==1 ( - echo. - echo Output directory: %__TARGET_DIR%\ - dir /b /a-d "%__TARGET_DIR%" -) -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% -exit /b %_EXITCODE% diff --git a/setenv.bat b/setenv.bat deleted file mode 100644 index 3e40b02725ac..000000000000 --- a/setenv.bat +++ /dev/null @@ -1,205 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem only for interactive debugging -set _DEBUG=0 - -rem ########################################################################## -rem ## Environment setup - -set _BASENAME=%~n0 - -set _EXITCODE=0 - -call :args %* -if not %_EXITCODE%==0 goto end -if defined _HELP call :help & exit /b %_EXITCODE% - -rem ########################################################################## -rem ## Main - -set _JDK_PATH= -set _SBT_PATH= -set _GIT_PATH= - -call :javac -if not %_EXITCODE%==0 goto end - -call :sbt -if not %_EXITCODE%==0 goto end - -call :git -if not %_EXITCODE%==0 goto end - -goto end - -rem ########################################################################## -rem ## Subroutines - -rem input parameter: %* -rem output parameter: _HELP, _VERBOSE -:args -set _HELP= -set _VERBOSE=0 - -:args_loop -set __ARG=%~1 -if not defined __ARG goto args_done -if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof -) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 -) else ( - echo Error: Unknown subcommand %__ARG% 1>&2 - set _EXITCODE=1 - goto :eof -) -shift -goto args_loop -:args_done -goto :eof - -:help -echo Usage: %_BASENAME% { options ^| subcommands } -echo Options: -echo -verbose display environment settings -echo Subcommands: -echo help display this help message -goto :eof - -:javac -where /q javac.exe -if %ERRORLEVEL%==0 goto :eof - -if defined JDK_HOME ( - set _JDK_HOME=%JDK_HOME% - if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JDK_HOME -) else ( - set _PATH=C:\Progra~1\Java - for /f "delims=" %%f in ('dir /ad /b "!_PATH!\jdk1.8*" 2^>NUL') do set _JDK_HOME=!_PATH!\%%f - if not defined _JDK_HOME ( - set _PATH=C:\opt - for /f %%f in ('dir /ad /b "!_PATH!\jdk1.8*" 2^>NUL') do set _JDK_HOME=!_PATH!\%%f - ) - if defined _JDK_HOME ( - if %_DEBUG%==1 echo [%_BASENAME%] Using default Java SDK installation directory !_JDK_HOME! - ) -) -if not exist "%_JDK_HOME%\bin\javac.exe" ( - echo Error: javac executable not found ^(%_JDK_HOME%^) 1>&2 - set _EXITCODE=1 - goto :eof -) -rem variable _JDK_PATH is prepended to PATH, so path separator must appear as last character -set "_JDK_PATH=%_JDK_HOME%\bin;" -goto :eof - -:sbt -where /q sbt.bat -if %ERRORLEVEL%==0 goto :eof - -if defined SBT_HOME ( - set _SBT_HOME=%SBT_HOME% - if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable SBT_HOME -) else ( - set _PATH=C:\opt - for /f %%f in ('dir /ad /b "!_PATH!\sbt-1*" 2^>NUL') do set _SBT_HOME=!_PATH!\%%f - if defined _SBT_HOME ( - if %_DEBUG%==1 echo [%_BASENAME%] Using default sbt installation directory !_SBT_HOME! - ) -) -if not exist "%_SBT_HOME%\bin\sbt.bat" ( - echo Error: sbt executable not found ^(%_SBT_HOME%^) 1>&2 - set _EXITCODE=1 - goto :eof -) -set "_SBT_PATH=;%_SBT_HOME%\bin" -goto :eof - -:git -where /q git.exe -if %ERRORLEVEL%==0 goto :eof - -if defined GIT_HOME ( - set _GIT_HOME=%GIT_HOME% - if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable GIT_HOME -) else ( - set __PATH=C:\opt - if exist "!__PATH!\Git\" ( set _GIT_HOME=!__PATH!\Git - ) else ( - for /f %%f in ('dir /ad /b "!__PATH!\Git*" 2^>NUL') do set _GIT_HOME=!__PATH!\%%f - if not defined _GIT_HOME ( - set __PATH=C:\Progra~1 - for /f %%f in ('dir /ad /b "!__PATH!\Git*" 2^>NUL') do set _GIT_HOME=!__PATH!\%%f - ) - ) - if defined _GIT_HOME ( - if %_DEBUG%==1 echo [%_BASENAME%] Using default Git installation directory !_GIT_HOME! - ) -) -if not exist "%_GIT_HOME%\bin\git.exe" ( - echo Error: Git executable not found ^(%_GIT_HOME%^) 1>&2 - set _EXITCODE=1 - goto :eof -) -set "_GIT_PATH=;%_GIT_HOME%\bin;%_GIT_HOME%\usr\bin" -goto :eof - -rem output parameter: _SBT_VERSION -rem Note: SBT requires special handling to know its version (no comment) -:sbt_version -set _SBT_VERSION= -for /f %%i in ('where sbt.bat') do for %%f in ("%%~dpi..") do set __SBT_LAUNCHER=%%~sf\bin\sbt-launch.jar -for /f "tokens=1,*" %%i in ('java.exe -jar "%__SBT_LAUNCHER%" sbtVersion ^| findstr [0-9].[0-9]') do set _SBT_VERSION=%%j -for /f "tokens=1,*" %%i in ('java.exe -jar "%__SBT_LAUNCHER%" scalaVersion ^| findstr [0-9].[0-9]') do set _SBT_VERSION=%_SBT_VERSION%/%%j -goto :eof - -:print_env -set __VERBOSE=%1 -set __VERSIONS_LINE1= -set __VERSIONS_LINE2= -set __WHERE_ARGS= -where /q javac.exe -if %ERRORLEVEL%==0 ( - for /f "tokens=1,2,*" %%i in ('javac.exe -version 2^>^&1') do set "__VERSIONS_LINE1=%__VERSIONS_LINE1% javac %%j," - set __WHERE_ARGS=%__WHERE_ARGS% javac.exe -) -where /q java.exe -if %ERRORLEVEL%==0 ( - for /f "tokens=1,2,3,*" %%i in ('java.exe -version 2^>^&1 ^| findstr version 2^>^&1') do set "__VERSIONS_LINE1=%__VERSIONS_LINE1% java %%~k," - set __WHERE_ARGS=%__WHERE_ARGS% java.exe -) -call :sbt_version -if defined _SBT_VERSION ( - set __VERSIONS_LINE2=%__VERSIONS_LINE2% sbt %_SBT_VERSION%, - set __WHERE_ARGS=%__WHERE_ARGS% sbt.bat -) -where /q git.exe -if %ERRORLEVEL%==0 ( - for /f "tokens=1,2,*" %%i in ('git.exe --version') do set __VERSIONS_LINE2=%__VERSIONS_LINE2% git %%k, - set __WHERE_ARGS=%__WHERE_ARGS% git.exe -) -where /q diff.exe -if %ERRORLEVEL%==0 ( - for /f "tokens=1-3,*" %%i in ('diff.exe --version ^| findstr diff') do set __VERSIONS_LINE2=%__VERSIONS_LINE2% diff %%l - set __WHERE_ARGS=%__WHERE_ARGS% diff.exe -) -echo Tool versions: -echo %__VERSIONS_LINE1% -echo %__VERSIONS_LINE2% -if %__VERBOSE%==1 ( - rem if %_DEBUG%==1 echo [%_BASENAME%] where %__WHERE_ARGS% - echo Tool paths: - for /f "tokens=*" %%p in ('where %__WHERE_ARGS%') do echo %%p -) -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -endlocal & ( - if not defined JAVA_HOME set JAVA_HOME=%_JDK_HOME% - set "PATH=%_JDK_PATH%%PATH%%_SBT_PATH%%_GIT_PATH%;%~dp0project\scripts" - call :print_env %_VERBOSE% - if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% - for /f "delims==" %%i in ('set ^| findstr /b "_"') do set %%i= -) From 6688ea66fe976c534c5ea4d822ea9fcfc428bc0c Mon Sep 17 00:00:00 2001 From: michelou Date: Wed, 14 Nov 2018 17:56:23 +0100 Subject: [PATCH 11/22] added batch scripts for a new PR --- bin/common.bat | 119 +++++++++++ bin/dotc.bat | 5 + bin/dotd.bat | 5 + bin/dotr.bat | 5 + dist/bin/common.bat | 63 ++++++ dist/bin/dotc.bat | 163 +++++++++++++++ dist/bin/dotd.bat | 104 ++++++++++ dist/bin/dotr.bat | 108 ++++++++++ project/scripts/build.bat | 426 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 998 insertions(+) create mode 100644 bin/common.bat create mode 100644 bin/dotc.bat create mode 100644 bin/dotd.bat create mode 100644 bin/dotr.bat create mode 100644 dist/bin/common.bat create mode 100644 dist/bin/dotc.bat create mode 100644 dist/bin/dotd.bat create mode 100644 dist/bin/dotr.bat create mode 100644 project/scripts/build.bat diff --git a/bin/common.bat b/bin/common.bat new file mode 100644 index 000000000000..264b3fedaa37 --- /dev/null +++ b/bin/common.bat @@ -0,0 +1,119 @@ +@echo off +setlocal enabledelayedexpansion + +rem # Wrapper for the published dotc/dotr script that check for file changes +rem # and use sbt to re build the compiler as needed. + +rem ########################################################################## +rem ## Environment setup + +set _BASENAME=%~n0 + +set _EXITCODE=0 + +for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf + +rem # Marker file used to obtain the date of latest call to sbt-back +set _VERSION=%_ROOT_DIR%\dist-bootstrapped\target\pack\VERSION + +rem ########################################################################## +rem ## Main + +rem # Create the target if absent or if file changed in ROOT/compiler +call :new_files "%_VERSION%" + +if exist "%_VERSION%" if %_NEW_FILES%==0 goto target +echo Building Dotty... +pushd %_ROOT% +sbt.bat "dist-bootstrapped/pack" +popd + +:target +set _TARGET=%~1 +rem # Mutates %* by deleting the first element (%1) +shift + +call %_TARGET% %* + +goto end + +rem ########################################################################## +rem ## Subroutines + +rem input parameter: %1=version file +rem Output parameter: _NEW_FILES +:new_files +set __VERSION_FILE=%~1 + +call :timestamp "%__VERSION_FILE%" +set __VERSION_TIMESTAMP=%_TIMESTAMP% + +set __JAVA_SOURCE_FILES= +for /f %%i in ('dir /s /b "%_ROOT_DIR%compiler\*.java" 2^>NUL') do ( + set __JAVA_SOURCE_FILES=!__JAVA_SOURCE_FILES! %%i +) +set __SCALA_SOURCE_FILES= +for /f %%i in ('dir /s /b "%_ROOT_DIR%compiler\*.scala" 2^>NUL') do ( + set __SCALA_SOURCE_FILES=!__SCALA_SOURCE_FILES! %%i +) + +call :compile_required "%__VERSION_TIMESTAMP%" "%__JAVA_SOURCE_FILES% %__SCALA_SOURCE_FILES%" +set _NEW_FILES=%_COMPILE_REQUIRED% + +goto :eof + +rem input parameter: 1=timestamp file 2=source files +rem output parameter: _COMPILE_REQUIRED +:compile_required +set __TIMESTAMP_FILE=%~1 +set __SOURCE_FILES=%~2 + +set __SOURCE_TIMESTAMP=00000000000000 +for %%i in (%__SOURCE_FILES%) do ( + call :timestamp "%%i" + call :newer !_TIMESTAMP! !__SOURCE_TIMESTAMP! + if !_NEWER!==1 set __SOURCE_TIMESTAMP=!_TIMESTAMP! +) +if exist "%__TIMESTAMP_FILE%" ( set /p __CLASS_TIMESTAMP=<%__TIMESTAMP_FILE% +) else ( set __CLASS_TIMESTAMP=00000000000000 +) + +call :newer %__SOURCE_TIMESTAMP% %__CLASS_TIMESTAMP% +set _COMPILE_REQUIRED=%_NEWER% +goto :eof + +rem output parameter: _NEWER +:newer +set __TIMESTAMP1=%~1 +set __TIMESTAMP2=%~2 + +set __TIMESTAMP1_DATE=%__TIMESTAMP1:~0,8% +set __TIMESTAMP1_TIME=%__TIMESTAMP1:~-6% + +set __TIMESTAMP2_DATE=%__TIMESTAMP2:~0,8% +set __TIMESTAMP2_TIME=%__TIMESTAMP2:~-6% + +if %__TIMESTAMP1_DATE% gtr %__TIMESTAMP2_DATE% ( set _NEWER=1 +) else if %__TIMESTAMP1_DATE% lss %__TIMESTAMP2_DATE% ( set _NEWER=0 +) else if %__TIMESTAMP1_TIME% gtr %__TIMESTAMP2_TIME% ( set _NEWER=1 +) else ( set _NEWER=0 +) +goto :eof + +rem input parameter: 1=file path +rem output parameter: _TIMESTAMP +:timestamp +set __FILE_PATH=%~1 + +set _TIMESTAMP=00000000000000 +for /f %%i in ('powershell -C "(Get-ChildItem '%__FILE_PATH%').LastWriteTime | Get-Date -uformat %%Y%%m%%d%%H%%M%%S"') do ( + set _TIMESTAMP=%%i +) +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +exit /b %_EXITCODE% +endlocal \ No newline at end of file diff --git a/bin/dotc.bat b/bin/dotc.bat new file mode 100644 index 000000000000..6cb1b20510dd --- /dev/null +++ b/bin/dotc.bat @@ -0,0 +1,5 @@ +@echo off + +for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf + +call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotc.bat" %* diff --git a/bin/dotd.bat b/bin/dotd.bat new file mode 100644 index 000000000000..5544e2bed952 --- /dev/null +++ b/bin/dotd.bat @@ -0,0 +1,5 @@ +@echo off + +for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf + +call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotd.bat" %* diff --git a/bin/dotr.bat b/bin/dotr.bat new file mode 100644 index 000000000000..3d62849591df --- /dev/null +++ b/bin/dotr.bat @@ -0,0 +1,5 @@ +@echo off + +for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf + +call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotr.bat" %* diff --git a/dist/bin/common.bat b/dist/bin/common.bat new file mode 100644 index 000000000000..fd26dbc009f8 --- /dev/null +++ b/dist/bin/common.bat @@ -0,0 +1,63 @@ +rem ########################################################################## +rem ## Code common to dotc.bat, dotd.bat and dotr.bat + +if defined JAVACMD ( + set _JAVACMD=%JAVACMD% + if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JAVACMD +) else if defined JAVA_HOME ( + set _JAVACMD=%JAVA_HOME%\bin\java.exe + if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JAVA_HOME +) else if defined JDK_HOME ( + set _JAVACMD=%JDK_HOME%\bin\java.exe + if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JDK_HOME +) else ( + where /q java.exe + if !ERRORLEVEL!==0 ( + for /f "delims=" %%i in ('where /f java.exe') do set _JAVA_BIN_DIR=%%~dpsi + rem we ignore Oracle path for java executable + if "!_JAVA_BIN_DIR!"=="!_JAVA_BIN_DIR:javapath=!" set _JAVACMD=!_JAVA_BIN_DIR!\java.exe + ) + if not defined _JAVACMD ( + set _PATH=C:\Progra~1\Java + for /f %%f in ('dir /ad /b "!_PATH!\jre*" 2^>NUL') do set _JAVA_HOME=!_PATH!\%%f + if not defined _JAVA_HOME ( + set _PATH=C:\opt + for /f %%f in ('dir /ad /b "!_PATH!\jdk*" 2^>NUL') do set _JAVA_HOME=!_PATH!\%%f\jre + ) + if defined _JAVA_HOME ( + if %_DEBUG%==1 echo [%_BASENAME%] Using default Java installation directory !_JAVA_HOME! + set _JAVACMD=!_JAVA_HOME!\bin\java.exe + ) + ) +) +if not exist "%_JAVACMD%" ( + echo Error: Java executable not found ^(%_JAVACMD%^) 1>&2 + set _EXITCODE=1 + goto :eof +) + +if defined DOTTY_HOME ( + set _LIB_DIR=%DOTTY_HOME%\lib +) else ( + if not defined _PROG_HOME ( + for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf + ) + set _LIB_DIR=!_PROG_HOME!\lib +) + +set _PSEP=; + +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-compiler*"') do set _DOTTY_COMP=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-interfaces*"') do set _DOTTY_INTF=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-library*"') do set _DOTTY_LIB=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-asm*"') do set _SCALA_ASM=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-library*"') do set _SCALA_LIB=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-xml*"') do set _SCALA_XML=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*compiler-interface*"') do set _SBT_INTF=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-reader-3*"') do set _JLINE_READER=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-terminal-3*"') do set _JLINE_TERMINAL=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-terminal-jna-3*"') do set _JLINE_TERMINAL_JNA=%_LIB_DIR%\%%f +for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jna-4*"') do set _JNA=%_LIB_DIR%\%%f + +rem debug +set _DEBUG_STR=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 diff --git a/dist/bin/dotc.bat b/dist/bin/dotc.bat new file mode 100644 index 000000000000..30675e37f11c --- /dev/null +++ b/dist/bin/dotc.bat @@ -0,0 +1,163 @@ +@echo off +setlocal enabledelayedexpansion + +rem only for interactive debugging ! +set _DEBUG=0 + +rem ########################################################################## +rem ## Environment setup + +set _EXITCODE=0 + +set _BASENAME=%~n0 + +for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf + +call %_PROG_HOME%\bin\common.bat +if not %_EXITCODE%==0 goto end + +set _COMPILER_MAIN=dotty.tools.dotc.Main +set _DECOMPILER_MAIN=dotty.tools.dotc.decompiler.Main +set _REPL_MAIN=dotty.tools.repl.Main + +set _PROG_NAME=%_COMPILER_MAIN% + +call :args %* + +rem ########################################################################## +rem ## Main + +call :classpathArgs + +if defined JAVA_OPTS ( set _JAVA_OPTS=%JAVA_OPTS% +) else ( set _JAVA_OPTS=-Xmx768m -Xms768m +) +if %_DEBUG%==1 echo [%_BASENAME%] "%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% %_JVM_CP_ARGS% -Dscala.usejavacp=true %_PROG_NAME% %_SCALA_ARGS% %_RESIDUAL_ARGS% +"%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% %_JVM_CP_ARGS% ^ +-Dscala.usejavacp=true ^ +%_PROG_NAME% %_SCALA_ARGS% %_RESIDUAL_ARGS% +if not %ERRORLEVEL%==0 ( + if %_DEBUG%==1 echo [%_BASENAME%] Dotty compiler execution failed + set _EXITCODE=1 + goto end +) +goto end + +rem ########################################################################## +rem ## Subroutines + +:args +set _JAVA_DEBUG= +set _HELP= +set _VERBOSE= +set _QUIET= +set _COLORS= +set _SCALA_ARGS= +set _JAVA_ARGS= +set _RESIDUAL_ARGS= + +:args_loop +if "%~1"=="" goto args_done +set __ARG=%~1 +if %_DEBUG%==1 echo [%_BASENAME%] __ARG=%__ARG% +if "%__ARG%"=="--" ( + rem for arg; do addResidual "$arg"; done; set -- ;; +) else if /i "%__ARG%"=="-h" ( + set _HELP=true + call :addScala "-help" +) else if /i "%__ARG%"=="-help" ( + set _HELP=true + call :addScala "-help" +) else if /i "%__ARG%"=="-v" ( + set _VERBOSE=true + call :addScala "-verbose" +) else if /i "%__ARG%"=="-verbose" ( + set _VERBOSE=true + call :addScala "-verbose" +) else if /i "%__ARG%"=="-debug" ( set _JAVA_DEBUG=%_DEBUG_STR% +) else if /i "%__ARG%"=="-q" ( set _QUIET=true +) else if /i "%__ARG%"=="-quiet" ( set _QUIET=true +rem Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 +) else if "%__ARG%"=="-=short" ( + call :addJava "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" +) else if /i "%__ARG%"=="-repl" ( set _PROG_NAME=%_REPL_MAIN% +) else if /i "%__ARG%"=="-compile" ( set _PROG_NAME=%_COMPILER_MAIN% +) else if /i "%__ARG%"=="-decompile" ( set _PROG_NAME=%_DECOMPILER_MAIN% +) else if /i "%__ARG%"=="print-tasty" ( + set _PROG_NAME=%_DECOMPILER_MAIN% + call :addScala "-print-tasty" +) else if /i "%__ARG%"=="-run" ( set _PROG_NAME=%_REPL_MAIN% +) else if /i "%__ARG%"=="-colors" ( set _COLORS=true +) else if /i "%__ARG%"=="-no-colors" ( set _COLORS= +) else if /i "%__ARG%"=="-with-compiler" ( set _JVM_CP_ARGS=%_PSEP%%_DOTTY_COMP% +rem break out -D and -J options and add them to JAVA_OPTS as well +rem so they reach the JVM in time to do some good. The -D options +rem will be available as system properties. +) else if "%_ARG:~0,2%"=="-D" ( + call :addJava "%__ARG%" + call :addScala "%__ARG%" +) else if "%_ARG:~0,2%"=="-J" ( + call :addJava "%__ARG%" + call :addScala "%__ARG%" +) else ( + call :addResidual "%__ARG%" +) +shift +goto args_loop +:args_done +if %_DEBUG%==1 echo [%_BASENAME%] _VERBOSE=%_VERBOSE% +if %_DEBUG%==1 echo [%_BASENAME%] _PROG_NAME=%_PROG_NAME% +goto :eof + +rem output parameter: _SCALA_ARGS +:addScala +set _SCALA_ARGS=%_SCALA_ARGS% %~1 +if %_DEBUG%==1 echo [%_BASENAME%] _SCALA_ARGS=%_SCALA_ARGS% +goto :eof + +rem output parameter: _JAVA_ARGS +:addJava +set _JAVA_ARGS=%_JAVA_ARGS% %~1 +if %_DEBUG%==1 echo [%_BASENAME%] _JAVA_ARGS=%_JAVA_ARGS% +goto :eof + +rem output parameter: _RESIDUAL_ARGS +:addResidual +set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %~1 +if %_DEBUG%==1 echo [%_BASENAME%] _RESIDUAL_ARGS=%_RESIDUAL_ARGS% +goto :eof + +rem output parameter: _JVM_CP_ARGS +:classpathArgs +rem echo dotty-compiler: %_DOTTY_COMP% +rem echo dotty-interface: %_DOTTY_INTF% +rem echo dotty-library: %_DOTTY_LIB% +rem echo scala-asm: %_SCALA_ASM% +rem echo scala-lib: %_SCALA_LIB% +rem echo scala-xml: %_SCALA_XML% +rem echo sbt-intface: %_SBT_INTF% + +set __TOOLCHAIN=%_SCALA_LIB%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_SCALA_ASM%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_SBT_INTF%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_INTF%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_LIB%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_COMP%%_PSEP% + +rem # jline +set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_READER%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_TERMINAL%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_TERMINAL_JNA%%_PSEP% +set __TOOLCHAIN=%__TOOLCHAIN%%_JNA% + +set _JVM_CP_ARGS=-classpath %__TOOLCHAIN% +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% +exit /b %_EXITCODE% +endlocal + diff --git a/dist/bin/dotd.bat b/dist/bin/dotd.bat new file mode 100644 index 000000000000..2712062adbe7 --- /dev/null +++ b/dist/bin/dotd.bat @@ -0,0 +1,104 @@ +@echo off +setlocal enabledelayedexpansion + +rem only for interactive debugging ! +set _DEBUG=0 + +rem ########################################################################## +rem ## Environment setup + +set _EXITCODE=0 + +set _BASENAME=%~n0 + +for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf + +call %_PROG_HOME%\bin\common.bat +if not %_EXITCODE%==0 goto end + +rem ########################################################################## +rem ## Main + +call :javaClassPath + +if %_DEBUG%==1 echo [%_BASENAME%] "%_JAVACMD%" -Dscala.usejavacp=true -classpath "%_CLASS_PATH%" dotty.tools.dottydoc.Main %* +"%_JAVACMD%" -Dscala.usejavacp=true -classpath "%_CLASS_PATH%" dotty.tools.dottydoc.Main %* +if not %ERRORLEVEL%==0 ( + if %_DEBUG%==1 echo [%_BASENAME%] Dottydoc execution failed + set _EXITCODE=1 + goto end +) +goto end + +rem ########################################################################## +rem ## Subroutines + +rem output parameter: _CLASS_PATH +:javaClassPath +set __LIB_DIR=%_PROG_HOME%\lib + +rem Set dotty-doc dep: +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*dotty-doc*"') do set _DOTTY_DOC_LIB=%__LIB_DIR%\%%f + +rem Set flexmark deps: +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-0*"') do set _FLEXMARK_LIBS=%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-anchorlink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-autolink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-emoji*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-strikethrough*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-tasklist*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-ins*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-superscript*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-wikilink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-yaml-front-matter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-formatter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-jira-converter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-util*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% + +rem Set jackson deps: +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-annotations*"') do set _JACKSON_LIBS=%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-core*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-databind*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-dataformat-yaml*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% + +rem Set liqp dep: +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*liqp*"') do set _LIQP_LIB=%__LIB_DIR%\%%f%_PSEP% + +rem Set ANTLR dep: +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*antlr-3*"') do set _ANTLR_LIB=%__LIB_DIR%\%%f%_PSEP% +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*antlr-runtime-3*"') do set _ANTLR_RUNTIME_LIB=%__LIB_DIR%\%%f%_PSEP% + +rem Set autolink dep: +rem conflict with flexmark-ext-autolink-0.11 +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*autolink-0.6*"') do set _AUTOLINK_LIB=%__LIB_DIR%\%%f + +rem Set snakeyaml dep: +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*snakeyaml*"') do set _SNAKEYAML_LIB=%__LIB_DIR%\%%f%_PSEP% + +rem Set ST4 dep: +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*ST4*"') do set _ST4_LIB=%__LIB_DIR%\%%f%_PSEP% + +rem Set jsoup dep: +for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jsoup*"') do set _JSOUP_LIB=%__LIB_DIR%\%%f%_PSEP% + +set _CLASS_PATH=%_DOTTY_LIB%%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_DOC_LIB%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SBT_INTF% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_SCALA_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_FLEXMARK_LIBS% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_JACKSON_LIBS% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_LIQP_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_ANTLR_LIB%%_PSEP%%_ANTLR_RUNTIME_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_AUTOLINK_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_SNAKEYAML_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_ST4_LIB% +set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_JSOUP_LIB% +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% +exit /b %_EXITCODE% +endlocal diff --git a/dist/bin/dotr.bat b/dist/bin/dotr.bat new file mode 100644 index 000000000000..8384e7b5ab5d --- /dev/null +++ b/dist/bin/dotr.bat @@ -0,0 +1,108 @@ +@echo off +setlocal enabledelayedexpansion + +rem only for interactive debugging ! +set _DEBUG=0 + +rem ########################################################################## +rem ## Environment setup + +set _EXITCODE=0 + +set _BASENAME=%~n0 + +for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf + +call %_PROG_HOME%\bin\common.bat +if not %_EXITCODE%==0 goto end + +call :args %* + +rem ########################################################################## +rem ## Main + +set _CASE_1=0 +if %_EXECUTE_REPL%==1 set _CASE_1=1 +if %_EXECUTE_RUN%==0 if not defined _RESIDUAL_ARGS set _CASE_1=1 + +set _CASE_2=0 +if %_EXECUTE_RUN%==1 set _CASE_2=1 +if defined _RESIDUAL_ARGS set _CASE_2=1 + +rem if [ $execute_repl == true ] || ([ $execute_run == false ] && [ $options_indicator == 0 ]); then +if %_CASE_1%==1 ( + set _DOTC_ARGS= + if defined _CLASS_PATH set _DOTC_ARGS=-classpath "%_CLASS_PATH%" + set _DOTC_ARGS=!_DOTC_ARGS! %_JAVA_OPTIONS% -repl %_RESIDUAL_ARGS% + echo Starting dotty REPL... + if %_DEBUG%==1 echo [%_BASENAME%] %_PROG_HOME%\bin\dotc.bat !_DOTC_ARGS! + %_PROG_HOME%\bin\dotc.bat !_DOTC_ARGS! +rem elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then +) else if %_CASE_2%==1 ( + set _CP_ARG=%_DOTTY_LIB%%_PSEP%%_SCALA_LIB% + if defined _CLASS_PATH ( set _CP_ARG=!_CP_ARG!%_PSEP%%_CLASS_PATH% + ) else ( set _CP_ARG=!_CP_ARG!%_PSEP%. + ) + if %_CLASS_PATH_COUNT% gtr 1 ( + echo Warning: Multiple classpaths are found, dotr only use the last one. 1>&2 + ) + if %_WITH_COMPILER%==1 ( + set _CP_ARG=!_CP_ARG!%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SCALA_ASM% + ) + set _JAVA_ARGS=%_JAVA_DEBUG% -classpath "!_CP_ARG!" %_RESIDUAL_ARGS% + if %_DEBUG%==1 echo [%_BASENAME%] %_JAVACMD% !_JAVA_ARGS! + %_JAVACMD% !_JAVA_ARGS! +) else ( + echo Warning: Command option is not correct. 1>&2 +) + +goto end + +rem ########################################################################## +rem ## Subroutines + +:args +set _RESIDUAL_ARGS= +set _EXECUTE_REPL=0 +set _EXECUTE_RUN=0 +set _WITH_COMPILER=0 +set _JAVA_DEBUG= +set _CLASS_PATH_COUNT=0 +set _CLASS_PATH= +set _JVM_OPTIONS= +set _JAVA_OPTIONS= + +:args_loop +if "%1"=="" goto args_done +set "__ARG=%1" +if %_DEBUG%==1 echo [%_BASENAME%] __ARG=%__ARG% +if /i "%__ARG%"=="-repl" ( + set _EXECUTE_REPL=1 +) else if /i "%__ARG%"=="-run" ( + set _EXECUTE_RUN=1 +) else if /i "%__ARG%"=="-classpath" ( + set _CLASS_PATH=%2 + set /a _CLASS_PATH_COUNT+=1 + shift +) else if /i "%__ARG%"=="-with-compiler" ( + set _WITH_COMPILER=1 +) else if /i "%__ARG%"=="-d" ( + set _JAVA_DEBUG=%_DEBUG_STR% +) else if /i "%_ARG:~0,2%"=="-J" ( + set _JVM_OPTIONS=!_JVM_OPTIONS! %__ARG% + set _JAVA_OPTIONS=!_JAVA_OPTIONS! %__ARG% +) else ( + set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %__ARG% +) +shift +goto args_loop +:args_done +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% +exit /b %_EXITCODE% +endlocal diff --git a/project/scripts/build.bat b/project/scripts/build.bat new file mode 100644 index 000000000000..760e485a95b9 --- /dev/null +++ b/project/scripts/build.bat @@ -0,0 +1,426 @@ +@echo off +setlocal enabledelayedexpansion + +rem only for interactive debugging +set _DEBUG=0 + +rem ########################################################################## +rem ## Environment setup + +set _BASENAME=%~n0 + +set _EXITCODE=0 + +set _BOT_TOKEN=dotty-token + +rem set _DRONE_BUILD_EVENT=pull_request +set _DRONE_BUILD_EVENT= +set _DRONE_REMOTE_URL= +set _DRONE_BRANCH= + +for %%f in ("%~dp0..\..") do set _ROOT_DIR=%%~sf +set _BIN_DIR=%_ROOT_DIR%bin +set _TESTS_POS_DIR=%_ROOT_DIR%test\pos + +set _SOURCE=tests/pos/HelloWorld.scala +set _MAIN=HelloWorld +set _EXPECTED_OUTPUT=hello world + +call :args %* +if not %_EXITCODE%==0 goto end +if defined _HELP call :help & exit /b %_EXITCODE% + +if exist "C:\Temp\" ( set _TMP_DIR=C:\Temp +) else ( set _TMP_DIR=%TEMP% +) +set _OUT_DIR=%_TMP_DIR%\%_BASENAME%_out +if not exist "%_OUT_DIR%" mkdir "%_OUT_DIR%" + +set _OUT1_DIR=%_TMP_DIR%\%_BASENAME%_out1 +if not exist "%_OUT1_DIR%" mkdir "%_OUT1_DIR%" + +set _TMP_FILE=%_TMP_DIR%\%_BASENAME%_tmp.txt + +rem see file project/scripts/sbt +rem SBT uses the value of the JAVA_OPTS environment variable if defined, rather than the config. +set JAVA_OPTS=-Xmx2048m ^ +-XX:ReservedCodeCacheSize=2048m ^ +-XX:MaxMetaspaceSize=1024m + +set SBT_OPTS=-Ddotty.drone.mem=4096m ^ +-Dsbt.ivy.home=%USERPROFILE%\.ivy2\ ^ +-Dsbt.log.noformat=true + +rem ########################################################################## +rem ## Main + +call :init +if not %_EXITCODE%==0 goto end + +if defined _CLEAN_ALL ( + call :clean_all + if not !_EXITCODE!==0 goto end +) +if defined _CLONE ( + call :clone + if not !_EXITCODE!==0 goto end +) +if defined _BUILD ( + call :test + if not !_EXITCODE!==0 goto end +) +if defined _BOOTSTRAP ( + call :test_bootstrapped + rem if not !_EXITCODE!==0 goto end + if not !_EXITCODE!==0 ( + if defined _IGNORE ( echo ###### Warning: _EXITCODE=!_EXITCODE! ####### 1>&2 + ) else ( goto end + ) + ) +) +if defined _DOCUMENTATION ( + call :documentation + if not !_EXITCODE!==0 goto end +) + +if defined _ARCHIVES ( + call :archives + if not !_EXITCODE!==0 goto end +) +goto end + +rem ########################################################################## +rem ## Subroutines + +rem input parameter: %* +rem output parameters: _VERBOSE, _DOCUMENTATION +:args +set _ARCHIVES= +set _BOOTSTRAP= +set _BUILD= +set _CLEAN_ALL= +set _CLONE= +set _DOCUMENTATION= +set _HELP= +set _VERBOSE=0 + +:args_loop +set __ARG=%~1 +if not defined __ARG goto args_done +if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof +) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 +) else if /i "%__ARG:~0,4%"=="arch" ( + if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _BUILD=1& set _BOOTSTRAP=1 + set _ARCHIVES=1 +) else if /i "%__ARG:~0,4%"=="boot" ( + if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _BUILD=1 + set _BOOTSTRAP=1 +) else if /i "%__ARG%"=="cleanall" ( set _CLEAN_ALL=1 +) else if /i "%__ARG%"=="clone" ( set _CLONE=1 +) else if /i "%__ARG:~0,3%"=="doc" ( + if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _BUILD=1& set _BOOTSTRAP=1 + set _DOCUMENTATION=1 +) else ( + echo Error: Unknown subcommand %__ARG% + set _EXITCODE=1 + goto :eof +) +shift +goto args_loop +:args_done +goto :eof + +:help +echo Usage: %_BASENAME% { options ^| subcommands } +echo Options: +echo -verbose display environment settings +echo Subcommands: +echo arch[ives] generate gz/zip archives (after bootstrap) +echo arch[ives]-only generate ONLY gz/zip archives +echo boot[strap] generate compiler bootstrap (after build) +echo boot[strap]-only generate ONLY compiler bootstrap +echo cleanall clean project (sbt+git) and quit +echo clone update submodules +echo doc[umentation] generate documentation (after bootstrap) +echo doc[umentation]-only] generate ONLY documentation +echo help display this help message +goto :eof + +rem output parameters: _GIT_CMD, _SBT_CMD +:init +where /q git.exe +if not %ERRORLEVEL%==0 ( + echo Error: Git command not found ^(check your PATH variable^) 1>&2 + set _EXITCODE=1 + goto end +) +set _GIT_CMD=git.exe + +where /q sbt.bat +if not %ERRORLEVEL%==0 ( + echo Error: SBT command not found ^(check your PATH variable^) 1>&2 + set _EXITCODE=1 + goto end +) +rem full path is required for sbt to run successfully +for /f %%i in ('where sbt.bat') do set _SBT_CMD=%%i + +if %_VERBOSE%==1 ( + for /f %%i in ('where git.exe') do set _GIT_CMD1=%%i + echo _GIT_CMD=!_GIT_CMD1! + echo _SBT_CMD=%_SBT_CMD% + echo JAVA_OPTS=%JAVA_OPTS% + echo SBT_OPTS=%SBT_OPTS% + echo. +) +goto :eof + +:clean_all +echo run sbt clean and git clean -xdf +if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" clean +call "%_SBT_CMD%" clean +if not %ERRORLEVEL%==0 ( + set _EXITCODE=1 + goto :eof +) +if %_DEBUG%==1 echo [%_BASENAME%] %_GIT_CMD% clean -xdf +%_GIT_CMD% clean -xdf +if not %ERRORLEVEL%==0 ( + set _EXITCODE=1 + goto :eof +) +goto :eof + +:clone +if "%_DRONE_BUILD_EVENT%"=="pull_request" if defined _DRONE_REMOTE_URL ( + %_GIT_CMD% config user.email "dotty.bot@epfl.ch" + %_GIT_CMD% config user.name "Dotty CI" + %_GIT_CMD% pull "%_DRONE_REMOTE_URL%" "%_DRONE_BRANCH%" +) +if %_DEBUG%==1 echo [%_BASENAME%] %_GIT_CMD% submodule update --init --recursive --jobs 3 +%_GIT_CMD% submodule update --init --recursive --jobs 3 +if not %ERRORLEVEL%==0 ( + echo Error: Failed to update Git submodules 1>&2 + set _EXITCODE=1 + goto :eof +) +goto :eof + +:clear_out +set __OUT_DIR=%~1 + +if exist "%__OUT_DIR%" ( + if %_DEBUG%==1 echo [%_BASENAME%] del /s /q "%__OUT_DIR%\*" 1^>NUL + del /s /q "%__OUT_DIR%\*" 1>NUL +) +goto :eof + +:grep +set __PATTERN=%~1 +set __FILE=%~2 + +if %_DEBUG%==1 echo [%_BASENAME%] findstr "%__PATTERN%" "%__FILE% +findstr "%__PATTERN%" "%__FILE%" +if not %ERRORLEVEL%==0 ( + echo Error: Failed to find pattern "%__PATTERN%" in file %__FILE% 1>&2 + set _EXITCODE=1 + goto :eof +) +goto :eof + +rem ## see file project/scripts/cmdTests +:cmdTests +echo testing sbt dotc and dotr +if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotr -classpath %_OUT_DIR% %_MAIN%" ^> "%_TMP_FILE%" +call "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotr -classpath %_OUT_DIR% %_MAIN%" > "%_TMP_FILE%" +call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +rem # check that `sbt dotc` compiles and `sbt dotr` runs it +echo testing sbt dotc -from-tasty and dotr -classpath +call :clear_out "%_OUT_DIR%" +call "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotc -from-tasty -classpath %_OUT_DIR% -d %_OUT1_DIR% %_MAIN% ;dotr -classpath %_OUT1_DIR% %_MAIN%" > "%_TMP_FILE%" +call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +rem # check that `sbt dotc -decompile` runs +echo testing sbt dotc -decompile +call "%_SBT_CMD%" ";dotc -decompile -color:never -classpath %_OUT_DIR% %_MAIN%" > "%_TMP_FILE%" +call :grep "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +echo testing sbt dotr with no -classpath +call :clear_out "%_OUT_DIR%" +if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" ";dotc %_SOURCE% ; dotr %_MAIN%" ^> "%_TMP_FILE%" +call "%_SBT_CMD%" ";dotc %_SOURCE% ; dotr %_MAIN%" > "%_TMP_FILE%" +call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +echo testing loading tasty from .tasty file in jar +call :clear_out "%_OUT_DIR%" +call "%_SBT_CMD%" ";dotc -d %_OUT_DIR%\out.jar %_SOURCE%; dotc -decompile -classpath %_OUT_DIR%/out.jar -color:never %_MAIN%" > "%_TMP_FILE%" +call :grep "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +goto :eof + +:test +if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";compile ;test" +call "%_SBT_CMD%" ";compile ;test" +if not %ERRORLEVEL%==0 ( + echo Error: Failed to build Dotty 1>&2 + set _EXITCODE=1 + goto :eof +) + +rem ## see shell script project/scripts/cmdTests +call :cmdTests +if not %_EXITCODE%==0 goto :eof + +goto :eof + +:test_pattern +set __PATTERN=%~1 +set __FILE=%~2 + +set /p __PATTERN2=<"%__FILE%" +if not "%__PATTERN2%"=="%__PATTERN%" ( + echo Error: failed to find pattern "%__PATTERN%" in file %__FILE% 1>&2 + set _EXITCODE=1 + goto :eof +) +goto :eof + +rem ## see shell script project/scripts/bootstrapCmdTests +:bootstrapCmdTests +rem # check that benchmarks can run +if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" +call "%_SBT_CMD%" "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" + +rem # The above is here as it relies on the bootstrapped library. +call "%_SBT_CMD%" "dotty-bench-bootstrapped/jmh:run 1 1 tests/pos/alias.scala" +call "%_SBT_CMD%" "dotty-bench-bootstrapped/jmh:run 1 1 -with-compiler compiler/src/dotty/tools/dotc/core/Types.scala" + +echo testing scala.quoted.Expr.run from sbt dotr +call "%_SBT_CMD%" ";dotty-compiler-bootstrapped/dotc tests/run-with-compiler/quote-run.scala; dotty-compiler-bootstrapped/dotr -with-compiler Test" > "%_TMP_FILE%" +call :grep "val a: scala.Int = 3" "%_TMP_FILE%" +if not %_EXITCODE%==0 goto :eof + +rem # setup for `dotc`/`dotr` script tests +if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" dist-bootstrapped/pack +call "%_SBT_CMD%" dist-bootstrapped/pack + +rem # check that `dotc` compiles and `dotr` runs it +echo testing ./bin/dotc and ./bin/dotr +call :clear_out "%_OUT_DIR%" +call %_BIN_DIR%\dotc.bat "%_SOURCE%" -d "%_OUT_DIR%" +call %_BIN_DIR%\dotr.bat -classpath "%_OUT_DIR%" "%_MAIN%" > "%_TMP_FILE%" +call :test_pattern "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" + +rem # check that `dotc -from-tasty` compiles and `dotr` runs it +echo testing ./bin/dotc -from-tasty and dotr -classpath +call :clear_out "%_OUT1_DIR%" +call %_BIN_DIR%\dotc.bat -from-tasty -classpath "%_OUT_DIR%" -d "%_OUT1_DIR%" "%_MAIN%" +call %_BIN_DIR%\dotr.bat -classpath "%_OUT1_DIR%" "%_MAIN%" > "%_TMP_FILE%" +call :test_pattern "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" + +rem # echo ":quit" | ./dist-bootstrapped/target/pack/bin/dotr # not supported by CI + +echo testing ./bin/dotd +call :clear_out "%_OUT_DIR%" +call %_BIN_DIR%\dotd.bat -project Hello -siteroot "%_OUT_DIR%" "%_SOURCE%" + +goto :eof + +:test_bootstrapped +if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" +call "%_SBT_CMD%" ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" +if not %ERRORLEVEL%==0 ( + echo Error: failed to bootstrap Dotty 1>&2 + set _EXITCODE=1 + goto :eof +) + +call :bootstrapCmdTests +if not %_EXITCODE%==0 goto :eof + +goto :eof + +:documentation +rem # make sure that _BOT_TOKEN is set +if not defined _BOT_TOKEN ( + echo Error: _BOT_TOKEN env unset, unable to push without password 1>&2 + set _EXITCODE=1 + goto :eof +) +for /f %%i in ('cd') do set _PWD=%%~si + +echo Working directory: %_PWD% + +call "%_SBT_CMD%" genDocs + +rem # make sure that the previous command actually succeeded +if not exist "%_PWD%\docs\_site\" ( + echo Error: output directory did not exist: %_PWD%\docs\_site 1>&2 + set _EXITCODE=1 + goto :eof +) + +goto :eof + +rem # save current head for commit message in gh-pages +rem for /f %%i in ('%_GIT_CMD% rev-parse HEAD 2^>NUL') do set _GIT_HEAD=%%i + +rem # set up remote and github credentials +rem %_GIT_CMD% remote add doc-remote "https://dotty-bot:%_BOT_TOKEN%@github.com/lampepfl/dotty-website.git" +rem %_GIT_CMD% config user.name "dotty-bot" +rem %_GIT_CMD% config user.email "dotty-bot@d-d.me" + +rem # check out correct branch +rem %_GIT_CMD% fetch doc-remote gh-pages +rem %_GIT_CMD% checkout gh-pages + +rem # move newly generated _site dir to $PWD +rem move %_PWD%\docs\_site . + +rem # remove everything BUT _site dir +rem del /f /q /s -rf !(_site) + +rem # copy new contents to $PWD +rem move _site\* . + +rem # remove now empty _site dir +rem del /f /q /s _site + +rem # add all contents of $PWD to commit +rem %_GIT_CMD% add -A +rem %_GIT_CMD% commit -m "Update gh-pages site for %_GIT_HEAD%" || echo "nothing new to commit" + +rem # push to doc-remote +rem %_GIT_CMD% push doc-remote || echo "couldn't push, since nothing was added" + +goto :eof + +:archives +if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" dist-bootstrapped/packArchive +call "%_SBT_CMD%" dist-bootstrapped/packArchive +rem output directory for gz/zip archives +set __TARGET_DIR=%_ROOT_DIR%\dist-bootstrapped\target +if not exist "%__TARGET_DIR%\" ( + echo Error: Directory target not found 1>&2 + set _EXITCODE=1 + goto :eof +) +if %_DEBUG%==1 ( + echo. + echo Output directory: %__TARGET_DIR%\ + dir /b /a-d "%__TARGET_DIR%" +) +goto :eof + +rem ########################################################################## +rem ## Cleanups + +:end +if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% +exit /b %_EXITCODE% From 205fab545dca6e775b8ae525d9b07c75fc1a1711 Mon Sep 17 00:00:00 2001 From: michelou Date: Wed, 14 Nov 2018 18:36:44 +0100 Subject: [PATCH 12/22] removed debug code from batch scripts --- dist/bin/common.bat | 4 ---- dist/bin/dotc.bat | 13 +------------ dist/bin/dotd.bat | 7 +------ dist/bin/dotr.bat | 6 ------ 4 files changed, 2 insertions(+), 28 deletions(-) diff --git a/dist/bin/common.bat b/dist/bin/common.bat index fd26dbc009f8..1d333d7b7a6f 100644 --- a/dist/bin/common.bat +++ b/dist/bin/common.bat @@ -3,13 +3,10 @@ rem ## Code common to dotc.bat, dotd.bat and dotr.bat if defined JAVACMD ( set _JAVACMD=%JAVACMD% - if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JAVACMD ) else if defined JAVA_HOME ( set _JAVACMD=%JAVA_HOME%\bin\java.exe - if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JAVA_HOME ) else if defined JDK_HOME ( set _JAVACMD=%JDK_HOME%\bin\java.exe - if %_DEBUG%==1 echo [%_BASENAME%] Using environment variable JDK_HOME ) else ( where /q java.exe if !ERRORLEVEL!==0 ( @@ -25,7 +22,6 @@ if defined JAVACMD ( for /f %%f in ('dir /ad /b "!_PATH!\jdk*" 2^>NUL') do set _JAVA_HOME=!_PATH!\%%f\jre ) if defined _JAVA_HOME ( - if %_DEBUG%==1 echo [%_BASENAME%] Using default Java installation directory !_JAVA_HOME! set _JAVACMD=!_JAVA_HOME!\bin\java.exe ) ) diff --git a/dist/bin/dotc.bat b/dist/bin/dotc.bat index 30675e37f11c..c7eade2fc917 100644 --- a/dist/bin/dotc.bat +++ b/dist/bin/dotc.bat @@ -1,9 +1,6 @@ @echo off setlocal enabledelayedexpansion -rem only for interactive debugging ! -set _DEBUG=0 - rem ########################################################################## rem ## Environment setup @@ -32,12 +29,11 @@ call :classpathArgs if defined JAVA_OPTS ( set _JAVA_OPTS=%JAVA_OPTS% ) else ( set _JAVA_OPTS=-Xmx768m -Xms768m ) -if %_DEBUG%==1 echo [%_BASENAME%] "%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% %_JVM_CP_ARGS% -Dscala.usejavacp=true %_PROG_NAME% %_SCALA_ARGS% %_RESIDUAL_ARGS% "%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% %_JVM_CP_ARGS% ^ -Dscala.usejavacp=true ^ %_PROG_NAME% %_SCALA_ARGS% %_RESIDUAL_ARGS% if not %ERRORLEVEL%==0 ( - if %_DEBUG%==1 echo [%_BASENAME%] Dotty compiler execution failed + rem echo Error: Dotty compiler execution failed 1>&2 set _EXITCODE=1 goto end ) @@ -59,7 +55,6 @@ set _RESIDUAL_ARGS= :args_loop if "%~1"=="" goto args_done set __ARG=%~1 -if %_DEBUG%==1 echo [%_BASENAME%] __ARG=%__ARG% if "%__ARG%"=="--" ( rem for arg; do addResidual "$arg"; done; set -- ;; ) else if /i "%__ARG%"=="-h" ( @@ -105,26 +100,21 @@ rem will be available as system properties. shift goto args_loop :args_done -if %_DEBUG%==1 echo [%_BASENAME%] _VERBOSE=%_VERBOSE% -if %_DEBUG%==1 echo [%_BASENAME%] _PROG_NAME=%_PROG_NAME% goto :eof rem output parameter: _SCALA_ARGS :addScala set _SCALA_ARGS=%_SCALA_ARGS% %~1 -if %_DEBUG%==1 echo [%_BASENAME%] _SCALA_ARGS=%_SCALA_ARGS% goto :eof rem output parameter: _JAVA_ARGS :addJava set _JAVA_ARGS=%_JAVA_ARGS% %~1 -if %_DEBUG%==1 echo [%_BASENAME%] _JAVA_ARGS=%_JAVA_ARGS% goto :eof rem output parameter: _RESIDUAL_ARGS :addResidual set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %~1 -if %_DEBUG%==1 echo [%_BASENAME%] _RESIDUAL_ARGS=%_RESIDUAL_ARGS% goto :eof rem output parameter: _JVM_CP_ARGS @@ -157,7 +147,6 @@ rem ########################################################################## rem ## Cleanups :end -if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% exit /b %_EXITCODE% endlocal diff --git a/dist/bin/dotd.bat b/dist/bin/dotd.bat index 2712062adbe7..f1a40fbeca51 100644 --- a/dist/bin/dotd.bat +++ b/dist/bin/dotd.bat @@ -1,9 +1,6 @@ @echo off setlocal enabledelayedexpansion -rem only for interactive debugging ! -set _DEBUG=0 - rem ########################################################################## rem ## Environment setup @@ -21,10 +18,9 @@ rem ## Main call :javaClassPath -if %_DEBUG%==1 echo [%_BASENAME%] "%_JAVACMD%" -Dscala.usejavacp=true -classpath "%_CLASS_PATH%" dotty.tools.dottydoc.Main %* "%_JAVACMD%" -Dscala.usejavacp=true -classpath "%_CLASS_PATH%" dotty.tools.dottydoc.Main %* if not %ERRORLEVEL%==0 ( - if %_DEBUG%==1 echo [%_BASENAME%] Dottydoc execution failed + rem echo Error: Dottydoc execution failed 1>&2 set _EXITCODE=1 goto end ) @@ -99,6 +95,5 @@ rem ########################################################################## rem ## Cleanups :end -if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% exit /b %_EXITCODE% endlocal diff --git a/dist/bin/dotr.bat b/dist/bin/dotr.bat index 8384e7b5ab5d..61c003af0cae 100644 --- a/dist/bin/dotr.bat +++ b/dist/bin/dotr.bat @@ -1,9 +1,6 @@ @echo off setlocal enabledelayedexpansion -rem only for interactive debugging ! -set _DEBUG=0 - rem ########################################################################## rem ## Environment setup @@ -35,7 +32,6 @@ if %_CASE_1%==1 ( if defined _CLASS_PATH set _DOTC_ARGS=-classpath "%_CLASS_PATH%" set _DOTC_ARGS=!_DOTC_ARGS! %_JAVA_OPTIONS% -repl %_RESIDUAL_ARGS% echo Starting dotty REPL... - if %_DEBUG%==1 echo [%_BASENAME%] %_PROG_HOME%\bin\dotc.bat !_DOTC_ARGS! %_PROG_HOME%\bin\dotc.bat !_DOTC_ARGS! rem elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then ) else if %_CASE_2%==1 ( @@ -50,7 +46,6 @@ rem elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then set _CP_ARG=!_CP_ARG!%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SCALA_ASM% ) set _JAVA_ARGS=%_JAVA_DEBUG% -classpath "!_CP_ARG!" %_RESIDUAL_ARGS% - if %_DEBUG%==1 echo [%_BASENAME%] %_JAVACMD% !_JAVA_ARGS! %_JAVACMD% !_JAVA_ARGS! ) else ( echo Warning: Command option is not correct. 1>&2 @@ -103,6 +98,5 @@ rem ########################################################################## rem ## Cleanups :end -if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% exit /b %_EXITCODE% endlocal From a6df7023fc0c3707f7e0e4b7b87391fddac77add Mon Sep 17 00:00:00 2001 From: Dotty CI Date: Wed, 14 Nov 2018 23:03:35 +0100 Subject: [PATCH 13/22] added compile subcommand to batch script --- project/scripts/build.bat | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/project/scripts/build.bat b/project/scripts/build.bat index 760e485a95b9..92c30b9eba94 100644 --- a/project/scripts/build.bat +++ b/project/scripts/build.bat @@ -65,7 +65,7 @@ if defined _CLONE ( call :clone if not !_EXITCODE!==0 goto end ) -if defined _BUILD ( +if defined _COMPILE ( call :test if not !_EXITCODE!==0 goto end ) @@ -97,7 +97,7 @@ rem output parameters: _VERBOSE, _DOCUMENTATION :args set _ARCHIVES= set _BOOTSTRAP= -set _BUILD= +set _COMPILE= set _CLEAN_ALL= set _CLONE= set _DOCUMENTATION= @@ -110,15 +110,18 @@ if not defined __ARG goto args_done if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof ) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 ) else if /i "%__ARG:~0,4%"=="arch" ( - if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _BUILD=1& set _BOOTSTRAP=1 + if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _COMPILE=1& set _BOOTSTRAP=1 set _ARCHIVES=1 ) else if /i "%__ARG:~0,4%"=="boot" ( - if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _BUILD=1 + if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _COMPILE=1 set _BOOTSTRAP=1 ) else if /i "%__ARG%"=="cleanall" ( set _CLEAN_ALL=1 ) else if /i "%__ARG%"=="clone" ( set _CLONE=1 +) else if /i "%__ARG%"=="compile" ( + if not "%__ARG:~-5%"=="-only" set _CLONE=1 + set _COMPILE=1 ) else if /i "%__ARG:~0,3%"=="doc" ( - if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _BUILD=1& set _BOOTSTRAP=1 + if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _COMPILE=1& set _BOOTSTRAP=1 set _DOCUMENTATION=1 ) else ( echo Error: Unknown subcommand %__ARG% @@ -137,10 +140,12 @@ echo -verbose display environment settings echo Subcommands: echo arch[ives] generate gz/zip archives (after bootstrap) echo arch[ives]-only generate ONLY gz/zip archives -echo boot[strap] generate compiler bootstrap (after build) +echo boot[strap] generate compiler bootstrap (after compile) echo boot[strap]-only generate ONLY compiler bootstrap echo cleanall clean project (sbt+git) and quit echo clone update submodules +echo compile generate compiler 1st stage (after clone) +echo compile-only generate ONLY compiler 1st stage echo doc[umentation] generate documentation (after bootstrap) echo doc[umentation]-only] generate ONLY documentation echo help display this help message @@ -265,6 +270,7 @@ if not %_EXITCODE%==0 goto :eof goto :eof :test +echo sbt compile and sbt test if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";compile ;test" call "%_SBT_CMD%" ";compile ;test" if not %ERRORLEVEL%==0 ( From 6a066394f9671ceef4d91e01958a7e9247216177 Mon Sep 17 00:00:00 2001 From: Dotty CI Date: Fri, 16 Nov 2018 13:10:16 +0100 Subject: [PATCH 14/22] Fix path separator on Windows --- compiler/src/dotty/tools/dotc/fromtasty/Debug.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala b/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala index c249f00a2368..f2d9adca1e50 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala @@ -6,6 +6,7 @@ import scala.util.control.NonFatal import dotty.tools.io.Directory +import java.io.{File => JFile} import java.nio.file.{Files, Paths} object Debug { @@ -65,7 +66,7 @@ object Debug { private def insertClasspathInArgs(args: List[String], cp: String): List[String] = { val (beforeCp, fromCp) = args.span(_ != "-classpath") - val classpath = fromCp.drop(1).headOption.fold(cp)(_ + ":" + cp) + val classpath = fromCp.drop(1).headOption.fold(cp)(_ + JFile.pathSeparator + cp) "-classpath" :: classpath :: beforeCp ::: fromCp.drop(2) } } From 211ce5de6c5985435b4a1c12559f2841f643743a Mon Sep 17 00:00:00 2001 From: Dotty CI Date: Fri, 16 Nov 2018 14:41:47 +0100 Subject: [PATCH 15/22] add -timer option, fix args subroutine --- project/scripts/build.bat | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/project/scripts/build.bat b/project/scripts/build.bat index 92c30b9eba94..bdbfd7e06f74 100644 --- a/project/scripts/build.bat +++ b/project/scripts/build.bat @@ -93,7 +93,7 @@ rem ########################################################################## rem ## Subroutines rem input parameter: %* -rem output parameters: _VERBOSE, _DOCUMENTATION +rem output parameters: _CLONE, _COMPILE, _DOCUMENTATION, _TIMER, _VERBOSE, :args set _ARCHIVES= set _BOOTSTRAP= @@ -102,12 +102,14 @@ set _CLEAN_ALL= set _CLONE= set _DOCUMENTATION= set _HELP= +set _TIMER=0 set _VERBOSE=0 :args_loop set __ARG=%~1 if not defined __ARG goto args_done if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof +) else if /i "%__ARG%"=="-timer" ( set _TIMER=1 ) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 ) else if /i "%__ARG:~0,4%"=="arch" ( if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _COMPILE=1& set _BOOTSTRAP=1 @@ -117,7 +119,7 @@ if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof set _BOOTSTRAP=1 ) else if /i "%__ARG%"=="cleanall" ( set _CLEAN_ALL=1 ) else if /i "%__ARG%"=="clone" ( set _CLONE=1 -) else if /i "%__ARG%"=="compile" ( +) else if /i "%__ARG:~0,7%"=="compile" ( if not "%__ARG:~-5%"=="-only" set _CLONE=1 set _COMPILE=1 ) else if /i "%__ARG:~0,3%"=="doc" ( @@ -136,6 +138,7 @@ goto :eof :help echo Usage: %_BASENAME% { options ^| subcommands } echo Options: +echo -timer display total build time echo -verbose display environment settings echo Subcommands: echo arch[ives] generate gz/zip archives (after bootstrap) @@ -178,6 +181,9 @@ if %_VERBOSE%==1 ( echo SBT_OPTS=%SBT_OPTS% echo. ) +if %_TIMER%==1 ( + for /f "delims=" %%i in ('powershell -c "(Get-Date)"') do set _TIMER_START=%%i +) goto :eof :clean_all @@ -424,9 +430,27 @@ if %_DEBUG%==1 ( ) goto :eof +rem output parameter: _DURATION +:duration +set __START=%~1 +set __END=%~2 + +for /f "delims=" %%i in ('powershell -c "$interval = New-TimeSpan -Start '%__START%' -End '%__END%'; Write-Host $interval"') do set _DURATION=%%i +goto :eof + +rem input parameter: 1=start time +:total +set __TIMER_START=%~1 + +for /f "delims=" %%i in ('powershell -c "(Get-Date)"') do set __TIMER_END=%%i +call :duration "%_TIMER_START%" "!__TIMER_END!" +echo Total execution time: %_DURATION% +goto :eof + rem ########################################################################## rem ## Cleanups :end +if %_TIMER%==1 call :total "%_TIMER_START%" if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% exit /b %_EXITCODE% From ae3e368ede572b409106c43bc871b55513d8b492 Mon Sep 17 00:00:00 2001 From: Dotty CI Date: Fri, 16 Nov 2018 20:54:35 +0100 Subject: [PATCH 16/22] 2nd attempt (wrong merge operation ?) --- .../dotc/decompiler/DecompilationPrinter.scala | 5 ++++- .../tools/dotc/reporting/MessageRendering.scala | 13 ++++++++----- compiler/src/dotty/tools/repl/ReplDriver.scala | 6 +++--- .../dotty/tools/repl/ReplCompilerTests.scala | 6 ++++-- .../test/dotty/tools/repl/ScriptedTests.scala | 10 ++++++---- .../dotty/tools/vulpix/ParallelTesting.scala | 16 +++++++++------- 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala b/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala index afa06ff9a115..be01393ef8b5 100644 --- a/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala +++ b/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala @@ -3,6 +3,8 @@ package decompiler import java.io.{OutputStream, PrintStream} +import scala.io.Codec + import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.core.Phases.Phase import dotty.tools.dotc.core.tasty.TastyPrinter @@ -24,8 +26,9 @@ class DecompilationPrinter extends Phase { var os: OutputStream = null var ps: PrintStream = null try { + implicit val codec = Codec.UTF8 os = File(outputDir.fileNamed("decompiled.scala").path).outputStream(append = true) - ps = new PrintStream(os) + ps = new PrintStream(os, /*autoFlush*/false, "UTF-8") printToOutput(ps) } finally { if (os ne null) os.close() diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala index 426b1f269c78..f22acd7e0ce8 100644 --- a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala +++ b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala @@ -15,6 +15,9 @@ import scala.annotation.switch import scala.collection.mutable trait MessageRendering { + + private final val EOL: String = sys.props("line.separator") + /** Remove ANSI coloring from `str`, useful for getting real length of * strings * @@ -101,7 +104,7 @@ trait MessageRendering { msg.linesIterator .map { line => " " * (offset - 1) + "|" + padding + line} - .mkString(sys.props("line.separator")) + .mkString(EOL) } /** The separator between errors containing the source file and error type @@ -132,8 +135,8 @@ trait MessageRendering { |${Blue("Explanation")} |${Blue("===========")}""" ) - sb.append('\n').append(m.explanation) - if (m.explanation.lastOption != Some('\n')) sb.append('\n') + sb.append(EOL).append(m.explanation) + if (m.explanation.lastOption != Some(EOL)) sb.append(EOL) sb.toString } @@ -141,12 +144,12 @@ trait MessageRendering { def messageAndPos(msg: Message, pos: SourcePosition, diagnosticLevel: String)(implicit ctx: Context): String = { val sb = mutable.StringBuilder.newBuilder val posString = posStr(pos, diagnosticLevel, msg) - if (posString.nonEmpty) sb.append(posString).append('\n') + if (posString.nonEmpty) sb.append(posString).append(EOL) if (pos.exists) { val (srcBefore, srcAfter, offset) = sourceLines(pos) val marker = columnMarker(pos, offset) val err = errorMsg(pos, msg.msg, offset) - sb.append((srcBefore ::: marker :: err :: outer(pos, " " * (offset - 1)) ::: srcAfter).mkString("\n")) + sb.append((srcBefore ::: marker :: err :: outer(pos, " " * (offset - 1)) ::: srcAfter).mkString(EOL)) } else sb.append(msg.msg) sb.toString } diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala index 98ad8636e274..3de64529da88 100644 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -1,6 +1,6 @@ package dotty.tools.repl -import java.io.PrintStream +import java.io.{File => JFile, PrintStream} import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.ast.{tpd, untpd} @@ -324,9 +324,9 @@ class ReplDriver(settings: Array[String], state case Load(path) => - val file = new java.io.File(path) + val file = new JFile(path) if (file.exists) { - val contents = scala.io.Source.fromFile(file).mkString + val contents = scala.io.Source.fromFile(file, "UTF-8").mkString run(contents) } else { diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index efe6876c269b..b1a20ad37571 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -5,6 +5,8 @@ import org.junit.{Ignore, Test} class ReplCompilerTests extends ReplTest { + private final val EOL: String = sys.props("line.separator") + @Test def compileSingle = fromInitialState { implicit state => run("def foo: 1 = 1") assertEquals("def foo: Int(1)", storedOutput().trim) @@ -51,7 +53,7 @@ class ReplCompilerTests extends ReplTest { "val res1: Int = 20" ) - assertEquals(expected, storedOutput().split("\n").toList) + assertEquals(expected, storedOutput().split(EOL).toList) } @Test def testImportMutable = @@ -122,6 +124,6 @@ class ReplCompilerTests extends ReplTest { ) run(source) - assertEquals(expected, storedOutput().split("\n").toList) + assertEquals(expected, storedOutput().split(EOL).toList) } } diff --git a/compiler/test/dotty/tools/repl/ScriptedTests.scala b/compiler/test/dotty/tools/repl/ScriptedTests.scala index 090d49949d08..59e3f78d48f0 100644 --- a/compiler/test/dotty/tools/repl/ScriptedTests.scala +++ b/compiler/test/dotty/tools/repl/ScriptedTests.scala @@ -14,6 +14,8 @@ import dotc.reporting.MessageRendering /** Runs all tests contained in `compiler/test-resources/repl/` */ class ScriptedTests extends ReplTest with MessageRendering { + private final val EOL: String = sys.props("line.separator") + private def scripts(path: String): Array[JFile] = { val dir = new JFile(getClass.getResource(path).getPath) assert(dir.exists && dir.isDirectory, "Couldn't load scripts dir") @@ -22,7 +24,7 @@ class ScriptedTests extends ReplTest with MessageRendering { private def testFile(f: JFile): Unit = { val prompt = "scala>" - val lines = Source.fromFile(f).getLines().buffered + val lines = Source.fromFile(f, "UTF-8").getLines().buffered assert(lines.head.startsWith(prompt), s"""Each file has to start with the prompt: "$prompt"""") @@ -44,7 +46,7 @@ class ScriptedTests extends ReplTest with MessageRendering { def evaluate(state: State, input: String, prompt: String) = try { val nstate = run(input.drop(prompt.length))(state) - val out = input + "\n" + storedOutput() + val out = input + EOL + storedOutput() (out, nstate) } catch { @@ -60,7 +62,7 @@ class ScriptedTests extends ReplTest with MessageRendering { } val expectedOutput = - Source.fromFile(f).getLines().flatMap(filterEmpties).mkString("\n") + Source.fromFile(f, "UTF-8").getLines().flatMap(filterEmpties).mkString(EOL) val actualOutput = { resetToInitial() val inputRes = extractInputs(prompt) @@ -70,7 +72,7 @@ class ScriptedTests extends ReplTest with MessageRendering { buf.append(out) nstate } - buf.flatMap(filterEmpties).mkString("\n") + buf.flatMap(filterEmpties).mkString(EOL) } if (expectedOutput != actualOutput) { diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 619a877d757a..ac90a34bf188 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -187,6 +187,8 @@ trait ParallelTesting extends RunnerOrchestration { self => protected final val realStdout = System.out protected final val realStderr = System.err + protected final val EOL: String = sys.props("line.separator") + /** A runnable that logs its contents in a buffer */ trait LoggedRunnable extends Runnable { /** Instances of `LoggedRunnable` implement this method instead of the @@ -535,16 +537,16 @@ trait ParallelTesting extends RunnerOrchestration { self => val ignoredFilePathLine = "/** Decompiled from" val stripTrailingWhitespaces = "(.*\\S|)\\s+".r val output = Source.fromFile(outDir.getParent + "_decompiled" + JFile.separator + outDir.getName - + JFile.separator + "decompiled.scala").getLines().map {line => + + JFile.separator + "decompiled.scala", "UTF-8").getLines().map {line => stripTrailingWhitespaces.unapplySeq(line).map(_.head).getOrElse(line) }.toList - val check: String = Source.fromFile(checkFile).getLines().filter(!_.startsWith(ignoredFilePathLine)) - .mkString("\n") + val check: String = Source.fromFile(checkFile, "UTF-8").getLines().filter(!_.startsWith(ignoredFilePathLine)) + .mkString(EOL) - if (output.filter(!_.startsWith(ignoredFilePathLine)).mkString("\n") != check) { + if (output.filter(!_.startsWith(ignoredFilePathLine)).mkString(EOL) != check) { val outFile = dotty.tools.io.File(checkFile.toPath).addExtension(".out") - outFile.writeAll(output.mkString("\n")) + outFile.writeAll(output.mkString(EOL)) val msg = s"""Output differed for test $name, use the following command to see the diff: | > diff $checkFile $outFile @@ -617,7 +619,7 @@ trait ParallelTesting extends RunnerOrchestration { self => case Success(_) if !checkFile.isDefined || !checkFile.get.exists => // success! case Success(output) => { val outputLines = output.linesIterator.toArray :+ DiffUtil.EOF - val checkLines: Array[String] = Source.fromFile(checkFile.get).getLines().toArray :+ DiffUtil.EOF + val checkLines: Array[String] = Source.fromFile(checkFile.get, "UTF-8").getLines().toArray :+ DiffUtil.EOF val sourceTitle = testSource.title def linesMatch = @@ -726,7 +728,7 @@ trait ParallelTesting extends RunnerOrchestration { self => val errorMap = new HashMap[String, Integer]() var expectedErrors = 0 files.filter(_.getName.endsWith(".scala")).foreach { file => - Source.fromFile(file).getLines().zipWithIndex.foreach { case (line, lineNbr) => + Source.fromFile(file, "UTF-8").getLines().zipWithIndex.foreach { case (line, lineNbr) => val errors = line.sliding("// error".length).count(_.mkString == "// error") if (errors > 0) errorMap.put(s"${file.getAbsolutePath}:${lineNbr}", errors) From e42b72c5a431f58df3f31295b06f86252e2074f5 Mon Sep 17 00:00:00 2001 From: Dotty CI Date: Wed, 21 Nov 2018 17:18:45 +0100 Subject: [PATCH 17/22] PR #5487 --- compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala index 8fca5cdbb0d7..340537fe5cff 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala @@ -67,7 +67,7 @@ class QuoteCompiler extends Compiler { */ private def inClass(expr: Expr[_])(implicit ctx: Context): Tree = { val pos = Position(0) - val assocFile = new PlainFile(Path("")) + val assocFile = new PlainFile(Path("_quote_")) val cls = ctx.newCompleteClassSymbol(defn.RootClass, outputClassName, EmptyFlags, defn.ObjectType :: Nil, newScope, coord = pos, assocFile = assocFile).entered.asClass From ca111b030485abc3179ad83f6559fc5a4545c8cb Mon Sep 17 00:00:00 2001 From: Dotty CI Date: Wed, 21 Nov 2018 17:24:07 +0100 Subject: [PATCH 18/22] removed files not belonging the branch `quoted` --- bin/common.bat | 119 -- bin/dotc.bat | 5 - bin/dotd.bat | 5 - bin/dotr.bat | 5 - .../decompiler/DecompilationPrinter.scala | 50 - .../dotty/tools/dotc/fromtasty/Debug.scala | 72 - .../dotc/reporting/MessageRendering.scala | 167 -- .../src/dotty/tools/repl/ReplDriver.scala | 370 ----- .../dotty/tools/repl/ReplCompilerTests.scala | 129 -- .../test/dotty/tools/repl/ScriptedTests.scala | 91 -- .../dotty/tools/vulpix/ParallelTesting.scala | 1412 ----------------- dist/bin/common.bat | 59 - dist/bin/dotc.bat | 152 -- dist/bin/dotd.bat | 99 -- dist/bin/dotr.bat | 102 -- project/scripts/build.bat | 456 ------ 16 files changed, 3293 deletions(-) delete mode 100644 bin/common.bat delete mode 100644 bin/dotc.bat delete mode 100644 bin/dotd.bat delete mode 100644 bin/dotr.bat delete mode 100644 compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala delete mode 100644 compiler/src/dotty/tools/dotc/fromtasty/Debug.scala delete mode 100644 compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala delete mode 100644 compiler/src/dotty/tools/repl/ReplDriver.scala delete mode 100644 compiler/test/dotty/tools/repl/ReplCompilerTests.scala delete mode 100644 compiler/test/dotty/tools/repl/ScriptedTests.scala delete mode 100644 compiler/test/dotty/tools/vulpix/ParallelTesting.scala delete mode 100644 dist/bin/common.bat delete mode 100644 dist/bin/dotc.bat delete mode 100644 dist/bin/dotd.bat delete mode 100644 dist/bin/dotr.bat delete mode 100644 project/scripts/build.bat diff --git a/bin/common.bat b/bin/common.bat deleted file mode 100644 index 264b3fedaa37..000000000000 --- a/bin/common.bat +++ /dev/null @@ -1,119 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem # Wrapper for the published dotc/dotr script that check for file changes -rem # and use sbt to re build the compiler as needed. - -rem ########################################################################## -rem ## Environment setup - -set _BASENAME=%~n0 - -set _EXITCODE=0 - -for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf - -rem # Marker file used to obtain the date of latest call to sbt-back -set _VERSION=%_ROOT_DIR%\dist-bootstrapped\target\pack\VERSION - -rem ########################################################################## -rem ## Main - -rem # Create the target if absent or if file changed in ROOT/compiler -call :new_files "%_VERSION%" - -if exist "%_VERSION%" if %_NEW_FILES%==0 goto target -echo Building Dotty... -pushd %_ROOT% -sbt.bat "dist-bootstrapped/pack" -popd - -:target -set _TARGET=%~1 -rem # Mutates %* by deleting the first element (%1) -shift - -call %_TARGET% %* - -goto end - -rem ########################################################################## -rem ## Subroutines - -rem input parameter: %1=version file -rem Output parameter: _NEW_FILES -:new_files -set __VERSION_FILE=%~1 - -call :timestamp "%__VERSION_FILE%" -set __VERSION_TIMESTAMP=%_TIMESTAMP% - -set __JAVA_SOURCE_FILES= -for /f %%i in ('dir /s /b "%_ROOT_DIR%compiler\*.java" 2^>NUL') do ( - set __JAVA_SOURCE_FILES=!__JAVA_SOURCE_FILES! %%i -) -set __SCALA_SOURCE_FILES= -for /f %%i in ('dir /s /b "%_ROOT_DIR%compiler\*.scala" 2^>NUL') do ( - set __SCALA_SOURCE_FILES=!__SCALA_SOURCE_FILES! %%i -) - -call :compile_required "%__VERSION_TIMESTAMP%" "%__JAVA_SOURCE_FILES% %__SCALA_SOURCE_FILES%" -set _NEW_FILES=%_COMPILE_REQUIRED% - -goto :eof - -rem input parameter: 1=timestamp file 2=source files -rem output parameter: _COMPILE_REQUIRED -:compile_required -set __TIMESTAMP_FILE=%~1 -set __SOURCE_FILES=%~2 - -set __SOURCE_TIMESTAMP=00000000000000 -for %%i in (%__SOURCE_FILES%) do ( - call :timestamp "%%i" - call :newer !_TIMESTAMP! !__SOURCE_TIMESTAMP! - if !_NEWER!==1 set __SOURCE_TIMESTAMP=!_TIMESTAMP! -) -if exist "%__TIMESTAMP_FILE%" ( set /p __CLASS_TIMESTAMP=<%__TIMESTAMP_FILE% -) else ( set __CLASS_TIMESTAMP=00000000000000 -) - -call :newer %__SOURCE_TIMESTAMP% %__CLASS_TIMESTAMP% -set _COMPILE_REQUIRED=%_NEWER% -goto :eof - -rem output parameter: _NEWER -:newer -set __TIMESTAMP1=%~1 -set __TIMESTAMP2=%~2 - -set __TIMESTAMP1_DATE=%__TIMESTAMP1:~0,8% -set __TIMESTAMP1_TIME=%__TIMESTAMP1:~-6% - -set __TIMESTAMP2_DATE=%__TIMESTAMP2:~0,8% -set __TIMESTAMP2_TIME=%__TIMESTAMP2:~-6% - -if %__TIMESTAMP1_DATE% gtr %__TIMESTAMP2_DATE% ( set _NEWER=1 -) else if %__TIMESTAMP1_DATE% lss %__TIMESTAMP2_DATE% ( set _NEWER=0 -) else if %__TIMESTAMP1_TIME% gtr %__TIMESTAMP2_TIME% ( set _NEWER=1 -) else ( set _NEWER=0 -) -goto :eof - -rem input parameter: 1=file path -rem output parameter: _TIMESTAMP -:timestamp -set __FILE_PATH=%~1 - -set _TIMESTAMP=00000000000000 -for /f %%i in ('powershell -C "(Get-ChildItem '%__FILE_PATH%').LastWriteTime | Get-Date -uformat %%Y%%m%%d%%H%%M%%S"') do ( - set _TIMESTAMP=%%i -) -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -exit /b %_EXITCODE% -endlocal \ No newline at end of file diff --git a/bin/dotc.bat b/bin/dotc.bat deleted file mode 100644 index 6cb1b20510dd..000000000000 --- a/bin/dotc.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off - -for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf - -call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotc.bat" %* diff --git a/bin/dotd.bat b/bin/dotd.bat deleted file mode 100644 index 5544e2bed952..000000000000 --- a/bin/dotd.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off - -for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf - -call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotd.bat" %* diff --git a/bin/dotr.bat b/bin/dotr.bat deleted file mode 100644 index 3d62849591df..000000000000 --- a/bin/dotr.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off - -for %%f in ("%~dp0..") do set _ROOT_DIR=%%~sf - -call %_ROOT_DIR%\bin\common.bat "%_ROOT_DIR%\dist-bootstrapped\target\pack\bin\dotr.bat" %* diff --git a/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala b/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala deleted file mode 100644 index be01393ef8b5..000000000000 --- a/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala +++ /dev/null @@ -1,50 +0,0 @@ -package dotty.tools.dotc -package decompiler - -import java.io.{OutputStream, PrintStream} - -import scala.io.Codec - -import dotty.tools.dotc.core.Contexts._ -import dotty.tools.dotc.core.Phases.Phase -import dotty.tools.dotc.core.tasty.TastyPrinter -import dotty.tools.dotc.tastyreflect.ReflectionImpl -import dotty.tools.io.File - -/** Phase that prints the trees in all loaded compilation units. - * - * @author Nicolas Stucki - */ -class DecompilationPrinter extends Phase { - - override def phaseName: String = "decompilationPrinter" - - override def run(implicit ctx: Context): Unit = { - if (ctx.settings.outputDir.isDefault) printToOutput(System.out) - else { - val outputDir = ctx.settings.outputDir.value - var os: OutputStream = null - var ps: PrintStream = null - try { - implicit val codec = Codec.UTF8 - os = File(outputDir.fileNamed("decompiled.scala").path).outputStream(append = true) - ps = new PrintStream(os, /*autoFlush*/false, "UTF-8") - printToOutput(ps) - } finally { - if (os ne null) os.close() - if (ps ne null) ps.close() - } - } - } - - private def printToOutput(out: PrintStream)(implicit ctx: Context): Unit = { - val unit = ctx.compilationUnit - if (ctx.settings.printTasty.value) { - new TastyPrinter(unit.pickled.head._2).printContents() - } else { - val unitFile = unit.source.toString.replace("\\", "/").replace(".class", ".tasty") - out.println(s"/** Decompiled from $unitFile */") - out.println(new ReflectionImpl(ctx).showSourceCode.showTree(unit.tpdTree)(ctx)) - } - } -} diff --git a/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala b/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala deleted file mode 100644 index f2d9adca1e50..000000000000 --- a/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala +++ /dev/null @@ -1,72 +0,0 @@ -package dotty.tools -package dotc -package fromtasty - -import scala.util.control.NonFatal - -import dotty.tools.io.Directory - -import java.io.{File => JFile} -import java.nio.file.{Files, Paths} - -object Debug { - def main(args: Array[String]): Unit = { - // Preload scala.util.control.NonFatal. Otherwise, when trying to catch a StackOverflowError, - // we may try to load it but fail with another StackOverflowError and lose the original exception, - // see . - val _ = NonFatal - - assert(!args.contains("-d")) - - val outPath = Paths.get("out") - Directory(outPath).createDirectory() - - val tmpOut = Files.createTempDirectory(outPath.toAbsolutePath, "from-tasty-tmp") - - val fromSourcesOut = Files.createDirectory(tmpOut.resolve("from-source")) - - println("Compiling from .scala sources") - val compilation1 = dotc.Main.process("-d" +: fromSourcesOut.toString +: args) - - if (compilation1.hasErrors) { - println("Failed compilation from sources") - Directory(tmpOut).deleteRecursively() - sys.exit(1) - } - - val fromTastyOut = Files.createDirectory(tmpOut.resolve("from-tasty")) - - val extensions = List("tasty", "hasTasty").map(_.toLowerCase) - val classes = Directory(fromSourcesOut).walk.filter(x => x.isFile && extensions.exists(_ == x.extension.toLowerCase)).map { x => - val source = x.toString - // transform foo/bar/Baz.hasTasty into foo.bar.Baz - source.substring(fromSourcesOut.toString.length + 1, source.length - x.extension.length - 1).replace('/', '.') - }.toList - - val fromTastyArgs = { - "-from-tasty" :: - "-d" :: fromTastyOut.toString :: - insertClasspathInArgs(args.filterNot(_.endsWith(".scala")).toList, fromSourcesOut.toString) ::: - classes - } - - println("Compiling TASTY from .class sources") - val compilation2 = dotc.Main.process(fromTastyArgs.toArray) - - if (compilation2.hasErrors) { - println("Failed compilation from TASTY") - println("Compilation input: " + fromSourcesOut) - // In this case we do not delete the generated class files to allow further debugging. - // For example `dotc -decompile` on one of the intermediate class files. - sys.exit(1) - } - - Directory(tmpOut).deleteRecursively() - } - - private def insertClasspathInArgs(args: List[String], cp: String): List[String] = { - val (beforeCp, fromCp) = args.span(_ != "-classpath") - val classpath = fromCp.drop(1).headOption.fold(cp)(_ + JFile.pathSeparator + cp) - "-classpath" :: classpath :: beforeCp ::: fromCp.drop(2) - } -} diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala deleted file mode 100644 index f22acd7e0ce8..000000000000 --- a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala +++ /dev/null @@ -1,167 +0,0 @@ -package dotty.tools -package dotc -package reporting - -import core.Contexts.Context -import core.Decorators._ -import printing.Highlighting.{Blue, Red} -import printing.SyntaxHighlighting -import diagnostic.{ErrorMessageID, Message, MessageContainer} -import diagnostic.messages._ -import util.SourcePosition -import scala.tasty.util.Chars.{ LF, CR, FF, SU } -import scala.annotation.switch - -import scala.collection.mutable - -trait MessageRendering { - - private final val EOL: String = sys.props("line.separator") - - /** Remove ANSI coloring from `str`, useful for getting real length of - * strings - * - * @return string stripped of ANSI escape codes - */ - def stripColor(str: String): String = - str.replaceAll("\u001b\\[.*?m", "") - - /** When inlining a method call, if there's an error we'd like to get the - * outer context and the `pos` at which the call was inlined. - * - * @return a list of strings with inline locations - */ - def outer(pos: SourcePosition, prefix: String)(implicit ctx: Context): List[String] = - if (pos.outer.exists) { - s"$prefix| This location is in code that was inlined at ${pos.outer}" :: - outer(pos.outer, prefix) - } else Nil - - /** Get the sourcelines before and after the position, as well as the offset - * for rendering line numbers - * - * @return (lines before error, lines after error, line numbers offset) - */ - def sourceLines(pos: SourcePosition)(implicit ctx: Context): (List[String], List[String], Int) = { - var maxLen = Int.MinValue - def render(offsetAndLine: (Int, String)): String = { - val (offset, line) = offsetAndLine - val lineNbr = pos.source.offsetToLine(offset) - val prefix = s"${lineNbr + 1} |" - maxLen = math.max(maxLen, prefix.length) - val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix).show - lnum + line.stripLineEnd - } - - def linesFrom(arr: Array[Char]): List[String] = { - def pred(c: Char) = (c: @switch) match { - case LF | CR | FF | SU => true - case _ => false - } - val (line, rest0) = arr.span(!pred(_)) - val (_, rest) = rest0.span(pred) - new String(line) :: { if (rest.isEmpty) Nil else linesFrom(rest) } - } - - val syntax = - if (ctx.settings.color.value != "never") - SyntaxHighlighting.highlight(new String(pos.linesSlice)).toCharArray - else pos.linesSlice - val lines = linesFrom(syntax) - val (before, after) = pos.beforeAndAfterPoint - - ( - before.zip(lines).map(render), - after.zip(lines.drop(before.length)).map(render), - maxLen - ) - } - - /** The column markers aligned under the error */ - def columnMarker(pos: SourcePosition, offset: Int)(implicit ctx: Context): String = { - val prefix = " " * (offset - 1) - val padding = pos.startColumnPadding - val carets = Red { - if (pos.startLine == pos.endLine) - "^" * math.max(1, pos.endColumn - pos.startColumn) - else "^" - } - s"$prefix|$padding${carets.show}" - } - - /** The error message (`msg`) aligned under `pos` - * - * @return aligned error message - */ - def errorMsg(pos: SourcePosition, msg: String, offset: Int)(implicit ctx: Context): String = { - val padding = msg.linesIterator.foldLeft(pos.startColumnPadding) { (pad, line) => - val lineLength = stripColor(line).length - val maxPad = math.max(0, ctx.settings.pageWidth.value - offset - lineLength) - offset - - if (maxPad < pad.length) " " * maxPad - else pad - } - - msg.linesIterator - .map { line => " " * (offset - 1) + "|" + padding + line} - .mkString(EOL) - } - - /** The separator between errors containing the source file and error type - * - * @return separator containing error location and kind - */ - def posStr(pos: SourcePosition, diagnosticLevel: String, message: Message)(implicit ctx: Context): String = - if (pos.exists) Blue({ - val file = s"${pos.source.file.toString}:${pos.line + 1}:${pos.column}" - val errId = - if (message.errorId ne ErrorMessageID.NoExplanationID) { - val errorNumber = message.errorId.errorNumber() - s"[E${"0" * (3 - errorNumber.toString.length) + errorNumber}] " - } else "" - val kind = - if (message.kind == "") diagnosticLevel - else s"${message.kind} $diagnosticLevel" - val prefix = s"-- ${errId}${kind}: $file " - - prefix + - ("-" * math.max(ctx.settings.pageWidth.value - stripColor(prefix).length, 0)) - }).show else "" - - /** Explanation rendered under "Explanation" header */ - def explanation(m: Message)(implicit ctx: Context): String = { - val sb = new StringBuilder( - hl"""| - |${Blue("Explanation")} - |${Blue("===========")}""" - ) - sb.append(EOL).append(m.explanation) - if (m.explanation.lastOption != Some(EOL)) sb.append(EOL) - sb.toString - } - - /** The whole message rendered from `msg` */ - def messageAndPos(msg: Message, pos: SourcePosition, diagnosticLevel: String)(implicit ctx: Context): String = { - val sb = mutable.StringBuilder.newBuilder - val posString = posStr(pos, diagnosticLevel, msg) - if (posString.nonEmpty) sb.append(posString).append(EOL) - if (pos.exists) { - val (srcBefore, srcAfter, offset) = sourceLines(pos) - val marker = columnMarker(pos, offset) - val err = errorMsg(pos, msg.msg, offset) - sb.append((srcBefore ::: marker :: err :: outer(pos, " " * (offset - 1)) ::: srcAfter).mkString(EOL)) - } else sb.append(msg.msg) - sb.toString - } - - def diagnosticLevel(cont: MessageContainer): String = - cont match { - case m: Error => "Error" - case m: FeatureWarning => "Feature Warning" - case m: DeprecationWarning => "Deprecation Warning" - case m: UncheckedWarning => "Unchecked Warning" - case m: MigrationWarning => "Migration Warning" - case m: Warning => "Warning" - case m: Info => "Info" - } -} diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala deleted file mode 100644 index 3de64529da88..000000000000 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ /dev/null @@ -1,370 +0,0 @@ -package dotty.tools.repl - -import java.io.{File => JFile, PrintStream} - -import dotty.tools.dotc.ast.Trees._ -import dotty.tools.dotc.ast.{tpd, untpd} -import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.core.Denotations.Denotation -import dotty.tools.dotc.core.Flags._ -import dotty.tools.dotc.core.Mode -import dotty.tools.dotc.core.NameKinds.SimpleNameKind -import dotty.tools.dotc.core.NameOps._ -import dotty.tools.dotc.core.Names.Name -import dotty.tools.dotc.core.StdNames._ -import dotty.tools.dotc.core.Symbols.{Symbol, defn} -import dotty.tools.dotc.interactive.Interactive -import dotty.tools.dotc.printing.SyntaxHighlighting -import dotty.tools.dotc.reporting.MessageRendering -import dotty.tools.dotc.reporting.diagnostic.{Message, MessageContainer} -import dotty.tools.dotc.util.Positions.Position -import dotty.tools.dotc.util.{SourceFile, SourcePosition} -import dotty.tools.dotc.{CompilationUnit, Driver} -import dotty.tools.io._ -import org.jline.reader._ - -import scala.annotation.tailrec -import scala.collection.JavaConverters._ - -/** The state of the REPL contains necessary bindings instead of having to have - * mutation - * - * The compiler in the REPL needs to do some wrapping in order to compile - * valid code. This wrapping occurs when a single `MemberDef` that cannot be - * top-level needs to be compiled. In order to do this, we need some unique - * identifier for each of these wrappers. That identifier is `objectIndex`. - * - * Free expressions such as `1 + 1` needs to have an assignment in order to be - * of use. These expressions are therefore given a identifier on the format - * `resX` where `X` starts at 0 and each new expression that needs an - * identifier is given the increment of the old identifier. This identifier is - * `valIndex`. - * - * @param objectIndex the index of the next wrapper - * @param valIndex the index of next value binding for free expressions - * @param imports a map from object index to the list of user defined imports - * @param context the latest compiler context - */ -case class State(objectIndex: Int, - valIndex: Int, - imports: Map[Int, List[tpd.Import]], - context: Context) - -/** Main REPL instance, orchestrating input, compilation and presentation */ -class ReplDriver(settings: Array[String], - out: PrintStream = Console.out, - classLoader: Option[ClassLoader] = None) extends Driver { - - /** Overridden to `false` in order to not have to give sources on the - * commandline - */ - override def sourcesRequired: Boolean = false - - /** Create a fresh and initialized context with IDE mode enabled */ - private[this] def initialCtx = { - val rootCtx = initCtx.fresh.addMode(Mode.ReadPositions | Mode.Interactive | Mode.ReadComments) - rootCtx.setSetting(rootCtx.settings.YcookComments, true) - val ictx = setup(settings, rootCtx)._2 - ictx.base.initialize()(ictx) - ictx - } - - /** the initial, empty state of the REPL session */ - final def initialState: State = State(0, 0, Map.empty, rootCtx) - - /** Reset state of repl to the initial state - * - * This method is responsible for performing an all encompassing reset. As - * such, when the user enters `:reset` this method should be called to reset - * everything properly - */ - protected[this] def resetToInitial(): Unit = { - rootCtx = initialCtx - if (rootCtx.settings.outputDir.isDefault(rootCtx)) - rootCtx = rootCtx.fresh - .setSetting(rootCtx.settings.outputDir, new VirtualDirectory("")) - compiler = new ReplCompiler - rendering = new Rendering(classLoader) - } - - private[this] var rootCtx: Context = _ - private[this] var compiler: ReplCompiler = _ - private[this] var rendering: Rendering = _ - - // initialize the REPL session as part of the constructor so that once `run` - // is called, we're in business - resetToInitial() - - /** Run REPL with `state` until `:quit` command found - * - * This method is the main entry point into the REPL. Its effects are not - * observable outside of the CLI, for this reason, most helper methods are - * `protected final` to facilitate testing. - */ - final def runUntilQuit(initialState: State = initialState): State = { - val terminal = new JLineTerminal - - /** Blockingly read a line, getting back a parse result */ - def readLine(state: State): ParseResult = { - val completer: Completer = { (_, line, candidates) => - val comps = completions(line.cursor, line.line, state) - candidates.addAll(comps.asJava) - } - implicit val ctx = state.context - try { - val line = terminal.readLine(completer) - ParseResult(line) - } catch { - case _: EndOfFileException | - _: UserInterruptException => // Ctrl+D or Ctrl+C - Quit - } - } - - @tailrec def loop(state: State): State = { - val res = readLine(state) - if (res == Quit) state - else loop(interpret(res)(state)) - } - - try withRedirectedOutput { loop(initialState) } - finally terminal.close() - } - - final def run(input: String)(implicit state: State): State = withRedirectedOutput { - val parsed = ParseResult(input)(state.context) - interpret(parsed) - } - - // TODO: i5069 - final def bind(name: String, value: Any)(implicit state: State): State = state - - private def withRedirectedOutput(op: => State): State = - Console.withOut(out) { Console.withErr(out) { op } } - - private def newRun(state: State) = { - val run = compiler.newRun(rootCtx.fresh.setReporter(newStoreReporter), state) - state.copy(context = run.runContext) - } - - /** Extract possible completions at the index of `cursor` in `expr` */ - protected[this] final def completions(cursor: Int, expr: String, state0: State): List[Candidate] = { - def makeCandidate(completion: Symbol)(implicit ctx: Context) = { - val displ = completion.name.toString - new Candidate( - /* value = */ displ, - /* displ = */ displ, // displayed value - /* group = */ null, // can be used to group completions together - /* descr = */ null, // TODO use for documentation? - /* suffix = */ null, - /* key = */ null, - /* complete = */ false // if true adds space when completing - ) - } - implicit val state = newRun(state0) - compiler - .typeCheck(expr, errorsAllowed = true) - .map { tree => - val file = new SourceFile("", expr) - val unit = new CompilationUnit(file) - unit.tpdTree = tree - implicit val ctx = state.context.fresh.setCompilationUnit(unit) - val srcPos = SourcePosition(file, Position(cursor)) - val (_, completions) = Interactive.completions(srcPos) - completions.map(makeCandidate) - } - .getOrElse(Nil) - } - - private def interpret(res: ParseResult)(implicit state: State): State = { - val newState = res match { - case parsed: Parsed if parsed.trees.nonEmpty => - compile(parsed, state) - - case SyntaxErrors(_, errs, _) => - displayErrors(errs) - state - - case cmd: Command => - interpretCommand(cmd) - - case SigKill => // TODO - state - - case _ => // new line, empty tree - state - } - out.println() - newState - } - - /** Compile `parsed` trees and evolve `state` in accordance */ - private def compile(parsed: Parsed, istate: State): State = { - def extractNewestWrapper(tree: untpd.Tree): Name = tree match { - case PackageDef(_, (obj: untpd.ModuleDef) :: Nil) => obj.name.moduleClassName - case _ => nme.NO_NAME - } - - def extractTopLevelImports(ctx: Context): List[tpd.Import] = - ctx.phases.collectFirst { case phase: CollectTopLevelImports => phase.imports }.get - - implicit val state = newRun(istate) - compiler - .compile(parsed) - .fold( - displayErrors, - { - case (unit: CompilationUnit, newState: State) => - val newestWrapper = extractNewestWrapper(unit.untpdTree) - val newImports = extractTopLevelImports(newState.context) - var allImports = newState.imports - if (newImports.nonEmpty) - allImports += (newState.objectIndex -> newImports) - val newStateWithImports = newState.copy(imports = allImports) - - val warnings = newState.context.reporter.removeBufferedMessages(newState.context) - displayErrors(warnings)(newState) // display warnings - displayDefinitions(unit.tpdTree, newestWrapper)(newStateWithImports) - } - ) - } - - /** Display definitions from `tree` */ - private def displayDefinitions(tree: tpd.Tree, newestWrapper: Name)(implicit state: State): State = { - implicit val ctx = state.context - - def resAndUnit(denot: Denotation) = { - import scala.util.{Success, Try} - val sym = denot.symbol - val name = sym.name.show - val hasValidNumber = Try(name.drop(3).toInt) match { - case Success(num) => num < state.valIndex - case _ => false - } - name.startsWith(str.REPL_RES_PREFIX) && hasValidNumber && sym.info == defn.UnitType - } - - def displayMembers(symbol: Symbol) = if (tree.symbol.info.exists) { - val info = symbol.info - val defs = - info.bounds.hi.finalResultType - .membersBasedOnFlags(Method, Accessor | ParamAccessor | Synthetic | Private) - .filterNot { denot => - denot.symbol.owner == defn.AnyClass || - denot.symbol.owner == defn.ObjectClass || - denot.symbol.isConstructor - } - - val vals = - info.fields - .filterNot(_.symbol.is(ParamAccessor | Private | Synthetic | Module)) - .filter(_.symbol.name.is(SimpleNameKind)) - - val typeAliases = - info.bounds.hi.typeMembers.filter(_.symbol.info.isTypeAlias) - - ( - typeAliases.map("// defined alias " + _.symbol.showUser) ++ - defs.map(rendering.renderMethod) ++ - vals.map(rendering.renderVal).flatten - ).foreach(str => out.println(SyntaxHighlighting.highlight(str))) - - state.copy(valIndex = state.valIndex - vals.count(resAndUnit)) - } - else state - - def isSyntheticCompanion(sym: Symbol) = - sym.is(Module) && sym.is(Synthetic) - - def displayTypeDefs(sym: Symbol) = sym.info.memberClasses - .collect { - case x if !isSyntheticCompanion(x.symbol) && !x.symbol.name.isReplWrapperName => - x.symbol - } - .foreach { sym => - out.println(SyntaxHighlighting.highlight("// defined " + sym.showUser)) - } - - - ctx.atPhase(ctx.typerPhase.next) { implicit ctx => - - // Display members of wrapped module: - tree.symbol.info.memberClasses - .find(_.symbol.name == newestWrapper.moduleClassName) - .map { wrapperModule => - displayTypeDefs(wrapperModule.symbol) - displayMembers(wrapperModule.symbol) - } - .getOrElse { - // user defined a trait/class/object, so no module needed - state - } - } - } - - /** Interpret `cmd` to action and propagate potentially new `state` */ - private def interpretCommand(cmd: Command)(implicit state: State): State = cmd match { - case UnknownCommand(cmd) => - out.println(s"""Unknown command: "$cmd", run ":help" for a list of commands""") - state - - case Help => - out.println(Help.text) - state - - case Reset => - resetToInitial() - initialState - - case Imports => - for { - objectIndex <- 1 to state.objectIndex - imp <- state.imports.getOrElse(objectIndex, Nil) - } out.println(imp.show(state.context)) - state - - case Load(path) => - val file = new JFile(path) - if (file.exists) { - val contents = scala.io.Source.fromFile(file, "UTF-8").mkString - run(contents) - } - else { - out.println(s"""Couldn't find file "${file.getCanonicalPath}"""") - state - } - - case TypeOf(expr) => - compiler.typeOf(expr)(newRun(state)).fold( - displayErrors, - res => out.println(SyntaxHighlighting.highlight(res)(state.context)) - ) - state - - case DocOf(expr) => - compiler.docOf(expr)(newRun(state)).fold( - displayErrors, - res => out.println(res) - ) - state - - case Quit => - // end of the world! - state - } - - /** A `MessageRenderer` without file positions */ - private val messageRenderer = new MessageRendering { - override def posStr(pos: SourcePosition, diagnosticLevel: String, message: Message)(implicit ctx: Context): String = "" - } - - /** Render messages using the `MessageRendering` trait */ - private def renderMessage(cont: MessageContainer): Context => String = - messageRenderer.messageAndPos(cont.contained(), cont.pos, messageRenderer.diagnosticLevel(cont))(_) - - /** Output errors to `out` */ - private def displayErrors(errs: Seq[MessageContainer])(implicit state: State): State = { - errs.map(renderMessage(_)(state.context)).foreach(out.println) - state - } -} diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala deleted file mode 100644 index b1a20ad37571..000000000000 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ /dev/null @@ -1,129 +0,0 @@ -package dotty.tools.repl - -import org.junit.Assert._ -import org.junit.{Ignore, Test} - -class ReplCompilerTests extends ReplTest { - - private final val EOL: String = sys.props("line.separator") - - @Test def compileSingle = fromInitialState { implicit state => - run("def foo: 1 = 1") - assertEquals("def foo: Int(1)", storedOutput().trim) - } - - @Test def compileTwo = - fromInitialState { implicit state => - run("def foo: 1 = 1") - } - .andThen { implicit state => - val s2 = run("def foo(i: Int): i.type = i") - assertEquals(2, s2.objectIndex) - } - - @Test def inspectWrapper = - fromInitialState { implicit state => - run("def foo = 1") - - }.andThen { implicit state => - storedOutput() // discard output - run("val x = rs$line$1.foo") - assertEquals("val x: Int = 1", storedOutput().trim) - } - - @Test def testVar = fromInitialState { implicit state => - run("var x = 5") - assertEquals("var x: Int = 5", storedOutput().trim) - } - - @Test def testRes = fromInitialState { implicit state => - run { - """|def foo = 1 + 1 - |val x = 5 + 5 - |1 + 1 - |var y = 5 - |10 + 10""".stripMargin - } - - val expected = List( - "def foo: Int", - "val x: Int = 10", - "val res0: Int = 2", - "var y: Int = 5", - "val res1: Int = 20" - ) - - assertEquals(expected, storedOutput().split(EOL).toList) - } - - @Test def testImportMutable = - fromInitialState { implicit state => - run("import scala.collection.mutable") - } - .andThen { implicit state => - assertEquals(1, state.imports.size) - run("""mutable.Map("one" -> 1)""") - assertEquals( - "val res0: scala.collection.mutable.Map[String, Int] = Map(one -> 1)", - storedOutput().trim - ) - } - - @Test def rebindVariable = - fromInitialState { implicit s => - val state = run("var x = 5") - assertEquals("var x: Int = 5", storedOutput().trim) - state - } - .andThen { implicit s => - run("x = 10") - assertEquals("x: Int = 10", storedOutput().trim) - } - - // FIXME: Tests are not run in isolation, the classloader is corrupted after the first exception - @Ignore @Test def i3305: Unit = { - fromInitialState { implicit s => - run("null.toString") - assertTrue(storedOutput().startsWith("java.lang.NullPointerException")) - } - - fromInitialState { implicit s => - run("def foo: Int = 1 + foo; foo") - assertTrue(storedOutput().startsWith("def foo: Int\njava.lang.StackOverflowError")) - } - - fromInitialState { implicit s => - run("""throw new IllegalArgumentException("Hello")""") - assertTrue(storedOutput().startsWith("java.lang.IllegalArgumentException: Hello")) - } - - fromInitialState { implicit s => - run("val (x, y) = null") - assertTrue(storedOutput().startsWith("scala.MatchError: null")) - } - } - - @Test def i2789: Unit = fromInitialState { implicit state => - run("(x: Int) => println(x)") - assertTrue(storedOutput().startsWith("val res0: Int => Unit =")) - } - - @Test def byNameParam: Unit = fromInitialState { implicit state => - run("def f(g: => Int): Int = g") - assertTrue(storedOutput().startsWith("def f(g: => Int): Int")) - } - - @Test def i4051 = fromInitialState { implicit state => - val source = - """val x: PartialFunction[Int, Int] = { case x => x } - |val y = Map(("A", 1), ("B", 2), ("X", 3)).collect { case (k, v) => v }.toList""".stripMargin - - val expected = List( - "val x: PartialFunction[Int, Int] = ", - "val y: List[Int] = List(1, 2, 3)" - ) - - run(source) - assertEquals(expected, storedOutput().split(EOL).toList) - } -} diff --git a/compiler/test/dotty/tools/repl/ScriptedTests.scala b/compiler/test/dotty/tools/repl/ScriptedTests.scala deleted file mode 100644 index 59e3f78d48f0..000000000000 --- a/compiler/test/dotty/tools/repl/ScriptedTests.scala +++ /dev/null @@ -1,91 +0,0 @@ -package dotty.tools -package repl - -import java.io.{ File => JFile } - -import org.junit.Assert._ -import org.junit.Test - -import scala.collection.mutable.ArrayBuffer -import scala.io.Source - -import dotc.reporting.MessageRendering - -/** Runs all tests contained in `compiler/test-resources/repl/` */ -class ScriptedTests extends ReplTest with MessageRendering { - - private final val EOL: String = sys.props("line.separator") - - private def scripts(path: String): Array[JFile] = { - val dir = new JFile(getClass.getResource(path).getPath) - assert(dir.exists && dir.isDirectory, "Couldn't load scripts dir") - dir.listFiles - } - - private def testFile(f: JFile): Unit = { - val prompt = "scala>" - val lines = Source.fromFile(f, "UTF-8").getLines().buffered - - assert(lines.head.startsWith(prompt), - s"""Each file has to start with the prompt: "$prompt"""") - - def extractInputs(prompt: String): List[String] = { - val input = lines.next() - - if (!input.startsWith(prompt)) extractInputs(prompt) - else if (lines.hasNext) { - // read lines and strip trailing whitespace: - while (lines.hasNext && !lines.head.startsWith(prompt)) - lines.next() - - input :: { if (lines.hasNext) extractInputs(prompt) else Nil } - } - else Nil - } - - def evaluate(state: State, input: String, prompt: String) = - try { - val nstate = run(input.drop(prompt.length))(state) - val out = input + EOL + storedOutput() - (out, nstate) - } - catch { - case ex: Throwable => - System.err.println(s"failed while running script: $f, on:\n$input") - throw ex - } - - def filterEmpties(line: String): List[String] = - line.replaceAll("""(?m)\s+$""", "") match { - case "" => Nil - case nonEmptyLine => nonEmptyLine :: Nil - } - - val expectedOutput = - Source.fromFile(f, "UTF-8").getLines().flatMap(filterEmpties).mkString(EOL) - val actualOutput = { - resetToInitial() - val inputRes = extractInputs(prompt) - val buf = new ArrayBuffer[String] - inputRes.foldLeft(initialState) { (state, input) => - val (out, nstate) = evaluate(state, input, prompt) - buf.append(out) - nstate - } - buf.flatMap(filterEmpties).mkString(EOL) - } - - if (expectedOutput != actualOutput) { - println("expected =========>") - println(expectedOutput) - println("actual ===========>") - println(actualOutput) - - fail(s"Error in file $f, expected output did not match actual") - } - } - - @Test def replTests = scripts("/repl").foreach(testFile) - - @Test def typePrinterTests = scripts("/type-printer").foreach(testFile) -} diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala deleted file mode 100644 index ac90a34bf188..000000000000 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ /dev/null @@ -1,1412 +0,0 @@ -package dotty -package tools -package vulpix - -import java.io.{File => JFile} -import java.text.SimpleDateFormat -import java.util.HashMap -import java.nio.file.StandardCopyOption.REPLACE_EXISTING -import java.nio.file.{Files, NoSuchFileException, Path, Paths} -import java.util.concurrent.{TimeUnit, TimeoutException, Executors => JExecutors} -import java.util.{Timer, TimerTask} - -import scala.io.Source -import scala.util.control.NonFatal -import scala.util.Try -import scala.collection.mutable -import scala.util.matching.Regex -import scala.util.Random -import dotc.core.Contexts._ -import dotc.reporting.{Reporter, TestReporter} -import dotc.reporting.diagnostic.MessageContainer -import dotc.interfaces.Diagnostic.ERROR -import dotc.util.DiffUtil -import dotc.{Compiler, Driver} -import dotc.decompiler -import dotty.tools.vulpix.TestConfiguration.defaultOptions - -/** A parallel testing suite whose goal is to integrate nicely with JUnit - * - * This trait can be mixed in to offer parallel testing to compile runs. When - * using this, you should be running your JUnit tests **sequentially**, as the - * test suite itself runs with a high level of concurrency. - */ -trait ParallelTesting extends RunnerOrchestration { self => - - import ParallelTesting._ - - /** If the running environment supports an interactive terminal, each `Test` - * will be run with a progress bar and real time feedback - */ - def isInteractive: Boolean - - /** A string which is used to filter which tests to run, if `None` will run - * all tests. All absolute paths that contain the substring `testFilter` - * will be run - */ - def testFilter: Option[String] - - /** A test source whose files or directory of files is to be compiled - * in a specific way defined by the `Test` - */ - sealed trait TestSource { self => - def name: String - def outDir: JFile - def flags: TestFlags - - def runClassPath: String = outDir.getAbsolutePath + JFile.pathSeparator + flags.runClassPath - - def title: String = self match { - case self: JointCompilationSource => - if (self.files.length > 1) name - else self.files.head.getPath - - case self: SeparateCompilationSource => - self.dir.getPath - } - - /** Adds the flags specified in `newFlags0` if they do not already exist */ - def withFlags(newFlags0: String*) = { - val newFlags = newFlags0.toArray - if (!flags.options.containsSlice(newFlags)) self match { - case self: JointCompilationSource => - self.copy(flags = flags.and(newFlags:_*)) - case self: SeparateCompilationSource => - self.copy(flags = flags.and(newFlags:_*)) - } - else self - } - - /** Generate the instructions to redo the test from the command line */ - def buildInstructions(errors: Int, warnings: Int): String = { - val sb = new StringBuilder - val maxLen = 80 - var lineLen = 0 - - sb.append( - s"""| - |Test '$title' compiled with $errors error(s) and $warnings warning(s), - |the test can be reproduced by running:""".stripMargin - ) - sb.append("\n\n./bin/dotc ") - flags.all.foreach { arg => - if (lineLen > maxLen) { - sb.append(" \\\n ") - lineLen = 4 - } - sb.append(arg) - lineLen += arg.length - sb += ' ' - } - - self match { - case source: JointCompilationSource => { - source.sourceFiles.map(_.getAbsolutePath).foreach { path => - sb.append("\\\n ") - sb.append(path) - sb += ' ' - } - sb.toString + "\n\n" - } - case self: SeparateCompilationSource => { - val command = sb.toString - val fsb = new StringBuilder(command) - self.compilationGroups.foreach { files => - files.map(_.getPath).foreach { path => - fsb.append("\\\n ") - lineLen = 8 - fsb.append(path) - fsb += ' ' - } - fsb.append("\n\n") - fsb.append(command) - } - fsb.toString + "\n\n" - } - } - } - } - - /** A group of files that may all be compiled together, with the same flags - * and output directory - */ - private case class JointCompilationSource( - name: String, - files: Array[JFile], - flags: TestFlags, - outDir: JFile, - fromTasty: Boolean = false, - decompilation: Boolean = false - ) extends TestSource { - def sourceFiles: Array[JFile] = files.filter(isSourceFile) - - override def toString() = outDir.toString - } - - /** A test source whose files will be compiled separately according to their - * suffix `_X` - */ - case class SeparateCompilationSource( - name: String, - dir: JFile, - flags: TestFlags, - outDir: JFile - ) extends TestSource { - - /** Get the files grouped by `_X` as a list of groups, files missing this - * suffix will be put into the same group. - * Files in each group are sorted alphabetically. - * - * Filters out all none source files - */ - def compilationGroups: List[Array[JFile]] = - dir - .listFiles - .groupBy { file => - val name = file.getName - Try { - val potentialNumber = name - .substring(0, name.lastIndexOf('.')) - .reverse.takeWhile(_ != '_').reverse - - potentialNumber.toInt.toString - } - .toOption - .getOrElse("") - } - .toList.sortBy(_._1).map(_._2.filter(isSourceFile).sorted) - } - - /** Each `Test` takes the `testSources` and performs the compilation and assertions - * according to the implementing class "neg", "run" or "pos". - */ - private abstract class Test(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit val summaryReport: SummaryReporting) { test => - - import summaryReport._ - - protected final val realStdout = System.out - protected final val realStderr = System.err - - protected final val EOL: String = sys.props("line.separator") - - /** A runnable that logs its contents in a buffer */ - trait LoggedRunnable extends Runnable { - /** Instances of `LoggedRunnable` implement this method instead of the - * `run` method - */ - def checkTestSource(): Unit - - private[this] val logBuffer = mutable.ArrayBuffer.empty[String] - def log(msg: String): Unit = logBuffer.append(msg) - - def logReporterContents(reporter: TestReporter): Unit = - reporter.messages.foreach(log) - - def echo(msg: String): Unit = { - log(msg) - test.echo(msg) - } - - final def run(): Unit = { - checkTestSource() - summaryReport.echoToLog(logBuffer.iterator) - } - } - - /** Actual compilation run logic, the test behaviour is defined here */ - protected def encapsulatedCompilation(testSource: TestSource): LoggedRunnable - - /** All testSources left after filtering out */ - private val filteredSources = - if (!testFilter.isDefined) testSources - else testSources.filter { - case JointCompilationSource(_, files, _, _, _, _) => - files.exists(file => file.getAbsolutePath.contains(testFilter.get)) - case SeparateCompilationSource(_, dir, _, _) => - dir.getAbsolutePath.contains(testFilter.get) - } - - /** Total amount of test sources being compiled by this test */ - val sourceCount = filteredSources.length - - private[this] var _testSourcesCompleted = 0 - private def testSourcesCompleted: Int = _testSourcesCompleted - - /** Complete the current compilation with the amount of errors encountered */ - protected final def registerCompletion() = synchronized { - _testSourcesCompleted += 1 - } - - sealed trait Failure - case class JavaCompilationFailure(reason: String) extends Failure - case class TimeoutFailure(title: String) extends Failure - case object Generic extends Failure - - private[this] var _failures = Set.empty[Failure] - private[this] var _failureCount = 0 - - /** Fail the current test */ - protected[this] final def fail(failure: Failure = Generic): Unit = synchronized { - _failures = _failures + failure - _failureCount = _failureCount + 1 - } - def didFail: Boolean = _failureCount != 0 - - /** A set of the different failures */ - def failureReasons: Set[Failure] = _failures - - /** Number of failed tests */ - def failureCount: Int = _failureCount - - protected def logBuildInstructions(reporter: TestReporter, testSource: TestSource, err: Int, war: Int) = { - val errorMsg = testSource.buildInstructions(reporter.errorCount, reporter.warningCount) - addFailureInstruction(errorMsg) - failTestSource(testSource) - } - - /** Instructions on how to reproduce failed test source compilations */ - private[this] val reproduceInstructions = mutable.ArrayBuffer.empty[String] - protected final def addFailureInstruction(ins: String): Unit = - synchronized { reproduceInstructions.append(ins) } - - /** The test sources that failed according to the implementing subclass */ - private[this] val failedTestSources = mutable.ArrayBuffer.empty[String] - protected final def failTestSource(testSource: TestSource, reason: Failure = Generic) = synchronized { - val extra = reason match { - case TimeoutFailure(title) => s", test '$title' timed out" - case JavaCompilationFailure(msg) => s", java test sources failed to compile with: \n$msg" - case Generic => "" - } - failedTestSources.append(testSource.title + s" failed" + extra) - fail(reason) - } - - /** Prints to `System.err` if we're not suppressing all output */ - protected def echo(msg: String): Unit = if (!suppressAllOutput) { - // pad right so that output is at least as large as progress bar line - val paddingRight = " " * math.max(0, 80 - msg.length) - realStderr.println(msg + paddingRight) - } - - /** Print a progress bar for the current `Test` */ - private def updateProgressMonitor(start: Long): Unit = { - val tCompiled = testSourcesCompleted - if (tCompiled < sourceCount) { - val timestamp = (System.currentTimeMillis - start) / 1000 - val progress = (tCompiled.toDouble / sourceCount * 40).toInt - - realStdout.print( - "[" + ("=" * (math.max(progress - 1, 0))) + - (if (progress > 0) ">" else "") + - (" " * (39 - progress)) + - s"] completed ($tCompiled/$sourceCount, $failureCount failed, ${timestamp}s)\r" - ) - } - } - - /** Wrapper function to make sure that the compiler itself did not crash - - * if it did, the test should automatically fail. - */ - protected def tryCompile(testSource: TestSource)(op: => Unit): Unit = - try { - val testing = s"Testing ${testSource.title}" - summaryReport.echoToLog(testing) - if (!isInteractive) realStdout.println(testing) - op - } catch { - case e: Throwable => { - // if an exception is thrown during compilation, the complete test - // run should fail - failTestSource(testSource) - e.printStackTrace() - registerCompletion() - throw e - } - } - - protected def compile(files0: Array[JFile], flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = { - - val flags = flags0 and ("-d", targetDir.getAbsolutePath) - - def flattenFiles(f: JFile): Array[JFile] = - if (f.isDirectory) f.listFiles.flatMap(flattenFiles) - else Array(f) - - val files: Array[JFile] = files0.flatMap(flattenFiles) - - def compileWithJavac(fs: Array[String]) = if (fs.nonEmpty) { - val fullArgs = Array( - "javac", - "-encoding", "UTF-8", - "-classpath", - s"${Properties.scalaLibrary}${JFile.pathSeparator}${targetDir.getAbsolutePath}" - ) ++ flags.all.takeRight(2) ++ fs - - val process = Runtime.getRuntime.exec(fullArgs) - val output = Source.fromInputStream(process.getErrorStream).mkString - - if (process.waitFor() != 0) Some(output) - else None - } else None - - val reporter = - TestReporter.reporter(realStdout, logLevel = - if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR) - - val driver = - if (times == 1) new Driver - else new Driver { - private def ntimes(n: Int)(op: Int => Reporter): Reporter = - (emptyReporter /: (1 to n)) ((_, i) => op(i)) - - override def doCompile(comp: Compiler, files: List[String])(implicit ctx: Context) = - ntimes(times) { run => - val start = System.nanoTime() - val rep = super.doCompile(comp, files) - ctx.echo(s"\ntime run $run: ${(System.nanoTime - start) / 1000000}ms") - rep - } - } - - val allArgs = flags.withClasspath(targetDir.getAbsolutePath).all - - // Compile with a try to catch any StackTrace generated by the compiler: - try { - // If a test contains a Java file that cannot be parsed by Dotty's Java source parser, its - // name must contain the string "JAVA_ONLY". - val dottyFiles = files.filterNot(_.getName.contains("JAVA_ONLY")).map(_.getAbsolutePath) - driver.process(allArgs ++ dottyFiles, reporter = reporter) - - val javaFiles = files.filter(_.getName.endsWith(".java")).map(_.getAbsolutePath) - val javaErrors = compileWithJavac(javaFiles) - - if (javaErrors.isDefined) { - echo(s"\njava compilation failed: \n${ javaErrors.get }") - fail(failure = JavaCompilationFailure(javaErrors.get)) - } - } - catch { - case NonFatal(ex) => reporter.logStackTrace(ex) - } - - reporter - } - - protected def compileFromTasty(flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = { - val tastyOutput = new JFile(targetDir.getPath + "_from-tasty") - tastyOutput.mkdir() - val flags = flags0 and ("-d", tastyOutput.getAbsolutePath) and "-from-tasty" - - def tastyFileToClassName(f: JFile): String = { - val pathStr = targetDir.toPath.relativize(f.toPath).toString.replace(JFile.separatorChar, '.') - pathStr.stripSuffix(".tasty").stripSuffix(".hasTasty") - } - val classes = flattenFiles(targetDir).filter(isTastyFile).map(tastyFileToClassName) - - val reporter = - TestReporter.reporter(realStdout, logLevel = - if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR) - - val driver = new Driver - - // Compile with a try to catch any StackTrace generated by the compiler: - try { - driver.process(flags.all ++ classes, reporter = reporter) - } - catch { - case NonFatal(ex) => reporter.logStackTrace(ex) - } - - reporter - } - - protected def decompile(flags0: TestFlags, suppressErrors: Boolean, targetDir0: JFile): TestReporter = { - val targetDir = new JFile(targetDir0.getParent + "_decompiled") - val decompilationOutput = new JFile(targetDir + JFile.separator + targetDir0.getName) - decompilationOutput.mkdirs() - val flags = - flags0 and ("-d", decompilationOutput.getAbsolutePath) and - "-decompile" and "-pagewidth" and "80" - - def hasTastyFileToClassName(f: JFile): String = - targetDir0.toPath.relativize(f.toPath).toString.stripSuffix(".hasTasty"). - stripSuffix(".tasty").replace(JFile.separatorChar, '.') - val classes = flattenFiles(targetDir0).filter(isTastyFile).map(hasTastyFileToClassName).sorted - - val reporter = - TestReporter.reporter(realStdout, logLevel = - if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR) - - val driver = decompiler.Main - - // Compile with a try to catch any StackTrace generated by the compiler: - try { - driver.process(flags.all ++ classes, reporter = reporter) - } - catch { - case NonFatal(ex) => reporter.logStackTrace(ex) - } - - reporter - } - - private[ParallelTesting] def executeTestSuite(): this.type = { - assert(testSourcesCompleted == 0, "not allowed to re-use a `CompileRun`") - - if (filteredSources.nonEmpty) { - val pool = threadLimit match { - case Some(i) => JExecutors.newWorkStealingPool(i) - case None => JExecutors.newWorkStealingPool() - } - - val timer = new Timer() - val logProgress = isInteractive && !suppressAllOutput - val start = System.currentTimeMillis() - if (logProgress) { - val task = new TimerTask { - def run(): Unit = updateProgressMonitor(start) - } - timer.schedule(task, 100, 200) - } - - val eventualResults = filteredSources.map { target => - pool.submit(encapsulatedCompilation(target)) - } - - pool.shutdown() - if (!pool.awaitTermination(20, TimeUnit.MINUTES)) { - pool.shutdownNow() - System.setOut(realStdout) - System.setErr(realStderr) - throw new TimeoutException("Compiling targets timed out") - } - - eventualResults.foreach(_.get) - - if (logProgress) { - timer.cancel() - val timestamp = (System.currentTimeMillis - start) / 1000 - realStdout.println( - s"[=======================================] completed ($sourceCount/$sourceCount, $failureCount failed, ${timestamp}s)" - ) - } - - if (didFail) { - reportFailed() - failedTestSources.toSet.foreach(addFailedTest) - reproduceInstructions.iterator.foreach(addReproduceInstruction) - } - else reportPassed() - } - else echo { - testFilter - .map(r => s"""No files matched "$r" in test""") - .getOrElse("No tests available under target - erroneous test?") - } - - this - } - - /** Returns all files in directory or the file if not a directory */ - private def flattenFiles(f: JFile): Array[JFile] = - if (f.isDirectory) f.listFiles.flatMap(flattenFiles) - else Array(f) - } - - private final class PosTest(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit summaryReport: SummaryReporting) - extends Test(testSources, times, threadLimit, suppressAllOutput) { - protected def encapsulatedCompilation(testSource: TestSource) = new LoggedRunnable { - def checkTestSource(): Unit = tryCompile(testSource) { - testSource match { - case testSource @ JointCompilationSource(name, files, flags, outDir, fromTasty, decompilation) => - val reporter = - if (decompilation) { - val rep = decompile(flags, false, outDir) - - val checkFileOpt = files.flatMap { file => - if (file.isDirectory) Nil - else { - val fname = file.getAbsolutePath.reverse.dropWhile(_ != '.').reverse + "decompiled" - val checkFile = new JFile(fname) - if (checkFile.exists) List(checkFile) - else Nil - } - }.headOption - checkFileOpt match { - case Some(checkFile) => - val ignoredFilePathLine = "/** Decompiled from" - val stripTrailingWhitespaces = "(.*\\S|)\\s+".r - val output = Source.fromFile(outDir.getParent + "_decompiled" + JFile.separator + outDir.getName - + JFile.separator + "decompiled.scala", "UTF-8").getLines().map {line => - stripTrailingWhitespaces.unapplySeq(line).map(_.head).getOrElse(line) - }.toList - - val check: String = Source.fromFile(checkFile, "UTF-8").getLines().filter(!_.startsWith(ignoredFilePathLine)) - .mkString(EOL) - - if (output.filter(!_.startsWith(ignoredFilePathLine)).mkString(EOL) != check) { - val outFile = dotty.tools.io.File(checkFile.toPath).addExtension(".out") - outFile.writeAll(output.mkString(EOL)) - val msg = - s"""Output differed for test $name, use the following command to see the diff: - | > diff $checkFile $outFile - """.stripMargin - - echo(msg) - addFailureInstruction(msg) - - // Print build instructions to file and summary: - val buildInstr = testSource.buildInstructions(0, rep.warningCount) - addFailureInstruction(buildInstr) - - // Fail target: - failTestSource(testSource) - } - case _ => - } - - rep - } - else if (fromTasty) compileFromTasty(flags, false, outDir) - else compile(testSource.sourceFiles, flags, false, outDir) - registerCompletion() - - if (reporter.compilerCrashed || reporter.errorCount > 0) { - logReporterContents(reporter) - logBuildInstructions(reporter, testSource, reporter.errorCount, reporter.warningCount) - } - - case testSource @ SeparateCompilationSource(_, dir, flags, outDir) => - val reporters = testSource.compilationGroups.map(files => compile(files, flags, false, outDir)) - val compilerCrashed = reporters.exists(_.compilerCrashed) - val errorCount = reporters.foldLeft(0) { (acc, reporter) => - if (reporter.errorCount > 0) - logBuildInstructions(reporter, testSource, reporter.errorCount, reporter.warningCount) - - acc + reporter.errorCount - } - - def warningCount = reporters.foldLeft(0)(_ + _.warningCount) - - registerCompletion() - - if (compilerCrashed || errorCount > 0) { - reporters.foreach(logReporterContents) - logBuildInstructions(reporters.head, testSource, errorCount, warningCount) - } - } - } - } - } - - private final class RunTest(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit summaryReport: SummaryReporting) - extends Test(testSources, times, threadLimit, suppressAllOutput) { - private[this] var didAddNoRunWarning = false - private[this] def addNoRunWarning() = if (!didAddNoRunWarning) { - didAddNoRunWarning = true - summaryReport.addStartingMessage { - """|WARNING - |------- - |Run tests were only compiled, not run - this is due to the `dotty.tests.norun` - |property being set - |""".stripMargin - } - } - - private def verifyOutput(checkFile: Option[JFile], dir: JFile, testSource: TestSource, warnings: Int) = { - if (Properties.testsNoRun) addNoRunWarning() - else runMain(testSource.runClassPath) match { - case Success(_) if !checkFile.isDefined || !checkFile.get.exists => // success! - case Success(output) => { - val outputLines = output.linesIterator.toArray :+ DiffUtil.EOF - val checkLines: Array[String] = Source.fromFile(checkFile.get, "UTF-8").getLines().toArray :+ DiffUtil.EOF - val sourceTitle = testSource.title - - def linesMatch = - outputLines - .zip(checkLines) - .forall { case (x, y) => x == y } - - if (outputLines.length != checkLines.length || !linesMatch) { - // Print diff to files and summary: - val diff = DiffUtil.mkColoredLineDiff(checkLines, outputLines) - - val msg = - s"""|Output from '$sourceTitle' did not match check file. - |Diff (expected on the left, actual right): - |""".stripMargin + diff + "\n" - echo(msg) - addFailureInstruction(msg) - - // Print build instructions to file and summary: - val buildInstr = testSource.buildInstructions(0, warnings) - addFailureInstruction(buildInstr) - - // Fail target: - failTestSource(testSource) - } - } - - case Failure(output) => - echo(s"Test '${testSource.title}' failed with output:") - echo(output) - failTestSource(testSource) - - case Timeout => - echo("failed because test " + testSource.title + " timed out") - failTestSource(testSource, TimeoutFailure(testSource.title)) - } - } - - protected def encapsulatedCompilation(testSource: TestSource) = new LoggedRunnable { - def checkTestSource(): Unit = tryCompile(testSource) { - val (compilerCrashed, errorCount, warningCount, verifier: Function0[Unit]) = testSource match { - case testSource @ JointCompilationSource(_, files, flags, outDir, fromTasty, decompilation) => - val checkFile = files.flatMap { file => - if (file.isDirectory) Nil - else { - val fname = file.getAbsolutePath.reverse.dropWhile(_ != '.').reverse + "check" - val checkFile = new JFile(fname) - if (checkFile.exists) List(checkFile) - else Nil - } - }.headOption - val reporter = - if (fromTasty) compileFromTasty(flags, false, outDir) - else compile(testSource.sourceFiles, flags, false, outDir) - - if (reporter.compilerCrashed || reporter.errorCount > 0) { - logReporterContents(reporter) - logBuildInstructions(reporter, testSource, reporter.errorCount, reporter.warningCount) - } - - (reporter.compilerCrashed, reporter.errorCount, reporter.warningCount, () => verifyOutput(checkFile, outDir, testSource, reporter.warningCount)) - - case testSource @ SeparateCompilationSource(_, dir, flags, outDir) => - val checkFile = new JFile(dir.getAbsolutePath.reverse.dropWhile(_ == JFile.separatorChar).reverse + ".check") - val reporters = testSource.compilationGroups.map(compile(_, flags, false, outDir)) - val compilerCrashed = reporters.exists(_.compilerCrashed) - val (errorCount, warningCount) = - reporters.foldLeft((0,0)) { case ((errors, warnings), reporter) => - if (reporter.errorCount > 0) - logBuildInstructions(reporter, testSource, reporter.errorCount, reporter.warningCount) - - (errors + reporter.errorCount, warnings + reporter.warningCount) - } - - if (errorCount > 0) { - reporters.foreach(logReporterContents) - logBuildInstructions(reporters.head, testSource, errorCount, warningCount) - } - - (compilerCrashed, errorCount, warningCount, () => verifyOutput(Some(checkFile), outDir, testSource, warningCount)) - } - - if (!compilerCrashed && errorCount == 0) verifier() - else { - echo(s" Compilation failed for: '${testSource.title}' ") - val buildInstr = testSource.buildInstructions(errorCount, warningCount) - addFailureInstruction(buildInstr) - failTestSource(testSource) - } - registerCompletion() - } - } - } - - private final class NegTest(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit summaryReport: SummaryReporting) - extends Test(testSources, times, threadLimit, suppressAllOutput) { - protected def encapsulatedCompilation(testSource: TestSource) = new LoggedRunnable { - def checkTestSource(): Unit = tryCompile(testSource) { - // In neg-tests we allow two types of error annotations, - // "nopos-error" which doesn't care about position and "error" which - // has to be annotated on the correct line number. - // - // We collect these in a map `"file:row" -> numberOfErrors`, for - // nopos errors we save them in `"file" -> numberOfNoPosErrors` - def getErrorMapAndExpectedCount(files: Array[JFile]): (HashMap[String, Integer], Int) = { - val errorMap = new HashMap[String, Integer]() - var expectedErrors = 0 - files.filter(_.getName.endsWith(".scala")).foreach { file => - Source.fromFile(file, "UTF-8").getLines().zipWithIndex.foreach { case (line, lineNbr) => - val errors = line.sliding("// error".length).count(_.mkString == "// error") - if (errors > 0) - errorMap.put(s"${file.getAbsolutePath}:${lineNbr}", errors) - - val noposErrors = line.sliding("// nopos-error".length).count(_.mkString == "// nopos-error") - if (noposErrors > 0) { - val nopos = errorMap.get("nopos") - val existing: Integer = if (nopos eq null) 0 else nopos - errorMap.put("nopos", noposErrors + existing) - } - - expectedErrors += noposErrors + errors - } - } - - (errorMap, expectedErrors) - } - - def getMissingExpectedErrors(errorMap: HashMap[String, Integer], reporterErrors: Iterator[MessageContainer]) = !reporterErrors.forall { error => - val key = if (error.pos.exists) { - val fileName = error.pos.source.file.toString - s"$fileName:${error.pos.line}" - - } else "nopos" - - val errors = errorMap.get(key) - - if (errors ne null) { - if (errors == 1) errorMap.remove(key) - else errorMap.put(key, errors - 1) - true - } - else { - echo(s"Error reported in ${error.pos.source}, but no annotation found") - false - } - } - - val (compilerCrashed, expectedErrors, actualErrors, hasMissingAnnotations, errorMap) = testSource match { - case testSource @ JointCompilationSource(_, files, flags, outDir, fromTasty, decompilation) => - val sourceFiles = testSource.sourceFiles - val (errorMap, expectedErrors) = getErrorMapAndExpectedCount(sourceFiles) - val reporter = compile(sourceFiles, flags, true, outDir) - val actualErrors = reporter.errorCount - - if (reporter.compilerCrashed || actualErrors > 0) - logReporterContents(reporter) - - (reporter.compilerCrashed, expectedErrors, actualErrors, () => getMissingExpectedErrors(errorMap, reporter.errors), errorMap) - - case testSource @ SeparateCompilationSource(_, dir, flags, outDir) => { - val compilationGroups = testSource.compilationGroups - val (errorMap, expectedErrors) = getErrorMapAndExpectedCount(compilationGroups.toArray.flatten) - val reporters = compilationGroups.map(compile(_, flags, true, outDir)) - val compilerCrashed = reporters.exists(_.compilerCrashed) - val actualErrors = reporters.foldLeft(0)(_ + _.errorCount) - val errors = reporters.iterator.flatMap(_.errors) - - if (actualErrors > 0) - reporters.foreach(logReporterContents) - - (compilerCrashed, expectedErrors, actualErrors, () => getMissingExpectedErrors(errorMap, errors), errorMap) - } - } - - def fail(msg: String): Unit = { - echo(msg) - failTestSource(testSource) - } - - if (compilerCrashed) - fail(s"Compiler crashed when compiling: ${testSource.title}") - else if (actualErrors == 0) - fail(s"\nNo errors found when compiling neg test $testSource") - else if (expectedErrors != actualErrors) - fail(s"\nWrong number of errors encountered when compiling $testSource, expected: $expectedErrors, actual: $actualErrors") - else if (hasMissingAnnotations()) - fail(s"\nErrors found on incorrect row numbers when compiling $testSource") - else if (!errorMap.isEmpty) - fail(s"\nExpected error(s) have {=}: $errorMap") - - registerCompletion() - } - } - } - - /** The `CompilationTest` is the main interface to `ParallelTesting`, it - * can be instantiated via one of the following methods: - * - * - `compileFile` - * - `compileDir` - * - `compileList` - * - `compileFilesInDir` - * - `compileShallowFilesInDir` - * - * Each compilation test can then be turned into either a "pos", "neg" or - * "run" test: - * - * ``` - * compileFile("tests/pos/i1103.scala", opts).pos() - * ``` - * - * These tests can be customized before calling one of the execution - * methods, for instance: - * - * ``` - * compileFile("tests/pos/i1103.scala", opts).times(2).verbose.pos() - * ``` - * - * Which would compile `i1103.scala` twice with the verbose flag as a "pos" - * test. - * - * pos tests - * ========= - * Pos tests verify that the compiler is able to compile the given - * `TestSource`s and that they generate no errors or exceptions during - * compilation - * - * neg tests - * ========= - * Neg tests are expected to generate a certain amount of errors - but not - * crash the compiler. In each `.scala` file, you specify the line on which - * the error will be generated, e.g: - * - * ``` - * val x: String = 1 // error - * ``` - * - * if a line generates multiple errors, you need to annotate it multiple - * times. For a line that generates two errors: - * - * ``` - * val y: String = { val y1: String = 1; 2 } // error // error - * ``` - * - * Certain errors have no position, if you need to check these annotate the - * file anywhere with `// nopos-error` - * - * run tests - * ========= - * Run tests are a superset of pos tests, they both verify compilation and - * that the compiler does not crash. In addition, run tests verify that the - * tests are able to run as expected. - * - * Run tests need to have the following form: - * - * ``` - * object Test { - * def main(args: Array[String]): Unit = () - * } - * ``` - * - * This is because the runner instantiates the `Test` class and calls the - * main method. - * - * Other definitions are allowed in the same file, but the file needs to at - * least have the `Test` object with a `main` method. - * - * To verify output you may use `.check` files. These files should share the - * name of the file or directory that they are testing. For instance: - * - * ```none - * . - * └── tests - * ├── i1513.scala - * └── i1513.check - * ``` - * - * If you are testing a directory under separate compilation, you would - * have: - * - * ```none - * . - * └── tests - * ├── myTestDir - * │ ├── T_1.scala - * │ ├── T_2.scala - * │ └── T_3.scala - * └── myTestDir.check - * ``` - * - * In the above example, `i1513.scala` and one of the files `T_X.scala` - * would contain a `Test` object with a main method. - * - * Composing tests - * =============== - * Since this is a parallel test suite, it is essential to be able to - * compose tests to take advantage of the concurrency. This is done using - * the `+` function. This function will make sure that tests being combined - * are compatible according to the `require`s in `+`. - */ - final class CompilationTest private ( - private[ParallelTesting] val targets: List[TestSource], - private[ParallelTesting] val times: Int, - private[ParallelTesting] val shouldDelete: Boolean, - private[ParallelTesting] val threadLimit: Option[Int], - private[ParallelTesting] val shouldFail: Boolean, - private[ParallelTesting] val shouldSuppressOutput: Boolean - ) { - import org.junit.Assert.fail - - def this(target: TestSource) = - this(List(target), 1, true, None, false, false) - - def this(targets: List[TestSource]) = - this(targets, 1, true, None, false, false) - - /** Compose test targets from `this` with `other` - * - * It does this, only if the two tests are compatible. Otherwise it throws - * an `IllegalArgumentException`. - * - * Grouping tests together like this allows us to take advantage of the - * concurrency offered by this test suite as each call to an executing - * method (`pos()` / `checkExpectedErrors()`/ `run()`) will spin up a thread pool with the - * maximum allowed level of concurrency. Doing this for only a few targets - * does not yield any real benefit over sequential compilation. - * - * As such, each `CompilationTest` should contain as many targets as - * possible. - */ - def +(other: CompilationTest) = { - require(other.times == times, "can't combine tests that are meant to be benchmark compiled") - require(other.shouldDelete == shouldDelete, "can't combine tests that differ on deleting output") - require(other.shouldFail == shouldFail, "can't combine tests that have different expectations on outcome") - require(other.shouldSuppressOutput == shouldSuppressOutput, "can't combine tests that both suppress and don't suppress output") - new CompilationTest(targets ++ other.targets, times, shouldDelete, threadLimit, shouldFail, shouldSuppressOutput) - } - - /** Creates a "pos" test run, which makes sure that all tests pass - * compilation without generating errors and that they do not crash the - * compiler - */ - def checkCompile()(implicit summaryReport: SummaryReporting): this.type = { - val test = new PosTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite() - - cleanup() - - if (!shouldFail && test.didFail) { - fail(s"Expected no errors when compiling, failed for the following reason(s):\n${ reasonsForFailure(test) }") - } - else if (shouldFail && !test.didFail) { - fail("Pos test should have failed, but didn't") - } - - this - } - - /** Creates a "neg" test run, which makes sure that each test generates the - * correct amount of errors at the correct positions. It also makes sure - * that none of these tests crash the compiler - */ - def checkExpectedErrors()(implicit summaryReport: SummaryReporting): this.type = { - val test = new NegTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite() - - cleanup() - - if (shouldFail && !test.didFail) { - fail(s"Neg test shouldn't have failed, but did. Reasons:\n${ reasonsForFailure(test) }") - } - else if (!shouldFail && test.didFail) { - fail("Neg test should have failed, but did not") - } - - this - } - - /** Creates a "run" test run, which is a superset of "pos". In addition to - * making sure that all tests pass compilation and that they do not crash - * the compiler; it also makes sure that all tests can run with the - * expected output - */ - def checkRuns()(implicit summaryReport: SummaryReporting): this.type = { - val test = new RunTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite() - - cleanup() - - if (!shouldFail && test.didFail) { - fail(s"Run test failed, but should not, reasons:\n${ reasonsForFailure(test) }") - } - else if (shouldFail && !test.didFail) { - fail("Run test should have failed, but did not") - } - - this - } - - /** Deletes output directories and files */ - private def cleanup(): this.type = { - if (shouldDelete) delete() - this - } - - /** Extract `Failure` set and render from `Test` */ - private[this] def reasonsForFailure(test: Test): String = { - val failureReport = - if (test.failureCount == 0) "" - else s"\n - encountered ${test.failureCount} test failures(s)" - - failureReport + test.failureReasons.collect { - case test.TimeoutFailure(title) => - s" - test '$title' timed out" - case test.JavaCompilationFailure(msg) => - s" - java compilation failed with:\n${ msg.linesIterator.map(" " + _).mkString("\n") }" - }.mkString("\n") - } - - /** Copies `file` to `dir` - taking into account if `file` is a directory, - * and if so copying recursively - */ - private def copyToDir(dir: JFile, file: JFile): JFile = { - val target = Paths.get(dir.getAbsolutePath, file.getName) - Files.copy(file.toPath, target, REPLACE_EXISTING) - if (file.isDirectory) file.listFiles.map(copyToDir(target.toFile, _)) - target.toFile - } - - /** Builds a new `CompilationTest` where we have copied the target files to - * the out directory. This is needed for tests that modify the original - * source, such as `-rewrite` tests - */ - def copyToTarget(): CompilationTest = new CompilationTest ( - targets.map { - case target @ JointCompilationSource(_, files, _, outDir, _, _) => - target.copy(files = files.map(copyToDir(outDir,_))) - case target @ SeparateCompilationSource(_, dir, _, outDir) => - target.copy(dir = copyToDir(outDir, dir)) - }, - times, shouldDelete, threadLimit, shouldFail, shouldSuppressOutput - ) - - /** Builds a `CompilationTest` which performs the compilation `i` times on - * each target - */ - def times(i: Int): CompilationTest = - new CompilationTest(targets, i, shouldDelete, threadLimit, shouldFail, shouldSuppressOutput) - - /** Builds a `Compilationtest` which passes the verbose flag and logs the - * classpath - */ - def verbose: CompilationTest = new CompilationTest( - targets.map(t => t.withFlags("-verbose", "-Ylog-classpath")), - times, shouldDelete, threadLimit, shouldFail, shouldSuppressOutput - ) - - /** Builds a `CompilationTest` which keeps the generated output files - * - * This is needed for tests like `tastyBootstrap` which relies on first - * compiling a certain part of the project and then compiling a second - * part which depends on the first - */ - def keepOutput: CompilationTest = - new CompilationTest(targets, times, false, threadLimit, shouldFail, shouldSuppressOutput) - - /** Builds a `CompilationTest` with a limited level of concurrency with - * maximum `i` threads - */ - def limitThreads(i: Int): CompilationTest = - new CompilationTest(targets, times, shouldDelete, Some(i), shouldFail, shouldSuppressOutput) - - /** Builds a `CompilationTest` where the executed test is expected to fail - * - * This behaviour is mainly needed for the tests that test the test suite. - */ - def expectFailure: CompilationTest = - new CompilationTest(targets, times, shouldDelete, threadLimit, true, shouldSuppressOutput) - - /** Builds a `CompilationTest` where all output is suppressed - * - * This behaviour is mainly needed for the tests that test the test suite. - */ - def suppressAllOutput: CompilationTest = - new CompilationTest(targets, times, shouldDelete, threadLimit, shouldFail, true) - - /** Delete all output files generated by this `CompilationTest` */ - def delete(): Unit = targets.foreach(t => delete(t.outDir)) - - private def delete(file: JFile): Unit = { - if (file.isDirectory) file.listFiles.foreach(delete) - try Files.delete(file.toPath) - catch { - case _: NoSuchFileException => // already deleted, everything's fine - } - } - } - - /** Create out directory for directory `d` */ - def createOutputDirsForDir(d: JFile, sourceDir: JFile, outDir: String): JFile = { - val targetDir = new JFile(outDir + s"${sourceDir.getName}/${d.getName}") - targetDir.mkdirs() - targetDir - } - - /** Create out directory for `file` */ - private def createOutputDirsForFile(file: JFile, sourceDir: JFile, outDir: String): JFile = { - val uniqueSubdir = file.getName.substring(0, file.getName.lastIndexOf('.')) - val targetDir = new JFile(outDir + s"${sourceDir.getName}${JFile.separatorChar}$uniqueSubdir") - targetDir.mkdirs() - targetDir - } - - /** Make sure that directory string is as expected */ - private def checkRequirements(f: String, sourceDir: JFile, outDir: String): Unit = { - require(sourceDir.isDirectory && sourceDir.exists, "passed non-directory to `compileFilesInDir`: " + sourceDir) - require(outDir.last == JFile.separatorChar, "please specify an `outDir` with a trailing file separator") - } - - /** Separates directories from files and returns them as `(dirs, files)` */ - private def compilationTargets(sourceDir: JFile, fileFilter: FileFilter = FileFilter.NoFilter): (List[JFile], List[JFile]) = - sourceDir.listFiles.foldLeft((List.empty[JFile], List.empty[JFile])) { case ((dirs, files), f) => - if (!fileFilter.accept(f.getName)) (dirs, files) - else if (f.isDirectory) (f :: dirs, files) - else if (isSourceFile(f)) (dirs, f :: files) - else (dirs, files) - } - - /** Compiles a single file from the string path `f` using the supplied flags */ - def compileFile(f: String, flags: TestFlags)(implicit testGroup: TestGroup): CompilationTest = { - val sourceFile = new JFile(f) - val parent = sourceFile.getParentFile - val outDir = - defaultOutputDir + testGroup + JFile.separator + - sourceFile.getName.substring(0, sourceFile.getName.lastIndexOf('.')) + JFile.separator - - require( - sourceFile.exists && !sourceFile.isDirectory && - (parent ne null) && parent.exists && parent.isDirectory, - s"Source file: $f, didn't exist" - ) - - val target = JointCompilationSource( - testGroup.name, - Array(sourceFile), - flags, - createOutputDirsForFile(sourceFile, parent, outDir) - ) - new CompilationTest(target) - } - - /** Compiles a directory `f` using the supplied `flags`. This method does - * deep compilation, that is - it compiles all files and subdirectories - * contained within the directory `f`. - * - * By default, files are compiled in alphabetical order. An optional seed - * can be used for randomization. - */ - def compileDir(f: String, flags: TestFlags, randomOrder: Option[Int] = None, recursive: Boolean = true)(implicit testGroup: TestGroup): CompilationTest = { - val outDir = defaultOutputDir + testGroup + JFile.separator - val sourceDir = new JFile(f) - checkRequirements(f, sourceDir, outDir) - - def flatten(f: JFile): Array[JFile] = - if (f.isDirectory) { - val files = f.listFiles - if (recursive) files.flatMap(flatten) else files - } - else Array(f) - - // Sort files either alphabetically or randomly using the provided seed: - val sortedFiles = flatten(sourceDir).sorted - val randomized = randomOrder match { - case None => sortedFiles - case Some(seed) => new Random(seed).shuffle(sortedFiles.toList).toArray - } - - // Directories in which to compile all containing files with `flags`: - val targetDir = new JFile(outDir + JFile.separator + sourceDir.getName + JFile.separator) - targetDir.mkdirs() - - val target = JointCompilationSource(s"compiling '$f' in test '$testGroup'", randomized, flags, targetDir) - new CompilationTest(target) - } - - /** Compiles all `files` together as a single compilation run. It is given a - * `testName` since files can be in separate directories and or be otherwise - * dissociated - */ - def compileList(testName: String, files: List[String], flags: TestFlags)(implicit testGroup: TestGroup): CompilationTest = { - val outDir = defaultOutputDir + testGroup + JFile.separator + testName + JFile.separator - - // Directories in which to compile all containing files with `flags`: - val targetDir = new JFile(outDir) - targetDir.mkdirs() - assert(targetDir.exists, s"couldn't create target directory: $targetDir") - - val target = JointCompilationSource(s"$testName from $testGroup", files.map(new JFile(_)).toArray, flags, targetDir) - - // Create a CompilationTest and let the user decide whether to execute a pos or a neg test - new CompilationTest(target) - } - - /** This function compiles the files and folders contained within directory - * `f` in a specific way. - * - * - Each file is compiled separately as a single compilation run - * - Each directory is compiled as a `SeparateCompilationTarget`, in this - * target all files are grouped according to the file suffix `_X` where `X` - * is a number. These groups are then ordered in ascending order based on - * the value of `X` and each group is compiled one after the other. - * - * For this function to work as expected, we use the same convention for - * directory layout as the old partest. That is: - * - * - Single files can have an associated check-file with the same name (but - * with file extension `.check`) - * - Directories can have an associated check-file, where the check file has - * the same name as the directory (with the file extension `.check`) - */ - def compileFilesInDir(f: String, flags: TestFlags, fileFilter: FileFilter = FileFilter.NoFilter)(implicit testGroup: TestGroup): CompilationTest = { - val outDir = defaultOutputDir + testGroup + JFile.separator - val sourceDir = new JFile(f) - checkRequirements(f, sourceDir, outDir) - - val (dirs, files) = compilationTargets(sourceDir, fileFilter) - - val targets = - files.map(f => JointCompilationSource(testGroup.name, Array(f), flags, createOutputDirsForFile(f, sourceDir, outDir))) ++ - dirs.map(dir => SeparateCompilationSource(testGroup.name, dir, flags, createOutputDirsForDir(dir, sourceDir, outDir))) - - // Create a CompilationTest and let the user decide whether to execute a pos or a neg test - new CompilationTest(targets) - } - - /** This function compiles the files and folders contained within directory - * `f` in a specific way. Once compiled, they are recompiled/run from tasty as sources. - * - * - Each file is compiled separately as a single compilation run - * - Each directory is compiled as a `SeparateCompilationTarget`, in this - * target all files are grouped according to the file suffix `_X` where `X` - * is a number. These groups are then ordered in ascending order based on - * the value of `X` and each group is compiled one after the other. - * - * For this function to work as expected, we use the same convention for - * directory layout as the old partest. That is: - * - * - Single files can have an associated check-file with the same name (but - * with file extension `.check`) - * - Directories can have an associated check-file, where the check file has - * the same name as the directory (with the file extension `.check`) - * - * Tests in the first part of the tuple must be executed before the second. - * Both testsRequires explicit delete(). - */ - def compileTastyInDir(f: String, flags0: TestFlags, fromTastyFilter: FileFilter, decompilationFilter: FileFilter, recompilationFilter: FileFilter)( - implicit testGroup: TestGroup): TastyCompilationTest = { - val outDir = defaultOutputDir + testGroup + JFile.separator - val flags = flags0 and "-Yretain-trees" - val sourceDir = new JFile(f) - checkRequirements(f, sourceDir, outDir) - - val (dirs, files) = compilationTargets(sourceDir, fromTastyFilter) - - val filteredFiles = testFilter match { - case Some(str) => files.filter(_.getAbsolutePath.contains(str)) - case None => files - } - - class JointCompilationSourceFromTasty( - name: String, - file: JFile, - flags: TestFlags, - outDir: JFile, - fromTasty: Boolean = false, - decompilation: Boolean = false - ) extends JointCompilationSource(name, Array(file), flags, outDir, fromTasty, decompilation) { - - override def buildInstructions(errors: Int, warnings: Int): String = { - val runOrPos = if (file.getPath.startsWith(s"tests${JFile.separator}run${JFile.separator}")) "run" else "pos" - val listName = if (fromTasty) "from-tasty" else "decompilation" - s"""| - |Test '$title' compiled with $errors error(s) and $warnings warning(s), - |the test can be reproduced by running: - | - | sbt "testFromTasty $file" - | - |This tests can be disabled by adding `${file.getName}` to `compiler${JFile.separator}test${JFile.separator}dotc${JFile.separator}$runOrPos-$listName.blacklist` - | - |""".stripMargin - } - - } - - val targets = filteredFiles.map { f => - val classpath = createOutputDirsForFile(f, sourceDir, outDir) - new JointCompilationSourceFromTasty(testGroup.name, f, flags.withClasspath(classpath.getPath), classpath, fromTasty = true) - } - // TODO add SeparateCompilationSource from tasty? - - val targets2 = - filteredFiles - .filter(f => decompilationFilter.accept(f.getName)) - .map { f => - val classpath = createOutputDirsForFile(f, sourceDir, outDir) - new JointCompilationSourceFromTasty(testGroup.name, f, flags.withClasspath(classpath.getPath), classpath, decompilation = true) - } - - // Create a CompilationTest and let the user decide whether to execute a pos or a neg test - val generateClassFiles = compileFilesInDir(f, flags0, fromTastyFilter) - - val decompilationDir = outDir + sourceDir.getName + "_decompiled" - - if (targets2.isEmpty) - new JFile(decompilationDir).mkdirs() - - new TastyCompilationTest( - generateClassFiles.keepOutput, - new CompilationTest(targets).keepOutput, - new CompilationTest(targets2).keepOutput, - recompilationFilter, - decompilationDir, - shouldDelete = true - ) - } - - class TastyCompilationTest(step1: CompilationTest, step2: CompilationTest, step3: CompilationTest, - recompilationFilter: FileFilter, decompilationDir: String, shouldDelete: Boolean)(implicit testGroup: TestGroup) { - - def keepOutput: TastyCompilationTest = - new TastyCompilationTest(step1, step2, step3, recompilationFilter, decompilationDir, shouldDelete) - - def checkCompile()(implicit summaryReport: SummaryReporting): this.type = { - step1.checkCompile() // Compile all files to generate the class files with tasty - step2.checkCompile() // Compile from tasty - step3.checkCompile() // Decompile from tasty - - val step4 = compileFilesInDir(decompilationDir, defaultOptions, recompilationFilter).keepOutput - step4.checkCompile() // Recompile decompiled code - - if (shouldDelete) - (step1 + step2 + step3 + step4).delete() - - this - } - - def checkRuns()(implicit summaryReport: SummaryReporting): this.type = { - step1.checkCompile() // Compile all files to generate the class files with tasty - step2.checkRuns() // Compile from tasty - step3.checkCompile() // Decompile from tasty - - val step4 = compileFilesInDir(decompilationDir, defaultOptions, recompilationFilter).keepOutput - step4.checkRuns() // Recompile decompiled code - - if (shouldDelete) - (step1 + step2 + step3 + step4).delete() - - this - } - } - - /** This function behaves similar to `compileFilesInDir` but it ignores - * sub-directories and as such, does **not** perform separate compilation - * tests. - */ - def compileShallowFilesInDir(f: String, flags: TestFlags)(implicit testGroup: TestGroup): CompilationTest = { - val outDir = defaultOutputDir + testGroup + JFile.separator - val sourceDir = new JFile(f) - checkRequirements(f, sourceDir, outDir) - - val (_, files) = compilationTargets(sourceDir) - - val targets = files.map { file => - JointCompilationSource(testGroup.name, Array(file), flags, createOutputDirsForFile(file, sourceDir, outDir)) - } - - // Create a CompilationTest and let the user decide whether to execute a pos or a neg test - new CompilationTest(targets) - } -} - -object ParallelTesting { - - def defaultOutputDir: String = "out"+JFile.separator - - def isSourceFile(f: JFile): Boolean = { - val name = f.getName - name.endsWith(".scala") || name.endsWith(".java") - } - - def isTastyFile(f: JFile): Boolean = - f.getName.endsWith(".hasTasty") || f.getName.endsWith(".tasty") -} diff --git a/dist/bin/common.bat b/dist/bin/common.bat deleted file mode 100644 index 1d333d7b7a6f..000000000000 --- a/dist/bin/common.bat +++ /dev/null @@ -1,59 +0,0 @@ -rem ########################################################################## -rem ## Code common to dotc.bat, dotd.bat and dotr.bat - -if defined JAVACMD ( - set _JAVACMD=%JAVACMD% -) else if defined JAVA_HOME ( - set _JAVACMD=%JAVA_HOME%\bin\java.exe -) else if defined JDK_HOME ( - set _JAVACMD=%JDK_HOME%\bin\java.exe -) else ( - where /q java.exe - if !ERRORLEVEL!==0 ( - for /f "delims=" %%i in ('where /f java.exe') do set _JAVA_BIN_DIR=%%~dpsi - rem we ignore Oracle path for java executable - if "!_JAVA_BIN_DIR!"=="!_JAVA_BIN_DIR:javapath=!" set _JAVACMD=!_JAVA_BIN_DIR!\java.exe - ) - if not defined _JAVACMD ( - set _PATH=C:\Progra~1\Java - for /f %%f in ('dir /ad /b "!_PATH!\jre*" 2^>NUL') do set _JAVA_HOME=!_PATH!\%%f - if not defined _JAVA_HOME ( - set _PATH=C:\opt - for /f %%f in ('dir /ad /b "!_PATH!\jdk*" 2^>NUL') do set _JAVA_HOME=!_PATH!\%%f\jre - ) - if defined _JAVA_HOME ( - set _JAVACMD=!_JAVA_HOME!\bin\java.exe - ) - ) -) -if not exist "%_JAVACMD%" ( - echo Error: Java executable not found ^(%_JAVACMD%^) 1>&2 - set _EXITCODE=1 - goto :eof -) - -if defined DOTTY_HOME ( - set _LIB_DIR=%DOTTY_HOME%\lib -) else ( - if not defined _PROG_HOME ( - for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf - ) - set _LIB_DIR=!_PROG_HOME!\lib -) - -set _PSEP=; - -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-compiler*"') do set _DOTTY_COMP=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-interfaces*"') do set _DOTTY_INTF=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*dotty-library*"') do set _DOTTY_LIB=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-asm*"') do set _SCALA_ASM=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-library*"') do set _SCALA_LIB=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*scala-xml*"') do set _SCALA_XML=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*compiler-interface*"') do set _SBT_INTF=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-reader-3*"') do set _JLINE_READER=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-terminal-3*"') do set _JLINE_TERMINAL=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jline-terminal-jna-3*"') do set _JLINE_TERMINAL_JNA=%_LIB_DIR%\%%f -for /f %%f in ('dir /a-d /b "%_LIB_DIR%\*jna-4*"') do set _JNA=%_LIB_DIR%\%%f - -rem debug -set _DEBUG_STR=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 diff --git a/dist/bin/dotc.bat b/dist/bin/dotc.bat deleted file mode 100644 index c7eade2fc917..000000000000 --- a/dist/bin/dotc.bat +++ /dev/null @@ -1,152 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem ########################################################################## -rem ## Environment setup - -set _EXITCODE=0 - -set _BASENAME=%~n0 - -for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf - -call %_PROG_HOME%\bin\common.bat -if not %_EXITCODE%==0 goto end - -set _COMPILER_MAIN=dotty.tools.dotc.Main -set _DECOMPILER_MAIN=dotty.tools.dotc.decompiler.Main -set _REPL_MAIN=dotty.tools.repl.Main - -set _PROG_NAME=%_COMPILER_MAIN% - -call :args %* - -rem ########################################################################## -rem ## Main - -call :classpathArgs - -if defined JAVA_OPTS ( set _JAVA_OPTS=%JAVA_OPTS% -) else ( set _JAVA_OPTS=-Xmx768m -Xms768m -) -"%_JAVACMD%" %_JAVA_OPTS% %_JAVA_DEBUG% %_JAVA_ARGS% %_JVM_CP_ARGS% ^ --Dscala.usejavacp=true ^ -%_PROG_NAME% %_SCALA_ARGS% %_RESIDUAL_ARGS% -if not %ERRORLEVEL%==0 ( - rem echo Error: Dotty compiler execution failed 1>&2 - set _EXITCODE=1 - goto end -) -goto end - -rem ########################################################################## -rem ## Subroutines - -:args -set _JAVA_DEBUG= -set _HELP= -set _VERBOSE= -set _QUIET= -set _COLORS= -set _SCALA_ARGS= -set _JAVA_ARGS= -set _RESIDUAL_ARGS= - -:args_loop -if "%~1"=="" goto args_done -set __ARG=%~1 -if "%__ARG%"=="--" ( - rem for arg; do addResidual "$arg"; done; set -- ;; -) else if /i "%__ARG%"=="-h" ( - set _HELP=true - call :addScala "-help" -) else if /i "%__ARG%"=="-help" ( - set _HELP=true - call :addScala "-help" -) else if /i "%__ARG%"=="-v" ( - set _VERBOSE=true - call :addScala "-verbose" -) else if /i "%__ARG%"=="-verbose" ( - set _VERBOSE=true - call :addScala "-verbose" -) else if /i "%__ARG%"=="-debug" ( set _JAVA_DEBUG=%_DEBUG_STR% -) else if /i "%__ARG%"=="-q" ( set _QUIET=true -) else if /i "%__ARG%"=="-quiet" ( set _QUIET=true -rem Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 -) else if "%__ARG%"=="-=short" ( - call :addJava "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" -) else if /i "%__ARG%"=="-repl" ( set _PROG_NAME=%_REPL_MAIN% -) else if /i "%__ARG%"=="-compile" ( set _PROG_NAME=%_COMPILER_MAIN% -) else if /i "%__ARG%"=="-decompile" ( set _PROG_NAME=%_DECOMPILER_MAIN% -) else if /i "%__ARG%"=="print-tasty" ( - set _PROG_NAME=%_DECOMPILER_MAIN% - call :addScala "-print-tasty" -) else if /i "%__ARG%"=="-run" ( set _PROG_NAME=%_REPL_MAIN% -) else if /i "%__ARG%"=="-colors" ( set _COLORS=true -) else if /i "%__ARG%"=="-no-colors" ( set _COLORS= -) else if /i "%__ARG%"=="-with-compiler" ( set _JVM_CP_ARGS=%_PSEP%%_DOTTY_COMP% -rem break out -D and -J options and add them to JAVA_OPTS as well -rem so they reach the JVM in time to do some good. The -D options -rem will be available as system properties. -) else if "%_ARG:~0,2%"=="-D" ( - call :addJava "%__ARG%" - call :addScala "%__ARG%" -) else if "%_ARG:~0,2%"=="-J" ( - call :addJava "%__ARG%" - call :addScala "%__ARG%" -) else ( - call :addResidual "%__ARG%" -) -shift -goto args_loop -:args_done -goto :eof - -rem output parameter: _SCALA_ARGS -:addScala -set _SCALA_ARGS=%_SCALA_ARGS% %~1 -goto :eof - -rem output parameter: _JAVA_ARGS -:addJava -set _JAVA_ARGS=%_JAVA_ARGS% %~1 -goto :eof - -rem output parameter: _RESIDUAL_ARGS -:addResidual -set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %~1 -goto :eof - -rem output parameter: _JVM_CP_ARGS -:classpathArgs -rem echo dotty-compiler: %_DOTTY_COMP% -rem echo dotty-interface: %_DOTTY_INTF% -rem echo dotty-library: %_DOTTY_LIB% -rem echo scala-asm: %_SCALA_ASM% -rem echo scala-lib: %_SCALA_LIB% -rem echo scala-xml: %_SCALA_XML% -rem echo sbt-intface: %_SBT_INTF% - -set __TOOLCHAIN=%_SCALA_LIB%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_SCALA_ASM%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_SBT_INTF%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_INTF%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_LIB%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_DOTTY_COMP%%_PSEP% - -rem # jline -set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_READER%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_TERMINAL%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_JLINE_TERMINAL_JNA%%_PSEP% -set __TOOLCHAIN=%__TOOLCHAIN%%_JNA% - -set _JVM_CP_ARGS=-classpath %__TOOLCHAIN% -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -exit /b %_EXITCODE% -endlocal - diff --git a/dist/bin/dotd.bat b/dist/bin/dotd.bat deleted file mode 100644 index f1a40fbeca51..000000000000 --- a/dist/bin/dotd.bat +++ /dev/null @@ -1,99 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem ########################################################################## -rem ## Environment setup - -set _EXITCODE=0 - -set _BASENAME=%~n0 - -for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf - -call %_PROG_HOME%\bin\common.bat -if not %_EXITCODE%==0 goto end - -rem ########################################################################## -rem ## Main - -call :javaClassPath - -"%_JAVACMD%" -Dscala.usejavacp=true -classpath "%_CLASS_PATH%" dotty.tools.dottydoc.Main %* -if not %ERRORLEVEL%==0 ( - rem echo Error: Dottydoc execution failed 1>&2 - set _EXITCODE=1 - goto end -) -goto end - -rem ########################################################################## -rem ## Subroutines - -rem output parameter: _CLASS_PATH -:javaClassPath -set __LIB_DIR=%_PROG_HOME%\lib - -rem Set dotty-doc dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*dotty-doc*"') do set _DOTTY_DOC_LIB=%__LIB_DIR%\%%f - -rem Set flexmark deps: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-0*"') do set _FLEXMARK_LIBS=%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-anchorlink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-autolink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-emoji*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-strikethrough*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-gfm-tasklist*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-ins*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-superscript*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-tables*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-wikilink*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-ext-yaml-front-matter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-formatter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-jira-converter*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*flexmark-util*"') do set _FLEXMARK_LIBS=%_FLEXMARK_LIBS%%__LIB_DIR%\%%f%_PSEP% - -rem Set jackson deps: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-annotations*"') do set _JACKSON_LIBS=%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-core*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-databind*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jackson-dataformat-yaml*"') do set _JACKSON_LIBS=%_JACKSON_LIBS%%__LIB_DIR%\%%f%_PSEP% - -rem Set liqp dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*liqp*"') do set _LIQP_LIB=%__LIB_DIR%\%%f%_PSEP% - -rem Set ANTLR dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*antlr-3*"') do set _ANTLR_LIB=%__LIB_DIR%\%%f%_PSEP% -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*antlr-runtime-3*"') do set _ANTLR_RUNTIME_LIB=%__LIB_DIR%\%%f%_PSEP% - -rem Set autolink dep: -rem conflict with flexmark-ext-autolink-0.11 -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*autolink-0.6*"') do set _AUTOLINK_LIB=%__LIB_DIR%\%%f - -rem Set snakeyaml dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*snakeyaml*"') do set _SNAKEYAML_LIB=%__LIB_DIR%\%%f%_PSEP% - -rem Set ST4 dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*ST4*"') do set _ST4_LIB=%__LIB_DIR%\%%f%_PSEP% - -rem Set jsoup dep: -for /f %%f in ('dir /a-d /b "%__LIB_DIR%\*jsoup*"') do set _JSOUP_LIB=%__LIB_DIR%\%%f%_PSEP% - -set _CLASS_PATH=%_DOTTY_LIB%%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_DOC_LIB%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SBT_INTF% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_SCALA_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_FLEXMARK_LIBS% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_JACKSON_LIBS% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_LIQP_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_ANTLR_LIB%%_PSEP%%_ANTLR_RUNTIME_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_AUTOLINK_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_SNAKEYAML_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_ST4_LIB% -set _CLASS_PATH=%_CLASS_PATH%%_PSEP%%_JSOUP_LIB% -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -exit /b %_EXITCODE% -endlocal diff --git a/dist/bin/dotr.bat b/dist/bin/dotr.bat deleted file mode 100644 index 61c003af0cae..000000000000 --- a/dist/bin/dotr.bat +++ /dev/null @@ -1,102 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem ########################################################################## -rem ## Environment setup - -set _EXITCODE=0 - -set _BASENAME=%~n0 - -for %%f in ("%~dp0..") do set _PROG_HOME=%%~sf - -call %_PROG_HOME%\bin\common.bat -if not %_EXITCODE%==0 goto end - -call :args %* - -rem ########################################################################## -rem ## Main - -set _CASE_1=0 -if %_EXECUTE_REPL%==1 set _CASE_1=1 -if %_EXECUTE_RUN%==0 if not defined _RESIDUAL_ARGS set _CASE_1=1 - -set _CASE_2=0 -if %_EXECUTE_RUN%==1 set _CASE_2=1 -if defined _RESIDUAL_ARGS set _CASE_2=1 - -rem if [ $execute_repl == true ] || ([ $execute_run == false ] && [ $options_indicator == 0 ]); then -if %_CASE_1%==1 ( - set _DOTC_ARGS= - if defined _CLASS_PATH set _DOTC_ARGS=-classpath "%_CLASS_PATH%" - set _DOTC_ARGS=!_DOTC_ARGS! %_JAVA_OPTIONS% -repl %_RESIDUAL_ARGS% - echo Starting dotty REPL... - %_PROG_HOME%\bin\dotc.bat !_DOTC_ARGS! -rem elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then -) else if %_CASE_2%==1 ( - set _CP_ARG=%_DOTTY_LIB%%_PSEP%%_SCALA_LIB% - if defined _CLASS_PATH ( set _CP_ARG=!_CP_ARG!%_PSEP%%_CLASS_PATH% - ) else ( set _CP_ARG=!_CP_ARG!%_PSEP%. - ) - if %_CLASS_PATH_COUNT% gtr 1 ( - echo Warning: Multiple classpaths are found, dotr only use the last one. 1>&2 - ) - if %_WITH_COMPILER%==1 ( - set _CP_ARG=!_CP_ARG!%_PSEP%%_DOTTY_COMP%%_PSEP%%_DOTTY_INTF%%_PSEP%%_SCALA_ASM% - ) - set _JAVA_ARGS=%_JAVA_DEBUG% -classpath "!_CP_ARG!" %_RESIDUAL_ARGS% - %_JAVACMD% !_JAVA_ARGS! -) else ( - echo Warning: Command option is not correct. 1>&2 -) - -goto end - -rem ########################################################################## -rem ## Subroutines - -:args -set _RESIDUAL_ARGS= -set _EXECUTE_REPL=0 -set _EXECUTE_RUN=0 -set _WITH_COMPILER=0 -set _JAVA_DEBUG= -set _CLASS_PATH_COUNT=0 -set _CLASS_PATH= -set _JVM_OPTIONS= -set _JAVA_OPTIONS= - -:args_loop -if "%1"=="" goto args_done -set "__ARG=%1" -if %_DEBUG%==1 echo [%_BASENAME%] __ARG=%__ARG% -if /i "%__ARG%"=="-repl" ( - set _EXECUTE_REPL=1 -) else if /i "%__ARG%"=="-run" ( - set _EXECUTE_RUN=1 -) else if /i "%__ARG%"=="-classpath" ( - set _CLASS_PATH=%2 - set /a _CLASS_PATH_COUNT+=1 - shift -) else if /i "%__ARG%"=="-with-compiler" ( - set _WITH_COMPILER=1 -) else if /i "%__ARG%"=="-d" ( - set _JAVA_DEBUG=%_DEBUG_STR% -) else if /i "%_ARG:~0,2%"=="-J" ( - set _JVM_OPTIONS=!_JVM_OPTIONS! %__ARG% - set _JAVA_OPTIONS=!_JAVA_OPTIONS! %__ARG% -) else ( - set _RESIDUAL_ARGS=%_RESIDUAL_ARGS% %__ARG% -) -shift -goto args_loop -:args_done -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -exit /b %_EXITCODE% -endlocal diff --git a/project/scripts/build.bat b/project/scripts/build.bat deleted file mode 100644 index bdbfd7e06f74..000000000000 --- a/project/scripts/build.bat +++ /dev/null @@ -1,456 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -rem only for interactive debugging -set _DEBUG=0 - -rem ########################################################################## -rem ## Environment setup - -set _BASENAME=%~n0 - -set _EXITCODE=0 - -set _BOT_TOKEN=dotty-token - -rem set _DRONE_BUILD_EVENT=pull_request -set _DRONE_BUILD_EVENT= -set _DRONE_REMOTE_URL= -set _DRONE_BRANCH= - -for %%f in ("%~dp0..\..") do set _ROOT_DIR=%%~sf -set _BIN_DIR=%_ROOT_DIR%bin -set _TESTS_POS_DIR=%_ROOT_DIR%test\pos - -set _SOURCE=tests/pos/HelloWorld.scala -set _MAIN=HelloWorld -set _EXPECTED_OUTPUT=hello world - -call :args %* -if not %_EXITCODE%==0 goto end -if defined _HELP call :help & exit /b %_EXITCODE% - -if exist "C:\Temp\" ( set _TMP_DIR=C:\Temp -) else ( set _TMP_DIR=%TEMP% -) -set _OUT_DIR=%_TMP_DIR%\%_BASENAME%_out -if not exist "%_OUT_DIR%" mkdir "%_OUT_DIR%" - -set _OUT1_DIR=%_TMP_DIR%\%_BASENAME%_out1 -if not exist "%_OUT1_DIR%" mkdir "%_OUT1_DIR%" - -set _TMP_FILE=%_TMP_DIR%\%_BASENAME%_tmp.txt - -rem see file project/scripts/sbt -rem SBT uses the value of the JAVA_OPTS environment variable if defined, rather than the config. -set JAVA_OPTS=-Xmx2048m ^ --XX:ReservedCodeCacheSize=2048m ^ --XX:MaxMetaspaceSize=1024m - -set SBT_OPTS=-Ddotty.drone.mem=4096m ^ --Dsbt.ivy.home=%USERPROFILE%\.ivy2\ ^ --Dsbt.log.noformat=true - -rem ########################################################################## -rem ## Main - -call :init -if not %_EXITCODE%==0 goto end - -if defined _CLEAN_ALL ( - call :clean_all - if not !_EXITCODE!==0 goto end -) -if defined _CLONE ( - call :clone - if not !_EXITCODE!==0 goto end -) -if defined _COMPILE ( - call :test - if not !_EXITCODE!==0 goto end -) -if defined _BOOTSTRAP ( - call :test_bootstrapped - rem if not !_EXITCODE!==0 goto end - if not !_EXITCODE!==0 ( - if defined _IGNORE ( echo ###### Warning: _EXITCODE=!_EXITCODE! ####### 1>&2 - ) else ( goto end - ) - ) -) -if defined _DOCUMENTATION ( - call :documentation - if not !_EXITCODE!==0 goto end -) - -if defined _ARCHIVES ( - call :archives - if not !_EXITCODE!==0 goto end -) -goto end - -rem ########################################################################## -rem ## Subroutines - -rem input parameter: %* -rem output parameters: _CLONE, _COMPILE, _DOCUMENTATION, _TIMER, _VERBOSE, -:args -set _ARCHIVES= -set _BOOTSTRAP= -set _COMPILE= -set _CLEAN_ALL= -set _CLONE= -set _DOCUMENTATION= -set _HELP= -set _TIMER=0 -set _VERBOSE=0 - -:args_loop -set __ARG=%~1 -if not defined __ARG goto args_done -if /i "%__ARG%"=="help" ( set _HELP=1& goto :eof -) else if /i "%__ARG%"=="-timer" ( set _TIMER=1 -) else if /i "%__ARG%"=="-verbose" ( set _VERBOSE=1 -) else if /i "%__ARG:~0,4%"=="arch" ( - if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _COMPILE=1& set _BOOTSTRAP=1 - set _ARCHIVES=1 -) else if /i "%__ARG:~0,4%"=="boot" ( - if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _COMPILE=1 - set _BOOTSTRAP=1 -) else if /i "%__ARG%"=="cleanall" ( set _CLEAN_ALL=1 -) else if /i "%__ARG%"=="clone" ( set _CLONE=1 -) else if /i "%__ARG:~0,7%"=="compile" ( - if not "%__ARG:~-5%"=="-only" set _CLONE=1 - set _COMPILE=1 -) else if /i "%__ARG:~0,3%"=="doc" ( - if not "%__ARG:~-5%"=="-only" set _CLONE=1& set _COMPILE=1& set _BOOTSTRAP=1 - set _DOCUMENTATION=1 -) else ( - echo Error: Unknown subcommand %__ARG% - set _EXITCODE=1 - goto :eof -) -shift -goto args_loop -:args_done -goto :eof - -:help -echo Usage: %_BASENAME% { options ^| subcommands } -echo Options: -echo -timer display total build time -echo -verbose display environment settings -echo Subcommands: -echo arch[ives] generate gz/zip archives (after bootstrap) -echo arch[ives]-only generate ONLY gz/zip archives -echo boot[strap] generate compiler bootstrap (after compile) -echo boot[strap]-only generate ONLY compiler bootstrap -echo cleanall clean project (sbt+git) and quit -echo clone update submodules -echo compile generate compiler 1st stage (after clone) -echo compile-only generate ONLY compiler 1st stage -echo doc[umentation] generate documentation (after bootstrap) -echo doc[umentation]-only] generate ONLY documentation -echo help display this help message -goto :eof - -rem output parameters: _GIT_CMD, _SBT_CMD -:init -where /q git.exe -if not %ERRORLEVEL%==0 ( - echo Error: Git command not found ^(check your PATH variable^) 1>&2 - set _EXITCODE=1 - goto end -) -set _GIT_CMD=git.exe - -where /q sbt.bat -if not %ERRORLEVEL%==0 ( - echo Error: SBT command not found ^(check your PATH variable^) 1>&2 - set _EXITCODE=1 - goto end -) -rem full path is required for sbt to run successfully -for /f %%i in ('where sbt.bat') do set _SBT_CMD=%%i - -if %_VERBOSE%==1 ( - for /f %%i in ('where git.exe') do set _GIT_CMD1=%%i - echo _GIT_CMD=!_GIT_CMD1! - echo _SBT_CMD=%_SBT_CMD% - echo JAVA_OPTS=%JAVA_OPTS% - echo SBT_OPTS=%SBT_OPTS% - echo. -) -if %_TIMER%==1 ( - for /f "delims=" %%i in ('powershell -c "(Get-Date)"') do set _TIMER_START=%%i -) -goto :eof - -:clean_all -echo run sbt clean and git clean -xdf -if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" clean -call "%_SBT_CMD%" clean -if not %ERRORLEVEL%==0 ( - set _EXITCODE=1 - goto :eof -) -if %_DEBUG%==1 echo [%_BASENAME%] %_GIT_CMD% clean -xdf -%_GIT_CMD% clean -xdf -if not %ERRORLEVEL%==0 ( - set _EXITCODE=1 - goto :eof -) -goto :eof - -:clone -if "%_DRONE_BUILD_EVENT%"=="pull_request" if defined _DRONE_REMOTE_URL ( - %_GIT_CMD% config user.email "dotty.bot@epfl.ch" - %_GIT_CMD% config user.name "Dotty CI" - %_GIT_CMD% pull "%_DRONE_REMOTE_URL%" "%_DRONE_BRANCH%" -) -if %_DEBUG%==1 echo [%_BASENAME%] %_GIT_CMD% submodule update --init --recursive --jobs 3 -%_GIT_CMD% submodule update --init --recursive --jobs 3 -if not %ERRORLEVEL%==0 ( - echo Error: Failed to update Git submodules 1>&2 - set _EXITCODE=1 - goto :eof -) -goto :eof - -:clear_out -set __OUT_DIR=%~1 - -if exist "%__OUT_DIR%" ( - if %_DEBUG%==1 echo [%_BASENAME%] del /s /q "%__OUT_DIR%\*" 1^>NUL - del /s /q "%__OUT_DIR%\*" 1>NUL -) -goto :eof - -:grep -set __PATTERN=%~1 -set __FILE=%~2 - -if %_DEBUG%==1 echo [%_BASENAME%] findstr "%__PATTERN%" "%__FILE% -findstr "%__PATTERN%" "%__FILE%" -if not %ERRORLEVEL%==0 ( - echo Error: Failed to find pattern "%__PATTERN%" in file %__FILE% 1>&2 - set _EXITCODE=1 - goto :eof -) -goto :eof - -rem ## see file project/scripts/cmdTests -:cmdTests -echo testing sbt dotc and dotr -if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotr -classpath %_OUT_DIR% %_MAIN%" ^> "%_TMP_FILE%" -call "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotr -classpath %_OUT_DIR% %_MAIN%" > "%_TMP_FILE%" -call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -rem # check that `sbt dotc` compiles and `sbt dotr` runs it -echo testing sbt dotc -from-tasty and dotr -classpath -call :clear_out "%_OUT_DIR%" -call "%_SBT_CMD%" ";dotc %_SOURCE% -d %_OUT_DIR% ;dotc -from-tasty -classpath %_OUT_DIR% -d %_OUT1_DIR% %_MAIN% ;dotr -classpath %_OUT1_DIR% %_MAIN%" > "%_TMP_FILE%" -call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -rem # check that `sbt dotc -decompile` runs -echo testing sbt dotc -decompile -call "%_SBT_CMD%" ";dotc -decompile -color:never -classpath %_OUT_DIR% %_MAIN%" > "%_TMP_FILE%" -call :grep "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -echo testing sbt dotr with no -classpath -call :clear_out "%_OUT_DIR%" -if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" ";dotc %_SOURCE% ; dotr %_MAIN%" ^> "%_TMP_FILE%" -call "%_SBT_CMD%" ";dotc %_SOURCE% ; dotr %_MAIN%" > "%_TMP_FILE%" -call :grep "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -echo testing loading tasty from .tasty file in jar -call :clear_out "%_OUT_DIR%" -call "%_SBT_CMD%" ";dotc -d %_OUT_DIR%\out.jar %_SOURCE%; dotc -decompile -classpath %_OUT_DIR%/out.jar -color:never %_MAIN%" > "%_TMP_FILE%" -call :grep "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -goto :eof - -:test -echo sbt compile and sbt test -if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";compile ;test" -call "%_SBT_CMD%" ";compile ;test" -if not %ERRORLEVEL%==0 ( - echo Error: Failed to build Dotty 1>&2 - set _EXITCODE=1 - goto :eof -) - -rem ## see shell script project/scripts/cmdTests -call :cmdTests -if not %_EXITCODE%==0 goto :eof - -goto :eof - -:test_pattern -set __PATTERN=%~1 -set __FILE=%~2 - -set /p __PATTERN2=<"%__FILE%" -if not "%__PATTERN2%"=="%__PATTERN%" ( - echo Error: failed to find pattern "%__PATTERN%" in file %__FILE% 1>&2 - set _EXITCODE=1 - goto :eof -) -goto :eof - -rem ## see shell script project/scripts/bootstrapCmdTests -:bootstrapCmdTests -rem # check that benchmarks can run -if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" -call "%_SBT_CMD%" "dotty-bench/jmh:run 1 1 tests/pos/alias.scala" - -rem # The above is here as it relies on the bootstrapped library. -call "%_SBT_CMD%" "dotty-bench-bootstrapped/jmh:run 1 1 tests/pos/alias.scala" -call "%_SBT_CMD%" "dotty-bench-bootstrapped/jmh:run 1 1 -with-compiler compiler/src/dotty/tools/dotc/core/Types.scala" - -echo testing scala.quoted.Expr.run from sbt dotr -call "%_SBT_CMD%" ";dotty-compiler-bootstrapped/dotc tests/run-with-compiler/quote-run.scala; dotty-compiler-bootstrapped/dotr -with-compiler Test" > "%_TMP_FILE%" -call :grep "val a: scala.Int = 3" "%_TMP_FILE%" -if not %_EXITCODE%==0 goto :eof - -rem # setup for `dotc`/`dotr` script tests -if %_DEBUG%==1 echo [%_BASENAME%] "%_SBT_CMD%" dist-bootstrapped/pack -call "%_SBT_CMD%" dist-bootstrapped/pack - -rem # check that `dotc` compiles and `dotr` runs it -echo testing ./bin/dotc and ./bin/dotr -call :clear_out "%_OUT_DIR%" -call %_BIN_DIR%\dotc.bat "%_SOURCE%" -d "%_OUT_DIR%" -call %_BIN_DIR%\dotr.bat -classpath "%_OUT_DIR%" "%_MAIN%" > "%_TMP_FILE%" -call :test_pattern "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" - -rem # check that `dotc -from-tasty` compiles and `dotr` runs it -echo testing ./bin/dotc -from-tasty and dotr -classpath -call :clear_out "%_OUT1_DIR%" -call %_BIN_DIR%\dotc.bat -from-tasty -classpath "%_OUT_DIR%" -d "%_OUT1_DIR%" "%_MAIN%" -call %_BIN_DIR%\dotr.bat -classpath "%_OUT1_DIR%" "%_MAIN%" > "%_TMP_FILE%" -call :test_pattern "%_EXPECTED_OUTPUT%" "%_TMP_FILE%" - -rem # echo ":quit" | ./dist-bootstrapped/target/pack/bin/dotr # not supported by CI - -echo testing ./bin/dotd -call :clear_out "%_OUT_DIR%" -call %_BIN_DIR%\dotd.bat -project Hello -siteroot "%_OUT_DIR%" "%_SOURCE%" - -goto :eof - -:test_bootstrapped -if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" -call "%_SBT_CMD%" ";dotty-bootstrapped/compile ;dotty-bootstrapped/test" -if not %ERRORLEVEL%==0 ( - echo Error: failed to bootstrap Dotty 1>&2 - set _EXITCODE=1 - goto :eof -) - -call :bootstrapCmdTests -if not %_EXITCODE%==0 goto :eof - -goto :eof - -:documentation -rem # make sure that _BOT_TOKEN is set -if not defined _BOT_TOKEN ( - echo Error: _BOT_TOKEN env unset, unable to push without password 1>&2 - set _EXITCODE=1 - goto :eof -) -for /f %%i in ('cd') do set _PWD=%%~si - -echo Working directory: %_PWD% - -call "%_SBT_CMD%" genDocs - -rem # make sure that the previous command actually succeeded -if not exist "%_PWD%\docs\_site\" ( - echo Error: output directory did not exist: %_PWD%\docs\_site 1>&2 - set _EXITCODE=1 - goto :eof -) - -goto :eof - -rem # save current head for commit message in gh-pages -rem for /f %%i in ('%_GIT_CMD% rev-parse HEAD 2^>NUL') do set _GIT_HEAD=%%i - -rem # set up remote and github credentials -rem %_GIT_CMD% remote add doc-remote "https://dotty-bot:%_BOT_TOKEN%@github.com/lampepfl/dotty-website.git" -rem %_GIT_CMD% config user.name "dotty-bot" -rem %_GIT_CMD% config user.email "dotty-bot@d-d.me" - -rem # check out correct branch -rem %_GIT_CMD% fetch doc-remote gh-pages -rem %_GIT_CMD% checkout gh-pages - -rem # move newly generated _site dir to $PWD -rem move %_PWD%\docs\_site . - -rem # remove everything BUT _site dir -rem del /f /q /s -rf !(_site) - -rem # copy new contents to $PWD -rem move _site\* . - -rem # remove now empty _site dir -rem del /f /q /s _site - -rem # add all contents of $PWD to commit -rem %_GIT_CMD% add -A -rem %_GIT_CMD% commit -m "Update gh-pages site for %_GIT_HEAD%" || echo "nothing new to commit" - -rem # push to doc-remote -rem %_GIT_CMD% push doc-remote || echo "couldn't push, since nothing was added" - -goto :eof - -:archives -if %_DEBUG%==1 echo [%_BASENAME%] call "%_SBT_CMD%" dist-bootstrapped/packArchive -call "%_SBT_CMD%" dist-bootstrapped/packArchive -rem output directory for gz/zip archives -set __TARGET_DIR=%_ROOT_DIR%\dist-bootstrapped\target -if not exist "%__TARGET_DIR%\" ( - echo Error: Directory target not found 1>&2 - set _EXITCODE=1 - goto :eof -) -if %_DEBUG%==1 ( - echo. - echo Output directory: %__TARGET_DIR%\ - dir /b /a-d "%__TARGET_DIR%" -) -goto :eof - -rem output parameter: _DURATION -:duration -set __START=%~1 -set __END=%~2 - -for /f "delims=" %%i in ('powershell -c "$interval = New-TimeSpan -Start '%__START%' -End '%__END%'; Write-Host $interval"') do set _DURATION=%%i -goto :eof - -rem input parameter: 1=start time -:total -set __TIMER_START=%~1 - -for /f "delims=" %%i in ('powershell -c "(Get-Date)"') do set __TIMER_END=%%i -call :duration "%_TIMER_START%" "!__TIMER_END!" -echo Total execution time: %_DURATION% -goto :eof - -rem ########################################################################## -rem ## Cleanups - -:end -if %_TIMER%==1 call :total "%_TIMER_START%" -if %_DEBUG%==1 echo [%_BASENAME%] _EXITCODE=%_EXITCODE% -exit /b %_EXITCODE% From 8232db169ce5b440fcb389f5b7ce783874d2aee3 Mon Sep 17 00:00:00 2001 From: Dotty CI Date: Wed, 21 Nov 2018 17:31:11 +0100 Subject: [PATCH 19/22] reverted removal of Debug.scala --- .../dotty/tools/dotc/fromtasty/Debug.scala | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 compiler/src/dotty/tools/dotc/fromtasty/Debug.scala diff --git a/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala b/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala new file mode 100644 index 000000000000..3b88408f3c82 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala @@ -0,0 +1,72 @@ +package dotty.tools +package dotc +package fromtasty + +import scala.util.control.NonFatal + +import dotty.tools.io.Directory + +import java.io{File => JFile} +import java.nio.file.{Files, Paths} + +object Debug { + def main(args: Array[String]): Unit = { + // Preload scala.util.control.NonFatal. Otherwise, when trying to catch a StackOverflowError, + // we may try to load it but fail with another StackOverflowError and lose the original exception, + // see . + val _ = NonFatal + + assert(!args.contains("-d")) + + val outPath = Paths.get("out") + Directory(outPath).createDirectory() + + val tmpOut = Files.createTempDirectory(outPath.toAbsolutePath, "from-tasty-tmp") + + val fromSourcesOut = Files.createDirectory(tmpOut.resolve("from-source")) + + println("Compiling from .scala sources") + val compilation1 = dotc.Main.process("-d" +: fromSourcesOut.toString +: args) + + if (compilation1.hasErrors) { + println("Failed compilation from sources") + Directory(tmpOut).deleteRecursively() + sys.exit(1) + } + + val fromTastyOut = Files.createDirectory(tmpOut.resolve("from-tasty")) + + val extensions = List("tasty", "hasTasty").map(_.toLowerCase) + val classes = Directory(fromSourcesOut).walk.filter(x => x.isFile && extensions.exists(_ == x.extension.toLowerCase)).map { x => + val source = x.toString + // transform foo/bar/Baz.hasTasty into foo.bar.Baz + source.substring(fromSourcesOut.toString.length + 1, source.length - x.extension.length - 1).replace('/', '.') + }.toList + + val fromTastyArgs = { + "-from-tasty" :: + "-d" :: fromTastyOut.toString :: + insertClasspathInArgs(args.filterNot(_.endsWith(".scala")).toList, fromSourcesOut.toString) ::: + classes + } + + println("Compiling TASTY from .class sources") + val compilation2 = dotc.Main.process(fromTastyArgs.toArray) + + if (compilation2.hasErrors) { + println("Failed compilation from TASTY") + println("Compilation input: " + fromSourcesOut) + // In this case we do not delete the generated class files to allow further debugging. + // For example `dotc -decompile` on one of the intermediate class files. + sys.exit(1) + } + + Directory(tmpOut).deleteRecursively() + } + + private def insertClasspathInArgs(args: List[String], cp: String): List[String] = { + val (beforeCp, fromCp) = args.span(_ != "-classpath") + val classpath = fromCp.drop(1).headOption.fold(cp)(_ + JFile.pathSeparator + cp) + "-classpath" :: classpath :: beforeCp ::: fromCp.drop(2) + } +} From b2c95db22bbe5deb341702e3fa97269bc11ed056 Mon Sep 17 00:00:00 2001 From: Dotty CI Date: Wed, 21 Nov 2018 18:19:20 +0100 Subject: [PATCH 20/22] attempt to resolve conficting files --- .../decompiler/DecompilationPrinter.scala | 47 + .../dotty/tools/dotc/fromtasty/Debug.scala | 2 +- .../dotc/reporting/MessageRendering.scala | 164 ++ .../src/dotty/tools/repl/ReplDriver.scala | 370 +++++ .../dotty/tools/repl/ReplCompilerTests.scala | 127 ++ .../test/dotty/tools/repl/ScriptedTests.scala | 89 ++ .../dotty/tools/vulpix/ParallelTesting.scala | 1410 +++++++++++++++++ 7 files changed, 2208 insertions(+), 1 deletion(-) create mode 100644 compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala create mode 100644 compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala create mode 100644 compiler/src/dotty/tools/repl/ReplDriver.scala create mode 100644 compiler/test/dotty/tools/repl/ReplCompilerTests.scala create mode 100644 compiler/test/dotty/tools/repl/ScriptedTests.scala create mode 100644 compiler/test/dotty/tools/vulpix/ParallelTesting.scala diff --git a/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala b/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala new file mode 100644 index 000000000000..afa06ff9a115 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala @@ -0,0 +1,47 @@ +package dotty.tools.dotc +package decompiler + +import java.io.{OutputStream, PrintStream} + +import dotty.tools.dotc.core.Contexts._ +import dotty.tools.dotc.core.Phases.Phase +import dotty.tools.dotc.core.tasty.TastyPrinter +import dotty.tools.dotc.tastyreflect.ReflectionImpl +import dotty.tools.io.File + +/** Phase that prints the trees in all loaded compilation units. + * + * @author Nicolas Stucki + */ +class DecompilationPrinter extends Phase { + + override def phaseName: String = "decompilationPrinter" + + override def run(implicit ctx: Context): Unit = { + if (ctx.settings.outputDir.isDefault) printToOutput(System.out) + else { + val outputDir = ctx.settings.outputDir.value + var os: OutputStream = null + var ps: PrintStream = null + try { + os = File(outputDir.fileNamed("decompiled.scala").path).outputStream(append = true) + ps = new PrintStream(os) + printToOutput(ps) + } finally { + if (os ne null) os.close() + if (ps ne null) ps.close() + } + } + } + + private def printToOutput(out: PrintStream)(implicit ctx: Context): Unit = { + val unit = ctx.compilationUnit + if (ctx.settings.printTasty.value) { + new TastyPrinter(unit.pickled.head._2).printContents() + } else { + val unitFile = unit.source.toString.replace("\\", "/").replace(".class", ".tasty") + out.println(s"/** Decompiled from $unitFile */") + out.println(new ReflectionImpl(ctx).showSourceCode.showTree(unit.tpdTree)(ctx)) + } + } +} diff --git a/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala b/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala index 3b88408f3c82..f2d9adca1e50 100644 --- a/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala +++ b/compiler/src/dotty/tools/dotc/fromtasty/Debug.scala @@ -6,7 +6,7 @@ import scala.util.control.NonFatal import dotty.tools.io.Directory -import java.io{File => JFile} +import java.io.{File => JFile} import java.nio.file.{Files, Paths} object Debug { diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala new file mode 100644 index 000000000000..426b1f269c78 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala @@ -0,0 +1,164 @@ +package dotty.tools +package dotc +package reporting + +import core.Contexts.Context +import core.Decorators._ +import printing.Highlighting.{Blue, Red} +import printing.SyntaxHighlighting +import diagnostic.{ErrorMessageID, Message, MessageContainer} +import diagnostic.messages._ +import util.SourcePosition +import scala.tasty.util.Chars.{ LF, CR, FF, SU } +import scala.annotation.switch + +import scala.collection.mutable + +trait MessageRendering { + /** Remove ANSI coloring from `str`, useful for getting real length of + * strings + * + * @return string stripped of ANSI escape codes + */ + def stripColor(str: String): String = + str.replaceAll("\u001b\\[.*?m", "") + + /** When inlining a method call, if there's an error we'd like to get the + * outer context and the `pos` at which the call was inlined. + * + * @return a list of strings with inline locations + */ + def outer(pos: SourcePosition, prefix: String)(implicit ctx: Context): List[String] = + if (pos.outer.exists) { + s"$prefix| This location is in code that was inlined at ${pos.outer}" :: + outer(pos.outer, prefix) + } else Nil + + /** Get the sourcelines before and after the position, as well as the offset + * for rendering line numbers + * + * @return (lines before error, lines after error, line numbers offset) + */ + def sourceLines(pos: SourcePosition)(implicit ctx: Context): (List[String], List[String], Int) = { + var maxLen = Int.MinValue + def render(offsetAndLine: (Int, String)): String = { + val (offset, line) = offsetAndLine + val lineNbr = pos.source.offsetToLine(offset) + val prefix = s"${lineNbr + 1} |" + maxLen = math.max(maxLen, prefix.length) + val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix).show + lnum + line.stripLineEnd + } + + def linesFrom(arr: Array[Char]): List[String] = { + def pred(c: Char) = (c: @switch) match { + case LF | CR | FF | SU => true + case _ => false + } + val (line, rest0) = arr.span(!pred(_)) + val (_, rest) = rest0.span(pred) + new String(line) :: { if (rest.isEmpty) Nil else linesFrom(rest) } + } + + val syntax = + if (ctx.settings.color.value != "never") + SyntaxHighlighting.highlight(new String(pos.linesSlice)).toCharArray + else pos.linesSlice + val lines = linesFrom(syntax) + val (before, after) = pos.beforeAndAfterPoint + + ( + before.zip(lines).map(render), + after.zip(lines.drop(before.length)).map(render), + maxLen + ) + } + + /** The column markers aligned under the error */ + def columnMarker(pos: SourcePosition, offset: Int)(implicit ctx: Context): String = { + val prefix = " " * (offset - 1) + val padding = pos.startColumnPadding + val carets = Red { + if (pos.startLine == pos.endLine) + "^" * math.max(1, pos.endColumn - pos.startColumn) + else "^" + } + s"$prefix|$padding${carets.show}" + } + + /** The error message (`msg`) aligned under `pos` + * + * @return aligned error message + */ + def errorMsg(pos: SourcePosition, msg: String, offset: Int)(implicit ctx: Context): String = { + val padding = msg.linesIterator.foldLeft(pos.startColumnPadding) { (pad, line) => + val lineLength = stripColor(line).length + val maxPad = math.max(0, ctx.settings.pageWidth.value - offset - lineLength) - offset + + if (maxPad < pad.length) " " * maxPad + else pad + } + + msg.linesIterator + .map { line => " " * (offset - 1) + "|" + padding + line} + .mkString(sys.props("line.separator")) + } + + /** The separator between errors containing the source file and error type + * + * @return separator containing error location and kind + */ + def posStr(pos: SourcePosition, diagnosticLevel: String, message: Message)(implicit ctx: Context): String = + if (pos.exists) Blue({ + val file = s"${pos.source.file.toString}:${pos.line + 1}:${pos.column}" + val errId = + if (message.errorId ne ErrorMessageID.NoExplanationID) { + val errorNumber = message.errorId.errorNumber() + s"[E${"0" * (3 - errorNumber.toString.length) + errorNumber}] " + } else "" + val kind = + if (message.kind == "") diagnosticLevel + else s"${message.kind} $diagnosticLevel" + val prefix = s"-- ${errId}${kind}: $file " + + prefix + + ("-" * math.max(ctx.settings.pageWidth.value - stripColor(prefix).length, 0)) + }).show else "" + + /** Explanation rendered under "Explanation" header */ + def explanation(m: Message)(implicit ctx: Context): String = { + val sb = new StringBuilder( + hl"""| + |${Blue("Explanation")} + |${Blue("===========")}""" + ) + sb.append('\n').append(m.explanation) + if (m.explanation.lastOption != Some('\n')) sb.append('\n') + sb.toString + } + + /** The whole message rendered from `msg` */ + def messageAndPos(msg: Message, pos: SourcePosition, diagnosticLevel: String)(implicit ctx: Context): String = { + val sb = mutable.StringBuilder.newBuilder + val posString = posStr(pos, diagnosticLevel, msg) + if (posString.nonEmpty) sb.append(posString).append('\n') + if (pos.exists) { + val (srcBefore, srcAfter, offset) = sourceLines(pos) + val marker = columnMarker(pos, offset) + val err = errorMsg(pos, msg.msg, offset) + sb.append((srcBefore ::: marker :: err :: outer(pos, " " * (offset - 1)) ::: srcAfter).mkString("\n")) + } else sb.append(msg.msg) + sb.toString + } + + def diagnosticLevel(cont: MessageContainer): String = + cont match { + case m: Error => "Error" + case m: FeatureWarning => "Feature Warning" + case m: DeprecationWarning => "Deprecation Warning" + case m: UncheckedWarning => "Unchecked Warning" + case m: MigrationWarning => "Migration Warning" + case m: Warning => "Warning" + case m: Info => "Info" + } +} diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala new file mode 100644 index 000000000000..98ad8636e274 --- /dev/null +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -0,0 +1,370 @@ +package dotty.tools.repl + +import java.io.PrintStream + +import dotty.tools.dotc.ast.Trees._ +import dotty.tools.dotc.ast.{tpd, untpd} +import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Denotations.Denotation +import dotty.tools.dotc.core.Flags._ +import dotty.tools.dotc.core.Mode +import dotty.tools.dotc.core.NameKinds.SimpleNameKind +import dotty.tools.dotc.core.NameOps._ +import dotty.tools.dotc.core.Names.Name +import dotty.tools.dotc.core.StdNames._ +import dotty.tools.dotc.core.Symbols.{Symbol, defn} +import dotty.tools.dotc.interactive.Interactive +import dotty.tools.dotc.printing.SyntaxHighlighting +import dotty.tools.dotc.reporting.MessageRendering +import dotty.tools.dotc.reporting.diagnostic.{Message, MessageContainer} +import dotty.tools.dotc.util.Positions.Position +import dotty.tools.dotc.util.{SourceFile, SourcePosition} +import dotty.tools.dotc.{CompilationUnit, Driver} +import dotty.tools.io._ +import org.jline.reader._ + +import scala.annotation.tailrec +import scala.collection.JavaConverters._ + +/** The state of the REPL contains necessary bindings instead of having to have + * mutation + * + * The compiler in the REPL needs to do some wrapping in order to compile + * valid code. This wrapping occurs when a single `MemberDef` that cannot be + * top-level needs to be compiled. In order to do this, we need some unique + * identifier for each of these wrappers. That identifier is `objectIndex`. + * + * Free expressions such as `1 + 1` needs to have an assignment in order to be + * of use. These expressions are therefore given a identifier on the format + * `resX` where `X` starts at 0 and each new expression that needs an + * identifier is given the increment of the old identifier. This identifier is + * `valIndex`. + * + * @param objectIndex the index of the next wrapper + * @param valIndex the index of next value binding for free expressions + * @param imports a map from object index to the list of user defined imports + * @param context the latest compiler context + */ +case class State(objectIndex: Int, + valIndex: Int, + imports: Map[Int, List[tpd.Import]], + context: Context) + +/** Main REPL instance, orchestrating input, compilation and presentation */ +class ReplDriver(settings: Array[String], + out: PrintStream = Console.out, + classLoader: Option[ClassLoader] = None) extends Driver { + + /** Overridden to `false` in order to not have to give sources on the + * commandline + */ + override def sourcesRequired: Boolean = false + + /** Create a fresh and initialized context with IDE mode enabled */ + private[this] def initialCtx = { + val rootCtx = initCtx.fresh.addMode(Mode.ReadPositions | Mode.Interactive | Mode.ReadComments) + rootCtx.setSetting(rootCtx.settings.YcookComments, true) + val ictx = setup(settings, rootCtx)._2 + ictx.base.initialize()(ictx) + ictx + } + + /** the initial, empty state of the REPL session */ + final def initialState: State = State(0, 0, Map.empty, rootCtx) + + /** Reset state of repl to the initial state + * + * This method is responsible for performing an all encompassing reset. As + * such, when the user enters `:reset` this method should be called to reset + * everything properly + */ + protected[this] def resetToInitial(): Unit = { + rootCtx = initialCtx + if (rootCtx.settings.outputDir.isDefault(rootCtx)) + rootCtx = rootCtx.fresh + .setSetting(rootCtx.settings.outputDir, new VirtualDirectory("")) + compiler = new ReplCompiler + rendering = new Rendering(classLoader) + } + + private[this] var rootCtx: Context = _ + private[this] var compiler: ReplCompiler = _ + private[this] var rendering: Rendering = _ + + // initialize the REPL session as part of the constructor so that once `run` + // is called, we're in business + resetToInitial() + + /** Run REPL with `state` until `:quit` command found + * + * This method is the main entry point into the REPL. Its effects are not + * observable outside of the CLI, for this reason, most helper methods are + * `protected final` to facilitate testing. + */ + final def runUntilQuit(initialState: State = initialState): State = { + val terminal = new JLineTerminal + + /** Blockingly read a line, getting back a parse result */ + def readLine(state: State): ParseResult = { + val completer: Completer = { (_, line, candidates) => + val comps = completions(line.cursor, line.line, state) + candidates.addAll(comps.asJava) + } + implicit val ctx = state.context + try { + val line = terminal.readLine(completer) + ParseResult(line) + } catch { + case _: EndOfFileException | + _: UserInterruptException => // Ctrl+D or Ctrl+C + Quit + } + } + + @tailrec def loop(state: State): State = { + val res = readLine(state) + if (res == Quit) state + else loop(interpret(res)(state)) + } + + try withRedirectedOutput { loop(initialState) } + finally terminal.close() + } + + final def run(input: String)(implicit state: State): State = withRedirectedOutput { + val parsed = ParseResult(input)(state.context) + interpret(parsed) + } + + // TODO: i5069 + final def bind(name: String, value: Any)(implicit state: State): State = state + + private def withRedirectedOutput(op: => State): State = + Console.withOut(out) { Console.withErr(out) { op } } + + private def newRun(state: State) = { + val run = compiler.newRun(rootCtx.fresh.setReporter(newStoreReporter), state) + state.copy(context = run.runContext) + } + + /** Extract possible completions at the index of `cursor` in `expr` */ + protected[this] final def completions(cursor: Int, expr: String, state0: State): List[Candidate] = { + def makeCandidate(completion: Symbol)(implicit ctx: Context) = { + val displ = completion.name.toString + new Candidate( + /* value = */ displ, + /* displ = */ displ, // displayed value + /* group = */ null, // can be used to group completions together + /* descr = */ null, // TODO use for documentation? + /* suffix = */ null, + /* key = */ null, + /* complete = */ false // if true adds space when completing + ) + } + implicit val state = newRun(state0) + compiler + .typeCheck(expr, errorsAllowed = true) + .map { tree => + val file = new SourceFile("", expr) + val unit = new CompilationUnit(file) + unit.tpdTree = tree + implicit val ctx = state.context.fresh.setCompilationUnit(unit) + val srcPos = SourcePosition(file, Position(cursor)) + val (_, completions) = Interactive.completions(srcPos) + completions.map(makeCandidate) + } + .getOrElse(Nil) + } + + private def interpret(res: ParseResult)(implicit state: State): State = { + val newState = res match { + case parsed: Parsed if parsed.trees.nonEmpty => + compile(parsed, state) + + case SyntaxErrors(_, errs, _) => + displayErrors(errs) + state + + case cmd: Command => + interpretCommand(cmd) + + case SigKill => // TODO + state + + case _ => // new line, empty tree + state + } + out.println() + newState + } + + /** Compile `parsed` trees and evolve `state` in accordance */ + private def compile(parsed: Parsed, istate: State): State = { + def extractNewestWrapper(tree: untpd.Tree): Name = tree match { + case PackageDef(_, (obj: untpd.ModuleDef) :: Nil) => obj.name.moduleClassName + case _ => nme.NO_NAME + } + + def extractTopLevelImports(ctx: Context): List[tpd.Import] = + ctx.phases.collectFirst { case phase: CollectTopLevelImports => phase.imports }.get + + implicit val state = newRun(istate) + compiler + .compile(parsed) + .fold( + displayErrors, + { + case (unit: CompilationUnit, newState: State) => + val newestWrapper = extractNewestWrapper(unit.untpdTree) + val newImports = extractTopLevelImports(newState.context) + var allImports = newState.imports + if (newImports.nonEmpty) + allImports += (newState.objectIndex -> newImports) + val newStateWithImports = newState.copy(imports = allImports) + + val warnings = newState.context.reporter.removeBufferedMessages(newState.context) + displayErrors(warnings)(newState) // display warnings + displayDefinitions(unit.tpdTree, newestWrapper)(newStateWithImports) + } + ) + } + + /** Display definitions from `tree` */ + private def displayDefinitions(tree: tpd.Tree, newestWrapper: Name)(implicit state: State): State = { + implicit val ctx = state.context + + def resAndUnit(denot: Denotation) = { + import scala.util.{Success, Try} + val sym = denot.symbol + val name = sym.name.show + val hasValidNumber = Try(name.drop(3).toInt) match { + case Success(num) => num < state.valIndex + case _ => false + } + name.startsWith(str.REPL_RES_PREFIX) && hasValidNumber && sym.info == defn.UnitType + } + + def displayMembers(symbol: Symbol) = if (tree.symbol.info.exists) { + val info = symbol.info + val defs = + info.bounds.hi.finalResultType + .membersBasedOnFlags(Method, Accessor | ParamAccessor | Synthetic | Private) + .filterNot { denot => + denot.symbol.owner == defn.AnyClass || + denot.symbol.owner == defn.ObjectClass || + denot.symbol.isConstructor + } + + val vals = + info.fields + .filterNot(_.symbol.is(ParamAccessor | Private | Synthetic | Module)) + .filter(_.symbol.name.is(SimpleNameKind)) + + val typeAliases = + info.bounds.hi.typeMembers.filter(_.symbol.info.isTypeAlias) + + ( + typeAliases.map("// defined alias " + _.symbol.showUser) ++ + defs.map(rendering.renderMethod) ++ + vals.map(rendering.renderVal).flatten + ).foreach(str => out.println(SyntaxHighlighting.highlight(str))) + + state.copy(valIndex = state.valIndex - vals.count(resAndUnit)) + } + else state + + def isSyntheticCompanion(sym: Symbol) = + sym.is(Module) && sym.is(Synthetic) + + def displayTypeDefs(sym: Symbol) = sym.info.memberClasses + .collect { + case x if !isSyntheticCompanion(x.symbol) && !x.symbol.name.isReplWrapperName => + x.symbol + } + .foreach { sym => + out.println(SyntaxHighlighting.highlight("// defined " + sym.showUser)) + } + + + ctx.atPhase(ctx.typerPhase.next) { implicit ctx => + + // Display members of wrapped module: + tree.symbol.info.memberClasses + .find(_.symbol.name == newestWrapper.moduleClassName) + .map { wrapperModule => + displayTypeDefs(wrapperModule.symbol) + displayMembers(wrapperModule.symbol) + } + .getOrElse { + // user defined a trait/class/object, so no module needed + state + } + } + } + + /** Interpret `cmd` to action and propagate potentially new `state` */ + private def interpretCommand(cmd: Command)(implicit state: State): State = cmd match { + case UnknownCommand(cmd) => + out.println(s"""Unknown command: "$cmd", run ":help" for a list of commands""") + state + + case Help => + out.println(Help.text) + state + + case Reset => + resetToInitial() + initialState + + case Imports => + for { + objectIndex <- 1 to state.objectIndex + imp <- state.imports.getOrElse(objectIndex, Nil) + } out.println(imp.show(state.context)) + state + + case Load(path) => + val file = new java.io.File(path) + if (file.exists) { + val contents = scala.io.Source.fromFile(file).mkString + run(contents) + } + else { + out.println(s"""Couldn't find file "${file.getCanonicalPath}"""") + state + } + + case TypeOf(expr) => + compiler.typeOf(expr)(newRun(state)).fold( + displayErrors, + res => out.println(SyntaxHighlighting.highlight(res)(state.context)) + ) + state + + case DocOf(expr) => + compiler.docOf(expr)(newRun(state)).fold( + displayErrors, + res => out.println(res) + ) + state + + case Quit => + // end of the world! + state + } + + /** A `MessageRenderer` without file positions */ + private val messageRenderer = new MessageRendering { + override def posStr(pos: SourcePosition, diagnosticLevel: String, message: Message)(implicit ctx: Context): String = "" + } + + /** Render messages using the `MessageRendering` trait */ + private def renderMessage(cont: MessageContainer): Context => String = + messageRenderer.messageAndPos(cont.contained(), cont.pos, messageRenderer.diagnosticLevel(cont))(_) + + /** Output errors to `out` */ + private def displayErrors(errs: Seq[MessageContainer])(implicit state: State): State = { + errs.map(renderMessage(_)(state.context)).foreach(out.println) + state + } +} diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala new file mode 100644 index 000000000000..efe6876c269b --- /dev/null +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -0,0 +1,127 @@ +package dotty.tools.repl + +import org.junit.Assert._ +import org.junit.{Ignore, Test} + +class ReplCompilerTests extends ReplTest { + + @Test def compileSingle = fromInitialState { implicit state => + run("def foo: 1 = 1") + assertEquals("def foo: Int(1)", storedOutput().trim) + } + + @Test def compileTwo = + fromInitialState { implicit state => + run("def foo: 1 = 1") + } + .andThen { implicit state => + val s2 = run("def foo(i: Int): i.type = i") + assertEquals(2, s2.objectIndex) + } + + @Test def inspectWrapper = + fromInitialState { implicit state => + run("def foo = 1") + + }.andThen { implicit state => + storedOutput() // discard output + run("val x = rs$line$1.foo") + assertEquals("val x: Int = 1", storedOutput().trim) + } + + @Test def testVar = fromInitialState { implicit state => + run("var x = 5") + assertEquals("var x: Int = 5", storedOutput().trim) + } + + @Test def testRes = fromInitialState { implicit state => + run { + """|def foo = 1 + 1 + |val x = 5 + 5 + |1 + 1 + |var y = 5 + |10 + 10""".stripMargin + } + + val expected = List( + "def foo: Int", + "val x: Int = 10", + "val res0: Int = 2", + "var y: Int = 5", + "val res1: Int = 20" + ) + + assertEquals(expected, storedOutput().split("\n").toList) + } + + @Test def testImportMutable = + fromInitialState { implicit state => + run("import scala.collection.mutable") + } + .andThen { implicit state => + assertEquals(1, state.imports.size) + run("""mutable.Map("one" -> 1)""") + assertEquals( + "val res0: scala.collection.mutable.Map[String, Int] = Map(one -> 1)", + storedOutput().trim + ) + } + + @Test def rebindVariable = + fromInitialState { implicit s => + val state = run("var x = 5") + assertEquals("var x: Int = 5", storedOutput().trim) + state + } + .andThen { implicit s => + run("x = 10") + assertEquals("x: Int = 10", storedOutput().trim) + } + + // FIXME: Tests are not run in isolation, the classloader is corrupted after the first exception + @Ignore @Test def i3305: Unit = { + fromInitialState { implicit s => + run("null.toString") + assertTrue(storedOutput().startsWith("java.lang.NullPointerException")) + } + + fromInitialState { implicit s => + run("def foo: Int = 1 + foo; foo") + assertTrue(storedOutput().startsWith("def foo: Int\njava.lang.StackOverflowError")) + } + + fromInitialState { implicit s => + run("""throw new IllegalArgumentException("Hello")""") + assertTrue(storedOutput().startsWith("java.lang.IllegalArgumentException: Hello")) + } + + fromInitialState { implicit s => + run("val (x, y) = null") + assertTrue(storedOutput().startsWith("scala.MatchError: null")) + } + } + + @Test def i2789: Unit = fromInitialState { implicit state => + run("(x: Int) => println(x)") + assertTrue(storedOutput().startsWith("val res0: Int => Unit =")) + } + + @Test def byNameParam: Unit = fromInitialState { implicit state => + run("def f(g: => Int): Int = g") + assertTrue(storedOutput().startsWith("def f(g: => Int): Int")) + } + + @Test def i4051 = fromInitialState { implicit state => + val source = + """val x: PartialFunction[Int, Int] = { case x => x } + |val y = Map(("A", 1), ("B", 2), ("X", 3)).collect { case (k, v) => v }.toList""".stripMargin + + val expected = List( + "val x: PartialFunction[Int, Int] = ", + "val y: List[Int] = List(1, 2, 3)" + ) + + run(source) + assertEquals(expected, storedOutput().split("\n").toList) + } +} diff --git a/compiler/test/dotty/tools/repl/ScriptedTests.scala b/compiler/test/dotty/tools/repl/ScriptedTests.scala new file mode 100644 index 000000000000..090d49949d08 --- /dev/null +++ b/compiler/test/dotty/tools/repl/ScriptedTests.scala @@ -0,0 +1,89 @@ +package dotty.tools +package repl + +import java.io.{ File => JFile } + +import org.junit.Assert._ +import org.junit.Test + +import scala.collection.mutable.ArrayBuffer +import scala.io.Source + +import dotc.reporting.MessageRendering + +/** Runs all tests contained in `compiler/test-resources/repl/` */ +class ScriptedTests extends ReplTest with MessageRendering { + + private def scripts(path: String): Array[JFile] = { + val dir = new JFile(getClass.getResource(path).getPath) + assert(dir.exists && dir.isDirectory, "Couldn't load scripts dir") + dir.listFiles + } + + private def testFile(f: JFile): Unit = { + val prompt = "scala>" + val lines = Source.fromFile(f).getLines().buffered + + assert(lines.head.startsWith(prompt), + s"""Each file has to start with the prompt: "$prompt"""") + + def extractInputs(prompt: String): List[String] = { + val input = lines.next() + + if (!input.startsWith(prompt)) extractInputs(prompt) + else if (lines.hasNext) { + // read lines and strip trailing whitespace: + while (lines.hasNext && !lines.head.startsWith(prompt)) + lines.next() + + input :: { if (lines.hasNext) extractInputs(prompt) else Nil } + } + else Nil + } + + def evaluate(state: State, input: String, prompt: String) = + try { + val nstate = run(input.drop(prompt.length))(state) + val out = input + "\n" + storedOutput() + (out, nstate) + } + catch { + case ex: Throwable => + System.err.println(s"failed while running script: $f, on:\n$input") + throw ex + } + + def filterEmpties(line: String): List[String] = + line.replaceAll("""(?m)\s+$""", "") match { + case "" => Nil + case nonEmptyLine => nonEmptyLine :: Nil + } + + val expectedOutput = + Source.fromFile(f).getLines().flatMap(filterEmpties).mkString("\n") + val actualOutput = { + resetToInitial() + val inputRes = extractInputs(prompt) + val buf = new ArrayBuffer[String] + inputRes.foldLeft(initialState) { (state, input) => + val (out, nstate) = evaluate(state, input, prompt) + buf.append(out) + nstate + } + buf.flatMap(filterEmpties).mkString("\n") + } + + if (expectedOutput != actualOutput) { + println("expected =========>") + println(expectedOutput) + println("actual ===========>") + println(actualOutput) + + fail(s"Error in file $f, expected output did not match actual") + } + } + + @Test def replTests = scripts("/repl").foreach(testFile) + + @Test def typePrinterTests = scripts("/type-printer").foreach(testFile) +} diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala new file mode 100644 index 000000000000..619a877d757a --- /dev/null +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -0,0 +1,1410 @@ +package dotty +package tools +package vulpix + +import java.io.{File => JFile} +import java.text.SimpleDateFormat +import java.util.HashMap +import java.nio.file.StandardCopyOption.REPLACE_EXISTING +import java.nio.file.{Files, NoSuchFileException, Path, Paths} +import java.util.concurrent.{TimeUnit, TimeoutException, Executors => JExecutors} +import java.util.{Timer, TimerTask} + +import scala.io.Source +import scala.util.control.NonFatal +import scala.util.Try +import scala.collection.mutable +import scala.util.matching.Regex +import scala.util.Random +import dotc.core.Contexts._ +import dotc.reporting.{Reporter, TestReporter} +import dotc.reporting.diagnostic.MessageContainer +import dotc.interfaces.Diagnostic.ERROR +import dotc.util.DiffUtil +import dotc.{Compiler, Driver} +import dotc.decompiler +import dotty.tools.vulpix.TestConfiguration.defaultOptions + +/** A parallel testing suite whose goal is to integrate nicely with JUnit + * + * This trait can be mixed in to offer parallel testing to compile runs. When + * using this, you should be running your JUnit tests **sequentially**, as the + * test suite itself runs with a high level of concurrency. + */ +trait ParallelTesting extends RunnerOrchestration { self => + + import ParallelTesting._ + + /** If the running environment supports an interactive terminal, each `Test` + * will be run with a progress bar and real time feedback + */ + def isInteractive: Boolean + + /** A string which is used to filter which tests to run, if `None` will run + * all tests. All absolute paths that contain the substring `testFilter` + * will be run + */ + def testFilter: Option[String] + + /** A test source whose files or directory of files is to be compiled + * in a specific way defined by the `Test` + */ + sealed trait TestSource { self => + def name: String + def outDir: JFile + def flags: TestFlags + + def runClassPath: String = outDir.getAbsolutePath + JFile.pathSeparator + flags.runClassPath + + def title: String = self match { + case self: JointCompilationSource => + if (self.files.length > 1) name + else self.files.head.getPath + + case self: SeparateCompilationSource => + self.dir.getPath + } + + /** Adds the flags specified in `newFlags0` if they do not already exist */ + def withFlags(newFlags0: String*) = { + val newFlags = newFlags0.toArray + if (!flags.options.containsSlice(newFlags)) self match { + case self: JointCompilationSource => + self.copy(flags = flags.and(newFlags:_*)) + case self: SeparateCompilationSource => + self.copy(flags = flags.and(newFlags:_*)) + } + else self + } + + /** Generate the instructions to redo the test from the command line */ + def buildInstructions(errors: Int, warnings: Int): String = { + val sb = new StringBuilder + val maxLen = 80 + var lineLen = 0 + + sb.append( + s"""| + |Test '$title' compiled with $errors error(s) and $warnings warning(s), + |the test can be reproduced by running:""".stripMargin + ) + sb.append("\n\n./bin/dotc ") + flags.all.foreach { arg => + if (lineLen > maxLen) { + sb.append(" \\\n ") + lineLen = 4 + } + sb.append(arg) + lineLen += arg.length + sb += ' ' + } + + self match { + case source: JointCompilationSource => { + source.sourceFiles.map(_.getAbsolutePath).foreach { path => + sb.append("\\\n ") + sb.append(path) + sb += ' ' + } + sb.toString + "\n\n" + } + case self: SeparateCompilationSource => { + val command = sb.toString + val fsb = new StringBuilder(command) + self.compilationGroups.foreach { files => + files.map(_.getPath).foreach { path => + fsb.append("\\\n ") + lineLen = 8 + fsb.append(path) + fsb += ' ' + } + fsb.append("\n\n") + fsb.append(command) + } + fsb.toString + "\n\n" + } + } + } + } + + /** A group of files that may all be compiled together, with the same flags + * and output directory + */ + private case class JointCompilationSource( + name: String, + files: Array[JFile], + flags: TestFlags, + outDir: JFile, + fromTasty: Boolean = false, + decompilation: Boolean = false + ) extends TestSource { + def sourceFiles: Array[JFile] = files.filter(isSourceFile) + + override def toString() = outDir.toString + } + + /** A test source whose files will be compiled separately according to their + * suffix `_X` + */ + case class SeparateCompilationSource( + name: String, + dir: JFile, + flags: TestFlags, + outDir: JFile + ) extends TestSource { + + /** Get the files grouped by `_X` as a list of groups, files missing this + * suffix will be put into the same group. + * Files in each group are sorted alphabetically. + * + * Filters out all none source files + */ + def compilationGroups: List[Array[JFile]] = + dir + .listFiles + .groupBy { file => + val name = file.getName + Try { + val potentialNumber = name + .substring(0, name.lastIndexOf('.')) + .reverse.takeWhile(_ != '_').reverse + + potentialNumber.toInt.toString + } + .toOption + .getOrElse("") + } + .toList.sortBy(_._1).map(_._2.filter(isSourceFile).sorted) + } + + /** Each `Test` takes the `testSources` and performs the compilation and assertions + * according to the implementing class "neg", "run" or "pos". + */ + private abstract class Test(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit val summaryReport: SummaryReporting) { test => + + import summaryReport._ + + protected final val realStdout = System.out + protected final val realStderr = System.err + + /** A runnable that logs its contents in a buffer */ + trait LoggedRunnable extends Runnable { + /** Instances of `LoggedRunnable` implement this method instead of the + * `run` method + */ + def checkTestSource(): Unit + + private[this] val logBuffer = mutable.ArrayBuffer.empty[String] + def log(msg: String): Unit = logBuffer.append(msg) + + def logReporterContents(reporter: TestReporter): Unit = + reporter.messages.foreach(log) + + def echo(msg: String): Unit = { + log(msg) + test.echo(msg) + } + + final def run(): Unit = { + checkTestSource() + summaryReport.echoToLog(logBuffer.iterator) + } + } + + /** Actual compilation run logic, the test behaviour is defined here */ + protected def encapsulatedCompilation(testSource: TestSource): LoggedRunnable + + /** All testSources left after filtering out */ + private val filteredSources = + if (!testFilter.isDefined) testSources + else testSources.filter { + case JointCompilationSource(_, files, _, _, _, _) => + files.exists(file => file.getAbsolutePath.contains(testFilter.get)) + case SeparateCompilationSource(_, dir, _, _) => + dir.getAbsolutePath.contains(testFilter.get) + } + + /** Total amount of test sources being compiled by this test */ + val sourceCount = filteredSources.length + + private[this] var _testSourcesCompleted = 0 + private def testSourcesCompleted: Int = _testSourcesCompleted + + /** Complete the current compilation with the amount of errors encountered */ + protected final def registerCompletion() = synchronized { + _testSourcesCompleted += 1 + } + + sealed trait Failure + case class JavaCompilationFailure(reason: String) extends Failure + case class TimeoutFailure(title: String) extends Failure + case object Generic extends Failure + + private[this] var _failures = Set.empty[Failure] + private[this] var _failureCount = 0 + + /** Fail the current test */ + protected[this] final def fail(failure: Failure = Generic): Unit = synchronized { + _failures = _failures + failure + _failureCount = _failureCount + 1 + } + def didFail: Boolean = _failureCount != 0 + + /** A set of the different failures */ + def failureReasons: Set[Failure] = _failures + + /** Number of failed tests */ + def failureCount: Int = _failureCount + + protected def logBuildInstructions(reporter: TestReporter, testSource: TestSource, err: Int, war: Int) = { + val errorMsg = testSource.buildInstructions(reporter.errorCount, reporter.warningCount) + addFailureInstruction(errorMsg) + failTestSource(testSource) + } + + /** Instructions on how to reproduce failed test source compilations */ + private[this] val reproduceInstructions = mutable.ArrayBuffer.empty[String] + protected final def addFailureInstruction(ins: String): Unit = + synchronized { reproduceInstructions.append(ins) } + + /** The test sources that failed according to the implementing subclass */ + private[this] val failedTestSources = mutable.ArrayBuffer.empty[String] + protected final def failTestSource(testSource: TestSource, reason: Failure = Generic) = synchronized { + val extra = reason match { + case TimeoutFailure(title) => s", test '$title' timed out" + case JavaCompilationFailure(msg) => s", java test sources failed to compile with: \n$msg" + case Generic => "" + } + failedTestSources.append(testSource.title + s" failed" + extra) + fail(reason) + } + + /** Prints to `System.err` if we're not suppressing all output */ + protected def echo(msg: String): Unit = if (!suppressAllOutput) { + // pad right so that output is at least as large as progress bar line + val paddingRight = " " * math.max(0, 80 - msg.length) + realStderr.println(msg + paddingRight) + } + + /** Print a progress bar for the current `Test` */ + private def updateProgressMonitor(start: Long): Unit = { + val tCompiled = testSourcesCompleted + if (tCompiled < sourceCount) { + val timestamp = (System.currentTimeMillis - start) / 1000 + val progress = (tCompiled.toDouble / sourceCount * 40).toInt + + realStdout.print( + "[" + ("=" * (math.max(progress - 1, 0))) + + (if (progress > 0) ">" else "") + + (" " * (39 - progress)) + + s"] completed ($tCompiled/$sourceCount, $failureCount failed, ${timestamp}s)\r" + ) + } + } + + /** Wrapper function to make sure that the compiler itself did not crash - + * if it did, the test should automatically fail. + */ + protected def tryCompile(testSource: TestSource)(op: => Unit): Unit = + try { + val testing = s"Testing ${testSource.title}" + summaryReport.echoToLog(testing) + if (!isInteractive) realStdout.println(testing) + op + } catch { + case e: Throwable => { + // if an exception is thrown during compilation, the complete test + // run should fail + failTestSource(testSource) + e.printStackTrace() + registerCompletion() + throw e + } + } + + protected def compile(files0: Array[JFile], flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = { + + val flags = flags0 and ("-d", targetDir.getAbsolutePath) + + def flattenFiles(f: JFile): Array[JFile] = + if (f.isDirectory) f.listFiles.flatMap(flattenFiles) + else Array(f) + + val files: Array[JFile] = files0.flatMap(flattenFiles) + + def compileWithJavac(fs: Array[String]) = if (fs.nonEmpty) { + val fullArgs = Array( + "javac", + "-encoding", "UTF-8", + "-classpath", + s"${Properties.scalaLibrary}${JFile.pathSeparator}${targetDir.getAbsolutePath}" + ) ++ flags.all.takeRight(2) ++ fs + + val process = Runtime.getRuntime.exec(fullArgs) + val output = Source.fromInputStream(process.getErrorStream).mkString + + if (process.waitFor() != 0) Some(output) + else None + } else None + + val reporter = + TestReporter.reporter(realStdout, logLevel = + if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR) + + val driver = + if (times == 1) new Driver + else new Driver { + private def ntimes(n: Int)(op: Int => Reporter): Reporter = + (emptyReporter /: (1 to n)) ((_, i) => op(i)) + + override def doCompile(comp: Compiler, files: List[String])(implicit ctx: Context) = + ntimes(times) { run => + val start = System.nanoTime() + val rep = super.doCompile(comp, files) + ctx.echo(s"\ntime run $run: ${(System.nanoTime - start) / 1000000}ms") + rep + } + } + + val allArgs = flags.withClasspath(targetDir.getAbsolutePath).all + + // Compile with a try to catch any StackTrace generated by the compiler: + try { + // If a test contains a Java file that cannot be parsed by Dotty's Java source parser, its + // name must contain the string "JAVA_ONLY". + val dottyFiles = files.filterNot(_.getName.contains("JAVA_ONLY")).map(_.getAbsolutePath) + driver.process(allArgs ++ dottyFiles, reporter = reporter) + + val javaFiles = files.filter(_.getName.endsWith(".java")).map(_.getAbsolutePath) + val javaErrors = compileWithJavac(javaFiles) + + if (javaErrors.isDefined) { + echo(s"\njava compilation failed: \n${ javaErrors.get }") + fail(failure = JavaCompilationFailure(javaErrors.get)) + } + } + catch { + case NonFatal(ex) => reporter.logStackTrace(ex) + } + + reporter + } + + protected def compileFromTasty(flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = { + val tastyOutput = new JFile(targetDir.getPath + "_from-tasty") + tastyOutput.mkdir() + val flags = flags0 and ("-d", tastyOutput.getAbsolutePath) and "-from-tasty" + + def tastyFileToClassName(f: JFile): String = { + val pathStr = targetDir.toPath.relativize(f.toPath).toString.replace(JFile.separatorChar, '.') + pathStr.stripSuffix(".tasty").stripSuffix(".hasTasty") + } + val classes = flattenFiles(targetDir).filter(isTastyFile).map(tastyFileToClassName) + + val reporter = + TestReporter.reporter(realStdout, logLevel = + if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR) + + val driver = new Driver + + // Compile with a try to catch any StackTrace generated by the compiler: + try { + driver.process(flags.all ++ classes, reporter = reporter) + } + catch { + case NonFatal(ex) => reporter.logStackTrace(ex) + } + + reporter + } + + protected def decompile(flags0: TestFlags, suppressErrors: Boolean, targetDir0: JFile): TestReporter = { + val targetDir = new JFile(targetDir0.getParent + "_decompiled") + val decompilationOutput = new JFile(targetDir + JFile.separator + targetDir0.getName) + decompilationOutput.mkdirs() + val flags = + flags0 and ("-d", decompilationOutput.getAbsolutePath) and + "-decompile" and "-pagewidth" and "80" + + def hasTastyFileToClassName(f: JFile): String = + targetDir0.toPath.relativize(f.toPath).toString.stripSuffix(".hasTasty"). + stripSuffix(".tasty").replace(JFile.separatorChar, '.') + val classes = flattenFiles(targetDir0).filter(isTastyFile).map(hasTastyFileToClassName).sorted + + val reporter = + TestReporter.reporter(realStdout, logLevel = + if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR) + + val driver = decompiler.Main + + // Compile with a try to catch any StackTrace generated by the compiler: + try { + driver.process(flags.all ++ classes, reporter = reporter) + } + catch { + case NonFatal(ex) => reporter.logStackTrace(ex) + } + + reporter + } + + private[ParallelTesting] def executeTestSuite(): this.type = { + assert(testSourcesCompleted == 0, "not allowed to re-use a `CompileRun`") + + if (filteredSources.nonEmpty) { + val pool = threadLimit match { + case Some(i) => JExecutors.newWorkStealingPool(i) + case None => JExecutors.newWorkStealingPool() + } + + val timer = new Timer() + val logProgress = isInteractive && !suppressAllOutput + val start = System.currentTimeMillis() + if (logProgress) { + val task = new TimerTask { + def run(): Unit = updateProgressMonitor(start) + } + timer.schedule(task, 100, 200) + } + + val eventualResults = filteredSources.map { target => + pool.submit(encapsulatedCompilation(target)) + } + + pool.shutdown() + if (!pool.awaitTermination(20, TimeUnit.MINUTES)) { + pool.shutdownNow() + System.setOut(realStdout) + System.setErr(realStderr) + throw new TimeoutException("Compiling targets timed out") + } + + eventualResults.foreach(_.get) + + if (logProgress) { + timer.cancel() + val timestamp = (System.currentTimeMillis - start) / 1000 + realStdout.println( + s"[=======================================] completed ($sourceCount/$sourceCount, $failureCount failed, ${timestamp}s)" + ) + } + + if (didFail) { + reportFailed() + failedTestSources.toSet.foreach(addFailedTest) + reproduceInstructions.iterator.foreach(addReproduceInstruction) + } + else reportPassed() + } + else echo { + testFilter + .map(r => s"""No files matched "$r" in test""") + .getOrElse("No tests available under target - erroneous test?") + } + + this + } + + /** Returns all files in directory or the file if not a directory */ + private def flattenFiles(f: JFile): Array[JFile] = + if (f.isDirectory) f.listFiles.flatMap(flattenFiles) + else Array(f) + } + + private final class PosTest(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit summaryReport: SummaryReporting) + extends Test(testSources, times, threadLimit, suppressAllOutput) { + protected def encapsulatedCompilation(testSource: TestSource) = new LoggedRunnable { + def checkTestSource(): Unit = tryCompile(testSource) { + testSource match { + case testSource @ JointCompilationSource(name, files, flags, outDir, fromTasty, decompilation) => + val reporter = + if (decompilation) { + val rep = decompile(flags, false, outDir) + + val checkFileOpt = files.flatMap { file => + if (file.isDirectory) Nil + else { + val fname = file.getAbsolutePath.reverse.dropWhile(_ != '.').reverse + "decompiled" + val checkFile = new JFile(fname) + if (checkFile.exists) List(checkFile) + else Nil + } + }.headOption + checkFileOpt match { + case Some(checkFile) => + val ignoredFilePathLine = "/** Decompiled from" + val stripTrailingWhitespaces = "(.*\\S|)\\s+".r + val output = Source.fromFile(outDir.getParent + "_decompiled" + JFile.separator + outDir.getName + + JFile.separator + "decompiled.scala").getLines().map {line => + stripTrailingWhitespaces.unapplySeq(line).map(_.head).getOrElse(line) + }.toList + + val check: String = Source.fromFile(checkFile).getLines().filter(!_.startsWith(ignoredFilePathLine)) + .mkString("\n") + + if (output.filter(!_.startsWith(ignoredFilePathLine)).mkString("\n") != check) { + val outFile = dotty.tools.io.File(checkFile.toPath).addExtension(".out") + outFile.writeAll(output.mkString("\n")) + val msg = + s"""Output differed for test $name, use the following command to see the diff: + | > diff $checkFile $outFile + """.stripMargin + + echo(msg) + addFailureInstruction(msg) + + // Print build instructions to file and summary: + val buildInstr = testSource.buildInstructions(0, rep.warningCount) + addFailureInstruction(buildInstr) + + // Fail target: + failTestSource(testSource) + } + case _ => + } + + rep + } + else if (fromTasty) compileFromTasty(flags, false, outDir) + else compile(testSource.sourceFiles, flags, false, outDir) + registerCompletion() + + if (reporter.compilerCrashed || reporter.errorCount > 0) { + logReporterContents(reporter) + logBuildInstructions(reporter, testSource, reporter.errorCount, reporter.warningCount) + } + + case testSource @ SeparateCompilationSource(_, dir, flags, outDir) => + val reporters = testSource.compilationGroups.map(files => compile(files, flags, false, outDir)) + val compilerCrashed = reporters.exists(_.compilerCrashed) + val errorCount = reporters.foldLeft(0) { (acc, reporter) => + if (reporter.errorCount > 0) + logBuildInstructions(reporter, testSource, reporter.errorCount, reporter.warningCount) + + acc + reporter.errorCount + } + + def warningCount = reporters.foldLeft(0)(_ + _.warningCount) + + registerCompletion() + + if (compilerCrashed || errorCount > 0) { + reporters.foreach(logReporterContents) + logBuildInstructions(reporters.head, testSource, errorCount, warningCount) + } + } + } + } + } + + private final class RunTest(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit summaryReport: SummaryReporting) + extends Test(testSources, times, threadLimit, suppressAllOutput) { + private[this] var didAddNoRunWarning = false + private[this] def addNoRunWarning() = if (!didAddNoRunWarning) { + didAddNoRunWarning = true + summaryReport.addStartingMessage { + """|WARNING + |------- + |Run tests were only compiled, not run - this is due to the `dotty.tests.norun` + |property being set + |""".stripMargin + } + } + + private def verifyOutput(checkFile: Option[JFile], dir: JFile, testSource: TestSource, warnings: Int) = { + if (Properties.testsNoRun) addNoRunWarning() + else runMain(testSource.runClassPath) match { + case Success(_) if !checkFile.isDefined || !checkFile.get.exists => // success! + case Success(output) => { + val outputLines = output.linesIterator.toArray :+ DiffUtil.EOF + val checkLines: Array[String] = Source.fromFile(checkFile.get).getLines().toArray :+ DiffUtil.EOF + val sourceTitle = testSource.title + + def linesMatch = + outputLines + .zip(checkLines) + .forall { case (x, y) => x == y } + + if (outputLines.length != checkLines.length || !linesMatch) { + // Print diff to files and summary: + val diff = DiffUtil.mkColoredLineDiff(checkLines, outputLines) + + val msg = + s"""|Output from '$sourceTitle' did not match check file. + |Diff (expected on the left, actual right): + |""".stripMargin + diff + "\n" + echo(msg) + addFailureInstruction(msg) + + // Print build instructions to file and summary: + val buildInstr = testSource.buildInstructions(0, warnings) + addFailureInstruction(buildInstr) + + // Fail target: + failTestSource(testSource) + } + } + + case Failure(output) => + echo(s"Test '${testSource.title}' failed with output:") + echo(output) + failTestSource(testSource) + + case Timeout => + echo("failed because test " + testSource.title + " timed out") + failTestSource(testSource, TimeoutFailure(testSource.title)) + } + } + + protected def encapsulatedCompilation(testSource: TestSource) = new LoggedRunnable { + def checkTestSource(): Unit = tryCompile(testSource) { + val (compilerCrashed, errorCount, warningCount, verifier: Function0[Unit]) = testSource match { + case testSource @ JointCompilationSource(_, files, flags, outDir, fromTasty, decompilation) => + val checkFile = files.flatMap { file => + if (file.isDirectory) Nil + else { + val fname = file.getAbsolutePath.reverse.dropWhile(_ != '.').reverse + "check" + val checkFile = new JFile(fname) + if (checkFile.exists) List(checkFile) + else Nil + } + }.headOption + val reporter = + if (fromTasty) compileFromTasty(flags, false, outDir) + else compile(testSource.sourceFiles, flags, false, outDir) + + if (reporter.compilerCrashed || reporter.errorCount > 0) { + logReporterContents(reporter) + logBuildInstructions(reporter, testSource, reporter.errorCount, reporter.warningCount) + } + + (reporter.compilerCrashed, reporter.errorCount, reporter.warningCount, () => verifyOutput(checkFile, outDir, testSource, reporter.warningCount)) + + case testSource @ SeparateCompilationSource(_, dir, flags, outDir) => + val checkFile = new JFile(dir.getAbsolutePath.reverse.dropWhile(_ == JFile.separatorChar).reverse + ".check") + val reporters = testSource.compilationGroups.map(compile(_, flags, false, outDir)) + val compilerCrashed = reporters.exists(_.compilerCrashed) + val (errorCount, warningCount) = + reporters.foldLeft((0,0)) { case ((errors, warnings), reporter) => + if (reporter.errorCount > 0) + logBuildInstructions(reporter, testSource, reporter.errorCount, reporter.warningCount) + + (errors + reporter.errorCount, warnings + reporter.warningCount) + } + + if (errorCount > 0) { + reporters.foreach(logReporterContents) + logBuildInstructions(reporters.head, testSource, errorCount, warningCount) + } + + (compilerCrashed, errorCount, warningCount, () => verifyOutput(Some(checkFile), outDir, testSource, warningCount)) + } + + if (!compilerCrashed && errorCount == 0) verifier() + else { + echo(s" Compilation failed for: '${testSource.title}' ") + val buildInstr = testSource.buildInstructions(errorCount, warningCount) + addFailureInstruction(buildInstr) + failTestSource(testSource) + } + registerCompletion() + } + } + } + + private final class NegTest(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit summaryReport: SummaryReporting) + extends Test(testSources, times, threadLimit, suppressAllOutput) { + protected def encapsulatedCompilation(testSource: TestSource) = new LoggedRunnable { + def checkTestSource(): Unit = tryCompile(testSource) { + // In neg-tests we allow two types of error annotations, + // "nopos-error" which doesn't care about position and "error" which + // has to be annotated on the correct line number. + // + // We collect these in a map `"file:row" -> numberOfErrors`, for + // nopos errors we save them in `"file" -> numberOfNoPosErrors` + def getErrorMapAndExpectedCount(files: Array[JFile]): (HashMap[String, Integer], Int) = { + val errorMap = new HashMap[String, Integer]() + var expectedErrors = 0 + files.filter(_.getName.endsWith(".scala")).foreach { file => + Source.fromFile(file).getLines().zipWithIndex.foreach { case (line, lineNbr) => + val errors = line.sliding("// error".length).count(_.mkString == "// error") + if (errors > 0) + errorMap.put(s"${file.getAbsolutePath}:${lineNbr}", errors) + + val noposErrors = line.sliding("// nopos-error".length).count(_.mkString == "// nopos-error") + if (noposErrors > 0) { + val nopos = errorMap.get("nopos") + val existing: Integer = if (nopos eq null) 0 else nopos + errorMap.put("nopos", noposErrors + existing) + } + + expectedErrors += noposErrors + errors + } + } + + (errorMap, expectedErrors) + } + + def getMissingExpectedErrors(errorMap: HashMap[String, Integer], reporterErrors: Iterator[MessageContainer]) = !reporterErrors.forall { error => + val key = if (error.pos.exists) { + val fileName = error.pos.source.file.toString + s"$fileName:${error.pos.line}" + + } else "nopos" + + val errors = errorMap.get(key) + + if (errors ne null) { + if (errors == 1) errorMap.remove(key) + else errorMap.put(key, errors - 1) + true + } + else { + echo(s"Error reported in ${error.pos.source}, but no annotation found") + false + } + } + + val (compilerCrashed, expectedErrors, actualErrors, hasMissingAnnotations, errorMap) = testSource match { + case testSource @ JointCompilationSource(_, files, flags, outDir, fromTasty, decompilation) => + val sourceFiles = testSource.sourceFiles + val (errorMap, expectedErrors) = getErrorMapAndExpectedCount(sourceFiles) + val reporter = compile(sourceFiles, flags, true, outDir) + val actualErrors = reporter.errorCount + + if (reporter.compilerCrashed || actualErrors > 0) + logReporterContents(reporter) + + (reporter.compilerCrashed, expectedErrors, actualErrors, () => getMissingExpectedErrors(errorMap, reporter.errors), errorMap) + + case testSource @ SeparateCompilationSource(_, dir, flags, outDir) => { + val compilationGroups = testSource.compilationGroups + val (errorMap, expectedErrors) = getErrorMapAndExpectedCount(compilationGroups.toArray.flatten) + val reporters = compilationGroups.map(compile(_, flags, true, outDir)) + val compilerCrashed = reporters.exists(_.compilerCrashed) + val actualErrors = reporters.foldLeft(0)(_ + _.errorCount) + val errors = reporters.iterator.flatMap(_.errors) + + if (actualErrors > 0) + reporters.foreach(logReporterContents) + + (compilerCrashed, expectedErrors, actualErrors, () => getMissingExpectedErrors(errorMap, errors), errorMap) + } + } + + def fail(msg: String): Unit = { + echo(msg) + failTestSource(testSource) + } + + if (compilerCrashed) + fail(s"Compiler crashed when compiling: ${testSource.title}") + else if (actualErrors == 0) + fail(s"\nNo errors found when compiling neg test $testSource") + else if (expectedErrors != actualErrors) + fail(s"\nWrong number of errors encountered when compiling $testSource, expected: $expectedErrors, actual: $actualErrors") + else if (hasMissingAnnotations()) + fail(s"\nErrors found on incorrect row numbers when compiling $testSource") + else if (!errorMap.isEmpty) + fail(s"\nExpected error(s) have {=}: $errorMap") + + registerCompletion() + } + } + } + + /** The `CompilationTest` is the main interface to `ParallelTesting`, it + * can be instantiated via one of the following methods: + * + * - `compileFile` + * - `compileDir` + * - `compileList` + * - `compileFilesInDir` + * - `compileShallowFilesInDir` + * + * Each compilation test can then be turned into either a "pos", "neg" or + * "run" test: + * + * ``` + * compileFile("tests/pos/i1103.scala", opts).pos() + * ``` + * + * These tests can be customized before calling one of the execution + * methods, for instance: + * + * ``` + * compileFile("tests/pos/i1103.scala", opts).times(2).verbose.pos() + * ``` + * + * Which would compile `i1103.scala` twice with the verbose flag as a "pos" + * test. + * + * pos tests + * ========= + * Pos tests verify that the compiler is able to compile the given + * `TestSource`s and that they generate no errors or exceptions during + * compilation + * + * neg tests + * ========= + * Neg tests are expected to generate a certain amount of errors - but not + * crash the compiler. In each `.scala` file, you specify the line on which + * the error will be generated, e.g: + * + * ``` + * val x: String = 1 // error + * ``` + * + * if a line generates multiple errors, you need to annotate it multiple + * times. For a line that generates two errors: + * + * ``` + * val y: String = { val y1: String = 1; 2 } // error // error + * ``` + * + * Certain errors have no position, if you need to check these annotate the + * file anywhere with `// nopos-error` + * + * run tests + * ========= + * Run tests are a superset of pos tests, they both verify compilation and + * that the compiler does not crash. In addition, run tests verify that the + * tests are able to run as expected. + * + * Run tests need to have the following form: + * + * ``` + * object Test { + * def main(args: Array[String]): Unit = () + * } + * ``` + * + * This is because the runner instantiates the `Test` class and calls the + * main method. + * + * Other definitions are allowed in the same file, but the file needs to at + * least have the `Test` object with a `main` method. + * + * To verify output you may use `.check` files. These files should share the + * name of the file or directory that they are testing. For instance: + * + * ```none + * . + * └── tests + * ├── i1513.scala + * └── i1513.check + * ``` + * + * If you are testing a directory under separate compilation, you would + * have: + * + * ```none + * . + * └── tests + * ├── myTestDir + * │ ├── T_1.scala + * │ ├── T_2.scala + * │ └── T_3.scala + * └── myTestDir.check + * ``` + * + * In the above example, `i1513.scala` and one of the files `T_X.scala` + * would contain a `Test` object with a main method. + * + * Composing tests + * =============== + * Since this is a parallel test suite, it is essential to be able to + * compose tests to take advantage of the concurrency. This is done using + * the `+` function. This function will make sure that tests being combined + * are compatible according to the `require`s in `+`. + */ + final class CompilationTest private ( + private[ParallelTesting] val targets: List[TestSource], + private[ParallelTesting] val times: Int, + private[ParallelTesting] val shouldDelete: Boolean, + private[ParallelTesting] val threadLimit: Option[Int], + private[ParallelTesting] val shouldFail: Boolean, + private[ParallelTesting] val shouldSuppressOutput: Boolean + ) { + import org.junit.Assert.fail + + def this(target: TestSource) = + this(List(target), 1, true, None, false, false) + + def this(targets: List[TestSource]) = + this(targets, 1, true, None, false, false) + + /** Compose test targets from `this` with `other` + * + * It does this, only if the two tests are compatible. Otherwise it throws + * an `IllegalArgumentException`. + * + * Grouping tests together like this allows us to take advantage of the + * concurrency offered by this test suite as each call to an executing + * method (`pos()` / `checkExpectedErrors()`/ `run()`) will spin up a thread pool with the + * maximum allowed level of concurrency. Doing this for only a few targets + * does not yield any real benefit over sequential compilation. + * + * As such, each `CompilationTest` should contain as many targets as + * possible. + */ + def +(other: CompilationTest) = { + require(other.times == times, "can't combine tests that are meant to be benchmark compiled") + require(other.shouldDelete == shouldDelete, "can't combine tests that differ on deleting output") + require(other.shouldFail == shouldFail, "can't combine tests that have different expectations on outcome") + require(other.shouldSuppressOutput == shouldSuppressOutput, "can't combine tests that both suppress and don't suppress output") + new CompilationTest(targets ++ other.targets, times, shouldDelete, threadLimit, shouldFail, shouldSuppressOutput) + } + + /** Creates a "pos" test run, which makes sure that all tests pass + * compilation without generating errors and that they do not crash the + * compiler + */ + def checkCompile()(implicit summaryReport: SummaryReporting): this.type = { + val test = new PosTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite() + + cleanup() + + if (!shouldFail && test.didFail) { + fail(s"Expected no errors when compiling, failed for the following reason(s):\n${ reasonsForFailure(test) }") + } + else if (shouldFail && !test.didFail) { + fail("Pos test should have failed, but didn't") + } + + this + } + + /** Creates a "neg" test run, which makes sure that each test generates the + * correct amount of errors at the correct positions. It also makes sure + * that none of these tests crash the compiler + */ + def checkExpectedErrors()(implicit summaryReport: SummaryReporting): this.type = { + val test = new NegTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite() + + cleanup() + + if (shouldFail && !test.didFail) { + fail(s"Neg test shouldn't have failed, but did. Reasons:\n${ reasonsForFailure(test) }") + } + else if (!shouldFail && test.didFail) { + fail("Neg test should have failed, but did not") + } + + this + } + + /** Creates a "run" test run, which is a superset of "pos". In addition to + * making sure that all tests pass compilation and that they do not crash + * the compiler; it also makes sure that all tests can run with the + * expected output + */ + def checkRuns()(implicit summaryReport: SummaryReporting): this.type = { + val test = new RunTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite() + + cleanup() + + if (!shouldFail && test.didFail) { + fail(s"Run test failed, but should not, reasons:\n${ reasonsForFailure(test) }") + } + else if (shouldFail && !test.didFail) { + fail("Run test should have failed, but did not") + } + + this + } + + /** Deletes output directories and files */ + private def cleanup(): this.type = { + if (shouldDelete) delete() + this + } + + /** Extract `Failure` set and render from `Test` */ + private[this] def reasonsForFailure(test: Test): String = { + val failureReport = + if (test.failureCount == 0) "" + else s"\n - encountered ${test.failureCount} test failures(s)" + + failureReport + test.failureReasons.collect { + case test.TimeoutFailure(title) => + s" - test '$title' timed out" + case test.JavaCompilationFailure(msg) => + s" - java compilation failed with:\n${ msg.linesIterator.map(" " + _).mkString("\n") }" + }.mkString("\n") + } + + /** Copies `file` to `dir` - taking into account if `file` is a directory, + * and if so copying recursively + */ + private def copyToDir(dir: JFile, file: JFile): JFile = { + val target = Paths.get(dir.getAbsolutePath, file.getName) + Files.copy(file.toPath, target, REPLACE_EXISTING) + if (file.isDirectory) file.listFiles.map(copyToDir(target.toFile, _)) + target.toFile + } + + /** Builds a new `CompilationTest` where we have copied the target files to + * the out directory. This is needed for tests that modify the original + * source, such as `-rewrite` tests + */ + def copyToTarget(): CompilationTest = new CompilationTest ( + targets.map { + case target @ JointCompilationSource(_, files, _, outDir, _, _) => + target.copy(files = files.map(copyToDir(outDir,_))) + case target @ SeparateCompilationSource(_, dir, _, outDir) => + target.copy(dir = copyToDir(outDir, dir)) + }, + times, shouldDelete, threadLimit, shouldFail, shouldSuppressOutput + ) + + /** Builds a `CompilationTest` which performs the compilation `i` times on + * each target + */ + def times(i: Int): CompilationTest = + new CompilationTest(targets, i, shouldDelete, threadLimit, shouldFail, shouldSuppressOutput) + + /** Builds a `Compilationtest` which passes the verbose flag and logs the + * classpath + */ + def verbose: CompilationTest = new CompilationTest( + targets.map(t => t.withFlags("-verbose", "-Ylog-classpath")), + times, shouldDelete, threadLimit, shouldFail, shouldSuppressOutput + ) + + /** Builds a `CompilationTest` which keeps the generated output files + * + * This is needed for tests like `tastyBootstrap` which relies on first + * compiling a certain part of the project and then compiling a second + * part which depends on the first + */ + def keepOutput: CompilationTest = + new CompilationTest(targets, times, false, threadLimit, shouldFail, shouldSuppressOutput) + + /** Builds a `CompilationTest` with a limited level of concurrency with + * maximum `i` threads + */ + def limitThreads(i: Int): CompilationTest = + new CompilationTest(targets, times, shouldDelete, Some(i), shouldFail, shouldSuppressOutput) + + /** Builds a `CompilationTest` where the executed test is expected to fail + * + * This behaviour is mainly needed for the tests that test the test suite. + */ + def expectFailure: CompilationTest = + new CompilationTest(targets, times, shouldDelete, threadLimit, true, shouldSuppressOutput) + + /** Builds a `CompilationTest` where all output is suppressed + * + * This behaviour is mainly needed for the tests that test the test suite. + */ + def suppressAllOutput: CompilationTest = + new CompilationTest(targets, times, shouldDelete, threadLimit, shouldFail, true) + + /** Delete all output files generated by this `CompilationTest` */ + def delete(): Unit = targets.foreach(t => delete(t.outDir)) + + private def delete(file: JFile): Unit = { + if (file.isDirectory) file.listFiles.foreach(delete) + try Files.delete(file.toPath) + catch { + case _: NoSuchFileException => // already deleted, everything's fine + } + } + } + + /** Create out directory for directory `d` */ + def createOutputDirsForDir(d: JFile, sourceDir: JFile, outDir: String): JFile = { + val targetDir = new JFile(outDir + s"${sourceDir.getName}/${d.getName}") + targetDir.mkdirs() + targetDir + } + + /** Create out directory for `file` */ + private def createOutputDirsForFile(file: JFile, sourceDir: JFile, outDir: String): JFile = { + val uniqueSubdir = file.getName.substring(0, file.getName.lastIndexOf('.')) + val targetDir = new JFile(outDir + s"${sourceDir.getName}${JFile.separatorChar}$uniqueSubdir") + targetDir.mkdirs() + targetDir + } + + /** Make sure that directory string is as expected */ + private def checkRequirements(f: String, sourceDir: JFile, outDir: String): Unit = { + require(sourceDir.isDirectory && sourceDir.exists, "passed non-directory to `compileFilesInDir`: " + sourceDir) + require(outDir.last == JFile.separatorChar, "please specify an `outDir` with a trailing file separator") + } + + /** Separates directories from files and returns them as `(dirs, files)` */ + private def compilationTargets(sourceDir: JFile, fileFilter: FileFilter = FileFilter.NoFilter): (List[JFile], List[JFile]) = + sourceDir.listFiles.foldLeft((List.empty[JFile], List.empty[JFile])) { case ((dirs, files), f) => + if (!fileFilter.accept(f.getName)) (dirs, files) + else if (f.isDirectory) (f :: dirs, files) + else if (isSourceFile(f)) (dirs, f :: files) + else (dirs, files) + } + + /** Compiles a single file from the string path `f` using the supplied flags */ + def compileFile(f: String, flags: TestFlags)(implicit testGroup: TestGroup): CompilationTest = { + val sourceFile = new JFile(f) + val parent = sourceFile.getParentFile + val outDir = + defaultOutputDir + testGroup + JFile.separator + + sourceFile.getName.substring(0, sourceFile.getName.lastIndexOf('.')) + JFile.separator + + require( + sourceFile.exists && !sourceFile.isDirectory && + (parent ne null) && parent.exists && parent.isDirectory, + s"Source file: $f, didn't exist" + ) + + val target = JointCompilationSource( + testGroup.name, + Array(sourceFile), + flags, + createOutputDirsForFile(sourceFile, parent, outDir) + ) + new CompilationTest(target) + } + + /** Compiles a directory `f` using the supplied `flags`. This method does + * deep compilation, that is - it compiles all files and subdirectories + * contained within the directory `f`. + * + * By default, files are compiled in alphabetical order. An optional seed + * can be used for randomization. + */ + def compileDir(f: String, flags: TestFlags, randomOrder: Option[Int] = None, recursive: Boolean = true)(implicit testGroup: TestGroup): CompilationTest = { + val outDir = defaultOutputDir + testGroup + JFile.separator + val sourceDir = new JFile(f) + checkRequirements(f, sourceDir, outDir) + + def flatten(f: JFile): Array[JFile] = + if (f.isDirectory) { + val files = f.listFiles + if (recursive) files.flatMap(flatten) else files + } + else Array(f) + + // Sort files either alphabetically or randomly using the provided seed: + val sortedFiles = flatten(sourceDir).sorted + val randomized = randomOrder match { + case None => sortedFiles + case Some(seed) => new Random(seed).shuffle(sortedFiles.toList).toArray + } + + // Directories in which to compile all containing files with `flags`: + val targetDir = new JFile(outDir + JFile.separator + sourceDir.getName + JFile.separator) + targetDir.mkdirs() + + val target = JointCompilationSource(s"compiling '$f' in test '$testGroup'", randomized, flags, targetDir) + new CompilationTest(target) + } + + /** Compiles all `files` together as a single compilation run. It is given a + * `testName` since files can be in separate directories and or be otherwise + * dissociated + */ + def compileList(testName: String, files: List[String], flags: TestFlags)(implicit testGroup: TestGroup): CompilationTest = { + val outDir = defaultOutputDir + testGroup + JFile.separator + testName + JFile.separator + + // Directories in which to compile all containing files with `flags`: + val targetDir = new JFile(outDir) + targetDir.mkdirs() + assert(targetDir.exists, s"couldn't create target directory: $targetDir") + + val target = JointCompilationSource(s"$testName from $testGroup", files.map(new JFile(_)).toArray, flags, targetDir) + + // Create a CompilationTest and let the user decide whether to execute a pos or a neg test + new CompilationTest(target) + } + + /** This function compiles the files and folders contained within directory + * `f` in a specific way. + * + * - Each file is compiled separately as a single compilation run + * - Each directory is compiled as a `SeparateCompilationTarget`, in this + * target all files are grouped according to the file suffix `_X` where `X` + * is a number. These groups are then ordered in ascending order based on + * the value of `X` and each group is compiled one after the other. + * + * For this function to work as expected, we use the same convention for + * directory layout as the old partest. That is: + * + * - Single files can have an associated check-file with the same name (but + * with file extension `.check`) + * - Directories can have an associated check-file, where the check file has + * the same name as the directory (with the file extension `.check`) + */ + def compileFilesInDir(f: String, flags: TestFlags, fileFilter: FileFilter = FileFilter.NoFilter)(implicit testGroup: TestGroup): CompilationTest = { + val outDir = defaultOutputDir + testGroup + JFile.separator + val sourceDir = new JFile(f) + checkRequirements(f, sourceDir, outDir) + + val (dirs, files) = compilationTargets(sourceDir, fileFilter) + + val targets = + files.map(f => JointCompilationSource(testGroup.name, Array(f), flags, createOutputDirsForFile(f, sourceDir, outDir))) ++ + dirs.map(dir => SeparateCompilationSource(testGroup.name, dir, flags, createOutputDirsForDir(dir, sourceDir, outDir))) + + // Create a CompilationTest and let the user decide whether to execute a pos or a neg test + new CompilationTest(targets) + } + + /** This function compiles the files and folders contained within directory + * `f` in a specific way. Once compiled, they are recompiled/run from tasty as sources. + * + * - Each file is compiled separately as a single compilation run + * - Each directory is compiled as a `SeparateCompilationTarget`, in this + * target all files are grouped according to the file suffix `_X` where `X` + * is a number. These groups are then ordered in ascending order based on + * the value of `X` and each group is compiled one after the other. + * + * For this function to work as expected, we use the same convention for + * directory layout as the old partest. That is: + * + * - Single files can have an associated check-file with the same name (but + * with file extension `.check`) + * - Directories can have an associated check-file, where the check file has + * the same name as the directory (with the file extension `.check`) + * + * Tests in the first part of the tuple must be executed before the second. + * Both testsRequires explicit delete(). + */ + def compileTastyInDir(f: String, flags0: TestFlags, fromTastyFilter: FileFilter, decompilationFilter: FileFilter, recompilationFilter: FileFilter)( + implicit testGroup: TestGroup): TastyCompilationTest = { + val outDir = defaultOutputDir + testGroup + JFile.separator + val flags = flags0 and "-Yretain-trees" + val sourceDir = new JFile(f) + checkRequirements(f, sourceDir, outDir) + + val (dirs, files) = compilationTargets(sourceDir, fromTastyFilter) + + val filteredFiles = testFilter match { + case Some(str) => files.filter(_.getAbsolutePath.contains(str)) + case None => files + } + + class JointCompilationSourceFromTasty( + name: String, + file: JFile, + flags: TestFlags, + outDir: JFile, + fromTasty: Boolean = false, + decompilation: Boolean = false + ) extends JointCompilationSource(name, Array(file), flags, outDir, fromTasty, decompilation) { + + override def buildInstructions(errors: Int, warnings: Int): String = { + val runOrPos = if (file.getPath.startsWith(s"tests${JFile.separator}run${JFile.separator}")) "run" else "pos" + val listName = if (fromTasty) "from-tasty" else "decompilation" + s"""| + |Test '$title' compiled with $errors error(s) and $warnings warning(s), + |the test can be reproduced by running: + | + | sbt "testFromTasty $file" + | + |This tests can be disabled by adding `${file.getName}` to `compiler${JFile.separator}test${JFile.separator}dotc${JFile.separator}$runOrPos-$listName.blacklist` + | + |""".stripMargin + } + + } + + val targets = filteredFiles.map { f => + val classpath = createOutputDirsForFile(f, sourceDir, outDir) + new JointCompilationSourceFromTasty(testGroup.name, f, flags.withClasspath(classpath.getPath), classpath, fromTasty = true) + } + // TODO add SeparateCompilationSource from tasty? + + val targets2 = + filteredFiles + .filter(f => decompilationFilter.accept(f.getName)) + .map { f => + val classpath = createOutputDirsForFile(f, sourceDir, outDir) + new JointCompilationSourceFromTasty(testGroup.name, f, flags.withClasspath(classpath.getPath), classpath, decompilation = true) + } + + // Create a CompilationTest and let the user decide whether to execute a pos or a neg test + val generateClassFiles = compileFilesInDir(f, flags0, fromTastyFilter) + + val decompilationDir = outDir + sourceDir.getName + "_decompiled" + + if (targets2.isEmpty) + new JFile(decompilationDir).mkdirs() + + new TastyCompilationTest( + generateClassFiles.keepOutput, + new CompilationTest(targets).keepOutput, + new CompilationTest(targets2).keepOutput, + recompilationFilter, + decompilationDir, + shouldDelete = true + ) + } + + class TastyCompilationTest(step1: CompilationTest, step2: CompilationTest, step3: CompilationTest, + recompilationFilter: FileFilter, decompilationDir: String, shouldDelete: Boolean)(implicit testGroup: TestGroup) { + + def keepOutput: TastyCompilationTest = + new TastyCompilationTest(step1, step2, step3, recompilationFilter, decompilationDir, shouldDelete) + + def checkCompile()(implicit summaryReport: SummaryReporting): this.type = { + step1.checkCompile() // Compile all files to generate the class files with tasty + step2.checkCompile() // Compile from tasty + step3.checkCompile() // Decompile from tasty + + val step4 = compileFilesInDir(decompilationDir, defaultOptions, recompilationFilter).keepOutput + step4.checkCompile() // Recompile decompiled code + + if (shouldDelete) + (step1 + step2 + step3 + step4).delete() + + this + } + + def checkRuns()(implicit summaryReport: SummaryReporting): this.type = { + step1.checkCompile() // Compile all files to generate the class files with tasty + step2.checkRuns() // Compile from tasty + step3.checkCompile() // Decompile from tasty + + val step4 = compileFilesInDir(decompilationDir, defaultOptions, recompilationFilter).keepOutput + step4.checkRuns() // Recompile decompiled code + + if (shouldDelete) + (step1 + step2 + step3 + step4).delete() + + this + } + } + + /** This function behaves similar to `compileFilesInDir` but it ignores + * sub-directories and as such, does **not** perform separate compilation + * tests. + */ + def compileShallowFilesInDir(f: String, flags: TestFlags)(implicit testGroup: TestGroup): CompilationTest = { + val outDir = defaultOutputDir + testGroup + JFile.separator + val sourceDir = new JFile(f) + checkRequirements(f, sourceDir, outDir) + + val (_, files) = compilationTargets(sourceDir) + + val targets = files.map { file => + JointCompilationSource(testGroup.name, Array(file), flags, createOutputDirsForFile(file, sourceDir, outDir)) + } + + // Create a CompilationTest and let the user decide whether to execute a pos or a neg test + new CompilationTest(targets) + } +} + +object ParallelTesting { + + def defaultOutputDir: String = "out"+JFile.separator + + def isSourceFile(f: JFile): Boolean = { + val name = f.getName + name.endsWith(".scala") || name.endsWith(".java") + } + + def isTastyFile(f: JFile): Boolean = + f.getName.endsWith(".hasTasty") || f.getName.endsWith(".tasty") +} From 0ffcf56093d88b6780509a005aaf5df967f5db8f Mon Sep 17 00:00:00 2001 From: Dotty CI Date: Thu, 22 Nov 2018 10:43:51 +0100 Subject: [PATCH 21/22] applied suggested change --- compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala index 340537fe5cff..19d4e1345f74 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala @@ -17,7 +17,7 @@ import dotty.tools.dotc.transform.Staging import dotty.tools.dotc.typer.FrontEnd import dotty.tools.dotc.util.Positions.Position import dotty.tools.dotc.util.SourceFile -import dotty.tools.io.{Path, PlainFile} +import dotty.tools.io.{Path, VirtualFile} import scala.quoted.{Expr, Type} @@ -67,7 +67,7 @@ class QuoteCompiler extends Compiler { */ private def inClass(expr: Expr[_])(implicit ctx: Context): Tree = { val pos = Position(0) - val assocFile = new PlainFile(Path("_quote_")) + val assocFile = new VirtualFile(Path("").path) val cls = ctx.newCompleteClassSymbol(defn.RootClass, outputClassName, EmptyFlags, defn.ObjectType :: Nil, newScope, coord = pos, assocFile = assocFile).entered.asClass From da92591291788489c378bf6336a9e78085ecb2fc Mon Sep 17 00:00:00 2001 From: Dotty CI Date: Thu, 22 Nov 2018 12:20:56 +0100 Subject: [PATCH 22/22] applied suggested change --- compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala index 19d4e1345f74..21b442ac4dfc 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala @@ -67,7 +67,7 @@ class QuoteCompiler extends Compiler { */ private def inClass(expr: Expr[_])(implicit ctx: Context): Tree = { val pos = Position(0) - val assocFile = new VirtualFile(Path("").path) + val assocFile = new VirtualFile("") val cls = ctx.newCompleteClassSymbol(defn.RootClass, outputClassName, EmptyFlags, defn.ObjectType :: Nil, newScope, coord = pos, assocFile = assocFile).entered.asClass