-
Notifications
You must be signed in to change notification settings - Fork 73
Add typeroots support #343
Add typeroots support #343
Conversation
Codecov Report
@@ 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
Continue to review full report at Codecov.
|
@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? |
@felixfbecker The content-preload for declaration files was missing typeRoots, tests pass with windows and unix-style paths now. |
src/project-manager.ts
Outdated
.filter(uri => this.isConfigDependency(uri2path(uri))) | ||
.mergeMap(uri => this.updater.ensure(uri)) | ||
.publishReplay() | ||
.refCount(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why publishReplay + refCount?
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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
src/project-manager.ts
Outdated
@@ -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; |
There was a problem hiding this comment.
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
src/project-manager.ts
Outdated
@@ -865,6 +894,19 @@ export class ProjectConfiguration { | |||
private ensuredBasicFiles = false; | |||
|
|||
/** | |||
* [isExpectedDeclarationFile description] | |||
* @param {string} fileName [description] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
template?
31c44a0
to
c259701
Compare
@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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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[]; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
src/project-manager.ts
Outdated
this.typeRoots.some(root => fileName.startsWith(root)); | ||
} else { | ||
return false; | ||
} |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return type
src/project-manager.ts
Outdated
@@ -337,6 +338,24 @@ export class ProjectManager implements Disposable { | |||
}); | |||
} | |||
|
|||
isConfigDependency(filePath: string): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add a docblock
src/project-manager.ts
Outdated
return false; | ||
} | ||
|
||
ensureConfigDependencies(): Observable<never> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add a docblock
There was a problem hiding this 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
@felixfbecker: your suggestions have been applied (with the exception of Set, see comment) |
Ping @felixfbecker, congrats on the big release today. Any chance we can work towards merging this PR and the plugin support PR? |
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())) |
There was a problem hiding this comment.
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
@felixfbecker I applied your suggestion, and verified that:
|
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: