Skip to content

Conversation

rbuckton
Copy link
Contributor

@rbuckton rbuckton commented Aug 3, 2017

This adds early support to create multiple "inferred projects" isolated by a project root path. Currently this requires providing an additional --useInferredProjectPerProjectRoot argument to tsserver. We may choose to fold this functionality into the existing --useSingleInferredProject, but that could constitute a breaking change.

This also adds support to define the default configuration for inferred projects under a project root path, though the addition of an optional projectRootPath property on SetCompilerOptionsForInferredProjectsArgs.

Fixes #16961

@rbuckton rbuckton requested review from RyanCavanaugh and a user August 3, 2017 23:10
if (opts.eventHandler !== undefined) {
opts.canUseEvents = true;
}
return new TestSession({
Copy link

Choose a reason for hiding this comment

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

I think this would be easier to read as:

const defaultOptions: server.sessionOptions = { <<...>> };
return new TestSession({ ...defaultOptions, ...opts });

this.compilerOptionsForInferredProjects = convertCompilerOptions(projectCompilerOptions);
setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions, projectRootPath?: string): void {
// ignore this settings if we are not creating inferred projects per project root.
if (projectRootPath && !this.useInferredProjectPerProjectRoot) return;
Copy link

Choose a reason for hiding this comment

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

Can we just assert that this method isn't called with a root path unless those are enabled?

*/
readonly openFiles: ScriptInfo[] = [];

private compilerOptionsForInferredProjects: CompilerOptions;
Copy link

Choose a reason for hiding this comment

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

Will this property not be used if compilerOptionsForInferredProjectsPerProjectRoot is? Or do we sometimes use both?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We would sometimes use both. complierOptionsForInferredProjects would be used for any workspace root that does not have its own distinct workspace settings in your *.code-workspace file.

this.updateProjectGraphs(this.inferredProjects);

const updatedProjects: Project[] = [];
for (const project of this.inferredProjects) {
Copy link

Choose a reason for hiding this comment

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

This looks like a filter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a bit more complex than what I'd want to put in a filter. Also a filter would introduce an unnecessary closure.

// ignore this settings if we are not creating inferred projects per project root.
if (projectRootPath && !this.useInferredProjectPerProjectRoot) return;

const compilerOptionsForInferredProjects = convertCompilerOptions(projectCompilerOptions);
Copy link

Choose a reason for hiding this comment

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

This local variable isn't accurately named any more since it might not be assigned to this.compilerOptionsForInferredProjects.


const updatedProjects: Project[] = [];
for (const project of this.inferredProjects) {
if (project.projectRootPath === projectRootPath || (project.projectRootPath && !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath))) {
Copy link

Choose a reason for hiding this comment

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

Don't understand the second half of this condition -- if the project has a root path set but it's somehow not in the map, update it anyway even if its root path doesn't match?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is a bug in this logic, it should be more like:

projectRootPath ? 
  project.projectRootPath === projectRootPath : 
  !project.projectRootPath || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The goal is to use the new compiler options:

  • Inferred projects without a projectRootPath, if the new options do not apply to a workspace root
  • Inferred projects with a projectRootPath, if the new options do not apply to a workspace root and there is no more specific set of options for that project's root path
  • Inferred projects with a projectRootPath, if the new options apply to that project root path.

return this.createInferredProject(/*isSingleInferredProject*/ false, projectRootPath);
}

// we don't have an explicit root path, so we should try to find an inferred project that best matches the file.
Copy link

Choose a reason for hiding this comment

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

Define best -- it looks like this is finding the project containing the file that is the most deeply nested, so given if we're looking for a project for /a/b/c.ts and we have a choice of projects at /a, /a/b, and /a/b/x, we'll choose /a/b.

return undefined;
}

if (this.inferredProjects.length > 0 && this.inferredProjects[0].projectRootPath === undefined) {
Copy link

Choose a reason for hiding this comment

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

If the length isn't always 1, we shouldn't call the option useSingleInferredProject, or at least comment it very well.
Should also comment that the reason we only look at entry 0 is that we always add the "single" inferred project with an unshift, so it will always be at the front.

@rbuckton
Copy link
Contributor Author

rbuckton commented Aug 9, 2017

@mjbvz Does this meet the needs of VS Code?

@rbuckton rbuckton requested a review from mjbvz August 9, 2017 00:24
Copy link
Contributor

@mjbvz mjbvz left a comment

Choose a reason for hiding this comment

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

Change looks go to me. Let's just make sure the protocol.d.ts for the tsserver gets update as well

Thanks for looking into this

project.compileOnSaveEnabled = compilerOptionsForInferredProjects.compileOnSave;
if (projectRootPath ?
project.projectRootPath === projectRootPath :
!project.projectRootPath || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath)) {
Copy link

Choose a reason for hiding this comment

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

Could you include your comment in the code?

@rbuckton rbuckton merged commit 360dc91 into master Aug 11, 2017
@rbuckton rbuckton deleted the multiInferredProjects branch August 11, 2017 23:07
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
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.

3 participants