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

buildSolutionReferences with instance transformers #1274

Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 23 additions & 23 deletions src/index.ts
Expand Up @@ -20,6 +20,7 @@ import {
WebpackLoaderCallback,
WebpackLoaderContext,
} from './interfaces';
import { installTransformers } from './transformers';
import {
appendSuffixesIfMatch,
arrify,
Expand All @@ -36,14 +37,15 @@ function loader(this: WebpackLoaderContext, contents: string) {
this.cacheable && this.cacheable();
const callback = this.async() as WebpackLoaderCallback;
const options = getLoaderOptions(this);
installTransformers(options);
const instanceOrError = getTypeScriptInstance(options, this);

if (instanceOrError.error !== undefined) {
callback(new Error(instanceOrError.error.message));
return;
}
const instance = instanceOrError.instance!;
buildSolutionReferences(instance, this);
buildSolutionReferences(instance, this); // Warning: references are built before hooks are set in initializeInstance
successLoader(this, contents, callback, instance);
}

Expand All @@ -59,14 +61,14 @@ function successLoader(

const filePath =
instance.loaderOptions.appendTsSuffixTo.length > 0 ||
instance.loaderOptions.appendTsxSuffixTo.length > 0
instance.loaderOptions.appendTsxSuffixTo.length > 0
? appendSuffixesIfMatch(
{
'.ts': instance.loaderOptions.appendTsSuffixTo,
'.tsx': instance.loaderOptions.appendTsxSuffixTo,
},
rawFilePath
)
{
'.ts': instance.loaderOptions.appendTsSuffixTo,
'.tsx': instance.loaderOptions.appendTsxSuffixTo,
},
rawFilePath
)
: rawFilePath;

const fileVersion = updateFileInCache(
Expand Down Expand Up @@ -107,10 +109,10 @@ function makeSourceMapAndFinish(
? ' The most common cause for this is having errors when building referenced projects.'
: !instance.loaderOptions.allowTsInNodeModules &&
filePath.indexOf('node_modules') !== -1
? ' By default, ts-loader will not compile .ts files in node_modules.\n' +
? ' By default, ts-loader will not compile .ts files in node_modules.\n' +
'You should not need to recompile .ts files there, but if you really want to, use the allowTsInNodeModules option.\n' +
'See: https://github.com/Microsoft/TypeScript/issues/12358'
: '';
: '';

callback(
new Error(
Expand Down Expand Up @@ -272,7 +274,6 @@ function makeLoaderOptions(instanceName: string, loaderOptions: LoaderOptions) {
compilerOptions: {},
appendTsSuffixTo: [],
appendTsxSuffixTo: [],
transformers: {},
happyPackMode: false,
colors: true,
onlyCompileBundledFiles: false,
Expand Down Expand Up @@ -426,7 +427,7 @@ function getEmit(
// the real dependency that webpack should watch is the JS output file.
addDependency(
getInputFileNameFromOutput(instance, path.resolve(resolvedFileName)) ||
originalFileName
originalFileName
);
}
}
Expand All @@ -439,16 +440,16 @@ function getEmit(
'@' +
(isReferencedFile(instance, defFilePath)
? instance
.solutionBuilderHost!.getInputFileStamp(defFilePath)
.toString()
.solutionBuilderHost!.getInputFileStamp(defFilePath)
.toString()
: (
instance.files.get(instance.filePathKeyMapper(defFilePath)) ||
instance.otherFiles.get(
instance.filePathKeyMapper(defFilePath)
) || {
version: '?',
}
).version)
instance.files.get(instance.filePathKeyMapper(defFilePath)) ||
instance.otherFiles.get(
instance.filePathKeyMapper(defFilePath)
) || {
version: '?',
}
).version)
);

return getOutputAndSourceMapFromOutputFiles(outputFiles);
Expand Down Expand Up @@ -602,7 +603,6 @@ function getTranspilationEmit(
diagnostics,
} = instance.compiler.transpileModule(contents, {
compilerOptions: { ...instance.compilerOptions, rootDir: undefined },
transformers: instance.transformers,
reportDiagnostics: true,
fileName,
});
Expand Down Expand Up @@ -658,5 +658,5 @@ export = loader;
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace loader {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface Options extends LoaderOptions {}
export interface Options extends LoaderOptions { }
}
92 changes: 29 additions & 63 deletions src/instances.ts
Expand Up @@ -108,8 +108,8 @@ function createFilePathKeyMapper(
const filePathKey = pathResolve(filePath);
cachedPath = fileNameLowerCaseRegExp.test(filePathKey)
? (filePathKey.replace(fileNameLowerCaseRegExp, ch =>
ch.toLowerCase()
) as FilePathKey)
ch.toLowerCase()
) as FilePathKey)
: filePathKey;
filePathMapperCache.set(filePath, cachedPath);
}
Expand Down Expand Up @@ -197,15 +197,15 @@ function successfulTypeScriptInstance(

const appendTsTsxSuffixesIfRequired =
loaderOptions.appendTsSuffixTo.length > 0 ||
loaderOptions.appendTsxSuffixTo.length > 0
loaderOptions.appendTsxSuffixTo.length > 0
? (filePath: string) =>
appendSuffixesIfMatch(
{
'.ts': loaderOptions.appendTsSuffixTo,
'.tsx': loaderOptions.appendTsxSuffixTo,
},
filePath
)
appendSuffixesIfMatch(
{
'.ts': loaderOptions.appendTsSuffixTo,
'.tsx': loaderOptions.appendTsxSuffixTo,
},
filePath
)
: (filePath: string) => filePath;

if (loaderOptions.transpileOnly) {
Expand All @@ -222,7 +222,6 @@ function successfulTypeScriptInstance(
version: 0,
program: undefined, // temporary, to be set later
dependencyGraph: new Map(),
transformers: {} as typescript.CustomTransformers, // this is only set temporarily, custom transformers are created further down
colors,
initialSetupPending: true,
reportTranspileErrors: true,
Expand All @@ -245,8 +244,8 @@ function successfulTypeScriptInstance(
try {
const filesToLoad = loaderOptions.onlyCompileBundledFiles
? configParseResult.fileNames.filter(fileName =>
dtsDtsxOrDtsDtsxMapRegex.test(fileName)
)
dtsDtsxOrDtsDtsxMapRegex.test(fileName)
)
: configParseResult.fileNames;
filesToLoad.forEach(filePath => {
normalizedFilePath = path.normalize(filePath);
Expand Down Expand Up @@ -279,7 +278,6 @@ function successfulTypeScriptInstance(
otherFiles,
languageService: null,
version: 0,
transformers: {} as typescript.CustomTransformers, // this is only set temporarily, custom transformers are created further down
dependencyGraph: new Map(),
colors,
initialSetupPending: true,
Expand Down Expand Up @@ -345,42 +343,16 @@ export function initializeInstance(

instance.initialSetupPending = false;

// same strategy as https://github.com/s-panferov/awesome-typescript-loader/pull/531/files
let { getCustomTransformers: customerTransformers } = instance.loaderOptions;
let getCustomTransformers = Function.prototype;

if (typeof customerTransformers === 'function') {
getCustomTransformers = customerTransformers;
} else if (typeof customerTransformers === 'string') {
try {
customerTransformers = require(customerTransformers);
} catch (err) {
throw new Error(
`Failed to load customTransformers from "${instance.loaderOptions.getCustomTransformers}": ${err.message}`
);
}

if (typeof customerTransformers !== 'function') {
throw new Error(
`Custom transformers in "${
instance.loaderOptions.getCustomTransformers
}" should export a function, got ${typeof getCustomTransformers}`
);
}
getCustomTransformers = customerTransformers;
}

if (instance.loaderOptions.transpileOnly) {
const program = (instance.program =
instance.program =
instance.configParseResult.projectReferences !== undefined
? instance.compiler.createProgram({
rootNames: instance.configParseResult.fileNames,
options: instance.configParseResult.options,
projectReferences: instance.configParseResult.projectReferences,
})
: instance.compiler.createProgram([], instance.compilerOptions));
rootNames: instance.configParseResult.fileNames,
options: instance.configParseResult.options,
projectReferences: instance.configParseResult.projectReferences,
})
: instance.compiler.createProgram([], instance.compilerOptions);

instance.transformers = getCustomTransformers(program);
// Setup watch run for solution building
if (instance.solutionBuilderHost) {
addAssetHooks(loader, instance);
Expand Down Expand Up @@ -412,7 +384,6 @@ export function initializeInstance(
instance.builderProgram = instance.watchOfFilesAndCompilerOptions.getProgram();
instance.program = instance.builderProgram.getProgram();

instance.transformers = getCustomTransformers(instance.program);
} else {
instance.servicesHost = makeServicesHost(
getScriptRegexp(instance),
Expand All @@ -425,10 +396,6 @@ export function initializeInstance(
instance.servicesHost,
instance.compiler.createDocumentRegistry()
);

instance.transformers = getCustomTransformers(
instance.languageService!.getProgram()
);
}

addAssetHooks(loader, instance);
Expand Down Expand Up @@ -504,6 +471,7 @@ export function buildSolutionReferences(
instance.configParseResult.projectReferences!.map(ref => ref.path),
{ verbose: true }
);

solutionBuilder.build();
instance.solutionBuilderHost.ensureAllReferenceTimestamps();
instancesBySolutionBuilderConfigs.set(
Expand Down Expand Up @@ -580,13 +548,13 @@ function getOutputPathWithoutChangingExt(
) {
return outputDir
? (instance.compiler as any).resolvePath(
outputDir,
(instance.compiler as any).getRelativePathFromDirectory(
rootDirOfOptions(instance, configFile),
inputFileName,
ignoreCase
)
outputDir,
(instance.compiler as any).getRelativePathFromDirectory(
rootDirOfOptions(instance, configFile),
inputFileName,
ignoreCase
)
)
: inputFileName;
}

Expand All @@ -612,8 +580,8 @@ function getOutputJSFileName(
? '.json'
: fileExtensionIs(inputFileName, '.tsx') &&
configFile.options.jsx === instance.compiler.JsxEmit.Preserve
? '.jsx'
: '.js'
? '.jsx'
: '.js'
);
return !isJsonFile ||
(instance.compiler as any).comparePaths(
Expand Down Expand Up @@ -743,8 +711,7 @@ export function getEmitFromWatchHost(instance: TSInstance, filePath?: string) {
const result = builderProgram.emitNextAffectedFile(
writeFile,
/*cancellationToken*/ undefined,
/*emitOnlyDtsFiles*/ false,
instance.transformers
/*emitOnlyDtsFiles*/ false
);
if (!result) {
break;
Expand Down Expand Up @@ -792,8 +759,7 @@ export function getEmitOutput(instance: TSInstance, filePath: string) {
sourceFile,
writeFile,
/*cancellationToken*/ undefined,
/*emitOnlyDtsFiles*/ false,
instance.transformers
/*emitOnlyDtsFiles*/ false
);
return outputFiles;
} else {
Expand Down
17 changes: 8 additions & 9 deletions src/interfaces.ts
Expand Up @@ -39,7 +39,7 @@ export interface CacheableHost extends HostMayBeCacheable {

export interface ModuleResolutionHostMayBeCacheable
extends typescript.ModuleResolutionHost,
HostMayBeCacheable {
HostMayBeCacheable {
readFile(filePath: string, encoding?: string): string | undefined;
trace: NonNullable<typescript.ModuleResolutionHost['trace']>;
directoryExists: NonNullable<
Expand All @@ -65,11 +65,11 @@ export interface ModuleResolutionHostMayBeCacheable

export interface ServiceHostWhichMayBeCacheable
extends typescript.LanguageServiceHost,
HostMayBeCacheable {}
HostMayBeCacheable { }

export interface WatchHost
extends typescript.WatchCompilerHostOfFilesAndCompilerOptions<typescript.EmitAndSemanticDiagnosticsBuilderProgram>,
HostMayBeCacheable {
HostMayBeCacheable {
invokeFileWatcher: WatchFactory['invokeFileWatcher'];
updateRootFileNames(): void;
outputFiles: Map<FilePathKey, typescript.OutputFile[]>;
Expand Down Expand Up @@ -104,7 +104,7 @@ export type FilePathKey = string & { __filePathKeyBrand: any };

export interface SolutionBuilderWithWatchHost
extends typescript.SolutionBuilderWithWatchHost<typescript.EmitAndSemanticDiagnosticsBuilderProgram>,
WatchFactory {
WatchFactory {
diagnostics: SolutionDiagnostics;
writtenFiles: typescript.OutputFile[];
configFileInfo: Map<FilePathKey, ConfigFileInfo>;
Expand Down Expand Up @@ -209,7 +209,6 @@ export interface TSInstance {
version: number;
dependencyGraph: DependencyGraph;
filesWithErrors?: TSFiles;
transformers: typescript.CustomTransformers;
colors: Chalk;

otherFiles: TSFiles;
Expand Down Expand Up @@ -282,10 +281,10 @@ export interface LoaderOptions {
appendTsxSuffixTo: (RegExp | string)[];
happyPackMode: boolean;
getCustomTransformers:
| string
| ((
program: typescript.Program
) => typescript.CustomTransformers | undefined);
| string
| ((
program: typescript.Program
) => typescript.CustomTransformers | undefined);
experimentalWatchApi: boolean;
allowTsInNodeModules: boolean;
experimentalFileCaching: boolean;
Expand Down