goscript 0.2.4 → 0.2.6
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 +1238 -194
- package/compiler/lowering_bench_test.go +4 -0
- package/compiler/override-facts.go +1 -1
- 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 +241 -15
- 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/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/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/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/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/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 +3 -3
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)
|
|
@@ -1853,42 +1937,395 @@ func initializerReferencesLaterPackageVar(
|
|
|
1853
1937
|
return references
|
|
1854
1938
|
}
|
|
1855
1939
|
|
|
1856
|
-
func initializerCallsFunctionReferencingLaterPackageVar(
|
|
1940
|
+
func initializerCallsFunctionReferencingLaterPackageVar(
|
|
1941
|
+
semPkg *semanticPackage,
|
|
1942
|
+
varOrder map[types.Object]int,
|
|
1943
|
+
current types.Object,
|
|
1944
|
+
expr ast.Expr,
|
|
1945
|
+
) bool {
|
|
1946
|
+
currentIdx, ok := varOrder[current]
|
|
1947
|
+
if !ok {
|
|
1948
|
+
return false
|
|
1949
|
+
}
|
|
1950
|
+
references := false
|
|
1951
|
+
ast.Inspect(expr, func(node ast.Node) bool {
|
|
1952
|
+
if references {
|
|
1953
|
+
return false
|
|
1954
|
+
}
|
|
1955
|
+
call, ok := node.(*ast.CallExpr)
|
|
1956
|
+
if !ok {
|
|
1957
|
+
return true
|
|
1958
|
+
}
|
|
1959
|
+
fn := calledFunction(semPkg.source, call.Fun)
|
|
1960
|
+
if fn == nil || fn.Pkg() == nil || fn.Pkg().Path() != semPkg.pkgPath {
|
|
1961
|
+
return true
|
|
1962
|
+
}
|
|
1963
|
+
if functionReferencesLaterPackageVar(semPkg, varOrder, currentIdx, fn, nil) {
|
|
1964
|
+
references = true
|
|
1965
|
+
return false
|
|
1966
|
+
}
|
|
1967
|
+
return true
|
|
1968
|
+
})
|
|
1969
|
+
return references
|
|
1970
|
+
}
|
|
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
|
+
|
|
2049
|
+
func functionReferencesLaterPackageVar(
|
|
2050
|
+
semPkg *semanticPackage,
|
|
2051
|
+
varOrder map[types.Object]int,
|
|
2052
|
+
currentIdx int,
|
|
2053
|
+
fn *types.Func,
|
|
2054
|
+
seen map[*types.Func]bool,
|
|
2055
|
+
) bool {
|
|
2056
|
+
if fn == nil {
|
|
2057
|
+
return false
|
|
2058
|
+
}
|
|
2059
|
+
if seen == nil {
|
|
2060
|
+
seen = make(map[*types.Func]bool)
|
|
2061
|
+
}
|
|
2062
|
+
if seen[fn] {
|
|
2063
|
+
return false
|
|
2064
|
+
}
|
|
2065
|
+
seen[fn] = true
|
|
2066
|
+
fnDecl := functionDeclForObject(semPkg, fn)
|
|
2067
|
+
if fnDecl == nil || fnDecl.Body == nil {
|
|
2068
|
+
return false
|
|
2069
|
+
}
|
|
2070
|
+
references := false
|
|
2071
|
+
ast.Inspect(fnDecl.Body, func(node ast.Node) bool {
|
|
2072
|
+
if references {
|
|
2073
|
+
return false
|
|
2074
|
+
}
|
|
2075
|
+
if _, ok := node.(*ast.FuncLit); ok {
|
|
2076
|
+
return false
|
|
2077
|
+
}
|
|
2078
|
+
if ident, ok := node.(*ast.Ident); ok {
|
|
2079
|
+
if obj, ok := semPkg.source.TypesInfo.Uses[ident].(*types.Var); ok &&
|
|
2080
|
+
obj.Pkg() != nil && obj.Pkg().Path() == semPkg.pkgPath {
|
|
2081
|
+
if idx, ok := varOrder[obj]; ok && idx > currentIdx {
|
|
2082
|
+
references = true
|
|
2083
|
+
return false
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
if call, ok := node.(*ast.CallExpr); ok {
|
|
2088
|
+
called := calledFunction(semPkg.source, call.Fun)
|
|
2089
|
+
if called != nil && called.Pkg() != nil && called.Pkg().Path() == semPkg.pkgPath &&
|
|
2090
|
+
functionReferencesLaterPackageVar(semPkg, varOrder, currentIdx, called, seen) {
|
|
2091
|
+
references = true
|
|
2092
|
+
return false
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
return true
|
|
2096
|
+
})
|
|
2097
|
+
return references
|
|
2098
|
+
}
|
|
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(
|
|
1857
2285
|
semPkg *semanticPackage,
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
2286
|
+
declFiles map[types.Object]string,
|
|
2287
|
+
ident *ast.Ident,
|
|
2288
|
+
sourcePath string,
|
|
1861
2289
|
) bool {
|
|
1862
|
-
|
|
1863
|
-
if !ok {
|
|
2290
|
+
if tv, ok := semPkg.source.TypesInfo.Types[ident]; ok && !tv.IsValue() {
|
|
1864
2291
|
return false
|
|
1865
2292
|
}
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
if functionReferencesLaterPackageVar(semPkg, varOrder, currentIdx, fn, nil) {
|
|
1880
|
-
references = true
|
|
1881
|
-
return false
|
|
1882
|
-
}
|
|
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 {
|
|
1883
2306
|
return true
|
|
1884
|
-
}
|
|
1885
|
-
|
|
2307
|
+
}
|
|
2308
|
+
if selection := semPkg.source.TypesInfo.Selections[selector]; selection != nil {
|
|
2309
|
+
return declFiles[selection.Obj()] == sourcePath
|
|
2310
|
+
}
|
|
2311
|
+
return false
|
|
1886
2312
|
}
|
|
1887
2313
|
|
|
1888
|
-
func
|
|
2314
|
+
func typeReferencesSourceFile(
|
|
1889
2315
|
semPkg *semanticPackage,
|
|
1890
|
-
|
|
1891
|
-
|
|
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,
|
|
1892
2329
|
fn *types.Func,
|
|
1893
2330
|
seen map[*types.Func]bool,
|
|
1894
2331
|
) bool {
|
|
@@ -1914,10 +2351,16 @@ func functionReferencesLaterPackageVar(
|
|
|
1914
2351
|
if _, ok := node.(*ast.FuncLit); ok {
|
|
1915
2352
|
return false
|
|
1916
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
|
+
}
|
|
1917
2360
|
if ident, ok := node.(*ast.Ident); ok {
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
if
|
|
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 {
|
|
1921
2364
|
references = true
|
|
1922
2365
|
return false
|
|
1923
2366
|
}
|
|
@@ -1926,7 +2369,7 @@ func functionReferencesLaterPackageVar(
|
|
|
1926
2369
|
if call, ok := node.(*ast.CallExpr); ok {
|
|
1927
2370
|
called := calledFunction(semPkg.source, call.Fun)
|
|
1928
2371
|
if called != nil && called.Pkg() != nil && called.Pkg().Path() == semPkg.pkgPath &&
|
|
1929
|
-
|
|
2372
|
+
functionReferencesOtherFileObject(semPkg, declFiles, sourcePath, called, seen) {
|
|
1930
2373
|
references = true
|
|
1931
2374
|
return false
|
|
1932
2375
|
}
|
|
@@ -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:
|
|
@@ -6868,6 +7439,21 @@ func (o *LoweringOwner) lowerFuncLitWithAsyncCalls(
|
|
|
6868
7439
|
lit *ast.FuncLit,
|
|
6869
7440
|
allowAsyncCalls bool,
|
|
6870
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) {
|
|
6871
7457
|
signature, _ := ctx.semPkg.source.TypesInfo.TypeOf(lit).(*types.Signature)
|
|
6872
7458
|
deferState := &loweredDeferState{}
|
|
6873
7459
|
bodyCtx := ctx.withSignature(signature).withAsyncFunction(false).withDeferState(deferState).withoutRangeBranch()
|
|
@@ -6897,8 +7483,7 @@ func (o *LoweringOwner) lowerFuncLitWithAsyncCalls(
|
|
|
6897
7483
|
function := prefix + "(" + renderLoweredParams(params) + "): " +
|
|
6898
7484
|
asyncResultType(o.tsSignatureResultFor(ctx, signature), async) + " => {\n" +
|
|
6899
7485
|
rendered.String() + "}"
|
|
6900
|
-
return
|
|
6901
|
-
"(" + function + ", " + o.runtimeFunctionTypeInfo(signature, "") + ")", async, diagnostics
|
|
7486
|
+
return function, async, signature, diagnostics
|
|
6902
7487
|
}
|
|
6903
7488
|
|
|
6904
7489
|
func renderLoweredParams(params []loweredParam) string {
|
|
@@ -6997,6 +7582,9 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
|
|
|
6997
7582
|
return constValue
|
|
6998
7583
|
}
|
|
6999
7584
|
}
|
|
7585
|
+
if imported, ok := o.lowerImportedIdent(ctx, obj, value, raw); ok {
|
|
7586
|
+
return imported
|
|
7587
|
+
}
|
|
7000
7588
|
if alias := ctx.localAliases[obj]; alias != "" {
|
|
7001
7589
|
if ctx.lazyPackageVars[obj] {
|
|
7002
7590
|
lazyValue := alias + "." + packageVarGetterName(value) + "()"
|
|
@@ -7029,6 +7617,29 @@ func (o *LoweringOwner) lowerIdent(ctx lowerFileContext, ident *ast.Ident, raw b
|
|
|
7029
7617
|
return value
|
|
7030
7618
|
}
|
|
7031
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
|
+
|
|
7032
7643
|
func (o *LoweringOwner) lowerPackageVarReadValue(ctx lowerFileContext, obj types.Object, value string) string {
|
|
7033
7644
|
if obj == nil || ctx.model == nil || !ctx.model.needsVarRef[obj] {
|
|
7034
7645
|
return value
|
|
@@ -7103,6 +7714,17 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
7103
7714
|
}
|
|
7104
7715
|
|
|
7105
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
|
+
}
|
|
7106
7728
|
|
|
7107
7729
|
switch fun := expr.Fun.(type) {
|
|
7108
7730
|
case *ast.Ident:
|
|
@@ -7260,16 +7882,6 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
7260
7882
|
ctx.deferState.async = true
|
|
7261
7883
|
}
|
|
7262
7884
|
return o.awaitCallIfNeeded(ctx, fun, call), append(diagnostics, calleeDiagnostics...)
|
|
7263
|
-
case *ast.FuncLit:
|
|
7264
|
-
callee, async, calleeDiagnostics := o.lowerFuncLit(ctx, fun)
|
|
7265
|
-
call := "(" + callee + ")(" + strings.Join(args, ", ") + ")"
|
|
7266
|
-
if async {
|
|
7267
|
-
call = "await " + call
|
|
7268
|
-
if ctx.deferState != nil {
|
|
7269
|
-
ctx.deferState.async = true
|
|
7270
|
-
}
|
|
7271
|
-
}
|
|
7272
|
-
return call, append(diagnostics, calleeDiagnostics...)
|
|
7273
7885
|
default:
|
|
7274
7886
|
if callTargetSignature(ctx, expr.Fun) != nil {
|
|
7275
7887
|
callee, calleeDiagnostics := o.lowerExpr(ctx, expr.Fun)
|
|
@@ -7680,6 +8292,11 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
7680
8292
|
if value, addressDiagnostics, ok := o.lowerUnsafePointerIntegerExpr(ctx, expr.Args[0]); ok {
|
|
7681
8293
|
return value, append(diagnostics, addressDiagnostics...)
|
|
7682
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
|
+
}
|
|
7683
8300
|
}
|
|
7684
8301
|
if helper, addressDiagnostics, ok := o.lowerReflectHeaderPointerConversion(ctx, targetType, expr.Args[0]); ok {
|
|
7685
8302
|
return helper, append(diagnostics, addressDiagnostics...)
|
|
@@ -7688,6 +8305,9 @@ func (o *LoweringOwner) lowerConversionExpr(
|
|
|
7688
8305
|
return helper, append(diagnostics, addressDiagnostics...)
|
|
7689
8306
|
}
|
|
7690
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
|
+
}
|
|
7691
8311
|
return "(" + value + " as any)", diagnostics
|
|
7692
8312
|
}
|
|
7693
8313
|
if isNilExpr(expr.Args[0]) && isPointerType(targetType) {
|
|
@@ -7838,6 +8458,12 @@ func (o *LoweringOwner) lowerWideIntegerBinaryExpr(ctx lowerFileContext, expr *a
|
|
|
7838
8458
|
case token.AND:
|
|
7839
8459
|
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64And, RuntimeHelperInt64And)) + "(" + left + ", " + right + ")", true
|
|
7840
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
|
+
}
|
|
7841
8467
|
return o.runtimeOwner.QualifiedHelper(wideIntegerHelper(signed, RuntimeHelperUint64Xor, RuntimeHelperInt64Xor)) + "(" + left + ", " + right + ")", true
|
|
7842
8468
|
case token.OR:
|
|
7843
8469
|
shift, ok := wideLeftShiftExpr(ctx, expr.X)
|
|
@@ -7909,6 +8535,11 @@ func lowIntegerBits(ctx lowerFileContext, expr ast.Expr) (int, bool) {
|
|
|
7909
8535
|
return integerBits(ctx.semPkg.source.TypesInfo.TypeOf(expr))
|
|
7910
8536
|
}
|
|
7911
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
|
+
|
|
7912
8543
|
func shiftMultiplier(amount int) string {
|
|
7913
8544
|
return "(2 ** " + strconv.Itoa(amount) + ")"
|
|
7914
8545
|
}
|
|
@@ -8359,6 +8990,9 @@ func (o *LoweringOwner) lowerFieldSelectionExpr(
|
|
|
8359
8990
|
selection *types.Selection,
|
|
8360
8991
|
address bool,
|
|
8361
8992
|
) (string, []Diagnostic) {
|
|
8993
|
+
if value, diagnostics, ok := o.lowerUnsafeStructFieldSelectionExpr(ctx, expr, selection, address); ok {
|
|
8994
|
+
return value, diagnostics
|
|
8995
|
+
}
|
|
8362
8996
|
receiver, diagnostics := o.lowerFieldReceiverExpr(ctx, expr.X)
|
|
8363
8997
|
receiver = parenthesizeAwaitedExpr(receiver)
|
|
8364
8998
|
index := selection.Index()
|
|
@@ -8369,46 +9003,117 @@ func (o *LoweringOwner) lowerFieldSelectionExpr(
|
|
|
8369
9003
|
}
|
|
8370
9004
|
return receiver + "." + fieldName, diagnostics
|
|
8371
9005
|
}
|
|
8372
|
-
|
|
8373
|
-
typ := derefPointerType(ctx.semPkg.source.TypesInfo.TypeOf(expr.X))
|
|
8374
|
-
for idx, fieldIndex := range index {
|
|
8375
|
-
structType := structUnderlyingType(typ)
|
|
8376
|
-
if structType == nil || fieldIndex < 0 || fieldIndex >= structType.NumFields() {
|
|
8377
|
-
fieldName := tsStructFieldName(expr.Sel.Name, 0)
|
|
8378
|
-
if address {
|
|
8379
|
-
return receiver + "._fields." + fieldName, diagnostics
|
|
8380
|
-
}
|
|
8381
|
-
return receiver + "." + fieldName, diagnostics
|
|
8382
|
-
}
|
|
8383
|
-
field := structType.Field(fieldIndex)
|
|
8384
|
-
name := tsStructFieldName(field.Name(), fieldIndex)
|
|
8385
|
-
if idx == len(index)-1 {
|
|
8386
|
-
if address {
|
|
8387
|
-
return o.lowerFieldAddressExpr(ctx, receiver, typ, name), diagnostics
|
|
8388
|
-
}
|
|
8389
|
-
return receiver + "." + name, diagnostics
|
|
8390
|
-
}
|
|
8391
|
-
|
|
8392
|
-
receiver += "." + name
|
|
8393
|
-
typ = field.Type()
|
|
8394
|
-
if pointer, ok := types.Unalias(typ).Underlying().(*types.Pointer); ok {
|
|
8395
|
-
receiver = o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
8396
|
-
"<" + o.tsTypeFor(ctx, pointer.Elem()) + ">(" + receiver + ")"
|
|
8397
|
-
typ = pointer.Elem()
|
|
8398
|
-
}
|
|
9006
|
+
|
|
9007
|
+
typ := derefPointerType(ctx.semPkg.source.TypesInfo.TypeOf(expr.X))
|
|
9008
|
+
for idx, fieldIndex := range index {
|
|
9009
|
+
structType := structUnderlyingType(typ)
|
|
9010
|
+
if structType == nil || fieldIndex < 0 || fieldIndex >= structType.NumFields() {
|
|
9011
|
+
fieldName := tsStructFieldName(expr.Sel.Name, 0)
|
|
9012
|
+
if address {
|
|
9013
|
+
return receiver + "._fields." + fieldName, diagnostics
|
|
9014
|
+
}
|
|
9015
|
+
return receiver + "." + fieldName, diagnostics
|
|
9016
|
+
}
|
|
9017
|
+
field := structType.Field(fieldIndex)
|
|
9018
|
+
name := tsStructFieldName(field.Name(), fieldIndex)
|
|
9019
|
+
if idx == len(index)-1 {
|
|
9020
|
+
if address {
|
|
9021
|
+
return o.lowerFieldAddressExpr(ctx, receiver, typ, name), diagnostics
|
|
9022
|
+
}
|
|
9023
|
+
return receiver + "." + name, diagnostics
|
|
9024
|
+
}
|
|
9025
|
+
|
|
9026
|
+
receiver += "." + name
|
|
9027
|
+
typ = field.Type()
|
|
9028
|
+
if pointer, ok := types.Unalias(typ).Underlying().(*types.Pointer); ok {
|
|
9029
|
+
receiver = o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
9030
|
+
"<" + o.tsTypeFor(ctx, pointer.Elem()) + ">(" + receiver + ")"
|
|
9031
|
+
typ = pointer.Elem()
|
|
9032
|
+
}
|
|
9033
|
+
}
|
|
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])
|
|
9097
|
+
if address {
|
|
9098
|
+
return o.lowerFieldAddressExpr(ctx, receiver, sourcePointer.Elem(), fieldName), diagnostics, true
|
|
8399
9099
|
}
|
|
9100
|
+
return receiver + "." + fieldName, diagnostics, true
|
|
9101
|
+
}
|
|
8400
9102
|
|
|
8401
|
-
|
|
8402
|
-
|
|
9103
|
+
func unsafeStructFieldLayoutCompatible(target *types.Var, source *types.Var) bool {
|
|
9104
|
+
if target == nil || source == nil || target.Name() != source.Name() {
|
|
9105
|
+
return false
|
|
8403
9106
|
}
|
|
8404
|
-
return
|
|
9107
|
+
return unsafeFieldTypeLayoutCompatible(target.Type(), source.Type())
|
|
8405
9108
|
}
|
|
8406
9109
|
|
|
8407
|
-
func (
|
|
8408
|
-
if
|
|
8409
|
-
return
|
|
9110
|
+
func unsafeFieldTypeLayoutCompatible(left types.Type, right types.Type) bool {
|
|
9111
|
+
if types.Identical(left, right) {
|
|
9112
|
+
return true
|
|
8410
9113
|
}
|
|
8411
|
-
|
|
9114
|
+
leftUnderlying := types.Unalias(left).Underlying()
|
|
9115
|
+
rightUnderlying := types.Unalias(right).Underlying()
|
|
9116
|
+
return types.Identical(leftUnderlying, rightUnderlying)
|
|
8412
9117
|
}
|
|
8413
9118
|
|
|
8414
9119
|
func (o *LoweringOwner) lowerMethodValueClosure(
|
|
@@ -8494,6 +9199,9 @@ func fieldReceiverNeedsVarRefValue(ctx lowerFileContext, expr ast.Expr, obj type
|
|
|
8494
9199
|
return true
|
|
8495
9200
|
}
|
|
8496
9201
|
if ctx.identAliases[obj] != "" {
|
|
9202
|
+
if obj == nil || ctx.model == nil || !ctx.model.needsVarRef[obj] {
|
|
9203
|
+
return false
|
|
9204
|
+
}
|
|
8497
9205
|
return !ctx.identAliasRefs[obj]
|
|
8498
9206
|
}
|
|
8499
9207
|
if ctx.localAliases[obj] != "" {
|
|
@@ -8654,6 +9362,10 @@ func (o *LoweringOwner) lowerAddressExpr(ctx lowerFileContext, expr ast.Expr) (s
|
|
|
8654
9362
|
return receiver + "._fields." + typed.Sel.Name, diagnostics
|
|
8655
9363
|
case *ast.IndexExpr:
|
|
8656
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)
|
|
8657
9369
|
default:
|
|
8658
9370
|
return "undefined", []Diagnostic{loweringUnsupportedAt(ctx, typed, "expression", ctx.semPkg.pkgPath, "unsupported address expression")}
|
|
8659
9371
|
}
|
|
@@ -8745,6 +9457,35 @@ func (o *LoweringOwner) lowerUnsafePointerIntegerExpr(
|
|
|
8745
9457
|
return o.lowerIndexByteAddressIntegerExpr(ctx, call.Args[0])
|
|
8746
9458
|
}
|
|
8747
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
|
+
|
|
8748
9489
|
func (o *LoweringOwner) lowerIndexAddressIntegerExpr(
|
|
8749
9490
|
ctx lowerFileContext,
|
|
8750
9491
|
expr ast.Expr,
|
|
@@ -8915,6 +9656,9 @@ func (o *LoweringOwner) lowerUnsafeArrayPointerConversion(
|
|
|
8915
9656
|
targetType types.Type,
|
|
8916
9657
|
expr ast.Expr,
|
|
8917
9658
|
) (string, []Diagnostic, bool) {
|
|
9659
|
+
if targetType == nil {
|
|
9660
|
+
return "", nil, false
|
|
9661
|
+
}
|
|
8918
9662
|
targetPointer, _ := types.Unalias(targetType).Underlying().(*types.Pointer)
|
|
8919
9663
|
if targetPointer == nil {
|
|
8920
9664
|
return "", nil, false
|
|
@@ -8923,29 +9667,191 @@ func (o *LoweringOwner) lowerUnsafeArrayPointerConversion(
|
|
|
8923
9667
|
if array == nil {
|
|
8924
9668
|
return "", nil, false
|
|
8925
9669
|
}
|
|
8926
|
-
|
|
8927
|
-
if !ok || len(unsafeCall.Args) != 1 || !isUnsafePointerType(typeFromExpr(ctx, unsafeCall.Fun)) {
|
|
8928
|
-
return "", nil, false
|
|
8929
|
-
}
|
|
8930
|
-
address, ok := unwrapParenExpr(unsafeCall.Args[0]).(*ast.UnaryExpr)
|
|
8931
|
-
if !ok || address.Op != token.AND {
|
|
8932
|
-
return "", nil, false
|
|
8933
|
-
}
|
|
8934
|
-
index, ok := unwrapParenExpr(address.X).(*ast.IndexExpr)
|
|
9670
|
+
ref, sourceType, diagnostics, ok := o.lowerUnsafeArrayPointerSourceRef(ctx, expr)
|
|
8935
9671
|
if !ok {
|
|
8936
9672
|
return "", nil, false
|
|
8937
9673
|
}
|
|
8938
|
-
|
|
8939
|
-
sourceElementSize := goScriptElementByteSize(ctx, indexElementType(ctx.semPkg.source.TypesInfo.TypeOf(index.X)))
|
|
9674
|
+
sourceElementSize := goScriptElementByteSize(ctx, sourceType)
|
|
8940
9675
|
targetElementSize := goScriptElementByteSize(ctx, array.Elem())
|
|
9676
|
+
sourceTypeArg := o.tsTypeFor(ctx, array.Elem())
|
|
9677
|
+
if sourceType != nil {
|
|
9678
|
+
sourceTypeArg = o.tsTypeFor(ctx, sourceType)
|
|
9679
|
+
}
|
|
8941
9680
|
helper := o.runtimeOwner.QualifiedHelper(RuntimeHelperArrayPointerFromIndexRef) +
|
|
8942
|
-
"<" +
|
|
9681
|
+
"<" + sourceTypeArg + ">(" + ref + ", " +
|
|
8943
9682
|
strconv.FormatInt(array.Len(), 10) + ", " +
|
|
8944
9683
|
strconv.FormatInt(sourceElementSize, 10) + ", " +
|
|
8945
9684
|
strconv.FormatInt(targetElementSize, 10) + ")"
|
|
8946
9685
|
return "(" + helper + " as unknown as " + o.tsTypeFor(ctx, targetType) + ")", diagnostics, true
|
|
8947
9686
|
}
|
|
8948
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
|
+
|
|
8949
9855
|
func (o *LoweringOwner) lowerAddressedValueRef(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
8950
9856
|
if ident, ok := unwrapParenExpr(expr).(*ast.Ident); ok {
|
|
8951
9857
|
if obj := objectForIdent(ctx, ident); obj != nil && ctx.model.needsVarRef[obj] {
|
|
@@ -9523,7 +10429,11 @@ func (o *LoweringOwner) lowerMapCompositeLit(
|
|
|
9523
10429
|
value = o.lowerValueForTarget(ctx, keyed.Value, mapType.Elem(), value)
|
|
9524
10430
|
entries = append(entries, "["+key+", "+value+"]")
|
|
9525
10431
|
}
|
|
9526
|
-
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 + ">"
|
|
9527
10437
|
}
|
|
9528
10438
|
|
|
9529
10439
|
func (o *LoweringOwner) lowerTypeAssertExpr(ctx lowerFileContext, expr *ast.TypeAssertExpr) (string, []Diagnostic) {
|
|
@@ -9560,7 +10470,11 @@ func (o *LoweringOwner) lowerMapGetTuple(ctx lowerFileContext, expr *ast.IndexEx
|
|
|
9560
10470
|
mapType, _ := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(expr.X)).Underlying().(*types.Map)
|
|
9561
10471
|
defaultValue := "undefined"
|
|
9562
10472
|
if mapType != nil {
|
|
10473
|
+
index = o.lowerValueForTarget(ctx, expr.Index, mapType.Key(), index)
|
|
9563
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 + ")"
|
|
9564
10478
|
}
|
|
9565
10479
|
return o.runtimeOwner.QualifiedHelper(RuntimeHelperMapGet) + "(" + target + ", " + index + ", " + defaultValue + ")"
|
|
9566
10480
|
}
|
|
@@ -10450,7 +11364,7 @@ func (o *LoweringOwner) tsTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
|
10450
11364
|
case *types.Slice:
|
|
10451
11365
|
return "$.Slice<" + o.tsSliceElemTypeFor(ctx, typed.Elem()) + ">"
|
|
10452
11366
|
case *types.Map:
|
|
10453
|
-
return
|
|
11367
|
+
return tsNativeMapType(o.tsTypeFor(ctx, typed.Key()), o.tsTypeFor(ctx, typed.Elem())) + " | null"
|
|
10454
11368
|
case *types.Chan:
|
|
10455
11369
|
return "$.Channel<" + o.tsTypeFor(ctx, typed.Elem()) + "> | null"
|
|
10456
11370
|
case *types.Struct:
|
|
@@ -10469,6 +11383,12 @@ func (o *LoweringOwner) tsTypeFor(ctx lowerFileContext, typ types.Type) string {
|
|
|
10469
11383
|
if !ctx.canReferenceNamedType(named) {
|
|
10470
11384
|
return "any"
|
|
10471
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
|
+
}
|
|
10472
11392
|
return "$.VarRef<" + o.namedTypeExpr(ctx, named) + "> | null"
|
|
10473
11393
|
}
|
|
10474
11394
|
if named := namedStructType(typed.Elem()); named != nil {
|
|
@@ -10511,6 +11431,9 @@ func (o *LoweringOwner) tsNonNilTypeFor(ctx lowerFileContext, typ types.Type) st
|
|
|
10511
11431
|
return "Exclude<$.GoError, null>"
|
|
10512
11432
|
}
|
|
10513
11433
|
if named, ok := types.Unalias(typ).(*types.Named); ok {
|
|
11434
|
+
if crossPackageUnexportedNamedType(ctx, named) {
|
|
11435
|
+
return "any"
|
|
11436
|
+
}
|
|
10514
11437
|
if _, ok := named.Underlying().(*types.Interface); ok {
|
|
10515
11438
|
if !ctx.canReferenceNamedType(named) {
|
|
10516
11439
|
return "any"
|
|
@@ -10837,7 +11760,7 @@ func isPointerToStructType(typ types.Type) bool {
|
|
|
10837
11760
|
if !ok {
|
|
10838
11761
|
return false
|
|
10839
11762
|
}
|
|
10840
|
-
return
|
|
11763
|
+
return structUnderlyingType(pointer.Elem()) != nil
|
|
10841
11764
|
}
|
|
10842
11765
|
|
|
10843
11766
|
func derefPointerType(typ types.Type) types.Type {
|
|
@@ -10914,6 +11837,9 @@ func isChannelType(typ types.Type) bool {
|
|
|
10914
11837
|
}
|
|
10915
11838
|
|
|
10916
11839
|
func isComplexType(typ types.Type) bool {
|
|
11840
|
+
if typ == nil {
|
|
11841
|
+
return false
|
|
11842
|
+
}
|
|
10917
11843
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10918
11844
|
return ok && basic.Info()&types.IsComplex != 0
|
|
10919
11845
|
}
|
|
@@ -10927,10 +11853,21 @@ func isPointerType(typ types.Type) bool {
|
|
|
10927
11853
|
}
|
|
10928
11854
|
|
|
10929
11855
|
func isUnsafePointerType(typ types.Type) bool {
|
|
11856
|
+
if typ == nil {
|
|
11857
|
+
return false
|
|
11858
|
+
}
|
|
10930
11859
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10931
11860
|
return ok && basic.Kind() == types.UnsafePointer
|
|
10932
11861
|
}
|
|
10933
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
|
+
|
|
10934
11871
|
func channelDirectionString(dir types.ChanDir) string {
|
|
10935
11872
|
switch dir {
|
|
10936
11873
|
case types.SendOnly:
|
|
@@ -10958,21 +11895,33 @@ func unwrapParenExpr(expr ast.Expr) ast.Expr {
|
|
|
10958
11895
|
}
|
|
10959
11896
|
|
|
10960
11897
|
func isStringType(typ types.Type) bool {
|
|
11898
|
+
if typ == nil {
|
|
11899
|
+
return false
|
|
11900
|
+
}
|
|
10961
11901
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10962
11902
|
return ok && basic.Info()&types.IsString != 0
|
|
10963
11903
|
}
|
|
10964
11904
|
|
|
10965
11905
|
func isNumericType(typ types.Type) bool {
|
|
11906
|
+
if typ == nil {
|
|
11907
|
+
return false
|
|
11908
|
+
}
|
|
10966
11909
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10967
11910
|
return ok && basic.Info()&types.IsNumeric != 0
|
|
10968
11911
|
}
|
|
10969
11912
|
|
|
10970
11913
|
func isIntegerType(typ types.Type) bool {
|
|
11914
|
+
if typ == nil {
|
|
11915
|
+
return false
|
|
11916
|
+
}
|
|
10971
11917
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10972
11918
|
return ok && basic.Info()&types.IsInteger != 0
|
|
10973
11919
|
}
|
|
10974
11920
|
|
|
10975
11921
|
func isFloatType(typ types.Type) bool {
|
|
11922
|
+
if typ == nil {
|
|
11923
|
+
return false
|
|
11924
|
+
}
|
|
10976
11925
|
basic, ok := types.Unalias(typ).Underlying().(*types.Basic)
|
|
10977
11926
|
return ok && basic.Info()&types.IsFloat != 0
|
|
10978
11927
|
}
|
|
@@ -11146,7 +12095,102 @@ func (o *LoweringOwner) functionAsync(ctx lowerFileContext, fn *types.Func) bool
|
|
|
11146
12095
|
if fn == nil || ctx.model == nil {
|
|
11147
12096
|
return false
|
|
11148
12097
|
}
|
|
11149
|
-
|
|
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)
|
|
11150
12194
|
}
|
|
11151
12195
|
|
|
11152
12196
|
func (o *LoweringOwner) callNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool {
|