Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Add typeroots support #343

Merged
merged 12 commits into from
Sep 27, 2017
Merged

Conversation

tomv564
Copy link
Contributor

@tomv564 tomv564 commented Aug 29, 2017

On codebases that rely on type roots for distributing extra declaration files, this code should prevent diagnostics about missing types and improve completions/hovers/etc.

To do:

  • Fix lint error
  • Add test(s)

@codecov
Copy link

codecov bot commented Aug 31, 2017

Codecov Report

Merging #343 into master will increase coverage by 0.32%.
The diff coverage is 90.47%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #343      +/-   ##
==========================================
+ Coverage    60.2%   60.52%   +0.32%     
==========================================
  Files          14       14              
  Lines        2151     2171      +20     
  Branches      351      355       +4     
==========================================
+ Hits         1295     1314      +19     
- Misses        706      707       +1     
  Partials      150      150
Impacted Files Coverage Δ
src/project-manager.ts 83.97% <90.47%> (+0.75%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6087974...521eba0. Read the comment docs.

@tomv564
Copy link
Contributor Author

tomv564 commented Aug 31, 2017

@felixfbecker, I am a bit stuck on this test - the types.d.ts file is added to the in-memory file system but its content is not loaded. What am I missing?

@tomv564
Copy link
Contributor Author

tomv564 commented Sep 8, 2017

@felixfbecker The content-preload for declaration files was missing typeRoots, tests pass with windows and unix-style paths now.
I'm not happy with having introduced yet another ensure function, but couldn't find any other place that loads content based on tsconfig settings?

.filter(uri => this.isConfigDependency(uri2path(uri)))
.mergeMap(uri => this.updater.ensure(uri))
.publishReplay()
.refCount();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why publishReplay + refCount?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at ensureModuleStructure, which I also understood would be invoked many times but should always return the same (cached) sequence. But I'd love to know how this use case differs (and remove it if unnecessary).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't actually save the (i.e. cache) the Observable, so it doesn't has a use here. If you want to always return the same Observable you need to save it in a property

@@ -838,6 +862,11 @@ export class ProjectConfiguration {
this.expectedFilePaths = new Set(configParseResult.fileNames);

const options = configParseResult.options;
const pathResolver = /[a-z]:\//i.test(base) ? path.win32 : path.posix;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the regexp should only match at the beginning of the string

@@ -865,6 +894,19 @@ export class ProjectConfiguration {
private ensuredBasicFiles = false;

/**
* [isExpectedDeclarationFile description]
* @param {string} fileName [description]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

template?

@tomv564 tomv564 force-pushed the add-typeroots-support branch from 31c44a0 to c259701 Compare September 9, 2017 11:20
@tomv564
Copy link
Contributor Author

tomv564 commented Sep 15, 2017

@felixfbecker: would you have time to look at this PR again soon?

@@ -735,6 +754,11 @@ export class ProjectConfiguration {
private expectedFilePaths = new Set<string>();

/**
* List of resolved extra root directories to allow global type declaration files to be loaded from.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this restricted to global typings?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From https://www.typescriptlang.org/docs/handbook/tsconfig-json.html:

By default all visible “@types” packages are included in your compilation.
If typesRoots is specified, only packages under typeRoots will be included.
Keep in mind that automatic inclusion is only important if you’re using files with global declarations (as opposed to files declared as modules)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They clarify in that page as well:

If you use an import "foo" statement, for instance, TypeScript may still look through node_modules & node_modules/@types folders to find the foo package.

@@ -735,6 +754,11 @@ export class ProjectConfiguration {
private expectedFilePaths = new Set<string>();

/**
* List of resolved extra root directories to allow global type declaration files to be loaded from.
*/
private typeRoots: string[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the order important? if not, use a Set

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this.typeRoots.some(root => fileName.startsWith(root)); is a good fit for Set?

this.typeRoots.some(root => fileName.startsWith(root));
} else {
return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function just needs to be a single boolean return

* Determines if a fileName is a declaration file within expected files or type roots
* @param fileName
*/
public isExpectedDeclarationFile(fileName: string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return type

@@ -337,6 +338,24 @@ export class ProjectManager implements Disposable {
});
}

isConfigDependency(filePath: string): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a docblock

return false;
}

ensureConfigDependencies(): Observable<never> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a docblock

Copy link
Contributor

@felixfbecker felixfbecker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks almost good to me

@tomv564
Copy link
Contributor Author

tomv564 commented Sep 16, 2017

@felixfbecker: your suggestions have been applied (with the exception of Set, see comment)

@tomv564
Copy link
Contributor Author

tomv564 commented Sep 20, 2017

Ping @felixfbecker, congrats on the big release today. Any chance we can work towards merging this PR and the plugin support PR?

@felixfbecker
Copy link
Contributor

Thank you, as you can imagine I was very busy in the last days :) Taking a look

@@ -321,6 +321,7 @@ export class ProjectManager implements Disposable {
span.addTags({ uri, maxDepth });
ignore.add(uri);
return this.ensureModuleStructure(span)
.concat(Observable.defer(() => this.ensureConfigDependencies()))
Copy link
Contributor

@felixfbecker felixfbecker Sep 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this have a performance impact? I think it probably has, as you are iterating in ensureConfigDependencies() over every single file in the workspace, and ensureReferencedFiles() is called recursively for every referenced file, so you are repeating that iteration every time. I think ensureConfigDependencies() needs to memoize its return value in the same way ensureAllFiles() does, or you could just add that logic to ensureModuleStructure() (which would already is memoized, has memoize cache invalidation logic and already iterates over all files so you'd only have to iterate once). Optionally, you could try this then on a very big TS project and see if it degrades perf in any way

@tomv564
Copy link
Contributor Author

tomv564 commented Sep 25, 2017

@felixfbecker I applied your suggestion, and verified that:

  • The logic still works with a typeRoots dependent project
  • Hovers on the Microsoft/Typescript source are still appearing quickly

@felixfbecker felixfbecker merged commit 25e0108 into sourcegraph:master Sep 27, 2017
@tomv564 tomv564 deleted the add-typeroots-support branch September 27, 2017 05:48
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants