goscript 0.1.2 → 0.1.4
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/cmd/goscript/cmd_compile.go +28 -8
- package/cmd/goscript/cmd_compile_test.go +105 -6
- package/compiler/build-flags.go +9 -10
- package/compiler/gotest/runner_test.go +127 -0
- package/compiler/lowered-program.go +1 -0
- package/compiler/lowering.go +1325 -194
- package/compiler/lowering_bench_test.go +350 -0
- package/compiler/override-registry_test.go +43 -0
- package/compiler/package-graph.go +61 -4
- package/compiler/package-graph_test.go +30 -0
- package/compiler/semantic-model-types.go +8 -0
- package/compiler/semantic-model.go +447 -22
- package/compiler/semantic-model_test.go +138 -0
- package/compiler/skeleton_test.go +1436 -50
- package/compiler/typescript-emitter.go +47 -4
- package/dist/gs/builtin/builtin.d.ts +2 -2
- package/dist/gs/builtin/builtin.js +20 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.js +36 -9
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/slice.js +5 -0
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +1 -1
- package/dist/gs/builtin/type.js +80 -8
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.d.ts +7 -5
- package/dist/gs/bytes/bytes.gs.js +10 -4
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +3 -3
- package/dist/gs/compress/zlib/index.js +88 -26
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/crypto/sha1/index.d.ts +5 -0
- package/dist/gs/crypto/sha1/index.js +103 -0
- package/dist/gs/crypto/sha1/index.js.map +1 -0
- package/dist/gs/crypto/sha256/index.js +2 -5
- package/dist/gs/crypto/sha256/index.js.map +1 -1
- package/dist/gs/crypto/sha512/index.js +2 -5
- package/dist/gs/crypto/sha512/index.js.map +1 -1
- package/dist/gs/embed/index.d.ts +6 -0
- package/dist/gs/embed/index.js +210 -5
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +4 -4
- package/dist/gs/fmt/fmt.js +93 -19
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +118 -6
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.d.ts +45 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js +229 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js.map +1 -0
- package/dist/gs/io/fs/readdir.js +5 -3
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/io.d.ts +18 -11
- package/dist/gs/io/io.js +107 -44
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +26 -5
- package/dist/gs/math/bits/index.js +13 -24
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.js +7 -5
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +11 -1
- package/dist/gs/net/http/index.js +157 -11
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +6 -2
- package/dist/gs/os/types_js.gs.js +169 -8
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +1 -0
- package/dist/gs/reflect/type.js +80 -51
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +2 -2
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +2 -1
- package/dist/gs/sync/sync.js +37 -16
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/js/index.js +9 -0
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/testing/testing.js +8 -6
- package/dist/gs/testing/testing.js.map +1 -1
- package/gs/builtin/builtin.ts +25 -2
- package/gs/builtin/channel.ts +47 -9
- package/gs/builtin/runtime-contract.test.ts +78 -0
- package/gs/builtin/slice.ts +7 -0
- package/gs/builtin/type.ts +97 -8
- package/gs/bytes/bytes.gs.ts +19 -10
- package/gs/bytes/bytes.test.ts +17 -0
- package/gs/compress/zlib/index.test.ts +97 -0
- package/gs/compress/zlib/index.ts +117 -27
- package/gs/compress/zlib/meta.json +4 -1
- package/gs/context/context.test.ts +5 -1
- package/gs/crypto/sha1/index.test.ts +45 -0
- package/gs/crypto/sha1/index.ts +127 -0
- package/gs/crypto/sha1/meta.json +8 -0
- package/gs/crypto/sha256/index.test.ts +14 -2
- package/gs/crypto/sha256/index.ts +3 -6
- package/gs/crypto/sha512/index.test.ts +17 -2
- package/gs/crypto/sha512/index.ts +3 -6
- package/gs/embed/index.test.ts +87 -0
- package/gs/embed/index.ts +229 -5
- package/gs/fmt/fmt.test.ts +61 -3
- package/gs/fmt/fmt.ts +115 -22
- package/gs/fmt/meta.json +6 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +8 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +139 -11
- package/gs/github.com/aperturerobotics/util/conc/index.test.ts +1 -1
- package/gs/github.com/go-git/go-billy/v6/osfs/index.test.ts +110 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/index.ts +280 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/meta.json +8 -0
- package/gs/io/fs/readdir.test.ts +38 -0
- package/gs/io/fs/readdir.ts +7 -3
- package/gs/io/io.test.ts +135 -0
- package/gs/io/io.ts +143 -63
- package/gs/io/meta.json +7 -1
- package/gs/math/bits/index.ts +52 -28
- package/gs/net/http/httptest/index.test.ts +34 -2
- package/gs/net/http/httptest/index.ts +23 -8
- package/gs/net/http/index.test.ts +46 -0
- package/gs/net/http/index.ts +178 -12
- package/gs/os/file_unix_js.test.ts +52 -0
- package/gs/os/meta.json +4 -0
- package/gs/os/readdir.test.ts +56 -0
- package/gs/os/types_js.gs.ts +169 -8
- package/gs/os/zero_copy_posix.gs.ts +1 -2
- package/gs/reflect/deepequal.test.ts +10 -1
- package/gs/reflect/type.ts +91 -56
- package/gs/reflect/typefor.test.ts +31 -1
- package/gs/strings/meta.json +5 -2
- package/gs/strings/reader.test.ts +2 -2
- package/gs/strings/reader.ts +2 -2
- package/gs/sync/meta.json +2 -0
- package/gs/sync/sync.test.ts +41 -1
- package/gs/sync/sync.ts +41 -16
- package/gs/syscall/js/index.test.ts +18 -0
- package/gs/syscall/js/index.ts +12 -0
- package/gs/testing/testing.test.ts +32 -3
- package/gs/testing/testing.ts +13 -10
- package/package.json +1 -1
|
@@ -88,12 +88,21 @@ func (o *SemanticModelOwner) Build(ctx context.Context, graph *PackageGraph) (*S
|
|
|
88
88
|
if diagnosticsHaveErrors(diagnostics) {
|
|
89
89
|
return model, diagnostics
|
|
90
90
|
}
|
|
91
|
+
anonymousInterfaceGraph, anonymousInterfaceDiagnostics := o.resolveAnonymousInterfaceImplementationGraph(ctx, model)
|
|
92
|
+
diagnostics = append(diagnostics, anonymousInterfaceDiagnostics...)
|
|
93
|
+
if diagnosticsHaveErrors(diagnostics) {
|
|
94
|
+
return model, diagnostics
|
|
95
|
+
}
|
|
91
96
|
for {
|
|
92
97
|
asyncCount := semanticAsyncFunctionCount(model)
|
|
93
98
|
diagnostics = append(diagnostics, o.applyInterfaceAsyncMethods(ctx, model, interfaceGraph)...)
|
|
94
99
|
if diagnosticsHaveErrors(diagnostics) {
|
|
95
100
|
return model, diagnostics
|
|
96
101
|
}
|
|
102
|
+
diagnostics = append(diagnostics, o.applyAnonymousInterfaceAsyncMethods(ctx, model, anonymousInterfaceGraph)...)
|
|
103
|
+
if diagnosticsHaveErrors(diagnostics) {
|
|
104
|
+
return model, diagnostics
|
|
105
|
+
}
|
|
97
106
|
diagnostics = append(diagnostics, o.propagateFunctionAsync(ctx, model)...)
|
|
98
107
|
if diagnosticsHaveErrors(diagnostics) {
|
|
99
108
|
return model, diagnostics
|
|
@@ -107,15 +116,18 @@ func (o *SemanticModelOwner) Build(ctx context.Context, graph *PackageGraph) (*S
|
|
|
107
116
|
|
|
108
117
|
func newSemanticModel() *SemanticModel {
|
|
109
118
|
return &SemanticModel{
|
|
110
|
-
packages:
|
|
111
|
-
addressTaken:
|
|
112
|
-
needsVarRef:
|
|
113
|
-
functions:
|
|
114
|
-
functionsByFullName:
|
|
115
|
-
functionLookupMisses:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
packages: make(map[string]*semanticPackage),
|
|
120
|
+
addressTaken: make(map[types.Object]bool),
|
|
121
|
+
needsVarRef: make(map[types.Object]bool),
|
|
122
|
+
functions: make(map[*types.Func]*semanticFunction),
|
|
123
|
+
functionsByFullName: make(map[string]*semanticFunction),
|
|
124
|
+
functionLookupMisses: make(map[*types.Func]bool),
|
|
125
|
+
functionFullNames: make(map[*types.Func]string),
|
|
126
|
+
types: make(map[*types.Named]*semanticType),
|
|
127
|
+
values: make(map[types.Object]*semanticValue),
|
|
128
|
+
generatedImports: make(map[string]map[string]bool),
|
|
129
|
+
asyncInterfaceMethods: make(map[string]bool),
|
|
130
|
+
asyncInterfaceMethodObjs: make(map[*types.Func]bool),
|
|
119
131
|
}
|
|
120
132
|
}
|
|
121
133
|
|
|
@@ -555,7 +567,7 @@ func (o *SemanticModelOwner) addFunction(
|
|
|
555
567
|
return existing
|
|
556
568
|
}
|
|
557
569
|
}
|
|
558
|
-
if fullName :=
|
|
570
|
+
if fullName := model.functionFullName(fn); fullName != "" {
|
|
559
571
|
if existing := model.functionsByFullName[fullName]; existing != nil {
|
|
560
572
|
model.functions[fn] = existing
|
|
561
573
|
if origin := fn.Origin(); origin != nil {
|
|
@@ -583,7 +595,7 @@ func (o *SemanticModelOwner) addFunction(
|
|
|
583
595
|
if origin := fn.Origin(); origin != nil {
|
|
584
596
|
model.functions[origin] = semFn
|
|
585
597
|
}
|
|
586
|
-
if fullName :=
|
|
598
|
+
if fullName := model.functionFullName(fn); fullName != "" {
|
|
587
599
|
if existing := model.functionsByFullName[fullName]; existing == nil {
|
|
588
600
|
model.functionsByFullName[fullName] = semFn
|
|
589
601
|
}
|
|
@@ -932,7 +944,7 @@ func semanticFunctionFor(model *SemanticModel, fn *types.Func) *semanticFunction
|
|
|
932
944
|
return semFn
|
|
933
945
|
}
|
|
934
946
|
}
|
|
935
|
-
if fullName :=
|
|
947
|
+
if fullName := model.functionFullName(fn); fullName != "" {
|
|
936
948
|
if semFn := model.functionsByFullName[fullName]; semFn != nil {
|
|
937
949
|
model.functions[fn] = semFn
|
|
938
950
|
return semFn
|
|
@@ -989,6 +1001,8 @@ func callUsesFunctionValue(pkg *packages.Package, expr ast.Expr) bool {
|
|
|
989
1001
|
switch typed := expr.(type) {
|
|
990
1002
|
case *ast.CallExpr:
|
|
991
1003
|
return true
|
|
1004
|
+
case *ast.TypeAssertExpr:
|
|
1005
|
+
return true
|
|
992
1006
|
case *ast.SelectorExpr:
|
|
993
1007
|
selection := pkg.TypesInfo.Selections[typed]
|
|
994
1008
|
if selection != nil {
|
|
@@ -1125,8 +1139,7 @@ func (o *SemanticModelOwner) propagateFunctionAsync(ctx context.Context, model *
|
|
|
1125
1139
|
return []Diagnostic{contextCanceledDiagnostic(err)}
|
|
1126
1140
|
}
|
|
1127
1141
|
for called := range semFn.calls {
|
|
1128
|
-
|
|
1129
|
-
if calledFn != nil && calledFn.async {
|
|
1142
|
+
if model.functionAsync(called) {
|
|
1130
1143
|
if markFunctionAsync(semFn, "call:"+called.FullName()) {
|
|
1131
1144
|
changed = true
|
|
1132
1145
|
}
|
|
@@ -1167,17 +1180,15 @@ func (o *SemanticModelOwner) resolveInterfaceImplementationGraph(
|
|
|
1167
1180
|
ctx context.Context,
|
|
1168
1181
|
model *SemanticModel,
|
|
1169
1182
|
) ([]semanticInterfaceImplementationGraphEntry, []Diagnostic) {
|
|
1170
|
-
|
|
1183
|
+
interfaces := collectInterfaceImplementationCandidates(model)
|
|
1171
1184
|
var concretes []*types.Named
|
|
1172
1185
|
for named, semType := range model.types {
|
|
1173
1186
|
if err := ctx.Err(); err != nil {
|
|
1174
1187
|
return nil, []Diagnostic{contextCanceledDiagnostic(err)}
|
|
1175
1188
|
}
|
|
1176
|
-
if semType.isInterface {
|
|
1177
|
-
|
|
1178
|
-
continue
|
|
1189
|
+
if !semType.isInterface {
|
|
1190
|
+
concretes = append(concretes, namedOriginOrSelf(named))
|
|
1179
1191
|
}
|
|
1180
|
-
concretes = append(concretes, named)
|
|
1181
1192
|
}
|
|
1182
1193
|
sortNamedTypes(interfaces)
|
|
1183
1194
|
sortNamedTypes(concretes)
|
|
@@ -1209,6 +1220,338 @@ func (o *SemanticModelOwner) resolveInterfaceImplementationGraph(
|
|
|
1209
1220
|
return implementationGraph, nil
|
|
1210
1221
|
}
|
|
1211
1222
|
|
|
1223
|
+
func (o *SemanticModelOwner) resolveAnonymousInterfaceImplementationGraph(
|
|
1224
|
+
ctx context.Context,
|
|
1225
|
+
model *SemanticModel,
|
|
1226
|
+
) ([]semanticAnonymousInterfaceImplementation, []Diagnostic) {
|
|
1227
|
+
interfaces := collectAnonymousInterfaceImplementationCandidates(model)
|
|
1228
|
+
var concretes []*types.Named
|
|
1229
|
+
for named, semType := range model.types {
|
|
1230
|
+
if err := ctx.Err(); err != nil {
|
|
1231
|
+
return nil, []Diagnostic{contextCanceledDiagnostic(err)}
|
|
1232
|
+
}
|
|
1233
|
+
if !semType.isInterface {
|
|
1234
|
+
concretes = append(concretes, namedOriginOrSelf(named))
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
methodSets := implementationMethodSets(concretes)
|
|
1238
|
+
for _, namedIface := range collectNamedInterfaceImplementationCandidates(model) {
|
|
1239
|
+
methodSets = append(methodSets, semanticImplementationMethodSet{
|
|
1240
|
+
typ: namedIface,
|
|
1241
|
+
receiver: namedIface,
|
|
1242
|
+
methods: methodSetMap(namedIface),
|
|
1243
|
+
})
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
implementationGraph := make([]semanticAnonymousInterfaceImplementation, 0)
|
|
1247
|
+
for _, iface := range interfaces {
|
|
1248
|
+
if err := ctx.Err(); err != nil {
|
|
1249
|
+
return nil, []Diagnostic{contextCanceledDiagnostic(err)}
|
|
1250
|
+
}
|
|
1251
|
+
iface.Complete()
|
|
1252
|
+
ifaceMethods := interfaceMethodMap(iface)
|
|
1253
|
+
if len(ifaceMethods) == 0 {
|
|
1254
|
+
continue
|
|
1255
|
+
}
|
|
1256
|
+
for _, methodSet := range methodSets {
|
|
1257
|
+
if err := ctx.Err(); err != nil {
|
|
1258
|
+
return nil, []Diagnostic{contextCanceledDiagnostic(err)}
|
|
1259
|
+
}
|
|
1260
|
+
if !implementationHasMethods(methodSet.methods, ifaceMethods) {
|
|
1261
|
+
continue
|
|
1262
|
+
}
|
|
1263
|
+
receiver := methodSet.receiver
|
|
1264
|
+
if (methodSet.typ.TypeArgs() == nil || methodSet.typ.TypeArgs().Len() == 0) &&
|
|
1265
|
+
methodSet.typ.TypeParams() != nil && methodSet.typ.TypeParams().Len() != 0 {
|
|
1266
|
+
args := typeParamTypes(methodSet.typ.TypeParams())
|
|
1267
|
+
if instantiated, err := types.Instantiate(nil, methodSet.typ, args, false); err == nil {
|
|
1268
|
+
receiver = instantiated
|
|
1269
|
+
if methodSet.pointer {
|
|
1270
|
+
receiver = types.NewPointer(instantiated)
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
if !types.Implements(receiver, iface) {
|
|
1275
|
+
continue
|
|
1276
|
+
}
|
|
1277
|
+
implementationGraph = append(implementationGraph, semanticAnonymousInterfaceImplementation{
|
|
1278
|
+
ifaceMethods: ifaceMethods,
|
|
1279
|
+
implMethods: implementationMethodMap(methodSet.methods, ifaceMethods),
|
|
1280
|
+
})
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
return implementationGraph, nil
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
func collectInterfaceImplementationCandidates(model *SemanticModel) []*types.Named {
|
|
1287
|
+
if model == nil {
|
|
1288
|
+
return nil
|
|
1289
|
+
}
|
|
1290
|
+
seen := make(map[string]bool)
|
|
1291
|
+
var interfaces []*types.Named
|
|
1292
|
+
add := func(named *types.Named) {
|
|
1293
|
+
if named == nil || named.Obj() == nil || named.Obj().Pkg() == nil {
|
|
1294
|
+
return
|
|
1295
|
+
}
|
|
1296
|
+
named = namedOriginOrSelf(named)
|
|
1297
|
+
if _, ok := types.Unalias(named.Underlying()).(*types.Interface); !ok {
|
|
1298
|
+
return
|
|
1299
|
+
}
|
|
1300
|
+
key := named.Obj().Pkg().Path() + "." + named.Obj().Name()
|
|
1301
|
+
if seen[key] {
|
|
1302
|
+
return
|
|
1303
|
+
}
|
|
1304
|
+
seen[key] = true
|
|
1305
|
+
interfaces = append(interfaces, named)
|
|
1306
|
+
}
|
|
1307
|
+
var collect func(types.Type)
|
|
1308
|
+
seenTypes := make(map[types.Type]bool)
|
|
1309
|
+
collect = func(typ types.Type) {
|
|
1310
|
+
if typ == nil {
|
|
1311
|
+
return
|
|
1312
|
+
}
|
|
1313
|
+
typ = types.Unalias(typ)
|
|
1314
|
+
if seenTypes[typ] {
|
|
1315
|
+
return
|
|
1316
|
+
}
|
|
1317
|
+
seenTypes[typ] = true
|
|
1318
|
+
switch typed := typ.(type) {
|
|
1319
|
+
case *types.Named:
|
|
1320
|
+
add(typed)
|
|
1321
|
+
collect(typed.Underlying())
|
|
1322
|
+
case *types.Pointer:
|
|
1323
|
+
collect(typed.Elem())
|
|
1324
|
+
case *types.Slice:
|
|
1325
|
+
collect(typed.Elem())
|
|
1326
|
+
case *types.Array:
|
|
1327
|
+
collect(typed.Elem())
|
|
1328
|
+
case *types.Map:
|
|
1329
|
+
collect(typed.Key())
|
|
1330
|
+
collect(typed.Elem())
|
|
1331
|
+
case *types.Chan:
|
|
1332
|
+
collect(typed.Elem())
|
|
1333
|
+
case *types.Struct:
|
|
1334
|
+
for field := range typed.Fields() {
|
|
1335
|
+
collect(field.Type())
|
|
1336
|
+
}
|
|
1337
|
+
case *types.Interface:
|
|
1338
|
+
typed.Complete()
|
|
1339
|
+
for method := range typed.Methods() {
|
|
1340
|
+
collect(method.Type())
|
|
1341
|
+
}
|
|
1342
|
+
case *types.Signature:
|
|
1343
|
+
if typed.Recv() != nil {
|
|
1344
|
+
collect(typed.Recv().Type())
|
|
1345
|
+
}
|
|
1346
|
+
collectTuple(collect, typed.Params())
|
|
1347
|
+
collectTuple(collect, typed.Results())
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
for _, semType := range model.types {
|
|
1351
|
+
collect(semType.named)
|
|
1352
|
+
for _, field := range semType.fields {
|
|
1353
|
+
collect(field.typ)
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
for _, semFn := range model.functions {
|
|
1357
|
+
collect(semFn.signature)
|
|
1358
|
+
}
|
|
1359
|
+
for _, semValue := range model.values {
|
|
1360
|
+
collect(semValue.typ)
|
|
1361
|
+
}
|
|
1362
|
+
for _, semPkg := range model.packages {
|
|
1363
|
+
for _, assertion := range semPkg.typeAssertions {
|
|
1364
|
+
collect(assertion.source)
|
|
1365
|
+
collect(assertion.target)
|
|
1366
|
+
}
|
|
1367
|
+
for _, fact := range semPkg.nilFacts {
|
|
1368
|
+
collect(fact.typ)
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return interfaces
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
func collectAnonymousInterfaceImplementationCandidates(model *SemanticModel) []*types.Interface {
|
|
1375
|
+
if model == nil {
|
|
1376
|
+
return nil
|
|
1377
|
+
}
|
|
1378
|
+
seen := make(map[*types.Interface]bool)
|
|
1379
|
+
var interfaces []*types.Interface
|
|
1380
|
+
add := func(iface *types.Interface) {
|
|
1381
|
+
if iface == nil || seen[iface] {
|
|
1382
|
+
return
|
|
1383
|
+
}
|
|
1384
|
+
seen[iface] = true
|
|
1385
|
+
interfaces = append(interfaces, iface)
|
|
1386
|
+
}
|
|
1387
|
+
var collect func(types.Type)
|
|
1388
|
+
seenTypes := make(map[types.Type]bool)
|
|
1389
|
+
collect = func(typ types.Type) {
|
|
1390
|
+
if typ == nil {
|
|
1391
|
+
return
|
|
1392
|
+
}
|
|
1393
|
+
typ = types.Unalias(typ)
|
|
1394
|
+
if seenTypes[typ] {
|
|
1395
|
+
return
|
|
1396
|
+
}
|
|
1397
|
+
seenTypes[typ] = true
|
|
1398
|
+
switch typed := typ.(type) {
|
|
1399
|
+
case *types.Named:
|
|
1400
|
+
collect(typed.Underlying())
|
|
1401
|
+
case *types.Pointer:
|
|
1402
|
+
collect(typed.Elem())
|
|
1403
|
+
case *types.Slice:
|
|
1404
|
+
collect(typed.Elem())
|
|
1405
|
+
case *types.Array:
|
|
1406
|
+
collect(typed.Elem())
|
|
1407
|
+
case *types.Map:
|
|
1408
|
+
collect(typed.Key())
|
|
1409
|
+
collect(typed.Elem())
|
|
1410
|
+
case *types.Chan:
|
|
1411
|
+
collect(typed.Elem())
|
|
1412
|
+
case *types.Struct:
|
|
1413
|
+
for field := range typed.Fields() {
|
|
1414
|
+
collect(field.Type())
|
|
1415
|
+
}
|
|
1416
|
+
case *types.Interface:
|
|
1417
|
+
typed.Complete()
|
|
1418
|
+
add(typed)
|
|
1419
|
+
for method := range typed.Methods() {
|
|
1420
|
+
collect(method.Type())
|
|
1421
|
+
}
|
|
1422
|
+
case *types.Signature:
|
|
1423
|
+
if typed.Recv() != nil {
|
|
1424
|
+
collect(typed.Recv().Type())
|
|
1425
|
+
}
|
|
1426
|
+
collectTuple(collect, typed.Params())
|
|
1427
|
+
collectTuple(collect, typed.Results())
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
for _, semType := range model.types {
|
|
1431
|
+
collect(semType.named)
|
|
1432
|
+
for _, field := range semType.fields {
|
|
1433
|
+
collect(field.typ)
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
for _, semFn := range model.functions {
|
|
1437
|
+
collect(semFn.signature)
|
|
1438
|
+
}
|
|
1439
|
+
for _, semValue := range model.values {
|
|
1440
|
+
collect(semValue.typ)
|
|
1441
|
+
}
|
|
1442
|
+
for _, semPkg := range model.packages {
|
|
1443
|
+
for _, assertion := range semPkg.typeAssertions {
|
|
1444
|
+
collect(assertion.source)
|
|
1445
|
+
collect(assertion.target)
|
|
1446
|
+
}
|
|
1447
|
+
for _, fact := range semPkg.nilFacts {
|
|
1448
|
+
collect(fact.typ)
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
return interfaces
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
func collectNamedInterfaceImplementationCandidates(model *SemanticModel) []*types.Named {
|
|
1455
|
+
if model == nil {
|
|
1456
|
+
return nil
|
|
1457
|
+
}
|
|
1458
|
+
seen := make(map[string]bool)
|
|
1459
|
+
var interfaces []*types.Named
|
|
1460
|
+
add := func(named *types.Named) {
|
|
1461
|
+
if named == nil {
|
|
1462
|
+
return
|
|
1463
|
+
}
|
|
1464
|
+
if _, ok := types.Unalias(named.Underlying()).(*types.Interface); !ok {
|
|
1465
|
+
return
|
|
1466
|
+
}
|
|
1467
|
+
key := types.TypeString(named, func(pkg *types.Package) string {
|
|
1468
|
+
if pkg == nil {
|
|
1469
|
+
return ""
|
|
1470
|
+
}
|
|
1471
|
+
return pkg.Path()
|
|
1472
|
+
})
|
|
1473
|
+
if seen[key] {
|
|
1474
|
+
return
|
|
1475
|
+
}
|
|
1476
|
+
seen[key] = true
|
|
1477
|
+
interfaces = append(interfaces, named)
|
|
1478
|
+
}
|
|
1479
|
+
var collect func(types.Type)
|
|
1480
|
+
seenTypes := make(map[types.Type]bool)
|
|
1481
|
+
collect = func(typ types.Type) {
|
|
1482
|
+
if typ == nil {
|
|
1483
|
+
return
|
|
1484
|
+
}
|
|
1485
|
+
typ = types.Unalias(typ)
|
|
1486
|
+
if seenTypes[typ] {
|
|
1487
|
+
return
|
|
1488
|
+
}
|
|
1489
|
+
seenTypes[typ] = true
|
|
1490
|
+
switch typed := typ.(type) {
|
|
1491
|
+
case *types.Named:
|
|
1492
|
+
add(typed)
|
|
1493
|
+
collect(typed.Underlying())
|
|
1494
|
+
case *types.Pointer:
|
|
1495
|
+
collect(typed.Elem())
|
|
1496
|
+
case *types.Slice:
|
|
1497
|
+
collect(typed.Elem())
|
|
1498
|
+
case *types.Array:
|
|
1499
|
+
collect(typed.Elem())
|
|
1500
|
+
case *types.Map:
|
|
1501
|
+
collect(typed.Key())
|
|
1502
|
+
collect(typed.Elem())
|
|
1503
|
+
case *types.Chan:
|
|
1504
|
+
collect(typed.Elem())
|
|
1505
|
+
case *types.Struct:
|
|
1506
|
+
for field := range typed.Fields() {
|
|
1507
|
+
collect(field.Type())
|
|
1508
|
+
}
|
|
1509
|
+
case *types.Interface:
|
|
1510
|
+
typed.Complete()
|
|
1511
|
+
for method := range typed.Methods() {
|
|
1512
|
+
collect(method.Type())
|
|
1513
|
+
}
|
|
1514
|
+
case *types.Signature:
|
|
1515
|
+
if typed.Recv() != nil {
|
|
1516
|
+
collect(typed.Recv().Type())
|
|
1517
|
+
}
|
|
1518
|
+
collectTuple(collect, typed.Params())
|
|
1519
|
+
collectTuple(collect, typed.Results())
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
for _, semType := range model.types {
|
|
1523
|
+
collect(semType.named)
|
|
1524
|
+
for _, field := range semType.fields {
|
|
1525
|
+
collect(field.typ)
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
for _, semFn := range model.functions {
|
|
1529
|
+
collect(semFn.signature)
|
|
1530
|
+
}
|
|
1531
|
+
for _, semValue := range model.values {
|
|
1532
|
+
collect(semValue.typ)
|
|
1533
|
+
}
|
|
1534
|
+
for _, semPkg := range model.packages {
|
|
1535
|
+
for _, assertion := range semPkg.typeAssertions {
|
|
1536
|
+
collect(assertion.source)
|
|
1537
|
+
collect(assertion.target)
|
|
1538
|
+
}
|
|
1539
|
+
for _, fact := range semPkg.nilFacts {
|
|
1540
|
+
collect(fact.typ)
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
return interfaces
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
func collectTuple(collect func(types.Type), tuple *types.Tuple) {
|
|
1547
|
+
if tuple == nil {
|
|
1548
|
+
return
|
|
1549
|
+
}
|
|
1550
|
+
for v := range tuple.Variables() {
|
|
1551
|
+
collect(v.Type())
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1212
1555
|
func (o *SemanticModelOwner) applyInterfaceAsyncMethods(
|
|
1213
1556
|
ctx context.Context,
|
|
1214
1557
|
model *SemanticModel,
|
|
@@ -1226,10 +1569,11 @@ func (o *SemanticModelOwner) applyInterfaceAsyncMethods(
|
|
|
1226
1569
|
asyncMethods: make(map[string]bool),
|
|
1227
1570
|
}
|
|
1228
1571
|
for methodName, implMethod := range graphEntry.implMethods {
|
|
1229
|
-
implFn := model
|
|
1572
|
+
implFn := semanticFunctionFor(model, implMethod)
|
|
1230
1573
|
if implFn != nil && implFn.async {
|
|
1231
1574
|
implementation.asyncMethods[methodName] = true
|
|
1232
|
-
|
|
1575
|
+
model.markInterfaceMethodAsync(graphEntry.ifaceMethods[methodName])
|
|
1576
|
+
if ifaceFn := semanticFunctionFor(model, graphEntry.ifaceMethods[methodName]); ifaceFn != nil {
|
|
1233
1577
|
markFunctionAsync(ifaceFn, "interface-implementation")
|
|
1234
1578
|
}
|
|
1235
1579
|
}
|
|
@@ -1238,13 +1582,61 @@ func (o *SemanticModelOwner) applyInterfaceAsyncMethods(
|
|
|
1238
1582
|
if !async {
|
|
1239
1583
|
continue
|
|
1240
1584
|
}
|
|
1241
|
-
markFunctionAsync(model
|
|
1585
|
+
markFunctionAsync(semanticFunctionFor(model, graphEntry.implMethods[methodName]), "interface-method")
|
|
1242
1586
|
}
|
|
1243
1587
|
model.interfaceImplementations = append(model.interfaceImplementations, implementation)
|
|
1244
1588
|
}
|
|
1245
1589
|
return nil
|
|
1246
1590
|
}
|
|
1247
1591
|
|
|
1592
|
+
func (o *SemanticModelOwner) applyAnonymousInterfaceAsyncMethods(
|
|
1593
|
+
ctx context.Context,
|
|
1594
|
+
model *SemanticModel,
|
|
1595
|
+
interfaceGraph []semanticAnonymousInterfaceImplementation,
|
|
1596
|
+
) []Diagnostic {
|
|
1597
|
+
for _, graphEntry := range interfaceGraph {
|
|
1598
|
+
if err := ctx.Err(); err != nil {
|
|
1599
|
+
return []Diagnostic{contextCanceledDiagnostic(err)}
|
|
1600
|
+
}
|
|
1601
|
+
for methodName, implMethod := range graphEntry.implMethods {
|
|
1602
|
+
if model.functionAsync(implMethod) {
|
|
1603
|
+
model.markInterfaceMethodAsync(graphEntry.ifaceMethods[methodName])
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
return nil
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
func (m *SemanticModel) functionAsync(fn *types.Func) bool {
|
|
1611
|
+
semFn := semanticFunctionFor(m, fn)
|
|
1612
|
+
if semFn != nil && semFn.async {
|
|
1613
|
+
return true
|
|
1614
|
+
}
|
|
1615
|
+
return m.interfaceMethodAsync(fn)
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
func (m *SemanticModel) markInterfaceMethodAsync(fn *types.Func) {
|
|
1619
|
+
if m == nil || fn == nil {
|
|
1620
|
+
return
|
|
1621
|
+
}
|
|
1622
|
+
m.asyncInterfaceMethodObjs[fn] = true
|
|
1623
|
+
key := m.functionFullName(fn)
|
|
1624
|
+
if key != "" {
|
|
1625
|
+
m.asyncInterfaceMethods[key] = true
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
func (m *SemanticModel) interfaceMethodAsync(fn *types.Func) bool {
|
|
1630
|
+
if m == nil || fn == nil {
|
|
1631
|
+
return false
|
|
1632
|
+
}
|
|
1633
|
+
if m.asyncInterfaceMethodObjs[fn] {
|
|
1634
|
+
return true
|
|
1635
|
+
}
|
|
1636
|
+
key := m.functionFullName(fn)
|
|
1637
|
+
return key != "" && m.asyncInterfaceMethods[key]
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1248
1640
|
func contextCanceledDiagnostic(err error) Diagnostic {
|
|
1249
1641
|
return Diagnostic{
|
|
1250
1642
|
Severity: DiagnosticSeverityError,
|
|
@@ -1304,6 +1696,29 @@ func interfaceMethodMap(iface *types.Interface) map[string]*types.Func {
|
|
|
1304
1696
|
return methods
|
|
1305
1697
|
}
|
|
1306
1698
|
|
|
1699
|
+
func (m *SemanticModel) functionFullName(fn *types.Func) string {
|
|
1700
|
+
if m == nil || fn == nil {
|
|
1701
|
+
return ""
|
|
1702
|
+
}
|
|
1703
|
+
original := fn
|
|
1704
|
+
if fullName, ok := m.functionFullNames[original]; ok {
|
|
1705
|
+
return fullName
|
|
1706
|
+
}
|
|
1707
|
+
if origin := fn.Origin(); origin != nil && origin != fn {
|
|
1708
|
+
if fullName, ok := m.functionFullNames[origin]; ok {
|
|
1709
|
+
m.functionFullNames[original] = fullName
|
|
1710
|
+
return fullName
|
|
1711
|
+
}
|
|
1712
|
+
fn = origin
|
|
1713
|
+
}
|
|
1714
|
+
fullName := fn.FullName()
|
|
1715
|
+
m.functionFullNames[fn] = fullName
|
|
1716
|
+
if original != fn {
|
|
1717
|
+
m.functionFullNames[original] = fullName
|
|
1718
|
+
}
|
|
1719
|
+
return fullName
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1307
1722
|
func implementationMethodSets(concretes []*types.Named) []semanticImplementationMethodSet {
|
|
1308
1723
|
methodSets := make([]semanticImplementationMethodSet, 0, len(concretes)*2)
|
|
1309
1724
|
for _, concrete := range concretes {
|
|
@@ -1378,6 +1793,16 @@ func typeParamTypes(params *types.TypeParamList) []types.Type {
|
|
|
1378
1793
|
return args
|
|
1379
1794
|
}
|
|
1380
1795
|
|
|
1796
|
+
func namedOriginOrSelf(named *types.Named) *types.Named {
|
|
1797
|
+
if named == nil {
|
|
1798
|
+
return nil
|
|
1799
|
+
}
|
|
1800
|
+
if origin := named.Origin(); origin != nil {
|
|
1801
|
+
return origin
|
|
1802
|
+
}
|
|
1803
|
+
return named
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1381
1806
|
func sortNamedTypes(named []*types.Named) {
|
|
1382
1807
|
slices.SortFunc(named, func(a, b *types.Named) int {
|
|
1383
1808
|
return cmp.Compare(namedTypeKey(a), namedTypeKey(b))
|