mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into mh/33603-error-message-for-missing-member
This commit is contained in:
+69
-8
@@ -13,11 +13,26 @@ namespace ts {
|
||||
referenced: boolean;
|
||||
}
|
||||
|
||||
export function getModuleInstanceState(node: ModuleDeclaration): ModuleInstanceState {
|
||||
return node.body ? getModuleInstanceStateWorker(node.body) : ModuleInstanceState.Instantiated;
|
||||
export function getModuleInstanceState(node: ModuleDeclaration, visited?: Map<ModuleInstanceState | undefined>): ModuleInstanceState {
|
||||
if (node.body && !node.body.parent) {
|
||||
// getModuleInstanceStateForAliasTarget needs to walk up the parent chain, so parent pointers must be set on this tree already
|
||||
setParentPointers(node, node.body);
|
||||
}
|
||||
return node.body ? getModuleInstanceStateCached(node.body, visited) : ModuleInstanceState.Instantiated;
|
||||
}
|
||||
|
||||
function getModuleInstanceStateWorker(node: Node): ModuleInstanceState {
|
||||
function getModuleInstanceStateCached(node: Node, visited = createMap<ModuleInstanceState | undefined>()) {
|
||||
const nodeId = "" + getNodeId(node);
|
||||
if (visited.has(nodeId)) {
|
||||
return visited.get(nodeId) || ModuleInstanceState.NonInstantiated;
|
||||
}
|
||||
visited.set(nodeId, undefined);
|
||||
const result = getModuleInstanceStateWorker(node, visited);
|
||||
visited.set(nodeId, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function getModuleInstanceStateWorker(node: Node, visited: Map<ModuleInstanceState | undefined>): ModuleInstanceState {
|
||||
// A module is uninstantiated if it contains only
|
||||
switch (node.kind) {
|
||||
// 1. interface declarations, type alias declarations
|
||||
@@ -37,11 +52,27 @@ namespace ts {
|
||||
return ModuleInstanceState.NonInstantiated;
|
||||
}
|
||||
break;
|
||||
// 4. other uninstantiated module declarations.
|
||||
// 4. Export alias declarations pointing at only uninstantiated modules or things uninstantiated modules contain
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
if (!(node as ExportDeclaration).moduleSpecifier && !!(node as ExportDeclaration).exportClause) {
|
||||
let state = ModuleInstanceState.NonInstantiated;
|
||||
for (const specifier of (node as ExportDeclaration).exportClause!.elements) {
|
||||
const specifierState = getModuleInstanceStateForAliasTarget(specifier, visited);
|
||||
if (specifierState > state) {
|
||||
state = specifierState;
|
||||
}
|
||||
if (state === ModuleInstanceState.Instantiated) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
break;
|
||||
// 5. other uninstantiated module declarations.
|
||||
case SyntaxKind.ModuleBlock: {
|
||||
let state = ModuleInstanceState.NonInstantiated;
|
||||
forEachChild(node, n => {
|
||||
const childState = getModuleInstanceStateWorker(n);
|
||||
const childState = getModuleInstanceStateCached(n, visited);
|
||||
switch (childState) {
|
||||
case ModuleInstanceState.NonInstantiated:
|
||||
// child is non-instantiated - continue searching
|
||||
@@ -61,7 +92,7 @@ namespace ts {
|
||||
return state;
|
||||
}
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return getModuleInstanceState(node as ModuleDeclaration);
|
||||
return getModuleInstanceState(node as ModuleDeclaration, visited);
|
||||
case SyntaxKind.Identifier:
|
||||
// Only jsdoc typedef definition can exist in jsdoc namespace, and it should
|
||||
// be considered the same as type alias
|
||||
@@ -72,6 +103,36 @@ namespace ts {
|
||||
return ModuleInstanceState.Instantiated;
|
||||
}
|
||||
|
||||
function getModuleInstanceStateForAliasTarget(specifier: ExportSpecifier, visited: Map<ModuleInstanceState | undefined>) {
|
||||
const name = specifier.propertyName || specifier.name;
|
||||
let p: Node | undefined = specifier.parent;
|
||||
while (p) {
|
||||
if (isBlock(p) || isModuleBlock(p) || isSourceFile(p)) {
|
||||
const statements = p.statements;
|
||||
let found: ModuleInstanceState | undefined;
|
||||
for (const statement of statements) {
|
||||
if (nodeHasName(statement, name)) {
|
||||
if (!statement.parent) {
|
||||
setParentPointers(p, statement);
|
||||
}
|
||||
const state = getModuleInstanceStateCached(statement, visited);
|
||||
if (found === undefined || state > found) {
|
||||
found = state;
|
||||
}
|
||||
if (found === ModuleInstanceState.Instantiated) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found !== undefined) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
p = p.parent;
|
||||
}
|
||||
return ModuleInstanceState.Instantiated; // Couldn't locate, assume could refer to a value
|
||||
}
|
||||
|
||||
const enum ContainerFlags {
|
||||
// The current node is not a container, and no container manipulation should happen before
|
||||
// recursing into it.
|
||||
@@ -2561,7 +2622,7 @@ namespace ts {
|
||||
// Declare a 'member' if the container is an ES5 class or ES6 constructor
|
||||
constructorSymbol.members = constructorSymbol.members || createSymbolTable();
|
||||
// It's acceptable for multiple 'this' assignments of the same identifier to occur
|
||||
declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
addDeclarationToSymbol(constructorSymbol, constructorSymbol.valueDeclaration, SymbolFlags.Class);
|
||||
}
|
||||
break;
|
||||
@@ -2575,7 +2636,7 @@ namespace ts {
|
||||
// Bind this property to the containing class
|
||||
const containingClass = thisContainer.parent;
|
||||
const symbolTable = hasModifier(thisContainer, ModifierFlags.Static) ? containingClass.symbol.exports! : containingClass.symbol.members!;
|
||||
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true);
|
||||
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.None, /*isReplaceableByMethod*/ true);
|
||||
break;
|
||||
case SyntaxKind.SourceFile:
|
||||
// this.property = assignment in a source file -- declare symbol in exports for a module, in locals for a script
|
||||
|
||||
+1423
-63
File diff suppressed because it is too large
Load Diff
@@ -1552,6 +1552,14 @@ namespace ts {
|
||||
return fn ? fn.bind(obj) : undefined;
|
||||
}
|
||||
|
||||
export function mapMap<T, U>(map: Map<T>, f: (t: T, key: string) => [string, U]): Map<U>;
|
||||
export function mapMap<T, U>(map: UnderscoreEscapedMap<T>, f: (t: T, key: __String) => [string, U]): Map<U>;
|
||||
export function mapMap<T, U>(map: Map<T> | UnderscoreEscapedMap<T>, f: ((t: T, key: string) => [string, U]) | ((t: T, key: __String) => [string, U])): Map<U> {
|
||||
const result = createMap<U>();
|
||||
map.forEach((t: T, key: string & __String) => result.set(...(f(t, key))));
|
||||
return result;
|
||||
}
|
||||
|
||||
export interface MultiMap<T> extends Map<T[]> {
|
||||
/**
|
||||
* Adds the value to an array of values associated with the key, and returns the array.
|
||||
|
||||
@@ -4587,6 +4587,14 @@
|
||||
"category": "Error",
|
||||
"code": 9004
|
||||
},
|
||||
"Declaration emit for this file requires using private name '{0}'. An explicit type annotation may unblock declaration emit.": {
|
||||
"category": "Error",
|
||||
"code": 9005
|
||||
},
|
||||
"Declaration emit for this file requires using private name '{0}' from module '{1}'. An explicit type annotation may unblock declaration emit.": {
|
||||
"category": "Error",
|
||||
"code": 9006
|
||||
},
|
||||
"JSX attributes must only be assigned a non-empty 'expression'.": {
|
||||
"category": "Error",
|
||||
"code": 17000
|
||||
|
||||
+8
-10
@@ -96,9 +96,7 @@ namespace ts {
|
||||
comparePaths(sourceFile.fileName, ownOutputFilePath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === Comparison.EqualTo;
|
||||
const jsFilePath = options.emitDeclarationOnly || isJsonEmittedToSameLocation ? undefined : ownOutputFilePath;
|
||||
const sourceMapFilePath = !jsFilePath || isJsonSourceFile(sourceFile) ? undefined : 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 = isSourceFileJS(sourceFile);
|
||||
const declarationFilePath = ((forceDtsPaths || getEmitDeclarations(options)) && !isJs) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined;
|
||||
const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined;
|
||||
const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
|
||||
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath: undefined };
|
||||
}
|
||||
@@ -146,7 +144,7 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean) {
|
||||
Debug.assert(!fileExtensionIs(inputFileName, Extension.Dts) && hasTSFileExtension(inputFileName));
|
||||
Debug.assert(!fileExtensionIs(inputFileName, Extension.Dts));
|
||||
return changeExtension(
|
||||
getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.declarationDir || configFile.options.outDir),
|
||||
Extension.Dts
|
||||
@@ -199,7 +197,7 @@ namespace ts {
|
||||
if (js && configFile.options.sourceMap) {
|
||||
addOutput(`${js}.map`);
|
||||
}
|
||||
if (getEmitDeclarations(configFile.options) && hasTSFileExtension(inputFileName)) {
|
||||
if (getEmitDeclarations(configFile.options)) {
|
||||
const dts = getOutputDeclarationFileName(inputFileName, configFile, ignoreCase);
|
||||
addOutput(dts);
|
||||
if (configFile.options.declarationMap) {
|
||||
@@ -248,7 +246,7 @@ namespace ts {
|
||||
const jsFilePath = getOutputJSFileName(inputFileName, configFile, ignoreCase);
|
||||
if (jsFilePath) return jsFilePath;
|
||||
if (fileExtensionIs(inputFileName, Extension.Json)) continue;
|
||||
if (getEmitDeclarations(configFile.options) && hasTSFileExtension(inputFileName)) {
|
||||
if (getEmitDeclarations(configFile.options)) {
|
||||
return getOutputDeclarationFileName(inputFileName, configFile, ignoreCase);
|
||||
}
|
||||
}
|
||||
@@ -395,17 +393,16 @@ namespace ts {
|
||||
declarationFilePath: string | undefined,
|
||||
declarationMapPath: string | undefined,
|
||||
relativeToBuildInfo: (path: string) => string) {
|
||||
if (!sourceFileOrBundle || !(declarationFilePath && !isInJSFile(sourceFileOrBundle))) {
|
||||
if (!sourceFileOrBundle || !declarationFilePath) {
|
||||
return;
|
||||
}
|
||||
const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles;
|
||||
// Setup and perform the transformation to retrieve declarations from the input files
|
||||
const nonJsFiles = filter(sourceFiles, isSourceFileNotJS);
|
||||
const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles;
|
||||
const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(sourceFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : sourceFiles;
|
||||
if (emitOnlyDtsFiles && !getEmitDeclarations(compilerOptions)) {
|
||||
// Checker wont collect the linked aliases since thats only done when declaration is enabled.
|
||||
// Do that here when emitting only dts files
|
||||
nonJsFiles.forEach(collectLinkedAliases);
|
||||
sourceFiles.forEach(collectLinkedAliases);
|
||||
}
|
||||
const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false);
|
||||
if (length(declarationTransform.diagnostics)) {
|
||||
@@ -659,6 +656,7 @@ namespace ts {
|
||||
getAllAccessorDeclarations: notImplemented,
|
||||
getSymbolOfExternalModuleSpecifier: notImplemented,
|
||||
isBindingCapturedByNode: notImplemented,
|
||||
getDeclarationStatementsForSourceFile: notImplemented,
|
||||
};
|
||||
|
||||
/*@internal*/
|
||||
|
||||
@@ -2259,6 +2259,11 @@ namespace ts {
|
||||
: node;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function createEmptyExports() {
|
||||
return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined);
|
||||
}
|
||||
|
||||
export function createNamedExports(elements: readonly ExportSpecifier[]) {
|
||||
const node = <NamedExports>createSynthesizedNode(SyntaxKind.NamedExports);
|
||||
node.elements = createNodeArray(elements);
|
||||
|
||||
+4
-11
@@ -856,7 +856,7 @@ namespace ts {
|
||||
}
|
||||
else if (getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) {
|
||||
for (const fileName of parsedRef.commandLine.fileNames) {
|
||||
if (!fileExtensionIs(fileName, Extension.Dts) && hasTSFileExtension(fileName)) {
|
||||
if (!fileExtensionIs(fileName, Extension.Dts)) {
|
||||
processSourceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames()), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
}
|
||||
@@ -2448,8 +2448,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getProjectReferenceRedirectProject(fileName: string) {
|
||||
// Ignore dts or any of the non ts files
|
||||
if (!resolvedProjectReferences || !resolvedProjectReferences.length || fileExtensionIs(fileName, Extension.Dts) || !fileExtensionIsOneOf(fileName, supportedTSExtensions)) {
|
||||
// Ignore dts
|
||||
if (!resolvedProjectReferences || !resolvedProjectReferences.length || fileExtensionIs(fileName, Extension.Dts)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -2510,7 +2510,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
forEach(resolvedRef.commandLine.fileNames, fileName => {
|
||||
if (!fileExtensionIs(fileName, Extension.Dts) && hasTSFileExtension(fileName)) {
|
||||
if (!fileExtensionIs(fileName, Extension.Dts)) {
|
||||
const outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, host.useCaseSensitiveFileNames());
|
||||
mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), fileName);
|
||||
}
|
||||
@@ -3077,10 +3077,6 @@ namespace ts {
|
||||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_target_is_ES3, "useDefineForClassFields");
|
||||
}
|
||||
|
||||
if (!options.noEmit && options.allowJs && getEmitDeclarations(options)) {
|
||||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", getEmitDeclarationOptionName(options));
|
||||
}
|
||||
|
||||
if (options.checkJs && !options.allowJs) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "checkJs", "allowJs"));
|
||||
}
|
||||
@@ -3425,9 +3421,6 @@ namespace ts {
|
||||
return resolveConfigFileProjectName(passedInRef.path);
|
||||
}
|
||||
|
||||
function getEmitDeclarationOptionName(options: CompilerOptions) {
|
||||
return options.declaration ? "declaration" : "composite";
|
||||
}
|
||||
/* @internal */
|
||||
/**
|
||||
* Returns a DiagnosticMessage if we won't include a resolved module due to its extension.
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined {
|
||||
if (file && isSourceFileJS(file)) {
|
||||
return []; // No declaration diagnostics for js for now
|
||||
}
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const result = transformNodes(resolver, host, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJS), [transformDeclarations], /*allowDtsFiles*/ false);
|
||||
const result = transformNodes(resolver, host, compilerOptions, file ? [file] : host.getSourceFiles(), [transformDeclarations], /*allowDtsFiles*/ false);
|
||||
return result.diagnostics;
|
||||
}
|
||||
|
||||
@@ -190,15 +187,24 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createEmptyExports() {
|
||||
return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined);
|
||||
function transformDeclarationsForJS(sourceFile: SourceFile, bundled?: boolean) {
|
||||
const oldDiag = getSymbolAccessibilityDiagnostic;
|
||||
getSymbolAccessibilityDiagnostic = (s) => ({
|
||||
diagnosticMessage: s.errorModuleName
|
||||
? Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_from_module_1_An_explicit_type_annotation_may_unblock_declaration_emit
|
||||
: Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_An_explicit_type_annotation_may_unblock_declaration_emit,
|
||||
errorNode: s.errorNode || sourceFile
|
||||
});
|
||||
const result = resolver.getDeclarationStatementsForSourceFile(sourceFile, declarationEmitNodeBuilderFlags, symbolTracker, bundled);
|
||||
getSymbolAccessibilityDiagnostic = oldDiag;
|
||||
return result;
|
||||
}
|
||||
|
||||
function transformRoot(node: Bundle): Bundle;
|
||||
function transformRoot(node: SourceFile): SourceFile;
|
||||
function transformRoot(node: SourceFile | Bundle): SourceFile | Bundle;
|
||||
function transformRoot(node: SourceFile | Bundle) {
|
||||
if (node.kind === SyntaxKind.SourceFile && (node.isDeclarationFile || isSourceFileJS(node))) {
|
||||
if (node.kind === SyntaxKind.SourceFile && node.isDeclarationFile) {
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -209,7 +215,7 @@ namespace ts {
|
||||
let hasNoDefaultLib = false;
|
||||
const bundle = createBundle(map(node.sourceFiles,
|
||||
sourceFile => {
|
||||
if (sourceFile.isDeclarationFile || isSourceFileJS(sourceFile)) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217
|
||||
if (sourceFile.isDeclarationFile) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217
|
||||
hasNoDefaultLib = hasNoDefaultLib || sourceFile.hasNoDefaultLib;
|
||||
currentSourceFile = sourceFile;
|
||||
enclosingDeclaration = sourceFile;
|
||||
@@ -221,10 +227,10 @@ namespace ts {
|
||||
resultHasScopeMarker = false;
|
||||
collectReferences(sourceFile, refs);
|
||||
collectLibs(sourceFile, libs);
|
||||
if (isExternalModule(sourceFile)) {
|
||||
if (isExternalOrCommonJsModule(sourceFile) || isJsonSourceFile(sourceFile)) {
|
||||
resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules)
|
||||
needsDeclare = false;
|
||||
const statements = visitNodes(sourceFile.statements, visitDeclarationStatements);
|
||||
const statements = isSourceFileJS(sourceFile) ? createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) : visitNodes(sourceFile.statements, visitDeclarationStatements);
|
||||
const newFile = updateSourceFileNode(sourceFile, [createModuleDeclaration(
|
||||
[],
|
||||
[createModifier(SyntaxKind.DeclareKeyword)],
|
||||
@@ -234,7 +240,7 @@ namespace ts {
|
||||
return newFile;
|
||||
}
|
||||
needsDeclare = true;
|
||||
const updated = visitNodes(sourceFile.statements, visitDeclarationStatements);
|
||||
const updated = isSourceFileJS(sourceFile) ? createNodeArray(transformDeclarationsForJS(sourceFile)) : visitNodes(sourceFile.statements, visitDeclarationStatements);
|
||||
return updateSourceFileNode(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []);
|
||||
}
|
||||
), mapDefined(node.prepends, prepend => {
|
||||
@@ -276,12 +282,19 @@ namespace ts {
|
||||
const references: FileReference[] = [];
|
||||
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
|
||||
const referenceVisitor = mapReferencesIntoArray(references, outputFilePath);
|
||||
const statements = visitNodes(node.statements, visitDeclarationStatements);
|
||||
let combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
|
||||
refs.forEach(referenceVisitor);
|
||||
emittedImports = filter(combinedStatements, isAnyImportSyntax);
|
||||
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
|
||||
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createEmptyExports()]), combinedStatements);
|
||||
let combinedStatements: NodeArray<Statement>;
|
||||
if (isSourceFileJS(currentSourceFile)) {
|
||||
combinedStatements = createNodeArray(transformDeclarationsForJS(node));
|
||||
emittedImports = filter(combinedStatements, isAnyImportSyntax);
|
||||
}
|
||||
else {
|
||||
const statements = visitNodes(node.statements, visitDeclarationStatements);
|
||||
combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
|
||||
refs.forEach(referenceVisitor);
|
||||
emittedImports = filter(combinedStatements, isAnyImportSyntax);
|
||||
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
|
||||
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createEmptyExports()]), combinedStatements);
|
||||
}
|
||||
}
|
||||
const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences());
|
||||
updated.exportedModulesFromDeclarationEmit = exportedModulesFromDeclarationEmit;
|
||||
@@ -755,15 +768,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function isExternalModuleIndicator(result: LateVisibilityPaintedStatement | ExportAssignment) {
|
||||
// Exported top-level member indicates moduleness
|
||||
return isAnyImportOrReExport(result) || isExportAssignment(result) || hasModifier(result, ModifierFlags.Export);
|
||||
}
|
||||
|
||||
function needsScopeMarker(result: LateVisibilityPaintedStatement | ExportAssignment) {
|
||||
return !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasModifier(result, ModifierFlags.Export) && !isAmbientModule(result);
|
||||
}
|
||||
|
||||
function visitDeclarationSubtree(input: Node): VisitResult<Node> {
|
||||
if (shouldStripInternal(input)) return;
|
||||
if (isDeclaration(input)) {
|
||||
|
||||
@@ -3734,6 +3734,7 @@ namespace ts {
|
||||
getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations;
|
||||
getSymbolOfExternalModuleSpecifier(node: StringLiteralLike): Symbol | undefined;
|
||||
isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean;
|
||||
getDeclarationStatementsForSourceFile(node: SourceFile, flags: NodeBuilderFlags, tracker: SymbolTracker, bundled?: boolean): Statement[] | undefined;
|
||||
}
|
||||
|
||||
export const enum SymbolFlags {
|
||||
@@ -3814,6 +3815,12 @@ namespace ts {
|
||||
|
||||
ClassMember = Method | Accessor | Property,
|
||||
|
||||
/* @internal */
|
||||
ExportSupportsDefaultModifier = Class | Function | Interface,
|
||||
|
||||
/* @internal */
|
||||
ExportDoesNotSupportDefaultModifier = ~ExportSupportsDefaultModifier,
|
||||
|
||||
/* @internal */
|
||||
// The set of things we consider semantically classifiable. Used to speed up the LS during
|
||||
// classification.
|
||||
@@ -3877,6 +3884,7 @@ namespace ts {
|
||||
variances?: VarianceFlags[]; // Alias symbol type argument variance cache
|
||||
deferralConstituents?: Type[]; // Calculated list of constituents for a deferred type
|
||||
deferralParent?: Type; // Source union/intersection of a deferred type
|
||||
cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -6024,7 +6032,7 @@ namespace ts {
|
||||
// Called when the symbol writer encounters a symbol to write. Currently only used by the
|
||||
// declaration emitter to help determine if it should patch up the final declaration file
|
||||
// with import statements it previously saw (but chose not to emit).
|
||||
trackSymbol?(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
|
||||
trackSymbol?(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags): void;
|
||||
reportInaccessibleThisError?(): void;
|
||||
reportPrivateInBaseOfClassExpression?(propertyName: string): void;
|
||||
reportInaccessibleUniqueSymbolError?(): void;
|
||||
|
||||
@@ -2606,6 +2606,8 @@ namespace ts {
|
||||
// export = <EntityNameExpression>
|
||||
// export default <EntityNameExpression>
|
||||
// module.exports = <EntityNameExpression>
|
||||
// {<Identifier>}
|
||||
// {name: <EntityNameExpression>}
|
||||
export function isAliasSymbolDeclaration(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.ImportEqualsDeclaration ||
|
||||
node.kind === SyntaxKind.NamespaceExportDeclaration ||
|
||||
@@ -2614,12 +2616,28 @@ namespace ts {
|
||||
node.kind === SyntaxKind.ImportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportSpecifier ||
|
||||
node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node) ||
|
||||
isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports && exportAssignmentIsAlias(node);
|
||||
isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports && exportAssignmentIsAlias(node) ||
|
||||
isPropertyAccessExpression(node) && isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAliasableExpression(node.parent.right) ||
|
||||
node.kind === SyntaxKind.ShorthandPropertyAssignment ||
|
||||
node.kind === SyntaxKind.PropertyAssignment && isAliasableExpression((node as PropertyAssignment).initializer);
|
||||
}
|
||||
|
||||
function isAliasableExpression(e: Expression) {
|
||||
return isEntityNameExpression(e) || isClassExpression(e);
|
||||
}
|
||||
|
||||
export function exportAssignmentIsAlias(node: ExportAssignment | BinaryExpression): boolean {
|
||||
const e = isExportAssignment(node) ? node.expression : node.right;
|
||||
return isEntityNameExpression(e) || isClassExpression(e);
|
||||
const e = getExportAssignmentExpression(node);
|
||||
return isAliasableExpression(e);
|
||||
}
|
||||
|
||||
export function getExportAssignmentExpression(node: ExportAssignment | BinaryExpression): Expression {
|
||||
return isExportAssignment(node) ? node.expression : node.right;
|
||||
}
|
||||
|
||||
export function getPropertyAssignmentAliasLikeExpression(node: PropertyAssignment | ShorthandPropertyAssignment | PropertyAccessExpression): Expression {
|
||||
return node.kind === SyntaxKind.ShorthandPropertyAssignment ? node.name : node.kind === SyntaxKind.PropertyAssignment ? node.initializer :
|
||||
(node.parent as BinaryExpression).right;
|
||||
}
|
||||
|
||||
export function getEffectiveBaseTypeNode(node: ClassLikeDeclaration | InterfaceDeclaration) {
|
||||
@@ -2699,6 +2717,11 @@ namespace ts {
|
||||
return token !== undefined && isNonContextualKeyword(token);
|
||||
}
|
||||
|
||||
export function isStringAKeyword(name: string) {
|
||||
const token = stringToToken(name);
|
||||
return token !== undefined && isKeyword(token);
|
||||
}
|
||||
|
||||
export function isIdentifierANonContextualKeyword({ originalKeywordKind }: Identifier): boolean {
|
||||
return !!originalKeywordKind && !isContextualKeyword(originalKeywordKind);
|
||||
}
|
||||
@@ -3450,11 +3473,17 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export function getResolvedExternalModuleName(host: EmitHost, file: SourceFile, referenceFile?: SourceFile): string {
|
||||
export interface ResolveModuleNameResolutionHost {
|
||||
getCanonicalFileName(p: string): string;
|
||||
getCommonSourceDirectory(): string;
|
||||
getCurrentDirectory(): string;
|
||||
}
|
||||
|
||||
export function getResolvedExternalModuleName(host: ResolveModuleNameResolutionHost, file: SourceFile, referenceFile?: SourceFile): string {
|
||||
return file.moduleName || getExternalModuleNameFromPath(host, file.fileName, referenceFile && referenceFile.fileName);
|
||||
}
|
||||
|
||||
export function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string | undefined {
|
||||
export function getExternalModuleNameFromDeclaration(host: ResolveModuleNameResolutionHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string | undefined {
|
||||
const file = resolver.getExternalModuleFileFromDeclaration(declaration);
|
||||
if (!file || file.isDeclarationFile) {
|
||||
return undefined;
|
||||
@@ -3465,7 +3494,7 @@ namespace ts {
|
||||
/**
|
||||
* Resolves a local path to a path which is absolute to the base of the emit
|
||||
*/
|
||||
export function getExternalModuleNameFromPath(host: EmitHost, fileName: string, referencePath?: string): string {
|
||||
export function getExternalModuleNameFromPath(host: ResolveModuleNameResolutionHost, fileName: string, referencePath?: string): string {
|
||||
const getCanonicalFileName = (f: string) => host.getCanonicalFileName(f);
|
||||
const dir = toPath(referencePath ? getDirectoryPath(referencePath) : host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName);
|
||||
const filePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
|
||||
@@ -5224,6 +5253,17 @@ namespace ts {
|
||||
return name && isIdentifier(name) ? name : undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function nodeHasName(statement: Node, name: Identifier) {
|
||||
if (isNamedDeclaration(statement) && isIdentifier(statement.name) && idText(statement.name as Identifier) === idText(name)) {
|
||||
return true;
|
||||
}
|
||||
if (isVariableStatement(statement) && some(statement.declarationList.declarations, d => nodeHasName(d, name))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined {
|
||||
return declaration.name || nameForNamelessJSDocTypedef(declaration);
|
||||
}
|
||||
@@ -6145,7 +6185,7 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.JSDocTypeExpression;
|
||||
}
|
||||
|
||||
export function isJSDocAllType(node: JSDocAllType): node is JSDocAllType {
|
||||
export function isJSDocAllType(node: Node): node is JSDocAllType {
|
||||
return node.kind === SyntaxKind.JSDocAllType;
|
||||
}
|
||||
|
||||
@@ -6762,6 +6802,27 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function isScopeMarker(node: Node) {
|
||||
return isExportAssignment(node) || isExportDeclaration(node);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function hasScopeMarker(statements: readonly Statement[]) {
|
||||
return some(statements, isScopeMarker);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function needsScopeMarker(result: Statement) {
|
||||
return !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasModifier(result, ModifierFlags.Export) && !isAmbientModule(result);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function isExternalModuleIndicator(result: Statement) {
|
||||
// Exported top-level member indicates moduleness
|
||||
return isAnyImportOrReExport(result) || isExportAssignment(result) || hasModifier(result, ModifierFlags.Export);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function isForInOrOfStatement(node: Node): node is ForInOrOfStatement {
|
||||
return node.kind === SyntaxKind.ForInStatement || node.kind === SyntaxKind.ForOfStatement;
|
||||
|
||||
+13
-8
@@ -219,14 +219,19 @@ namespace compiler {
|
||||
return vpath.changeExtension(path, ext);
|
||||
}
|
||||
|
||||
public getNumberOfJsFiles() {
|
||||
let count = this.js.size;
|
||||
this.js.forEach(document => {
|
||||
if (ts.fileExtensionIs(document.file, ts.Extension.Json)) {
|
||||
count--;
|
||||
}
|
||||
});
|
||||
return count;
|
||||
public getNumberOfJsFiles(includeJson: boolean) {
|
||||
if (includeJson) {
|
||||
return this.js.size;
|
||||
}
|
||||
else {
|
||||
let count = this.js.size;
|
||||
this.js.forEach(document => {
|
||||
if (ts.fileExtensionIs(document.file, ts.Extension.Json)) {
|
||||
count--;
|
||||
}
|
||||
});
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -888,7 +888,7 @@ namespace Harness {
|
||||
throw new Error("Only declaration files should be generated when emitDeclarationOnly:true");
|
||||
}
|
||||
}
|
||||
else if (result.dts.size !== result.getNumberOfJsFiles()) {
|
||||
else if (result.dts.size !== result.getNumberOfJsFiles(/*includeJson*/ true)) {
|
||||
throw new Error("There were no errors and declFiles generated did not match number of js files generated");
|
||||
}
|
||||
}
|
||||
@@ -907,7 +907,7 @@ namespace Harness {
|
||||
if (vpath.isDeclaration(file.unitName) || vpath.isJson(file.unitName)) {
|
||||
dtsFiles.push(file);
|
||||
}
|
||||
else if (vpath.isTypeScript(file.unitName)) {
|
||||
else if (vpath.isTypeScript(file.unitName) || (vpath.isJavaScript(file.unitName) && options.allowJs)) {
|
||||
const declFile = findResultCodeFile(file.unitName);
|
||||
if (declFile && !findUnit(declFile.file, declInputFiles) && !findUnit(declFile.file, declOtherFiles)) {
|
||||
dtsFiles.push({ unitName: declFile.file, content: utils.removeByteOrderMark(declFile.text) });
|
||||
@@ -1269,7 +1269,7 @@ namespace Harness {
|
||||
return;
|
||||
}
|
||||
else if (options.sourceMap || declMaps) {
|
||||
if (result.maps.size !== (result.getNumberOfJsFiles() * (declMaps && options.sourceMap ? 2 : 1))) {
|
||||
if (result.maps.size !== ((options.sourceMap ? result.getNumberOfJsFiles(/*includeJson*/ false) : 0) + (declMaps ? result.getNumberOfJsFiles(/*includeJson*/ true) : 0))) {
|
||||
throw new Error("Number of sourcemap files should be same as js files.");
|
||||
}
|
||||
|
||||
|
||||
@@ -1971,8 +1971,7 @@ namespace ts {
|
||||
const notAccessible = () => { typeIsAccessible = false; };
|
||||
const res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, {
|
||||
trackSymbol: (symbol, declaration, meaning) => {
|
||||
// TODO: GH#18217
|
||||
typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning!, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible;
|
||||
typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible;
|
||||
},
|
||||
reportInaccessibleThisError: notAccessible,
|
||||
reportPrivateInBaseOfClassExpression: notAccessible,
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
"unittests/tsbuild/emptyFiles.ts",
|
||||
"unittests/tsbuild/graphOrdering.ts",
|
||||
"unittests/tsbuild/inferredTypeFromTransitiveModule.ts",
|
||||
"unittests/tsbuild/javascriptProjectEmit.ts",
|
||||
"unittests/tsbuild/lateBoundSymbol.ts",
|
||||
"unittests/tsbuild/missingExtendedFile.ts",
|
||||
"unittests/tsbuild/moduleSpecifiers.ts",
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild:: javascriptProjectEmit:: loads js-based projects and emits them correctly", () => {
|
||||
verifyTsc({
|
||||
scenario: "javascriptProjectEmit",
|
||||
subScenario: `loads js-based projects and emits them correctly`,
|
||||
fs: () => loadProjectFromFiles({
|
||||
"/src/common/nominal.js": utils.dedent`
|
||||
/**
|
||||
* @template T, Name
|
||||
* @typedef {T & {[Symbol.species]: Name}} Nominal
|
||||
*/
|
||||
module.exports = {};
|
||||
`,
|
||||
"/src/common/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"include": ["nominal.js"]
|
||||
}`,
|
||||
"/src/sub-project/index.js": utils.dedent`
|
||||
import { Nominal } from '../common/nominal';
|
||||
|
||||
/**
|
||||
* @typedef {Nominal<string, 'MyNominal'>} MyNominal
|
||||
*/
|
||||
`,
|
||||
"/src/sub-project/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../common" }
|
||||
],
|
||||
"include": ["./index.js"]
|
||||
}`,
|
||||
"/src/sub-project-2/index.js": utils.dedent`
|
||||
import { MyNominal } from '../sub-project/index';
|
||||
|
||||
const variable = {
|
||||
key: /** @type {MyNominal} */('value'),
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {keyof typeof variable}
|
||||
*/
|
||||
export function getVar() {
|
||||
return 'key';
|
||||
}
|
||||
`,
|
||||
"/src/sub-project-2/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../sub-project" }
|
||||
],
|
||||
"include": ["./index.js"]
|
||||
}`,
|
||||
"/src/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "./sub-project" },
|
||||
{ "path": "./sub-project-2" }
|
||||
],
|
||||
"include": []
|
||||
}`,
|
||||
"/src/tsconfig.base.json": utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"rootDir": "./",
|
||||
"outDir": "../lib",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"declaration": true
|
||||
}
|
||||
}`,
|
||||
}, symbolLibContent),
|
||||
commandLineArgs: ["-b", "/src"]
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsbuild:: javascriptProjectEmit:: loads outfile js projects and concatenates them correctly", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
before(() => {
|
||||
projFs = loadProjectFromFiles({
|
||||
"/src/common/nominal.js": utils.dedent`
|
||||
/**
|
||||
* @template T, Name
|
||||
* @typedef {T & {[Symbol.species]: Name}} Nominal
|
||||
*/
|
||||
`,
|
||||
"/src/common/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"outFile": "common.js"
|
||||
},
|
||||
"include": ["nominal.js"]
|
||||
}`,
|
||||
"/src/sub-project/index.js": utils.dedent`
|
||||
/**
|
||||
* @typedef {Nominal<string, 'MyNominal'>} MyNominal
|
||||
*/
|
||||
const c = /** @type {*} */(null);
|
||||
`,
|
||||
"/src/sub-project/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"outFile": "sub-project.js"
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../common", "prepend": true }
|
||||
],
|
||||
"include": ["./index.js"]
|
||||
}`,
|
||||
"/src/sub-project-2/index.js": utils.dedent`
|
||||
const variable = {
|
||||
key: /** @type {MyNominal} */('value'),
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {keyof typeof variable}
|
||||
*/
|
||||
function getVar() {
|
||||
return 'key';
|
||||
}
|
||||
`,
|
||||
"/src/sub-project-2/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"outFile": "sub-project-2.js"
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../sub-project", "prepend": true }
|
||||
],
|
||||
"include": ["./index.js"]
|
||||
}`,
|
||||
"/src/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"outFile": "src.js"
|
||||
},
|
||||
"references": [
|
||||
{ "path": "./sub-project", "prepend": true },
|
||||
{ "path": "./sub-project-2", "prepend": true }
|
||||
],
|
||||
"include": []
|
||||
}`,
|
||||
"/src/tsconfig.base.json": utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"rootDir": "./",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"declaration": true
|
||||
}
|
||||
}`,
|
||||
}, symbolLibContent);
|
||||
});
|
||||
after(() => {
|
||||
projFs = undefined!;
|
||||
});
|
||||
verifyTsc({
|
||||
scenario: "javascriptProjectEmit",
|
||||
subScenario: `loads outfile js projects and concatenates them correctly`,
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["-b", "/src"]
|
||||
});
|
||||
verifyTscIncrementalEdits({
|
||||
scenario: "javascriptProjectEmit",
|
||||
subScenario: `modifies outfile js projects and concatenates them correctly`,
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["-b", "/src"],
|
||||
incrementalScenarios: [{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
modifyFs: fs => replaceText(fs, "/src/sub-project/index.js", "null", "undefined")
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsbuild:: javascriptProjectEmit:: loads js-based projects with non-moved json files and emits them correctly", () => {
|
||||
verifyTsc({
|
||||
scenario: "javascriptProjectEmit",
|
||||
subScenario: `loads js-based projects with non-moved json files and emits them correctly`,
|
||||
fs: () => loadProjectFromFiles({
|
||||
"/src/common/obj.json": utils.dedent`
|
||||
{
|
||||
"val": 42
|
||||
}`,
|
||||
"/src/common/index.ts": utils.dedent`
|
||||
import x = require("./obj.json");
|
||||
export = x;
|
||||
`,
|
||||
"/src/common/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": null
|
||||
"composite": true
|
||||
},
|
||||
"include": ["index.ts", "obj.json"]
|
||||
}`,
|
||||
"/src/sub-project/index.js": utils.dedent`
|
||||
import mod from '../common';
|
||||
|
||||
export const m = mod;
|
||||
`,
|
||||
"/src/sub-project/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../common" }
|
||||
],
|
||||
"include": ["./index.js"]
|
||||
}`,
|
||||
"/src/sub-project-2/index.js": utils.dedent`
|
||||
import { m } from '../sub-project/index';
|
||||
|
||||
const variable = {
|
||||
key: m,
|
||||
};
|
||||
|
||||
export function getVar() {
|
||||
return variable;
|
||||
}
|
||||
`,
|
||||
"/src/sub-project-2/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../sub-project" }
|
||||
],
|
||||
"include": ["./index.js"]
|
||||
}`,
|
||||
"/src/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "./sub-project" },
|
||||
{ "path": "./sub-project-2" }
|
||||
],
|
||||
"include": []
|
||||
}`,
|
||||
"/src/tsconfig.base.json": utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"rootDir": "./",
|
||||
"outDir": "../out",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"declaration": true
|
||||
}
|
||||
}`,
|
||||
}, symbolLibContent),
|
||||
commandLineArgs: ["-b", "/src"]
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -52,7 +52,12 @@ namespace ts {
|
||||
|
||||
export default hello.hello`);
|
||||
const allExpectedOutputs = ["/src/dist/src/index.js", "/src/dist/src/index.d.ts", "/src/dist/src/index.json"];
|
||||
verifyProjectWithResolveJsonModuleWithFs(fs, "/src/tsconfig_withIncludeOfJson.json", allExpectedOutputs);
|
||||
verifyProjectWithResolveJsonModuleWithFs(
|
||||
fs,
|
||||
"/src/tsconfig_withIncludeOfJson.json",
|
||||
allExpectedOutputs,
|
||||
errorDiagnostic([Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, "/src/dist/src/index.d.ts"])
|
||||
);
|
||||
});
|
||||
|
||||
it("with resolveJsonModule and files containing json file", () => {
|
||||
|
||||
@@ -885,8 +885,8 @@ namespace ts.tscWatch {
|
||||
// More comment`;
|
||||
const configFileContentAfterComment = `
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"declaration": true
|
||||
"inlineSourceMap": true,
|
||||
"mapRoot": "./"
|
||||
}
|
||||
}`;
|
||||
const configFileContentWithComment = configFileContentBeforeComment + configFileContentComment + configFileContentAfterComment;
|
||||
@@ -900,8 +900,9 @@ namespace ts.tscWatch {
|
||||
const host = createWatchedSystem(files);
|
||||
const watch = createWatchOfConfigFile(configFile.path, host);
|
||||
const errors = () => [
|
||||
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"allowJs"'), '"allowJs"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"),
|
||||
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")
|
||||
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"inlineSourceMap"'), '"inlineSourceMap"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap"),
|
||||
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"mapRoot"'), '"mapRoot"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap"),
|
||||
getDiagnosticOfFile(watch().getCompilerOptions().configFile!, configFile.content.indexOf('"mapRoot"'), '"mapRoot"'.length, Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "mapRoot", "sourceMap", "declarationMap")
|
||||
];
|
||||
const intialErrors = errors();
|
||||
checkOutputErrorsInitial(host, intialErrors);
|
||||
|
||||
@@ -849,8 +849,8 @@ declare module '@custom/plugin' {
|
||||
// comment`;
|
||||
const configFileContentAfterComment = `
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"declaration": true
|
||||
"inlineSourceMap": true,
|
||||
"mapRoot": "./"
|
||||
}
|
||||
}`;
|
||||
const configFileContentWithComment = configFileContentBeforeComment + configFileContentComment + configFileContentAfterComment;
|
||||
@@ -874,7 +874,7 @@ declare module '@custom/plugin' {
|
||||
seq: 2,
|
||||
arguments: { file: configFile.path, projectFileName: projectName, includeLinePosition: true }
|
||||
}).response as readonly server.protocol.DiagnosticWithLinePosition[];
|
||||
assert.isTrue(diags.length === 2);
|
||||
assert.isTrue(diags.length === 3);
|
||||
|
||||
configFile.content = configFileContentWithoutCommentLine;
|
||||
host.reloadFS([file, configFile]);
|
||||
@@ -885,10 +885,11 @@ declare module '@custom/plugin' {
|
||||
seq: 2,
|
||||
arguments: { file: configFile.path, projectFileName: projectName, includeLinePosition: true }
|
||||
}).response as readonly server.protocol.DiagnosticWithLinePosition[];
|
||||
assert.isTrue(diagsAfterEdit.length === 2);
|
||||
assert.isTrue(diagsAfterEdit.length === 3);
|
||||
|
||||
verifyDiagnostic(diags[0], diagsAfterEdit[0]);
|
||||
verifyDiagnostic(diags[1], diagsAfterEdit[1]);
|
||||
verifyDiagnostic(diags[2], diagsAfterEdit[2]);
|
||||
|
||||
function verifyDiagnostic(beforeEditDiag: server.protocol.DiagnosticWithLinePosition, afterEditDiag: server.protocol.DiagnosticWithLinePosition) {
|
||||
assert.equal(beforeEditDiag.message, afterEditDiag.message);
|
||||
|
||||
Reference in New Issue
Block a user