|
5 | 5 | "testing" |
6 | 6 |
|
7 | 7 | "github.com/microsoft/typescript-go/internal/bundled" |
| 8 | + "github.com/microsoft/typescript-go/internal/lsp/lsproto" |
8 | 9 | "github.com/microsoft/typescript-go/internal/testutil/projecttestutil" |
9 | 10 | "github.com/microsoft/typescript-go/internal/tspath" |
10 | 11 | "gotest.tools/v3/assert" |
@@ -192,3 +193,63 @@ func TestSessionTracksAndReleasesAPIRefs(t *testing.T) { |
192 | 193 | ) |
193 | 194 | }) |
194 | 195 | } |
| 196 | + |
| 197 | +// TestUpdateSnapshotResponseSkipsUnloadedAncestorProject verifies that API |
| 198 | +// updateSnapshot does not report unloaded ancestor project placeholders. This |
| 199 | +// covers the case where opening a file loads its nearest configured project |
| 200 | +// while solution search discovers an ancestor tsconfig placeholder whose command |
| 201 | +// line is still nil. |
| 202 | +func TestUpdateSnapshotResponseSkipsUnloadedAncestorProject(t *testing.T) { |
| 203 | + t.Parallel() |
| 204 | + if !bundled.Embedded { |
| 205 | + t.Skip("bundled files are not embedded") |
| 206 | + } |
| 207 | + |
| 208 | + const ( |
| 209 | + nestedConfigFileName = "/repo/packages/app/tsconfig.json" |
| 210 | + ancestorConfigFileName = "/repo/packages/tsconfig.json" |
| 211 | + fileName = "/repo/packages/app/src/index.ts" |
| 212 | + ) |
| 213 | + files := map[string]any{ |
| 214 | + ancestorConfigFileName: `{ "files": [] }`, |
| 215 | + nestedConfigFileName: `{ |
| 216 | + "compilerOptions": { "composite": true }, |
| 217 | + "include": ["**/*"] |
| 218 | + }`, |
| 219 | + fileName: `let s: string = 1234;`, |
| 220 | + } |
| 221 | + projectSession, _ := projecttestutil.Setup(files) |
| 222 | + defer projectSession.Close() |
| 223 | + |
| 224 | + projectSession.DidOpenFile(context.Background(), lsproto.DocumentUri("file://"+fileName), 1, files[fileName].(string), lsproto.LanguageKindTypeScript) |
| 225 | + snapshot := projectSession.Snapshot() |
| 226 | + nestedProject := snapshot.ProjectCollection.ConfiguredProject(tspath.Path(nestedConfigFileName)) |
| 227 | + assert.Assert(t, nestedProject != nil) |
| 228 | + assert.Assert(t, nestedProject.CommandLine != nil) |
| 229 | + ancestorProject := snapshot.ProjectCollection.ConfiguredProject(tspath.Path(ancestorConfigFileName)) |
| 230 | + assert.Assert(t, ancestorProject != nil) |
| 231 | + assert.Assert(t, ancestorProject.CommandLine == nil) |
| 232 | + |
| 233 | + session := NewSession(projectSession, nil) |
| 234 | + defer session.Close() |
| 235 | + |
| 236 | + response, err := session.handleUpdateSnapshot(context.Background(), &UpdateSnapshotParams{ |
| 237 | + OpenProjects: []DocumentIdentifier{{FileName: nestedConfigFileName}}, |
| 238 | + }) |
| 239 | + assert.NilError(t, err) |
| 240 | + |
| 241 | + var foundNestedProject bool |
| 242 | + var foundAncestorProject bool |
| 243 | + for _, project := range response.Projects { |
| 244 | + switch project.ConfigFileName { |
| 245 | + case nestedConfigFileName: |
| 246 | + foundNestedProject = true |
| 247 | + assert.Assert(t, project.RootFiles != nil) |
| 248 | + assert.Assert(t, project.CompilerOptions != nil) |
| 249 | + case ancestorConfigFileName: |
| 250 | + foundAncestorProject = true |
| 251 | + } |
| 252 | + } |
| 253 | + assert.Assert(t, foundNestedProject) |
| 254 | + assert.Assert(t, !foundAncestorProject) |
| 255 | +} |
0 commit comments