Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolving project references in tsconfig.json probably doesn't work #876

Open
dsherret opened this issue Oct 16, 2020 · 4 comments
Open
Labels

Comments

@dsherret
Copy link
Owner

See https://twitter.com/OliverJAsh/status/1317024049252438018

@dsherret dsherret added the bug label Oct 16, 2020
@rachel-church
Copy link

Running into the same issue. The underlying implementation will need to utilize the createIncrementalProgram and createIncrementalCompilerHost methods instead of createProgram and createCompilerHost to build the incremental ts programs.

See microsoft/TypeScript#31432 and TypeStrong/ts-loader#935

Without fully understanding TS incremental programs and the ts compiler API, I think a unit test along these lines would encompass the expected behavior:

it("should resolve dependent composite projects", () => {
    /*
    A project with one modules (units) and a corresponding test file:
    /
    ├── src/
    │   ├── units.ts
    │   └── tsconfig.json
    ├── test/
    │   ├── units.tests.ts
    │   └── tsconfig.json
    ├── package.json
    └── tsconfig.json
     */
    const fileSystem = new InMemoryFileSystemHost();

    fileSystem.writeFileSync("/package.json", `{ "name": "testing", "version": "0.0.1" }`);
    fileSystem.writeFileSync("/tsconfig.json", `{ "compilerOptions": { "composite": true }, "references": [{ "path": "./src" }, { "path": "./test" }] }`);
    fileSystem.mkdirSync("/src");
    fileSystem.writeFileSync(
      "/src/units.ts",
      "export class Test {}",
    );
    fileSystem.writeFileSync("/src/tsconfig.json", `{ "files": ["units.ts"], "compilerOptions": { "composite": true } }`);
    fileSystem.writeFileSync("/tsconfig.json", `{ "compilerOptions": { "composite": true }, "references": [{ "path": "./src" }, { "path": "./test" }] }`);
    fileSystem.mkdirSync("/test");
    fileSystem.writeFileSync(
      "/test/units.tests.ts",
      `import { Test } from 'units';`,
    );
    fileSystem.writeFileSync("/test/tsconfig.json", `{ "files": ["units.tests.ts"], "compilerOptions": { "composite": true }, "references": [{ "path": "../src" }] }`);

    const initialFiles = ['/test/units.tests.ts'];
    const resolvedFiles = ['/test/units.tests.ts', '/src/units.ts'];

    const project = new Project({
      tsConfigFilePath: "test/tsconfig.json",
      fileSystem,
      skipLoadingLibFiles: true,
      skipFileDependencyResolution: true,
    });
    expect(project.getSourceFiles().map(s => s.getFilePath())).to.deep.equal([...initialFiles]);
    const result = project.resolveSourceFileDependencies();
    expect(result.map(s => s.getFilePath())).to.deep.equal(resolvedFiles);
    assertHasSourceFiles(project, [...initialFiles, ...resolvedFiles]);
  });

@typeholes
Copy link

Another way to handle this could be to treat each referenced project as its own Project. A property with a map of path to Project would be added to the Project class. This is implemented at https://github.com/typeholes/ts-morph/tree/project-references

There is much to think about here:

  1. is this even a feasible approach
  2. how much plumbing is possible or desirable to transparently recurse into referenced projects
    a. for example, saving the root project can and probably should save the referenced projects
  3. how to handle circular references
  4. how do we handle projects which can be reached from different references.
    a. probably need a project manager to memoize opened projects by path

I can play around with this on a couple of projects using references, but I wanted to get your thoughts before I dug in too deep.

@typeholes
Copy link

Do we have an example project with project references that fails when we simply open the project with

   compilerOptions: { composite: false },

It may well be that no fix is needed.

@niieani
Copy link

niieani commented Oct 14, 2023

@typeholes This approach only works superficially, because you can have files in one project importing a file from another project, and thus these will be loaded multiple times, with different compiler instances. If you modify the file in one project, it won't get updated in the other. Uncertain how to solve this. 😞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants