浏览代码

Merge branch 'development' into hlcode_absolute_jump_offsets

Simon Krajewski 1 年之前
父节点
当前提交
73cde7b83c
共有 100 个文件被更改,包括 2629 次插入1860 次删除
  1. 137 105
      .github/workflows/main.yml
  2. 4 0
      .vscode/schemas/define.schema.json
  3. 4 1
      Earthfile
  4. 9 4
      Makefile
  5. 5 2
      Makefile.win
  6. 2 1
      dune
  7. 1 1
      extra/BUILDING.md
  8. 180 5
      extra/CHANGES.txt
  9. 1 1
      extra/EnvVarUpdate.nsh
  10. 37 38
      extra/ImportAll.hx
  11. 3 3
      extra/choco/haxe.nuspec
  12. 4 5
      extra/github-actions/build-mac.yml
  13. 8 1
      extra/github-actions/build-windows.yml
  14. 0 6
      extra/github-actions/cache-opam.yml
  15. 4 2
      extra/github-actions/install-nsis.yml
  16. 2 7
      extra/github-actions/install-ocaml-libs-windows.yml
  17. 30 8
      extra/github-actions/install-ocaml-windows.yml
  18. 11 7
      extra/github-actions/install-ocaml-windows64.yml
  19. 4 0
      extra/github-actions/test-windows.yml
  20. 56 53
      extra/github-actions/workflows/main.yml
  21. 1 1
      extra/haxelib_src
  22. 1 1
      extra/installer.nsi
  23. 2 2
      extra/mac-installer/scripts/neko-postinstall.sh
  24. 15 11
      extra/release-checklist.txt
  25. 7 5
      haxe.opam
  26. 3 3
      libs/extc/extc.ml
  27. 21 21
      libs/extc/extc_stubs.c
  28. 2 2
      libs/extc/process_stubs.c
  29. 7 1
      libs/extlib-leftovers/dune
  30. 5 5
      libs/extlib-leftovers/multiArray.ml
  31. 1 1
      libs/extlib-leftovers/uTF8.ml
  32. 7 1
      libs/ilib/dune
  33. 2 2
      libs/ilib/peReader.ml
  34. 7 1
      libs/javalib/dune
  35. 7 1
      libs/neko/dune
  36. 2 2
      libs/neko/ncompile.ml
  37. 27 4
      libs/objsize/c_objsize.c
  38. 9 6
      libs/pcre2/pcre2_stubs.c
  39. 7 1
      libs/swflib/dune
  40. 1 1
      libs/swflib/swfParser.ml
  41. 1 1
      libs/swflib/swfPic.ml
  42. 7 1
      libs/ttflib/dune
  43. 1 1
      libs/ttflib/tTFParser.ml
  44. 7 1
      libs/ziplib/dune
  45. 8 8
      libs/ziplib/zip.ml
  46. 7 1
      plugins/example/dune
  47. 199 37
      src-json/define.json
  48. 2 1
      src-json/meta.json
  49. 10 0
      src-json/warning.json
  50. 7 1
      src-prebuild/dune
  51. 68 28
      src-prebuild/prebuild.ml
  52. 24 24
      src/codegen/codegen.ml
  53. 14 13
      src/codegen/dotnet.ml
  54. 14 7
      src/codegen/gencommon/castDetect.ml
  55. 13 21
      src/codegen/gencommon/closuresToClass.ml
  56. 5 5
      src/codegen/gencommon/dynamicFieldAccess.ml
  57. 0 1
      src/codegen/gencommon/dynamicOperators.ml
  58. 2 3
      src/codegen/gencommon/enumToClass.ml
  59. 0 1
      src/codegen/gencommon/enumToClass2.ml
  60. 18 6
      src/codegen/gencommon/expressionUnwrap.ml
  61. 1 1
      src/codegen/gencommon/filterClosures.ml
  62. 1 2
      src/codegen/gencommon/fixOverrides.ml
  63. 14 12
      src/codegen/gencommon/gencommon.ml
  64. 0 1
      src/codegen/gencommon/initFunction.ml
  65. 9 11
      src/codegen/gencommon/overloadingConstructor.ml
  66. 18 16
      src/codegen/gencommon/realTypeParams.ml
  67. 32 26
      src/codegen/gencommon/reflectionCFs.ml
  68. 4 10
      src/codegen/gencommon/renameTypeParameters.ml
  69. 15 10
      src/codegen/gencommon/switchToIf.ml
  70. 6 2
      src/codegen/gencommon/unnecessaryCastsRemoval.ml
  71. 16 9
      src/codegen/gencommon/unreachableCodeEliminationSynf.ml
  72. 37 35
      src/codegen/java.ml
  73. 69 33
      src/codegen/javaModern.ml
  74. 4 13
      src/codegen/overloads.ml
  75. 21 17
      src/codegen/swfLoader.ml
  76. 26 13
      src/compiler/args.ml
  77. 28 10
      src/compiler/compilationContext.ml
  78. 153 96
      src/compiler/compiler.ml
  79. 18 12
      src/compiler/displayOutput.ml
  80. 20 18
      src/compiler/displayProcessing.ml
  81. 11 9
      src/compiler/generate.ml
  82. 14 3
      src/compiler/helper.ml
  83. 401 0
      src/compiler/messageReporting.ml
  84. 18 20
      src/compiler/retyper.ml
  85. 91 413
      src/compiler/server.ml
  86. 7 3
      src/compiler/serverCompilationContext.ml
  87. 2 1
      src/compiler/serverConfig.ml
  88. 7 1
      src/compiler/serverMessage.ml
  89. 23 21
      src/context/abstractCast.ml
  90. 168 129
      src/context/common.ml
  91. 42 55
      src/context/display/deprecationCheck.ml
  92. 29 30
      src/context/display/diagnostics.ml
  93. 82 34
      src/context/display/diagnosticsPrinter.ml
  94. 5 231
      src/context/display/display.ml
  95. 18 15
      src/context/display/displayEmitter.ml
  96. 8 8
      src/context/display/displayException.ml
  97. 30 25
      src/context/display/displayFields.ml
  98. 125 13
      src/context/display/displayJson.ml
  99. 7 10
      src/context/display/displayTexpr.ml
  100. 6 9
      src/context/display/displayToplevel.ml

+ 137 - 105
.github/workflows/main.yml

@@ -10,13 +10,9 @@ jobs:
     env:
       ACTIONS_ALLOW_UNSECURE_COMMANDS: true
       PLATFORM: windows64
-      OPAMYES: 1
-      OPAMROOT: D:\.opam
-      CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin/
       ARCH: 64
       MINGW_ARCH: x86_64
-      CYGWIN_SETUP: https://cygwin.com/setup-x86_64.exe
-      CYG_ROOT: C:/cygwin64
+      CYG_ROOT: D:\cygwin
     steps:
       - uses: actions/checkout@main
         with:
@@ -27,12 +23,20 @@ jobs:
           echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
           rm C:\msys64\usr\bin\bash.exe
 
-      - name: Cache opam
-        id: cache-opam
-        uses: actions/[email protected]
+      - name: choco install nsis
+        uses: nick-invision/retry@v2
         with:
-          path: D:\.opam
-          key: ${{ runner.os }}64-${{ hashFiles('./opam', './libs/') }}
+          timeout_minutes: 10
+          max_attempts: 10
+          command: choco install --no-progress nsis.portable --version 3.09 -y
+
+      - name: choco install things
+        shell: pwsh
+        run: choco install --no-progress curl wget 7zip.portable -y
+
+      - name: Prepend Chocolatey path
+        shell: pwsh
+        run: Write-Host "::add-path::C:\ProgramData\chocolatey\bin"
 
       - name: Install Neko from S3
         shell: pwsh
@@ -46,47 +50,33 @@ jobs:
       - name: Print Neko version
         run: neko -version 2>&1
 
-      - name: choco install nsis
-        uses: nick-invision/retry@v1
+      - name: Setup ocaml
+        uses: ocaml/setup-ocaml@v2
         with:
-          timeout_minutes: 10
-          max_attempts: 10
-          command: choco install --no-progress nsis.portable --version 3.02 -y
-      - name: choco install things
-        shell: pwsh
-        run: choco install --no-progress curl wget 7zip.portable -y
-      - name: Prepend Chocolatey path
-        shell: pwsh
-        run: Write-Host "::add-path::C:\ProgramData\chocolatey\bin"
+          ocaml-compiler: 4.08.1
+          opam-repositories: |
+            opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+            default: https://github.com/ocaml/opam-repository.git
+          opam-local-packages: |
+            haxe.opam
 
-      - name: Install OCaml
+      - name: Install dependencies
         shell: pwsh
         run: |
           Set-PSDebug -Trace 1
-          curl.exe -fsSL -o cygwin-setup.exe --retry 3 $($env:CYGWIN_SETUP)
-          Start-Process -FilePath "cygwin-setup.exe" -ArgumentList "-B -q -R $($env:CYG_ROOT) -l C:/tmp -s $($env:CYG_MIRROR) -P default -P make -P git -P zlib-devel -P rsync -P patch -P diffutils -P curl -P unzip -P tar -P m4 -P perl -P libpcre2-devel -P mbedtls-devel -P mingw64-$($env:MINGW_ARCH)-zlib -P mingw64-$($env:MINGW_ARCH)-gcc-core -P mingw64-$($env:MINGW_ARCH)-pcre2" -Wait -RedirectStandardOutput cygwin-setup-out.txt
-          Get-Content cygwin-setup-out.txt
-          curl.exe -fsSL -o "opam.tar.xz" --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.2/opam$($env:ARCH).tar.xz
           curl.exe -fsSL -o "libmbedtls.tar.xz" --retry 3 https://github.com/Simn/mingw64-mbedtls/releases/download/2.16.3/mingw64-$($env:MINGW_ARCH)-mbedtls-2.16.3-1.tar.xz
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'curl -L https://cpanmin.us | perl - App::cpanminus')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm IPC::System::Simple module')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm String::ShellQuote')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'echo "$OLDPWD"')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -C / -xvf libmbedtls.tar.xz')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -xf opam.tar.xz')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && bash opam${ARCH}/install.sh')
 
       - name: Install OCaml libraries
-        if: steps.cache-opam.outputs.cache-hit != 'true'
         shell: pwsh
         run: |
           Set-PSDebug -Trace 1
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam init mingw "https://github.com/fdopen/opam-repository-mingw.git#opam2" --comp 4.07.0+mingw${ARCH}c --switch 4.07.0+mingw${ARCH}c --auto-setup --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam update --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam pin add haxe . --kind=path --no-action --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam install haxe --deps-only --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam list')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'ocamlopt -v')
+          opam install haxe --deps-only
+          opam list
 
       - name: Expose mingw dll files
         shell: pwsh
@@ -116,8 +106,15 @@ jobs:
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && cygcheck ./haxelib.exe')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && ls ./out')
 
+      - name: Check artifact
+        shell: bash
+        run: |
+          ls out
+          # Output should contain binaries zip, installer zip and nupkg
+          [ $(ls -1 out | wc -l) -eq "3" ]
+
       - name: Upload artifact
-        uses: actions/[email protected]
+        uses: actions/upload-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
           path: out
@@ -128,13 +125,9 @@ jobs:
     env:
       ACTIONS_ALLOW_UNSECURE_COMMANDS: true
       PLATFORM: windows
-      OPAMYES: 1
-      OPAMROOT: D:\.opam
-      CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin-archive/20221123
       ARCH: 32
       MINGW_ARCH: i686
-      CYGWIN_SETUP: https://cygwin.com/setup-x86.exe
-      CYG_ROOT: C:/cygwin
+      CYG_ROOT: D:\cygwin
     steps:
       - uses: actions/checkout@main
         with:
@@ -145,12 +138,20 @@ jobs:
           echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
           rm C:\msys64\usr\bin\bash.exe
 
-      - name: Cache opam
-        id: cache-opam
-        uses: actions/[email protected]
+      - name: choco install nsis
+        uses: nick-invision/retry@v2
         with:
-          path: D:\.opam
-          key: ${{ runner.os }}32-${{ hashFiles('./opam', './libs/') }}
+          timeout_minutes: 10
+          max_attempts: 10
+          command: choco install --no-progress nsis.portable --version 3.09 -y
+
+      - name: choco install things
+        shell: pwsh
+        run: choco install --no-progress curl wget 7zip.portable -y
+
+      - name: Prepend Chocolatey path
+        shell: pwsh
+        run: Write-Host "::add-path::C:\ProgramData\chocolatey\bin"
 
       - name: Install Neko from S3
         shell: pwsh
@@ -164,48 +165,52 @@ jobs:
       - name: Print Neko version
         run: neko -version 2>&1
 
-      - name: choco install nsis
-        uses: nick-invision/retry@v1
+      - name: Setup ocaml
+        id: ocaml
+        continue-on-error: true
+        uses: kLabz/setup-ocaml@win32
         with:
-          timeout_minutes: 10
-          max_attempts: 10
-          command: choco install --no-progress nsis.portable --version 3.02 -y
-      - name: choco install things
-        shell: pwsh
-        run: choco install --no-progress curl wget 7zip.portable -y
-      - name: Prepend Chocolatey path
-        shell: pwsh
-        run: Write-Host "::add-path::C:\ProgramData\chocolatey\bin"
+          ocaml-compiler: 4.08.1
+          opam-depext: false
+          opam-repositories: |
+            opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+            default: https://github.com/ocaml/opam-repository.git
+          opam-local-packages: |
+            haxe.opam
+          cache-prefix: w32-v1
+
+      # TODO make it work on first try
+      # (when cygwin cache doesn't exist, ocaml install fails with a curl error)
+      - name: Setup ocaml (second chance)
+        if: steps.ocaml.outcome == 'failure'
+        uses: kLabz/setup-ocaml@win32
+        with:
+          ocaml-compiler: 4.08.1
+          opam-depext: false
+          opam-repositories: |
+            opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+            default: https://github.com/ocaml/opam-repository.git
+          opam-local-packages: |
+            haxe.opam
+          cache-prefix: w32-v1
 
-      - name: Install OCaml
+      - name: Install dependencies
         shell: pwsh
         run: |
           Set-PSDebug -Trace 1
-          curl.exe -fsSL -o cygwin-setup.exe --retry 3 $($env:CYGWIN_SETUP)
-          Start-Process -FilePath "cygwin-setup.exe" -ArgumentList "-B -q -R $($env:CYG_ROOT) -l C:/tmp -s $($env:CYG_MIRROR) -P default -P make -P git -P zlib-devel -P rsync -P patch -P diffutils -P curl -P unzip -P tar -P m4 -P perl -P libpcre2-devel -P mbedtls-devel -P mingw64-$($env:MINGW_ARCH)-zlib -P mingw64-$($env:MINGW_ARCH)-gcc-core -P mingw64-$($env:MINGW_ARCH)-pcre2 --allow-unsupported-windows" -Wait -RedirectStandardOutput cygwin-setup-out.txt
-          Get-Content cygwin-setup-out.txt
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('--norc', '--noprofile', '/etc/postinstall/ca-certificates.sh')
-          curl.exe -fsSL -o "opam.tar.xz" --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.2/opam$($env:ARCH).tar.xz
           curl.exe -fsSL -o "libmbedtls.tar.xz" --retry 3 https://github.com/Simn/mingw64-mbedtls/releases/download/2.16.3/mingw64-$($env:MINGW_ARCH)-mbedtls-2.16.3-1.tar.xz
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'curl -L https://cpanmin.us | perl - App::cpanminus')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm IPC::System::Simple module')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm String::ShellQuote')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'echo "$OLDPWD"')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -C / -xvf libmbedtls.tar.xz')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -xf opam.tar.xz')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && bash opam${ARCH}/install.sh')
 
       - name: Install OCaml libraries
-        if: steps.cache-opam.outputs.cache-hit != 'true'
         shell: pwsh
         run: |
           Set-PSDebug -Trace 1
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam init mingw "https://github.com/fdopen/opam-repository-mingw.git#opam2" --comp 4.07.0+mingw${ARCH}c --switch 4.07.0+mingw${ARCH}c --auto-setup --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam update --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam pin add haxe . --kind=path --no-action --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam install haxe --deps-only --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam list')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'ocamlopt -v')
+          opam install haxe --deps-only
+          opam list
 
       - name: Expose mingw dll files
         shell: pwsh
@@ -235,18 +240,29 @@ jobs:
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && cygcheck ./haxelib.exe')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && ls ./out')
 
+      - name: Check artifact
+        shell: bash
+        run: |
+          ls out
+          # Output should contain binaries zip, installer zip and nupkg
+          [ $(ls -1 out | wc -l) -eq "3" ]
+
       - name: Upload artifact
-        uses: actions/[email protected]
+        uses: actions/upload-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
           path: out
 
 
   linux-build:
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     env:
       PLATFORM: linux64
       OPAMYES: 1
+    strategy:
+      fail-fast: false
+      matrix:
+        ocaml: ["4.08.1", "5.0.0"]
     steps:
       - uses: actions/checkout@main
         with:
@@ -257,7 +273,7 @@ jobs:
         uses: actions/[email protected]
         with:
           path: ~/.opam/
-          key: ${{ runner.os }}-${{ hashFiles('./opam', './libs/') }}-1
+          key: ${{ runner.os }}-${{ matrix.ocaml }}-${{ hashFiles('./haxe.opam', './libs/') }}
 
       - name: Install Neko from S3
         run: |
@@ -291,6 +307,7 @@ jobs:
           set -ex
           opam init # --disable-sandboxing
           opam update
+          opam switch create ${{ matrix.ocaml }}
           opam pin add haxe . --no-action
           opam install haxe --deps-only --assume-depexts
           opam list
@@ -315,9 +332,10 @@ jobs:
       - name: Extract branch name
         id: extract_branch
         shell: bash
-        run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
+        run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
 
       - name: Build xmldoc
+        if: matrix.ocaml == '4.08.1'
         run: |
           set -ex
           make -s xmldoc
@@ -329,20 +347,21 @@ jobs:
           EOL
 
       - name: Upload artifact
-        uses: actions/upload-artifact@v1.0.0
+        uses: actions/upload-artifact@v3
         with:
-          name: linuxBinaries
+          name: linuxBinaries${{ (matrix.ocaml == '5.0.0' && '_ocaml5') || '' }}
           path: out
 
       - name: Upload xmldoc artifact
-        uses: actions/[email protected]
+        uses: actions/upload-artifact@v3
+        if: matrix.ocaml == '4.08.1'
         with:
           name: xmldoc
           path: extra/doc
 
   linux-test:
     needs: linux-build
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     env:
       PLATFORM: linux64
       TEST: ${{matrix.target}}
@@ -351,6 +370,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
+        ocaml: ["4.08.1", "5.0.0"]
         target: [macro, js, hl, cpp, 'java,jvm', cs, php, python, lua, flash, neko]
         include:
           - target: hl
@@ -360,14 +380,15 @@ jobs:
           - target: lua
             APT_PACKAGES: ncurses-dev
           - target: flash
-            APT_PACKAGES: libglib2.0-0 libfreetype6 xvfb
+            APT_PACKAGES: libglib2.0-0 libgtk2.0-0 libfreetype6 xvfb
     steps:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
-          name: linuxBinaries
+          name: linuxBinaries${{ (matrix.ocaml == '5.0.0' && '_ocaml5') || '' }}
+          path: linuxBinaries
 
       - name: Install Neko from S3
         run: |
@@ -425,7 +446,7 @@ jobs:
 
   test-docgen:
     needs: linux-build
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     env:
       PLATFORM: linux64
       HXCPP_COMPILE_CACHE: ~/hxcache
@@ -434,12 +455,13 @@ jobs:
         with:
           submodules: recursive
 
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: linuxBinaries
+          path: linuxBinaries
 
       - name: Download xmldoc artifact
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: xmldoc
           path: xmldoc
@@ -501,14 +523,14 @@ jobs:
         working-directory: ${{github.workspace}}/tests/docgen
 
   linux-arm64:
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     permissions:
       packages: write
     env:
       FORCE_COLOR: 1
     steps:
       - name: Login to GitHub Container Registry
-        uses: docker/login-action@v1
+        uses: docker/login-action@v2
         with:
           registry: ghcr.io
           username: ${{ github.actor }}
@@ -519,7 +541,7 @@ jobs:
 
       - name: Set up QEMU
         id: qemu
-        uses: docker/setup-qemu-action@v1
+        uses: docker/setup-qemu-action@v2
         with:
             image: tonistiigi/binfmt:latest
             platforms: all
@@ -551,7 +573,7 @@ jobs:
           EARTHLY_REMOTE_CACHE: "ghcr.io/${{env.CONTAINER_REG}}_cache:build-${{env.CONTAINER_TAG}}-arm64"
 
       - name: Upload artifact
-        uses: actions/upload-artifact@v1.0.0
+        uses: actions/upload-artifact@v3
         with:
           name: linuxArm64Binaries
           path: out/linux/arm64
@@ -572,7 +594,7 @@ jobs:
         uses: actions/[email protected]
         with:
           path: ~/.opam/
-          key: ${{ runner.os }}-${{ hashFiles('./opam', './libs/') }}-1
+          key: ${{ runner.os }}-${{ hashFiles('./haxe.opam', './libs/') }}
 
       - name: Install Neko from S3
         run: |
@@ -594,8 +616,8 @@ jobs:
       - name: Install dependencies
         env:
           # For compatibility with macOS 10.13
-          ZLIB_VERSION: 1.2.13
-          MBEDTLS_VERSION: 2.25.0
+          ZLIB_VERSION: 1.3
+          MBEDTLS_VERSION: 2.28.5
           PCRE2_VERSION: 10.42
         run: |
           set -ex
@@ -625,14 +647,13 @@ jobs:
           make && make install
           cd ..
 
-
       - name: Install OCaml libraries
         if: steps.cache-opam.outputs.cache-hit != 'true'
         run: |
           set -ex
           opam init # --disable-sandboxing
           opam update
-          opam switch create 4.07.1
+          opam switch create 4.08.1
           eval $(opam env)
           opam env
           opam pin add ctypes 0.17.1 --yes
@@ -657,7 +678,7 @@ jobs:
           otool -L ./haxelib
 
       - name: Upload artifact
-        uses: actions/upload-artifact@v1.0.0
+        uses: actions/upload-artifact@v3
         with:
           name: macBinaries
           path: out
@@ -681,9 +702,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
+          path: win${{env.ARCH}}Binaries
 
       - name: Install Neko from S3
         shell: pwsh
@@ -697,6 +719,10 @@ jobs:
       - name: Print Neko version
         run: neko -version 2>&1
 
+      - uses: actions/setup-node@v3
+        with:
+          node-version: 18.17.1
+
       # - name: Quick test
       #   shell: pwsh
       #   run: |
@@ -773,9 +799,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
+          path: win${{env.ARCH}}Binaries
 
       - name: Install Neko from S3
         shell: pwsh
@@ -789,6 +816,10 @@ jobs:
       - name: Print Neko version
         run: neko -version 2>&1
 
+      - uses: actions/setup-node@v3
+        with:
+          node-version: 18.17.1
+
       # - name: Quick test
       #   shell: pwsh
       #   run: |
@@ -865,9 +896,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: macBinaries
+          path: macBinaries
 
       - name: Install Neko from S3
         run: |
@@ -923,7 +955,7 @@ jobs:
   deploy:
     if: success() && github.repository_owner == 'HaxeFoundation' && github.event_name != 'pull_request'
     needs: [linux-test, linux-arm64, mac-test, windows-test, windows64-test]
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     steps:
       # this is only needed for to get `COMMIT_DATE`...
       # maybe https://github.community/t/expose-commit-timestamp-in-the-github-context-data/16460/3
@@ -932,7 +964,7 @@ jobs:
         uses: actions/checkout@main
 
       - name: Download build artifacts
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
 
       - name: Install awscli
         run: |
@@ -944,7 +976,7 @@ jobs:
       - name: Extract branch name
         id: extract_branch
         shell: bash
-        run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
+        run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
 
       - name: Upload binaries
         shell: bash
@@ -999,7 +1031,7 @@ jobs:
   deploy_apidoc:
     if: success() && github.repository_owner == 'HaxeFoundation' && github.event_name != 'pull_request'
     needs: [linux-test, linux-arm64, mac-test, windows-test, windows64-test]
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     steps:
       - name: Install dependencies
         run: |
@@ -1007,7 +1039,7 @@ jobs:
           sudo apt-get install -qqy libc6
 
       - name: Download Haxe
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: linuxBinaries
           path: linuxBinaries
@@ -1023,7 +1055,7 @@ jobs:
           sudo ln -s `pwd`/linuxBinaries/std /usr/local/share/haxe/std
 
       - name: Download xmldoc artifact
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: xmldoc
           path: xmldoc

+ 4 - 0
.vscode/schemas/define.schema.json

@@ -61,6 +61,10 @@
 			"reserved": {
 				"type": "boolean",
 				"markdownDescription": "Reserved defines may not be defined from the command line."
+			},
+			"deprecated": {
+				"type": "string",
+				"markdownDescription": "Reason for the define to be deprecated."
 			}
 		},
 		"required": [

+ 4 - 1
Earthfile

@@ -91,8 +91,11 @@ devcontainer:
     RUN git config --global codespaces-theme.hide-status 1
 
     # Install OCaml libraries
-    COPY opam .
+    COPY haxe.opam .
     RUN opam init --disable-sandboxing
+    RUN opam switch create 4.08.1
+    RUN eval $(opam env)
+    RUN opam env
     RUN opam install . --yes --deps-only --no-depexts
     RUN opam list
     RUN ocamlopt -v

+ 9 - 4
Makefile

@@ -59,6 +59,10 @@ PACKAGE_FILE_NAME=haxe_$(COMMIT_DATE)_$(COMMIT_SHA)
 HAXE_VERSION=$(shell $(CURDIR)/$(HAXE_OUTPUT) -version 2>&1 | awk '{print $$1;}')
 HAXE_VERSION_SHORT=$(shell echo "$(HAXE_VERSION)" | grep -oE "^[0-9]+\.[0-9]+\.[0-9]+")
 
+NEKO_VERSION=2.3.0
+NEKO_MAJOR_VERSION=$(shell echo "$(NEKO_VERSION)" | grep -oE "^[0-9]+")
+NEKO_VERSION_TAG=v$(shell echo "$(NEKO_VERSION)" | sed "s/\./-/g")
+
 ifneq ($(STATICLINK),0)
 	LIB_PARAMS= -cclib '-Wl,-Bstatic -lpcre2-8 -lz -lmbedtls -lmbedx509 -lmbedcrypto -Wl,-Bdynamic '
 else
@@ -165,7 +169,7 @@ $(INSTALLER_TMP_DIR):
 	mkdir -p $(INSTALLER_TMP_DIR)
 
 $(INSTALLER_TMP_DIR)/neko-osx64.tar.gz: $(INSTALLER_TMP_DIR)
-	wget -nv https://github.com/HaxeFoundation/neko/releases/download/v2-3-0/neko-2.3.0-osx64.tar.gz -O installer/neko-osx64.tar.gz
+	wget -nv https://github.com/HaxeFoundation/neko/releases/download/$(NEKO_VERSION_TAG)/neko-$(NEKO_VERSION)-osx64.tar.gz -O installer/neko-osx64.tar.gz
 
 # Installer
 
@@ -173,7 +177,6 @@ package_installer_mac: $(INSTALLER_TMP_DIR)/neko-osx64.tar.gz package_unix
 	$(eval OUTFILE := $(shell pwd)/$(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_installer.tar.gz)
 	$(eval PACKFILE := $(shell pwd)/$(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_bin.tar.gz)
 	$(eval VERSION := $(shell $(CURDIR)/$(HAXE_OUTPUT) -version 2>&1))
-	$(eval NEKOVER := $(shell neko -version 2>&1))
 	bash -c "rm -rf $(INSTALLER_TMP_DIR)/{resources,pkg,tgz,haxe.tar.gz}"
 	mkdir $(INSTALLER_TMP_DIR)/resources
 	# neko - unpack to change the dir name
@@ -186,6 +189,8 @@ package_installer_mac: $(INSTALLER_TMP_DIR)/neko-osx64.tar.gz package_unix
 	cd $(INSTALLER_TMP_DIR)/resources && tar -zcvf haxe.tar.gz haxe
 	# scripts
 	cp -rf extra/mac-installer/* $(INSTALLER_TMP_DIR)/resources
+	sed -i '' 's/%%NEKO_VERSION%%/$(NEKO_VERSION)/g' $(INSTALLER_TMP_DIR)/resources/scripts/neko-postinstall.sh
+	sed -i '' 's/%%NEKO_MAJOR_VERSION%%/$(NEKO_MAJOR_VERSION)/g' $(INSTALLER_TMP_DIR)/resources/scripts/neko-postinstall.sh
 	cd $(INSTALLER_TMP_DIR)/resources && tar -zcvf scripts.tar.gz scripts
 	# installer structure
 	mkdir -p $(INSTALLER_TMP_DIR)/pkg
@@ -201,12 +206,12 @@ package_installer_mac: $(INSTALLER_TMP_DIR)/neko-osx64.tar.gz package_unix
 	sed -i '' 's/%%VERSION%%/$(VERSION)/g' PackageInfo ;\
 	sed -i '' 's/%%VERSTRING%%/$(VERSION)/g' PackageInfo ;\
 	sed -i '' 's/%%VERLONG%%/$(VERSION)/g' PackageInfo ;\
-	sed -i '' 's/%%NEKOVER%%/$(NEKOVER)/g' PackageInfo ;\
+	sed -i '' 's/%%NEKOVER%%/$(NEKO_VERSION)/g' PackageInfo ;\
 	cd .. ;\
 	sed -i '' 's/%%VERSION%%/$(VERSION)/g' Distribution ;\
 	sed -i '' 's/%%VERSTRING%%/$(VERSION)/g' Distribution ;\
 	sed -i '' 's/%%VERLONG%%/$(VERSION)/g' Distribution ;\
-	sed -i '' 's/%%NEKOVER%%/$(NEKOVER)/g' Distribution ;\
+	sed -i '' 's/%%NEKOVER%%/$(NEKO_VERSION)/g' Distribution ;\
 	sed -i '' 's/%%INSTKB%%/$$INSTKBH/g' Distribution"
 	# repackage
 	cd $(INSTALLER_TMP_DIR)/pkg; xar --compression none -cf ../$(PACKAGE_FILE_NAME).pkg *

+ 5 - 2
Makefile.win

@@ -75,13 +75,15 @@ package_choco:
 	mkdir -p OUTPUT
 	7z x -y out/$(PACKAGE_FILE_NAME)_bin.zip -oout > log.txt || type log.txt
 	mv out/$(PACKAGE_FILE_NAME) out/choco
-	sed -e 's/@SNAPSHOT_VERSION@/$(HAXE_VERSION_SHORT)-SNAP$(COMMIT_DATE)/g' extra/choco/haxe.nuspec > out/choco/haxe.nuspec
+	cp extra/choco/haxe.nuspec out/choco/haxe.nuspec
+	sed -i 's/@SNAPSHOT_VERSION@/$(HAXE_VERSION_SHORT)-SNAP$(COMMIT_DATE)/g' out/choco/haxe.nuspec
+	sed -i 's/@NEKO_VERSION@/$(NEKO_VERSION)/g' out/choco/haxe.nuspec
 	cd out/choco && choco pack
 	mv out/choco/haxe.*.nupkg out
 	rm -rf out/choco
 
 $(INSTALLER_TMP_DIR)/neko-win.zip: $(INSTALLER_TMP_DIR)
-	wget -nv https://github.com/HaxeFoundation/neko/releases/download/v2-3-0/neko-2.3.0-win$(NEKO_ARCH_STR).zip -O installer/neko-win.zip
+	curl -L https://github.com/HaxeFoundation/neko/releases/download/$(NEKO_VERSION_TAG)/neko-$(NEKO_VERSION)-win$(NEKO_ARCH_STR).zip -o installer/neko-win.zip
 
 package_installer_win: $(INSTALLER_TMP_DIR)/neko-win.zip package_win
 	$(eval OUTFILE := $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_installer.zip)
@@ -104,6 +106,7 @@ package_installer_win: $(INSTALLER_TMP_DIR)/neko-win.zip package_win
 	sed -i "s/%%VERSION%%/$(HAXE_VERSION_SHORT)/g" $(INSTALLER_TMP_DIR)/installer.nsi
 	sed -i "s/%%VERSTRING%%/$(HAXE_VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi
 	sed -i "s/%%VERLONG%%/$(HAXE_VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi
+	sed -i "s/%%NEKO_VERSION%%/$(NEKO_VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi
 	cd $(INSTALLER_TMP_DIR) && makensis installer.nsi
 	7z a -r -tzip $(OUTFILE) $(INSTALLER_TMP_DIR)/*.exe
 	dir $(PACKAGE_OUT_DIR)

+ 2 - 1
dune

@@ -1 +1,2 @@
-(data_only_dirs extra lib std tests)
+(dirs :standard \ tests std extra)
+(data_only_dirs lib)

+ 1 - 1
extra/BUILDING.md

@@ -36,7 +36,7 @@ You need to install some native libraries as well as some OCaml libraries.
 To install the native libraries, use the appropriate system package manager.
 
  * Mac OS X
-    * Use [Homebrew](https://brew.sh/), `brew install zlib pcre2`.
+    * Use [Homebrew](https://brew.sh/), `brew install zlib pcre2 mbedtls@2`.
  * Debian / Ubuntu
     * `sudo apt install libpcre2-dev zlib1g-dev libmbedtls-dev`.
  * Windows (Cygwin)

+ 180 - 5
extra/CHANGES.txt

@@ -1,9 +1,184 @@
-2022-xx-xx 4.3.0
+2023-09-17 4.3.3
 
 	General improvements:
 
+	all : improve extra field error range (#11335)
+	all : better error messages for --connect
+	hl : improve error message when hl_version is missing (#11086)
+	hl/c : compiler now adds hlc define when targeting hl/c (#11382)
+	macro : update macro API restriction warnings when using -D haxe-next (#11377)
+
+	Bugfixes:
+
+	all : handle non existing files for positions in pretty errors (#11364)
+	all : metadata support for local static vars
+	all : catch trailing invalid syntax in string interpolation (#10287)
+	eval : fix Array.resize retaining values (#11317)
+	eval/hl : fix catching haxe.ValueException (#11321)
+	hl : make genhl respect Meta.NoExpr (#11257)
+	hl : don't add bindings for non existing methods
+	hl/c : add missing I64 mod support
+	hl/c : rework reserved keywords (#11293, #11378)
+	hl/c : fix Int64 unsigned right shift overflow (#11382)
+	java/cs: fix stack overflow from closures constraints (#11350)
+	js : DOMElement insertAdjacentElement should not be pure (#11333)
+	macro : catch trailing invalid syntax in Context.parseInlineString (#11368)
+	macro : fix TDAbstract without flags in haxe.macro.Printer
+
+2023-09-01 4.3.2
+
+	General improvements:
+
+	all : do not raise error on no-op reification outside macro
+
+	Bugfixes:
+
+	all : don't infer Null<?> if it already is Null<?> (#11286)
+	all : fix ?? inference and precedence (#11252)
+	all : bring back forced inline (#11217)
+	all : allow non constant "inline" var init with -D no-inline (#11192)
+	all : improve @:enum abstract deprecation warning handling (#11302)
+	all : fix some stack overflow with pretty errors
+	display : fix go to definition with final (#11173)
+	display : fix completion requests with @:forwardStatics (#11294)
+	eval : fix MainLoop.add not repeating (#11202)
+	hl/eval/neko : fix exception stack when wrapping native exceptions (#11249)
+	macro : map `this` when restoring typed expressions (#11212)
+	macro : safe navigation fix for ExprTools.map (#11204)
+	macro : safe navigation fix for haxe.macro.Printer (#11206)
+	macro : macro generated EVars position fixes (#11163)
+	macro : fix abstract casts for local statics (#11301)
+	macro : add flags to TDAbstract to be able to construct enum abstracts (#11230)
+	nullsafety : make break/continue expressions not-nullable (#11269)
+	nullsafety : handle return in assignment (#11114)
+
+2023-04-28 4.3.1
+
+	Breaking changes:
+
+	all : namespace message reporting defines (#11142)
+
+	General improvements:
+
+	all : support deprecation for defines
+
+	Bugfixes:
+
+	all : fix --times with compilation server (#11091)
+	all : fix default type parameters not respecting imports (#11161)
+	all : fix bytecode bindings issues (#11098)
+	macro : allow local statics in macro functions (#11096)
+	cpp : fix AtomicInt warnings on cppia (#11105)
+	cpp : fix deprecated implicit casts of cpp.Int64 (#10998)
+	cpp : add white space around template type syntax (#11107)
+	java : don't check native signatures on extern functions (#11131)
+	lua : remove non existent luautf8 charCodeAt extern (#11097)
+
+2023-04-06 4.3.0
+
+	New features:
+
+	all : support defaults for type parameters (#10518)
+	all : support @:op(a()) on abstracts (#10119)
+	all : support abstract keyword to reference the abstract (#10513)
+	all : support static var at expression-level (#10555)
+	all : support ?. safe navigation operator (#10561)
+	all : added ?? null coalescing operator (#10428)
+	all : add -w compiler option to configure warnings (#10612)
+	all : added new error reporting modes (#10863)
+	all : support custom metadata and defines (#10858)
+
+	General improvements:
+
+	all : made various optimizations in the analyzer
+	all : made various improvements to diagnostics
+	all : made various improvements to null-safety
 	all : optimize `.bind` for instance methods (#10737)
-	lua : add lua-standalone global compiler flag (#10979)
+	all : improved various parser error messages
+	all : improved compilation server performance
+	all : improved code generation for try/catch (#10519)
+	all : infer property accessor type from the property (#10569)
+	all : improved inference of local functions typed against abstracts (#10336)
+	all : improved completion on module-level fields
+	all : improved handling of native libraries on the compilation server
+	all : improved performance when generating locals (#10648)
+	all : made Std.parseInt more consistent across targets (#10664)
+	all : infer null literals as Null<?> (#7736)
+	all : made field access errors more consistent (#10896)
+	all : consistently allow trailing commas (#11009)
+	all : migrated all relevant targets to PCRE2 (#10491)
+	all : made analyzer reconstruct do-while loops (#7979)
+	all : improved restrictions on init macros (#11043)
+	all : improved positions of @:structInit fields (#9318)
+	macro : support map literals in Context.makeExpr (#10259)
+	macro : added haxe.macro.Compiler.getConfiguration() (#10871)
+	macro : added withImports and withOption to haxe.macro.Context
+	macro : added getMacroStack and onAfterInitMacros to haxe.macro.Context (#11043)
+	macro : added haxe.macro.Context.makeMonomorph (#10728)
+	eval : added dictionary mode to objects, increasing performance in some cases (#10284)
+	eval : fixed Sys.exit handling messing up the compilation server (#10642)
+	eval : added -D eval-print-depth and -D eval-pretty-print (#10952, #10963)
+	cpp : supported type parameters on extern classes (#10415)
+	cpp : haxe.Int64 improvements (#9935)
+	cpp : non-blocking process exit code reading (#10321)
+	js : improved type names for debugger (#10894)
+	lua : added SSL implementation (#10593)
+	lua : fixed String API when -D no-inline was in place (#11057)
+	lua : non-zero exit code in case of uncaught exception (#11082)
+	java : deal with default implementations when loading extern libraries (#10466)
+	jvm : improved closure naming (#10571)
+	jvm : supported --jvm dir (#10614)
+	jvm : added some missing TShort and TFloat handling (#10722)
+	jvm : added experimental support for functional interfaces (#11019)
+	php : added and fixed several extern functions
+
+	Standard Library:
+
+	all : added atomic operations to several targets (#10610)
+	all : added Vector.fill (#10687)
+	sys : added sys.thread.Condition and Semaphore (#10503)
+	sys : added Http.getResponseHeaderValues to deal with multiple values of same key (#10812)
+	sys : make Sys.environment consistent between targets (#10460)
+	sys : consistent way to unset environment variables with Sys.putEnv (#10402)
+
+	Bugfixes:
+
+	all : properly disallowed macro reification in invalid places (#10883)
+	all : fixed behavior when extending abstract classes with final fields (#10139)
+	all : addressed some issues with constructor inlining (#10304)
+	all : fixed pattern matcher bug related to null-guards (#10291)
+	all : fixed weird parser behavior on first offset in files (#10322)
+	all : fixed various issues related to the final modifier
+	all : fixed various issues related to overload handling
+	all : fixed precedence of => vs. ?: (#10455)
+	all : made error positions in structure declarations more accurate (#9584)
+	all : brought back proper check when accessing super fields (#10521)
+	all : fixed @:publicFields on abstracts (#10541)
+	all : inherited some metadata to @:generic implementation classes (#10557)
+	all : fixed various problems in EventLoop and MainLoop
+	all : fixed infinite recursion from invalid inheritance (#10245)
+	all : fixed strange interaction between static extensions and macro functions (#10587)
+	all : fixed problems with @:generic on the compilation server (#10635)
+	all : fixed Context.onTypeNotFound being called multiple times for the same thing (#10678)
+	all : fixed type parameter problem involving abstract classes and interfaces (#10748)
+	all : fixed #if (a != b) yielding true for nonexistent values (#10868)
+	all : fixed interaction between @:generic and abstract class (#10735)
+	all : fixed @:using loading types too eagerly (#10107)
+	all : fixed parser ignoring subsequent documentation comments (#10171)
+	all : fixed parser function messing up unrelated file state in some cases (#10763)
+	all : unified Map printing to always use [] (#9260)
+	cpp : fixed problem with cpp.Pointer being used in enum arguments (#10831)
+	macro : improved handling of macro this expressions (#10793)
+	eval : fixed bit shift operations > 31 (#10752)
+	eval : fixed Bytes.toString causing an internal exception (#10623)
+	jvm : fixed @:native processing (#10280)
+	jvm : fixed Type.getEnumConstructs on native enums (#10508)
+	jvm : fixed @:volatile being ignored (#10594)
+	jvm : fixed some hashing issue when pattern matching on emojis (#10720)
+	jvm : fixed stack handling on return return (#10743)
+	hl : fixed various code generation problems
+	python : fixed SslSocket for newer python versions (#8401)
+	python : fixed syntax issue related to Vector (#11060)
 
 2021-03-06 4.2.5:
 
@@ -941,7 +1116,7 @@
 	Bugfixes:
 
 	php7: fix Reflect.field() for strings (#6276)
-	php7: fix `@:enum abstract` generation  without `-dce full` (#6175)
+	php7: fix `@:enum abstract` generation without `-dce full` (#6175)
 	php7: fix using enum constructor with arguments as a call argument (#6177)
 	php7: fix `null` property access (#6281)
 	php7: fix setting values in a map stored in another map (#6257)
@@ -987,7 +1162,7 @@
 
 	all : fixed DCE issue with interface fields (#6502)
 	cpp : fixed return typing for embedded closures (#6121)
-	php7: fixed `@:enum abstract` generation  without `-dce full` (#6175)
+	php7: fixed `@:enum abstract` generation without `-dce full` (#6175)
 	php7: fixed using enum constructor with arguments as a call argument (#6177)
 	php7: fixed accessing methods on dynamic values (#6211)
 	php7: fixed `null` property access (#6281)
@@ -1703,7 +1878,7 @@
 	all : allow to access root package with std prefix (std.Type for example)
 	all : added haxe.EnumFlags
 	sys : io.File.getChar/stdin/stdout/stderr are now in Sys class
-	cpp : Reflect.getField and Reflect.setField no longer call property functions.  Use Reflect.getProperty and Refelect.setProperty instead.
+	cpp : Reflect.getField and Reflect.setField no longer call property functions. Use Reflect.getProperty and Refelect.setProperty instead.
 	cpp : Default arguments now use Null<T> for performance increase and interface compatibility
 	cpp : Added metadata options for injecting native cpp code into headers, classes and functions
 	php : added php.Lib.mail

+ 1 - 1
extra/EnvVarUpdate.nsh

@@ -43,7 +43,7 @@
   !ifndef Un${StrFuncName}_INCLUDED
     ${Un${StrFuncName}}
   !endif
-  !define un.${StrFuncName} "${Un${StrFuncName}}"
+  !define un.${StrFuncName} '${Un${StrFuncName}}'
 !macroend
 
 !insertmacro _IncludeStrFunction StrTok

+ 37 - 38
extra/ImportAll.hx

@@ -26,7 +26,7 @@ class ImportAll {
 	static function isSysTarget() {
 		return Context.defined("neko") || Context.defined("php") || Context.defined("cpp") ||
 		       Context.defined("java") || Context.defined("python") ||
-		       Context.defined("lua") || Context.defined("hl") || Context.defined("eval"); // TODO: have to add cs here, SPOD gets in the way at the moment
+		       Context.defined("lua") || Context.defined("hl") || Context.defined("eval");
 	}
 
 	public static function run( ?pack ) {
@@ -34,9 +34,6 @@ class ImportAll {
 			pack = "";
 			haxe.macro.Compiler.define("doc_gen");
 		}
-		if (Context.defined("interp")) {
-			haxe.macro.Compiler.define("macro");
-		}
 		switch( pack ) {
 		case "php":
 			if( !Context.defined("php") ) return;
@@ -72,42 +69,44 @@ class ImportAll {
 			if (!Context.defined("neko") && !Context.defined("cpp")) return;
 		case "tools", "build-tool", "jar-tool": return;
 		}
-		for( p in Context.getClassPath() ) {
-			if( p == "/" || p == "" )
-				continue;
-			// skip if we have a classpath to haxe
-			if( pack.length == 0 && sys.FileSystem.exists(p+"std") )
-				continue;
-			var p = p + pack.split(".").join("/");
-			if( StringTools.endsWith(p,"/") )
-				p = p.substr(0,-1);
-			if( !sys.FileSystem.exists(p) || !sys.FileSystem.isDirectory(p) )
-				continue;
-			for( file in sys.FileSystem.readDirectory(p) ) {
-				if( file == ".svn" || file == "_std" )
+		Context.onAfterInitMacros(() -> {
+			for( p in Context.getClassPath() ) {
+				if( p == "/" || p == "" )
+					continue;
+				// skip if we have a classpath to haxe
+				if( pack.length == 0 && sys.FileSystem.exists(p+"std") )
 					continue;
-				var full = (pack == "") ? file : pack + "." + file;
-				if( StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0 ) {
-					var cl = full.substr(0, full.length - 3);
-					switch( cl ) {
-					case "ImportAll", "neko.db.MacroManager": continue;
-					case "haxe.TimerQueue": if( Context.defined("neko") || Context.defined("php") || Context.defined("cpp") ) continue;
-					case "Sys": if(!isSysTarget()) continue;
-					case "haxe.web.Request": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("js")) ) continue;
-					case "haxe.macro.ExampleJSGenerator","haxe.macro.Context", "haxe.macro.Compiler": if( !Context.defined("eval") ) continue;
-					case "haxe.remoting.SocketWrapper": if( !Context.defined("flash") ) continue;
-					case "haxe.remoting.SyncSocketConnection": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue;
-					case "neko.vm.Ui" | "sys.db.Sqlite" | "sys.db.Mysql" if ( Context.defined("interp") ): continue;
-					case "sys.db.Sqlite" | "sys.db.Mysql" | "cs.db.AdoNet" if ( Context.defined("cs") ): continue;
-					case "haxe.atomic.AtomicBool" if(!Context.defined("target.atomics")): continue;
-					case "haxe.atomic.AtomicInt" if(!Context.defined("target.atomics")): continue;
-					case "haxe.atomic.AtomicObject" if(!Context.defined("target.atomics") || Context.defined("js") || Context.defined("cpp")): continue;
-					}
-					Context.getModule(cl);
-				} else if( sys.FileSystem.isDirectory(p + "/" + file) )
-					run(full);
+				var p = p + pack.split(".").join("/");
+				if( StringTools.endsWith(p,"/") )
+					p = p.substr(0,-1);
+				if( !sys.FileSystem.exists(p) || !sys.FileSystem.isDirectory(p) )
+					continue;
+				for( file in sys.FileSystem.readDirectory(p) ) {
+					if( file == ".svn" || file == "_std" )
+						continue;
+					var full = (pack == "") ? file : pack + "." + file;
+					if( StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0 ) {
+						var cl = full.substr(0, full.length - 3);
+						switch( cl ) {
+						case "ImportAll", "neko.db.MacroManager": continue;
+						case "haxe.TimerQueue": if( Context.defined("neko") || Context.defined("php") || Context.defined("cpp") ) continue;
+						case "Sys": if(!isSysTarget()) continue;
+						case "haxe.web.Request": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("js")) ) continue;
+						case "haxe.macro.ExampleJSGenerator","haxe.macro.Context", "haxe.macro.Compiler": if( !Context.defined("eval") ) continue;
+						case "haxe.remoting.SocketWrapper": if( !Context.defined("flash") ) continue;
+						case "haxe.remoting.SyncSocketConnection": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue;
+						case "neko.vm.Ui" | "sys.db.Sqlite" | "sys.db.Mysql" if ( Context.defined("interp") ): continue;
+						case "sys.db.Sqlite" | "sys.db.Mysql" | "cs.db.AdoNet" if ( Context.defined("cs") ): continue;
+						case "haxe.atomic.AtomicBool" if(!Context.defined("target.atomics")): continue;
+						case "haxe.atomic.AtomicInt" if(!Context.defined("target.atomics")): continue;
+						case "haxe.atomic.AtomicObject" if(!Context.defined("target.atomics") || Context.defined("js") || Context.defined("cpp")): continue;
+						}
+						Context.getModule(cl);
+					} else if( sys.FileSystem.isDirectory(p + "/" + file) )
+						run(full);
+				}
 			}
-		}
+		});
 	}
 
 }

+ 3 - 3
extra/choco/haxe.nuspec

@@ -17,12 +17,12 @@
         <requireLicenseAcceptance>false</requireLicenseAcceptance>
         <summary>Haxe is an open source toolkit based on a modern, high level, strictly typed programming language, a cross-compiler, a complete cross-platform standard library and ways to access each platform's native capabilities.</summary>
         <description>Haxe is an open source toolkit based on a modern, high level, strictly typed programming language, a cross-compiler, a complete cross-platform standard library and ways to access each platform's native capabilities.
- 
+
 This package will install haxe and haxelib. After installation, you should run `haxelib setup %path%;`, where `%path%` is the haxelib repository folder for placing third-party libraries. The folder should be created manually before running the command.</description>
         <releaseNotes>https://github.com/HaxeFoundation/haxe/blob/master/extra/CHANGES.txt</releaseNotes>
         <tags>haxe programming development foss cross-platform</tags>
         <dependencies>
-            <dependency id="neko" version="2.1.0" />
+            <dependency id="neko" version="@NEKO_VERSION@" />
         </dependencies>
     </metadata>
-</package>
+</package>

+ 4 - 5
extra/github-actions/build-mac.yml

@@ -1,8 +1,8 @@
 - name: Install dependencies
   env:
     # For compatibility with macOS 10.13
-    ZLIB_VERSION: 1.2.13
-    MBEDTLS_VERSION: 2.25.0
+    ZLIB_VERSION: 1.3
+    MBEDTLS_VERSION: 2.28.5
     PCRE2_VERSION: 10.42
   run: |
     set -ex
@@ -32,14 +32,13 @@
     make && make install
     cd ..
 
-
 - name: Install OCaml libraries
   if: steps.cache-opam.outputs.cache-hit != 'true'
   run: |
     set -ex
     opam init # --disable-sandboxing
     opam update
-    opam switch create 4.07.1
+    opam switch create 4.08.1
     eval $(opam env)
     opam env
     opam pin add ctypes 0.17.1 --yes
@@ -64,7 +63,7 @@
     otool -L ./haxelib
 
 - name: Upload artifact
-  uses: actions/upload-artifact@v1.0.0
+  uses: actions/upload-artifact@v3
   with:
     name: macBinaries
     path: out

+ 8 - 1
extra/github-actions/build-windows.yml

@@ -26,8 +26,15 @@
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && cygcheck ./haxelib.exe')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && ls ./out')
 
+- name: Check artifact
+  shell: bash
+  run: |
+    ls out
+    # Output should contain binaries zip, installer zip and nupkg
+    [ $(ls -1 out | wc -l) -eq "3" ]
+
 - name: Upload artifact
-  uses: actions/[email protected]
+  uses: actions/upload-artifact@v3
   with:
     name: win${{env.ARCH}}Binaries
     path: out

+ 0 - 6
extra/github-actions/cache-opam.yml

@@ -1,6 +0,0 @@
-- name: Cache opam
-  id: cache-opam
-  uses: actions/[email protected]
-  with:
-    path: ~/.opam/
-    key: ${{ runner.os }}-${{ hashFiles('./opam', './libs/') }}-1

+ 4 - 2
extra/github-actions/install-nsis.yml

@@ -1,12 +1,14 @@
 - name: choco install nsis
-  uses: nick-invision/retry@v1
+  uses: nick-invision/retry@v2
   with:
     timeout_minutes: 10
     max_attempts: 10
-    command: choco install --no-progress nsis.portable --version 3.02 -y
+    command: choco install --no-progress nsis.portable --version 3.09 -y
+
 - name: choco install things
   shell: pwsh
   run: choco install --no-progress curl wget 7zip.portable -y
+
 - name: Prepend Chocolatey path
   shell: pwsh
   run: Write-Host "::add-path::C:\ProgramData\chocolatey\bin"

+ 2 - 7
extra/github-actions/install-ocaml-libs-windows.yml

@@ -1,11 +1,6 @@
 - name: Install OCaml libraries
-  if: steps.cache-opam.outputs.cache-hit != 'true'
   shell: pwsh
   run: |
     Set-PSDebug -Trace 1
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam init mingw "https://github.com/fdopen/opam-repository-mingw.git#opam2" --comp 4.07.0+mingw${ARCH}c --switch 4.07.0+mingw${ARCH}c --auto-setup --yes 2>&1')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam update --yes 2>&1')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam pin add haxe . --kind=path --no-action --yes 2>&1')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam install haxe --deps-only --yes 2>&1')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam list')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'ocamlopt -v')
+    opam install haxe --deps-only
+    opam list

+ 30 - 8
extra/github-actions/install-ocaml-windows.yml

@@ -1,17 +1,39 @@
-- name: Install OCaml
+- name: Setup ocaml
+  id: ocaml
+  continue-on-error: true
+  uses: kLabz/setup-ocaml@win32
+  with:
+    ocaml-compiler: 4.08.1
+    opam-depext: false
+    opam-repositories: |
+      opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+      default: https://github.com/ocaml/opam-repository.git
+    opam-local-packages: |
+      haxe.opam
+    cache-prefix: w32-v1
+
+# TODO make it work on first try
+# (when cygwin cache doesn't exist, ocaml install fails with a curl error)
+- name: Setup ocaml (second chance)
+  if: steps.ocaml.outcome == 'failure'
+  uses: kLabz/setup-ocaml@win32
+  with:
+    ocaml-compiler: 4.08.1
+    opam-depext: false
+    opam-repositories: |
+      opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+      default: https://github.com/ocaml/opam-repository.git
+    opam-local-packages: |
+      haxe.opam
+    cache-prefix: w32-v1
+
+- name: Install dependencies
   shell: pwsh
   run: |
     Set-PSDebug -Trace 1
-    curl.exe -fsSL -o cygwin-setup.exe --retry 3 $($env:CYGWIN_SETUP)
-    Start-Process -FilePath "cygwin-setup.exe" -ArgumentList "-B -q -R $($env:CYG_ROOT) -l C:/tmp -s $($env:CYG_MIRROR) -P default -P make -P git -P zlib-devel -P rsync -P patch -P diffutils -P curl -P unzip -P tar -P m4 -P perl -P libpcre2-devel -P mbedtls-devel -P mingw64-$($env:MINGW_ARCH)-zlib -P mingw64-$($env:MINGW_ARCH)-gcc-core -P mingw64-$($env:MINGW_ARCH)-pcre2 --allow-unsupported-windows" -Wait -RedirectStandardOutput cygwin-setup-out.txt
-    Get-Content cygwin-setup-out.txt
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('--norc', '--noprofile', '/etc/postinstall/ca-certificates.sh')
-    curl.exe -fsSL -o "opam.tar.xz" --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.2/opam$($env:ARCH).tar.xz
     curl.exe -fsSL -o "libmbedtls.tar.xz" --retry 3 https://github.com/Simn/mingw64-mbedtls/releases/download/2.16.3/mingw64-$($env:MINGW_ARCH)-mbedtls-2.16.3-1.tar.xz
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'curl -L https://cpanmin.us | perl - App::cpanminus')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm IPC::System::Simple module')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm String::ShellQuote')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'echo "$OLDPWD"')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -C / -xvf libmbedtls.tar.xz')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -xf opam.tar.xz')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && bash opam${ARCH}/install.sh')

+ 11 - 7
extra/github-actions/install-ocaml-windows64.yml

@@ -1,16 +1,20 @@
-- name: Install OCaml
+- name: Setup ocaml
+  uses: ocaml/setup-ocaml@v2
+  with:
+    ocaml-compiler: 4.08.1
+    opam-repositories: |
+      opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+      default: https://github.com/ocaml/opam-repository.git
+    opam-local-packages: |
+      haxe.opam
+
+- name: Install dependencies
   shell: pwsh
   run: |
     Set-PSDebug -Trace 1
-    curl.exe -fsSL -o cygwin-setup.exe --retry 3 $($env:CYGWIN_SETUP)
-    Start-Process -FilePath "cygwin-setup.exe" -ArgumentList "-B -q -R $($env:CYG_ROOT) -l C:/tmp -s $($env:CYG_MIRROR) -P default -P make -P git -P zlib-devel -P rsync -P patch -P diffutils -P curl -P unzip -P tar -P m4 -P perl -P libpcre2-devel -P mbedtls-devel -P mingw64-$($env:MINGW_ARCH)-zlib -P mingw64-$($env:MINGW_ARCH)-gcc-core -P mingw64-$($env:MINGW_ARCH)-pcre2" -Wait -RedirectStandardOutput cygwin-setup-out.txt
-    Get-Content cygwin-setup-out.txt
-    curl.exe -fsSL -o "opam.tar.xz" --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.2/opam$($env:ARCH).tar.xz
     curl.exe -fsSL -o "libmbedtls.tar.xz" --retry 3 https://github.com/Simn/mingw64-mbedtls/releases/download/2.16.3/mingw64-$($env:MINGW_ARCH)-mbedtls-2.16.3-1.tar.xz
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'curl -L https://cpanmin.us | perl - App::cpanminus')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm IPC::System::Simple module')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm String::ShellQuote')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'echo "$OLDPWD"')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -C / -xvf libmbedtls.tar.xz')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -xf opam.tar.xz')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && bash opam${ARCH}/install.sh')

+ 4 - 0
extra/github-actions/test-windows.yml

@@ -1,3 +1,7 @@
+- uses: actions/setup-node@v3
+  with:
+    node-version: 18.17.1
+
 # - name: Quick test
 #   shell: pwsh
 #   run: |

+ 56 - 53
extra/github-actions/workflows/main.yml

@@ -9,13 +9,9 @@ jobs:
     env:
       ACTIONS_ALLOW_UNSECURE_COMMANDS: true
       PLATFORM: windows64
-      OPAMYES: 1
-      OPAMROOT: D:\.opam
-      CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin/
       ARCH: 64
       MINGW_ARCH: x86_64
-      CYGWIN_SETUP: https://cygwin.com/setup-x86_64.exe
-      CYG_ROOT: C:/cygwin64
+      CYG_ROOT: D:\cygwin
     steps:
       - uses: actions/checkout@main
         with:
@@ -26,15 +22,8 @@ jobs:
           echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
           rm C:\msys64\usr\bin\bash.exe
 
-      - name: Cache opam
-        id: cache-opam
-        uses: actions/[email protected]
-        with:
-          path: D:\.opam
-          key: ${{ runner.os }}64-${{ hashFiles('./opam', './libs/') }}
-
-      @import install-neko-windows.yml
       @import install-nsis.yml
+      @import install-neko-windows.yml
       @import install-ocaml-windows64.yml
       @import install-ocaml-libs-windows.yml
       @import build-windows.yml
@@ -44,13 +33,9 @@ jobs:
     env:
       ACTIONS_ALLOW_UNSECURE_COMMANDS: true
       PLATFORM: windows
-      OPAMYES: 1
-      OPAMROOT: D:\.opam
-      CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin-archive/20221123
       ARCH: 32
       MINGW_ARCH: i686
-      CYGWIN_SETUP: https://cygwin.com/setup-x86.exe
-      CYG_ROOT: C:/cygwin
+      CYG_ROOT: D:\cygwin
     steps:
       - uses: actions/checkout@main
         with:
@@ -61,30 +46,33 @@ jobs:
           echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
           rm C:\msys64\usr\bin\bash.exe
 
-      - name: Cache opam
-        id: cache-opam
-        uses: actions/[email protected]
-        with:
-          path: D:\.opam
-          key: ${{ runner.os }}32-${{ hashFiles('./opam', './libs/') }}
-
-      @import install-neko-windows.yml
       @import install-nsis.yml
+      @import install-neko-windows.yml
       @import install-ocaml-windows.yml
       @import install-ocaml-libs-windows.yml
       @import build-windows.yml
 
   linux-build:
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     env:
       PLATFORM: linux64
       OPAMYES: 1
+    strategy:
+      fail-fast: false
+      matrix:
+        ocaml: ["4.08.1", "5.0.0"]
     steps:
       - uses: actions/checkout@main
         with:
           submodules: recursive
 
-      @import cache-opam.yml
+      - name: Cache opam
+        id: cache-opam
+        uses: actions/[email protected]
+        with:
+          path: ~/.opam/
+          key: ${{ runner.os }}-${{ matrix.ocaml }}-${{ hashFiles('./haxe.opam', './libs/') }}
+
       @import install-neko-unix.yml
 
       - name: Install dependencies
@@ -101,6 +89,7 @@ jobs:
           set -ex
           opam init # --disable-sandboxing
           opam update
+          opam switch create ${{ matrix.ocaml }}
           opam pin add haxe . --no-action
           opam install haxe --deps-only --assume-depexts
           opam list
@@ -125,9 +114,10 @@ jobs:
       - name: Extract branch name
         id: extract_branch
         shell: bash
-        run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
+        run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
 
       - name: Build xmldoc
+        if: matrix.ocaml == '4.08.1'
         run: |
           set -ex
           make -s xmldoc
@@ -139,20 +129,21 @@ jobs:
           EOL
 
       - name: Upload artifact
-        uses: actions/upload-artifact@v1.0.0
+        uses: actions/upload-artifact@v3
         with:
-          name: linuxBinaries
+          name: linuxBinaries${{ (matrix.ocaml == '5.0.0' && '_ocaml5') || '' }}
           path: out
 
       - name: Upload xmldoc artifact
-        uses: actions/[email protected]
+        uses: actions/upload-artifact@v3
+        if: matrix.ocaml == '4.08.1'
         with:
           name: xmldoc
           path: extra/doc
 
   linux-test:
     needs: linux-build
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     env:
       PLATFORM: linux64
       TEST: ${{matrix.target}}
@@ -161,6 +152,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
+        ocaml: ["4.08.1", "5.0.0"]
         target: [macro, js, hl, cpp, 'java,jvm', cs, php, python, lua, flash, neko]
         include:
           - target: hl
@@ -170,14 +162,15 @@ jobs:
           - target: lua
             APT_PACKAGES: ncurses-dev
           - target: flash
-            APT_PACKAGES: libglib2.0-0 libfreetype6 xvfb
+            APT_PACKAGES: libglib2.0-0 libgtk2.0-0 libfreetype6 xvfb
     steps:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
-          name: linuxBinaries
+          name: linuxBinaries${{ (matrix.ocaml == '5.0.0' && '_ocaml5') || '' }}
+          path: linuxBinaries
 
       @import install-neko-unix.yml
 
@@ -219,7 +212,7 @@ jobs:
 
   test-docgen:
     needs: linux-build
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     env:
       PLATFORM: linux64
       HXCPP_COMPILE_CACHE: ~/hxcache
@@ -228,12 +221,13 @@ jobs:
         with:
           submodules: recursive
 
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: linuxBinaries
+          path: linuxBinaries
 
       - name: Download xmldoc artifact
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: xmldoc
           path: xmldoc
@@ -279,14 +273,14 @@ jobs:
         working-directory: ${{github.workspace}}/tests/docgen
 
   linux-arm64:
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     permissions:
       packages: write
     env:
       FORCE_COLOR: 1
     steps:
       - name: Login to GitHub Container Registry
-        uses: docker/login-action@v1
+        uses: docker/login-action@v2
         with:
           registry: ghcr.io
           username: ${{ github.actor }}
@@ -297,7 +291,7 @@ jobs:
 
       - name: Set up QEMU
         id: qemu
-        uses: docker/setup-qemu-action@v1
+        uses: docker/setup-qemu-action@v2
         with:
             image: tonistiigi/binfmt:latest
             platforms: all
@@ -329,7 +323,7 @@ jobs:
           EARTHLY_REMOTE_CACHE: "ghcr.io/${{env.CONTAINER_REG}}_cache:build-${{env.CONTAINER_TAG}}-arm64"
 
       - name: Upload artifact
-        uses: actions/upload-artifact@v1.0.0
+        uses: actions/upload-artifact@v3
         with:
           name: linuxArm64Binaries
           path: out/linux/arm64
@@ -345,7 +339,13 @@ jobs:
         with:
           submodules: recursive
 
-      @import cache-opam.yml
+      - name: Cache opam
+        id: cache-opam
+        uses: actions/[email protected]
+        with:
+          path: ~/.opam/
+          key: ${{ runner.os }}-${{ hashFiles('./haxe.opam', './libs/') }}
+
       @import install-neko-unix.yml
       @import build-mac.yml
 
@@ -367,9 +367,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
+          path: win${{env.ARCH}}Binaries
 
       @import install-neko-windows.yml
       @import test-windows.yml
@@ -393,9 +394,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
+          path: win${{env.ARCH}}Binaries
 
       @import install-neko-windows.yml
       @import test-windows.yml
@@ -419,9 +421,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: macBinaries
+          path: macBinaries
 
       @import install-neko-unix.yml
       @import test-mac.yml
@@ -429,7 +432,7 @@ jobs:
   deploy:
     if: success() && github.repository_owner == 'HaxeFoundation' && github.event_name != 'pull_request'
     needs: [linux-test, linux-arm64, mac-test, windows-test, windows64-test]
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     steps:
       # this is only needed for to get `COMMIT_DATE`...
       # maybe https://github.community/t/expose-commit-timestamp-in-the-github-context-data/16460/3
@@ -438,7 +441,7 @@ jobs:
         uses: actions/checkout@main
 
       - name: Download build artifacts
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
 
       - name: Install awscli
         run: |
@@ -450,7 +453,7 @@ jobs:
       - name: Extract branch name
         id: extract_branch
         shell: bash
-        run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
+        run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
 
       - name: Upload binaries
         shell: bash
@@ -505,7 +508,7 @@ jobs:
   deploy_apidoc:
     if: success() && github.repository_owner == 'HaxeFoundation' && github.event_name != 'pull_request'
     needs: [linux-test, linux-arm64, mac-test, windows-test, windows64-test]
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-20.04
     steps:
       - name: Install dependencies
         run: |
@@ -513,7 +516,7 @@ jobs:
           sudo apt-get install -qqy libc6
 
       - name: Download Haxe
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: linuxBinaries
           path: linuxBinaries
@@ -529,7 +532,7 @@ jobs:
           sudo ln -s `pwd`/linuxBinaries/std /usr/local/share/haxe/std
 
       - name: Download xmldoc artifact
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: xmldoc
           path: xmldoc

+ 1 - 1
extra/haxelib_src

@@ -1 +1 @@
-Subproject commit 4e4b03464ae272179692edf92c2f84848901e07d
+Subproject commit 70ff6b69a5b35049d767056555c0bf7a54e8ad4e

+ 1 - 1
extra/installer.nsi

@@ -21,7 +21,7 @@
 !define VERLONG "%%VERLONG%%"
 
 ; Define Neko info
-!define NEKO_VERSION "2.3.0"
+!define NEKO_VERSION "%%NEKO_VERSION%%"
 
 ; Installer details
 VIAddVersionKey "CompanyName" "Haxe Foundation"

+ 2 - 2
extra/mac-installer/scripts/neko-postinstall.sh

@@ -15,5 +15,5 @@ ln -s /usr/local/lib/neko/nekoc /usr/local/bin/nekoc
 ln -s /usr/local/lib/neko/nekoml /usr/local/bin/nekoml
 ln -s /usr/local/lib/neko/nekotools /usr/local/bin/nekotools
 ln -s /usr/local/lib/neko/libneko.dylib /usr/local/lib/libneko.dylib
-ln -s /usr/local/lib/neko/libneko.2.dylib /usr/local/lib/libneko.2.dylib
-ln -s /usr/local/lib/neko/libneko.2.1.0.dylib /usr/local/lib/libneko.2.1.0.dylib
+ln -s /usr/local/lib/neko/libneko.%%NEKO_MAJOR_VERSION%%.dylib /usr/local/lib/libneko.%%NEKO_MAJOR_VERSION%%.dylib
+ln -s /usr/local/lib/neko/libneko.%%NEKO_VERSION%%.dylib /usr/local/lib/libneko.%%NEKO_VERSION%%.dylib

+ 15 - 11
extra/release-checklist.txt

@@ -3,28 +3,32 @@
 - Check that haxelib is working
 - Make sure to update the haxelib submodule
 - Check that the run-time haxelibs are ready for release: hxcpp, hxjava, hxcs
-- Check that the osx & windows installers has the latest neko release in "Makefile" and "Makefile.win" files
+- Check that the NEKO_VERSION variable in the "Makefile" is set to the latest Neko version
 
 # Making the release
 
 - Make sure CHANGES.txt has a proper date set!
 - Make sure `version` in globals.ml has the correct value
-- Update `version` in `./opam`
+- Make sure the copyright year in args.ml has the correct value
+- Update `version` in `haxe.opam`
 - Check if the protocolVersion in displayJson.ml has to be updated
-- Make an empty GitHub release in https://github.com/HaxeFoundation/haxe/releases (do this first because we need the tag for the builds)
-- Wait for the CI to build (check https://build.haxe.org/builds/haxe/)
-- Get https://github.com/simn/hxgithub
-- Store your GitHub personal access token in .github-token
-- Run something like this: `neko release.n -h 4.0.0-rc.1 -u -uw -ur -d haxe_2019-02-01_development_1fdd3d5.zip --dry`
-- Tell yourself that you're gonna fix `-doc` generation next time
-- Write the announcement to `./haxe-version/RELEASE.md`
-- If everything was working, run the command again without `--dry` (and probably without the `-d`)
+- Create a version tag and push it with above changes (CI needs to run on the tag)
+- Make an empty GitHub release in https://github.com/HaxeFoundation/haxe/releases
+- Wait for the CI to build (check https://build.haxe.org/builds/haxe/, look for `haxe_[date]_refs/tags`)
+- Get https://github.com/HaxeFoundation/hxgithub
+- Follow "Haxe releases" section of hxgithub README, with the equivalent of `-d haxe_2023-04-28_refs/tags/4.3.1_964c84c.tar.gz`
+	- Tell yourself that you're gonna fix `-doc` generation next time
+	- Make sure changelog isn't empty in `./haxe-version/CHANGES.md`
+	- Write the announcement to `./haxe-version/RELEASE.md`
+	- If everything was working, run the command again without `--dry`
 - Update https://github.com/HaxeFoundation/haxe.org/blob/staging/downloads/versions.json
+- Wait for staging to update, check everything related to release and merge to master
 
 # Cleanup
 
 - Remove issues with released fixes from the "Hotfix" milestone: https://github.com/HaxeFoundation/haxe/milestone/18
+- Set back the version in `globals.ml` to something appropriate for nightlies
 
 # Announcing the release
 
-- Find someone to announce the release on our various communication channels
+- Find someone to announce the release on our various communication channels

+ 7 - 5
opam → haxe.opam

@@ -1,6 +1,6 @@
 opam-version: "2.0"
 name: "haxe"
-version: "4.2.4"
+version: "4.3.0"
 synopsis: "Multi-target universal programming language"
 description: """
 Haxe is an open source toolkit based on a modern,
@@ -19,17 +19,19 @@ build: [
 install: [make "install" "INSTALL_DIR=%{prefix}%"]
 remove: [make "uninstall" "INSTALL_DIR=%{prefix}%"]
 depends: [
-  "ocaml" {>= "4.02"}
+  ("ocaml" {>= "5.0"} & ("camlp5" {build}))
+    | ("ocaml" {>= "4.08" & < "5.0"} & ("camlp5" {build & = "8.00"}))
   "ocamlfind" {build}
   "dune" {>= "1.11"}
-  "camlp5" {build & = "8.00"}
   "sedlex" {>= "2.0"}
   "xml-light"
   "extlib" {>= "1.7.8"}
-  "ptmap" {>= "2.0.0"}
   "sha"
+  "camlp-streams"
   "conf-libpcre2-8"
   "conf-zlib"
   "conf-neko"
-  "luv"
+  "luv" {>= "0.5.12"}
+  "ipaddr"
+  "terminal_size"
 ]

+ 3 - 3
libs/extc/extc.ml

@@ -110,10 +110,10 @@ let input_zip ?(bufsize=65536) ch =
 	let buf = ref "" in
 	let p = ref 0 in
 	let z = zlib_inflate_init() in
-	let rec fill_buffer() =
+	let fill_buffer() =
 		let rec loop pos len =
 			if len > 0 || pos = 0 then begin
-				let r = zlib_inflate z (Bytes.unsafe_to_string tmp_in) pos len tmp_out 0 bufsize (if pos = 0 && len = 0 then Z_FINISH else Z_SYNC_FLUSH) in
+				let r = zlib_inflate z ~src:(Bytes.unsafe_to_string tmp_in) ~spos:pos ~slen:len ~dst:tmp_out ~dpos:0 ~dlen:bufsize (if pos = 0 && len = 0 then Z_FINISH else Z_SYNC_FLUSH) in
 				Buffer.add_subbytes tmp_buf tmp_out 0 r.z_wrote;
 				loop (pos + r.z_read) (len - r.z_read);
 			end
@@ -155,7 +155,7 @@ let output_zip ?(bufsize=65536) ?(level=9) ch =
 	let tmp_out = Bytes.create bufsize in
 	let p = ref 0 in
 	let rec flush finish =
-		let r = zlib_deflate z (Bytes.unsafe_to_string out) 0 !p tmp_out 0 bufsize (if finish then Z_FINISH else Z_SYNC_FLUSH) in
+		let r = zlib_deflate z ~src:(Bytes.unsafe_to_string out) ~spos:0 ~slen:!p ~dst:tmp_out ~dpos:0 ~dlen:bufsize (if finish then Z_FINISH else Z_SYNC_FLUSH) in
 		ignore(IO.really_output ch tmp_out 0 r.z_wrote);
 		let remain = !p - r.z_read in
 		Bytes.blit out r.z_read out 0 remain;

+ 21 - 21
libs/extc/extc_stubs.c

@@ -92,7 +92,7 @@ int Zflush_val(value zflush_val) {
 		case 4: return Z_FINISH;
 		// TODO: support Z_BLOCK and Z_TREE
 		// TODO: append the received value
-		default: failwith("Error in `Zflush_val` (extc_stubs.c): Unknown zflush value");
+		default: caml_failwith("Error in `Zflush_val` (extc_stubs.c): Unknown zflush value");
 	}
 	assert(0);
 }
@@ -222,14 +222,14 @@ CAMLprim value zlib_deflate_init2(value level_val, value window_bits_val) {
 			break;
 		case Z_STREAM_ERROR:
 			// TODO: use stream->msg to get _zlib_'s text message
-			failwith("Error in `zlib_deflate_init2` (extc_stubs.c): call to `deflateInit2` failed: Z_STREAM_ERROR");
+			caml_failwith("Error in `zlib_deflate_init2` (extc_stubs.c): call to `deflateInit2` failed: Z_STREAM_ERROR");
 			break;
 		case Z_VERSION_ERROR:
 			// TODO: use stream->msg to get _zlib_'s text message
-			failwith("Error in `zlib_deflate_init2` (extc_stubs.c): call to `deflateInit2` failed: Z_VERSION_ERROR");
+			caml_failwith("Error in `zlib_deflate_init2` (extc_stubs.c): call to `deflateInit2` failed: Z_VERSION_ERROR");
 			break;
 		default:
-			failwith("Error in `zlib_deflate_init2` (extc_stubs.c): unknown return code from `deflateInit2`");
+			caml_failwith("Error in `zlib_deflate_init2` (extc_stubs.c): unknown return code from `deflateInit2`");
 	}
 	assert(0);
 }
@@ -275,7 +275,7 @@ CAMLprim value zlib_deflate(value stream_val, value src, value spos, value slen,
 	if (deflate_result == Z_OK || deflate_result == Z_STREAM_END) {
 		stream->next_in = NULL;
 		stream->next_out = NULL;
-		value zresult = alloc_small(3, 0);
+		value zresult = caml_alloc_small(3, 0);
 		// z_finish
 		Field(zresult, 0) = Val_bool(deflate_result == Z_STREAM_END);
 		// z_read
@@ -291,14 +291,14 @@ CAMLprim value zlib_deflate(value stream_val, value src, value spos, value slen,
 			break;
 		case Z_STREAM_ERROR:
 			// TODO: use stream->msg to get _zlib_'s text message
-			failwith("Error in `zlib_deflate` (extc_stubs.c): call to `deflate` failed: Z_STREAM_ERROR");
+			caml_failwith("Error in `zlib_deflate` (extc_stubs.c): call to `deflate` failed: Z_STREAM_ERROR");
 			break;
 		case Z_BUF_ERROR:
 			// TODO: use stream->msg to get _zlib_'s text message
-			failwith("Error in `zlib_deflate` (extc_stubs.c): call to `deflate` failed: Z_BUF_ERROR");
+			caml_failwith("Error in `zlib_deflate` (extc_stubs.c): call to `deflate` failed: Z_BUF_ERROR");
 			break;
 		default:
-			failwith("Error in `zlib_deflate` (extc_stubs.c): unknown return code from `deflate`");
+			caml_failwith("Error in `zlib_deflate` (extc_stubs.c): unknown return code from `deflate`");
 	}
 	assert(0);
 }
@@ -309,14 +309,14 @@ CAMLprim value zlib_deflate_bytecode(value *arg, int nargs) {
 
 CAMLprim value zlib_deflate_end(value zv) {
 	if( deflateEnd(ZStreamP_val(zv)) != 0 )
-		failwith("zlib_deflate_end");
+		caml_failwith("zlib_deflate_end");
 	return Val_unit;
 }
 
 CAMLprim value zlib_inflate_init(value wbits) {
 	value z = zlib_new_stream();
 	if( inflateInit2(ZStreamP_val(z),Int_val(wbits)) != Z_OK )
-		failwith("zlib_inflate_init");
+		caml_failwith("zlib_inflate_init");
 	return z;
 }
 
@@ -330,12 +330,12 @@ CAMLprim value zlib_inflate( value zv, value src, value spos, value slen, value
 	z->avail_in = Int_val(slen);
 	z->avail_out = Int_val(dlen);
 	if( (r = inflate(z,Int_val(flush))) < 0 )
-		failwith("zlib_inflate");
+		caml_failwith("zlib_inflate");
 
 	z->next_in = NULL;
 	z->next_out = NULL;
 
-	res = alloc_small(3, 0);
+	res = caml_alloc_small(3, 0);
 	Field(res, 0) = Val_bool(r == Z_STREAM_END);
 	Field(res, 1) = Val_int(Int_val(slen) - z->avail_in);
 	Field(res, 2) = Val_int(Int_val(dlen) - z->avail_out);
@@ -348,7 +348,7 @@ CAMLprim value zlib_inflate_bytecode(value * arg, int nargs) {
 
 CAMLprim value zlib_inflate_end(value zv) {
 	if( inflateEnd(ZStreamP_val(zv)) != 0 )
-		failwith("zlib_inflate_end");
+		caml_failwith("zlib_inflate_end");
 	return Val_unit;
 }
 
@@ -368,13 +368,13 @@ CAMLprim value executable_path(value u) {
 #ifdef _WIN32
 	char path[MAX_PATH];
 	if( GetModuleFileName(NULL,path,MAX_PATH) == 0 )
-		failwith("executable_path");
+		caml_failwith("executable_path");
 	return caml_copy_string(path);
 #elif __APPLE__
 	char path[MAXPATHLEN+1];
 	uint32_t path_len = MAXPATHLEN;
 	if ( _NSGetExecutablePath(path, &path_len) )
-		failwith("executable_path");
+		caml_failwith("executable_path");
 	return caml_copy_string(path);
 #elif __FreeBSD__
 	char path[PATH_MAX];
@@ -387,7 +387,7 @@ CAMLprim value executable_path(value u) {
 	len = sizeof(path);
 	error = sysctl(name, 4, path, &len, NULL, 0);
 	if( error < 0 )
-		failwith("executable_path");
+		caml_failwith("executable_path");
 	return caml_copy_string(path);
 #else
 	char path[PATH_MAX];
@@ -397,7 +397,7 @@ CAMLprim value executable_path(value u) {
 		if( p != NULL )
 			return caml_copy_string(p);
 		else
-			failwith("executable_path");
+			caml_failwith("executable_path");
 	}
 	path[length] = '\0';
 	return caml_copy_string(path);
@@ -408,12 +408,12 @@ CAMLprim value get_full_path( value f ) {
 #ifdef _WIN32
 	char path[MAX_PATH];
 	if( GetFullPathName(String_val(f),MAX_PATH,path,NULL) == 0 )
-		failwith("get_full_path");
+		caml_failwith("get_full_path");
 	return caml_copy_string(path);
 #else
 	char path[4096];
 	if( realpath(String_val(f),path) == NULL )
-		failwith("get_full_path");
+		caml_failwith("get_full_path");
 	return caml_copy_string(path);
 #endif
 }
@@ -428,7 +428,7 @@ CAMLprim value get_real_path( value path ) {
 
 	// this will ensure the full class path with proper casing
 	if( GetFullPathName(String_val(path),MAX_PATH,out,NULL) == 0 )
-		failwith("get_real_path");
+		caml_failwith("get_real_path");
 
 	len = strlen(out);
 	i = 0;
@@ -501,7 +501,7 @@ CAMLprim value sys_time() {
 		ULARGE_INTEGER ui;
 		GetSystemTime(&t);
 		if( !SystemTimeToFileTime(&t,&ft) )
-			failwith("sys_cpu_time");
+			caml_failwith("sys_cpu_time");
 		ui.LowPart = ft.dwLowDateTime;
 		ui.HighPart = ft.dwHighDateTime;
 		return caml_copy_double( ((double)ui.QuadPart) / 10000000.0 - EPOCH_DIFF );

+ 2 - 2
libs/extc/process_stubs.c

@@ -67,10 +67,10 @@
 #define val_null Val_int(0)
 #define val_some(v) Field(v,0)
 #define val_int(v) Int_val(v)
-#define neko_error() failwith(__FUNCTION__)
+#define neko_error() caml_failwith(__FUNCTION__)
 
 static value alloc_private( int size ) {
-	return alloc((size + sizeof(value) - 1) / sizeof(value), Abstract_tag);
+	return caml_alloc((size + sizeof(value) - 1) / sizeof(value), Abstract_tag);
 }
 
 // --- buffer api

+ 7 - 1
libs/extlib-leftovers/dune

@@ -1,7 +1,13 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -3 -w -27 -w -32))
+	)
+)
+
 (library
 	(name extlib_leftovers)
 	(libraries extlib)
 	; (wrapped false)
-)
+)

+ 5 - 5
libs/extlib-leftovers/multiArray.ml

@@ -77,7 +77,7 @@ let init len f =
 			len = len;
 			arr = imake 0 0;
 			darr = Some arr;
-		}		
+		}
 	end
 
 let make len e =
@@ -124,7 +124,7 @@ let set d idx v =
 	| None -> iset (iget d.arr (idx lsr nbits)) (idx land mask) v
 	| Some arr -> iset arr idx v
 
-let rec add d v =
+let add d v =
 	(match d.darr with
 	| None ->
 		let asize = ilen d.arr in
@@ -140,7 +140,7 @@ let rec add d v =
 	| Some arr ->
 		if d.len < ilen arr then begin
 			(* set *)
-			iset arr d.len v;			
+			iset arr d.len v;
 		end else if d.len lsl 1 >= Sys.max_array_length then begin
 			(* promote *)
 			let count = (d.len + size) lsr nbits in
@@ -180,7 +180,7 @@ let of_list src =
 	let c = create() in
 	List.iter (add c) src;
 	c
-	
+
 let iter f d = match d.darr with
 	| None ->
 	 	let max = ilen d.arr - 1 in
@@ -281,4 +281,4 @@ let fold_left f acc d = match d.darr with
 		for i = 0 to d.len - 1 do
 			acc := f !acc (iget arr i)
 		done;
-		!acc
+		!acc

+ 1 - 1
libs/extlib-leftovers/uTF8.ml

@@ -177,7 +177,7 @@ let rec iter_aux proc s i =
 
 let iter proc s = iter_aux proc s 0
 
-let compare s1 s2 = Pervasives.compare s1 s2
+let compare s1 s2 = Stdlib.compare s1 s2
 
 exception Malformed_code
 

+ 7 - 1
libs/ilib/dune

@@ -1,9 +1,15 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -3 -w -27))
+	)
+)
+
 (library
 	(name ilib)
 	(modules_without_implementation ilData ilMeta)
 	(modules (:standard \ dump))
 	(libraries extlib)
 	(wrapped false)
-)
+)

+ 2 - 2
libs/ilib/peReader.ml

@@ -25,7 +25,7 @@ open ExtList;;
 exception Error_message of string
 
 type reader_ctx = {
-	ch : Pervasives.in_channel;
+	ch : Stdlib.in_channel;
 	i : IO.input;
 	verbose : bool;
 }
@@ -42,7 +42,7 @@ let seek r pos =
 	seek_in r.ch pos
 
 let pos r =
-	Pervasives.pos_in r.ch
+	Stdlib.pos_in r.ch
 
 let info r msg =
 	if r.verbose then

+ 7 - 1
libs/javalib/dune

@@ -1,7 +1,13 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -50))
+	)
+)
+
 (library
 	(name javalib)
 	(libraries extlib)
 	(wrapped false)
-)
+)

+ 7 - 1
libs/neko/dune

@@ -1,7 +1,13 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -27))
+	)
+)
+
 (library
 	(name neko)
 	(libraries extlib)
 	(wrapped false)
-)
+)

+ 2 - 2
libs/neko/ncompile.ml

@@ -673,8 +673,8 @@ and compile_builtin ctx tail b el p =
 			write ctx (Call 1);
 			(* // insert an infinite loop in order to
 			// comply with bytecode checker *)
-			let _ = jmp ctx in
-			()
+			let _jmp = jmp ctx in
+			ignore(_jmp)
 		) dtraps;
 	| ("goto" , _) ->
 		error "Invalid $goto statement" p

+ 27 - 4
libs/objsize/c_objsize.c

@@ -12,6 +12,11 @@
 #include "util.h"
 
 #include <caml/memory.h>
+#include <caml/version.h>
+
+#if OCAML_VERSION_MAJOR >= 5
+#include <caml/address_class.h>
+#endif
 
 // FROM byterun/gc.h
 #define Caml_white (0 << 8)
@@ -38,6 +43,7 @@
 #define In_static_data 4
 #define In_code_area 8
 
+#if OCAML_VERSION_MAJOR < 5
 #ifdef ARCH_SIXTYFOUR
 
 // 64 bits: Represent page table as a sparse hash table
@@ -63,6 +69,23 @@ CAMLextern unsigned char * caml_page_table[Pagetable1_size];
 
 #define Is_in_heap_or_young(a) (Classify_addr(a) & (In_heap | In_young))
 
+void store_explicit(header_t hd, value v, int col)
+ {
+  Hd_val(v) = Coloredhd_hd(hd, col);
+ }
+
+#else
+
+void store_explicit(header_t hd, value v, int col)
+ {
+  atomic_store_explicit(
+	Hp_atomic_val(v),
+	Coloredhd_hd(hd, col),
+	memory_order_release);
+ }
+
+#endif
+
 //--------------------------------------------------------
 
 
@@ -352,7 +375,7 @@ void c_rec_objsize(value v, size_t depth)
 
   DBG(printf("COL: w %08lx %i\n", v, col));
 
-  Hd_val(v) = Coloredhd_hd(hd, Col_blue);
+  store_explicit(hd, v, Col_blue);
 
   if (Tag_val(v) < No_scan_tag)
    {
@@ -378,7 +401,7 @@ void restore_colors(value v)
 
   col = readcolor();
   DBG(printf("COL: r %08lx %i\n", v, col));
-  Hd_val(v) = Coloredhd_hd(Hd_val(v), col);
+  store_explicit(Hd_val(v), v, col);
 
   if (Tag_val(v) < No_scan_tag)
    {
@@ -417,7 +440,7 @@ int c_objsize(value v, value scan, value reach, size_t* headers, size_t* data, s
 	head = Field(head,1);
 	if( col == Col_blue ) continue;
 	writecolor(col);
-	Hd_val(v) = Coloredhd_hd(hd, Col_blue);
+	store_explicit(hd, v, Col_blue);
  }
 
  acc_data = 0;
@@ -444,7 +467,7 @@ int c_objsize(value v, value scan, value reach, size_t* headers, size_t* data, s
 	head = Field(head,1);
 	if( Colornum_hd(Hd_val(v)) != Col_blue ) continue;
 	col = readcolor();
-	Hd_val(v) = Coloredhd_hd(Hd_val(v), col);
+	store_explicit(Hd_val(v), v, col);
  }
 
   while( COND_BLOCK(reach) ) {

+ 9 - 6
libs/pcre2/pcre2_stubs.c

@@ -326,7 +326,7 @@ CAMLprim value pcre2_compile_stub(int64_t v_opt, value v_tables, value v_pat)
 
 CAMLprim value pcre2_compile_stub_bc(value v_opt, value v_tables, value v_pat)
 {
-  return pcre2_compile_stub(Long_val(v_opt), v_tables, v_pat);
+  return pcre2_compile_stub(Int64_val(v_opt), v_tables, v_pat);
 }
 
 /* Gets the depth limit of a regular expression if it exists */
@@ -338,7 +338,7 @@ CAMLprim value pcre2_compile_stub_bc(value v_opt, value v_tables, value v_pat)
 
 /* Sets a match limit for a regular expression imperatively */
 
-CAMLprim value pcre2_set_imp_match_limit_stub(value v_rex, value v_lim) {
+CAMLprim value pcre2_set_imp_match_limit_stub(value v_rex, intnat v_lim) {
   pcre2_match_context* mcontext = get_mcontext(v_rex);
   pcre2_set_match_limit(mcontext, v_lim);
   return v_rex;
@@ -395,12 +395,15 @@ CAMLprim int64_t pcre2_argoptions_stub(value v_rex)
 {
   uint32_t options;
   const int ret = pcre2_pattern_info_stub(v_rex, PCRE2_INFO_ARGOPTIONS, &options);
-  if (ret != 0) raise_internal_error("pcre2_##name##_stub");
+  if (ret != 0) raise_internal_error("pcre2_argoptions_stub");
   return (int64_t)options;
 }
 
 CAMLprim value pcre2_argoptions_stub_bc(value v_rex)
-{ return Val_long(pcre2_argoptions_stub(v_rex)); }
+{
+  CAMLparam1(v_rex);
+  CAMLreturn(caml_copy_int64(pcre2_argoptions_stub(v_rex)));
+}
 
 CAMLprim value pcre2_firstcodeunit_stub(value v_rex)
 {
@@ -627,7 +630,7 @@ CAMLprim value pcre2_match_stub_bc(value *argv, int __unused argn)
 {
   return
     pcre2_match_stub0(
-        Long_val(argv[0]), argv[1], Int_val(argv[2]), Int_val(argv[3]),
+        Int64_val(argv[0]), argv[1], Int_val(argv[2]), Int_val(argv[3]),
         argv[4], argv[5], argv[6], (value) NULL);
 }
 
@@ -637,7 +640,7 @@ CAMLprim value pcre2_dfa_match_stub_bc(value *argv, int __unused argn)
 {
   return
     pcre2_match_stub0(
-        Long_val(argv[0]), argv[1], Int_val(argv[2]), Int_val(argv[3]),
+        Int64_val(argv[0]), argv[1], Int_val(argv[2]), Int_val(argv[3]),
         argv[4], argv[5], argv[6], argv[7]);
 }
 

+ 7 - 1
libs/swflib/dune

@@ -1,8 +1,14 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -3 -w -27))
+	)
+)
+
 (library
 	(name swflib)
 	(libraries extc extlib extlib_leftovers)
 	(modules_without_implementation as3 as3hl)
 	(wrapped false)
-)
+)

+ 1 - 1
libs/swflib/swfParser.ml

@@ -444,7 +444,7 @@ and tag_length t =
 (* READ PRIMS *)
 
 let skip ch n =
-	seek_in ch ((Pervasives.pos_in ch) + n)
+	seek_in ch ((Stdlib.pos_in ch) + n)
 
 let read_rgba ch =
 	let r = read_byte ch in

+ 1 - 1
libs/swflib/swfPic.ml

@@ -59,7 +59,7 @@ let load_picture file id =
 	let len = String.length file in
 	let p = (try String.rindex file '.' with Not_found -> len) in
 	let ext = String.sub file (p + 1) (len - (p + 1)) in
-	match String.uppercase ext with
+	match ExtString.String.uppercase ext with
 	| "PNG" ->
 		let png , header, data = (try
 			let p = Png.parse ch in

+ 7 - 1
libs/ttflib/dune

@@ -1,8 +1,14 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -3 -w -27 -w -35))
+	)
+)
+
 (library
 	(name ttflib)
 	(libraries extlib extlib_leftovers swflib unix)
 	(modules (:standard \ main))
 	(wrapped false)
-)
+)

+ 1 - 1
libs/ttflib/tTFParser.ml

@@ -24,7 +24,7 @@ open TTFData
 open IO
 
 type ctx = {
-	file : Pervasives.in_channel;
+	file : Stdlib.in_channel;
 	ch : input;
 	mutable entry : entry;
 }

+ 7 - 1
libs/ziplib/dune

@@ -1,7 +1,13 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -3 -w -27 -w -35 -w -50))
+	)
+)
+
 (library
 	(name ziplib)
 	(libraries extc unix)
 	(wrapped false)
-)
+)

+ 8 - 8
libs/ziplib/zip.ml

@@ -62,7 +62,7 @@ type entry =
 
 type in_file =
   { if_filename: string;
-    if_channel: Pervasives.in_channel;
+    if_channel: Stdlib.in_channel;
     if_entries: entry list;
     if_directory: (string, entry) Hashtbl.t;
     if_comment: string }
@@ -72,7 +72,7 @@ let comment ifile = ifile.if_comment
 
 type out_file =
   { of_filename: string;
-    of_channel: Pervasives.out_channel;
+    of_channel: Stdlib.out_channel;
     mutable of_entries: entry list;
     of_comment: string }
 
@@ -217,7 +217,7 @@ let read_cd filename ic cd_entries cd_offset cd_bound =
 (* Open a ZIP file for reading *)
 
 let open_in filename =
-  let ic = Pervasives.open_in_bin filename in
+  let ic = Stdlib.open_in_bin filename in
   let (cd_entries, cd_size, cd_offset, cd_comment) = read_ecd filename ic in
   let entries =
     read_cd filename ic cd_entries cd_offset (Int32.add cd_offset cd_size) in
@@ -232,7 +232,7 @@ let open_in filename =
 (* Close a ZIP file opened for reading *)
 
 let close_in ifile =
-  Pervasives.close_in ifile.if_channel
+  Stdlib.close_in ifile.if_channel
 
 (* Return the info associated with an entry *)
 
@@ -369,7 +369,7 @@ let open_out ?(comment = "") filename =
   if String.length comment >= 0x10000 then
     raise(Error(filename, "", "comment too long"));
   { of_filename = filename;
-    of_channel = Pervasives.open_out_bin filename;
+    of_channel = Stdlib.open_out_bin filename;
     of_entries = [];
     of_comment = comment }
 
@@ -416,7 +416,7 @@ let close_out ofile =
   write4_int oc start_cd;               (* offset of central dir *)
   write2 oc (String.length ofile.of_comment); (* length of comment *)
   writestring oc ofile.of_comment;         (* comment *)
-  Pervasives.close_out oc
+  Stdlib.close_out oc
 
 (* Write a local file header and return the corresponding entry *)
 
@@ -552,9 +552,9 @@ let copy_file_to_entry infilename ofile ?(extra = "") ?(comment = "")
         with Unix.Unix_error(_,_,_) -> None in
   try
     copy_channel_to_entry ic ofile ~extra ~comment ~level ?mtime:mtime' name;
-    Pervasives.close_in ic
+    Stdlib.close_in ic
   with x ->
-    Pervasives.close_in ic; raise x
+    Stdlib.close_in ic; raise x
 
 
 (* Add an entry whose content will be produced by the caller *)

+ 7 - 1
plugins/example/dune

@@ -1,7 +1,13 @@
 (data_only_dirs cmxs hx)
 (include_subdirs unqualified)
 
+(env
+	(_
+		(flags -w -27 -w -50)
+	)
+)
+
 (library
 	(name example)
 	(libraries haxe)
-)
+)

+ 199 - 37
src-json/define.json

@@ -8,7 +8,8 @@
 		"name": "AdvancedTelemetry",
 		"define": "advanced-telemetry",
 		"doc": "Allow the SWF to be measured with Monocle tool.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "AnalyzerOptimize",
@@ -199,7 +200,8 @@
 		"name": "Fdb",
 		"define": "fdb",
 		"doc": "Enable full flash debug infos for FDB interactive debugging.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "FileExtension",
@@ -211,13 +213,15 @@
 		"name": "FlashStrict",
 		"define": "flash-strict",
 		"doc": "More strict typing for flash target.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "FlashUseStage",
 		"define": "flash-use-stage",
 		"doc": "Keep the SWF library initial stage.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"devcomment": "force-lib-check is only here as a debug facility - compiler checking allows errors to be found more easily",
@@ -241,13 +245,15 @@
 	{
 		"name": "Haxe3Compat",
 		"define": "haxe3compat",
-		"doc": "Gives warnings about transition from Haxe 3.x to Haxe 4.0."
+		"doc": "Gives warnings about transition from Haxe 3.x to Haxe 4.0.",
+		"deprecated": "This flag is no longer supported in Haxe 5"
 	},
 	{
 		"name": "HaxeBoot",
 		"define": "haxe-boot",
 		"doc": "Give the name 'haxe' to the flash boot class instead of a generated name.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "HaxeVer",
@@ -261,6 +267,32 @@
 		"doc": "The current Haxe version value in SemVer format.",
 		"reserved": true
 	},
+	{
+		"name": "HaxeNext",
+		"define": "haxe-next",
+		"doc": "Enable experimental features that are meant to be released on next Haxe version."
+	},
+	{
+		"name": "HaxeOutputFile",
+		"define": "HAXE_OUTPUT_FILE",
+		"doc": "Force the full output name of the executable/library without library prefix and debug suffix.",
+		"platforms": ["cpp"],
+		"params": ["name"]
+	},
+	{
+		"name": "HaxeOutputPart",
+		"define": "HAXE_OUTPUT_PART",
+		"doc": "Output name of the executable/library. (default: main class name)",
+		"platforms": ["cpp"],
+		"params": ["name"]
+	},
+	{
+		"name": "Hlc",
+		"define": "hlc",
+		"doc": "Defined by compiler when using hl/c target.",
+		"platforms": ["hl"],
+		"reserved": true
+	},
 	{
 		"name": "HlVer",
 		"define": "hl-ver",
@@ -287,6 +319,114 @@
 		"doc": "Include additional information for hxcpp-debugger.",
 		"platforms": ["cpp"]
 	},
+	{
+		"name": "HxcppGcMoving",
+		"define": "HXCPP-GC-MOVING",
+		"doc": "Allow garbage collector to move memory to reduce fragmentation",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppGcSummary",
+		"define": "HXCPP-GC-SUMMARY",
+		"doc": "Print small profiling summary at end of program",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppGcDynamicSize",
+		"define": "HXCPP-GC-DYNAMIC-SIZE",
+		"doc": "Monitor GC times and expand memory working space if required",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppGcBigBlocks",
+		"define": "HXCPP-GC-BIG-BLOCKS",
+		"doc": "Allow working memory greater than 1 Gig",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppGcDebugLevel",
+		"define": "HXCPP-GC-DEBUG-LEVEL",
+		"doc": "Number 1-4 indicating additional debugging in GC",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppDebugLink",
+		"define": "HXCPP-DEBUG-LINK",
+		"doc": "Add symbols to final binary, even in release mode.",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppStackTrace",
+		"define": "HXCPP-STACK-TRACE",
+		"doc": "Have valid function-level stack traces, even in release mode.",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppStackLine",
+		"define": "HXCPP-STACK-LINE",
+		"doc": "Include line information in stack traces, even in release mode.",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppCheckPointer",
+		"define": "HXCPP-CHECK-POINTER",
+		"doc": "Add null-pointer checks, even in release mode.",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppProfiler",
+		"define": "HXCPP-PROFILER",
+		"doc": "Add profiler support",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppTelemetry",
+		"define": "HXCPP-TELEMETRY",
+		"doc": "Add telemetry support",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppCpp11",
+		"define": "HXCPP-CPP11",
+		"doc": "Use C++11 features and link libraries",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppVerbose",
+		"define": "HXCPP-VERBOSE",
+		"doc": "Print extra output from build tool.",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppTimes",
+		"define": "HXCPP-TIMES",
+		"doc": "Show some basic profiling information",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppM32",
+		"define": "HXCPP-M32",
+		"doc": "Force 32-bit compile for current desktop",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppM64",
+		"define": "HXCPP-M64",
+		"doc": "Force 64-bit compile for current desktop",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppArm64",
+		"define": "HXCPP-ARM64",
+		"doc": "Compile arm-based devices for 64 bits",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppLinuxArm64",
+		"define": "HXCPP-LINUX-ARM64",
+		"doc": "Run on a linux ARM64 device",
+		"platforms": ["cpp"]
+	},
 	{
 		"name": "HxcppSmartStings",
 		"define": "hxcpp-smart-strings",
@@ -308,7 +448,8 @@
 		"name": "JarLegacyLoader",
 		"define": "jar-legacy-loader",
 		"doc": "Use the legacy loader to load .jar files on the JVM target.",
-		"platforms": ["java"]
+		"platforms": ["java"],
+		"deprecated": "The legacy JAR loader will be removed in Haxe 5"
 	},
 	{
 		"name": "JavaVer",
@@ -397,12 +538,6 @@
 		"doc": "Enable the jit compiler for lua (version 5.2 only).",
 		"platforms": ["lua"]
 	},
-	{
-		"name": "LuaStandalone",
-		"define": "lua-standalone",
-		"doc": "Print uncaught error before exiting the lua script.",
-		"platforms": ["lua"]
-	},
 	{
 		"name": "LuaVanilla",
 		"define": "lua-vanilla",
@@ -455,6 +590,14 @@
 		"doc": "Output neko source instead of bytecode.",
 		"platforms": ["neko"]
 	},
+	{
+		"name": "NekoNoHaxelibPaths",
+		"define": "neko-no-haxelib-paths",
+		"doc": "Disable hard-coded Haxelib ndll paths.",
+		"platforms": [
+			"neko"
+		]
+	},
 	{
 		"name": "NekoV1",
 		"define": "neko-v1",
@@ -465,7 +608,8 @@
 		"name": "NetworkSandbox",
 		"define": "network-sandbox",
 		"doc": "Use local network sandbox instead of local file access one.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "NoCompilation",
@@ -487,7 +631,8 @@
 		"name": "NoFlashOverride",
 		"define": "no-flash-override",
 		"doc": "Change overrides on some basic classes into HX suffixed methods",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "NoOpt",
@@ -521,7 +666,8 @@
 		"name": "NoSwfCompress",
 		"define": "no-swf-compress",
 		"doc": "Disable SWF output compression.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "NoTraces",
@@ -624,71 +770,82 @@
 		"define": "swc",
 		"doc": "Output a SWC instead of a SWF.",
 		"platforms": ["flash"],
-		"reserved": true
+		"reserved": true,
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfCompressLevel",
 		"define": "swf-compress-level",
 		"doc": "Set the amount of compression for the SWF output.",
 		"platforms": ["flash"],
-		"params": ["level: 1-9"]
+		"params": ["level: 1-9"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfDebugPassword",
 		"define": "swf-debug-password",
 		"doc": "Set a password for debugging.",
 		"platforms": ["flash"],
-		"params": ["password"]
+		"params": ["password"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfDirectBlit",
 		"define": "swf-direct-blit",
 		"doc": "Use hardware acceleration to blit graphics.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfGpu",
 		"define": "swf-gpu",
 		"doc": "Use GPU compositing features when drawing graphics.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfHeader",
 		"define": "swf-header",
 		"doc": "define SWF header (width:height:fps:color)",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfMetadata",
 		"define": "swf-metadata",
 		"doc": "Include contents of the given file as metadata in the SWF.",
 		"platforms": ["flash"],
-		"params": ["file"]
+		"params": ["file"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfPreloaderFrame",
 		"define": "swf-preloader-frame",
 		"doc": "Insert empty first frame in SWF.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfProtected",
 		"define": "swf-protected",
 		"doc": "Compile Haxe `private` as `protected` in the SWF instead of `public`.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfScriptTimeout",
 		"define": "swf-script-timeout",
 		"doc": "Maximum ActionScript processing time before script stuck dialog box displays.",
 		"platforms": ["flash"],
-		"params": ["time in seconds"]
+		"params": ["time in seconds"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfUseDoAbc",
 		"define": "swf-use-doabc",
 		"doc": "Use `DoAbc` SWF-tag instead of `DoAbcDefine`.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "Sys",
@@ -732,24 +889,29 @@
 	},
 	{
 		"name": "MessageReporting",
-		"define": "message-reporting",
+		"define": "message.reporting",
 		"doc": "Select message reporting mode for compiler output. (default: classic)",
 		"params": ["mode: classic | pretty | indent"]
 	},
 	{
-		"name": "NoColor",
-		"define": "no-color",
-		"doc": "Disable ANSI color codes when using rich output."
+		"name": "MessageNoColor",
+		"define": "message.no-color",
+		"doc": "Disable ANSI color codes in message reporting."
+	},
+	{
+		"name": "MessageAbsolutePositions",
+		"define": "message.absolute-positions",
+		"doc": "Use absolute character positions instead of line/columns for message reporting."
 	},
 	{
-		"name": "MessagesLogFile",
-		"define": "messages-log-file",
-		"doc": "Path to a text file to write messages log to, in addition to regular output."
+		"name": "MessageLogFile",
+		"define": "message.log-file",
+		"doc": "Path to a text file to write message reporting to, in addition to regular output."
 	},
 	{
-		"name": "MessagesLogFormat",
-		"define": "messages-log-format",
-		"doc": "Select message reporting mode for messages log output. (default: indent)",
+		"name": "MessageLogFormat",
+		"define": "message.log-format",
+		"doc": "Select message reporting mode for message log file. (default: indent)",
 		"params": ["format: classic | pretty | indent"]
 	}
 ]

+ 2 - 1
src-json/meta.json

@@ -41,7 +41,8 @@
 	{
 		"name": "Annotation",
 		"metadata": ":annotation",
-		"doc": "Annotation (`@interface`) definitions on `--java-lib` imports will be annotated with this metadata. Has no effect on types compiled by Haxe.",
+		"doc": "Marks a class as a Java annotation",
+		"params": ["Retention policy"],
 		"platforms": ["java"],
 		"targets": ["TClass"]
 	},

+ 10 - 0
src-json/warning.json

@@ -58,6 +58,16 @@
 		"name": "WDeprecated",
 		"doc": "This is deprecated and should no longer be used"
 	},
+	{
+		"name": "WDeprecatedDefine",
+		"doc": "This define is deprecated and should no longer be used",
+		"parent": "WDeprecated"
+	},
+	{
+		"name": "WDeprecatedEnumAbstract",
+		"doc": "`@:enum abstract` is deprecated, `enum abstract` should be used instead",
+		"parent": "WDeprecated"
+	},
 	{
 		"name": "WVarInit",
 		"doc": "A local variable might be used before being assigned a value",

+ 7 - 1
src-prebuild/dune

@@ -1,8 +1,14 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -9 -w -32))
+	)
+)
+
 (executable
 	(name prebuild)
 	(public_name haxe_prebuild)
 	(package haxe_prebuild)
 	(libraries extlib json)
-)
+)

+ 68 - 28
src-prebuild/prebuild.ml

@@ -9,6 +9,17 @@ type parsed_warning = {
 	w_generic : bool;
 }
 
+type parsed_meta = {
+	m_name : string;
+	m_meta : string;
+	m_doc : string;
+	m_params : string list;
+	m_platforms : string list;
+	m_targets : string list;
+	m_internal : bool;
+	m_links : string list;
+}
+
 let as_string = function
 	| JString s -> Some s
 	| _ -> None
@@ -104,21 +115,24 @@ let parse_define json =
 	(* doc *) get_field "doc" as_string fields,
 	(* params *) get_optional_field "params" as_params [] fields,
 	(* platforms *) get_optional_field "platforms" as_platforms [] fields,
-	(* links *) get_optional_field "links" as_links [] fields
+	(* links *) get_optional_field "links" as_links [] fields,
+	(* deprecated *) get_optional_field2 "deprecated" as_string fields
 
 let parse_meta json =
 	let fields = match json with
 		| JObject fl -> fl
 		| _ -> raise (Prebuild_error "not an object")
 	in
-	(* name *) get_field "name" as_string fields,
-	(* metadata *) get_field "metadata" as_string fields,
-	(* doc *) get_field "doc" as_string fields,
-	(* params *) get_optional_field "params" as_params [] fields,
-	(* platforms *) get_optional_field "platforms" as_platforms [] fields,
-	(* targets *) get_optional_field "targets" as_targets [] fields,
-	(* internal *) get_optional_field "internal" as_bool false fields,
-	(* links *) get_optional_field "links" as_links [] fields
+	{
+		m_name = get_field "name" as_string fields;
+		m_meta = get_field "metadata" as_string fields;
+		m_doc = get_field "doc" as_string fields;
+		m_params = get_optional_field "params" as_params [] fields;
+		m_platforms = get_optional_field "platforms" as_platforms [] fields;
+		m_targets = get_optional_field "targets" as_targets [] fields;
+		m_internal = get_optional_field "internal" as_bool false fields;
+		m_links = get_optional_field "links" as_links [] fields
+	}
 
 let parse_warning json =
 	let fields = match json with
@@ -165,42 +179,54 @@ let gen_params = List.map (function param -> "HasParam \"" ^ param ^ "\"" )
 let gen_links = List.map (function link -> "Link \"" ^ link ^ "\"" )
 
 let gen_define_type defines =
-	String.concat "\n" (List.map (function (name, _, _, _, _, _) -> "\t| " ^ name) defines)
+	String.concat "\n" (List.map (function (name, _, _, _, _, _, _) -> "\t| " ^ name) defines)
+
+let gen_option f = function
+	| None -> "None"
+	| Some x -> Printf.sprintf "Some(%s)" (f x)
 
 let gen_define_info defines =
+	let deprecations = DynArray.create() in
 	let define_str = List.map (function
-		(name, define, doc, params, platforms, links) ->
+		(name, define, doc, params, platforms, links, deprecated) ->
 			let platforms_str = gen_platforms platforms in
 			let params_str = gen_params params in
 			let links_str = gen_links links in
 			let define = String.concat "_" (ExtString.String.nsplit define "-") in
-			"\t| " ^ name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str)) ^ "])"
+			let deprecated = match deprecated with
+				| None ->
+					[]
+				| Some x ->
+					let quoted = Printf.sprintf "%S" x in
+					DynArray.add deprecations (Printf.sprintf "\t(%S,%S)" define x);
+					[Printf.sprintf "Deprecated(%s)" quoted]
+			in
+			"\t| " ^ name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str @ deprecated)) ^ "])"
 	) defines in
-	String.concat "\n" define_str
+	String.concat "\n" define_str,String.concat ";\n" (DynArray.to_list deprecations)
 
 let gen_meta_type metas =
 	String.concat "\n" (List.map (function
-		| ("InlineConstructorArgument", _, _, _, _, _, _, _) -> "\t| InlineConstructorArgument of int * int"
-		| (name, _, _, _, _, _, _, _) -> "\t| " ^ name
+		| {m_name = "InlineConstructorArgument"} -> "\t| InlineConstructorArgument of int * int"
+		| {m_name = name} -> "\t| " ^ name
 	) metas)
 
 let gen_meta_info metas =
-	let meta_str = List.map (function
-		(name, metadata, doc, params, platforms, targets, internal, links) ->
-			let platforms_str = gen_platforms platforms in
-			let params_str = gen_params params in
-			let targets_str = (match targets with
+	let meta_str = List.map (function meta ->
+			let platforms_str = gen_platforms meta.m_platforms in
+			let params_str = gen_params meta.m_params in
+			let targets_str = (match meta.m_targets with
 				| [] -> []
 				| targets -> ["UsedOn [" ^ (String.concat ";" targets) ^ "]"]
 			) in
-			let internal_str = if internal then ["UsedInternally"] else [] in
-			let links_str = gen_links links in
-			let name = (match name with
+			let internal_str = if meta.m_internal then ["UsedInternally"] else [] in
+			let links_str = gen_links meta.m_links in
+			let name = (match meta.m_name with
 				(* this is a hacky, I know *)
 				| "InlineConstructorArgument" -> "InlineConstructorArgument _"
-				| _ -> name
+				| _ -> meta.m_name
 			) in
-			"\t| " ^ name ^ " -> \"" ^ metadata ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ targets_str @ internal_str @ links_str)) ^ "])"
+			"\t| " ^ name ^ " -> \"" ^ meta.m_meta ^ "\",(" ^ (Printf.sprintf "%S" meta.m_doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ targets_str @ internal_str @ links_str)) ^ "])"
 	) metas in
 	String.concat "\n" meta_str
 
@@ -241,7 +267,7 @@ type define_parameter =
 	| HasParam of string
 	| Platforms of platform list
 	| Link of string
-
+	| Deprecated of string
 "
 
 let meta_header = autogen_header ^ "
@@ -272,6 +298,18 @@ let parse_meta_usage = function
 	| \"TVariable\" -> TVariable
 	| t -> raise (failwith (\"invalid metadata target \" ^ t))
 
+let print_meta_usage = function
+	| TClass -> \"TClass\"
+	| TClassField -> \"TClassField\"
+	| TAbstract -> \"TAbstract\"
+	| TAbstractField -> \"TAbstractField\"
+	| TEnum -> \"TEnum\"
+	| TTypedef -> \"TTypedef\"
+	| TAnyField -> \"TAnyField\"
+	| TExpr -> \"TExpr\"
+	| TTypeParameter -> \"TTypeParameter\"
+	| TVariable -> \"TVariable\"
+
 type meta_parameter =
 	| HasParam of string
 	| Platforms of platform list
@@ -290,9 +328,11 @@ match Array.to_list (Sys.argv) with
 		Printf.printf "type strict_defined =\n";
 		Printf.printf "%s" (gen_define_type defines);
 		Printf.printf "\n\t| Last\n\t| Custom of string\n\n";
+		let infos,deprecations = gen_define_info defines in
 		Printf.printf "let infos = function\n";
-		Printf.printf "%s" (gen_define_info defines);
-		Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Custom s -> s,(\"\",[])\n"
+		Printf.printf "%s" infos;
+		Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Custom s -> s,(\"\",[])\n";
+		Printf.printf "\nlet deprecated_defines = [\n%s\n]\n" deprecations;
 	| [_; "meta"; meta_path]->
 		let metas = parse_file_array meta_path parse_meta in
 		Printf.printf "%s" meta_header;

+ 24 - 24
src/codegen/codegen.ml

@@ -20,7 +20,6 @@
 open Ast
 open Type
 open Common
-open Error
 open Globals
 open Extlib_leftovers
 
@@ -66,12 +65,12 @@ let add_property_field com c =
 		c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics;
 		c.cl_ordered_statics <- cf :: c.cl_ordered_statics
 
-let escape_res_name name allow_dirs =
+let escape_res_name name allowed =
 	ExtString.String.replace_chars (fun chr ->
 		if (chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9') || chr = '_' || chr = '.' then
 			Char.escaped chr
-		else if chr = '/' && allow_dirs then
-			"/"
+		else if List.mem chr allowed then
+			Char.escaped chr
 		else
 			"-x" ^ (string_of_int (Char.code chr))) name
 
@@ -123,8 +122,13 @@ let fix_override com c f fd =
 					(* Flash generates type parameters with a single constraint as that constraint type, so we
 					   have to detect this case and change the variable (issue #2712). *)
 					begin match follow v.v_type with
-						| TInst({cl_kind = KTypeParameter [tc]} as cp,_) when com.platform = Flash ->
-							if List.exists (fun tp -> tp.ttp_name = (snd cp.cl_path)) c.cl_params then raise (Unify_error [])
+						| TInst({cl_kind = KTypeParameter ttp} as cp,_) when com.platform = Flash ->
+							begin match get_constraints ttp with
+							| [tc] ->
+								if List.exists (fun tp -> tp.ttp_name = (snd cp.cl_path)) c.cl_params then raise (Unify_error [])
+							| _ ->
+								()
+							end
 						| _ ->
 							()
 					end;
@@ -236,11 +240,16 @@ module Dump = struct
 		let buf,close = create_dumpfile [] ((dump_path com) :: (platform_name_macro com) :: fst path @ [snd path]) in
 		buf,close
 
-	let dump_types com s_expr =
+	let dump_types com pretty =
 		let s_type = s_type (Type.print_context()) in
+		let s_expr,s_type_param = if not pretty then
+			(Type.s_expr_ast (not (Common.defined com Define.DumpIgnoreVarIds)) "\t"),(Printer.s_type_param "")
+		else
+			(Type.s_expr_pretty false "\t" true),(s_type_param s_type)
+		in
 		let params tl = match tl with
 			| [] -> ""
-			| l -> Printf.sprintf "<%s>" (String.concat ", " (List.map Printer.s_type_param l))
+			| l -> Printf.sprintf "<%s>" (String.concat ", " (List.map s_type_param l))
 		in
 		List.iter (fun mt ->
 			let path = Type.t_path mt in
@@ -372,11 +381,10 @@ module Dump = struct
 
 	let dump_types com =
 		match Common.defined_value_safe com Define.Dump with
-			| "pretty" -> dump_types com (Type.s_expr_pretty false "\t" true)
-			| "legacy" -> dump_types com Type.s_expr
+			| "pretty" -> dump_types com true
 			| "record" -> dump_record com
 			| "position" -> dump_position com
-			| _ -> dump_types com (Type.s_expr_ast (not (Common.defined com Define.DumpIgnoreVarIds)) "\t")
+			| _ -> dump_types com false 
 
 	let dump_dependencies ?(target_override=None) com =
 		let target_name = match target_override with
@@ -389,7 +397,8 @@ module Dump = struct
 		let dep = Hashtbl.create 0 in
 		List.iter (fun m ->
 			print "%s:\n" (Path.UniqueKey.lazy_path m.m_extra.m_file);
-			PMap.iter (fun _ m2 ->
+			PMap.iter (fun _ (sign,mpath) ->
+				let m2 = com.module_lut#find mpath in
 				let file = Path.UniqueKey.lazy_path m2.m_extra.m_file in
 				print "\t%s\n" file;
 				let l = try Hashtbl.find dep file with Not_found -> [] in
@@ -415,16 +424,10 @@ end
 *)
 let default_cast ?(vtmp="$t") com e texpr t p =
 	let api = com.basic in
-	let mk_texpr = function
-		| TClassDecl c -> mk_anon (ref (Statics c))
-		| TEnumDecl e -> mk_anon (ref (EnumStatics e))
-		| TAbstractDecl a -> mk_anon (ref (AbstractStatics a))
-		| TTypeDecl _ -> die "" __LOC__
-	in
 	let vtmp = alloc_var VGenerated vtmp e.etype e.epos in
 	let var = mk (TVar (vtmp,Some e)) api.tvoid p in
 	let vexpr = mk (TLocal vtmp) e.etype p in
-	let texpr = mk (TTypeExpr texpr) (mk_texpr texpr) p in
+	let texpr = Texpr.Builder.make_typeexpr texpr p in
 	let std = (try List.find (fun t -> t_path t = ([],"Std")) com.types with Not_found -> die "" __LOC__) in
 	let fis = (try
 			let c = (match std with TClassDecl c -> c | _ -> die "" __LOC__) in
@@ -432,7 +435,7 @@ let default_cast ?(vtmp="$t") com e texpr t p =
 		with Not_found ->
 			die "" __LOC__
 	) in
-	let std = mk (TTypeExpr std) (mk_texpr std) p in
+	let std = Texpr.Builder.make_typeexpr std p in
 	let is = mk (TField (std,fis)) (tfun [t_dynamic;t_dynamic] api.tbool) p in
 	let is = mk (TCall (is,[vexpr;texpr])) api.tbool p in
 	let enull = Texpr.Builder.make_null vexpr.etype p in
@@ -478,10 +481,6 @@ let interpolate_code com code tl f_string f_expr p =
 			i := !i + String.length txt;
 			f_string txt;
 			loop tl
-		| Str.Delim a :: Str.Delim b :: tl when a = b ->
-			i := !i + 2;
-			f_string a;
-			loop tl
 		| Str.Delim "{" :: Str.Text n :: Str.Delim "}" :: tl ->
 			begin try
 				let expr = Array.get exprs (int_of_string n) in
@@ -520,3 +519,4 @@ module ExtClass = struct
 		let e_assign = mk (TBinop(OpAssign,ef1,e)) e.etype p in
 		add_cl_init c e_assign
 end
+	

+ 14 - 13
src/codegen/dotnet.ml

@@ -68,7 +68,7 @@ let cs_unops =
 let netname_to_hx name =
 	let len = String.length name in
 	let chr = String.get name 0 in
-	String.make 1 (Char.uppercase chr) ^ (String.sub name 1 (len-1))
+	String.make 1 (Char.uppercase_ascii chr) ^ (String.sub name 1 (len-1))
 
 (* -net-lib implementation *)
 
@@ -105,7 +105,7 @@ let escape_chars =
 
 let netcl_to_hx cl =
 	let cl = if String.length cl > 0 && String.get cl 0 >= 'a' && String.get cl 0 <= 'z' then
-			Char.escaped (Char.uppercase (String.get cl 0)) ^ (String.sub cl 1 (String.length cl - 1))
+			Char.escaped (Char.uppercase_ascii (String.get cl 0)) ^ (String.sub cl 1 (String.length cl - 1))
 		else
 			cl
 	in
@@ -145,7 +145,7 @@ let mk_type_path ctx path params =
 			let nested = List.map (netcl_to_hx) nested in
 			ns, Some (String.concat "_" nested ^ "_" ^ netcl_to_hx cl), nhd
 	in
-	CTPath {
+	make_ptp_ct_null {
 		tpackage = fst (netpath_to_hx ctx.nstd (pack,[],""));
 		Ast.tname = name;
 		tparams = params;
@@ -153,12 +153,13 @@ let mk_type_path ctx path params =
 	}
 
 let raw_type_path ctx path params =
-	{
+	let tp = {
 		tpackage = fst path;
 		Ast.tname = snd path;
 		tparams = params;
 		tsub = None;
-	}
+	} in
+	make_ptp tp null_pos
 
 let rec convert_signature ctx p = function
 	| LVoid ->
@@ -577,7 +578,7 @@ let convert_ilprop ctx p prop is_explicit_impl =
 		cff_kind = kind;
 	}
 
-let get_type_path ctx ct = match ct with | CTPath p -> p | _ -> die "" __LOC__
+let get_type_path ctx ct = match ct with | CTPath ptp -> ptp | _ -> die "" __LOC__
 
 let is_explicit ctx ilcls i =
 	let s = match i with
@@ -754,12 +755,12 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with
 		(match ilcls.csuper with
 			| Some { snorm = LClass ( (["System"],[],"Object"), [] ) } -> ()
 			| Some ({ snorm = LClass ( (["System"],[],"ValueType"), [] ) } as s) ->
-				flags := HExtends (get_type_path ctx (convert_signature ctx p s.snorm),null_pos) :: !flags;
+				flags := HExtends (get_type_path ctx (convert_signature ctx p s.snorm)) :: !flags;
 				meta := (Meta.Struct,[],p) :: !meta
 			| Some { snorm = LClass ( (["haxe";"lang"],[],"HxObject"), [] ) } ->
 				meta := (Meta.HxGen,[],p) :: !meta
 			| Some s ->
-				flags := HExtends (get_type_path ctx (convert_signature ctx p s.snorm),null_pos) :: !flags
+				flags := HExtends (get_type_path ctx (convert_signature ctx p s.snorm)) :: !flags
 			| _ -> ());
 
 			let has_explicit_ifaces = ref false in
@@ -771,9 +772,9 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with
 				| i ->
 					if is_explicit ctx ilcls i then has_explicit_ifaces := true;
 					flags := if !is_interface then
-						HExtends (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags
+						HExtends (get_type_path ctx (convert_signature ctx p i)) :: !flags
 					else
-						HImplements (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags
+						HImplements (get_type_path ctx (convert_signature ctx p i)) :: !flags
 			) ilcls.cimplements;
 			(* this is needed because of explicit interfaces. see http://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx *)
 			(* explicit interfaces can't be mapped into Haxe in any way - since their fields can't be accessed directly, but they still implement that interface *)
@@ -784,9 +785,9 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with
 			ignore (List.exists (function
 			| { psig = { snorm = LMethod(_,ret,[v]) } } ->
 				flags := if !is_interface then
-					(HExtends( raw_type_path ctx ([],"ArrayAccess") [ TPType (convert_signature ctx p ret,null_pos) ],null_pos) :: !flags)
+					(HExtends( raw_type_path ctx ([],"ArrayAccess") [ TPType (convert_signature ctx p ret,null_pos) ]) :: !flags)
 				else
-					(HImplements( raw_type_path ctx ([],"ArrayAccess") [ TPType (convert_signature ctx p ret,null_pos) ],null_pos) :: !flags);
+					(HImplements( raw_type_path ctx ([],"ArrayAccess") [ TPType (convert_signature ctx p ret,null_pos) ]) :: !flags);
 				true
 			| _ -> false) ilcls.cprops);
 
@@ -1112,7 +1113,7 @@ let normalize_ilcls ctx cls =
 	in
 	let refclsfields = List.fold_left fold_field [] refclsfields in
 
-	let rec fold (fields,methods,props) f = match !f with
+	let fold (fields,methods,props) f = match !f with
 		| IlField f,_,_,_ -> f :: fields,methods,props
 		| IlMethod m,_,_,_ -> fields,m :: methods,props
 		| IlProp p,_,_,_ -> fields,methods,p :: props

+ 14 - 7
src/codegen/gencommon/castDetect.ml

@@ -21,7 +21,6 @@ open Common
 open Ast
 open Globals
 open Type
-open Codegen
 open Gencommon
 
 (* ******************************************* *)
@@ -241,7 +240,7 @@ let is_exactly_basic gen t1 t2 =
 		| _ ->
 			false
 
-let rec is_unsafe_cast gen to_t from_t =
+let is_unsafe_cast gen to_t from_t =
 	match (follow to_t, follow from_t) with
 		| TInst(cl_to, to_params), TInst(cl_from, from_params) ->
 			not (is_cl_related gen cl_from from_params cl_to to_params)
@@ -291,7 +290,7 @@ let do_unsafe_cast gen from_t to_t e	=
 			| _ -> raise Not_found
 	in
 	match gen.gfollow#run_f from_t, gen.gfollow#run_f to_t with
-	| TInst({ cl_kind = KTypeParameter tl },_), t2 when List.exists (fun t -> unifies t t2) tl ->
+	| TInst({ cl_kind = KTypeParameter ttp },_), t2 when List.exists (fun t -> unifies t t2) (get_constraints ttp) ->
 		mk_cast to_t (mk_cast t_dynamic e)
 	| from_t, to_t when gen.gspecial_needs_cast to_t from_t ->
 		mk_cast to_t e
@@ -419,7 +418,7 @@ let rec handle_cast gen e real_to_t real_from_t =
 				mk_cast true to_t e
 		| _, TAnon(anon) -> (try
 			let p2 = match !(anon.a_status) with
-			| Statics c -> TInst(c,List.map (fun _ -> t_dynamic) c.cl_params)
+			| ClassStatics c -> TInst(c,List.map (fun _ -> t_dynamic) c.cl_params)
 			| EnumStatics e -> TEnum(e, List.map (fun _ -> t_dynamic) e.e_params)
 			| AbstractStatics a -> TAbstract(a, List.map (fun _ -> t_dynamic) a.a_params)
 			| _ -> raise Not_found
@@ -657,7 +656,7 @@ let choose_ctor gen cl tparams etl maybe_empty_t p =
 		| _ ->
 			false
 	in
-	let rec check_cf cf =
+	let check_cf cf =
 		let t = apply_params sup.cl_params stl cf.cf_type in
 		replace_mono t;
 		let args, _ = get_fun t in
@@ -1271,8 +1270,16 @@ let configure gen ?(overloads_cast_to_base = false) maybe_empty_t calls_paramete
 				{ e with eexpr = TIf (handle (run econd) gen.gcon.basic.tbool econd.etype, (in_value := false; run (mk_block ethen)), Option.map (fun e -> in_value := false; run (mk_block e)) eelse) }
 			| TWhile (econd, e1, flag) ->
 				{ e with eexpr = TWhile (handle (run econd) gen.gcon.basic.tbool econd.etype, (in_value := false; run (mk_block e1)), flag) }
-			| TSwitch (cond, el_e_l, edef) ->
-				{ e with eexpr = TSwitch(run cond, List.map (fun (el,e) -> (List.map run el, (in_value := false; run (mk_block e)))) el_e_l, Option.map (fun e -> in_value := false; run (mk_block e)) edef) }
+			| TSwitch switch ->
+				let switch = { switch with
+					switch_subject = run switch.switch_subject;
+					switch_cases = List.map (fun case -> {
+						case_patterns = List.map run case.case_patterns;
+						case_expr = (in_value := false; run (mk_block case.case_expr))
+					}) switch.switch_cases;
+					switch_default = Option.map (fun e -> in_value := false; run (mk_block e)) switch.switch_default;
+				} in
+				{ e with eexpr = TSwitch switch }
 			| TFor (v,cond,e1) ->
 				{ e with eexpr = TFor(v, run cond, (in_value := false; run (mk_block e1))) }
 			| TTry (e, ve_l) ->

+ 13 - 21
src/codegen/gencommon/closuresToClass.ml

@@ -19,7 +19,6 @@
 open Option
 open Common
 open Globals
-open Codegen
 open Texpr.Builder
 open Ast
 open Type
@@ -278,9 +277,8 @@ let traverse gen ?tparam_anon_decl ?tparam_anon_acc (handle_anon_func:texpr->tfu
 
 let rec get_type_params acc t =
 	match t with
-		| TInst(( { cl_kind = KTypeParameter constraints } as cl), []) ->
-			let params = List.fold_left get_type_params acc constraints in
-			List.filter (fun t -> not (List.memq t acc)) (cl :: params) @ acc;
+		| TInst(( { cl_kind = KTypeParameter _ } as cl), []) ->
+			if List.memq cl acc then acc else cl :: acc
 		| TFun (params,tret) ->
 			List.fold_left get_type_params acc ( tret :: List.map (fun (_,_,t) -> t) params )
 		| TDynamic None ->
@@ -291,10 +289,7 @@ let rec get_type_params acc t =
 				get_type_params acc ( Abstract.get_underlying_type a pl)
 		| TAnon a ->
 			PMap.fold (fun cf acc ->
-				let params = List.map (fun tp -> match follow tp.ttp_type with
-					| TInst(c,_) -> c
-					| _ -> die "" __LOC__) cf.cf_params
-				in
+				let params = List.map (fun tp -> tp.ttp_class) cf.cf_params in
 				List.filter (fun t -> not (List.memq t params)) (get_type_params acc cf.cf_type)
 			) a.a_fields acc
 		| TType(_, [])
@@ -398,7 +393,7 @@ let configure gen ft =
 		in
 
 		(*let cltypes = List.map (fun cl -> (snd cl.cl_path, TInst(map_param cl, []) )) tparams in*)
-		let cltypes = List.map (fun cl -> mk_type_param (snd cl.cl_path) (TInst(cl, [])) None) tparams in
+		let cltypes = List.map (fun cl -> mk_type_param cl TPHType None None) tparams in
 
 		(* create a new class that extends abstract function class, with a ctor implementation that will setup all captured variables *)
 		let cfield = match gen.gcurrent_classfield with
@@ -615,14 +610,10 @@ let configure gen ft =
 
 			let monos = List.map (fun t -> apply_params types (List.map (fun _ -> t_dynamic) types) t) monos in
 
-			let same_cl t1 t2 = match follow t1, follow t2 with
-				| TInst(c,_), TInst(c2,_) -> c == c2
-				| _ -> false
-			in
-			let passoc = List.map2 (fun tp m -> tp.ttp_type,m) types monos in
+			let passoc = List.map2 (fun tp m -> tp.ttp_class,m) types monos in
 			let cltparams = List.map (fun tp ->
 				try
-					snd (List.find (fun (t2,_) -> same_cl tp.ttp_type t2) passoc)
+					snd (List.find (fun (t2,_) -> tp.ttp_class == t2) passoc)
 				with | Not_found -> tp.ttp_type) cls.cl_params
 			in
 			{ e with eexpr = TNew(cls, cltparams, List.rev captured) }
@@ -1080,7 +1071,7 @@ struct
 			let cl = parent_func_class in
 			let pos = cl.cl_pos in
 
-			let rec mk_dyn_call arity api =
+			let mk_dyn_call arity api =
 				let zero = make_float gen.gcon.basic "0.0" pos in
 				let rec loop i acc =
 					if i = 0 then
@@ -1099,7 +1090,10 @@ struct
 			let mk_invoke_switch i api =
 				let t = TFun (func_sig_i i, t_dynamic) in
 				(* case i: return this.invokeX_o(0, 0, 0, 0, 0, ... arg[0], args[1]....); *)
-				[make_int gen.gcon.basic i pos], mk_return (mk (TCall(mk_this (iname i false) t, mk_dyn_call i api)) t_dynamic pos)
+				{
+					case_patterns = [make_int gen.gcon.basic i pos];
+					case_expr = mk_return (mk (TCall(mk_this (iname i false) t, mk_dyn_call i api)) t_dynamic pos)
+				}
 			in
 			let rec loop_cases api arity acc =
 				if arity < 0 then
@@ -1148,11 +1142,9 @@ struct
 						epos = pos;
 					} in
 
+					let switch = mk_switch switch_cond (loop_cases api !max_arity []) (Some(make_throw (mk_arg_exception "Too many arguments" pos) pos)) true in
 					{
-						eexpr = TSwitch(
-							switch_cond,
-							loop_cases api !max_arity [],
-							Some(make_throw (mk_arg_exception "Too many arguments" pos) pos));
+						eexpr = TSwitch switch;
 						etype = basic.tvoid;
 						epos = pos;
 					}

+ 5 - 5
src/codegen/gencommon/dynamicFieldAccess.ml

@@ -33,7 +33,7 @@ open Gencommon
 
 	(TODO: should it be separated?)
 	As a plus, the default implementation adds something that doesn't hurt anybody, it looks for
-	TAnon with Statics / EnumStatics field accesses and transforms them into real static calls.
+	TAnon with ClassStatics / EnumStatics field accesses and transforms them into real static calls.
 	This means it will take this
 
 	var m = Math;
@@ -58,8 +58,8 @@ let priority = solve_deps name [DAfter DynamicOperators.priority]
 *)
 let configure gen (is_dynamic:texpr->Type.tfield_access->bool) (change_expr:texpr->texpr->string->texpr option->bool->texpr) (call_expr:texpr->texpr->string->texpr list->texpr) =
 	let is_nondynamic_tparam fexpr f = match follow fexpr.etype with
-		| TInst({ cl_kind = KTypeParameter(tl) }, _) ->
-			List.exists (fun t -> not (is_dynamic { fexpr with etype = t } f)) tl
+		| TInst({ cl_kind = KTypeParameter(ttp) }, _) ->
+			List.exists (fun t -> not (is_dynamic { fexpr with etype = t } f)) (get_constraints ttp)
 		| _ -> false
 	in
 
@@ -68,8 +68,8 @@ let configure gen (is_dynamic:texpr->Type.tfield_access->bool) (change_expr:texp
 		(* class types *)
 		| TField(fexpr, f) when is_nondynamic_tparam fexpr f ->
 			(match follow fexpr.etype with
-				| TInst( ({ cl_kind = KTypeParameter(tl) } as tp_cl), tp_tl) ->
-					let t = apply_params tp_cl.cl_params tp_tl (List.find (fun t -> not (is_dynamic { fexpr with etype = t } f)) tl) in
+				| TInst( ({ cl_kind = KTypeParameter(ttp) } as tp_cl), tp_tl) ->
+					let t = apply_params tp_cl.cl_params tp_tl (List.find (fun t -> not (is_dynamic { fexpr with etype = t } f)) (get_constraints ttp)) in
 					{ e with eexpr = TField(mk_cast t (run fexpr), f) }
 				| _ -> Globals.die "" __LOC__)
 

+ 0 - 1
src/codegen/gencommon/dynamicOperators.ml

@@ -19,7 +19,6 @@
 open Common
 open Ast
 open Type
-open Codegen
 open Texpr.Builder
 open Gencommon
 

+ 2 - 3
src/codegen/gencommon/enumToClass.ml

@@ -20,7 +20,6 @@ open Common
 open Globals
 open Ast
 open Type
-open Codegen
 open Texpr.Builder
 open Gencommon
 
@@ -103,7 +102,7 @@ struct
 			| _ -> ());
 		let c_types =
 			if handle_type_params then
-				List.map (fun tp -> {tp with ttp_type=TInst (map_param (get_cl_t tp.ttp_type), [])}) en.e_params
+				List.map clone_param en.e_params
 			else
 				[]
 		in
@@ -121,7 +120,7 @@ struct
 				| TFun(params,ret) ->
 					let dup_types =
 						if handle_type_params then
-							List.map (fun tp -> {tp with ttp_type = TInst (map_param (get_cl_t tp.ttp_type), [])}) en.e_params
+							List.map clone_param en.e_params
 						else
 							[]
 					in

+ 0 - 1
src/codegen/gencommon/enumToClass2.ml

@@ -18,7 +18,6 @@
 *)
 open Common
 open Ast
-open Codegen
 open Texpr.Builder
 open Type
 open Gencommon

+ 18 - 6
src/codegen/gencommon/expressionUnwrap.ml

@@ -170,8 +170,12 @@ let rec expr_stat_map fn (expr:texpr) =
 			{ expr with eexpr = TIf(fn cond, eif, eelse) }
 		| TWhile(cond, block, flag) ->
 			{ expr with eexpr = TWhile(fn cond, block, flag) }
-		| TSwitch(cond, el_block_l, default) ->
-			{ expr with eexpr = TSwitch( fn cond, List.map (fun (el,block) -> (List.map fn el, block)) el_block_l, default ) }
+		| TSwitch switch ->
+			let switch = { switch with
+				switch_subject = fn switch.switch_subject;
+				switch_cases = List.map (fun case -> {case with case_patterns = List.map fn case.case_patterns}) switch.switch_cases;
+			} in
+			{ expr with eexpr = TSwitch switch }
 		| TReturn(eopt) ->
 			{ expr with eexpr = TReturn(Option.map fn eopt) }
 		| TThrow (texpr) ->
@@ -361,8 +365,12 @@ let rec apply_assign assign_fun right =
 	match right.eexpr with
 		| TBlock el ->
 			{ right with eexpr = TBlock(apply_assign_block assign_fun el) }
-		| TSwitch (cond, elblock_l, default) ->
-			{ right with eexpr = TSwitch(cond, List.map (fun (el,block) -> (el, mk_get_block assign_fun block)) elblock_l, Option.map (mk_get_block assign_fun) default) }
+		| TSwitch switch ->
+			let switch = { switch with
+				switch_cases = List.map (fun case -> {case with case_expr = mk_get_block assign_fun case.case_expr}) switch.switch_cases;
+				switch_default = Option.map (mk_get_block assign_fun) switch.switch_default;
+			} in
+			{ right with eexpr = TSwitch switch }
 		| TTry (block, catches) ->
 			{ right with eexpr = TTry(mk_get_block assign_fun block, List.map (fun (v,block) -> (v,mk_get_block assign_fun block) ) catches) }
 		| TIf (cond,eif,eelse) ->
@@ -621,8 +629,12 @@ let configure gen =
 			{ e with eexpr = TBlock block }
 		| TTry (block, catches) ->
 			{ e with eexpr = TTry(traverse (mk_block block), List.map (fun (v,block) -> (v, traverse (mk_block block))) catches) }
-		| TSwitch (cond,el_e_l, default) ->
-			{ e with eexpr = TSwitch(cond, List.map (fun (el,e) -> (el, traverse (mk_block e))) el_e_l, Option.map (fun e -> traverse (mk_block e)) default) }
+		| TSwitch switch ->
+			let switch = { switch with
+				switch_cases = List.map (fun case -> {case with case_expr = traverse (mk_block case.case_expr)}) switch.switch_cases;
+				switch_default = Option.map (fun e -> traverse (mk_block e)) switch.switch_default;
+			} in
+			{ e with eexpr = TSwitch switch }
 		| TWhile (cond,block,flag) ->
 			{e with eexpr = TWhile(cond,traverse (mk_block block), flag) }
 		| TIf (cond, eif, eelse) ->

+ 1 - 1
src/codegen/gencommon/filterClosures.ml

@@ -28,7 +28,7 @@ open Gencommon
 	not via reflection and not to be called instantly
 
 	dependencies:
-		must run after DynamicFieldAccess, so any TAnon { Statics / EnumStatics } will be changed to the corresponding TTypeExpr
+		must run after DynamicFieldAccess, so any TAnon { ClassStatics / EnumStatics } will be changed to the corresponding TTypeExpr
 *)
 let name = "filter_closures"
 let priority = solve_deps name [DAfter DynamicFieldAccess.priority]

+ 1 - 2
src/codegen/gencommon/fixOverrides.ml

@@ -19,7 +19,6 @@
 open Option
 open Common
 open Type
-open Codegen
 open Gencommon
 
 (* ******************************************* *)
@@ -161,7 +160,7 @@ let run ~explicit_fn_name ~get_vmtype gen =
 			in
 			List.iter (fun (iface,itl) -> loop_iface iface itl) c.cl_implements;
 			(* now go through all overrides, *)
-			let rec check_f f =
+			let check_f f =
 				(* find the first declared field *)
 				let is_overload = has_class_field_flag f CfOverload in
 				let decl = if is_overload then

+ 14 - 12
src/codegen/gencommon/gencommon.ml

@@ -60,7 +60,6 @@ open Globals
 open Option
 open Printf
 open ExtString
-open Codegen
 open Overloads
 
 (* ******************************************* *)
@@ -132,7 +131,7 @@ let path_of_md_def md_def =
 		| _ -> md_def.m_path
 
 let debug_type t = (s_type (print_context())) t
-let debug_expr = s_expr debug_type
+let debug_expr = s_expr_ast true "" debug_type
 
 let debug_mode = ref false
 let trace s = if !debug_mode then print_endline s else ()
@@ -147,7 +146,7 @@ let anon_class t =
 	match follow t with
 	| TAnon anon ->
 		(match !(anon.a_status) with
-		| Statics cl -> Some (TClassDecl cl)
+		| ClassStatics cl -> Some (TClassDecl cl)
 		| EnumStatics e -> Some (TEnumDecl e)
 		| AbstractStatics a -> Some (TAbstractDecl a)
 		| _ -> None)
@@ -161,7 +160,7 @@ let anon_class t =
 	| TAnon anon ->
 		(match !(anon.a_status) with
 			| EnumStatics e -> TEnumDecl e
-			| Statics cl -> TClassDecl cl
+			| ClassStatics cl -> TClassDecl cl
 			| AbstractStatics a -> TAbstractDecl a
 			| _ -> die "" __LOC__)
 	| TLazy f -> t_to_md (lazy_type f)
@@ -627,11 +626,11 @@ let new_ctx con =
 		gadd_type = (fun md should_filter ->
 			if should_filter then begin
 				gen.gtypes_list <- md :: gen.gtypes_list;
-				gen.gmodules <- { m_id = alloc_mid(); m_path = (t_path md); m_types = [md]; m_statics = None; m_extra = module_extra "" "" 0. MFake [] } :: gen.gmodules;
+				gen.gmodules <- { m_id = alloc_mid(); m_path = (t_path md); m_types = [md]; m_statics = None; m_extra = module_extra "" "" 0. MFake gen.gcon.compilation_step [] } :: gen.gmodules;
 				Hashtbl.add gen.gtypes (t_path md) md;
 			end else gen.gafter_filters_ended <- (fun () ->
 				gen.gtypes_list <- md :: gen.gtypes_list;
-				gen.gmodules <- { m_id = alloc_mid(); m_path = (t_path md); m_types = [md]; m_statics = None; m_extra = module_extra "" "" 0. MFake [] } :: gen.gmodules;
+				gen.gmodules <- { m_id = alloc_mid(); m_path = (t_path md); m_types = [md]; m_statics = None; m_extra = module_extra "" "" 0. MFake gen.gcon.compilation_step [] } :: gen.gmodules;
 				Hashtbl.add gen.gtypes (t_path md) md;
 			) :: gen.gafter_filters_ended;
 		);
@@ -730,9 +729,9 @@ let run_filters_from gen t filters =
 		()
 
 let run_filters gen =
-	let last_error = gen.gcon.error in
+	let last_error = gen.gcon.error_ext in
 	let has_errors = ref false in
-	gen.gcon.error <- (fun ?(depth=0) msg pos -> has_errors := true; last_error ~depth msg pos);
+	gen.gcon.error_ext <- (fun err -> has_errors := true; last_error err);
 	(* first of all, we have to make sure that the filters won't trigger a major Gc collection *)
 	let t = Timer.timer ["gencommon_filters"] in
 	(if Common.defined gen.gcon Define.GencommonDebug then debug_mode := true else debug_mode := false);
@@ -820,7 +819,7 @@ let run_filters gen =
 
 	reorder_modules gen;
 	t();
-	if !has_errors then raise (Abort("Compilation aborted with errors",null_pos))
+	if !has_errors then abort "Compilation aborted with errors" null_pos
 
 (* ******************************************* *)
 (* basic generation module that source code compilation implementations can use *)
@@ -1138,11 +1137,14 @@ let mk_class_field ?(static = false) name t public pos kind params =
 (* this helper just duplicates the type parameter class, which is assumed that cl is. *)
 (* This is so we can use class parameters on function parameters, without running the risk of name clash *)
 (* between both *)
-let map_param cl =
+let clone_param ttp =
+	let cl = ttp.ttp_class in
 	let ret = mk_class cl.cl_module (fst cl.cl_path, snd cl.cl_path ^ "_c") cl.cl_pos null_pos in
 	ret.cl_implements <- cl.cl_implements;
 	ret.cl_kind <- cl.cl_kind;
-	ret
+	let ttp = mk_type_param ret ttp.ttp_host ttp.ttp_default ttp.ttp_constraints in
+	ret.cl_kind <- KTypeParameter ttp;
+	ttp
 
 let get_cl_t t =
 	match follow t with | TInst (cl,_) -> cl | _ -> die "" __LOC__
@@ -1275,7 +1277,7 @@ let rec field_access gen (t:t) (field:string) : (tfield_access) =
 				FNotFound)
 		| TAnon anon ->
 			(try match !(anon.a_status) with
-				| Statics cl ->
+				| ClassStatics cl ->
 					let cf = PMap.find field cl.cl_statics in
 					FClassField(cl, List.map (fun _ -> t_dynamic) cl.cl_params, cl, cf, true, cf.cf_type, cf.cf_type)
 				| EnumStatics e ->

+ 0 - 1
src/codegen/gencommon/initFunction.ml

@@ -18,7 +18,6 @@
 *)
 open Common
 open Type
-open Codegen
 open Texpr.Builder
 open Gencommon
 

+ 9 - 11
src/codegen/gencommon/overloadingConstructor.ml

@@ -19,7 +19,6 @@
 open Option
 open Common
 open Type
-open Codegen
 open Gencommon
 
 (* ******************************************* *)
@@ -114,16 +113,15 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type =
 	| false ->
 		let static_ctor_name = make_static_ctor_name cl in
 		(* create the static constructor *)
-		let ctor_types = List.map (fun tp -> {tp with ttp_type = TInst(map_param (get_cl_t tp.ttp_type), [])}) cl.cl_params in
+		let ctor_types = List.map clone_param cl.cl_params in
 		let ctor_type_params = extract_param_types ctor_types in
-		List.iter (function {ttp_type=TInst(c,[])} -> (
-			match c.cl_kind with
-			| KTypeParameter (hd :: tail) ->
-				let before = hd :: tail in
-				let after = List.map (apply_params cl.cl_params ctor_type_params) (before) in
-				c.cl_kind <- KTypeParameter(after)
-			| _ -> ())
-		| _ -> ()) ctor_types;
+		List.iter (fun ttp -> match get_constraints ttp with
+			| [] ->
+				()
+			| before ->
+				let after = List.map (apply_params cl.cl_params ctor_type_params) before in
+				ttp.ttp_constraints <- Some (lazy after)
+		) ctor_types;
 		let me = alloc_var "__hx_this" (TInst(cl, extract_param_types ctor_types)) in
 		add_var_flag me VCaptured;
 
@@ -237,7 +235,7 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type =
 
 (* makes constructors that only call super() for the 'ctor' argument *)
 let clone_ctors com ctor sup stl cl =
-	let rec clone cf =
+	let clone cf =
 		let ncf = mk_class_field "new" (apply_params sup.cl_params stl cf.cf_type) (has_class_field_flag cf CfPublic) cf.cf_pos cf.cf_kind cf.cf_params in
 		if Meta.has Meta.Protected cf.cf_meta then
 			ncf.cf_meta <- (Meta.Protected,[],ncf.cf_pos) :: ncf.cf_meta;

+ 18 - 16
src/codegen/gencommon/realTypeParams.ml

@@ -20,7 +20,6 @@ open Option
 open Common
 open Ast
 open Type
-open Codegen
 open Texpr.Builder
 open Gencommon
 
@@ -91,7 +90,7 @@ let rec has_type_params t =
 			List.exists (fun (n,o,t) -> has_type_params t) args || has_type_params ret
 		| _ -> false
 
-let rec follow_all_md md =
+let follow_all_md md =
 	let t = match md with
 		| TClassDecl { cl_kind = KAbstractImpl a } ->
 			TAbstract(a, extract_param_types a.a_params)
@@ -309,10 +308,9 @@ let set_hxgeneric gen md =
 		if not ret then begin
 			match md with
 			| TClassDecl c ->
-				let set_hxgeneric tp = match follow tp.ttp_type with
-					| TInst(c,_) ->
-						c.cl_meta <- (Meta.NativeGeneric, [], c.cl_pos) :: c.cl_meta
-					| _ -> ()
+				let set_hxgeneric tp =
+					let c = tp.ttp_class in
+					c.cl_meta <- (Meta.NativeGeneric, [], c.cl_pos) :: c.cl_meta
 				in
 				List.iter set_hxgeneric c.cl_params;
 				let rec handle_field cf =
@@ -366,7 +364,7 @@ module RealTypeParamsModf =
 struct
 
 	let set_only_hxgeneric gen =
-		let rec run md =
+		let run md =
 			match md with
 				| TTypeDecl _ | TAbstractDecl _ -> md
 				| _ -> ignore (set_hxgeneric gen md); md
@@ -401,7 +399,7 @@ struct
 
 		let rec loop curcls params level reverse_params =
 			if (level <> 0 || (has_class_flag curcls CInterface) || (has_class_flag curcls CAbstract) ) && params <> [] && is_hxgeneric (TClassDecl curcls) then begin
-				let cparams = List.map (fun tp -> {tp with ttp_type=TInst (map_param (get_cl_t tp.ttp_type), [])}) curcls.cl_params in
+				let cparams = List.map clone_param curcls.cl_params in
 				let name = get_cast_name curcls in
 				if not (PMap.mem name cl.cl_fields) then begin
 					let reverse_params = List.map (apply_params curcls.cl_params params) reverse_params in
@@ -460,7 +458,7 @@ struct
 	let create_cast_cfield gen cl name =
 		reset_temps();
 		let basic = gen.gcon.basic in
-		let cparams = List.map (fun tp -> {tp with ttp_type = TInst (map_param (get_cl_t tp.ttp_type), [])}) cl.cl_params in
+		let cparams = List.map clone_param cl.cl_params in
 		let cfield = mk_class_field name (TFun([], t_dynamic)) false cl.cl_pos (Method MethNormal) cparams in
 		let params = extract_param_types cparams in
 
@@ -522,7 +520,10 @@ struct
 						t_cf
 						pos
 				in
-				[make_string gen.gcon.basic cf.cf_name pos], expr
+				{
+					case_patterns = [make_string gen.gcon.basic cf.cf_name pos];
+					case_expr = expr;
+				}
 			) fields
 		in
 
@@ -567,10 +568,11 @@ struct
 						(
 							(* default: Reflect.setField(new_me, field, Reflect.field(this, field)) *)
 							let edef = gen.gtools.r_set_field basic.tvoid local_new_me local_field (gen.gtools.r_field false basic.tvoid this local_field) in
-							if fields <> [] then
+							if fields <> [] then begin
 								(* switch(field) { ... } *)
-								mk (TSwitch (local_field, fields_to_cases fields, Some edef)) basic.tvoid pos
-							else
+								let switch = mk_switch local_field (fields_to_cases fields) (Some edef) true in
+								mk (TSwitch switch) basic.tvoid pos
+							end else
 								edef;
 						)
 					]) basic.tvoid pos,
@@ -587,7 +589,7 @@ struct
 	let create_static_cast_cf gen iface cf =
 		let p = iface.cl_pos in
 		let basic = gen.gcon.basic in
-		let cparams = List.map (fun tp -> {tp with ttp_name = "To_" ^ tp.ttp_name;ttp_type = TInst (map_param (get_cl_t tp.ttp_type), [])}) cf.cf_params in
+		let cparams = List.map clone_param cf.cf_params in
 		let me_type = TInst(iface,[]) in
 		let cfield = mk_class_field ~static:true "__hx_cast" (TFun(["me",false,me_type], t_dynamic)) false iface.cl_pos (Method MethNormal) (cparams) in
 		let params = extract_param_types cparams in
@@ -634,7 +636,7 @@ struct
 		let implement_stub_cast cthis iface tl =
 			let name = get_cast_name iface in
 			if not (PMap.mem name cthis.cl_fields) then begin
-				let cparams = List.map (fun tp -> {tp with ttp_name = "To_" ^ tp.ttp_name;ttp_type = TInst(map_param (get_cl_t tp.ttp_type), [])}) iface.cl_params in
+				let cparams = List.map clone_param iface.cl_params in
 				let field = mk_class_field name (TFun([],t_dynamic)) false iface.cl_pos (Method MethNormal) cparams in
 				let this = { eexpr = TConst TThis; etype = TInst(cthis, extract_param_types cthis.cl_params); epos = cthis.cl_pos } in
 				field.cf_expr <- Some {
@@ -651,7 +653,7 @@ struct
 			end
 		in
 
-		let rec run md =
+		let run md =
 			match md with
 				| TClassDecl ({ cl_params = [] } as cl) ->
 					(* see if we're implementing any generic interface *)

+ 32 - 26
src/codegen/gencommon/reflectionCFs.ml

@@ -20,7 +20,6 @@ open Option
 open Common
 open Ast
 open Type
-open Codegen
 open Texpr.Builder
 open Gencommon
 open ClosuresToClass
@@ -1000,11 +999,14 @@ let implement_get_set ctx cl =
 			(if fields <> [] then has_fields := true);
 			let cases = List.map (fun (names, cf) ->
 				(if names = [] then Globals.die "" __LOC__);
-				(List.map (switch_case ctx pos) names, do_field cf cf.cf_type)
+				{
+					case_patterns = List.map (switch_case ctx pos) names;
+					case_expr = do_field cf cf.cf_type;
+				}
 			) fields in
 			let default = Some(do_default()) in
-
-			mk_block { eexpr = TSwitch(local_switch_var, cases, default); etype = basic.tvoid; epos = pos }
+			let switch = mk_switch local_switch_var cases default true in
+			mk_block { eexpr = TSwitch switch; etype = basic.tvoid; epos = pos }
 		in
 
 		let is_override = match cl.cl_super with
@@ -1177,26 +1179,27 @@ let implement_invokeField ctx slow_invoke cl =
 				let t = apply_params cf.cf_params (List.map (fun _ -> t_dynamic) cf.cf_params) cf.cf_type in
 				mk_this_call_raw cf.cf_name t params
 			in
-			(cases,
-				mk_return (
-					mk_this_call cf (List.map (fun (name,optional,t) ->
-						let idx = make_int ctx.rcf_gen.gcon.basic !i pos in
-						let ret = { eexpr = TArray(dyn_arg_local, idx); etype = t_dynamic; epos = pos } in
-						let ret =
-							if ExtType.is_rest t then
-								{ ret with eexpr = TUnop(Spread,Prefix,{ ret with etype = t }) }
+			{
+				case_patterns = cases;
+				case_expr =	mk_return (
+						mk_this_call cf (List.map (fun (name,optional,t) ->
+							let idx = make_int ctx.rcf_gen.gcon.basic !i pos in
+							let ret = { eexpr = TArray(dyn_arg_local, idx); etype = t_dynamic; epos = pos } in
+							let ret =
+								if ExtType.is_rest t then
+									{ ret with eexpr = TUnop(Spread,Prefix,{ ret with etype = t }) }
+								else
+									ret
+							in
+							incr i;
+							if optional then
+								let condition = binop OpGt dyn_arg_length idx ctx.rcf_gen.gcon.basic.tbool pos in
+								mk (TIf (condition, ret, Some (make_null ret.etype pos))) ret.etype pos
 							else
 								ret
-						in
-						incr i;
-						if optional then
-							let condition = binop OpGt dyn_arg_length idx ctx.rcf_gen.gcon.basic.tbool pos in
-							mk (TIf (condition, ret, Some (make_null ret.etype pos))) ret.etype pos
-						else
-							ret
-					) (fst (get_fun (cf.cf_type))))
-				)
-			)
+						) (fst (get_fun (cf.cf_type))))
+					)
+			}
 		in
 
 		let cfs = List.filter (fun (_,cf) -> match cf.cf_kind with
@@ -1209,7 +1212,10 @@ let implement_invokeField ctx slow_invoke cl =
 			| [] -> cases
 			| _ ->
 				let ncases = List.map (fun cf -> switch_case ctx pos cf.cf_name) old in
-				( ncases, mk_return (slow_invoke this (mk_local (fst (List.hd field_args)) pos) (mk_local dynamic_arg pos)) ) :: cases
+				{
+					case_patterns = ncases;
+					case_expr = mk_return (slow_invoke this (mk_local (fst (List.hd field_args)) pos) (mk_local dynamic_arg pos))
+				} :: cases
 		in
 
 		let default = if !is_override then
@@ -1235,9 +1241,9 @@ let implement_invokeField ctx slow_invoke cl =
 				epos = pos
 			} )
 		in
-
+		let switch = mk_switch (mk_local switch_var pos) cases (Some default) true in
 		{
-			eexpr = TSwitch(mk_local switch_var pos, cases, Some default);
+			eexpr = TSwitch switch;
 			etype = basic.tvoid;
 			epos = pos;
 		}
@@ -1483,7 +1489,7 @@ struct
 	let priority = min_dep +. 10.
 
 	let configure gen baseclass baseinterface basedynamic =
-		let rec run md =
+		let run md =
 			if is_hxgen md then
 				match md with
 				| TClassDecl cl when (has_class_flag cl CInterface) && cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && cl.cl_path <> basedynamic.cl_path ->

+ 4 - 10
src/codegen/gencommon/renameTypeParameters.ml

@@ -41,22 +41,16 @@ let run types =
 		end else found_types := PMap.add name true !found_types
 	in
 
-	let get_cls t =
-		match follow t with
-		| TInst(cl,_) -> cl
-		| _ -> Globals.die "" __LOC__
-	in
-
 	let iter_types tp =
-		let cls = get_cls tp.ttp_type in
+		let cls = tp.ttp_class in
 		let orig = cls.cl_path in
 		check_type (snd orig) (fun name -> cls.cl_path <- (fst orig, name))
 	in
 
 	let save_params save params =
 		List.fold_left (fun save tp ->
-			let cls = get_cls tp.ttp_type in
-			(cls.cl_path,tp.ttp_type) :: save) save params
+			let cls = tp.ttp_class in
+			(cls.cl_path,tp.ttp_class) :: save) save params
 	in
 
 	List.iter (function
@@ -82,7 +76,7 @@ let run types =
 				cl.cl_restore <- (fun () ->
 					res();
 					List.iter (fun (path,t) ->
-						let cls = get_cls t in
+						let cls = t in
 						cls.cl_path <- path) save
 				);
 			end

+ 15 - 10
src/codegen/gencommon/switchToIf.ml

@@ -18,7 +18,6 @@
 *)
 open Common
 open Type
-open Codegen
 open Gencommon
 
 (* ******************************************* *)
@@ -42,7 +41,7 @@ let configure gen (should_convert:texpr->bool) =
 	let basic = gen.gcon.basic in
 	let rec run e =
 		match e.eexpr with
-		| TSwitch (cond, cases, default) when should_convert e ->
+		| TSwitch ({switch_subject = cond;switch_cases = cases;switch_default = default} as switch) when should_convert e ->
 			let cond_etype, should_cache =
 				match gen.gfollow#run_f cond.etype with
 				| TAbstract ({ a_path = [], "Null" }, [t]) ->
@@ -56,8 +55,13 @@ let configure gen (should_convert:texpr->bool) =
 					cond.etype, false
 			in
 
-			if should_cache && not (should_convert { e with eexpr = TSwitch ({ cond with etype = cond_etype }, cases, default) }) then begin
-				{ e with eexpr = TSwitch (mk_cast cond_etype (run cond), List.map (fun (cs,e) -> (List.map run cs, run e)) cases, Option.map run default) }
+			if should_cache && not (should_convert { e with eexpr = TSwitch {switch with switch_subject = { cond with etype = cond_etype }}}) then begin
+				let switch = { switch with
+					switch_subject = mk_cast cond_etype (run cond);
+					switch_cases = List.map (fun case -> {case_patterns = List.map run case.case_patterns;case_expr = run case.case_expr}) cases;
+					switch_default = Option.map run default;
+				} in
+				{ e with eexpr = TSwitch switch }
 			end else begin
 				let local, fst_block =
 					match cond.eexpr, should_cache with
@@ -96,9 +100,9 @@ let configure gen (should_convert:texpr->bool) =
 
 				let rec loop cases =
 					match cases with
-					| (conds, e) :: [] ->
+					| {case_patterns = conds;case_expr = e} :: [] ->
 						mk (TIf (mk_many_cond conds, run e, Option.map run default)) e.etype e.epos
-					| (conds, e) :: tl ->
+					| {case_patterns = conds;case_expr = e} :: tl ->
 						mk (TIf (mk_many_cond conds, run e, Some (loop tl))) e.etype e.epos
 					| [] ->
 						match default with
@@ -120,7 +124,7 @@ let configure gen (should_convert:texpr->bool) =
 			`switch e { case MyEnum.A: ...; case MyEnum.B: ...; }`, which is supported natively
 			by some target languages like Java and C#.
 		*)
-		| TSwitch (cond, cases, default) ->
+		| TSwitch ({switch_subject = cond;switch_cases = cases;switch_default = default} as switch)  ->
 			begin
 				try
 					match (simplify_expr cond).eexpr with
@@ -138,7 +142,7 @@ let configure gen (should_convert:texpr->bool) =
 						PMap.iter (fun _ ef -> Hashtbl.add fields ef.ef_index ef) real_enum.e_constrs;
 
 						let enum_expr = Texpr.Builder.make_typeexpr (TEnumDecl real_enum) e.epos in
-						let cases = List.map (fun (patterns, body) ->
+						let cases = List.map (fun {case_patterns = patterns; case_expr = body} ->
 							let patterns = List.map (fun e ->
 								match e.eexpr with
 								| TConst (TInt i) ->
@@ -148,9 +152,10 @@ let configure gen (should_convert:texpr->bool) =
 									raise Not_found
 							) patterns in
 							let body = run body in
-							patterns, body
+							{ case_patterns = patterns;case_expr = body}
 						) cases in
-						{ e with eexpr = TSwitch (enum, cases, Option.map run default) }
+						let switch = mk_switch enum cases (Option.map run default) switch.switch_exhaustive in
+						{ e with eexpr = TSwitch switch }
 					| _ ->
 						raise Not_found
 				with Not_found ->

+ 6 - 2
src/codegen/gencommon/unnecessaryCastsRemoval.ml

@@ -40,8 +40,12 @@ let rec traverse e =
 		{ e with eexpr = TBlock bl }
 	| TTry (block, catches) ->
 		{ e with eexpr = TTry(traverse (mk_block block), List.map (fun (v,block) -> (v, traverse (mk_block block))) catches) }
-	| TSwitch (cond,el_e_l, default) ->
-		{ e with eexpr = TSwitch(cond, List.map (fun (el,e) -> (el, traverse (mk_block e))) el_e_l, Option.map (fun e -> traverse (mk_block e)) default) }
+	| TSwitch switch ->
+		let switch = { switch with
+			switch_cases = List.map (fun case -> { case with case_expr = traverse (mk_block e)}) switch.switch_cases;
+			switch_default = Option.map (fun e -> traverse (mk_block e)) switch.switch_default;
+		} in
+		{ e with eexpr = TSwitch switch }
 	| TWhile (cond,block,flag) ->
 		{e with eexpr = TWhile(cond,traverse (mk_block block), flag) }
 	| TIf (cond, eif, eelse) ->

+ 16 - 9
src/codegen/gencommon/unreachableCodeEliminationSynf.ml

@@ -16,7 +16,6 @@
 	along with this program; if not, write to the Free Software
 	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *)
-open Common
 open Ast
 open Type
 open Gencommon
@@ -178,17 +177,25 @@ let init gen java_mode =
 					has_break := last_has_break;
 					return_loop { expr with eexpr = TWhile(cond,block,flag) } Normal
 				end
-			| TSwitch(cond, el_e_l, None) ->
-				{ expr with eexpr = TSwitch(cond, List.map (fun (el, e) -> (el, handle_case (process_expr e))) el_e_l, None) }, Normal
-			| TSwitch(cond, el_e_l, Some def) ->
+			| TSwitch ({switch_default = None} as switch) ->
+				let switch = { switch with
+					switch_cases = List.map (fun case -> {case with case_expr = handle_case (process_expr case.case_expr)}) switch.switch_cases;
+					switch_default = None;
+				} in
+				{ expr with eexpr = TSwitch switch }, Normal
+			| TSwitch ({switch_default = Some def} as switch) ->
 				let def, k = process_expr def in
 				let def = handle_case (def, k) in
 				let k = ref k in
-				let ret = { expr with eexpr = TSwitch(cond, List.map (fun (el, e) ->
-					let e, ek = process_expr e in
-					k := aggregate_kind !k ek;
-					(el, handle_case (e, ek))
-				) el_e_l, Some def) } in
+				let switch = { switch with
+					switch_cases = List.map (fun case ->
+						let e, ek = process_expr case.case_expr in
+						k := aggregate_kind !k ek;
+						{case with case_expr = handle_case (e, ek)}
+					) switch.switch_cases;
+					switch_default = Some def;
+				} in
+				let ret = { expr with eexpr = TSwitch switch } in
 				ret, !k
 			| TTry (e, catches) ->
 				let e, k = process_expr e in

+ 37 - 35
src/codegen/java.ml

@@ -46,7 +46,7 @@ let is_haxe_keyword = function
 let jname_to_hx name =
 	let name =
 		if name <> "" && (String.get name 0 < 'A' || String.get name 0 > 'Z') then
-			Char.escaped (Char.uppercase (String.get name 0)) ^ String.sub name 1 (String.length name - 1)
+			Char.escaped (Char.uppercase_ascii (String.get name 0)) ^ String.sub name 1 (String.length name - 1)
 		else
 			name
 	in
@@ -81,7 +81,7 @@ let lookup_jclass com path =
 		| Some p -> Some p
 	) com.native_libs.java_libs None
 
-let mk_type_path ctx path params =
+let mk_type_path ctx path params p =
 	let name, sub = try
 		let p, _ = String.split (snd path) "$" in
 		jname_to_hx p, Some (jname_to_hx (snd path))
@@ -104,31 +104,31 @@ let mk_type_path ctx path params =
 		| _ ->
 			pack, sub, name
 	in
-	CTPath {
+	make_ptp_ct {
 		tpackage = pack;
 		tname = name;
 		tparams = params;
 		tsub = sub;
-	}
+	} p
 
 let has_tparam name params = List.exists(fun (n,_,_) -> n = name) params
 
 let rec convert_arg ctx p arg =
 	match arg with
-	| TAny | TType (WSuper, _) -> TPType (mk_type_path ctx ([], "Dynamic") [],null_pos)
+	| TAny | TType (WSuper, _) -> TPType (mk_type_path ctx ([], "Dynamic") [] p,null_pos)
 	| TType (_, jsig) -> TPType (convert_signature ctx p jsig,null_pos)
 
 and convert_signature ctx p jsig =
 	match jsig with
-	| TByte -> mk_type_path ctx (["java"; "types"], "Int8") []
-	| TChar -> mk_type_path ctx (["java"; "types"], "Char16") []
-	| TDouble -> mk_type_path ctx ([], "Float") []
-	| TFloat -> mk_type_path ctx ([], "Single") []
-	| TInt -> mk_type_path ctx ([], "Int") []
-	| TLong -> mk_type_path ctx (["haxe"], "Int64") []
-	| TShort -> mk_type_path ctx (["java"; "types"], "Int16") []
-	| TBool -> mk_type_path ctx ([], "Bool") []
-	| TObject ( (["haxe";"root"], name), args ) -> mk_type_path ctx ([], name) (List.map (convert_arg ctx p) args)
+	| TByte -> mk_type_path ctx (["java"; "types"], "Int8") [] p
+	| TChar -> mk_type_path ctx (["java"; "types"], "Char16") [] p
+	| TDouble -> mk_type_path ctx ([], "Float") [] p
+	| TFloat -> mk_type_path ctx ([], "Single") [] p
+	| TInt -> mk_type_path ctx ([], "Int") [] p
+	| TLong -> mk_type_path ctx (["haxe"], "Int64") [] p
+	| TShort -> mk_type_path ctx (["java"; "types"], "Int16") [] p
+	| TBool -> mk_type_path ctx ([], "Bool") [] p
+	| TObject ( (["haxe";"root"], name), args ) -> mk_type_path ctx ([], name) (List.map (convert_arg ctx p) args) p
 	(** nullable types *)
 	(* replaced from Null<Type> to the actual abstract type to fix #2738 *)
 	(* | TObject ( (["java";"lang"], "Integer"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx ([], "Int") []) ] *)
@@ -140,34 +140,34 @@ and convert_signature ctx p jsig =
 	(* | TObject ( (["java";"lang"], "Short"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx (["java";"types"], "Int16") []) ] *)
 	(* | TObject ( (["java";"lang"], "Long"), [] ) -> mk_type_path ctx ([], "Null") [ TPType (mk_type_path ctx (["haxe"], "Int64") []) ] *)
 	(** other std types *)
-	| TObject ( (["java";"lang"], "Object"), [] ) -> mk_type_path ctx ([], "Dynamic") []
-	| TObject ( (["java";"lang"], "String"), [] ) -> mk_type_path ctx ([], "String") []
-	| TObject ( (["java";"lang"], "Enum"), [_] ) -> mk_type_path ctx ([], "EnumValue") []
+	| TObject ( (["java";"lang"], "Object"), [] ) -> mk_type_path ctx ([], "Dynamic") [] p
+	| TObject ( (["java";"lang"], "String"), [] ) -> mk_type_path ctx ([], "String") [] p
+	| TObject ( (["java";"lang"], "Enum"), [_] ) -> mk_type_path ctx ([], "EnumValue") [] p
 	(** other types *)
 	| TObject ( path, [] ) ->
 		(match lookup_jclass ctx.jcom path with
-		| Some (jcl, _, _) -> mk_type_path ctx path (List.map (fun _ -> convert_arg ctx p TAny) jcl.ctypes)
-		| None -> mk_type_path ctx path [])
-	| TObject ( path, args ) -> mk_type_path ctx path (List.map (convert_arg ctx p) args)
+		| Some (jcl, _, _) -> mk_type_path ctx path (List.map (fun _ -> convert_arg ctx p TAny) jcl.ctypes) p
+		| None -> mk_type_path ctx path [] p)
+	| TObject ( path, args ) -> mk_type_path ctx path (List.map (convert_arg ctx p) args) p
 	| TObjectInner (pack, (name, params) :: inners) ->
 			let actual_param = match List.rev inners with
 			| (_, p) :: _ -> p
 			| _ -> die "" __LOC__ in
-			mk_type_path ctx (pack, name ^ "$" ^ String.concat "$" (List.map fst inners)) (List.map (fun param -> convert_arg ctx p param) actual_param)
+			mk_type_path ctx (pack, name ^ "$" ^ String.concat "$" (List.map fst inners)) (List.map (fun param -> convert_arg ctx p param) actual_param) p
 	| TObjectInner (pack, inners) -> die "" __LOC__
-	| TArray (jsig, _) -> mk_type_path ctx (["java"], "NativeArray") [ TPType (convert_signature ctx p jsig,null_pos) ]
+	| TArray (jsig, _) -> mk_type_path ctx (["java"], "NativeArray") [ TPType (convert_signature ctx p jsig,null_pos) ] p
 	| TMethod _ -> JReader.error "TMethod cannot be converted directly into Complex Type"
 	| TTypeParameter s -> (match ctx.jtparams with
 		| cur :: others ->
 			if has_tparam s cur then
-				mk_type_path ctx ([], s) []
+				mk_type_path ctx ([], s) [] p
 			else begin
 				if ctx.jcom.verbose && not(List.exists (has_tparam s) others) then print_endline ("Type parameter " ^ s ^ " was not found while building type!");
-				mk_type_path ctx ([], "Dynamic") []
+				mk_type_path ctx ([], "Dynamic") [] p
 			end
 		| _ ->
 			if ctx.jcom.verbose then print_endline ("Empty type parameter stack!");
-			mk_type_path ctx ([], "Dynamic") [])
+			mk_type_path ctx ([], "Dynamic") [] p)
 
 let convert_constant ctx p const =
 	Option.map_default (function
@@ -196,7 +196,7 @@ let convert_param ctx p parent param =
 			tp_meta = [];
 		}
 
-let get_type_path ctx ct = match ct with | CTPath p -> p | _ -> die "" __LOC__
+let get_type_path ctx ct = match ct with | CTPath ptp -> ptp | _ -> die "" __LOC__
 
 let is_override field =
 	List.exists (function | AttrVisibleAnnotations [{ ann_type = TObject( (["java";"lang"], "Override"), _ ) }] -> true | _ -> false) field.jf_attributes
@@ -308,6 +308,7 @@ let convert_java_enum ctx p pe =
 		List.iter (fun jsig ->
 			match convert_signature ctx p jsig with
 				| CTPath path ->
+					let path = path.path in
 					cff_meta := (Meta.Throws, [Ast.EConst (Ast.String (s_type_path (path.tpackage,path.tname),SDoubleQuotes)), p],p) :: !cff_meta
 				| _ -> ()
 		) field.jf_throws;
@@ -360,13 +361,13 @@ let convert_java_enum ctx p pe =
 						let hx_sig =
 							match s with
 							| TArray (s1,_) when !is_varargs && !i = args_count && is_eligible_for_haxe_rest_args s1 ->
-								mk_type_path ctx (["haxe"], "Rest") [TPType (convert_signature ctx p s1,null_pos)]
+								mk_type_path ctx (["haxe"], "Rest") [TPType (convert_signature ctx p s1,null_pos)] p
 							| _ ->
 								convert_signature ctx null_pos s
 						in
 						(local_names !i,null_pos), false, [], Some(hx_sig,null_pos), None
 					) args in
-					let t = Option.map_default (convert_signature ctx p) (mk_type_path ctx ([], "Void") []) ret in
+					let t = Option.map_default (convert_signature ctx p) (mk_type_path ctx ([], "Void") [] p) ret in
 					cff_access := (AOverload,p) :: !cff_access;
 					let types = List.map (function
 						| (name, Some ext, impl) ->
@@ -485,7 +486,7 @@ let convert_java_enum ctx p pe =
 			(match jc.csuper with
 				| TObject( (["java";"lang"], "Object"), _ ) -> ()
 				| TObject( (["haxe";"lang"], "HxObject"), _ ) -> meta := (Meta.HxGen,[],p) :: !meta
-				| _ -> flags := HExtends (get_type_path ctx (convert_signature ctx p jc.csuper),null_pos) :: !flags
+				| _ -> flags := HExtends (get_type_path ctx (convert_signature ctx p jc.csuper)) :: !flags
 			);
 
 			List.iter (fun i ->
@@ -493,9 +494,9 @@ let convert_java_enum ctx p pe =
 				| TObject ( (["haxe";"lang"], "IHxObject"), _ ) -> meta := (Meta.HxGen,[],p) :: !meta
 				| _ -> flags :=
 					if !is_interface then
-						HExtends (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags
+						HExtends (get_type_path ctx (convert_signature ctx p i)) :: !flags
 					else
-						HImplements (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags
+						HImplements (get_type_path ctx (convert_signature ctx p i)) :: !flags
 			) jc.cinterfaces;
 
 			let fields = ref [] in
@@ -520,6 +521,7 @@ let convert_java_enum ctx p pe =
 					match convert_signature ctx p jsig with
 						| CTPath path ->
 							let pos = { p with pfile = p.pfile ^ " (" ^ f.jf_name ^" @:throws)" } in
+							let path = path.path in
 							EImport( List.map (fun s -> s,pos) (path.tpackage @ [path.tname]), INormal )
 						| _ -> die "" __LOC__
 				) f.jf_throws
@@ -1069,19 +1071,19 @@ class virtual java_library com name file_path = object(self)
 														d_params = c.d_params;
 														d_meta = [];
 														d_flags = [];
-														d_data = CTPath {
+														d_data = make_ptp_th_null {
 															tpackage = pack;
 															tname = snd path;
 															tparams = List.map (fun tp ->
-																TPType (CTPath {
+																TPType (make_ptp_th_null {
 																	tpackage = [];
 																	tname = fst tp.tp_name;
 																	tparams = [];
 																	tsub = None;
-																},null_pos)
+																})
 															) c.d_params;
 															tsub = Some(fst c.d_name);
-														},null_pos;
+														};
 													} in
 													inner_alias := SS.add alias_name !inner_alias;
 													alias_list := (alias_def, pos) :: !alias_list;

+ 69 - 33
src/codegen/javaModern.ml

@@ -18,6 +18,7 @@ module AccessFlags = struct
 		| MAbstract
 		| MStrict
 		| MSynthetic
+		| MAnnotation
 		| MEnum
 
 	let to_int = function
@@ -34,6 +35,7 @@ module AccessFlags = struct
 		| MAbstract -> 0x400
 		| MStrict -> 0x800
 		| MSynthetic -> 0x1000
+		| MAnnotation -> 0x2000
 		| MEnum -> 0x4000
 
 	let has_flag b flag =
@@ -422,7 +424,7 @@ module JReaderModern = struct
 			let len = read_i32 ch in
 			ignore(IO.nread_string ch len); (* code *)
 			let len = read_ui16 ch in
-			for i = 0 to len - 1 do
+			for _ = 0 to len - 1 do
 				ignore(IO.nread_string ch 8);
 			done; (* exceptions *)
 			let attribs = parse_attributes consts ch in
@@ -555,7 +557,7 @@ module PathConverter = struct
 	let jname_to_hx name =
 		let name =
 			if name <> "" && (String.get name 0 < 'A' || String.get name 0 > 'Z') then
-				Char.escaped (Char.uppercase (String.get name 0)) ^ String.sub name 1 (String.length name - 1)
+				Char.escaped (Char.uppercase_ascii (String.get name 0)) ^ String.sub name 1 (String.length name - 1)
 			else
 				name
 		in
@@ -615,46 +617,48 @@ type java_lib_ctx = {
 module SignatureConverter = struct
 	open PathConverter
 
-	let mk_type_path path params =
+	let mk_type_path path params p =
 		let pack,(mname,name) = jpath_to_hx path in
-		match mname with
+		let path = match mname with
 		| None ->
-			CTPath {
+			{
 				tpackage = pack;
 				tname = name;
 				tparams = params;
 				tsub = None;
 			}
 		| Some mname ->
-			CTPath {
+			{
 				tpackage = pack;
 				tname = mname;
 				tparams = params;
 				tsub = Some name;
 			}
+		in
+		make_ptp_ct path p
 
-	let ct_type_param name = CTPath {
+	let ct_type_param name = make_ptp_ct_null {
 		tpackage = [];
 		tname = name;
 		tparams = [];
 		tsub = None
 	}
 
-	let ct_void = CTPath {
+	let ct_void = make_ptp_ct_null {
 		tpackage = [];
 		tname = "Void";
 		tparams = [];
 		tsub = None;
 	}
 
-	let ct_dynamic = CTPath {
+	let ct_dynamic = make_ptp_ct_null {
 		tpackage = [];
 		tname = "Dynamic";
 		tparams = [];
 		tsub = None;
 	}
 
-	let ct_string = CTPath {
+	let ct_string = make_ptp_ct_null {
 		tpackage = [];
 		tname = "String";
 		tparams = [];
@@ -663,33 +667,33 @@ module SignatureConverter = struct
 
 	let rec convert_arg ctx p arg =
 		match arg with
-		| TAny | TType (WSuper, _) -> TPType (mk_type_path ([], "Dynamic") [],p)
+		| TAny | TType (WSuper, _) -> TPType (mk_type_path ([], "Dynamic") [] p,p)
 		| TType (_, jsig) -> TPType (convert_signature ctx p jsig,p)
 
 	and convert_signature ctx p jsig =
 		match jsig with
-		| TByte -> mk_type_path (["java"; "types"], "Int8") []
-		| TChar -> mk_type_path (["java"; "types"], "Char16") []
-		| TDouble -> mk_type_path ([], "Float") []
-		| TFloat -> mk_type_path ([], "Single") []
-		| TInt -> mk_type_path ([], "Int") []
-		| TLong -> mk_type_path (["haxe"], "Int64") []
-		| TShort -> mk_type_path (["java"; "types"], "Int16") []
-		| TBool -> mk_type_path ([], "Bool") []
-		| TObject ( (["haxe";"root"], name), args ) -> mk_type_path ([], name) (List.map (convert_arg ctx p) args)
-		| TObject ( (["java";"lang"], "Object"), [] ) -> mk_type_path ([], "Dynamic") []
-		| TObject ( (["java";"lang"], "String"), [] ) -> mk_type_path ([], "String") []
-		| TObject ( (["java";"lang"], "Enum"), [_] ) -> mk_type_path ([], "EnumValue") []
+		| TByte -> mk_type_path (["java"; "types"], "Int8") [] p
+		| TChar -> mk_type_path (["java"; "types"], "Char16") [] p
+		| TDouble -> mk_type_path ([], "Float") [] p
+		| TFloat -> mk_type_path ([], "Single") [] p
+		| TInt -> mk_type_path ([], "Int") [] p
+		| TLong -> mk_type_path (["haxe"], "Int64") [] p
+		| TShort -> mk_type_path (["java"; "types"], "Int16") [] p
+		| TBool -> mk_type_path ([], "Bool") [] p
+		| TObject ( (["haxe";"root"], name), args ) -> mk_type_path ([], name) (List.map (convert_arg ctx p) args) p
+		| TObject ( (["java";"lang"], "Object"), [] ) -> mk_type_path ([], "Dynamic") [] p
+		| TObject ( (["java";"lang"], "String"), [] ) -> mk_type_path ([], "String") [] p
+		| TObject ( (["java";"lang"], "Enum"), [_] ) -> mk_type_path ([], "EnumValue") [] p
 		| TObject ( path, [] ) ->
-			mk_type_path path []
-		| TObject ( path, args ) -> mk_type_path path (List.map (convert_arg ctx p) args)
+			mk_type_path path [] p
+		| TObject ( path, args ) -> mk_type_path path (List.map (convert_arg ctx p) args) p
 		| TObjectInner (pack, (name, params) :: inners) ->
 			let actual_param = match List.rev inners with
 			| (_, p) :: _ -> p
 			| _ -> die "" __LOC__ in
-			mk_type_path (pack, name ^ "$" ^ String.concat "$" (List.map fst inners)) (List.map (fun param -> convert_arg ctx p param) actual_param)
+			mk_type_path (pack, name ^ "$" ^ String.concat "$" (List.map fst inners)) (List.map (fun param -> convert_arg ctx p param) actual_param) p
 		| TObjectInner (pack, inners) -> die "" __LOC__
-		| TArray (jsig, _) -> mk_type_path (["java"], "NativeArray") [ TPType (convert_signature ctx p jsig,p) ]
+		| TArray (jsig, _) -> mk_type_path (["java"], "NativeArray") [ TPType (convert_signature ctx p jsig,p) ] p
 		| TMethod _ -> failwith "TMethod cannot be converted directly into Complex Type"
 		| TTypeParameter s ->
 			try
@@ -698,7 +702,7 @@ module SignatureConverter = struct
 				ct_dynamic
 end
 
-let get_type_path ct = match ct with | CTPath p -> p | _ -> die "" __LOC__
+let get_type_path ct = match ct with | CTPath ptp -> ptp | _ -> die "" __LOC__
 
 module Converter = struct
 
@@ -706,6 +710,27 @@ module Converter = struct
 	open PathConverter
 	open SignatureConverter
 
+	let extract_retention_policy l =
+		let rec loop2 l = match l with
+			| [] ->
+				None
+			| ann :: l ->
+				match ann.ann_type,ann.ann_elements with
+				| TObject((["java";"lang";"annotation"],"Retention"),_),[("value",ValEnum(_,name))] ->
+					Some name
+				| _ ->
+					loop2 l
+		in
+		let rec loop l = match l with
+			| [] ->
+				None
+			| AttrVisibleAnnotations l :: _ ->
+				loop2 l
+			| _ :: l ->
+				loop l
+		in
+		loop l
+
 	let convert_type_parameter ctx (name,extends,implements) p =
 		let jsigs = match extends with
 			| Some jsig -> jsig :: implements
@@ -867,7 +892,7 @@ module Converter = struct
 						let hx_sig =
 							match jsig with
 							| TArray (jsig1,_) when is_varargs && i + 1 = args_count && is_eligible_for_haxe_rest_args jsig1 ->
-								mk_type_path (["haxe"], "Rest") [TPType (convert_signature ctx p jsig1,p)]
+								mk_type_path (["haxe"], "Rest") [TPType (convert_signature ctx p jsig1,p)] p
 							| _ ->
 								convert_signature ctx p jsig
 						in
@@ -908,15 +933,17 @@ module Converter = struct
 		let is_interface = AccessFlags.has_flag jc.jc_flags MInterface in
 		if is_interface then add_flag HInterface
 		else if AccessFlags.has_flag jc.jc_flags MAbstract then add_flag HAbstract;
+		let is_annotation = AccessFlags.has_flag jc.jc_flags MAnnotation in
 		begin match jc.jc_super with
 			| TObject(([],""),_)
 			| TObject((["java";"lang"],"Object"),_) ->
-				()
+				if is_annotation then
+					add_flag (HExtends (make_ptp {tpackage = ["java";"lang";"annotation"]; tname = "Annotation"; tsub = None; tparams = []} p))
 			| jsig ->
-				add_flag (HExtends (get_type_path (convert_signature ctx p jsig),p))
+				add_flag (HExtends (get_type_path (convert_signature ctx p jsig)))
 		end;
 		List.iter (fun jsig ->
-			let path = (get_type_path (convert_signature ctx p jsig),p) in
+			let path = get_type_path (convert_signature ctx p jsig) in
 			if is_interface then
 				add_flag (HExtends path)
 			else
@@ -957,6 +984,15 @@ module Converter = struct
 		end;
 		let _,class_name = jname_to_hx (snd jc.jc_path) in
 		add_meta (Meta.Native, [EConst (String (s_type_path jc.jc_path,SDoubleQuotes) ),p],p);
+		if is_annotation then begin
+			let args = match extract_retention_policy jc.jc_attributes with
+				| None ->
+					[]
+				| Some v ->
+					[EConst (String(v,SDoubleQuotes)),p]
+			in
+			add_meta (Meta.Annotation,args,p)
+		end;
 		let d = {
 			d_name = (class_name,p);
 			d_doc = None;
@@ -1056,4 +1092,4 @@ class java_library_modern com name file_path = object(self)
 		build path
 
 	method get_data = ()
-end
+end

+ 4 - 13
src/codegen/overloads.ml

@@ -1,6 +1,6 @@
 open Globals
 open Type
-open Typecore
+open FieldCallCandidate
 
 let same_overload_args ?(get_vmtype) t1 t2 f1 f2 =
 	let f_transform = match get_vmtype with
@@ -13,13 +13,10 @@ let same_overload_args ?(get_vmtype) t1 t2 f1 f2 =
 			| [],[] ->
 				true
 			| tp1 :: params1,tp2 :: params2 ->
-				let constraints_equal t1 t2 = match follow t1,follow t2 with
-					| TInst({cl_kind = KTypeParameter tl1},_),TInst({cl_kind = KTypeParameter tl2},_) ->
-						Ast.safe_for_all2 f_eq tl1 tl2
-					| _ ->
-						false
+				let constraints_equal ttp1 ttp2 = 
+					Ast.safe_for_all2 f_eq (get_constraints ttp2) (get_constraints ttp2)
 				in
-				tp1.ttp_name = tp2.ttp_name && constraints_equal tp1.ttp_type tp2.ttp_type && loop params1 params2
+				tp1.ttp_name = tp2.ttp_name && constraints_equal tp1 tp2 && loop params1 params2
 			| [],_
 			| _,[] ->
 				false
@@ -219,12 +216,6 @@ struct
 		| r :: ret ->
 			rm_duplicates (r :: acc) ret
 
-	let s_options rated =
-		String.concat ",\n" (List.map (fun ((elist,t,_),rate) ->
-			"( " ^ (String.concat "," (List.map (fun(e,_) -> s_expr (s_type (print_context())) e) elist)) ^ " ) => " ^
-			"( " ^ (String.concat "," (List.map (fun (i,i2) -> string_of_int i ^ ":" ^ string_of_int i2) rate)) ^ " ) => " ^ (s_type (print_context()) t)
-		) rated)
-
 	let count_optionals t =
 		match follow t with
 		| TFun(args,_) ->

+ 21 - 17
src/codegen/swfLoader.ml

@@ -33,7 +33,7 @@ let lowercase_pack pack =
 			let name =
 				let fchar = String.get name 0 in
 				if fchar >= 'A' && fchar <= 'Z' then
-					(String.make 1 (Char.lowercase fchar)) ^ String.sub name 1 (String.length name - 1)
+					(String.make 1 (Char.lowercase_ascii fchar)) ^ String.sub name 1 (String.length name - 1)
 				else
 					name
 			in
@@ -42,18 +42,19 @@ let lowercase_pack pack =
 	loop [] pack
 
 
-let tp_dyn = { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; }
+let tp_dyn = make_ptp { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; } null_pos
 
 let ct_dyn = CTPath tp_dyn
 
-let ct_rest = CTPath {
+let ct_rest = make_ptp_ct_null {
 	tpackage = ["haxe"];
 	tname = "Rest";
 	tparams = [TPType (ct_dyn,null_pos)];
 	tsub = None;
 }
 
-let rec make_tpath = function
+let rec make_tpath x =
+	let path = match x with
 	| HMPath (pack,name) ->
 		let pdyn = ref false in
 		let pack, name = match pack, name with
@@ -116,7 +117,10 @@ let rec make_tpath = function
 		die "" __LOC__
 	| HMParams (t,params) ->
 		let params = List.map (fun t -> TPType (CTPath (make_tpath t),null_pos)) params in
-		{ (make_tpath t) with tparams = params }
+		let ptp = make_tpath t in
+		{ptp.path with tparams = params}
+	in
+	make_ptp path null_pos
 
 let make_topt = function
 	| None -> tp_dyn
@@ -126,7 +130,7 @@ let make_type t = CTPath (make_topt t)
 
 let make_dyn_type t =
 	match make_topt t with
-	| { tpackage = ["flash";"utils"]; tname = ("Object"|"Function") } -> make_type None
+	| {path = { tpackage = ["flash";"utils"]; tname = ("Object"|"Function") }} -> make_type None
 	| o -> CTPath o
 
 let is_valid_path com pack name =
@@ -142,7 +146,7 @@ let is_valid_path com pack name =
 	loop com.load_extern_type || (try ignore(Common.find_file com file); true with Not_found -> false)
 
 let build_class com c file =
-	let path = make_tpath c.hlc_name in
+	let path = (make_tpath c.hlc_name).path in
 	let pos = { pfile = file ^ "@" ^ s_type_path (path.tpackage,path.tname); pmin = 0; pmax = 0 } in
 	match path with
 	| { tpackage = ["flash";"utils"]; tname = ("Object"|"Function") } ->
@@ -162,7 +166,7 @@ let build_class com c file =
 	let flags = (match c.hlc_super with
 		| None | Some (HMPath ([],"Object")) -> flags
 		| Some (HMPath ([],"Function")) -> flags (* found in AIR SDK *)
-		| Some s -> HExtends (make_tpath s,null_pos) :: flags
+		| Some s -> HExtends (make_tpath s) :: flags
 	) in
 	let flags = List.map (fun i ->
 		let i = (match i with
@@ -176,9 +180,9 @@ let build_class com c file =
 			| HMPath _ -> i
 			| _ -> die "" __LOC__
 		) in
-		if c.hlc_interface then HExtends (make_tpath i,null_pos) else HImplements (make_tpath i,null_pos)
+		if c.hlc_interface then HExtends (make_tpath i) else HImplements (make_tpath i)
 	) (Array.to_list c.hlc_implements) @ flags in
-	let flags = if c.hlc_sealed || Common.defined com Define.FlashStrict then flags else HImplements (tp_dyn,null_pos) :: flags in
+	let flags = if c.hlc_sealed || Common.defined com Define.FlashStrict then flags else HImplements tp_dyn :: flags in
 	(* make fields *)
 	let getters = Hashtbl.create 0 in
 	let setters = Hashtbl.create 0 in
@@ -209,7 +213,7 @@ let build_class com c file =
 		) in
 		if flags = [] then acc else
 		let flags = if stat then (AStatic,null_pos) :: flags else flags in
-		let name = (make_tpath f.hlf_name).tname in
+		let name = (make_tpath f.hlf_name).path.tname in
 		let mk_meta() =
 			List.map (fun (s,cl) -> s, List.map (fun c -> EConst c,pos) cl, pos) (!meta)
 		in
@@ -395,8 +399,8 @@ let build_class com c file =
 			| [] -> []
 			| f :: l ->
 				match f.cff_kind with
-				| FVar (Some ((CTPath { tpackage = []; tname = ("String" | "Int" | "UInt")} as real_t),_),None)
-				| FProp (("default",_),("never",_),Some ((CTPath { tpackage = []; tname = ("String" | "Int" | "UInt")}) as real_t,_),None) when List.mem_assoc AStatic f.cff_access ->
+				| FVar (Some ((CTPath {path = { tpackage = []; tname = ("String" | "Int" | "UInt")}} as real_t),_),None)
+				| FProp (("default",_),("never",_),Some ((CTPath { path = { tpackage = []; tname = ("String" | "Int" | "UInt")}}) as real_t,_),None) when List.mem_assoc AStatic f.cff_access ->
 					(match !real_type with
 					| None ->
 						real_type := Some real_t
@@ -454,10 +458,10 @@ let build_class com c file =
 let extract_data (_,tags) =
 	let t = Timer.timer ["read";"swf"] in
 	let h = Hashtbl.create 0 in
-	let rec loop_field f =
+	let loop_field f =
 		match f.hlf_kind with
 		| HFClass c ->
-			let path = make_tpath f.hlf_name in
+			let path = (make_tpath f.hlf_name).path in
 			(match path with
 			| { tpackage = []; tname = "Float" | "Bool" | "Int" | "UInt" | "Dynamic" } -> ()
 			| { tpackage = _; tname = "MethodClosure" } -> ()
@@ -647,10 +651,10 @@ let remove_classes toremove lib l =
 					match t.tdata with
 					| TActionScript3 (h,data) ->
 						let data = As3hlparse.parse data in
-						let rec loop f =
+						let loop f =
 							match f.hlf_kind with
 							| HFClass _ ->
-								let path = make_tpath f.hlf_name in
+								let path = (make_tpath f.hlf_name).path in
 								not (List.mem (path.tpackage,path.tname) classes)
 							| _ -> true
 						in

+ 26 - 13
src/compiler/args.ml

@@ -2,8 +2,10 @@ open Globals
 open Common
 open CompilationContext
 
+let columns = lazy (match Terminal_size.get_columns () with None -> 80 | Some c -> c)
+
 let limit_string s offset =
-	let rest = 80 - offset in
+	let rest = (Lazy.force columns) - offset in
 	let words = ExtString.String.nsplit s " " in
 	let rec loop i words = match words with
 		| word :: words ->
@@ -40,7 +42,7 @@ let process_args arg_spec =
 
 let parse_args com =
 	let usage = Printf.sprintf
-		"Haxe Compiler %s - (C)2005-2022 Haxe Foundation\nUsage: haxe%s <target> [options] [hxml files and dot paths...]\n"
+		"Haxe Compiler %s - (C)2005-2024 Haxe Foundation\nUsage: haxe%s <target> [options] [hxml files and dot paths...]\n"
 		s_version_full (if Sys.os_type = "Win32" then ".exe" else "")
 	in
 	let actx = {
@@ -64,7 +66,10 @@ let parse_args com =
 	let add_deprecation s =
 		actx.deprecations <- s :: actx.deprecations
 	in
-	let add_native_lib file extern = actx.native_libs <- (file,extern) :: actx.native_libs in
+	let add_native_lib file extern kind =
+		let lib = create_native_lib file extern kind in
+		actx.native_libs <- lib :: actx.native_libs
+	in
 	let basic_args_spec = [
 		("Target",["--js"],["-js"],Arg.String (set_platform com Js),"<file>","generate JavaScript code into target file");
 		("Target",["--lua"],["-lua"],Arg.String (set_platform com Lua),"<file>","generate Lua code into target file");
@@ -98,6 +103,10 @@ let parse_args com =
 		("Target",["--hl"],["-hl"],Arg.String (fun file ->
 			set_platform com Hl file;
 		),"<file>","generate HashLink .hl bytecode or .c code into target file");
+		("Target",["--custom-target"],["-custom"],Arg.String (fun target ->
+			let name, path = try let split = ExtString.String.split target "=" in split with _ -> target, "" in
+			set_custom_target com name path;
+		),"<name[=path]>","generate code for a custom target");
 		("Target",[],["-x"], Arg.String (fun cl ->
 			let cpath = Path.parse_type_path cl in
 			(match com.main_class with
@@ -125,12 +134,16 @@ let parse_args com =
 			com.main_class <- Some cpath;
 			actx.classes <- cpath :: actx.classes
 		),"<class>","select startup class");
+		("Compilation",["-L";"--library"],["-lib"],Arg.String (fun _ -> ()),"<name[:ver]>","use a haxelib library");
 		("Compilation",["-D";"--define"],[],Arg.String (fun var ->
 			let flag, value = try let split = ExtString.String.split var "=" in (fst split, Some (snd split)) with _ -> var, None in
 			match value with
 				| Some value -> Common.external_define_value com flag value
 				| None -> Common.external_define com flag;
 		),"<var[=value]>","define a conditional compilation flag");
+		("Compilation",["--undefine"],[],Arg.String (fun var ->
+			Common.external_undefine com var
+		),"","remove a conditional compilation flag");
 		("Debug",["-v";"--verbose"],[],Arg.Unit (fun () ->
 			com.verbose <- true
 		),"","turn on verbose mode");
@@ -157,7 +170,7 @@ let parse_args com =
 				let all,max_length = Define.get_user_documentation_list com.user_defines in
 				let all = List.map (fun (n,doc) -> Printf.sprintf " %-*s: %s" max_length n (limit_string doc (max_length + 3))) all in
 				List.iter (fun msg -> com.print (msg ^ "\n")) all;
-				exit 0
+				raise Abort
 			)
 		),"","print help for all user defines");
 		("Miscellaneous",["--help-metas"],[], Arg.Unit (fun() ->
@@ -172,7 +185,7 @@ let parse_args com =
 				let all,max_length = Meta.get_user_documentation_list com.user_metas in
 				let all = List.map (fun (n,doc) -> Printf.sprintf " %-*s: %s" max_length n (limit_string doc (max_length + 3))) all in
 				List.iter (fun msg -> com.print (msg ^ "\n")) all;
-				exit 0
+				raise Abort
 			)
 		),"","print help for all user metadatas");
 	] in
@@ -196,22 +209,22 @@ let parse_args com =
 			Common.define com Define.FlashStrict
 		), "","more type strict flash API");
 		("Target-specific",["--swf-lib"],["-swf-lib"],Arg.String (fun file ->
-			add_native_lib file false;
+			add_native_lib file false SwfLib;
 		),"<file>","add the SWF library to the compiled SWF");
-		("Target-specific",["--neko-lib"],[],Arg.String (fun file ->
-			com.neko_libs <- file :: com.neko_libs
-		),"<file>","add the neko library");
+		("Target-specific",[],["--neko-lib-path"],Arg.String (fun dir ->
+			com.neko_lib_paths <- dir :: com.neko_lib_paths
+		),"<directory>","add the neko library path");
 		("Target-specific",["--swf-lib-extern"],["-swf-lib-extern"],Arg.String (fun file ->
-			add_native_lib file true;
+			add_native_lib file true SwfLib;
 		),"<file>","use the SWF library for type checking");
 		("Target-specific",["--java-lib"],["-java-lib"],Arg.String (fun file ->
-			add_native_lib file false;
+			add_native_lib file false JavaLib;
 		),"<file>","add an external JAR or directory of JAR files");
 		("Target-specific",["--java-lib-extern"],[],Arg.String (fun file ->
-			add_native_lib file true;
+			add_native_lib file true JavaLib;
 		),"<file>","use an external JAR or directory of JAR files for type checking");
 		("Target-specific",["--net-lib"],["-net-lib"],Arg.String (fun file ->
-			add_native_lib file false;
+			add_native_lib file false NetLib;
 		),"<file>[@std]","add an external .NET DLL file");
 		("Target-specific",["--net-std"],["-net-std"],Arg.String (fun file ->
 			Dotnet.add_net_std com file

+ 28 - 10
src/compiler/compilationContext.ml

@@ -7,6 +7,17 @@ type server_mode =
 	| SMListen of string
 	| SMConnect of string
 
+type native_lib_kind =
+	| NetLib
+	| JavaLib
+	| SwfLib
+
+type native_lib_arg = {
+	lib_file : string;
+	lib_kind : native_lib_kind;
+	lib_extern : bool;
+}
+
 type arg_context = {
 	mutable classes : Globals.path list;
 	mutable xml_out : string option;
@@ -20,7 +31,7 @@ type arg_context = {
 	mutable interp : bool;
 	mutable jvm_flag : bool;
 	mutable swf_version : bool;
-	mutable native_libs : (string * bool) list;
+	mutable native_libs : native_lib_arg list;
 	mutable raise_usage : unit -> unit;
 	mutable display_arg : string option;
 	mutable deprecations : string list;
@@ -44,7 +55,7 @@ and compilation_context = {
 
 type compilation_callbacks = {
 	before_anything : compilation_context -> unit;
-	after_arg_parsing : compilation_context -> unit;
+	after_target_init : compilation_context -> unit;
 	after_compilation : compilation_context -> unit;
 }
 
@@ -54,20 +65,27 @@ type server_api = {
 	cache : CompilationCache.t;
 	callbacks : compilation_callbacks;
 	on_context_create : unit -> int;
-	init_wait_socket : string -> int -> server_accept;
-	init_wait_connect : string -> int -> server_accept;
+	init_wait_socket : (Ipaddr.V4.t, Ipaddr.V6.t) Ipaddr.v4v6 -> int -> server_accept;
+	init_wait_connect : (Ipaddr.V4.t, Ipaddr.V6.t) Ipaddr.v4v6 -> int -> server_accept;
 	init_wait_stdio : unit -> server_accept;
 	wait_loop : bool -> server_accept -> int;
-	do_connect : string -> int -> string list -> unit;
+	do_connect : (Ipaddr.V4.t, Ipaddr.V6.t) Ipaddr.v4v6 -> int -> string list -> unit;
 }
 
 let message ctx msg =
 	ctx.messages <- msg :: ctx.messages
 
-let error ctx ?(depth=0) msg p =
-	message ctx (make_compiler_message msg p depth DKCompilerMessage Error);
+let error ctx ?(depth=0) ?(from_macro = false) msg p =
+	message ctx (make_compiler_message ~from_macro msg p depth DKCompilerMessage Error);
 	ctx.has_error <- true
 
-let located_error ctx ?(depth=0) msg =
-	message ctx (make_compiler_message (extract_located_msg msg) (extract_located_pos msg) depth DKCompilerMessage Error);
-	ctx.has_error <- true
+let error_ext ctx (err : Error.error) =
+	Error.recurse_error (fun depth err ->
+		error ~depth ~from_macro:err.err_from_macro ctx (Error.error_msg err.err_message) err.err_pos
+	) err
+
+let create_native_lib file extern kind = {
+	lib_file = file;
+	lib_extern = extern;
+	lib_kind = kind;
+}

+ 153 - 96
src/compiler/compiler.ml

@@ -2,25 +2,35 @@ open Globals
 open Common
 open CompilationContext
 
-let run_or_diagnose ctx f arg =
+let run_or_diagnose ctx f =
 	let com = ctx.com in
-	let handle_diagnostics msg kind =
+	let handle_diagnostics msg p kind =
 		ctx.has_error <- true;
-		add_diagnostics_message com msg kind Error;
-		DisplayOutput.emit_diagnostics ctx.com
+		add_diagnostics_message com msg p kind Error;
+		match com.report_mode with
+		| RMLegacyDiagnostics _ -> DisplayOutput.emit_legacy_diagnostics ctx.com
+		| RMDiagnostics _ -> DisplayOutput.emit_diagnostics ctx.com
+		| _ -> die "" __LOC__
 	in
 	if is_diagnostics com then begin try
-			f arg
+			f ()
 		with
-		| Error.Error(msg,p,_) ->
-			handle_diagnostics (Error.error_msg p msg) DKCompilerMessage
+		| Error.Error err ->
+			ctx.has_error <- true;
+			Error.recurse_error (fun depth err ->
+				add_diagnostics_message ~depth com (Error.error_msg err.err_message) err.err_pos DKCompilerMessage Error
+			) err;
+			(match com.report_mode with
+			| RMLegacyDiagnostics _ -> DisplayOutput.emit_legacy_diagnostics ctx.com
+			| RMDiagnostics _ -> DisplayOutput.emit_diagnostics ctx.com
+			| _ -> die "" __LOC__)
 		| Parser.Error(msg,p) ->
-			handle_diagnostics (located (Parser.error_msg msg) p) DKParserError
+			handle_diagnostics (Parser.error_msg msg) p DKParserError
 		| Lexer.Error(msg,p) ->
-			handle_diagnostics (located (Lexer.error_msg msg) p) DKParserError
+			handle_diagnostics (Lexer.error_msg msg) p DKParserError
 		end
 	else
-		f arg
+		f ()
 
 let run_command ctx cmd =
 	let t = Timer.timer ["command";cmd] in
@@ -67,14 +77,15 @@ let run_command ctx cmd =
 
 module Setup = struct
 	let initialize_target ctx com actx =
+		init_platform com;
 		let add_std dir =
 			com.class_path <- List.filter (fun s -> not (List.mem s com.std_path)) com.class_path @ List.map (fun p -> p ^ dir ^ "/_std/") com.std_path @ com.std_path
 		in
 		match com.platform with
 			| Cross ->
-				(* no platform selected *)
-				set_platform com Cross "";
 				"?"
+			| CustomTarget name ->
+				name
 			| Flash ->
 				let rec loop = function
 					| [] -> ()
@@ -138,13 +149,20 @@ module Setup = struct
 				"python"
 			| Hl ->
 				add_std "hl";
-				if not (Common.defined com Define.HlVer) then Define.define_value com.defines Define.HlVer (try Std.input_file (Common.find_file com "hl/hl_version") with Not_found -> die "" __LOC__);
+				if not (Common.defined com Define.HlVer) then begin
+					let hl_ver = try
+						Std.input_file (Common.find_file com "hl/hl_version")
+					with Not_found ->
+						failwith "The file hl_version could not be found. Please make sure HAXE_STD_PATH is set to the standard library corresponding to the used compiler version."
+					in
+					Define.define_value com.defines Define.HlVer hl_ver
+				end;
 				"hl"
 			| Eval ->
 				add_std "eval";
 				"eval"
 
-	let create_typer_context ctx native_libs =
+	let create_typer_context ctx macros native_libs =
 		let com = ctx.com in
 		Common.log com ("Classpath: " ^ (String.concat ";" com.class_path));
 		let buffer = Buffer.create 64 in
@@ -155,13 +173,12 @@ module Setup = struct
 		) com.defines.values;
 		Buffer.truncate buffer (Buffer.length buffer - 1);
 		Common.log com (Buffer.contents buffer);
-		Typecore.type_expr_ref := (fun ?(mode=MGet) ctx e with_type -> Typer.type_expr ~mode ctx e with_type);
-		List.iter (fun f -> f ()) (List.rev com.callbacks#get_before_typer_create);
+		com.callbacks#run com.error_ext com.callbacks#get_before_typer_create;
 		(* Native lib pass 1: Register *)
-		let fl = List.map (fun (file,extern) -> NativeLibraryHandler.add_native_lib com file extern) (List.rev native_libs) in
+		let fl = List.map (fun lib -> NativeLibraryHandler.add_native_lib com lib) (List.rev native_libs) in
 		(* Native lib pass 2: Initialize *)
 		List.iter (fun f -> f()) fl;
-		Typer.create com
+		TyperEntry.create com macros
 
 	let executable_path() =
 		Extc.executable_path()
@@ -188,18 +205,14 @@ module Setup = struct
 				let share_path = Filename.concat prefix_path "share" in
 				[
 					"";
-					Path.add_trailing_slash (Filename.concat lib_path "haxe/std");
-					Path.add_trailing_slash (Filename.concat lib_path "haxe/extraLibs");
 					Path.add_trailing_slash (Filename.concat share_path "haxe/std");
-					Path.add_trailing_slash (Filename.concat share_path "haxe/extraLibs");
+					Path.add_trailing_slash (Filename.concat lib_path "haxe/std");
 					Path.add_trailing_slash (Filename.concat base_path "std");
-					Path.add_trailing_slash (Filename.concat base_path "extraLibs")
 				]
 			else
 				[
 					"";
 					Path.add_trailing_slash (Filename.concat base_path "std");
-					Path.add_trailing_slash (Filename.concat base_path "extraLibs")
 				]
 
 	let setup_common_context ctx =
@@ -211,8 +224,10 @@ module Setup = struct
 		Common.define_value com Define.Haxe s_version;
 		Common.raw_define com "true";
 		Common.define_value com Define.Dce "std";
-		com.info <- (fun ?(depth=0) msg p -> message ctx (make_compiler_message msg p depth DKCompilerMessage Information));
-		com.warning <- (fun ?(depth=0) w options msg p ->
+		com.info <- (fun ?(depth=0) ?(from_macro=false) msg p ->
+			message ctx (make_compiler_message ~from_macro msg p depth DKCompilerMessage Information)
+		);
+		com.warning <- (fun ?(depth=0) ?(from_macro=false) w options msg p ->
 			match Warning.get_mode w (com.warning_options @ options) with
 			| WMEnable ->
 				let wobj = Warning.warning_obj w in
@@ -221,11 +236,12 @@ module Setup = struct
 				else
 					Printf.sprintf "(%s) %s" wobj.w_name msg
 				in
-				message ctx (make_compiler_message msg p depth DKCompilerMessage Warning)
+				message ctx (make_compiler_message ~from_macro msg p depth DKCompilerMessage Warning)
 			| WMDisable ->
 				()
 		);
-		com.error <- error ctx;
+		com.error_ext <- error_ext ctx;
+		com.error <- (fun ?(depth = 0) msg p -> com.error_ext (Error.make_error ~depth (Custom msg) p));
 		let filter_messages = (fun keep_errors predicate -> (List.filter (fun cm ->
 			(match cm.cm_severity with
 			| MessageSeverity.Error -> keep_errors;
@@ -243,83 +259,128 @@ module Setup = struct
 
 end
 
+let check_defines com =
+	if is_next com then begin
+		PMap.iter (fun k _ ->
+			try
+				let reason = Hashtbl.find Define.deprecation_lut k in
+				let p = { pfile = "-D " ^ k; pmin = -1; pmax = -1 } in
+				com.warning WDeprecatedDefine [] reason p
+			with Not_found ->
+				()
+		) com.defines.values
+	end
+
 (** Creates the typer context and types [classes] into it. *)
-let do_type ctx tctx actx =
-	let com = tctx.Typecore.com in
+let do_type ctx mctx actx display_file_dot_path macro_cache_enabled =
+	let com = ctx.com in
 	let t = Timer.timer ["typing"] in
 	let cs = com.cs in
 	CommonCache.maybe_add_context_sign cs com "before_init_macros";
-	com.stage <- CInitMacrosStart;
-	List.iter (MacroContext.call_init_macro tctx) (List.rev actx.config_macros);
-	com.stage <- CInitMacrosDone;
+	enter_stage com CInitMacrosStart;
+	ServerMessage.compiler_stage com;
+
+	let mctx = List.fold_left (fun mctx path ->
+		Some (MacroContext.call_init_macro ctx.com mctx path)
+	) mctx (List.rev actx.config_macros) in
+	enter_stage com CInitMacrosDone;
+	ServerMessage.compiler_stage com;
+	MacroContext.macro_enable_cache := macro_cache_enabled;
+
+	let macros = match mctx with None -> None | Some mctx -> mctx.g.macros in
+	let tctx = Setup.create_typer_context ctx macros actx.native_libs in
+	let display_file_dot_path = DisplayProcessing.maybe_load_display_file_before_typing tctx display_file_dot_path in
+	check_defines ctx.com;
 	CommonCache.lock_signature com "after_init_macros";
-	List.iter (fun f -> f ()) (List.rev com.callbacks#get_after_init_macros);
-	run_or_diagnose ctx (fun () ->
-		if com.display.dms_kind <> DMNone then DisplayTexpr.check_display_file tctx cs;
-		List.iter (fun cpath -> ignore(tctx.Typecore.g.Typecore.do_load_module tctx cpath null_pos)) (List.rev actx.classes);
-		Finalization.finalize tctx;
-	) ();
-	com.stage <- CTypingDone;
+	Option.may (fun mctx -> MacroContext.finalize_macro_api tctx mctx) mctx;
+	(try begin
+		com.callbacks#run com.error_ext com.callbacks#get_after_init_macros;
+		run_or_diagnose ctx (fun () ->
+			if com.display.dms_kind <> DMNone then DisplayTexpr.check_display_file tctx cs;
+			List.iter (fun cpath -> ignore(tctx.Typecore.g.Typecore.do_load_module tctx cpath null_pos)) (List.rev actx.classes);
+			Finalization.finalize tctx;
+		);
+	end with TypeloadParse.DisplayInMacroBlock ->
+		ignore(DisplayProcessing.load_display_module_in_macro tctx display_file_dot_path true)
+	);
+	enter_stage com CTypingDone;
+	ServerMessage.compiler_stage com;
 	(* If we are trying to find references, let's syntax-explore everything we know to check for the
 		identifier we are interested in. We then type only those modules that contain the identifier. *)
 	begin match com.display.dms_kind with
 		| (DMUsage _ | DMImplementation) -> FindReferences.find_possible_references tctx cs;
 		| _ -> ()
 	end;
-	t()
+	t();
+	(tctx, display_file_dot_path)
 
 let finalize_typing ctx tctx =
 	let t = Timer.timer ["finalize"] in
 	let com = ctx.com in
-	com.stage <- CFilteringStart;
-	let main, types, modules = run_or_diagnose ctx Finalization.generate tctx in
+	enter_stage com CFilteringStart;
+	ServerMessage.compiler_stage com;
+	let main, types, modules = run_or_diagnose ctx (fun () -> Finalization.generate tctx) in
 	com.main <- main;
 	com.types <- types;
 	com.modules <- modules;
 	t()
 
-let filter ctx tctx =
+let filter ctx tctx before_destruction =
 	let t = Timer.timer ["filters"] in
 	DeprecationCheck.run ctx.com;
-	Filters.run ctx.com tctx ctx.com.main;
+	run_or_diagnose ctx (fun () -> Filters.run tctx ctx.com.main before_destruction);
 	t()
 
-let compile ctx actx =
+let compile ctx actx callbacks =
 	let com = ctx.com in
 	(* Set up display configuration *)
 	DisplayProcessing.process_display_configuration ctx;
 	let display_file_dot_path = DisplayProcessing.process_display_file com actx in
+	let macro_cache_enabled = !MacroContext.macro_enable_cache in
+	MacroContext.macro_enable_cache := true;
+	let mctx = match com.platform with
+		| CustomTarget name ->
+			begin try
+				Some (MacroContext.call_init_macro com None (Printf.sprintf "%s.Init.init()" name))
+			with (Error.Error { err_message = Module_not_found ([pack],"Init") }) when pack = name ->
+				(* ignore if <target_name>.Init doesn't exist *)
+				None
+			end
+		| _ ->
+			None
+		in
 	(* Initialize target: This allows access to the appropriate std packages and sets the -D defines. *)
 	let ext = Setup.initialize_target ctx com actx in
-	com.config <- get_config com; (* make sure to adapt all flags changes defined after platform *)
+	update_platform_config com; (* make sure to adapt all flags changes defined after platform *)
+	callbacks.after_target_init ctx;
 	let t = Timer.timer ["init"] in
 	List.iter (fun f -> f()) (List.rev (actx.pre_compilation));
 	t();
-	com.stage <- CInitialized;
+	enter_stage com CInitialized;
+	ServerMessage.compiler_stage com;
 	if actx.classes = [([],"Std")] && not actx.force_typing then begin
 		if actx.cmds = [] && not actx.did_something then actx.raise_usage();
 	end else begin
 		(* Actual compilation starts here *)
-		let tctx = Setup.create_typer_context ctx actx.native_libs in
-		com.stage <- CTyperCreated;
-		let display_file_dot_path = DisplayProcessing.maybe_load_display_file_before_typing tctx display_file_dot_path in
-		begin try
-			do_type ctx tctx actx
-		with TypeloadParse.DisplayInMacroBlock ->
-			ignore(DisplayProcessing.load_display_module_in_macro tctx display_file_dot_path true);
-		end;
+		let (tctx,display_file_dot_path) = do_type ctx mctx actx display_file_dot_path macro_cache_enabled in
 		DisplayProcessing.handle_display_after_typing ctx tctx display_file_dot_path;
 		finalize_typing ctx tctx;
-		DisplayProcessing.handle_display_after_finalization ctx tctx display_file_dot_path;
-		filter ctx tctx;
+		if is_diagnostics com then
+			filter ctx tctx (fun () -> DisplayProcessing.handle_display_after_finalization ctx tctx display_file_dot_path)
+		else begin
+			DisplayProcessing.handle_display_after_finalization ctx tctx display_file_dot_path;
+			filter ctx tctx (fun () -> ());
+		end;
 		if ctx.has_error then raise Abort;
 		Generate.check_auxiliary_output com actx;
-		com.stage <- CGenerationStart;
+		enter_stage com CGenerationStart;
+		ServerMessage.compiler_stage com;
 		if not actx.no_output then Generate.generate ctx tctx ext actx;
-		com.stage <- CGenerationDone;
+		enter_stage com CGenerationDone;
+		ServerMessage.compiler_stage com;
 	end;
 	Sys.catch_break false;
-	List.iter (fun f -> f()) (List.rev com.callbacks#get_after_generation);
+	com.callbacks#run com.error_ext com.callbacks#get_after_generation;
 	if not actx.no_output then begin
 		List.iter (fun c ->
 			let r = run_command ctx c in
@@ -334,10 +395,8 @@ try
 with
 	| Abort ->
 		()
-	| Error.Fatal_error (m,depth) ->
-		located_error ~depth ctx m
-	| Common.Abort (m,p) ->
-		error ctx m p
+	| Error.Fatal_error err ->
+		error_ext ctx err
 	| Lexer.Error (m,p) ->
 		error ctx (Lexer.error_msg m) p
 	| Parser.Error (m,p) ->
@@ -350,16 +409,8 @@ with
 			error ctx (Printf.sprintf "You cannot access the %s package while %s (for %s)" pack (if pf = "macro" then "in a macro" else "targeting " ^ pf) (s_type_path m) ) p;
 			List.iter (error ~depth:1 ctx (Error.compl_msg "referenced here")) (List.rev pl);
 		end
-	| Error.Error (Stack stack,_,depth) -> (match stack with
-		| [] -> ()
-		| (e,p) :: stack -> begin
-			located_error ~depth ctx (Error.error_msg p e);
-			List.iter (fun (e,p) -> located_error ~depth:(depth+1) ctx (Error.error_msg p e)) stack;
-		end)
-	| Error.Error (m,p,depth) ->
-		located_error ~depth ctx (Error.error_msg p m)
-	| Generic.Generic_Exception(m,p) ->
-		error ctx m p
+	| Error.Error err ->
+		error_ext ctx err
 	| Arg.Bad msg ->
 		error ctx ("Error: " ^ msg) null_pos
 	| Failure msg when not Helper.is_debug_run ->
@@ -373,7 +424,7 @@ with
 		error ctx ("Error: No completion point was found") null_pos
 	| DisplayException.DisplayException dex ->
 		DisplayOutput.handle_display_exception ctx dex
-	| Out_of_memory | EvalExceptions.Sys_exit _ | Hlinterp.Sys_exit _ | DisplayProcessingGlobals.Completion _ as exc ->
+	| Out_of_memory | EvalTypes.Sys_exit _ | Hlinterp.Sys_exit _ | DisplayProcessingGlobals.Completion _ as exc ->
 		(* We don't want these to be caught by the catchall below *)
 		raise exc
 	| e when (try Sys.getenv "OCAMLRUNPARAM" <> "b" with _ -> true) && not Helper.is_debug_run ->
@@ -399,7 +450,7 @@ let catch_completion_and_exit ctx callbacks run =
 			ServerMessage.completion str;
 			ctx.comm.write_err str;
 			0
-		| EvalExceptions.Sys_exit i | Hlinterp.Sys_exit i ->
+		| EvalTypes.Sys_exit i | Hlinterp.Sys_exit i ->
 			if i <> 0 then ctx.has_error <- true;
 			finalize ctx;
 			i
@@ -408,7 +459,10 @@ let process_actx ctx actx =
 	DisplayProcessing.process_display_arg ctx actx;
 	List.iter (fun s ->
 		ctx.com.warning WDeprecated [] s null_pos
-	) actx.deprecations
+	) actx.deprecations;
+	if defined ctx.com NoDeprecationWarnings then begin
+		ctx.com.warning_options <- [{wo_warning = WDeprecated; wo_mode = WMDisable}] :: ctx.com.warning_options
+	end
 
 let compile_ctx callbacks ctx =
 	let run ctx =
@@ -417,8 +471,7 @@ let compile_ctx callbacks ctx =
 		compile_safe ctx (fun () ->
 			let actx = Args.parse_args ctx.com in
 			process_actx ctx actx;
-			callbacks.after_arg_parsing ctx;
-			compile ctx actx;
+			compile ctx actx callbacks;
 		);
 		finalize ctx;
 		callbacks.after_compilation ctx;
@@ -430,7 +483,7 @@ let compile_ctx callbacks ctx =
 		catch_completion_and_exit ctx callbacks run
 
 let create_context comm cs compilation_step params = {
-	com = Common.create compilation_step cs version params;
+	com = Common.create compilation_step cs version params (DisplayTypes.DisplayMode.create !Parser.display_mode);
 	messages = [];
 	has_next = false;
 	has_error = false;
@@ -481,7 +534,7 @@ module HighLevel = struct
 					"-cp" :: l :: acc
 				else match (try ExtString.String.split l " " with _ -> l, "") with
 				| ("-L",dir) ->
-					"--neko-lib" :: (String.sub l 3 (String.length l - 3)) :: acc
+					"--neko-lib-path" :: (String.sub l 3 (String.length l - 3)) :: acc
 				| param, value ->
 					let acc = if value <> "" then value :: acc else acc in
 					let acc = param :: acc in
@@ -490,14 +543,13 @@ module HighLevel = struct
 			lines
 
 	(* Returns a list of contexts, but doesn't do anything yet *)
-	let process_params server_api create each_params has_display is_server pl =
-		let curdir = Unix.getcwd () in
+	let process_params server_api create each_args has_display is_server args =
+		(* We want the loop below to actually see all the --each params, so let's prepend them *)
+		let args = !each_args @ args in
 		let added_libs = Hashtbl.create 0 in
 		let server_mode = ref SMNone in
 		let create_context args =
 			let ctx = create (server_api.on_context_create()) args in
-			(* --cwd triggers immediately, so let's reset *)
-			Unix.chdir curdir;
 			ctx
 		in
 		let rec find_subsequent_libs acc args = match args with
@@ -508,16 +560,16 @@ module HighLevel = struct
 		in
 		let rec loop acc = function
 			| [] ->
-				[],Some (create_context (!each_params @ (List.rev acc)))
+				[],Some (create_context (List.rev acc))
 			| "--next" :: l when acc = [] -> (* skip empty --next *)
 				loop [] l
 			| "--next" :: l ->
-				let ctx = create_context (!each_params @ (List.rev acc)) in
+				let ctx = create_context (List.rev acc) in
 				ctx.has_next <- true;
 				l,Some ctx
 			| "--each" :: l ->
-				each_params := List.rev acc;
-				loop [] l
+				each_args := List.rev acc;
+				loop acc l
 			| "--cwd" :: dir :: l | "-C" :: dir :: l ->
 				(* we need to change it immediately since it will affect hxml loading *)
 				(try Unix.chdir dir with _ -> raise (Arg.Bad ("Invalid directory: " ^ dir)));
@@ -528,8 +580,8 @@ module HighLevel = struct
 					(* If we are already connected, ignore (issue #10813) *)
 					loop acc l
 				else begin
-					let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in
-					server_api.do_connect host (try int_of_string port with _ -> raise (Arg.Bad "Invalid port")) ((List.rev acc) @ l);
+					let host, port = Helper.parse_host_port hp in
+					server_api.do_connect host port ((List.rev acc) @ l);
 					[],None
 				end
 			| "--server-connect" :: hp :: l ->
@@ -540,14 +592,14 @@ module HighLevel = struct
 				loop acc l
 			| "--run" :: cl :: args ->
 				let acc = cl :: "-x" :: acc in
-				let ctx = create_context (!each_params @ (List.rev acc)) in
+				let ctx = create_context (List.rev acc) in
 				ctx.com.sys_args <- args;
 				[],Some ctx
 			| ("-L" | "--library" | "-lib") :: name :: args ->
 				let libs,args = find_subsequent_libs [name] args in
 				let libs = List.filter (fun l -> not (Hashtbl.mem added_libs l)) libs in
 				List.iter (fun l -> Hashtbl.add added_libs l ()) libs;
-				let lines = add_libs libs pl server_api.cache has_display in
+				let lines = add_libs libs args server_api.cache has_display in
 				loop acc (lines @ args)
 			| ("--jvm" | "--java" | "-java" as arg) :: dir :: args ->
 				loop_lib arg dir "hxjava" acc args
@@ -563,7 +615,7 @@ module HighLevel = struct
 		and loop_lib arg dir lib acc args =
 			loop (dir :: arg :: acc) ("-lib" :: lib :: args)
 		in
-		let args,ctx = loop [] pl in
+		let args,ctx = loop [] args in
 		args,!server_mode,ctx
 
 	let execute_ctx server_api ctx server_mode =
@@ -591,6 +643,7 @@ module HighLevel = struct
 	let entry server_api comm args =
 		let create = create_context comm server_api.cache in
 		let each_args = ref [] in
+		let curdir = Unix.getcwd () in
 		let has_display = ref false in
 		(* put --display in front if it was last parameter *)
 		let args = match List.rev args with
@@ -610,14 +663,18 @@ module HighLevel = struct
 			in
 			let code = match ctx with
 				| Some ctx ->
+					(* Need chdir here because --cwd is eagerly applied in process_params *)
+					Unix.chdir curdir;
 					execute_ctx server_api ctx server_mode
 				| None ->
 					(* caused by --connect *)
 					0
 			in
-			if code = 0 && args <> [] then
+			if code = 0 && args <> [] && not !has_display then begin
+				(* We have to chdir here again because any --cwd also takes effect in execute_ctx *)
+				Unix.chdir curdir;
 				loop args
-			else
+			end else
 				code
 		in
 		let code = loop args in

+ 18 - 12
src/compiler/displayOutput.ml

@@ -1,20 +1,16 @@
 open Globals
 open Ast
 open Common
-open Filename
 open Timer
 open DisplayTypes.DisplayMode
 open DisplayTypes.CompletionResultKind
 open CompletionItem
 open CompletionClassField
 open CompletionEnumField
-open ClassFieldOrigin
 open DisplayException
 open Type
-open Display
 open DisplayTypes
 open CompletionModuleType
-open Typecore
 open Genjson
 open CompilationContext
 open DisplayProcessingGlobals
@@ -71,8 +67,8 @@ let print_fields fields =
 		| ITPackage(path,_) -> "package",snd path,"",None
 		| ITModule path -> "type",snd path,"",None
 		| ITMetadata  meta ->
-			let s,(doc,_),_ = Meta.get_info meta in
-			"metadata","@" ^ s,"",doc_from_string doc
+			let s,data  = Meta.get_info meta in
+			"metadata","@" ^ s,"",doc_from_string data.m_doc
 		| ITTimer(name,value) -> "timer",name,"",doc_from_string value
 		| ITLiteral s ->
 			let t = match k.ci_type with None -> t_dynamic | Some (t,_) -> t in
@@ -213,7 +209,7 @@ let find_doc t =
 	let doc = match follow t with
 		| TAnon an ->
 			begin match !(an.a_status) with
-				| Statics c -> c.cl_doc
+				| ClassStatics c -> c.cl_doc
 				| EnumStatics en -> en.e_doc
 				| AbstractStatics a -> a.a_doc
 				| _ -> None
@@ -348,10 +344,10 @@ let handle_type_path_exception ctx p c is_import pos =
 			| None ->
 				DisplayPath.TypePathHandler.complete_type_path com p
 			| Some (c,cur_package) ->
-				let ctx = Typer.create com in
+				let ctx = TyperEntry.create com None in
 				DisplayPath.TypePathHandler.complete_type_path_inner ctx p c cur_package is_import
-		end with Common.Abort(msg,p) ->
-			error ctx msg p;
+		end with Error.Fatal_error err ->
+			error_ext ctx err;
 			None
 	in
 	begin match ctx.com.json_out,fields with
@@ -372,13 +368,23 @@ let handle_type_path_exception ctx p c is_import pos =
 		api.send_result (DisplayException.fields_to_json ctx fields kind (DisplayTypes.make_subject None pos));
 	end
 
-let emit_diagnostics com =
+let emit_legacy_diagnostics com =
 	let dctx = Diagnostics.run com in
 	let s = Json.string_of_json (DiagnosticsPrinter.json_of_diagnostics com dctx) in
 	DisplayPosition.display_position#reset;
 	raise (Completion s)
 
+let emit_diagnostics com =
+	(match com.Common.json_out with
+	| None -> die "" __LOC__
+	| Some api ->
+		let dctx = Diagnostics.run com in
+		let diagnostics = DiagnosticsPrinter.json_of_diagnostics com dctx in
+		DisplayPosition.display_position#reset;
+		api.send_result diagnostics;
+		raise Abort (* not reached because send_result always raises *))
+
 let emit_statistics tctx =
 	let stats = Statistics.collect_statistics tctx [SFFile (DisplayPosition.display_position#get).pfile] true in
 	let s = Statistics.Printer.print_statistics stats in
-	raise (Completion s)
+	raise (Completion s)

+ 20 - 18
src/compiler/displayProcessing.ml

@@ -22,7 +22,7 @@ let handle_display_argument_old com file_pos actx =
 		actx.did_something <- true;
 		(try Memory.display_memory com with e -> prerr_endline (Printexc.get_backtrace ()));
 	| "diagnostics" ->
-		com.report_mode <- RMDiagnostics []
+		com.report_mode <- RMLegacyDiagnostics []
 	| _ ->
 		let file, pos = try ExtString.String.split file_pos "@" with _ -> failwith ("Invalid format: " ^ file_pos) in
 		let file = Helper.unquote file in
@@ -46,9 +46,9 @@ let handle_display_argument_old com file_pos actx =
 			| "module-symbols" ->
 				create (DMModuleSymbols None)
 			| "diagnostics" ->
-				com.report_mode <- RMDiagnostics [file_unique];
+				com.report_mode <- RMLegacyDiagnostics [file_unique];
 				let dm = create DMNone in
-				{dm with dms_display_file_policy = DFPAlso; dms_per_file = true}
+				{dm with dms_display_file_policy = DFPOnly; dms_per_file = true; dms_populate_cache = !ServerConfig.populate_cache_from_display}
 			| "statistics" ->
 				com.report_mode <- RMStatistics;
 				let dm = create DMNone in
@@ -92,13 +92,14 @@ let process_display_arg ctx actx =
 let process_display_configuration ctx =
 	let com = ctx.com in
 	if is_diagnostics com then begin
-		com.info <- (fun ?depth s p ->
-			add_diagnostics_message com (located s p) DKCompilerMessage Information
+		com.info <- (fun ?depth ?from_macro s p ->
+			add_diagnostics_message ?depth com s p DKCompilerMessage Information
 		);
-		com.warning <- (fun ?depth w options s p ->
+		com.warning <- (fun ?(depth = 0) ?from_macro w options s p ->
 			match Warning.get_mode w (com.warning_options @ options) with
 			| WMEnable ->
-				add_diagnostics_message com (located s p) DKCompilerMessage Warning
+				let wobj = Warning.warning_obj w in
+				add_diagnostics_message ~depth ~code:(Some wobj.w_name) com s p DKCompilerMessage Warning
 			| WMDisable ->
 				()
 		);
@@ -142,11 +143,11 @@ let process_display_file com actx =
 		| DFPOnly when (DisplayPosition.display_position#get).pfile = file_input_marker ->
 			actx.classes <- [];
 			com.main_class <- None;
-			begin match !TypeloadParse.current_stdin with
-			| Some input ->
-				TypeloadParse.current_stdin := None;
+			begin match com.file_contents with
+			| [_, Some input] ->
+				com.file_contents <- [];
 				DPKInput input
-			| None ->
+			| _ ->
 				DPKNone
 			end
 		| dfp ->
@@ -192,24 +193,24 @@ let load_display_module_in_macro tctx display_file_dot_path clear = match displa
 		let p = null_pos in
 		begin try
 			let open Typecore in
-			let _, mctx = MacroContext.get_macro_context tctx p in
+			let mctx = MacroContext.get_macro_context tctx in
 			(* Tricky stuff: We want to remove the module from our lookups and load it again in
 				display mode. This covers some cases like --macro typing it in non-display mode (issue #7017). *)
 			if clear then begin
 				begin try
 					let m = mctx.com.module_lut#find cpath in
 					mctx.com.module_lut#remove cpath;
-					mctx.com.type_to_module#remove cpath;
+					mctx.com.module_lut#get_type_lut#remove cpath;
 					List.iter (fun mt ->
 						let ti = Type.t_infos mt in
 						mctx.com.module_lut#remove ti.mt_path;
-						mctx.com.type_to_module#remove ti.mt_path;
+						mctx.com.module_lut#get_type_lut#remove ti.mt_path;
 					) m.m_types
 				with Not_found ->
 					()
 				end;
 			end;
-			let _ = MacroContext.load_macro_module tctx cpath true p in
+			let _ = MacroContext.load_macro_module (MacroContext.get_macro_context tctx) tctx.com cpath true p in
 			Finalization.finalize mctx;
 			Some mctx
 		with DisplayException.DisplayException _ | Parser.TypePath _ as exc ->
@@ -268,7 +269,7 @@ let maybe_load_display_file_before_typing tctx display_file_dot_path = match dis
 
 let handle_display_after_typing ctx tctx display_file_dot_path =
 	let com = ctx.com in
-	if ctx.com.display.dms_kind = DMNone & ctx.has_error then raise Abort;
+	if ctx.com.display.dms_kind = DMNone && ctx.has_error then raise Abort;
 	begin match ctx.com.display.dms_kind,!Parser.delayed_syntax_completion with
 		| DMDefault,Some(kind,subj) -> DisplayOutput.handle_syntax_completion com kind subj
 		| _ -> ()
@@ -311,7 +312,6 @@ let process_global_display_mode com tctx =
 		FindReferences.find_references tctx com with_definition
 	| DMImplementation ->
 		FindReferences.find_implementations tctx com
-	| DMModuleSymbols (Some "") -> ()
 	| DMModuleSymbols filter ->
 		let open CompilationCache in
 		let cs = com.cs in
@@ -348,10 +348,12 @@ let handle_display_after_finalization ctx tctx display_file_dot_path =
 	end;
 	process_global_display_mode com tctx;
 	begin match com.report_mode with
+	| RMLegacyDiagnostics _ ->
+		DisplayOutput.emit_legacy_diagnostics com
 	| RMDiagnostics _ ->
 		DisplayOutput.emit_diagnostics com
 	| RMStatistics ->
 		DisplayOutput.emit_statistics tctx
 	| RMNone ->
 		()
-	end
+	end

+ 11 - 9
src/compiler/generate.ml

@@ -57,8 +57,6 @@ let generate ctx tctx ext actx =
 	end;
 	if actx.interp then
 		Std.finally (Timer.timer ["interp"]) MacroContext.interpret tctx
-	else if com.platform = Cross then
-		()
 	else begin
 		let generate,name = match com.platform with
 		| Flash ->
@@ -91,11 +89,15 @@ let generate ctx tctx ext actx =
 			Genhl.generate,"hl"
 		| Eval ->
 			(fun _ -> MacroContext.interpret tctx),"eval"
-		| Cross ->
-			die "" __LOC__
+		| Cross
+		| CustomTarget _ ->
+			(fun _ -> ()),""
 		in
-		Common.log com ("Generating " ^ name ^ ": " ^ com.file);
-		let t = Timer.timer ["generate";name] in
-		generate com;
-		t()
-	end
+		if name = "" then ()
+		else begin
+			Common.log com ("Generating " ^ name ^ ": " ^ com.file);
+			let t = Timer.timer ["generate";name] in
+			generate com;
+			t()
+		end
+	end

+ 14 - 3
src/compiler/helper.ml

@@ -1,3 +1,4 @@
+open Ipaddr
 exception HelpMessage of string
 
 let is_debug_run = try Sys.getenv "HAXEDEBUG" = "1" with _ -> false
@@ -52,6 +53,16 @@ let parse_hxml file =
 	parse_hxml_data data
 
 let parse_host_port hp =
-	let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in
-	let port = try int_of_string port with _ -> raise (Arg.Bad "Invalid port") in
-	host, port
+	match (Ipaddr.with_port_of_string ~default:(-1) hp) with
+	(* Short ipv6 notation will be mixed up with port; extract port and rebuild ipv6 *)
+	| Ok (V6 ip, -1) ->
+		let octets = ExtLib.String.split_on_char ':' (V6.to_string ip) in
+		(match (List.rev octets) with
+			| port :: octets -> (try V6 (V6.of_string_exn (ExtLib.String.join ":" (List.rev octets))), int_of_string port with _ -> raise (Arg.Bad "Invalid host/port"))
+			| _ -> raise (Arg.Bad "Invalid host/port")
+		)
+	| Ok (_, -1) -> raise (Arg.Bad "Invalid host/port: missing port")
+	| Ok (ip, port) -> ip, port
+	(* Default to 127.0.0.1 with given port if no host is provided *)
+	| Error _ when Str.string_match (Str.regexp "[0-9]+$") hp 0 -> V4 (V4.of_string_exn "127.0.0.1"), int_of_string hp
+	| Error _ -> raise (Arg.Bad "Invalid host/port")

+ 401 - 0
src/compiler/messageReporting.ml

@@ -0,0 +1,401 @@
+open Extlib_leftovers
+open Globals
+open Common
+open CompilationContext
+
+let resolve_source file l1 p1 l2 p2 =
+	let ch = open_in_bin file in
+	let curline = ref 1 in
+	let lines = ref [] in
+	let rec loop p line =
+		let inc i line =
+			if (!curline >= l1) && (!curline <= l2) then lines := (!curline, line) :: !lines;
+			curline := !curline + 1;
+			(i, "")
+		in
+
+		let input_char_or_done ch line =
+			try input_char ch with End_of_file -> begin
+				ignore(inc 0 line);
+				raise End_of_file
+			end
+		in
+
+		let read_char line = match input_char_or_done ch line with
+			| '\n' -> inc 1 line
+			| '\r' ->
+				ignore(input_char_or_done ch line);
+				inc 2 line
+			| c -> begin
+				let line = ref (line ^ (String.make 1 c)) in
+				let rec skip n =
+					if n > 0 then begin
+						let c = input_char_or_done ch !line in
+						line := !line ^ (String.make 1 c);
+						skip (n - 1)
+					end
+				in
+
+				let code = int_of_char c in
+				if code < 0xC0 then ()
+				else if code < 0xE0 then skip 1
+				else if code < 0xF0 then skip 2
+				else skip 3;
+
+				(1, !line)
+			end
+		in
+
+		let (delta, line) = read_char line in
+		loop (p + delta) line
+	in
+
+	try loop 0 ""; with End_of_file -> close_in ch;
+	List.rev !lines
+
+let resolve_file ctx f =
+		let ext = Common.extension f in
+		let second_ext = Common.extension (Common.remove_extension f) in
+		let platform_ext = "." ^ (platform_name_macro ctx) in
+		if platform_ext = second_ext then
+			(Common.remove_extension (Common.remove_extension f)) ^ ext
+		else
+			f
+
+let error_printer file line = Printf.sprintf "%s:%d:" file line
+
+type error_context = {
+	absolute_positions : bool;
+	mutable last_positions : pos IntMap.t;
+	mutable max_lines : int IntMap.t;
+	mutable gutter : int IntMap.t;
+	mutable previous : (pos * MessageSeverity.t * int) option;
+}
+
+let create_error_context absolute_positions = {
+	absolute_positions = absolute_positions;
+	last_positions = IntMap.empty;
+	max_lines = IntMap.empty;
+	gutter = IntMap.empty;
+	previous = None;
+}
+
+let compiler_pretty_message_string com ectx cm =
+	match cm.cm_message with
+	(* Filter some messages that don't add much when using this message renderer *)
+	| "End of overload failure reasons" -> None
+	| _ -> begin
+		ectx.last_positions <- (IntMap.add cm.cm_depth cm.cm_pos ectx.last_positions);
+		let is_null_pos = cm.cm_pos = null_pos || cm.cm_pos.pmin = -1 in
+		let is_unknown_file f = f = "" || f = "?" in
+
+		(* Extract informations from position *)
+		let l1, p1, l2, p2, epos, lines =
+			if is_null_pos then begin
+				let epos = if is_unknown_file cm.cm_pos.pfile then "(unknown position)" else cm.cm_pos.pfile in
+				(-1, -1, -1, -1, epos, [])
+			end else try begin
+				let f = resolve_file com cm.cm_pos.pfile in
+				let f = Common.find_file com f in
+				let l1, p1, l2, p2 = Lexer.get_pos_coords cm.cm_pos in
+				let lines = resolve_source f l1 p1 l2 p2 in
+				let epos =
+					if ectx.absolute_positions then TPrinting.Printer.s_pos cm.cm_pos
+					else Lexer.get_error_pos error_printer cm.cm_pos
+				in
+				(l1, p1, l2, p2, epos, lines)
+			end with Not_found | Sys_error _ ->
+				(1, 1, 1, 1, cm.cm_pos.pfile, [])
+			in
+
+		(* If 4 lines or less, display all; if more, crop the middle *)
+		let lines = match lines with
+			| _ :: (_ :: (_ :: (_ :: []))) -> lines
+			| hd :: (_ :: (_ :: (_ :: l))) ->
+				let _,line = hd in
+				let indent = ref 0 in
+				let found = ref false in
+
+				while (not !found) && (!indent < (String.length line - 1)) do
+					found := not (Lexer.is_whitespace (String.unsafe_get line !indent));
+					indent := !indent + 1
+				done;
+
+				[hd; (0, (String.make (!indent+1) ' ') ^ "[...]"); List.hd (List.rev l)]
+			| _ -> lines
+		in
+
+		let parent_pos =
+			if cm.cm_depth = 0 then null_pos
+			else (try IntMap.find (cm.cm_depth-1) ectx.last_positions with Not_found -> null_pos)
+		in
+
+		let prev_pos,prev_sev,prev_nl = match ectx.previous with
+			| None -> (None, None, 0)
+			| Some (p, sev, depth) -> (Some p, Some sev, depth)
+		in
+
+		let sev_changed = prev_sev = None || Some cm.cm_severity <> prev_sev in
+		let pos_changed = (prev_pos = None || cm.cm_pos <> Option.get prev_pos || (cm.cm_depth <> prev_nl && cm.cm_depth <> prev_nl + 1)) && (parent_pos = null_pos || cm.cm_pos <> parent_pos) in
+		let file_changed = prev_pos = None || (pos_changed && match (cm.cm_pos.pfile, (Option.get prev_pos).pfile) with
+			| (f1, f2) when (is_unknown_file f1) && (is_unknown_file f2) -> false
+			| (f1, f2) -> f1 <> f2
+		) in
+
+		let display_heading = cm.cm_depth = 0 || sev_changed || file_changed in
+		let has_source = match lines with | [] -> false | _ -> true in
+		let display_source = has_source && (cm.cm_depth = 0 || sev_changed || pos_changed) in
+		let display_pos_marker = (not is_null_pos) && has_source && (cm.cm_depth = 0 || sev_changed || pos_changed) in
+
+		let gutter_len = (try String.length (Printf.sprintf "%d" (IntMap.find cm.cm_depth ectx.max_lines)) with Not_found -> 0) + 2 in
+
+		let no_color = Define.defined com.defines Define.MessageNoColor in
+		let c_reset = if no_color then "" else "\x1b[0m" in
+		let c_bold = if no_color then "" else "\x1b[1m" in
+		let c_dim = if no_color then "" else "\x1b[2m" in
+
+		let (c_sev, c_sev_bg) = if no_color then ("", "") else match cm.cm_severity with
+			| MessageSeverity.Warning -> ("\x1b[33m", "\x1b[30;43m")
+			| Information | Hint -> ("\x1b[34m", "\x1b[30;44m")
+			| Error -> ("\x1b[31m", "\x1b[30;41m")
+		in
+
+		let sev_label = if cm.cm_depth > 0 then " -> " else Printf.sprintf
+			(if no_color then "[%s]" else " %s ")
+			(match cm.cm_severity with
+				| MessageSeverity.Warning -> "WARNING"
+				| Information -> "INFO"
+				| Hint -> "HINT"
+				| Error -> "ERROR"
+			) in
+
+		let out = ref "" in
+
+		if display_heading then
+			out := Printf.sprintf "%s%s%s\n\n"
+				(* Severity heading *)
+				(c_sev_bg ^ sev_label ^ c_reset ^ " ")
+				(* Macro context indicator *)
+				(if cm.cm_from_macro then c_sev ^ "(macro) " ^ c_reset else "")
+				(* File + line pointer *)
+				epos;
+
+		(* Error source *)
+		if display_source then out := List.fold_left (fun out (l, line) ->
+			let nb_len = String.length (string_of_int l) in
+
+			(* Replace tabs with 1 space to avoid column misalignments *)
+			let line = String.concat " " (ExtString.String.nsplit line "\t") in
+			let len = String.length line in
+
+			out ^ Printf.sprintf "%s%s | %s\n"
+				(* left-padded line number *)
+				(String.make (gutter_len-nb_len-1) ' ')
+				(if l = 0 then "-" else Printf.sprintf "%d" l)
+				(* Source code at that line *)
+				(
+					if l = 0 then
+						c_dim ^ line ^ c_reset
+					else if l1 = l2 then
+						(if p1 > 1 then c_dim ^ (String.sub line 0 (p1-1)) else "")
+						^ c_reset ^ c_bold ^ (String.sub line (p1-1) (p2-p1))
+						^ c_reset ^ c_dim ^ (String.sub line (p2-1) (len - p2 + 1))
+						^ c_reset
+					else begin
+						(if (l = l1) then
+							(if p1 > 1 then c_dim ^ (String.sub line 0 (p1-1)) else "")
+							^ c_reset ^ c_bold ^ (String.sub line (p1-1) (len-p1+1))
+							^ c_reset
+						else if (l = l2) then
+							(if p2 > 1 then c_bold ^ (String.sub line 0 (p2-1)) else "")
+							^ c_reset ^ c_dim ^ (String.sub line (p2-1) (len-p2+1))
+							^ c_reset
+						else c_bold ^ line ^ c_reset)
+					end
+				)
+		) !out lines;
+
+		(* Error position marker *)
+		if display_pos_marker then
+			out := Printf.sprintf "%s%s|%s\n"
+				!out
+				(String.make gutter_len ' ')
+				(if l1 = l2 then String.make p1 ' ' ^ c_sev ^ String.make (if p1 = p2 then 1 else p2-p1) '^' ^ c_reset else "");
+
+		(* Error message *)
+		out := List.fold_left (fun out str -> Printf.sprintf "%s%s| %s\n"
+			out
+			(String.make gutter_len ' ')
+			(* Remove "... " prefix *)
+			(if (ExtString.String.starts_with str "... ") then String.sub str 4 ((String.length str) - 4) else str)
+		) !out (ExtString.String.nsplit cm.cm_message "\n");
+
+		ectx.previous <- Some ((if is_null_pos then null_pos else cm.cm_pos), cm.cm_severity, cm.cm_depth);
+		ectx.gutter <- (IntMap.add cm.cm_depth gutter_len ectx.gutter);
+
+		(* Indent sub errors *)
+		let rec indent ?(acc=0) depth =
+			if depth = 0 then acc
+			else indent ~acc:(acc + try IntMap.find (depth-1) ectx.gutter with Not_found -> 3) (depth-1)
+		in
+
+		Some (
+			if cm.cm_depth > 0 then String.concat "\n" (List.map (fun str -> match str with
+				| "" -> ""
+				| _ -> (String.make (indent cm.cm_depth) ' ') ^ str
+			) (ExtString.String.nsplit !out "\n"))
+			else !out
+		)
+	end
+
+let compiler_message_string ectx cm =
+	let str = match cm.cm_severity with
+		| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
+		| Information | Error | Hint -> cm.cm_message
+	in
+
+	if cm.cm_pos = null_pos then
+		Some str
+	else begin
+		let epos =
+			if ectx.absolute_positions then TPrinting.Printer.s_pos cm.cm_pos
+			else Lexer.get_error_pos error_printer cm.cm_pos
+		in
+		let str =
+			let lines =
+				match (ExtString.String.nsplit str "\n") with
+				| first :: rest -> first :: List.map Error.compl_msg rest
+				| l -> l
+			in
+			String.concat ("\n" ^ epos ^ " : ") lines
+		in
+		Some (Printf.sprintf "%s : %s" epos str)
+	end
+
+let compiler_indented_message_string ectx cm =
+	match cm.cm_message with
+	(* Filter some messages that don't add much when using this message renderer *)
+	| "End of overload failure reasons" -> None
+	| _ ->
+		let str = match cm.cm_severity with
+			| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
+			| Information -> "Info : " ^ cm.cm_message
+			| Error | Hint -> cm.cm_message
+		in
+
+		if cm.cm_pos = null_pos then
+			Some str
+		else begin
+			let epos =
+				if ectx.absolute_positions then TPrinting.Printer.s_pos cm.cm_pos
+				else Lexer.get_error_pos error_printer cm.cm_pos
+			in
+			let lines =
+				match (ExtString.String.nsplit str "\n") with
+				| first :: rest -> (cm.cm_depth, first) :: List.map (fun msg -> (cm.cm_depth+1, msg)) rest
+				| l -> [(cm.cm_depth, List.hd l)]
+			in
+			let rm_prefix str = if (ExtString.String.starts_with str "... ") then String.sub str 4 ((String.length str) - 4) else str in
+			Some (String.concat "\n" (List.map (fun (depth, msg) -> (String.make (depth*2) ' ') ^ epos ^ " : " ^ (rm_prefix msg)) lines))
+		end
+
+let get_max_line max_lines messages =
+	List.fold_left (fun max_lines cm ->
+		let _,_,l2,_ = Lexer.get_pos_coords cm.cm_pos in
+		let old = try IntMap.find cm.cm_depth max_lines with Not_found -> 0 in
+
+		if l2 > old then IntMap.add cm.cm_depth l2 max_lines
+		else max_lines
+	) max_lines messages
+
+exception ConfigError of string
+
+let get_formatter com def default =
+	let format_mode = Define.defined_value_safe ~default com.defines def in
+	match format_mode with
+		| "pretty" -> compiler_pretty_message_string com
+		| "indent" -> compiler_indented_message_string
+		| "classic" -> compiler_message_string
+		| m -> begin
+			let def = Define.get_define_key def in
+			raise (ConfigError (Printf.sprintf "Invalid message reporting mode: \"%s\", expected classic | pretty | indent (for -D %s)." m def))
+		end
+
+let print_error (err : Error.error) =
+	let ret = ref "" in
+	Error.recurse_error (fun depth err ->
+		ret := !ret ^ (Lexer.get_error_pos (Printf.sprintf "%s:%d: ") err.err_pos) ^ (Error.error_msg err.err_message) ^ "\n"
+	) err;
+	!ret
+
+let format_messages com messages =
+	let absolute_positions = Define.defined com.defines Define.MessageAbsolutePositions in
+	let ectx = create_error_context absolute_positions in
+	ectx.max_lines <- get_max_line ectx.max_lines messages;
+	let message_formatter = get_formatter com Define.MessageReporting "classic" in
+	let lines = List.rev (
+		List.fold_left (fun lines cm -> match (message_formatter ectx cm) with
+			| None -> lines
+			| Some str -> str :: lines
+		) [] messages
+	) in
+	ExtLib.String.join "\n" lines
+
+let display_messages ctx on_message = begin
+	let absolute_positions = Define.defined ctx.com.defines Define.MessageAbsolutePositions in
+	let ectx = create_error_context absolute_positions in
+	ectx.max_lines <- get_max_line ectx.max_lines ctx.messages;
+
+	let get_formatter _ def default =
+		try get_formatter ctx.com def default
+		with | ConfigError s ->
+			error ctx s null_pos;
+			compiler_message_string
+	in
+
+	let message_formatter = get_formatter ctx.com Define.MessageReporting "classic" in
+	let log_formatter = get_formatter ctx.com Define.MessageLogFormat "indent" in
+
+	let log_messages = ref (Define.defined ctx.com.defines Define.MessageLogFile) in
+	let log_message = ref None in
+	let close_logs = ref None in
+
+	if !log_messages then begin
+		try begin
+			let buf = Rbuffer.create 16000 in
+
+			let file = Define.defined_value ctx.com.defines Define.MessageLogFile in
+			let chan =
+				Path.mkdir_from_path file;
+				open_out_bin file
+			in
+
+			log_message := (Some (fun msg ->
+				match (log_formatter ectx msg) with
+					| None -> ()
+					| Some str -> Rbuffer.add_string buf (str ^ "\n")));
+
+			close_logs := (Some (fun () ->
+				Rbuffer.output_buffer chan buf;
+				Rbuffer.clear buf;
+				close_out chan
+			));
+		end with
+			| Failure e | Sys_error e -> begin
+				let def = Define.get_define_key Define.MessageLogFile in
+				error ctx (Printf.sprintf "Error opening log file: %s. Logging to file disabled (-D %s)" e def) null_pos;
+				log_messages := false;
+			end
+	end;
+
+	List.iter (fun cm ->
+		if !log_messages then (Option.get !log_message) cm;
+
+		match (message_formatter ectx cm) with
+			| None -> ()
+			| Some str -> on_message cm.cm_severity str
+	) (List.rev ctx.messages);
+
+	if !log_messages then (Option.get !close_logs) ();
+end
+

+ 18 - 20
src/compiler/retyper.ml

@@ -21,7 +21,7 @@ let disable_typeloading rctx ctx f =
 	ctx.g.load_only_cached_modules <- true;
 	try
 		Std.finally (fun () -> ctx.g.load_only_cached_modules <- old) f ()
-	with (Error.Error (Module_not_found path,_,_)) ->
+	with (Error.Error { err_message = Module_not_found path }) ->
 		fail rctx (Printf.sprintf "Could not load [Module %s]" (s_type_path path))
 
 let pair_type th t = match th with
@@ -74,13 +74,13 @@ let pair_class_field rctx ctx cctx fctx cf cff p =
 				remove_class_field_flag cf CfPostProcessed;
 		)
 
-let pair_classes rctx context_init c d p =
+let pair_classes rctx c d p =
 	let rctx = {rctx with
 		print_stack = (Printf.sprintf "[Class %s]" (s_type_path c.cl_path)) :: rctx.print_stack
 	} in
 	c.cl_restore();
 	(* TODO: What do we do with build macros? *)
-	let cctx = create_class_context c context_init p in
+	let cctx = create_class_context c p in
 	let ctx = create_typer_context_for_class rctx.typer cctx p in
 	let _ =
 		let rctx = {rctx with
@@ -89,16 +89,16 @@ let pair_classes rctx context_init c d p =
 		let has_extends = ref false in
 		let implements = ref c.cl_implements in
 		List.iter (function
-			| HExtends(path,p) ->
+			| HExtends ptp ->
 				has_extends := true;
 				begin match c.cl_super with
 				| None ->
-					fail rctx (Printf.sprintf "parent %s appeared" (Ast.Printer.s_complex_type_path "" (path,p)))
+					fail rctx (Printf.sprintf "parent %s appeared" (Ast.Printer.s_complex_type_path "" ptp))
 				| Some(c,tl) ->
-					let th = pair_type (Some(CTPath path,p)) (TInst(c,tl)) in
+					let th = pair_type (Some(CTPath ptp,ptp.pos_full)) (TInst(c,tl)) in
 					ignore (disable_typeloading rctx ctx (fun () -> Typeload.load_complex_type ctx false th))
 				end
-			| HImplements(path,p) ->
+			| HImplements ptp ->
 				begin match !implements with
 					| (c,tl) :: rest ->
 						(* TODO: I think this should somehow check if it's actually the same interface. There could be cases
@@ -106,10 +106,10 @@ let pair_classes rctx context_init c d p =
 						   However, this doesn't matter until we start retyping invalidated modules.
 						*)
 						implements := rest;
-						let th = pair_type (Some(CTPath path,p)) (TInst(c,tl)) in
+						let th = pair_type (Some(CTPath ptp,ptp.pos_full)) (TInst(c,tl)) in
 						ignore (disable_typeloading rctx ctx (fun () -> Typeload.load_complex_type ctx false th));
 					| [] ->
-						fail rctx (Printf.sprintf "interface %s appeared" (Ast.Printer.s_complex_type_path "" (path,p)))
+						fail rctx (Printf.sprintf "interface %s appeared" (Ast.Printer.s_complex_type_path "" ptp))
 				end
 			| _ ->
 				()
@@ -130,7 +130,7 @@ let pair_classes rctx context_init c d p =
 			print_stack = (Printf.sprintf "[Field %s]" name) :: rctx.print_stack
 		} in
 		let display_modifier = Typeload.check_field_access ctx cff in
-		let fctx = create_field_context cctx cff ctx.is_display_file display_modifier in
+		let fctx = create_field_context ctx cctx cff ctx.is_display_file display_modifier in
 		let cf = match fctx.field_kind with
 			| FKConstructor ->
 				begin match c.cl_constructor with
@@ -180,14 +180,14 @@ let pair_typedefs ctx rctx td d =
 	ignore (disable_typeloading rctx ctx (fun () -> Typeload.load_complex_type ctx false d.d_data));
 	[]
 
-let pair_abstracts ctx rctx context_init a d p =
+let pair_abstracts ctx rctx a d p =
 	let rctx = {rctx with
 		print_stack = (Printf.sprintf "[Abstract %s]" (s_type_path a.a_path)) :: rctx.print_stack
 	} in
 	match a.a_impl with
 	| Some c ->
 		c.cl_restore();
-		let cctx = create_class_context c context_init p in
+		let cctx = create_class_context c p in
 		let ctx = create_typer_context_for_class rctx.typer cctx p in
 		let fl = List.map (fun cff ->
 			let cff = TypeloadFields.transform_abstract_field2 ctx a cff in
@@ -196,7 +196,7 @@ let pair_abstracts ctx rctx context_init a d p =
 				print_stack = (Printf.sprintf "[Field %s]" name) :: rctx.print_stack
 			} in
 			let display_modifier = Typeload.check_field_access ctx cff in
-			let fctx = create_field_context cctx cff ctx.is_display_file display_modifier in
+			let fctx = create_field_context ctx cctx cff ctx.is_display_file display_modifier in
 			let cf = try
 				PMap.find name c.cl_statics
 			with Not_found ->
@@ -218,7 +218,6 @@ let attempt_retyping ctx m p =
 		print_stack = [Printf.sprintf "[Module %s]" (s_type_path m.m_path)];
 	} in
 	(* log rctx 0 (Printf.sprintf "Retyping module %s" (s_type_path m.m_path)); *)
-	let context_init = new TypeloadFields.context_init in
 	let find_type name = try
 		List.find (fun t -> snd (t_infos t).mt_path = name) ctx.m.curmod.m_types
 	with Not_found ->
@@ -230,11 +229,11 @@ let attempt_retyping ctx m p =
 		| (d,p) :: decls ->
 			begin match d with
 			| EImport (path,mode) ->
-				ImportHandling.init_import ctx context_init path mode p;
+				ImportHandling.init_import ctx path mode p;
 				ImportHandling.commit_import ctx path mode p;
 				loop acc decls
 			| EUsing path ->
-				ImportHandling.init_using ctx context_init path p;
+				ImportHandling.init_using ctx path p;
 				loop acc decls
 			| EClass c ->
 				let mt = find_type (fst c.d_name) in
@@ -257,18 +256,17 @@ let attempt_retyping ctx m p =
 		let pairs = loop [] decls in
 		let fl = List.map (fun (d,mt) -> match d,mt with
 			| EClass d,TClassDecl c ->
-				pair_classes rctx context_init c d p
+				pair_classes rctx c d p
 			| EEnum d,TEnumDecl en ->
 				pair_enums ctx rctx en d
 			| ETypedef d,TTypeDecl td ->
 				pair_typedefs ctx rctx td d
 			| EAbstract d,TAbstractDecl a ->
-				pair_abstracts ctx rctx context_init a d p
+				pair_abstracts ctx rctx a d p
 			| _ ->
 				fail rctx "?"
 		) pairs in
 		(* If we get here we know that the everything is ok. *)
-		delay ctx PConnectField (fun () -> context_init#run);
 		List.iter (fun fl ->
 			List.iter (fun f -> f()) fl
 		) fl;
@@ -276,4 +274,4 @@ let attempt_retyping ctx m p =
 		m.m_extra.m_time <- Common.file_time file;
 		None
 	with Fail s ->
-		Some s
+		Some s

+ 91 - 413
src/compiler/server.ml

@@ -1,15 +1,13 @@
-open Extlib_leftovers
-open Printf
 open Globals
-open Ast
 open Common
 open CompilationCache
 open Timer
 open Type
 open DisplayProcessingGlobals
+open Ipaddr
 open Json
-open Compiler
 open CompilationContext
+open MessageReporting
 
 exception Dirty of module_skip_reason
 exception ServerError of string
@@ -18,15 +16,7 @@ let has_error ctx =
 	ctx.has_error || ctx.com.Common.has_error
 
 let check_display_flush ctx f_otherwise = match ctx.com.json_out with
-	| None ->
-		if is_diagnostics ctx.com then begin
-			List.iter (fun cm ->
-				add_diagnostics_message ctx.com (located cm.cm_message cm.cm_pos) cm.cm_kind cm.cm_severity
-			) (List.rev ctx.messages);
-			raise (Completion (Diagnostics.print ctx.com))
-		end else
-			f_otherwise ()
-	| Some api ->
+	| Some api when not (is_diagnostics ctx.com) ->
 		if has_error ctx then begin
 			let errors = List.map (fun cm ->
 				JObject [
@@ -37,6 +27,17 @@ let check_display_flush ctx f_otherwise = match ctx.com.json_out with
 			) (List.rev ctx.messages) in
 			api.send_error errors
 		end
+	| _ ->
+		if is_diagnostics ctx.com then begin
+			List.iter (fun cm ->
+				add_diagnostics_message ~depth:cm.cm_depth ctx.com cm.cm_message cm.cm_pos cm.cm_kind cm.cm_severity
+			) (List.rev ctx.messages);
+			(match ctx.com.report_mode with
+			| RMDiagnostics _ -> ()
+			| RMLegacyDiagnostics _ -> raise (Completion (Diagnostics.print ctx.com))
+			| _ -> die "" __LOC__)
+		end else
+			f_otherwise ()
 
 let current_stdin = ref None
 
@@ -46,7 +47,7 @@ let parse_file cs com file p =
 	and fkey = com.file_keys#get file in
 	let is_display_file = DisplayPosition.display_position#is_in_file (com.file_keys#get ffile) in
 	match is_display_file, !current_stdin with
-	| true, Some stdin when Common.defined com Define.DisplayStdin ->
+	| true, Some stdin when (com.file_contents <> [] || Common.defined com Define.DisplayStdin) ->
 		TypeloadParse.parse_file_from_string com file p stdin
 	| _ ->
 		let ftime = file_time ffile in
@@ -87,365 +88,6 @@ let parse_file cs com file p =
 open ServerCompilationContext
 
 module Communication = struct
-	type error_context = {
-		mutable last_positions : pos IntMap.t;
-		mutable max_lines : int IntMap.t;
-		mutable gutter : int IntMap.t;
-		mutable previous : (pos * MessageSeverity.t * int) option;
-	}
-
-	let create_error_context () = {
-		last_positions = IntMap.empty;
-		max_lines = IntMap.empty;
-		gutter = IntMap.empty;
-		previous = None;
-	}
-
-	let error_printer file line = Printf.sprintf "%s:%d:" file line
-
-	let resolve_source file l1 p1 l2 p2 =
-		let ch = open_in_bin file in
-		let curline = ref 1 in
-		let lines = ref [] in
-		let rec loop p line =
-			let inc i line =
-				if (!curline >= l1) && (!curline <= l2) then lines := (!curline, line) :: !lines;
-				curline := !curline + 1;
-				(i, "")
-			in
-
-			let input_char_or_done ch line =
-				try input_char ch with End_of_file -> begin
-					ignore(inc 0 line);
-					raise End_of_file
-				end
-			in
-
-			try
-				let read_char line = match input_char_or_done ch line with
-					| '\n' -> inc 1 line
-					| '\r' ->
-						ignore(input_char_or_done ch line);
-						inc 2 line
-					| c -> begin
-						let line = ref (line ^ (String.make 1 c)) in
-						let rec skip n =
-							if n > 0 then begin
-								let c = input_char_or_done ch !line in
-								line := !line ^ (String.make 1 c);
-								skip (n - 1)
-							end
-						in
-
-						let code = int_of_char c in
-						if code < 0xC0 then ()
-						else if code < 0xE0 then skip 1
-						else if code < 0xF0 then skip 2
-						else skip 3;
-
-						(1, !line)
-					end
-				in
-
-				let (delta, line) = read_char line in
-				loop (p + delta) line
-			with End_of_file ->
-				close_in ch;
-		in
-
-		loop 0 "";
-		List.rev !lines
-
-	let resolve_file ctx f =
-			let ext = Common.extension f in
-			let second_ext = Common.extension (Common.remove_extension f) in
-			let platform_ext = "." ^ (platform_name_macro ctx) in
-			if platform_ext = second_ext then
-				(Common.remove_extension (Common.remove_extension f)) ^ ext
-			else
-				f
-
-	let compiler_pretty_message_string ctx ectx cm =
-		match cm.cm_message with
-		(* Filter some messages that don't add much when using this message renderer *)
-		| "End of overload failure reasons" -> None
-		| _ -> begin
-			ectx.last_positions <- (IntMap.add cm.cm_depth cm.cm_pos ectx.last_positions);
-			let is_null_pos = cm.cm_pos = null_pos || cm.cm_pos.pmin = -1 in
-			let is_unknown_file f = f = "" || f = "?" in
-
-			(* Extract informations from position *)
-			let l1, p1, l2, p2, epos, lines =
-				if is_null_pos then begin
-					let epos = if is_unknown_file cm.cm_pos.pfile then "(unknown position)" else cm.cm_pos.pfile in
-					(-1, -1, -1, -1, epos, [])
-				end else begin
-					let f = resolve_file ctx.com cm.cm_pos.pfile in
-					let f =
-						try Common.find_file ctx.com f
-						with Not_found -> failwith ("File not found '" ^ cm.cm_pos.pfile ^ "'")
-						in
-
-					let l1, p1, l2, p2 = Lexer.get_pos_coords cm.cm_pos in
-					let lines = resolve_source f l1 p1 l2 p2 in
-					let epos = Lexer.get_error_pos error_printer cm.cm_pos in
-					(l1, p1, l2, p2, epos, lines)
-				end in
-
-			(* If 4 lines or less, display all; if more, crop the middle *)
-			let lines = match lines with
-				| _ :: (_ :: (_ :: (_ :: []))) -> lines
-				| hd :: (_ :: (_ :: (_ :: l))) ->
-					let _,line = hd in
-					let indent = ref 0 in
-					let found = ref false in
-
-					while (not !found) && (!indent < (String.length line - 1)) do
-						found := not (Lexer.is_whitespace (String.unsafe_get line !indent));
-						indent := !indent + 1
-					done;
-
-					[hd; (0, (String.make (!indent+1) ' ') ^ "[...]"); List.hd (List.rev l)]
-				| _ -> lines
-			in
-
-			let parent_pos =
-				if cm.cm_depth = 0 then null_pos
-				else (try IntMap.find (cm.cm_depth-1) ectx.last_positions with Not_found -> null_pos)
-			in
-
-			let prev_pos,prev_sev,prev_nl = match ectx.previous with
-				| None -> (None, None, 0)
-				| Some (p, sev, depth) -> (Some p, Some sev, depth)
-			in
-
-			let sev_changed = prev_sev = None || Some cm.cm_severity <> prev_sev in
-			let pos_changed = (prev_pos = None || cm.cm_pos <> Option.get prev_pos || (cm.cm_depth <> prev_nl && cm.cm_depth <> prev_nl + 1)) && (parent_pos = null_pos || cm.cm_pos <> parent_pos) in
-			let file_changed = prev_pos = None || (pos_changed && match (cm.cm_pos.pfile, (Option.get prev_pos).pfile) with
-				| (f1, f2) when (is_unknown_file f1) && (is_unknown_file f2) -> false
-				| (f1, f2) -> f1 <> f2
-			) in
-
-			let display_heading = cm.cm_depth = 0 || sev_changed || file_changed in
-			let display_source = cm.cm_depth = 0 || sev_changed || pos_changed in
-			let display_pos_marker = (not is_null_pos) && (cm.cm_depth = 0 || sev_changed || pos_changed) in
-
-			let gutter_len = (try String.length (Printf.sprintf "%d" (IntMap.find cm.cm_depth ectx.max_lines)) with Not_found -> 0) + 2 in
-
-			let no_color = Define.defined ctx.com.defines Define.NoColor in
-			let c_reset = if no_color then "" else "\x1b[0m" in
-			let c_bold = if no_color then "" else "\x1b[1m" in
-			let c_dim = if no_color then "" else "\x1b[2m" in
-
-			let (c_sev, c_sev_bg) = if no_color then ("", "") else match cm.cm_severity with
-				| MessageSeverity.Warning -> ("\x1b[33m", "\x1b[30;43m")
-				| Information | Hint -> ("\x1b[34m", "\x1b[30;44m")
-				| Error -> ("\x1b[31m", "\x1b[30;41m")
-			in
-
-			let sev_label = if cm.cm_depth > 0 then " -> " else Printf.sprintf
-				(if no_color then "[%s]" else " %s ")
-				(match cm.cm_severity with
-					| MessageSeverity.Warning -> "WARNING"
-					| Information -> "INFO"
-					| Hint -> "HINT"
-					| Error -> "ERROR"
-				) in
-
-			let out = ref "" in
-
-			if display_heading then
-				out := Printf.sprintf "%s%s\n\n"
-					(* Severity heading *)
-					(c_sev_bg ^ sev_label ^ c_reset ^ " ")
-					(* File + line pointer *)
-					epos;
-
-			(* Error source *)
-			if display_source then out := List.fold_left (fun out (l, line) ->
-				let nb_len = String.length (string_of_int l) in
-
-				(* Replace tabs with 1 space to avoid column misalignments *)
-				let line = String.concat " " (ExtString.String.nsplit line "\t") in
-				let len = String.length line in
-
-				out ^ Printf.sprintf "%s%s | %s\n"
-					(* left-padded line number *)
-					(String.make (gutter_len-nb_len-1) ' ')
-					(if l = 0 then "-" else Printf.sprintf "%d" l)
-					(* Source code at that line *)
-					(
-						if l = 0 then
-							c_dim ^ line ^ c_reset
-						else if l1 = l2 then
-							(if p1 > 1 then c_dim ^ (String.sub line 0 (p1-1)) else "")
-							^ c_reset ^ c_bold ^ (String.sub line (p1-1) (p2-p1))
-							^ c_reset ^ c_dim ^ (String.sub line (p2-1) (len - p2 + 1))
-							^ c_reset
-						else begin
-							(if (l = l1) then
-								(if p1 > 1 then c_dim ^ (String.sub line 0 (p1-1)) else "")
-								^ c_reset ^ c_bold ^ (String.sub line (p1-1) (len-p1+1))
-								^ c_reset
-							else if (l = l2) then
-								(if p2 > 1 then c_bold ^ (String.sub line 0 (p2-1)) else "")
-								^ c_reset ^ c_dim ^ (String.sub line (p2-1) (len-p2+1))
-								^ c_reset
-							else c_bold ^ line ^ c_reset)
-						end
-					)
-			) !out lines;
-
-			(* Error position marker *)
-			if display_pos_marker then
-				out := Printf.sprintf "%s%s|%s\n"
-					!out
-					(String.make gutter_len ' ')
-					(if l1 = l2 then String.make p1 ' ' ^ c_sev ^ String.make (if p1 = p2 then 1 else p2-p1) '^' ^ c_reset else "");
-
-			(* Error message *)
-			out := List.fold_left (fun out str -> Printf.sprintf "%s%s| %s\n"
-				out
-				(String.make gutter_len ' ')
-				(* Remove "... " prefix *)
-				(if (ExtString.String.starts_with str "... ") then String.sub str 4 ((String.length str) - 4) else str)
-			) !out (ExtString.String.nsplit cm.cm_message "\n");
-
-			ectx.previous <- Some ((if is_null_pos then null_pos else cm.cm_pos), cm.cm_severity, cm.cm_depth);
-			ectx.gutter <- (IntMap.add cm.cm_depth gutter_len ectx.gutter);
-
-			(* Indent sub errors *)
-			let rec indent ?(acc=0) depth =
-				if depth = 0 then acc
-				else indent ~acc:(acc + try IntMap.find (depth-1) ectx.gutter with Not_found -> 3) (depth-1)
-			in
-
-			Some (
-				if cm.cm_depth > 0 then String.concat "\n" (List.map (fun str -> match str with
-					| "" -> ""
-					| _ -> (String.make (indent cm.cm_depth) ' ') ^ str
-				) (ExtString.String.nsplit !out "\n"))
-				else !out
-			)
-		end
-
-	let compiler_message_string ctx ectx cm =
-		let str = match cm.cm_severity with
-			| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
-			| Information | Error | Hint -> cm.cm_message
-		in
-
-		if cm.cm_pos = null_pos then
-			Some str
-		else begin
-			let epos = Lexer.get_error_pos error_printer cm.cm_pos in
-			let str =
-				let lines =
-					match (ExtString.String.nsplit str "\n") with
-					| first :: rest -> first :: List.map Error.compl_msg rest
-					| l -> l
-				in
-				String.concat ("\n" ^ epos ^ " : ") lines
-			in
-			Some (Printf.sprintf "%s : %s" epos str)
-		end
-
-	let compiler_indented_message_string ctx ectx cm =
-		match cm.cm_message with
-		(* Filter some messages that don't add much when using this message renderer *)
-		| "End of overload failure reasons" -> None
-		| _ ->
-			let str = match cm.cm_severity with
-				| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
-				| Information -> "Info : " ^ cm.cm_message
-				| Error | Hint -> cm.cm_message
-			in
-
-			if cm.cm_pos = null_pos then
-				Some str
-			else begin
-				let epos = Lexer.get_error_pos error_printer cm.cm_pos in
-				let lines =
-					match (ExtString.String.nsplit str "\n") with
-					| first :: rest -> (cm.cm_depth, first) :: List.map (fun msg -> (cm.cm_depth+1, msg)) rest
-					| l -> [(cm.cm_depth, List.hd l)]
-				in
-				let rm_prefix str = if (ExtString.String.starts_with str "... ") then String.sub str 4 ((String.length str) - 4) else str in
-				Some (String.concat "\n" (List.map (fun (depth, msg) -> (String.make (depth*2) ' ') ^ epos ^ " : " ^ (rm_prefix msg)) lines))
-			end
-
-	let get_max_line max_lines messages =
-		List.fold_left (fun max_lines cm ->
-			let _,_,l2,_ = Lexer.get_pos_coords cm.cm_pos in
-			let old = try IntMap.find cm.cm_depth max_lines with Not_found -> 0 in
-
-			if l2 > old then IntMap.add cm.cm_depth l2 max_lines
-			else max_lines
-		) max_lines messages
-
-	let display_messages ctx on_message = begin
-		let ectx = create_error_context () in
-		ectx.max_lines <- get_max_line ectx.max_lines ctx.messages;
-
-		let get_formatter def default =
-			let format_mode = Define.defined_value_safe ~default ctx.com.defines def in
-			match format_mode with
-				| "pretty" -> compiler_pretty_message_string ctx ectx
-				| "indent" -> compiler_indented_message_string ctx ectx
-				| "classic" -> compiler_message_string ctx ectx
-				| m -> begin
-					let def = Define.get_define_key def in
-					error ctx (Printf.sprintf "Invalid message reporting mode: \"%s\", expected classic | pretty | indent (for -D %s)." m def) null_pos;
-					compiler_message_string ctx ectx
-				end
-			in
-
-		let message_formatter = get_formatter Define.MessageReporting "classic" in
-		let log_formatter = get_formatter Define.MessagesLogFormat "indent" in
-
-		let log_messages = ref (Define.defined ctx.com.defines Define.MessagesLogFile) in
-		let log_message = ref None in
-		let close_logs = ref None in
-
-		if !log_messages then begin
-			try begin
-				let buf = Rbuffer.create 16000 in
-
-				let file = Define.defined_value ctx.com.defines Define.MessagesLogFile in
-				let chan =
-					Path.mkdir_from_path file;
-					open_out_bin file
-				in
-
-				log_message := (Some (fun msg ->
-					match (log_formatter msg) with
-						| None -> ()
-						| Some str -> Rbuffer.add_string buf (str ^ "\n")));
-
-				close_logs := (Some (fun () ->
-					Rbuffer.output_buffer chan buf;
-					Rbuffer.clear buf;
-					close_out chan
-				));
-			end with
-				| Failure e | Sys_error e -> begin
-					let def = Define.get_define_key Define.MessagesLogFile in
-					error ctx (Printf.sprintf "Error opening log file: %s. Logging to file disabled (-D %s)" e def) null_pos;
-					log_messages := false;
-				end
-		end;
-
-		List.iter (fun cm ->
-			if !log_messages then (Option.get !log_message) cm;
-
-			match (message_formatter cm) with
-				| None -> ()
-				| Some str -> on_message cm.cm_severity str
-		) (List.rev ctx.messages);
-
-		if !log_messages then (Option.get !close_logs) ();
-	end
-
 	let create_stdio () =
 		let rec self = {
 			write_out = (fun s ->
@@ -479,32 +121,38 @@ module Communication = struct
 		} in
 		self
 
-	let create_pipe sctx write = {
-		write_out = (fun s ->
-			write ("\x01" ^ String.concat "\x01" (ExtString.String.nsplit s "\n") ^ "\n")
-		);
-		write_err = (fun s ->
-			write s
-		);
-		flush = (fun ctx ->
-			check_display_flush ctx (fun () ->
-				display_messages ctx (fun _ output ->
-					write (output ^ "\n");
-					ServerMessage.message output;
-				);
-
-				sctx.was_compilation <- ctx.com.display.dms_full_typing;
-				if has_error ctx then begin
-					measure_times := false;
-					write "\x02\n"
-				end
-			)
-		);
-		exit = (fun i ->
-			()
-		);
-		is_server = true;
-	}
+	let create_pipe sctx write =
+		let rec self = {
+			write_out = (fun s ->
+				write ("\x01" ^ String.concat "\n\x01" (ExtString.String.nsplit s "\n") ^ "\n")
+			);
+			write_err = (fun s ->
+				write s
+			);
+			flush = (fun ctx ->
+				check_display_flush ctx (fun () ->
+					display_messages ctx (fun _ output ->
+						write (output ^ "\n");
+						ServerMessage.message output;
+					);
+
+					sctx.was_compilation <- ctx.com.display.dms_full_typing;
+					if has_error ctx then begin
+						measure_times := false;
+						write "\x02\n"
+					end else begin
+						Timer.close_times();
+						if !Timer.measure_times then Timer.report_times (fun s -> self.write_err (s ^ "\n"));
+					end
+				)
+			);
+			exit = (fun i ->
+				()
+			);
+			is_server = true;
+		}
+		in
+		self
 end
 
 let stat dir =
@@ -643,7 +291,7 @@ let check_module sctx ctx m p =
 					raise (ServerError ("Infinite loop in Haxe server detected. "
 						^ "Probably caused by shadowing a module of the standard library. "
 						^ "Make sure shadowed module does not pull macro context."));
-				let _, mctx = MacroContext.get_macro_context ctx p in
+				let mctx = MacroContext.get_macro_context ctx in
 				check_module_shadowing (get_changed_directories sctx mctx) m
 		in
 		let has_policy policy = List.mem policy m.m_extra.m_check_policy || match policy with
@@ -663,7 +311,9 @@ let check_module sctx ctx m p =
 			end
 		in
 		let check_dependencies () =
-			PMap.iter (fun _ m2 -> match check m2 with
+			PMap.iter (fun _ (sign,mpath) ->
+				let m2 = (com.cs#get_context sign)#find_module mpath in
+				match check m2 with
 				| None -> ()
 				| Some reason -> raise (Dirty (DependencyDirty(m2.m_path,reason)))
 			) m.m_extra.m_deps;
@@ -745,6 +395,16 @@ let check_module sctx ctx m p =
 	end;
 	state
 
+let handle_cache_bound_objects com cbol =
+	DynArray.iter (function
+		| Resource(name,data) ->
+			Hashtbl.replace com.resources name data
+		| IncludeFile(file,position) ->
+			com.include_files <- (file,position) :: com.include_files
+		| Warning(w,msg,p) ->
+			com.warning w [] msg p
+	) cbol
+
 (* Adds module [m] and all its dependencies (recursively) from the cache to the current compilation
    context. *)
 let add_modules sctx ctx m p =
@@ -754,7 +414,7 @@ let add_modules sctx ctx m p =
 			(match m0.m_extra.m_kind, m.m_extra.m_kind with
 			| MCode, MMacro | MMacro, MCode ->
 				(* this was just a dependency to check : do not add to the context *)
-				PMap.iter (Hashtbl.replace com.resources) m.m_extra.m_binded_res;
+				handle_cache_bound_objects com m.m_extra.m_cache_bound_objects;
 			| _ ->
 				m.m_extra.m_added <- ctx.com.compilation_step;
 				ServerMessage.reusing com tabs m;
@@ -762,8 +422,11 @@ let add_modules sctx ctx m p =
 					(t_infos t).mt_restore()
 				) m.m_types;
 				TypeloadModule.ModuleLevel.add_module ctx m p;
-				PMap.iter (Hashtbl.replace com.resources) m.m_extra.m_binded_res;
-				PMap.iter (fun _ m2 -> add_modules (tabs ^ "  ") m0 m2) m.m_extra.m_deps
+				handle_cache_bound_objects com m.m_extra.m_cache_bound_objects;
+				PMap.iter (fun _ (sign,mpath) ->
+					let m2 = (com.cs#get_context sign)#find_module mpath in
+					add_modules (tabs ^ "  ") m0 m2
+				) m.m_extra.m_deps
 			)
 		end
 	in
@@ -798,7 +461,7 @@ let type_module sctx (ctx:Typecore.typer) mpath p =
 let before_anything sctx ctx =
 	ensure_macro_setup sctx
 
-let after_arg_parsing sctx ctx =
+let after_target_init sctx ctx =
 	let com = ctx.com in
 	let cs = sctx.cs in
 	let sign = Define.get_signature com.defines in
@@ -893,9 +556,16 @@ let init_wait_stdio() =
 	mk_length_prefixed_communication false stdin stderr
 
 (* The connect function to connect to [host] at [port] and send arguments [args]. *)
-let do_connect host port args =
-	let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
-	(try Unix.connect sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't connect on " ^ host ^ ":" ^ string_of_int port));
+let do_connect ip port args =
+	let (domain, host) = match ip with
+		| V4 ip -> (Unix.PF_INET, V4.to_string ip)
+		| V6 ip -> (Unix.PF_INET6, V6.to_string ip)
+	in
+	let sock = Unix.socket domain Unix.SOCK_STREAM 0 in
+	(try Unix.connect sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with
+		| Unix.Unix_error(code,_,_) -> failwith("Couldn't connect on " ^ host ^ ":" ^ string_of_int port ^ " (" ^ (Unix.error_message code) ^ ")");
+		| _ -> failwith ("Couldn't connect on " ^ host ^ ":" ^ string_of_int port)
+	);
 	let rec display_stdin args =
 		match args with
 		| [] -> ""
@@ -910,7 +580,7 @@ let do_connect host port args =
 	let s = (String.concat "" (List.map (fun a -> a ^ "\n") args)) ^ (display_stdin args) in
 	ssend sock (Bytes.of_string (s ^ "\000"));
 	let has_error = ref false in
-	let rec print line =
+	let print line =
 		match (if line = "" then '\x00' else line.[0]) with
 		| '\x01' ->
 			print_string (String.concat "\n" (List.tl (ExtString.String.nsplit line "\x01")));
@@ -961,7 +631,7 @@ let rec process sctx comm args =
 		cache = sctx.cs;
 		callbacks = {
 			before_anything = before_anything sctx;
-			after_arg_parsing = after_arg_parsing sctx;
+			after_target_init = after_target_init sctx;
 			after_compilation = after_compilation sctx;
 		};
 		init_wait_socket = init_wait_socket;
@@ -1058,14 +728,22 @@ and wait_loop verbose accept =
 	0
 
 (* Connect to given host/port and return accept function for communication *)
-and init_wait_connect host port =
+and init_wait_connect ip port =
+	let host = match ip with
+		| V4 ip -> V4.to_string ip
+		| V6 ip -> V6.to_string ip
+	in
 	let host = Unix.inet_addr_of_string host in
 	let chin, chout = Unix.open_connection (Unix.ADDR_INET (host,port)) in
 	mk_length_prefixed_communication true chin chout
 
 (* The accept-function to wait for a socket connection. *)
-and init_wait_socket host port =
-	let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
+and init_wait_socket ip port =
+	let (domain, host) = match ip with
+		| V4 ip -> (Unix.PF_INET, V4.to_string ip)
+		| V6 ip -> (Unix.PF_INET6, V6.to_string ip)
+	in
+	let sock = Unix.socket domain Unix.SOCK_STREAM 0 in
 	(try Unix.setsockopt sock Unix.SO_REUSEADDR true with _ -> ());
 	(try Unix.bind sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't wait on " ^ host ^ ":" ^ string_of_int port));
 	ServerMessage.socket_message ("Waiting on " ^ host ^ ":" ^ string_of_int port);

+ 7 - 3
src/compiler/serverCompilationContext.ml

@@ -58,7 +58,7 @@ let reset sctx =
 	Helper.start_time := get_time()
 
 let maybe_cache_context sctx com =
-	if com.display.dms_full_typing then begin
+	if com.display.dms_full_typing && com.display.dms_populate_cache then begin
 		CommonCache.cache_context sctx.cs com;
 		ServerMessage.cached_modules com "" (List.length com.modules);
 	end
@@ -70,5 +70,9 @@ let ensure_macro_setup sctx =
 	end
 
 let cleanup () = match !MacroContext.macro_interp_cache with
-	| Some interp -> EvalContext.GlobalState.cleanup interp
-	| None -> ()
+	| Some interp ->
+		(* curapi holds a reference to the typing context which we don't want to persist. Let's unset it so the
+		   context can be collected. *)
+		interp.curapi <- Obj.magic ""
+	| None ->
+		()

+ 2 - 1
src/compiler/serverConfig.ml

@@ -1,2 +1,3 @@
 let do_not_check_modules = ref false
-let legacy_completion = ref false
+let populate_cache_from_display = ref true
+let legacy_completion = ref false

+ 7 - 1
src/compiler/serverMessage.ml

@@ -2,9 +2,9 @@ open Globals
 open Common
 open CompilationCache
 open Type
-open Json
 
 type server_message_options = {
+	mutable print_compiler_stage : bool;
 	mutable print_added_directory : bool;
 	mutable print_found_directories : bool;
 	mutable print_changed_directories : bool;
@@ -31,6 +31,7 @@ type server_message_options = {
 }
 
 let config = {
+	print_compiler_stage = false;
 	print_added_directory = false;
 	print_found_directories = false;
 	print_changed_directories = false;
@@ -62,6 +63,9 @@ let sign_string com =
 	let	sign_id = (cs#get_context sign)#get_index in
 	Printf.sprintf "%2i,%3s: " sign_id (short_platform_name com.platform)
 
+let compiler_stage com =
+	if config.print_compiler_stage then print_endline (Printf.sprintf "compiler stage: %s" (s_compiler_stage com.stage))
+
 let added_directory com tabs dir =
 	if config.print_added_directory then print_endline (Printf.sprintf "%sadded directory %s" (sign_string com) dir)
 
@@ -157,6 +161,7 @@ let uncaught_error s =
 	if config.print_uncaught_error then print_endline ("Uncaught Error : " ^ s)
 
 let enable_all () =
+	config.print_compiler_stage <- true;
 	config.print_added_directory <- true;
 	config.print_found_directories <- true;
 	config.print_changed_directories <- true;
@@ -181,6 +186,7 @@ let enable_all () =
 	config.print_new_context <- true
 
 let set_by_name name value = match name with
+	| "compilerStage" -> config.print_compiler_stage <- value
 	| "addedDirectory" -> config.print_added_directory <- value
 	| "foundDirectories" -> config.print_found_directories <- value;
 	| "changedDirectories" -> config.print_changed_directories <- value;

+ 23 - 21
src/context/abstractCast.ml

@@ -4,7 +4,6 @@ open Ast
 open Type
 open Typecore
 open Error
-open CallUnification
 
 let cast_stack = new_rec_stack()
 
@@ -15,11 +14,11 @@ let rec make_static_call ctx c cf a pl args t p =
 				let e,f = push_this ctx e in
 				ctx.with_type_stack <- (WithType.with_type t) :: ctx.with_type_stack;
 				let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name [e] p with
-					| Some e -> type_expr ctx e (WithType.with_type t)
-					| None ->  type_expr ctx (EConst (Ident "null"),p) WithType.value
+					| MSuccess e -> type_expr ctx e (WithType.with_type t)
+					| _ ->  type_expr ctx (EConst (Ident "null"),p) WithType.value
 				in
 				ctx.with_type_stack <- List.tl ctx.with_type_stack;
-				let e = try cast_or_unify_raise ctx t e p with Error(Unify _,_,_) -> raise Not_found in
+				let e = try cast_or_unify_raise ctx t e p with Error { err_message = Unify _ } -> raise Not_found in
 				f();
 				e
 			| _ -> die "" __LOC__
@@ -38,10 +37,10 @@ and do_check_cast ctx uctx tleft eright p =
 				(try
 					Type.unify_custom uctx eright.etype tleft;
 				with Unify_error l ->
-					raise (Error (Unify l, eright.epos,0)))
+					raise_error_msg (Unify l) eright.epos)
 			| _ -> ()
 		end;
-		if cf == ctx.curfield || rec_stack_memq cf cast_stack then typing_error "Recursive implicit cast" p;
+		if cf == ctx.curfield || rec_stack_memq cf cast_stack then raise_typing_error "Recursive implicit cast" p;
 		rec_stack_loop cast_stack cf f ()
 	in
 	let make (a,tl,(tcf,cf)) =
@@ -89,7 +88,9 @@ and do_check_cast ctx uctx tleft eright p =
 					end
 				| TInst(c,tl), TFun _ when has_class_flag c CFunctionalInterface ->
 					let cf = ctx.g.functional_interface_lut#find c.cl_path in
-					unify_raise_custom uctx eright.etype (apply_params c.cl_params tl cf.cf_type) p;
+					let map = apply_params c.cl_params tl in
+					let monos = Monomorph.spawn_constrained_monos map cf.cf_params in
+					unify_raise_custom uctx eright.etype (map (apply_params cf.cf_params monos cf.cf_type)) p;
 					eright
 				| _ ->
 					raise Not_found
@@ -112,18 +113,19 @@ and cast_or_unify_raise ctx ?(uctx=None) tleft eright p =
 and cast_or_unify ctx tleft eright p =
 	try
 		cast_or_unify_raise ctx tleft eright p
-	with Error (Unify l,p,_) ->
-		raise_or_display ctx l p;
+	with Error ({ err_message = Unify _ } as err) ->
+		raise_or_display_error ctx err;
 		eright
 
 let prepare_array_access_field ctx a pl cf p =
 	let monos = List.map (fun _ -> spawn_monomorph ctx p) cf.cf_params in
 	let map t = apply_params a.a_params pl (apply_params cf.cf_params monos t) in
 	let check_constraints () =
-		List.iter2 (fun m tp -> match follow tp.ttp_type with
-			| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
+		List.iter2 (fun m ttp -> match get_constraints ttp with
+			| [] ->
+				()
+			| constr ->
 				List.iter (fun tc -> match follow m with TMono _ -> raise (Unify_error []) | _ -> Type.unify m (map tc) ) constr
-			| _ -> ()
 		) monos cf.cf_params;
 	in
 	let get_ta() =
@@ -146,7 +148,7 @@ let find_array_read_access_raise ctx a pl e1 p =
 					let e1 = cast_or_unify_raise ctx ta1 e1 p in
 					check_constraints();
 					cf,tf,r,e1
-				with Unify_error _ | Error (Unify _,_,_) ->
+				with Unify_error _ | Error { err_message = Unify _ } ->
 					loop cfl
 				end
 			| _ -> loop cfl
@@ -167,7 +169,7 @@ let find_array_write_access_raise ctx a pl e1 e2  p =
 					let e2 = cast_or_unify_raise ctx ta2 e2 p in
 					check_constraints();
 					cf,tf,r,e1,e2
-				with Unify_error _ | Error (Unify _,_,_) ->
+				with Unify_error _ | Error { err_message = Unify _ } ->
 					loop cfl
 				end
 			| _ -> loop cfl
@@ -179,14 +181,14 @@ let find_array_read_access ctx a tl e1 p =
 		find_array_read_access_raise ctx a tl e1 p
 	with Not_found ->
 		let s_type = s_type (print_context()) in
-		typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts argument of %s" (s_type (TAbstract(a,tl))) (s_type e1.etype)) p
+		raise_typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts argument of %s" (s_type (TAbstract(a,tl))) (s_type e1.etype)) p
 
 let find_array_write_access ctx a tl e1 e2 p =
 	try
 		find_array_write_access_raise ctx a tl e1 e2 p
 	with Not_found ->
 		let s_type = s_type (print_context()) in
-		typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts arguments of %s and %s" (s_type (TAbstract(a,tl))) (s_type e1.etype) (s_type e2.etype)) p
+		raise_typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts arguments of %s and %s" (s_type (TAbstract(a,tl))) (s_type e1.etype) (s_type e2.etype)) p
 
 let find_multitype_specialization com a pl p =
 	let uctx = default_unification_context in
@@ -202,7 +204,7 @@ let find_multitype_specialization com a pl p =
 					stack := t :: !stack;
 					match follow t with
 					| TAbstract ({ a_path = [],"Class" },_) ->
-						typing_error (Printf.sprintf "Cannot use %s as key type to Map because Class<T> is not comparable on JavaScript" (s_type (print_context()) t1)) p;
+						raise_typing_error (Printf.sprintf "Cannot use %s as key type to Map because Class<T> is not comparable on JavaScript" (s_type (print_context()) t1)) p;
 					| TEnum(en,tl) ->
 						PMap.iter (fun _ ef -> ignore(loop ef.ef_type)) en.e_constrs;
 						Type.map loop t
@@ -219,16 +221,16 @@ let find_multitype_specialization com a pl p =
 			if List.exists (fun t -> has_mono t) definitive_types then begin
 				let at = apply_params a.a_params pl a.a_this in
 				let st = s_type (print_context()) at in
-				typing_error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
+				raise_typing_error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
 			end;
 			t
 		with Not_found ->
 			let at = apply_params a.a_params pl a.a_this in
 			let st = s_type (print_context()) at in
 			if has_mono at then
-				typing_error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
+				raise_typing_error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
 			else
-				typing_error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p;
+				raise_typing_error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p;
 	in
 	cf, follow m
 
@@ -240,7 +242,7 @@ let handle_abstract_casts ctx e =
 					let's construct the underlying type. *)
 				match Abstract.get_underlying_type a pl with
 				| TInst(c,tl) as t -> {e with eexpr = TNew(c,tl,el); etype = t}
-				| _ -> typing_error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos
+				| _ -> raise_typing_error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos
 			end else begin
 				(* a TNew of an abstract implementation is only generated if it is a multi type abstract *)
 				let cf,m = find_multitype_specialization ctx.com a pl e.epos in

+ 168 - 129
src/context/common.ml

@@ -20,6 +20,7 @@ open Extlib_leftovers
 open Ast
 open Type
 open Globals
+open Lookup
 open Define
 open NativeLibraries
 open Warning
@@ -168,39 +169,48 @@ type platform_config = {
 }
 
 class compiler_callbacks = object(self)
-	val mutable before_typer_create = [];
-	val mutable after_init_macros = [];
+	val before_typer_create = ref [];
+	val after_init_macros = ref [];
 	val mutable after_typing = [];
-	val mutable before_save = [];
-	val mutable after_save = [];
-	val mutable after_filters = [];
-	val mutable after_generation = [];
+	val before_save = ref [];
+	val after_save = ref [];
+	val after_filters = ref [];
+	val after_generation = ref [];
 	val mutable null_safety_report = [];
 
 	method add_before_typer_create (f : unit -> unit) : unit =
-		before_typer_create <- f :: before_typer_create
+		before_typer_create := f :: !before_typer_create
 
 	method add_after_init_macros (f : unit -> unit) : unit =
-		after_init_macros <- f :: after_init_macros
+		after_init_macros := f :: !after_init_macros
 
 	method add_after_typing (f : module_type list -> unit) : unit =
 		after_typing <- f :: after_typing
 
 	method add_before_save (f : unit -> unit) : unit =
-		before_save <- f :: before_save
+		before_save := f :: !before_save
 
 	method add_after_save (f : unit -> unit) : unit =
-		after_save <- f :: after_save
+		after_save := f :: !after_save
 
 	method add_after_filters (f : unit -> unit) : unit =
-		after_filters <- f :: after_filters
+		after_filters := f :: !after_filters
 
 	method add_after_generation (f : unit -> unit) : unit =
-		after_generation <- f :: after_generation
+		after_generation := f :: !after_generation
 
 	method add_null_safety_report (f : (string*pos) list -> unit) : unit =
 		null_safety_report <- f :: null_safety_report
 
+	method run handle_error r =
+		match !r with
+		| [] ->
+			()
+		| l ->
+			r := [];
+			List.iter (fun f -> try f() with Error.Error err -> handle_error err) (List.rev l);
+			self#run handle_error r
+
 	method get_before_typer_create = before_typer_create
 	method get_after_init_macros = after_init_macros
 	method get_after_typing = after_typing
@@ -224,7 +234,7 @@ class file_keys = object(self)
 end
 
 type shared_display_information = {
-	mutable diagnostics_messages : (string * pos * MessageKind.t * MessageSeverity.t) list;
+	mutable diagnostics_messages : diagnostic list;
 }
 
 type display_information = {
@@ -247,7 +257,6 @@ type json_api = {
 type compiler_stage =
 	| CCreated          (* Context was just created *)
 	| CInitialized      (* Context was initialized (from CLI args and such). *)
-	| CTyperCreated     (* The typer context was just created. *)
 	| CInitMacrosStart  (* Init macros are about to run. *)
 	| CInitMacrosDone   (* Init macros did run - at this point the signature is locked. *)
 	| CTypingDone       (* The typer is done - at this point com.types/modules/main is filled. *)
@@ -262,71 +271,67 @@ type compiler_stage =
 	| CGenerationStart  (* Generation is about to begin. *)
 	| CGenerationDone   (* Generation just finished. *)
 
+let s_compiler_stage = function
+	| CCreated          -> "CCreated"
+	| CInitialized      -> "CInitialized"
+	| CInitMacrosStart  -> "CInitMacrosStart"
+	| CInitMacrosDone   -> "CInitMacrosDone"
+	| CTypingDone       -> "CTypingDone"
+	| CFilteringStart   -> "CFilteringStart"
+	| CAnalyzerStart    -> "CAnalyzerStart"
+	| CAnalyzerDone     -> "CAnalyzerDone"
+	| CSaveStart        -> "CSaveStart"
+	| CSaveDone         -> "CSaveDone"
+	| CDceStart         -> "CDceStart"
+	| CDceDone          -> "CDceDone"
+	| CFilteringDone    -> "CFilteringDone"
+	| CGenerationStart  -> "CGenerationStart"
+	| CGenerationDone   -> "CGenerationDone"
+
 type report_mode =
 	| RMNone
-	| RMDiagnostics of Path.UniqueKey.t list
+	| RMLegacyDiagnostics of (Path.UniqueKey.t list)
+	| RMDiagnostics of (Path.UniqueKey.t list)
 	| RMStatistics
 
-class virtual ['key,'value] lookup = object(self)
-	method virtual add : 'key -> 'value -> unit
-	method virtual remove : 'key -> unit
-	method virtual find : 'key -> 'value
-	method virtual iter : ('key -> 'value -> unit) -> unit
-	method virtual fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc
-	method virtual mem : 'key -> bool
-	method virtual clear : unit
-end
-
-class ['key,'value] pmap_lookup = object(self)
-	inherit ['key,'value] lookup
-	val mutable lut : ('key,'value) PMap.t = PMap.empty
-
-	method add (key : 'key) (value : 'value) =
-		lut <- PMap.add key value lut
-
-	method remove (key : 'key) =
-		lut <- PMap.remove key lut
-
-	method find (key : 'key) : 'value =
-		PMap.find key lut
-
-	method iter (f : 'key -> 'value -> unit) =
-		PMap.iter f lut
-
-	method fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc = fun f acc ->
-		PMap.foldi f lut acc
+class module_lut = object(self)
+	inherit [path,module_def] hashtbl_lookup as super
 
-	method mem (key : 'key) =
-		PMap.mem key lut
+	val type_lut : (path,path) lookup = new hashtbl_lookup
 
-	method clear =
-		lut <- PMap.empty
-end
-
-class ['key,'value] hashtbl_lookup = object(self)
-	inherit ['key,'value] lookup
-	val lut : ('key,'value) Hashtbl.t = Hashtbl.create 0
-
-	method add (key : 'key) (value : 'value) =
-		Hashtbl.replace lut key value
-
-	method remove (key : 'key) =
-		Hashtbl.remove lut key
+	method add_module_type (m : module_def) (mt : module_type) =
+		let t = t_infos mt in
+		try
+			let path2 = type_lut#find t.mt_path in
+			let p = t.mt_pos in
+			if m.m_path <> path2 && String.lowercase_ascii (s_type_path path2) = String.lowercase_ascii (s_type_path m.m_path) then Error.raise_typing_error ("Module " ^ s_type_path path2 ^ " is loaded with a different case than " ^ s_type_path m.m_path) p;
+			let m2 = self#find path2 in
+			let hex1 = Digest.to_hex m.m_extra.m_sign in
+			let hex2 = Digest.to_hex m2.m_extra.m_sign in
+			let s = if hex1 = hex2 then hex1 else Printf.sprintf "was %s, is %s" hex2 hex1 in
+			Error.raise_typing_error (Printf.sprintf "Type name %s is redefined from module %s (%s)" (s_type_path t.mt_path)  (s_type_path path2) s) p
+		with Not_found ->
+			type_lut#add t.mt_path m.m_path
 
-	method find (key : 'key) : 'value =
-		Hashtbl.find lut key
+	method! add (path : path) (m : module_def) =
+		super#add path m;
+		List.iter (fun mt -> self#add_module_type m mt) m.m_types
 
-	method iter (f : 'key -> 'value -> unit) =
-		Hashtbl.iter f lut
+	method! remove (path : path) =
+		try
+			List.iter (fun mt -> type_lut#remove (t_path mt)) (self#find path).m_types;
+			super#remove path;
+		with Not_found ->
+			()
 
-	method fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc = fun f acc ->
-		Hashtbl.fold f lut acc
+	method find_by_type (path : path) =
+		self#find (type_lut#find path)
 
-	method mem (key : 'key) =
-		Hashtbl.mem lut key
+	method! clear =
+		super#clear;
+		type_lut#clear
 
-	method clear =
-		Hashtbl.clear lut
+	method get_type_lut = type_lut
 end
 
 type context = {
@@ -354,8 +359,9 @@ type context = {
 	(* communication *)
 	mutable print : string -> unit;
 	mutable error : ?depth:int -> string -> pos -> unit;
-	mutable info : ?depth:int -> string -> pos -> unit;
-	mutable warning : ?depth:int -> warning -> Warning.warning_option list list -> string -> pos -> unit;
+	mutable error_ext : Error.error -> unit;
+	mutable info : ?depth:int -> ?from_macro:bool -> string -> pos -> unit;
+	mutable warning : ?depth:int -> ?from_macro:bool -> warning -> Warning.warning_option list list -> string -> pos -> unit;
 	mutable warning_options : Warning.warning_option list list;
 	mutable get_messages : unit -> compiler_message list;
 	mutable filter_messages : (compiler_message -> bool) -> unit;
@@ -369,19 +375,20 @@ type context = {
 	mutable user_metas : (string, Meta.user_meta) Hashtbl.t;
 	mutable get_macros : unit -> context option;
 	(* typing state *)
+	mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list;
 	shared : shared_context;
 	display_information : display_information;
 	file_lookup_cache : (string,string option) lookup;
 	file_keys : file_keys;
+	mutable file_contents : (Path.UniqueKey.t * string option) list;
 	readdir_cache : (string * string,(string array) option) lookup;
 	parser_cache : (string,(type_def * pos) list) lookup;
 	module_to_file : (path,string) lookup;
 	cached_macros : (path * string,(((string * bool * t) list * t * tclass * Type.tclass_field) * module_def)) lookup;
 	stored_typed_exprs : (int, texpr) lookup;
 	overload_cache : ((path * string),(Type.t * tclass_field) list) lookup;
-	module_lut : (path,module_def) lookup;
+	module_lut : module_lut;
 	module_nonexistent_lut : (path,bool) lookup;
-	type_to_module : (path,path) lookup;
 	mutable has_error : bool;
 	pass_debug_messages : string DynArray.t;
 	(* output *)
@@ -393,7 +400,7 @@ type context = {
 	mutable resources : (string,string) Hashtbl.t;
 	(* target-specific *)
 	mutable flash_version : float;
-	mutable neko_libs : string list;
+	mutable neko_lib_paths : string list;
 	mutable include_files : (string * string) list;
 	mutable native_libs : native_libraries;
 	mutable net_std : string list;
@@ -405,14 +412,19 @@ type context = {
 	memory_marker : float array;
 }
 
-exception Abort of string * pos
+let enter_stage com stage =
+	(* print_endline (Printf.sprintf "Entering stage %s" (s_compiler_stage stage)); *)
+	com.stage <- stage
 
 let ignore_error com =
 	let b = com.display.dms_error_policy = EPIgnore in
-	if b then
-		if b then com.has_error <- true;
+	if b then com.has_error <- true;
 	b
 
+let module_warning com m w options msg p =
+	DynArray.add m.m_extra.m_cache_bound_objects (Warning(w,msg,p));
+	com.warning w options msg p
+
 (* Defines *)
 
 module Define = Define
@@ -443,6 +455,8 @@ let define_value com k v =
 let convert_define k =
 	String.concat "_" (ExtString.String.nsplit k "-")
 
+let is_next com = defined com HaxeNext
+
 let external_defined ctx k =
 	Define.raw_defined ctx.defines (convert_define k)
 
@@ -450,9 +464,9 @@ let external_defined_value ctx k =
 	Define.raw_defined_value ctx.defines (convert_define k)
 
 let reserved_flags = [
-	"true";"false";"null";"cross";"js";"lua";"neko";"flash";"php";"cpp";"cs";"java";"python";
+	"true";"false";"null";"cross";"js";"lua";"neko";"flash";"php";"cpp";"cs";"java";"python";"hl";"hlc";
 	"swc";"macro";"sys";"static";"utf16";"haxe";"haxe_ver"
-	]
+]
 
 let reserved_flag_namespaces = ["target"]
 
@@ -472,16 +486,11 @@ let convert_and_validate k =
 let external_define_value ctx k v =
 	raw_define_value ctx.defines (convert_and_validate k) v
 
-(* TODO: Temporary function until #8690, remove after *)
-let external_define_value_no_check ctx k v =
-	Define.raw_define_value ctx.defines (convert_define k) v
-
 let external_define ctx k =
 	Define.raw_define ctx.defines (convert_and_validate k)
 
-(* TODO: Temporary function until #8690, remove after *)
-let external_define_no_check ctx k =
-	Define.raw_define ctx.defines (convert_define k)
+let external_undefine ctx k =
+	Define.raw_undefine ctx.defines (convert_and_validate k)
 
 let defines_for_external ctx =
 	PMap.foldi (fun k v acc ->
@@ -507,6 +516,7 @@ let short_platform_name = function
 	| Python -> "py"
 	| Hl -> "hl"
 	| Eval -> "evl"
+	| CustomTarget n -> "c_" ^ n
 
 let stats =
 	{
@@ -552,6 +562,9 @@ let get_config com =
 	match com.platform with
 	| Cross ->
 		default_config
+	| CustomTarget _ ->
+		(* impossible to reach. see update_platform_config *)
+		raise Exit
 	| Js ->
 		let es6 = get_es_version com >= 6 in
 		{
@@ -750,6 +763,10 @@ let get_config com =
 			pf_pad_nulls = true;
 			pf_supports_threads = true;
 			pf_supports_atomics = true;
+			pf_scoping = {
+				vs_scope = BlockScope;
+				vs_flags = [NoShadowing]
+			};
 		}
 	| Eval ->
 		{
@@ -763,8 +780,7 @@ let get_config com =
 
 let memory_marker = [|Unix.time()|]
 
-let create compilation_step cs version args =
-	let m = Type.mk_mono() in
+let create compilation_step cs version args display_mode =
 	let rec com = {
 		compilation_step = compilation_step;
 		cs = cs;
@@ -784,7 +800,7 @@ let create compilation_step cs version args =
 		};
 		sys_args = args;
 		debug = false;
-		display = DisplayTypes.DisplayMode.create !Parser.display_mode;
+		display = display_mode;
 		verbose = false;
 		foptimize = true;
 		features = Hashtbl.create 0;
@@ -800,10 +816,10 @@ let create compilation_step cs version args =
 		file = "";
 		types = [];
 		callbacks = new compiler_callbacks;
+		global_metadata = [];
 		modules = [];
-		module_lut = new hashtbl_lookup;
+		module_lut = new module_lut;
 		module_nonexistent_lut = new hashtbl_lookup;
-		type_to_module = new hashtbl_lookup;
 		main = None;
 		flash_version = 10.;
 		resources = Hashtbl.create 0;
@@ -811,7 +827,7 @@ let create compilation_step cs version args =
 		native_libs = create_native_libs();
 		net_path_map = Hashtbl.create 0;
 		c_args = [];
-		neko_libs = [];
+		neko_lib_paths = [];
 		include_files = [];
 		js_gen = None;
 		load_extern_type = [];
@@ -822,24 +838,26 @@ let create compilation_step cs version args =
 		user_defines = Hashtbl.create 0;
 		user_metas = Hashtbl.create 0;
 		get_macros = (fun() -> None);
-		info = (fun ?depth _ _ -> die "" __LOC__);
-		warning = (fun ?depth _ _ _ -> die "" __LOC__);
+		info = (fun ?depth ?from_macro _ _ -> die "" __LOC__);
+		warning = (fun ?depth ?from_macro _ _ _ -> die "" __LOC__);
 		warning_options = [];
 		error = (fun ?depth _ _ -> die "" __LOC__);
+		error_ext = (fun _ -> die "" __LOC__);
 		get_messages = (fun() -> []);
 		filter_messages = (fun _ -> ());
 		pass_debug_messages = DynArray.create();
 		basic = {
-			tvoid = m;
-			tint = m;
-			tfloat = m;
-			tbool = m;
+			tvoid = mk_mono();
+			tint = mk_mono();
+			tfloat = mk_mono();
+			tbool = mk_mono();
+			tstring = mk_mono();
 			tnull = (fun _ -> die "Could use locate abstract Null<T> (was it redefined?)" __LOC__);
-			tstring = m;
 			tarray = (fun _ -> die "Could not locate class Array<T> (was it redefined?)" __LOC__);
 		};
 		file_lookup_cache = new hashtbl_lookup;
 		file_keys = new file_keys;
+		file_contents = [];
 		readdir_cache = new hashtbl_lookup;
 		module_to_file = new hashtbl_lookup;
 		stored_typed_exprs = new hashtbl_lookup;
@@ -855,7 +873,7 @@ let create compilation_step cs version args =
 	com
 
 let is_diagnostics com = match com.report_mode with
-	| RMDiagnostics _ -> true
+	| RMLegacyDiagnostics _ | RMDiagnostics _ -> true
 	| _ -> false
 
 let disable_report_mode com =
@@ -870,7 +888,12 @@ let clone com is_macro_context =
 	let t = com.basic in
 	{ com with
 		cache = None;
-		basic = { t with tvoid = t.tvoid };
+		basic = { t with
+			tint = mk_mono();
+			tfloat = mk_mono();
+			tbool = mk_mono();
+			tstring = mk_mono();
+		};
 		main_class = None;
 		features = Hashtbl.create 0;
 		callbacks = new compiler_callbacks;
@@ -890,8 +913,7 @@ let clone com is_macro_context =
 		parser_cache = new hashtbl_lookup;
 		module_to_file = new hashtbl_lookup;
 		overload_cache = new hashtbl_lookup;
-		module_lut = new hashtbl_lookup;
-		type_to_module = new hashtbl_lookup;
+		module_lut = new module_lut;
 	}
 
 let file_time file = Extc.filetime file
@@ -923,12 +945,23 @@ let flash_version_tag = function
 	| v when v >= 12.0 && float_of_int (int_of_float v) = v -> int_of_float v + 11
 	| v -> failwith ("Invalid SWF version " ^ string_of_float v)
 
-let init_platform com pf =
-	com.platform <- pf;
-	let name = platform_name pf in
+let update_platform_config com =
+	match com.platform with
+	| CustomTarget _ ->
+		() (* do nothing, configured with macro api *)
+	| _ ->
+		com.config <- get_config com
+
+let init_platform com =
+	let name = platform_name com.platform in
+	if (com.platform = Flash) && Path.file_extension com.file = "swc" then define com Define.Swc
+	else if (com.platform = Hl) && Path.file_extension com.file = "c" then define com Define.Hlc;
+	(* Set the source header, unless the user has set one already or the platform sets a custom one *)
+	if not (defined com Define.SourceHeader) && (com.platform <> Hl) then
+		define_value com Define.SourceHeader ("Generated by Haxe " ^ s_version_full);
 	let forbid acc p = if p = name || PMap.mem p acc then acc else PMap.add p Forbidden acc in
 	com.package_rules <- List.fold_left forbid com.package_rules ("jvm" :: (List.map platform_name platforms));
-	com.config <- get_config com;
+	update_platform_config com;
 	if com.config.pf_static then begin
 		raw_define com "target.static";
 		define com Define.Static;
@@ -949,19 +982,26 @@ let init_platform com pf =
 		raw_define com "target.unicode";
 	end;
 	raw_define_value com.defines "target.name" name;
-	raw_define com name;
+	raw_define com (match com.platform with | CustomTarget _ -> "custom_target" | _ -> name);
 	if com.config.pf_supports_atomics then begin
 		raw_define com "target.atomics"
 	end
 
 let set_platform com pf file =
 	if com.platform <> Cross then failwith "Multiple targets";
-	init_platform com pf;
-	com.file <- file;
-	if (pf = Flash) && Path.file_extension file = "swc" then define com Define.Swc;
-	(* Set the source header, unless the user has set one already or the platform sets a custom one *)
-	if not (defined com Define.SourceHeader) && (pf <> Hl) then
-		define_value com Define.SourceHeader ("Generated by Haxe " ^ s_version_full)
+	com.platform <- pf;
+	com.file <- file
+
+let set_custom_target com name path =
+	if List.find_opt (fun pf -> (platform_name pf) = name) platforms <> None then
+		raise (Arg.Bad (Printf.sprintf "--custom-target cannot use reserved name %s" name));
+	if String.length name > max_custom_target_len then
+		raise (Arg.Bad (Printf.sprintf "--custom-target name %s exceeds the maximum of %d characters" name max_custom_target_len));
+	let name_regexp = Str.regexp "^[a-zA-Z0-9\\_]+$" in
+	if Str.string_match name_regexp name 0 then
+		set_platform com (CustomTarget name) path
+	else
+		raise (Arg.Bad (Printf.sprintf "--custom-target name %s may only contain alphanumeric or underscore characters" name))
 
 let add_feature com f =
 	Hashtbl.replace com.features f true
@@ -1013,12 +1053,13 @@ let allow_package ctx s =
 	with Not_found ->
 		()
 
-let abort ?depth msg p = raise (Abort (msg,p))
+let abort ?(depth = 0) msg p = raise (Error.Fatal_error (Error.make_error ~depth (Custom msg) p))
 
 let platform ctx p = ctx.platform = p
 
 let platform_name_macro com =
-	if defined com Define.Macro then "macro" else platform_name com.platform
+	if defined com Define.Macro then "macro"
+	else platform_name com.platform
 
 let remove_extension file =
 	try String.sub file 0 (String.rindex file '.')
@@ -1078,7 +1119,7 @@ let cache_directory ctx class_path dir f_dir =
 	in
 	Option.may (Array.iter prepare_file) dir_listing
 
-let find_file ctx f =
+let find_file ctx ?(class_path=ctx.class_path) f =
 	try
 		match ctx.file_lookup_cache#find f with
 		| None -> raise Exit
@@ -1113,7 +1154,7 @@ let find_file ctx f =
 						loop (had_empty || p = "") l
 				end
 		in
-		let r = try Some (loop false ctx.class_path) with Not_found -> None in
+		let r = try Some (loop false class_path) with Not_found -> None in
 		ctx.file_lookup_cache#add f r;
 		match r with
 		| None -> raise Not_found
@@ -1217,23 +1258,21 @@ let utf16_to_utf8 str =
 	loop 0;
 	Buffer.contents b
 
-let add_diagnostics_message com msg kind sev =
-	let p = Globals.extract_located_pos msg in
-	let s = Globals.extract_located_msg msg in
+let add_diagnostics_message ?(depth = 0) ?(code = None) com s p kind sev =
 	if sev = MessageSeverity.Error then com.has_error <- true;
 	let di = com.shared.shared_display_information in
-	di.diagnostics_messages <- (s,p,kind,sev) :: di.diagnostics_messages
+	di.diagnostics_messages <- (make_diagnostic ~depth ~code s p kind sev) :: di.diagnostics_messages
 
-let located_display_error com ?(depth = 0) msg =
-	if is_diagnostics com then
-		add_diagnostics_message com msg MessageKind.DKCompilerMessage MessageSeverity.Error
-	else
-		com.error (Globals.extract_located_msg msg) (Globals.extract_located_pos msg) ~depth
+let display_error_ext com err =
+	if is_diagnostics com then begin
+		Error.recurse_error (fun depth err ->
+			add_diagnostics_message ~depth com (Error.error_msg err.err_message) err.err_pos MessageKind.DKCompilerMessage MessageSeverity.Error;
+		) err;
+	end else
+		com.error_ext err
 
 let display_error com ?(depth = 0) msg p =
-	located_display_error com ~depth (Globals.located msg p)
-
-open Printer
+	display_error_ext com (Error.make_error ~depth (Custom msg) p)
 
 let dump_path com =
 	Define.defined_value_safe ~default:"dump" com.defines Define.DumpPath

+ 42 - 55
src/context/display/deprecationCheck.ml

@@ -3,37 +3,48 @@ open Type
 open Common
 open Ast
 
-let curclass = ref null_class
-let curfield = ref null_field
+type deprecation_context = {
+	com        : Common.context;
+	class_meta : metadata_entry list;
+	field_meta : metadata_entry list;
+	curmod     : module_def;
+}
+
+let create_context com = {
+	com = com;
+	class_meta = [];
+	field_meta = [];
+	curmod = null_module;
+}
 
 let warned_positions = Hashtbl.create 0
 
-let warn_deprecation com s p_usage =
+let warn_deprecation dctx s p_usage =
 	let pkey p = (p.pfile,p.pmin) in
 	if not (Hashtbl.mem warned_positions (pkey p_usage)) then begin
 		Hashtbl.add warned_positions (pkey p_usage) (s,p_usage);
-		if not (is_diagnostics com) then begin
-			let options = Warning.from_meta (!curclass.cl_meta @ !curfield.cf_meta) in
-			com.warning WDeprecated options s p_usage;
+		if not (is_diagnostics dctx.com) then begin
+			let options = Warning.from_meta (dctx.class_meta @ dctx.field_meta) in
+			module_warning dctx.com dctx.curmod WDeprecated options s p_usage;
 		end
 	end
 
-let print_deprecation_message com meta s p_usage =
+let print_deprecation_message dctx meta s p_usage =
 	let s = match meta with
 		| _,[EConst(String(s,_)),_],_ -> s
 		| _ -> Printf.sprintf "Usage of this %s is deprecated" s
 	in
-	warn_deprecation com s p_usage
+	warn_deprecation dctx s p_usage
 
-let check_meta com meta s p_usage =
+let check_meta dctx meta s p_usage =
 	try
-		print_deprecation_message com (Meta.get Meta.Deprecated meta) s p_usage;
+		print_deprecation_message dctx (Meta.get Meta.Deprecated meta) s p_usage;
 	with Not_found ->
 		()
 
 let check_cf com cf p = check_meta com cf.cf_meta "field" p
 
-let check_class com c p = if c != !curclass then check_meta com c.cl_meta "class" p
+let check_class dctx c p = check_meta dctx c.cl_meta "class" p
 
 let check_enum com en p = check_meta com en.e_meta "enum" p
 
@@ -83,56 +94,32 @@ let run_on_expr com e =
 	in
 	expr e
 
-let run_on_field com cf =
+let run_on_field dctx cf =
 	match cf.cf_expr with
-	| None ->
+	| Some e when not (Meta.has Meta.Deprecated cf.cf_meta) ->
+		run_on_expr {dctx with field_meta = cf.cf_meta} e
+	| _ ->
 		()
-	| Some e ->
-		curfield := cf;
-		run_on_expr com e;
-		curfield := null_field
 
 let run com =
+	let dctx = create_context com in
 	List.iter (fun t -> match t with
-		| TClassDecl c ->
-			curclass := c;
-			(match c.cl_constructor with None -> () | Some cf -> run_on_field com cf);
-			(match c.cl_init with None -> () | Some e -> run_on_expr com e);
-			List.iter (run_on_field com) c.cl_ordered_statics;
-			List.iter (run_on_field com) c.cl_ordered_fields;
-			curclass := null_class;
+		| TClassDecl c when not (Meta.has Meta.Deprecated c.cl_meta) ->
+			let dctx = {dctx with class_meta = c.cl_meta; curmod = c.cl_module} in
+			(match c.cl_constructor with None -> () | Some cf -> run_on_field dctx cf);
+			(match c.cl_init with None -> () | Some e -> run_on_expr dctx e);
+			List.iter (run_on_field dctx) c.cl_ordered_statics;
+			List.iter (run_on_field dctx) c.cl_ordered_fields;
 		| _ ->
 			()
 	) com.types
 
-let if_enabled ?(force=false) com fn =
-	if force || not (defined com Define.NoDeprecationWarnings) then fn()
-
-let warn_deprecation ?(force=false) com s p_usage = if_enabled ~force com (fun() -> warn_deprecation com s p_usage)
-
-let print_deprecation_message ?(force=false) com meta s p_usage = if_enabled ~force com (fun() -> print_deprecation_message com meta s p_usage)
-
-let check_meta ?(force=false) com meta s p_usage = if_enabled ~force com (fun() -> check_meta com meta s p_usage)
-
-let check_cf ?(force=false) com cf p = if_enabled ~force com (fun() -> check_cf com cf p)
-
-let check_class ?(force=false) com c p = if_enabled ~force com (fun() -> check_class com c p)
-
-let check_enum ?(force=false) com en p = if_enabled ~force com (fun() -> check_enum com en p)
-
-let check_ef ?(force=false) com ef p = if_enabled ~force com (fun() -> check_ef com ef p)
-
-let check_typedef ?(force=false) com t p = if_enabled ~force com (fun() -> check_typedef com t p)
-
-let check_module_type ?(force=false) com mt p = if_enabled ~force com (fun() -> check_module_type com mt p)
-
-let run_on_expr ?(force=false) com e = if_enabled ~force com (fun() -> run_on_expr com e)
-
-let run_on_field ?(force=false) com cf = if_enabled ~force com (fun() -> run_on_field com cf)
-
-let run ?(force=false) com = if_enabled ~force com (fun() -> run com)
-
-let check_is com name meta p =
-	()
-	(* if name = "is" && not (Meta.has Meta.Deprecated meta) then
-		warn_deprecation com "Using \"is\" as an identifier is deprecated" p *)
+let check_is com m cl_meta cf_meta name meta p =
+	let dctx = {
+		com = com;
+		class_meta = cl_meta;
+		field_meta = cf_meta;
+		curmod = m;
+	} in
+	if is_next dctx.com && name = "is" && not (Meta.has Meta.Deprecated meta) then
+		warn_deprecation dctx "Using \"is\" as an identifier is deprecated" p

+ 29 - 30
src/context/display/diagnostics.ml

@@ -1,15 +1,16 @@
 open Globals
 open Ast
 open Type
-open Typecore
 open Common
-open Display
-open DisplayTypes.DisplayMode
 open DisplayTypes
-open DisplayException
 
-let add_removable_code ctx s p prange =
-	ctx.removable_code <- (s,p,prange) :: ctx.removable_code
+let add_replaceable_code ctx reason replacement display_range replace_range =
+	ctx.replaceable_code <- {
+		reason = reason;
+		replacement = replacement;
+		display_range = display_range;
+		replace_range = replace_range;
+	} :: ctx.replaceable_code
 
 let error_in_diagnostics_run com p =
 	let b = DiagnosticsPrinter.is_diagnostics_file com (com.file_keys#get p.pfile) in
@@ -20,33 +21,34 @@ let find_unused_variables com e =
 	let vars = Hashtbl.create 0 in
 	let pmin_map = Hashtbl.create 0 in
 	let rec loop e = match e.eexpr with
-		| TVar({v_kind = VUser _} as v,eo) when v.v_name <> "_" ->
+		| TVar({v_kind = VUser origin} as v,eo) when v.v_name <> "_" && not (has_var_flag v VUsedByTyper) ->
 			Hashtbl.add pmin_map e.epos.pmin v;
-			let p = match eo with
-				| None -> e.epos
-				| Some e1 ->
-					loop e1;
-					{ e.epos with pmax = e1.epos.pmin }
+			let p,replacement = match eo with
+			| Some e1 when origin <> TVOPatternVariable ->
+				loop e1;
+				{ e.epos with pmax = e1.epos.pmin },""
+			| _ ->
+				e.epos,"_"
 			in
-			Hashtbl.replace vars v.v_id (v,p);
+			Hashtbl.replace vars v.v_id (v,p,replacement);
 		| TLocal ({v_kind = VUser _} as v) ->
 			Hashtbl.remove vars v.v_id;
 		| _ ->
 			Type.iter loop e
 	in
 	loop e;
-	Hashtbl.iter (fun _ (v,p) ->
+	Hashtbl.iter (fun _ (v,p,replacement) ->
 		let p = match (Hashtbl.find_all pmin_map p.pmin) with [_] -> p | _ -> null_pos in
-		add_removable_code com "Unused variable" v.v_pos p
+		add_replaceable_code com "Unused variable" replacement v.v_pos p
 	) vars
 
 let check_other_things com e =
 	let had_effect = ref false in
 	let no_effect p =
-		add_diagnostics_message com (located "This code has no effect" p) DKCompilerMessage Warning;
+		add_diagnostics_message com "This code has no effect" p DKCompilerMessage Warning;
 	in
 	let pointless_compound s p =
-		add_diagnostics_message com (located (Printf.sprintf "This %s has no effect, but some of its sub-expressions do" s) p) DKCompilerMessage Warning;
+		add_diagnostics_message com (Printf.sprintf "This %s has no effect, but some of its sub-expressions do" s) p DKCompilerMessage Warning;
 	in
 	let rec compound s el p =
 		let old = !had_effect in
@@ -93,20 +95,22 @@ let check_other_things com e =
 	in
 	loop true e
 
-let prepare_field dctx com cf = match cf.cf_expr with
+let prepare_field dctx dectx com cf = match cf.cf_expr with
 	| None -> ()
 	| Some e ->
 		find_unused_variables dctx e;
 		check_other_things com e;
-		DeprecationCheck.run_on_expr ~force:true com e
+		DeprecationCheck.run_on_expr {dectx with field_meta = cf.cf_meta} e
 
 let collect_diagnostics dctx com =
 	let open CompilationCache in
+	let dectx = DeprecationCheck.create_context com in
 	List.iter (function
 		| TClassDecl c when DiagnosticsPrinter.is_diagnostics_file com (com.file_keys#get c.cl_pos.pfile) ->
-			List.iter (prepare_field dctx com) c.cl_ordered_fields;
-			List.iter (prepare_field dctx com) c.cl_ordered_statics;
-			(match c.cl_constructor with None -> () | Some cf -> prepare_field dctx com cf);
+			let dectx = {dectx with class_meta = c.cl_meta} in
+			List.iter (prepare_field dctx dectx com) c.cl_ordered_fields;
+			List.iter (prepare_field dctx dectx com) c.cl_ordered_statics;
+			(match c.cl_constructor with None -> () | Some cf -> prepare_field dctx dectx com cf);
 		| _ ->
 			()
 	) com.types;
@@ -136,14 +140,14 @@ let collect_diagnostics dctx com =
 
 let prepare com =
 	let dctx = {
-		removable_code = [];
+		replaceable_code = [];
 		import_positions = PMap.empty;
 		dead_blocks = Hashtbl.create 0;
 		diagnostics_messages = [];
 		unresolved_identifiers = [];
 		missing_fields = PMap.empty;
 	} in
-	if not (List.exists (fun (_,_,_,sev) -> sev = MessageSeverity.Error) com.shared.shared_display_information.diagnostics_messages) then
+	if not (List.exists (fun diag -> diag.diag_severity = MessageSeverity.Error) com.shared.shared_display_information.diagnostics_messages) then
 		collect_diagnostics dctx com;
 	let process_modules com =
 		List.iter (fun m ->
@@ -177,15 +181,10 @@ let prepare com =
 	dctx.unresolved_identifiers <- com.display_information.unresolved_identifiers;
 	dctx
 
-let secure_generated_code ctx e =
-	(* This causes problems and sucks in general... need a different solution. But I forgot which problem this solved anyway. *)
-	(* mk (TMeta((Meta.Extern,[],e.epos),e)) e.etype e.epos *)
-	e
-
 let print com =
 	let dctx = prepare com in
 	Json.string_of_json (DiagnosticsPrinter.json_of_diagnostics com dctx)
 
 let run com =
 	let dctx = prepare com in
-	dctx
+	dctx

+ 82 - 34
src/context/display/diagnosticsPrinter.ml

@@ -2,17 +2,32 @@ open Globals
 open Common
 open Json
 open DisplayTypes
-open DisplayTypes
 open Type
 open Genjson
 open MessageKind
 
-(* type t = DiagnosticsKind.t * pos *)
+type t = {
+	diag_kind : MessageKind.t;
+	diag_pos : pos;
+	diag_severity : MessageSeverity.t;
+	diag_code : string option;
+	diag_args : Json.t;
+	mutable diag_related_information : (pos * int * string) list;
+}
+
+let make_diagnostic kd p sev code args = {
+	diag_kind = kd;
+	diag_pos = p;
+	diag_severity = sev;
+	diag_code = code;
+	diag_args = args;
+	diag_related_information = [];
+}
 
 let is_diagnostics_file com file_key =
 	match com.report_mode with
-	| RMDiagnostics [] -> true
-	| RMDiagnostics file_keys -> List.exists (fun key' -> file_key = key') file_keys
+	| RMLegacyDiagnostics [] | RMDiagnostics [] -> true
+	| RMLegacyDiagnostics file_keys | RMDiagnostics file_keys -> List.mem file_key file_keys
 	| _ -> false
 
 module UnresolvedIdentifierSuggestion = struct
@@ -30,24 +45,26 @@ open CompletionItem
 open CompletionModuleType
 
 let json_of_diagnostics com dctx =
-	let diag = Hashtbl.create 0 in
-	let add append dk p sev args =
+	let diagnostics = Hashtbl.create 0 in
+	let current = ref None in
+	let add append diag =
+		let p = diag.diag_pos in
 		let file = if p = null_pos then p.pfile else Path.get_real_path p.pfile in
-		let diag = try
-			Hashtbl.find diag file
+		let fdiag = try
+			Hashtbl.find diagnostics file
 		with Not_found ->
-			let d = Hashtbl.create 0 in
-			Hashtbl.add diag file d;
+			let d = [] in
+			Hashtbl.add diagnostics file d;
 			d
 		in
-		if append || not (Hashtbl.mem diag p) then
-			Hashtbl.add diag p (dk,p,sev,args)
+		if append || (List.find_opt (fun diag -> diag.diag_pos = p) fdiag) = None then
+			Hashtbl.replace diagnostics file (diag :: fdiag)
 	in
 	let file_keys = new Common.file_keys in
-	let add dk p sev args =
+	let add dk p sev code args =
 		let append = match dk with
 			| DKUnusedImport
-			| DKRemovableCode
+			| DKReplacableCode
 			| DKDeprecationWarning
 			| DKInactiveBlock ->
 				false
@@ -57,7 +74,11 @@ let json_of_diagnostics com dctx =
 			| DKMissingFields ->
 				true
 		in
-		if p = null_pos || is_diagnostics_file com (file_keys#get p.pfile) then add append dk p sev args
+		if p = null_pos || is_diagnostics_file com (file_keys#get p.pfile) then begin
+			let diag = make_diagnostic dk p sev code args in
+			current := Some diag;
+			add append diag
+		end else current := None
 	in
 	List.iter (fun (s,p,suggestions) ->
 		let suggestions = ExtList.List.filter_map (fun (s,item,r) ->
@@ -77,10 +98,24 @@ let json_of_diagnostics com dctx =
 					"name",JString s;
 				])
 		) suggestions in
-		add DKUnresolvedIdentifier p MessageSeverity.Error (JArray suggestions);
+		add DKUnresolvedIdentifier p MessageSeverity.Error None (JArray suggestions);
 	) dctx.unresolved_identifiers;
-	List.iter (fun (s,p,kind,sev) ->
-		add kind p sev (JString s)
+	List.iter (fun d -> match (d.diag_depth, !current) with
+		| depth, Some diag when depth > 0 ->
+			let lines = ExtString.String.nsplit d.diag_message "\n" in
+			(match lines with
+				| [] -> ()
+				| s :: sub ->
+					let related = List.fold_left (fun acc s -> (d.diag_pos,depth,Error.compl_msg s) :: acc) [] (List.rev sub) in
+					diag.diag_related_information <- List.append diag.diag_related_information ((d.diag_pos,depth,s) :: related);
+			)
+		| 0, _ ->
+			add d.diag_kind d.diag_pos d.diag_severity d.diag_code (JString d.diag_message)
+		| _ ->
+			(* Do not add errors with depth greater than one as top level diagnostic. *)
+			(* This could happen when running diagnostics for a file that is wentioned in *)
+			(* sub errors of a file not included for diagnostics. *)
+			()
 	) (List.rev dctx.diagnostics_messages);
 	PMap.iter (fun p (mt,mfl) ->
 		let jctx = create_context GMMinimum in
@@ -143,23 +178,28 @@ let json_of_diagnostics com dctx =
 			"moduleFile",jstring (Path.UniqueKey.lazy_path (t_infos mt).mt_module.m_extra.m_file);
 			"entries",jarray l
 		] in
-		add DKMissingFields p MessageSeverity.Error j
+		add DKMissingFields p MessageSeverity.Error None j
 	) dctx.missing_fields;
 	(* non-append from here *)
 	begin match Warning.get_mode WDeprecated com.warning_options with
 	| WMEnable ->
 		Hashtbl.iter (fun _ (s,p) ->
-			add DKDeprecationWarning p MessageSeverity.Warning (JString s);
+			let wobj = Warning.warning_obj WDeprecated in
+			add DKDeprecationWarning p MessageSeverity.Warning (Some wobj.w_name) (JString s);
 		) DeprecationCheck.warned_positions;
 	| WMDisable ->
 		()
 	end;
 	PMap.iter (fun p r ->
-		if not !r then add DKUnusedImport p MessageSeverity.Warning (JArray [])
+		if not !r then add DKUnusedImport p MessageSeverity.Warning None (JArray [])
 	) dctx.import_positions;
-	List.iter (fun (s,p,prange) ->
-		add DKRemovableCode p MessageSeverity.Warning (JObject ["description",JString s;"range",if prange = null_pos then JNull else Genjson.generate_pos_as_range prange])
-	) dctx.removable_code;
+	List.iter (fun rc ->
+		add DKReplacableCode rc.display_range MessageSeverity.Warning None (JObject [
+			"description",JString rc.reason;
+			"newCode",JString rc.replacement;
+			"range",if rc.replace_range = null_pos then JNull else Genjson.generate_pos_as_range rc.replace_range
+		])
+	) dctx.replaceable_code;
 	Hashtbl.iter (fun file ranges ->
 		List.iter (fun (p,e) ->
 			let jo = JObject [
@@ -167,22 +207,30 @@ let json_of_diagnostics com dctx =
 					"string",JString (Ast.Printer.s_expr e)
 				]
 			] in
-			add DKInactiveBlock p MessageSeverity.Hint jo
+			add DKInactiveBlock p MessageSeverity.Hint None jo
 		) ranges
 	) dctx.dead_blocks;
 	let jl = Hashtbl.fold (fun file diag acc ->
-		let jl = Hashtbl.fold (fun _ (dk,p,sev,jargs) acc ->
+		let jl = List.rev_map (fun diag ->
 			(JObject [
-				"kind",JInt (MessageKind.to_int dk);
-				"severity",JInt (MessageSeverity.to_int sev);
-				"range",Genjson.generate_pos_as_range p;
-				"args",jargs
-			]) :: acc
-		) diag [] in
+				"kind",JInt (MessageKind.to_int diag.diag_kind);
+				"severity",JInt (MessageSeverity.to_int diag.diag_severity);
+				"range",Genjson.generate_pos_as_range diag.diag_pos;
+				"args",diag.diag_args;
+				"code",(match diag.diag_code with None -> JNull | Some c -> JString c);
+				"relatedInformation",JArray (
+					List.map (fun (pos,depth,msg) -> (JObject [
+						"location",Genjson.generate_pos_as_location pos;
+						"depth",JInt depth;
+						"message",JString msg;
+					])) diag.diag_related_information
+				)
+			])
+		) diag in
 		(JObject [
 			"file",if file = "?" then JNull else JString file;
 			"diagnostics",JArray jl
 		]) :: acc
-	) diag [] in
+	) diagnostics [] in
 	let js = JArray jl in
-	js
+	js

+ 5 - 231
src/context/display/display.ml

@@ -2,13 +2,10 @@ open Ast
 open Common
 open DisplayTypes
 open DisplayMode
-open DisplayPosition
 open CompletionItem
-open CompletionResultKind
 open Type
 open Typecore
 open Globals
-open Genjson
 open DisplayPosition
 open ImportStatus
 
@@ -33,233 +30,10 @@ module ReferencePosition = struct
 	let reset () = reference_position := ("",null_pos,SKOther)
 end
 
-module ExprPreprocessing = struct
-	let find_before_pos dm e =
-		let display_pos = ref (DisplayPosition.display_position#get) in
-		let was_annotated = ref false in
-		let is_annotated,is_completion = match dm with
-			| DMDefault -> (fun p -> not !was_annotated && encloses_position !display_pos p),true
-			| DMHover -> (fun p -> not !was_annotated && encloses_position_gt !display_pos p),false
-			| _ -> (fun p -> not !was_annotated && encloses_position !display_pos p),false
-		in
-		let annotate e dk =
-			was_annotated := true;
-			(EDisplay(e,dk),pos e)
-		in
-		let annotate_marked e = annotate e DKMarked in
-		let mk_null p = annotate_marked ((EConst(Ident "null")),p) in
-		let loop_el el =
-			let pr = DisplayPosition.display_position#with_pos (pos e) in
-			let rec loop el = match el with
-				| [] -> [mk_null pr]
-				| e :: el ->
-					if (pos e).pmin >= pr.pmax then (mk_null pr) :: e :: el
-					else e :: loop el
-			in
-			(* print_endline (Printf.sprintf "%i-%i: PR" pr.pmin pr.pmax);
-			List.iter (fun e ->
-				print_endline (Printf.sprintf "%i-%i: %s" (pos e).pmin (pos e).pmax (Ast.s_expr e));
-			) el; *)
-			match el with
-			| [] -> [mk_null pr]
-			| e :: el ->
-				if (pos e).pmin >= pr.pmax then (mk_null pr) :: e :: el
-				else loop (e :: el)
-		in
-		let in_pattern = ref false in
-		let loop e =
-			(* print_endline (Printf.sprintf "%i-%i: %s" (pos e).pmin (pos e).pmax (Ast.s_expr e)); *)
-			match fst e with
-			| EFunction(FKNamed((_,p),_),_) when is_annotated p && is_completion ->
-				raise Exit
-			| EVars vl when is_annotated (pos e) && is_completion ->
-				let rec loop2 acc mark vl = match vl with
-					| v :: vl ->
-						if mark then
-							loop2 (v :: acc) mark vl
-						else if is_annotated (snd v.ev_name) then
-							(* If the name is the display position, mark the expression *)
-							loop2 (v :: acc) true vl
-						else begin match v.ev_expr with
-							| None ->
-								(* If there is no expression, we don't have to do anything.
-								   Should the display position be on the type-hint, it will
-								   be picked up while loading the type. *)
-								loop2 (v :: acc) mark vl
-							| Some e ->
-								(* Determine the area between the `|` in `var x| = | e`. This is not really
-								   correct because we don't want completion on the left side of the `=`, but
-								   we cannot determine that correctly without knowing its position.
-								   Note: We know `e` itself isn't the display position because this entire
-								   algorithm is bottom-up and it would be marked already if it was. *)
-								let p0 = match v.ev_type with
-									| Some (_,pt) -> pt
-									| None -> snd v.ev_name
-								in
-								let p = {p0 with pmax = (pos e).pmin} in
-								let e = if is_annotated p then annotate_marked e else e in
-								loop2 ({ v with ev_expr = Some e } :: acc) mark vl
-						end
-					| [] ->
-						List.rev acc,mark
-				in
-				let vl,mark = loop2 [] false vl in
-				let e = EVars (List.rev vl),pos e in
-				if !was_annotated then e else raise Exit
-			| EBinop((OpAssign | OpAssignOp _) as op,e1,e2) when is_annotated (pos e) && is_completion ->
-				(* Special case for assign ops: If the expression is marked, but none of its operands are,
-				   we are "probably" interested in the rhs. Like with EVars, this isn't accurate because we
-				   could be on the left side of the `=`. I don't think there's a reason for requesting
-				   completion there though. *)
-				(EBinop(op,e1,annotate_marked e2)),(pos e)
-			| EBinop(OpOr,e1,(EIf(_,(EConst(Ident "null"),_),None),p1)) when is_annotated (pos e) && is_completion && !in_pattern ->
-				(* This HAS TO come from an attempted `case pattern | guard:` completion (issue #7068). *)
-				let p = { p1 with pmin = (pos e1).pmax; pmax = p1.pmin } in
-				EBinop(OpOr,e1,mk_null p),(pos e)
-			| EIf(_,(EConst(Ident "null"),_),None) when is_completion && !in_pattern ->
-				(* This is fine. *)
-				mk_null (pos e)
-			| EBlock [] when is_annotated (pos e) ->
-				annotate e DKStructure
-			| EBlock [EDisplay((EConst(Ident s),pn),DKMarked),_] when is_completion ->
-				let e = EObjectDecl [(s,pn,NoQuotes),(EConst (Ident "null"),null_pos)],(pos e) in
-				annotate e DKStructure
-			| EBlock el when is_annotated (pos e) && is_completion ->
-				let el = loop_el el in
-				EBlock el,(pos e)
-			| ECall(e1,el) when is_annotated (pos e) && is_completion ->
-				let el = loop_el el in
-				ECall(e1,el),(pos e)
-			| ENew((tp,pp),el) when is_annotated (pos e) && is_completion ->
-				if is_annotated pp || pp.pmax >= (DisplayPosition.display_position#get).pmax then
-					annotate_marked e
-				else begin
-					let el = loop_el el in
-					ENew((tp,pp),el),(pos e)
-				end
-			| EArrayDecl el when is_annotated (pos e) && is_completion ->
-				let el = loop_el el in
-				EArrayDecl el,(pos e)
-			| EObjectDecl fl when is_annotated (pos e) && is_completion ->
-				annotate e DKStructure
-			| ESwitch(e1,cases,def) when is_annotated (pos e) ->
-				(* We must be "between" two cases, or at the end of the last case.
-				   Let's find the last case which has a position that is < the display
-				   position and mark it. *)
-				let did_mark = ref false in
-				let mark_case ec p =
-					did_mark := true;
-					let ep = mk_null p in
-					match ec with
-					| Some ec ->
-						let ec = match fst ec with
-							| EBlock el -> (EBlock (el @ [ep]),p)
-							| _ -> (EBlock [ec;ep],p)
-						in
-						Some ec
-					| None ->
-						Some (mk_null p)
-				in
-				let rec loop cases = match cases with
-					| [el,eg,ec,p1] ->
-						let ec = match def with
-						| None when (pos e).pmax > !display_pos.pmin -> (* this is so we don't trigger if we're on the } *)
-							mark_case ec p1 (* no default, must be the last case *)
-						| Some (_,p2) when p1.pmax <= !display_pos.pmin && p2.pmin >= !display_pos.pmax ->
-							mark_case ec p1 (* default is beyond display position, mark *)
-						| _ ->
-							ec (* default contains display position, don't mark *)
-						in
-						[el,eg,ec,p1]
-					| (el1,eg1,ec1,p1) :: (el2,eg2,ec2,p2) :: cases ->
-						if p1.pmax <= !display_pos.pmin && p2.pmin >= !display_pos.pmax then
-							(el1,eg1,mark_case ec1 p1,p1) :: (el2,eg2,ec2,p2) :: cases
-						else
-							(el1,eg1,ec1,p1) :: loop ((el2,eg2,ec2,p2) :: cases)
-					| [] ->
-						[]
-				in
-				let cases = loop cases in
-				let def = if !did_mark then
-					def
-				else match def with
-					| Some(eo,p) when (pos e).pmax > !display_pos.pmin -> Some (mark_case eo p,p)
-					| _ -> def
-				in
-				ESwitch(e1,cases,def),pos e
-			| EDisplay _ ->
-				raise Exit
-			| EMeta((Meta.Markup,_,_),(EConst(String _),p)) when is_annotated p ->
-				annotate_marked e
-			| EConst (String (_,q)) when ((q <> SSingleQuotes) || !Parser.was_auto_triggered) && is_annotated (pos e) && is_completion ->
-				(* TODO: check if this makes any sense *)
-				raise Exit
-			| EConst(Regexp _) when is_annotated (pos e) && is_completion ->
-				raise Exit
-			| EVars vl when is_annotated (pos e) ->
-				(* We only want to mark EVars if we're on a var name. *)
-				if List.exists (fun v -> is_annotated (snd v.ev_name)) vl then
-					annotate_marked e
-				else
-					raise Exit
-			| _ ->
-				if is_annotated (pos e) then
-					annotate_marked e
-				else
-					e
-		in
-		let opt f o =
-			match o with None -> None | Some v -> Some (f v)
-		in
-		let rec map e = match fst e with
-			| ESwitch(e1,cases,def) when is_annotated (pos e) ->
-				let e1 = map e1 in
-				let cases = List.map (fun (el,eg,e,p) ->
-					let old = !in_pattern in
-					in_pattern := true;
-					let el = List.map map el in
-					in_pattern := old;
-					let eg = opt map eg in
-					let e = opt map e in
-					el,eg,e,p
-				) cases in
-				let def = opt (fun (eo,p) -> opt map eo,p) def in
-				loop (ESwitch (e1, cases, def),(pos e))
-			| _ ->
-				loop (Ast.map_expr map e)
-		in
-		try map e with Exit -> e
-
-	let find_display_call e =
-		let found = ref false in
-		let handle_el e el =
-			let call_arg_is_marked () =
-				el = [] || List.exists (fun (e,_) -> match e with EDisplay(_,DKMarked) -> true | _ -> false) el
-			in
-			if not !Parser.was_auto_triggered || call_arg_is_marked () then begin
-			found := true;
-			Parser.mk_display_expr e DKCall
-			end else
-				e
-		in
-		let loop e = match fst e with
-			| ECall(_,el) | ENew(_,el) when not !found && display_position#enclosed_in (pos e) ->
-				handle_el e el
-			| EArray(e1,e2) when not !found && display_position#enclosed_in (pos e2) ->
-				handle_el e [e2]
-			| EDisplay(_,DKCall) ->
-				raise Exit
-			| _ -> e
-		in
-		let rec map e = loop (Ast.map_expr map e) in
-		try map e with Exit -> e
-
-
-	let process_expr com e = match com.display.dms_kind with
-		| DMDefinition | DMTypeDefinition | DMUsage _ | DMImplementation | DMHover | DMDefault -> find_before_pos com.display.dms_kind e
-		| DMSignature -> find_display_call e
-		| _ -> e
-end
+let preprocess_expr com e = match com.display.dms_kind with
+	| DMDefinition | DMTypeDefinition | DMUsage _ | DMImplementation | DMHover | DMDefault -> ExprPreprocessing.find_before_pos com.display.dms_kind e
+	| DMSignature -> ExprPreprocessing.find_display_call e
+	| _ -> e
 
 let get_expected_name with_type = match with_type with
 	| WithType.Value (Some src) | WithType.WithType(_,Some src) ->
@@ -290,7 +64,7 @@ let sort_fields l with_type tk =
 	in
 	let l = match with_type with
 		| WithType.WithType(t,_) when (match follow t with TMono _ -> false | _ -> true) ->
-			let rec comp item = match item.ci_type with
+			let comp item = match item.ci_type with
 				| None -> 9
 				| Some (t',_) ->
 				(* For enum constructors, we consider the return type of the constructor function

+ 18 - 15
src/context/display/displayEmitter.ml

@@ -6,7 +6,6 @@ open DisplayException
 open DisplayTypes
 open DisplayMode
 open CompletionItem
-open CompletionType
 open ClassFieldOrigin
 open DisplayTypes.CompletionResultKind
 open Common
@@ -19,6 +18,17 @@ let symbol_of_module_type = function
 	| TTypeDecl td -> SKTypedef td
 	| TAbstractDecl a -> SKAbstract a
 
+let display_alias ctx name t p = match ctx.com.display.dms_kind with
+	| DMDefinition | DMTypeDefinition ->
+		raise_positions [p];
+	| DMUsage _ | DMImplementation ->
+		ReferencePosition.set (name,p,SKOther)
+	| DMHover ->
+		let ct = CompletionType.from_type (get_import_status ctx) t in
+		raise_hover (make_ci_literal name (t,ct)) None p
+	| _ ->
+		()
+
 let display_module_type ctx mt p = match ctx.com.display.dms_kind with
 	| DMDefinition | DMTypeDefinition ->
 		begin match mt with
@@ -56,20 +66,13 @@ let rec display_type ctx t p =
 			| _ ->
 				()
 
-let check_display_type ctx t path =
+let check_display_type ctx t ptp =
 	let add_type_hint () =
-		ctx.g.type_hints <- (ctx.m.curmod.m_extra.m_display,pos path,t) :: ctx.g.type_hints;
+		ctx.g.type_hints <- (ctx.m.curmod.m_extra.m_display,ptp.pos_full,t) :: ctx.g.type_hints;
 	in
 	let maybe_display_type () =
-		if ctx.is_display_file && display_position#enclosed_in (pos path) then
-			let p =
-				match path with
-				| ({ tpackage = pack; tname = name; tsub = sub },p) ->
-					let strings = match sub with None -> name :: pack | Some s -> s :: name :: pack in
-					let length = String.length (String.concat "." strings) in
-					{ p with pmax = p.pmin + length }
-			in
-			display_type ctx t p
+		if ctx.is_display_file && display_position#enclosed_in ptp.pos_full then
+			display_type ctx t ptp.pos_path
 	in
 	add_type_hint();
 	maybe_display_type()
@@ -109,7 +112,7 @@ let display_field ctx origin scope cf p = match ctx.com.display.dms_kind with
 				(* For constructors, we care about the class name so we don't end up looking for "new". *)
 				snd c.cl_path,SKConstructor cf
 			| _,(Self (TClassDecl c) | Parent(TClassDecl c)) ->
-				cf.cf_name,SKField (cf,Some c.cl_path)
+				cf.cf_name,SKField (cf,Some c)
 			| _ ->
 				cf.cf_name,SKField (cf,None)
 		in
@@ -165,7 +168,7 @@ let check_display_metadata ctx meta =
 		if display_position#enclosed_in p then display_meta ctx.com meta p;
 		List.iter (fun e ->
 			if display_position#enclosed_in (pos e) then begin
-				let e = ExprPreprocessing.process_expr ctx.com e in
+				let e = preprocess_expr ctx.com e in
 				delay ctx PTypeField (fun _ -> ignore(type_expr ctx e WithType.value));
 			end
 		) args
@@ -192,4 +195,4 @@ let check_field_modifiers ctx c cf override display_modifier =
 			) missing_fields [] in
 			let l = sort_fields l NoValue TKOverride in
 			raise_fields l CROverride (make_subject (Some cf.cf_name) cf.cf_name_pos)
-		| _ -> ()
+		| _ -> ()

+ 8 - 8
src/context/display/displayException.ml

@@ -23,9 +23,9 @@ let max_completion_items = ref 0
 let filter_somehow ctx items kind subj =
 	let subject = match subj.s_name with
 		| None -> ""
-		| Some name-> String.lowercase name
+		| Some name-> ExtString.String.lowercase name
 	in
-	let subject_length = String.length subject in
+	let subject_length = ExtString.String.length subject in
 	let determine_cost s =
 		let get_initial_cost o =
 			if o = 0 then
@@ -33,7 +33,7 @@ let filter_somehow ctx items kind subj =
 			else begin
 				(* Consider `.` as anchors and determine distance from closest one. Penalize starting distance by factor 2. *)
 				try
-					let last_anchor = String.rindex_from s o '.' in
+					let last_anchor = ExtString.String.rindex_from s o '.' in
 					(o - (last_anchor + 1)) * 2
 				with Not_found ->
 					o * 2
@@ -54,12 +54,12 @@ let filter_somehow ctx items kind subj =
 				let o',new_cost = index_from o subject.[i] in
 				loop (i + 1) o' (cost + new_cost)
 			end else
-				cost + (if o = String.length s - 1 then 0 else 1) (* Slightly penalize for not-exact matches. *)
+				cost + (if o = ExtString.String.length s - 1 then 0 else 1) (* Slightly penalize for not-exact matches. *)
 		in
 		if subject_length = 0 then
 			0
 		else try
-			let o = String.index s subject.[0] in
+			let o = ExtString.String.index s subject.[0] in
 			loop 1 o (get_initial_cost o);
 		with Not_found | Invalid_argument _ ->
 			-1
@@ -67,7 +67,7 @@ let filter_somehow ctx items kind subj =
 	let rec loop acc items index =
 		match items with
 		| item :: items ->
-			let name = String.lowercase (get_filter_name item) in
+			let name = ExtString.String.lowercase (get_filter_name item) in
 			let cost = determine_cost name in
 			let acc = if cost >= 0 then
 				(item,index,cost) :: acc
@@ -102,8 +102,8 @@ let patch_completion_subject subj =
 	match subj.s_name with
 	| Some name ->
 		let delta = p.pmax - p.pmin in
-		let name = if delta > 0 && delta < String.length name then
-			String.sub name 0 delta
+		let name = if delta > 0 && delta < ExtString.String.length name then
+			ExtString.String.sub name 0 delta
 		else
 			name
 		in

+ 30 - 25
src/context/display/displayFields.ml

@@ -56,10 +56,11 @@ let collect_static_extensions ctx items e p =
 		| TFun((_,_,t) :: args, ret) ->
 			begin try
 				let e = TyperBase.unify_static_extension ctx {e with etype = dup e.etype} t p in
-				List.iter2 (fun m tp -> match follow tp.ttp_type with
-					| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
+				List.iter2 (fun m ttp -> match get_constraints ttp with
+					| [] ->
+						()
+					| constr ->
 						List.iter (fun tc -> unify_raise m (map tc) e.epos) constr
-					| _ -> ()
 				) monos f.cf_params;
 				if not (can_access ctx c f true) || follow e.etype == t_dynamic && follow t != t_dynamic then
 					acc
@@ -75,7 +76,7 @@ let collect_static_extensions ctx items e p =
 					let item = make_ci_class_field (CompletionClassField.make f CFSMember origin true) (f.cf_type,ct) in
 					PMap.add f.cf_name item acc
 				end
-			with Error (Unify _,_,_) | Unify_error _ ->
+			with Error { err_message = Unify _ } | Unify_error _ ->
 				acc
 			end
 		| _ ->
@@ -157,9 +158,9 @@ let collect ctx e_ast e dk with_type p =
 				List.fold_left fold_constraints items l
 			in
 			fold_constraints items (Monomorph.classify_down_constraints m)
-		| TInst ({cl_kind = KTypeParameter tl},_) ->
+		| TInst ({cl_kind = KTypeParameter ttp},_) ->
 			(* Type parameters can access the fields of their constraints *)
-			List.fold_left (fun acc t -> loop acc t) items tl
+			List.fold_left (fun acc t -> loop acc t) items (get_constraints ttp)
 		| TInst(c0,tl) ->
 			(* For classes, browse the hierarchy *)
 			let fields = TClass.get_all_fields c0 tl in
@@ -228,21 +229,25 @@ let collect ctx e_ast e dk with_type p =
 		| TAnon an ->
 			(* @:forwardStatics *)
 			let items = match !(an.a_status) with
-				| Statics { cl_kind = KAbstractImpl { a_meta = meta; a_this = TInst (c,_) }} when Meta.has Meta.ForwardStatics meta ->
-					let items = List.fold_left (fun acc cf ->
-						if should_access c cf true && is_new_item acc cf.cf_name then begin
-							let origin = Self(TClassDecl c) in
-							let item = make_class_field origin cf in
-							PMap.add cf.cf_name item acc
-						end else
-							acc
-					) items c.cl_ordered_statics in
-					PMap.foldi (fun name item acc ->
-						if is_new_item acc name then
-							PMap.add name item acc
-						else
-							acc
-					) PMap.empty items
+				| ClassStatics { cl_kind = KAbstractImpl { a_meta = meta; a_this}} when Meta.has Meta.ForwardStatics meta ->
+					begin match follow a_this with
+					| TInst (c,_) ->
+						let items = List.fold_left (fun acc cf ->
+							if should_access c cf true && is_new_item acc cf.cf_name then begin
+								let origin = Self(TClassDecl c) in
+								let item = make_class_field origin cf in
+								PMap.add cf.cf_name item acc
+							end else
+								acc
+						) items c.cl_ordered_statics in
+						PMap.foldi (fun name item acc ->
+							if is_new_item acc name then
+								PMap.add name item acc
+							else
+								acc
+						) PMap.empty items
+					| _ -> items
+					end
 				| _ -> items
 			in
 			(* Anon own fields *)
@@ -257,7 +262,7 @@ let collect ctx e_ast e dk with_type p =
 						PMap.add name (make_field (CompletionClassField.make cf CFSMember origin true) (cf.cf_type,ct)) acc
 					in
 					match !(an.a_status) with
-						| Statics ({cl_kind = KAbstractImpl a} as c) ->
+						| ClassStatics ({cl_kind = KAbstractImpl a} as c) ->
 							if allow_static_abstract_access c cf then
 								let make = if has_class_field_flag cf CfEnum then
 										(make_ci_enum_abstract_field a)
@@ -267,7 +272,7 @@ let collect ctx e_ast e dk with_type p =
 								add (Self (TAbstractDecl a)) make
 							else
 								acc;
-						| Statics c ->
+						| ClassStatics c ->
 							Display.merge_core_doc ctx (TClassDecl c);
 							if should_access c cf true then add (Self (TClassDecl c)) make_ci_class_field else acc;
 						| EnumStatics en ->
@@ -373,7 +378,7 @@ let handle_missing_field_raise ctx tthis i mode with_type pfield =
 		| TAbstract(a,_) -> TAbstractDecl a,CFSMember,true
 		| TAnon an ->
 			begin match !(an.a_status) with
-			| Statics c -> TClassDecl c,CFSStatic,not (can_access ctx c cf true)
+			| ClassStatics c -> TClassDecl c,CFSStatic,not (can_access ctx c cf true)
 			| EnumStatics en -> TEnumDecl en,CFSStatic,true
 			| AbstractStatics a -> TAbstractDecl a,CFSStatic,true
 			| _ -> raise Exit
@@ -409,4 +414,4 @@ let handle_missing_ident ctx i mode with_type p =
 			handle_missing_field_raise ctx ctx.tthis i mode with_type p
 		with Exit ->
 			()
-		end
+		end

+ 125 - 13
src/context/display/displayJson.ml

@@ -1,5 +1,4 @@
 open Globals
-open Json.Reader
 open JsonRpc
 open Jsonrpc_handler
 open Json
@@ -60,18 +59,49 @@ class display_handler (jsonrpc : jsonrpc_handler) com (cs : CompilationCache.t)
 			let file = jsonrpc#get_string_param "file" in
 			Path.get_full_path file
 		) file_input_marker in
-		let pos = if requires_offset then jsonrpc#get_int_param "offset" else (-1) in
-		TypeloadParse.current_stdin := jsonrpc#get_opt_param (fun () ->
+		let contents = jsonrpc#get_opt_param (fun () ->
 			let s = jsonrpc#get_string_param "contents" in
-			Common.define com Define.DisplayStdin; (* TODO: awkward *)
 			Some s
-		) None;
+		) None in
+
+		let pos = if requires_offset then jsonrpc#get_int_param "offset" else (-1) in
 		Parser.was_auto_triggered := was_auto_triggered;
-		DisplayPosition.display_position#set {
-			pfile = file;
-			pmin = pos;
-			pmax = pos;
-		}
+
+		if file <> file_input_marker then begin
+			let file_unique = com.file_keys#get file in
+
+			DisplayPosition.display_position#set {
+				pfile = file;
+				pmin = pos;
+				pmax = pos;
+			};
+
+			com.file_contents <- [file_unique, contents];
+		end else begin
+			let file_contents = jsonrpc#get_opt_param (fun () ->
+				jsonrpc#get_opt_param (fun () -> jsonrpc#get_array_param "fileContents") []
+			) [] in
+
+			let file_contents = List.map (fun fc -> match fc with
+				| JObject fl ->
+					let file = jsonrpc#get_string_field "fileContents" "file" fl in
+					let file = Path.get_full_path file in
+					let file_unique = com.file_keys#get file in
+					let contents = jsonrpc#get_opt_param (fun () ->
+						let s = jsonrpc#get_string_field "fileContents" "contents" fl in
+						Some s
+					) None in
+					(file_unique, contents)
+				| _ -> invalid_arg "fileContents"
+			) file_contents in
+
+			let files = (List.map (fun (k, _) -> k) file_contents) in
+			com.file_contents <- file_contents;
+
+			match files with
+			| [] | [_] -> DisplayPosition.display_position#set { pfile = file; pmin = pos; pmax = pos; };
+			| _ -> DisplayPosition.display_position#set_files files;
+		end
 end
 
 type handler_context = {
@@ -126,6 +156,16 @@ let handler =
 			hctx.display#set_display_file false true;
 			hctx.display#enable_display DMDefinition;
 		);
+		"display/diagnostics", (fun hctx ->
+			hctx.display#set_display_file false false;
+			hctx.display#enable_display DMNone;
+			hctx.com.report_mode <- RMDiagnostics (List.map (fun (f,_) -> f) hctx.com.file_contents);
+
+			(match hctx.com.file_contents with
+			| [file, None] ->
+				hctx.com.display <- { hctx.com.display with dms_display_file_policy = DFPAlso; dms_per_file = true; dms_populate_cache = !ServerConfig.populate_cache_from_display};
+			| _ -> ());
+		);
 		"display/implementation", (fun hctx ->
 			hctx.display#set_display_file false true;
 			hctx.display#enable_display (DMImplementation);
@@ -156,6 +196,71 @@ let handler =
 			hctx.display#set_display_file (hctx.jsonrpc#get_bool_param "wasAutoTriggered") true;
 			hctx.display#enable_display DMSignature
 		);
+		"display/metadata", (fun hctx ->
+			let include_compiler_meta = hctx.jsonrpc#get_bool_param "compiler" in
+			let include_user_meta = hctx.jsonrpc#get_bool_param "user" in
+
+			hctx.com.callbacks#add_after_init_macros (fun () ->
+				let all = Meta.get_meta_list hctx.com.user_metas in
+				let all = List.filter (fun (_, (data:Meta.meta_infos)) ->
+					match data.m_origin with
+					| Compiler when include_compiler_meta -> true
+					| UserDefined _ when include_user_meta -> true
+					| _ -> false
+				) all in
+
+				hctx.send_result (jarray (List.map (fun (t, (data:Meta.meta_infos)) ->
+					let fields = [
+						"name", jstring t;
+						"doc", jstring data.m_doc;
+						"parameters", jarray (List.map jstring data.m_params);
+						"platforms", jarray (List.map (fun p -> jstring (platform_name p)) data.m_platforms);
+						"targets", jarray (List.map (fun u -> jstring (Meta.print_meta_usage u)) data.m_used_on);
+						"internal", jbool data.m_internal;
+						"origin", jstring (match data.m_origin with
+							| Compiler -> "haxe compiler"
+							| UserDefined None -> "user-defined"
+							| UserDefined (Some o) -> o
+						);
+						"links", jarray (List.map jstring data.m_links)
+					] in
+
+					(jobject fields)
+				) all))
+			)
+		);
+		"display/defines", (fun hctx ->
+			let include_compiler_defines = hctx.jsonrpc#get_bool_param "compiler" in
+			let include_user_defines = hctx.jsonrpc#get_bool_param "user" in
+
+			hctx.com.callbacks#add_after_init_macros (fun () ->
+				let all = Define.get_define_list hctx.com.user_defines in
+				let all = List.filter (fun (_, (data:Define.define_infos)) ->
+					match data.d_origin with
+					| Compiler when include_compiler_defines -> true
+					| UserDefined _ when include_user_defines -> true
+					| _ -> false
+				) all in
+
+				hctx.send_result (jarray (List.map (fun (t, (data:Define.define_infos)) ->
+					let fields = [
+						"name", jstring t;
+						"doc", jstring data.d_doc;
+						"parameters", jarray (List.map jstring data.d_params);
+						"platforms", jarray (List.map (fun p -> jstring (platform_name p)) data.d_platforms);
+						"origin", jstring (match data.d_origin with
+							| Compiler -> "haxe compiler"
+							| UserDefined None -> "user-defined"
+							| UserDefined (Some o) -> o
+						);
+						"deprecated", jopt jstring data.d_deprecated;
+						"links", jarray (List.map jstring data.d_links)
+					] in
+
+					(jobject fields)
+				) all))
+			)
+		);
 		"server/readClassPaths", (fun hctx ->
 			hctx.com.callbacks#add_after_init_macros (fun () ->
 				let cc = hctx.display#get_cs#get_context (Define.get_signature hctx.com.defines) in
@@ -183,13 +288,14 @@ let handler =
 		"server/module", (fun hctx ->
 			let sign = Digest.from_hex (hctx.jsonrpc#get_string_param "signature") in
 			let path = Path.parse_path (hctx.jsonrpc#get_string_param "path") in
-			let cc = hctx.display#get_cs#get_context sign in
+			let cs = hctx.display#get_cs in
+			let cc = cs#get_context sign in
 			let m = try
 				cc#find_module path
 			with Not_found ->
 				hctx.send_error [jstring "No such module"]
 			in
-			hctx.send_result (generate_module cc m)
+			hctx.send_result (generate_module cs cc m)
 		);
 		"server/type", (fun hctx ->
 			let sign = Digest.from_hex (hctx.jsonrpc#get_string_param "signature") in
@@ -272,7 +378,7 @@ let handler =
 			let file = hctx.jsonrpc#get_string_param "file" in
 			let fkey = hctx.com.file_keys#get file in
 			let cs = hctx.display#get_cs in
-			cs#taint_modules fkey "server/invalidate";
+			cs#taint_modules fkey ServerInvalidate;
 			cs#remove_files fkey;
 			hctx.send_result jnull
 		);
@@ -297,6 +403,12 @@ let handler =
 				l := jstring ("Legacy completion " ^ (if b then "enabled" else "disabled")) :: !l;
 				()
 			) ();
+			hctx.jsonrpc#get_opt_param (fun () ->
+				let b = hctx.jsonrpc#get_bool_param "populateCacheFromDisplay" in
+				ServerConfig.populate_cache_from_display := b;
+				l := jstring ("Compilation cache refill from display " ^ (if b then "enabled" else "disabled")) :: !l;
+				()
+			) ();
 			hctx.send_result (jarray !l)
 		);
 		"server/memory",(fun hctx ->

+ 7 - 10
src/context/display/displayTexpr.ml

@@ -4,9 +4,7 @@ open Ast
 open Type
 open Typecore
 open DisplayPosition
-open CompletionItem
 open CompilationCache
-open ClassFieldOrigin
 
 let find_field_by_position sc p =
 	List.find (fun cff ->
@@ -59,14 +57,13 @@ let find_abstract_by_position decls p =
 	loop decls
 
 let actually_check_display_field ctx c cff p =
-	let context_init = new TypeloadFields.context_init in
-	let cctx = TypeloadFields.create_class_context c context_init p in
+	let cctx = TypeloadFields.create_class_context c p in
 	let ctx = TypeloadFields.create_typer_context_for_class ctx cctx p in
 	let cff = TypeloadFields.transform_field (ctx,cctx) c cff (ref []) (pos cff.cff_name) in
 	let display_modifier = Typeload.check_field_access ctx cff in
-	let fctx = TypeloadFields.create_field_context cctx cff true display_modifier in
+	let fctx = TypeloadFields.create_field_context ctx cctx cff true display_modifier in
 	let cf = TypeloadFields.init_field (ctx,cctx,fctx) cff in
-	flush_pass ctx PTypeField "check_display_field";
+	flush_pass ctx PTypeField ("check_display_field",(fst c.cl_path @ [snd c.cl_path;fst cff.cff_name]));
 	ignore(follow cf.cf_type)
 
 let check_display_field ctx sc c cf =
@@ -92,8 +89,8 @@ let check_display_class ctx decls c =
 		let sc = find_class_by_position decls c.cl_name_pos in
 		ignore(Typeload.type_type_params ctx TPHType c.cl_path (fun() -> c.cl_params) null_pos sc.d_params);
 		List.iter (function
-			| (HExtends(ct,p) | HImplements(ct,p)) when display_position#enclosed_in p ->
-				ignore(Typeload.load_instance ~allow_display:true ctx (ct,p) false)
+			| (HExtends ptp | HImplements ptp) when display_position#enclosed_in ptp.pos_full ->
+				ignore(Typeload.load_instance ~allow_display:true ctx ptp ParamNormal)
 			| _ ->
 				()
 		) sc.d_flags;
@@ -181,7 +178,7 @@ let check_display_file ctx cs =
 			let fkey = DisplayPosition.display_position#get_file_key in
 			(* force parsing again : if the completion point have been changed *)
 			cs#remove_files fkey;
-			cs#taint_modules fkey "check_display_file";
+			cs#taint_modules fkey CheckDisplayFile;
 		end
 	| None ->
-		()
+		()

+ 6 - 9
src/context/display/displayToplevel.ml

@@ -24,7 +24,6 @@ open Typecore
 open CompletionItem
 open ClassFieldOrigin
 open DisplayTypes
-open Genjson
 open Globals
 
 (* Merges argument and return types from macro and non-macro context, preferring the one that isn't Dynamic.
@@ -188,7 +187,7 @@ module CollectionContext = struct
 			Shadowed
 		with Not_found ->
 			let check_wildcard () =
-				List.exists (fun (sl,_) -> (sl,snd path) = path) ctx.ctx.m.wildcard_packages
+				List.exists (fun (sl,_) -> (sl,snd path) = path) ctx.ctx.m.import_resolution#extract_wildcard_packages
 			in
 			if is_import || (fst path = []) || check_wildcard () then Imported else Unimported
 
@@ -378,7 +377,7 @@ let collect ctx tk with_type sort =
 				()
 		in
 		List.iter enum_ctors ctx.m.curmod.m_types;
-		List.iter enum_ctors (List.map fst ctx.m.module_imports);
+		List.iter enum_ctors (List.map fst ctx.m.import_resolution#extract_type_imports);
 
 		(* enum constructors of expected type *)
 		begin match with_type with
@@ -415,7 +414,7 @@ let collect ctx tk with_type sort =
 					| _ -> raise Not_found
 			with Not_found ->
 				()
-		) ctx.m.module_globals;
+		) ctx.m.import_resolution#extract_field_imports;
 
 		(* literals *)
 		add (make_ci_literal "null" (tpair t_dynamic)) (Some "null");
@@ -450,17 +449,15 @@ let collect ctx tk with_type sort =
 	end;
 
 	(* type params *)
-	List.iter (fun tp -> match follow tp.ttp_type with
-		| TInst(c,_) ->
-			add (make_ci_type_param c (tpair tp.ttp_type)) (Some (snd c.cl_path))
-		| _ -> die "" __LOC__
+	List.iter (fun tp ->
+		add (make_ci_type_param tp.ttp_class (tpair tp.ttp_type)) (Some (snd tp.ttp_class.cl_path))
 	) ctx.type_params;
 
 	(* module types *)
 	List.iter add_type ctx.m.curmod.m_types;
 
 	(* module imports *)
-	List.iter add_type (List.rev_map fst ctx.m.module_imports); (* reverse! *)
+	List.iter add_type (List.rev_map fst ctx.m.import_resolution#extract_type_imports); (* reverse! *)
 
 	(* types from files *)
 	let cs = ctx.com.cs in

部分文件因为文件数量过多而无法显示