goscript 0.2.3 → 0.2.5
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 +8 -8
- package/cmd/go_js_wasm_exec/main.go +1 -1
- package/cmd/go_js_wasm_exec/main_test.go +1 -1
- package/cmd/goscript/cmd-compile.go +9 -1
- package/cmd/goscript/cmd-test.go +1 -1
- package/cmd/goscript/cmd_compile_test.go +44 -0
- package/cmd/goscript/deps.go +1 -1
- package/cmd/goscript-wasm/main.go +2 -2
- package/compiler/compile-request.go +19 -0
- package/compiler/compile_bench_test.go +121 -0
- package/compiler/compliance_test.go +17 -1
- package/compiler/config.go +2 -0
- package/compiler/gotest/result.go +1 -1
- package/compiler/gotest/runner.go +2 -2
- package/compiler/gotest/runner_test.go +4 -7
- package/compiler/index.test.ts +28 -0
- package/compiler/index.ts +32 -16
- package/compiler/lowering.go +1236 -143
- package/compiler/lowering_bench_test.go +4 -0
- package/compiler/override-facts.go +1 -1
- package/compiler/override-registry_test.go +125 -0
- package/compiler/package-graph.go +92 -0
- package/compiler/package-graph_test.go +113 -0
- package/compiler/runtime-contract.go +1 -1
- package/compiler/semantic-model.go +32 -0
- package/compiler/skeleton_test.go +284 -11
- package/compiler/wasm/compile.go +1 -1
- package/compiler/wasm/compile_test.go +1 -1
- package/dist/compiler/index.d.ts +4 -0
- package/dist/compiler/index.js +26 -15
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/compress/gzip/index.d.ts +41 -0
- package/dist/gs/compress/gzip/index.js +235 -0
- package/dist/gs/compress/gzip/index.js.map +1 -0
- package/dist/gs/database/sql/driver/index.d.ts +165 -0
- package/dist/gs/database/sql/driver/index.js +432 -0
- package/dist/gs/database/sql/driver/index.js.map +1 -0
- package/dist/gs/encoding/binary/index.d.ts +71 -0
- package/dist/gs/encoding/binary/index.js +778 -0
- package/dist/gs/encoding/binary/index.js.map +1 -0
- package/dist/gs/fmt/fmt.js +156 -57
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/klauspost/cpuid/v2/index.d.ts +11 -0
- package/dist/gs/github.com/klauspost/cpuid/v2/index.js +28 -0
- package/dist/gs/github.com/klauspost/cpuid/v2/index.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/errors.d.ts +0 -2
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/index.d.ts +2 -1
- package/dist/gs/github.com/pkg/errors/index.js +1 -1
- package/dist/gs/github.com/pkg/errors/index.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/stack.d.ts +8 -19
- package/dist/gs/github.com/pkg/errors/stack.js +26 -61
- package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
- package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.d.ts +19 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.js +25 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.js.map +1 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.d.ts +104 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1107 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -0
- package/dist/gs/golang.org/x/crypto/internal/alias/index.d.ts +3 -0
- package/dist/gs/golang.org/x/crypto/internal/alias/index.js +39 -0
- package/dist/gs/golang.org/x/crypto/internal/alias/index.js.map +1 -0
- package/dist/gs/io/fs/glob.js +1 -1
- package/dist/gs/io/fs/glob.js.map +1 -1
- package/dist/gs/io/fs/readlink.d.ts +1 -1
- package/dist/gs/io/fs/readlink.js +2 -2
- package/dist/gs/io/fs/readlink.js.map +1 -1
- package/dist/gs/io/fs/stat.d.ts +4 -2
- package/dist/gs/io/fs/stat.js +12 -73
- package/dist/gs/io/fs/stat.js.map +1 -1
- package/dist/gs/io/fs/sub.d.ts +2 -2
- package/dist/gs/io/fs/sub.js +7 -7
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/fs/walk.js +1 -1
- package/dist/gs/io/fs/walk.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +18 -14
- package/dist/gs/net/http/index.js +44 -23
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/net/http/pprof/index.d.ts +5 -5
- package/dist/gs/net/http/pprof/index.js +21 -21
- package/dist/gs/net/http/pprof/index.js.map +1 -1
- package/dist/gs/runtime/runtime.d.ts +6 -1
- package/dist/gs/runtime/runtime.js +15 -8
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/runtime/trace/index.d.ts +8 -5
- package/dist/gs/runtime/trace/index.js +324 -23
- package/dist/gs/runtime/trace/index.js.map +1 -1
- package/dist/gs/slices/slices.d.ts +2 -1
- package/dist/gs/slices/slices.js +9 -3
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/sort/search.gs.d.ts +3 -1
- package/dist/gs/sort/search.gs.js +18 -53
- package/dist/gs/sort/search.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +1 -1
- package/dist/gs/sync/sync.js +3 -0
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/time/time.d.ts +22 -29
- package/dist/gs/time/time.js +111 -32
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unsafe/unsafe.d.ts +3 -2
- package/dist/gs/unsafe/unsafe.js.map +1 -1
- package/go.mod +7 -5
- package/go.sum +12 -26
- package/gs/builtin/runtime-contract.test.ts +25 -0
- package/gs/compress/gzip/index.test.ts +86 -0
- package/gs/compress/gzip/index.ts +297 -0
- package/gs/compress/gzip/meta.json +6 -0
- package/gs/compress/gzip/parity.json +45 -0
- package/gs/database/sql/driver/index.test.ts +88 -0
- package/gs/database/sql/driver/index.ts +675 -0
- package/gs/database/sql/driver/meta.json +3 -0
- package/gs/database/sql/driver/parity.json +144 -0
- package/gs/embed/index.test.ts +1 -1
- package/gs/encoding/binary/index.test.ts +239 -0
- package/gs/encoding/binary/index.ts +999 -0
- package/gs/encoding/binary/meta.json +9 -0
- package/gs/encoding/binary/parity.json +72 -0
- package/gs/fmt/fmt.test.ts +28 -0
- package/gs/fmt/fmt.ts +198 -61
- package/gs/fmt/meta.json +2 -1
- package/gs/github.com/klauspost/cpuid/v2/index.ts +38 -0
- package/gs/github.com/klauspost/cpuid/v2/meta.json +3 -0
- package/gs/github.com/pkg/errors/errors.ts +1 -2
- package/gs/github.com/pkg/errors/index.ts +2 -1
- package/gs/github.com/pkg/errors/stack.ts +34 -62
- package/gs/golang.org/x/crypto/cryptobyte/asn1/index.test.ts +19 -0
- package/gs/golang.org/x/crypto/cryptobyte/asn1/index.ts +29 -0
- package/gs/golang.org/x/crypto/cryptobyte/index.test.ts +255 -0
- package/gs/golang.org/x/crypto/cryptobyte/index.ts +1441 -0
- package/gs/golang.org/x/crypto/cryptobyte/meta.json +3 -0
- package/gs/golang.org/x/crypto/internal/alias/index.test.ts +40 -0
- package/gs/golang.org/x/crypto/internal/alias/index.ts +40 -0
- package/gs/io/fs/glob.ts +1 -1
- package/gs/io/fs/meta.json +3 -0
- package/gs/io/fs/readlink.test.ts +2 -2
- package/gs/io/fs/readlink.ts +5 -2
- package/gs/io/fs/stat.test.ts +79 -0
- package/gs/io/fs/stat.ts +24 -10
- package/gs/io/fs/sub.test.ts +93 -0
- package/gs/io/fs/sub.ts +9 -9
- package/gs/io/fs/walk.ts +1 -1
- package/gs/net/http/index.test.ts +207 -2
- package/gs/net/http/index.ts +68 -37
- package/gs/net/http/meta.json +3 -1
- package/gs/net/http/pprof/index.test.ts +4 -4
- package/gs/net/http/pprof/index.ts +30 -27
- package/gs/runtime/runtime.test.ts +16 -0
- package/gs/runtime/runtime.ts +17 -9
- package/gs/runtime/trace/index.test.ts +113 -14
- package/gs/runtime/trace/index.ts +384 -34
- package/gs/runtime/trace/meta.json +1 -0
- package/gs/slices/slices.test.ts +24 -1
- package/gs/slices/slices.ts +14 -4
- package/gs/sort/meta.json +1 -0
- package/gs/sort/search.gs.ts +20 -5
- package/gs/sync/sync.ts +4 -1
- package/gs/time/time.test.ts +79 -2
- package/gs/time/time.ts +133 -33
- package/gs/unsafe/unsafe.ts +4 -2
- package/package.json +2 -2
package/compiler/lowering.go
CHANGED
|
@@ -76,6 +76,8 @@ func (o *LoweringOwner) Build(ctx context.Context, model *SemanticModel, opts ..
|
|
|
76
76
|
|
|
77
77
|
program := &LoweredProgram{}
|
|
78
78
|
lazyPackageVars := make(map[string]map[types.Object]bool, len(model.packages))
|
|
79
|
+
asyncLazyFunctionCache := make(map[*types.Func]bool)
|
|
80
|
+
asyncLazyFunctionVisiting := make(map[*types.Func]bool)
|
|
79
81
|
runtimeMethodSets := make(runtimeMethodSetCache)
|
|
80
82
|
semPkgs := make([]*semanticPackage, 0, len(model.packages))
|
|
81
83
|
for _, semPkg := range model.packages {
|
|
@@ -91,7 +93,15 @@ func (o *LoweringOwner) Build(ctx context.Context, model *SemanticModel, opts ..
|
|
|
91
93
|
diagnostics = append(diagnostics, loweringUnsupported("package", semPkg.pkgPath, "missing semantic source package"))
|
|
92
94
|
continue
|
|
93
95
|
}
|
|
94
|
-
loweredPkg, pkgDiagnostics := o.lowerPackage(
|
|
96
|
+
loweredPkg, pkgDiagnostics := o.lowerPackage(
|
|
97
|
+
model,
|
|
98
|
+
semPkg,
|
|
99
|
+
lazyPackageVars,
|
|
100
|
+
asyncLazyFunctionCache,
|
|
101
|
+
asyncLazyFunctionVisiting,
|
|
102
|
+
runtimeMethodSets,
|
|
103
|
+
options,
|
|
104
|
+
)
|
|
95
105
|
diagnostics = append(diagnostics, pkgDiagnostics...)
|
|
96
106
|
if loweredPkg != nil {
|
|
97
107
|
program.packages = append(program.packages, loweredPkg)
|
|
@@ -107,6 +117,8 @@ func (o *LoweringOwner) lowerPackage(
|
|
|
107
117
|
model *SemanticModel,
|
|
108
118
|
semPkg *semanticPackage,
|
|
109
119
|
lazyPackageVarsByPkg map[string]map[types.Object]bool,
|
|
120
|
+
asyncLazyFunctionCache map[*types.Func]bool,
|
|
121
|
+
asyncLazyFunctionVisiting map[*types.Func]bool,
|
|
110
122
|
runtimeMethodSets runtimeMethodSetCache,
|
|
111
123
|
options LoweringOptions,
|
|
112
124
|
) (*loweredPackage, []Diagnostic) {
|
|
@@ -143,6 +155,8 @@ func (o *LoweringOwner) lowerPackage(
|
|
|
143
155
|
outputNames,
|
|
144
156
|
lazyPackageVars,
|
|
145
157
|
lazyPackageVarsByPkg,
|
|
158
|
+
asyncLazyFunctionCache,
|
|
159
|
+
asyncLazyFunctionVisiting,
|
|
146
160
|
runtimeMethodSets,
|
|
147
161
|
protobufAdapter,
|
|
148
162
|
options.DisplayRoot,
|
|
@@ -163,6 +177,8 @@ func (o *LoweringOwner) lowerPackage(
|
|
|
163
177
|
outputNames,
|
|
164
178
|
lazyPackageVars,
|
|
165
179
|
lazyPackageVarsByPkg,
|
|
180
|
+
asyncLazyFunctionCache,
|
|
181
|
+
asyncLazyFunctionVisiting,
|
|
166
182
|
runtimeMethodSets,
|
|
167
183
|
false,
|
|
168
184
|
options.DisplayRoot,
|
|
@@ -199,6 +215,8 @@ func (o *LoweringOwner) lowerFile(
|
|
|
199
215
|
outputNames map[string]string,
|
|
200
216
|
lazyPackageVars map[types.Object]bool,
|
|
201
217
|
lazyPackageVarsByPkg map[string]map[types.Object]bool,
|
|
218
|
+
asyncLazyFunctionCache map[*types.Func]bool,
|
|
219
|
+
asyncLazyFunctionVisiting map[*types.Func]bool,
|
|
202
220
|
runtimeMethodSets runtimeMethodSetCache,
|
|
203
221
|
protobufTypeScriptAdapter bool,
|
|
204
222
|
displayRoot string,
|
|
@@ -308,21 +326,23 @@ func (o *LoweringOwner) lowerFile(
|
|
|
308
326
|
loweredFile.imports = append(loweredFile.imports, localImports...)
|
|
309
327
|
|
|
310
328
|
ctx := lowerFileContext{
|
|
311
|
-
model:
|
|
312
|
-
semPkg:
|
|
313
|
-
file:
|
|
314
|
-
importAliases:
|
|
315
|
-
importPaths:
|
|
316
|
-
importNames:
|
|
317
|
-
importObjects:
|
|
318
|
-
sourcePath:
|
|
319
|
-
localAliases:
|
|
320
|
-
lazyPackageVars:
|
|
321
|
-
lazyPackageVarsByPkg:
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
329
|
+
model: model,
|
|
330
|
+
semPkg: semPkg,
|
|
331
|
+
file: file,
|
|
332
|
+
importAliases: importAliases,
|
|
333
|
+
importPaths: importPaths,
|
|
334
|
+
importNames: importNames,
|
|
335
|
+
importObjects: importObjects,
|
|
336
|
+
sourcePath: sourcePath,
|
|
337
|
+
localAliases: localRefs.aliases,
|
|
338
|
+
lazyPackageVars: lazyPackageVars,
|
|
339
|
+
lazyPackageVarsByPkg: lazyPackageVarsByPkg,
|
|
340
|
+
asyncLazyFunctionCache: asyncLazyFunctionCache,
|
|
341
|
+
asyncLazyFunctionVisiting: asyncLazyFunctionVisiting,
|
|
342
|
+
tempNames: newTempNameOwner(),
|
|
343
|
+
topLevel: true,
|
|
344
|
+
protobufTSAdapter: protobufTypeScriptAdapter,
|
|
345
|
+
displayRoot: displayRoot,
|
|
326
346
|
}
|
|
327
347
|
var diagnostics []Diagnostic
|
|
328
348
|
var packageInitCalls []string
|
|
@@ -1067,7 +1087,7 @@ func safeIdentifier(value string) string {
|
|
|
1067
1087
|
switch identifier {
|
|
1068
1088
|
case "abstract", "any", "arguments", "as", "asserts", "async", "await", "boolean",
|
|
1069
1089
|
"break", "case", "catch", "class", "const", "constructor", "continue", "debugger",
|
|
1070
|
-
"declare", "default", "delete", "do", "else", "enum", "export", "extends", "false",
|
|
1090
|
+
"declare", "default", "delete", "do", "else", "enum", "eval", "export", "extends", "false",
|
|
1071
1091
|
"finally", "for", "from", "function", "get", "if", "implements", "import", "in",
|
|
1072
1092
|
"infer", "instanceof", "interface", "is", "keyof", "let", "module", "namespace",
|
|
1073
1093
|
"never", "new", "null", "number", "object", "of", "package", "private", "protected",
|
|
@@ -1095,40 +1115,42 @@ func safeParamName(param *types.Var, idx int) string {
|
|
|
1095
1115
|
}
|
|
1096
1116
|
|
|
1097
1117
|
type lowerFileContext struct {
|
|
1098
|
-
model
|
|
1099
|
-
semPkg
|
|
1100
|
-
file
|
|
1101
|
-
importAliases
|
|
1102
|
-
importPaths
|
|
1103
|
-
importNames
|
|
1104
|
-
importObjects
|
|
1105
|
-
sourcePath
|
|
1106
|
-
localAliases
|
|
1107
|
-
lazyPackageVars
|
|
1108
|
-
lazyPackageVarsByPkg
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1118
|
+
model *SemanticModel
|
|
1119
|
+
semPkg *semanticPackage
|
|
1120
|
+
file *ast.File
|
|
1121
|
+
importAliases map[string]string
|
|
1122
|
+
importPaths map[string]string
|
|
1123
|
+
importNames map[string]string
|
|
1124
|
+
importObjects map[*types.PkgName]string
|
|
1125
|
+
sourcePath string
|
|
1126
|
+
localAliases map[types.Object]string
|
|
1127
|
+
lazyPackageVars map[types.Object]bool
|
|
1128
|
+
lazyPackageVarsByPkg map[string]map[types.Object]bool
|
|
1129
|
+
asyncLazyFunctionCache map[*types.Func]bool
|
|
1130
|
+
asyncLazyFunctionVisiting map[*types.Func]bool
|
|
1131
|
+
identAliases map[types.Object]string
|
|
1132
|
+
identAliasRefs map[types.Object]bool
|
|
1133
|
+
tempNames *tempNameOwner
|
|
1134
|
+
signature *types.Signature
|
|
1135
|
+
typeParams map[string]bool
|
|
1136
|
+
staticTypeParams map[string]bool
|
|
1137
|
+
asyncFunction bool
|
|
1138
|
+
functionTypeDepth int
|
|
1139
|
+
deferState *loweredDeferState
|
|
1140
|
+
rangeBranch *loweredRangeBranch
|
|
1141
|
+
rangeBreak bool
|
|
1142
|
+
rangeContinue bool
|
|
1143
|
+
gotoLabels map[string]bool
|
|
1144
|
+
forwardGotos map[string]bool
|
|
1145
|
+
gotoStateLabels map[string]bool
|
|
1146
|
+
gotoStateVar string
|
|
1147
|
+
gotoStateLoop string
|
|
1148
|
+
functionScopedDecls bool
|
|
1149
|
+
loopLabel string
|
|
1150
|
+
switchBreak bool
|
|
1151
|
+
topLevel bool
|
|
1152
|
+
protobufTSAdapter bool
|
|
1153
|
+
displayRoot string
|
|
1132
1154
|
}
|
|
1133
1155
|
|
|
1134
1156
|
func (ctx lowerFileContext) diagnosticPosition(pos token.Pos) *DiagnosticPosition {
|
|
@@ -1349,7 +1371,12 @@ func (o *LoweringOwner) lowerGenDecl(ctx lowerFileContext, decl *ast.GenDecl) ([
|
|
|
1349
1371
|
"if (((" + declName + ") as any) === undefined) {\n\t\t" +
|
|
1350
1372
|
declName + " = " + value + "\n\t}\n}"
|
|
1351
1373
|
decls = append(decls, loweredDecl{code: initCode, indexExport: initIndexExport})
|
|
1352
|
-
|
|
1374
|
+
readDrivenInit := idx < len(typed.Values) &&
|
|
1375
|
+
asyncLazyInitializerReferencesCyclicOtherFile(ctx, typed.Values[idx]) &&
|
|
1376
|
+
!packageInitFunctionReferencesObject(ctx, obj)
|
|
1377
|
+
if !readDrivenInit {
|
|
1378
|
+
decls = append(decls, loweredDecl{packageInitCall: initName + "()"})
|
|
1379
|
+
}
|
|
1353
1380
|
getterCode += "if (((" + declName + ") as any) === undefined) {\n\t\t" +
|
|
1354
1381
|
"throw new Error(" + strconv.Quote("goscript package variable "+name.Name+" read before initialization") + ")\n\t}\n"
|
|
1355
1382
|
} else {
|
|
@@ -1409,21 +1436,33 @@ func (o *LoweringOwner) topLevelInitializerNeedsAwait(ctx lowerFileContext, expr
|
|
|
1409
1436
|
if ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
1410
1437
|
return false
|
|
1411
1438
|
}
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1439
|
+
needsAwait := false
|
|
1440
|
+
ast.Inspect(expr, func(node ast.Node) bool {
|
|
1441
|
+
if needsAwait {
|
|
1442
|
+
return false
|
|
1443
|
+
}
|
|
1444
|
+
if _, ok := node.(*ast.FuncLit); ok {
|
|
1445
|
+
return false
|
|
1446
|
+
}
|
|
1447
|
+
call, ok := node.(*ast.CallExpr)
|
|
1448
|
+
if !ok {
|
|
1449
|
+
return true
|
|
1450
|
+
}
|
|
1451
|
+
if o.callNeedsAwait(ctx, call.Fun) {
|
|
1452
|
+
needsAwait = true
|
|
1453
|
+
return false
|
|
1454
|
+
}
|
|
1455
|
+
if o.callUsesOverridePackage(ctx, call.Fun) {
|
|
1456
|
+
return true
|
|
1457
|
+
}
|
|
1458
|
+
fn := calledFunction(ctx.semPkg.source, call.Fun)
|
|
1459
|
+
if fn != nil && fn.Pkg() != nil && fn.Pkg().Path() != ctx.semPkg.pkgPath {
|
|
1460
|
+
needsAwait = true
|
|
1461
|
+
return false
|
|
1462
|
+
}
|
|
1417
1463
|
return true
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
return false
|
|
1421
|
-
}
|
|
1422
|
-
fn := calledFunction(ctx.semPkg.source, call.Fun)
|
|
1423
|
-
if fn == nil || fn.Pkg() == nil || fn.Pkg().Path() == ctx.semPkg.pkgPath {
|
|
1424
|
-
return false
|
|
1425
|
-
}
|
|
1426
|
-
return true
|
|
1464
|
+
})
|
|
1465
|
+
return needsAwait
|
|
1427
1466
|
}
|
|
1428
1467
|
|
|
1429
1468
|
func initializerMayHaveRuntimeEffects(ctx lowerFileContext, expr ast.Expr) bool {
|
|
@@ -1542,14 +1581,47 @@ func packageDeclFiles(semPkg *semanticPackage) map[types.Object]string {
|
|
|
1542
1581
|
return nil
|
|
1543
1582
|
}
|
|
1544
1583
|
declFiles := make(map[types.Object]string, len(semPkg.declarations))
|
|
1584
|
+
for idx, file := range semPkg.source.Syntax {
|
|
1585
|
+
sourcePath := sourceFilePath(semPkg, idx, file)
|
|
1586
|
+
for _, decl := range file.Decls {
|
|
1587
|
+
recordDeclFileObjects(semPkg.source.TypesInfo, declFiles, sourcePath, decl)
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1545
1590
|
for _, decl := range semPkg.declarations {
|
|
1546
|
-
if decl.object != nil && decl.position.file != "" {
|
|
1591
|
+
if decl.object != nil && decl.position.file != "" && declFiles[decl.object] == "" {
|
|
1547
1592
|
declFiles[decl.object] = decl.position.file
|
|
1548
1593
|
}
|
|
1549
1594
|
}
|
|
1550
1595
|
return declFiles
|
|
1551
1596
|
}
|
|
1552
1597
|
|
|
1598
|
+
func recordDeclFileObjects(info *types.Info, declFiles map[types.Object]string, sourcePath string, decl ast.Decl) {
|
|
1599
|
+
if info == nil || sourcePath == "" {
|
|
1600
|
+
return
|
|
1601
|
+
}
|
|
1602
|
+
switch typed := decl.(type) {
|
|
1603
|
+
case *ast.FuncDecl:
|
|
1604
|
+
if obj := info.Defs[typed.Name]; obj != nil {
|
|
1605
|
+
declFiles[obj] = sourcePath
|
|
1606
|
+
}
|
|
1607
|
+
case *ast.GenDecl:
|
|
1608
|
+
for _, spec := range typed.Specs {
|
|
1609
|
+
switch typedSpec := spec.(type) {
|
|
1610
|
+
case *ast.TypeSpec:
|
|
1611
|
+
if obj := info.Defs[typedSpec.Name]; obj != nil {
|
|
1612
|
+
declFiles[obj] = sourcePath
|
|
1613
|
+
}
|
|
1614
|
+
case *ast.ValueSpec:
|
|
1615
|
+
for _, name := range typedSpec.Names {
|
|
1616
|
+
if obj := info.Defs[name]; obj != nil {
|
|
1617
|
+
declFiles[obj] = sourcePath
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1553
1625
|
func packageOutputNames(semPkg *semanticPackage) map[string]string {
|
|
1554
1626
|
if semPkg == nil || semPkg.source == nil {
|
|
1555
1627
|
return nil
|
|
@@ -1624,6 +1696,11 @@ func (o *LoweringOwner) lazyPackageVars(semPkg *semanticPackage, declFiles map[t
|
|
|
1624
1696
|
lazy[obj] = true
|
|
1625
1697
|
continue
|
|
1626
1698
|
}
|
|
1699
|
+
if valueIdx < len(valueSpec.Values) &&
|
|
1700
|
+
initializerCallsFunctionReferencingOtherFileObject(semPkg, declFiles, sourcePath, valueSpec.Values[valueIdx]) {
|
|
1701
|
+
lazy[obj] = true
|
|
1702
|
+
continue
|
|
1703
|
+
}
|
|
1627
1704
|
if valueIdx < len(valueSpec.Values) &&
|
|
1628
1705
|
initializerCallsFunctionReferencingLaterPackageVar(semPkg, varOrder, obj, valueSpec.Values[valueIdx]) {
|
|
1629
1706
|
lazy[obj] = true
|
|
@@ -1794,7 +1871,14 @@ func (o *LoweringOwner) packageVarNameHasAsyncLazyInit(ctx lowerFileContext, pkg
|
|
|
1794
1871
|
if semPkg == nil || semPkg.source == nil {
|
|
1795
1872
|
return false
|
|
1796
1873
|
}
|
|
1797
|
-
initCtx := lowerFileContext{
|
|
1874
|
+
initCtx := lowerFileContext{
|
|
1875
|
+
model: ctx.model,
|
|
1876
|
+
semPkg: semPkg,
|
|
1877
|
+
lazyPackageVarsByPkg: ctx.lazyPackageVarsByPkg,
|
|
1878
|
+
asyncLazyFunctionCache: ctx.asyncLazyFunctionCache,
|
|
1879
|
+
asyncLazyFunctionVisiting: ctx.asyncLazyFunctionVisiting,
|
|
1880
|
+
topLevel: true,
|
|
1881
|
+
}
|
|
1798
1882
|
for _, file := range semPkg.source.Syntax {
|
|
1799
1883
|
for _, decl := range file.Decls {
|
|
1800
1884
|
genDecl, ok := decl.(*ast.GenDecl)
|
|
@@ -1885,6 +1969,83 @@ func initializerCallsFunctionReferencingLaterPackageVar(
|
|
|
1885
1969
|
return references
|
|
1886
1970
|
}
|
|
1887
1971
|
|
|
1972
|
+
func asyncLazyInitializerReferencesCyclicOtherFile(ctx lowerFileContext, expr ast.Expr) bool {
|
|
1973
|
+
if ctx.semPkg == nil || ctx.semPkg.source == nil || expr == nil {
|
|
1974
|
+
return false
|
|
1975
|
+
}
|
|
1976
|
+
declFiles := packageDeclFiles(ctx.semPkg)
|
|
1977
|
+
for otherFile := range initializerReferencedOtherFiles(ctx.semPkg, declFiles, ctx.sourcePath, expr) {
|
|
1978
|
+
if fileRuntimeReferencesSourceFile(ctx.semPkg, declFiles, otherFile, ctx.sourcePath) {
|
|
1979
|
+
return true
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
return false
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
func packageInitFunctionReferencesObject(ctx lowerFileContext, obj types.Object) bool {
|
|
1986
|
+
if obj == nil || ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
1987
|
+
return false
|
|
1988
|
+
}
|
|
1989
|
+
references := false
|
|
1990
|
+
for _, file := range ctx.semPkg.source.Syntax {
|
|
1991
|
+
for _, decl := range file.Decls {
|
|
1992
|
+
fnDecl, ok := decl.(*ast.FuncDecl)
|
|
1993
|
+
if !ok || fnDecl.Recv != nil || fnDecl.Name == nil || fnDecl.Name.Name != "init" || fnDecl.Body == nil {
|
|
1994
|
+
continue
|
|
1995
|
+
}
|
|
1996
|
+
ast.Inspect(fnDecl.Body, func(node ast.Node) bool {
|
|
1997
|
+
if references {
|
|
1998
|
+
return false
|
|
1999
|
+
}
|
|
2000
|
+
if _, ok := node.(*ast.FuncLit); ok {
|
|
2001
|
+
return false
|
|
2002
|
+
}
|
|
2003
|
+
ident, ok := node.(*ast.Ident)
|
|
2004
|
+
if !ok {
|
|
2005
|
+
return true
|
|
2006
|
+
}
|
|
2007
|
+
if ctx.semPkg.source.TypesInfo.Uses[ident] == obj {
|
|
2008
|
+
references = true
|
|
2009
|
+
return false
|
|
2010
|
+
}
|
|
2011
|
+
return true
|
|
2012
|
+
})
|
|
2013
|
+
if references {
|
|
2014
|
+
return true
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
return false
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
func initializerCallsFunctionReferencingOtherFileObject(
|
|
2022
|
+
semPkg *semanticPackage,
|
|
2023
|
+
declFiles map[types.Object]string,
|
|
2024
|
+
sourcePath string,
|
|
2025
|
+
expr ast.Expr,
|
|
2026
|
+
) bool {
|
|
2027
|
+
references := false
|
|
2028
|
+
ast.Inspect(expr, func(node ast.Node) bool {
|
|
2029
|
+
if references {
|
|
2030
|
+
return false
|
|
2031
|
+
}
|
|
2032
|
+
call, ok := node.(*ast.CallExpr)
|
|
2033
|
+
if !ok {
|
|
2034
|
+
return true
|
|
2035
|
+
}
|
|
2036
|
+
fn := calledFunction(semPkg.source, call.Fun)
|
|
2037
|
+
if fn == nil || fn.Pkg() == nil || fn.Pkg().Path() != semPkg.pkgPath {
|
|
2038
|
+
return true
|
|
2039
|
+
}
|
|
2040
|
+
if functionReferencesOtherFileObject(semPkg, declFiles, sourcePath, fn, nil) {
|
|
2041
|
+
references = true
|
|
2042
|
+
return false
|
|
2043
|
+
}
|
|
2044
|
+
return true
|
|
2045
|
+
})
|
|
2046
|
+
return references
|
|
2047
|
+
}
|
|
2048
|
+
|
|
1888
2049
|
func functionReferencesLaterPackageVar(
|
|
1889
2050
|
semPkg *semanticPackage,
|
|
1890
2051
|
varOrder map[types.Object]int,
|
|
@@ -1936,6 +2097,288 @@ func functionReferencesLaterPackageVar(
|
|
|
1936
2097
|
return references
|
|
1937
2098
|
}
|
|
1938
2099
|
|
|
2100
|
+
func initializerReferencedOtherFiles(
|
|
2101
|
+
semPkg *semanticPackage,
|
|
2102
|
+
declFiles map[types.Object]string,
|
|
2103
|
+
sourcePath string,
|
|
2104
|
+
expr ast.Expr,
|
|
2105
|
+
) map[string]bool {
|
|
2106
|
+
refs := make(map[string]bool)
|
|
2107
|
+
ast.Inspect(expr, func(node ast.Node) bool {
|
|
2108
|
+
if _, ok := node.(*ast.FuncLit); ok {
|
|
2109
|
+
return false
|
|
2110
|
+
}
|
|
2111
|
+
collectOtherFileReferences(semPkg, declFiles, sourcePath, node, refs)
|
|
2112
|
+
call, ok := node.(*ast.CallExpr)
|
|
2113
|
+
if !ok {
|
|
2114
|
+
return true
|
|
2115
|
+
}
|
|
2116
|
+
fn := calledFunction(semPkg.source, call.Fun)
|
|
2117
|
+
if fn == nil || fn.Pkg() == nil || fn.Pkg().Path() != semPkg.pkgPath {
|
|
2118
|
+
return true
|
|
2119
|
+
}
|
|
2120
|
+
collectFunctionOtherFileReferences(semPkg, declFiles, sourcePath, fn, nil, refs)
|
|
2121
|
+
return true
|
|
2122
|
+
})
|
|
2123
|
+
return refs
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
func collectFunctionOtherFileReferences(
|
|
2127
|
+
semPkg *semanticPackage,
|
|
2128
|
+
declFiles map[types.Object]string,
|
|
2129
|
+
sourcePath string,
|
|
2130
|
+
fn *types.Func,
|
|
2131
|
+
seen map[*types.Func]bool,
|
|
2132
|
+
refs map[string]bool,
|
|
2133
|
+
) {
|
|
2134
|
+
if fn == nil {
|
|
2135
|
+
return
|
|
2136
|
+
}
|
|
2137
|
+
if seen == nil {
|
|
2138
|
+
seen = make(map[*types.Func]bool)
|
|
2139
|
+
}
|
|
2140
|
+
if seen[fn] {
|
|
2141
|
+
return
|
|
2142
|
+
}
|
|
2143
|
+
seen[fn] = true
|
|
2144
|
+
fnDecl := functionDeclForObject(semPkg, fn)
|
|
2145
|
+
if fnDecl == nil || fnDecl.Body == nil {
|
|
2146
|
+
return
|
|
2147
|
+
}
|
|
2148
|
+
ast.Inspect(fnDecl.Body, func(node ast.Node) bool {
|
|
2149
|
+
if _, ok := node.(*ast.FuncLit); ok {
|
|
2150
|
+
return false
|
|
2151
|
+
}
|
|
2152
|
+
collectOtherFileReferences(semPkg, declFiles, sourcePath, node, refs)
|
|
2153
|
+
if call, ok := node.(*ast.CallExpr); ok {
|
|
2154
|
+
called := calledFunction(semPkg.source, call.Fun)
|
|
2155
|
+
if called != nil && called.Pkg() != nil && called.Pkg().Path() == semPkg.pkgPath {
|
|
2156
|
+
collectFunctionOtherFileReferences(semPkg, declFiles, sourcePath, called, seen, refs)
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
return true
|
|
2160
|
+
})
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
func collectOtherFileReferences(
|
|
2164
|
+
semPkg *semanticPackage,
|
|
2165
|
+
declFiles map[types.Object]string,
|
|
2166
|
+
sourcePath string,
|
|
2167
|
+
node ast.Node,
|
|
2168
|
+
refs map[string]bool,
|
|
2169
|
+
) {
|
|
2170
|
+
if node == nil {
|
|
2171
|
+
return
|
|
2172
|
+
}
|
|
2173
|
+
if lit, ok := node.(*ast.CompositeLit); ok {
|
|
2174
|
+
collectOtherFileTypeReferences(semPkg, declFiles, sourcePath, semPkg.source.TypesInfo.TypeOf(lit), refs, make(map[types.Type]bool))
|
|
2175
|
+
}
|
|
2176
|
+
switch typed := node.(type) {
|
|
2177
|
+
case *ast.Ident:
|
|
2178
|
+
collectOtherFileObjectReference(declFiles, sourcePath, semPkg.source.TypesInfo.Uses[typed], refs)
|
|
2179
|
+
case *ast.SelectorExpr:
|
|
2180
|
+
collectOtherFileObjectReference(declFiles, sourcePath, semPkg.source.TypesInfo.Uses[typed.Sel], refs)
|
|
2181
|
+
if selection := semPkg.source.TypesInfo.Selections[typed]; selection != nil {
|
|
2182
|
+
collectOtherFileObjectReference(declFiles, sourcePath, selection.Obj(), refs)
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
func collectOtherFileObjectReference(
|
|
2188
|
+
declFiles map[types.Object]string,
|
|
2189
|
+
sourcePath string,
|
|
2190
|
+
obj types.Object,
|
|
2191
|
+
refs map[string]bool,
|
|
2192
|
+
) {
|
|
2193
|
+
if obj == nil || obj.Pkg() == nil {
|
|
2194
|
+
return
|
|
2195
|
+
}
|
|
2196
|
+
if declFile := declFiles[obj]; declFile != "" && declFile != sourcePath {
|
|
2197
|
+
refs[declFile] = true
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
func collectOtherFileTypeReferences(
|
|
2202
|
+
semPkg *semanticPackage,
|
|
2203
|
+
declFiles map[types.Object]string,
|
|
2204
|
+
sourcePath string,
|
|
2205
|
+
typ types.Type,
|
|
2206
|
+
refs map[string]bool,
|
|
2207
|
+
seen map[types.Type]bool,
|
|
2208
|
+
) {
|
|
2209
|
+
if typ == nil || seen[typ] {
|
|
2210
|
+
return
|
|
2211
|
+
}
|
|
2212
|
+
seen[typ] = true
|
|
2213
|
+
if named := namedStructType(typ); named != nil {
|
|
2214
|
+
collectOtherFileObjectReference(declFiles, sourcePath, named.Obj(), refs)
|
|
2215
|
+
}
|
|
2216
|
+
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
2217
|
+
case *types.Array:
|
|
2218
|
+
collectOtherFileTypeReferences(semPkg, declFiles, sourcePath, typed.Elem(), refs, seen)
|
|
2219
|
+
case *types.Slice:
|
|
2220
|
+
collectOtherFileTypeReferences(semPkg, declFiles, sourcePath, typed.Elem(), refs, seen)
|
|
2221
|
+
case *types.Pointer:
|
|
2222
|
+
collectOtherFileTypeReferences(semPkg, declFiles, sourcePath, typed.Elem(), refs, seen)
|
|
2223
|
+
case *types.Map:
|
|
2224
|
+
collectOtherFileTypeReferences(semPkg, declFiles, sourcePath, typed.Key(), refs, seen)
|
|
2225
|
+
collectOtherFileTypeReferences(semPkg, declFiles, sourcePath, typed.Elem(), refs, seen)
|
|
2226
|
+
case *types.Struct:
|
|
2227
|
+
for field := range typed.Fields() {
|
|
2228
|
+
collectOtherFileTypeReferences(semPkg, declFiles, sourcePath, field.Type(), refs, seen)
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
func fileRuntimeReferencesSourceFile(
|
|
2234
|
+
semPkg *semanticPackage,
|
|
2235
|
+
declFiles map[types.Object]string,
|
|
2236
|
+
filePath string,
|
|
2237
|
+
sourcePath string,
|
|
2238
|
+
) bool {
|
|
2239
|
+
if semPkg == nil || semPkg.source == nil || filePath == "" || sourcePath == "" {
|
|
2240
|
+
return false
|
|
2241
|
+
}
|
|
2242
|
+
for idx, file := range semPkg.source.Syntax {
|
|
2243
|
+
if sourceFilePath(semPkg, idx, file) != filePath {
|
|
2244
|
+
continue
|
|
2245
|
+
}
|
|
2246
|
+
references := false
|
|
2247
|
+
ast.Inspect(file, func(node ast.Node) bool {
|
|
2248
|
+
if references {
|
|
2249
|
+
return false
|
|
2250
|
+
}
|
|
2251
|
+
if _, ok := node.(*ast.FuncLit); ok {
|
|
2252
|
+
return false
|
|
2253
|
+
}
|
|
2254
|
+
if lit, ok := node.(*ast.CompositeLit); ok &&
|
|
2255
|
+
typeReferencesSourceFile(semPkg, declFiles, lit, sourcePath) {
|
|
2256
|
+
references = true
|
|
2257
|
+
return false
|
|
2258
|
+
}
|
|
2259
|
+
if ident, ok := node.(*ast.Ident); ok &&
|
|
2260
|
+
valueIdentReferencesSourceFile(semPkg, declFiles, ident, sourcePath) {
|
|
2261
|
+
references = true
|
|
2262
|
+
return false
|
|
2263
|
+
}
|
|
2264
|
+
if selector, ok := node.(*ast.SelectorExpr); ok {
|
|
2265
|
+
if valueSelectorReferencesSourceFile(semPkg, declFiles, selector, sourcePath) {
|
|
2266
|
+
references = true
|
|
2267
|
+
return false
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
if call, ok := node.(*ast.CallExpr); ok {
|
|
2271
|
+
called := calledFunction(semPkg.source, call.Fun)
|
|
2272
|
+
if called != nil && declFiles[called] == sourcePath {
|
|
2273
|
+
references = true
|
|
2274
|
+
return false
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
return true
|
|
2278
|
+
})
|
|
2279
|
+
return references
|
|
2280
|
+
}
|
|
2281
|
+
return false
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
func valueIdentReferencesSourceFile(
|
|
2285
|
+
semPkg *semanticPackage,
|
|
2286
|
+
declFiles map[types.Object]string,
|
|
2287
|
+
ident *ast.Ident,
|
|
2288
|
+
sourcePath string,
|
|
2289
|
+
) bool {
|
|
2290
|
+
if tv, ok := semPkg.source.TypesInfo.Types[ident]; ok && !tv.IsValue() {
|
|
2291
|
+
return false
|
|
2292
|
+
}
|
|
2293
|
+
return declFiles[semPkg.source.TypesInfo.Uses[ident]] == sourcePath
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
func valueSelectorReferencesSourceFile(
|
|
2297
|
+
semPkg *semanticPackage,
|
|
2298
|
+
declFiles map[types.Object]string,
|
|
2299
|
+
selector *ast.SelectorExpr,
|
|
2300
|
+
sourcePath string,
|
|
2301
|
+
) bool {
|
|
2302
|
+
if tv, ok := semPkg.source.TypesInfo.Types[selector]; ok && !tv.IsValue() {
|
|
2303
|
+
return false
|
|
2304
|
+
}
|
|
2305
|
+
if declFiles[semPkg.source.TypesInfo.Uses[selector.Sel]] == sourcePath {
|
|
2306
|
+
return true
|
|
2307
|
+
}
|
|
2308
|
+
if selection := semPkg.source.TypesInfo.Selections[selector]; selection != nil {
|
|
2309
|
+
return declFiles[selection.Obj()] == sourcePath
|
|
2310
|
+
}
|
|
2311
|
+
return false
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
func typeReferencesSourceFile(
|
|
2315
|
+
semPkg *semanticPackage,
|
|
2316
|
+
declFiles map[types.Object]string,
|
|
2317
|
+
expr ast.Expr,
|
|
2318
|
+
sourcePath string,
|
|
2319
|
+
) bool {
|
|
2320
|
+
refs := make(map[string]bool)
|
|
2321
|
+
collectOtherFileTypeReferences(semPkg, declFiles, "", semPkg.source.TypesInfo.TypeOf(expr), refs, make(map[types.Type]bool))
|
|
2322
|
+
return refs[sourcePath]
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
func functionReferencesOtherFileObject(
|
|
2326
|
+
semPkg *semanticPackage,
|
|
2327
|
+
declFiles map[types.Object]string,
|
|
2328
|
+
sourcePath string,
|
|
2329
|
+
fn *types.Func,
|
|
2330
|
+
seen map[*types.Func]bool,
|
|
2331
|
+
) bool {
|
|
2332
|
+
if fn == nil {
|
|
2333
|
+
return false
|
|
2334
|
+
}
|
|
2335
|
+
if seen == nil {
|
|
2336
|
+
seen = make(map[*types.Func]bool)
|
|
2337
|
+
}
|
|
2338
|
+
if seen[fn] {
|
|
2339
|
+
return false
|
|
2340
|
+
}
|
|
2341
|
+
seen[fn] = true
|
|
2342
|
+
fnDecl := functionDeclForObject(semPkg, fn)
|
|
2343
|
+
if fnDecl == nil || fnDecl.Body == nil {
|
|
2344
|
+
return false
|
|
2345
|
+
}
|
|
2346
|
+
references := false
|
|
2347
|
+
ast.Inspect(fnDecl.Body, func(node ast.Node) bool {
|
|
2348
|
+
if references {
|
|
2349
|
+
return false
|
|
2350
|
+
}
|
|
2351
|
+
if _, ok := node.(*ast.FuncLit); ok {
|
|
2352
|
+
return false
|
|
2353
|
+
}
|
|
2354
|
+
if lit, ok := node.(*ast.CompositeLit); ok {
|
|
2355
|
+
if zeroValueReferencesOtherFileObject(semPkg, declFiles, sourcePath, semPkg.source.TypesInfo.TypeOf(lit)) {
|
|
2356
|
+
references = true
|
|
2357
|
+
return false
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
if ident, ok := node.(*ast.Ident); ok {
|
|
2361
|
+
obj := semPkg.source.TypesInfo.Uses[ident]
|
|
2362
|
+
if obj != nil && obj.Pkg() != nil && obj.Pkg().Path() == semPkg.pkgPath {
|
|
2363
|
+
if declFile := declFiles[obj]; declFile != "" && declFile != sourcePath {
|
|
2364
|
+
references = true
|
|
2365
|
+
return false
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
if call, ok := node.(*ast.CallExpr); ok {
|
|
2370
|
+
called := calledFunction(semPkg.source, call.Fun)
|
|
2371
|
+
if called != nil && called.Pkg() != nil && called.Pkg().Path() == semPkg.pkgPath &&
|
|
2372
|
+
functionReferencesOtherFileObject(semPkg, declFiles, sourcePath, called, seen) {
|
|
2373
|
+
references = true
|
|
2374
|
+
return false
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
return true
|
|
2378
|
+
})
|
|
2379
|
+
return references
|
|
2380
|
+
}
|
|
2381
|
+
|
|
1939
2382
|
func functionDeclForObject(semPkg *semanticPackage, fn *types.Func) *ast.FuncDecl {
|
|
1940
2383
|
if semPkg == nil || semPkg.source == nil || fn == nil {
|
|
1941
2384
|
return nil
|
|
@@ -1962,6 +2405,12 @@ func initializerReferencesOtherFileObject(
|
|
|
1962
2405
|
if references {
|
|
1963
2406
|
return false
|
|
1964
2407
|
}
|
|
2408
|
+
if lit, ok := node.(*ast.CompositeLit); ok {
|
|
2409
|
+
if zeroValueReferencesOtherFileObject(semPkg, declFiles, sourcePath, semPkg.source.TypesInfo.TypeOf(lit)) {
|
|
2410
|
+
references = true
|
|
2411
|
+
return false
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
1965
2414
|
ident, ok := node.(*ast.Ident)
|
|
1966
2415
|
if !ok {
|
|
1967
2416
|
return true
|
|
@@ -2237,7 +2686,7 @@ func (o *LoweringOwner) lowerGoEmbedFSValue(ctx lowerFileContext, diagPos token.
|
|
|
2237
2686
|
entries = append(entries, "["+strconv.Quote(path)+", "+byteSliceLiteral(filesByPath[path])+"]")
|
|
2238
2687
|
}
|
|
2239
2688
|
builtinAlias := o.runtimeOwner.BuiltinImport().Alias
|
|
2240
|
-
return builtinAlias + ".markAsStructValue(new " + embedAlias + ".FS(new Map<string, Uint8Array>([" + strings.Join(entries, ", ") + "])))", nil
|
|
2689
|
+
return builtinAlias + ".markAsStructValue(new " + embedAlias + ".FS(new globalThis.Map<string, Uint8Array>([" + strings.Join(entries, ", ") + "])))", nil
|
|
2241
2690
|
}
|
|
2242
2691
|
|
|
2243
2692
|
type goEmbedFile struct {
|
|
@@ -2639,7 +3088,10 @@ func (o *LoweringOwner) lowerStructType(ctx lowerFileContext, semType *semanticT
|
|
|
2639
3088
|
}
|
|
2640
3089
|
|
|
2641
3090
|
methodDecls := o.methodDeclsForType(ctx, semType.named)
|
|
2642
|
-
explicitMethods := make(map[string]bool, len(methodDecls))
|
|
3091
|
+
explicitMethods := make(map[string]bool, len(methodDecls)+len(semType.fields))
|
|
3092
|
+
for _, field := range semType.fields {
|
|
3093
|
+
explicitMethods[field.name] = true
|
|
3094
|
+
}
|
|
2643
3095
|
if len(methodDecls) != 0 {
|
|
2644
3096
|
lowered.methods = make([]loweredFunction, 0, len(methodDecls))
|
|
2645
3097
|
for _, methodDecl := range methodDecls {
|
|
@@ -3622,28 +4074,17 @@ func (o *LoweringOwner) lowerStmtListAfter(
|
|
|
3622
4074
|
hasGoto := stmtListHasGoto(stmts)
|
|
3623
4075
|
var gotoSpans map[string]int
|
|
3624
4076
|
var gotoLabels map[string]bool
|
|
3625
|
-
var
|
|
4077
|
+
var forwardSpans map[string]forwardGotoLabelSpan
|
|
3626
4078
|
if hasGoto {
|
|
3627
4079
|
gotoSpans = backwardGotoLabelSpans(stmts)
|
|
3628
4080
|
gotoLabels = make(map[string]bool, len(gotoSpans))
|
|
3629
4081
|
for label := range gotoSpans {
|
|
3630
4082
|
gotoLabels[label] = true
|
|
3631
4083
|
}
|
|
3632
|
-
forwardSpans
|
|
3633
|
-
forwardStarts = make(map[int]forwardGotoLabelSpan, len(forwardSpans))
|
|
4084
|
+
forwardSpans = forwardGotoLabelSpans(stmts, gotoSpans)
|
|
3634
4085
|
for label, span := range forwardSpans {
|
|
3635
4086
|
span.label = label
|
|
3636
|
-
|
|
3637
|
-
if group.forwardLabels == nil {
|
|
3638
|
-
group.forwardLabels = make(map[string]bool)
|
|
3639
|
-
}
|
|
3640
|
-
group.forwardLabels[label] = true
|
|
3641
|
-
if group.label == "" || span.labelIdx > group.labelIdx {
|
|
3642
|
-
group.label = span.label
|
|
3643
|
-
group.start = span.start
|
|
3644
|
-
group.labelIdx = span.labelIdx
|
|
3645
|
-
}
|
|
3646
|
-
forwardStarts[span.start] = group
|
|
4087
|
+
forwardSpans[label] = span
|
|
3647
4088
|
}
|
|
3648
4089
|
}
|
|
3649
4090
|
for idx := 0; idx < len(stmts); idx++ {
|
|
@@ -3680,20 +4121,17 @@ func (o *LoweringOwner) lowerStmtListAfter(
|
|
|
3680
4121
|
idx = span.endIdx
|
|
3681
4122
|
continue
|
|
3682
4123
|
}
|
|
3683
|
-
if
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
4124
|
+
if group, ok := forwardGotoLabelGroupAt(idx, forwardSpans); ok {
|
|
4125
|
+
groupLowered, groupDiagnostics := o.lowerForwardGotoLabelGroup(
|
|
4126
|
+
ctx,
|
|
4127
|
+
stmts,
|
|
4128
|
+
group,
|
|
3688
4129
|
prevEndLine,
|
|
4130
|
+
leading,
|
|
3689
4131
|
)
|
|
3690
|
-
diagnostics = append(diagnostics,
|
|
3691
|
-
|
|
3692
|
-
if
|
|
3693
|
-
block.leading = append(leading, block.leading...)
|
|
3694
|
-
}
|
|
3695
|
-
lowered = append(lowered, block)
|
|
3696
|
-
if labeled, ok := stmts[span.labelIdx].(*ast.LabeledStmt); ok {
|
|
4132
|
+
diagnostics = append(diagnostics, groupDiagnostics...)
|
|
4133
|
+
lowered = append(lowered, groupLowered...)
|
|
4134
|
+
if labeled, ok := stmts[group.labelIdx].(*ast.LabeledStmt); ok {
|
|
3697
4135
|
labelLowered, labelDiagnostics := o.lowerStmt(ctx, labeled.Stmt)
|
|
3698
4136
|
diagnostics = append(diagnostics, labelDiagnostics...)
|
|
3699
4137
|
lowered = append(lowered, labelLowered...)
|
|
@@ -3701,7 +4139,7 @@ func (o *LoweringOwner) lowerStmtListAfter(
|
|
|
3701
4139
|
prevEndLine = endLine
|
|
3702
4140
|
}
|
|
3703
4141
|
}
|
|
3704
|
-
idx =
|
|
4142
|
+
idx = group.labelIdx
|
|
3705
4143
|
continue
|
|
3706
4144
|
}
|
|
3707
4145
|
if labeled, ok := stmt.(*ast.LabeledStmt); ok {
|
|
@@ -4033,12 +4471,105 @@ func (o *LoweringOwner) lowerBackwardGotoLoop(
|
|
|
4033
4471
|
}
|
|
4034
4472
|
|
|
4035
4473
|
type forwardGotoLabelSpan struct {
|
|
4036
|
-
label
|
|
4474
|
+
label string
|
|
4475
|
+
start int
|
|
4476
|
+
labelIdx int
|
|
4477
|
+
}
|
|
4478
|
+
|
|
4479
|
+
type forwardGotoLabelGroup struct {
|
|
4037
4480
|
start int
|
|
4038
4481
|
labelIdx int
|
|
4482
|
+
spans []forwardGotoLabelSpan
|
|
4039
4483
|
forwardLabels map[string]bool
|
|
4040
4484
|
}
|
|
4041
4485
|
|
|
4486
|
+
func forwardGotoLabelGroupAt(start int, spans map[string]forwardGotoLabelSpan) (forwardGotoLabelGroup, bool) {
|
|
4487
|
+
var included map[string]bool
|
|
4488
|
+
group := forwardGotoLabelGroup{start: start, labelIdx: -1}
|
|
4489
|
+
for label, span := range spans {
|
|
4490
|
+
if span.start != start {
|
|
4491
|
+
continue
|
|
4492
|
+
}
|
|
4493
|
+
if included == nil {
|
|
4494
|
+
included = make(map[string]bool)
|
|
4495
|
+
group.forwardLabels = make(map[string]bool)
|
|
4496
|
+
}
|
|
4497
|
+
included[label] = true
|
|
4498
|
+
group.spans = append(group.spans, span)
|
|
4499
|
+
group.forwardLabels[label] = true
|
|
4500
|
+
if span.labelIdx > group.labelIdx {
|
|
4501
|
+
group.labelIdx = span.labelIdx
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
if len(group.spans) == 0 {
|
|
4505
|
+
return forwardGotoLabelGroup{}, false
|
|
4506
|
+
}
|
|
4507
|
+
|
|
4508
|
+
for {
|
|
4509
|
+
changed := false
|
|
4510
|
+
for label, span := range spans {
|
|
4511
|
+
if included[label] || span.start < start || span.start >= group.labelIdx {
|
|
4512
|
+
continue
|
|
4513
|
+
}
|
|
4514
|
+
included[label] = true
|
|
4515
|
+
group.spans = append(group.spans, span)
|
|
4516
|
+
group.forwardLabels[label] = true
|
|
4517
|
+
if span.labelIdx > group.labelIdx {
|
|
4518
|
+
group.labelIdx = span.labelIdx
|
|
4519
|
+
}
|
|
4520
|
+
changed = true
|
|
4521
|
+
}
|
|
4522
|
+
if !changed {
|
|
4523
|
+
break
|
|
4524
|
+
}
|
|
4525
|
+
}
|
|
4526
|
+
|
|
4527
|
+
slices.SortFunc(group.spans, func(a, b forwardGotoLabelSpan) int {
|
|
4528
|
+
if n := cmp.Compare(a.labelIdx, b.labelIdx); n != 0 {
|
|
4529
|
+
return n
|
|
4530
|
+
}
|
|
4531
|
+
return cmp.Compare(a.label, b.label)
|
|
4532
|
+
})
|
|
4533
|
+
return group, true
|
|
4534
|
+
}
|
|
4535
|
+
|
|
4536
|
+
func (o *LoweringOwner) lowerForwardGotoLabelGroup(
|
|
4537
|
+
ctx lowerFileContext,
|
|
4538
|
+
stmts []ast.Stmt,
|
|
4539
|
+
group forwardGotoLabelGroup,
|
|
4540
|
+
prevEndLine int,
|
|
4541
|
+
leading []string,
|
|
4542
|
+
) ([]loweredStmt, []Diagnostic) {
|
|
4543
|
+
forwardCtx := ctx.withForwardGotos(group.forwardLabels)
|
|
4544
|
+
first := group.spans[0]
|
|
4545
|
+
body, diagnostics := o.lowerStmtListAfter(forwardCtx, stmts[group.start:first.labelIdx], prevEndLine)
|
|
4546
|
+
block := loweredStmt{hasBlock: true, text: first.label + ":", children: body}
|
|
4547
|
+
|
|
4548
|
+
for idx := 1; idx < len(group.spans); idx++ {
|
|
4549
|
+
prev := group.spans[idx-1]
|
|
4550
|
+
next := group.spans[idx]
|
|
4551
|
+
children := []loweredStmt{block}
|
|
4552
|
+
if labeled, ok := stmts[prev.labelIdx].(*ast.LabeledStmt); ok {
|
|
4553
|
+
segment := make([]ast.Stmt, 0, next.labelIdx-prev.labelIdx)
|
|
4554
|
+
segment = append(segment, labeled.Stmt)
|
|
4555
|
+
segment = append(segment, stmts[prev.labelIdx+1:next.labelIdx]...)
|
|
4556
|
+
segmentLowered, segmentDiagnostics := o.lowerStmtListAfter(
|
|
4557
|
+
forwardCtx,
|
|
4558
|
+
segment,
|
|
4559
|
+
sourceLine(ctx, labeled.Label.End()),
|
|
4560
|
+
)
|
|
4561
|
+
diagnostics = append(diagnostics, segmentDiagnostics...)
|
|
4562
|
+
children = append(children, segmentLowered...)
|
|
4563
|
+
}
|
|
4564
|
+
block = loweredStmt{hasBlock: true, text: next.label + ":", children: children}
|
|
4565
|
+
}
|
|
4566
|
+
|
|
4567
|
+
if len(leading) != 0 {
|
|
4568
|
+
block.leading = append(leading, block.leading...)
|
|
4569
|
+
}
|
|
4570
|
+
return []loweredStmt{block}, diagnostics
|
|
4571
|
+
}
|
|
4572
|
+
|
|
4042
4573
|
type leadingGotoBackwardLoop struct {
|
|
4043
4574
|
label string
|
|
4044
4575
|
labelIdx int
|
|
@@ -4395,6 +4926,9 @@ func (o *LoweringOwner) lowerMapIndexUpdateStmts(
|
|
|
4395
4926
|
mapExpr, mapDiagnostics := o.lowerExpr(ctx, index.X)
|
|
4396
4927
|
keyExpr, keyDiagnostics := o.lowerExpr(ctx, index.Index)
|
|
4397
4928
|
diagnostics := append(mapDiagnostics, keyDiagnostics...)
|
|
4929
|
+
if mapType, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(index.X)).Underlying().(*types.Map); ok {
|
|
4930
|
+
keyExpr = o.lowerValueForTarget(ctx, index.Index, mapType.Key(), keyExpr)
|
|
4931
|
+
}
|
|
4398
4932
|
if tok == token.ASSIGN {
|
|
4399
4933
|
return []loweredStmt{{text: o.runtimeOwner.QualifiedHelper(RuntimeHelperMapSet) + "(" + mapExpr + ", " + keyExpr + ", " + right + ")"}}, diagnostics
|
|
4400
4934
|
}
|
|
@@ -4802,6 +5336,11 @@ func (o *LoweringOwner) lowerShortDeclNewShadowAliases(
|
|
|
4802
5336
|
func shortDeclShadowNonValueIdents(ctx lowerFileContext, expr ast.Expr) map[*ast.Ident]bool {
|
|
4803
5337
|
idents := make(map[*ast.Ident]bool)
|
|
4804
5338
|
ast.Inspect(expr, func(node ast.Node) bool {
|
|
5339
|
+
if ident, ok := node.(*ast.Ident); ok {
|
|
5340
|
+
if _, ok := ctx.semPkg.source.TypesInfo.Uses[ident].(*types.TypeName); ok {
|
|
5341
|
+
idents[ident] = true
|
|
5342
|
+
}
|
|
5343
|
+
}
|
|
4805
5344
|
switch typed := node.(type) {
|
|
4806
5345
|
case *ast.CallExpr:
|
|
4807
5346
|
if ident, ok := typed.Fun.(*ast.Ident); ok {
|
|
@@ -6354,7 +6893,7 @@ func (o *LoweringOwner) lowerTypeSwitchStmt(ctx lowerFileContext, stmt *ast.Type
|
|
|
6354
6893
|
func (o *LoweringOwner) tsTypeSwitchCaseTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
6355
6894
|
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
6356
6895
|
if _, ok := named.Underlying().(*types.Interface); ok {
|
|
6357
|
-
return o.
|
|
6896
|
+
return o.tsTypeFor(ctx, named)
|
|
6358
6897
|
}
|
|
6359
6898
|
}
|
|
6360
6899
|
return o.tsTypeFor(ctx, typ)
|
|
@@ -6366,7 +6905,7 @@ func loweredStmtsUseVarRefName(stmts []loweredStmt, name string) bool {
|
|
|
6366
6905
|
}
|
|
6367
6906
|
needle := name + ".value"
|
|
6368
6907
|
for _, stmt := range stmts {
|
|
6369
|
-
if
|
|
6908
|
+
if loweredStmtTextUsesVarRefName(stmt.text, needle) {
|
|
6370
6909
|
return true
|
|
6371
6910
|
}
|
|
6372
6911
|
if loweredStmtsUseVarRefName(stmt.children, name) {
|
|
@@ -6393,6 +6932,38 @@ func loweredStmtsUseVarRefName(stmts []loweredStmt, name string) bool {
|
|
|
6393
6932
|
return false
|
|
6394
6933
|
}
|
|
6395
6934
|
|
|
6935
|
+
func loweredStmtTextUsesVarRefName(text, needle string) bool {
|
|
6936
|
+
offset := 0
|
|
6937
|
+
for {
|
|
6938
|
+
idx := strings.Index(text[offset:], needle)
|
|
6939
|
+
if idx < 0 {
|
|
6940
|
+
return false
|
|
6941
|
+
}
|
|
6942
|
+
start := offset + idx
|
|
6943
|
+
end := start + len(needle)
|
|
6944
|
+
if tsIdentifierBoundaryBefore(text, start) && tsIdentifierBoundaryAfter(text, end) {
|
|
6945
|
+
return true
|
|
6946
|
+
}
|
|
6947
|
+
offset = start + 1
|
|
6948
|
+
}
|
|
6949
|
+
}
|
|
6950
|
+
|
|
6951
|
+
func tsIdentifierBoundaryBefore(text string, idx int) bool {
|
|
6952
|
+
if idx == 0 {
|
|
6953
|
+
return true
|
|
6954
|
+
}
|
|
6955
|
+
prev := text[idx-1]
|
|
6956
|
+
return prev != '.' && !isTSIdentifierByte(prev)
|
|
6957
|
+
}
|
|
6958
|
+
|
|
6959
|
+
func tsIdentifierBoundaryAfter(text string, idx int) bool {
|
|
6960
|
+
return idx >= len(text) || !isTSIdentifierByte(text[idx])
|
|
6961
|
+
}
|
|
6962
|
+
|
|
6963
|
+
func isTSIdentifierByte(b byte) bool {
|
|
6964
|
+
return b == '$' || b == '_' || ('0' <= b && b <= '9') || ('A' <= b && b <= 'Z') || ('a' <= b && b <= 'z')
|
|
6965
|
+
}
|
|
6966
|
+
|
|
6396
6967
|
func (o *LoweringOwner) lowerTypeSwitchAssign(ctx lowerFileContext, stmt ast.Stmt) (string, string, bool, []Diagnostic) {
|
|
6397
6968
|
switch typed := stmt.(type) {
|
|
6398
6969
|
case *ast.ExprStmt:
|
|
@@ -6847,11 +7418,47 @@ func isLegacyOctalLiteral(value string) bool {
|
|
|
6847
7418
|
}
|
|
6848
7419
|
|
|
6849
7420
|
func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (string, bool, []Diagnostic) {
|
|
7421
|
+
return o.lowerFuncLitWithAsyncCalls(ctx, lit, true)
|
|
7422
|
+
}
|
|
7423
|
+
|
|
7424
|
+
func (o *LoweringOwner) lowerFuncLitForTarget(
|
|
7425
|
+
ctx lowerFileContext,
|
|
7426
|
+
lit *ast.FuncLit,
|
|
7427
|
+
targetType types.Type,
|
|
7428
|
+
allowAsyncOverrideCallback bool,
|
|
7429
|
+
) (string, bool, []Diagnostic) {
|
|
7430
|
+
allowAsyncCalls := true
|
|
7431
|
+
if !allowAsyncOverrideCallback && signatureForType(targetType) != nil {
|
|
7432
|
+
allowAsyncCalls = false
|
|
7433
|
+
}
|
|
7434
|
+
return o.lowerFuncLitWithAsyncCalls(ctx, lit, allowAsyncCalls)
|
|
7435
|
+
}
|
|
7436
|
+
|
|
7437
|
+
func (o *LoweringOwner) lowerFuncLitWithAsyncCalls(
|
|
7438
|
+
ctx lowerFileContext,
|
|
7439
|
+
lit *ast.FuncLit,
|
|
7440
|
+
allowAsyncCalls bool,
|
|
7441
|
+
) (string, bool, []Diagnostic) {
|
|
7442
|
+
function, async, signature, diagnostics := o.lowerFuncLitArrowWithAsyncCalls(ctx, lit, allowAsyncCalls)
|
|
7443
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperFunctionValue) +
|
|
7444
|
+
"(" + function + ", " + o.runtimeFunctionTypeInfo(signature, "") + ")", async, diagnostics
|
|
7445
|
+
}
|
|
7446
|
+
|
|
7447
|
+
func (o *LoweringOwner) lowerFuncLitCallCallee(ctx lowerFileContext, lit *ast.FuncLit) (string, bool, []Diagnostic) {
|
|
7448
|
+
function, async, _, diagnostics := o.lowerFuncLitArrowWithAsyncCalls(ctx, lit, true)
|
|
7449
|
+
return function, async, diagnostics
|
|
7450
|
+
}
|
|
7451
|
+
|
|
7452
|
+
func (o *LoweringOwner) lowerFuncLitArrowWithAsyncCalls(
|
|
7453
|
+
ctx lowerFileContext,
|
|
7454
|
+
lit *ast.FuncLit,
|
|
7455
|
+
allowAsyncCalls bool,
|
|
7456
|
+
) (string, bool, *types.Signature, []Diagnostic) {
|
|
6850
7457
|
signature, _ := ctx.semPkg.source.TypesInfo.TypeOf(lit).(*types.Signature)
|
|
6851
7458
|
deferState := &loweredDeferState{}
|
|
6852
7459
|
bodyCtx := ctx.withSignature(signature).withAsyncFunction(false).withDeferState(deferState).withoutRangeBranch()
|
|
6853
7460
|
asyncCompatibleParams := funcLiteralNeedsAsyncFunctionParamCalls(signature)
|
|
6854
|
-
if asyncCompatibleParams || funcLiteralUsesAwaitableCall(ctx, lit) {
|
|
7461
|
+
if allowAsyncCalls && (asyncCompatibleParams || funcLiteralUsesAwaitableCall(ctx, lit)) {
|
|
6855
7462
|
bodyCtx = bodyCtx.withAsyncFunction(true)
|
|
6856
7463
|
}
|
|
6857
7464
|
var params []loweredParam
|
|
@@ -6876,8 +7483,7 @@ func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (st
|
|
|
6876
7483
|
function := prefix + "(" + renderLoweredParams(params) + "): " +
|
|
6877
7484
|
asyncResultType(o.tsSignatureResultFor(ctx, signature), async) + " => {\n" +
|
|
6878
7485
|
rendered.String() + "}"
|
|
6879
|
-
return
|
|
6880
|
-
"(" + function + ", " + o.runtimeFunctionTypeInfo(signature, "") + ")", async, diagnostics
|
|
7486
|
+
return function, async, signature, diagnostics
|
|
6881
7487
|
}
|
|
6882
7488
|
|
|
6883
7489
|
func renderLoweredParams(params []loweredParam) string {
|
|
@@ -6976,6 +7582,9 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
|
|
|
6976
7582
|
return constValue
|
|
6977
7583
|
}
|
|
6978
7584
|
}
|
|
7585
|
+
if imported, ok := o.lowerImportedIdent(ctx, obj, value, raw); ok {
|
|
7586
|
+
return imported
|
|
7587
|
+
}
|
|
6979
7588
|
if alias := ctx.localAliases[obj]; alias != "" {
|
|
6980
7589
|
if ctx.lazyPackageVars[obj] {
|
|
6981
7590
|
lazyValue := alias + "." + packageVarGetterName(value) + "()"
|
|
@@ -7008,6 +7617,29 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
|
|
|
7008
7617
|
return value
|
|
7009
7618
|
}
|
|
7010
7619
|
|
|
7620
|
+
func (o *LoweringOwner) lowerImportedIdent(ctx lowerFileContext, obj types.Object, value string, raw bool) (string, bool) {
|
|
7621
|
+
if obj == nil || obj.Pkg() == nil || ctx.semPkg == nil || obj.Pkg().Path() == ctx.semPkg.pkgPath {
|
|
7622
|
+
return "", false
|
|
7623
|
+
}
|
|
7624
|
+
alias := ctx.importPaths[obj.Pkg().Path()]
|
|
7625
|
+
if alias == "" {
|
|
7626
|
+
return "", false
|
|
7627
|
+
}
|
|
7628
|
+
qualified := alias + "." + value
|
|
7629
|
+
if varObj, ok := obj.(*types.Var); ok &&
|
|
7630
|
+
(o.packageVarIsLazy(ctx, varObj) || o.packageVarNameIsLazy(ctx, obj.Pkg().Path(), obj.Name())) {
|
|
7631
|
+
qualified = alias + "." + packageVarGetterName(value) + "()"
|
|
7632
|
+
if (ctx.asyncFunction || ctx.topLevel) &&
|
|
7633
|
+
o.packageVarNameHasAsyncLazyInit(ctx, obj.Pkg().Path(), obj.Name()) {
|
|
7634
|
+
qualified = "(await " + alias + "." + packageVarInitName(value) + "(), " + qualified + ")"
|
|
7635
|
+
}
|
|
7636
|
+
}
|
|
7637
|
+
if raw {
|
|
7638
|
+
return qualified, true
|
|
7639
|
+
}
|
|
7640
|
+
return o.lowerPackageVarReadValue(ctx, obj, qualified), true
|
|
7641
|
+
}
|
|
7642
|
+
|
|
7011
7643
|
func (o *LoweringOwner) lowerPackageVarReadValue(ctx lowerFileContext, obj types.Object, value string) string {
|
|
7012
7644
|
if obj == nil || ctx.model == nil || !ctx.model.needsVarRef[obj] {
|
|
7013
7645
|
return value
|
|
@@ -7082,6 +7714,17 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
7082
7714
|
}
|
|
7083
7715
|
|
|
7084
7716
|
args, diagnostics := o.lowerCallArgs(ctx, expr, callTargetSignature(ctx, expr.Fun))
|
|
7717
|
+
if fun, ok := unwrapParenExpr(expr.Fun).(*ast.FuncLit); ok {
|
|
7718
|
+
callee, async, calleeDiagnostics := o.lowerFuncLitCallCallee(ctx, fun)
|
|
7719
|
+
call := "(" + callee + ")(" + strings.Join(args, ", ") + ")"
|
|
7720
|
+
if async {
|
|
7721
|
+
call = "await " + call
|
|
7722
|
+
if ctx.deferState != nil {
|
|
7723
|
+
ctx.deferState.async = true
|
|
7724
|
+
}
|
|
7725
|
+
}
|
|
7726
|
+
return call, append(diagnostics, calleeDiagnostics...)
|
|
7727
|
+
}
|
|
7085
7728
|
|
|
7086
7729
|
switch fun := expr.Fun.(type) {
|
|
7087
7730
|
case *ast.Ident:
|
|
@@ -7239,16 +7882,6 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
7239
7882
|
ctx.deferState.async = true
|
|
7240
7883
|
}
|
|
7241
7884
|
return o.awaitCallIfNeeded(ctx, fun, call), append(diagnostics, calleeDiagnostics...)
|
|
7242
|
-
case *ast.FuncLit:
|
|
7243
|
-
callee, async, calleeDiagnostics := o.lowerFuncLit(ctx, fun)
|
|
7244
|
-
call := "(" + callee + ")(" + strings.Join(args, ", ") + ")"
|
|
7245
|
-
if async {
|
|
7246
|
-
call = "await " + call
|
|
7247
|
-
if ctx.deferState != nil {
|
|
7248
|
-
ctx.deferState.async = true
|
|
7249
|
-
}
|
|
7250
|
-
}
|
|
7251
|
-
return call, append(diagnostics, calleeDiagnostics...)
|
|
7252
7885
|
default:
|
|
7253
7886
|
if callTargetSignature(ctx, expr.Fun) != nil {
|
|
7254
7887
|
callee, calleeDiagnostics := o.lowerExpr(ctx, expr.Fun)
|
|
@@ -7276,13 +7909,14 @@ func (o *LoweringOwner) lowerCallArgs(
|
|
|
7276
7909
|
signature *types.Signature,
|
|
7277
7910
|
) ([]string, []Diagnostic) {
|
|
7278
7911
|
overrideCall := o.callUsesOverridePackage(ctx, expr.Fun)
|
|
7912
|
+
allowAsyncOverrideCallback := !overrideCall || o.overrideCallNeedsAwait(ctx, expr.Fun)
|
|
7279
7913
|
if args, diagnostics, ok := o.lowerTupleCallArgs(ctx, expr, signature, overrideCall); ok {
|
|
7280
7914
|
return args, diagnostics
|
|
7281
7915
|
}
|
|
7282
7916
|
if signature != nil && signature.Variadic() && overrideCall && !isBuiltinCallTarget(ctx, expr.Fun) {
|
|
7283
7917
|
params := signature.Params()
|
|
7284
7918
|
if params == nil || params.Len() == 0 {
|
|
7285
|
-
return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall)
|
|
7919
|
+
return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall, allowAsyncOverrideCallback)
|
|
7286
7920
|
}
|
|
7287
7921
|
fixedCount := params.Len() - 1
|
|
7288
7922
|
targetType := params.At(fixedCount).Type()
|
|
@@ -7292,7 +7926,7 @@ func (o *LoweringOwner) lowerCallArgs(
|
|
|
7292
7926
|
args := make([]string, 0, len(expr.Args))
|
|
7293
7927
|
var diagnostics []Diagnostic
|
|
7294
7928
|
for idx, arg := range expr.Args {
|
|
7295
|
-
lowered, argDiagnostics := o.
|
|
7929
|
+
lowered, argDiagnostics := o.lowerCallArgExpr(ctx, arg, params.At(min(idx, fixedCount)).Type(), allowAsyncOverrideCallback)
|
|
7296
7930
|
diagnostics = append(diagnostics, argDiagnostics...)
|
|
7297
7931
|
if idx < fixedCount {
|
|
7298
7932
|
lowered = o.lowerCallArgForTarget(ctx, arg, params.At(idx).Type(), lowered, overrideCall)
|
|
@@ -7309,11 +7943,11 @@ func (o *LoweringOwner) lowerCallArgs(
|
|
|
7309
7943
|
if signature == nil || !signature.Variadic() ||
|
|
7310
7944
|
isBuiltinCallTarget(ctx, expr.Fun) ||
|
|
7311
7945
|
overrideCall {
|
|
7312
|
-
return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall)
|
|
7946
|
+
return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall, allowAsyncOverrideCallback)
|
|
7313
7947
|
}
|
|
7314
7948
|
params := signature.Params()
|
|
7315
7949
|
if params == nil || params.Len() == 0 {
|
|
7316
|
-
return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall)
|
|
7950
|
+
return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall, allowAsyncOverrideCallback)
|
|
7317
7951
|
}
|
|
7318
7952
|
|
|
7319
7953
|
fixedCount := params.Len() - 1
|
|
@@ -7321,7 +7955,11 @@ func (o *LoweringOwner) lowerCallArgs(
|
|
|
7321
7955
|
var variadicArgs []string
|
|
7322
7956
|
var diagnostics []Diagnostic
|
|
7323
7957
|
for idx, arg := range expr.Args {
|
|
7324
|
-
|
|
7958
|
+
targetType := params.At(fixedCount).Type()
|
|
7959
|
+
if idx < fixedCount {
|
|
7960
|
+
targetType = params.At(idx).Type()
|
|
7961
|
+
}
|
|
7962
|
+
lowered, argDiagnostics := o.lowerCallArgExpr(ctx, arg, targetType, allowAsyncOverrideCallback)
|
|
7325
7963
|
diagnostics = append(diagnostics, argDiagnostics...)
|
|
7326
7964
|
if idx < fixedCount {
|
|
7327
7965
|
lowered = o.lowerCallArgForTarget(ctx, arg, params.At(idx).Type(), lowered, overrideCall)
|
|
@@ -7422,6 +8060,7 @@ func (o *LoweringOwner) lowerFixedCallArgs(
|
|
|
7422
8060
|
exprs []ast.Expr,
|
|
7423
8061
|
signature *types.Signature,
|
|
7424
8062
|
overrideCall bool,
|
|
8063
|
+
allowAsyncOverrideCallback bool,
|
|
7425
8064
|
) ([]string, []Diagnostic) {
|
|
7426
8065
|
var params *types.Tuple
|
|
7427
8066
|
if signature != nil {
|
|
@@ -7430,7 +8069,11 @@ func (o *LoweringOwner) lowerFixedCallArgs(
|
|
|
7430
8069
|
args := make([]string, 0, len(exprs))
|
|
7431
8070
|
var diagnostics []Diagnostic
|
|
7432
8071
|
for idx, expr := range exprs {
|
|
7433
|
-
|
|
8072
|
+
var targetType types.Type
|
|
8073
|
+
if params != nil && idx < params.Len() {
|
|
8074
|
+
targetType = params.At(idx).Type()
|
|
8075
|
+
}
|
|
8076
|
+
lowered, exprDiagnostics := o.lowerCallArgExpr(ctx, expr, targetType, allowAsyncOverrideCallback)
|
|
7434
8077
|
diagnostics = append(diagnostics, exprDiagnostics...)
|
|
7435
8078
|
if params != nil && idx < params.Len() {
|
|
7436
8079
|
lowered = o.lowerCallArgForTarget(ctx, expr, params.At(idx).Type(), lowered, overrideCall)
|
|
@@ -7440,6 +8083,19 @@ func (o *LoweringOwner) lowerFixedCallArgs(
|
|
|
7440
8083
|
return args, diagnostics
|
|
7441
8084
|
}
|
|
7442
8085
|
|
|
8086
|
+
func (o *LoweringOwner) lowerCallArgExpr(
|
|
8087
|
+
ctx lowerFileContext,
|
|
8088
|
+
expr ast.Expr,
|
|
8089
|
+
targetType types.Type,
|
|
8090
|
+
overrideCall bool,
|
|
8091
|
+
) (string, []Diagnostic) {
|
|
8092
|
+
if lit, ok := ast.Unparen(expr).(*ast.FuncLit); ok && targetType != nil {
|
|
8093
|
+
value, _, diagnostics := o.lowerFuncLitForTarget(ctx, lit, targetType, overrideCall)
|
|
8094
|
+
return value, diagnostics
|
|
8095
|
+
}
|
|
8096
|
+
return o.lowerExpr(ctx, expr)
|
|
8097
|
+
}
|
|
8098
|
+
|
|
7443
8099
|
func (o *LoweringOwner) lowerCallArgForTarget(
|
|
7444
8100
|
ctx lowerFileContext,
|
|
7445
8101
|
expr ast.Expr,
|
|
@@ -7636,6 +8292,11 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
7636
8292
|
if value, addressDiagnostics, ok := o.lowerUnsafePointerIntegerExpr(ctx, expr.Args[0]); ok {
|
|
7637
8293
|
return value, append(diagnostics, addressDiagnostics...)
|
|
7638
8294
|
}
|
|
8295
|
+
if isUintptrType(targetType) {
|
|
8296
|
+
// Opaque unsafe pointers have no JS integer address; keep identity-only
|
|
8297
|
+
// uintptr round trips, such as the standard noescape xor-zero pattern, as pointer tokens.
|
|
8298
|
+
return "(" + value + " as any)", diagnostics
|
|
8299
|
+
}
|
|
7639
8300
|
}
|
|
7640
8301
|
if helper, addressDiagnostics, ok := o.lowerReflectHeaderPointerConversion(ctx, targetType, expr.Args[0]); ok {
|
|
7641
8302
|
return helper, append(diagnostics, addressDiagnostics...)
|
|
@@ -7644,6 +8305,9 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
7644
8305
|
return helper, append(diagnostics, addressDiagnostics...)
|
|
7645
8306
|
}
|
|
7646
8307
|
if isUnsafePointerType(targetType) {
|
|
8308
|
+
if value, identityDiagnostics, ok := o.lowerUnsafePointerIdentityExpr(ctx, expr.Args[0]); ok {
|
|
8309
|
+
return "(" + value + " as any)", append(diagnostics, identityDiagnostics...)
|
|
8310
|
+
}
|
|
7647
8311
|
return "(" + value + " as any)", diagnostics
|
|
7648
8312
|
}
|
|
7649
8313
|
if isNilExpr(expr.Args[0]) && isPointerType(targetType) {
|
|
@@ -7794,6 +8458,12 @@ func (o *LoweringOwner) lowerWideIntegerBinaryExpr(ctx lowerFileContext, expr *a
|
|
|
7794
8458
|
case token.AND:
|
|
7795
8459
|
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64And, RuntimeHelperInt64And)) + "(" + left + ", " + right + ")", true
|
|
7796
8460
|
case token.XOR:
|
|
8461
|
+
if isZeroIntegerExpr(ctx, expr.Y) {
|
|
8462
|
+
return left, true
|
|
8463
|
+
}
|
|
8464
|
+
if isZeroIntegerExpr(ctx, expr.X) {
|
|
8465
|
+
return right, true
|
|
8466
|
+
}
|
|
7797
8467
|
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Xor, RuntimeHelperInt64Xor)) + "(" + left + ", " + right + ")", true
|
|
7798
8468
|
case token.OR:
|
|
7799
8469
|
shift, ok := wideLeftShiftExpr(ctx, expr.X)
|
|
@@ -7865,6 +8535,11 @@ func lowIntegerBits(ctx lowerFileContext, expr ast.Expr) (int, bool) {
|
|
|
7865
8535
|
return integerBits(ctx.semPkg.source.TypesInfo.TypeOf(expr))
|
|
7866
8536
|
}
|
|
7867
8537
|
|
|
8538
|
+
func isZeroIntegerExpr(ctx lowerFileContext, expr ast.Expr) bool {
|
|
8539
|
+
value := ctx.semPkg.source.TypesInfo.Types[unwrapParenExpr(expr)].Value
|
|
8540
|
+
return value != nil && value.Kind() == constant.Int && constant.Sign(value) == 0
|
|
8541
|
+
}
|
|
8542
|
+
|
|
7868
8543
|
func shiftMultiplier(amount int) string {
|
|
7869
8544
|
return "(2 ** " + strconv.Itoa(amount) + ")"
|
|
7870
8545
|
}
|
|
@@ -8315,6 +8990,9 @@ func (o *LoweringOwner) lowerFieldSelectionExpr(
|
|
|
8315
8990
|
selection *types.Selection,
|
|
8316
8991
|
address bool,
|
|
8317
8992
|
) (string, []Diagnostic) {
|
|
8993
|
+
if value, diagnostics, ok := o.lowerUnsafeStructFieldSelectionExpr(ctx, expr, selection, address); ok {
|
|
8994
|
+
return value, diagnostics
|
|
8995
|
+
}
|
|
8318
8996
|
receiver, diagnostics := o.lowerFieldReceiverExpr(ctx, expr.X)
|
|
8319
8997
|
receiver = parenthesizeAwaitedExpr(receiver)
|
|
8320
8998
|
index := selection.Index()
|
|
@@ -8353,18 +9031,89 @@ func (o *LoweringOwner) lowerFieldSelectionExpr(
|
|
|
8353
9031
|
typ = pointer.Elem()
|
|
8354
9032
|
}
|
|
8355
9033
|
}
|
|
8356
|
-
|
|
9034
|
+
|
|
9035
|
+
if address {
|
|
9036
|
+
return o.lowerFieldAddressExpr(ctx, receiver, typ, tsStructFieldName(expr.Sel.Name, 0)), diagnostics
|
|
9037
|
+
}
|
|
9038
|
+
return receiver + "." + tsStructFieldName(expr.Sel.Name, 0), diagnostics
|
|
9039
|
+
}
|
|
9040
|
+
|
|
9041
|
+
func (o *LoweringOwner) lowerFieldAddressExpr(ctx lowerFileContext, receiver string, typ types.Type, fieldName string) string {
|
|
9042
|
+
if namedStructType(derefPointerType(typ)) != nil {
|
|
9043
|
+
return receiver + "._fields." + fieldName
|
|
9044
|
+
}
|
|
9045
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperFieldRef) + "(" + receiver + ", " + strconv.Quote(fieldName) + ")"
|
|
9046
|
+
}
|
|
9047
|
+
|
|
9048
|
+
func (o *LoweringOwner) lowerUnsafeStructFieldSelectionExpr(
|
|
9049
|
+
ctx lowerFileContext,
|
|
9050
|
+
expr *ast.SelectorExpr,
|
|
9051
|
+
selection *types.Selection,
|
|
9052
|
+
address bool,
|
|
9053
|
+
) (string, []Diagnostic, bool) {
|
|
9054
|
+
index := selection.Index()
|
|
9055
|
+
if len(index) != 1 {
|
|
9056
|
+
return "", nil, false
|
|
9057
|
+
}
|
|
9058
|
+
targetCall, ok := unwrapParenExpr(expr.X).(*ast.CallExpr)
|
|
9059
|
+
if !ok || len(targetCall.Args) != 1 {
|
|
9060
|
+
return "", nil, false
|
|
9061
|
+
}
|
|
9062
|
+
targetType := typeFromExpr(ctx, targetCall.Fun)
|
|
9063
|
+
if targetType == nil {
|
|
9064
|
+
return "", nil, false
|
|
9065
|
+
}
|
|
9066
|
+
targetPointer, _ := types.Unalias(targetType).Underlying().(*types.Pointer)
|
|
9067
|
+
if targetPointer == nil {
|
|
9068
|
+
return "", nil, false
|
|
9069
|
+
}
|
|
9070
|
+
targetStruct := structUnderlyingType(targetPointer.Elem())
|
|
9071
|
+
if targetStruct == nil || index[0] < 0 || index[0] >= targetStruct.NumFields() {
|
|
9072
|
+
return "", nil, false
|
|
9073
|
+
}
|
|
9074
|
+
unsafeCall, ok := unwrapParenExpr(targetCall.Args[0]).(*ast.CallExpr)
|
|
9075
|
+
if !ok || len(unsafeCall.Args) != 1 || !isUnsafePointerType(typeFromExpr(ctx, unsafeCall.Fun)) {
|
|
9076
|
+
return "", nil, false
|
|
9077
|
+
}
|
|
9078
|
+
sourceType := ctx.semPkg.source.TypesInfo.TypeOf(unsafeCall.Args[0])
|
|
9079
|
+
if sourceType == nil {
|
|
9080
|
+
return "", nil, false
|
|
9081
|
+
}
|
|
9082
|
+
sourcePointer, _ := types.Unalias(sourceType).Underlying().(*types.Pointer)
|
|
9083
|
+
if sourcePointer == nil {
|
|
9084
|
+
return "", nil, false
|
|
9085
|
+
}
|
|
9086
|
+
sourceStruct := structUnderlyingType(sourcePointer.Elem())
|
|
9087
|
+
if sourceStruct == nil || index[0] >= sourceStruct.NumFields() {
|
|
9088
|
+
return "", nil, false
|
|
9089
|
+
}
|
|
9090
|
+
targetField := targetStruct.Field(index[0])
|
|
9091
|
+
sourceField := sourceStruct.Field(index[0])
|
|
9092
|
+
if !unsafeStructFieldLayoutCompatible(targetField, sourceField) {
|
|
9093
|
+
return "", nil, false
|
|
9094
|
+
}
|
|
9095
|
+
receiver, diagnostics := o.lowerFieldReceiverExpr(ctx, unsafeCall.Args[0])
|
|
9096
|
+
fieldName := tsStructFieldName(sourceField.Name(), index[0])
|
|
8357
9097
|
if address {
|
|
8358
|
-
return o.lowerFieldAddressExpr(ctx, receiver,
|
|
9098
|
+
return o.lowerFieldAddressExpr(ctx, receiver, sourcePointer.Elem(), fieldName), diagnostics, true
|
|
8359
9099
|
}
|
|
8360
|
-
return receiver + "." +
|
|
9100
|
+
return receiver + "." + fieldName, diagnostics, true
|
|
8361
9101
|
}
|
|
8362
9102
|
|
|
8363
|
-
func (
|
|
8364
|
-
if
|
|
8365
|
-
return
|
|
9103
|
+
func unsafeStructFieldLayoutCompatible(target *types.Var, source *types.Var) bool {
|
|
9104
|
+
if target == nil || source == nil || target.Name() != source.Name() {
|
|
9105
|
+
return false
|
|
8366
9106
|
}
|
|
8367
|
-
return
|
|
9107
|
+
return unsafeFieldTypeLayoutCompatible(target.Type(), source.Type())
|
|
9108
|
+
}
|
|
9109
|
+
|
|
9110
|
+
func unsafeFieldTypeLayoutCompatible(left types.Type, right types.Type) bool {
|
|
9111
|
+
if types.Identical(left, right) {
|
|
9112
|
+
return true
|
|
9113
|
+
}
|
|
9114
|
+
leftUnderlying := types.Unalias(left).Underlying()
|
|
9115
|
+
rightUnderlying := types.Unalias(right).Underlying()
|
|
9116
|
+
return types.Identical(leftUnderlying, rightUnderlying)
|
|
8368
9117
|
}
|
|
8369
9118
|
|
|
8370
9119
|
func (o *LoweringOwner) lowerMethodValueClosure(
|
|
@@ -8390,7 +9139,12 @@ func (o *LoweringOwner) lowerMethodValueClosure(
|
|
|
8390
9139
|
if includeReceiver {
|
|
8391
9140
|
args = append([]string{"__receiver"}, args...)
|
|
8392
9141
|
}
|
|
8393
|
-
|
|
9142
|
+
closure := "((__receiver) => (" + strings.Join(params, ", ") + ") => " + callee + "(" + strings.Join(args, ", ") + "))(" + receiver + ")"
|
|
9143
|
+
if signature == nil {
|
|
9144
|
+
return closure
|
|
9145
|
+
}
|
|
9146
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperFunctionValue) +
|
|
9147
|
+
"(" + closure + ", " + o.runtimeFunctionTypeInfo(signature, "") + ")"
|
|
8394
9148
|
}
|
|
8395
9149
|
|
|
8396
9150
|
func (o *LoweringOwner) lowerMethodExpressionClosure(ctx lowerFileContext, selection *types.Selection) string {
|
|
@@ -8445,6 +9199,9 @@ func fieldReceiverNeedsVarRefValue(ctx lowerFileContext, expr ast.Expr, obj type
|
|
|
8445
9199
|
return true
|
|
8446
9200
|
}
|
|
8447
9201
|
if ctx.identAliases[obj] != "" {
|
|
9202
|
+
if obj == nil || ctx.model == nil || !ctx.model.needsVarRef[obj] {
|
|
9203
|
+
return false
|
|
9204
|
+
}
|
|
8448
9205
|
return !ctx.identAliasRefs[obj]
|
|
8449
9206
|
}
|
|
8450
9207
|
if ctx.localAliases[obj] != "" {
|
|
@@ -8605,6 +9362,10 @@ func (o *LoweringOwner) lowerAddressExpr(ctx lowerFileContext, expr ast.Expr) (s
|
|
|
8605
9362
|
return receiver + "._fields." + typed.Sel.Name, diagnostics
|
|
8606
9363
|
case *ast.IndexExpr:
|
|
8607
9364
|
return o.lowerIndexAddressExpr(ctx, typed)
|
|
9365
|
+
case *ast.StarExpr:
|
|
9366
|
+
// &*p is the identity address-of-dereference: it yields the original
|
|
9367
|
+
// pointer, not a copy, so emit the pointer expression directly.
|
|
9368
|
+
return o.lowerExpr(ctx, typed.X)
|
|
8608
9369
|
default:
|
|
8609
9370
|
return "undefined", []Diagnostic{loweringUnsupportedAt(ctx, typed, "expression", ctx.semPkg.pkgPath, "unsupported address expression")}
|
|
8610
9371
|
}
|
|
@@ -8696,6 +9457,35 @@ func (o *LoweringOwner) lowerUnsafePointerIntegerExpr(
|
|
|
8696
9457
|
return o.lowerIndexByteAddressIntegerExpr(ctx, call.Args[0])
|
|
8697
9458
|
}
|
|
8698
9459
|
|
|
9460
|
+
func (o *LoweringOwner) lowerUnsafePointerIdentityExpr(
|
|
9461
|
+
ctx lowerFileContext,
|
|
9462
|
+
expr ast.Expr,
|
|
9463
|
+
) (string, []Diagnostic, bool) {
|
|
9464
|
+
expr = unwrapParenExpr(expr)
|
|
9465
|
+
if binary, ok := expr.(*ast.BinaryExpr); ok && binary.Op == token.XOR {
|
|
9466
|
+
switch {
|
|
9467
|
+
case isZeroIntegerExpr(ctx, binary.Y):
|
|
9468
|
+
return o.lowerUnsafePointerIdentityExpr(ctx, binary.X)
|
|
9469
|
+
case isZeroIntegerExpr(ctx, binary.X):
|
|
9470
|
+
return o.lowerUnsafePointerIdentityExpr(ctx, binary.Y)
|
|
9471
|
+
}
|
|
9472
|
+
}
|
|
9473
|
+
call, ok := expr.(*ast.CallExpr)
|
|
9474
|
+
if !ok || len(call.Args) != 1 {
|
|
9475
|
+
return "", nil, false
|
|
9476
|
+
}
|
|
9477
|
+
targetType := typeFromExpr(ctx, call.Fun)
|
|
9478
|
+
sourceType := ctx.semPkg.source.TypesInfo.TypeOf(call.Args[0])
|
|
9479
|
+
if !isUintptrType(targetType) || !isUnsafePointerType(sourceType) {
|
|
9480
|
+
return "", nil, false
|
|
9481
|
+
}
|
|
9482
|
+
if _, _, ok := o.lowerUnsafePointerIntegerExpr(ctx, call.Args[0]); ok {
|
|
9483
|
+
return "", nil, false
|
|
9484
|
+
}
|
|
9485
|
+
value, diagnostics := o.lowerExpr(ctx, call.Args[0])
|
|
9486
|
+
return value, diagnostics, true
|
|
9487
|
+
}
|
|
9488
|
+
|
|
8699
9489
|
func (o *LoweringOwner) lowerIndexAddressIntegerExpr(
|
|
8700
9490
|
ctx lowerFileContext,
|
|
8701
9491
|
expr ast.Expr,
|
|
@@ -8866,6 +9656,9 @@ func (o *LoweringOwner) lowerUnsafeArrayPointerConversion(
|
|
|
8866
9656
|
targetType types.Type,
|
|
8867
9657
|
expr ast.Expr,
|
|
8868
9658
|
) (string, []Diagnostic, bool) {
|
|
9659
|
+
if targetType == nil {
|
|
9660
|
+
return "", nil, false
|
|
9661
|
+
}
|
|
8869
9662
|
targetPointer, _ := types.Unalias(targetType).Underlying().(*types.Pointer)
|
|
8870
9663
|
if targetPointer == nil {
|
|
8871
9664
|
return "", nil, false
|
|
@@ -8874,29 +9667,191 @@ func (o *LoweringOwner) lowerUnsafeArrayPointerConversion(
|
|
|
8874
9667
|
if array == nil {
|
|
8875
9668
|
return "", nil, false
|
|
8876
9669
|
}
|
|
8877
|
-
|
|
8878
|
-
if !ok || len(unsafeCall.Args) != 1 || !isUnsafePointerType(typeFromExpr(ctx, unsafeCall.Fun)) {
|
|
8879
|
-
return "", nil, false
|
|
8880
|
-
}
|
|
8881
|
-
address, ok := unwrapParenExpr(unsafeCall.Args[0]).(*ast.UnaryExpr)
|
|
8882
|
-
if !ok || address.Op != token.AND {
|
|
8883
|
-
return "", nil, false
|
|
8884
|
-
}
|
|
8885
|
-
index, ok := unwrapParenExpr(address.X).(*ast.IndexExpr)
|
|
9670
|
+
ref, sourceType, diagnostics, ok := o.lowerUnsafeArrayPointerSourceRef(ctx, expr)
|
|
8886
9671
|
if !ok {
|
|
8887
9672
|
return "", nil, false
|
|
8888
9673
|
}
|
|
8889
|
-
|
|
8890
|
-
sourceElementSize := goScriptElementByteSize(ctx, indexElementType(ctx.semPkg.source.TypesInfo.TypeOf(index.X)))
|
|
9674
|
+
sourceElementSize := goScriptElementByteSize(ctx, sourceType)
|
|
8891
9675
|
targetElementSize := goScriptElementByteSize(ctx, array.Elem())
|
|
9676
|
+
sourceTypeArg := o.tsTypeFor(ctx, array.Elem())
|
|
9677
|
+
if sourceType != nil {
|
|
9678
|
+
sourceTypeArg = o.tsTypeFor(ctx, sourceType)
|
|
9679
|
+
}
|
|
8892
9680
|
helper := o.runtimeOwner.QualifiedHelper(RuntimeHelperArrayPointerFromIndexRef) +
|
|
8893
|
-
"<" +
|
|
9681
|
+
"<" + sourceTypeArg + ">(" + ref + ", " +
|
|
8894
9682
|
strconv.FormatInt(array.Len(), 10) + ", " +
|
|
8895
9683
|
strconv.FormatInt(sourceElementSize, 10) + ", " +
|
|
8896
9684
|
strconv.FormatInt(targetElementSize, 10) + ")"
|
|
8897
9685
|
return "(" + helper + " as unknown as " + o.tsTypeFor(ctx, targetType) + ")", diagnostics, true
|
|
8898
9686
|
}
|
|
8899
9687
|
|
|
9688
|
+
func (o *LoweringOwner) lowerUnsafeArrayPointerSourceRef(
|
|
9689
|
+
ctx lowerFileContext,
|
|
9690
|
+
expr ast.Expr,
|
|
9691
|
+
) (string, types.Type, []Diagnostic, bool) {
|
|
9692
|
+
if unsafeCall, ok := unwrapParenExpr(expr).(*ast.CallExpr); ok && len(unsafeCall.Args) == 1 {
|
|
9693
|
+
if isUnsafePointerType(typeFromExpr(ctx, unsafeCall.Fun)) {
|
|
9694
|
+
return o.lowerUnsafeArrayPointerAddressSourceRef(ctx, unsafeCall.Args[0])
|
|
9695
|
+
}
|
|
9696
|
+
if arg, ok := unsafePointerIdentityCallArg(ctx, unsafeCall); ok {
|
|
9697
|
+
return o.lowerUnsafeArrayPointerSourceRef(ctx, arg)
|
|
9698
|
+
}
|
|
9699
|
+
}
|
|
9700
|
+
return o.lowerUnsafeArrayPointerAddressSourceRef(ctx, expr)
|
|
9701
|
+
}
|
|
9702
|
+
|
|
9703
|
+
func (o *LoweringOwner) lowerUnsafeArrayPointerAddressSourceRef(
|
|
9704
|
+
ctx lowerFileContext,
|
|
9705
|
+
expr ast.Expr,
|
|
9706
|
+
) (string, types.Type, []Diagnostic, bool) {
|
|
9707
|
+
if source, ok := stringHeaderDataSource(ctx, expr); ok {
|
|
9708
|
+
value, diagnostics := o.lowerExpr(ctx, source)
|
|
9709
|
+
bytes := o.runtimeOwner.QualifiedHelper(RuntimeHelperStringToBytes) + "(" + value + ")"
|
|
9710
|
+
ref := o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexRef) + "(" + bytes + ", 0)"
|
|
9711
|
+
return ref, types.Typ[types.Uint8], diagnostics, true
|
|
9712
|
+
}
|
|
9713
|
+
|
|
9714
|
+
address, ok := unwrapParenExpr(expr).(*ast.UnaryExpr)
|
|
9715
|
+
if !ok || address.Op != token.AND {
|
|
9716
|
+
return "", nil, nil, false
|
|
9717
|
+
}
|
|
9718
|
+
if index, ok := unwrapParenExpr(address.X).(*ast.IndexExpr); ok {
|
|
9719
|
+
ref, diagnostics := o.lowerAddressExpr(ctx, index)
|
|
9720
|
+
return ref, indexElementType(ctx.semPkg.source.TypesInfo.TypeOf(index.X)), diagnostics, true
|
|
9721
|
+
}
|
|
9722
|
+
sourceType := ctx.semPkg.source.TypesInfo.TypeOf(address.X)
|
|
9723
|
+
if isNumericType(sourceType) || isStringType(sourceType) || isComplexType(sourceType) {
|
|
9724
|
+
value, diagnostics := o.lowerExpr(ctx, address.X)
|
|
9725
|
+
ref := o.runtimeOwner.QualifiedHelper(RuntimeHelperIndexRef) + "([" + value + "], 0)"
|
|
9726
|
+
return ref, sourceType, diagnostics, true
|
|
9727
|
+
}
|
|
9728
|
+
ref, diagnostics := o.lowerAddressExpr(ctx, address.X)
|
|
9729
|
+
return ref, sourceType, diagnostics, true
|
|
9730
|
+
}
|
|
9731
|
+
|
|
9732
|
+
func unsafePointerIdentityCallArg(ctx lowerFileContext, call *ast.CallExpr) (ast.Expr, bool) {
|
|
9733
|
+
if call == nil || len(call.Args) != 1 ||
|
|
9734
|
+
!isUnsafePointerType(ctx.semPkg.source.TypesInfo.TypeOf(call)) ||
|
|
9735
|
+
!isUnsafePointerType(ctx.semPkg.source.TypesInfo.TypeOf(call.Args[0])) {
|
|
9736
|
+
return nil, false
|
|
9737
|
+
}
|
|
9738
|
+
fn := calledFunction(ctx.semPkg.source, call.Fun)
|
|
9739
|
+
decl := functionDeclForObject(ctx.semPkg, fn)
|
|
9740
|
+
if decl == nil || decl.Type == nil || decl.Type.Params == nil ||
|
|
9741
|
+
len(decl.Type.Params.List) != 1 || len(decl.Type.Params.List[0].Names) != 1 ||
|
|
9742
|
+
decl.Body == nil {
|
|
9743
|
+
return nil, false
|
|
9744
|
+
}
|
|
9745
|
+
param := objectForIdent(ctx, decl.Type.Params.List[0].Names[0])
|
|
9746
|
+
if param == nil {
|
|
9747
|
+
return nil, false
|
|
9748
|
+
}
|
|
9749
|
+
aliases := make(map[types.Object]bool)
|
|
9750
|
+
for _, stmt := range decl.Body.List {
|
|
9751
|
+
switch typed := stmt.(type) {
|
|
9752
|
+
case *ast.AssignStmt:
|
|
9753
|
+
if !recordUnsafePointerUintptrAlias(ctx, typed, param, aliases) {
|
|
9754
|
+
return nil, false
|
|
9755
|
+
}
|
|
9756
|
+
case *ast.ReturnStmt:
|
|
9757
|
+
if len(typed.Results) == 1 && unsafePointerIdentityReturnExpr(ctx, typed.Results[0], param, aliases) {
|
|
9758
|
+
return call.Args[0], true
|
|
9759
|
+
}
|
|
9760
|
+
return nil, false
|
|
9761
|
+
default:
|
|
9762
|
+
return nil, false
|
|
9763
|
+
}
|
|
9764
|
+
}
|
|
9765
|
+
return nil, false
|
|
9766
|
+
}
|
|
9767
|
+
|
|
9768
|
+
func recordUnsafePointerUintptrAlias(ctx lowerFileContext, stmt *ast.AssignStmt, param types.Object, aliases map[types.Object]bool) bool {
|
|
9769
|
+
if stmt == nil || len(stmt.Lhs) != 1 || len(stmt.Rhs) != 1 {
|
|
9770
|
+
return false
|
|
9771
|
+
}
|
|
9772
|
+
ident, ok := unwrapParenExpr(stmt.Lhs[0]).(*ast.Ident)
|
|
9773
|
+
if !ok || ident.Name == "_" {
|
|
9774
|
+
return false
|
|
9775
|
+
}
|
|
9776
|
+
if !unsafePointerUintptrIdentityExpr(ctx, stmt.Rhs[0], param, aliases) {
|
|
9777
|
+
return false
|
|
9778
|
+
}
|
|
9779
|
+
obj := objectForIdent(ctx, ident)
|
|
9780
|
+
if obj == nil {
|
|
9781
|
+
return false
|
|
9782
|
+
}
|
|
9783
|
+
aliases[obj] = true
|
|
9784
|
+
return true
|
|
9785
|
+
}
|
|
9786
|
+
|
|
9787
|
+
func unsafePointerIdentityReturnExpr(ctx lowerFileContext, expr ast.Expr, param types.Object, aliases map[types.Object]bool) bool {
|
|
9788
|
+
expr = unwrapParenExpr(expr)
|
|
9789
|
+
if ident, ok := expr.(*ast.Ident); ok {
|
|
9790
|
+
return objectForIdent(ctx, ident) == param
|
|
9791
|
+
}
|
|
9792
|
+
call, ok := expr.(*ast.CallExpr)
|
|
9793
|
+
if !ok || len(call.Args) != 1 || !isUnsafePointerType(typeFromExpr(ctx, call.Fun)) {
|
|
9794
|
+
return false
|
|
9795
|
+
}
|
|
9796
|
+
return unsafePointerUintptrIdentityExpr(ctx, call.Args[0], param, aliases)
|
|
9797
|
+
}
|
|
9798
|
+
|
|
9799
|
+
func unsafePointerUintptrIdentityExpr(ctx lowerFileContext, expr ast.Expr, param types.Object, aliases map[types.Object]bool) bool {
|
|
9800
|
+
expr = unwrapParenExpr(expr)
|
|
9801
|
+
if binary, ok := expr.(*ast.BinaryExpr); ok && binary.Op == token.XOR {
|
|
9802
|
+
switch {
|
|
9803
|
+
case isZeroIntegerExpr(ctx, binary.Y):
|
|
9804
|
+
return unsafePointerUintptrIdentityExpr(ctx, binary.X, param, aliases)
|
|
9805
|
+
case isZeroIntegerExpr(ctx, binary.X):
|
|
9806
|
+
return unsafePointerUintptrIdentityExpr(ctx, binary.Y, param, aliases)
|
|
9807
|
+
}
|
|
9808
|
+
return false
|
|
9809
|
+
}
|
|
9810
|
+
if ident, ok := expr.(*ast.Ident); ok {
|
|
9811
|
+
obj := objectForIdent(ctx, ident)
|
|
9812
|
+
return obj == param || aliases[obj]
|
|
9813
|
+
}
|
|
9814
|
+
call, ok := expr.(*ast.CallExpr)
|
|
9815
|
+
if !ok || len(call.Args) != 1 || !isUintptrType(typeFromExpr(ctx, call.Fun)) {
|
|
9816
|
+
return false
|
|
9817
|
+
}
|
|
9818
|
+
ident, ok := unwrapParenExpr(call.Args[0]).(*ast.Ident)
|
|
9819
|
+
return ok && objectForIdent(ctx, ident) == param
|
|
9820
|
+
}
|
|
9821
|
+
|
|
9822
|
+
func stringHeaderDataSource(ctx lowerFileContext, expr ast.Expr) (ast.Expr, bool) {
|
|
9823
|
+
selector, ok := unwrapParenExpr(expr).(*ast.SelectorExpr)
|
|
9824
|
+
if !ok || selector.Sel.Name != "Data" {
|
|
9825
|
+
return nil, false
|
|
9826
|
+
}
|
|
9827
|
+
call, ok := unwrapParenExpr(selector.X).(*ast.CallExpr)
|
|
9828
|
+
if !ok || len(call.Args) != 1 {
|
|
9829
|
+
return nil, false
|
|
9830
|
+
}
|
|
9831
|
+
targetType := typeFromExpr(ctx, call.Fun)
|
|
9832
|
+
if targetType == nil {
|
|
9833
|
+
return nil, false
|
|
9834
|
+
}
|
|
9835
|
+
targetPointer, _ := types.Unalias(targetType).Underlying().(*types.Pointer)
|
|
9836
|
+
if targetPointer == nil {
|
|
9837
|
+
return nil, false
|
|
9838
|
+
}
|
|
9839
|
+
header, _ := types.Unalias(targetPointer.Elem()).(*types.Named)
|
|
9840
|
+
if header == nil || header.Obj() == nil || header.Obj().Pkg() == nil ||
|
|
9841
|
+
header.Obj().Pkg().Path() != "reflect" || header.Obj().Name() != "StringHeader" {
|
|
9842
|
+
return nil, false
|
|
9843
|
+
}
|
|
9844
|
+
unsafeCall, ok := unwrapParenExpr(call.Args[0]).(*ast.CallExpr)
|
|
9845
|
+
if !ok || len(unsafeCall.Args) != 1 || !isUnsafePointerType(typeFromExpr(ctx, unsafeCall.Fun)) {
|
|
9846
|
+
return nil, false
|
|
9847
|
+
}
|
|
9848
|
+
address, ok := unwrapParenExpr(unsafeCall.Args[0]).(*ast.UnaryExpr)
|
|
9849
|
+
if !ok || address.Op != token.AND || !isStringType(ctx.semPkg.source.TypesInfo.TypeOf(address.X)) {
|
|
9850
|
+
return nil, false
|
|
9851
|
+
}
|
|
9852
|
+
return address.X, true
|
|
9853
|
+
}
|
|
9854
|
+
|
|
8900
9855
|
func (o *LoweringOwner) lowerAddressedValueRef(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
8901
9856
|
if ident, ok := unwrapParenExpr(expr).(*ast.Ident); ok {
|
|
8902
9857
|
if obj := objectForIdent(ctx, ident); obj != nil && ctx.model.needsVarRef[obj] {
|
|
@@ -9474,7 +10429,11 @@ func (o *LoweringOwner) lowerMapCompositeLit(
|
|
|
9474
10429
|
value = o.lowerValueForTarget(ctx, keyed.Value, mapType.Elem(), value)
|
|
9475
10430
|
entries = append(entries, "["+key+", "+value+"]")
|
|
9476
10431
|
}
|
|
9477
|
-
return "new
|
|
10432
|
+
return "new " + tsNativeMapType(o.tsTypeFor(ctx, mapType.Key()), o.tsTypeFor(ctx, mapType.Elem())) + "([" + strings.Join(entries, ", ") + "])", diagnostics
|
|
10433
|
+
}
|
|
10434
|
+
|
|
10435
|
+
func tsNativeMapType(keyType, elemType string) string {
|
|
10436
|
+
return "globalThis.Map<" + keyType + ", " + elemType + ">"
|
|
9478
10437
|
}
|
|
9479
10438
|
|
|
9480
10439
|
func (o *LoweringOwner) lowerTypeAssertExpr(ctx lowerFileContext, expr *ast.TypeAssertExpr) (string, []Diagnostic) {
|
|
@@ -9511,7 +10470,11 @@ func (o *LoweringOwner) lowerMapGetTuple(ctx lowerFileContext, expr *ast.IndexEx
|
|
|
9511
10470
|
mapType, _ := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(expr.X)).Underlying().(*types.Map)
|
|
9512
10471
|
defaultValue := "undefined"
|
|
9513
10472
|
if mapType != nil {
|
|
10473
|
+
index = o.lowerValueForTarget(ctx, expr.Index, mapType.Key(), index)
|
|
9514
10474
|
defaultValue = o.lowerZeroValueExprFor(ctx, mapType.Elem())
|
|
10475
|
+
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMapGet) +
|
|
10476
|
+
"<" + o.tsTypeFor(ctx, mapType.Key()) + ", " + o.tsTypeFor(ctx, mapType.Elem()) + ", " + o.tsTypeFor(ctx, mapType.Elem()) + ">(" +
|
|
10477
|
+
target + ", " + index + ", " + defaultValue + ")"
|
|
9515
10478
|
}
|
|
9516
10479
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMapGet) + "(" + target + ", " + index + ", " + defaultValue + ")"
|
|
9517
10480
|
}
|
|
@@ -10401,7 +11364,7 @@ func (o *LoweringOwner) tsTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
|
10401
11364
|
case *types.Slice:
|
|
10402
11365
|
return "$.Slice<" + o.tsSliceElemTypeFor(ctx, typed.Elem()) + ">"
|
|
10403
11366
|
case *types.Map:
|
|
10404
|
-
return
|
|
11367
|
+
return tsNativeMapType(o.tsTypeFor(ctx, typed.Key()), o.tsTypeFor(ctx, typed.Elem())) + " | null"
|
|
10405
11368
|
case *types.Chan:
|
|
10406
11369
|
return "$.Channel<" + o.tsTypeFor(ctx, typed.Elem()) + "> | null"
|
|
10407
11370
|
case *types.Struct:
|
|
@@ -10420,6 +11383,12 @@ func (o *LoweringOwner) tsTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
|
10420
11383
|
if !ctx.canReferenceNamedType(named) {
|
|
10421
11384
|
return "any"
|
|
10422
11385
|
}
|
|
11386
|
+
if _, ok := named.Underlying().(*types.Interface); ok {
|
|
11387
|
+
return "$.VarRef<" + o.tsTypeFor(ctx, typed.Elem()) + "> | null"
|
|
11388
|
+
}
|
|
11389
|
+
if _, ok := types.Unalias(named.Underlying()).(*types.Signature); ok {
|
|
11390
|
+
return "$.VarRef<" + o.tsTypeFor(ctx, typed.Elem()) + "> | null"
|
|
11391
|
+
}
|
|
10423
11392
|
return "$.VarRef<" + o.namedTypeExpr(ctx, named) + "> | null"
|
|
10424
11393
|
}
|
|
10425
11394
|
if named := namedStructType(typed.Elem()); named != nil {
|
|
@@ -10462,6 +11431,9 @@ func (o *LoweringOwner) tsNonNilTypeFor(ctx lowerFileContext, typ types.Type) st
|
|
|
10462
11431
|
return "Exclude<$.GoError, null>"
|
|
10463
11432
|
}
|
|
10464
11433
|
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
11434
|
+
if crossPackageUnexportedNamedType(ctx, named) {
|
|
11435
|
+
return "any"
|
|
11436
|
+
}
|
|
10465
11437
|
if _, ok := named.Underlying().(*types.Interface); ok {
|
|
10466
11438
|
if !ctx.canReferenceNamedType(named) {
|
|
10467
11439
|
return "any"
|
|
@@ -10788,7 +11760,7 @@ func isPointerToStructType(typ types.Type) bool {
|
|
|
10788
11760
|
if !ok {
|
|
10789
11761
|
return false
|
|
10790
11762
|
}
|
|
10791
|
-
return
|
|
11763
|
+
return structUnderlyingType(pointer.Elem()) != nil
|
|
10792
11764
|
}
|
|
10793
11765
|
|
|
10794
11766
|
func derefPointerType(typ types.Type) types.Type {
|
|
@@ -10865,6 +11837,9 @@ func isChannelType(typ types.Type) bool {
|
|
|
10865
11837
|
}
|
|
10866
11838
|
|
|
10867
11839
|
func isComplexType(typ types.Type) bool {
|
|
11840
|
+
if typ == nil {
|
|
11841
|
+
return false
|
|
11842
|
+
}
|
|
10868
11843
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10869
11844
|
return ok && basic.Info()&types.IsComplex != 0
|
|
10870
11845
|
}
|
|
@@ -10878,10 +11853,21 @@ func isPointerType(typ types.Type) bool {
|
|
|
10878
11853
|
}
|
|
10879
11854
|
|
|
10880
11855
|
func isUnsafePointerType(typ types.Type) bool {
|
|
11856
|
+
if typ == nil {
|
|
11857
|
+
return false
|
|
11858
|
+
}
|
|
10881
11859
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10882
11860
|
return ok && basic.Kind() == types.UnsafePointer
|
|
10883
11861
|
}
|
|
10884
11862
|
|
|
11863
|
+
func isUintptrType(typ types.Type) bool {
|
|
11864
|
+
if typ == nil {
|
|
11865
|
+
return false
|
|
11866
|
+
}
|
|
11867
|
+
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
11868
|
+
return ok && basic.Kind() == types.Uintptr
|
|
11869
|
+
}
|
|
11870
|
+
|
|
10885
11871
|
func channelDirectionString(dir types.ChanDir) string {
|
|
10886
11872
|
switch dir {
|
|
10887
11873
|
case types.SendOnly:
|
|
@@ -10909,21 +11895,33 @@ func unwrapParenExpr(expr ast.Expr) ast.Expr {
|
|
|
10909
11895
|
}
|
|
10910
11896
|
|
|
10911
11897
|
func isStringType(typ types.Type) bool {
|
|
11898
|
+
if typ == nil {
|
|
11899
|
+
return false
|
|
11900
|
+
}
|
|
10912
11901
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10913
11902
|
return ok && basic.Info()&types.IsString != 0
|
|
10914
11903
|
}
|
|
10915
11904
|
|
|
10916
11905
|
func isNumericType(typ types.Type) bool {
|
|
11906
|
+
if typ == nil {
|
|
11907
|
+
return false
|
|
11908
|
+
}
|
|
10917
11909
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10918
11910
|
return ok && basic.Info()&types.IsNumeric != 0
|
|
10919
11911
|
}
|
|
10920
11912
|
|
|
10921
11913
|
func isIntegerType(typ types.Type) bool {
|
|
11914
|
+
if typ == nil {
|
|
11915
|
+
return false
|
|
11916
|
+
}
|
|
10922
11917
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10923
11918
|
return ok && basic.Info()&types.IsInteger != 0
|
|
10924
11919
|
}
|
|
10925
11920
|
|
|
10926
11921
|
func isFloatType(typ types.Type) bool {
|
|
11922
|
+
if typ == nil {
|
|
11923
|
+
return false
|
|
11924
|
+
}
|
|
10927
11925
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10928
11926
|
return ok && basic.Info()&types.IsFloat != 0
|
|
10929
11927
|
}
|
|
@@ -11097,7 +12095,102 @@ func (o *LoweringOwner) functionAsync(ctx lowerFileContext, fn *types.Func) bool
|
|
|
11097
12095
|
if fn == nil || ctx.model == nil {
|
|
11098
12096
|
return false
|
|
11099
12097
|
}
|
|
11100
|
-
|
|
12098
|
+
if ctx.model.functionAsync(fn) {
|
|
12099
|
+
return true
|
|
12100
|
+
}
|
|
12101
|
+
return o.functionReferencesAsyncLazyPackageVar(ctx, fn, make(map[*types.Func]bool))
|
|
12102
|
+
}
|
|
12103
|
+
|
|
12104
|
+
func (o *LoweringOwner) functionReferencesAsyncLazyPackageVar(
|
|
12105
|
+
ctx lowerFileContext,
|
|
12106
|
+
fn *types.Func,
|
|
12107
|
+
seen map[*types.Func]bool,
|
|
12108
|
+
) bool {
|
|
12109
|
+
fn = functionOriginOrSelf(fn)
|
|
12110
|
+
if fn == nil || ctx.model == nil {
|
|
12111
|
+
return false
|
|
12112
|
+
}
|
|
12113
|
+
if cached, ok := ctx.asyncLazyFunctionCache[fn]; ok {
|
|
12114
|
+
return cached
|
|
12115
|
+
}
|
|
12116
|
+
if ctx.asyncLazyFunctionVisiting != nil {
|
|
12117
|
+
if ctx.asyncLazyFunctionVisiting[fn] {
|
|
12118
|
+
return false
|
|
12119
|
+
}
|
|
12120
|
+
ctx.asyncLazyFunctionVisiting[fn] = true
|
|
12121
|
+
defer delete(ctx.asyncLazyFunctionVisiting, fn)
|
|
12122
|
+
} else {
|
|
12123
|
+
if seen[fn] {
|
|
12124
|
+
return false
|
|
12125
|
+
}
|
|
12126
|
+
seen[fn] = true
|
|
12127
|
+
}
|
|
12128
|
+
references := false
|
|
12129
|
+
defer func() {
|
|
12130
|
+
if ctx.asyncLazyFunctionCache != nil {
|
|
12131
|
+
ctx.asyncLazyFunctionCache[fn] = references
|
|
12132
|
+
}
|
|
12133
|
+
}()
|
|
12134
|
+
if fn.Pkg() == nil {
|
|
12135
|
+
return false
|
|
12136
|
+
}
|
|
12137
|
+
semPkg := ctx.model.packages[fn.Pkg().Path()]
|
|
12138
|
+
if semPkg == nil || semPkg.source == nil {
|
|
12139
|
+
return false
|
|
12140
|
+
}
|
|
12141
|
+
decl := functionDeclForObject(semPkg, fn)
|
|
12142
|
+
if decl == nil || decl.Body == nil {
|
|
12143
|
+
return false
|
|
12144
|
+
}
|
|
12145
|
+
analysisCtx := lowerFileContext{
|
|
12146
|
+
model: ctx.model,
|
|
12147
|
+
semPkg: semPkg,
|
|
12148
|
+
lazyPackageVarsByPkg: ctx.lazyPackageVarsByPkg,
|
|
12149
|
+
asyncLazyFunctionCache: ctx.asyncLazyFunctionCache,
|
|
12150
|
+
asyncLazyFunctionVisiting: ctx.asyncLazyFunctionVisiting,
|
|
12151
|
+
topLevel: true,
|
|
12152
|
+
}
|
|
12153
|
+
ast.Inspect(decl.Body, func(node ast.Node) bool {
|
|
12154
|
+
if references {
|
|
12155
|
+
return false
|
|
12156
|
+
}
|
|
12157
|
+
if _, ok := node.(*ast.FuncLit); ok {
|
|
12158
|
+
return false
|
|
12159
|
+
}
|
|
12160
|
+
if ident, ok := node.(*ast.Ident); ok {
|
|
12161
|
+
if o.objectIsAsyncLazyPackageVar(analysisCtx, semPkg.source.TypesInfo.Uses[ident]) {
|
|
12162
|
+
references = true
|
|
12163
|
+
return false
|
|
12164
|
+
}
|
|
12165
|
+
}
|
|
12166
|
+
if selector, ok := node.(*ast.SelectorExpr); ok {
|
|
12167
|
+
if o.objectIsAsyncLazyPackageVar(analysisCtx, semPkg.source.TypesInfo.Uses[selector.Sel]) {
|
|
12168
|
+
references = true
|
|
12169
|
+
return false
|
|
12170
|
+
}
|
|
12171
|
+
}
|
|
12172
|
+
call, ok := node.(*ast.CallExpr)
|
|
12173
|
+
if !ok {
|
|
12174
|
+
return true
|
|
12175
|
+
}
|
|
12176
|
+
if o.functionReferencesAsyncLazyPackageVar(ctx, calledFunction(semPkg.source, call.Fun), seen) {
|
|
12177
|
+
references = true
|
|
12178
|
+
return false
|
|
12179
|
+
}
|
|
12180
|
+
return true
|
|
12181
|
+
})
|
|
12182
|
+
return references
|
|
12183
|
+
}
|
|
12184
|
+
|
|
12185
|
+
func (o *LoweringOwner) objectIsAsyncLazyPackageVar(ctx lowerFileContext, obj types.Object) bool {
|
|
12186
|
+
varObj, _ := obj.(*types.Var)
|
|
12187
|
+
if varObj == nil || varObj.Pkg() == nil {
|
|
12188
|
+
return false
|
|
12189
|
+
}
|
|
12190
|
+
if !o.packageVarIsLazy(ctx, varObj) && !o.packageVarNameIsLazy(ctx, varObj.Pkg().Path(), varObj.Name()) {
|
|
12191
|
+
return false
|
|
12192
|
+
}
|
|
12193
|
+
return o.packageVarHasAsyncLazyInit(ctx, varObj)
|
|
11101
12194
|
}
|
|
11102
12195
|
|
|
11103
12196
|
func (o *LoweringOwner) callNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool {
|