@@ -12,27 +12,27 @@ import (
1212 "github.com/microsoft/typescript-go/internal/astnav"
1313 "github.com/microsoft/typescript-go/internal/checker"
1414 "github.com/microsoft/typescript-go/internal/core"
15- "github.com/microsoft/typescript-go/internal/lsp/lsproto "
15+ "github.com/microsoft/typescript-go/internal/ls "
1616 "github.com/microsoft/typescript-go/internal/project"
17+ "github.com/microsoft/typescript-go/internal/project/logging"
1718 "github.com/microsoft/typescript-go/internal/tsoptions"
1819 "github.com/microsoft/typescript-go/internal/tspath"
1920 "github.com/microsoft/typescript-go/internal/vfs"
2021)
2122
2223type handleMap [T any ] map [Handle [T ]]* T
2324
24- type APIOptions struct {
25- Logger * project.Logger
25+ type APIInit struct {
26+ Logger logging.Logger
27+ FS vfs.FS
28+ SessionOptions * project.SessionOptions
2629}
2730
2831type API struct {
29- host APIHost
30- options APIOptions
32+ logger logging. Logger
33+ session * project. Session
3134
32- documentStore * project.DocumentStore
33- configFileRegistry * project.ConfigFileRegistry
34-
35- projects handleMap [project.Project ]
35+ projects map [Handle [project.Project ]]tspath.Path
3636 filesMu sync.Mutex
3737 files handleMap [ast.SourceFile ]
3838 symbolsMu sync.Mutex
@@ -41,91 +41,22 @@ type API struct {
4141 types handleMap [checker.Type ]
4242}
4343
44- var _ project.ProjectHost = (* API )(nil )
45-
46- func NewAPI (host APIHost , options APIOptions ) * API {
44+ func NewAPI (init * APIInit ) * API {
4745 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 ),
5152 files : make (handleMap [ast.SourceFile ]),
5253 symbols : make (handleMap [ast.Symbol ]),
5354 types : make (handleMap [checker.Type ]),
5455 }
5556
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- }
7157 return api
7258}
7359
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-
12960func (api * API ) HandleRequest (ctx context.Context , method string , payload []byte ) ([]byte , error ) {
13061 params , err := unmarshalPayload (method , payload )
13162 if err != nil {
@@ -149,7 +80,7 @@ func (api *API) HandleRequest(ctx context.Context, method string, payload []byte
14980 case MethodParseConfigFile :
15081 return encodeJSON (api .ParseConfigFile (params .(* ParseConfigFileParams ).FileName ))
15182 case MethodLoadProject :
152- return encodeJSON (api .LoadProject (params .(* LoadProjectParams ).ConfigFileName ))
83+ return encodeJSON (api .LoadProject (ctx , params .(* LoadProjectParams ).ConfigFileName ))
15384 case MethodGetSymbolAtPosition :
15485 params := params .(* GetSymbolAtPositionParams )
15586 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
180111}
181112
182113func (api * API ) Close () {
183- api .options . Logger .Close ()
114+ api .session .Close ()
184115}
185116
186117func (api * API ) ParseConfigFile (configFileName string ) (* ConfigFileResponse , error ) {
187118 configFileName = api .toAbsoluteFileName (configFileName )
188- configFileContent , ok := api .host .FS ().ReadFile (configFileName )
119+ configFileContent , ok := api .session .FS ().ReadFile (configFileName )
189120 if ! ok {
190121 return nil , fmt .Errorf ("could not read file %q" , configFileName )
191122 }
192123 configDir := tspath .GetDirectoryPath (configFileName )
193124 tsConfigSourceFile := tsoptions .NewTsconfigSourceFileFromFilePath (configFileName , api .toPath (configFileName ), configFileContent )
194125 parsedCommandLine := tsoptions .ParseJsonSourceFileConfigFileContent (
195126 tsConfigSourceFile ,
196- api .host ,
127+ api .session ,
197128 configDir ,
198129 nil , /*existingOptions*/
199130 configFileName ,
@@ -207,26 +138,29 @@ func (api *API) ParseConfigFile(configFileName string) (*ConfigFileResponse, err
207138 }, nil
208139}
209140
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 {
215144 return nil , err
216145 }
217- p .GetProgram ()
218- data := NewProjectResponse (p )
219- api .projects [data .Id ] = p
146+ data := NewProjectResponse (project )
147+ api .projects [data .Id ] = project .ConfigFilePath ()
220148 return data , nil
221149}
222150
223151func (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 ]
225153 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 {
226160 return nil , errors .New ("project not found" )
227161 }
228- languageService , done := project . GetLanguageServiceForRequest ( ctx )
229- defer done ( )
162+
163+ languageService := ls . NewLanguageService ( project , snapshot . Converters () )
230164 symbol , err := languageService .GetSymbolAtPosition (ctx , fileName , position )
231165 if err != nil || symbol == nil {
232166 return nil , err
@@ -239,10 +173,17 @@ func (api *API) GetSymbolAtPosition(ctx context.Context, projectId Handle[projec
239173}
240174
241175func (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 ]
243177 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 {
244184 return nil , errors .New ("project not found" )
245185 }
186+
246187 fileHandle , pos , kind , err := parseNodeHandle (location )
247188 if err != nil {
248189 return nil , err
@@ -261,8 +202,7 @@ func (api *API) GetSymbolAtLocation(ctx context.Context, projectId Handle[projec
261202 if node == nil {
262203 return nil , fmt .Errorf ("node of kind %s not found at position %d in file %q" , kind .String (), pos , sourceFile .FileName ())
263204 }
264- languageService , done := project .GetLanguageServiceForRequest (ctx )
265- defer done ()
205+ languageService := ls .NewLanguageService (project , snapshot .Converters ())
266206 symbol := languageService .GetSymbolAtLocation (ctx , node )
267207 if symbol == nil {
268208 return nil , nil
@@ -275,18 +215,24 @@ func (api *API) GetSymbolAtLocation(ctx context.Context, projectId Handle[projec
275215}
276216
277217func (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 ]
279219 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 {
280226 return nil , errors .New ("project not found" )
281227 }
228+
282229 api .symbolsMu .Lock ()
283230 defer api .symbolsMu .Unlock ()
284231 symbol , ok := api .symbols [symbolHandle ]
285232 if ! ok {
286233 return nil , fmt .Errorf ("symbol %q not found" , symbolHandle )
287234 }
288- languageService , done := project .GetLanguageServiceForRequest (ctx )
289- defer done ()
235+ languageService := ls .NewLanguageService (project , snapshot .Converters ())
290236 t := languageService .GetTypeOfSymbol (ctx , symbol )
291237 if t == nil {
292238 return nil , nil
@@ -295,10 +241,17 @@ func (api *API) GetTypeOfSymbol(ctx context.Context, projectId Handle[project.Pr
295241}
296242
297243func (api * API ) GetSourceFile (projectId Handle [project.Project ], fileName string ) (* ast.SourceFile , error ) {
298- project , ok := api .projects [projectId ]
244+ projectPath , ok := api .projects [projectId ]
299245 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 {
300252 return nil , errors .New ("project not found" )
301253 }
254+
302255 sourceFile := project .GetProgram ().GetSourceFile (fileName )
303256 if sourceFile == nil {
304257 return nil , fmt .Errorf ("source file %q not found" , fileName )
@@ -313,12 +266,11 @@ func (api *API) releaseHandle(handle string) error {
313266 switch handle [0 ] {
314267 case handlePrefixProject :
315268 projectId := Handle [project.Project ](handle )
316- project , ok := api .projects [projectId ]
269+ _ , ok := api .projects [projectId ]
317270 if ! ok {
318271 return fmt .Errorf ("project %q not found" , handle )
319272 }
320273 delete (api .projects , projectId )
321- project .Close ()
322274 case handlePrefixFile :
323275 fileId := Handle [ast.SourceFile ](handle )
324276 api .filesMu .Lock ()
@@ -353,11 +305,11 @@ func (api *API) releaseHandle(handle string) error {
353305}
354306
355307func (api * API ) toAbsoluteFileName (fileName string ) string {
356- return tspath .GetNormalizedAbsolutePath (fileName , api .host .GetCurrentDirectory ())
308+ return tspath .GetNormalizedAbsolutePath (fileName , api .session .GetCurrentDirectory ())
357309}
358310
359311func (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 ())
361313}
362314
363315func encodeJSON (v any , err error ) ([]byte , error ) {
0 commit comments