Skip to content

Commit

Permalink
Support for symlinks in project references (#1136)
Browse files Browse the repository at this point in the history
* Test for symlinks

* Basleine assets

* Baselines for More symlinks

* Handle the path casing in preparation to handling symlinks

* Handle symlinks to paths that could be in memory

* Handle changes to referenced files

* Update baselines correctly

* Add use correct FileWatcherEventKind

* Support typescript@3.6.3 or more

* handle compiler options to extend correctly
This is what resulted in using incorrect newLine in tests in SolutionBuilderHost

* Use casesensitive host to run tests

* More test fixes

* Use LF to build already built program

* Update version to 8.0.0 in package.json

* Update CHANGELOG.md

Co-authored-by: John Reilly <johnny_reilly@hotmail.com>
  • Loading branch information
sheetalkamat and johnnyreilly committed Jul 8, 2020
1 parent 8b7c8ed commit 4ad247a
Show file tree
Hide file tree
Showing 517 changed files with 9,487 additions and 1,855 deletions.
7 changes: 5 additions & 2 deletions .gitignore
@@ -1,6 +1,7 @@
/*.js
!index.js
/src/*.js
/src/.vscode
/*.d.ts
/*.log
*.js.map
Expand All @@ -10,11 +11,13 @@ npm-debug.log
/test/execution-tests/**/typings
!/test/**/expectedOutput-*/**
/**/node_modules
/**/dist
/dist
/test/execution-tests/**/dist
/**/.happypack
/**/.cache-loader
!build.js
/**/debug.log
.pnp
.pnp.js
!.eslintrc.js
!.eslintrc.js
.vs/**
12 changes: 0 additions & 12 deletions .travis.yml
Expand Up @@ -18,16 +18,4 @@ env:
- TYPESCRIPT=typescript@3.8.2
- TYPESCRIPT=typescript@3.7.4
- TYPESCRIPT=typescript@3.6.3
- TYPESCRIPT=typescript@3.5.1
- TYPESCRIPT=typescript@3.4.4
- TYPESCRIPT=typescript@3.3.3
- TYPESCRIPT=typescript@3.2.1
- TYPESCRIPT=typescript@3.1.1
- TYPESCRIPT=typescript@3.0.1
- TYPESCRIPT=typescript@2.9.2
- TYPESCRIPT=typescript@2.8.1
- TYPESCRIPT=typescript@2.7.1
- TYPESCRIPT=typescript@2.6.1
- TYPESCRIPT=typescript@2.5.2
- TYPESCRIPT=typescript@2.4.1

4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog

## v8.0.0
* [Support for symlinks in project references](https://github.com/TypeStrong/ts-loader/pull/1136) - thanks @sheetalkamat!
* `ts-loader` now supports TypeScript 3.6 and greater **BREAKING CHANGE**

## v7.0.5
* [Add a delay before starting the comparison tests to avoid failures under WSL](https://github.com/TypeStrong/ts-loader/pull/1109) - thanks @appzuka
* [Apply other loaders when updating files in watch mode](https://github.com/TypeStrong/ts-loader/pull/1115) - thanks @iorate
Expand Down
13 changes: 1 addition & 12 deletions appveyor.yml
Expand Up @@ -8,18 +8,7 @@ environment:
- TYPESCRIPT: typescript@3.8.2
- TYPESCRIPT: typescript@3.7.4
- TYPESCRIPT: typescript@3.6.3
- TYPESCRIPT: typescript@3.5.1
- TYPESCRIPT: typescript@3.4.4
- TYPESCRIPT: typescript@3.3.3
- TYPESCRIPT: typescript@3.2.1
- TYPESCRIPT: typescript@3.1.1
- TYPESCRIPT: typescript@3.0.1
- TYPESCRIPT: typescript@2.9.2
- TYPESCRIPT: typescript@2.8.1
- TYPESCRIPT: typescript@2.7.1
- TYPESCRIPT: typescript@2.6.1
- TYPESCRIPT: typescript@2.5.2
- TYPESCRIPT: typescript@2.4.1

install:
- ps: Install-Product node $env:nodejs_version
- yarn install
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "ts-loader",
"version": "7.0.5",
"version": "8.0.0",
"description": "TypeScript loader for webpack",
"main": "index.js",
"types": "dist",
Expand Down
93 changes: 46 additions & 47 deletions src/after-compile.ts
Expand Up @@ -3,23 +3,21 @@ import * as ts from 'typescript';
import * as webpack from 'webpack';

import * as constants from './constants';
import { getEmitFromWatchHost, getEmitOutput } from './instances';
import {
getEmitFromWatchHost,
getEmitOutput,
isReferencedFile,
} from './instances';
import {
TSFile,
FilePathKey,
TSFiles,
TSInstance,
WebpackError,
WebpackModule,
TSFile,
} from './interfaces';
import {
collectAllDependants,
ensureProgram,
formatErrors,
isUsingProjectReferences,
isReferencedFile,
populateReverseDependencyGraph,
} from './utils';

export function makeAfterCompile(
Expand Down Expand Up @@ -55,15 +53,15 @@ export function makeAfterCompile(
);
getCompilerOptionDiagnostics = false;

const modules = determineModules(compilation);
const modules = determineModules(compilation, instance);

const filesToCheckForErrors = determineFilesToCheckForErrors(
checkAllFilesForErrors,
instance
);
checkAllFilesForErrors = false;

const filesWithErrors: TSFiles = new Map<string, TSFile>();
const filesWithErrors: TSFiles = new Map();
provideErrorsToWebpack(
filesToCheckForErrors,
filesWithErrors,
Expand Down Expand Up @@ -119,11 +117,14 @@ function provideCompilerOptionDiagnosticErrorsToWebpack(
* this is used for quick-lookup when trying to find modules
* based on filepath
*/
function determineModules(compilation: webpack.compilation.Compilation) {
return compilation.modules.reduce<Map<string, WebpackModule[]>>(
function determineModules(
compilation: webpack.compilation.Compilation,
{ filePathKeyMapper }: TSInstance
) {
return compilation.modules.reduce<Map<FilePathKey, WebpackModule[]>>(
(modules, module) => {
if (module.resource) {
const modulePath = path.normalize(module.resource);
const modulePath = filePathKeyMapper(module.resource);
const existingModules = modules.get(modulePath);
if (existingModules !== undefined) {
if (existingModules.indexOf(module) === -1) {
Expand All @@ -136,7 +137,7 @@ function determineModules(compilation: webpack.compilation.Compilation) {

return modules;
},
new Map<string, WebpackModule[]>()
new Map()
);
}

Expand All @@ -146,43 +147,54 @@ function determineFilesToCheckForErrors(
) {
const { files, modifiedFiles, filesWithErrors, otherFiles } = instance;
// calculate array of files to check
const filesToCheckForErrors: TSFiles = new Map<string, TSFile>();
const filesToCheckForErrors: TSFiles = new Map();
if (checkAllFilesForErrors) {
// check all files on initial run
for (const [filePath, file] of files) {
filesToCheckForErrors.set(filePath, file);
addFileToCheckForErrors(filePath, file);
}
for (const [filePath, file] of otherFiles) {
filesToCheckForErrors.set(filePath, file);
addFileToCheckForErrors(filePath, file);
}
} else if (modifiedFiles !== null && modifiedFiles !== undefined) {
} else if (
modifiedFiles !== null &&
modifiedFiles !== undefined &&
modifiedFiles.size
) {
const reverseDependencyGraph = populateReverseDependencyGraph(instance);
// check all modified files, and all dependants
for (const modifiedFileName of modifiedFiles.keys()) {
collectAllDependants(
instance.reverseDependencyGraph,
for (const fileName of collectAllDependants(
reverseDependencyGraph,
modifiedFileName
).forEach(fileName => {
).keys()) {
const fileToCheckForErrors =
files.get(fileName) || otherFiles.get(fileName);
filesToCheckForErrors.set(fileName, fileToCheckForErrors!);
});
addFileToCheckForErrors(fileName, fileToCheckForErrors!);
}
}
}

// re-check files with errors from previous build
if (filesWithErrors !== undefined) {
for (const [fileWithErrorName, fileWithErrors] of filesWithErrors) {
filesToCheckForErrors.set(fileWithErrorName, fileWithErrors);
addFileToCheckForErrors(fileWithErrorName, fileWithErrors);
}
}
return filesToCheckForErrors;

function addFileToCheckForErrors(filePath: FilePathKey, file: TSFile) {
if (!isReferencedFile(instance, filePath)) {
filesToCheckForErrors.set(filePath, file);
}
}
}

function provideErrorsToWebpack(
filesToCheckForErrors: TSFiles,
filesWithErrors: TSFiles,
compilation: webpack.compilation.Compilation,
modules: Map<string, WebpackModule[]>,
modules: Map<FilePathKey, WebpackModule[]>,
instance: TSInstance
) {
const {
Expand All @@ -200,20 +212,12 @@ function provideErrorsToWebpack(

// I’m pretty sure this will never be undefined here
const program = ensureProgram(instance);
for (const filePath of filesToCheckForErrors.keys()) {
if (filePath.match(filePathRegex) === null) {
continue;
}

const sourceFile = program && program.getSourceFile(filePath);
// If the source file is undefined, that probably means it’s actually part of an unbuilt project reference,
// which will have already produced a more useful error than the one we would get by proceeding here.
// If it’s undefined and we’re not using project references at all, I guess carry on so the user will
// get a useful error about which file was unexpectedly missing.
if (isUsingProjectReferences(instance) && sourceFile === undefined) {
for (const [filePath, { fileName }] of filesToCheckForErrors.entries()) {
if (fileName.match(filePathRegex) === null) {
continue;
}

const sourceFile = program && program.getSourceFile(fileName);
const errors: ts.Diagnostic[] = [];
if (program && sourceFile) {
errors.push(
Expand All @@ -231,7 +235,7 @@ function provideErrorsToWebpack(
}

// if we have access to a webpack module, use that
const associatedModules = modules.get(filePath);
const associatedModules = modules.get(instance.filePathKeyMapper(fileName));
if (associatedModules !== undefined) {
associatedModules.forEach(module => {
// remove any existing errors
Expand All @@ -257,7 +261,7 @@ function provideErrorsToWebpack(
loaderOptions,
instance.colors,
compiler,
{ file: filePath },
{ file: fileName },
compilation.compiler.context
);

Expand All @@ -268,7 +272,7 @@ function provideErrorsToWebpack(

function provideSolutionErrorsToWebpack(
compilation: webpack.compilation.Compilation,
modules: Map<string, WebpackModule[]>,
modules: Map<FilePathKey, WebpackModule[]>,
instance: TSInstance
) {
if (
Expand Down Expand Up @@ -315,7 +319,7 @@ function provideSolutionErrorsToWebpack(
loaderOptions,
instance.colors,
compiler,
{ file: filePath },
{ file: path.resolve(perFileDiagnostics[0].file!.fileName) },
compilation.compiler.context
);

Expand Down Expand Up @@ -344,17 +348,12 @@ function provideDeclarationFilesToWebpack(
instance: TSInstance,
compilation: webpack.compilation.Compilation
) {
for (const filePath of filesToCheckForErrors.keys()) {
if (filePath.match(constants.tsTsxRegex) === null) {
for (const { fileName } of filesToCheckForErrors.values()) {
if (fileName.match(constants.tsTsxRegex) === null) {
continue;
}

if (!isReferencedFile(instance, filePath)) {
addDeclarationFilesAsAsset(
getEmitOutput(instance, filePath),
compilation
);
}
addDeclarationFilesAsAsset(getEmitOutput(instance, fileName), compilation);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/compilerSetup.ts
Expand Up @@ -27,7 +27,7 @@ export function getCompiler(loaderOptions: LoaderOptions, log: logger.Logger) {
if (loaderOptions.compiler === 'typescript') {
if (
compiler!.version !== undefined &&
semver.gte(compiler!.version, '2.4.1')
semver.gte(compiler!.version, '3.6.3')
) {
// don't log yet in this case, if a tsconfig.json exists we want to combine the message
compilerCompatible = true;
Expand Down

0 comments on commit 4ad247a

Please sign in to comment.