Single file output from LanguageService

Topics: General
Jun 4, 2014 at 1:56 AM
Hi! I'm attempting to add single file output support to an Eclipse TypeScript plug-in (https://github.com/palantir/eclipse-typescript) and I'm having some problems with the file ordering via the language services. Specifically, it seems like the only place to set the files in the proper order is in the ILanguageServiceHost implementation which I'm doing via code that looks like this:
    public getScriptFileNames(): string[] {
            var scriptFileNames = Object.getOwnPropertyNames(this.fileInfos);

            if (!isEmpty(this.compilationSettings.outFileOption)) {
                var resolutionResults = TypeScript.ReferenceResolver.resolve(scriptFileNames, this, true);

                scriptFileNames = resolutionResults.resolvedFiles.map(resolvedFile => resolvedFile.path);
            }

            return scriptFileNames;
        }
(from https://github.com/palantir/eclipse-typescript/blob/master/Bridge/src/languageServiceHost.ts)

This works but it severely degrades performance of the plug-in since getScriptFileNames() is called frequently. I considered caching the file ordering and only invalidating the cache when a file is touched but I'm worried that this still won't help much in cases like completion calls where the user is frequently editing a file while making language service calls. It seems like maybe file ordering is something the language service should be handling natively (perhaps by only getting the file ordering when compilation is requested) but I'm not entirely sure where file references fit into the design of the system so its also possible (likely?) I'm just doing something wrong.

Currently I'm using the getEmitOutput() API to get the single output file but perhaps it would be better to use the compiler directly for this use case?

I'd love some suggestions on how to implement this properly - thanks in advance for any assistance!
Developer
Jun 4, 2014 at 2:11 AM
Edited Jun 4, 2014 at 2:12 AM
Hey Derek,

You're definitely right that getScriptFileNames needs to return the files in the "right" order. While not necessary for getting errors and getting general language services (like completion, or parameter help), it is necessary so that code is correctly emitted in the right order.

That said, it's unclear why you'd need to recompute this once you have the initial ordering determined. From that point on you should just return the same array of file names in the same order.




Of course, when a file is touched, you do need to figure out what the new set of file names should be. However, you don't need to do that in getScriptFileNames. In VS, for example, we do that on another thread entirely. This thread operates at low pri, and only processes after all other requests have gone through. Once that new set of files names is computed, it can become the 'official' set of file names for all future calls to getScriptFileNames.

Please let me know if you have any further questions. I'm happy to help out with this!
  • Cyrus
Jun 4, 2014 at 3:24 AM
Thanks, that's good context. I'll try to think about how I can do something similar in the Eclipse plug-in.

I think there may be a related issue: after the language service calls getScriptFileNames() on the host, it doesn't seem like it has a supported/working mechanism for flushing that ordering later on (if the ordering changes). I tried to call cleanupSemanticCache() before compiling but it throws a null pointer exception if the compiler inside the language service hasn't been initialized prior to the call. I could try to make that call work but its hard to detect when the compiler would be null from the outside - it might be better to make that API safe to call at all times. For now I've resorted to re-creating the language service each time before compiling but that seems pretty heavy.
Developer
Jun 4, 2014 at 3:31 AM
Edited Jun 4, 2014 at 3:31 AM
Hey Derek,

You're right. We are missing that capability right now. And we should certainly consider adding it later.

Right now we do what you do. If the host detects a file ordering change, it totally dumps the language service and creates a new one. This is due to limitations we had early on (our original compiler simply couldn't handle this sort of change). Our current compiler would be totally ok with this, so we should support this in the future.

"but that seems pretty heavy." It is heavy. But ordering changes are rare... so it doesn't seem like a huge deal.

Feel free to file a suggestion bug on this topic and link it back to this discussion so we can track things.

Thanks!
  • Cyrus
Jun 4, 2014 at 3:42 AM
Ok cool, I'll file 2 issues: one for better tracking of referenced files and one for the somewhat dangerous cleanupSemanticCache() API. Thanks for all the info - this is really helpful!
Jun 4, 2014 at 3:52 AM