goscript 0.1.3 → 0.2.0
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 +5 -2
- package/cmd/go_js_wasm_exec/main.go +201 -0
- package/cmd/go_js_wasm_exec/main_test.go +83 -0
- package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +35 -8
- package/cmd/goscript/cmd-test.go +14 -0
- package/cmd/goscript/cmd-test_test.go +1 -1
- package/cmd/goscript/cmd_compile_test.go +105 -6
- package/compiler/build-flags.go +9 -10
- package/compiler/compile-request.go +12 -9
- package/compiler/compliance_test.go +0 -1
- package/compiler/config.go +2 -0
- package/compiler/gotest/request.go +28 -0
- package/compiler/gotest/runner.go +353 -27
- package/compiler/gotest/runner_test.go +400 -1
- package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
- package/compiler/gotest/testdata/browserapi/go.mod +3 -0
- package/compiler/lowered-program.go +24 -17
- package/compiler/lowering.go +988 -263
- package/compiler/lowering_bench_test.go +364 -0
- package/compiler/override-facts.go +15 -0
- package/compiler/override-parity-verifier.go +450 -0
- package/compiler/override-parity.go +122 -0
- package/compiler/override-registry_test.go +559 -0
- package/compiler/package-graph.go +61 -4
- package/compiler/package-graph_test.go +30 -0
- package/compiler/protobuf-ts-binding.go +514 -0
- package/compiler/protobuf-ts-binding_test.go +172 -0
- package/compiler/semantic-model-types.go +17 -4
- package/compiler/semantic-model.go +709 -72
- package/compiler/semantic-model_test.go +219 -0
- package/compiler/service.go +20 -1
- package/compiler/skeleton_test.go +1008 -20
- package/compiler/typescript-emitter.go +147 -15
- package/dist/gs/builtin/builtin.d.ts +2 -2
- package/dist/gs/builtin/builtin.js +20 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +2 -1
- package/dist/gs/builtin/slice.js +34 -4
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +14 -6
- package/dist/gs/builtin/type.js +224 -64
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +11 -0
- package/dist/gs/builtin/varRef.js +57 -2
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js +1 -1
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.js +1 -1
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +13 -6
- package/dist/gs/compress/zlib/index.js +131 -35
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/crypto/sha1/index.js +2 -5
- package/dist/gs/crypto/sha1/index.js.map +1 -1
- package/dist/gs/crypto/sha256/index.js +2 -5
- package/dist/gs/crypto/sha256/index.js.map +1 -1
- package/dist/gs/crypto/sha512/index.js +2 -5
- package/dist/gs/crypto/sha512/index.js.map +1 -1
- package/dist/gs/embed/index.d.ts +6 -0
- package/dist/gs/embed/index.js +210 -5
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/encoding/json/index.d.ts +114 -0
- package/dist/gs/encoding/json/index.js +544 -36
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +3 -3
- package/dist/gs/fmt/fmt.js +29 -16
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +100 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +564 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.d.ts +45 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js +229 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/errors.js +54 -30
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/go/scanner/index.d.ts +2 -0
- package/dist/gs/go/scanner/index.js +29 -5
- package/dist/gs/go/scanner/index.js.map +1 -1
- package/dist/gs/go/token/index.js +22 -6
- package/dist/gs/go/token/index.js.map +1 -1
- package/dist/gs/hash/index.d.ts +6 -0
- package/dist/gs/hash/index.js +20 -0
- package/dist/gs/hash/index.js.map +1 -1
- package/dist/gs/internal/goarch/index.d.ts +43 -3
- package/dist/gs/internal/goarch/index.js +42 -10
- package/dist/gs/internal/goarch/index.js.map +1 -1
- package/dist/gs/io/fs/fs.js +26 -14
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/fs/readdir.js +8 -4
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/sub.js +8 -1
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/io.d.ts +12 -6
- package/dist/gs/io/io.js +87 -42
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +31 -5
- package/dist/gs/math/bits/index.js +29 -28
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/mime/index.d.ts +16 -0
- package/dist/gs/mime/index.js +315 -6
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.d.ts +12 -0
- package/dist/gs/net/http/httptest/index.js +85 -6
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +303 -6
- package/dist/gs/net/http/index.js +1615 -58
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/dir_unix.gs.js +1 -1
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/error.gs.js +1 -1
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.d.ts +1 -0
- package/dist/gs/os/exec.gs.js +4 -8
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.js +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/index.d.ts +1 -1
- package/dist/gs/os/index.js +1 -1
- package/dist/gs/os/index.js.map +1 -1
- package/dist/gs/os/proc.gs.d.ts +4 -0
- package/dist/gs/os/proc.gs.js +12 -6
- package/dist/gs/os/proc.gs.js.map +1 -1
- package/dist/gs/os/root_js.gs.js +1 -1
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/types.gs.js +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +6 -2
- package/dist/gs/os/types_js.gs.js +170 -9
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/path/path.js +11 -7
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +5 -4
- package/dist/gs/reflect/index.js +4 -3
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js +15 -0
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +26 -6
- package/dist/gs/reflect/type.js +1498 -279
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +14 -6
- package/dist/gs/reflect/types.js +35 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.d.ts +1 -0
- package/dist/gs/reflect/value.js +83 -41
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +4 -140
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/pprof/index.d.ts +8 -2
- package/dist/gs/runtime/pprof/index.js +50 -30
- package/dist/gs/runtime/pprof/index.js.map +1 -1
- package/dist/gs/runtime/runtime.js +5 -4
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/runtime/trace/index.js +5 -19
- package/dist/gs/runtime/trace/index.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.js +1 -1
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/complex.gs.d.ts +3 -0
- package/dist/gs/strconv/complex.gs.js +148 -0
- package/dist/gs/strconv/complex.gs.js.map +1 -0
- package/dist/gs/strconv/index.d.ts +1 -0
- package/dist/gs/strconv/index.js +1 -0
- package/dist/gs/strconv/index.js.map +1 -1
- package/dist/gs/strings/builder.js +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +11 -7
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.js +15 -7
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/strings.d.ts +5 -0
- package/dist/gs/strings/strings.js +57 -5
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.js +9 -9
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/atomic/value.gs.js +2 -2
- package/dist/gs/sync/atomic/value.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +2 -1
- package/dist/gs/sync/sync.js +37 -16
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/env.js +22 -14
- package/dist/gs/syscall/env.js.map +1 -1
- package/dist/gs/syscall/js/index.js +9 -0
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/testing/testing.js +59 -15
- package/dist/gs/testing/testing.js.map +1 -1
- package/dist/gs/time/time.d.ts +24 -1
- package/dist/gs/time/time.js +43 -3
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unique/index.js +7 -1
- package/dist/gs/unique/index.js.map +1 -1
- package/go.mod +3 -3
- package/go.sum +16 -0
- package/gs/builtin/builtin.ts +25 -2
- package/gs/builtin/runtime-contract.test.ts +260 -18
- package/gs/builtin/slice.ts +51 -4
- package/gs/builtin/type.ts +310 -63
- package/gs/builtin/varRef.ts +85 -2
- package/gs/bytes/buffer.gs.ts +1 -1
- package/gs/bytes/reader.gs.ts +1 -1
- package/gs/compress/zlib/index.test.ts +159 -1
- package/gs/compress/zlib/index.ts +164 -37
- package/gs/compress/zlib/meta.json +4 -1
- package/gs/compress/zlib/parity.json +51 -0
- package/gs/crypto/sha1/index.test.ts +19 -2
- package/gs/crypto/sha1/index.ts +3 -6
- package/gs/crypto/sha256/index.test.ts +14 -2
- package/gs/crypto/sha256/index.ts +3 -6
- package/gs/crypto/sha512/index.test.ts +17 -2
- package/gs/crypto/sha512/index.ts +3 -6
- package/gs/embed/index.test.ts +87 -0
- package/gs/embed/index.ts +229 -5
- package/gs/encoding/json/index.test.ts +360 -6
- package/gs/encoding/json/index.ts +679 -38
- package/gs/encoding/json/parity.json +81 -0
- package/gs/fmt/fmt.test.ts +41 -3
- package/gs/fmt/fmt.ts +40 -17
- package/gs/fmt/meta.json +6 -1
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +211 -3
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +857 -1
- package/gs/github.com/go-git/go-billy/v6/osfs/index.test.ts +110 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/index.ts +280 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/meta.json +8 -0
- package/gs/github.com/pkg/errors/errors.ts +54 -30
- package/gs/go/scanner/index.test.ts +39 -56
- package/gs/go/scanner/index.ts +33 -5
- package/gs/go/scanner/parity.json +27 -0
- package/gs/go/token/index.ts +22 -6
- package/gs/hash/index.test.ts +20 -33
- package/gs/hash/index.ts +28 -0
- package/gs/hash/parity.json +21 -0
- package/gs/internal/goarch/index.test.ts +32 -0
- package/gs/internal/goarch/index.ts +45 -13
- package/gs/internal/goarch/parity.json +144 -0
- package/gs/io/fs/fs.ts +26 -14
- package/gs/io/fs/readdir.test.ts +38 -0
- package/gs/io/fs/readdir.ts +8 -4
- package/gs/io/fs/sub.ts +8 -1
- package/gs/io/io.test.ts +77 -6
- package/gs/io/io.ts +115 -52
- package/gs/io/meta.json +7 -1
- package/gs/io/parity.json +162 -0
- package/gs/math/bits/index.test.ts +14 -1
- package/gs/math/bits/index.ts +75 -32
- package/gs/math/bits/parity.json +156 -0
- package/gs/mime/index.test.ts +90 -0
- package/gs/mime/index.ts +369 -6
- package/gs/mime/parity.json +36 -0
- package/gs/net/http/httptest/index.test.ts +98 -2
- package/gs/net/http/httptest/index.ts +101 -6
- package/gs/net/http/httptest/parity.json +15 -0
- package/gs/net/http/index.test.ts +797 -12
- package/gs/net/http/index.ts +1874 -136
- package/gs/net/http/meta.json +16 -1
- package/gs/net/http/parity.json +193 -0
- package/gs/os/dir_unix.gs.ts +1 -1
- package/gs/os/error.gs.ts +1 -1
- package/gs/os/exec.gs.ts +4 -8
- package/gs/os/exec_posix.gs.ts +1 -1
- package/gs/os/file_unix_js.test.ts +52 -0
- package/gs/os/index.test.ts +9 -0
- package/gs/os/index.ts +1 -0
- package/gs/os/meta.json +4 -0
- package/gs/os/parity.json +9 -0
- package/gs/os/proc.gs.ts +18 -5
- package/gs/os/proc.test.ts +26 -0
- package/gs/os/readdir.test.ts +56 -0
- package/gs/os/root_js.gs.ts +1 -1
- package/gs/os/types.gs.ts +1 -1
- package/gs/os/types_js.gs.ts +170 -9
- package/gs/os/types_unix.gs.ts +1 -1
- package/gs/path/path.ts +11 -7
- package/gs/reflect/deepequal.test.ts +10 -1
- package/gs/reflect/field.test.ts +37 -15
- package/gs/reflect/function-types.test.ts +518 -22
- package/gs/reflect/index.ts +8 -6
- package/gs/reflect/map.ts +20 -0
- package/gs/reflect/meta.json +6 -4
- package/gs/reflect/parity.json +234 -0
- package/gs/reflect/sliceat.test.ts +156 -0
- package/gs/reflect/structof.test.ts +401 -0
- package/gs/reflect/type.ts +1980 -365
- package/gs/reflect/typefor.test.ts +540 -10
- package/gs/reflect/types.ts +43 -18
- package/gs/reflect/value.ts +105 -45
- package/gs/reflect/visiblefields.ts +5 -168
- package/gs/runtime/parity.json +24 -0
- package/gs/runtime/pprof/index.test.ts +29 -7
- package/gs/runtime/pprof/index.ts +56 -30
- package/gs/runtime/pprof/parity.json +27 -0
- package/gs/runtime/runtime.test.ts +3 -1
- package/gs/runtime/runtime.ts +4 -3
- package/gs/runtime/trace/index.test.ts +5 -3
- package/gs/runtime/trace/index.ts +8 -20
- package/gs/runtime/trace/parity.json +36 -0
- package/gs/strconv/atoi.gs.ts +1 -1
- package/gs/strconv/complex.gs.ts +174 -0
- package/gs/strconv/complex.test.ts +65 -0
- package/gs/strconv/index.ts +1 -0
- package/gs/strconv/parity.json +120 -0
- package/gs/strings/builder.ts +1 -1
- package/gs/strings/meta.json +5 -2
- package/gs/strings/parity.json +186 -0
- package/gs/strings/reader.test.ts +2 -2
- package/gs/strings/reader.ts +11 -7
- package/gs/strings/replace.ts +15 -7
- package/gs/strings/strings.test.ts +22 -2
- package/gs/strings/strings.ts +64 -6
- package/gs/sync/atomic/type.gs.ts +9 -9
- package/gs/sync/atomic/value.gs.ts +2 -2
- package/gs/sync/meta.json +1 -0
- package/gs/sync/sync.test.ts +41 -1
- package/gs/sync/sync.ts +41 -16
- package/gs/syscall/env.ts +29 -14
- package/gs/syscall/js/index.test.ts +18 -0
- package/gs/syscall/js/index.ts +12 -0
- package/gs/testing/testing.test.ts +99 -3
- package/gs/testing/testing.ts +95 -24
- package/gs/time/parity.json +225 -0
- package/gs/time/time.test.ts +20 -2
- package/gs/time/time.ts +49 -7
- package/gs/unique/index.ts +7 -1
- package/package.json +4 -2
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -814
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -31
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1233
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
- /package/compiler/{wasm_api.go → wasm-api.go} +0 -0
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
package compiler
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"go/ast"
|
|
6
|
+
"go/types"
|
|
7
|
+
"path"
|
|
8
|
+
"regexp"
|
|
9
|
+
"slices"
|
|
10
|
+
"strings"
|
|
11
|
+
|
|
12
|
+
"github.com/pkg/errors"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
var (
|
|
16
|
+
overrideExportDeclarationPattern = regexp.MustCompile(`(?m)^\s*export\s+(?:async\s+)?(const|let|var|function|class|interface|type|enum)\s+([A-Za-z_$][A-Za-z0-9_$]*)`)
|
|
17
|
+
overrideLocalDeclarationPattern = regexp.MustCompile(`(?m)^\s*(?:export\s+)?(?:async\s+)?(const|let|var|function|class|interface|type|enum)\s+([A-Za-z_$][A-Za-z0-9_$]*)`)
|
|
18
|
+
overrideImportNamedPattern = regexp.MustCompile(`(?s)import\s+(type\s+)?\{([^}]*)\}\s+from\s+['"][^'"]+['"]`)
|
|
19
|
+
overrideExportNamedPattern = regexp.MustCompile(`(?s)export\s+(type\s+)?\{([^}]*)\}\s*(?:from\s+['"]([^'"]+)['"])?`)
|
|
20
|
+
overrideExportAllPattern = regexp.MustCompile(`(?m)^\s*export\s+\*\s+from\s+['"]([^'"]+)['"]`)
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
type goPackageExport struct {
|
|
24
|
+
name string
|
|
25
|
+
requiresValue bool
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type typeScriptExport struct {
|
|
29
|
+
value bool
|
|
30
|
+
typ bool
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type namedTypeScriptExport struct {
|
|
34
|
+
source string
|
|
35
|
+
target string
|
|
36
|
+
typeOnly bool
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// OverrideParityVerifier owns compiler-side parity checks for ledgered overrides.
|
|
40
|
+
type OverrideParityVerifier struct{}
|
|
41
|
+
|
|
42
|
+
// NewOverrideParityVerifier creates the override parity verifier.
|
|
43
|
+
func NewOverrideParityVerifier() *OverrideParityVerifier {
|
|
44
|
+
return &OverrideParityVerifier{}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Verify checks ledgered override packages against JS/WASM Go exports and
|
|
48
|
+
// effective TypeScript package exports.
|
|
49
|
+
func (v *OverrideParityVerifier) Verify(
|
|
50
|
+
ctx context.Context,
|
|
51
|
+
graph *PackageGraph,
|
|
52
|
+
facts *OverrideFacts,
|
|
53
|
+
) []Diagnostic {
|
|
54
|
+
if err := ctx.Err(); err != nil {
|
|
55
|
+
return []Diagnostic{contextCanceledDiagnostic(err)}
|
|
56
|
+
}
|
|
57
|
+
if graph == nil || facts == nil {
|
|
58
|
+
return nil
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
var diagnostics []Diagnostic
|
|
62
|
+
for _, node := range graph.Nodes {
|
|
63
|
+
if err := ctx.Err(); err != nil {
|
|
64
|
+
return append(diagnostics, contextCanceledDiagnostic(err))
|
|
65
|
+
}
|
|
66
|
+
if node == nil || !node.OverrideCandidate {
|
|
67
|
+
continue
|
|
68
|
+
}
|
|
69
|
+
ledger := facts.parityLedger(node.PkgPath)
|
|
70
|
+
if !ledger.Strict && len(ledger.Symbols) == 0 {
|
|
71
|
+
continue
|
|
72
|
+
}
|
|
73
|
+
pkg := graph.packagesByPath[node.PkgPath]
|
|
74
|
+
if pkg == nil || pkg.Types == nil {
|
|
75
|
+
diagnostics = append(diagnostics, Diagnostic{
|
|
76
|
+
Severity: DiagnosticSeverityError,
|
|
77
|
+
Code: "goscript/overrides:parity-no-package",
|
|
78
|
+
Message: "override parity verification requires typed Go package facts",
|
|
79
|
+
Detail: node.PkgPath,
|
|
80
|
+
})
|
|
81
|
+
continue
|
|
82
|
+
}
|
|
83
|
+
exports, err := facts.effectiveTypeScriptExports(node.PkgPath)
|
|
84
|
+
if err != nil {
|
|
85
|
+
diagnostics = append(diagnostics, Diagnostic{
|
|
86
|
+
Severity: DiagnosticSeverityError,
|
|
87
|
+
Code: "goscript/overrides:parity-export-scan",
|
|
88
|
+
Message: "override parity verification failed to scan TypeScript exports",
|
|
89
|
+
Detail: node.PkgPath + ": " + err.Error(),
|
|
90
|
+
})
|
|
91
|
+
continue
|
|
92
|
+
}
|
|
93
|
+
diagnostics = append(diagnostics, verifyOverrideParityPackage(node.PkgPath, pkg.Types, ledger, exports)...)
|
|
94
|
+
}
|
|
95
|
+
diagnostics = append(diagnostics, verifyBlockedOverrideUses(graph, facts)...)
|
|
96
|
+
return diagnostics
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// VerifyNoDeferred reports transient parity entries that remain in packages
|
|
100
|
+
// whose parity surface is expected to be closed.
|
|
101
|
+
func (v *OverrideParityVerifier) VerifyNoDeferred(facts *OverrideFacts, pkgPaths ...string) []Diagnostic {
|
|
102
|
+
if facts == nil {
|
|
103
|
+
return nil
|
|
104
|
+
}
|
|
105
|
+
var diagnostics []Diagnostic
|
|
106
|
+
for _, pkgPath := range pkgPaths {
|
|
107
|
+
ledger := facts.parityLedger(pkgPath)
|
|
108
|
+
symbols := make([]string, 0, len(ledger.Symbols))
|
|
109
|
+
for symbol := range ledger.Symbols {
|
|
110
|
+
symbols = append(symbols, symbol)
|
|
111
|
+
}
|
|
112
|
+
slices.Sort(symbols)
|
|
113
|
+
for _, symbol := range symbols {
|
|
114
|
+
entry := ledger.Symbols[symbol]
|
|
115
|
+
if entry.Status != overrideParityStatusDeferred {
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
diagnostics = append(diagnostics, Diagnostic{
|
|
119
|
+
Severity: DiagnosticSeverityError,
|
|
120
|
+
Code: "goscript/overrides:parity-deferred",
|
|
121
|
+
Message: "override parity ledger still contains a transient deferred symbol",
|
|
122
|
+
Detail: pkgPath + "." + symbol,
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return diagnostics
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
func verifyOverrideParityPackage(
|
|
130
|
+
pkgPath string,
|
|
131
|
+
goPkg *types.Package,
|
|
132
|
+
ledger overrideParityLedger,
|
|
133
|
+
tsExports map[string]typeScriptExport,
|
|
134
|
+
) []Diagnostic {
|
|
135
|
+
goExports := exportedPackageSymbols(goPkg)
|
|
136
|
+
goExportSet := make(map[string]bool, len(goExports))
|
|
137
|
+
var diagnostics []Diagnostic
|
|
138
|
+
for _, symbol := range goExports {
|
|
139
|
+
goExportSet[symbol.name] = true
|
|
140
|
+
entry, ok := ledger.Symbols[symbol.name]
|
|
141
|
+
if ledger.Strict && !ok {
|
|
142
|
+
diagnostics = append(diagnostics, Diagnostic{
|
|
143
|
+
Severity: DiagnosticSeverityError,
|
|
144
|
+
Code: "goscript/overrides:parity-unclassified",
|
|
145
|
+
Message: "Go export is missing from override parity ledger",
|
|
146
|
+
Detail: pkgPath + "." + symbol.name,
|
|
147
|
+
})
|
|
148
|
+
continue
|
|
149
|
+
}
|
|
150
|
+
if !ok {
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
153
|
+
if entry.Status.requiresExport() && !symbol.satisfiedBy(tsExports[symbol.name]) {
|
|
154
|
+
diagnostics = append(diagnostics, Diagnostic{
|
|
155
|
+
Severity: DiagnosticSeverityError,
|
|
156
|
+
Code: "goscript/overrides:parity-missing-export",
|
|
157
|
+
Message: "override parity ledger requires a TypeScript export that is missing",
|
|
158
|
+
Detail: pkgPath + "." + symbol.name + " is classified as " + string(entry.Status),
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
if entry.Status.forbidsExport() && tsExports[symbol.name].present() {
|
|
162
|
+
diagnostics = append(diagnostics, Diagnostic{
|
|
163
|
+
Severity: DiagnosticSeverityError,
|
|
164
|
+
Code: "goscript/overrides:parity-unexpected-export",
|
|
165
|
+
Message: "override parity ledger marks a Go export blocked, but TypeScript exports it",
|
|
166
|
+
Detail: pkgPath + "." + symbol.name + " is classified as " + string(entry.Status),
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
for symbol := range ledger.Symbols {
|
|
171
|
+
if !goExportSet[symbol] {
|
|
172
|
+
diagnostics = append(diagnostics, Diagnostic{
|
|
173
|
+
Severity: DiagnosticSeverityError,
|
|
174
|
+
Code: "goscript/overrides:parity-unknown-symbol",
|
|
175
|
+
Message: "override parity ledger references a symbol not exported by the Go package",
|
|
176
|
+
Detail: pkgPath + "." + symbol,
|
|
177
|
+
})
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return diagnostics
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
func (symbol goPackageExport) satisfiedBy(export typeScriptExport) bool {
|
|
184
|
+
if symbol.requiresValue {
|
|
185
|
+
return export.value
|
|
186
|
+
}
|
|
187
|
+
return export.typ
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
func (export typeScriptExport) present() bool {
|
|
191
|
+
return export.value || export.typ
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
func exportedPackageSymbols(goPkg *types.Package) []goPackageExport {
|
|
195
|
+
if goPkg == nil || goPkg.Scope() == nil {
|
|
196
|
+
return nil
|
|
197
|
+
}
|
|
198
|
+
names := goPkg.Scope().Names()
|
|
199
|
+
symbols := make([]goPackageExport, 0, len(names))
|
|
200
|
+
for _, name := range names {
|
|
201
|
+
if !ast.IsExported(name) {
|
|
202
|
+
continue
|
|
203
|
+
}
|
|
204
|
+
obj := goPkg.Scope().Lookup(name)
|
|
205
|
+
typeName, isTypeName := obj.(*types.TypeName)
|
|
206
|
+
symbols = append(symbols, goPackageExport{
|
|
207
|
+
name: name,
|
|
208
|
+
requiresValue: !isTypeName || typeNameRequiresValue(typeName),
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
slices.SortFunc(symbols, func(a, b goPackageExport) int {
|
|
212
|
+
return strings.Compare(a.name, b.name)
|
|
213
|
+
})
|
|
214
|
+
return symbols
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
func typeNameRequiresValue(typeName *types.TypeName) bool {
|
|
218
|
+
if typeName == nil || typeName.Type() == nil {
|
|
219
|
+
return false
|
|
220
|
+
}
|
|
221
|
+
_, ok := types.Unalias(typeName.Type()).Underlying().(*types.Struct)
|
|
222
|
+
return ok
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
func verifyBlockedOverrideUses(graph *PackageGraph, facts *OverrideFacts) []Diagnostic {
|
|
226
|
+
if graph == nil || facts == nil {
|
|
227
|
+
return nil
|
|
228
|
+
}
|
|
229
|
+
seen := make(map[string]bool)
|
|
230
|
+
var diagnostics []Diagnostic
|
|
231
|
+
for _, node := range graph.Nodes {
|
|
232
|
+
if node == nil || node.OverrideCandidate {
|
|
233
|
+
continue
|
|
234
|
+
}
|
|
235
|
+
pkg := graph.packagesByPath[node.PkgPath]
|
|
236
|
+
if pkg == nil || pkg.TypesInfo == nil {
|
|
237
|
+
continue
|
|
238
|
+
}
|
|
239
|
+
sourcePkgPath := packagePath(pkg)
|
|
240
|
+
for ident, obj := range pkg.TypesInfo.Uses {
|
|
241
|
+
if ident == nil || obj == nil || obj.Pkg() == nil {
|
|
242
|
+
continue
|
|
243
|
+
}
|
|
244
|
+
if sourcePkgPath == obj.Pkg().Path() {
|
|
245
|
+
continue
|
|
246
|
+
}
|
|
247
|
+
ledger := facts.parityLedger(obj.Pkg().Path())
|
|
248
|
+
entry, ok := ledger.Symbols[obj.Name()]
|
|
249
|
+
if !ok || entry.Status != overrideParityStatusBlocked {
|
|
250
|
+
continue
|
|
251
|
+
}
|
|
252
|
+
key := sourcePkgPath + "->" + obj.Pkg().Path() + "." + obj.Name()
|
|
253
|
+
if seen[key] {
|
|
254
|
+
continue
|
|
255
|
+
}
|
|
256
|
+
seen[key] = true
|
|
257
|
+
diagnostics = append(diagnostics, Diagnostic{
|
|
258
|
+
Severity: DiagnosticSeverityError,
|
|
259
|
+
Code: "goscript/overrides:parity-blocked-use",
|
|
260
|
+
Message: "Go code uses an override symbol classified as blocked",
|
|
261
|
+
Detail: obj.Pkg().Path() + "." + obj.Name() + ": " + entry.Reason,
|
|
262
|
+
})
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return diagnostics
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
func (f *OverrideFacts) effectiveTypeScriptExports(pkgPath string) (map[string]typeScriptExport, error) {
|
|
269
|
+
pkg, _, ok := f.copyPackage(pkgPath)
|
|
270
|
+
if !ok {
|
|
271
|
+
return nil, errors.Errorf("override package %q is missing", pkgPath)
|
|
272
|
+
}
|
|
273
|
+
files := make(map[string]string, len(pkg.files))
|
|
274
|
+
for _, file := range pkg.files {
|
|
275
|
+
files[path.Clean(file.path)] = string(file.data)
|
|
276
|
+
}
|
|
277
|
+
exports := make(map[string]typeScriptExport)
|
|
278
|
+
visited := make(map[string]bool)
|
|
279
|
+
if err := collectTypeScriptExports(path.Join(pkgPath, "index.ts"), files, exports, visited); err != nil {
|
|
280
|
+
return nil, err
|
|
281
|
+
}
|
|
282
|
+
return exports, nil
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
func collectTypeScriptExports(
|
|
286
|
+
filePath string,
|
|
287
|
+
files map[string]string,
|
|
288
|
+
exports map[string]typeScriptExport,
|
|
289
|
+
visited map[string]bool,
|
|
290
|
+
) error {
|
|
291
|
+
filePath = path.Clean(filePath)
|
|
292
|
+
if visited[filePath] {
|
|
293
|
+
return nil
|
|
294
|
+
}
|
|
295
|
+
visited[filePath] = true
|
|
296
|
+
data, ok := files[filePath]
|
|
297
|
+
if !ok {
|
|
298
|
+
return errors.Errorf("missing %s", filePath)
|
|
299
|
+
}
|
|
300
|
+
localBindings := localTypeScriptBindings(data)
|
|
301
|
+
for _, match := range overrideExportDeclarationPattern.FindAllStringSubmatch(data, -1) {
|
|
302
|
+
addTypeScriptExport(exports, match[2], typeScriptExportForDeclaration(match[1]))
|
|
303
|
+
}
|
|
304
|
+
for _, match := range overrideExportNamedPattern.FindAllStringSubmatch(data, -1) {
|
|
305
|
+
namedExports := parseNamedTypeScriptExports(match[2], match[1] != "")
|
|
306
|
+
if match[3] == "" {
|
|
307
|
+
if err := addLocalNamedTypeScriptExports(filePath, exports, localBindings, namedExports); err != nil {
|
|
308
|
+
return err
|
|
309
|
+
}
|
|
310
|
+
continue
|
|
311
|
+
}
|
|
312
|
+
target, ok := resolveOverrideExportPath(filePath, match[3])
|
|
313
|
+
if !ok {
|
|
314
|
+
continue
|
|
315
|
+
}
|
|
316
|
+
targetExports := make(map[string]typeScriptExport)
|
|
317
|
+
if err := collectTypeScriptExports(target, files, targetExports, make(map[string]bool)); err != nil {
|
|
318
|
+
return err
|
|
319
|
+
}
|
|
320
|
+
for _, namedExport := range namedExports {
|
|
321
|
+
sourceExport := targetExports[namedExport.source]
|
|
322
|
+
if !sourceExport.present() {
|
|
323
|
+
return errors.Errorf("%s re-exports missing symbol %s from %s", filePath, namedExport.source, target)
|
|
324
|
+
}
|
|
325
|
+
exportShape := sourceExport
|
|
326
|
+
if namedExport.typeOnly {
|
|
327
|
+
if !sourceExport.typ {
|
|
328
|
+
return errors.Errorf("%s re-exports missing type symbol %s from %s", filePath, namedExport.source, target)
|
|
329
|
+
}
|
|
330
|
+
exportShape = typeScriptExport{typ: true}
|
|
331
|
+
} else if !sourceExport.value {
|
|
332
|
+
return errors.Errorf("%s re-exports missing value symbol %s from %s", filePath, namedExport.source, target)
|
|
333
|
+
}
|
|
334
|
+
addTypeScriptExport(exports, namedExport.target, exportShape)
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
for _, match := range overrideExportAllPattern.FindAllStringSubmatch(data, -1) {
|
|
338
|
+
target, ok := resolveOverrideExportPath(filePath, match[1])
|
|
339
|
+
if ok {
|
|
340
|
+
if err := collectTypeScriptExports(target, files, exports, visited); err != nil {
|
|
341
|
+
return err
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return nil
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
func typeScriptExportForDeclaration(kind string) typeScriptExport {
|
|
349
|
+
switch kind {
|
|
350
|
+
case "const", "let", "var", "function":
|
|
351
|
+
return typeScriptExport{value: true}
|
|
352
|
+
case "class", "enum":
|
|
353
|
+
return typeScriptExport{value: true, typ: true}
|
|
354
|
+
case "interface", "type":
|
|
355
|
+
return typeScriptExport{typ: true}
|
|
356
|
+
default:
|
|
357
|
+
return typeScriptExport{}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
func addTypeScriptExport(exports map[string]typeScriptExport, name string, export typeScriptExport) {
|
|
362
|
+
if name == "" {
|
|
363
|
+
return
|
|
364
|
+
}
|
|
365
|
+
current := exports[name]
|
|
366
|
+
current.value = current.value || export.value
|
|
367
|
+
current.typ = current.typ || export.typ
|
|
368
|
+
exports[name] = current
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
func localTypeScriptBindings(data string) map[string]typeScriptExport {
|
|
372
|
+
bindings := make(map[string]typeScriptExport)
|
|
373
|
+
for _, match := range overrideLocalDeclarationPattern.FindAllStringSubmatch(data, -1) {
|
|
374
|
+
addTypeScriptExport(bindings, match[2], typeScriptExportForDeclaration(match[1]))
|
|
375
|
+
}
|
|
376
|
+
for _, match := range overrideImportNamedPattern.FindAllStringSubmatch(data, -1) {
|
|
377
|
+
for _, namedImport := range parseNamedTypeScriptExports(match[2], match[1] != "") {
|
|
378
|
+
exportShape := typeScriptExport{value: true, typ: true}
|
|
379
|
+
if namedImport.typeOnly {
|
|
380
|
+
exportShape = typeScriptExport{typ: true}
|
|
381
|
+
}
|
|
382
|
+
addTypeScriptExport(bindings, namedImport.target, exportShape)
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return bindings
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
func addLocalNamedTypeScriptExports(
|
|
389
|
+
filePath string,
|
|
390
|
+
exports map[string]typeScriptExport,
|
|
391
|
+
localBindings map[string]typeScriptExport,
|
|
392
|
+
namedExports []namedTypeScriptExport,
|
|
393
|
+
) error {
|
|
394
|
+
for _, namedExport := range namedExports {
|
|
395
|
+
exportShape := localBindings[namedExport.source]
|
|
396
|
+
if namedExport.typeOnly {
|
|
397
|
+
if !exportShape.typ {
|
|
398
|
+
return errors.Errorf("%s exports missing local type symbol %s", filePath, namedExport.source)
|
|
399
|
+
}
|
|
400
|
+
exportShape = typeScriptExport{typ: true}
|
|
401
|
+
} else if !exportShape.value {
|
|
402
|
+
return errors.Errorf("%s exports missing local value symbol %s", filePath, namedExport.source)
|
|
403
|
+
}
|
|
404
|
+
addTypeScriptExport(exports, namedExport.target, exportShape)
|
|
405
|
+
}
|
|
406
|
+
return nil
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
func parseNamedTypeScriptExports(list string, statementTypeOnly bool) []namedTypeScriptExport {
|
|
410
|
+
var exports []namedTypeScriptExport
|
|
411
|
+
for item := range strings.SplitSeq(list, ",") {
|
|
412
|
+
item = strings.TrimSpace(item)
|
|
413
|
+
if item == "" {
|
|
414
|
+
continue
|
|
415
|
+
}
|
|
416
|
+
typeOnly := statementTypeOnly
|
|
417
|
+
if strings.HasPrefix(item, "type ") {
|
|
418
|
+
typeOnly = true
|
|
419
|
+
item = strings.TrimSpace(strings.TrimPrefix(item, "type "))
|
|
420
|
+
}
|
|
421
|
+
parts := strings.Fields(item)
|
|
422
|
+
if len(parts) == 0 {
|
|
423
|
+
continue
|
|
424
|
+
}
|
|
425
|
+
namedExport := namedTypeScriptExport{
|
|
426
|
+
source: parts[0],
|
|
427
|
+
target: parts[0],
|
|
428
|
+
typeOnly: typeOnly,
|
|
429
|
+
}
|
|
430
|
+
if len(parts) >= 3 && parts[len(parts)-2] == "as" {
|
|
431
|
+
namedExport.target = parts[len(parts)-1]
|
|
432
|
+
}
|
|
433
|
+
exports = append(exports, namedExport)
|
|
434
|
+
}
|
|
435
|
+
return exports
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
func resolveOverrideExportPath(currentFile, spec string) (string, bool) {
|
|
439
|
+
if !strings.HasPrefix(spec, ".") {
|
|
440
|
+
return "", false
|
|
441
|
+
}
|
|
442
|
+
target := path.Clean(path.Join(path.Dir(currentFile), spec))
|
|
443
|
+
switch path.Ext(target) {
|
|
444
|
+
case ".js", ".ts":
|
|
445
|
+
target = strings.TrimSuffix(target, path.Ext(target)) + ".ts"
|
|
446
|
+
case "":
|
|
447
|
+
target = path.Join(target, "index.ts")
|
|
448
|
+
}
|
|
449
|
+
return target, true
|
|
450
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
package compiler
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"io"
|
|
5
|
+
"io/fs"
|
|
6
|
+
"maps"
|
|
7
|
+
"path"
|
|
8
|
+
"strings"
|
|
9
|
+
|
|
10
|
+
jsoniter "github.com/aperturerobotics/json-iterator-lite"
|
|
11
|
+
"github.com/pkg/errors"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
type overrideParityStatus string
|
|
15
|
+
|
|
16
|
+
const (
|
|
17
|
+
overrideParityStatusReal overrideParityStatus = "real"
|
|
18
|
+
overrideParityStatusBlocked overrideParityStatus = "blocked"
|
|
19
|
+
overrideParityStatusDeferred overrideParityStatus = "deferred"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
type overrideParityLedger struct {
|
|
23
|
+
SchemaVersion int `json:"schemaVersion"`
|
|
24
|
+
Strict bool `json:"strict"`
|
|
25
|
+
Symbols map[string]overrideParityEntry `json:"symbols"`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type overrideParityEntry struct {
|
|
29
|
+
Status overrideParityStatus `json:"status"`
|
|
30
|
+
Reason string `json:"reason,omitempty"`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
func newOverrideParityLedger() overrideParityLedger {
|
|
34
|
+
return overrideParityLedger{
|
|
35
|
+
Symbols: make(map[string]overrideParityEntry),
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
func loadOverrideParityLedger(root overridePackageRoot) (overrideParityLedger, error) {
|
|
40
|
+
ledger := newOverrideParityLedger()
|
|
41
|
+
data, err := fs.ReadFile(root.fsys, path.Join(root.dir, "parity.json"))
|
|
42
|
+
if err != nil {
|
|
43
|
+
if errors.Is(err, fs.ErrNotExist) {
|
|
44
|
+
return ledger, nil
|
|
45
|
+
}
|
|
46
|
+
return overrideParityLedger{}, err
|
|
47
|
+
}
|
|
48
|
+
iter := jsoniter.ParseBytes(data)
|
|
49
|
+
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
|
|
50
|
+
switch field {
|
|
51
|
+
case "schemaVersion":
|
|
52
|
+
ledger.SchemaVersion = iter.ReadInt()
|
|
53
|
+
case "strict":
|
|
54
|
+
ledger.Strict = iter.ReadBool()
|
|
55
|
+
case "symbols":
|
|
56
|
+
for symbol := iter.ReadObject(); symbol != ""; symbol = iter.ReadObject() {
|
|
57
|
+
entry := overrideParityEntry{}
|
|
58
|
+
for entryField := iter.ReadObject(); entryField != ""; entryField = iter.ReadObject() {
|
|
59
|
+
switch entryField {
|
|
60
|
+
case "status":
|
|
61
|
+
entry.Status = overrideParityStatus(iter.ReadString())
|
|
62
|
+
case "reason":
|
|
63
|
+
entry.Reason = iter.ReadString()
|
|
64
|
+
default:
|
|
65
|
+
iter.Skip()
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
ledger.Symbols[symbol] = entry
|
|
69
|
+
}
|
|
70
|
+
default:
|
|
71
|
+
iter.Skip()
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if iter.Error != nil && !errors.Is(iter.Error, io.EOF) {
|
|
75
|
+
return overrideParityLedger{}, iter.Error
|
|
76
|
+
}
|
|
77
|
+
if ledger.SchemaVersion != 1 {
|
|
78
|
+
return overrideParityLedger{}, errors.New("parity.json schemaVersion must be 1")
|
|
79
|
+
}
|
|
80
|
+
if ledger.Symbols == nil {
|
|
81
|
+
ledger.Symbols = make(map[string]overrideParityEntry)
|
|
82
|
+
}
|
|
83
|
+
for symbol, entry := range ledger.Symbols {
|
|
84
|
+
if symbol == "" {
|
|
85
|
+
return overrideParityLedger{}, errors.New("parity.json symbol names must not be empty")
|
|
86
|
+
}
|
|
87
|
+
if !entry.Status.valid() {
|
|
88
|
+
return overrideParityLedger{}, errors.New("parity.json contains an unknown status")
|
|
89
|
+
}
|
|
90
|
+
if entry.Status == overrideParityStatusBlocked && strings.TrimSpace(entry.Reason) == "" {
|
|
91
|
+
return overrideParityLedger{}, errors.New("parity.json blocked symbols must include a reason")
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return ledger, nil
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
func (s overrideParityStatus) valid() bool {
|
|
98
|
+
switch s {
|
|
99
|
+
case overrideParityStatusReal,
|
|
100
|
+
overrideParityStatusBlocked,
|
|
101
|
+
overrideParityStatusDeferred:
|
|
102
|
+
return true
|
|
103
|
+
default:
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
func (s overrideParityStatus) requiresExport() bool {
|
|
109
|
+
return s == overrideParityStatusReal
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
func (s overrideParityStatus) forbidsExport() bool {
|
|
113
|
+
return s == overrideParityStatusBlocked
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
func cloneOverrideParityLedger(ledger overrideParityLedger) overrideParityLedger {
|
|
117
|
+
return overrideParityLedger{
|
|
118
|
+
SchemaVersion: ledger.SchemaVersion,
|
|
119
|
+
Strict: ledger.Strict,
|
|
120
|
+
Symbols: maps.Clone(ledger.Symbols),
|
|
121
|
+
}
|
|
122
|
+
}
|