@greenpandastudios/aug-cli 0.19.0 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/bin/aug.mjs +12 -2
- package/docs/about.md +27 -0
- package/docs/api/crypto.md +103 -69
- package/docs/api/io.md +35 -33
- package/docs/api/json.md +3 -3
- package/docs/api/memory.md +23 -19
- package/docs/api/time.md +10 -9
- package/docs/api/web.md +33 -38
- package/docs/compatibility.md +3 -3
- package/docs/contributing-benchmarks.md +38 -0
- package/docs/dev-containers.md +95 -0
- package/docs/diagnostics.md +15 -5
- package/docs/docker.md +174 -12
- package/docs/editor.md +35 -0
- package/docs/example-projects.json +206 -24
- package/docs/examples/approved-design/counters.md +34 -126
- package/docs/examples/approved-design/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/approved-design/domain/app.md +13 -77
- package/docs/examples/approved-design/domain/export.md +5 -19
- package/docs/examples/approved-design/domain/models.md +4 -23
- package/docs/examples/approved-design/domain/numbers.md +24 -114
- package/docs/examples/approved-design/index.md +16 -7
- package/docs/examples/approved-design/main.md +19 -96
- package/docs/examples/benchmark/index.md +6 -5
- package/docs/examples/benchmark/main.md +7 -35
- package/docs/examples/cli-args/index.md +6 -5
- package/docs/examples/cli-args/main.md +6 -31
- package/docs/examples/collections/index.md +6 -5
- package/docs/examples/collections/main.md +7 -35
- package/docs/examples/collections-benchmark/index.md +6 -5
- package/docs/examples/collections-benchmark/main.md +7 -35
- package/docs/examples/cpu-benchmark/index.md +6 -5
- package/docs/examples/cpu-benchmark/main.md +5 -24
- package/docs/examples/developer-workflow/calculator.md +39 -186
- package/docs/examples/developer-workflow/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/developer-workflow/index.md +16 -7
- package/docs/examples/developer-workflow/logging/console.md +10 -56
- package/docs/examples/developer-workflow/logging/export.md +4 -14
- package/docs/examples/developer-workflow/logging/logger.md +7 -43
- package/docs/examples/developer-workflow/main.md +17 -69
- package/docs/examples/drop/index.md +6 -5
- package/docs/examples/drop/main.md +7 -27
- package/docs/examples/drop/resource.md +7 -30
- package/docs/examples/errors/errors.md +7 -27
- package/docs/examples/errors/index.md +6 -5
- package/docs/examples/errors/main.md +7 -28
- package/docs/examples/ffi/index.md +6 -5
- package/docs/examples/ffi/main.md +6 -20
- package/docs/examples/ffi/native.md +8 -34
- package/docs/examples/generic-di/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/generic-di/index.md +6 -5
- package/docs/examples/generic-di/main.md +9 -39
- package/docs/examples/generic-di/types.md +23 -92
- package/docs/examples/generics/index.md +6 -5
- package/docs/examples/generics/main.md +10 -47
- package/docs/examples/generics/types.md +25 -100
- package/docs/examples/hello/app/export.md +4 -12
- package/docs/examples/hello/app/greeter.md +13 -91
- package/docs/examples/hello/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/hello/index.md +17 -6
- package/docs/examples/hello/logging/console.md +10 -54
- package/docs/examples/hello/logging/export.md +4 -14
- package/docs/examples/hello/logging/logger.md +7 -45
- package/docs/examples/hello/main.md +9 -39
- package/docs/examples/http-benchmark/index.md +6 -5
- package/docs/examples/http-benchmark/main.md +6 -20
- package/docs/examples/http-benchmark/routes.md +9 -31
- package/docs/examples/index.md +46 -29
- package/docs/examples/interceptors/app.md +20 -139
- package/docs/examples/interceptors/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/interceptors/index.md +6 -5
- package/docs/examples/interceptors/interceptors.md +24 -148
- package/docs/examples/interceptors/logging.md +13 -76
- package/docs/examples/interceptors/main.md +10 -65
- package/docs/examples/json-benchmark/data.md +4 -20
- package/docs/examples/json-benchmark/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
- package/docs/examples/json-benchmark/index.md +7 -5
- package/docs/examples/json-benchmark/main-yaml.md +20 -0
- package/docs/examples/json-benchmark/main.md +10 -49
- package/docs/examples/new-syntax/console.md +10 -52
- package/docs/examples/new-syntax/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/new-syntax/greeter.md +13 -71
- package/docs/examples/new-syntax/index.md +6 -5
- package/docs/examples/new-syntax/logger.md +7 -43
- package/docs/examples/new-syntax/main.md +10 -53
- package/docs/examples/new-syntax/math.md +6 -24
- package/docs/examples/oidc-login/client/contracts.md +10 -61
- package/docs/examples/oidc-login/client/endpoints.md +32 -154
- package/docs/examples/oidc-login/client/export.md +5 -23
- package/docs/examples/oidc-login/client/login.md +234 -344
- package/docs/examples/oidc-login/client/logout.md +38 -143
- package/docs/examples/oidc-login/client/protocol.md +183 -304
- package/docs/examples/oidc-login/client/session.md +41 -149
- package/docs/examples/oidc-login/client/views.md +13 -58
- package/docs/examples/oidc-login/common/export.md +6 -26
- package/docs/examples/oidc-login/common/headers.md +42 -72
- package/docs/examples/oidc-login/common/keys.md +40 -164
- package/docs/examples/oidc-login/common/settings.md +24 -40
- package/docs/examples/oidc-login/common/views.md +7 -28
- package/docs/examples/oidc-login/dependencies/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.md +205 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +267 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.md +415 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.md +271 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +89 -0
- package/docs/examples/oidc-login/index.md +8 -7
- package/docs/examples/oidc-login/main-yaml.md +7 -0
- package/docs/examples/oidc-login/main.md +26 -153
- package/docs/examples/oidc-login/provider/authorization.md +232 -275
- package/docs/examples/oidc-login/provider/contracts.md +24 -146
- package/docs/examples/oidc-login/provider/credentials.md +24 -57
- package/docs/examples/oidc-login/provider/discovery.md +48 -122
- package/docs/examples/oidc-login/provider/export.md +11 -37
- package/docs/examples/oidc-login/provider/token.md +159 -237
- package/docs/examples/oidc-login/provider/userinfo.md +47 -102
- package/docs/examples/oidc-login/provider/views.md +13 -53
- package/docs/examples/ownership/counter.md +17 -63
- package/docs/examples/ownership/index.md +6 -5
- package/docs/examples/ownership/main.md +7 -30
- package/docs/examples/ownership-transfer/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/ownership-transfer/index.md +6 -5
- package/docs/examples/ownership-transfer/main.md +10 -52
- package/docs/examples/ownership-transfer/resource.md +15 -67
- package/docs/examples/packages-app/dependencies/packages/@example/aug-math/0.1.0/arithmetic.md +12 -50
- package/docs/examples/packages-app/index.md +7 -6
- package/docs/examples/packages-app/main.md +7 -25
- package/docs/examples/packages-math/aug-package-json.md +1 -1
- package/docs/examples/packages-math/index.md +7 -6
- package/docs/examples/packages-math/src/arithmetic.md +12 -50
- package/docs/examples/packages-math/src/export.md +4 -12
- package/docs/examples/startup-benchmark/index.md +6 -5
- package/docs/examples/startup-benchmark/main.md +5 -17
- package/docs/examples/visibility/counter.md +19 -67
- package/docs/examples/visibility/index.md +6 -5
- package/docs/examples/visibility/main.md +7 -31
- package/docs/examples/weather-api/forecasts.md +168 -0
- package/docs/examples/weather-api/index.md +42 -0
- package/docs/examples/weather-api/main-yaml.md +21 -0
- package/docs/examples/weather-api/main.md +65 -0
- package/docs/examples.json +10 -0
- package/docs/getting-started.md +105 -2
- package/docs/grammar.md +6 -4
- package/docs/guides/change-a-module.md +64 -0
- package/docs/guides/index.md +27 -0
- package/docs/index.md +51 -29
- package/docs/language-conformance.md +1 -1
- package/docs/language-constructs.md +22 -22
- package/docs/language-design-audit.md +1 -1
- package/docs/learn/data-and-errors.md +77 -0
- package/docs/learn/index.md +30 -0
- package/docs/learn/modules-and-dependencies.md +73 -0
- package/docs/learn/state-and-tests.md +71 -0
- package/docs/learn/values-and-functions.md +62 -0
- package/docs/lesson-failures.json +8 -0
- package/docs/maintaining-docs.md +16 -4
- package/docs/packages.md +72 -126
- package/docs/performance.md +13 -41
- package/docs/production-readiness.md +5 -4
- package/docs/public/downloads/approved-design.zip +0 -0
- package/docs/public/downloads/benchmark.zip +0 -0
- package/docs/public/downloads/cli-args.zip +0 -0
- package/docs/public/downloads/collections-benchmark.zip +0 -0
- package/docs/public/downloads/collections.zip +0 -0
- package/docs/public/downloads/cpu-benchmark.zip +0 -0
- package/docs/public/downloads/developer-workflow.zip +0 -0
- package/docs/public/downloads/drop.zip +0 -0
- package/docs/public/downloads/errors.zip +0 -0
- package/docs/public/downloads/ffi.zip +0 -0
- package/docs/public/downloads/generic-di.zip +0 -0
- package/docs/public/downloads/generics.zip +0 -0
- package/docs/public/downloads/hello.zip +0 -0
- package/docs/public/downloads/http-benchmark.zip +0 -0
- package/docs/public/downloads/interceptors.zip +0 -0
- package/docs/public/downloads/json-benchmark.zip +0 -0
- package/docs/public/downloads/new-syntax.zip +0 -0
- package/docs/public/downloads/oidc-login.zip +0 -0
- package/docs/public/downloads/ownership-transfer.zip +0 -0
- package/docs/public/downloads/ownership.zip +0 -0
- package/docs/public/downloads/packages-app.zip +0 -0
- package/docs/public/downloads/packages-math.zip +0 -0
- package/docs/public/downloads/startup-benchmark.zip +0 -0
- package/docs/public/downloads/visibility.zip +0 -0
- package/docs/public/downloads/weather-api.zip +0 -0
- package/docs/reference.md +23 -17
- package/docs/releasing.md +29 -15
- package/docs/research/code-to-natural-language.md +108 -0
- package/docs/research/ecosystem-workflow.md +41 -0
- package/docs/research/wiki-editorial-design.md +71 -0
- package/docs/roadmap.md +1 -1
- package/docs/specifications.md +27 -11
- package/docs/testing.md +19 -5
- package/docs/tooling.md +25 -12
- package/docs/weather-api.md +65 -0
- package/docs/web.md +50 -18
- package/docs/writing-docs.md +49 -0
- package/examples/{hello/.aug-spec/august/0.19.0 → approved-design/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/approved-design/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/approved-design/.aug-spec/manifest.json +3 -3
- package/examples/approved-design/counters.aug +5 -4
- package/examples/approved-design/counters.aug.md +25 -132
- package/examples/approved-design/domain/app.aug +2 -1
- package/examples/approved-design/domain/app.aug.md +10 -80
- package/examples/approved-design/domain/export.aug +1 -0
- package/examples/approved-design/domain/export.aug.md +4 -20
- package/examples/approved-design/domain/models.aug +1 -0
- package/examples/approved-design/domain/models.aug.md +3 -25
- package/examples/approved-design/domain/numbers.aug +3 -2
- package/examples/approved-design/domain/numbers.aug.md +19 -116
- package/examples/approved-design/main.aug +1 -0
- package/examples/approved-design/main.aug.md +12 -95
- package/examples/benchmark/.aug-spec/manifest.json +1 -1
- package/examples/benchmark/main.aug +1 -0
- package/examples/benchmark/main.aug.md +6 -36
- package/examples/cli-args/.aug-spec/manifest.json +1 -1
- package/examples/cli-args/main.aug +1 -0
- package/examples/cli-args/main.aug.md +5 -32
- package/examples/collections/.aug-spec/manifest.json +1 -1
- package/examples/collections/main.aug +1 -0
- package/examples/collections/main.aug.md +6 -36
- package/examples/{generic-di/.aug-spec/august/0.19.0 → developer-workflow/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/developer-workflow/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/developer-workflow/.aug-spec/manifest.json +3 -3
- package/examples/developer-workflow/calculator.aug +3 -2
- package/examples/developer-workflow/calculator.aug.md +28 -189
- package/examples/developer-workflow/logging/console.aug +2 -1
- package/examples/developer-workflow/logging/console.aug.md +7 -57
- package/examples/developer-workflow/logging/export.aug +1 -0
- package/examples/developer-workflow/logging/export.aug.md +3 -15
- package/examples/developer-workflow/logging/logger.aug +1 -0
- package/examples/developer-workflow/logging/logger.aug.md +6 -46
- package/examples/developer-workflow/main.aug +1 -0
- package/examples/developer-workflow/main.aug.md +10 -68
- package/examples/drop/.aug-spec/manifest.json +1 -1
- package/examples/drop/main.aug +1 -0
- package/examples/drop/main.aug.md +6 -28
- package/examples/drop/resource.aug +1 -0
- package/examples/drop/resource.aug.md +6 -34
- package/examples/errors/.aug-spec/manifest.json +1 -1
- package/examples/errors/errors.aug +2 -1
- package/examples/errors/errors.aug.md +4 -27
- package/examples/errors/main.aug +1 -0
- package/examples/errors/main.aug.md +6 -29
- package/examples/ffi/.aug-spec/manifest.json +1 -1
- package/examples/ffi/main.aug +1 -0
- package/examples/ffi/main.aug.md +5 -21
- package/examples/ffi/native.aug +2 -1
- package/examples/ffi/native.aug.md +5 -35
- package/examples/{approved-design/.aug-spec/august/0.19.0 → generic-di/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/generic-di/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/generic-di/.aug-spec/manifest.json +3 -3
- package/examples/generic-di/main.aug +1 -0
- package/examples/generic-di/main.aug.md +8 -40
- package/examples/generic-di/types.aug +3 -2
- package/examples/generic-di/types.aug.md +18 -97
- package/examples/generics/.aug-spec/manifest.json +1 -1
- package/examples/generics/main.aug +1 -0
- package/examples/generics/main.aug.md +9 -48
- package/examples/generics/types.aug +4 -3
- package/examples/generics/types.aug.md +18 -104
- package/examples/{developer-workflow/.aug-spec/august/0.19.0 → hello/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/hello/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/hello/.aug-spec/manifest.json +3 -3
- package/examples/hello/app/export.aug +1 -0
- package/examples/hello/app/export.aug.md +3 -13
- package/examples/hello/app/greeter.aug +2 -1
- package/examples/hello/app/greeter.aug.md +10 -94
- package/examples/hello/logging/console.aug +2 -1
- package/examples/hello/logging/console.aug.md +7 -55
- package/examples/hello/logging/export.aug +1 -0
- package/examples/hello/logging/export.aug.md +3 -15
- package/examples/hello/logging/logger.aug +1 -0
- package/examples/hello/logging/logger.aug.md +6 -48
- package/examples/hello/main.aug +1 -0
- package/examples/hello/main.aug.md +8 -40
- package/examples/interceptors/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
- package/examples/interceptors/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/interceptors/.aug-spec/manifest.json +3 -3
- package/examples/interceptors/app.aug +3 -2
- package/examples/interceptors/app.aug.md +15 -141
- package/examples/interceptors/interceptors.aug +3 -2
- package/examples/interceptors/interceptors.aug.md +19 -152
- package/examples/interceptors/logging.aug +2 -1
- package/examples/interceptors/logging.aug.md +10 -79
- package/examples/interceptors/main.aug +1 -0
- package/examples/interceptors/main.aug.md +9 -66
- package/examples/new-syntax/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
- package/examples/new-syntax/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/new-syntax/.aug-spec/manifest.json +3 -3
- package/examples/new-syntax/console.aug +2 -1
- package/examples/new-syntax/console.aug.md +7 -53
- package/examples/new-syntax/greeter.aug +2 -1
- package/examples/new-syntax/greeter.aug.md +10 -74
- package/examples/new-syntax/logger.aug +1 -0
- package/examples/new-syntax/logger.aug.md +6 -46
- package/examples/new-syntax/main.aug +1 -0
- package/examples/new-syntax/main.aug.md +9 -54
- package/examples/new-syntax/math.aug +2 -1
- package/examples/new-syntax/math.aug.md +3 -24
- package/examples/oidc-login/.aug-spec/manifest.json +13 -13
- package/examples/oidc-login/.aug-spec/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md +71 -0
- package/examples/oidc-login/.aug-spec/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +17 -0
- package/examples/oidc-login/.aug-spec/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +125 -0
- package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/contracts.aug +12 -11
- package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md +244 -0
- package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/jose.aug +6 -5
- package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md +71 -0
- package/examples/oidc-login/.aug-spec/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +30 -0
- package/examples/oidc-login/aug.lock.json +100 -0
- package/examples/oidc-login/client/contracts.aug +1 -0
- package/examples/oidc-login/client/contracts.aug.md +9 -66
- package/examples/oidc-login/client/endpoints.aug +6 -5
- package/examples/oidc-login/client/endpoints.aug.md +13 -145
- package/examples/oidc-login/client/export.aug +1 -0
- package/examples/oidc-login/client/export.aug.md +4 -24
- package/examples/oidc-login/client/login.aug +7 -6
- package/examples/oidc-login/client/login.aug.md +25 -303
- package/examples/oidc-login/client/logout.aug +5 -4
- package/examples/oidc-login/client/logout.aug.md +13 -135
- package/examples/oidc-login/client/protocol.aug +7 -6
- package/examples/oidc-login/client/protocol.aug.md +36 -283
- package/examples/oidc-login/client/session.aug +5 -4
- package/examples/oidc-login/client/session.aug.md +12 -139
- package/examples/oidc-login/client/views.aug +3 -2
- package/examples/oidc-login/client/views.aug.md +8 -57
- package/examples/oidc-login/common/export.aug +1 -0
- package/examples/oidc-login/common/export.aug.md +5 -27
- package/examples/oidc-login/common/headers.aug +4 -3
- package/examples/oidc-login/common/headers.aug.md +9 -67
- package/examples/oidc-login/common/keys.aug +6 -5
- package/examples/oidc-login/common/keys.aug.md +29 -165
- package/examples/oidc-login/common/settings.aug +2 -1
- package/examples/oidc-login/common/settings.aug.md +5 -39
- package/examples/oidc-login/common/views.aug +2 -1
- package/examples/oidc-login/common/views.aug.md +4 -28
- package/examples/oidc-login/main.aug +6 -16
- package/examples/oidc-login/main.aug.md +17 -146
- package/examples/oidc-login/main.yaml +7 -0
- package/examples/oidc-login/provider/authorization.aug +7 -6
- package/examples/oidc-login/provider/authorization.aug.md +23 -238
- package/examples/oidc-login/provider/contracts.aug +1 -0
- package/examples/oidc-login/provider/contracts.aug.md +23 -158
- package/examples/oidc-login/provider/credentials.aug +3 -2
- package/examples/oidc-login/provider/credentials.aug.md +9 -53
- package/examples/oidc-login/provider/discovery.aug +4 -3
- package/examples/oidc-login/provider/discovery.aug.md +11 -118
- package/examples/oidc-login/provider/export.aug +1 -0
- package/examples/oidc-login/provider/export.aug.md +6 -34
- package/examples/oidc-login/provider/token.aug +6 -5
- package/examples/oidc-login/provider/token.aug.md +16 -204
- package/examples/oidc-login/provider/userinfo.aug +4 -3
- package/examples/oidc-login/provider/userinfo.aug.md +10 -92
- package/examples/oidc-login/provider/views.aug +3 -2
- package/examples/oidc-login/provider/views.aug.md +8 -52
- package/examples/ownership/.aug-spec/manifest.json +1 -1
- package/examples/ownership/counter.aug +3 -2
- package/examples/ownership/counter.aug.md +12 -66
- package/examples/ownership/main.aug +1 -0
- package/examples/ownership/main.aug.md +6 -31
- package/examples/ownership-transfer/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
- package/examples/ownership-transfer/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/ownership-transfer/.aug-spec/manifest.json +3 -3
- package/examples/ownership-transfer/main.aug +1 -0
- package/examples/ownership-transfer/main.aug.md +9 -53
- package/examples/ownership-transfer/resource.aug +2 -1
- package/examples/ownership-transfer/resource.aug.md +12 -71
- package/examples/packages/app/.aug-spec/manifest.json +1 -1
- package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug +2 -1
- package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug.md +9 -51
- package/examples/packages/app/main.aug +1 -0
- package/examples/packages/app/main.aug.md +6 -26
- package/examples/packages/math/.aug-spec/manifest.json +1 -1
- package/examples/packages/math/aug-package.json +1 -1
- package/examples/packages/math/src/arithmetic.aug +2 -1
- package/examples/packages/math/src/arithmetic.aug.md +9 -51
- package/examples/packages/math/src/export.aug +1 -0
- package/examples/packages/math/src/export.aug.md +3 -13
- package/examples/visibility/.aug-spec/manifest.json +1 -1
- package/examples/visibility/counter.aug +4 -3
- package/examples/visibility/counter.aug.md +12 -68
- package/examples/visibility/main.aug +1 -0
- package/examples/visibility/main.aug.md +6 -32
- package/examples/weather-api/.aug-spec/manifest.json +8 -0
- package/examples/weather-api/AGENTS.md +17 -0
- package/examples/weather-api/README.md +19 -0
- package/examples/weather-api/forecasts.aug +47 -0
- package/examples/weather-api/forecasts.aug.md +32 -0
- package/examples/weather-api/main.aug +4 -0
- package/examples/weather-api/main.aug.md +15 -0
- package/examples/weather-api/main.yaml +5 -0
- package/examples/weather-api/weather.http +5 -0
- package/package.json +3 -4
- package/scripts/bootstrap-native.mjs +181 -106
- package/scripts/native-setup.mjs +98 -0
- package/scripts/native-toolchain.mjs +28 -0
- package/src/builtins.js +1 -1
- package/src/checker.js +259 -72
- package/src/cli.js +114 -20
- package/src/codegen.js +1 -1
- package/src/config.js +1 -1
- package/src/contracts.js +10 -0
- package/src/editor.js +71 -16
- package/src/fixes.js +90 -2
- package/src/formatter.js +19 -8
- package/src/git-packages.js +110 -0
- package/src/help.js +24 -23
- package/src/http-contracts.js +14 -0
- package/src/http-policies.js +5 -5
- package/src/libraries.js +1 -1
- package/src/lsp.js +14 -5
- package/src/native.js +19 -13
- package/src/navigation.js +4 -2
- package/src/openapi.js +5 -4
- package/src/package-locking.js +45 -0
- package/src/package-manager.js +251 -67
- package/src/parser.js +13 -5
- package/src/policies.js +3 -3
- package/src/project-init.js +78 -4
- package/src/project.js +9 -7
- package/src/semantic.js +46 -2
- package/src/snippets.js +59 -0
- package/src/spec-hints.js +56 -0
- package/src/spec-tree.js +241 -0
- package/src/spec.js +626 -303
- package/docs/examples/approved-design/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/developer-workflow/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/generic-di/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/hello/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/interceptors/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/json-benchmark/dependencies/august/0.19.0/json/contracts.md +0 -103
- package/docs/examples/new-syntax/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/contracts.md +0 -925
- package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/jose.md +0 -434
- package/docs/examples/oidc-login/dependencies/august/0.19.0/json/contracts.md +0 -103
- package/docs/examples/oidc-login/dependencies/august/0.19.0/memory/store.md +0 -374
- package/docs/examples/oidc-login/dependencies/august/0.19.0/time/contracts.md +0 -150
- package/docs/examples/oidc-login/dependencies/august/0.19.0/web/contracts.md +0 -532
- package/docs/examples/ownership-transfer/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/examples/approved-design/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/developer-workflow/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/generic-di/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/hello/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
- package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
- package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/contracts.aug.md +0 -791
- package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/jose.aug.md +0 -266
- package/examples/oidc-login/.aug-spec/august/0.19.0/json/contracts.aug.md +0 -55
- package/examples/oidc-login/.aug-spec/august/0.19.0/memory/store.aug.md +0 -250
- package/examples/oidc-login/.aug-spec/august/0.19.0/time/contracts.aug.md +0 -96
- package/examples/oidc-login/.aug-spec/august/0.19.0/web/contracts.aug.md +0 -420
- package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
- package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/memory → packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/store.aug +0 -0
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/json → packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/web → packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/time → packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
package/src/cli.js
CHANGED
|
@@ -11,26 +11,53 @@ import { checkUnitTests, discoverTests, mergeTestAnalysis, uniqueDiagnostics } f
|
|
|
11
11
|
import { describe, SemanticWorkspace } from "./semantic.js";
|
|
12
12
|
import { formatFile, migrateFile } from "./formatter.js";
|
|
13
13
|
import { updateSpecs } from "./spec.js";
|
|
14
|
+
import { updateSpecHints } from "./spec-hints.js";
|
|
14
15
|
import { runLanguageServer } from "./lsp.js";
|
|
15
16
|
import { benchmark, compileNative, writeCoverage } from "./native.js";
|
|
16
17
|
import { generateOpenApi } from "./openapi.js";
|
|
17
|
-
import { initPackage, installPackages, preparePackage, packPackage } from "./package-manager.js";
|
|
18
|
+
import { addPackage, initPackage, installPackages, preparePackage, packPackage, prepareRunPackages } from "./package-manager.js";
|
|
18
19
|
import { initProject } from "./project-init.js";
|
|
20
|
+
import { prepareNativeDependencies } from '../scripts/native-setup.mjs';
|
|
21
|
+
function failureMessage(error) {
|
|
22
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
23
|
+
if (error instanceof Error && 'code' in error && ['EACCES', 'EPERM', 'EROFS'].includes(String(error.code)))
|
|
24
|
+
return `${message}\nAugust needs a writable project and native cache. Check the folder permissions, or set AUG_NATIVE_HOME to a directory you own.`;
|
|
25
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOSPC')
|
|
26
|
+
return `${message}\nThere is not enough disk space to compile or prepare dependencies. Free space and retry aug run.`;
|
|
27
|
+
return message;
|
|
28
|
+
}
|
|
19
29
|
function printDiagnostics(diagnostics, json, root) {
|
|
20
30
|
if (json) {
|
|
21
31
|
process.stdout.write(JSON.stringify(diagnostics.map(issue => ({ ...issue,
|
|
22
32
|
help: diagnosticHelp[issue.code] }))) + '\n');
|
|
23
33
|
return;
|
|
24
34
|
}
|
|
35
|
+
const sources = new Map();
|
|
25
36
|
for (const issue of diagnostics) {
|
|
26
|
-
const file =
|
|
37
|
+
const file = relative(root, issue.file) || issue.file;
|
|
27
38
|
process.stderr.write(`${file}:${issue.line}:${issue.column}: ${issue.code}: ${issue.message}\n`);
|
|
39
|
+
try {
|
|
40
|
+
if (!sources.has(issue.file))
|
|
41
|
+
sources.set(issue.file, readFileSync(issue.file, 'utf8').split(/\r?\n/));
|
|
42
|
+
const line = sources.get(issue.file)?.[issue.line - 1];
|
|
43
|
+
if (line !== undefined) {
|
|
44
|
+
const column = Math.max(0, Math.min(line.length, issue.column - 1));
|
|
45
|
+
const start = Math.max(0, column - 70), end = Math.min(line.length, start + 150);
|
|
46
|
+
const text = (start ? '…' : '') + line.slice(start, end).replace(/\t/g, ' ') + (end < line.length ? '…' : '');
|
|
47
|
+
const padding = (start ? 1 : 0) + line.slice(start, column).replace(/\t/g, ' ').length;
|
|
48
|
+
process.stderr.write(` ${issue.line} | ${text}\n ${' '.repeat(String(issue.line).length)} | ${' '.repeat(padding)}^\n`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch { /* Source may have been removed; the location and help remain useful. */ }
|
|
52
|
+
if (diagnosticHelp[issue.code])
|
|
53
|
+
process.stderr.write(` help: ${diagnosticHelp[issue.code]}\n`);
|
|
28
54
|
}
|
|
29
55
|
}
|
|
30
56
|
function usage() {
|
|
31
57
|
process.stdout.write(`AugScript compiler\n\n` +
|
|
32
58
|
`Usage: aug <init|check|build|run|emit-c|test|openapi|format|migrate|spec|bench|explain|context|lsp|symbols|definition|complete|hover|fixes|semantic-tokens> [project directory] [options] [-- args]\n` +
|
|
33
|
-
`New application: aug init DIRECTORY\n` +
|
|
59
|
+
`New application: aug init DIRECTORY [--template hello|weather]\n` +
|
|
60
|
+
`Run: aug run [project directory] [--offline] [-- args] — prepare dependencies, compile, and start\n` +
|
|
34
61
|
`Tests: aug test [project directory] [GROUP_NAME] [--group GROUP_NAME] [--list] [--coverage] [--json] [--timeout milliseconds]\n` +
|
|
35
62
|
`Format: aug format [project directory] [--file path] [--write]\n` +
|
|
36
63
|
`Specifications: aug spec [project directory] [--check] [--json]\n` +
|
|
@@ -38,7 +65,7 @@ function usage() {
|
|
|
38
65
|
`Context: aug context [project directory] [--file path] [--name declaration] [--budget characters]\n` +
|
|
39
66
|
`Benchmark: aug bench [project directory] [--iterations 10] [--warmup 2] [--json] [-- args]\n` +
|
|
40
67
|
`Packages: aug package init DIRECTORY --name @owner/name; aug package pack DIRECTORY\n` +
|
|
41
|
-
`Dependencies: aug install [project directory] [--frozen] [--offline]\n` +
|
|
68
|
+
`Dependencies: aug add URL --as NAME [--project DIRECTORY]; aug install [project directory] [--frozen|--update] [--offline]\n` +
|
|
42
69
|
`Entry point: main.aug at the project root.\n`);
|
|
43
70
|
}
|
|
44
71
|
export async function main(argv) {
|
|
@@ -53,18 +80,46 @@ export async function main(argv) {
|
|
|
53
80
|
usage();
|
|
54
81
|
return 0;
|
|
55
82
|
}
|
|
83
|
+
if (command === 'add') {
|
|
84
|
+
const aliasIndex = argv.indexOf('--as'), projectIndex = argv.indexOf('--project');
|
|
85
|
+
if (!argv[1] || argv[1].startsWith('--') || aliasIndex < 0 || !argv[aliasIndex + 1]) {
|
|
86
|
+
process.stderr.write('Use aug add URL --as NAME [--project DIRECTORY] [--offline]\n');
|
|
87
|
+
return 2;
|
|
88
|
+
}
|
|
89
|
+
for (let index = 2; index < argv.length; index++) {
|
|
90
|
+
if (['--as', '--project'].includes(argv[index])) {
|
|
91
|
+
if (!argv[++index] || argv[index].startsWith('--'))
|
|
92
|
+
return 2;
|
|
93
|
+
}
|
|
94
|
+
else if (argv[index] !== '--offline') {
|
|
95
|
+
process.stderr.write('Unknown add option: ' + argv[index] + '\n');
|
|
96
|
+
return 2;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const alias = argv[aliasIndex + 1], root = resolve(projectIndex < 0 ? process.cwd() : argv[projectIndex + 1]);
|
|
101
|
+
const lock = addPackage(root, argv[1], alias, argv.includes('--offline'));
|
|
102
|
+
process.stdout.write(`Added ${alias}; installed ${lock.packages.length} source package(s).\nImport public names with: import NAME from ${alias}\n`);
|
|
103
|
+
return 0;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
process.stderr.write(failureMessage(error) + '\n');
|
|
107
|
+
return 1;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
56
110
|
if (command === 'init') {
|
|
57
|
-
|
|
58
|
-
|
|
111
|
+
const template = argv.length === 2 ? 'hello' : argv[2] === '--template' && argv.length === 4 ? argv[3] : undefined;
|
|
112
|
+
if (!argv[1] || argv[1].startsWith('--') || !['hello', 'weather'].includes(template ?? '')) {
|
|
113
|
+
process.stderr.write('Use aug init DIRECTORY [--template hello|weather]\n');
|
|
59
114
|
return 2;
|
|
60
115
|
}
|
|
61
116
|
try {
|
|
62
|
-
const root = initProject(argv[1]);
|
|
63
|
-
process.stdout.write(`Created August application in ${root}\nNext: cd ${argv[1]}
|
|
117
|
+
const root = initProject(argv[1], template);
|
|
118
|
+
process.stdout.write(`Created August application in ${root}\nNext: cd ${argv[1]}\n aug run\n`);
|
|
64
119
|
return 0;
|
|
65
120
|
}
|
|
66
121
|
catch (error) {
|
|
67
|
-
process.stderr.write(error
|
|
122
|
+
process.stderr.write(failureMessage(error) + '\n');
|
|
68
123
|
return 1;
|
|
69
124
|
}
|
|
70
125
|
}
|
|
@@ -73,17 +128,18 @@ export async function main(argv) {
|
|
|
73
128
|
const root = resolve((command === 'install' ? argv[1] : argv[2]) && !(command === 'install' ? argv[1] : argv[2]).startsWith('--')
|
|
74
129
|
? (command === 'install' ? argv[1] : argv[2]) : process.cwd());
|
|
75
130
|
if (command === 'install') {
|
|
76
|
-
const lock = installPackages(root, argv.includes('--frozen'), argv.includes('--offline'));
|
|
131
|
+
const lock = installPackages(root, argv.includes('--frozen'), argv.includes('--offline'), argv.includes('--update'));
|
|
77
132
|
process.stdout.write(`Installed ${lock.packages.length} August package(s); aug.lock.json is current.\n`);
|
|
78
133
|
}
|
|
79
134
|
else if (argv[1] === 'init') {
|
|
80
|
-
const name = argv[argv.indexOf('--name') + 1];
|
|
81
|
-
if (!
|
|
82
|
-
throw new Error('Use aug package init DIRECTORY --name @owner/name');
|
|
83
|
-
initPackage(root, name);
|
|
135
|
+
const name = argv.includes('--name') ? argv[argv.indexOf('--name') + 1] : root.split(/[\\/]/).at(-1);
|
|
136
|
+
if (!name)
|
|
137
|
+
throw new Error('Use aug package init DIRECTORY [--name @owner/name]');
|
|
138
|
+
initPackage(root, name, argv.includes('--name'));
|
|
84
139
|
process.stdout.write(`Created August library ${name} in ${root}\n`);
|
|
85
140
|
}
|
|
86
141
|
else if (argv[1] === 'pack') {
|
|
142
|
+
prepareRunPackages(root);
|
|
87
143
|
preparePackage(root);
|
|
88
144
|
const project = loadProject(root), checked = checkProject(project);
|
|
89
145
|
const tests = checkUnitTests(project, discoverTests(project).tests);
|
|
@@ -101,7 +157,7 @@ export async function main(argv) {
|
|
|
101
157
|
return 0;
|
|
102
158
|
}
|
|
103
159
|
catch (error) {
|
|
104
|
-
process.stderr.write(error
|
|
160
|
+
process.stderr.write(failureMessage(error) + '\n');
|
|
105
161
|
return 1;
|
|
106
162
|
}
|
|
107
163
|
}
|
|
@@ -116,6 +172,26 @@ export async function main(argv) {
|
|
|
116
172
|
const separator = argv.indexOf('--');
|
|
117
173
|
const options = separator >= 0 ? argv.slice(1, separator) : argv.slice(1);
|
|
118
174
|
const programArgs = separator >= 0 ? argv.slice(separator + 1) : [];
|
|
175
|
+
if (options.includes('--help')) {
|
|
176
|
+
usage();
|
|
177
|
+
return 0;
|
|
178
|
+
}
|
|
179
|
+
const valueOptions = new Set(['--out', '--stdin-file', '--file', '--name', '--offset', '--budget', '--baseline', '--group', '--case', '--timeout', '--iterations', '--warmup']);
|
|
180
|
+
const booleanOptions = new Set(['--json', '--coverage', '--list', '--write', '--check', '--offline']);
|
|
181
|
+
for (let index = 0; index < options.length; index++) {
|
|
182
|
+
const option = options[index];
|
|
183
|
+
if (valueOptions.has(option)) {
|
|
184
|
+
if (!options[index + 1] || options[index + 1].startsWith('--')) {
|
|
185
|
+
process.stderr.write(`${option} needs a value. See aug ${command} --help.\n`);
|
|
186
|
+
return 2;
|
|
187
|
+
}
|
|
188
|
+
index++;
|
|
189
|
+
}
|
|
190
|
+
else if (option.startsWith('-') && !booleanOptions.has(option)) {
|
|
191
|
+
process.stderr.write(`Unknown option ${option}. See aug ${command} --help. To pass an option to your program, put it after --.\n`);
|
|
192
|
+
return 2;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
119
195
|
const json = options.includes('--json');
|
|
120
196
|
const outIndex = options.indexOf('--out');
|
|
121
197
|
const outputOption = outIndex >= 0 ? options[outIndex + 1] : undefined;
|
|
@@ -171,6 +247,10 @@ export async function main(argv) {
|
|
|
171
247
|
process.stdout.write(JSON.stringify(result) + '\n');
|
|
172
248
|
return 0;
|
|
173
249
|
}
|
|
250
|
+
if (!existsSync(root) || !statSync(root).isDirectory())
|
|
251
|
+
throw new Error(`Project directory does not exist: ${root}\nUse aug init DIRECTORY to create a project, or run aug run from the folder containing main.aug.`);
|
|
252
|
+
if (command === 'run')
|
|
253
|
+
prepareRunPackages(root, options.includes('--offline'));
|
|
174
254
|
const project = loadProject(root, overrides);
|
|
175
255
|
if (project.library && ['build', 'run', 'bench', 'openapi'].includes(command))
|
|
176
256
|
throw new Error('This is an August library; use check, test, or package pack. Import its exports from an application with main.aug to run it.');
|
|
@@ -217,7 +297,9 @@ export async function main(argv) {
|
|
|
217
297
|
const results = [];
|
|
218
298
|
const coverage = options.includes('--coverage'), reports = [];
|
|
219
299
|
for (const [index, { unit, checked: testChecked }] of checks.entries()) {
|
|
220
|
-
const
|
|
300
|
+
const generated = generateC(testChecked, { coverage });
|
|
301
|
+
await prepareNativeDependencies(generated, { offline: options.includes('--offline') });
|
|
302
|
+
const native = compileNative(root, generated, { testIndex: index, checked: testChecked });
|
|
221
303
|
const report = join(root, '.aug-build', 'tests', `coverage-${index}.tsv`);
|
|
222
304
|
reports.push(report);
|
|
223
305
|
if (coverage)
|
|
@@ -244,7 +326,7 @@ export async function main(argv) {
|
|
|
244
326
|
`${passed} passed, ${failed} failed\n` + (report ? `Coverage: ${report.covered}/${report.executable} statement lines (${report.percent.toFixed(1)}%); ${report.path}\n` : ''));
|
|
245
327
|
return failed ? 1 : 0;
|
|
246
328
|
}
|
|
247
|
-
|
|
329
|
+
let checked = checkProject(project);
|
|
248
330
|
const testChecks = checkUnitTests(project, discovered.tests);
|
|
249
331
|
checked.diagnostics = uniqueDiagnostics([...checked.diagnostics, ...discovered.diagnostics,
|
|
250
332
|
...testChecks.flatMap(entry => entry.checked.diagnostics)]);
|
|
@@ -305,6 +387,13 @@ export async function main(argv) {
|
|
|
305
387
|
process.stdout.write(json ? JSON.stringify(result) + '\n' : result.stale.length ? 'Stale specifications:\n' + result.stale.map(file => ' ' + file).join('\n') + '\n' : `${result.files} specification artifact(s) ${options.includes('--check') ? 'are current' : 'generated'}.\n`);
|
|
306
388
|
return result.stale.length ? 1 : 0;
|
|
307
389
|
}
|
|
390
|
+
if (['build', 'run', 'bench'].includes(command)) {
|
|
391
|
+
checked = updateSpecHints(checked);
|
|
392
|
+
if (checked.diagnostics.some(issue => issue.severity !== 'warning')) {
|
|
393
|
+
printDiagnostics(checked.diagnostics, json, root);
|
|
394
|
+
return 1;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
308
397
|
const generated = generateC(checked);
|
|
309
398
|
if (command === 'emit-c') {
|
|
310
399
|
process.stdout.write(generated);
|
|
@@ -313,6 +402,7 @@ export async function main(argv) {
|
|
|
313
402
|
if (command === 'bench' && (!Number.isInteger(iterations) || iterations < 1 || iterations > 1000 ||
|
|
314
403
|
!Number.isInteger(warmup) || warmup < 0 || warmup > 100 || !Number.isInteger(timeout) || timeout < 1))
|
|
315
404
|
throw new Error('bench requires iterations 1–1000, warmup 0–100, and a positive timeout');
|
|
405
|
+
await prepareNativeDependencies(generated, { offline: options.includes('--offline') });
|
|
316
406
|
const native = compileNative(root, generated, { output: outputOption, release: command === 'bench' ? true : undefined, checked });
|
|
317
407
|
const output = native.output;
|
|
318
408
|
if (native.status !== 0) {
|
|
@@ -334,11 +424,15 @@ export async function main(argv) {
|
|
|
334
424
|
}
|
|
335
425
|
const run = spawnSync(output, programArgs, { stdio: 'inherit', cwd: root });
|
|
336
426
|
if (run.error)
|
|
337
|
-
throw run.error;
|
|
427
|
+
throw new Error(`Cannot start the compiled program ${output}: ${run.error.message}.\nCheck executable permissions and the native shared-library paths.`);
|
|
428
|
+
if (run.signal)
|
|
429
|
+
process.stderr.write(`Program stopped by ${run.signal}. Check the runtime message above; aug run compiled and started ${output}.\n`);
|
|
430
|
+
else if (run.status !== 0)
|
|
431
|
+
process.stderr.write(`Program exited with status ${run.status}.\n`);
|
|
338
432
|
return run.status ?? 1;
|
|
339
433
|
}
|
|
340
434
|
catch (error) {
|
|
341
|
-
process.stderr.write(
|
|
342
|
-
return 1;
|
|
435
|
+
process.stderr.write(failureMessage(error) + '\n');
|
|
436
|
+
return error instanceof Error && 'exitCode' in error && typeof error.exitCode === 'number' ? error.exitCode : 1;
|
|
343
437
|
}
|
|
344
438
|
}
|
package/src/codegen.js
CHANGED
|
@@ -154,7 +154,7 @@ class CGenerator {
|
|
|
154
154
|
` aug_register_globals(aug_bindings, ${bindingCount});`,
|
|
155
155
|
` aug_set_cli_args(argc, argv);`,
|
|
156
156
|
...([...this.activeFiles].some(file => this.checked.project.files.get(file)?.items.some(item => item.kind === 'function' && !!item.endpoint) ||
|
|
157
|
-
|
|
157
|
+
this.checked.project.files.get(file)?.items.some(item => item.kind === 'function' && item.externC && item.name.startsWith('_aug_http_'))) ? [this.httpConfiguration()] : []),
|
|
158
158
|
...[...this.coverage.values()].map(point => ` aug_coverage_register(${cString(point.file)}, ${point.line});`),
|
|
159
159
|
initializeBindings,
|
|
160
160
|
` AugValue result = aug_main_body(NULL, 0);`,
|
package/src/config.js
CHANGED
|
@@ -55,7 +55,7 @@ export function loadConfig(root) {
|
|
|
55
55
|
seen.add(path);
|
|
56
56
|
if (path.startsWith('packages.')) {
|
|
57
57
|
if (!/^[a-z][a-z0-9_]*$/.test(entry[1]) || entry[1] === 'august' || !value)
|
|
58
|
-
report(index + 1, 'Packages map lowercase public aliases to local paths or npm:name@exact-version');
|
|
58
|
+
report(index + 1, 'Packages map lowercase public aliases to repository URLs, local paths, or npm:name@exact-version');
|
|
59
59
|
else
|
|
60
60
|
config.packages[entry[1]] = value;
|
|
61
61
|
continue;
|
package/src/contracts.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { schemaType } from "./schemas.js";
|
|
2
|
+
import { tyName } from "./types.js";
|
|
3
|
+
/** Checked contracts shared by the editor, documentation and wire schemas. */
|
|
4
|
+
export function callableResult(checked, method) {
|
|
5
|
+
return checked.callableContracts.get(method)?.result ?? schemaType(checked.project, method.returns, method.span.file);
|
|
6
|
+
}
|
|
7
|
+
export function callableErrors(checked, method) {
|
|
8
|
+
return [...new Set([...(checked.callableContracts.get(method)?.errors.map(tyName) ?? method.throws.map(type => tyName(schemaType(checked.project, type, method.span.file)))),
|
|
9
|
+
...(checked.interceptorPlans.get(method) ?? []).flatMap(layer => layer.errors.map(tyName))])].sort();
|
|
10
|
+
}
|
package/src/editor.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { callableResult, callableErrors } from "./contracts.js";
|
|
1
2
|
import { dirname, join, relative, resolve, sep } from 'node:path';
|
|
2
3
|
import { fieldsOf, typeName } from "./ast.js";
|
|
3
4
|
import { tyName } from "./checker.js";
|
|
@@ -12,6 +13,8 @@ import { interceptorBehavior } from "./interceptors.js";
|
|
|
12
13
|
import { httpPolicyNames, httpPolicyOptions, httpPolicyOptionHelp } from "./http-policies.js";
|
|
13
14
|
import { builtinTypes } from "./builtins.js";
|
|
14
15
|
import { libraryChild, libraryRelative } from "./libraries.js";
|
|
16
|
+
import { importSource, isGitSource, sourceAlias } from "./git-packages.js";
|
|
17
|
+
import { snippetBody, snippetCatalog } from "./snippets.js";
|
|
15
18
|
const builtins = [
|
|
16
19
|
...builtinFunctions.map(operation => {
|
|
17
20
|
const parameters = operation.parameters.map(param => `${param.label}=${param.type}`);
|
|
@@ -24,6 +27,8 @@ const builtins = [
|
|
|
24
27
|
.map(([label, help]) => ({ label, kind: 'type', detail: help.detail, documentation: help.documentation })),
|
|
25
28
|
];
|
|
26
29
|
const keywords = [
|
|
30
|
+
...snippetCatalog.map(snippet => ({ label: snippet.prefix + ' template', kind: 'snippet', detail: snippet.description,
|
|
31
|
+
documentation: snippet.description, insertText: snippet.body })),
|
|
27
32
|
{ label: 'initialize block', kind: 'snippet', detail: 'Constructor initialization inside a class or record', documentation: languageHelp.initialize.documentation,
|
|
28
33
|
insertText: 'initialize:\n $0' },
|
|
29
34
|
...Object.entries(languageHelp).filter(([label, help]) => help.category === 'keyword' &&
|
|
@@ -38,7 +43,7 @@ const keywords = [
|
|
|
38
43
|
insertText: 'borrow ${1:value} {\n $0\n}' },
|
|
39
44
|
{ label: 'interceptor declaration', kind: 'snippet', detail: 'Generic interceptor wrapping any result type',
|
|
40
45
|
documentation: languageHelp.interceptor.documentation,
|
|
41
|
-
insertText: 'interceptor ${1:Audit}<T>() {\n around()
|
|
46
|
+
insertText: 'interceptor ${1:Audit}<T>() {\n around() {\n result = next()\n $0\n return result\n }\n}' },
|
|
42
47
|
{ label: 'test suite', kind: 'snippet', detail: 'Same-file class tests with fresh setup per case',
|
|
43
48
|
documentation: languageHelp.test.documentation,
|
|
44
49
|
insertText: 'test ${1:Worker} ${2:worker} {\n when ${3:ready} {\n ${2:worker} = ${1:Worker}()\n it ${4:works} {\n assert(${5:true})\n }\n }\n}' },
|
|
@@ -59,15 +64,18 @@ function parameterText(param) {
|
|
|
59
64
|
`${typeName(param.type)} ${param.label ?? param.name}${param.label && param.label !== param.name ? ` to ${param.name}` : ''}` +
|
|
60
65
|
(param.source ? ` from ${param.source.kind}${param.source.name ? ' ' + JSON.stringify(param.source.name) : ''}` : '');
|
|
61
66
|
}
|
|
62
|
-
function signature(method, callSite = false, additionalErrors = []) {
|
|
67
|
+
function signature(method, callSite = false, additionalErrors = [], checked) {
|
|
63
68
|
const generic = method.typeParams.length ? `<${method.typeParams.join(', ')}>` : '';
|
|
64
69
|
const params = callSite ? method.params.filter(param => !param.injected)
|
|
65
70
|
.map(param => `${param.label ?? param.name}=${typeName(param.type)}`) : method.params.map(parameterText);
|
|
66
|
-
const errors = [...new Set([...method.throws.map(typeName), ...additionalErrors])];
|
|
71
|
+
const errors = checked ? callableErrors(checked, method) : [...new Set([...method.throws.map(typeName), ...additionalErrors])];
|
|
72
|
+
const contract = checked?.effectContracts.get(method);
|
|
73
|
+
const changes = contract?.changes ?? method.changes ?? [];
|
|
74
|
+
const uses = [...(contract?.uses.values() ?? method.uses ?? [])].map(use => `${use.source}.${use.operation}`);
|
|
67
75
|
return (method.endpoint ? `endpoint ${method.endpoint.method} ${JSON.stringify(method.endpoint.path)} as ` : '') + `${method.name}${generic}(${params.join(', ')}) ${method.endpoint?.streams ? 'streams' : 'returns'} ` +
|
|
68
|
-
`${method.returnOwnership === 'own' ? 'own ' : ''}${typeName(method.returns)}` +
|
|
69
|
-
(
|
|
70
|
-
(
|
|
76
|
+
`${method.returnOwnership === 'own' ? 'own ' : ''}${checked ? tyName(callableResult(checked, method)) : typeName(method.returns)}` +
|
|
77
|
+
(changes.length ? ` changes ${changes.join(' and ')}` : '') +
|
|
78
|
+
(uses.length ? ` uses ${uses.join(' and ')}` : '') +
|
|
71
79
|
(errors.length ? ` unless ${errors.join(', ')}` : '') +
|
|
72
80
|
(method.endpoint && method.endpoint.status !== 200 ? ` with status ${method.endpoint.status}` : '');
|
|
73
81
|
}
|
|
@@ -117,14 +125,14 @@ function methodDocumentation(checked, method, owner) {
|
|
|
117
125
|
}
|
|
118
126
|
function methodItem(checked, method, kind, owner) {
|
|
119
127
|
const errors = (checked.interceptorPlans.get(method) ?? []).flatMap(layer => layer.errors.map(tyName));
|
|
120
|
-
const label = signature(method, false, errors);
|
|
128
|
+
const label = signature(method, false, errors, checked);
|
|
121
129
|
const injected = method.params.filter(param => param.injected);
|
|
122
130
|
const doc = methodDocumentation(checked, method, owner);
|
|
123
131
|
const injectionHelp = injected.length ? `Injected from bindings: ${injected.map(parameterText).join(', ')}.` : '';
|
|
124
132
|
const contract = checked.effectContracts.get(method);
|
|
125
133
|
const effects = contract ? `${contract.inferred ? 'Inferred capabilities; effective' : 'Effective'} contract: changes ${contract.changes.join(', ') || 'nothing'}; capabilities ` +
|
|
126
134
|
`${[...contract.uses.values()].map(effect => `${effect.source}.${effect.operation}`).join(', ') || 'none'}.` : '';
|
|
127
|
-
return { label: method.name, kind, detail: label, signature: signature(method, true, errors),
|
|
135
|
+
return { label: method.name, kind, detail: label, signature: signature(method, true, errors, checked),
|
|
128
136
|
documentation: [doc?.markdown, isPrivateName(method.name) ? 'Private to its declaring type.' : '',
|
|
129
137
|
injectionHelp, effects, interceptorDescription(checked, method), 'Call arguments require labels; their order does not matter.']
|
|
130
138
|
.filter(Boolean).join('\n\n'),
|
|
@@ -147,7 +155,7 @@ function definitionItem(checked, def) {
|
|
|
147
155
|
const doc = around && methodDocumentation(checked, around, def);
|
|
148
156
|
return { label: def.name, kind: 'interceptor',
|
|
149
157
|
detail: `interceptor ${node.name}${node.typeParams.length ? `<${node.typeParams.join(', ')}>` : ''}` +
|
|
150
|
-
`(${node.fields.map(parameterText).join(', ')})` + (around ? `\n${signature(around)}` : ''),
|
|
158
|
+
`(${node.fields.map(parameterText).join(', ')})` + (around ? `\n${signature(around, false, [], checked)}` : ''),
|
|
151
159
|
signature: `${node.name}(${params.map(param => `${param.name}=targetLabel`).join(', ')})`,
|
|
152
160
|
parameters: params.map(param => `${param.name}=targetLabel`),
|
|
153
161
|
parameterDocumentation: params.map(param => [doc?.parameters.get(param.name),
|
|
@@ -292,7 +300,9 @@ export function importItems(checked, file) {
|
|
|
292
300
|
if (isPrivateName(item.name))
|
|
293
301
|
continue;
|
|
294
302
|
items.push({ label: item.name, kind: 'snippet',
|
|
295
|
-
detail: `import ${item.name} from ${from}`, insertText: `${item.name} from ${from}
|
|
303
|
+
detail: `import ${item.name} from ${from}`, insertText: `${item.name} from ${from}`,
|
|
304
|
+
signature: definitionItem(checked, project.scopes.get(sibling.path).get(item.name)).signature,
|
|
305
|
+
parameters: definitionItem(checked, project.scopes.get(sibling.path).get(item.name)).parameters,
|
|
296
306
|
documentation: item.kind === 'interface' ? documentation(checked, sibling.path, item.span.start)?.markdown :
|
|
297
307
|
declarationDocumentation(checked, item)?.markdown });
|
|
298
308
|
}
|
|
@@ -335,7 +345,8 @@ export function importItems(checked, file) {
|
|
|
335
345
|
continue;
|
|
336
346
|
for (const prefix of prefixes)
|
|
337
347
|
for (const item of exportFile.items) {
|
|
338
|
-
const
|
|
348
|
+
const specification = (owner?.specifications ?? project.packages.specifications)[prefix[0]];
|
|
349
|
+
const from = isGitSource(specification ?? '') && prefix[0] === sourceAlias(specification) ? importSource([specification, ...segments]) : [...prefix, ...segments].join('.');
|
|
339
350
|
if (!from)
|
|
340
351
|
continue;
|
|
341
352
|
if (item.kind !== 'export' || item.folder)
|
|
@@ -344,13 +355,15 @@ export function importItems(checked, file) {
|
|
|
344
355
|
continue;
|
|
345
356
|
const exported = project.scopes.get(join(folder, `${item.from}.aug`))?.get(item.name);
|
|
346
357
|
items.push({ label: item.name, kind: 'snippet',
|
|
347
|
-
detail: `import ${item.name} from ${from}`, insertText: `${item.name} from ${from}
|
|
358
|
+
detail: `import ${item.name} from ${from}`, insertText: `${item.name} from ${from}`,
|
|
359
|
+
signature: exported && definitionItem(checked, exported).signature,
|
|
360
|
+
parameters: exported && definitionItem(checked, exported).parameters,
|
|
348
361
|
documentation: exported && definitionItem(checked, exported).documentation });
|
|
349
362
|
}
|
|
350
363
|
}
|
|
351
364
|
return items;
|
|
352
365
|
}
|
|
353
|
-
|
|
366
|
+
function rawCompletions(checked, fileName, offset) {
|
|
354
367
|
const file = checked.project.files.get(resolve(fileName));
|
|
355
368
|
if (!file)
|
|
356
369
|
return [];
|
|
@@ -364,12 +377,13 @@ export function completions(checked, fileName, offset) {
|
|
|
364
377
|
const used = new Set(joined[1].split(/\s+and\s+/));
|
|
365
378
|
return unique(imports.filter(item => !used.has(item.label)).map(item => ({ ...item, kind: 'snippet', insertText: item.label })));
|
|
366
379
|
}
|
|
367
|
-
const from = /^\s*import\s+(.+?)\s+from\s+[A-Za-z_0-9.]
|
|
380
|
+
const from = /^\s*import\s+(.+?)\s+from\s+([A-Za-z_0-9.]*|"[^"\n]*"?(?:\.[A-Za-z_0-9.]*)?)$/.exec(line);
|
|
368
381
|
if (from)
|
|
369
382
|
return unique(imports.filter(item => from[1] === 'everything' || item.label === from[1].split(/\s+and\s+/)[0]).map(item => {
|
|
370
383
|
const path = item.detail.slice(item.detail.lastIndexOf(' from ') + 6);
|
|
371
384
|
return { label: path, kind: 'snippet', detail: item.detail,
|
|
372
|
-
insertText:
|
|
385
|
+
insertText: path, documentation: item.documentation,
|
|
386
|
+
replacement: { start: offset - from[2].length, end: offset } };
|
|
373
387
|
}));
|
|
374
388
|
const annotation = /(?<=^|\n)[ \t]*\[\s*([A-Za-z_][A-Za-z0-9_]*|)(?:<[^\[\]()]*>)?(?:\(([^\n()]*))?$/.exec(prefix);
|
|
375
389
|
if (annotation) {
|
|
@@ -463,7 +477,48 @@ export function completions(checked, fileName, offset) {
|
|
|
463
477
|
return all.filter(item => item.kind === 'interface');
|
|
464
478
|
if (/\b(?:returns|unless|catch)\s+[A-Za-z_0-9]*$/.test(prefix))
|
|
465
479
|
return all.filter(item => ['class', 'interface', 'type'].includes(item.kind));
|
|
466
|
-
|
|
480
|
+
const visible = new Set(all.map(item => item.label));
|
|
481
|
+
const importsEnd = file.items.filter(item => item.kind === 'import').at(-1)?.span.end ?? 0;
|
|
482
|
+
const insertion = importsEnd ? file.source.indexOf('\n', importsEnd) : 0;
|
|
483
|
+
return [...all, ...imports.filter(item => !visible.has(item.label)).map(item => ({ ...item,
|
|
484
|
+
kind: item.signature ? 'function' : 'type',
|
|
485
|
+
insertText: item.label, sortText: '2-' + item.label,
|
|
486
|
+
additionalEdits: [{ start: insertion < 0 ? file.source.length : insertion, end: insertion < 0 ? file.source.length : insertion,
|
|
487
|
+
text: `${importsEnd ? '\n' : ''}${item.detail}${importsEnd ? '' : '\n'}` }] }))];
|
|
488
|
+
}
|
|
489
|
+
/** Fill labeled calls, keep dependency imports visible, and replace only the token being completed. */
|
|
490
|
+
export function completions(checked, fileName, offset) {
|
|
491
|
+
const file = checked.project.files.get(resolve(fileName));
|
|
492
|
+
if (!file)
|
|
493
|
+
return [];
|
|
494
|
+
const prefix = file.source.slice(0, offset), line = prefix.slice(prefix.lastIndexOf('\n') + 1);
|
|
495
|
+
const typeContext = /\b(?:import|export|implement|implements|extends|returns|unless|catch|resolve)\b[^\n]*$/.test(line);
|
|
496
|
+
const token = /[A-Za-z_][A-Za-z0-9_]*$/.exec(prefix);
|
|
497
|
+
const start = token ? offset - token[0].length : offset;
|
|
498
|
+
const end = offset + (/^[A-Za-z0-9_]*/.exec(file.source.slice(offset))?.[0].length ?? 0);
|
|
499
|
+
const escape = (text) => text.replace(/[\\$}]/g, '\\$&');
|
|
500
|
+
const argument = (parameter, index) => {
|
|
501
|
+
const [name, type] = parameter.split('=');
|
|
502
|
+
const value = type === 'string' ? '""' : type === 'bool' ? 'false' : ['int', 'float', 'c_int'].includes(type) ? '0' : name;
|
|
503
|
+
return `${name}=\${${index + 1}:${escape(value)}}`;
|
|
504
|
+
};
|
|
505
|
+
return rawCompletions(checked, fileName, offset).map(item => {
|
|
506
|
+
const callable = !typeContext && ['function', 'method', 'class'].includes(item.kind) && item.signature &&
|
|
507
|
+
!/^\s*\(/.test(file.source.slice(offset));
|
|
508
|
+
let insertText = callable ? `${item.label}(${(item.parameters ?? []).map(argument).join(', ')})$0` : item.insertText;
|
|
509
|
+
const template = snippetCatalog.find(snippet => item.label === snippet.prefix + ' template');
|
|
510
|
+
if (template)
|
|
511
|
+
insertText = snippetBody(template.body, checked.project.config.block_style, checked.project.config.indentation === 'tabs');
|
|
512
|
+
if (item.kind === 'snippet' && insertText && checked.project.config.block_style === 'indent' && insertText.includes('{\n'))
|
|
513
|
+
insertText = insertText.replace(/^(\s*)\} catch /gm, '$1catch ').replace(/ \{\n/g, ':\n').replace(/^[ \t]*\}\n?/gm, '').trimEnd();
|
|
514
|
+
let additionalEdits = item.additionalEdits;
|
|
515
|
+
if (additionalEdits?.some(edit => edit.start >= start && edit.start <= end)) {
|
|
516
|
+
insertText = additionalEdits.map(edit => escape(edit.text)).join('') + (insertText ?? item.label);
|
|
517
|
+
additionalEdits = undefined;
|
|
518
|
+
}
|
|
519
|
+
return { ...item, insertText, additionalEdits, replacement: item.replacement ?? { start, end },
|
|
520
|
+
sortText: item.sortText ?? (['variable', 'parameter', 'property'].includes(item.kind) ? '0-' : '1-') + item.label };
|
|
521
|
+
});
|
|
467
522
|
}
|
|
468
523
|
/** Resolve exactly the token under the cursor, including syntax outside completion contexts. */
|
|
469
524
|
export function hoverInfo(checked, fileName, offset) {
|
package/src/fixes.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import { typeName } from "./ast.js";
|
|
3
|
+
import { completions, hoverInfo, importItems } from "./editor.js";
|
|
4
|
+
import { importSource } from "./git-packages.js";
|
|
3
5
|
import { languageHelp } from "./help.js";
|
|
4
6
|
import { lex } from "./lexer.js";
|
|
5
7
|
import { tyName } from "./types.js";
|
|
@@ -74,6 +76,24 @@ function containingStatement(file, offset) {
|
|
|
74
76
|
}
|
|
75
77
|
return result.at(-1);
|
|
76
78
|
}
|
|
79
|
+
function callsIn(file) {
|
|
80
|
+
const result = [];
|
|
81
|
+
const visit = (value) => {
|
|
82
|
+
if (!value || typeof value !== 'object')
|
|
83
|
+
return;
|
|
84
|
+
if (Array.isArray(value)) {
|
|
85
|
+
value.forEach(visit);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if ('kind' in value && value.kind === 'call')
|
|
89
|
+
result.push(value);
|
|
90
|
+
for (const [key, child] of Object.entries(value))
|
|
91
|
+
if (key !== 'span')
|
|
92
|
+
visit(child);
|
|
93
|
+
};
|
|
94
|
+
visit(file.items);
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
77
97
|
function wrappedStatement(file, issue, opener, closer = '}') {
|
|
78
98
|
const stmt = containingStatement(file, offsetAt(file.source, issue.line, issue.column));
|
|
79
99
|
// A declaration moved into a new block would become invisible afterward.
|
|
@@ -108,7 +128,7 @@ export function suggestedFixes(checked, fileName) {
|
|
|
108
128
|
if (names.length)
|
|
109
129
|
fixes.push({ title: 'Expand to named imports', issue: { code: 'IMPORT', line: item.span.line, column: item.span.column,
|
|
110
130
|
message: 'Make imported dependencies explicit' }, edits: [{ file: file.path, start: item.span.start, end: item.span.end,
|
|
111
|
-
text: `import ${names.join(' and ')} from ${item.from
|
|
131
|
+
text: `import ${names.join(' and ')} from ${importSource(item.from)}` }] });
|
|
112
132
|
}
|
|
113
133
|
for (const issue of checked.diagnostics.filter(issue => issue.file === file.path)) {
|
|
114
134
|
const add = (title, edit) => {
|
|
@@ -118,6 +138,43 @@ export function suggestedFixes(checked, fileName) {
|
|
|
118
138
|
const unknown = /^(?:Unknown name|Unknown type|Unknown interceptor) ([A-Za-z_][A-Za-z0-9_]*)$/.exec(issue.message);
|
|
119
139
|
const mistyped = /^Expected ([A-Za-z_]+), found "([A-Za-z_]+)"$/.exec(issue.message);
|
|
120
140
|
const redundant = /^Remove (class|function|fuction); declarations start with their name$/.exec(issue.message);
|
|
141
|
+
const missing = /^([A-Za-z_][A-Za-z0-9_]*) must implement ([A-Za-z_][A-Za-z0-9_]*)$/.exec(issue.message);
|
|
142
|
+
if (issue.code === 'INTERFACE' && missing) {
|
|
143
|
+
const owner = file.items.find(item => item.kind === 'class' && item.name === missing[1]);
|
|
144
|
+
if (owner?.kind === 'class') {
|
|
145
|
+
const seen = new Set();
|
|
146
|
+
const substitute = (ref, types) => types.get(ref.name) ?? { ...ref, args: ref.args.map(arg => substitute(arg, types)) };
|
|
147
|
+
const find = (ref, source) => {
|
|
148
|
+
const def = checked.project.scopes.get(source)?.get(ref.name);
|
|
149
|
+
if (!def || def.node.kind !== 'interface' || seen.has(def.id))
|
|
150
|
+
return;
|
|
151
|
+
seen.add(def.id);
|
|
152
|
+
const types = new Map(def.node.typeParams.map((name, index) => [name, ref.args[index]]).filter((entry) => !!entry[1]));
|
|
153
|
+
const method = def.node.methods.find(method => method.name === missing[2]);
|
|
154
|
+
if (method)
|
|
155
|
+
return { method, types };
|
|
156
|
+
for (const parent of def.node.extends) {
|
|
157
|
+
const found = find(substitute(parent, types), def.file);
|
|
158
|
+
if (found)
|
|
159
|
+
return found;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
const contract = owner.implements.map(ref => find(ref, file.path)).find(Boolean);
|
|
163
|
+
if (contract) {
|
|
164
|
+
const params = contract.method.params.map(param => `${param.injected ? 'resolve ' : ''}${param.ownership === 'managed' ? '' : param.ownership + ' '}${typeName(substitute(param.type, contract.types))} ${param.name}`);
|
|
165
|
+
const generic = contract.method.typeParams.length ? '<' + contract.method.typeParams.join(', ') + '>' : '';
|
|
166
|
+
const header = `${missing[2]}${generic}(${params.join(', ')}) returns ${contract.method.returnOwnership === 'own' ? 'own ' : ''}${typeName(substitute(contract.method.returns, contract.types))}` +
|
|
167
|
+
(contract.method.throws.length ? ' unless ' + contract.method.throws.map(ref => typeName(substitute(ref, contract.types))).join(', ') : '');
|
|
168
|
+
const unit = checked.project.config.indentation === 'tabs' ? '\t' : ' ';
|
|
169
|
+
const start = owner.headerEnd ?? owner.span.start;
|
|
170
|
+
const braces = file.source[start] === '{' || file.source.slice(owner.span.start, start + 1).trimEnd().endsWith('{');
|
|
171
|
+
const insertion = braces ? file.source.lastIndexOf('}', owner.span.end - 1) : owner.span.end;
|
|
172
|
+
if (insertion >= owner.span.start)
|
|
173
|
+
add(`Implement ${missing[2]} in ${owner.name}`, { file: file.path, start: insertion, end: insertion,
|
|
174
|
+
text: braces ? `\n${unit}${header} {\n${unit}${unit}// TODO: implement ${missing[2]}\n${unit}}\n` : `\n${unit}${header}:\n${unit}${unit}// TODO: implement ${missing[2]}\n${unit}${unit}pass\n` });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
121
178
|
if (issue.code === 'PARSE' && redundant) {
|
|
122
179
|
const start = offsetAt(file.source, issue.line, issue.column);
|
|
123
180
|
if (file.source.slice(start, start + redundant[1].length) === redundant[1])
|
|
@@ -140,6 +197,37 @@ export function suggestedFixes(checked, fileName) {
|
|
|
140
197
|
seen.add(declaration);
|
|
141
198
|
add(`Import ${unknown[1]} from ${item.detail.split(' from ')[1]}`, { file: file.path, start: 0, end: 0, text: `${declaration}\n` });
|
|
142
199
|
}
|
|
200
|
+
const start = offsetAt(file.source, issue.line, issue.column);
|
|
201
|
+
const candidates = completions(checked, file.path, start + unknown[1].length).filter(item => !item.additionalEdits && ['variable', 'parameter', 'property', 'function', 'class', 'interface', 'type'].includes(item.kind) &&
|
|
202
|
+
item.label !== unknown[1] && distance(item.label, unknown[1]) <= Math.min(2, Math.floor(unknown[1].length / 3)));
|
|
203
|
+
for (const candidate of candidates.slice(0, 3))
|
|
204
|
+
fixes.push({ title: `Replace ${unknown[1]} with ${candidate.label}`, issue,
|
|
205
|
+
preferred: candidates.length === 1, edits: [{ file: file.path, start, end: start + unknown[1].length, text: candidate.label }] });
|
|
206
|
+
}
|
|
207
|
+
const badMember = / has no (?:member|method) ([A-Za-z_][A-Za-z0-9_]*)$/.exec(issue.message);
|
|
208
|
+
if (badMember) {
|
|
209
|
+
const start = offsetAt(file.source, issue.line, issue.column), tokens = lex(file.path, file.source).tokens;
|
|
210
|
+
const member = tokens.find(token => token.value === badMember[1] && token.span.start >= start && token.span.line === issue.line);
|
|
211
|
+
if (member) {
|
|
212
|
+
const candidates = completions(checked, file.path, member.span.end).filter(item => item.label !== member.value && distance(item.label, member.value) <= 2);
|
|
213
|
+
for (const candidate of candidates.slice(0, 3))
|
|
214
|
+
fixes.push({ title: `Replace ${member.value} with ${candidate.label}`, issue,
|
|
215
|
+
preferred: candidates.length === 1, edits: [{ file: file.path, start: member.span.start, end: member.span.end, text: candidate.label }] });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const badLabel = / has no parameter ([A-Za-z_][A-Za-z0-9_]*)$/.exec(issue.message);
|
|
219
|
+
if (issue.code === 'CALL' && badLabel) {
|
|
220
|
+
const start = offsetAt(file.source, issue.line, issue.column);
|
|
221
|
+
const calls = callsIn(file).filter(call => call.span.start <= start && start < call.span.end)
|
|
222
|
+
.sort((a, b) => a.span.end - a.span.start - (b.span.end - b.span.start));
|
|
223
|
+
const call = calls[0], entry = call && hoverInfo(checked, file.path, call.callee.span.end - 1);
|
|
224
|
+
const tokens = call && lex(file.path, file.source).tokens.filter(token => call.span.start < token.span.start && token.span.end <= start);
|
|
225
|
+
const label = tokens?.findLast(token => token.value === badLabel[1]);
|
|
226
|
+
const candidates = entry?.parameters?.map(parameter => parameter.split('=')[0]).filter(name => !call.argLabels.includes(name) && distance(name, badLabel[1]) <= 2) ?? [];
|
|
227
|
+
if (label)
|
|
228
|
+
for (const name of candidates)
|
|
229
|
+
fixes.push({ title: `Use argument label ${name}`, issue, preferred: candidates.length === 1,
|
|
230
|
+
edits: [{ file: file.path, start: label.span.start, end: label.span.end, text: name }] });
|
|
143
231
|
}
|
|
144
232
|
if (issue.code === 'INTERCEPTOR' && /constructor parameter .* must be marked resolve/.test(issue.message)) {
|
|
145
233
|
const start = offsetAt(file.source, issue.line, issue.column);
|