@@ -12,27 +12,27 @@ import (
12
12
"github.com/microsoft/typescript-go/internal/astnav"
13
13
"github.com/microsoft/typescript-go/internal/checker"
14
14
"github.com/microsoft/typescript-go/internal/core"
15
- "github.com/microsoft/typescript-go/internal/lsp/lsproto "
15
+ "github.com/microsoft/typescript-go/internal/ls "
16
16
"github.com/microsoft/typescript-go/internal/project"
17
+ "github.com/microsoft/typescript-go/internal/project/logging"
17
18
"github.com/microsoft/typescript-go/internal/tsoptions"
18
19
"github.com/microsoft/typescript-go/internal/tspath"
19
20
"github.com/microsoft/typescript-go/internal/vfs"
20
21
)
21
22
22
23
type handleMap [T any ] map [Handle [T ]]* T
23
24
24
- type APIOptions struct {
25
- Logger * project.Logger
25
+ type APIInit struct {
26
+ Logger logging.Logger
27
+ FS vfs.FS
28
+ SessionOptions * project.SessionOptions
26
29
}
27
30
28
31
type API struct {
29
- host APIHost
30
- options APIOptions
32
+ logger logging. Logger
33
+ session * project. Session
31
34
32
- documentStore * project.DocumentStore
33
- configFileRegistry * project.ConfigFileRegistry
34
-
35
- projects handleMap [project.Project ]
35
+ projects map [Handle [project.Project ]]tspath.Path
36
36
filesMu sync.Mutex
37
37
files handleMap [ast.SourceFile ]
38
38
symbolsMu sync.Mutex
@@ -41,91 +41,22 @@ type API struct {
41
41
types handleMap [checker.Type ]
42
42
}
43
43
44
- var _ project.ProjectHost = (* API )(nil )
45
-
46
- func NewAPI (host APIHost , options APIOptions ) * API {
44
+ func NewAPI (init * APIInit ) * API {
47
45
api := & API {
48
- host : host ,
49
- options : options ,
50
- projects : make (handleMap [project.Project ]),
46
+ session : project .NewSession (& project.SessionInit {
47
+ Logger : init .Logger ,
48
+ FS : init .FS ,
49
+ Options : init .SessionOptions ,
50
+ }),
51
+ projects : make (map [Handle [project.Project ]]tspath.Path ),
51
52
files : make (handleMap [ast.SourceFile ]),
52
53
symbols : make (handleMap [ast.Symbol ]),
53
54
types : make (handleMap [checker.Type ]),
54
55
}
55
56
56
- api .documentStore = project .NewDocumentStore (project.DocumentStoreOptions {
57
- ComparePathsOptions : tspath.ComparePathsOptions {
58
- UseCaseSensitiveFileNames : host .FS ().UseCaseSensitiveFileNames (),
59
- CurrentDirectory : host .GetCurrentDirectory (),
60
- },
61
- Hooks : project.DocumentRegistryHooks {
62
- OnReleaseDocument : func (file * ast.SourceFile ) {
63
- _ = api .releaseHandle (string (FileHandle (file )))
64
- },
65
- },
66
- })
67
-
68
- api .configFileRegistry = & project.ConfigFileRegistry {
69
- Host : api ,
70
- }
71
57
return api
72
58
}
73
59
74
- // DefaultLibraryPath implements ProjectHost.
75
- func (api * API ) DefaultLibraryPath () string {
76
- return api .host .DefaultLibraryPath ()
77
- }
78
-
79
- // TypingsInstaller implements ProjectHost
80
- func (api * API ) TypingsInstaller () * project.TypingsInstaller {
81
- return nil
82
- }
83
-
84
- // DocumentStore implements ProjectHost.
85
- func (api * API ) DocumentStore () * project.DocumentStore {
86
- return api .documentStore
87
- }
88
-
89
- // ConfigFileRegistry implements ProjectHost.
90
- func (api * API ) ConfigFileRegistry () * project.ConfigFileRegistry {
91
- return api .configFileRegistry
92
- }
93
-
94
- // FS implements ProjectHost.
95
- func (api * API ) FS () vfs.FS {
96
- return api .host .FS ()
97
- }
98
-
99
- // GetCurrentDirectory implements ProjectHost.
100
- func (api * API ) GetCurrentDirectory () string {
101
- return api .host .GetCurrentDirectory ()
102
- }
103
-
104
- // Log implements ProjectHost.
105
- func (api * API ) Log (s string ) {
106
- api .options .Logger .Info (s )
107
- }
108
-
109
- // Log implements ProjectHost.
110
- func (api * API ) Trace (s string ) {
111
- api .options .Logger .Info (s )
112
- }
113
-
114
- // PositionEncoding implements ProjectHost.
115
- func (api * API ) PositionEncoding () lsproto.PositionEncodingKind {
116
- return lsproto .PositionEncodingKindUTF8
117
- }
118
-
119
- // Client implements ProjectHost.
120
- func (api * API ) Client () project.Client {
121
- return nil
122
- }
123
-
124
- // IsWatchEnabled implements ProjectHost.
125
- func (api * API ) IsWatchEnabled () bool {
126
- return false
127
- }
128
-
129
60
func (api * API ) HandleRequest (ctx context.Context , method string , payload []byte ) ([]byte , error ) {
130
61
params , err := unmarshalPayload (method , payload )
131
62
if err != nil {
@@ -149,7 +80,7 @@ func (api *API) HandleRequest(ctx context.Context, method string, payload []byte
149
80
case MethodParseConfigFile :
150
81
return encodeJSON (api .ParseConfigFile (params .(* ParseConfigFileParams ).FileName ))
151
82
case MethodLoadProject :
152
- return encodeJSON (api .LoadProject (params .(* LoadProjectParams ).ConfigFileName ))
83
+ return encodeJSON (api .LoadProject (ctx , params .(* LoadProjectParams ).ConfigFileName ))
153
84
case MethodGetSymbolAtPosition :
154
85
params := params .(* GetSymbolAtPositionParams )
155
86
return encodeJSON (api .GetSymbolAtPosition (ctx , params .Project , params .FileName , int (params .Position )))
@@ -180,20 +111,20 @@ func (api *API) HandleRequest(ctx context.Context, method string, payload []byte
180
111
}
181
112
182
113
func (api * API ) Close () {
183
- api .options . Logger .Close ()
114
+ api .session .Close ()
184
115
}
185
116
186
117
func (api * API ) ParseConfigFile (configFileName string ) (* ConfigFileResponse , error ) {
187
118
configFileName = api .toAbsoluteFileName (configFileName )
188
- configFileContent , ok := api .host .FS ().ReadFile (configFileName )
119
+ configFileContent , ok := api .session .FS ().ReadFile (configFileName )
189
120
if ! ok {
190
121
return nil , fmt .Errorf ("could not read file %q" , configFileName )
191
122
}
192
123
configDir := tspath .GetDirectoryPath (configFileName )
193
124
tsConfigSourceFile := tsoptions .NewTsconfigSourceFileFromFilePath (configFileName , api .toPath (configFileName ), configFileContent )
194
125
parsedCommandLine := tsoptions .ParseJsonSourceFileConfigFileContent (
195
126
tsConfigSourceFile ,
196
- api .host ,
127
+ api .session ,
197
128
configDir ,
198
129
nil , /*existingOptions*/
199
130
configFileName ,
@@ -207,26 +138,29 @@ func (api *API) ParseConfigFile(configFileName string) (*ConfigFileResponse, err
207
138
}, nil
208
139
}
209
140
210
- func (api * API ) LoadProject (configFileName string ) (* ProjectResponse , error ) {
211
- configFileName = api .toAbsoluteFileName (configFileName )
212
- configFilePath := api .toPath (configFileName )
213
- p := project .NewConfiguredProject (configFileName , configFilePath , api )
214
- if err := p .LoadConfig (); err != nil {
141
+ func (api * API ) LoadProject (ctx context.Context , configFileName string ) (* ProjectResponse , error ) {
142
+ project , err := api .session .OpenProject (ctx , api .toAbsoluteFileName (configFileName ))
143
+ if err != nil {
215
144
return nil , err
216
145
}
217
- p .GetProgram ()
218
- data := NewProjectResponse (p )
219
- api .projects [data .Id ] = p
146
+ data := NewProjectResponse (project )
147
+ api .projects [data .Id ] = project .ConfigFilePath ()
220
148
return data , nil
221
149
}
222
150
223
151
func (api * API ) GetSymbolAtPosition (ctx context.Context , projectId Handle [project.Project ], fileName string , position int ) (* SymbolResponse , error ) {
224
- project , ok := api .projects [projectId ]
152
+ projectPath , ok := api .projects [projectId ]
225
153
if ! ok {
154
+ return nil , errors .New ("project ID not found" )
155
+ }
156
+ snapshot , release := api .session .Snapshot ()
157
+ defer release ()
158
+ project := snapshot .ProjectCollection .GetProjectByPath (projectPath )
159
+ if project == nil {
226
160
return nil , errors .New ("project not found" )
227
161
}
228
- languageService , done := project . GetLanguageServiceForRequest ( ctx )
229
- defer done ( )
162
+
163
+ languageService := ls . NewLanguageService ( project , snapshot . Converters () )
230
164
symbol , err := languageService .GetSymbolAtPosition (ctx , fileName , position )
231
165
if err != nil || symbol == nil {
232
166
return nil , err
@@ -239,10 +173,17 @@ func (api *API) GetSymbolAtPosition(ctx context.Context, projectId Handle[projec
239
173
}
240
174
241
175
func (api * API ) GetSymbolAtLocation (ctx context.Context , projectId Handle [project.Project ], location Handle [ast.Node ]) (* SymbolResponse , error ) {
242
- project , ok := api .projects [projectId ]
176
+ projectPath , ok := api .projects [projectId ]
243
177
if ! ok {
178
+ return nil , errors .New ("project ID not found" )
179
+ }
180
+ snapshot , release := api .session .Snapshot ()
181
+ defer release ()
182
+ project := snapshot .ProjectCollection .GetProjectByPath (projectPath )
183
+ if project == nil {
244
184
return nil , errors .New ("project not found" )
245
185
}
186
+
246
187
fileHandle , pos , kind , err := parseNodeHandle (location )
247
188
if err != nil {
248
189
return nil , err
@@ -261,8 +202,7 @@ func (api *API) GetSymbolAtLocation(ctx context.Context, projectId Handle[projec
261
202
if node == nil {
262
203
return nil , fmt .Errorf ("node of kind %s not found at position %d in file %q" , kind .String (), pos , sourceFile .FileName ())
263
204
}
264
- languageService , done := project .GetLanguageServiceForRequest (ctx )
265
- defer done ()
205
+ languageService := ls .NewLanguageService (project , snapshot .Converters ())
266
206
symbol := languageService .GetSymbolAtLocation (ctx , node )
267
207
if symbol == nil {
268
208
return nil , nil
@@ -275,18 +215,24 @@ func (api *API) GetSymbolAtLocation(ctx context.Context, projectId Handle[projec
275
215
}
276
216
277
217
func (api * API ) GetTypeOfSymbol (ctx context.Context , projectId Handle [project.Project ], symbolHandle Handle [ast.Symbol ]) (* TypeResponse , error ) {
278
- project , ok := api .projects [projectId ]
218
+ projectPath , ok := api .projects [projectId ]
279
219
if ! ok {
220
+ return nil , errors .New ("project ID not found" )
221
+ }
222
+ snapshot , release := api .session .Snapshot ()
223
+ defer release ()
224
+ project := snapshot .ProjectCollection .GetProjectByPath (projectPath )
225
+ if project == nil {
280
226
return nil , errors .New ("project not found" )
281
227
}
228
+
282
229
api .symbolsMu .Lock ()
283
230
defer api .symbolsMu .Unlock ()
284
231
symbol , ok := api .symbols [symbolHandle ]
285
232
if ! ok {
286
233
return nil , fmt .Errorf ("symbol %q not found" , symbolHandle )
287
234
}
288
- languageService , done := project .GetLanguageServiceForRequest (ctx )
289
- defer done ()
235
+ languageService := ls .NewLanguageService (project , snapshot .Converters ())
290
236
t := languageService .GetTypeOfSymbol (ctx , symbol )
291
237
if t == nil {
292
238
return nil , nil
@@ -295,10 +241,17 @@ func (api *API) GetTypeOfSymbol(ctx context.Context, projectId Handle[project.Pr
295
241
}
296
242
297
243
func (api * API ) GetSourceFile (projectId Handle [project.Project ], fileName string ) (* ast.SourceFile , error ) {
298
- project , ok := api .projects [projectId ]
244
+ projectPath , ok := api .projects [projectId ]
299
245
if ! ok {
246
+ return nil , errors .New ("project ID not found" )
247
+ }
248
+ snapshot , release := api .session .Snapshot ()
249
+ defer release ()
250
+ project := snapshot .ProjectCollection .GetProjectByPath (projectPath )
251
+ if project == nil {
300
252
return nil , errors .New ("project not found" )
301
253
}
254
+
302
255
sourceFile := project .GetProgram ().GetSourceFile (fileName )
303
256
if sourceFile == nil {
304
257
return nil , fmt .Errorf ("source file %q not found" , fileName )
@@ -313,12 +266,11 @@ func (api *API) releaseHandle(handle string) error {
313
266
switch handle [0 ] {
314
267
case handlePrefixProject :
315
268
projectId := Handle [project.Project ](handle )
316
- project , ok := api .projects [projectId ]
269
+ _ , ok := api .projects [projectId ]
317
270
if ! ok {
318
271
return fmt .Errorf ("project %q not found" , handle )
319
272
}
320
273
delete (api .projects , projectId )
321
- project .Close ()
322
274
case handlePrefixFile :
323
275
fileId := Handle [ast.SourceFile ](handle )
324
276
api .filesMu .Lock ()
@@ -353,11 +305,11 @@ func (api *API) releaseHandle(handle string) error {
353
305
}
354
306
355
307
func (api * API ) toAbsoluteFileName (fileName string ) string {
356
- return tspath .GetNormalizedAbsolutePath (fileName , api .host .GetCurrentDirectory ())
308
+ return tspath .GetNormalizedAbsolutePath (fileName , api .session .GetCurrentDirectory ())
357
309
}
358
310
359
311
func (api * API ) toPath (fileName string ) tspath.Path {
360
- return tspath .ToPath (fileName , api .host .GetCurrentDirectory (), api .host .FS ().UseCaseSensitiveFileNames ())
312
+ return tspath .ToPath (fileName , api .session .GetCurrentDirectory (), api .session .FS ().UseCaseSensitiveFileNames ())
361
313
}
362
314
363
315
func encodeJSON (v any , err error ) ([]byte , error ) {
0 commit comments