vendor tsgo
This commit is contained in:
420
tools/tsgo/internal/project/refcountcache_test.go
Normal file
420
tools/tsgo/internal/project/refcountcache_test.go
Normal file
@@ -0,0 +1,420 @@
|
||||
package project
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/ast"
|
||||
"github.com/microsoft/typescript-go/internal/bundled"
|
||||
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
|
||||
"github.com/microsoft/typescript-go/internal/tspath"
|
||||
"github.com/microsoft/typescript-go/internal/vfs/vfstest"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestRefCountingCaches(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if !bundled.Embedded {
|
||||
t.Skip("bundled files are not embedded")
|
||||
}
|
||||
|
||||
setup := func(files map[string]any) *Session {
|
||||
fs := bundled.WrapFS(vfstest.FromMap(files, false /*useCaseSensitiveFileNames*/))
|
||||
session := NewSession(&SessionInit{
|
||||
BackgroundCtx: context.Background(),
|
||||
Options: &SessionOptions{
|
||||
CurrentDirectory: "/",
|
||||
DefaultLibraryPath: bundled.LibPath(),
|
||||
TypingsLocation: "/home/src/Library/Caches/typescript",
|
||||
PositionEncoding: lsproto.PositionEncodingKindUTF8,
|
||||
WatchEnabled: false,
|
||||
LoggingEnabled: false,
|
||||
},
|
||||
FS: fs,
|
||||
})
|
||||
return session
|
||||
}
|
||||
|
||||
t.Run("parseCache", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/myproject/src/main.ts": "const x = 1;",
|
||||
"/user/username/projects/myproject/src/utils.ts": "export function util() {}",
|
||||
}
|
||||
|
||||
t.Run("reuse unchanged file", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
session := setup(files)
|
||||
session.DidOpenFile(context.Background(), "file:///user/username/projects/myproject/src/main.ts", 1, files["/user/username/projects/myproject/src/main.ts"].(string), lsproto.LanguageKindTypeScript)
|
||||
session.DidOpenFile(context.Background(), "file:///user/username/projects/myproject/src/utils.ts", 1, files["/user/username/projects/myproject/src/utils.ts"].(string), lsproto.LanguageKindTypeScript)
|
||||
snapshot := session.Snapshot()
|
||||
program := snapshot.ProjectCollection.InferredProject().Program
|
||||
main := program.GetSourceFile("/user/username/projects/myproject/src/main.ts")
|
||||
utils := program.GetSourceFile("/user/username/projects/myproject/src/utils.ts")
|
||||
mainEntry, _ := session.parseCache.entries.Load(NewParseCacheKey(main.ParseOptions(), main.Hash, main.ScriptKind))
|
||||
utilsEntry, _ := session.parseCache.entries.Load(NewParseCacheKey(utils.ParseOptions(), utils.Hash, utils.ScriptKind))
|
||||
assert.Equal(t, mainEntry.refCount, 1)
|
||||
assert.Equal(t, utilsEntry.refCount, 1)
|
||||
|
||||
session.DidChangeFile(context.Background(), "file:///user/username/projects/myproject/src/main.ts", 2, []lsproto.TextDocumentContentChangePartialOrWholeDocument{
|
||||
{
|
||||
Partial: &lsproto.TextDocumentContentChangePartial{
|
||||
Range: lsproto.Range{
|
||||
Start: lsproto.Position{Line: 0, Character: 0},
|
||||
End: lsproto.Position{Line: 0, Character: 12},
|
||||
},
|
||||
Text: "const x = 2;",
|
||||
},
|
||||
},
|
||||
})
|
||||
ls, err := session.GetLanguageService(context.Background(), "file:///user/username/projects/myproject/src/main.ts")
|
||||
assert.NilError(t, err)
|
||||
session.WaitForBackgroundTasks()
|
||||
newMain := ls.GetProgram().GetSourceFile("/user/username/projects/myproject/src/main.ts")
|
||||
newMainEntry, _ := session.parseCache.entries.Load(NewParseCacheKey(newMain.ParseOptions(), newMain.Hash, newMain.ScriptKind))
|
||||
assert.Assert(t, newMain != main)
|
||||
assert.Assert(t, newMainEntry != mainEntry)
|
||||
assert.Equal(t, ls.GetProgram().GetSourceFile("/user/username/projects/myproject/src/utils.ts"), utils)
|
||||
// Old snapshot is deref'd immediately when replaced by UpdateSnapshot,
|
||||
// so old mainEntry is already disposed and utils refCount is already 1.
|
||||
assert.Equal(t, mainEntry.refCount, 0)
|
||||
assert.Equal(t, newMainEntry.refCount, 1)
|
||||
assert.Equal(t, utilsEntry.refCount, 1)
|
||||
})
|
||||
|
||||
t.Run("release file on close", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
session := setup(files)
|
||||
session.DidOpenFile(context.Background(), "file:///user/username/projects/myproject/src/main.ts", 1, files["/user/username/projects/myproject/src/main.ts"].(string), lsproto.LanguageKindTypeScript)
|
||||
session.DidOpenFile(context.Background(), "file:///user/username/projects/myproject/src/utils.ts", 1, files["/user/username/projects/myproject/src/utils.ts"].(string), lsproto.LanguageKindTypeScript)
|
||||
snapshot := session.Snapshot()
|
||||
program := snapshot.ProjectCollection.InferredProject().Program
|
||||
main := program.GetSourceFile("/user/username/projects/myproject/src/main.ts")
|
||||
utils := program.GetSourceFile("/user/username/projects/myproject/src/utils.ts")
|
||||
mainEntry, _ := session.parseCache.entries.Load(NewParseCacheKey(main.ParseOptions(), main.Hash, main.ScriptKind))
|
||||
utilsEntry, _ := session.parseCache.entries.Load(NewParseCacheKey(utils.ParseOptions(), utils.Hash, utils.ScriptKind))
|
||||
assert.Equal(t, mainEntry.refCount, 1)
|
||||
assert.Equal(t, utilsEntry.refCount, 1)
|
||||
|
||||
session.DidCloseFile(context.Background(), "file:///user/username/projects/myproject/src/main.ts")
|
||||
_, err := session.GetLanguageService(context.Background(), "file:///user/username/projects/myproject/src/utils.ts")
|
||||
assert.NilError(t, err)
|
||||
session.WaitForBackgroundTasks()
|
||||
assert.Equal(t, utilsEntry.refCount, 1)
|
||||
assert.Equal(t, mainEntry.refCount, 0)
|
||||
mainEntry, ok := session.parseCache.entries.Load(NewParseCacheKey(main.ParseOptions(), main.Hash, main.ScriptKind))
|
||||
assert.Equal(t, ok, false)
|
||||
})
|
||||
|
||||
t.Run("unchanged program does not over-ref", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// When a program is reused across snapshots without changes, we should
|
||||
// not accumulate extra refs. The ref count should stay at 1 per source file
|
||||
// until the program is finally disposed.
|
||||
session := setup(files)
|
||||
session.DidOpenFile(context.Background(), "file:///user/username/projects/myproject/src/main.ts", 1, files["/user/username/projects/myproject/src/main.ts"].(string), lsproto.LanguageKindTypeScript)
|
||||
session.DidOpenFile(context.Background(), "file:///user/username/projects/myproject/src/utils.ts", 1, files["/user/username/projects/myproject/src/utils.ts"].(string), lsproto.LanguageKindTypeScript)
|
||||
|
||||
// Get first snapshot and capture the program/entries
|
||||
snapshot1 := session.Snapshot()
|
||||
program1 := snapshot1.ProjectCollection.InferredProject().Program
|
||||
main := program1.GetSourceFile("/user/username/projects/myproject/src/main.ts")
|
||||
mainEntry, _ := session.parseCache.entries.Load(NewParseCacheKey(main.ParseOptions(), main.Hash, main.ScriptKind))
|
||||
assert.Equal(t, mainEntry.refCount, 1, "initial refCount should be 1")
|
||||
|
||||
// Change utils.ts to trigger a new snapshot, but main.ts stays the same
|
||||
// so main's source file should be reused.
|
||||
session.DidChangeFile(context.Background(), "file:///user/username/projects/myproject/src/utils.ts", 2, []lsproto.TextDocumentContentChangePartialOrWholeDocument{
|
||||
{
|
||||
Partial: &lsproto.TextDocumentContentChangePartial{
|
||||
Range: lsproto.Range{
|
||||
Start: lsproto.Position{Line: 0, Character: 0},
|
||||
End: lsproto.Position{Line: 0, Character: 25},
|
||||
},
|
||||
Text: "export function util2() {}",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// Get second snapshot - main.ts should be reused (program is new but shares source files)
|
||||
ls, err := session.GetLanguageService(context.Background(), "file:///user/username/projects/myproject/src/main.ts")
|
||||
assert.NilError(t, err)
|
||||
session.WaitForBackgroundTasks()
|
||||
program2 := ls.GetProgram()
|
||||
main2 := program2.GetSourceFile("/user/username/projects/myproject/src/main.ts")
|
||||
assert.Equal(t, main, main2, "main.ts source file should be reused")
|
||||
|
||||
// main.ts refCount should be 1: the old snapshot was immediately deref'd
|
||||
// when replaced, so only the new snapshot holds a ref.
|
||||
mainEntry, _ = session.parseCache.entries.Load(NewParseCacheKey(main.ParseOptions(), main.Hash, main.ScriptKind))
|
||||
assert.Equal(t, mainEntry.refCount, 1, "refCount should be 1 (only new snapshot)")
|
||||
|
||||
// Close files to trigger cleanup
|
||||
session.DidCloseFile(context.Background(), "file:///user/username/projects/myproject/src/main.ts")
|
||||
session.DidCloseFile(context.Background(), "file:///user/username/projects/myproject/src/utils.ts")
|
||||
session.DidOpenFile(context.Background(), "untitled:Untitled-1", 1, "", lsproto.LanguageKindTypeScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Entry should now be gone (refCount 0, deleted)
|
||||
mainEntry, ok := session.parseCache.entries.Load(NewParseCacheKey(main.ParseOptions(), main.Hash, main.ScriptKind))
|
||||
if ok {
|
||||
t.Logf("Entry still exists with refCount=%d", mainEntry.refCount)
|
||||
}
|
||||
assert.Assert(t, !ok, "entry should be deleted after program is disposed")
|
||||
})
|
||||
|
||||
t.Run("fallback rebuild does not double-ref changed file", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testFiles := map[string]any{
|
||||
"/user/username/projects/myproject/src/main.ts": "const x = 1;",
|
||||
"/user/username/projects/myproject/src/utils.ts": "export const util = 1;",
|
||||
}
|
||||
session := setup(testFiles)
|
||||
mainURI := lsproto.DocumentUri("file:///user/username/projects/myproject/src/main.ts")
|
||||
session.DidOpenFile(context.Background(), mainURI, 1, testFiles["/user/username/projects/myproject/src/main.ts"].(string), lsproto.LanguageKindTypeScript)
|
||||
|
||||
_, err := session.GetLanguageService(context.Background(), mainURI)
|
||||
assert.NilError(t, err)
|
||||
|
||||
session.DidChangeFile(context.Background(), mainURI, 2, []lsproto.TextDocumentContentChangePartialOrWholeDocument{
|
||||
{
|
||||
WholeDocument: &lsproto.TextDocumentContentChangeWholeDocument{
|
||||
Text: "import { util } from \"./utils\";\nconst x = util;",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
lsAfter, err := session.GetLanguageService(context.Background(), mainURI)
|
||||
assert.NilError(t, err)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
project := session.Snapshot().ProjectCollection.InferredProject()
|
||||
assert.Assert(t, project != nil)
|
||||
assert.Equal(t, project.ProgramUpdateKind, ProgramUpdateKindNewFiles)
|
||||
|
||||
main := lsAfter.GetProgram().GetSourceFile("/user/username/projects/myproject/src/main.ts")
|
||||
mainKey := NewParseCacheKey(main.ParseOptions(), main.Hash, main.ScriptKind)
|
||||
mainEntry, ok := session.parseCache.entries.Load(mainKey)
|
||||
assert.Assert(t, ok)
|
||||
assert.Equal(t, mainEntry.refCount, 1)
|
||||
|
||||
session.DidCloseFile(context.Background(), mainURI)
|
||||
session.DidOpenFile(context.Background(), "untitled:Untitled-1", 1, "", lsproto.LanguageKindTypeScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
_, ok = session.parseCache.entries.Load(mainKey)
|
||||
assert.Assert(t, !ok)
|
||||
})
|
||||
|
||||
t.Run("case-only duplicate loads are released on dispose", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testFiles := map[string]any{
|
||||
"/user/username/projects/myproject/src/main.ts": "import { util as a } from \"./utils\";\nimport { util as b } from \"./UTILS\";\nconst x = a + b;",
|
||||
"/user/username/projects/myproject/src/utils.ts": "export const util = 1;",
|
||||
}
|
||||
session := setup(testFiles)
|
||||
mainURI := lsproto.DocumentUri("file:///user/username/projects/myproject/src/main.ts")
|
||||
session.DidOpenFile(context.Background(), mainURI, 1, testFiles["/user/username/projects/myproject/src/main.ts"].(string), lsproto.LanguageKindTypeScript)
|
||||
|
||||
ls, err := session.GetLanguageService(context.Background(), mainURI)
|
||||
assert.NilError(t, err)
|
||||
|
||||
var projectEntries int
|
||||
session.parseCache.entries.Range(func(key ParseCacheKey, _ *refCountCacheEntry[*ast.SourceFile]) bool {
|
||||
if strings.HasPrefix(key.FileName, "/user/username/projects/myproject/src/") {
|
||||
projectEntries++
|
||||
}
|
||||
return true
|
||||
})
|
||||
assert.Equal(t, projectEntries, 3)
|
||||
|
||||
utils := ls.GetProgram().GetSourceFile("/user/username/projects/myproject/src/utils.ts")
|
||||
assert.Assert(t, utils != nil)
|
||||
|
||||
session.DidCloseFile(context.Background(), mainURI)
|
||||
session.DidOpenFile(context.Background(), "untitled:Untitled-1", 1, "", lsproto.LanguageKindTypeScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
projectEntries = 0
|
||||
session.parseCache.entries.Range(func(key ParseCacheKey, _ *refCountCacheEntry[*ast.SourceFile]) bool {
|
||||
if strings.HasPrefix(key.FileName, "/user/username/projects/myproject/src/") {
|
||||
projectEntries++
|
||||
}
|
||||
return true
|
||||
})
|
||||
assert.Equal(t, projectEntries, 0)
|
||||
})
|
||||
|
||||
t.Run("case-only duplicate imported from multiple files is refcounted once", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// A file reached through a case-only-different file name from more than one
|
||||
// import site is parsed and acquired in the parse cache exactly once (same-casing
|
||||
// loads dedupe), but it must also be recorded as a duplicate exactly once.
|
||||
// Recording it once per import site would release it from the parse cache more
|
||||
// times than it was acquired, deleting the live entry out from under a program
|
||||
// that still references it and panicking the next time it is ref'd during a clone.
|
||||
testFiles := map[string]any{
|
||||
// entry.ts imports the canonical casing first, then pulls in a.ts and b.ts,
|
||||
// which both import the same file through an upper-cased name.
|
||||
"/user/username/projects/myproject/src/entry.ts": "import { dep } from './sub/dep';\nimport './a';\nimport './b';\nexport const e = dep;",
|
||||
"/user/username/projects/myproject/src/a.ts": "import { dep } from './sub/DEP';\nexport const a = dep;",
|
||||
"/user/username/projects/myproject/src/b.ts": "import { dep } from './sub/DEP';\nexport const b = dep;",
|
||||
"/user/username/projects/myproject/src/sub/dep.ts": "export const dep = 1;",
|
||||
"/user/username/projects/myproject/src/c.ts": "export const c = 1;",
|
||||
}
|
||||
session := setup(testFiles)
|
||||
entryURI := lsproto.DocumentUri("file:///user/username/projects/myproject/src/entry.ts")
|
||||
session.DidOpenFile(context.Background(), entryURI, 1, testFiles["/user/username/projects/myproject/src/entry.ts"].(string), lsproto.LanguageKindTypeScript)
|
||||
|
||||
ls, err := session.GetLanguageService(context.Background(), entryURI)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// The upper-cased name is recorded as a duplicate, and it should appear exactly once.
|
||||
program := ls.GetProgram()
|
||||
var dupKeys []ParseCacheKey
|
||||
for _, dup := range program.DuplicateSourceFiles() {
|
||||
if strings.HasSuffix(dup.ParseOptions.FileName, "/sub/DEP.ts") {
|
||||
dupKeys = append(dupKeys, NewParseCacheKey(dup.ParseOptions, dup.Hash, dup.ScriptKind))
|
||||
}
|
||||
}
|
||||
assert.Equal(t, len(dupKeys), 1, "case-only duplicate should be recorded exactly once")
|
||||
dupEntry, ok := session.parseCache.entries.Load(dupKeys[0])
|
||||
assert.Assert(t, ok, "duplicate entry should exist in the parse cache")
|
||||
assert.Equal(t, dupEntry.refCount, 1)
|
||||
|
||||
// Force a full program rebuild (adding an import changes the file's module
|
||||
// structure). The old snapshot is disposed, releasing each of its source and
|
||||
// duplicate files exactly once. If the duplicate were recorded twice, the
|
||||
// shared cache entry would be released to zero and deleted here even though
|
||||
// the new program still references it.
|
||||
session.DidChangeFile(context.Background(), entryURI, 2, []lsproto.TextDocumentContentChangePartialOrWholeDocument{
|
||||
{
|
||||
WholeDocument: &lsproto.TextDocumentContentChangeWholeDocument{
|
||||
Text: "import { dep } from \"./sub/dep\";\nimport \"./a\";\nimport \"./b\";\nimport \"./c\";\nexport const e = dep;",
|
||||
},
|
||||
},
|
||||
})
|
||||
lsAfterRebuild, err := session.GetLanguageService(context.Background(), entryURI)
|
||||
assert.NilError(t, err)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Every parse-cache key referenced by the live program must still exist.
|
||||
rebuiltProgram := lsAfterRebuild.GetProgram()
|
||||
assertKeyAlive := func(key ParseCacheKey) {
|
||||
_, alive := session.parseCache.entries.Load(key)
|
||||
assert.Assert(t, alive, "live program references a deleted parse-cache entry: %s", key.FileName)
|
||||
}
|
||||
for _, file := range rebuiltProgram.SourceFiles() {
|
||||
assertKeyAlive(NewParseCacheKey(file.ParseOptions(), file.Hash, file.ScriptKind))
|
||||
}
|
||||
for _, dup := range rebuiltProgram.DuplicateSourceFiles() {
|
||||
assertKeyAlive(NewParseCacheKey(dup.ParseOptions, dup.Hash, dup.ScriptKind))
|
||||
}
|
||||
|
||||
// An incremental (clone) update re-references the duplicate files; this must
|
||||
// not panic with "cache entry not found".
|
||||
session.DidChangeFile(context.Background(), entryURI, 3, []lsproto.TextDocumentContentChangePartialOrWholeDocument{
|
||||
{
|
||||
WholeDocument: &lsproto.TextDocumentContentChangeWholeDocument{
|
||||
Text: "import { dep } from './sub/dep';\nimport './a';\nimport './b';\nimport './c';\nexport const e = dep + 0;",
|
||||
},
|
||||
},
|
||||
})
|
||||
_, err = session.GetLanguageService(context.Background(), entryURI)
|
||||
assert.NilError(t, err)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Closing the project releases everything cleanly.
|
||||
// (The configured project is not disposed until another file in another project is opened,
|
||||
// so we open an untitled file to trigger that.)
|
||||
session.DidCloseFile(context.Background(), entryURI)
|
||||
session.DidOpenFile(context.Background(), "untitled:Untitled-1", 1, "", lsproto.LanguageKindTypeScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
projectEntries := 0
|
||||
session.parseCache.entries.Range(func(key ParseCacheKey, _ *refCountCacheEntry[*ast.SourceFile]) bool {
|
||||
if strings.HasPrefix(key.FileName, "/user/username/projects/myproject/src/") {
|
||||
projectEntries++
|
||||
}
|
||||
return true
|
||||
})
|
||||
assert.Equal(t, projectEntries, 0)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("extendedConfigCache", func(t *testing.T) {
|
||||
files := map[string]any{
|
||||
"/user/username/projects/myproject/tsconfig.json": `{
|
||||
"extends": "./tsconfig.base.json"
|
||||
}`,
|
||||
"/user/username/projects/myproject/tsconfig.base.json": `{
|
||||
"compilerOptions": {}
|
||||
}`,
|
||||
"/user/username/projects/myproject/src/main.ts": "const x = 1;",
|
||||
}
|
||||
|
||||
t.Run("release extended configs with project close", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
session := setup(files)
|
||||
session.DidOpenFile(context.Background(), "file:///user/username/projects/myproject/src/main.ts", 1, files["/user/username/projects/myproject/src/main.ts"].(string), lsproto.LanguageKindTypeScript)
|
||||
snapshot := session.Snapshot()
|
||||
config := snapshot.ConfigFileRegistry.GetConfig("/user/username/projects/myproject/tsconfig.json")
|
||||
assert.Equal(t, config.ExtendedSourceFiles()[0], "/user/username/projects/myproject/tsconfig.base.json")
|
||||
extendedConfigEntry, _ := session.extendedConfigCache.entries.Load("/user/username/projects/myproject/tsconfig.base.json")
|
||||
assert.Equal(t, len(extendedConfigEntry.owners), 1)
|
||||
|
||||
session.DidCloseFile(context.Background(), "file:///user/username/projects/myproject/src/main.ts")
|
||||
session.DidOpenFile(context.Background(), "untitled:Untitled-1", 1, "", lsproto.LanguageKindTypeScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
_, ok := session.extendedConfigCache.entries.Load("/user/username/projects/myproject/tsconfig.base.json")
|
||||
assert.Equal(t, ok, false)
|
||||
})
|
||||
|
||||
t.Run("release cache entries for unretained clone", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
session := setup(files)
|
||||
uri := lsproto.DocumentUri("file:///user/username/projects/myproject/src/main.ts")
|
||||
baseSnapshot := session.Snapshot()
|
||||
extendedConfigPath := tspath.Path("/user/username/projects/myproject/tsconfig.base.json")
|
||||
clone := baseSnapshot.Clone(context.Background(), SnapshotChange{
|
||||
reason: UpdateReasonRequestedLanguageServiceProjectNotLoaded,
|
||||
ResourceRequest: ResourceRequest{
|
||||
Documents: []lsproto.DocumentUri{uri},
|
||||
},
|
||||
}, baseSnapshot.fs.overlays, session)
|
||||
|
||||
project := clone.GetDefaultProject(uri)
|
||||
assert.Assert(t, project != nil)
|
||||
assert.Equal(t, project.ProgramLastUpdate, clone.id)
|
||||
|
||||
main := project.Program.GetSourceFile("/user/username/projects/myproject/src/main.ts")
|
||||
mainKey := NewParseCacheKey(main.ParseOptions(), main.Hash, main.ScriptKind)
|
||||
mainEntry, ok := session.parseCache.entries.Load(mainKey)
|
||||
assert.Assert(t, ok)
|
||||
assert.Equal(t, mainEntry.refCount, 1)
|
||||
|
||||
extendedConfigEntry, ok := session.extendedConfigCache.entries.Load(extendedConfigPath)
|
||||
assert.Assert(t, ok)
|
||||
assert.Equal(t, len(extendedConfigEntry.owners), 1)
|
||||
|
||||
clone.Deref(session)
|
||||
|
||||
_, ok = session.parseCache.entries.Load(mainKey)
|
||||
assert.Assert(t, !ok)
|
||||
|
||||
_, ok = session.extendedConfigCache.entries.Load(extendedConfigPath)
|
||||
assert.Assert(t, !ok)
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user