goscript 0.0.59 → 0.0.60
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/compiler/analysis.go +74 -29
- package/go.mod +4 -4
- package/go.sum +8 -0
- package/package.json +1 -1
package/compiler/analysis.go
CHANGED
|
@@ -2,7 +2,6 @@ package compiler
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"encoding/json"
|
|
5
|
-
"fmt"
|
|
6
5
|
"go/ast"
|
|
7
6
|
"go/token"
|
|
8
7
|
"go/types"
|
|
@@ -1472,6 +1471,14 @@ func (a *Analysis) loadGsMetadata(metaFilePath string) *GsMetadata {
|
|
|
1472
1471
|
return &metadata
|
|
1473
1472
|
}
|
|
1474
1473
|
|
|
1474
|
+
// isHandwrittenPackage checks if a package path corresponds to a handwritten package in gs/
|
|
1475
|
+
func (a *Analysis) isHandwrittenPackage(pkgPath string) bool {
|
|
1476
|
+
// Check if the package exists in the embedded gs/ directory
|
|
1477
|
+
metaFilePath := filepath.Join("gs", pkgPath, "meta.json")
|
|
1478
|
+
_, err := goscript.GsOverrides.ReadFile(metaFilePath)
|
|
1479
|
+
return err == nil
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1475
1482
|
// IsMethodAsync checks if a method call is async based on package metadata
|
|
1476
1483
|
func (a *Analysis) IsMethodAsync(pkgPath, typeName, methodName string) bool {
|
|
1477
1484
|
// First, check pre-computed method async status
|
|
@@ -2246,13 +2253,49 @@ func (v *analysisVisitor) analyzeAllMethodsAsync() {
|
|
|
2246
2253
|
// Initialize visitingMethods map
|
|
2247
2254
|
v.visitingMethods = make(map[MethodKey]bool)
|
|
2248
2255
|
|
|
2249
|
-
//
|
|
2250
|
-
|
|
2256
|
+
// Fixed-point iteration: keep analyzing until nothing changes
|
|
2257
|
+
// This handles cases where method A calls method B, but B is analyzed after A
|
|
2258
|
+
maxIterations := 10
|
|
2259
|
+
for iteration := 0; iteration < maxIterations; iteration++ {
|
|
2260
|
+
// Clear visitingMethods map for this iteration
|
|
2261
|
+
v.visitingMethods = make(map[MethodKey]bool)
|
|
2251
2262
|
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2263
|
+
// Track if anything changed in this iteration
|
|
2264
|
+
changed := false
|
|
2265
|
+
|
|
2266
|
+
// Save previous state
|
|
2267
|
+
previousState := make(map[MethodKey]bool)
|
|
2268
|
+
for k, v := range v.analysis.MethodAsyncStatus {
|
|
2269
|
+
previousState[k] = v
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
// Re-analyze methods in current package
|
|
2273
|
+
v.analyzePackageMethodsAsync(v.pkg)
|
|
2274
|
+
|
|
2275
|
+
// Re-analyze methods in all dependency packages
|
|
2276
|
+
for _, pkg := range v.analysis.AllPackages {
|
|
2277
|
+
if pkg != v.pkg {
|
|
2278
|
+
v.analyzePackageMethodsAsync(pkg)
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
// Check if anything changed
|
|
2283
|
+
for k, newValue := range v.analysis.MethodAsyncStatus {
|
|
2284
|
+
oldValue, existed := previousState[k]
|
|
2285
|
+
if !existed {
|
|
2286
|
+
// New method added - check if it's async (if sync, no need to re-analyze dependents)
|
|
2287
|
+
if newValue {
|
|
2288
|
+
changed = true
|
|
2289
|
+
}
|
|
2290
|
+
} else if oldValue != newValue {
|
|
2291
|
+
// Method changed from sync to async (or vice versa)
|
|
2292
|
+
changed = true
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
// If nothing changed, we've reached a fixed point
|
|
2297
|
+
if !changed {
|
|
2298
|
+
break
|
|
2256
2299
|
}
|
|
2257
2300
|
}
|
|
2258
2301
|
|
|
@@ -2311,11 +2354,6 @@ func (v *analysisVisitor) analyzeFunctionLiteralAsync(funcLit *ast.FuncLit, pkg
|
|
|
2311
2354
|
func (v *analysisVisitor) analyzeMethodAsync(funcDecl *ast.FuncDecl, pkg *packages.Package) {
|
|
2312
2355
|
methodKey := v.getMethodKey(funcDecl, pkg)
|
|
2313
2356
|
|
|
2314
|
-
// Check if already analyzed
|
|
2315
|
-
if _, exists := v.analysis.MethodAsyncStatus[methodKey]; exists {
|
|
2316
|
-
return
|
|
2317
|
-
}
|
|
2318
|
-
|
|
2319
2357
|
// Check for cycles
|
|
2320
2358
|
if v.visitingMethods[methodKey] {
|
|
2321
2359
|
// Cycle detected, assume sync to break recursion
|
|
@@ -2329,17 +2367,32 @@ func (v *analysisVisitor) analyzeMethodAsync(funcDecl *ast.FuncDecl, pkg *packag
|
|
|
2329
2367
|
// Determine if method is async
|
|
2330
2368
|
isAsync := false
|
|
2331
2369
|
|
|
2332
|
-
// Determine if this is a
|
|
2333
|
-
|
|
2370
|
+
// Determine if this is a handwritten package (from gs/ directory)
|
|
2371
|
+
// Handwritten packages should not have their bodies analyzed
|
|
2372
|
+
isHandwrittenPackage := v.analysis.isHandwrittenPackage(methodKey.PackagePath)
|
|
2334
2373
|
|
|
2335
|
-
if
|
|
2336
|
-
//
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2374
|
+
if isHandwrittenPackage {
|
|
2375
|
+
// For handwritten packages, check if we have pre-loaded metadata
|
|
2376
|
+
metadataKey := MethodKey{
|
|
2377
|
+
PackagePath: methodKey.PackagePath,
|
|
2378
|
+
ReceiverType: methodKey.ReceiverType,
|
|
2379
|
+
MethodName: methodKey.MethodName,
|
|
2380
|
+
}
|
|
2381
|
+
metadataIsAsync, hasMetadata := v.analysis.MethodAsyncStatus[metadataKey]
|
|
2382
|
+
|
|
2383
|
+
if hasMetadata {
|
|
2384
|
+
// Use explicit metadata from handwritten packages (gs/)
|
|
2385
|
+
isAsync = metadataIsAsync
|
|
2386
|
+
} else {
|
|
2387
|
+
// Handwritten package but no explicit metadata: assume sync
|
|
2388
|
+
isAsync = false
|
|
2389
|
+
}
|
|
2390
|
+
} else if funcDecl.Body != nil {
|
|
2391
|
+
// Not a handwritten package and has body: always analyze for async operations
|
|
2392
|
+
// This allows fixed-point iteration to update results
|
|
2341
2393
|
isAsync = v.containsAsyncOperationsComplete(funcDecl.Body, pkg)
|
|
2342
2394
|
}
|
|
2395
|
+
// Otherwise leave isAsync as false
|
|
2343
2396
|
|
|
2344
2397
|
// Store result in MethodAsyncStatus
|
|
2345
2398
|
v.analysis.MethodAsyncStatus[methodKey] = isAsync
|
|
@@ -2417,16 +2470,8 @@ func (v *analysisVisitor) containsAsyncOperationsComplete(node ast.Node, pkg *pa
|
|
|
2417
2470
|
|
|
2418
2471
|
case *ast.CallExpr:
|
|
2419
2472
|
// Check if we're calling a function known to be async
|
|
2420
|
-
|
|
2421
|
-
if isCallAsyncResult {
|
|
2473
|
+
if v.isCallAsync(s, pkg) {
|
|
2422
2474
|
hasAsync = true
|
|
2423
|
-
callName := ""
|
|
2424
|
-
if ident, ok := s.Fun.(*ast.Ident); ok {
|
|
2425
|
-
callName = ident.Name
|
|
2426
|
-
} else if sel, ok := s.Fun.(*ast.SelectorExpr); ok {
|
|
2427
|
-
callName = sel.Sel.Name
|
|
2428
|
-
}
|
|
2429
|
-
asyncReasons = append(asyncReasons, fmt.Sprintf("async call: %s", callName))
|
|
2430
2475
|
return false
|
|
2431
2476
|
}
|
|
2432
2477
|
}
|
package/go.mod
CHANGED
|
@@ -3,18 +3,18 @@ module github.com/aperturerobotics/goscript
|
|
|
3
3
|
go 1.25.3
|
|
4
4
|
|
|
5
5
|
require (
|
|
6
|
-
github.com/aperturerobotics/cli v1.0.
|
|
6
|
+
github.com/aperturerobotics/cli v1.0.1
|
|
7
7
|
github.com/aperturerobotics/protobuf-go-lite v0.11.0
|
|
8
|
-
github.com/aperturerobotics/util v1.31.
|
|
8
|
+
github.com/aperturerobotics/util v1.31.4
|
|
9
9
|
github.com/pkg/errors v0.9.1
|
|
10
10
|
github.com/sirupsen/logrus v1.9.3
|
|
11
11
|
golang.org/x/tools v0.38.0
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
require (
|
|
15
|
-
github.com/aperturerobotics/common v0.22.
|
|
15
|
+
github.com/aperturerobotics/common v0.22.12 // indirect
|
|
16
16
|
github.com/aperturerobotics/json-iterator-lite v1.0.1-0.20240713111131-be6bf89c3008 // indirect
|
|
17
|
-
github.com/xrash/smetrics v0.0.0-
|
|
17
|
+
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 // indirect
|
|
18
18
|
golang.org/x/mod v0.29.0 // indirect
|
|
19
19
|
golang.org/x/sync v0.17.0 // indirect
|
|
20
20
|
golang.org/x/sys v0.37.0 // indirect
|
package/go.sum
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
github.com/aperturerobotics/cli v1.0.0 h1:s3xT2h7eBih4/4yZKTn/HQ6P+qpk6ygWZl2416xAI1M=
|
|
2
2
|
github.com/aperturerobotics/cli v1.0.0/go.mod h1:wtlINjMcKuwyV1x4ftReuA6hHZcPB8kPMXHyQqGFCSc=
|
|
3
|
+
github.com/aperturerobotics/cli v1.0.1 h1:9KsECHGESJ/iGU13Z4zNQzKFz5bMave4bA6lPXGjtOU=
|
|
4
|
+
github.com/aperturerobotics/cli v1.0.1/go.mod h1:s1Gh4eTOGGlrPqpyi/q8aIQwk0T6yDCF7C2xPyBMtek=
|
|
3
5
|
github.com/aperturerobotics/common v0.22.10 h1:XFfXq9NGrirjW6rtqq525qiY1IN+1siGBZwIsvBJGfQ=
|
|
4
6
|
github.com/aperturerobotics/common v0.22.10/go.mod h1:xMXHNN6oCvG0FfG1tY6+2Si7iWh1QfSSCSrqohFUeIk=
|
|
7
|
+
github.com/aperturerobotics/common v0.22.12 h1:uSo+fDQg6xCoNI34Y7gueW1cW9Cy4d/2FQb/T006LZQ=
|
|
8
|
+
github.com/aperturerobotics/common v0.22.12/go.mod h1:xMXHNN6oCvG0FfG1tY6+2Si7iWh1QfSSCSrqohFUeIk=
|
|
5
9
|
github.com/aperturerobotics/json-iterator-lite v1.0.1-0.20240713111131-be6bf89c3008 h1:So9JeziaWKx2Fw8sK4AUN/szqKtJ0jEMhS6bU4sHbxs=
|
|
6
10
|
github.com/aperturerobotics/json-iterator-lite v1.0.1-0.20240713111131-be6bf89c3008/go.mod h1:snaApCEDtrHHP6UWSLKiYNOZU9A5NyzccKenx9oZEzg=
|
|
7
11
|
github.com/aperturerobotics/protobuf-go-lite v0.11.0 h1:IAaZISqrEpodqECYxk0yKWgROEbZtMhs7bErP+Zma9o=
|
|
8
12
|
github.com/aperturerobotics/protobuf-go-lite v0.11.0/go.mod h1:c4kGy7Dkfz6B1m0t4QBIMQoNeQ7m+nYj3Qxxnlwhygo=
|
|
9
13
|
github.com/aperturerobotics/util v1.31.3 h1:3irvlwlwwvOl4jD2lHg/N8bBp9B/3kx9Ec4qlJxQKEU=
|
|
10
14
|
github.com/aperturerobotics/util v1.31.3/go.mod h1:G5yKUDojt6uzVvs7kGByey0lBfKdDg4O4jXmdkSqO6Y=
|
|
15
|
+
github.com/aperturerobotics/util v1.31.4 h1:2F4j5CML/Hb4dQT1E1pjkZd3AdJhsAQiaRCR9pD/dwo=
|
|
16
|
+
github.com/aperturerobotics/util v1.31.4/go.mod h1:qfeWUnkC60QpjxH4yocO6Q/No+J1E488yzuconPgF8c=
|
|
11
17
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
12
18
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
13
19
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
@@ -25,6 +31,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
|
|
|
25
31
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
|
26
32
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
|
27
33
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
|
34
|
+
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg=
|
|
35
|
+
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
|
28
36
|
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
|
29
37
|
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
|
30
38
|
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|