-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Declaration maps and transparent goto definition using them #22658
Changes from 4 commits
ab7cb27
91cc19c
c291828
2b26a27
ec44da5
ffb7f85
589ac28
5584a2d
238ba98
ff158cf
b9f6149
53f72de
29c732e
6070108
0a63553
d8480b2
ca88d5e
2b231d7
fed6132
509e4f3
0c44ba1
c8620e3
5687e10
e64e73d
47e701a
6a467ba
f2c8d3f
bd9cccf
c7a5296
f6e81f2
d0a5e28
943dc12
265cc1a
e34a6bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,15 +49,17 @@ namespace ts { | |
const jsFilePath = options.outFile || options.out; | ||
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); | ||
const declarationFilePath = (forceDtsPaths || options.declaration) ? removeFileExtension(jsFilePath) + Extension.Dts : undefined; | ||
return { jsFilePath, sourceMapFilePath, declarationFilePath }; | ||
const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; | ||
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath }; | ||
} | ||
else { | ||
const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options)); | ||
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); | ||
// For legacy reasons (ie, we have baselines capturing the behavior), js files don't report a .d.ts output path - this would only matter if `declaration` and `allowJs` were both on, which is currently an error | ||
const isJs = isSourceFileJavaScript(sourceFile); | ||
const declarationFilePath = ((forceDtsPaths || options.declaration) && !isJs) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; | ||
return { jsFilePath, sourceMapFilePath, declarationFilePath }; | ||
const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; | ||
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath }; | ||
} | ||
} | ||
|
||
|
@@ -83,12 +85,19 @@ namespace ts { | |
return Extension.Js; | ||
} | ||
|
||
const enum SourceMapEmitKind { | ||
None, | ||
File, | ||
Inline, | ||
DeclarationFile | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to consider allowing inline declaration maps? The current behavior seems inconsistent because
Barring feedback from other reviewers, I'd lean towards the former than the latter. |
||
} | ||
|
||
/*@internal*/ | ||
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature | ||
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory<SourceFile>[]): EmitResult { | ||
const compilerOptions = host.getCompilerOptions(); | ||
const moduleKind = getEmitModuleKind(compilerOptions); | ||
const sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; | ||
const sourceMapDataList: SourceMapData[] = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined; | ||
const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined; | ||
const emitterDiagnostics = createDiagnosticCollection(); | ||
const newLine = host.getNewLine(); | ||
|
@@ -113,9 +122,9 @@ namespace ts { | |
sourceMaps: sourceMapDataList | ||
}; | ||
|
||
function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { | ||
function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { | ||
emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath); | ||
emitDeclarationFileOrBundle(sourceFileOrBundle, declarationFilePath); | ||
emitDeclarationFileOrBundle(sourceFileOrBundle, declarationFilePath, declarationMapPath); | ||
|
||
if (!emitSkipped && emittedFilesList) { | ||
if (!emitOnlyDtsFiles) { | ||
|
@@ -162,13 +171,14 @@ namespace ts { | |
onSetSourceFile: setSourceFile, | ||
}); | ||
|
||
printSourceFileOrBundle(jsFilePath, sourceMapFilePath, isSourceFile(sourceFileOrBundle) ? transform.transformed[0] : createBundle(transform.transformed), printer); | ||
const sourcemapKind = compilerOptions.inlineSourceMap ? SourceMapEmitKind.Inline : compilerOptions.sourceMap ? SourceMapEmitKind.File : SourceMapEmitKind.None; | ||
printSourceFileOrBundle(jsFilePath, sourceMapFilePath, isSourceFile(sourceFileOrBundle) ? transform.transformed[0] : createBundle(transform.transformed), printer, sourcemapKind); | ||
|
||
// Clean up emit nodes on parse tree | ||
transform.dispose(); | ||
} | ||
|
||
function emitDeclarationFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, declarationFilePath: string | undefined) { | ||
function emitDeclarationFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, declarationFilePath: string | undefined, declarationMapPath: string | undefined) { | ||
if (!(declarationFilePath && !isInJavaScriptFile(sourceFileOrBundle))) { | ||
return; | ||
} | ||
|
@@ -186,25 +196,34 @@ namespace ts { | |
// resolver hooks | ||
hasGlobalName: resolver.hasGlobalName, | ||
|
||
// sourcemap hooks | ||
onEmitSourceMapOfNode: sourceMap.emitNodeWithSourceMap, | ||
onEmitSourceMapOfToken: sourceMap.emitTokenWithSourceMap, | ||
onEmitSourceMapOfPosition: sourceMap.emitPos, | ||
onSetSourceFile: setSourceFile, | ||
|
||
// transform hooks | ||
onEmitNode: declarationTransform.emitNodeWithNotification, | ||
substituteNode: declarationTransform.substituteNode, | ||
}); | ||
const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!compilerOptions.noEmit; | ||
emitSkipped = emitSkipped || declBlocked; | ||
if (!declBlocked || emitOnlyDtsFiles) { | ||
const previousState = sourceMap.setState(/*disabled*/ true); | ||
printSourceFileOrBundle(declarationFilePath, /*sourceMapFilePath*/ undefined, declarationTransform.transformed[0], declarationPrinter, /*shouldSkipSourcemap*/ true); | ||
sourceMap.setState(previousState); | ||
printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], declarationPrinter, getAreDeclarationMapsEnabled(compilerOptions) ? SourceMapEmitKind.DeclarationFile : SourceMapEmitKind.None); | ||
} | ||
declarationTransform.dispose(); | ||
} | ||
|
||
function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle, printer: Printer, shouldSkipSourcemap = false) { | ||
function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, printer: Printer, sourcemapKind: SourceMapEmitKind) { | ||
const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined; | ||
const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined; | ||
const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile]; | ||
sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFileOrBundle); | ||
if (sourcemapKind !== SourceMapEmitKind.None) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In sourcemap.ts we still set the initial state of |
||
sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFileOrBundle); | ||
} | ||
else { | ||
sourceMap.setState(/*disabled*/ true); | ||
} | ||
|
||
if (bundle) { | ||
bundledHelpers = createMap<boolean>(); | ||
|
@@ -219,25 +238,31 @@ namespace ts { | |
writer.writeLine(); | ||
|
||
const sourceMappingURL = sourceMap.getSourceMappingURL(); | ||
if (!shouldSkipSourcemap && sourceMappingURL) { | ||
if (sourceMappingURL) { | ||
writer.write(`//# ${"sourceMappingURL"}=${sourceMappingURL}`); // Sometimes tools can sometimes see this line as a source mapping url comment | ||
} | ||
|
||
// Write the source map | ||
if (!shouldSkipSourcemap && compilerOptions.sourceMap && !compilerOptions.inlineSourceMap) { | ||
if (sourceMapFilePath && (sourcemapKind === SourceMapEmitKind.File || sourcemapKind === SourceMapEmitKind.DeclarationFile)) { | ||
writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap.getText(), /*writeByteOrderMark*/ false, sourceFiles); | ||
} | ||
|
||
// Record source map data for the test harness. | ||
if (!shouldSkipSourcemap && sourceMapDataList) { | ||
if (sourcemapKind !== SourceMapEmitKind.None) { | ||
sourceMapDataList.push(sourceMap.getSourceMapData()); | ||
} | ||
|
||
// Write the output file | ||
writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), compilerOptions.emitBOM, sourceFiles); | ||
|
||
// Reset state | ||
sourceMap.reset(); | ||
|
||
if (sourcemapKind !== SourceMapEmitKind.None) { | ||
sourceMap.reset(); | ||
} | ||
else { | ||
sourceMap.setState(/*disabled*/ false); | ||
} | ||
writer.clear(); | ||
|
||
currentSourceFile = undefined; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2122,7 +2122,7 @@ namespace ts { | |
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile"); | ||
} | ||
|
||
if (options.mapRoot && !options.sourceMap) { | ||
if (options.mapRoot && !(options.sourceMap || options.declarationMaps)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Though the condition has changed, the related diagnostic still only says |
||
// Error to specify --mapRoot without --sourcemap | ||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap"); | ||
} | ||
|
@@ -2136,6 +2136,12 @@ namespace ts { | |
} | ||
} | ||
|
||
if (options.declarationMaps) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unnecessary nested |
||
if (!options.declaration) { | ||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationMaps", "declaration"); | ||
} | ||
} | ||
|
||
if (options.lib && options.noLib) { | ||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2807,7 +2807,8 @@ namespace ts { | |
export interface EmitFileNames { | ||
jsFilePath: string; | ||
sourceMapFilePath: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this also be |
||
declarationFilePath: string; | ||
declarationFilePath: string | undefined; | ||
declarationMapPath: string | undefined; | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is
--declarationMaps
plural when--sourceMap
is singular?