Skip to content

Commit 74b92d3

Browse files
authored
fix(compiler): don't resolve files from build folder for projectReferences (#1614)
1 parent 8a29aaa commit 74b92d3

File tree

10 files changed

+74
-369
lines changed

10 files changed

+74
-369
lines changed

e2e/__external-repos__/simple-project-references/jest.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/** @type {import('@jest/types').Config.InitialOptions} */
2+
/** @typedef {import('ts-jest')} */
3+
14
module.exports = {
25
preset: 'ts-jest',
36
testEnvironment: 'node',
@@ -7,6 +10,7 @@ module.exports = {
710
globals: {
811
'ts-jest': {
912
isolatedModules: true,
13+
tsConfig: 'tsconfig-tests.json'
1014
},
1115
},
1216
}

e2e/__external-repos__/simple-project-references/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
{
22
"private": true,
33
"scripts": {
4-
"build": "yarn tsc -b -f tsconfig.json",
5-
"test": "yarn build && jest"
4+
"test": "jest"
65
},
76
"devDependencies": {
87
"@types/jest": "^25.2.1",

e2e/__external-repos__/yarn-workspace-composite/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"packages/*"
77
],
88
"scripts": {
9-
"test": "yarn tsc -b packages/my-app/tsconfig.json && jest --no-cache"
9+
"test": "jest --no-cache"
1010
},
1111
"devDependencies": {
1212
"@types/jest": "^25.2.1",

src/compiler/compiler-utils.ts

Lines changed: 2 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import { Logger } from 'bs-logger'
22
import { writeFileSync } from 'fs'
33
import micromatch = require('micromatch')
4-
import { dirname, join, normalize, relative, resolve } from 'path'
4+
import { join, normalize } from 'path'
55
import * as _ts from 'typescript'
66

7-
import { ConfigSet } from '../config/config-set'
8-
import { EXTENSION_REGEX, JSON_REGEX, TS_TSX_REGEX } from '../constants'
9-
import { MemoryCache, SourceOutput, TSFiles } from '../types'
7+
import { MemoryCache } from '../types'
108
import { sha1 } from '../util/sha1'
119

1210
/**
@@ -60,151 +58,3 @@ export function isTestFile(testMatchPatterns: (string | RegExp)[], fileName: str
6058
typeof pattern === 'string' ? micromatch.isMatch(fileName, pattern) : pattern.test(fileName),
6159
)
6260
}
63-
64-
/* istanbul ignore next (we leave this for e2e) */
65-
function isUsingProjectReferences(
66-
program: _ts.Program,
67-
projectReferences: readonly _ts.ProjectReference[] | undefined,
68-
) {
69-
if (projectReferences && !!program.getProjectReferences) {
70-
return Boolean(program && program.getProjectReferences())
71-
}
72-
73-
return false
74-
}
75-
76-
/* istanbul ignore next (we leave this for e2e) */
77-
function getResolvedProjectReferences(
78-
program: _ts.Program,
79-
): readonly (_ts.ResolvedProjectReference | undefined)[] | undefined {
80-
const getProjectReferences = program.getResolvedProjectReferences ?? program.getProjectReferences
81-
if (getProjectReferences) {
82-
return getProjectReferences()
83-
}
84-
85-
return
86-
}
87-
88-
/* istanbul ignore next (we leave this for e2e) */
89-
function getProjectReferenceForFile(
90-
filePath: string,
91-
program: _ts.Program,
92-
projectReferences: readonly _ts.ProjectReference[] | undefined,
93-
) {
94-
if (isUsingProjectReferences(program, projectReferences)) {
95-
return (
96-
program &&
97-
getResolvedProjectReferences(program)!.find(
98-
ref => (ref && ref.commandLine.fileNames.some(file => normalize(file) === filePath)) || false,
99-
)
100-
)
101-
}
102-
103-
return
104-
}
105-
106-
/**
107-
* @internal
108-
*/
109-
/* istanbul ignore next (we leave this for e2e) */
110-
export function getAndCacheProjectReference(
111-
filePath: string,
112-
program: _ts.Program,
113-
files: TSFiles,
114-
projectReferences: readonly _ts.ProjectReference[] | undefined,
115-
) {
116-
const file = files.get(filePath)
117-
if (file?.projectReference) {
118-
return file.projectReference.project
119-
}
120-
121-
const projectReference = getProjectReferenceForFile(filePath, program, projectReferences)
122-
if (file !== undefined) {
123-
file.projectReference = { project: projectReference }
124-
}
125-
126-
return projectReference
127-
}
128-
129-
// Adapted from https://github.com/Microsoft/TypeScript/blob/45101491c0b077c509b25830ef0ee5f85b293754/src/compiler/tsbuild.ts#L305
130-
/* istanbul ignore next (we leave this for e2e) */
131-
function getOutputJavaScriptFileName(inputFileName: string, projectReference: _ts.ResolvedProjectReference) {
132-
const { options } = projectReference.commandLine
133-
const projectDirectory = options.rootDir || dirname(projectReference.sourceFile.fileName)
134-
const relativePath = relative(projectDirectory, inputFileName)
135-
const outputPath = resolve(options.outDir || projectDirectory, relativePath)
136-
const newExtension = JSON_REGEX.test(inputFileName)
137-
? '.json'
138-
: TS_TSX_REGEX.test(inputFileName) && options.jsx === _ts.JsxEmit.Preserve
139-
? '.jsx'
140-
: '.js'
141-
142-
return outputPath.replace(EXTENSION_REGEX, newExtension)
143-
}
144-
145-
/**
146-
* Gets the output JS file path for an input file governed by a composite project.
147-
* Pulls from the cache if it exists; computes and caches the result otherwise.
148-
*/
149-
/* istanbul ignore next (we leave this for e2e) */
150-
function getAndCacheOutputJSFileName(
151-
inputFileName: string,
152-
projectReference: _ts.ResolvedProjectReference,
153-
files: TSFiles,
154-
) {
155-
const file = files.get(inputFileName)
156-
if (file?.projectReference?.outputFileName) {
157-
return file.projectReference.outputFileName
158-
}
159-
160-
const outputFileName = getOutputJavaScriptFileName(inputFileName, projectReference)
161-
if (file !== undefined) {
162-
file.projectReference = file.projectReference ?? {
163-
project: projectReference,
164-
}
165-
file.projectReference.outputFileName = outputFileName
166-
}
167-
168-
return outputFileName
169-
}
170-
171-
/**
172-
* @internal
173-
*/
174-
/* istanbul ignore next (we leave this for e2e) */
175-
export function getCompileResultFromReferencedProject(
176-
fileName: string,
177-
configs: ConfigSet,
178-
files: TSFiles,
179-
referencedProject: _ts.ResolvedProjectReference,
180-
): SourceOutput {
181-
const [relativeProjectConfigPath, relativeFilePath] = [
182-
configs.resolvePath(referencedProject.sourceFile.fileName),
183-
configs.resolvePath(fileName),
184-
]
185-
if (referencedProject.commandLine.options.outFile !== undefined) {
186-
throw new Error(
187-
`The referenced project at ${relativeProjectConfigPath} is using ` +
188-
"the outFile' option, which is not supported with ts-jest.",
189-
)
190-
}
191-
192-
const jsFileName = getAndCacheOutputJSFileName(fileName, referencedProject, files)
193-
const relativeJSFileName = configs.resolvePath(jsFileName)
194-
if (!configs.compilerModule.sys.fileExists(jsFileName)) {
195-
throw new Error(
196-
'Could not find output JavaScript file for input ' +
197-
`${relativeFilePath} (looked at ${relativeJSFileName}).\n` +
198-
'The input file is part of a project reference located at ' +
199-
`${relativeProjectConfigPath}, so ts-jest is looking for the ` +
200-
'project’s pre-built output on disk. Try running `tsc --build` ' +
201-
'to build project references.',
202-
)
203-
}
204-
205-
const mapFileName = `${jsFileName}.map`
206-
const outputText = configs.compilerModule.sys.readFile(jsFileName)
207-
const sourceMapText = configs.compilerModule.sys.readFile(mapFileName)
208-
209-
return [outputText!, sourceMapText!]
210-
}

src/compiler/language-service.spec.ts

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -17,57 +17,6 @@ describe('Language service', () => {
1717
logTarget.clear()
1818
})
1919

20-
it('should get compile result from referenced project when there is a built reference project', () => {
21-
const tmp = tempDir('compiler')
22-
const compiler = makeCompiler({
23-
jestConfig: { cache: true, cacheDirectory: tmp },
24-
tsJestConfig: { tsConfig: false },
25-
})
26-
const source = 'console.log("hello")'
27-
const fileName = 'test-reference-project.ts'
28-
const getAndCacheProjectReferenceSpy = jest
29-
.spyOn(compilerUtils, 'getAndCacheProjectReference')
30-
.mockReturnValueOnce({} as any)
31-
jest
32-
.spyOn(compilerUtils, 'getCompileResultFromReferencedProject')
33-
.mockImplementationOnce(() => [
34-
source,
35-
'{"version":3,"file":"test-reference-project.js","sourceRoot":"","sources":["test-reference-project.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA","sourcesContent":["console.log(\\"hello\\")"]}',
36-
])
37-
writeFileSync(fileName, source, 'utf8')
38-
39-
compiler.compile(source, fileName)
40-
41-
expect(getAndCacheProjectReferenceSpy).toHaveBeenCalled()
42-
expect(compilerUtils.getCompileResultFromReferencedProject).toHaveBeenCalled()
43-
44-
jest.restoreAllMocks()
45-
removeSync(fileName)
46-
})
47-
48-
it('should get compile result from language service when there is no referenced project', () => {
49-
const tmp = tempDir('compiler')
50-
const compiler = makeCompiler({
51-
jestConfig: { cache: true, cacheDirectory: tmp },
52-
tsJestConfig: { tsConfig: false },
53-
})
54-
const source = 'console.log("hello")'
55-
const fileName = 'test-no-reference-project.ts'
56-
const getAndCacheProjectReferenceSpy = jest
57-
.spyOn(compilerUtils, 'getAndCacheProjectReference')
58-
.mockReturnValueOnce(undefined)
59-
jest.spyOn(compilerUtils, 'getCompileResultFromReferencedProject')
60-
writeFileSync(fileName, source, 'utf8')
61-
62-
compiler.compile(source, fileName)
63-
64-
expect(getAndCacheProjectReferenceSpy).toHaveBeenCalled()
65-
expect(compilerUtils.getCompileResultFromReferencedProject).not.toHaveBeenCalled()
66-
67-
jest.restoreAllMocks()
68-
removeSync(fileName)
69-
})
70-
7120
it('should cache resolved modules for test file with testMatchPatterns from jest config when match', () => {
7221
const spy = jest.spyOn(compilerUtils, 'cacheResolvedModules').mockImplementationOnce(() => {})
7322
const tmp = tempDir('compiler')

0 commit comments

Comments
 (0)