mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-20 19:45:07 -06:00
Merge branch 'master' into keyoftypes
# Conflicts: # src/compiler/diagnosticMessages.json
This commit is contained in:
commit
6b28d21a82
@ -15,7 +15,7 @@ matrix:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- release-2.0
|
||||
- release-2.1
|
||||
|
||||
install:
|
||||
- npm uninstall typescript
|
||||
|
||||
12
Jakefile.js
12
Jakefile.js
@ -70,15 +70,15 @@ var compilerSources = [
|
||||
"visitor.ts",
|
||||
"transformers/destructuring.ts",
|
||||
"transformers/ts.ts",
|
||||
"transformers/module/es2015.ts",
|
||||
"transformers/module/system.ts",
|
||||
"transformers/module/module.ts",
|
||||
"transformers/jsx.ts",
|
||||
"transformers/es2017.ts",
|
||||
"transformers/es2016.ts",
|
||||
"transformers/es2015.ts",
|
||||
"transformers/generators.ts",
|
||||
"transformers/es5.ts",
|
||||
"transformers/module/es2015.ts",
|
||||
"transformers/module/system.ts",
|
||||
"transformers/module/module.ts",
|
||||
"transformer.ts",
|
||||
"sourcemap.ts",
|
||||
"comments.ts",
|
||||
@ -106,15 +106,15 @@ var servicesSources = [
|
||||
"visitor.ts",
|
||||
"transformers/destructuring.ts",
|
||||
"transformers/ts.ts",
|
||||
"transformers/module/es2015.ts",
|
||||
"transformers/module/system.ts",
|
||||
"transformers/module/module.ts",
|
||||
"transformers/jsx.ts",
|
||||
"transformers/es2017.ts",
|
||||
"transformers/es2016.ts",
|
||||
"transformers/es2015.ts",
|
||||
"transformers/generators.ts",
|
||||
"transformers/es5.ts",
|
||||
"transformers/module/es2015.ts",
|
||||
"transformers/module/system.ts",
|
||||
"transformers/module/module.ts",
|
||||
"transformer.ts",
|
||||
"sourcemap.ts",
|
||||
"comments.ts",
|
||||
|
||||
@ -54,6 +54,11 @@ namespace ts {
|
||||
const body = (<ModuleDeclaration>node).body;
|
||||
return body ? getModuleInstanceState(body) : ModuleInstanceState.Instantiated;
|
||||
}
|
||||
// Only jsdoc typedef definition can exist in jsdoc namespace, and it should
|
||||
// be considered the same as type alias
|
||||
else if (node.kind === SyntaxKind.Identifier && (<Identifier>node).isInJSDocNamespace) {
|
||||
return ModuleInstanceState.NonInstantiated;
|
||||
}
|
||||
else {
|
||||
return ModuleInstanceState.Instantiated;
|
||||
}
|
||||
@ -429,7 +434,11 @@ namespace ts {
|
||||
// during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation
|
||||
// and this case is specially handled. Module augmentations should only be merged with original module definition
|
||||
// and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed.
|
||||
if (!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) {
|
||||
const isJSDocTypedefInJSDocNamespace = node.kind === SyntaxKind.JSDocTypedefTag &&
|
||||
node.name &&
|
||||
node.name.kind === SyntaxKind.Identifier &&
|
||||
(<Identifier>node.name).isInJSDocNamespace;
|
||||
if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypedefInJSDocNamespace) {
|
||||
const exportKind =
|
||||
(symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) |
|
||||
(symbolFlags & SymbolFlags.Type ? SymbolFlags.ExportType : 0) |
|
||||
@ -490,8 +499,8 @@ namespace ts {
|
||||
const saveReturnTarget = currentReturnTarget;
|
||||
const saveActiveLabels = activeLabels;
|
||||
const saveHasExplicitReturn = hasExplicitReturn;
|
||||
const isIIFE = containerFlags & ContainerFlags.IsFunctionExpression && !!getImmediatelyInvokedFunctionExpression(node);
|
||||
// An IIFE is considered part of the containing control flow. Return statements behave
|
||||
const isIIFE = containerFlags & ContainerFlags.IsFunctionExpression && !hasModifier(node, ModifierFlags.Async) && !!getImmediatelyInvokedFunctionExpression(node);
|
||||
// A non-async IIFE is considered part of the containing control flow. Return statements behave
|
||||
// similarly to break statements that exit to a label just past the statement body.
|
||||
if (isIIFE) {
|
||||
currentReturnTarget = createBranchLabel();
|
||||
@ -883,8 +892,13 @@ namespace ts {
|
||||
|
||||
function bindDoStatement(node: DoStatement): void {
|
||||
const preDoLabel = createLoopLabel();
|
||||
const preConditionLabel = createBranchLabel();
|
||||
const postDoLabel = createBranchLabel();
|
||||
const enclosingLabeledStatement = node.parent.kind === SyntaxKind.LabeledStatement
|
||||
? lastOrUndefined(activeLabels)
|
||||
: undefined;
|
||||
// if do statement is wrapped in labeled statement then target labels for break/continue with or without
|
||||
// label should be the same
|
||||
const preConditionLabel = enclosingLabeledStatement ? enclosingLabeledStatement.continueTarget : createBranchLabel();
|
||||
const postDoLabel = enclosingLabeledStatement ? enclosingLabeledStatement.breakTarget : createBranchLabel();
|
||||
addAntecedent(preDoLabel, currentFlow);
|
||||
currentFlow = preDoLabel;
|
||||
bindIterativeStatement(node.statement, postDoLabel, preConditionLabel);
|
||||
@ -1007,7 +1021,7 @@ namespace ts {
|
||||
currentFlow = finishFlowLabel(preFinallyLabel);
|
||||
bind(node.finallyBlock);
|
||||
// if flow after finally is unreachable - keep it
|
||||
// otherwise check if flows after try and after catch are unreachable
|
||||
// otherwise check if flows after try and after catch are unreachable
|
||||
// if yes - convert current flow to unreachable
|
||||
// i.e.
|
||||
// try { return "1" } finally { console.log(1); }
|
||||
@ -1102,8 +1116,11 @@ namespace ts {
|
||||
if (!activeLabel.referenced && !options.allowUnusedLabels) {
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(node.label, Diagnostics.Unused_label));
|
||||
}
|
||||
addAntecedent(postStatementLabel, currentFlow);
|
||||
currentFlow = finishFlowLabel(postStatementLabel);
|
||||
if (!node.statement || node.statement.kind !== SyntaxKind.DoStatement) {
|
||||
// do statement sets current flow inside bindDoStatement
|
||||
addAntecedent(postStatementLabel, currentFlow);
|
||||
currentFlow = finishFlowLabel(postStatementLabel);
|
||||
}
|
||||
}
|
||||
|
||||
function bindDestructuringTargetFlow(node: Expression) {
|
||||
@ -1828,6 +1845,17 @@ namespace ts {
|
||||
switch (node.kind) {
|
||||
/* Strict mode checks */
|
||||
case SyntaxKind.Identifier:
|
||||
// for typedef type names with namespaces, bind the new jsdoc type symbol here
|
||||
// because it requires all containing namespaces to be in effect, namely the
|
||||
// current "blockScopeContainer" needs to be set to its immediate namespace parent.
|
||||
if ((<Identifier>node).isInJSDocNamespace) {
|
||||
let parentNode = node.parent;
|
||||
while (parentNode && parentNode.kind !== SyntaxKind.JSDocTypedefTag) {
|
||||
parentNode = parentNode.parent;
|
||||
}
|
||||
bindBlockScopedDeclaration(<Declaration>parentNode, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ThisKeyword:
|
||||
if (currentFlow && (isExpression(node) || parent.kind === SyntaxKind.ShorthandPropertyAssignment)) {
|
||||
node.flowNode = currentFlow;
|
||||
@ -1951,6 +1979,10 @@ namespace ts {
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
if (!(<JSDocTypedefTag>node).fullName || (<JSDocTypedefTag>node).fullName.kind === SyntaxKind.Identifier) {
|
||||
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
@ -2421,6 +2453,9 @@ namespace ts {
|
||||
case SyntaxKind.HeritageClause:
|
||||
return computeHeritageClause(<HeritageClause>node, subtreeFlags);
|
||||
|
||||
case SyntaxKind.CatchClause:
|
||||
return computeCatchClause(<CatchClause>node, subtreeFlags);
|
||||
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return computeExpressionWithTypeArguments(<ExpressionWithTypeArguments>node, subtreeFlags);
|
||||
|
||||
@ -2507,7 +2542,7 @@ namespace ts {
|
||||
&& (leftKind === SyntaxKind.ObjectLiteralExpression
|
||||
|| leftKind === SyntaxKind.ArrayLiteralExpression)) {
|
||||
// Destructuring assignments are ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.DestructuringAssignment;
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment;
|
||||
}
|
||||
else if (operatorTokenKind === SyntaxKind.AsteriskAsteriskToken
|
||||
|| operatorTokenKind === SyntaxKind.AsteriskAsteriskEqualsToken) {
|
||||
@ -2588,9 +2623,9 @@ namespace ts {
|
||||
|
||||
// A class with a parameter property assignment, property initializer, or decorator is
|
||||
// TypeScript syntax.
|
||||
// An exported declaration may be TypeScript syntax.
|
||||
// An exported declaration may be TypeScript syntax, but is handled by the visitor
|
||||
// for a namespace declaration.
|
||||
if ((subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask)
|
||||
|| (modifierFlags & ModifierFlags.Export)
|
||||
|| node.typeParameters) {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
@ -2650,6 +2685,17 @@ namespace ts {
|
||||
return transformFlags & ~TransformFlags.NodeExcludes;
|
||||
}
|
||||
|
||||
function computeCatchClause(node: CatchClause, subtreeFlags: TransformFlags) {
|
||||
let transformFlags = subtreeFlags;
|
||||
|
||||
if (node.variableDeclaration && isBindingPattern(node.variableDeclaration.name)) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
return transformFlags & ~TransformFlags.NodeExcludes;
|
||||
}
|
||||
|
||||
function computeExpressionWithTypeArguments(node: ExpressionWithTypeArguments, subtreeFlags: TransformFlags) {
|
||||
// An ExpressionWithTypeArguments is ES6 syntax, as it is used in the
|
||||
// extends clause of a class.
|
||||
@ -2749,11 +2795,6 @@ namespace ts {
|
||||
else {
|
||||
transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion;
|
||||
|
||||
// If a FunctionDeclaration is exported, then it is either ES6 or TypeScript syntax.
|
||||
if (modifierFlags & ModifierFlags.Export) {
|
||||
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.AssertES2015;
|
||||
}
|
||||
|
||||
// TypeScript-specific modifiers, type parameters, and type annotations are TypeScript
|
||||
// syntax.
|
||||
if (modifierFlags & ModifierFlags.TypeScriptModifier
|
||||
@ -2895,11 +2936,6 @@ namespace ts {
|
||||
else {
|
||||
transformFlags = subtreeFlags;
|
||||
|
||||
// If a VariableStatement is exported, then it is either ES6 or TypeScript syntax.
|
||||
if (modifierFlags & ModifierFlags.Export) {
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
if (declarationListTransformFlags & TransformFlags.ContainsBindingPattern) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
@ -3016,12 +3052,6 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertJsx;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExportKeyword:
|
||||
// This node is both ES6 and TypeScript syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.AssertTypeScript;
|
||||
break;
|
||||
|
||||
case SyntaxKind.DefaultKeyword:
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
case SyntaxKind.TemplateHead:
|
||||
case SyntaxKind.TemplateMiddle:
|
||||
@ -3030,6 +3060,7 @@ namespace ts {
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
case SyntaxKind.StaticKeyword:
|
||||
// These nodes are ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
break;
|
||||
|
||||
@ -139,6 +139,11 @@ namespace ts {
|
||||
const stringOrNumberType = getUnionType([stringType, numberType]);
|
||||
|
||||
const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
|
||||
const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral | SymbolFlags.Transient, "__type");
|
||||
emptyTypeLiteralSymbol.members = createMap<Symbol>();
|
||||
const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
|
||||
const emptyGenericType = <GenericType><ObjectType>createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
emptyGenericType.instantiations = createMap<TypeReference>();
|
||||
|
||||
@ -494,7 +499,7 @@ namespace ts {
|
||||
const moduleNotFoundError = !isInAmbientContext(moduleName.parent.parent)
|
||||
? Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found
|
||||
: undefined;
|
||||
let mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError);
|
||||
let mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, /*isForAugmentation*/ true);
|
||||
if (!mainModule) {
|
||||
return;
|
||||
}
|
||||
@ -1347,16 +1352,16 @@ namespace ts {
|
||||
return resolveExternalModuleNameWorker(location, moduleReferenceExpression, Diagnostics.Cannot_find_module_0);
|
||||
}
|
||||
|
||||
function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage): Symbol {
|
||||
function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage, isForAugmentation = false): Symbol {
|
||||
if (moduleReferenceExpression.kind !== SyntaxKind.StringLiteral) {
|
||||
return;
|
||||
}
|
||||
|
||||
const moduleReferenceLiteral = <LiteralExpression>moduleReferenceExpression;
|
||||
return resolveExternalModule(location, moduleReferenceLiteral.text, moduleNotFoundError, moduleReferenceLiteral);
|
||||
return resolveExternalModule(location, moduleReferenceLiteral.text, moduleNotFoundError, moduleReferenceLiteral, isForAugmentation);
|
||||
}
|
||||
|
||||
function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage, errorNode: Node): Symbol {
|
||||
function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage, errorNode: Node, isForAugmentation = false): Symbol {
|
||||
// Module names are escaped in our symbol table. However, string literal values aren't.
|
||||
// Escape the name in the "require(...)" clause to ensure we find the right symbol.
|
||||
const moduleName = escapeIdentifier(moduleReference);
|
||||
@ -1366,8 +1371,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
const isRelative = isExternalModuleNameRelative(moduleName);
|
||||
const quotedName = '"' + moduleName + '"';
|
||||
if (!isRelative) {
|
||||
const symbol = getSymbol(globals, '"' + moduleName + '"', SymbolFlags.ValueModule);
|
||||
const symbol = getSymbol(globals, quotedName, SymbolFlags.ValueModule);
|
||||
if (symbol) {
|
||||
// merged symbol is module declaration symbol combined with all augmentations
|
||||
return getMergedSymbol(symbol);
|
||||
@ -1375,7 +1381,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
const resolvedModule = getResolvedModule(getSourceFileOfNode(location), moduleReference);
|
||||
const sourceFile = resolvedModule && host.getSourceFile(resolvedModule.resolvedFileName);
|
||||
const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule);
|
||||
const sourceFile = resolvedModule && !resolutionDiagnostic && host.getSourceFile(resolvedModule.resolvedFileName);
|
||||
if (sourceFile) {
|
||||
if (sourceFile.symbol) {
|
||||
// merged symbol is module declaration symbol combined with all augmentations
|
||||
@ -1395,15 +1402,37 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// May be an untyped module. If so, ignore resolutionDiagnostic.
|
||||
if (!isRelative && resolvedModule && !extensionIsTypeScript(resolvedModule.extension)) {
|
||||
if (isForAugmentation) {
|
||||
Debug.assert(!!moduleNotFoundError);
|
||||
const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented;
|
||||
error(errorNode, diag, moduleName, resolvedModule.resolvedFileName);
|
||||
}
|
||||
else if (compilerOptions.noImplicitAny && moduleNotFoundError) {
|
||||
error(errorNode,
|
||||
Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type,
|
||||
moduleReference,
|
||||
resolvedModule.resolvedFileName);
|
||||
}
|
||||
// Failed imports and untyped modules are both treated in an untyped manner; only difference is whether we give a diagnostic first.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (moduleNotFoundError) {
|
||||
// report errors only if it was requested
|
||||
const tsExtension = tryExtractTypeScriptExtension(moduleName);
|
||||
if (tsExtension) {
|
||||
const diag = Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead;
|
||||
error(errorNode, diag, tsExtension, removeExtension(moduleName, tsExtension));
|
||||
if (resolutionDiagnostic) {
|
||||
error(errorNode, resolutionDiagnostic, moduleName, resolvedModule.resolvedFileName);
|
||||
}
|
||||
else {
|
||||
error(errorNode, moduleNotFoundError, moduleName);
|
||||
const tsExtension = tryExtractTypeScriptExtension(moduleName);
|
||||
if (tsExtension) {
|
||||
const diag = Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead;
|
||||
error(errorNode, diag, tsExtension, removeExtension(moduleName, tsExtension));
|
||||
}
|
||||
else {
|
||||
error(errorNode, moduleNotFoundError, moduleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
@ -3320,7 +3349,7 @@ namespace ts {
|
||||
}
|
||||
// Handle catch clause variables
|
||||
const declaration = symbol.valueDeclaration;
|
||||
if (declaration.parent.kind === SyntaxKind.CatchClause) {
|
||||
if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) {
|
||||
return links.type = anyType;
|
||||
}
|
||||
// Handle export default expressions
|
||||
@ -3468,7 +3497,7 @@ namespace ts {
|
||||
function getTypeOfFuncClassEnumModule(symbol: Symbol): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.type) {
|
||||
if (symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && isShorthandAmbientModuleSymbol(symbol)) {
|
||||
if (symbol.flags & SymbolFlags.Module && isShorthandAmbientModuleSymbol(symbol)) {
|
||||
links.type = anyType;
|
||||
}
|
||||
else {
|
||||
@ -5795,10 +5824,15 @@ namespace ts {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
// Deferred resolution of members is handled by resolveObjectTypeMembers
|
||||
const type = createObjectType(ObjectFlags.Anonymous, node.symbol);
|
||||
type.aliasSymbol = aliasSymbol;
|
||||
type.aliasTypeArguments = aliasTypeArguments;
|
||||
links.resolvedType = type;
|
||||
if (isEmpty(node.symbol.members) && !aliasSymbol && !aliasTypeArguments) {
|
||||
links.resolvedType = emptyTypeLiteralType;
|
||||
}
|
||||
else {
|
||||
const type = createObjectType(ObjectFlags.Anonymous, node.symbol);
|
||||
type.aliasSymbol = aliasSymbol;
|
||||
type.aliasTypeArguments = aliasTypeArguments;
|
||||
links.resolvedType = type;
|
||||
}
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
@ -6139,6 +6173,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isSymbolInScopeOfMappedTypeParameter(symbol: Symbol, mapper: TypeMapper) {
|
||||
if (!(symbol.declarations && symbol.declarations.length)) {
|
||||
return false;
|
||||
}
|
||||
const mappedTypes = mapper.mappedTypes;
|
||||
// Starting with the parent of the symbol's declaration, check if the mapper maps any of
|
||||
// the type parameters introduced by enclosing declarations. We just pick the first
|
||||
@ -10447,16 +10484,32 @@ namespace ts {
|
||||
|
||||
// If the given type is an object or union type, if that type has a single signature, and if
|
||||
// that signature is non-generic, return the signature. Otherwise return undefined.
|
||||
function getNonGenericSignature(type: Type): Signature {
|
||||
function getNonGenericSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature {
|
||||
const signatures = getSignaturesOfStructuredType(type, SignatureKind.Call);
|
||||
if (signatures.length === 1) {
|
||||
const signature = signatures[0];
|
||||
if (!signature.typeParameters) {
|
||||
if (!signature.typeParameters && !isAritySmaller(signature, node)) {
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** If the contextual signature has fewer parameters than the function expression, do not use it */
|
||||
function isAritySmaller(signature: Signature, target: FunctionExpression | ArrowFunction | MethodDeclaration) {
|
||||
let targetParameterCount = 0;
|
||||
for (; targetParameterCount < target.parameters.length; targetParameterCount++) {
|
||||
const param = target.parameters[targetParameterCount];
|
||||
if (param.initializer || param.questionToken || param.dotDotDotToken || isJSDocOptionalParameter(param)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (target.parameters.length && parameterIsThisKeyword(target.parameters[0])) {
|
||||
targetParameterCount--;
|
||||
}
|
||||
const sourceLength = signature.hasRestParameter ? Number.MAX_VALUE : signature.parameters.length;
|
||||
return sourceLength < targetParameterCount;
|
||||
}
|
||||
|
||||
function isFunctionExpressionOrArrowFunction(node: Node): node is FunctionExpression | ArrowFunction {
|
||||
return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction;
|
||||
}
|
||||
@ -10486,12 +10539,12 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
if (!(type.flags & TypeFlags.Union)) {
|
||||
return getNonGenericSignature(type);
|
||||
return getNonGenericSignature(type, node);
|
||||
}
|
||||
let signatureList: Signature[];
|
||||
const types = (<UnionType>type).types;
|
||||
for (const current of types) {
|
||||
const signature = getNonGenericSignature(current);
|
||||
const signature = getNonGenericSignature(current, node);
|
||||
if (signature) {
|
||||
if (!signatureList) {
|
||||
// This signature will contribute to contextual union signature
|
||||
@ -12937,16 +12990,41 @@ namespace ts {
|
||||
}
|
||||
|
||||
// In JavaScript files, calls to any identifier 'require' are treated as external module imports
|
||||
if (isInJavaScriptFile(node) &&
|
||||
isRequireCall(node, /*checkArgumentIsStringLiteral*/true) &&
|
||||
// Make sure require is not a local function
|
||||
!resolveName(node.expression, (<Identifier>node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)) {
|
||||
if (isInJavaScriptFile(node) && isCommonJsRequire(node)) {
|
||||
return resolveExternalModuleTypeByLiteral(<StringLiteral>node.arguments[0]);
|
||||
}
|
||||
|
||||
return getReturnTypeOfSignature(signature);
|
||||
}
|
||||
|
||||
function isCommonJsRequire(node: Node) {
|
||||
if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) {
|
||||
return false;
|
||||
}
|
||||
// Make sure require is not a local function
|
||||
const resolvedRequire = resolveName(node.expression, (<Identifier>node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
|
||||
if (!resolvedRequire) {
|
||||
// project does not contain symbol named 'require' - assume commonjs require
|
||||
return true;
|
||||
}
|
||||
// project includes symbol named 'require' - make sure that it it ambient and local non-alias
|
||||
if (resolvedRequire.flags & SymbolFlags.Alias) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const targetDeclarationKind = resolvedRequire.flags & SymbolFlags.Function
|
||||
? SyntaxKind.FunctionDeclaration
|
||||
: resolvedRequire.flags & SymbolFlags.Variable
|
||||
? SyntaxKind.VariableDeclaration
|
||||
: SyntaxKind.Unknown;
|
||||
if (targetDeclarationKind !== SyntaxKind.Unknown) {
|
||||
const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind);
|
||||
// function/variable declaration should be ambient
|
||||
return isInAmbientContext(decl);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type {
|
||||
return getReturnTypeOfSignature(getResolvedSignature(node));
|
||||
}
|
||||
@ -15551,31 +15629,24 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the return type of an async function to ensure it is a compatible
|
||||
* Promise implementation.
|
||||
* @param node The signature to check
|
||||
* @param returnType The return type for the function
|
||||
* @remarks
|
||||
* This checks that an async function has a valid Promise-compatible return type,
|
||||
* and returns the *awaited type* of the promise. An async function has a valid
|
||||
* Promise-compatible return type if the resolved value of the return type has a
|
||||
* construct signature that takes in an `initializer` function that in turn supplies
|
||||
* a `resolve` function as one of its arguments and results in an object with a
|
||||
* callable `then` signature.
|
||||
*/
|
||||
* Checks the return type of an async function to ensure it is a compatible
|
||||
* Promise implementation.
|
||||
*
|
||||
* This checks that an async function has a valid Promise-compatible return type,
|
||||
* and returns the *awaited type* of the promise. An async function has a valid
|
||||
* Promise-compatible return type if the resolved value of the return type has a
|
||||
* construct signature that takes in an `initializer` function that in turn supplies
|
||||
* a `resolve` function as one of its arguments and results in an object with a
|
||||
* callable `then` signature.
|
||||
*
|
||||
* @param node The signature to check
|
||||
*/
|
||||
function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
|
||||
if (languageVersion >= ScriptTarget.ES2015) {
|
||||
const returnType = getTypeFromTypeNode(node.type);
|
||||
return checkCorrectPromiseType(returnType, node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
|
||||
}
|
||||
|
||||
const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
|
||||
if (globalPromiseConstructorLikeType === emptyObjectType) {
|
||||
// If we couldn't resolve the global PromiseConstructorLike type we cannot verify
|
||||
// compatibility with __awaiter.
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
// As part of our emit for an async function, we will need to emit the entity name of
|
||||
// the return type annotation as an expression. To meet the necessary runtime semantics
|
||||
// for __awaiter, we must also check that the type of the declaration (e.g. the static
|
||||
@ -15600,42 +15671,56 @@ namespace ts {
|
||||
// then<U>(...): Promise<U>;
|
||||
// }
|
||||
//
|
||||
// When we get the type of the `Promise` symbol here, we get the type of the static
|
||||
// side of the `Promise` class, which would be `{ new <T>(...): Promise<T> }`.
|
||||
|
||||
// Always mark the type node as referenced if it points to a value
|
||||
markTypeNodeAsReferenced(node.type);
|
||||
|
||||
const promiseConstructorName = getEntityNameFromTypeNode(node.type);
|
||||
const promiseType = getTypeFromTypeNode(node.type);
|
||||
if (promiseType === unknownType && compilerOptions.isolatedModules) {
|
||||
// If we are compiling with isolatedModules, we may not be able to resolve the
|
||||
// type as a value. As such, we will just return unknownType;
|
||||
if (promiseType === unknownType) {
|
||||
if (!compilerOptions.isolatedModules) {
|
||||
if (promiseConstructorName) {
|
||||
error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
|
||||
}
|
||||
else {
|
||||
error(node.type, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
|
||||
}
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
const promiseConstructor = getNodeLinks(node.type).resolvedSymbol;
|
||||
if (!promiseConstructor || !symbolIsValue(promiseConstructor)) {
|
||||
// try to fall back to global promise type.
|
||||
const typeName = promiseConstructor
|
||||
? symbolToString(promiseConstructor)
|
||||
: typeToString(promiseType);
|
||||
return checkCorrectPromiseType(promiseType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName);
|
||||
if (promiseConstructorName === undefined) {
|
||||
error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(promiseType));
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
// If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced.
|
||||
checkReturnTypeAnnotationAsExpression(node);
|
||||
const promiseConstructorSymbol = resolveEntityName(promiseConstructorName, SymbolFlags.Value, /*ignoreErrors*/ true);
|
||||
const promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) : unknownType;
|
||||
if (promiseConstructorType === unknownType) {
|
||||
error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
// Validate the promise constructor type.
|
||||
const promiseConstructorType = getTypeOfSymbol(promiseConstructor);
|
||||
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
|
||||
const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
|
||||
if (globalPromiseConstructorLikeType === emptyObjectType) {
|
||||
// If we couldn't resolve the global PromiseConstructorLike type we cannot verify
|
||||
// compatibility with __awaiter.
|
||||
error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type,
|
||||
Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value)) {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
// Verify there is no local declaration that could collide with the promise constructor.
|
||||
const promiseName = getEntityNameFromTypeNode(node.type);
|
||||
const promiseNameOrNamespaceRoot = getFirstIdentifier(promiseName);
|
||||
const rootSymbol = getSymbol(node.locals, promiseNameOrNamespaceRoot.text, SymbolFlags.Value);
|
||||
if (rootSymbol) {
|
||||
error(rootSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions,
|
||||
promiseNameOrNamespaceRoot.text,
|
||||
getFullyQualifiedName(promiseConstructor));
|
||||
const rootName = promiseConstructorName && getFirstIdentifier(promiseConstructorName);
|
||||
const collidingSymbol = getSymbol(node.locals, rootName.text, SymbolFlags.Value);
|
||||
if (collidingSymbol) {
|
||||
error(collidingSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions,
|
||||
rootName.text,
|
||||
entityNameToString(promiseConstructorName));
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
@ -15693,44 +15778,19 @@ namespace ts {
|
||||
errorInfo);
|
||||
}
|
||||
|
||||
/** Checks a type reference node as an expression. */
|
||||
function checkTypeNodeAsExpression(node: TypeNode) {
|
||||
// When we are emitting type metadata for decorators, we need to try to check the type
|
||||
// as if it were an expression so that we can emit the type in a value position when we
|
||||
// serialize the type metadata.
|
||||
if (node && node.kind === SyntaxKind.TypeReference) {
|
||||
const root = getFirstIdentifier((<TypeReferenceNode>node).typeName);
|
||||
const meaning = root.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;
|
||||
// Resolve type so we know which symbol is referenced
|
||||
const rootSymbol = resolveName(root, root.text, meaning | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
|
||||
// Resolved symbol is alias
|
||||
if (rootSymbol && rootSymbol.flags & SymbolFlags.Alias) {
|
||||
const aliasTarget = resolveAlias(rootSymbol);
|
||||
// If alias has value symbol - mark alias as referenced
|
||||
if (aliasTarget.flags & SymbolFlags.Value && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) {
|
||||
markAliasSymbolAsReferenced(rootSymbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the type annotation of an accessor declaration or property declaration as
|
||||
* an expression if it is a type reference to a type with a value declaration.
|
||||
*/
|
||||
function checkTypeAnnotationAsExpression(node: VariableLikeDeclaration) {
|
||||
checkTypeNodeAsExpression((<PropertyDeclaration>node).type);
|
||||
}
|
||||
|
||||
function checkReturnTypeAnnotationAsExpression(node: FunctionLikeDeclaration) {
|
||||
checkTypeNodeAsExpression(node.type);
|
||||
}
|
||||
|
||||
/** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */
|
||||
function checkParameterTypeAnnotationsAsExpressions(node: FunctionLikeDeclaration) {
|
||||
// ensure all type annotations with a value declaration are checked as an expression
|
||||
for (const parameter of node.parameters) {
|
||||
checkTypeAnnotationAsExpression(parameter);
|
||||
* If a TypeNode can be resolved to a value symbol imported from an external module, it is
|
||||
* marked as referenced to prevent import elision.
|
||||
*/
|
||||
function markTypeNodeAsReferenced(node: TypeNode) {
|
||||
const typeName = node && getEntityNameFromTypeNode(node);
|
||||
const rootName = typeName && getFirstIdentifier(typeName);
|
||||
const rootSymbol = rootName && resolveName(rootName, rootName.text, (typeName.kind === SyntaxKind.Identifier ? SymbolFlags.Type : SymbolFlags.Namespace) | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
|
||||
if (rootSymbol
|
||||
&& rootSymbol.flags & SymbolFlags.Alias
|
||||
&& symbolIsValue(rootSymbol)
|
||||
&& !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) {
|
||||
markAliasSymbolAsReferenced(rootSymbol);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15756,20 +15816,25 @@ namespace ts {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
const constructor = getFirstConstructorWithBody(<ClassDeclaration>node);
|
||||
if (constructor) {
|
||||
checkParameterTypeAnnotationsAsExpressions(constructor);
|
||||
for (const parameter of constructor.parameters) {
|
||||
markTypeNodeAsReferenced(parameter.type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
checkParameterTypeAnnotationsAsExpressions(<FunctionLikeDeclaration>node);
|
||||
checkReturnTypeAnnotationAsExpression(<FunctionLikeDeclaration>node);
|
||||
for (const parameter of (<FunctionLikeDeclaration>node).parameters) {
|
||||
markTypeNodeAsReferenced(parameter.type);
|
||||
}
|
||||
|
||||
markTypeNodeAsReferenced((<FunctionLikeDeclaration>node).type);
|
||||
break;
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
checkTypeAnnotationAsExpression(<PropertyDeclaration | ParameterDeclaration>node);
|
||||
markTypeNodeAsReferenced((<PropertyDeclaration | ParameterDeclaration>node).type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -15915,12 +15980,12 @@ namespace ts {
|
||||
for (const key in node.locals) {
|
||||
const local = node.locals[key];
|
||||
if (!local.isReferenced) {
|
||||
if (local.valueDeclaration && local.valueDeclaration.kind === SyntaxKind.Parameter) {
|
||||
const parameter = <ParameterDeclaration>local.valueDeclaration;
|
||||
if (local.valueDeclaration && getRootDeclaration(local.valueDeclaration).kind === SyntaxKind.Parameter) {
|
||||
const parameter = <ParameterDeclaration>getRootDeclaration(local.valueDeclaration);
|
||||
if (compilerOptions.noUnusedParameters &&
|
||||
!isParameterPropertyDeclaration(parameter) &&
|
||||
!parameterIsThisKeyword(parameter) &&
|
||||
!parameterNameStartsWithUnderscore(parameter)) {
|
||||
!parameterNameStartsWithUnderscore(local.valueDeclaration.name)) {
|
||||
error(local.valueDeclaration.name, Diagnostics._0_is_declared_but_never_used, local.name);
|
||||
}
|
||||
}
|
||||
@ -15944,8 +16009,8 @@ namespace ts {
|
||||
error(node, Diagnostics._0_is_declared_but_never_used, name);
|
||||
}
|
||||
|
||||
function parameterNameStartsWithUnderscore(parameter: ParameterDeclaration) {
|
||||
return parameter.name && isIdentifierThatStartsWithUnderScore(parameter.name);
|
||||
function parameterNameStartsWithUnderscore(parameterName: DeclarationName) {
|
||||
return parameterName && isIdentifierThatStartsWithUnderScore(parameterName);
|
||||
}
|
||||
|
||||
function isIdentifierThatStartsWithUnderScore(node: Node) {
|
||||
@ -17009,22 +17074,20 @@ namespace ts {
|
||||
if (catchClause) {
|
||||
// Grammar checking
|
||||
if (catchClause.variableDeclaration) {
|
||||
if (catchClause.variableDeclaration.name.kind !== SyntaxKind.Identifier) {
|
||||
grammarErrorOnFirstToken(catchClause.variableDeclaration.name, Diagnostics.Catch_clause_variable_name_must_be_an_identifier);
|
||||
}
|
||||
else if (catchClause.variableDeclaration.type) {
|
||||
if (catchClause.variableDeclaration.type) {
|
||||
grammarErrorOnFirstToken(catchClause.variableDeclaration.type, Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation);
|
||||
}
|
||||
else if (catchClause.variableDeclaration.initializer) {
|
||||
grammarErrorOnFirstToken(catchClause.variableDeclaration.initializer, Diagnostics.Catch_clause_variable_cannot_have_an_initializer);
|
||||
}
|
||||
else {
|
||||
const identifierName = (<Identifier>catchClause.variableDeclaration.name).text;
|
||||
const locals = catchClause.block.locals;
|
||||
if (locals) {
|
||||
const localSymbol = locals[identifierName];
|
||||
if (localSymbol && (localSymbol.flags & SymbolFlags.BlockScopedVariable) !== 0) {
|
||||
grammarErrorOnNode(localSymbol.valueDeclaration, Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, identifierName);
|
||||
const blockLocals = catchClause.block.locals;
|
||||
if (blockLocals) {
|
||||
for (const caughtName in catchClause.locals) {
|
||||
const blockLocal = blockLocals[caughtName];
|
||||
if (blockLocal && (blockLocal.flags & SymbolFlags.BlockScopedVariable) !== 0) {
|
||||
grammarErrorOnNode(blockLocal.valueDeclaration, Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17292,7 +17355,7 @@ namespace ts {
|
||||
if (declaration && getModifierFlags(declaration) & ModifierFlags.Private) {
|
||||
const typeClassDeclaration = <ClassLikeDeclaration>getClassLikeDeclarationOfSymbol(type.symbol);
|
||||
if (!isNodeWithinClass(node, typeClassDeclaration)) {
|
||||
error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, (<Identifier>node.expression).text);
|
||||
error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18484,9 +18547,33 @@ namespace ts {
|
||||
function getDiagnosticsWorker(sourceFile: SourceFile): Diagnostic[] {
|
||||
throwIfNonDiagnosticsProducing();
|
||||
if (sourceFile) {
|
||||
// Some global diagnostics are deferred until they are needed and
|
||||
// may not be reported in the firt call to getGlobalDiagnostics.
|
||||
// We should catch these changes and report them.
|
||||
const previousGlobalDiagnostics = diagnostics.getGlobalDiagnostics();
|
||||
const previousGlobalDiagnosticsSize = previousGlobalDiagnostics.length;
|
||||
|
||||
checkSourceFile(sourceFile);
|
||||
return diagnostics.getDiagnostics(sourceFile.fileName);
|
||||
|
||||
const semanticDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName);
|
||||
const currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics();
|
||||
if (currentGlobalDiagnostics !== previousGlobalDiagnostics) {
|
||||
// If the arrays are not the same reference, new diagnostics were added.
|
||||
const deferredGlobalDiagnostics = relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, compareDiagnostics);
|
||||
return concatenate(deferredGlobalDiagnostics, semanticDiagnostics);
|
||||
}
|
||||
else if (previousGlobalDiagnosticsSize === 0 && currentGlobalDiagnostics.length > 0) {
|
||||
// If the arrays are the same reference, but the length has changed, a single
|
||||
// new diagnostic was added as DiagnosticCollection attempts to reuse the
|
||||
// same array.
|
||||
return concatenate(currentGlobalDiagnostics, semanticDiagnostics);
|
||||
}
|
||||
|
||||
return semanticDiagnostics;
|
||||
}
|
||||
|
||||
// Global diagnostics are always added when a file is not provided to
|
||||
// getDiagnostics
|
||||
forEach(host.getSourceFiles(), checkSourceFile);
|
||||
return diagnostics.getDiagnostics();
|
||||
}
|
||||
@ -19566,6 +19653,10 @@ namespace ts {
|
||||
if (typeReferenceDirective) {
|
||||
(typeReferenceDirectives || (typeReferenceDirectives = [])).push(typeReferenceDirective);
|
||||
}
|
||||
else {
|
||||
// found at least one entry that does not originate from type reference directive
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
return typeReferenceDirectives;
|
||||
|
||||
@ -912,6 +912,9 @@ namespace ts {
|
||||
if (hasProperty(json, "files")) {
|
||||
if (isArray(json["files"])) {
|
||||
fileNames = <string[]>json["files"];
|
||||
if (fileNames.length === 0) {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "files", "Array"));
|
||||
@ -954,7 +957,18 @@ namespace ts {
|
||||
includeSpecs = ["**/*"];
|
||||
}
|
||||
|
||||
return matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors);
|
||||
const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors);
|
||||
|
||||
if (result.fileNames.length === 0 && !hasProperty(json, "files") && resolutionStack.length === 0) {
|
||||
errors.push(
|
||||
createCompilerDiagnostic(
|
||||
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
configFileName || "tsconfig.json",
|
||||
JSON.stringify(includeSpecs || []),
|
||||
JSON.stringify(excludeSpecs || [])));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -994,9 +1008,7 @@ namespace ts {
|
||||
function convertTypingOptionsFromJsonWorker(jsonOptions: any,
|
||||
basePath: string, errors: Diagnostic[], configFileName?: string): TypingOptions {
|
||||
|
||||
const options: TypingOptions = getBaseFileName(configFileName) === "jsconfig.json"
|
||||
? { enableAutoDiscovery: true, include: [], exclude: [] }
|
||||
: { enableAutoDiscovery: false, include: [], exclude: [] };
|
||||
const options: TypingOptions = { enableAutoDiscovery: getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] };
|
||||
convertOptionsFromJson(typingOptionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_typing_option_0, errors);
|
||||
return options;
|
||||
}
|
||||
@ -1249,12 +1261,13 @@ namespace ts {
|
||||
/**
|
||||
* Gets directories in a set of include patterns that should be watched for changes.
|
||||
*/
|
||||
function getWildcardDirectories(include: string[], exclude: string[], path: string, useCaseSensitiveFileNames: boolean) {
|
||||
function getWildcardDirectories(include: string[], exclude: string[], path: string, useCaseSensitiveFileNames: boolean): Map<WatchDirectoryFlags> {
|
||||
// We watch a directory recursively if it contains a wildcard anywhere in a directory segment
|
||||
// of the pattern:
|
||||
//
|
||||
// /a/b/**/d - Watch /a/b recursively to catch changes to any d in any subfolder recursively
|
||||
// /a/b/*/d - Watch /a/b recursively to catch any d in any immediate subfolder, even if a new subfolder is added
|
||||
// /a/b - Watch /a/b recursively to catch changes to anything in any recursive subfoler
|
||||
//
|
||||
// We watch a directory without recursion if it contains a wildcard in the file segment of
|
||||
// the pattern:
|
||||
@ -1267,15 +1280,14 @@ namespace ts {
|
||||
if (include !== undefined) {
|
||||
const recursiveKeys: string[] = [];
|
||||
for (const file of include) {
|
||||
const name = normalizePath(combinePaths(path, file));
|
||||
if (excludeRegex && excludeRegex.test(name)) {
|
||||
const spec = normalizePath(combinePaths(path, file));
|
||||
if (excludeRegex && excludeRegex.test(spec)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const match = wildcardDirectoryPattern.exec(name);
|
||||
const match = getWildcardDirectoryFromSpec(spec, useCaseSensitiveFileNames);
|
||||
if (match) {
|
||||
const key = useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase();
|
||||
const flags = watchRecursivePattern.test(name) ? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None;
|
||||
const { key, flags } = match;
|
||||
const existingFlags = wildcardDirectories[key];
|
||||
if (existingFlags === undefined || existingFlags < flags) {
|
||||
wildcardDirectories[key] = flags;
|
||||
@ -1299,6 +1311,20 @@ namespace ts {
|
||||
return wildcardDirectories;
|
||||
}
|
||||
|
||||
function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: boolean): { key: string, flags: WatchDirectoryFlags } | undefined {
|
||||
const match = wildcardDirectoryPattern.exec(spec);
|
||||
if (match) {
|
||||
return {
|
||||
key: useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase(),
|
||||
flags: watchRecursivePattern.test(spec) ? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None
|
||||
};
|
||||
}
|
||||
if (isImplicitGlob(spec)) {
|
||||
return { key: spec, flags: WatchDirectoryFlags.Recursive };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a literal or wildcard file has already been included that has a higher
|
||||
* extension priority.
|
||||
|
||||
@ -124,6 +124,13 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function zipWith<T, U>(arrayA: T[], arrayB: U[], callback: (a: T, b: U, index: number) => void): void {
|
||||
Debug.assert(arrayA.length === arrayB.length);
|
||||
for (let i = 0; i < arrayA.length; i++) {
|
||||
callback(arrayA[i], arrayB[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through `array` by index and performs the callback on each element of array until the callback
|
||||
* returns a falsey value, then returns false.
|
||||
@ -424,18 +431,23 @@ namespace ts {
|
||||
|
||||
export function some<T>(array: T[], predicate?: (value: T) => boolean): boolean {
|
||||
if (array) {
|
||||
for (const v of array) {
|
||||
if (!predicate || predicate(v)) {
|
||||
return true;
|
||||
if (predicate) {
|
||||
for (const v of array) {
|
||||
if (predicate(v)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return array.length > 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function concatenate<T>(array1: T[], array2: T[]): T[] {
|
||||
if (!array2 || !array2.length) return array1;
|
||||
if (!array1 || !array1.length) return array2;
|
||||
if (!some(array2)) return array1;
|
||||
if (!some(array1)) return array2;
|
||||
return [...array1, ...array2];
|
||||
}
|
||||
|
||||
@ -456,6 +468,44 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T>, array2: ReadonlyArray<T>, equaler?: (a: T, b: T) => boolean): boolean {
|
||||
if (!array1 || !array2) {
|
||||
return array1 === array2;
|
||||
}
|
||||
|
||||
if (array1.length !== array2.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
const equals = equaler ? equaler(array1[i], array2[i]) : array1[i] === array2[i];
|
||||
if (!equals) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function changesAffectModuleResolution(oldOptions: CompilerOptions, newOptions: CompilerOptions): boolean {
|
||||
return !oldOptions ||
|
||||
(oldOptions.module !== newOptions.module) ||
|
||||
(oldOptions.moduleResolution !== newOptions.moduleResolution) ||
|
||||
(oldOptions.noResolve !== newOptions.noResolve) ||
|
||||
(oldOptions.target !== newOptions.target) ||
|
||||
(oldOptions.noLib !== newOptions.noLib) ||
|
||||
(oldOptions.jsx !== newOptions.jsx) ||
|
||||
(oldOptions.allowJs !== newOptions.allowJs) ||
|
||||
(oldOptions.rootDir !== newOptions.rootDir) ||
|
||||
(oldOptions.configFilePath !== newOptions.configFilePath) ||
|
||||
(oldOptions.baseUrl !== newOptions.baseUrl) ||
|
||||
(oldOptions.maxNodeModuleJsDepth !== newOptions.maxNodeModuleJsDepth) ||
|
||||
!arrayIsEqualTo(oldOptions.lib, newOptions.lib) ||
|
||||
!arrayIsEqualTo(oldOptions.typeRoots, newOptions.typeRoots) ||
|
||||
!arrayIsEqualTo(oldOptions.rootDirs, newOptions.rootDirs) ||
|
||||
!equalOwnProperties(oldOptions.paths, newOptions.paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compacts an array, removing any falsey elements.
|
||||
*/
|
||||
@ -477,6 +527,27 @@ namespace ts {
|
||||
return result || array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the relative complement of `arrayA` with respect to `b`, returning the elements that
|
||||
* are not present in `arrayA` but are present in `arrayB`. Assumes both arrays are sorted
|
||||
* based on the provided comparer.
|
||||
*/
|
||||
export function relativeComplement<T>(arrayA: T[] | undefined, arrayB: T[] | undefined, comparer: (x: T, y: T) => Comparison = compareValues, offsetA = 0, offsetB = 0): T[] | undefined {
|
||||
if (!arrayB || !arrayA || arrayB.length === 0 || arrayA.length === 0) return arrayB;
|
||||
const result: T[] = [];
|
||||
outer: for (; offsetB < arrayB.length; offsetB++) {
|
||||
inner: for (; offsetA < arrayA.length; offsetA++) {
|
||||
switch (comparer(arrayB[offsetB], arrayA[offsetA])) {
|
||||
case Comparison.LessThan: break inner;
|
||||
case Comparison.EqualTo: continue outer;
|
||||
case Comparison.GreaterThan: continue inner;
|
||||
}
|
||||
}
|
||||
result.push(arrayB[offsetB]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function sum(array: any[], prop: string): number {
|
||||
let result = 0;
|
||||
for (const v of array) {
|
||||
@ -485,14 +556,35 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function addRange<T>(to: T[], from: T[]): void {
|
||||
if (to && from) {
|
||||
for (const v of from) {
|
||||
if (v !== undefined) {
|
||||
to.push(v);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Appends a value to an array, returning the array.
|
||||
*
|
||||
* @param to The array to which `value` is to be appended. If `to` is `undefined`, a new array
|
||||
* is created if `value` was appended.
|
||||
* @param value The value to append to the array. If `value` is `undefined`, nothing is
|
||||
* appended.
|
||||
*/
|
||||
export function append<T>(to: T[] | undefined, value: T | undefined): T[] | undefined {
|
||||
if (value === undefined) return to;
|
||||
if (to === undefined) to = [];
|
||||
to.push(value);
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a range of value to an array, returning the array.
|
||||
*
|
||||
* @param to The array to which `value` is to be appended. If `to` is `undefined`, a new array
|
||||
* is created if `value` was appended.
|
||||
* @param from The values to append to the array. If `from` is `undefined`, nothing is
|
||||
* appended. If an element of `from` is `undefined`, that element is not appended.
|
||||
*/
|
||||
export function addRange<T>(to: T[] | undefined, from: T[] | undefined): T[] | undefined {
|
||||
if (from === undefined) return to;
|
||||
for (const v of from) {
|
||||
to = append(to, v);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
export function rangeEquals<T>(array1: T[], array2: T[], pos: number, end: number) {
|
||||
@ -505,33 +597,43 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first element of an array if non-empty, `undefined` otherwise.
|
||||
*/
|
||||
export function firstOrUndefined<T>(array: T[]): T {
|
||||
return array && array.length > 0
|
||||
? array[0]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last element of an array if non-empty, `undefined` otherwise.
|
||||
*/
|
||||
export function lastOrUndefined<T>(array: T[]): T {
|
||||
return array && array.length > 0
|
||||
? array[array.length - 1]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the only element of an array if it contains only one element, `undefined` otherwise.
|
||||
*/
|
||||
export function singleOrUndefined<T>(array: T[]): T {
|
||||
return array && array.length === 1
|
||||
? array[0]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the only element of an array if it contains only one element; otheriwse, returns the
|
||||
* array.
|
||||
*/
|
||||
export function singleOrMany<T>(array: T[]): T | T[] {
|
||||
return array && array.length === 1
|
||||
? array[0]
|
||||
: array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last element of an array if non-empty, undefined otherwise.
|
||||
*/
|
||||
export function lastOrUndefined<T>(array: T[]): T {
|
||||
return array && array.length > 0
|
||||
? array[array.length - 1]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export function replaceElement<T>(array: T[], index: number, value: T): T[] {
|
||||
const result = array.slice(0);
|
||||
result[index] = value;
|
||||
@ -545,12 +647,12 @@ namespace ts {
|
||||
* @param array A sorted array whose first element must be no larger than number
|
||||
* @param number The value to be searched for in the array.
|
||||
*/
|
||||
export function binarySearch<T>(array: T[], value: T, comparer?: (v1: T, v2: T) => number): number {
|
||||
export function binarySearch<T>(array: T[], value: T, comparer?: (v1: T, v2: T) => number, offset?: number): number {
|
||||
if (!array || array.length === 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let low = 0;
|
||||
let low = offset || 0;
|
||||
let high = array.length - 1;
|
||||
comparer = comparer !== undefined
|
||||
? comparer
|
||||
@ -821,7 +923,7 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function extend<T1, T2>(first: T1 , second: T2): T1 & T2 {
|
||||
export function extend<T1, T2>(first: T1, second: T2): T1 & T2 {
|
||||
const result: T1 & T2 = <any>{};
|
||||
for (const id in second) if (hasOwnProperty.call(second, id)) {
|
||||
(result as any)[id] = (second as any)[id];
|
||||
@ -836,7 +938,7 @@ namespace ts {
|
||||
* Adds the value to an array of values associated with the key, and returns the array.
|
||||
* Creates the array if it does not already exist.
|
||||
*/
|
||||
export function multiMapAdd<V>(map: Map<V[]>, key: string, value: V): V[] {
|
||||
export function multiMapAdd<V>(map: Map<V[]>, key: string | number, value: V): V[] {
|
||||
const values = map[key];
|
||||
if (values) {
|
||||
values.push(value);
|
||||
@ -974,8 +1076,8 @@ namespace ts {
|
||||
Debug.assert(length >= 0, "length must be non-negative, is " + length);
|
||||
|
||||
if (file) {
|
||||
Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`);
|
||||
Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`);
|
||||
Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${start} > ${file.text.length}`);
|
||||
Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${end} > ${file.text.length}`);
|
||||
}
|
||||
|
||||
let text = getLocaleSpecificMessage(message);
|
||||
@ -1231,7 +1333,7 @@ namespace ts {
|
||||
*/
|
||||
export function getDirectoryPath(path: Path): Path;
|
||||
export function getDirectoryPath(path: string): string;
|
||||
export function getDirectoryPath(path: string): any {
|
||||
export function getDirectoryPath(path: string): string {
|
||||
return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(directorySeparator)));
|
||||
}
|
||||
|
||||
@ -1491,6 +1593,10 @@ namespace ts {
|
||||
return expectedPos >= 0 && str.indexOf(suffix, expectedPos) === expectedPos;
|
||||
}
|
||||
|
||||
export function hasExtension(fileName: string): boolean {
|
||||
return getBaseFileName(fileName).indexOf(".") >= 0;
|
||||
}
|
||||
|
||||
export function fileExtensionIs(path: string, extension: string): boolean {
|
||||
return path.length > extension.length && endsWith(path, extension);
|
||||
}
|
||||
@ -1525,7 +1631,7 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const replaceWildcardCharacter = usage === "files" ? replaceWildCardCharacterFiles : replaceWildCardCharacterOther;
|
||||
const replaceWildcardCharacter = usage === "files" ? replaceWildCardCharacterFiles : replaceWildCardCharacterOther;
|
||||
const singleAsteriskRegexFragment = usage === "files" ? singleAsteriskRegexFragmentFiles : singleAsteriskRegexFragmentOther;
|
||||
|
||||
/**
|
||||
@ -1536,73 +1642,21 @@ namespace ts {
|
||||
|
||||
let pattern = "";
|
||||
let hasWrittenSubpattern = false;
|
||||
spec: for (const spec of specs) {
|
||||
for (const spec of specs) {
|
||||
if (!spec) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let subpattern = "";
|
||||
let hasRecursiveDirectoryWildcard = false;
|
||||
let hasWrittenComponent = false;
|
||||
const components = getNormalizedPathComponents(spec, basePath);
|
||||
if (usage !== "exclude" && components[components.length - 1] === "**") {
|
||||
continue spec;
|
||||
}
|
||||
|
||||
// getNormalizedPathComponents includes the separator for the root component.
|
||||
// We need to remove to create our regex correctly.
|
||||
components[0] = removeTrailingDirectorySeparator(components[0]);
|
||||
|
||||
let optionalCount = 0;
|
||||
for (let component of components) {
|
||||
if (component === "**") {
|
||||
if (hasRecursiveDirectoryWildcard) {
|
||||
continue spec;
|
||||
}
|
||||
|
||||
subpattern += doubleAsteriskRegexFragment;
|
||||
hasRecursiveDirectoryWildcard = true;
|
||||
hasWrittenComponent = true;
|
||||
}
|
||||
else {
|
||||
if (usage === "directories") {
|
||||
subpattern += "(";
|
||||
optionalCount++;
|
||||
}
|
||||
|
||||
if (hasWrittenComponent) {
|
||||
subpattern += directorySeparator;
|
||||
}
|
||||
|
||||
if (usage !== "exclude") {
|
||||
// The * and ? wildcards should not match directories or files that start with . if they
|
||||
// appear first in a component. Dotted directories and files can be included explicitly
|
||||
// like so: **/.*/.*
|
||||
if (component.charCodeAt(0) === CharacterCodes.asterisk) {
|
||||
subpattern += "([^./]" + singleAsteriskRegexFragment + ")?";
|
||||
component = component.substr(1);
|
||||
}
|
||||
else if (component.charCodeAt(0) === CharacterCodes.question) {
|
||||
subpattern += "[^./]";
|
||||
component = component.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
subpattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter);
|
||||
hasWrittenComponent = true;
|
||||
}
|
||||
}
|
||||
|
||||
while (optionalCount > 0) {
|
||||
subpattern += ")?";
|
||||
optionalCount--;
|
||||
const subPattern = getSubPatternFromSpec(spec, basePath, usage, singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter);
|
||||
if (subPattern === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasWrittenSubpattern) {
|
||||
pattern += "|";
|
||||
}
|
||||
|
||||
pattern += "(" + subpattern + ")";
|
||||
pattern += "(" + subPattern + ")";
|
||||
hasWrittenSubpattern = true;
|
||||
}
|
||||
|
||||
@ -1610,7 +1664,83 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return "^(" + pattern + (usage === "exclude" ? ")($|/)" : ")$");
|
||||
// If excluding, match "foo/bar/baz...", but if including, only allow "foo".
|
||||
const terminator = usage === "exclude" ? "($|/)" : "$";
|
||||
return `^(${pattern})${terminator}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* An "includes" path "foo" is implicitly a glob "foo/** /*" (without the space) if its last component has no extension,
|
||||
* and does not contain any glob characters itself.
|
||||
*/
|
||||
export function isImplicitGlob(lastPathComponent: string): boolean {
|
||||
return !/[.*?]/.test(lastPathComponent);
|
||||
}
|
||||
|
||||
function getSubPatternFromSpec(spec: string, basePath: string, usage: "files" | "directories" | "exclude", singleAsteriskRegexFragment: string, doubleAsteriskRegexFragment: string, replaceWildcardCharacter: (match: string) => string): string | undefined {
|
||||
let subpattern = "";
|
||||
let hasRecursiveDirectoryWildcard = false;
|
||||
let hasWrittenComponent = false;
|
||||
const components = getNormalizedPathComponents(spec, basePath);
|
||||
const lastComponent = lastOrUndefined(components);
|
||||
if (usage !== "exclude" && lastComponent === "**") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// getNormalizedPathComponents includes the separator for the root component.
|
||||
// We need to remove to create our regex correctly.
|
||||
components[0] = removeTrailingDirectorySeparator(components[0]);
|
||||
|
||||
if (isImplicitGlob(lastComponent)) {
|
||||
components.push("**", "*");
|
||||
}
|
||||
|
||||
let optionalCount = 0;
|
||||
for (let component of components) {
|
||||
if (component === "**") {
|
||||
if (hasRecursiveDirectoryWildcard) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
subpattern += doubleAsteriskRegexFragment;
|
||||
hasRecursiveDirectoryWildcard = true;
|
||||
}
|
||||
else {
|
||||
if (usage === "directories") {
|
||||
subpattern += "(";
|
||||
optionalCount++;
|
||||
}
|
||||
|
||||
if (hasWrittenComponent) {
|
||||
subpattern += directorySeparator;
|
||||
}
|
||||
|
||||
if (usage !== "exclude") {
|
||||
// The * and ? wildcards should not match directories or files that start with . if they
|
||||
// appear first in a component. Dotted directories and files can be included explicitly
|
||||
// like so: **/.*/.*
|
||||
if (component.charCodeAt(0) === CharacterCodes.asterisk) {
|
||||
subpattern += "([^./]" + singleAsteriskRegexFragment + ")?";
|
||||
component = component.substr(1);
|
||||
}
|
||||
else if (component.charCodeAt(0) === CharacterCodes.question) {
|
||||
subpattern += "[^./]";
|
||||
component = component.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
subpattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter);
|
||||
}
|
||||
|
||||
hasWrittenComponent = true;
|
||||
}
|
||||
|
||||
while (optionalCount > 0) {
|
||||
subpattern += ")?";
|
||||
optionalCount--;
|
||||
}
|
||||
|
||||
return subpattern;
|
||||
}
|
||||
|
||||
function replaceWildCardCharacterFiles(match: string) {
|
||||
@ -1697,6 +1827,7 @@ namespace ts {
|
||||
function getBasePaths(path: string, includes: string[], useCaseSensitiveFileNames: boolean) {
|
||||
// Storage for our results in the form of literal paths (e.g. the paths as written by the user).
|
||||
const basePaths: string[] = [path];
|
||||
|
||||
if (includes) {
|
||||
// Storage for literal base paths amongst the include patterns.
|
||||
const includeBasePaths: string[] = [];
|
||||
@ -1704,14 +1835,8 @@ namespace ts {
|
||||
// We also need to check the relative paths by converting them to absolute and normalizing
|
||||
// in case they escape the base path (e.g "..\somedirectory")
|
||||
const absolute: string = isRootedDiskPath(include) ? include : normalizePath(combinePaths(path, include));
|
||||
|
||||
const wildcardOffset = indexOfAnyCharCode(absolute, wildcardCharCodes);
|
||||
const includeBasePath = wildcardOffset < 0
|
||||
? removeTrailingDirectorySeparator(getDirectoryPath(absolute))
|
||||
: absolute.substring(0, absolute.lastIndexOf(directorySeparator, wildcardOffset));
|
||||
|
||||
// Append the literal and canonical candidate base paths.
|
||||
includeBasePaths.push(includeBasePath);
|
||||
includeBasePaths.push(getIncludeBasePath(absolute));
|
||||
}
|
||||
|
||||
// Sort the offsets array using either the literal or canonical path representations.
|
||||
@ -1719,21 +1844,27 @@ namespace ts {
|
||||
|
||||
// Iterate over each include base path and include unique base paths that are not a
|
||||
// subpath of an existing base path
|
||||
include: for (let i = 0; i < includeBasePaths.length; i++) {
|
||||
const includeBasePath = includeBasePaths[i];
|
||||
for (let j = 0; j < basePaths.length; j++) {
|
||||
if (containsPath(basePaths[j], includeBasePath, path, !useCaseSensitiveFileNames)) {
|
||||
continue include;
|
||||
}
|
||||
for (const includeBasePath of includeBasePaths) {
|
||||
if (ts.every(basePaths, basePath => !containsPath(basePath, includeBasePath, path, !useCaseSensitiveFileNames))) {
|
||||
basePaths.push(includeBasePath);
|
||||
}
|
||||
|
||||
basePaths.push(includeBasePath);
|
||||
}
|
||||
}
|
||||
|
||||
return basePaths;
|
||||
}
|
||||
|
||||
function getIncludeBasePath(absolute: string): string {
|
||||
const wildcardOffset = indexOfAnyCharCode(absolute, wildcardCharCodes);
|
||||
if (wildcardOffset < 0) {
|
||||
// No "*" or "?" in the path
|
||||
return !hasExtension(absolute)
|
||||
? absolute
|
||||
: removeTrailingDirectorySeparator(getDirectoryPath(absolute));
|
||||
}
|
||||
return absolute.substring(0, absolute.lastIndexOf(directorySeparator, wildcardOffset));
|
||||
}
|
||||
|
||||
export function ensureScriptKind(fileName: string, scriptKind?: ScriptKind): ScriptKind {
|
||||
// Using scriptKind as a condition handles both:
|
||||
// - 'scriptKind' is unspecified and thus it is `undefined`
|
||||
@ -1767,7 +1898,7 @@ namespace ts {
|
||||
/** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */
|
||||
export const supportedTypescriptExtensionsForExtractExtension = [".d.ts", ".ts", ".tsx"];
|
||||
export const supportedJavascriptExtensions = [".js", ".jsx"];
|
||||
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
|
||||
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
|
||||
|
||||
export function getSupportedExtensions(options?: CompilerOptions): string[] {
|
||||
return options && options.allowJs ? allSupportedExtensions : supportedTypeScriptExtensions;
|
||||
@ -1864,10 +1995,6 @@ namespace ts {
|
||||
return path.substring(0, path.length - extension.length);
|
||||
}
|
||||
|
||||
export function isJsxOrTsxExtension(ext: string): boolean {
|
||||
return ext === ".jsx" || ext === ".tsx";
|
||||
}
|
||||
|
||||
export function changeExtension<T extends string | Path>(path: T, newExtension: string): T {
|
||||
return <T>(removeFileExtension(path) + newExtension);
|
||||
}
|
||||
@ -2060,4 +2187,33 @@ namespace ts {
|
||||
// pos === undefined || pos === null || isNaN(pos) || pos < 0;
|
||||
return !(pos >= 0);
|
||||
}
|
||||
|
||||
/** True if an extension is one of the supported TypeScript extensions. */
|
||||
export function extensionIsTypeScript(ext: Extension): boolean {
|
||||
return ext <= Extension.LastTypeScriptExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the extension from a path.
|
||||
* Path must have a valid extension.
|
||||
*/
|
||||
export function extensionFromPath(path: string): Extension {
|
||||
if (fileExtensionIs(path, ".d.ts")) {
|
||||
return Extension.Dts;
|
||||
}
|
||||
if (fileExtensionIs(path, ".ts")) {
|
||||
return Extension.Ts;
|
||||
}
|
||||
if (fileExtensionIs(path, ".tsx")) {
|
||||
return Extension.Tsx;
|
||||
}
|
||||
if (fileExtensionIs(path, ".js")) {
|
||||
return Extension.Js;
|
||||
}
|
||||
if (fileExtensionIs(path, ".jsx")) {
|
||||
return Extension.Jsx;
|
||||
}
|
||||
Debug.fail(`File ${path} has unknown extension.`);
|
||||
return Extension.Js;
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@
|
||||
"category": "Error",
|
||||
"code": 1054
|
||||
},
|
||||
"Type '{0}' is not a valid async function return type.": {
|
||||
"Type '{0}' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.": {
|
||||
"category": "Error",
|
||||
"code": 1055
|
||||
},
|
||||
@ -603,10 +603,6 @@
|
||||
"category": "Error",
|
||||
"code": 1194
|
||||
},
|
||||
"Catch clause variable name must be an identifier.": {
|
||||
"category": "Error",
|
||||
"code": 1195
|
||||
},
|
||||
"Catch clause variable cannot have a type annotation.": {
|
||||
"category": "Error",
|
||||
"code": 1196
|
||||
@ -1855,6 +1851,10 @@
|
||||
"category": "Error",
|
||||
"code": 2664
|
||||
},
|
||||
"Invalid module name in augmentation. Module '{0}' resolves to an untyped module at '{1}', which cannot be augmented.": {
|
||||
"category": "Error",
|
||||
"code": 2665
|
||||
},
|
||||
"Exports and export assignments are not permitted in module augmentations.": {
|
||||
"category": "Error",
|
||||
"code": 2666
|
||||
@ -2709,7 +2709,7 @@
|
||||
"category": "Message",
|
||||
"code": 6099
|
||||
},
|
||||
"'package.json' does not have 'types' field.": {
|
||||
"'package.json' does not have a 'types' or 'main' field.": {
|
||||
"category": "Message",
|
||||
"code": 6100
|
||||
},
|
||||
@ -2857,7 +2857,7 @@
|
||||
"category": "Message",
|
||||
"code": 6136
|
||||
},
|
||||
"No types specified in 'package.json' but 'allowJs' is set, so returning 'main' value of '{0}'": {
|
||||
"No types specified in 'package.json', so returning 'main' value of '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 6137
|
||||
},
|
||||
@ -2877,6 +2877,14 @@
|
||||
"category": "Message",
|
||||
"code": 6141
|
||||
},
|
||||
"Module '{0}' was resolved to '{1}', but '--jsx' is not set.": {
|
||||
"category": "Error",
|
||||
"code": 6142
|
||||
},
|
||||
"Module '{0}' was resolved to '{1}', but '--allowJs' is not set.": {
|
||||
"category": "Error",
|
||||
"code": 6143
|
||||
},
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
"code": 7005
|
||||
@ -2909,6 +2917,10 @@
|
||||
"category": "Error",
|
||||
"code": 7015
|
||||
},
|
||||
"Could not find a declaration file for module '{0}'. '{1}' implicitly has an 'any' type.": {
|
||||
"category": "Error",
|
||||
"code": 7016
|
||||
},
|
||||
"Element implicitly has an 'any' type because type '{0}' has no index signature.": {
|
||||
"category": "Error",
|
||||
"code": 7017
|
||||
@ -3089,6 +3101,7 @@
|
||||
"category": "Error",
|
||||
"code": 17010
|
||||
},
|
||||
|
||||
"Circularity detected while resolving configuration: {0}": {
|
||||
"category": "Error",
|
||||
"code": 18000
|
||||
@ -3097,6 +3110,15 @@
|
||||
"category": "Error",
|
||||
"code": 18001
|
||||
},
|
||||
"The 'files' list in config file '{0}' is empty.": {
|
||||
"category": "Error",
|
||||
"code": 18002
|
||||
},
|
||||
"No inputs were found in config file '{0}'. Specified 'include' paths were '{1}' and 'exclude' paths were '{2}'.": {
|
||||
"category": "Error",
|
||||
"code": 18003
|
||||
},
|
||||
|
||||
"Add missing 'super()' call.": {
|
||||
"category": "Message",
|
||||
"code": 90001
|
||||
|
||||
@ -109,12 +109,12 @@ namespace ts {
|
||||
export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression;
|
||||
export function createLiteral(value: string | number | boolean | StringLiteral | Identifier, location?: TextRange): PrimaryExpression {
|
||||
if (typeof value === "number") {
|
||||
const node = <LiteralExpression>createNode(SyntaxKind.NumericLiteral, location, /*flags*/ undefined);
|
||||
const node = <NumericLiteral>createNode(SyntaxKind.NumericLiteral, location, /*flags*/ undefined);
|
||||
node.text = value.toString();
|
||||
return node;
|
||||
}
|
||||
else if (typeof value === "boolean") {
|
||||
return <PrimaryExpression>createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword, location, /*flags*/ undefined);
|
||||
return <BooleanLiteral>createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword, location, /*flags*/ undefined);
|
||||
}
|
||||
else if (typeof value === "string") {
|
||||
const node = <StringLiteral>createNode(SyntaxKind.StringLiteral, location, /*flags*/ undefined);
|
||||
@ -226,20 +226,7 @@ namespace ts {
|
||||
|
||||
// Signature elements
|
||||
|
||||
export function createParameter(name: string | Identifier | BindingPattern, initializer?: Expression, location?: TextRange) {
|
||||
return createParameterDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
name,
|
||||
/*questionToken*/ undefined,
|
||||
/*type*/ undefined,
|
||||
initializer,
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
export function createParameterDeclaration(decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: DotDotDotToken, name: string | Identifier | BindingPattern, questionToken: QuestionToken, type: TypeNode, initializer: Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
export function createParameter(decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: DotDotDotToken, name: string | Identifier | BindingPattern, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
const node = <ParameterDeclaration>createNode(SyntaxKind.Parameter, location, flags);
|
||||
node.decorators = decorators ? createNodeArray(decorators) : undefined;
|
||||
node.modifiers = modifiers ? createNodeArray(modifiers) : undefined;
|
||||
@ -251,9 +238,9 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateParameterDeclaration(node: ParameterDeclaration, decorators: Decorator[], modifiers: Modifier[], name: BindingName, type: TypeNode, initializer: Expression) {
|
||||
export function updateParameter(node: ParameterDeclaration, decorators: Decorator[], modifiers: Modifier[], name: BindingName, type: TypeNode, initializer: Expression) {
|
||||
if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.type !== type || node.initializer !== initializer) {
|
||||
return updateNode(createParameterDeclaration(decorators, modifiers, node.dotDotDotToken, name, node.questionToken, type, initializer, /*location*/ node, /*flags*/ node.flags), node);
|
||||
return updateNode(createParameter(decorators, modifiers, node.dotDotDotToken, name, node.questionToken, type, initializer, /*location*/ node, /*flags*/ node.flags), node);
|
||||
}
|
||||
|
||||
return node;
|
||||
@ -1474,6 +1461,28 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a synthetic element to act as a placeholder for the end of an emitted declaration in
|
||||
* order to properly emit exports.
|
||||
*/
|
||||
export function createEndOfDeclarationMarker(original: Node) {
|
||||
const node = <EndOfDeclarationMarker>createNode(SyntaxKind.EndOfDeclarationMarker);
|
||||
node.emitNode = {};
|
||||
node.original = original;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a synthetic element to act as a placeholder for the beginning of a merged declaration in
|
||||
* order to properly emit exports.
|
||||
*/
|
||||
export function createMergeDeclarationMarker(original: Node) {
|
||||
const node = <MergeDeclarationMarker>createNode(SyntaxKind.MergeDeclarationMarker);
|
||||
node.emitNode = {};
|
||||
node.original = original;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a synthetic expression to act as a placeholder for a not-emitted expression in
|
||||
* order to preserve comments or sourcemap positions.
|
||||
@ -1557,18 +1566,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function createRestParameter(name: string | Identifier) {
|
||||
return createParameterDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createToken(SyntaxKind.DotDotDotToken),
|
||||
name,
|
||||
/*questionToken*/ undefined,
|
||||
/*type*/ undefined,
|
||||
/*initializer*/ undefined
|
||||
);
|
||||
}
|
||||
|
||||
export function createFunctionCall(func: Expression, thisArg: Expression, argumentsList: Expression[], location?: TextRange) {
|
||||
return createCall(
|
||||
createPropertyAccess(func, "call"),
|
||||
@ -1625,7 +1622,9 @@ namespace ts {
|
||||
// flag and setting a parent node.
|
||||
const react = createIdentifier(reactNamespace || "React");
|
||||
react.flags &= ~NodeFlags.Synthesized;
|
||||
react.parent = parent;
|
||||
// Set the parent that is in parse tree
|
||||
// this makes sure that parent chain is intact for checker to traverse complete scope tree
|
||||
react.parent = getParseTreeNode(parent);
|
||||
return react;
|
||||
}
|
||||
|
||||
@ -1662,6 +1661,18 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
export function createExportDefault(expression: Expression) {
|
||||
return createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, expression);
|
||||
}
|
||||
|
||||
export function createExternalModuleExport(exportName: Identifier) {
|
||||
return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([createExportSpecifier(exportName)]));
|
||||
}
|
||||
|
||||
export function createLetStatement(name: Identifier, initializer: Expression, location?: TextRange) {
|
||||
return createVariableStatement(/*modifiers*/ undefined, createLetDeclarationList([createVariableDeclaration(name, /*type*/ undefined, initializer)]), location);
|
||||
}
|
||||
|
||||
export function createLetDeclarationList(declarations: VariableDeclaration[], location?: TextRange) {
|
||||
return createVariableDeclarationList(declarations, location, NodeFlags.Let);
|
||||
}
|
||||
@ -1781,13 +1792,10 @@ namespace ts {
|
||||
return createArrowFunction(
|
||||
/*modifiers*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter("name")],
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "name")],
|
||||
/*type*/ undefined,
|
||||
/*equalsGreaterThanToken*/ undefined,
|
||||
createElementAccess(
|
||||
target,
|
||||
createIdentifier("name")
|
||||
)
|
||||
createToken(SyntaxKind.EqualsGreaterThanToken),
|
||||
createElementAccess(target, createIdentifier("name"))
|
||||
);
|
||||
}
|
||||
|
||||
@ -1797,11 +1805,11 @@ namespace ts {
|
||||
/*modifiers*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[
|
||||
createParameter("name"),
|
||||
createParameter("value")
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "name"),
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "value")
|
||||
],
|
||||
/*type*/ undefined,
|
||||
/*equalsGreaterThanToken*/ undefined,
|
||||
createToken(SyntaxKind.EqualsGreaterThanToken),
|
||||
createAssignment(
|
||||
createElementAccess(
|
||||
target,
|
||||
@ -1853,7 +1861,7 @@ namespace ts {
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
"value",
|
||||
[createParameter("v")],
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "v")],
|
||||
createBlock([
|
||||
createStatement(
|
||||
createCall(
|
||||
@ -1873,9 +1881,9 @@ namespace ts {
|
||||
createArrowFunction(
|
||||
/*modifiers*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter("name")],
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "name")],
|
||||
/*type*/ undefined,
|
||||
/*equalsGreaterThanToken*/ undefined,
|
||||
createToken(SyntaxKind.EqualsGreaterThanToken),
|
||||
createLogicalOr(
|
||||
createElementAccess(
|
||||
createIdentifier("cache"),
|
||||
@ -1915,8 +1923,8 @@ namespace ts {
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[
|
||||
createParameter("geti"),
|
||||
createParameter("seti")
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "geti"),
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "seti")
|
||||
],
|
||||
/*type*/ undefined,
|
||||
createBlock([
|
||||
@ -2193,6 +2201,107 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local name of a declaration. This is primarily used for declarations that can be
|
||||
* referred to by name in the declaration's immediate scope (classes, enums, namespaces). A
|
||||
* local name will *never* be prefixed with an module or namespace export modifier like
|
||||
* "exports." when emitted as an expression.
|
||||
*
|
||||
* @param node The declaration.
|
||||
* @param allowComments A value indicating whether comments may be emitted for the name.
|
||||
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
||||
*/
|
||||
export function getLocalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) {
|
||||
return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether an identifier should only be referred to by its local name.
|
||||
*/
|
||||
export function isLocalName(node: Identifier) {
|
||||
return (getEmitFlags(node) & EmitFlags.LocalName) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the export name of a declaration. This is primarily used for declarations that can be
|
||||
* referred to by name in the declaration's immediate scope (classes, enums, namespaces). An
|
||||
* export name will *always* be prefixed with an module or namespace export modifier like
|
||||
* `"exports."` when emitted as an expression if the name points to an exported symbol.
|
||||
*
|
||||
* @param node The declaration.
|
||||
* @param allowComments A value indicating whether comments may be emitted for the name.
|
||||
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
||||
*/
|
||||
export function getExportName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier {
|
||||
return getName(node, allowComments, allowSourceMaps, EmitFlags.ExportName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether an identifier should only be referred to by its export representation if the
|
||||
* name points to an exported symbol.
|
||||
*/
|
||||
export function isExportName(node: Identifier) {
|
||||
return (getEmitFlags(node) & EmitFlags.ExportName) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of a declaration for use in declarations.
|
||||
*
|
||||
* @param node The declaration.
|
||||
* @param allowComments A value indicating whether comments may be emitted for the name.
|
||||
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
||||
*/
|
||||
export function getDeclarationName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) {
|
||||
return getName(node, allowComments, allowSourceMaps);
|
||||
}
|
||||
|
||||
function getName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags?: EmitFlags) {
|
||||
if (node.name && isIdentifier(node.name) && !isGeneratedIdentifier(node.name)) {
|
||||
const name = getMutableClone(node.name);
|
||||
emitFlags |= getEmitFlags(node.name);
|
||||
if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap;
|
||||
if (!allowComments) emitFlags |= EmitFlags.NoComments;
|
||||
if (emitFlags) setEmitFlags(name, emitFlags);
|
||||
return name;
|
||||
}
|
||||
return getGeneratedNameForNode(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exported name of a declaration for use in expressions.
|
||||
*
|
||||
* An exported name will *always* be prefixed with an module or namespace export modifier like
|
||||
* "exports." if the name points to an exported symbol.
|
||||
*
|
||||
* @param ns The namespace identifier.
|
||||
* @param node The declaration.
|
||||
* @param allowComments A value indicating whether comments may be emitted for the name.
|
||||
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
||||
*/
|
||||
export function getExternalModuleOrNamespaceExportName(ns: Identifier | undefined, node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier | PropertyAccessExpression {
|
||||
if (ns && hasModifier(node, ModifierFlags.Export)) {
|
||||
return getNamespaceMemberName(ns, getName(node), allowComments, allowSourceMaps);
|
||||
}
|
||||
return getExportName(node, allowComments, allowSourceMaps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a namespace-qualified name for use in expressions.
|
||||
*
|
||||
* @param ns The namespace identifier.
|
||||
* @param name The name.
|
||||
* @param allowComments A value indicating whether comments may be emitted for the name.
|
||||
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
||||
*/
|
||||
export function getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression {
|
||||
const qualifiedName = createPropertyAccess(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name), /*location*/ name);
|
||||
let emitFlags: EmitFlags;
|
||||
if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap;
|
||||
if (!allowComments) emitFlags |= EmitFlags.NoComments;
|
||||
if (emitFlags) setEmitFlags(qualifiedName, emitFlags);
|
||||
return qualifiedName;
|
||||
}
|
||||
|
||||
// Utilities
|
||||
|
||||
function isUseStrictPrologue(node: ExpressionStatement): boolean {
|
||||
@ -2246,7 +2355,7 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Ensures "use strict" directive is added
|
||||
*
|
||||
*
|
||||
* @param node source file
|
||||
*/
|
||||
export function ensureUseStrict(node: SourceFile): SourceFile {
|
||||
|
||||
@ -2,39 +2,86 @@
|
||||
/// <reference path="diagnosticInformationMap.generated.ts" />
|
||||
|
||||
namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export function trace(host: ModuleResolutionHost, message: DiagnosticMessage, ...args: any[]): void;
|
||||
export function trace(host: ModuleResolutionHost): void {
|
||||
function trace(host: ModuleResolutionHost, message: DiagnosticMessage, ...args: any[]): void;
|
||||
function trace(host: ModuleResolutionHost): void {
|
||||
host.trace(formatMessage.apply(undefined, arguments));
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function isTraceEnabled(compilerOptions: CompilerOptions, host: ModuleResolutionHost): boolean {
|
||||
function isTraceEnabled(compilerOptions: CompilerOptions, host: ModuleResolutionHost): boolean {
|
||||
return compilerOptions.traceResolution && host.trace !== undefined;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function createResolvedModule(resolvedFileName: string, isExternalLibraryImport: boolean, failedLookupLocations: string[]): ResolvedModuleWithFailedLookupLocations {
|
||||
return { resolvedModule: resolvedFileName ? { resolvedFileName, isExternalLibraryImport } : undefined, failedLookupLocations };
|
||||
/**
|
||||
* Result of trying to resolve a module.
|
||||
* At least one of `ts` and `js` should be defined, or the whole thing should be `undefined`.
|
||||
*/
|
||||
interface Resolved {
|
||||
path: string;
|
||||
extension: Extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kinds of file that we are currently looking for.
|
||||
* Typically there is one pass with Extensions.TypeScript, then a second pass with Extensions.JavaScript.
|
||||
*/
|
||||
const enum Extensions {
|
||||
TypeScript, /** '.ts', '.tsx', or '.d.ts' */
|
||||
JavaScript, /** '.js' or '.jsx' */
|
||||
DtsOnly /** Only '.d.ts' */
|
||||
}
|
||||
|
||||
/** Used with `Extensions.DtsOnly` to extract the path from TypeScript results. */
|
||||
function resolvedTypeScriptOnly(resolved: Resolved | undefined): string | undefined {
|
||||
if (!resolved) {
|
||||
return undefined;
|
||||
}
|
||||
Debug.assert(extensionIsTypeScript(resolved.extension));
|
||||
return resolved.path;
|
||||
}
|
||||
|
||||
/** Create Resolved from a file with unknown extension. */
|
||||
function resolvedFromAnyFile(path: string): Resolved | undefined {
|
||||
return { path, extension: extensionFromPath(path) };
|
||||
}
|
||||
|
||||
/** Adds `isExernalLibraryImport` to a Resolved to get a ResolvedModule. */
|
||||
function resolvedModuleFromResolved({ path, extension }: Resolved, isExternalLibraryImport: boolean): ResolvedModuleFull {
|
||||
return { resolvedFileName: path, extension, isExternalLibraryImport };
|
||||
}
|
||||
|
||||
function createResolvedModuleWithFailedLookupLocations(resolved: Resolved | undefined, isExternalLibraryImport: boolean, failedLookupLocations: string[]): ResolvedModuleWithFailedLookupLocations {
|
||||
return { resolvedModule: resolved && resolvedModuleFromResolved(resolved, isExternalLibraryImport), failedLookupLocations };
|
||||
}
|
||||
|
||||
function moduleHasNonRelativeName(moduleName: string): boolean {
|
||||
return !(isRootedDiskPath(moduleName) || isExternalModuleNameRelative(moduleName));
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface ModuleResolutionState {
|
||||
interface ModuleResolutionState {
|
||||
host: ModuleResolutionHost;
|
||||
compilerOptions: CompilerOptions;
|
||||
// We only use this subset of the compiler options.
|
||||
compilerOptions: { rootDirs?: string[], baseUrl?: string, paths?: MapLike<string[]> };
|
||||
traceEnabled: boolean;
|
||||
// skip .tsx files if jsx is not enabled
|
||||
skipTsx: boolean;
|
||||
}
|
||||
|
||||
function tryReadTypesSection(packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string {
|
||||
function tryReadTypesSection(extensions: Extensions, packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string {
|
||||
const jsonContent = readJson(packageJsonPath, state.host);
|
||||
|
||||
switch (extensions) {
|
||||
case Extensions.DtsOnly:
|
||||
case Extensions.TypeScript:
|
||||
return tryReadFromField("typings") || tryReadFromField("types");
|
||||
|
||||
case Extensions.JavaScript:
|
||||
if (typeof jsonContent.main === "string") {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.No_types_specified_in_package_json_so_returning_main_value_of_0, jsonContent.main);
|
||||
}
|
||||
return normalizePath(combinePaths(baseDirectory, jsonContent.main));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function tryReadFromField(fieldName: string) {
|
||||
if (hasProperty(jsonContent, fieldName)) {
|
||||
const typesFile = (<any>jsonContent)[fieldName];
|
||||
@ -52,21 +99,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const typesFilePath = tryReadFromField("typings") || tryReadFromField("types");
|
||||
if (typesFilePath) {
|
||||
return typesFilePath;
|
||||
}
|
||||
|
||||
// Use the main module for inferring types if no types package specified and the allowJs is set
|
||||
if (state.compilerOptions.allowJs && jsonContent.main && typeof jsonContent.main === "string") {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0, jsonContent.main);
|
||||
}
|
||||
const mainFilePath = normalizePath(combinePaths(baseDirectory, jsonContent.main));
|
||||
return mainFilePath;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function readJson(path: string, host: ModuleResolutionHost): { typings?: string, types?: string, main?: string } {
|
||||
@ -80,8 +112,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const typeReferenceExtensions = [".d.ts"];
|
||||
|
||||
export function getEffectiveTypeRoots(options: CompilerOptions, host: { directoryExists?: (directoryName: string) => boolean, getCurrentDirectory?: () => string }): string[] | undefined {
|
||||
if (options.typeRoots) {
|
||||
return options.typeRoots;
|
||||
@ -132,12 +162,11 @@ namespace ts {
|
||||
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups
|
||||
* is assumed to be the same as root directory of the project.
|
||||
*/
|
||||
export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
|
||||
export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations {
|
||||
const traceEnabled = isTraceEnabled(options, host);
|
||||
const moduleResolutionState: ModuleResolutionState = {
|
||||
compilerOptions: options,
|
||||
host: host,
|
||||
skipTsx: true,
|
||||
traceEnabled
|
||||
};
|
||||
|
||||
@ -168,19 +197,20 @@ namespace ts {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", "));
|
||||
}
|
||||
const primarySearchPaths = typeRoots;
|
||||
for (const typeRoot of primarySearchPaths) {
|
||||
for (const typeRoot of typeRoots) {
|
||||
const candidate = combinePaths(typeRoot, typeReferenceDirectiveName);
|
||||
const candidateDirectory = getDirectoryPath(candidate);
|
||||
const resolvedFile = loadNodeModuleFromDirectory(typeReferenceExtensions, candidate, failedLookupLocations,
|
||||
!directoryProbablyExists(candidateDirectory, host), moduleResolutionState);
|
||||
|
||||
if (resolvedFile) {
|
||||
const resolved = resolvedTypeScriptOnly(
|
||||
loadNodeModuleFromDirectory(Extensions.DtsOnly, candidate, failedLookupLocations,
|
||||
!directoryProbablyExists(candidateDirectory, host), moduleResolutionState));
|
||||
|
||||
if (resolved) {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile, true);
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolved, true);
|
||||
}
|
||||
return {
|
||||
resolvedTypeReferenceDirective: { primary: true, resolvedFileName: resolvedFile },
|
||||
resolvedTypeReferenceDirective: { primary: true, resolvedFileName: resolved },
|
||||
failedLookupLocations
|
||||
};
|
||||
}
|
||||
@ -193,17 +223,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
let resolvedFile: string;
|
||||
let initialLocationForSecondaryLookup: string;
|
||||
if (containingFile) {
|
||||
initialLocationForSecondaryLookup = getDirectoryPath(containingFile);
|
||||
}
|
||||
const initialLocationForSecondaryLookup = containingFile && getDirectoryPath(containingFile);
|
||||
|
||||
if (initialLocationForSecondaryLookup !== undefined) {
|
||||
// check secondary locations
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup);
|
||||
}
|
||||
resolvedFile = loadModuleFromNodeModules(typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, /*checkOneLevel*/ false);
|
||||
resolvedFile = resolvedTypeScriptOnly(loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, /*checkOneLevel*/ false));
|
||||
if (traceEnabled) {
|
||||
if (resolvedFile) {
|
||||
trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile, false);
|
||||
@ -219,9 +246,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
return {
|
||||
resolvedTypeReferenceDirective: resolvedFile
|
||||
? { primary: false, resolvedFileName: resolvedFile }
|
||||
: undefined,
|
||||
resolvedTypeReferenceDirective: resolvedFile ? { primary: false, resolvedFileName: resolvedFile } : undefined,
|
||||
failedLookupLocations
|
||||
};
|
||||
}
|
||||
@ -313,7 +338,7 @@ namespace ts {
|
||||
* 'typings' entry or file 'index' with some supported extension
|
||||
* - Classic loader will only try to interpret '/a/b/c' as file.
|
||||
*/
|
||||
type ResolutionKindSpecificLoader = (candidate: string, extensions: string[], failedLookupLocations: string[], onlyRecordFailures: boolean, state: ModuleResolutionState) => string;
|
||||
type ResolutionKindSpecificLoader = (extensions: Extensions, candidate: string, failedLookupLocations: string[], onlyRecordFailures: boolean, state: ModuleResolutionState) => Resolved | undefined;
|
||||
|
||||
/**
|
||||
* Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to
|
||||
@ -375,19 +400,19 @@ namespace ts {
|
||||
* be converted to a path relative to found rootDir entry './content/protocols/file2' (*). As a last step compiler will check all remaining
|
||||
* entries in 'rootDirs', use them to build absolute path out of (*) and try to resolve module from this location.
|
||||
*/
|
||||
function tryLoadModuleUsingOptionalResolutionSettings(moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader,
|
||||
failedLookupLocations: string[], supportedExtensions: string[], state: ModuleResolutionState): string {
|
||||
function tryLoadModuleUsingOptionalResolutionSettings(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader,
|
||||
failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
|
||||
|
||||
if (moduleHasNonRelativeName(moduleName)) {
|
||||
return tryLoadModuleUsingBaseUrl(moduleName, loader, failedLookupLocations, supportedExtensions, state);
|
||||
return tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, failedLookupLocations, state);
|
||||
}
|
||||
else {
|
||||
return tryLoadModuleUsingRootDirs(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state);
|
||||
return tryLoadModuleUsingRootDirs(extensions, moduleName, containingDirectory, loader, failedLookupLocations, state);
|
||||
}
|
||||
}
|
||||
|
||||
function tryLoadModuleUsingRootDirs(moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader,
|
||||
failedLookupLocations: string[], supportedExtensions: string[], state: ModuleResolutionState): string {
|
||||
function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader,
|
||||
failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
|
||||
|
||||
if (!state.compilerOptions.rootDirs) {
|
||||
return undefined;
|
||||
@ -432,7 +457,7 @@ namespace ts {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate);
|
||||
}
|
||||
const resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(containingDirectory, state.host), state);
|
||||
const resolvedFileName = loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(containingDirectory, state.host), state);
|
||||
if (resolvedFileName) {
|
||||
return resolvedFileName;
|
||||
}
|
||||
@ -451,7 +476,7 @@ namespace ts {
|
||||
trace(state.host, Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, rootDir, candidate);
|
||||
}
|
||||
const baseDirectory = getDirectoryPath(candidate);
|
||||
const resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(baseDirectory, state.host), state);
|
||||
const resolvedFileName = loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(baseDirectory, state.host), state);
|
||||
if (resolvedFileName) {
|
||||
return resolvedFileName;
|
||||
}
|
||||
@ -463,9 +488,7 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function tryLoadModuleUsingBaseUrl(moduleName: string, loader: ResolutionKindSpecificLoader, failedLookupLocations: string[],
|
||||
supportedExtensions: string[], state: ModuleResolutionState): string {
|
||||
|
||||
function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, loader: ResolutionKindSpecificLoader, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
|
||||
if (!state.compilerOptions.baseUrl) {
|
||||
return undefined;
|
||||
}
|
||||
@ -494,9 +517,9 @@ namespace ts {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path);
|
||||
}
|
||||
const resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state);
|
||||
if (resolvedFileName) {
|
||||
return resolvedFileName;
|
||||
const resolved = loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state);
|
||||
if (resolved) {
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
@ -508,56 +531,64 @@ namespace ts {
|
||||
trace(state.host, Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, state.compilerOptions.baseUrl, candidate);
|
||||
}
|
||||
|
||||
return loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state);
|
||||
return loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state);
|
||||
}
|
||||
}
|
||||
|
||||
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
|
||||
const containingDirectory = getDirectoryPath(containingFile);
|
||||
const supportedExtensions = getSupportedExtensions(compilerOptions);
|
||||
const traceEnabled = isTraceEnabled(compilerOptions, host);
|
||||
|
||||
const failedLookupLocations: string[] = [];
|
||||
const state = { compilerOptions, host, traceEnabled, skipTsx: false };
|
||||
let resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, nodeLoadModuleByRelativeName,
|
||||
failedLookupLocations, supportedExtensions, state);
|
||||
const state: ModuleResolutionState = { compilerOptions, host, traceEnabled };
|
||||
|
||||
const result = tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript);
|
||||
if (result) {
|
||||
const { resolved, isExternalLibraryImport } = result;
|
||||
return createResolvedModuleWithFailedLookupLocations(resolved && resolvedWithRealpath(resolved, host, traceEnabled), isExternalLibraryImport, failedLookupLocations);
|
||||
}
|
||||
return { resolvedModule: undefined, failedLookupLocations };
|
||||
|
||||
function tryResolve(extensions: Extensions): { resolved: Resolved, isExternalLibraryImport: boolean } | undefined {
|
||||
const resolved = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, nodeLoadModuleByRelativeName, failedLookupLocations, state);
|
||||
if (resolved) {
|
||||
return { resolved, isExternalLibraryImport: false };
|
||||
}
|
||||
|
||||
let isExternalLibraryImport = false;
|
||||
if (!resolvedFileName) {
|
||||
if (moduleHasNonRelativeName(moduleName)) {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Loading_module_0_from_node_modules_folder, moduleName);
|
||||
}
|
||||
resolvedFileName = loadModuleFromNodeModules(moduleName, containingDirectory, failedLookupLocations, state, /*checkOneLevel*/ false);
|
||||
isExternalLibraryImport = resolvedFileName !== undefined;
|
||||
const resolved = loadModuleFromNodeModules(extensions, moduleName, containingDirectory, failedLookupLocations, state, /*checkOneLevel*/ false);
|
||||
return resolved && { resolved, isExternalLibraryImport: true };
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
resolvedFileName = nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
const resolved = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
return resolved && { resolved, isExternalLibraryImport: false };
|
||||
}
|
||||
}
|
||||
|
||||
if (resolvedFileName && host.realpath) {
|
||||
const originalFileName = resolvedFileName;
|
||||
resolvedFileName = normalizePath(host.realpath(resolvedFileName));
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Resolving_real_path_for_0_result_1, originalFileName, resolvedFileName);
|
||||
}
|
||||
}
|
||||
|
||||
return createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations);
|
||||
}
|
||||
|
||||
function nodeLoadModuleByRelativeName(candidate: string, supportedExtensions: string[], failedLookupLocations: string[],
|
||||
onlyRecordFailures: boolean, state: ModuleResolutionState): string {
|
||||
function resolvedWithRealpath(resolved: Resolved, host: ModuleResolutionHost, traceEnabled: boolean): Resolved {
|
||||
if (!host.realpath) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
const real = normalizePath(host.realpath(resolved.path));
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Resolving_real_path_for_0_result_1, resolved.path, real);
|
||||
}
|
||||
return { path: real, extension: resolved.extension };
|
||||
}
|
||||
|
||||
function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, failedLookupLocations: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0, candidate);
|
||||
}
|
||||
|
||||
const resolvedFileName = !pathEndsWithDirectorySeparator(candidate) && loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state);
|
||||
|
||||
return resolvedFileName || loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, onlyRecordFailures, state);
|
||||
const resolvedFromFile = !pathEndsWithDirectorySeparator(candidate) && loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state);
|
||||
return resolvedFromFile || loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, onlyRecordFailures, state);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@ -570,9 +601,9 @@ namespace ts {
|
||||
* @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary
|
||||
* in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
|
||||
*/
|
||||
function loadModuleFromFile(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
function loadModuleFromFile(extensions: Extensions, candidate: string, failedLookupLocations: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
// First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts"
|
||||
const resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
const resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocations, onlyRecordFailures, state);
|
||||
if (resolvedByAddingExtension) {
|
||||
return resolvedByAddingExtension;
|
||||
}
|
||||
@ -585,12 +616,12 @@ namespace ts {
|
||||
const extension = candidate.substring(extensionless.length);
|
||||
trace(state.host, Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension);
|
||||
}
|
||||
return tryAddingExtensions(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
return tryAddingExtensions(extensionless, extensions, failedLookupLocations, onlyRecordFailures, state);
|
||||
}
|
||||
}
|
||||
|
||||
/** Try to return an existing file that adds one of the `extensions` to `candidate`. */
|
||||
function tryAddingExtensions(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined {
|
||||
function tryAddingExtensions(candidate: string, extensions: Extensions, failedLookupLocations: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
if (!onlyRecordFailures) {
|
||||
// check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing
|
||||
const directory = getDirectoryPath(candidate);
|
||||
@ -598,8 +629,20 @@ namespace ts {
|
||||
onlyRecordFailures = !directoryProbablyExists(directory, state.host);
|
||||
}
|
||||
}
|
||||
return forEach(extensions, ext =>
|
||||
!(state.skipTsx && isJsxOrTsxExtension(ext)) && tryFile(candidate + ext, failedLookupLocation, onlyRecordFailures, state));
|
||||
|
||||
switch (extensions) {
|
||||
case Extensions.DtsOnly:
|
||||
return tryExtension(".d.ts", Extension.Dts);
|
||||
case Extensions.TypeScript:
|
||||
return tryExtension(".ts", Extension.Ts) || tryExtension(".tsx", Extension.Tsx) || tryExtension(".d.ts", Extension.Dts);
|
||||
case Extensions.JavaScript:
|
||||
return tryExtension(".js", Extension.Js) || tryExtension(".jsx", Extension.Jsx);
|
||||
}
|
||||
|
||||
function tryExtension(ext: string, extension: Extension): Resolved | undefined {
|
||||
const path = tryFile(candidate + ext, failedLookupLocations, onlyRecordFailures, state);
|
||||
return path && { path, extension };
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the file if it exists. */
|
||||
@ -619,26 +662,31 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
|
||||
function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
const packageJsonPath = pathToPackageJson(candidate);
|
||||
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host);
|
||||
|
||||
if (directoryExists && state.host.fileExists(packageJsonPath)) {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Found_package_json_at_0, packageJsonPath);
|
||||
}
|
||||
const typesFile = tryReadTypesSection(packageJsonPath, candidate, state);
|
||||
const typesFile = tryReadTypesSection(extensions, packageJsonPath, candidate, state);
|
||||
if (typesFile) {
|
||||
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(typesFile), state.host);
|
||||
// A package.json "typings" may specify an exact filename, or may choose to omit an extension.
|
||||
const result = tryFile(typesFile, failedLookupLocation, onlyRecordFailures, state) ||
|
||||
tryAddingExtensions(typesFile, extensions, failedLookupLocation, onlyRecordFailures, state);
|
||||
if (result) {
|
||||
return result;
|
||||
const fromFile = tryFile(typesFile, failedLookupLocation, onlyRecordFailures, state);
|
||||
if (fromFile) {
|
||||
// Note: this would allow a package.json to specify a ".js" file as typings. Maybe that should be forbidden.
|
||||
return resolvedFromAnyFile(fromFile);
|
||||
}
|
||||
const x = tryAddingExtensions(typesFile, Extensions.TypeScript, failedLookupLocation, onlyRecordFailures, state);
|
||||
if (x) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.package_json_does_not_have_types_field);
|
||||
trace(state.host, Diagnostics.package_json_does_not_have_a_types_or_main_field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -650,104 +698,90 @@ namespace ts {
|
||||
failedLookupLocation.push(packageJsonPath);
|
||||
}
|
||||
|
||||
return loadModuleFromFile(combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state);
|
||||
return loadModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocation, !directoryExists, state);
|
||||
}
|
||||
|
||||
function pathToPackageJson(directory: string): string {
|
||||
return combinePaths(directory, "package.json");
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModulesFolder(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): string {
|
||||
function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
|
||||
const nodeModulesFolder = combinePaths(directory, "node_modules");
|
||||
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host);
|
||||
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
|
||||
const supportedExtensions = getSupportedExtensions(state.compilerOptions);
|
||||
|
||||
let result = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, !nodeModulesFolderExists, state);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
result = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
return loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) ||
|
||||
loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function loadModuleFromNodeModules(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, checkOneLevel: boolean): string {
|
||||
return loadModuleFromNodeModulesWorker(moduleName, directory, failedLookupLocations, state, checkOneLevel, /*typesOnly*/ false);
|
||||
function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, checkOneLevel: boolean): Resolved | undefined {
|
||||
return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, checkOneLevel, /*typesOnly*/ false);
|
||||
}
|
||||
function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
|
||||
return loadModuleFromNodeModulesWorker(Extensions.TypeScript, moduleName, directory, failedLookupLocations, state, /*checkOneLevel*/ false, /*typesOnly*/ true);
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): string {
|
||||
return loadModuleFromNodeModulesWorker(moduleName, directory, failedLookupLocations, state, /*checkOneLevel*/ false, /*typesOnly*/ true);
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModulesWorker(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, checkOneLevel: boolean, typesOnly: boolean): string {
|
||||
function loadModuleFromNodeModulesWorker(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, checkOneLevel: boolean, typesOnly: boolean): Resolved | undefined {
|
||||
directory = normalizeSlashes(directory);
|
||||
while (true) {
|
||||
const baseName = getBaseFileName(directory);
|
||||
if (baseName !== "node_modules") {
|
||||
let packageResult: string | undefined;
|
||||
if (!typesOnly) {
|
||||
// Try to load source from the package
|
||||
packageResult = loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state);
|
||||
if (packageResult && hasTypeScriptFileExtension(packageResult)) {
|
||||
// Always prefer a TypeScript (.ts, .tsx, .d.ts) file shipped with the package
|
||||
return packageResult;
|
||||
}
|
||||
}
|
||||
|
||||
// Else prefer a types package over non-TypeScript results (e.g. JavaScript files)
|
||||
const typesResult = loadModuleFromNodeModulesFolder(combinePaths("@types", moduleName), directory, failedLookupLocations, state);
|
||||
if (typesResult || packageResult) {
|
||||
return typesResult || packageResult;
|
||||
if (getBaseFileName(directory) !== "node_modules") {
|
||||
const resolved = tryInDirectory();
|
||||
if (resolved) {
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
const parentPath = getDirectoryPath(directory);
|
||||
if (parentPath === directory || checkOneLevel) {
|
||||
break;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
directory = parentPath;
|
||||
}
|
||||
return undefined;
|
||||
|
||||
function tryInDirectory(): Resolved | undefined {
|
||||
const packageResult = typesOnly ? undefined : loadModuleFromNodeModulesFolder(extensions, moduleName, directory, failedLookupLocations, state);
|
||||
return packageResult || loadModuleFromNodeModulesFolder(extensions, combinePaths("@types", moduleName), directory, failedLookupLocations, state);
|
||||
}
|
||||
}
|
||||
|
||||
export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
|
||||
const traceEnabled = isTraceEnabled(compilerOptions, host);
|
||||
const state = { compilerOptions, host, traceEnabled, skipTsx: !compilerOptions.jsx };
|
||||
const state: ModuleResolutionState = { compilerOptions, host, traceEnabled };
|
||||
const failedLookupLocations: string[] = [];
|
||||
const supportedExtensions = getSupportedExtensions(compilerOptions);
|
||||
const containingDirectory = getDirectoryPath(containingFile);
|
||||
|
||||
const resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loadModuleFromFile, failedLookupLocations, supportedExtensions, state);
|
||||
if (resolvedFileName) {
|
||||
return createResolvedModule(resolvedFileName, /*isExternalLibraryImport*/false, failedLookupLocations);
|
||||
}
|
||||
const resolved = tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript);
|
||||
return createResolvedModuleWithFailedLookupLocations(resolved, /*isExternalLibraryImport*/ false, failedLookupLocations);
|
||||
|
||||
let referencedSourceFile: string;
|
||||
if (moduleHasNonRelativeName(moduleName)) {
|
||||
referencedSourceFile = referencedSourceFile = loadModuleFromAncestorDirectories(moduleName, containingDirectory, supportedExtensions, failedLookupLocations, state) ||
|
||||
// If we didn't find the file normally, look it up in @types.
|
||||
loadModuleFromNodeModulesAtTypes(moduleName, containingDirectory, failedLookupLocations, state);
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
referencedSourceFile = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
}
|
||||
function tryResolve(extensions: Extensions): Resolved | undefined {
|
||||
const resolvedUsingSettings = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loadModuleFromFile, failedLookupLocations, state);
|
||||
if (resolvedUsingSettings) {
|
||||
return resolvedUsingSettings;
|
||||
}
|
||||
|
||||
|
||||
return referencedSourceFile
|
||||
? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations }
|
||||
: { resolvedModule: undefined, failedLookupLocations };
|
||||
if (moduleHasNonRelativeName(moduleName)) {
|
||||
const resolved = loadModuleFromAncestorDirectories(extensions, moduleName, containingDirectory, failedLookupLocations, state);
|
||||
if (resolved) {
|
||||
return resolved;
|
||||
}
|
||||
if (extensions === Extensions.TypeScript) {
|
||||
// If we didn't find the file normally, look it up in @types.
|
||||
return loadModuleFromNodeModulesAtTypes(moduleName, containingDirectory, failedLookupLocations, state);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
return loadModuleFromFile(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Climb up parent directories looking for a module. */
|
||||
function loadModuleFromAncestorDirectories(moduleName: string, containingDirectory: string, supportedExtensions: string[], failedLookupLocations: string[], state: ModuleResolutionState): string | undefined {
|
||||
function loadModuleFromAncestorDirectories(extensions: Extensions, moduleName: string, containingDirectory: string, failedLookupLocations: string[], state: ModuleResolutionState): Resolved | undefined {
|
||||
while (true) {
|
||||
const searchName = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
const referencedSourceFile = loadModuleFromFile(searchName, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
const referencedSourceFile = loadModuleFromFile(extensions, searchName, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
if (referencedSourceFile) {
|
||||
return referencedSourceFile;
|
||||
}
|
||||
@ -758,4 +792,21 @@ namespace ts {
|
||||
containingDirectory = parentPath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LSHost may load a module from a global cache of typings.
|
||||
* This is the minumum code needed to expose that functionality; the rest is in LSHost.
|
||||
*/
|
||||
/* @internal */
|
||||
export function loadModuleFromGlobalCache(moduleName: string, projectName: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, globalCache: string): ResolvedModuleWithFailedLookupLocations {
|
||||
const traceEnabled = isTraceEnabled(compilerOptions, host);
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, projectName, moduleName, globalCache);
|
||||
}
|
||||
const state: ModuleResolutionState = { compilerOptions, host, traceEnabled };
|
||||
const failedLookupLocations: string[] = [];
|
||||
const resolved = loadModuleFromNodeModules(Extensions.TypeScript, moduleName, globalCache, failedLookupLocations, state, /*checkOneLevel*/ true) ||
|
||||
loadModuleFromNodeModules(Extensions.JavaScript, moduleName, globalCache, failedLookupLocations, state, /*checkOneLevel*/ true);
|
||||
return createResolvedModuleWithFailedLookupLocations(resolved, /*isExternalLibraryImport*/ true, failedLookupLocations);
|
||||
}
|
||||
}
|
||||
@ -415,6 +415,7 @@ namespace ts {
|
||||
return visitNodes(cbNodes, (<JSDocTemplateTag>node).typeParameters);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression) ||
|
||||
visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
|
||||
visitNode(cbNode, (<JSDocTypedefTag>node).name) ||
|
||||
visitNode(cbNode, (<JSDocTypedefTag>node).jsDocTypeLiteral);
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
@ -5501,7 +5502,7 @@ namespace ts {
|
||||
|
||||
exportDeclaration.name = parseIdentifier();
|
||||
|
||||
parseExpected(SyntaxKind.SemicolonToken);
|
||||
parseSemicolon();
|
||||
|
||||
return finishNode(exportDeclaration);
|
||||
}
|
||||
@ -6581,7 +6582,14 @@ namespace ts {
|
||||
const typedefTag = <JSDocTypedefTag>createNode(SyntaxKind.JSDocTypedefTag, atToken.pos);
|
||||
typedefTag.atToken = atToken;
|
||||
typedefTag.tagName = tagName;
|
||||
typedefTag.name = parseJSDocIdentifierName();
|
||||
typedefTag.fullName = parseJSDocTypeNameWithNamespace(/*flags*/ 0);
|
||||
if (typedefTag.fullName) {
|
||||
let rightNode = typedefTag.fullName;
|
||||
while (rightNode.kind !== SyntaxKind.Identifier) {
|
||||
rightNode = rightNode.body;
|
||||
}
|
||||
typedefTag.name = rightNode;
|
||||
}
|
||||
typedefTag.typeExpression = typeExpression;
|
||||
skipWhitespace();
|
||||
|
||||
@ -6644,8 +6652,27 @@ namespace ts {
|
||||
scanner.setTextPos(resumePos);
|
||||
return finishNode(jsDocTypeLiteral);
|
||||
}
|
||||
|
||||
function parseJSDocTypeNameWithNamespace(flags: NodeFlags) {
|
||||
const pos = scanner.getTokenPos();
|
||||
const typeNameOrNamespaceName = parseJSDocIdentifierName();
|
||||
|
||||
if (typeNameOrNamespaceName && parseOptional(SyntaxKind.DotToken)) {
|
||||
const jsDocNamespaceNode = <JSDocNamespaceDeclaration>createNode(SyntaxKind.ModuleDeclaration, pos);
|
||||
jsDocNamespaceNode.flags |= flags;
|
||||
jsDocNamespaceNode.name = typeNameOrNamespaceName;
|
||||
jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(NodeFlags.NestedNamespace);
|
||||
return jsDocNamespaceNode;
|
||||
}
|
||||
|
||||
if (typeNameOrNamespaceName && flags & NodeFlags.NestedNamespace) {
|
||||
typeNameOrNamespaceName.isInJSDocNamespace = true;
|
||||
}
|
||||
return typeNameOrNamespaceName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function tryParseChildTag(parentTag: JSDocTypeLiteral): boolean {
|
||||
Debug.assert(token() === SyntaxKind.AtToken);
|
||||
const atToken = <AtToken>createNode(SyntaxKind.AtToken, scanner.getStartPos());
|
||||
@ -6668,12 +6695,16 @@ namespace ts {
|
||||
return true;
|
||||
case "prop":
|
||||
case "property":
|
||||
if (!parentTag.jsDocPropertyTags) {
|
||||
parentTag.jsDocPropertyTags = <NodeArray<JSDocPropertyTag>>[];
|
||||
}
|
||||
const propertyTag = parsePropertyTag(atToken, tagName);
|
||||
parentTag.jsDocPropertyTags.push(propertyTag);
|
||||
return true;
|
||||
if (propertyTag) {
|
||||
if (!parentTag.jsDocPropertyTags) {
|
||||
parentTag.jsDocPropertyTags = <NodeArray<JSDocPropertyTag>>[];
|
||||
}
|
||||
parentTag.jsDocPropertyTags.push(propertyTag);
|
||||
return true;
|
||||
}
|
||||
// Error parsing property tag
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -307,7 +307,7 @@ namespace ts {
|
||||
// - This calls resolveModuleNames, and then calls findSourceFile for each resolved module.
|
||||
// As all these operations happen - and are nested - within the createProgram call, they close over the below variables.
|
||||
// The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses.
|
||||
const maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 0;
|
||||
const maxNodeModuleJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 0;
|
||||
let currentNodeModulesDepth = 0;
|
||||
|
||||
// If a module has some of its imports skipped due to being at the depth limit under node_modules, then track
|
||||
@ -329,9 +329,17 @@ namespace ts {
|
||||
// Map storing if there is emit blocking diagnostics for given input
|
||||
const hasEmitBlockingDiagnostics = createFileMap<boolean>(getCanonicalFileName);
|
||||
|
||||
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string) => ResolvedModule[];
|
||||
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string) => ResolvedModuleFull[];
|
||||
if (host.resolveModuleNames) {
|
||||
resolveModuleNamesWorker = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile);
|
||||
resolveModuleNamesWorker = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile).map(resolved => {
|
||||
// An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName.
|
||||
if (!resolved || (resolved as ResolvedModuleFull).extension !== undefined) {
|
||||
return resolved as ResolvedModuleFull;
|
||||
}
|
||||
const withExtension = clone(resolved) as ResolvedModuleFull;
|
||||
withExtension.extension = extensionFromPath(resolved.resolvedFileName);
|
||||
return withExtension;
|
||||
});
|
||||
}
|
||||
else {
|
||||
const loader = (moduleName: string, containingFile: string) => resolveModuleName(moduleName, containingFile, options, host).resolvedModule;
|
||||
@ -462,21 +470,7 @@ namespace ts {
|
||||
// check properties that can affect structure of the program or module resolution strategy
|
||||
// if any of these properties has changed - structure cannot be reused
|
||||
const oldOptions = oldProgram.getCompilerOptions();
|
||||
if ((oldOptions.module !== options.module) ||
|
||||
(oldOptions.moduleResolution !== options.moduleResolution) ||
|
||||
(oldOptions.noResolve !== options.noResolve) ||
|
||||
(oldOptions.target !== options.target) ||
|
||||
(oldOptions.noLib !== options.noLib) ||
|
||||
(oldOptions.jsx !== options.jsx) ||
|
||||
(oldOptions.allowJs !== options.allowJs) ||
|
||||
(oldOptions.rootDir !== options.rootDir) ||
|
||||
(oldOptions.configFilePath !== options.configFilePath) ||
|
||||
(oldOptions.baseUrl !== options.baseUrl) ||
|
||||
(oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) ||
|
||||
!arrayIsEqualTo(oldOptions.lib, options.lib) ||
|
||||
!arrayIsEqualTo(oldOptions.typeRoots, options.typeRoots) ||
|
||||
!arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) ||
|
||||
!equalOwnProperties(oldOptions.paths, options.paths)) {
|
||||
if (changesAffectModuleResolution(oldOptions, options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -725,6 +719,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
|
||||
// For JavaScript files, we report semantic errors for using TypeScript-only
|
||||
// constructs from within a JavaScript file as syntactic errors.
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
if (!sourceFile.additionalSyntacticDiagnostics) {
|
||||
sourceFile.additionalSyntacticDiagnostics = getJavaScriptSyntacticDiagnosticsForFile(sourceFile);
|
||||
}
|
||||
return concatenate(sourceFile.additionalSyntacticDiagnostics, sourceFile.parseDiagnostics);
|
||||
}
|
||||
return sourceFile.parseDiagnostics;
|
||||
}
|
||||
|
||||
@ -757,12 +759,10 @@ namespace ts {
|
||||
|
||||
Debug.assert(!!sourceFile.bindDiagnostics);
|
||||
const bindDiagnostics = sourceFile.bindDiagnostics;
|
||||
// For JavaScript files, we don't want to report the normal typescript semantic errors.
|
||||
// Instead, we just report errors for using TypeScript-only constructs from within a
|
||||
// JavaScript file.
|
||||
const checkDiagnostics = isSourceFileJavaScript(sourceFile) ?
|
||||
getJavaScriptSemanticDiagnosticsForFile(sourceFile) :
|
||||
typeChecker.getDiagnostics(sourceFile, cancellationToken);
|
||||
// For JavaScript files, we don't want to report semantic errors.
|
||||
// Instead, we'll report errors for using TypeScript-only constructs from within a
|
||||
// JavaScript file when we get syntactic diagnostics for the file.
|
||||
const checkDiagnostics = isSourceFileJavaScript(sourceFile) ? [] : typeChecker.getDiagnostics(sourceFile, cancellationToken);
|
||||
const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
|
||||
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
|
||||
|
||||
@ -770,7 +770,7 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function getJavaScriptSemanticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
|
||||
function getJavaScriptSyntacticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
|
||||
return runWithCancellationToken(() => {
|
||||
const diagnostics: Diagnostic[] = [];
|
||||
walk(sourceFile);
|
||||
@ -971,10 +971,6 @@ namespace ts {
|
||||
return sortAndDeduplicateDiagnostics(allDiagnostics);
|
||||
}
|
||||
|
||||
function hasExtension(fileName: string): boolean {
|
||||
return getBaseFileName(fileName).indexOf(".") >= 0;
|
||||
}
|
||||
|
||||
function processRootFile(fileName: string, isDefaultLib: boolean) {
|
||||
processSourceFile(normalizePath(fileName), isDefaultLib);
|
||||
}
|
||||
@ -1084,9 +1080,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 'isReference' indicates whether the file was brought in via a reference directive (rather than an import declaration)
|
||||
*/
|
||||
function processSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) {
|
||||
let diagnosticArgument: string[];
|
||||
let diagnostic: DiagnosticMessage;
|
||||
@ -1163,7 +1156,7 @@ namespace ts {
|
||||
}
|
||||
// See if we need to reprocess the imports due to prior skipped imports
|
||||
else if (file && modulesWithElidedImports[file.path]) {
|
||||
if (currentNodeModulesDepth < maxNodeModulesJsDepth) {
|
||||
if (currentNodeModulesDepth < maxNodeModuleJsDepth) {
|
||||
modulesWithElidedImports[file.path] = false;
|
||||
processImportedModules(file);
|
||||
}
|
||||
@ -1303,38 +1296,43 @@ namespace ts {
|
||||
function processImportedModules(file: SourceFile) {
|
||||
collectExternalModuleReferences(file);
|
||||
if (file.imports.length || file.moduleAugmentations.length) {
|
||||
file.resolvedModules = createMap<ResolvedModule>();
|
||||
file.resolvedModules = createMap<ResolvedModuleFull>();
|
||||
const moduleNames = map(concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral);
|
||||
const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory));
|
||||
Debug.assert(resolutions.length === moduleNames.length);
|
||||
for (let i = 0; i < moduleNames.length; i++) {
|
||||
const resolution = resolutions[i];
|
||||
setResolvedModule(file, moduleNames[i], resolution);
|
||||
|
||||
if (!resolution) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const isFromNodeModulesSearch = resolution.isExternalLibraryImport;
|
||||
const isJsFileFromNodeModules = isFromNodeModulesSearch && !extensionIsTypeScript(resolution.extension);
|
||||
const resolvedFileName = resolution.resolvedFileName;
|
||||
|
||||
if (isFromNodeModulesSearch) {
|
||||
currentNodeModulesDepth++;
|
||||
}
|
||||
|
||||
// add file to program only if:
|
||||
// - resolution was successful
|
||||
// - noResolve is falsy
|
||||
// - module name comes from the list of imports
|
||||
// - it's not a top level JavaScript module that exceeded the search max
|
||||
const isFromNodeModulesSearch = resolution && resolution.isExternalLibraryImport;
|
||||
const isJsFileFromNodeModules = isFromNodeModulesSearch && hasJavaScriptFileExtension(resolution.resolvedFileName);
|
||||
|
||||
if (isFromNodeModulesSearch) {
|
||||
currentNodeModulesDepth++;
|
||||
}
|
||||
|
||||
const elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModulesJsDepth;
|
||||
const shouldAddFile = resolution && !options.noResolve && i < file.imports.length && !elideImport;
|
||||
const elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModuleJsDepth;
|
||||
// Don't add the file if it has a bad extension (e.g. 'tsx' if we don't have '--allowJs')
|
||||
// This may still end up being an untyped module -- the file won't be included but imports will be allowed.
|
||||
const shouldAddFile = resolvedFileName && !getResolutionDiagnostic(options, resolution) && !options.noResolve && i < file.imports.length && !elideImport;
|
||||
|
||||
if (elideImport) {
|
||||
modulesWithElidedImports[file.path] = true;
|
||||
}
|
||||
else if (shouldAddFile) {
|
||||
findSourceFile(resolution.resolvedFileName,
|
||||
toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName),
|
||||
/*isDefaultLib*/ false,
|
||||
file,
|
||||
skipTrivia(file.text, file.imports[i].pos),
|
||||
file.imports[i].end);
|
||||
const path = toPath(resolvedFileName, currentDirectory, getCanonicalFileName);
|
||||
const pos = skipTrivia(file.text, file.imports[i].pos);
|
||||
findSourceFile(resolvedFileName, path, /*isDefaultLib*/ false, file, pos, file.imports[i].end);
|
||||
}
|
||||
|
||||
if (isFromNodeModulesSearch) {
|
||||
@ -1346,7 +1344,6 @@ namespace ts {
|
||||
// no imports - drop cached module resolutions
|
||||
file.resolvedModules = undefined;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function computeCommonSourceDirectory(sourceFiles: SourceFile[]): string {
|
||||
@ -1571,4 +1568,32 @@ namespace ts {
|
||||
programDiagnostics.add(createCompilerDiagnostic(message, emitFileName));
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
/**
|
||||
* Returns a DiagnosticMessage if we won't include a resolved module due to its extension.
|
||||
* The DiagnosticMessage's parameters are the imported module name, and the filename it resolved to.
|
||||
* This returns a diagnostic even if the module will be an untyped module.
|
||||
*/
|
||||
export function getResolutionDiagnostic(options: CompilerOptions, { extension }: ResolvedModuleFull): DiagnosticMessage | undefined {
|
||||
switch (extension) {
|
||||
case Extension.Ts:
|
||||
case Extension.Dts:
|
||||
// These are always allowed.
|
||||
return undefined;
|
||||
case Extension.Tsx:
|
||||
return needJsx();
|
||||
case Extension.Jsx:
|
||||
return needJsx() || needAllowJs();
|
||||
case Extension.Js:
|
||||
return needAllowJs();
|
||||
}
|
||||
|
||||
function needJsx() {
|
||||
return options.jsx ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set;
|
||||
}
|
||||
function needAllowJs() {
|
||||
return options.allowJs ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_allowJs_is_not_set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1800,6 +1800,9 @@ namespace ts {
|
||||
case CharacterCodes.comma:
|
||||
pos++;
|
||||
return token = SyntaxKind.CommaToken;
|
||||
case CharacterCodes.dot:
|
||||
pos++;
|
||||
return token = SyntaxKind.DotToken;
|
||||
}
|
||||
|
||||
if (isIdentifierStart(ch, ScriptTarget.Latest)) {
|
||||
|
||||
@ -111,7 +111,6 @@ namespace ts {
|
||||
const transformers: Transformer[] = [];
|
||||
|
||||
transformers.push(transformTypeScript);
|
||||
transformers.push(moduleTransformerMap[moduleKind] || moduleTransformerMap[ModuleKind.None]);
|
||||
|
||||
if (jsx === JsxEmit.React) {
|
||||
transformers.push(transformJsx);
|
||||
@ -130,6 +129,10 @@ namespace ts {
|
||||
transformers.push(transformGenerators);
|
||||
}
|
||||
|
||||
transformers.push(moduleTransformerMap[moduleKind] || moduleTransformerMap[ModuleKind.None]);
|
||||
|
||||
// The ES5 transformer is last so that it can substitute expressions like `exports.default`
|
||||
// for ES3.
|
||||
if (languageVersion < ScriptTarget.ES5) {
|
||||
transformers.push(transformES5);
|
||||
}
|
||||
@ -351,4 +354,4 @@ namespace ts {
|
||||
return statements;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,13 +174,14 @@ namespace ts {
|
||||
*
|
||||
* @param node The VariableDeclaration to flatten.
|
||||
* @param recordTempVariable A callback used to record new temporary variables.
|
||||
* @param nameSubstitution An optional callback used to substitute binding names.
|
||||
* @param createAssignmentCallback An optional callback used to create assignment expressions
|
||||
* for non-temporary variables.
|
||||
* @param visitor An optional visitor to use to visit expressions.
|
||||
*/
|
||||
export function flattenVariableDestructuringToExpression(
|
||||
node: VariableDeclaration,
|
||||
recordTempVariable: (name: Identifier) => void,
|
||||
nameSubstitution?: (name: Identifier) => Expression,
|
||||
createAssignmentCallback?: (name: Identifier, value: Expression, location?: TextRange) => Expression,
|
||||
visitor?: (node: Node) => VisitResult<Node>) {
|
||||
|
||||
const pendingAssignments: Expression[] = [];
|
||||
@ -192,18 +193,20 @@ namespace ts {
|
||||
return expression;
|
||||
|
||||
function emitAssignment(name: Identifier, value: Expression, location: TextRange, original: Node) {
|
||||
const left = nameSubstitution && nameSubstitution(name) || name;
|
||||
emitPendingAssignment(left, value, location, original);
|
||||
const expression = createAssignmentCallback
|
||||
? createAssignmentCallback(name, value, location)
|
||||
: createAssignment(name, value, location);
|
||||
|
||||
emitPendingAssignment(expression, original);
|
||||
}
|
||||
|
||||
function emitTempVariableAssignment(value: Expression, location: TextRange) {
|
||||
const name = createTempVariable(recordTempVariable);
|
||||
emitPendingAssignment(name, value, location, /*original*/ undefined);
|
||||
emitPendingAssignment(createAssignment(name, value, location), /*original*/ undefined);
|
||||
return name;
|
||||
}
|
||||
|
||||
function emitPendingAssignment(name: Expression, value: Expression, location: TextRange, original: Node) {
|
||||
const expression = createAssignment(name, value, location);
|
||||
function emitPendingAssignment(expression: Expression, original: Node) {
|
||||
expression.original = original;
|
||||
|
||||
// NOTE: this completely disables source maps, but aligns with the behavior of
|
||||
@ -211,7 +214,6 @@ namespace ts {
|
||||
setEmitFlags(expression, EmitFlags.NoNestedSourceMaps);
|
||||
|
||||
pendingAssignments.push(expression);
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -186,6 +186,7 @@ namespace ts {
|
||||
let enclosingFunction: FunctionLikeDeclaration;
|
||||
let enclosingNonArrowFunction: FunctionLikeDeclaration;
|
||||
let enclosingNonAsyncFunctionBody: FunctionLikeDeclaration | ClassElement;
|
||||
let isInConstructorWithCapturedSuper: boolean;
|
||||
|
||||
/**
|
||||
* Used to track if we are emitting body of the converted loop
|
||||
@ -231,14 +232,17 @@ namespace ts {
|
||||
const savedCurrentParent = currentParent;
|
||||
const savedCurrentNode = currentNode;
|
||||
const savedConvertedLoopState = convertedLoopState;
|
||||
const savedIsInConstructorWithCapturedSuper = isInConstructorWithCapturedSuper;
|
||||
if (nodeStartsNewLexicalEnvironment(node)) {
|
||||
// don't treat content of nodes that start new lexical environment as part of converted loop copy
|
||||
// don't treat content of nodes that start new lexical environment as part of converted loop copy or constructor body
|
||||
isInConstructorWithCapturedSuper = false;
|
||||
convertedLoopState = undefined;
|
||||
}
|
||||
|
||||
onBeforeVisitNode(node);
|
||||
const visited = f(node);
|
||||
|
||||
isInConstructorWithCapturedSuper = savedIsInConstructorWithCapturedSuper;
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
enclosingFunction = savedEnclosingFunction;
|
||||
enclosingNonArrowFunction = savedEnclosingNonArrowFunction;
|
||||
@ -251,6 +255,14 @@ namespace ts {
|
||||
return visited;
|
||||
}
|
||||
|
||||
function returnCapturedThis(node: Node): Node {
|
||||
return setOriginalNode(createReturn(createIdentifier("_this")), node);
|
||||
}
|
||||
|
||||
function isReturnVoidStatementInConstructorWithCapturedSuper(node: Node): boolean {
|
||||
return isInConstructorWithCapturedSuper && node.kind === SyntaxKind.ReturnStatement && !(<ReturnStatement>node).expression;
|
||||
}
|
||||
|
||||
function shouldCheckNode(node: Node): boolean {
|
||||
return (node.transformFlags & TransformFlags.ES2015) !== 0 ||
|
||||
node.kind === SyntaxKind.LabeledStatement ||
|
||||
@ -258,10 +270,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitorWorker(node: Node): VisitResult<Node> {
|
||||
if (shouldCheckNode(node)) {
|
||||
if (isReturnVoidStatementInConstructorWithCapturedSuper(node)) {
|
||||
return returnCapturedThis(<ReturnStatement>node);
|
||||
}
|
||||
else if (shouldCheckNode(node)) {
|
||||
return visitJavaScript(node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.ContainsES2015) {
|
||||
else if (node.transformFlags & TransformFlags.ContainsES2015 || (isInConstructorWithCapturedSuper && !isExpression(node))) {
|
||||
// we want to dive in this branch either if node has children with ES2015 specific syntax
|
||||
// or we are inside constructor that captures result of the super call so all returns without expression should be
|
||||
// rewritten. Note: we skip expressions since returns should never appear there
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
else {
|
||||
@ -283,6 +301,7 @@ namespace ts {
|
||||
function visitNodesInConvertedLoop(node: Node): VisitResult<Node> {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ReturnStatement:
|
||||
node = isReturnVoidStatementInConstructorWithCapturedSuper(node) ? returnCapturedThis(node) : node;
|
||||
return visitReturnStatement(<ReturnStatement>node);
|
||||
|
||||
case SyntaxKind.VariableStatement:
|
||||
@ -308,8 +327,8 @@ namespace ts {
|
||||
|
||||
function visitJavaScript(node: Node): VisitResult<Node> {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ExportKeyword:
|
||||
return node;
|
||||
case SyntaxKind.StaticKeyword:
|
||||
return undefined; // elide static keyword
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return visitClassDeclaration(<ClassDeclaration>node);
|
||||
@ -362,6 +381,9 @@ namespace ts {
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return visitObjectLiteralExpression(<ObjectLiteralExpression>node);
|
||||
|
||||
case SyntaxKind.CatchClause:
|
||||
return visitCatchClause(<CatchClause>node);
|
||||
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
return visitShorthandPropertyAssignment(<ShorthandPropertyAssignment>node);
|
||||
|
||||
@ -584,47 +606,39 @@ namespace ts {
|
||||
// return C;
|
||||
// }());
|
||||
|
||||
const modifierFlags = getModifierFlags(node);
|
||||
const isExported = modifierFlags & ModifierFlags.Export;
|
||||
const isDefault = modifierFlags & ModifierFlags.Default;
|
||||
|
||||
// Add an `export` modifier to the statement if needed (for `--target es5 --module es6`)
|
||||
const modifiers = isExported && !isDefault
|
||||
? filter(node.modifiers, isExportModifier)
|
||||
: undefined;
|
||||
|
||||
const statement = createVariableStatement(
|
||||
modifiers,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
getDeclarationName(node, /*allowComments*/ true),
|
||||
/*type*/ undefined,
|
||||
transformClassLikeDeclarationToExpression(node)
|
||||
)
|
||||
]),
|
||||
/*location*/ node
|
||||
const variable = createVariableDeclaration(
|
||||
getLocalName(node, /*allowComments*/ true),
|
||||
/*type*/ undefined,
|
||||
transformClassLikeDeclarationToExpression(node)
|
||||
);
|
||||
|
||||
setOriginalNode(variable, node);
|
||||
|
||||
const statements: Statement[] = [];
|
||||
const statement = createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([variable]), /*location*/ node);
|
||||
|
||||
setOriginalNode(statement, node);
|
||||
startOnNewLine(statement);
|
||||
statements.push(statement);
|
||||
|
||||
// Add an `export default` statement for default exports (for `--target es5 --module es6`)
|
||||
if (isExported && isDefault) {
|
||||
const statements: Statement[] = [statement];
|
||||
statements.push(createExportAssignment(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*isExportEquals*/ false,
|
||||
getDeclarationName(node, /*allowComments*/ false)
|
||||
));
|
||||
return statements;
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
const exportStatement = hasModifier(node, ModifierFlags.Default)
|
||||
? createExportDefault(getLocalName(node))
|
||||
: createExternalModuleExport(getLocalName(node));
|
||||
|
||||
setOriginalNode(exportStatement, statement);
|
||||
statements.push(exportStatement);
|
||||
}
|
||||
|
||||
return statement;
|
||||
}
|
||||
const emitFlags = getEmitFlags(node);
|
||||
if ((emitFlags & EmitFlags.HasEndOfDeclarationMarker) === 0) {
|
||||
// Add a DeclarationMarker as a marker for the end of the declaration
|
||||
statements.push(createEndOfDeclarationMarker(node));
|
||||
setEmitFlags(statement, emitFlags | EmitFlags.HasEndOfDeclarationMarker);
|
||||
}
|
||||
|
||||
function isExportModifier(node: Modifier) {
|
||||
return node.kind === SyntaxKind.ExportKeyword;
|
||||
return singleOrMany(statements);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -685,7 +699,7 @@ namespace ts {
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
extendsClauseElement ? [createParameter("_super")] : [],
|
||||
extendsClauseElement ? [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "_super")] : [],
|
||||
/*type*/ undefined,
|
||||
transformClassBody(node, extendsClauseElement)
|
||||
);
|
||||
@ -764,7 +778,7 @@ namespace ts {
|
||||
if (extendsClauseElement) {
|
||||
statements.push(
|
||||
createStatement(
|
||||
createExtendsHelper(currentSourceFile.externalHelpersModuleName, getDeclarationName(node)),
|
||||
createExtendsHelper(currentSourceFile.externalHelpersModuleName, getLocalName(node)),
|
||||
/*location*/ extendsClauseElement
|
||||
)
|
||||
);
|
||||
@ -861,7 +875,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (constructor) {
|
||||
const body = saveStateAndInvoke(constructor, constructor => visitNodes(constructor.body.statements, visitor, isStatement, /*start*/ statementOffset));
|
||||
const body = saveStateAndInvoke(constructor, constructor => {
|
||||
isInConstructorWithCapturedSuper = superCaptureStatus === SuperCaptureResult.ReplaceSuperCapture;
|
||||
return visitNodes(constructor.body.statements, visitor, isStatement, /*start*/ statementOffset);
|
||||
});
|
||||
addRange(statements, body);
|
||||
}
|
||||
|
||||
@ -1035,7 +1052,12 @@ namespace ts {
|
||||
// evaluated inside the function body.
|
||||
return setOriginalNode(
|
||||
createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
getGeneratedNameForNode(node),
|
||||
/*questionToken*/ undefined,
|
||||
/*type*/ undefined,
|
||||
/*initializer*/ undefined,
|
||||
/*location*/ node
|
||||
),
|
||||
@ -1046,7 +1068,12 @@ namespace ts {
|
||||
// Initializers are elided
|
||||
return setOriginalNode(
|
||||
createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
node.name,
|
||||
/*questionToken*/ undefined,
|
||||
/*type*/ undefined,
|
||||
/*initializer*/ undefined,
|
||||
/*location*/ node
|
||||
),
|
||||
@ -1690,7 +1717,7 @@ namespace ts {
|
||||
if (decl.initializer) {
|
||||
let assignment: Expression;
|
||||
if (isBindingPattern(decl.name)) {
|
||||
assignment = flattenVariableDestructuringToExpression(decl, hoistVariableDeclaration, /*nameSubstitution*/ undefined, visitor);
|
||||
assignment = flattenVariableDestructuringToExpression(decl, hoistVariableDeclaration, /*createAssignmentCallback*/ undefined, visitor);
|
||||
}
|
||||
else {
|
||||
assignment = createBinary(<Identifier>decl.name, SyntaxKind.EqualsToken, visitNode(decl.initializer, visitor, isExpression));
|
||||
@ -1973,13 +2000,16 @@ namespace ts {
|
||||
statements.push(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
firstOriginalDeclaration ? firstOriginalDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined),
|
||||
/*type*/ undefined,
|
||||
createElementAccess(rhsReference, counter)
|
||||
)
|
||||
], /*location*/ moveRangePos(initializer, -1)),
|
||||
setOriginalNode(
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
firstOriginalDeclaration ? firstOriginalDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined),
|
||||
/*type*/ undefined,
|
||||
createElementAccess(rhsReference, counter)
|
||||
)
|
||||
], /*location*/ moveRangePos(initializer, -1)),
|
||||
initializer
|
||||
),
|
||||
/*location*/ moveRangeEnd(initializer, -1)
|
||||
)
|
||||
);
|
||||
@ -2041,10 +2071,13 @@ namespace ts {
|
||||
setEmitFlags(body, EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps);
|
||||
|
||||
const forStatement = createFor(
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0), /*location*/ moveRangePos(node.expression, -1)),
|
||||
createVariableDeclaration(rhsReference, /*type*/ undefined, expression, /*location*/ node.expression)
|
||||
], /*location*/ node.expression),
|
||||
setEmitFlags(
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0), /*location*/ moveRangePos(node.expression, -1)),
|
||||
createVariableDeclaration(rhsReference, /*type*/ undefined, expression, /*location*/ node.expression)
|
||||
], /*location*/ node.expression),
|
||||
EmitFlags.NoHoisting
|
||||
),
|
||||
createLessThan(
|
||||
counter,
|
||||
createPropertyAccess(rhsReference, "length"),
|
||||
@ -2236,25 +2269,28 @@ namespace ts {
|
||||
const convertedLoopVariable =
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
[
|
||||
createVariableDeclaration(
|
||||
functionName,
|
||||
/*type*/ undefined,
|
||||
setEmitFlags(
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
isAsyncBlockContainingAwait ? createToken(SyntaxKind.AsteriskToken) : undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
loopParameters,
|
||||
/*type*/ undefined,
|
||||
<Block>loopBody
|
||||
),
|
||||
loopBodyFlags
|
||||
setEmitFlags(
|
||||
createVariableDeclarationList(
|
||||
[
|
||||
createVariableDeclaration(
|
||||
functionName,
|
||||
/*type*/ undefined,
|
||||
setEmitFlags(
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
isAsyncBlockContainingAwait ? createToken(SyntaxKind.AsteriskToken) : undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
loopParameters,
|
||||
/*type*/ undefined,
|
||||
<Block>loopBody
|
||||
),
|
||||
loopBodyFlags
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
EmitFlags.NoHoisting
|
||||
)
|
||||
);
|
||||
|
||||
@ -2505,7 +2541,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
loopParameters.push(createParameter(name));
|
||||
loopParameters.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name));
|
||||
if (resolver.getNodeCheckFlags(decl) & NodeCheckFlags.NeedsLoopOutParameter) {
|
||||
const outParamName = createUniqueName("out_" + name.text);
|
||||
loopOutParameters.push({ originalName: name, outParamName });
|
||||
@ -2622,6 +2658,24 @@ namespace ts {
|
||||
return expression;
|
||||
}
|
||||
|
||||
function visitCatchClause(node: CatchClause): CatchClause {
|
||||
Debug.assert(isBindingPattern(node.variableDeclaration.name));
|
||||
|
||||
const temp = createTempVariable(undefined);
|
||||
const newVariableDeclaration = createVariableDeclaration(temp, undefined, undefined, node.variableDeclaration);
|
||||
|
||||
const vars = flattenVariableDestructuring(node.variableDeclaration, temp, visitor);
|
||||
const list = createVariableDeclarationList(vars, /*location*/node.variableDeclaration, /*flags*/node.variableDeclaration.flags);
|
||||
const destructure = createVariableStatement(undefined, list);
|
||||
|
||||
return updateCatchClause(node, newVariableDeclaration, addStatementToStartOfBlock(node.block, destructure));
|
||||
}
|
||||
|
||||
function addStatementToStartOfBlock(block: Block, statement: Statement): Block {
|
||||
const transformedStatements = visitNodes(block.statements, visitor, isStatement);
|
||||
return updateBlock(block, [statement].concat(transformedStatements));
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a MethodDeclaration of an ObjectLiteralExpression and transforms it into a
|
||||
* PropertyAssignment.
|
||||
@ -3080,9 +3134,8 @@ namespace ts {
|
||||
/**
|
||||
* Hooks node substitutions.
|
||||
*
|
||||
* @param emitContext The context for the emitter.
|
||||
* @param node The node to substitute.
|
||||
* @param isExpression A value indicating whether the node is to be used in an expression
|
||||
* position.
|
||||
*/
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
@ -3182,45 +3235,6 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local name for a declaration for use in expressions.
|
||||
*
|
||||
* A local name will *never* be prefixed with an module or namespace export modifier like
|
||||
* "exports.".
|
||||
*
|
||||
* @param node The declaration.
|
||||
* @param allowComments A value indicating whether comments may be emitted for the name.
|
||||
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
||||
*/
|
||||
function getLocalName(node: ClassDeclaration | ClassExpression | FunctionDeclaration, allowComments?: boolean, allowSourceMaps?: boolean) {
|
||||
return getDeclarationName(node, allowComments, allowSourceMaps, EmitFlags.LocalName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of a declaration, without source map or comments.
|
||||
*
|
||||
* @param node The declaration.
|
||||
* @param allowComments Allow comments for the name.
|
||||
*/
|
||||
function getDeclarationName(node: ClassDeclaration | ClassExpression | FunctionDeclaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags?: EmitFlags) {
|
||||
if (node.name && !isGeneratedIdentifier(node.name)) {
|
||||
const name = getMutableClone(node.name);
|
||||
emitFlags |= getEmitFlags(node.name);
|
||||
if (!allowSourceMaps) {
|
||||
emitFlags |= EmitFlags.NoSourceMap;
|
||||
}
|
||||
if (!allowComments) {
|
||||
emitFlags |= EmitFlags.NoComments;
|
||||
}
|
||||
if (emitFlags) {
|
||||
setEmitFlags(name, emitFlags);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
return getGeneratedNameForNode(node);
|
||||
}
|
||||
|
||||
function getClassMemberPrefix(node: ClassExpression | ClassDeclaration, member: ClassElement) {
|
||||
const expression = getLocalName(node);
|
||||
return hasModifier(member, ModifierFlags.Static) ? expression : createPropertyAccess(expression, "prototype");
|
||||
|
||||
@ -262,7 +262,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody | FunctionBody {
|
||||
const nodeType = node.original ? (<FunctionLikeDeclaration>node.original).type : node.type;
|
||||
const original = getOriginalNode(node, isFunctionLike);
|
||||
const nodeType = original.type;
|
||||
const promiseConstructor = languageVersion < ScriptTarget.ES2015 ? getPromiseConstructor(nodeType) : undefined;
|
||||
const isArrowFunction = node.kind === SyntaxKind.ArrowFunction;
|
||||
const hasLexicalArguments = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureArguments) !== 0;
|
||||
@ -336,15 +337,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getPromiseConstructor(type: TypeNode) {
|
||||
const typeName = getEntityNameFromTypeNode(type);
|
||||
if (typeName && isEntityName(typeName)) {
|
||||
const serializationKind = resolver.getTypeReferenceSerializationKind(typeName);
|
||||
if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue
|
||||
|| serializationKind === TypeReferenceSerializationKind.Unknown) {
|
||||
return typeName;
|
||||
if (type) {
|
||||
const typeName = getEntityNameFromTypeNode(type);
|
||||
if (typeName && isEntityName(typeName)) {
|
||||
const serializationKind = resolver.getTypeReferenceSerializationKind(typeName);
|
||||
if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue
|
||||
|| serializationKind === TypeReferenceSerializationKind.Unknown) {
|
||||
return typeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
@ -2369,7 +2369,7 @@ namespace ts {
|
||||
labelExpressions = [];
|
||||
}
|
||||
|
||||
const expression = <LiteralExpression>createSynthesizedNode(SyntaxKind.NumericLiteral);
|
||||
const expression = createLiteral(-1);
|
||||
if (labelExpressions[label] === undefined) {
|
||||
labelExpressions[label] = [expression];
|
||||
}
|
||||
@ -2380,7 +2380,7 @@ namespace ts {
|
||||
return expression;
|
||||
}
|
||||
|
||||
return <OmittedExpression>createNode(SyntaxKind.OmittedExpression);
|
||||
return createOmittedExpression();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2596,7 +2596,7 @@ namespace ts {
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(state)],
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)],
|
||||
/*type*/ undefined,
|
||||
createBlock(
|
||||
buildResult,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -48,7 +48,7 @@ namespace ts {
|
||||
let currentNamespaceContainerName: Identifier;
|
||||
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
|
||||
let currentScopeFirstDeclarationsOfName: Map<Node>;
|
||||
let currentSourceFileExternalHelpersModuleName: Identifier;
|
||||
let currentExternalHelpersModuleName: Identifier;
|
||||
|
||||
/**
|
||||
* Keeps track of whether expression substitution has been enabled for specific edge cases.
|
||||
@ -241,6 +241,18 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function modifierVisitor(node: Node): VisitResult<Node> {
|
||||
if (modifierToFlag(node.kind) & ModifierFlags.TypeScriptModifier) {
|
||||
return undefined;
|
||||
}
|
||||
else if (currentNamespace && node.kind === SyntaxKind.ExportKeyword) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Branching visitor, visits a TypeScript syntax node.
|
||||
*
|
||||
@ -477,16 +489,16 @@ namespace ts {
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText)
|
||||
);
|
||||
createLiteral(externalHelpersModuleNameText));
|
||||
|
||||
externalHelpersModuleImport.parent = node;
|
||||
externalHelpersModuleImport.flags &= ~NodeFlags.Synthesized;
|
||||
statements.push(externalHelpersModuleImport);
|
||||
|
||||
currentSourceFileExternalHelpersModuleName = externalHelpersModuleName;
|
||||
currentExternalHelpersModuleName = externalHelpersModuleName;
|
||||
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
currentSourceFileExternalHelpersModuleName = undefined;
|
||||
currentExternalHelpersModuleName = undefined;
|
||||
|
||||
node = updateSourceFileNode(node, createNodeArray(statements, node.statements));
|
||||
node.externalHelpersModuleName = externalHelpersModuleName;
|
||||
@ -537,7 +549,6 @@ namespace ts {
|
||||
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
|
||||
const hasExtendsClause = getClassExtendsHeritageClauseElement(node) !== undefined;
|
||||
const isDecoratedClass = shouldEmitDecorateCallForClass(node);
|
||||
let classAlias: Identifier;
|
||||
|
||||
// emit name if
|
||||
// - node has a name
|
||||
@ -548,33 +559,11 @@ namespace ts {
|
||||
name = getGeneratedNameForNode(node);
|
||||
}
|
||||
|
||||
const statements: Statement[] = [];
|
||||
if (!isDecoratedClass) {
|
||||
// ${modifiers} class ${name} ${heritageClauses} {
|
||||
// ${members}
|
||||
// }
|
||||
const classDeclaration = createClassDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.heritageClauses, visitor, isHeritageClause),
|
||||
transformClassMembers(node, hasExtendsClause),
|
||||
/*location*/ node
|
||||
);
|
||||
setOriginalNode(classDeclaration, node);
|
||||
const classStatement = isDecoratedClass
|
||||
? createClassDeclarationHeadWithDecorators(node, name, hasExtendsClause)
|
||||
: createClassDeclarationHeadWithoutDecorators(node, name, hasExtendsClause, staticProperties.length > 0);
|
||||
|
||||
// To better align with the old emitter, we should not emit a trailing source map
|
||||
// entry if the class has static properties.
|
||||
if (staticProperties.length > 0) {
|
||||
setEmitFlags(classDeclaration, EmitFlags.NoTrailingSourceMap | getEmitFlags(classDeclaration));
|
||||
}
|
||||
|
||||
statements.push(classDeclaration);
|
||||
}
|
||||
else {
|
||||
classAlias = addClassDeclarationHeadWithDecorators(statements, node, name, hasExtendsClause);
|
||||
}
|
||||
const statements: Statement[] = [classStatement];
|
||||
|
||||
// Emit static property assignment. Because classDeclaration is lexically evaluated,
|
||||
// it is safe to emit static property assignment after classDeclaration
|
||||
@ -582,13 +571,13 @@ namespace ts {
|
||||
// HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using
|
||||
// a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
|
||||
if (staticProperties.length) {
|
||||
addInitializedPropertyStatements(statements, staticProperties, getLocalName(node, /*noSourceMaps*/ true));
|
||||
addInitializedPropertyStatements(statements, staticProperties, getLocalName(node));
|
||||
}
|
||||
|
||||
// Write any decorators of the node.
|
||||
addClassElementDecorationStatements(statements, node, /*isStatic*/ false);
|
||||
addClassElementDecorationStatements(statements, node, /*isStatic*/ true);
|
||||
addConstructorDecorationStatement(statements, node, classAlias);
|
||||
addConstructorDecorationStatement(statements, node);
|
||||
|
||||
// If the class is exported as part of a TypeScript namespace, emit the namespace export.
|
||||
// Otherwise, if the class was exported at the top level and was decorated, emit an export
|
||||
@ -598,29 +587,66 @@ namespace ts {
|
||||
}
|
||||
else if (isDecoratedClass) {
|
||||
if (isDefaultExternalModuleExport(node)) {
|
||||
statements.push(createExportAssignment(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*isExportEquals*/ false,
|
||||
getLocalName(node)));
|
||||
statements.push(createExportDefault(getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)));
|
||||
}
|
||||
else if (isNamedExternalModuleExport(node)) {
|
||||
statements.push(createExternalModuleExport(name));
|
||||
statements.push(createExternalModuleExport(getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)));
|
||||
}
|
||||
}
|
||||
|
||||
return statements;
|
||||
if (statements.length > 1) {
|
||||
// Add a DeclarationMarker as a marker for the end of the declaration
|
||||
statements.push(createEndOfDeclarationMarker(node));
|
||||
setEmitFlags(classStatement, getEmitFlags(classStatement) | EmitFlags.HasEndOfDeclarationMarker);
|
||||
}
|
||||
|
||||
return singleOrMany(statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a non-decorated class declaration and appends the resulting statements.
|
||||
*
|
||||
* @param node A ClassDeclaration node.
|
||||
* @param name The name of the class.
|
||||
* @param hasExtendsClause A value indicating whether the class has an extends clause.
|
||||
* @param hasStaticProperties A value indicating whether the class has static properties.
|
||||
*/
|
||||
function createClassDeclarationHeadWithoutDecorators(node: ClassDeclaration, name: Identifier, hasExtendsClause: boolean, hasStaticProperties: boolean) {
|
||||
// ${modifiers} class ${name} ${heritageClauses} {
|
||||
// ${members}
|
||||
// }
|
||||
const classDeclaration = createClassDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.heritageClauses, visitor, isHeritageClause),
|
||||
transformClassMembers(node, hasExtendsClause),
|
||||
node);
|
||||
|
||||
let emitFlags = getEmitFlags(node);
|
||||
|
||||
// To better align with the old emitter, we should not emit a trailing source map
|
||||
// entry if the class has static properties.
|
||||
if (hasStaticProperties) {
|
||||
emitFlags |= EmitFlags.NoTrailingSourceMap;
|
||||
}
|
||||
|
||||
setOriginalNode(classDeclaration, node);
|
||||
setEmitFlags(classDeclaration, emitFlags);
|
||||
return classDeclaration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a decorated class declaration and appends the resulting statements. If
|
||||
* the class requires an alias to avoid issues with double-binding, the alias is returned.
|
||||
*
|
||||
* @param statements A statement list to which to add the declaration.
|
||||
* @param node A ClassDeclaration node.
|
||||
* @param name The name of the class.
|
||||
* @param hasExtendsClause A value indicating whether
|
||||
* @param hasExtendsClause A value indicating whether the class has an extends clause.
|
||||
*/
|
||||
function addClassDeclarationHeadWithDecorators(statements: Statement[], node: ClassDeclaration, name: Identifier, hasExtendsClause: boolean) {
|
||||
function createClassDeclarationHeadWithDecorators(node: ClassDeclaration, name: Identifier, hasExtendsClause: boolean) {
|
||||
// When we emit an ES6 class that has a class decorator, we must tailor the
|
||||
// emit to certain specific cases.
|
||||
//
|
||||
@ -655,20 +681,20 @@ namespace ts {
|
||||
// ---------------------------------------------------------------------
|
||||
// TypeScript | Javascript
|
||||
// ---------------------------------------------------------------------
|
||||
// @dec | let C_1 = class C {
|
||||
// @dec | let C = C_1 = class C {
|
||||
// class C { | static x() { return C_1.y; }
|
||||
// static x() { return C.y; } | }
|
||||
// static y = 1; | let C = C_1;
|
||||
// } | C.y = 1;
|
||||
// | C = C_1 = __decorate([dec], C);
|
||||
// static y = 1; | C.y = 1;
|
||||
// } | C = C_1 = __decorate([dec], C);
|
||||
// | var C_1;
|
||||
// ---------------------------------------------------------------------
|
||||
// @dec | let C_1 = class C {
|
||||
// @dec | let C = class C {
|
||||
// export class C { | static x() { return C_1.y; }
|
||||
// static x() { return C.y; } | }
|
||||
// static y = 1; | let C = C_1;
|
||||
// } | C.y = 1;
|
||||
// | C = C_1 = __decorate([dec], C);
|
||||
// static y = 1; | C.y = 1;
|
||||
// } | C = C_1 = __decorate([dec], C);
|
||||
// | export { C };
|
||||
// | var C_1;
|
||||
// ---------------------------------------------------------------------
|
||||
//
|
||||
// If a class declaration is the default export of a module, we instead emit
|
||||
@ -697,92 +723,34 @@ namespace ts {
|
||||
// ---------------------------------------------------------------------
|
||||
// TypeScript | Javascript
|
||||
// ---------------------------------------------------------------------
|
||||
// @dec | let C_1 = class C {
|
||||
// @dec | let C = class C {
|
||||
// export default class C { | static x() { return C_1.y; }
|
||||
// static x() { return C.y; } | }
|
||||
// static y = 1; | let C = C_1;
|
||||
// } | C.y = 1;
|
||||
// | C = C_1 = __decorate([dec], C);
|
||||
// static y = 1; | C.y = 1;
|
||||
// } | C = C_1 = __decorate([dec], C);
|
||||
// | export default C;
|
||||
// | var C_1;
|
||||
// ---------------------------------------------------------------------
|
||||
//
|
||||
|
||||
const location = moveRangePastDecorators(node);
|
||||
const classAlias = getClassAliasIfNeeded(node);
|
||||
const declName = getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true);
|
||||
|
||||
// ... = class ${name} ${heritageClauses} {
|
||||
// ${members}
|
||||
// }
|
||||
const classExpression: Expression = setOriginalNode(
|
||||
createClassExpression(
|
||||
/*modifiers*/ undefined,
|
||||
name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.heritageClauses, visitor, isHeritageClause),
|
||||
transformClassMembers(node, hasExtendsClause),
|
||||
/*location*/ location
|
||||
),
|
||||
node
|
||||
);
|
||||
|
||||
if (!name) {
|
||||
name = getGeneratedNameForNode(node);
|
||||
}
|
||||
|
||||
// Record an alias to avoid class double-binding.
|
||||
let classAlias: Identifier;
|
||||
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) {
|
||||
enableSubstitutionForClassAliases();
|
||||
classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? node.name.text : "default");
|
||||
classAliases[getOriginalNodeId(node)] = classAlias;
|
||||
}
|
||||
|
||||
const declaredName = getDeclarationName(node, /*allowComments*/ true);
|
||||
const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause);
|
||||
const members = transformClassMembers(node, hasExtendsClause);
|
||||
const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members, location);
|
||||
setOriginalNode(classExpression, node);
|
||||
|
||||
// let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference
|
||||
// or decoratedClassAlias if the class contain self-reference.
|
||||
const transformedClassExpression = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createLetDeclarationList([
|
||||
createVariableDeclaration(
|
||||
classAlias || declaredName,
|
||||
/*type*/ undefined,
|
||||
classExpression
|
||||
)
|
||||
]),
|
||||
/*location*/ location
|
||||
);
|
||||
setCommentRange(transformedClassExpression, node);
|
||||
statements.push(
|
||||
setOriginalNode(
|
||||
/*node*/ transformedClassExpression,
|
||||
/*original*/ node
|
||||
)
|
||||
);
|
||||
|
||||
if (classAlias) {
|
||||
// We emit the class alias as a `let` declaration here so that it has the same
|
||||
// TDZ as the class.
|
||||
|
||||
// let ${declaredName} = ${decoratedClassAlias}
|
||||
statements.push(
|
||||
setOriginalNode(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createLetDeclarationList([
|
||||
createVariableDeclaration(
|
||||
declaredName,
|
||||
/*type*/ undefined,
|
||||
classAlias
|
||||
)
|
||||
]),
|
||||
/*location*/ location
|
||||
),
|
||||
/*original*/ node
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return classAlias;
|
||||
const statement = createLetStatement(declName, classAlias ? createAssignment(classAlias, classExpression) : classExpression, location);
|
||||
setOriginalNode(statement, node);
|
||||
setCommentRange(statement, node);
|
||||
return statement;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -992,7 +960,7 @@ namespace ts {
|
||||
statements,
|
||||
/*location*/ constructor ? constructor.body.statements : node.members
|
||||
),
|
||||
/*location*/ constructor ? constructor.body : undefined
|
||||
/*location*/ constructor ? constructor.body : /*location*/ undefined
|
||||
),
|
||||
true
|
||||
);
|
||||
@ -1452,7 +1420,7 @@ namespace ts {
|
||||
: undefined;
|
||||
|
||||
const helper = createDecorateHelper(
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
currentExternalHelpersModuleName,
|
||||
decoratorExpressions,
|
||||
prefix,
|
||||
memberName,
|
||||
@ -1469,8 +1437,8 @@ namespace ts {
|
||||
*
|
||||
* @param node The class node.
|
||||
*/
|
||||
function addConstructorDecorationStatement(statements: Statement[], node: ClassDeclaration, decoratedClassAlias: Identifier) {
|
||||
const expression = generateConstructorDecorationExpression(node, decoratedClassAlias);
|
||||
function addConstructorDecorationStatement(statements: Statement[], node: ClassDeclaration) {
|
||||
const expression = generateConstructorDecorationExpression(node);
|
||||
if (expression) {
|
||||
statements.push(setOriginalNode(createStatement(expression), node));
|
||||
}
|
||||
@ -1481,61 +1449,20 @@ namespace ts {
|
||||
*
|
||||
* @param node The class node.
|
||||
*/
|
||||
function generateConstructorDecorationExpression(node: ClassExpression | ClassDeclaration, decoratedClassAlias: Identifier) {
|
||||
function generateConstructorDecorationExpression(node: ClassExpression | ClassDeclaration) {
|
||||
const allDecorators = getAllDecoratorsOfConstructor(node);
|
||||
const decoratorExpressions = transformAllDecoratorsOfDeclaration(node, allDecorators);
|
||||
if (!decoratorExpressions) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Emit the call to __decorate. Given the class:
|
||||
//
|
||||
// @dec
|
||||
// class C {
|
||||
// }
|
||||
//
|
||||
// The emit for the class is:
|
||||
//
|
||||
// C = C_1 = __decorate([dec], C);
|
||||
//
|
||||
if (decoratedClassAlias) {
|
||||
const expression = createAssignment(
|
||||
decoratedClassAlias,
|
||||
createDecorateHelper(
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
decoratorExpressions,
|
||||
getDeclarationName(node)
|
||||
)
|
||||
);
|
||||
|
||||
const result = createAssignment(getDeclarationName(node), expression, moveRangePastDecorators(node));
|
||||
setEmitFlags(result, EmitFlags.NoComments);
|
||||
return result;
|
||||
}
|
||||
// Emit the call to __decorate. Given the class:
|
||||
//
|
||||
// @dec
|
||||
// export declare class C {
|
||||
// }
|
||||
//
|
||||
// The emit for the class is:
|
||||
//
|
||||
// C = __decorate([dec], C);
|
||||
//
|
||||
else {
|
||||
const result = createAssignment(
|
||||
getDeclarationName(node),
|
||||
createDecorateHelper(
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
decoratorExpressions,
|
||||
getDeclarationName(node)
|
||||
),
|
||||
moveRangePastDecorators(node)
|
||||
);
|
||||
|
||||
setEmitFlags(result, EmitFlags.NoComments);
|
||||
return result;
|
||||
}
|
||||
const classAlias = classAliases && classAliases[getOriginalNodeId(node)];
|
||||
const localName = getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true);
|
||||
const decorate = createDecorateHelper(currentExternalHelpersModuleName, decoratorExpressions, localName);
|
||||
const expression = createAssignment(localName, classAlias ? createAssignment(classAlias, decorate) : decorate);
|
||||
setEmitFlags(expression, EmitFlags.NoComments);
|
||||
setSourceMapRange(expression, moveRangePastDecorators(node));
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1559,7 +1486,7 @@ namespace ts {
|
||||
expressions = [];
|
||||
for (const decorator of decorators) {
|
||||
const helper = createParamHelper(
|
||||
currentSourceFileExternalHelpersModuleName,
|
||||
currentExternalHelpersModuleName,
|
||||
transformDecorator(decorator),
|
||||
parameterOffset,
|
||||
/*location*/ decorator.expression);
|
||||
@ -1589,13 +1516,13 @@ namespace ts {
|
||||
function addOldTypeMetadata(node: Declaration, decoratorExpressions: Expression[]) {
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
if (shouldAddTypeMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:type", serializeTypeOfNode(node)));
|
||||
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:type", serializeTypeOfNode(node)));
|
||||
}
|
||||
if (shouldAddParamTypesMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:paramtypes", serializeParameterTypesOfNode(node)));
|
||||
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:paramtypes", serializeParameterTypesOfNode(node)));
|
||||
}
|
||||
if (shouldAddReturnTypeMetadata(node)) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:returntype", serializeReturnTypeOfNode(node)));
|
||||
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:returntype", serializeReturnTypeOfNode(node)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1604,16 +1531,16 @@ namespace ts {
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
let properties: ObjectLiteralElementLike[];
|
||||
if (shouldAddTypeMetadata(node)) {
|
||||
(properties || (properties = [])).push(createPropertyAssignment("type", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, serializeTypeOfNode(node))));
|
||||
(properties || (properties = [])).push(createPropertyAssignment("type", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeTypeOfNode(node))));
|
||||
}
|
||||
if (shouldAddParamTypesMetadata(node)) {
|
||||
(properties || (properties = [])).push(createPropertyAssignment("paramTypes", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, serializeParameterTypesOfNode(node))));
|
||||
(properties || (properties = [])).push(createPropertyAssignment("paramTypes", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeParameterTypesOfNode(node))));
|
||||
}
|
||||
if (shouldAddReturnTypeMetadata(node)) {
|
||||
(properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, serializeReturnTypeOfNode(node))));
|
||||
(properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeReturnTypeOfNode(node))));
|
||||
}
|
||||
if (properties) {
|
||||
decoratorExpressions.push(createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)));
|
||||
decoratorExpressions.push(createMetadataHelper(currentExternalHelpersModuleName, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2133,7 +2060,7 @@ namespace ts {
|
||||
|
||||
const method = createMethod(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
node.asteriskToken,
|
||||
visitPropertyNameOfClassElement(node),
|
||||
/*typeParameters*/ undefined,
|
||||
@ -2178,7 +2105,7 @@ namespace ts {
|
||||
|
||||
const accessor = createGetAccessor(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
visitPropertyNameOfClassElement(node),
|
||||
visitNodes(node.parameters, visitor, isParameter),
|
||||
/*type*/ undefined,
|
||||
@ -2188,9 +2115,9 @@ namespace ts {
|
||||
|
||||
// While we emit the source map for the node after skipping decorators and modifiers,
|
||||
// we need to emit the comments for the original range.
|
||||
setOriginalNode(accessor, node);
|
||||
setCommentRange(accessor, node);
|
||||
setSourceMapRange(accessor, moveRangePastDecorators(node));
|
||||
setOriginalNode(accessor, node);
|
||||
|
||||
return accessor;
|
||||
}
|
||||
@ -2211,7 +2138,7 @@ namespace ts {
|
||||
|
||||
const accessor = createSetAccessor(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
visitPropertyNameOfClassElement(node),
|
||||
visitNodes(node.parameters, visitor, isParameter),
|
||||
node.body ? visitEachChild(node.body, visitor, context) : createBlock([]),
|
||||
@ -2220,9 +2147,9 @@ namespace ts {
|
||||
|
||||
// While we emit the source map for the node after skipping decorators and modifiers,
|
||||
// we need to emit the comments for the original range.
|
||||
setOriginalNode(accessor, node);
|
||||
setCommentRange(accessor, node);
|
||||
setSourceMapRange(accessor, moveRangePastDecorators(node));
|
||||
setOriginalNode(accessor, node);
|
||||
|
||||
return accessor;
|
||||
}
|
||||
@ -2244,7 +2171,7 @@ namespace ts {
|
||||
|
||||
const func = createFunctionDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
node.asteriskToken,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
@ -2278,7 +2205,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const func = createFunctionExpression(
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
node.asteriskToken,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
@ -2300,7 +2227,7 @@ namespace ts {
|
||||
*/
|
||||
function visitArrowFunction(node: ArrowFunction) {
|
||||
const func = createArrowFunction(
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.parameters, visitor, isParameter),
|
||||
/*type*/ undefined,
|
||||
@ -2372,7 +2299,7 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const parameter = createParameterDeclaration(
|
||||
const parameter = createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
node.dotDotDotToken,
|
||||
@ -2425,7 +2352,7 @@ namespace ts {
|
||||
return flattenVariableDestructuringToExpression(
|
||||
node,
|
||||
hoistVariableDeclaration,
|
||||
getNamespaceMemberNameWithSourceMapsAndWithoutComments,
|
||||
createNamespaceExportExpression,
|
||||
visitor
|
||||
);
|
||||
}
|
||||
@ -2515,29 +2442,6 @@ namespace ts {
|
||||
|| compilerOptions.isolatedModules;
|
||||
}
|
||||
|
||||
function shouldEmitVarForEnumDeclaration(node: EnumDeclaration | ModuleDeclaration) {
|
||||
return isFirstEmittedDeclarationInScope(node)
|
||||
&& (!hasModifier(node, ModifierFlags.Export)
|
||||
|| isES6ExportedDeclaration(node));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Adds a trailing VariableStatement for an enum or module declaration.
|
||||
*/
|
||||
function addVarForEnumExportedFromNamespace(statements: Statement[], node: EnumDeclaration | ModuleDeclaration) {
|
||||
const statement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
[createVariableDeclaration(
|
||||
getDeclarationName(node),
|
||||
/*type*/ undefined,
|
||||
getExportName(node)
|
||||
)]
|
||||
);
|
||||
setSourceMapRange(statement, node);
|
||||
statements.push(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an enum declaration.
|
||||
*
|
||||
@ -2559,10 +2463,7 @@ namespace ts {
|
||||
// If needed, we should emit a variable declaration for the enum. If we emit
|
||||
// a leading variable declaration, we should not emit leading comments for the
|
||||
// enum body.
|
||||
recordEmittedDeclarationInScope(node);
|
||||
if (shouldEmitVarForEnumDeclaration(node)) {
|
||||
addVarForEnumOrModuleDeclaration(statements, node);
|
||||
|
||||
if (addVarForEnumOrModuleDeclaration(statements, node)) {
|
||||
// We should still emit the comments if we are emitting a system module.
|
||||
if (moduleKind !== ModuleKind.System || currentScope !== currentSourceFile) {
|
||||
emitFlags |= EmitFlags.NoLeadingComments;
|
||||
@ -2576,7 +2477,28 @@ namespace ts {
|
||||
const containerName = getNamespaceContainerName(node);
|
||||
|
||||
// `exportName` is the expression used within this node's container for any exported references.
|
||||
const exportName = getExportName(node);
|
||||
const exportName = hasModifier(node, ModifierFlags.Export)
|
||||
? getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true)
|
||||
: getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true);
|
||||
|
||||
// x || (x = {})
|
||||
// exports.x || (exports.x = {})
|
||||
let moduleArg =
|
||||
createLogicalOr(
|
||||
exportName,
|
||||
createAssignment(
|
||||
exportName,
|
||||
createObjectLiteral()
|
||||
)
|
||||
);
|
||||
|
||||
if (hasNamespaceQualifiedExportName(node)) {
|
||||
// `localName` is the expression used within this node's containing scope for any local references.
|
||||
const localName = getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true);
|
||||
|
||||
// x = (exports.x || (exports.x = {}))
|
||||
moduleArg = createAssignment(localName, moduleArg);
|
||||
}
|
||||
|
||||
// (function (x) {
|
||||
// x[x["y"] = 0] = "y";
|
||||
@ -2589,18 +2511,12 @@ namespace ts {
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(parameterName)],
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)],
|
||||
/*type*/ undefined,
|
||||
transformEnumBody(node, containerName)
|
||||
),
|
||||
/*typeArguments*/ undefined,
|
||||
[createLogicalOr(
|
||||
exportName,
|
||||
createAssignment(
|
||||
exportName,
|
||||
createObjectLiteral()
|
||||
)
|
||||
)]
|
||||
[moduleArg]
|
||||
),
|
||||
/*location*/ node
|
||||
);
|
||||
@ -2609,10 +2525,9 @@ namespace ts {
|
||||
setEmitFlags(enumStatement, emitFlags);
|
||||
statements.push(enumStatement);
|
||||
|
||||
if (isNamespaceExport(node)) {
|
||||
addVarForEnumExportedFromNamespace(statements, node);
|
||||
}
|
||||
|
||||
// Add a DeclarationMarker for the enum to preserve trailing comments and mark
|
||||
// the end of the declaration.
|
||||
statements.push(createEndOfDeclarationMarker(node));
|
||||
return statements;
|
||||
}
|
||||
|
||||
@ -2697,9 +2612,15 @@ namespace ts {
|
||||
return isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules);
|
||||
}
|
||||
|
||||
function isES6ExportedDeclaration(node: Node) {
|
||||
return isExternalModuleExport(node)
|
||||
&& moduleKind === ModuleKind.ES2015;
|
||||
/**
|
||||
* Determines whether an exported declaration will have a qualified export name (e.g. `f.x`
|
||||
* or `exports.x`).
|
||||
*/
|
||||
function hasNamespaceQualifiedExportName(node: Node) {
|
||||
return isNamespaceExport(node)
|
||||
|| (isExternalModuleExport(node)
|
||||
&& moduleKind !== ModuleKind.ES2015
|
||||
&& moduleKind !== ModuleKind.System);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2737,57 +2658,65 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function shouldEmitVarForModuleDeclaration(node: ModuleDeclaration) {
|
||||
return isFirstEmittedDeclarationInScope(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a leading VariableStatement for a enum or module declaration.
|
||||
*/
|
||||
function addVarForEnumOrModuleDeclaration(statements: Statement[], node: ModuleDeclaration | EnumDeclaration) {
|
||||
// Emit a variable statement for the module.
|
||||
const statement = createVariableStatement(
|
||||
isES6ExportedDeclaration(node)
|
||||
? visitNodes(node.modifiers, visitor, isModifier)
|
||||
: undefined,
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
[
|
||||
createVariableDeclaration(
|
||||
getDeclarationName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)
|
||||
getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
setOriginalNode(statement, /*original*/ node);
|
||||
setOriginalNode(statement, node);
|
||||
|
||||
// Adjust the source map emit to match the old emitter.
|
||||
if (node.kind === SyntaxKind.EnumDeclaration) {
|
||||
setSourceMapRange(statement.declarationList, node);
|
||||
recordEmittedDeclarationInScope(node);
|
||||
if (isFirstEmittedDeclarationInScope(node)) {
|
||||
// Adjust the source map emit to match the old emitter.
|
||||
if (node.kind === SyntaxKind.EnumDeclaration) {
|
||||
setSourceMapRange(statement.declarationList, node);
|
||||
}
|
||||
else {
|
||||
setSourceMapRange(statement, node);
|
||||
}
|
||||
|
||||
// Trailing comments for module declaration should be emitted after the function closure
|
||||
// instead of the variable statement:
|
||||
//
|
||||
// /** Module comment*/
|
||||
// module m1 {
|
||||
// function foo4Export() {
|
||||
// }
|
||||
// } // trailing comment module
|
||||
//
|
||||
// Should emit:
|
||||
//
|
||||
// /** Module comment*/
|
||||
// var m1;
|
||||
// (function (m1) {
|
||||
// function foo4Export() {
|
||||
// }
|
||||
// })(m1 || (m1 = {})); // trailing comment module
|
||||
//
|
||||
setCommentRange(statement, node);
|
||||
setEmitFlags(statement, EmitFlags.NoTrailingComments | EmitFlags.HasEndOfDeclarationMarker);
|
||||
statements.push(statement);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
setSourceMapRange(statement, node);
|
||||
// For an EnumDeclaration or ModuleDeclaration that merges with a preceeding
|
||||
// declaration we do not emit a leading variable declaration. To preserve the
|
||||
// begin/end semantics of the declararation and to properly handle exports
|
||||
// we wrap the leading variable declaration in a `MergeDeclarationMarker`.
|
||||
const mergeMarker = createMergeDeclarationMarker(statement);
|
||||
setEmitFlags(mergeMarker, EmitFlags.NoComments | EmitFlags.HasEndOfDeclarationMarker);
|
||||
statements.push(mergeMarker);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Trailing comments for module declaration should be emitted after the function closure
|
||||
// instead of the variable statement:
|
||||
//
|
||||
// /** Module comment*/
|
||||
// module m1 {
|
||||
// function foo4Export() {
|
||||
// }
|
||||
// } // trailing comment module
|
||||
//
|
||||
// Should emit:
|
||||
//
|
||||
// /** Module comment*/
|
||||
// var m1;
|
||||
// (function (m1) {
|
||||
// function foo4Export() {
|
||||
// }
|
||||
// })(m1 || (m1 = {})); // trailing comment module
|
||||
//
|
||||
setCommentRange(statement, node);
|
||||
setEmitFlags(statement, EmitFlags.NoTrailingComments);
|
||||
statements.push(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2814,9 +2743,7 @@ namespace ts {
|
||||
// If needed, we should emit a variable declaration for the module. If we emit
|
||||
// a leading variable declaration, we should not emit leading comments for the
|
||||
// module body.
|
||||
recordEmittedDeclarationInScope(node);
|
||||
if (shouldEmitVarForModuleDeclaration(node)) {
|
||||
addVarForEnumOrModuleDeclaration(statements, node);
|
||||
if (addVarForEnumOrModuleDeclaration(statements, node)) {
|
||||
// We should still emit the comments if we are emitting a system module.
|
||||
if (moduleKind !== ModuleKind.System || currentScope !== currentSourceFile) {
|
||||
emitFlags |= EmitFlags.NoLeadingComments;
|
||||
@ -2830,7 +2757,9 @@ namespace ts {
|
||||
const containerName = getNamespaceContainerName(node);
|
||||
|
||||
// `exportName` is the expression used within this node's container for any exported references.
|
||||
const exportName = getExportName(node);
|
||||
const exportName = hasModifier(node, ModifierFlags.Export)
|
||||
? getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true)
|
||||
: getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true);
|
||||
|
||||
// x || (x = {})
|
||||
// exports.x || (exports.x = {})
|
||||
@ -2843,9 +2772,9 @@ namespace ts {
|
||||
)
|
||||
);
|
||||
|
||||
if (hasModifier(node, ModifierFlags.Export) && !isES6ExportedDeclaration(node)) {
|
||||
if (hasNamespaceQualifiedExportName(node)) {
|
||||
// `localName` is the expression used within this node's containing scope for any local references.
|
||||
const localName = getLocalName(node);
|
||||
const localName = getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true);
|
||||
|
||||
// x = (exports.x || (exports.x = {}))
|
||||
moduleArg = createAssignment(localName, moduleArg);
|
||||
@ -2861,7 +2790,7 @@ namespace ts {
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(parameterName)],
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)],
|
||||
/*type*/ undefined,
|
||||
transformModuleBody(node, containerName)
|
||||
),
|
||||
@ -2874,6 +2803,10 @@ namespace ts {
|
||||
setOriginalNode(moduleStatement, node);
|
||||
setEmitFlags(moduleStatement, emitFlags);
|
||||
statements.push(moduleStatement);
|
||||
|
||||
// Add a DeclarationMarker for the namespace to preserve trailing comments and mark
|
||||
// the end of the declaration.
|
||||
statements.push(createEndOfDeclarationMarker(node));
|
||||
return statements;
|
||||
}
|
||||
|
||||
@ -3129,12 +3062,15 @@ namespace ts {
|
||||
// var ${name} = ${moduleReference};
|
||||
return setOriginalNode(
|
||||
createVariableStatement(
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
node.name,
|
||||
/*type*/ undefined,
|
||||
moduleReference
|
||||
setOriginalNode(
|
||||
createVariableDeclaration(
|
||||
node.name,
|
||||
/*type*/ undefined,
|
||||
moduleReference
|
||||
),
|
||||
node
|
||||
)
|
||||
]),
|
||||
node
|
||||
@ -3202,8 +3138,8 @@ namespace ts {
|
||||
|
||||
function addExportMemberAssignment(statements: Statement[], node: ClassDeclaration | FunctionDeclaration) {
|
||||
const expression = createAssignment(
|
||||
getExportName(node),
|
||||
getLocalName(node, /*noSourceMaps*/ true)
|
||||
getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true),
|
||||
getLocalName(node)
|
||||
);
|
||||
setSourceMapRange(expression, createRange(node.name.pos, node.end));
|
||||
|
||||
@ -3215,40 +3151,19 @@ namespace ts {
|
||||
function createNamespaceExport(exportName: Identifier, exportValue: Expression, location?: TextRange) {
|
||||
return createStatement(
|
||||
createAssignment(
|
||||
getNamespaceMemberName(exportName, /*allowComments*/ false, /*allowSourceMaps*/ true),
|
||||
getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true),
|
||||
exportValue
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
function createExternalModuleExport(exportName: Identifier) {
|
||||
return createExportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createNamedExports([
|
||||
createExportSpecifier(exportName)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
function getNamespaceMemberName(name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): Expression {
|
||||
const qualifiedName = createPropertyAccess(currentNamespaceContainerName, getSynthesizedClone(name), /*location*/ name);
|
||||
let emitFlags: EmitFlags;
|
||||
if (!allowComments) {
|
||||
emitFlags |= EmitFlags.NoComments;
|
||||
}
|
||||
if (!allowSourceMaps) {
|
||||
emitFlags |= EmitFlags.NoSourceMap;
|
||||
}
|
||||
if (emitFlags) {
|
||||
setEmitFlags(qualifiedName, emitFlags);
|
||||
}
|
||||
return qualifiedName;
|
||||
function createNamespaceExportExpression(exportName: Identifier, exportValue: Expression, location?: TextRange) {
|
||||
return createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue, location);
|
||||
}
|
||||
|
||||
function getNamespaceMemberNameWithSourceMapsAndWithoutComments(name: Identifier) {
|
||||
return getNamespaceMemberName(name, /*allowComments*/ false, /*allowSourceMaps*/ true);
|
||||
return getNamespaceMemberName(currentNamespaceContainerName, name, /*allowComments*/ false, /*allowSourceMaps*/ true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3269,65 +3184,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local name for a declaration for use in expressions.
|
||||
*
|
||||
* A local name will *never* be prefixed with an module or namespace export modifier like
|
||||
* "exports.".
|
||||
*
|
||||
* @param node The declaration.
|
||||
* @param noSourceMaps A value indicating whether source maps may not be emitted for the name.
|
||||
* @param allowComments A value indicating whether comments may be emitted for the name.
|
||||
* Gets a local alias for a class declaration if it is a decorated class with an internal
|
||||
* reference to the static side of the class. This is necessary to avoid issues with
|
||||
* double-binding semantics for the class name.
|
||||
*/
|
||||
function getLocalName(node: FunctionDeclaration | ClassDeclaration | ClassExpression | ModuleDeclaration | EnumDeclaration, noSourceMaps?: boolean, allowComments?: boolean) {
|
||||
return getDeclarationName(node, allowComments, !noSourceMaps, EmitFlags.LocalName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the export name for a declaration for use in expressions.
|
||||
*
|
||||
* An export name will *always* be prefixed with an module or namespace export modifier
|
||||
* like "exports." if one is required.
|
||||
*
|
||||
* @param node The declaration.
|
||||
* @param noSourceMaps A value indicating whether source maps may not be emitted for the name.
|
||||
* @param allowComments A value indicating whether comments may be emitted for the name.
|
||||
*/
|
||||
function getExportName(node: FunctionDeclaration | ClassDeclaration | ClassExpression | ModuleDeclaration | EnumDeclaration, noSourceMaps?: boolean, allowComments?: boolean) {
|
||||
if (isNamespaceExport(node)) {
|
||||
return getNamespaceMemberName(getDeclarationName(node), allowComments, !noSourceMaps);
|
||||
}
|
||||
|
||||
return getDeclarationName(node, allowComments, !noSourceMaps, EmitFlags.ExportName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name for a declaration for use in declarations.
|
||||
*
|
||||
* @param node The declaration.
|
||||
* @param allowComments A value indicating whether comments may be emitted for the name.
|
||||
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
||||
* @param emitFlags Additional NodeEmitFlags to specify for the name.
|
||||
*/
|
||||
function getDeclarationName(node: FunctionDeclaration | ClassDeclaration | ClassExpression | ModuleDeclaration | EnumDeclaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags?: EmitFlags) {
|
||||
if (node.name) {
|
||||
const name = getMutableClone(<Identifier>node.name);
|
||||
emitFlags |= getEmitFlags(node.name);
|
||||
if (!allowSourceMaps) {
|
||||
emitFlags |= EmitFlags.NoSourceMap;
|
||||
}
|
||||
|
||||
if (!allowComments) {
|
||||
emitFlags |= EmitFlags.NoComments;
|
||||
}
|
||||
|
||||
if (emitFlags) {
|
||||
setEmitFlags(name, emitFlags);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
else {
|
||||
return getGeneratedNameForNode(node);
|
||||
function getClassAliasIfNeeded(node: ClassDeclaration) {
|
||||
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) {
|
||||
enableSubstitutionForClassAliases();
|
||||
const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? node.name.text : "default");
|
||||
classAliases[getOriginalNodeId(node)] = classAlias;
|
||||
hoistVariableDeclaration(classAlias);
|
||||
return classAlias;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3386,6 +3253,7 @@ namespace ts {
|
||||
/**
|
||||
* Hook for node emit.
|
||||
*
|
||||
* @param emitContext A context hint for the emitter.
|
||||
* @param node The node to emit.
|
||||
* @param emit A callback used to emit the node in the printer.
|
||||
*/
|
||||
@ -3408,9 +3276,8 @@ namespace ts {
|
||||
/**
|
||||
* Hooks node substitutions.
|
||||
*
|
||||
* @param emitContext A context hint for the emitter.
|
||||
* @param node The node to substitute.
|
||||
* @param isExpression A value indicating whether the node is to be used in an expression
|
||||
* position.
|
||||
*/
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
@ -3486,11 +3353,11 @@ namespace ts {
|
||||
|
||||
function trySubstituteNamespaceExportedName(node: Identifier): Expression {
|
||||
// If this is explicitly a local name, do not substitute.
|
||||
if (enabledSubstitutions & applicableSubstitutions && (getEmitFlags(node) & EmitFlags.LocalName) === 0) {
|
||||
if (enabledSubstitutions & applicableSubstitutions && !isLocalName(node)) {
|
||||
// If we are nested within a namespace declaration, we may need to qualifiy
|
||||
// an identifier that is exported from a merged namespace.
|
||||
const container = resolver.getReferencedExportContainer(node, /*prefixLocals*/ false);
|
||||
if (container) {
|
||||
if (container && container.kind !== SyntaxKind.SourceFile) {
|
||||
const substitute =
|
||||
(applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && container.kind === SyntaxKind.ModuleDeclaration) ||
|
||||
(applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration);
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
"transformers/es2017.ts",
|
||||
"transformers/es2016.ts",
|
||||
"transformers/es2015.ts",
|
||||
"transformers/es5.ts",
|
||||
"transformers/generators.ts",
|
||||
"transformers/es5.ts",
|
||||
"transformers/destructuring.ts",
|
||||
|
||||
@ -365,6 +365,8 @@ namespace ts {
|
||||
// Transformation nodes
|
||||
NotEmittedStatement,
|
||||
PartiallyEmittedExpression,
|
||||
MergeDeclarationMarker,
|
||||
EndOfDeclarationMarker,
|
||||
|
||||
// Enum value count
|
||||
Count,
|
||||
@ -460,7 +462,8 @@ namespace ts {
|
||||
ParameterPropertyModifier = AccessibilityModifier | Readonly,
|
||||
NonPublicAccessibilityModifier = Private | Protected,
|
||||
|
||||
TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const
|
||||
TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const,
|
||||
ExportDefault = Export | Default,
|
||||
}
|
||||
|
||||
export const enum JsxFlags {
|
||||
@ -548,6 +551,7 @@ namespace ts {
|
||||
originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later
|
||||
/*@internal*/ autoGenerateKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier.
|
||||
/*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name.
|
||||
isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace
|
||||
}
|
||||
|
||||
// Transient identifier node (marked by id === -1)
|
||||
@ -555,6 +559,14 @@ namespace ts {
|
||||
resolvedSymbol: Symbol;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface GeneratedIdentifier extends Identifier {
|
||||
autoGenerateKind: GeneratedIdentifierKind.Auto
|
||||
| GeneratedIdentifierKind.Loop
|
||||
| GeneratedIdentifierKind.Unique
|
||||
| GeneratedIdentifierKind.Node;
|
||||
}
|
||||
|
||||
export interface QualifiedName extends Node {
|
||||
kind: SyntaxKind.QualifiedName;
|
||||
left: EntityName;
|
||||
@ -1157,6 +1169,21 @@ namespace ts {
|
||||
right: Expression;
|
||||
}
|
||||
|
||||
export interface AssignmentExpression extends BinaryExpression {
|
||||
left: LeftHandSideExpression;
|
||||
operatorToken: Token<SyntaxKind.EqualsToken>;
|
||||
}
|
||||
|
||||
export interface ObjectDestructuringAssignment extends AssignmentExpression {
|
||||
left: ObjectLiteralExpression;
|
||||
}
|
||||
|
||||
export interface ArrayDestructuringAssignment extends AssignmentExpression {
|
||||
left: ArrayLiteralExpression;
|
||||
}
|
||||
|
||||
export type DestructuringAssignment = ObjectDestructuringAssignment | ArrayDestructuringAssignment;
|
||||
|
||||
export interface ConditionalExpression extends Expression {
|
||||
kind: SyntaxKind.ConditionalExpression;
|
||||
condition: Expression;
|
||||
@ -1429,6 +1456,22 @@ namespace ts {
|
||||
kind: SyntaxKind.NotEmittedStatement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the end of transformed declaration to properly emit exports.
|
||||
*/
|
||||
/* @internal */
|
||||
export interface EndOfDeclarationMarker extends Statement {
|
||||
kind: SyntaxKind.EndOfDeclarationMarker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the beginning of a merged transformed declaration.
|
||||
*/
|
||||
/* @internal */
|
||||
export interface MergeDeclarationMarker extends Statement {
|
||||
kind: SyntaxKind.MergeDeclarationMarker;
|
||||
}
|
||||
|
||||
export interface EmptyStatement extends Statement {
|
||||
kind: SyntaxKind.EmptyStatement;
|
||||
}
|
||||
@ -1645,7 +1688,7 @@ namespace ts {
|
||||
export interface ModuleDeclaration extends DeclarationStatement {
|
||||
kind: SyntaxKind.ModuleDeclaration;
|
||||
name: Identifier | LiteralExpression;
|
||||
body?: ModuleBlock | NamespaceDeclaration;
|
||||
body?: ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | Identifier;
|
||||
}
|
||||
|
||||
export interface NamespaceDeclaration extends ModuleDeclaration {
|
||||
@ -1653,6 +1696,11 @@ namespace ts {
|
||||
body: ModuleBlock | NamespaceDeclaration;
|
||||
}
|
||||
|
||||
export interface JSDocNamespaceDeclaration extends ModuleDeclaration {
|
||||
name: Identifier;
|
||||
body: JSDocNamespaceDeclaration | Identifier;
|
||||
}
|
||||
|
||||
export interface ModuleBlock extends Node, Statement {
|
||||
kind: SyntaxKind.ModuleBlock;
|
||||
statements: NodeArray<Statement>;
|
||||
@ -1882,6 +1930,7 @@ namespace ts {
|
||||
|
||||
export interface JSDocTypedefTag extends JSDocTag, Declaration {
|
||||
kind: SyntaxKind.JSDocTypedefTag;
|
||||
fullName?: JSDocNamespaceDeclaration | Identifier;
|
||||
name?: Identifier;
|
||||
typeExpression?: JSDocTypeExpression;
|
||||
jsDocTypeLiteral?: JSDocTypeLiteral;
|
||||
@ -2035,6 +2084,9 @@ namespace ts {
|
||||
// as well as code diagnostics).
|
||||
/* @internal */ parseDiagnostics: Diagnostic[];
|
||||
|
||||
// Stores additional file level diagnostics reported by the program
|
||||
/* @internal */ additionalSyntacticDiagnostics?: Diagnostic[];
|
||||
|
||||
// File level diagnostics reported by the binder.
|
||||
/* @internal */ bindDiagnostics: Diagnostic[];
|
||||
|
||||
@ -2045,7 +2097,7 @@ namespace ts {
|
||||
// Stores a mapping 'external module reference text' -> 'resolved file name' | undefined
|
||||
// It is used to resolve module names in the checker.
|
||||
// Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead
|
||||
/* @internal */ resolvedModules: Map<ResolvedModule>;
|
||||
/* @internal */ resolvedModules: Map<ResolvedModuleFull>;
|
||||
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
|
||||
/* @internal */ imports: LiteralExpression[];
|
||||
/* @internal */ moduleAugmentations: LiteralExpression[];
|
||||
@ -3060,6 +3112,7 @@ namespace ts {
|
||||
packageNameToTypingLocation: Map<string>; // The map of package names to their cached typing locations
|
||||
typingOptions: TypingOptions; // Used to customize the typing inference process
|
||||
compilerOptions: CompilerOptions; // Used as a source for typing inference
|
||||
unresolvedImports: ReadonlyArray<string>; // List of unresolved module ids from imports
|
||||
}
|
||||
|
||||
export enum ModuleKind {
|
||||
@ -3118,6 +3171,7 @@ namespace ts {
|
||||
Pretty,
|
||||
}
|
||||
|
||||
/** Either a parsed command line or a parsed tsconfig.json */
|
||||
export interface ParsedCommandLine {
|
||||
options: CompilerOptions;
|
||||
typingOptions?: TypingOptions;
|
||||
@ -3323,10 +3377,18 @@ namespace ts {
|
||||
getDirectories?(path: string): string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the result of module resolution.
|
||||
* Module resolution will pick up tsx/jsx/js files even if '--jsx' and '--allowJs' are turned off.
|
||||
* The Program will then filter results based on these flags.
|
||||
*
|
||||
* Prefer to return a `ResolvedModuleFull` so that the file type does not have to be inferred.
|
||||
*/
|
||||
export interface ResolvedModule {
|
||||
/** Path of the file the module was resolved to. */
|
||||
resolvedFileName: string;
|
||||
/*
|
||||
* Denotes if 'resolvedFileName' is isExternalLibraryImport and thus should be proper external module:
|
||||
/**
|
||||
* Denotes if 'resolvedFileName' is isExternalLibraryImport and thus should be a proper external module:
|
||||
* - be a .d.ts file
|
||||
* - use top level imports\exports
|
||||
* - don't use tripleslash references
|
||||
@ -3334,8 +3396,29 @@ namespace ts {
|
||||
isExternalLibraryImport?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* ResolvedModule with an explicitly provided `extension` property.
|
||||
* Prefer this over `ResolvedModule`.
|
||||
*/
|
||||
export interface ResolvedModuleFull extends ResolvedModule {
|
||||
/**
|
||||
* Extension of resolvedFileName. This must match what's at the end of resolvedFileName.
|
||||
* This is optional for backwards-compatibility, but will be added if not provided.
|
||||
*/
|
||||
extension: Extension;
|
||||
}
|
||||
|
||||
export enum Extension {
|
||||
Ts,
|
||||
Tsx,
|
||||
Dts,
|
||||
Js,
|
||||
Jsx,
|
||||
LastTypeScriptExtension = Dts
|
||||
}
|
||||
|
||||
export interface ResolvedModuleWithFailedLookupLocations {
|
||||
resolvedModule: ResolvedModule;
|
||||
resolvedModule: ResolvedModuleFull | undefined;
|
||||
failedLookupLocations: string[];
|
||||
}
|
||||
|
||||
@ -3395,25 +3478,26 @@ namespace ts {
|
||||
ContainsES2016 = 1 << 7,
|
||||
ES2015 = 1 << 8,
|
||||
ContainsES2015 = 1 << 9,
|
||||
DestructuringAssignment = 1 << 10,
|
||||
Generator = 1 << 11,
|
||||
ContainsGenerator = 1 << 12,
|
||||
Generator = 1 << 10,
|
||||
ContainsGenerator = 1 << 11,
|
||||
DestructuringAssignment = 1 << 12,
|
||||
ContainsDestructuringAssignment = 1 << 13,
|
||||
|
||||
// Markers
|
||||
// - Flags used to indicate that a subtree contains a specific transformation.
|
||||
ContainsDecorators = 1 << 13,
|
||||
ContainsPropertyInitializer = 1 << 14,
|
||||
ContainsLexicalThis = 1 << 15,
|
||||
ContainsCapturedLexicalThis = 1 << 16,
|
||||
ContainsLexicalThisInComputedPropertyName = 1 << 17,
|
||||
ContainsDefaultValueAssignments = 1 << 18,
|
||||
ContainsParameterPropertyAssignments = 1 << 19,
|
||||
ContainsSpreadElementExpression = 1 << 20,
|
||||
ContainsComputedPropertyName = 1 << 21,
|
||||
ContainsBlockScopedBinding = 1 << 22,
|
||||
ContainsBindingPattern = 1 << 23,
|
||||
ContainsYield = 1 << 24,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 25,
|
||||
ContainsDecorators = 1 << 14,
|
||||
ContainsPropertyInitializer = 1 << 15,
|
||||
ContainsLexicalThis = 1 << 16,
|
||||
ContainsCapturedLexicalThis = 1 << 17,
|
||||
ContainsLexicalThisInComputedPropertyName = 1 << 18,
|
||||
ContainsDefaultValueAssignments = 1 << 19,
|
||||
ContainsParameterPropertyAssignments = 1 << 20,
|
||||
ContainsSpreadElementExpression = 1 << 21,
|
||||
ContainsComputedPropertyName = 1 << 22,
|
||||
ContainsBlockScopedBinding = 1 << 23,
|
||||
ContainsBindingPattern = 1 << 24,
|
||||
ContainsYield = 1 << 25,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 26,
|
||||
|
||||
HasComputedFlags = 1 << 29, // Transform flags have been computed.
|
||||
|
||||
@ -3425,6 +3509,7 @@ namespace ts {
|
||||
AssertES2016 = ES2016 | ContainsES2016,
|
||||
AssertES2015 = ES2015 | ContainsES2015,
|
||||
AssertGenerator = Generator | ContainsGenerator,
|
||||
AssertDestructuringAssignment = DestructuringAssignment | ContainsDestructuringAssignment,
|
||||
|
||||
// Scope Exclusions
|
||||
// - Bitmasks that exclude flags from propagating out of a specific context
|
||||
@ -3487,6 +3572,8 @@ namespace ts {
|
||||
AsyncFunctionBody = 1 << 21,
|
||||
ReuseTempVariableScope = 1 << 22, // Reuse the existing temp variable scope during emit.
|
||||
CustomPrologue = 1 << 23, // Treat the statement as if it were a prologue directive (NOTE: Prologue directives are *not* transformed).
|
||||
NoHoisting = 1 << 24, // Do not hoist this declaration in --module system
|
||||
HasEndOfDeclarationMarker = 1 << 25, // Declaration has an associated NotEmittedStatement to mark the end of the declaration
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@ -83,36 +83,17 @@ namespace ts {
|
||||
return node.end - node.pos;
|
||||
}
|
||||
|
||||
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T>, array2: ReadonlyArray<T>, equaler?: (a: T, b: T) => boolean): boolean {
|
||||
if (!array1 || !array2) {
|
||||
return array1 === array2;
|
||||
}
|
||||
|
||||
if (array1.length !== array2.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
const equals = equaler ? equaler(array1[i], array2[i]) : array1[i] === array2[i];
|
||||
if (!equals) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean {
|
||||
return !!(sourceFile && sourceFile.resolvedModules && sourceFile.resolvedModules[moduleNameText]);
|
||||
}
|
||||
|
||||
export function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModule {
|
||||
export function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModuleFull {
|
||||
return hasResolvedModule(sourceFile, moduleNameText) ? sourceFile.resolvedModules[moduleNameText] : undefined;
|
||||
}
|
||||
|
||||
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModule): void {
|
||||
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModuleFull): void {
|
||||
if (!sourceFile.resolvedModules) {
|
||||
sourceFile.resolvedModules = createMap<ResolvedModule>();
|
||||
sourceFile.resolvedModules = createMap<ResolvedModuleFull>();
|
||||
}
|
||||
|
||||
sourceFile.resolvedModules[moduleNameText] = resolvedModule;
|
||||
@ -127,8 +108,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function moduleResolutionIsEqualTo(oldResolution: ResolvedModule, newResolution: ResolvedModule): boolean {
|
||||
return oldResolution.resolvedFileName === newResolution.resolvedFileName && oldResolution.isExternalLibraryImport === newResolution.isExternalLibraryImport;
|
||||
export function moduleResolutionIsEqualTo(oldResolution: ResolvedModuleFull, newResolution: ResolvedModuleFull): boolean {
|
||||
return oldResolution.isExternalLibraryImport === newResolution.isExternalLibraryImport &&
|
||||
oldResolution.extension === newResolution.extension &&
|
||||
oldResolution.resolvedFileName === newResolution.resolvedFileName;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@ -406,7 +389,12 @@ namespace ts {
|
||||
|
||||
export function isBlockOrCatchScoped(declaration: Declaration) {
|
||||
return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 ||
|
||||
isCatchClauseVariableDeclaration(declaration);
|
||||
isCatchClauseVariableDeclarationOrBindingElement(declaration);
|
||||
}
|
||||
|
||||
export function isCatchClauseVariableDeclarationOrBindingElement(declaration: Declaration) {
|
||||
const node = getRootDeclaration(declaration);
|
||||
return node.kind === SyntaxKind.VariableDeclaration && node.parent.kind === SyntaxKind.CatchClause;
|
||||
}
|
||||
|
||||
export function isAmbientModule(node: Node): boolean {
|
||||
@ -414,6 +402,7 @@ namespace ts {
|
||||
((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(<ModuleDeclaration>node));
|
||||
}
|
||||
|
||||
/** Given a symbol for a module, checks that it is either an untyped import or a shorthand ambient module. */
|
||||
export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean {
|
||||
return isShorthandAmbientModule(moduleSymbol.valueDeclaration);
|
||||
}
|
||||
@ -489,13 +478,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function isCatchClauseVariableDeclaration(declaration: Declaration) {
|
||||
return declaration &&
|
||||
declaration.kind === SyntaxKind.VariableDeclaration &&
|
||||
declaration.parent &&
|
||||
declaration.parent.kind === SyntaxKind.CatchClause;
|
||||
}
|
||||
|
||||
// Return display name of an identifier
|
||||
// Computed property names will just be emitted as "[<expr>]", where <expr> is the source
|
||||
// text of the expression in the computed property.
|
||||
@ -503,6 +485,17 @@ namespace ts {
|
||||
return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
|
||||
}
|
||||
|
||||
export function entityNameToString(name: EntityNameOrEntityNameExpression): string {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return getFullWidth(name) === 0 ? unescapeIdentifier((<Identifier>name).text) : getTextOfNode(name);
|
||||
case SyntaxKind.QualifiedName:
|
||||
return entityNameToString((<QualifiedName>name).left) + "." + entityNameToString((<QualifiedName>name).right);
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return entityNameToString((<PropertyAccessEntityNameExpression>name).expression) + "." + entityNameToString((<PropertyAccessEntityNameExpression>name).name);
|
||||
}
|
||||
}
|
||||
|
||||
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic {
|
||||
const sourceFile = getSourceFileOfNode(node);
|
||||
const span = getErrorSpanForNode(sourceFile, node);
|
||||
@ -1060,17 +1053,19 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
return (<TypeReferenceNode>node).typeName;
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
Debug.assert(isEntityNameExpression((<ExpressionWithTypeArguments>node).expression));
|
||||
return <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression;
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.QualifiedName:
|
||||
return (<EntityName><Node>node);
|
||||
}
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
case SyntaxKind.JSDocTypeReference:
|
||||
return (<TypeReferenceNode>node).typeName;
|
||||
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return isEntityNameExpression((<ExpressionWithTypeArguments>node).expression)
|
||||
? <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression
|
||||
: undefined;
|
||||
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.QualifiedName:
|
||||
return (<EntityName><Node>node);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@ -1975,14 +1970,16 @@ namespace ts {
|
||||
|| positionIsSynthesized(node.end);
|
||||
}
|
||||
|
||||
export function getOriginalNode(node: Node): Node {
|
||||
export function getOriginalNode(node: Node): Node;
|
||||
export function getOriginalNode<T extends Node>(node: Node, nodeTest: (node: Node) => node is T): T;
|
||||
export function getOriginalNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
|
||||
if (node) {
|
||||
while (node.original !== undefined) {
|
||||
node = node.original;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
return !nodeTest || nodeTest(node) ? node : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3060,7 +3057,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (node.flags & NodeFlags.NestedNamespace) {
|
||||
if (node.flags & NodeFlags.NestedNamespace || (node.kind === SyntaxKind.Identifier && (<Identifier>node).isInJSDocNamespace)) {
|
||||
flags |= ModifierFlags.Export;
|
||||
}
|
||||
|
||||
@ -3104,7 +3101,13 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function isDestructuringAssignment(node: Node): node is BinaryExpression {
|
||||
export function isAssignmentExpression(node: Node): node is AssignmentExpression {
|
||||
return isBinaryExpression(node)
|
||||
&& isAssignmentOperator(node.operatorToken.kind)
|
||||
&& isLeftHandSideExpression(node.left);
|
||||
}
|
||||
|
||||
export function isDestructuringAssignment(node: Node): node is DestructuringAssignment {
|
||||
if (isBinaryExpression(node)) {
|
||||
if (node.operatorToken.kind === SyntaxKind.EqualsToken) {
|
||||
const kind = node.left.kind;
|
||||
@ -3528,9 +3531,21 @@ namespace ts {
|
||||
return positionIsSynthesized(range.pos) ? -1 : skipTrivia(sourceFile.text, range.pos);
|
||||
}
|
||||
|
||||
export function collectExternalModuleInfo(sourceFile: SourceFile) {
|
||||
export interface ExternalModuleInfo {
|
||||
externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; // imports of other external modules
|
||||
exportSpecifiers: Map<ExportSpecifier[]>; // export specifiers by name
|
||||
exportedBindings: Map<Identifier[]>; // exported names of local declarations
|
||||
exportedNames: Identifier[]; // all exported names local to module
|
||||
exportEquals: ExportAssignment | undefined; // an export= declaration if one was present
|
||||
hasExportStarsToExportValues: boolean; // whether this module contains export*
|
||||
}
|
||||
|
||||
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver): ExternalModuleInfo {
|
||||
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
|
||||
const exportSpecifiers = createMap<ExportSpecifier[]>();
|
||||
const exportedBindings = createMap<Identifier[]>();
|
||||
const uniqueExports = createMap<Identifier>();
|
||||
let hasExportDefault = false;
|
||||
let exportEquals: ExportAssignment = undefined;
|
||||
let hasExportStarsToExportValues = false;
|
||||
for (const node of sourceFile.statements) {
|
||||
@ -3548,6 +3563,7 @@ namespace ts {
|
||||
// import x = require("mod")
|
||||
externalImports.push(<ImportEqualsDeclaration>node);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
@ -3565,8 +3581,19 @@ namespace ts {
|
||||
else {
|
||||
// export { x, y }
|
||||
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
|
||||
const name = (specifier.propertyName || specifier.name).text;
|
||||
(exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier);
|
||||
if (!uniqueExports[specifier.name.text]) {
|
||||
const name = specifier.propertyName || specifier.name;
|
||||
multiMapAdd(exportSpecifiers, name.text, specifier);
|
||||
|
||||
const decl = resolver.getReferencedImportDeclaration(name)
|
||||
|| resolver.getReferencedValueDeclaration(name);
|
||||
|
||||
if (decl) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
|
||||
}
|
||||
|
||||
uniqueExports[specifier.name.text] = specifier.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -3577,10 +3604,94 @@ namespace ts {
|
||||
exportEquals = <ExportAssignment>node;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.VariableStatement:
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
for (const decl of (<VariableStatement>node).declarationList.declarations) {
|
||||
collectExportedVariableInfo(decl, uniqueExports);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
if (hasModifier(node, ModifierFlags.Default)) {
|
||||
// export default function() { }
|
||||
if (!hasExportDefault) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<FunctionDeclaration>node));
|
||||
hasExportDefault = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// export function x() { }
|
||||
const name = (<FunctionDeclaration>node).name;
|
||||
if (!uniqueExports[name.text]) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), name);
|
||||
uniqueExports[name.text] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
if (hasModifier(node, ModifierFlags.Default)) {
|
||||
// export default class { }
|
||||
if (!hasExportDefault) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<ClassDeclaration>node));
|
||||
hasExportDefault = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// export class x { }
|
||||
const name = (<ClassDeclaration>node).name;
|
||||
if (!uniqueExports[name.text]) {
|
||||
multiMapAdd(exportedBindings, getOriginalNodeId(node), name);
|
||||
uniqueExports[name.text] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues };
|
||||
let exportedNames: Identifier[];
|
||||
for (const key in uniqueExports) {
|
||||
exportedNames = ts.append(exportedNames, uniqueExports[key]);
|
||||
}
|
||||
|
||||
return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames };
|
||||
}
|
||||
|
||||
function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map<Identifier>) {
|
||||
if (isBindingPattern(decl.name)) {
|
||||
for (const element of decl.name.elements) {
|
||||
if (!isOmittedExpression(element)) {
|
||||
collectExportedVariableInfo(element, uniqueExports);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!isGeneratedIdentifier(decl.name)) {
|
||||
if (!uniqueExports[decl.name.text]) {
|
||||
uniqueExports[decl.name.text] = decl.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a name was originally the declaration name of an enum or namespace
|
||||
* declaration.
|
||||
*/
|
||||
export function isDeclarationNameOfEnumOrNamespace(node: Identifier) {
|
||||
const parseNode = getParseTreeNode(node);
|
||||
if (parseNode) {
|
||||
switch (parseNode.parent.kind) {
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return parseNode === (<EnumDeclaration | ModuleDeclaration>parseNode.parent).name;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getInitializedVariables(node: VariableDeclarationList) {
|
||||
@ -3668,7 +3779,7 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.Identifier;
|
||||
}
|
||||
|
||||
export function isGeneratedIdentifier(node: Node): boolean {
|
||||
export function isGeneratedIdentifier(node: Node): node is GeneratedIdentifier {
|
||||
// Using `>` here catches both `GeneratedIdentifierKind.None` and `undefined`.
|
||||
return isIdentifier(node) && node.autoGenerateKind > GeneratedIdentifierKind.None;
|
||||
}
|
||||
@ -3804,6 +3915,14 @@ namespace ts {
|
||||
|
||||
// Expression
|
||||
|
||||
export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression {
|
||||
return node.kind === SyntaxKind.ArrayLiteralExpression;
|
||||
}
|
||||
|
||||
export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression {
|
||||
return node.kind === SyntaxKind.ObjectLiteralExpression;
|
||||
}
|
||||
|
||||
export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
|
||||
return node.kind === SyntaxKind.PropertyAccessExpression;
|
||||
}
|
||||
@ -4063,7 +4182,9 @@ namespace ts {
|
||||
|| kind === SyntaxKind.VariableStatement
|
||||
|| kind === SyntaxKind.WhileStatement
|
||||
|| kind === SyntaxKind.WithStatement
|
||||
|| kind === SyntaxKind.NotEmittedStatement;
|
||||
|| kind === SyntaxKind.NotEmittedStatement
|
||||
|| kind === SyntaxKind.EndOfDeclarationMarker
|
||||
|| kind === SyntaxKind.MergeDeclarationMarker;
|
||||
}
|
||||
|
||||
export function isDeclaration(node: Node): node is Declaration {
|
||||
|
||||
@ -692,7 +692,7 @@ namespace ts {
|
||||
|
||||
// Signature elements
|
||||
case SyntaxKind.Parameter:
|
||||
return updateParameterDeclaration(<ParameterDeclaration>node,
|
||||
return updateParameter(<ParameterDeclaration>node,
|
||||
visitNodes((<ParameterDeclaration>node).decorators, visitor, isDecorator),
|
||||
visitNodes((<ParameterDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ParameterDeclaration>node).name, visitor, isBindingName),
|
||||
|
||||
@ -438,9 +438,8 @@ namespace FourSlash {
|
||||
private getAllDiagnostics(): ts.Diagnostic[] {
|
||||
const diagnostics: ts.Diagnostic[] = [];
|
||||
|
||||
const fileNames = this.languageServiceAdapterHost.getFilenames();
|
||||
for (let i = 0, n = fileNames.length; i < n; i++) {
|
||||
diagnostics.push.apply(this.getDiagnostics(fileNames[i]));
|
||||
for (const fileName of this.languageServiceAdapterHost.getFilenames()) {
|
||||
diagnostics.push.apply(this.getDiagnostics(fileName));
|
||||
}
|
||||
|
||||
return diagnostics;
|
||||
@ -580,12 +579,12 @@ namespace FourSlash {
|
||||
this.raiseError(`goToDefinitions failed - expected to find ${endMarkers.length} definitions but got ${definitions.length}`);
|
||||
}
|
||||
|
||||
for (let i = 0; i < endMarkers.length; i++) {
|
||||
const marker = this.getMarkerByName(endMarkers[i]), definition = definitions[i];
|
||||
ts.zipWith(endMarkers, definitions, (endMarker, definition, i) => {
|
||||
const marker = this.getMarkerByName(endMarker);
|
||||
if (marker.fileName !== definition.fileName || marker.position !== definition.textSpan.start) {
|
||||
this.raiseError(`goToDefinition failed for definition ${i}: expected ${marker.fileName} at ${marker.position}, got ${definition.fileName} at ${definition.textSpan.start}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public verifyGetEmitOutputForCurrentFile(expected: string): void {
|
||||
@ -602,10 +601,10 @@ namespace FourSlash {
|
||||
public verifyGetEmitOutputContentsForCurrentFile(expected: ts.OutputFile[]): void {
|
||||
const emit = this.languageService.getEmitOutput(this.activeFile.fileName);
|
||||
assert.equal(emit.outputFiles.length, expected.length, "Number of emit output files");
|
||||
for (let i = 0; i < emit.outputFiles.length; i++) {
|
||||
assert.equal(emit.outputFiles[i].name, expected[i].name, "FileName");
|
||||
assert.equal(emit.outputFiles[i].text, expected[i].text, "Content");
|
||||
}
|
||||
ts.zipWith(emit.outputFiles, expected, (outputFile, expected) => {
|
||||
assert.equal(outputFile.name, expected.name, "FileName");
|
||||
assert.equal(outputFile.text, expected.text, "Content");
|
||||
});
|
||||
}
|
||||
|
||||
public verifyMemberListContains(symbol: string, text?: string, documentation?: string, kind?: string) {
|
||||
@ -668,9 +667,9 @@ namespace FourSlash {
|
||||
|
||||
const entries = this.getCompletionListAtCaret().entries;
|
||||
assert.isTrue(items.length <= entries.length, `Amount of expected items in completion list [ ${items.length} ] is greater than actual number of items in list [ ${entries.length} ]`);
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
assert.equal(entries[i].name, items[i], `Unexpected item in completion list`);
|
||||
}
|
||||
ts.zipWith(entries, items, (entry, item) => {
|
||||
assert.equal(entry.name, item, `Unexpected item in completion list`);
|
||||
});
|
||||
}
|
||||
|
||||
public noItemsWithSameNameButDifferentKind(): void {
|
||||
@ -692,15 +691,7 @@ namespace FourSlash {
|
||||
this.raiseError("Member list is empty at Caret");
|
||||
}
|
||||
else if ((members && members.entries.length !== 0) && !negative) {
|
||||
|
||||
let errorMsg = "\n" + "Member List contains: [" + members.entries[0].name;
|
||||
for (let i = 1; i < members.entries.length; i++) {
|
||||
errorMsg += ", " + members.entries[i].name;
|
||||
}
|
||||
errorMsg += "]\n";
|
||||
|
||||
this.raiseError("Member list is not empty at Caret: " + errorMsg);
|
||||
|
||||
this.raiseError(`Member list is not empty at Caret:\nMember List contains: ${stringify(members.entries.map(e => e.name))}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -710,13 +701,8 @@ namespace FourSlash {
|
||||
this.raiseError("Completion list is empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition);
|
||||
}
|
||||
else if (completions && completions.entries.length !== 0 && !negative) {
|
||||
let errorMsg = "\n" + "Completion List contains: [" + completions.entries[0].name;
|
||||
for (let i = 1; i < completions.entries.length; i++) {
|
||||
errorMsg += ", " + completions.entries[i].name;
|
||||
}
|
||||
errorMsg += "]\n";
|
||||
|
||||
this.raiseError("Completion list is not empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition + errorMsg);
|
||||
this.raiseError(`Completion list is not empty at caret at position ${this.activeFile.fileName} ${this.currentCaretPosition}\n` +
|
||||
`Completion List contains: ${stringify(completions.entries.map(e => e.name))}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -890,8 +876,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) {
|
||||
for (let i = 0; i < references.length; i++) {
|
||||
const reference = references[i];
|
||||
for (const reference of references) {
|
||||
if (reference && reference.fileName === fileName && reference.textSpan.start === start && ts.textSpanEnd(reference.textSpan) === end) {
|
||||
if (typeof isWriteAccess !== "undefined" && reference.isWriteAccess !== isWriteAccess) {
|
||||
this.raiseError(`verifyReferencesAtPositionListContains failed - item isWriteAccess value does not match, actual: ${reference.isWriteAccess}, expected: ${isWriteAccess}.`);
|
||||
@ -1008,16 +993,11 @@ namespace FourSlash {
|
||||
ranges = ranges.sort((r1, r2) => r1.start - r2.start);
|
||||
references = references.sort((r1, r2) => r1.textSpan.start - r2.textSpan.start);
|
||||
|
||||
for (let i = 0, n = ranges.length; i < n; i++) {
|
||||
const reference = references[i];
|
||||
const range = ranges[i];
|
||||
|
||||
if (reference.textSpan.start !== range.start ||
|
||||
ts.textSpanEnd(reference.textSpan) !== range.end) {
|
||||
|
||||
ts.zipWith(references, ranges, (reference, range) => {
|
||||
if (reference.textSpan.start !== range.start || ts.textSpanEnd(reference.textSpan) !== range.end) {
|
||||
this.raiseError("Rename location results do not match.\n\nExpected: " + stringify(ranges) + "\n\nActual:" + JSON.stringify(references));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.raiseError("Expected rename to succeed, but it actually failed.");
|
||||
@ -1247,8 +1227,7 @@ namespace FourSlash {
|
||||
const emitFiles: FourSlashFile[] = []; // List of FourSlashFile that has emitThisFile flag on
|
||||
|
||||
const allFourSlashFiles = this.testData.files;
|
||||
for (let idx = 0; idx < allFourSlashFiles.length; idx++) {
|
||||
const file = allFourSlashFiles[idx];
|
||||
for (const file of allFourSlashFiles) {
|
||||
if (file.fileOptions[metadataOptionNames.emitThisFile] === "true") {
|
||||
// Find a file with the flag emitThisFile turned on
|
||||
emitFiles.push(file);
|
||||
@ -1273,8 +1252,8 @@ namespace FourSlash {
|
||||
if (emitOutput.emitSkipped) {
|
||||
resultString += "Diagnostics:" + Harness.IO.newLine();
|
||||
const diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram());
|
||||
for (let i = 0, n = diagnostics.length; i < n; i++) {
|
||||
resultString += " " + diagnostics[0].messageText + Harness.IO.newLine();
|
||||
for (const diagnostic of diagnostics) {
|
||||
resultString += " " + diagnostic.messageText + Harness.IO.newLine();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1340,8 +1319,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
public printCurrentFileState(makeWhitespaceVisible = false, makeCaretVisible = true) {
|
||||
for (let i = 0; i < this.testData.files.length; i++) {
|
||||
const file = this.testData.files[i];
|
||||
for (const file of this.testData.files) {
|
||||
const active = (this.activeFile === file);
|
||||
Harness.IO.log(`=== Script (${file.fileName}) ${(active ? "(active, cursor at |)" : "")} ===`);
|
||||
let content = this.getFileContent(file.fileName);
|
||||
@ -1576,10 +1554,10 @@ namespace FourSlash {
|
||||
edits = edits.sort((a, b) => a.span.start - b.span.start);
|
||||
// Get a snapshot of the content of the file so we can make sure any formatting edits didn't destroy non-whitespace characters
|
||||
const oldContent = this.getFileContent(this.activeFile.fileName);
|
||||
for (let j = 0; j < edits.length; j++) {
|
||||
this.languageServiceAdapterHost.editScript(fileName, edits[j].span.start + runningOffset, ts.textSpanEnd(edits[j].span) + runningOffset, edits[j].newText);
|
||||
this.updateMarkersForEdit(fileName, edits[j].span.start + runningOffset, ts.textSpanEnd(edits[j].span) + runningOffset, edits[j].newText);
|
||||
const change = (edits[j].span.start - ts.textSpanEnd(edits[j].span)) + edits[j].newText.length;
|
||||
for (const edit of edits) {
|
||||
this.languageServiceAdapterHost.editScript(fileName, edit.span.start + runningOffset, ts.textSpanEnd(edit.span) + runningOffset, edit.newText);
|
||||
this.updateMarkersForEdit(fileName, edit.span.start + runningOffset, ts.textSpanEnd(edit.span) + runningOffset, edit.newText);
|
||||
const change = (edit.span.start - ts.textSpanEnd(edit.span)) + edit.newText.length;
|
||||
runningOffset += change;
|
||||
// TODO: Consider doing this at least some of the time for higher fidelity. Currently causes a failure (bug 707150)
|
||||
// this.languageService.getScriptLexicalStructure(fileName);
|
||||
@ -1913,10 +1891,7 @@ namespace FourSlash {
|
||||
jsonMismatchString());
|
||||
}
|
||||
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
const expectedClassification = expected[i];
|
||||
const actualClassification = actual[i];
|
||||
|
||||
ts.zipWith(expected, actual, (expectedClassification, actualClassification) => {
|
||||
const expectedType: string = (<any>ts.ClassificationTypeNames)[expectedClassification.classificationType];
|
||||
if (expectedType !== actualClassification.classificationType) {
|
||||
this.raiseError("verifyClassifications failed - expected classifications type to be " +
|
||||
@ -1946,7 +1921,7 @@ namespace FourSlash {
|
||||
actualText +
|
||||
jsonMismatchString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function jsonMismatchString() {
|
||||
return Harness.IO.newLine() +
|
||||
@ -1991,13 +1966,11 @@ namespace FourSlash {
|
||||
this.raiseError(`verifyOutliningSpans failed - expected total spans to be ${spans.length}, but was ${actual.length}`);
|
||||
}
|
||||
|
||||
for (let i = 0; i < spans.length; i++) {
|
||||
const expectedSpan = spans[i];
|
||||
const actualSpan = actual[i];
|
||||
ts.zipWith(spans, actual, (expectedSpan, actualSpan, i) => {
|
||||
if (expectedSpan.start !== actualSpan.textSpan.start || expectedSpan.end !== ts.textSpanEnd(actualSpan.textSpan)) {
|
||||
this.raiseError(`verifyOutliningSpans failed - span ${(i + 1)} expected: (${expectedSpan.start},${expectedSpan.end}), actual: (${actualSpan.textSpan.start},${ts.textSpanEnd(actualSpan.textSpan)})`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public verifyTodoComments(descriptors: string[], spans: TextSpan[]) {
|
||||
@ -2008,15 +1981,13 @@ namespace FourSlash {
|
||||
this.raiseError(`verifyTodoComments failed - expected total spans to be ${spans.length}, but was ${actual.length}`);
|
||||
}
|
||||
|
||||
for (let i = 0; i < spans.length; i++) {
|
||||
const expectedSpan = spans[i];
|
||||
const actualComment = actual[i];
|
||||
ts.zipWith(spans, actual, (expectedSpan, actualComment, i) => {
|
||||
const actualCommentSpan = ts.createTextSpan(actualComment.position, actualComment.message.length);
|
||||
|
||||
if (expectedSpan.start !== actualCommentSpan.start || expectedSpan.end !== ts.textSpanEnd(actualCommentSpan)) {
|
||||
this.raiseError(`verifyOutliningSpans failed - span ${(i + 1)} expected: (${expectedSpan.start},${expectedSpan.end}), actual: (${actualCommentSpan.start},${ts.textSpanEnd(actualCommentSpan)})`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getCodeFixes(errorCode?: number) {
|
||||
@ -2163,11 +2134,9 @@ namespace FourSlash {
|
||||
public verifyNavigationItemsCount(expected: number, searchValue: string, matchKind?: string, fileName?: string) {
|
||||
const items = this.languageService.getNavigateToItems(searchValue, /*maxResultCount*/ undefined, fileName);
|
||||
let actual = 0;
|
||||
let item: ts.NavigateToItem;
|
||||
|
||||
// Count only the match that match the same MatchKind
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
item = items[i];
|
||||
for (const item of items) {
|
||||
if (!matchKind || item.matchKind === matchKind) {
|
||||
actual++;
|
||||
}
|
||||
@ -2195,8 +2164,7 @@ namespace FourSlash {
|
||||
this.raiseError("verifyNavigationItemsListContains failed - found 0 navigation items, expected at least one.");
|
||||
}
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
for (const item of items) {
|
||||
if (item && item.name === name && item.kind === kind &&
|
||||
(matchKind === undefined || item.matchKind === matchKind) &&
|
||||
(fileName === undefined || item.fileName === fileName) &&
|
||||
@ -2247,24 +2215,16 @@ namespace FourSlash {
|
||||
|
||||
public printNavigationItems(searchValue: string) {
|
||||
const items = this.languageService.getNavigateToItems(searchValue);
|
||||
const length = items && items.length;
|
||||
|
||||
Harness.IO.log(`NavigationItems list (${length} items)`);
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
const item = items[i];
|
||||
Harness.IO.log(`NavigationItems list (${items.length} items)`);
|
||||
for (const item of items) {
|
||||
Harness.IO.log(`name: ${item.name}, kind: ${item.kind}, parentName: ${item.containerName}, fileName: ${item.fileName}`);
|
||||
}
|
||||
}
|
||||
|
||||
public printNavigationBar() {
|
||||
const items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
|
||||
const length = items && items.length;
|
||||
|
||||
Harness.IO.log(`Navigation bar (${length} items)`);
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
const item = items[i];
|
||||
Harness.IO.log(`Navigation bar (${items.length} items)`);
|
||||
for (const item of items) {
|
||||
Harness.IO.log(`${repeatString(item.indent, " ")}name: ${item.text}, kind: ${item.kind}, childItems: ${item.childItems.map(child => child.text)}`);
|
||||
}
|
||||
}
|
||||
@ -2385,8 +2345,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
private assertItemInCompletionList(items: ts.CompletionEntry[], name: string, text?: string, documentation?: string, kind?: string, spanIndex?: number) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
for (const item of items) {
|
||||
if (item.name === name) {
|
||||
if (documentation != undefined || text !== undefined) {
|
||||
const details = this.getCompletionEntryDetails(item.name);
|
||||
@ -2435,20 +2394,17 @@ namespace FourSlash {
|
||||
name = name.indexOf("/") === -1 ? (this.basePath + "/" + name) : name;
|
||||
|
||||
const availableNames: string[] = [];
|
||||
let foundIt = false;
|
||||
for (let i = 0; i < this.testData.files.length; i++) {
|
||||
const fn = this.testData.files[i].fileName;
|
||||
result = ts.forEach(this.testData.files, file => {
|
||||
const fn = file.fileName;
|
||||
if (fn) {
|
||||
if (fn === name) {
|
||||
result = this.testData.files[i];
|
||||
foundIt = true;
|
||||
break;
|
||||
return file;
|
||||
}
|
||||
availableNames.push(fn);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!foundIt) {
|
||||
if (!result) {
|
||||
throw new Error(`No test file named "${name}" exists. Available file names are: ${availableNames.join(", ")}`);
|
||||
}
|
||||
}
|
||||
@ -2549,8 +2505,8 @@ ${code}
|
||||
|
||||
function chompLeadingSpace(content: string) {
|
||||
const lines = content.split("\n");
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if ((lines[i].length !== 0) && (lines[i].charAt(0) !== " ")) {
|
||||
for (const line of lines) {
|
||||
if ((line.length !== 0) && (line.charAt(0) !== " ")) {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
@ -2588,8 +2544,7 @@ ${code}
|
||||
currentFileName = fileName;
|
||||
}
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i];
|
||||
for (let line of lines) {
|
||||
const lineLength = line.length;
|
||||
|
||||
if (lineLength > 0 && line.charAt(lineLength - 1) === "\r") {
|
||||
|
||||
@ -1029,7 +1029,7 @@ namespace Harness {
|
||||
},
|
||||
realpath: realPathMap && ((f: string) => {
|
||||
const path = ts.toPath(f, currentDirectory, getCanonicalFileName);
|
||||
return realPathMap.contains(path) ? realPathMap.get(path) : path;
|
||||
return realPathMap.get(path) || path;
|
||||
}),
|
||||
directoryExists: dir => {
|
||||
let path = ts.toPath(dir, currentDirectory, getCanonicalFileName);
|
||||
@ -1037,13 +1037,7 @@ namespace Harness {
|
||||
if (path[path.length - 1] === "/") {
|
||||
path = <ts.Path>path.substr(0, path.length - 1);
|
||||
}
|
||||
let exists = false;
|
||||
fileMap.forEachValue(key => {
|
||||
if (key.indexOf(path) === 0 && key[path.length] === "/") {
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
return exists;
|
||||
return mapHasFileInDirectory(path, fileMap) || mapHasFileInDirectory(path, realPathMap);
|
||||
},
|
||||
getDirectories: d => {
|
||||
const path = ts.toPath(d, currentDirectory, getCanonicalFileName);
|
||||
@ -1064,6 +1058,19 @@ namespace Harness {
|
||||
};
|
||||
}
|
||||
|
||||
function mapHasFileInDirectory(directoryPath: ts.Path, map: ts.FileMap<any>): boolean {
|
||||
if (!map) {
|
||||
return false;
|
||||
}
|
||||
let exists = false;
|
||||
map.forEachValue(fileName => {
|
||||
if (!exists && ts.startsWith(fileName, directoryPath) && fileName[directoryPath.length] === "/") {
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
return exists;
|
||||
}
|
||||
|
||||
interface HarnessOptions {
|
||||
useCaseSensitiveFileNames?: boolean;
|
||||
includeBuiltFile?: string;
|
||||
@ -1108,22 +1115,7 @@ namespace Harness {
|
||||
const option = getCommandLineOption(name);
|
||||
if (option) {
|
||||
const errors: ts.Diagnostic[] = [];
|
||||
switch (option.type) {
|
||||
case "boolean":
|
||||
options[option.name] = value.toLowerCase() === "true";
|
||||
break;
|
||||
case "string":
|
||||
options[option.name] = value;
|
||||
break;
|
||||
// If not a primitive, the possible types are specified in what is effectively a map of options.
|
||||
case "list":
|
||||
options[option.name] = ts.parseListTypeOption(<ts.CommandLineOptionOfListType>option, value, errors);
|
||||
break;
|
||||
default:
|
||||
options[option.name] = ts.parseCustomTypeOption(<ts.CommandLineOptionOfCustomType>option, value, errors);
|
||||
break;
|
||||
}
|
||||
|
||||
options[option.name] = optionValue(option, value, errors);
|
||||
if (errors.length > 0) {
|
||||
throw new Error(`Unknown value '${value}' for compiler option '${name}'.`);
|
||||
}
|
||||
@ -1135,6 +1127,27 @@ namespace Harness {
|
||||
}
|
||||
}
|
||||
|
||||
function optionValue(option: ts.CommandLineOption, value: string, errors: ts.Diagnostic[]): any {
|
||||
switch (option.type) {
|
||||
case "boolean":
|
||||
return value.toLowerCase() === "true";
|
||||
case "string":
|
||||
return value;
|
||||
case "number": {
|
||||
const number = parseInt(value, 10);
|
||||
if (isNaN(number)) {
|
||||
throw new Error(`Value must be a number, got: ${JSON.stringify(value)}`);
|
||||
}
|
||||
return number;
|
||||
}
|
||||
// If not a primitive, the possible types are specified in what is effectively a map of options.
|
||||
case "list":
|
||||
return ts.parseListTypeOption(<ts.CommandLineOptionOfListType>option, value, errors);
|
||||
default:
|
||||
return ts.parseCustomTypeOption(<ts.CommandLineOptionOfCustomType>option, value, errors);
|
||||
}
|
||||
}
|
||||
|
||||
export interface TestFile {
|
||||
unitName: string;
|
||||
content: string;
|
||||
@ -1238,7 +1251,7 @@ namespace Harness {
|
||||
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) {
|
||||
ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles));
|
||||
ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));
|
||||
const output = compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory);
|
||||
const output = compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory || harnessSettings["currentDirectory"]);
|
||||
return { declInputFiles, declOtherFiles, declResult: output.result };
|
||||
}
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
"../compiler/transformers/es2017.ts",
|
||||
"../compiler/transformers/es2016.ts",
|
||||
"../compiler/transformers/es2015.ts",
|
||||
"../compiler/transformers/es5.ts",
|
||||
"../compiler/transformers/generators.ts",
|
||||
"../compiler/transformers/es5.ts",
|
||||
"../compiler/transformers/destructuring.ts",
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
namespace ts {
|
||||
const caseInsensitiveBasePath = "c:/dev/";
|
||||
const caseInsensitiveTsconfigPath = "c:/dev/tsconfig.json";
|
||||
const caseInsensitiveHost = new Utils.MockParseConfigHost(caseInsensitiveBasePath, /*useCaseSensitiveFileNames*/ false, [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/a.d.ts",
|
||||
@ -88,6 +89,14 @@ namespace ts {
|
||||
"c:/dev/g.min.js/.g/g.ts"
|
||||
]);
|
||||
|
||||
const defaultExcludes = ["node_modules", "bower_components", "jspm_packages"];
|
||||
|
||||
function assertParsed(actual: ts.ParsedCommandLine, expected: ts.ParsedCommandLine): void {
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
}
|
||||
|
||||
describe("matchFiles", () => {
|
||||
describe("with literal file list", () => {
|
||||
it("without exclusions", () => {
|
||||
@ -107,9 +116,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("missing files are still present", () => {
|
||||
const json = {
|
||||
@ -128,9 +135,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("are not removed due to excludes", () => {
|
||||
const json = {
|
||||
@ -152,9 +157,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
@ -176,9 +179,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with non .ts file extensions are excluded", () => {
|
||||
const json = {
|
||||
@ -189,14 +190,15 @@ namespace ts {
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
|
||||
],
|
||||
fileNames: [],
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with missing files are excluded", () => {
|
||||
const json = {
|
||||
@ -207,14 +209,15 @@ namespace ts {
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
|
||||
],
|
||||
fileNames: [],
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with literal excludes", () => {
|
||||
const json = {
|
||||
@ -235,9 +238,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with wildcard excludes", () => {
|
||||
const json = {
|
||||
@ -265,9 +266,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with recursive excludes", () => {
|
||||
const json = {
|
||||
@ -294,9 +293,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with case sensitive exclude", () => {
|
||||
const json = {
|
||||
@ -316,9 +313,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseSensitiveHost, caseSensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with common package folders and no exclusions", () => {
|
||||
const json = {
|
||||
@ -340,9 +335,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with common package folders and exclusions", () => {
|
||||
const json = {
|
||||
@ -369,9 +362,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with common package folders and empty exclude", () => {
|
||||
const json = {
|
||||
@ -397,9 +388,7 @@ namespace ts {
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
@ -423,9 +412,7 @@ namespace ts {
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("`*` matches only ts files", () => {
|
||||
const json = {
|
||||
@ -446,9 +433,7 @@ namespace ts {
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("`?` matches only a single character", () => {
|
||||
const json = {
|
||||
@ -468,9 +453,7 @@ namespace ts {
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with recursive directory", () => {
|
||||
const json = {
|
||||
@ -492,9 +475,7 @@ namespace ts {
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with multiple recursive directories", () => {
|
||||
const json = {
|
||||
@ -518,9 +499,7 @@ namespace ts {
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("case sensitive", () => {
|
||||
const json = {
|
||||
@ -539,9 +518,7 @@ namespace ts {
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseSensitiveHost, caseSensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with missing files are excluded", () => {
|
||||
const json = {
|
||||
@ -551,16 +528,17 @@ namespace ts {
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
|
||||
],
|
||||
fileNames: [],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("always include literal files", () => {
|
||||
const json = {
|
||||
@ -585,9 +563,7 @@ namespace ts {
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("exclude folders", () => {
|
||||
const json = {
|
||||
@ -612,14 +588,12 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with common package folders and no exclusions", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"**/a.ts"
|
||||
"**/a.ts"
|
||||
]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
@ -633,9 +607,7 @@ namespace ts {
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with common package folders and exclusions", () => {
|
||||
const json = {
|
||||
@ -659,9 +631,7 @@ namespace ts {
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with common package folders and empty exclude", () => {
|
||||
const json = {
|
||||
@ -684,9 +654,7 @@ namespace ts {
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("exclude .js files when allowJs=false", () => {
|
||||
const json = {
|
||||
@ -701,16 +669,17 @@ namespace ts {
|
||||
options: {
|
||||
allowJs: false
|
||||
},
|
||||
errors: [],
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
|
||||
],
|
||||
fileNames: [],
|
||||
wildcardDirectories: {
|
||||
"c:/dev/js": ts.WatchDirectoryFlags.None
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("include .js files when allowJs=true", () => {
|
||||
const json = {
|
||||
@ -735,9 +704,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("include explicitly listed .min.js files when allowJs=true", () => {
|
||||
const json = {
|
||||
@ -762,9 +729,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("include paths outside of the project", () => {
|
||||
const json = {
|
||||
@ -788,9 +753,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("include paths outside of the project using relative paths", () => {
|
||||
const json = {
|
||||
@ -813,9 +776,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("exclude paths outside of the project using relative paths", () => {
|
||||
const json = {
|
||||
@ -828,14 +789,15 @@ namespace ts {
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))]
|
||||
,
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("include files with .. in their name", () => {
|
||||
const json = {
|
||||
@ -855,9 +817,7 @@ namespace ts {
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("exclude files with .. in their name", () => {
|
||||
const json = {
|
||||
@ -879,9 +839,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with jsx=none, allowJs=false", () => {
|
||||
const json = {
|
||||
@ -904,9 +862,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with jsx=preserve, allowJs=false", () => {
|
||||
const json = {
|
||||
@ -931,9 +887,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with jsx=none, allowJs=true", () => {
|
||||
const json = {
|
||||
@ -958,9 +912,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with jsx=preserve, allowJs=true", () => {
|
||||
const json = {
|
||||
@ -987,9 +939,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("exclude .min.js files using wildcards", () => {
|
||||
const json = {
|
||||
@ -1016,9 +966,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
describe("with trailing recursive directory", () => {
|
||||
it("in includes", () => {
|
||||
@ -1030,15 +978,15 @@ namespace ts {
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**")
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**"),
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
|
||||
],
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("in excludes", () => {
|
||||
const json = {
|
||||
@ -1051,14 +999,15 @@ namespace ts {
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))
|
||||
],
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
});
|
||||
describe("with multiple recursive directory patterns", () => {
|
||||
@ -1071,15 +1020,15 @@ namespace ts {
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, "**/x/**/*")
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, "**/x/**/*"),
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
|
||||
],
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("in excludes", () => {
|
||||
const json = {
|
||||
@ -1106,9 +1055,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1122,15 +1069,15 @@ namespace ts {
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*")
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*"),
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
|
||||
],
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
|
||||
it("in includes after a subdirectory", () => {
|
||||
@ -1142,15 +1089,15 @@ namespace ts {
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*")
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*"),
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
|
||||
],
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
|
||||
it("in excludes immediately after", () => {
|
||||
@ -1178,9 +1125,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
|
||||
it("in excludes after a subdirectory", () => {
|
||||
@ -1195,7 +1140,7 @@ namespace ts {
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..")
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..")
|
||||
],
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
@ -1208,9 +1153,25 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with implicit globbification", () => {
|
||||
it("Expands 'z' to 'z/**/*'", () => {
|
||||
const json = {
|
||||
include: ["z"]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [ "a.ts", "aba.ts", "abz.ts", "b.ts", "bba.ts", "bbz.ts" ].map(x => `c:/dev/z/${x}`),
|
||||
wildcardDirectories: {
|
||||
"c:/dev/z": ts.WatchDirectoryFlags.Recursive
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1235,9 +1196,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
describe("that are explicitly included", () => {
|
||||
it("without wildcards", () => {
|
||||
@ -1257,9 +1216,7 @@ namespace ts {
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with recursive wildcards that match directories", () => {
|
||||
const json = {
|
||||
@ -1281,9 +1238,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with recursive wildcards that match nothing", () => {
|
||||
const json = {
|
||||
@ -1305,9 +1260,7 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with wildcard excludes that implicitly exclude dotted files", () => {
|
||||
const json = {
|
||||
@ -1320,14 +1273,15 @@ namespace ts {
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
errors: [
|
||||
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
|
||||
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))
|
||||
],
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
assert.deepEqual(actual.errors, expected.errors);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,6 +1,28 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
|
||||
namespace ts {
|
||||
export function checkResolvedModule(expected: ResolvedModuleFull, actual: ResolvedModuleFull): boolean {
|
||||
if (!expected === !actual) {
|
||||
if (expected) {
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.extension === actual.extension, `'ext': expected '${Extension[expected.extension]}' to be equal to '${Extension[actual.extension]}'`);
|
||||
assert.isTrue(expected.isExternalLibraryImport === actual.isExternalLibraryImport, `'isExternalLibraryImport': expected '${expected.isExternalLibraryImport}' to be equal to '${actual.isExternalLibraryImport}'`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function checkResolvedModuleWithFailedLookupLocations(actual: ResolvedModuleWithFailedLookupLocations, expectedResolvedModule: ResolvedModuleFull, expectedFailedLookupLocations: string[]): void {
|
||||
assert.isTrue(actual.resolvedModule !== undefined, "module should be resolved");
|
||||
checkResolvedModule(actual.resolvedModule, expectedResolvedModule);
|
||||
assert.deepEqual(actual.failedLookupLocations, expectedFailedLookupLocations);
|
||||
}
|
||||
|
||||
export function createResolvedModule(resolvedFileName: string, isExternalLibraryImport = false): ResolvedModuleFull {
|
||||
return { resolvedFileName, extension: extensionFromPath(resolvedFileName), isExternalLibraryImport };
|
||||
}
|
||||
|
||||
interface File {
|
||||
name: string;
|
||||
content?: string;
|
||||
@ -53,8 +75,7 @@ namespace ts {
|
||||
const containingFile = { name: containingFileName };
|
||||
const moduleFile = { name: moduleFileNameNoExt + ext };
|
||||
const resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
checkResolvedModule(resolution.resolvedModule, createResolvedModule(moduleFile.name));
|
||||
|
||||
const failedLookupLocations: string[] = [];
|
||||
const dir = getDirectoryPath(containingFileName);
|
||||
@ -97,8 +118,7 @@ namespace ts {
|
||||
const packageJson = { name: packageJsonFileName, content: JSON.stringify({ "typings": fieldRef }) };
|
||||
const moduleFile = { name: moduleFileName };
|
||||
const resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
checkResolvedModule(resolution.resolvedModule, createResolvedModule(moduleFile.name));
|
||||
// expect three failed lookup location - attempt to load module as file with all supported extensions
|
||||
assert.equal(resolution.failedLookupLocations.length, supportedTypeScriptExtensions.length);
|
||||
}
|
||||
@ -125,7 +145,7 @@ namespace ts {
|
||||
|
||||
const resolution = nodeModuleNameResolver("b", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile, indexFile));
|
||||
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, indexPath);
|
||||
checkResolvedModule(resolution.resolvedModule, createResolvedModule(indexPath, /*isExternalLibraryImport*/true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +158,6 @@ namespace ts {
|
||||
/* tslint:enable no-null-keyword */
|
||||
testTypingsIgnored(undefined);
|
||||
});
|
||||
|
||||
it("module name as directory - load index.d.ts", () => {
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
@ -148,9 +167,7 @@ namespace ts {
|
||||
const packageJson = { name: "/a/b/foo/package.json", content: JSON.stringify({ main: "/c/d" }) };
|
||||
const indexFile = { name: "/a/b/foo/index.d.ts" };
|
||||
const resolution = nodeModuleNameResolver("./foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, indexFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, indexFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
checkResolvedModuleWithFailedLookupLocations(resolution, createResolvedModule(indexFile.name), [
|
||||
"/a/b/foo.ts",
|
||||
"/a/b/foo.tsx",
|
||||
"/a/b/foo.d.ts",
|
||||
@ -170,33 +187,39 @@ namespace ts {
|
||||
const containingFile = { name: "/a/b/c/d/e.ts" };
|
||||
const moduleFile = { name: "/a/b/node_modules/foo.ts" };
|
||||
const resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
checkResolvedModuleWithFailedLookupLocations(resolution, createResolvedModule(moduleFile.name, /*isExternalLibraryImport*/ true), [
|
||||
"/a/b/c/d/node_modules/foo.ts",
|
||||
"/a/b/c/d/node_modules/foo.tsx",
|
||||
"/a/b/c/d/node_modules/foo.d.ts",
|
||||
"/a/b/c/d/node_modules/foo/package.json",
|
||||
|
||||
"/a/b/c/d/node_modules/foo/index.ts",
|
||||
"/a/b/c/d/node_modules/foo/index.tsx",
|
||||
"/a/b/c/d/node_modules/foo/index.d.ts",
|
||||
|
||||
"/a/b/c/d/node_modules/@types/foo.ts",
|
||||
"/a/b/c/d/node_modules/@types/foo.tsx",
|
||||
"/a/b/c/d/node_modules/@types/foo.d.ts",
|
||||
"/a/b/c/d/node_modules/@types/foo/package.json",
|
||||
|
||||
"/a/b/c/d/node_modules/@types/foo/index.ts",
|
||||
"/a/b/c/d/node_modules/@types/foo/index.tsx",
|
||||
"/a/b/c/d/node_modules/@types/foo/index.d.ts",
|
||||
|
||||
"/a/b/c/node_modules/foo.ts",
|
||||
"/a/b/c/node_modules/foo.tsx",
|
||||
"/a/b/c/node_modules/foo.d.ts",
|
||||
"/a/b/c/node_modules/foo/package.json",
|
||||
|
||||
"/a/b/c/node_modules/foo/index.ts",
|
||||
"/a/b/c/node_modules/foo/index.tsx",
|
||||
"/a/b/c/node_modules/foo/index.d.ts",
|
||||
|
||||
"/a/b/c/node_modules/@types/foo.ts",
|
||||
"/a/b/c/node_modules/@types/foo.tsx",
|
||||
"/a/b/c/node_modules/@types/foo.d.ts",
|
||||
"/a/b/c/node_modules/@types/foo/package.json",
|
||||
|
||||
"/a/b/c/node_modules/@types/foo/index.ts",
|
||||
"/a/b/c/node_modules/@types/foo/index.tsx",
|
||||
"/a/b/c/node_modules/@types/foo/index.d.ts",
|
||||
@ -212,8 +235,7 @@ namespace ts {
|
||||
const containingFile = { name: "/a/b/c/d/e.ts" };
|
||||
const moduleFile = { name: "/a/b/node_modules/foo.d.ts" };
|
||||
const resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(resolution.resolvedModule.isExternalLibraryImport, true);
|
||||
checkResolvedModule(resolution.resolvedModule, createResolvedModule(moduleFile.name, /*isExternalLibraryImport*/ true));
|
||||
}
|
||||
});
|
||||
|
||||
@ -225,55 +247,66 @@ namespace ts {
|
||||
const containingFile = { name: "/a/node_modules/b/c/node_modules/d/e.ts" };
|
||||
const moduleFile = { name: "/a/node_modules/foo/index.d.ts" };
|
||||
const resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(resolution.resolvedModule.isExternalLibraryImport, true);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
checkResolvedModuleWithFailedLookupLocations(resolution, createResolvedModule(moduleFile.name, /*isExternalLibraryImport*/ true), [
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo.tsx",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo.d.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/package.json",
|
||||
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/index.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/index.tsx",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/index.d.ts",
|
||||
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/@types/foo.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/@types/foo.tsx",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/@types/foo.d.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/@types/foo/package.json",
|
||||
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/@types/foo/index.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/@types/foo/index.tsx",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/@types/foo/index.d.ts",
|
||||
|
||||
"/a/node_modules/b/c/node_modules/foo.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo.tsx",
|
||||
"/a/node_modules/b/c/node_modules/foo.d.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo/package.json",
|
||||
|
||||
"/a/node_modules/b/c/node_modules/foo/index.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo/index.tsx",
|
||||
"/a/node_modules/b/c/node_modules/foo/index.d.ts",
|
||||
|
||||
"/a/node_modules/b/c/node_modules/@types/foo.ts",
|
||||
"/a/node_modules/b/c/node_modules/@types/foo.tsx",
|
||||
"/a/node_modules/b/c/node_modules/@types/foo.d.ts",
|
||||
"/a/node_modules/b/c/node_modules/@types/foo/package.json",
|
||||
|
||||
"/a/node_modules/b/c/node_modules/@types/foo/index.ts",
|
||||
"/a/node_modules/b/c/node_modules/@types/foo/index.tsx",
|
||||
"/a/node_modules/b/c/node_modules/@types/foo/index.d.ts",
|
||||
|
||||
"/a/node_modules/b/node_modules/foo.ts",
|
||||
"/a/node_modules/b/node_modules/foo.tsx",
|
||||
"/a/node_modules/b/node_modules/foo.d.ts",
|
||||
"/a/node_modules/b/node_modules/foo/package.json",
|
||||
|
||||
"/a/node_modules/b/node_modules/foo/index.ts",
|
||||
"/a/node_modules/b/node_modules/foo/index.tsx",
|
||||
"/a/node_modules/b/node_modules/foo/index.d.ts",
|
||||
|
||||
"/a/node_modules/b/node_modules/@types/foo.ts",
|
||||
"/a/node_modules/b/node_modules/@types/foo.tsx",
|
||||
"/a/node_modules/b/node_modules/@types/foo.d.ts",
|
||||
"/a/node_modules/b/node_modules/@types/foo/package.json",
|
||||
|
||||
"/a/node_modules/b/node_modules/@types/foo/index.ts",
|
||||
"/a/node_modules/b/node_modules/@types/foo/index.tsx",
|
||||
"/a/node_modules/b/node_modules/@types/foo/index.d.ts",
|
||||
|
||||
"/a/node_modules/foo.ts",
|
||||
"/a/node_modules/foo.tsx",
|
||||
"/a/node_modules/foo.d.ts",
|
||||
"/a/node_modules/foo/package.json",
|
||||
|
||||
"/a/node_modules/foo/index.ts",
|
||||
"/a/node_modules/foo/index.tsx"
|
||||
]);
|
||||
@ -481,21 +514,15 @@ import b = require("./moduleB");
|
||||
const options: CompilerOptions = { moduleResolution, baseUrl: "/root" };
|
||||
{
|
||||
const result = resolveModuleName("folder2/file2", file1.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined, "module should be resolved");
|
||||
assert.equal(result.resolvedModule.resolvedFileName, file2.name);
|
||||
assert.deepEqual(result.failedLookupLocations, []);
|
||||
checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(file2.name), []);
|
||||
}
|
||||
{
|
||||
const result = resolveModuleName("./file3", file2.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined, "module should be resolved");
|
||||
assert.equal(result.resolvedModule.resolvedFileName, file3.name);
|
||||
assert.deepEqual(result.failedLookupLocations, []);
|
||||
checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(file3.name), []);
|
||||
}
|
||||
{
|
||||
const result = resolveModuleName("/root/folder1/file1", file2.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined, "module should be resolved");
|
||||
assert.equal(result.resolvedModule.resolvedFileName, file1.name);
|
||||
assert.deepEqual(result.failedLookupLocations, []);
|
||||
checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(file1.name), []);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -520,12 +547,11 @@ import b = require("./moduleB");
|
||||
check("m1", main, m1);
|
||||
check("m2", main, m2);
|
||||
check("m3", main, m3Typings);
|
||||
check("m4", main, m4);
|
||||
check("m4", main, m4, /*isExternalLibraryImport*/true);
|
||||
|
||||
function check(name: string, caller: File, expected: File) {
|
||||
function check(name: string, caller: File, expected: File, isExternalLibraryImport = false) {
|
||||
const result = resolveModuleName(name, caller.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined);
|
||||
assert.equal(result.resolvedModule.resolvedFileName, expected.name);
|
||||
checkResolvedModule(result.resolvedModule, createResolvedModule(expected.name, isExternalLibraryImport));
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -547,8 +573,7 @@ import b = require("./moduleB");
|
||||
|
||||
function check(name: string, caller: File, expected: File) {
|
||||
const result = resolveModuleName(name, caller.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined);
|
||||
assert.equal(result.resolvedModule.resolvedFileName, expected.name);
|
||||
checkResolvedModule(result.resolvedModule, createResolvedModule(expected.name));
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -590,9 +615,10 @@ import b = require("./moduleB");
|
||||
"/root/folder1/file2.tsx",
|
||||
"/root/folder1/file2.d.ts",
|
||||
"/root/folder1/file2/package.json",
|
||||
|
||||
"/root/folder1/file2/index.ts",
|
||||
"/root/folder1/file2/index.tsx",
|
||||
"/root/folder1/file2/index.d.ts"
|
||||
"/root/folder1/file2/index.d.ts",
|
||||
// then first attempt on 'generated/*' was successful
|
||||
]);
|
||||
check("folder2/file3", file3, [
|
||||
@ -601,14 +627,17 @@ import b = require("./moduleB");
|
||||
"/root/folder2/file3.tsx",
|
||||
"/root/folder2/file3.d.ts",
|
||||
"/root/folder2/file3/package.json",
|
||||
|
||||
"/root/folder2/file3/index.ts",
|
||||
"/root/folder2/file3/index.tsx",
|
||||
"/root/folder2/file3/index.d.ts",
|
||||
|
||||
// then use remapped location
|
||||
"/root/generated/folder2/file3.ts",
|
||||
"/root/generated/folder2/file3.tsx",
|
||||
"/root/generated/folder2/file3.d.ts",
|
||||
"/root/generated/folder2/file3/package.json",
|
||||
|
||||
"/root/generated/folder2/file3/index.ts",
|
||||
"/root/generated/folder2/file3/index.tsx",
|
||||
// success on index.d.ts
|
||||
@ -619,13 +648,15 @@ import b = require("./moduleB");
|
||||
"/root/folder2/file4.tsx",
|
||||
"/root/folder2/file4.d.ts",
|
||||
"/root/folder2/file4/package.json",
|
||||
|
||||
"/root/folder2/file4/index.ts",
|
||||
"/root/folder2/file4/index.tsx",
|
||||
"/root/folder2/file4/index.d.ts",
|
||||
|
||||
// try to load from file from remapped location
|
||||
"/root/generated/folder2/file4.ts",
|
||||
"/root/generated/folder2/file4.tsx",
|
||||
"/root/generated/folder2/file4.d.ts"
|
||||
"/root/generated/folder2/file4.d.ts",
|
||||
// success on loading as from folder
|
||||
]);
|
||||
check("somefolder/file5", file5, [
|
||||
@ -634,6 +665,7 @@ import b = require("./moduleB");
|
||||
"/root/someanotherfolder/file5.ts",
|
||||
"/root/someanotherfolder/file5.tsx",
|
||||
"/root/someanotherfolder/file5.d.ts",
|
||||
|
||||
// load from folder
|
||||
"/root/someanotherfolder/file5/package.json",
|
||||
"/root/someanotherfolder/file5/index.ts",
|
||||
@ -646,46 +678,51 @@ import b = require("./moduleB");
|
||||
"/root/file6.ts",
|
||||
"/root/file6.tsx",
|
||||
"/root/file6.d.ts",
|
||||
|
||||
// load from folder
|
||||
"/root/file6/package.json",
|
||||
"/root/file6/index.ts",
|
||||
"/root/file6/index.tsx",
|
||||
"/root/file6/index.d.ts",
|
||||
|
||||
// then try 'generated/*'
|
||||
// load from file
|
||||
"/root/generated/file6.ts",
|
||||
"/root/generated/file6.tsx",
|
||||
"/root/generated/file6.d.ts",
|
||||
|
||||
// load from folder
|
||||
"/root/generated/file6/package.json",
|
||||
"/root/generated/file6/index.ts",
|
||||
"/root/generated/file6/index.tsx",
|
||||
"/root/generated/file6/index.d.ts",
|
||||
|
||||
// fallback to standard node behavior
|
||||
// load from file
|
||||
"/root/folder1/node_modules/file6.ts",
|
||||
"/root/folder1/node_modules/file6.tsx",
|
||||
"/root/folder1/node_modules/file6.d.ts",
|
||||
|
||||
// load from folder
|
||||
"/root/folder1/node_modules/file6/package.json",
|
||||
"/root/folder1/node_modules/file6/index.ts",
|
||||
"/root/folder1/node_modules/file6/index.tsx",
|
||||
"/root/folder1/node_modules/file6/index.d.ts",
|
||||
|
||||
"/root/folder1/node_modules/@types/file6.ts",
|
||||
"/root/folder1/node_modules/@types/file6.tsx",
|
||||
"/root/folder1/node_modules/@types/file6.d.ts",
|
||||
|
||||
"/root/folder1/node_modules/@types/file6/package.json",
|
||||
"/root/folder1/node_modules/@types/file6/index.ts",
|
||||
"/root/folder1/node_modules/@types/file6/index.tsx",
|
||||
"/root/folder1/node_modules/@types/file6/index.d.ts"
|
||||
"/root/folder1/node_modules/@types/file6/index.d.ts",
|
||||
// success on /root/node_modules/file6.ts
|
||||
]);
|
||||
], /*isExternalLibraryImport*/ true);
|
||||
|
||||
function check(name: string, expected: File, expectedFailedLookups: string[]) {
|
||||
function check(name: string, expected: File, expectedFailedLookups: string[], isExternalLibraryImport = false) {
|
||||
const result = resolveModuleName(name, main.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined, "module should be resolved");
|
||||
assert.equal(result.resolvedModule.resolvedFileName, expected.name);
|
||||
assert.deepEqual(result.failedLookupLocations, expectedFailedLookups);
|
||||
checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(expected.name, isExternalLibraryImport), expectedFailedLookups);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -744,9 +781,7 @@ import b = require("./moduleB");
|
||||
|
||||
function check(name: string, expected: File, expectedFailedLookups: string[]) {
|
||||
const result = resolveModuleName(name, main.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined, "module should be resolved");
|
||||
assert.equal(result.resolvedModule.resolvedFileName, expected.name);
|
||||
assert.deepEqual(result.failedLookupLocations, expectedFailedLookups);
|
||||
checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(expected.name), expectedFailedLookups);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -819,9 +854,7 @@ import b = require("./moduleB");
|
||||
|
||||
function check(name: string, container: File, expected: File, expectedFailedLookups: string[]) {
|
||||
const result = resolveModuleName(name, container.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined, "module should be resolved");
|
||||
assert.equal(result.resolvedModule.resolvedFileName, expected.name);
|
||||
assert.deepEqual(result.failedLookupLocations, expectedFailedLookups);
|
||||
checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(expected.name), expectedFailedLookups);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -875,9 +908,7 @@ import b = require("./moduleB");
|
||||
|
||||
function check(name: string, container: File, expected: File, expectedFailedLookups: string[]) {
|
||||
const result = resolveModuleName(name, container.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined, "module should be resolved");
|
||||
assert.equal(result.resolvedModule.resolvedFileName, expected.name);
|
||||
assert.deepEqual(result.failedLookupLocations, expectedFailedLookups);
|
||||
checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(expected.name), expectedFailedLookups);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -899,9 +930,7 @@ import b = require("./moduleB");
|
||||
}
|
||||
};
|
||||
const result = resolveModuleName("libs/guid", app.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined, "module should be resolved");
|
||||
assert.equal(result.resolvedModule.resolvedFileName, libsTypings.name);
|
||||
assert.deepEqual(result.failedLookupLocations, [
|
||||
checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(libsTypings.name), [
|
||||
// first try to load module as file
|
||||
"/root/src/libs/guid.ts",
|
||||
"/root/src/libs/guid.tsx",
|
||||
|
||||
@ -150,17 +150,6 @@ namespace ts {
|
||||
return program;
|
||||
}
|
||||
|
||||
function checkResolvedModule(expected: ResolvedModule, actual: ResolvedModule): boolean {
|
||||
if (!expected === !actual) {
|
||||
if (expected) {
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.isExternalLibraryImport === actual.isExternalLibraryImport, `'isExternalLibraryImport': expected '${expected.isExternalLibraryImport}' to be equal to '${actual.isExternalLibraryImport}'`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkResolvedTypeDirective(expected: ResolvedTypeReferenceDirective, actual: ResolvedTypeReferenceDirective): boolean {
|
||||
if (!expected === !actual) {
|
||||
if (expected) {
|
||||
@ -300,7 +289,7 @@ namespace ts {
|
||||
const options: CompilerOptions = { target };
|
||||
|
||||
const program_1 = newProgram(files, ["a.ts"], options);
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMap({ "b": { resolvedFileName: "b.ts" } }));
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMap({ "b": createResolvedModule("b.ts") }));
|
||||
checkResolvedModulesCache(program_1, "b.ts", undefined);
|
||||
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], options, files => {
|
||||
@ -309,7 +298,7 @@ namespace ts {
|
||||
assert.isTrue(program_1.structureIsReused);
|
||||
|
||||
// content of resolution cache should not change
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMap({ "b": { resolvedFileName: "b.ts" } }));
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMap({ "b": createResolvedModule("b.ts") }));
|
||||
checkResolvedModulesCache(program_1, "b.ts", undefined);
|
||||
|
||||
// imports has changed - program is not reused
|
||||
@ -326,7 +315,7 @@ namespace ts {
|
||||
files[0].text = files[0].text.updateImportsAndExports(newImports);
|
||||
});
|
||||
assert.isTrue(!program_3.structureIsReused);
|
||||
checkResolvedModulesCache(program_4, "a.ts", createMap({ "b": { resolvedFileName: "b.ts" }, "c": undefined }));
|
||||
checkResolvedModulesCache(program_4, "a.ts", createMap({ "b": createResolvedModule("b.ts"), "c": undefined }));
|
||||
});
|
||||
|
||||
it("resolved type directives cache follows type directives", () => {
|
||||
|
||||
@ -150,7 +150,8 @@ namespace ts.server {
|
||||
target: ScriptTarget.ES5,
|
||||
jsx: JsxEmit.React,
|
||||
newLine: NewLineKind.LineFeed,
|
||||
moduleResolution: ModuleResolutionKind.NodeJs
|
||||
moduleResolution: ModuleResolutionKind.NodeJs,
|
||||
allowNonTsExtensions: true // injected by tsserver
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -28,6 +28,14 @@ namespace ts {
|
||||
assert.isTrue(arrayIsEqualTo(parsed.fileNames.sort(), expectedFileList.sort()));
|
||||
}
|
||||
|
||||
function assertParseFileDiagnostics(jsonText: string, configFileName: string, basePath: string, allFileList: string[], expectedDiagnosticCode: number) {
|
||||
const json = JSON.parse(jsonText);
|
||||
const host: ParseConfigHost = new Utils.MockParseConfigHost(basePath, true, allFileList);
|
||||
const parsed = ts.parseJsonConfigFileContent(json, host, basePath, /*existingOptions*/ undefined, configFileName);
|
||||
assert.isTrue(parsed.errors.length >= 0);
|
||||
assert.isTrue(parsed.errors.filter(e => e.code === expectedDiagnosticCode).length > 0, `Expected error code ${expectedDiagnosticCode} to be in ${JSON.stringify(parsed.errors)}`);
|
||||
}
|
||||
|
||||
it("returns empty config for file with only whitespaces", () => {
|
||||
assertParseResult("", { config : {} });
|
||||
assertParseResult(" ", { config : {} });
|
||||
@ -202,5 +210,64 @@ namespace ts {
|
||||
assert.isTrue(diagnostics.length === 2);
|
||||
assert.equal(JSON.stringify(configJsonObject), JSON.stringify(expectedResult));
|
||||
});
|
||||
|
||||
it("generates errors for empty files list", () => {
|
||||
const content = `{
|
||||
"files": []
|
||||
}`;
|
||||
assertParseFileDiagnostics(content,
|
||||
"/apath/tsconfig.json",
|
||||
"tests/cases/unittests",
|
||||
["/apath/a.ts"],
|
||||
Diagnostics.The_files_list_in_config_file_0_is_empty.code);
|
||||
});
|
||||
|
||||
it("generates errors for directory with no .ts files", () => {
|
||||
const content = `{
|
||||
}`;
|
||||
assertParseFileDiagnostics(content,
|
||||
"/apath/tsconfig.json",
|
||||
"tests/cases/unittests",
|
||||
["/apath/a.js"],
|
||||
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
|
||||
});
|
||||
|
||||
it("generates errors for empty directory", () => {
|
||||
const content = `{
|
||||
"compilerOptions": {
|
||||
"allowJs": true
|
||||
}
|
||||
}`;
|
||||
assertParseFileDiagnostics(content,
|
||||
"/apath/tsconfig.json",
|
||||
"tests/cases/unittests",
|
||||
[],
|
||||
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
|
||||
});
|
||||
|
||||
it("generates errors for empty include", () => {
|
||||
const content = `{
|
||||
"include": []
|
||||
}`;
|
||||
assertParseFileDiagnostics(content,
|
||||
"/apath/tsconfig.json",
|
||||
"tests/cases/unittests",
|
||||
["/apath/a.ts"],
|
||||
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
|
||||
});
|
||||
|
||||
it("generates errors for includes with outDir", () => {
|
||||
const content = `{
|
||||
"compilerOptions": {
|
||||
"outDir": "./"
|
||||
},
|
||||
"include": ["**/*"]
|
||||
}`;
|
||||
assertParseFileDiagnostics(content,
|
||||
"/apath/tsconfig.json",
|
||||
"tests/cases/unittests",
|
||||
["/apath/a.ts"],
|
||||
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -94,8 +94,8 @@ namespace ts.projectSystem {
|
||||
this.projectService.updateTypingsForProject(response);
|
||||
}
|
||||
|
||||
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions) {
|
||||
const request = server.createInstallTypingsRequest(project, typingOptions, this.globalTypingsCacheLocation);
|
||||
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions, unresolvedImports: server.SortedReadonlyArray<string>) {
|
||||
const request = server.createInstallTypingsRequest(project, typingOptions, unresolvedImports, this.globalTypingsCacheLocation);
|
||||
this.install(request);
|
||||
}
|
||||
|
||||
@ -1659,67 +1659,74 @@ namespace ts.projectSystem {
|
||||
"File '/a/b/node_modules/lib.ts' does not exist.",
|
||||
"File '/a/b/node_modules/lib.tsx' does not exist.",
|
||||
"File '/a/b/node_modules/lib.d.ts' does not exist.",
|
||||
"File '/a/b/node_modules/lib.js' does not exist.",
|
||||
"File '/a/b/node_modules/lib.jsx' does not exist.",
|
||||
"File '/a/b/node_modules/lib/package.json' does not exist.",
|
||||
"File '/a/b/node_modules/lib/index.ts' does not exist.",
|
||||
"File '/a/b/node_modules/lib/index.tsx' does not exist.",
|
||||
"File '/a/b/node_modules/lib/index.d.ts' does not exist.",
|
||||
"File '/a/b/node_modules/lib/index.js' does not exist.",
|
||||
"File '/a/b/node_modules/lib/index.jsx' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib.ts' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib.tsx' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib.d.ts' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib.js' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib.jsx' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib/package.json' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib/index.ts' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib/index.tsx' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib/index.d.ts' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib/index.js' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib/index.jsx' does not exist.",
|
||||
"File '/a/node_modules/lib.ts' does not exist.",
|
||||
"File '/a/node_modules/lib.tsx' does not exist.",
|
||||
"File '/a/node_modules/lib.d.ts' does not exist.",
|
||||
"File '/a/node_modules/lib.js' does not exist.",
|
||||
"File '/a/node_modules/lib.jsx' does not exist.",
|
||||
"File '/a/node_modules/lib/package.json' does not exist.",
|
||||
"File '/a/node_modules/lib/index.ts' does not exist.",
|
||||
"File '/a/node_modules/lib/index.tsx' does not exist.",
|
||||
"File '/a/node_modules/lib/index.d.ts' does not exist.",
|
||||
"File '/a/node_modules/lib/index.js' does not exist.",
|
||||
"File '/a/node_modules/lib/index.jsx' does not exist.",
|
||||
"File '/a/node_modules/@types/lib.ts' does not exist.",
|
||||
"File '/a/node_modules/@types/lib.tsx' does not exist.",
|
||||
"File '/a/node_modules/@types/lib.d.ts' does not exist.",
|
||||
"File '/a/node_modules/@types/lib.js' does not exist.",
|
||||
"File '/a/node_modules/@types/lib.jsx' does not exist.",
|
||||
"File '/a/node_modules/@types/lib/package.json' does not exist.",
|
||||
"File '/a/node_modules/@types/lib/index.ts' does not exist.",
|
||||
"File '/a/node_modules/@types/lib/index.tsx' does not exist.",
|
||||
"File '/a/node_modules/@types/lib/index.d.ts' does not exist.",
|
||||
"File '/a/node_modules/@types/lib/index.js' does not exist.",
|
||||
"File '/a/node_modules/@types/lib/index.jsx' does not exist.",
|
||||
"File '/node_modules/lib.ts' does not exist.",
|
||||
"File '/node_modules/lib.tsx' does not exist.",
|
||||
"File '/node_modules/lib.d.ts' does not exist.",
|
||||
"File '/node_modules/lib.js' does not exist.",
|
||||
"File '/node_modules/lib.jsx' does not exist.",
|
||||
"File '/node_modules/lib/package.json' does not exist.",
|
||||
"File '/node_modules/lib/index.ts' does not exist.",
|
||||
"File '/node_modules/lib/index.tsx' does not exist.",
|
||||
"File '/node_modules/lib/index.d.ts' does not exist.",
|
||||
"File '/node_modules/lib/index.js' does not exist.",
|
||||
"File '/node_modules/lib/index.jsx' does not exist.",
|
||||
"File '/node_modules/@types/lib.ts' does not exist.",
|
||||
"File '/node_modules/@types/lib.tsx' does not exist.",
|
||||
"File '/node_modules/@types/lib.d.ts' does not exist.",
|
||||
"File '/node_modules/@types/lib.js' does not exist.",
|
||||
"File '/node_modules/@types/lib.jsx' does not exist.",
|
||||
"File '/node_modules/@types/lib/package.json' does not exist.",
|
||||
"File '/node_modules/@types/lib/index.ts' does not exist.",
|
||||
"File '/node_modules/@types/lib/index.tsx' does not exist.",
|
||||
"File '/node_modules/@types/lib/index.d.ts' does not exist.",
|
||||
"Loading module 'lib' from 'node_modules' folder.",
|
||||
"File '/a/b/node_modules/lib.js' does not exist.",
|
||||
"File '/a/b/node_modules/lib.jsx' does not exist.",
|
||||
"File '/a/b/node_modules/lib/package.json' does not exist.",
|
||||
"File '/a/b/node_modules/lib/index.js' does not exist.",
|
||||
"File '/a/b/node_modules/lib/index.jsx' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib.js' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib.jsx' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib/package.json' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib/index.js' does not exist.",
|
||||
"File '/a/b/node_modules/@types/lib/index.jsx' does not exist.",
|
||||
"File '/a/node_modules/lib.js' does not exist.",
|
||||
"File '/a/node_modules/lib.jsx' does not exist.",
|
||||
"File '/a/node_modules/lib/package.json' does not exist.",
|
||||
"File '/a/node_modules/lib/index.js' does not exist.",
|
||||
"File '/a/node_modules/lib/index.jsx' does not exist.",
|
||||
"File '/a/node_modules/@types/lib.js' does not exist.",
|
||||
"File '/a/node_modules/@types/lib.jsx' does not exist.",
|
||||
"File '/a/node_modules/@types/lib/package.json' does not exist.",
|
||||
"File '/a/node_modules/@types/lib/index.js' does not exist.",
|
||||
"File '/a/node_modules/@types/lib/index.jsx' does not exist.",
|
||||
"File '/node_modules/lib.js' does not exist.",
|
||||
"File '/node_modules/lib.jsx' does not exist.",
|
||||
"File '/node_modules/lib/package.json' does not exist.",
|
||||
"File '/node_modules/lib/index.js' does not exist.",
|
||||
"File '/node_modules/lib/index.jsx' does not exist.",
|
||||
"File '/node_modules/@types/lib.js' does not exist.",
|
||||
"File '/node_modules/@types/lib.jsx' does not exist.",
|
||||
"File '/node_modules/@types/lib/package.json' does not exist.",
|
||||
"File '/node_modules/@types/lib/index.js' does not exist.",
|
||||
"File '/node_modules/@types/lib/index.jsx' does not exist.",
|
||||
"======== Module name 'lib' was not resolved. ========",
|
||||
@ -1727,19 +1734,13 @@ namespace ts.projectSystem {
|
||||
"File '/a/cache/node_modules/lib.ts' does not exist.",
|
||||
"File '/a/cache/node_modules/lib.tsx' does not exist.",
|
||||
"File '/a/cache/node_modules/lib.d.ts' does not exist.",
|
||||
"File '/a/cache/node_modules/lib.js' does not exist.",
|
||||
"File '/a/cache/node_modules/lib.jsx' does not exist.",
|
||||
"File '/a/cache/node_modules/lib/package.json' does not exist.",
|
||||
"File '/a/cache/node_modules/lib/index.ts' does not exist.",
|
||||
"File '/a/cache/node_modules/lib/index.tsx' does not exist.",
|
||||
"File '/a/cache/node_modules/lib/index.d.ts' does not exist.",
|
||||
"File '/a/cache/node_modules/lib/index.js' does not exist.",
|
||||
"File '/a/cache/node_modules/lib/index.jsx' does not exist.",
|
||||
"File '/a/cache/node_modules/@types/lib.ts' does not exist.",
|
||||
"File '/a/cache/node_modules/@types/lib.tsx' does not exist.",
|
||||
"File '/a/cache/node_modules/@types/lib.d.ts' does not exist.",
|
||||
"File '/a/cache/node_modules/@types/lib.js' does not exist.",
|
||||
"File '/a/cache/node_modules/@types/lib.jsx' does not exist.",
|
||||
"File '/a/cache/node_modules/@types/lib/package.json' does not exist.",
|
||||
"File '/a/cache/node_modules/@types/lib/index.ts' does not exist.",
|
||||
"File '/a/cache/node_modules/@types/lib/index.tsx' does not exist.",
|
||||
@ -2470,4 +2471,38 @@ namespace ts.projectSystem {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe("Inferred projects", () => {
|
||||
it("should support files without extensions", () => {
|
||||
const f = {
|
||||
path: "/a/compile",
|
||||
content: "let x = 1"
|
||||
};
|
||||
const host = createServerHost([f]);
|
||||
const session = createSession(host);
|
||||
session.executeCommand(<server.protocol.SetCompilerOptionsForInferredProjectsRequest>{
|
||||
seq: 1,
|
||||
type: "request",
|
||||
command: "compilerOptionsForInferredProjects",
|
||||
arguments: {
|
||||
options: {
|
||||
allowJs: true
|
||||
}
|
||||
}
|
||||
});
|
||||
session.executeCommand(<server.protocol.OpenRequest>{
|
||||
seq: 2,
|
||||
type: "request",
|
||||
command: "open",
|
||||
arguments: {
|
||||
file: f.path,
|
||||
fileContent: f.content,
|
||||
scriptKindName: "JS"
|
||||
}
|
||||
});
|
||||
const projectService = session.getProjectService();
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [f.path]);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -217,9 +217,9 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host);
|
||||
}
|
||||
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions) {
|
||||
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions, unresolvedImports: server.SortedReadonlyArray<string>) {
|
||||
enqueueIsCalled = true;
|
||||
super.enqueueInstallTypingsRequest(project, typingOptions);
|
||||
super.enqueueInstallTypingsRequest(project, typingOptions, unresolvedImports);
|
||||
}
|
||||
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
|
||||
const installedTypings = ["@types/jquery"];
|
||||
@ -319,9 +319,9 @@ namespace ts.projectSystem {
|
||||
constructor() {
|
||||
super(host);
|
||||
}
|
||||
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions) {
|
||||
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions, unresolvedImports: server.SortedReadonlyArray<string>) {
|
||||
enqueueIsCalled = true;
|
||||
super.enqueueInstallTypingsRequest(project, typingOptions);
|
||||
super.enqueueInstallTypingsRequest(project, typingOptions, unresolvedImports);
|
||||
}
|
||||
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
|
||||
const installedTypings: string[] = [];
|
||||
@ -724,7 +724,7 @@ namespace ts.projectSystem {
|
||||
it("Malformed package.json should be watched", () => {
|
||||
const f = {
|
||||
path: "/a/b/app.js",
|
||||
content: "var x = require('commander')"
|
||||
content: "var x = 1"
|
||||
};
|
||||
const brokenPackageJson = {
|
||||
path: "/a/b/package.json",
|
||||
@ -763,6 +763,133 @@ namespace ts.projectSystem {
|
||||
service.checkNumberOfProjects({ inferredProjects: 1 });
|
||||
checkProjectActualFiles(service.inferredProjects[0], [f.path, commander.path]);
|
||||
});
|
||||
|
||||
it("should install typings for unresolved imports", () => {
|
||||
const file = {
|
||||
path: "/a/b/app.js",
|
||||
content: `
|
||||
import * as fs from "fs";
|
||||
import * as commander from "commander";`
|
||||
};
|
||||
const cachePath = "/a/cache";
|
||||
const node = {
|
||||
path: cachePath + "/node_modules/@types/node/index.d.ts",
|
||||
content: "export let x: number"
|
||||
};
|
||||
const commander = {
|
||||
path: cachePath + "/node_modules/@types/commander/index.d.ts",
|
||||
content: "export let y: string"
|
||||
};
|
||||
const host = createServerHost([file]);
|
||||
const installer = new (class extends Installer {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: cachePath });
|
||||
}
|
||||
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/node", "@types/commander"];
|
||||
const typingFiles = [node, commander];
|
||||
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
|
||||
}
|
||||
})();
|
||||
const service = createProjectService(host, { typingsInstaller: installer });
|
||||
service.openClientFile(file.path);
|
||||
|
||||
service.checkNumberOfProjects({ inferredProjects: 1 });
|
||||
checkProjectActualFiles(service.inferredProjects[0], [file.path]);
|
||||
|
||||
installer.installAll([TI.NpmViewRequest, TI.NpmViewRequest], [TI.NpmInstallRequest]);
|
||||
|
||||
assert.isTrue(host.fileExists(node.path), "typings for 'node' should be created");
|
||||
assert.isTrue(host.fileExists(commander.path), "typings for 'commander' should be created");
|
||||
|
||||
checkProjectActualFiles(service.inferredProjects[0], [file.path, node.path, commander.path]);
|
||||
});
|
||||
|
||||
it("should pick typing names from non-relative unresolved imports", () => {
|
||||
const f1 = {
|
||||
path: "/a/b/app.js",
|
||||
content: `
|
||||
import * as a from "foo/a/a";
|
||||
import * as b from "foo/a/b";
|
||||
import * as c from "foo/a/c";
|
||||
import * as d from "@bar/router/";
|
||||
import * as e from "@bar/common/shared";
|
||||
import * as e from "@bar/common/apps";
|
||||
import * as f from "./lib"
|
||||
`
|
||||
};
|
||||
|
||||
const host = createServerHost([f1]);
|
||||
const installer = new (class extends Installer {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: "/tmp" });
|
||||
}
|
||||
executeRequest(requestKind: TI.RequestKind, _requestId: number, args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
|
||||
if (requestKind === TI.NpmViewRequest) {
|
||||
// args should have only non-scoped packages - scoped packages are not yet supported
|
||||
assert.deepEqual(args, ["foo"]);
|
||||
}
|
||||
executeCommand(this, host, ["foo"], [], requestKind, cb);
|
||||
}
|
||||
})();
|
||||
const projectService = createProjectService(host, { typingsInstaller: installer });
|
||||
projectService.openClientFile(f1.path);
|
||||
projectService.checkNumberOfProjects({ inferredProjects: 1 });
|
||||
|
||||
const proj = projectService.inferredProjects[0];
|
||||
proj.updateGraph();
|
||||
|
||||
assert.deepEqual(
|
||||
proj.getCachedUnresolvedImportsPerFile_TestOnly().get(<Path>f1.path),
|
||||
["foo", "foo", "foo", "@bar/router", "@bar/common", "@bar/common"]
|
||||
);
|
||||
|
||||
installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]);
|
||||
});
|
||||
|
||||
it("cached unresolved typings are not recomputed if program structure did not change", () => {
|
||||
const host = createServerHost([]);
|
||||
const session = createSession(host);
|
||||
const f = {
|
||||
path: "/a/app.js",
|
||||
content: `
|
||||
import * as fs from "fs";
|
||||
import * as cmd from "commander
|
||||
`
|
||||
};
|
||||
session.executeCommand(<server.protocol.OpenRequest>{
|
||||
seq: 1,
|
||||
type: "request",
|
||||
command: "open",
|
||||
arguments: {
|
||||
file: f.path,
|
||||
fileContent: f.content
|
||||
}
|
||||
});
|
||||
const projectService = session.getProjectService();
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 1 });
|
||||
const proj = projectService.inferredProjects[0];
|
||||
const version1 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion();
|
||||
|
||||
// make a change that should not affect the structure of the program
|
||||
session.executeCommand(<server.protocol.ChangeRequest>{
|
||||
seq: 2,
|
||||
type: "request",
|
||||
command: "change",
|
||||
arguments: {
|
||||
file: f.path,
|
||||
insertString: "\nlet x = 1;",
|
||||
line: 2,
|
||||
offset: 0,
|
||||
endLine: 2,
|
||||
endOffset: 0
|
||||
}
|
||||
});
|
||||
host.checkTimeoutQueueLength(1);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
const version2 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion();
|
||||
assert.equal(version1, version2, "set of unresolved imports should not change");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Validate package name:", () => {
|
||||
@ -820,4 +947,35 @@ namespace ts.projectSystem {
|
||||
assert.isTrue(messages.indexOf("Package name '; say ‘Hello from TypeScript!’ #' contains non URI safe characters") > 0, "should find package with invalid name");
|
||||
});
|
||||
});
|
||||
|
||||
describe("discover typings", () => {
|
||||
it("should return node for core modules", () => {
|
||||
const f = {
|
||||
path: "/a/b/app.js",
|
||||
content: ""
|
||||
};
|
||||
const host = createServerHost([f]);
|
||||
const cache = createMap<string>();
|
||||
for (const name of JsTyping.nodeCoreModuleList) {
|
||||
const result = JsTyping.discoverTypings(host, [f.path], getDirectoryPath(<Path>f.path), /*safeListPath*/ undefined, cache, { enableAutoDiscovery: true }, [name, "somename"]);
|
||||
assert.deepEqual(result.newTypingNames.sort(), ["node", "somename"]);
|
||||
}
|
||||
});
|
||||
|
||||
it("should use cached locaitons", () => {
|
||||
const f = {
|
||||
path: "/a/b/app.js",
|
||||
content: ""
|
||||
};
|
||||
const node = {
|
||||
path: "/a/b/node.d.ts",
|
||||
content: ""
|
||||
};
|
||||
const host = createServerHost([f, node]);
|
||||
const cache = createMap<string>({ "node": node.path });
|
||||
const result = JsTyping.discoverTypings(host, [f.path], getDirectoryPath(<Path>f.path), /*safeListPath*/ undefined, cache, { enableAutoDiscovery: true }, ["fs", "bar"]);
|
||||
assert.deepEqual(result.cachedTypingPaths, [node.path]);
|
||||
assert.deepEqual(result.newTypingNames, ["bar"]);
|
||||
});
|
||||
});
|
||||
}
|
||||
28
src/lib/dom.generated.d.ts
vendored
28
src/lib/dom.generated.d.ts
vendored
@ -1679,6 +1679,7 @@ interface CSSStyleDeclaration {
|
||||
writingMode: string | null;
|
||||
zIndex: string | null;
|
||||
zoom: string | null;
|
||||
resize: string | null;
|
||||
getPropertyPriority(propertyName: string): string;
|
||||
getPropertyValue(propertyName: string): string;
|
||||
item(index: number): string;
|
||||
@ -1748,6 +1749,7 @@ declare var CanvasGradient: {
|
||||
}
|
||||
|
||||
interface CanvasPattern {
|
||||
setTransform(matrix: SVGMatrix): void;
|
||||
}
|
||||
|
||||
declare var CanvasPattern: {
|
||||
@ -2173,7 +2175,7 @@ interface DataTransfer {
|
||||
effectAllowed: string;
|
||||
readonly files: FileList;
|
||||
readonly items: DataTransferItemList;
|
||||
readonly types: DOMStringList;
|
||||
readonly types: string[];
|
||||
clearData(format?: string): boolean;
|
||||
getData(format: string): string;
|
||||
setData(format: string, data: string): boolean;
|
||||
@ -7584,7 +7586,7 @@ declare var IDBCursorWithValue: {
|
||||
|
||||
interface IDBDatabase extends EventTarget {
|
||||
readonly name: string;
|
||||
readonly objectStoreNames: DOMStringList;
|
||||
readonly objectStoreNames: string[];
|
||||
onabort: (this: this, ev: Event) => any;
|
||||
onerror: (this: this, ev: ErrorEvent) => any;
|
||||
version: number;
|
||||
@ -7650,7 +7652,7 @@ declare var IDBKeyRange: {
|
||||
}
|
||||
|
||||
interface IDBObjectStore {
|
||||
readonly indexNames: DOMStringList;
|
||||
readonly indexNames: string[];
|
||||
keyPath: string | string[];
|
||||
readonly name: string;
|
||||
readonly transaction: IDBTransaction;
|
||||
@ -8602,7 +8604,7 @@ interface MouseEvent extends UIEvent {
|
||||
readonly x: number;
|
||||
readonly y: number;
|
||||
getModifierState(keyArg: string): boolean;
|
||||
initMouseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget): void;
|
||||
initMouseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget | null): void;
|
||||
}
|
||||
|
||||
declare var MouseEvent: {
|
||||
@ -8715,6 +8717,7 @@ interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorConte
|
||||
readonly plugins: PluginArray;
|
||||
readonly pointerEnabled: boolean;
|
||||
readonly webdriver: boolean;
|
||||
readonly hardwareConcurrency: number;
|
||||
getGamepads(): Gamepad[];
|
||||
javaEnabled(): boolean;
|
||||
msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void;
|
||||
@ -8732,18 +8735,18 @@ interface Node extends EventTarget {
|
||||
readonly attributes: NamedNodeMap;
|
||||
readonly baseURI: string | null;
|
||||
readonly childNodes: NodeList;
|
||||
readonly firstChild: Node;
|
||||
readonly lastChild: Node;
|
||||
readonly firstChild: Node | null;
|
||||
readonly lastChild: Node | null;
|
||||
readonly localName: string | null;
|
||||
readonly namespaceURI: string | null;
|
||||
readonly nextSibling: Node;
|
||||
readonly nextSibling: Node | null;
|
||||
readonly nodeName: string;
|
||||
readonly nodeType: number;
|
||||
nodeValue: string | null;
|
||||
readonly ownerDocument: Document;
|
||||
readonly parentElement: HTMLElement;
|
||||
readonly parentNode: Node;
|
||||
readonly previousSibling: Node;
|
||||
readonly parentElement: HTMLElement | null;
|
||||
readonly parentNode: Node | null;
|
||||
readonly previousSibling: Node | null;
|
||||
textContent: string | null;
|
||||
appendChild(newChild: Node): Node;
|
||||
cloneNode(deep?: boolean): Node;
|
||||
@ -12853,7 +12856,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window
|
||||
readonly devicePixelRatio: number;
|
||||
readonly doNotTrack: string;
|
||||
readonly document: Document;
|
||||
event: Event;
|
||||
event: Event | undefined;
|
||||
readonly external: External;
|
||||
readonly frameElement: Element;
|
||||
readonly frames: Window;
|
||||
@ -13155,6 +13158,7 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget {
|
||||
readonly upload: XMLHttpRequestUpload;
|
||||
withCredentials: boolean;
|
||||
msCaching?: string;
|
||||
readonly responseURL: string;
|
||||
abort(): void;
|
||||
getAllResponseHeaders(): string;
|
||||
getResponseHeader(header: string): string | null;
|
||||
@ -14301,7 +14305,7 @@ declare var defaultStatus: string;
|
||||
declare var devicePixelRatio: number;
|
||||
declare var doNotTrack: string;
|
||||
declare var document: Document;
|
||||
declare var event: Event;
|
||||
declare var event: Event | undefined;
|
||||
declare var external: External;
|
||||
declare var frameElement: Element;
|
||||
declare var frames: Window;
|
||||
|
||||
6
src/lib/webworker.generated.d.ts
vendored
6
src/lib/webworker.generated.d.ts
vendored
@ -341,7 +341,7 @@ declare var IDBCursorWithValue: {
|
||||
|
||||
interface IDBDatabase extends EventTarget {
|
||||
readonly name: string;
|
||||
readonly objectStoreNames: DOMStringList;
|
||||
readonly objectStoreNames: string[];
|
||||
onabort: (this: this, ev: Event) => any;
|
||||
onerror: (this: this, ev: ErrorEvent) => any;
|
||||
version: number;
|
||||
@ -407,7 +407,7 @@ declare var IDBKeyRange: {
|
||||
}
|
||||
|
||||
interface IDBObjectStore {
|
||||
readonly indexNames: DOMStringList;
|
||||
readonly indexNames: string[];
|
||||
keyPath: string | string[];
|
||||
readonly name: string;
|
||||
readonly transaction: IDBTransaction;
|
||||
@ -740,6 +740,7 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget {
|
||||
readonly upload: XMLHttpRequestUpload;
|
||||
withCredentials: boolean;
|
||||
msCaching?: string;
|
||||
readonly responseURL: string;
|
||||
abort(): void;
|
||||
getAllResponseHeaders(): string;
|
||||
getResponseHeader(header: string): string | null;
|
||||
@ -902,6 +903,7 @@ declare var WorkerLocation: {
|
||||
}
|
||||
|
||||
interface WorkerNavigator extends Object, NavigatorID, NavigatorOnLine {
|
||||
readonly hardwareConcurrency: number;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
|
||||
}
|
||||
|
||||
|
||||
@ -287,17 +287,20 @@ namespace ts.server {
|
||||
}
|
||||
switch (response.kind) {
|
||||
case "set":
|
||||
this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.typings);
|
||||
project.updateGraph();
|
||||
this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.unresolvedImports, response.typings);
|
||||
break;
|
||||
case "invalidate":
|
||||
this.typingsCache.invalidateCachedTypingsForProject(project);
|
||||
this.typingsCache.deleteTypingsForProject(response.projectName);
|
||||
break;
|
||||
}
|
||||
project.updateGraph();
|
||||
}
|
||||
|
||||
setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions): void {
|
||||
this.compilerOptionsForInferredProjects = convertCompilerOptions(projectCompilerOptions);
|
||||
// always set 'allowNonTsExtensions' for inferred projects since user cannot configure it from the outside
|
||||
// previously we did not expose a way for user to change these settings and this option was enabled by default
|
||||
this.compilerOptionsForInferredProjects.allowNonTsExtensions = true;
|
||||
this.compileOnSaveForInferredProjects = projectCompilerOptions.compileOnSave;
|
||||
for (const proj of this.inferredProjects) {
|
||||
proj.setCompilerOptions(this.compilerOptionsForInferredProjects);
|
||||
@ -1008,7 +1011,7 @@ namespace ts.server {
|
||||
const useExistingProject = this.useSingleInferredProject && this.inferredProjects.length;
|
||||
const project = useExistingProject
|
||||
? this.inferredProjects[0]
|
||||
: new InferredProject(this, this.documentRegistry, /*languageServiceEnabled*/ true, this.compilerOptionsForInferredProjects, /*compileOnSaveEnabled*/ this.compileOnSaveForInferredProjects);
|
||||
: new InferredProject(this, this.documentRegistry, /*languageServiceEnabled*/ true, this.compilerOptionsForInferredProjects);
|
||||
|
||||
project.addRoot(root);
|
||||
|
||||
|
||||
@ -5,59 +5,60 @@
|
||||
namespace ts.server {
|
||||
export class LSHost implements ts.LanguageServiceHost, ModuleResolutionHost, ServerLanguageServiceHost {
|
||||
private compilationSettings: ts.CompilerOptions;
|
||||
private readonly resolvedModuleNames: ts.FileMap<Map<ResolvedModuleWithFailedLookupLocations>>;
|
||||
private readonly resolvedTypeReferenceDirectives: ts.FileMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>;
|
||||
private readonly resolvedModuleNames= createFileMap<Map<ResolvedModuleWithFailedLookupLocations>>();
|
||||
private readonly resolvedTypeReferenceDirectives = createFileMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
|
||||
private readonly getCanonicalFileName: (fileName: string) => string;
|
||||
|
||||
private filesWithChangedSetOfUnresolvedImports: Path[];
|
||||
|
||||
private readonly resolveModuleName: typeof resolveModuleName;
|
||||
readonly trace: (s: string) => void;
|
||||
|
||||
constructor(private readonly host: ServerHost, private readonly project: Project, private readonly cancellationToken: HostCancellationToken) {
|
||||
this.getCanonicalFileName = ts.createGetCanonicalFileName(this.host.useCaseSensitiveFileNames);
|
||||
this.resolvedModuleNames = createFileMap<Map<ResolvedModuleWithFailedLookupLocations>>();
|
||||
this.resolvedTypeReferenceDirectives = createFileMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
|
||||
|
||||
if (host.trace) {
|
||||
this.trace = s => host.trace(s);
|
||||
}
|
||||
|
||||
this.resolveModuleName = (moduleName, containingFile, compilerOptions, host) => {
|
||||
const globalCache = this.project.getTypingOptions().enableAutoDiscovery
|
||||
? this.project.projectService.typingsInstaller.globalTypingsCacheLocation
|
||||
: undefined;
|
||||
const primaryResult = resolveModuleName(moduleName, containingFile, compilerOptions, host);
|
||||
if (primaryResult.resolvedModule) {
|
||||
// return result immediately only if it is .ts, .tsx or .d.ts
|
||||
// return result immediately only if it is .ts, .tsx or .d.ts
|
||||
if (!(primaryResult.resolvedModule && extensionIsTypeScript(primaryResult.resolvedModule.extension)) && globalCache !== undefined) {
|
||||
// otherwise try to load typings from @types
|
||||
if (fileExtensionIsAny(primaryResult.resolvedModule.resolvedFileName, supportedTypeScriptExtensions)) {
|
||||
return primaryResult;
|
||||
|
||||
// create different collection of failed lookup locations for second pass
|
||||
// if it will fail and we've already found something during the first pass - we don't want to pollute its results
|
||||
const { resolvedModule, failedLookupLocations } = loadModuleFromGlobalCache(moduleName, this.project.getProjectName(), compilerOptions, host, globalCache);
|
||||
if (resolvedModule) {
|
||||
return { resolvedModule, failedLookupLocations: primaryResult.failedLookupLocations.concat(failedLookupLocations) };
|
||||
}
|
||||
}
|
||||
// create different collection of failed lookup locations for second pass
|
||||
// if it will fail and we've already found something during the first pass - we don't want to pollute its results
|
||||
const secondaryLookupFailedLookupLocations: string[] = [];
|
||||
const globalCache = this.project.projectService.typingsInstaller.globalTypingsCacheLocation;
|
||||
if (this.project.getTypingOptions().enableAutoDiscovery && globalCache) {
|
||||
const traceEnabled = isTraceEnabled(compilerOptions, host);
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, this.project.getProjectName(), moduleName, globalCache);
|
||||
}
|
||||
const state: ModuleResolutionState = { compilerOptions, host, skipTsx: false, traceEnabled };
|
||||
const resolvedName = loadModuleFromNodeModules(moduleName, globalCache, secondaryLookupFailedLookupLocations, state, /*checkOneLevel*/ true);
|
||||
if (resolvedName) {
|
||||
return createResolvedModule(resolvedName, /*isExternalLibraryImport*/ true, primaryResult.failedLookupLocations.concat(secondaryLookupFailedLookupLocations));
|
||||
}
|
||||
}
|
||||
if (!primaryResult.resolvedModule && secondaryLookupFailedLookupLocations.length) {
|
||||
primaryResult.failedLookupLocations = primaryResult.failedLookupLocations.concat(secondaryLookupFailedLookupLocations);
|
||||
}
|
||||
return primaryResult;
|
||||
};
|
||||
}
|
||||
|
||||
private resolveNamesWithLocalCache<T extends { failedLookupLocations: string[] }, R extends { resolvedFileName?: string }>(
|
||||
public startRecordingFilesWithChangedResolutions() {
|
||||
this.filesWithChangedSetOfUnresolvedImports = [];
|
||||
}
|
||||
|
||||
public finishRecordingFilesWithChangedResolutions() {
|
||||
const collected = this.filesWithChangedSetOfUnresolvedImports;
|
||||
this.filesWithChangedSetOfUnresolvedImports = undefined;
|
||||
return collected;
|
||||
}
|
||||
|
||||
private resolveNamesWithLocalCache<T extends { failedLookupLocations: string[] }, R>(
|
||||
names: string[],
|
||||
containingFile: string,
|
||||
cache: ts.FileMap<Map<T>>,
|
||||
loader: (name: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost) => T,
|
||||
getResult: (s: T) => R): R[] {
|
||||
getResult: (s: T) => R,
|
||||
getResultFileName: (result: R) => string | undefined,
|
||||
logChanges: boolean): R[] {
|
||||
|
||||
const path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName);
|
||||
const currentResolutionsInFile = cache.get(path);
|
||||
@ -79,6 +80,11 @@ namespace ts.server {
|
||||
else {
|
||||
newResolutions[name] = resolution = loader(name, containingFile, compilerOptions, this);
|
||||
}
|
||||
if (logChanges && this.filesWithChangedSetOfUnresolvedImports && !resolutionIsEqualTo(existingResolution, resolution)) {
|
||||
this.filesWithChangedSetOfUnresolvedImports.push(path);
|
||||
// reset log changes to avoid recording the same file multiple times
|
||||
logChanges = false;
|
||||
}
|
||||
}
|
||||
|
||||
ts.Debug.assert(resolution !== undefined);
|
||||
@ -90,6 +96,24 @@ namespace ts.server {
|
||||
cache.set(path, newResolutions);
|
||||
return resolvedModules;
|
||||
|
||||
function resolutionIsEqualTo(oldResolution: T, newResolution: T): boolean {
|
||||
if (oldResolution === newResolution) {
|
||||
return true;
|
||||
}
|
||||
if (!oldResolution || !newResolution) {
|
||||
return false;
|
||||
}
|
||||
const oldResult = getResult(oldResolution);
|
||||
const newResult = getResult(newResolution);
|
||||
if (oldResult === newResult) {
|
||||
return true;
|
||||
}
|
||||
if (!oldResult || !newResult) {
|
||||
return false;
|
||||
}
|
||||
return getResultFileName(oldResult) === getResultFileName(newResult);
|
||||
}
|
||||
|
||||
function moduleResolutionIsValid(resolution: T): boolean {
|
||||
if (!resolution) {
|
||||
return false;
|
||||
@ -97,10 +121,7 @@ namespace ts.server {
|
||||
|
||||
const result = getResult(resolution);
|
||||
if (result) {
|
||||
if (result.resolvedFileName && result.resolvedFileName === lastDeletedFileName) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return getResultFileName(result) !== lastDeletedFileName;
|
||||
}
|
||||
|
||||
// consider situation if we have no candidate locations as valid resolution.
|
||||
@ -126,11 +147,13 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[] {
|
||||
return this.resolveNamesWithLocalCache(typeDirectiveNames, containingFile, this.resolvedTypeReferenceDirectives, resolveTypeReferenceDirective, m => m.resolvedTypeReferenceDirective);
|
||||
return this.resolveNamesWithLocalCache(typeDirectiveNames, containingFile, this.resolvedTypeReferenceDirectives, resolveTypeReferenceDirective,
|
||||
m => m.resolvedTypeReferenceDirective, r => r.resolvedFileName, /*logChanges*/ false);
|
||||
}
|
||||
|
||||
resolveModuleNames(moduleNames: string[], containingFile: string): ResolvedModule[] {
|
||||
return this.resolveNamesWithLocalCache(moduleNames, containingFile, this.resolvedModuleNames, this.resolveModuleName, m => m.resolvedModule);
|
||||
resolveModuleNames(moduleNames: string[], containingFile: string): ResolvedModuleFull[] {
|
||||
return this.resolveNamesWithLocalCache(moduleNames, containingFile, this.resolvedModuleNames, this.resolveModuleName,
|
||||
m => m.resolvedModule, r => r.resolvedFileName, /*logChanges*/ true);
|
||||
}
|
||||
|
||||
getDefaultLibFileName() {
|
||||
@ -197,10 +220,11 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
setCompilationSettings(opt: ts.CompilerOptions) {
|
||||
if (changesAffectModuleResolution(this.compilationSettings, opt)) {
|
||||
this.resolvedModuleNames.clear();
|
||||
this.resolvedTypeReferenceDirectives.clear();
|
||||
}
|
||||
this.compilationSettings = opt;
|
||||
// conservatively assume that changing compiler options might affect module resolution strategy
|
||||
this.resolvedModuleNames.clear();
|
||||
this.resolvedTypeReferenceDirectives.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,12 +62,43 @@ namespace ts.server {
|
||||
projectErrors: Diagnostic[];
|
||||
}
|
||||
|
||||
export class UnresolvedImportsMap {
|
||||
readonly perFileMap = createFileMap<ReadonlyArray<string>>();
|
||||
private version = 0;
|
||||
|
||||
public clear() {
|
||||
this.perFileMap.clear();
|
||||
this.version = 0;
|
||||
}
|
||||
|
||||
public getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public remove(path: Path) {
|
||||
this.perFileMap.remove(path);
|
||||
this.version++;
|
||||
}
|
||||
|
||||
public get(path: Path) {
|
||||
return this.perFileMap.get(path);
|
||||
}
|
||||
|
||||
public set(path: Path, value: ReadonlyArray<string>) {
|
||||
this.perFileMap.set(path, value);
|
||||
this.version++;
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class Project {
|
||||
private rootFiles: ScriptInfo[] = [];
|
||||
private rootFilesMap: FileMap<ScriptInfo> = createFileMap<ScriptInfo>();
|
||||
private lsHost: ServerLanguageServiceHost;
|
||||
private program: ts.Program;
|
||||
|
||||
private cachedUnresolvedImportsPerFile = new UnresolvedImportsMap();
|
||||
private lastCachedUnresolvedImportsList: SortedReadonlyArray<string>;
|
||||
|
||||
private languageService: LanguageService;
|
||||
builder: Builder;
|
||||
/**
|
||||
@ -91,7 +122,7 @@ namespace ts.server {
|
||||
*/
|
||||
private projectStateVersion = 0;
|
||||
|
||||
private typingFiles: TypingsArray;
|
||||
private typingFiles: SortedReadonlyArray<string>;
|
||||
|
||||
protected projectErrors: Diagnostic[];
|
||||
|
||||
@ -107,6 +138,10 @@ namespace ts.server {
|
||||
return hasOneOrMoreJsAndNoTsFiles(this);
|
||||
}
|
||||
|
||||
public getCachedUnresolvedImportsPerFile_TestOnly() {
|
||||
return this.cachedUnresolvedImportsPerFile;
|
||||
}
|
||||
|
||||
constructor(
|
||||
readonly projectKind: ProjectKind,
|
||||
readonly projectService: ProjectService,
|
||||
@ -326,6 +361,7 @@ namespace ts.server {
|
||||
removeFile(info: ScriptInfo, detachFromProject = true) {
|
||||
this.removeRootFileIfNecessary(info);
|
||||
this.lsHost.notifyFileRemoved(info);
|
||||
this.cachedUnresolvedImportsPerFile.remove(info.path);
|
||||
|
||||
if (detachFromProject) {
|
||||
info.detachFromProject(this);
|
||||
@ -338,6 +374,38 @@ namespace ts.server {
|
||||
this.projectStateVersion++;
|
||||
}
|
||||
|
||||
private extractUnresolvedImportsFromSourceFile(file: SourceFile, result: string[]) {
|
||||
const cached = this.cachedUnresolvedImportsPerFile.get(file.path);
|
||||
if (cached) {
|
||||
// found cached result - use it and return
|
||||
for (const f of cached) {
|
||||
result.push(f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let unresolvedImports: string[];
|
||||
if (file.resolvedModules) {
|
||||
for (const name in file.resolvedModules) {
|
||||
// pick unresolved non-relative names
|
||||
if (!file.resolvedModules[name] && !isExternalModuleNameRelative(name)) {
|
||||
// for non-scoped names extract part up-to the first slash
|
||||
// for scoped names - extract up to the second slash
|
||||
let trimmed = name.trim();
|
||||
let i = trimmed.indexOf("/");
|
||||
if (i !== -1 && trimmed.charCodeAt(0) === CharacterCodes.at) {
|
||||
i = trimmed.indexOf("/", i + 1);
|
||||
}
|
||||
if (i !== -1) {
|
||||
trimmed = trimmed.substr(0, i);
|
||||
}
|
||||
(unresolvedImports || (unresolvedImports = [])).push(trimmed);
|
||||
result.push(trimmed);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.cachedUnresolvedImportsPerFile.set(file.path, unresolvedImports || emptyArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates set of files that contribute to this project
|
||||
* @returns: true if set of files in the project stays the same and false - otherwise.
|
||||
@ -346,8 +414,35 @@ namespace ts.server {
|
||||
if (!this.languageServiceEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.lsHost.startRecordingFilesWithChangedResolutions();
|
||||
|
||||
let hasChanges = this.updateGraphWorker();
|
||||
const cachedTypings = this.projectService.typingsCache.getTypingsForProject(this, hasChanges);
|
||||
|
||||
const changedFiles: ReadonlyArray<Path> = this.lsHost.finishRecordingFilesWithChangedResolutions() || emptyArray;
|
||||
|
||||
for (const file of changedFiles) {
|
||||
// delete cached information for changed files
|
||||
this.cachedUnresolvedImportsPerFile.remove(file);
|
||||
}
|
||||
|
||||
// 1. no changes in structure, no changes in unresolved imports - do nothing
|
||||
// 2. no changes in structure, unresolved imports were changed - collect unresolved imports for all files
|
||||
// (can reuse cached imports for files that were not changed)
|
||||
// 3. new files were added/removed, but compilation settings stays the same - collect unresolved imports for all new/modified files
|
||||
// (can reuse cached imports for files that were not changed)
|
||||
// 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch
|
||||
let unresolvedImports: SortedReadonlyArray<string>;
|
||||
if (hasChanges || changedFiles.length) {
|
||||
const result: string[] = [];
|
||||
for (const sourceFile of this.program.getSourceFiles()) {
|
||||
this.extractUnresolvedImportsFromSourceFile(sourceFile, result);
|
||||
}
|
||||
this.lastCachedUnresolvedImportsList = toSortedReadonlyArray(result);
|
||||
}
|
||||
unresolvedImports = this.lastCachedUnresolvedImportsList;
|
||||
|
||||
const cachedTypings = this.projectService.typingsCache.getTypingsForProject(this, unresolvedImports, hasChanges);
|
||||
if (this.setTypings(cachedTypings)) {
|
||||
hasChanges = this.updateGraphWorker() || hasChanges;
|
||||
}
|
||||
@ -357,7 +452,7 @@ namespace ts.server {
|
||||
return !hasChanges;
|
||||
}
|
||||
|
||||
private setTypings(typings: TypingsArray): boolean {
|
||||
private setTypings(typings: SortedReadonlyArray<string>): boolean {
|
||||
if (arrayIsEqualTo(this.typingFiles, typings)) {
|
||||
return false;
|
||||
}
|
||||
@ -430,6 +525,11 @@ namespace ts.server {
|
||||
compilerOptions.allowJs = true;
|
||||
}
|
||||
compilerOptions.allowNonTsExtensions = true;
|
||||
if (changesAffectModuleResolution(this.compilerOptions, compilerOptions)) {
|
||||
// reset cached unresolved imports if changes in compiler options affected module resolution
|
||||
this.cachedUnresolvedImportsPerFile.clear();
|
||||
this.lastCachedUnresolvedImportsList = undefined;
|
||||
}
|
||||
this.compilerOptions = compilerOptions;
|
||||
this.lsHost.setCompilationSettings(compilerOptions);
|
||||
|
||||
@ -566,14 +666,14 @@ namespace ts.server {
|
||||
// Used to keep track of what directories are watched for this project
|
||||
directoriesWatchedForTsconfig: string[] = [];
|
||||
|
||||
constructor(projectService: ProjectService, documentRegistry: ts.DocumentRegistry, languageServiceEnabled: boolean, compilerOptions: CompilerOptions, public compileOnSaveEnabled: boolean) {
|
||||
constructor(projectService: ProjectService, documentRegistry: ts.DocumentRegistry, languageServiceEnabled: boolean, compilerOptions: CompilerOptions) {
|
||||
super(ProjectKind.Inferred,
|
||||
projectService,
|
||||
documentRegistry,
|
||||
/*files*/ undefined,
|
||||
languageServiceEnabled,
|
||||
compilerOptions,
|
||||
compileOnSaveEnabled);
|
||||
/*compileOnSaveEnabled*/ false);
|
||||
|
||||
this.inferredProjectName = makeInferredProjectName(InferredProject.NextId);
|
||||
InferredProject.NextId++;
|
||||
|
||||
@ -14,21 +14,33 @@ namespace ts.server {
|
||||
} = require("child_process");
|
||||
|
||||
const os: {
|
||||
homedir(): string
|
||||
homedir?(): string;
|
||||
tmpdir(): string;
|
||||
} = require("os");
|
||||
|
||||
|
||||
function getGlobalTypingsCacheLocation() {
|
||||
let basePath: string;
|
||||
switch (process.platform) {
|
||||
case "win32":
|
||||
basePath = process.env.LOCALAPPDATA || process.env.APPDATA || os.homedir();
|
||||
basePath = process.env.LOCALAPPDATA ||
|
||||
process.env.APPDATA ||
|
||||
(os.homedir && os.homedir()) ||
|
||||
process.env.USERPROFILE ||
|
||||
(process.env.HOMEDRIVE && process.env.HOMEPATH && normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) ||
|
||||
os.tmpdir();
|
||||
break;
|
||||
case "linux":
|
||||
basePath = os.homedir();
|
||||
basePath = (os.homedir && os.homedir()) ||
|
||||
process.env.HOME ||
|
||||
((process.env.LOGNAME || process.env.USER) && `/home/${process.env.LOGNAME || process.env.USER}`) ||
|
||||
os.tmpdir();
|
||||
break;
|
||||
case "darwin":
|
||||
basePath = combinePaths(os.homedir(), "Library/Application Support/");
|
||||
const homeDir = (os.homedir && os.homedir()) ||
|
||||
process.env.HOME ||
|
||||
((process.env.LOGNAME || process.env.USER) && `/Users/${process.env.LOGNAME || process.env.USER}`) ||
|
||||
os.tmpdir();
|
||||
basePath = combinePaths(homeDir, "Library/Application Support/");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -40,6 +52,7 @@ namespace ts.server {
|
||||
send(message: any, sendHandle?: any): void;
|
||||
on(message: "message", f: (m: any) => void): void;
|
||||
kill(): void;
|
||||
pid: number;
|
||||
}
|
||||
|
||||
interface NodeSocket {
|
||||
@ -179,21 +192,40 @@ namespace ts.server {
|
||||
|
||||
class NodeTypingsInstaller implements ITypingsInstaller {
|
||||
private installer: NodeChildProcess;
|
||||
private installerPidReported = false;
|
||||
private socket: NodeSocket;
|
||||
private projectService: ProjectService;
|
||||
private throttledOperations: ThrottledOperations;
|
||||
|
||||
constructor(
|
||||
private readonly logger: server.Logger,
|
||||
host: ServerHost,
|
||||
eventPort: number,
|
||||
readonly globalTypingsCacheLocation: string,
|
||||
private newLine: string) {
|
||||
this.throttledOperations = new ThrottledOperations(host);
|
||||
if (eventPort) {
|
||||
const s = net.connect({ port: eventPort }, () => {
|
||||
this.socket = s;
|
||||
this.reportInstallerProcessId();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private reportInstallerProcessId() {
|
||||
if (this.installerPidReported) {
|
||||
return;
|
||||
}
|
||||
if (this.socket && this.installer) {
|
||||
this.sendEvent(0, "typingsInstallerPid", { pid: this.installer.pid });
|
||||
this.installerPidReported = true;
|
||||
}
|
||||
}
|
||||
|
||||
private sendEvent(seq: number, event: string, body: any): void {
|
||||
this.socket.write(formatMessage({ seq, type: "event", event, body }, this.logger, Buffer.byteLength, this.newLine), "utf8");
|
||||
}
|
||||
|
||||
attach(projectService: ProjectService) {
|
||||
this.projectService = projectService;
|
||||
if (this.logger.hasLevel(LogLevel.requestTime)) {
|
||||
@ -222,6 +254,8 @@ namespace ts.server {
|
||||
|
||||
this.installer = childProcess.fork(combinePaths(__dirname, "typingsInstaller.js"), args, { execArgv });
|
||||
this.installer.on("message", m => this.handleMessage(m));
|
||||
this.reportInstallerProcessId();
|
||||
|
||||
process.on("exit", () => {
|
||||
this.installer.kill();
|
||||
});
|
||||
@ -231,12 +265,19 @@ namespace ts.server {
|
||||
this.installer.send({ projectName: p.getProjectName(), kind: "closeProject" });
|
||||
}
|
||||
|
||||
enqueueInstallTypingsRequest(project: Project, typingOptions: TypingOptions): void {
|
||||
const request = createInstallTypingsRequest(project, typingOptions);
|
||||
enqueueInstallTypingsRequest(project: Project, typingOptions: TypingOptions, unresolvedImports: SortedReadonlyArray<string>): void {
|
||||
const request = createInstallTypingsRequest(project, typingOptions, unresolvedImports);
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Sending request: ${JSON.stringify(request)}`);
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Scheduling throttled operation: ${JSON.stringify(request)}`);
|
||||
}
|
||||
}
|
||||
this.installer.send(request);
|
||||
this.throttledOperations.schedule(project.getProjectName(), /*ms*/ 250, () => {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Sending request: ${JSON.stringify(request)}`);
|
||||
}
|
||||
this.installer.send(request);
|
||||
});
|
||||
}
|
||||
|
||||
private handleMessage(response: SetTypings | InvalidateCachedTypings) {
|
||||
@ -245,7 +286,7 @@ namespace ts.server {
|
||||
}
|
||||
this.projectService.updateTypingsForProject(response);
|
||||
if (response.kind == "set" && this.socket) {
|
||||
this.socket.write(formatMessage({ seq: 0, type: "event", message: response }, this.logger, Buffer.byteLength, this.newLine), "utf8");
|
||||
this.sendEvent(0, "setTypings", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,7 +307,7 @@ namespace ts.server {
|
||||
useSingleInferredProject,
|
||||
disableAutomaticTypingAcquisition
|
||||
? nullTypingsInstaller
|
||||
: new NodeTypingsInstaller(logger, installerEventPort, globalTypingsCacheLocation, host.newLine),
|
||||
: new NodeTypingsInstaller(logger, host, installerEventPort, globalTypingsCacheLocation, host.newLine),
|
||||
Buffer.byteLength,
|
||||
process.hrtime,
|
||||
logger,
|
||||
|
||||
16
src/server/types.d.ts
vendored
16
src/server/types.d.ts
vendored
@ -18,6 +18,10 @@ declare namespace ts.server {
|
||||
trace?(s: string): void;
|
||||
}
|
||||
|
||||
export interface SortedReadonlyArray<T> extends ReadonlyArray<T> {
|
||||
" __sortedReadonlyArrayBrand": any;
|
||||
}
|
||||
|
||||
export interface TypingInstallerRequest {
|
||||
readonly projectName: string;
|
||||
readonly kind: "discover" | "closeProject";
|
||||
@ -26,8 +30,9 @@ declare namespace ts.server {
|
||||
export interface DiscoverTypings extends TypingInstallerRequest {
|
||||
readonly fileNames: string[];
|
||||
readonly projectRootPath: ts.Path;
|
||||
readonly typingOptions: ts.TypingOptions;
|
||||
readonly compilerOptions: ts.CompilerOptions;
|
||||
readonly typingOptions: ts.TypingOptions;
|
||||
readonly unresolvedImports: SortedReadonlyArray<string>;
|
||||
readonly cachePath?: string;
|
||||
readonly kind: "discover";
|
||||
}
|
||||
@ -36,20 +41,23 @@ declare namespace ts.server {
|
||||
readonly kind: "closeProject";
|
||||
}
|
||||
|
||||
export type SetRequest = "set";
|
||||
export type InvalidateRequest = "invalidate";
|
||||
export interface TypingInstallerResponse {
|
||||
readonly projectName: string;
|
||||
readonly kind: "set" | "invalidate";
|
||||
readonly kind: SetRequest | InvalidateRequest;
|
||||
}
|
||||
|
||||
export interface SetTypings extends TypingInstallerResponse {
|
||||
readonly typingOptions: ts.TypingOptions;
|
||||
readonly compilerOptions: ts.CompilerOptions;
|
||||
readonly typings: string[];
|
||||
readonly kind: "set";
|
||||
readonly unresolvedImports: SortedReadonlyArray<string>;
|
||||
readonly kind: SetRequest;
|
||||
}
|
||||
|
||||
export interface InvalidateCachedTypings extends TypingInstallerResponse {
|
||||
readonly kind: "invalidate";
|
||||
readonly kind: InvalidateRequest;
|
||||
}
|
||||
|
||||
export interface InstallTypingHost extends JsTyping.TypingResolutionHost {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
namespace ts.server {
|
||||
export interface ITypingsInstaller {
|
||||
enqueueInstallTypingsRequest(p: Project, typingOptions: TypingOptions): void;
|
||||
enqueueInstallTypingsRequest(p: Project, typingOptions: TypingOptions, unresolvedImports: SortedReadonlyArray<string>): void;
|
||||
attach(projectService: ProjectService): void;
|
||||
onProjectClosed(p: Project): void;
|
||||
readonly globalTypingsCacheLocation: string;
|
||||
@ -18,7 +18,9 @@ namespace ts.server {
|
||||
class TypingsCacheEntry {
|
||||
readonly typingOptions: TypingOptions;
|
||||
readonly compilerOptions: CompilerOptions;
|
||||
readonly typings: TypingsArray;
|
||||
readonly typings: SortedReadonlyArray<string>;
|
||||
readonly unresolvedImports: SortedReadonlyArray<string>;
|
||||
/* mainly useful for debugging */
|
||||
poisoned: boolean;
|
||||
}
|
||||
|
||||
@ -61,13 +63,11 @@ namespace ts.server {
|
||||
return opt1.allowJs != opt2.allowJs;
|
||||
}
|
||||
|
||||
export interface TypingsArray extends ReadonlyArray<string> {
|
||||
" __typingsArrayBrand": any;
|
||||
}
|
||||
|
||||
function toTypingsArray(arr: string[]): TypingsArray {
|
||||
arr.sort();
|
||||
return <any>arr;
|
||||
function unresolvedImportsChanged(imports1: SortedReadonlyArray<string>, imports2: SortedReadonlyArray<string>): boolean {
|
||||
if (imports1 === imports2) {
|
||||
return false;
|
||||
}
|
||||
return !arrayIsEqualTo(imports1, imports2);
|
||||
}
|
||||
|
||||
export class TypingsCache {
|
||||
@ -76,7 +76,7 @@ namespace ts.server {
|
||||
constructor(private readonly installer: ITypingsInstaller) {
|
||||
}
|
||||
|
||||
getTypingsForProject(project: Project, forceRefresh: boolean): TypingsArray {
|
||||
getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray<string>, forceRefresh: boolean): SortedReadonlyArray<string> {
|
||||
const typingOptions = project.getTypingOptions();
|
||||
|
||||
if (!typingOptions || !typingOptions.enableAutoDiscovery) {
|
||||
@ -84,39 +84,41 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
const entry = this.perProjectCache[project.getProjectName()];
|
||||
const result: TypingsArray = entry ? entry.typings : <any>emptyArray;
|
||||
if (forceRefresh || !entry || typingOptionsChanged(typingOptions, entry.typingOptions) || compilerOptionsChanged(project.getCompilerOptions(), entry.compilerOptions)) {
|
||||
const result: SortedReadonlyArray<string> = entry ? entry.typings : <any>emptyArray;
|
||||
if (forceRefresh ||
|
||||
!entry ||
|
||||
typingOptionsChanged(typingOptions, entry.typingOptions) ||
|
||||
compilerOptionsChanged(project.getCompilerOptions(), entry.compilerOptions) ||
|
||||
unresolvedImportsChanged(unresolvedImports, entry.unresolvedImports)) {
|
||||
// Note: entry is now poisoned since it does not really contain typings for a given combination of compiler options\typings options.
|
||||
// instead it acts as a placeholder to prevent issuing multiple requests
|
||||
this.perProjectCache[project.getProjectName()] = {
|
||||
compilerOptions: project.getCompilerOptions(),
|
||||
typingOptions,
|
||||
typings: result,
|
||||
unresolvedImports,
|
||||
poisoned: true
|
||||
};
|
||||
// something has been changed, issue a request to update typings
|
||||
this.installer.enqueueInstallTypingsRequest(project, typingOptions);
|
||||
this.installer.enqueueInstallTypingsRequest(project, typingOptions, unresolvedImports);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
invalidateCachedTypingsForProject(project: Project) {
|
||||
const typingOptions = project.getTypingOptions();
|
||||
if (!typingOptions.enableAutoDiscovery) {
|
||||
return;
|
||||
}
|
||||
this.installer.enqueueInstallTypingsRequest(project, typingOptions);
|
||||
}
|
||||
|
||||
updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typingOptions: TypingOptions, newTypings: string[]) {
|
||||
updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typingOptions: TypingOptions, unresolvedImports: SortedReadonlyArray<string>, newTypings: string[]) {
|
||||
this.perProjectCache[projectName] = {
|
||||
compilerOptions,
|
||||
typingOptions,
|
||||
typings: toTypingsArray(newTypings),
|
||||
typings: toSortedReadonlyArray(newTypings),
|
||||
unresolvedImports,
|
||||
poisoned: false
|
||||
};
|
||||
}
|
||||
|
||||
deleteTypingsForProject(projectName: string) {
|
||||
delete this.perProjectCache[projectName];
|
||||
}
|
||||
|
||||
onProjectClosed(project: Project) {
|
||||
delete this.perProjectCache[project.getProjectName()];
|
||||
this.installer.onProjectClosed(project);
|
||||
|
||||
@ -26,6 +26,7 @@ namespace ts.server.typingsInstaller {
|
||||
export enum PackageNameValidationResult {
|
||||
Ok,
|
||||
ScopedPackagesNotSupported,
|
||||
EmptyName,
|
||||
NameTooLong,
|
||||
NameStartsWithDot,
|
||||
NameStartsWithUnderscore,
|
||||
@ -38,7 +39,9 @@ namespace ts.server.typingsInstaller {
|
||||
* Validates package name using rules defined at https://docs.npmjs.com/files/package.json
|
||||
*/
|
||||
export function validatePackageName(packageName: string): PackageNameValidationResult {
|
||||
Debug.assert(!!packageName, "Package name is not specified");
|
||||
if (!packageName) {
|
||||
return PackageNameValidationResult.EmptyName;
|
||||
}
|
||||
if (packageName.length > MaxPackageNameLength) {
|
||||
return PackageNameValidationResult.NameTooLong;
|
||||
}
|
||||
@ -145,7 +148,8 @@ namespace ts.server.typingsInstaller {
|
||||
req.projectRootPath,
|
||||
this.safeListPath,
|
||||
this.packageNameToTypingLocation,
|
||||
req.typingOptions);
|
||||
req.typingOptions,
|
||||
req.unresolvedImports);
|
||||
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Finished typings discovery: ${JSON.stringify(discoverTypingsResult)}`);
|
||||
@ -238,6 +242,9 @@ namespace ts.server.typingsInstaller {
|
||||
this.missingTypingsSet[typing] = true;
|
||||
if (this.log.isEnabled()) {
|
||||
switch (validationResult) {
|
||||
case PackageNameValidationResult.EmptyName:
|
||||
this.log.writeLine(`Package name '${typing}' cannot be empty`);
|
||||
break;
|
||||
case PackageNameValidationResult.NameTooLong:
|
||||
this.log.writeLine(`Package name '${typing}' should be less than ${MaxPackageNameLength} characters`);
|
||||
break;
|
||||
@ -397,6 +404,7 @@ namespace ts.server.typingsInstaller {
|
||||
typingOptions: request.typingOptions,
|
||||
compilerOptions: request.compilerOptions,
|
||||
typings,
|
||||
unresolvedImports: request.unresolvedImports,
|
||||
kind: "set"
|
||||
};
|
||||
}
|
||||
|
||||
@ -45,12 +45,13 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
export function createInstallTypingsRequest(project: Project, typingOptions: TypingOptions, cachePath?: string): DiscoverTypings {
|
||||
export function createInstallTypingsRequest(project: Project, typingOptions: TypingOptions, unresolvedImports: SortedReadonlyArray<string>, cachePath?: string): DiscoverTypings {
|
||||
return {
|
||||
projectName: project.getProjectName(),
|
||||
fileNames: project.getFileNames(),
|
||||
compilerOptions: project.getCompilerOptions(),
|
||||
typingOptions,
|
||||
unresolvedImports,
|
||||
projectRootPath: getProjectRootPath(project),
|
||||
cachePath,
|
||||
kind: "discover"
|
||||
@ -209,11 +210,15 @@ namespace ts.server {
|
||||
export interface ServerLanguageServiceHost {
|
||||
setCompilationSettings(options: CompilerOptions): void;
|
||||
notifyFileRemoved(info: ScriptInfo): void;
|
||||
startRecordingFilesWithChangedResolutions(): void;
|
||||
finishRecordingFilesWithChangedResolutions(): Path[];
|
||||
}
|
||||
|
||||
export const nullLanguageServiceHost: ServerLanguageServiceHost = {
|
||||
setCompilationSettings: () => undefined,
|
||||
notifyFileRemoved: () => undefined
|
||||
notifyFileRemoved: () => undefined,
|
||||
startRecordingFilesWithChangedResolutions: () => undefined,
|
||||
finishRecordingFilesWithChangedResolutions: () => undefined
|
||||
};
|
||||
|
||||
export interface ProjectOptions {
|
||||
@ -240,6 +245,11 @@ namespace ts.server {
|
||||
return `/dev/null/inferredProject${counter}*`;
|
||||
}
|
||||
|
||||
export function toSortedReadonlyArray(arr: string[]): SortedReadonlyArray<string> {
|
||||
arr.sort();
|
||||
return <any>arr;
|
||||
}
|
||||
|
||||
export class ThrottledOperations {
|
||||
private pendingTimeouts: Map<any> = createMap<any>();
|
||||
constructor(private readonly host: ServerHost) {
|
||||
|
||||
@ -1590,7 +1590,9 @@ namespace ts.Completions {
|
||||
if (m.kind !== SyntaxKind.PropertyAssignment &&
|
||||
m.kind !== SyntaxKind.ShorthandPropertyAssignment &&
|
||||
m.kind !== SyntaxKind.BindingElement &&
|
||||
m.kind !== SyntaxKind.MethodDeclaration) {
|
||||
m.kind !== SyntaxKind.MethodDeclaration &&
|
||||
m.kind !== SyntaxKind.GetAccessor &&
|
||||
m.kind !== SyntaxKind.SetAccessor) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -31,6 +31,17 @@ namespace ts.JsTyping {
|
||||
|
||||
const EmptySafeList: Map<string> = createMap<string>();
|
||||
|
||||
/* @internal */
|
||||
export const nodeCoreModuleList: ReadonlyArray<string> = [
|
||||
"buffer", "querystring", "events", "http", "cluster",
|
||||
"zlib", "os", "https", "punycode", "repl", "readline",
|
||||
"vm", "child_process", "url", "dns", "net",
|
||||
"dgram", "fs", "path", "string_decoder", "tls",
|
||||
"crypto", "stream", "util", "assert", "tty", "domain",
|
||||
"constants", "process", "v8", "timers", "console"];
|
||||
|
||||
const nodeCoreModules = arrayToMap(<string[]>nodeCoreModuleList, x => x);
|
||||
|
||||
/**
|
||||
* @param host is the object providing I/O related operations.
|
||||
* @param fileNames are the file names that belong to the same project
|
||||
@ -46,7 +57,8 @@ namespace ts.JsTyping {
|
||||
projectRootPath: Path,
|
||||
safeListPath: Path,
|
||||
packageNameToTypingLocation: Map<string>,
|
||||
typingOptions: TypingOptions):
|
||||
typingOptions: TypingOptions,
|
||||
unresolvedImports: ReadonlyArray<string>):
|
||||
{ cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } {
|
||||
|
||||
// A typing name to typing file path mapping
|
||||
@ -92,6 +104,15 @@ namespace ts.JsTyping {
|
||||
}
|
||||
getTypingNamesFromSourceFileNames(fileNames);
|
||||
|
||||
// add typings for unresolved imports
|
||||
if (unresolvedImports) {
|
||||
for (const moduleId of unresolvedImports) {
|
||||
const typingName = moduleId in nodeCoreModules ? "node" : moduleId;
|
||||
if (!(typingName in inferredTypings)) {
|
||||
inferredTypings[typingName] = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add the cached typing locations for inferred typings that are already installed
|
||||
for (const name in packageNameToTypingLocation) {
|
||||
if (name in inferredTypings && !inferredTypings[name]) {
|
||||
|
||||
@ -403,6 +403,9 @@ namespace ts.NavigationBar {
|
||||
if (getModifierFlags(node) & ModifierFlags.Default) {
|
||||
return "default";
|
||||
}
|
||||
// We may get a string with newlines or other whitespace in the case of an object dereference
|
||||
// (eg: "app\n.onactivated"), so we should remove the whitespace for readabiltiy in the
|
||||
// navigation bar.
|
||||
return getFunctionOrClassName(<ArrowFunction | FunctionExpression | ClassExpression>node);
|
||||
case SyntaxKind.Constructor:
|
||||
return "constructor";
|
||||
@ -602,7 +605,7 @@ namespace ts.NavigationBar {
|
||||
// See if it is of the form "<expr> = function(){...}". If so, use the text from the left-hand side.
|
||||
else if (node.parent.kind === SyntaxKind.BinaryExpression &&
|
||||
(node.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
|
||||
return nodeText((node.parent as BinaryExpression).left);
|
||||
return nodeText((node.parent as BinaryExpression).left).replace(whiteSpaceRegex, "");
|
||||
}
|
||||
// See if it is a property assignment, and if so use the property name
|
||||
else if (node.parent.kind === SyntaxKind.PropertyAssignment && (node.parent as PropertyAssignment).name) {
|
||||
@ -620,4 +623,19 @@ namespace ts.NavigationBar {
|
||||
function isFunctionOrClassExpression(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction || node.kind === SyntaxKind.ClassExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches all whitespace characters in a string. Eg:
|
||||
*
|
||||
* "app.
|
||||
*
|
||||
* onactivated"
|
||||
*
|
||||
* matches because of the newline, whereas
|
||||
*
|
||||
* "app.onactivated"
|
||||
*
|
||||
* does not match.
|
||||
*/
|
||||
const whiteSpaceRegex = /\s+/g;
|
||||
}
|
||||
|
||||
@ -467,7 +467,7 @@ namespace ts {
|
||||
public languageVariant: LanguageVariant;
|
||||
public identifiers: Map<string>;
|
||||
public nameTable: Map<number>;
|
||||
public resolvedModules: Map<ResolvedModule>;
|
||||
public resolvedModules: Map<ResolvedModuleFull>;
|
||||
public resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
|
||||
public imports: LiteralExpression[];
|
||||
public moduleAugmentations: LiteralExpression[];
|
||||
|
||||
@ -316,7 +316,7 @@ namespace ts {
|
||||
private loggingEnabled = false;
|
||||
private tracingEnabled = false;
|
||||
|
||||
public resolveModuleNames: (moduleName: string[], containingFile: string) => ResolvedModule[];
|
||||
public resolveModuleNames: (moduleName: string[], containingFile: string) => ResolvedModuleFull[];
|
||||
public resolveTypeReferenceDirectives: (typeDirectiveNames: string[], containingFile: string) => ResolvedTypeReferenceDirective[];
|
||||
public directoryExists: (directoryName: string) => boolean;
|
||||
|
||||
@ -328,7 +328,7 @@ namespace ts {
|
||||
const resolutionsInFile = <MapLike<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
|
||||
return map(moduleNames, name => {
|
||||
const result = getProperty(resolutionsInFile, name);
|
||||
return result ? { resolvedFileName: result } : undefined;
|
||||
return result ? { resolvedFileName: result, extension: extensionFromPath(result), isExternalLibraryImport: false } : undefined;
|
||||
});
|
||||
};
|
||||
}
|
||||
@ -1168,7 +1168,8 @@ namespace ts {
|
||||
toPath(info.projectRootPath, info.projectRootPath, getCanonicalFileName),
|
||||
toPath(info.safeListPath, info.safeListPath, getCanonicalFileName),
|
||||
info.packageNameToTypingLocation,
|
||||
info.typingOptions);
|
||||
info.typingOptions,
|
||||
info.unresolvedImports);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
"../compiler/transformers/es2017.ts",
|
||||
"../compiler/transformers/es2016.ts",
|
||||
"../compiler/transformers/es2015.ts",
|
||||
"../compiler/transformers/es5.ts",
|
||||
"../compiler/transformers/generators.ts",
|
||||
"../compiler/transformers/generators.ts",
|
||||
"../compiler/transformers/destructuring.ts",
|
||||
|
||||
@ -11,5 +11,4 @@ var C = (function () {
|
||||
}
|
||||
return C;
|
||||
}());
|
||||
exports.C = C;
|
||||
module.exports = B;
|
||||
|
||||
@ -11,5 +11,4 @@ var C = (function () {
|
||||
}
|
||||
return C;
|
||||
}());
|
||||
exports.C = C;
|
||||
module.exports = B;
|
||||
|
||||
@ -18,6 +18,12 @@
|
||||
"end": 16,
|
||||
"text": "typedef"
|
||||
},
|
||||
"fullName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 17,
|
||||
"end": 23,
|
||||
"text": "People"
|
||||
},
|
||||
"name": {
|
||||
"kind": "Identifier",
|
||||
"pos": 17,
|
||||
|
||||
@ -14,11 +14,11 @@ var b = A.Day.Monday;
|
||||
//// [ModuleWithExportedAndNonExportedEnums.js]
|
||||
var A;
|
||||
(function (A) {
|
||||
var Color;
|
||||
(function (Color) {
|
||||
Color[Color["Red"] = 0] = "Red";
|
||||
Color[Color["Blue"] = 1] = "Blue";
|
||||
})(A.Color || (A.Color = {}));
|
||||
var Color = A.Color;
|
||||
})(Color = A.Color || (A.Color = {}));
|
||||
var Day;
|
||||
(function (Day) {
|
||||
Day[Day["Monday"] = 0] = "Monday";
|
||||
|
||||
21
tests/baselines/reference/ambientRequireFunction.js
Normal file
21
tests/baselines/reference/ambientRequireFunction.js
Normal file
@ -0,0 +1,21 @@
|
||||
//// [tests/cases/compiler/ambientRequireFunction.ts] ////
|
||||
|
||||
//// [node.d.ts]
|
||||
|
||||
|
||||
declare function require(moduleName: string): any;
|
||||
|
||||
declare module "fs" {
|
||||
export function readFileSync(s: string): string;
|
||||
}
|
||||
|
||||
//// [app.js]
|
||||
/// <reference path="node.d.ts"/>
|
||||
|
||||
const fs = require("fs");
|
||||
const text = fs.readFileSync("/a/b/c");
|
||||
|
||||
//// [app.js]
|
||||
/// <reference path="node.d.ts"/>
|
||||
var fs = require("fs");
|
||||
var text = fs.readFileSync("/a/b/c");
|
||||
27
tests/baselines/reference/ambientRequireFunction.symbols
Normal file
27
tests/baselines/reference/ambientRequireFunction.symbols
Normal file
@ -0,0 +1,27 @@
|
||||
=== tests/cases/compiler/app.js ===
|
||||
/// <reference path="node.d.ts"/>
|
||||
|
||||
const fs = require("fs");
|
||||
>fs : Symbol(fs, Decl(app.js, 2, 5))
|
||||
>require : Symbol(require, Decl(node.d.ts, 0, 0))
|
||||
>"fs" : Symbol("fs", Decl(node.d.ts, 2, 50))
|
||||
|
||||
const text = fs.readFileSync("/a/b/c");
|
||||
>text : Symbol(text, Decl(app.js, 3, 5))
|
||||
>fs.readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
|
||||
>fs : Symbol(fs, Decl(app.js, 2, 5))
|
||||
>readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
|
||||
|
||||
=== tests/cases/compiler/node.d.ts ===
|
||||
|
||||
|
||||
declare function require(moduleName: string): any;
|
||||
>require : Symbol(require, Decl(node.d.ts, 0, 0))
|
||||
>moduleName : Symbol(moduleName, Decl(node.d.ts, 2, 25))
|
||||
|
||||
declare module "fs" {
|
||||
export function readFileSync(s: string): string;
|
||||
>readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
|
||||
>s : Symbol(s, Decl(node.d.ts, 5, 33))
|
||||
}
|
||||
|
||||
30
tests/baselines/reference/ambientRequireFunction.types
Normal file
30
tests/baselines/reference/ambientRequireFunction.types
Normal file
@ -0,0 +1,30 @@
|
||||
=== tests/cases/compiler/app.js ===
|
||||
/// <reference path="node.d.ts"/>
|
||||
|
||||
const fs = require("fs");
|
||||
>fs : typeof "fs"
|
||||
>require("fs") : typeof "fs"
|
||||
>require : (moduleName: string) => any
|
||||
>"fs" : "fs"
|
||||
|
||||
const text = fs.readFileSync("/a/b/c");
|
||||
>text : string
|
||||
>fs.readFileSync("/a/b/c") : string
|
||||
>fs.readFileSync : (s: string) => string
|
||||
>fs : typeof "fs"
|
||||
>readFileSync : (s: string) => string
|
||||
>"/a/b/c" : "/a/b/c"
|
||||
|
||||
=== tests/cases/compiler/node.d.ts ===
|
||||
|
||||
|
||||
declare function require(moduleName: string): any;
|
||||
>require : (moduleName: string) => any
|
||||
>moduleName : string
|
||||
|
||||
declare module "fs" {
|
||||
export function readFileSync(s: string): string;
|
||||
>readFileSync : (s: string) => string
|
||||
>s : string
|
||||
}
|
||||
|
||||
@ -15,12 +15,12 @@ if(foo.E1.A === 0){
|
||||
//// [foo_0.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
"use strict";
|
||||
var E1;
|
||||
(function (E1) {
|
||||
E1[E1["A"] = 0] = "A";
|
||||
E1[E1["B"] = 1] = "B";
|
||||
E1[E1["C"] = 2] = "C";
|
||||
})(exports.E1 || (exports.E1 = {}));
|
||||
var E1 = exports.E1;
|
||||
})(E1 = exports.E1 || (exports.E1 = {}));
|
||||
});
|
||||
//// [foo_1.js]
|
||||
define(["require", "exports", "./foo_0"], function (require, exports, foo) {
|
||||
|
||||
@ -40,14 +40,14 @@ define(["require", "exports"], function (require, exports) {
|
||||
}
|
||||
return C1;
|
||||
}());
|
||||
exports.C1 = C1;
|
||||
C1.s1 = true;
|
||||
exports.C1 = C1;
|
||||
var E1;
|
||||
(function (E1) {
|
||||
E1[E1["A"] = 0] = "A";
|
||||
E1[E1["B"] = 1] = "B";
|
||||
E1[E1["C"] = 2] = "C";
|
||||
})(exports.E1 || (exports.E1 = {}));
|
||||
var E1 = exports.E1;
|
||||
})(E1 = exports.E1 || (exports.E1 = {}));
|
||||
});
|
||||
//// [foo_1.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts(3,21): error TS1055: Type 'PromiseAlias' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
|
||||
|
||||
==== tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts (1 errors) ====
|
||||
type PromiseAlias<T> = Promise<T>;
|
||||
|
||||
async function f(): PromiseAlias<void> {
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS1055: Type 'PromiseAlias' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
}
|
||||
@ -77,6 +77,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
}
|
||||
};
|
||||
var _this = this;
|
||||
var missing_1 = require("missing");
|
||||
function f0() {
|
||||
return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
|
||||
return [2 /*return*/];
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(6,23): error TS1055: Type '{}' is not a valid async function return type.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(7,23): error TS1055: Type 'any' is not a valid async function return type.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(8,23): error TS1055: Type 'number' is not a valid async function return type.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(9,23): error TS1055: Type 'PromiseLike' is not a valid async function return type.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(6,23): error TS1055: Type '{}' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(7,23): error TS1055: Type 'any' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(8,23): error TS1055: Type 'number' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(9,23): error TS1055: Type 'PromiseLike' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
Type 'Thenable' is not assignable to type 'PromiseLike<any>'.
|
||||
Types of property 'then' are incompatible.
|
||||
Type '() => void' is not assignable to type '{ (onfulfilled?: (value: any) => any, onrejected?: (reason: any) => any): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => any, onrejected: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>; <TResult1, TResult2>(onfulfilled: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>; }'.
|
||||
@ -20,21 +20,21 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
|
||||
async function fn1() { } // valid: Promise<void>
|
||||
async function fn2(): { } { } // error
|
||||
~~~
|
||||
!!! error TS1055: Type '{}' is not a valid async function return type.
|
||||
!!! error TS1055: Type '{}' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
async function fn3(): any { } // error
|
||||
~~~
|
||||
!!! error TS1055: Type 'any' is not a valid async function return type.
|
||||
!!! error TS1055: Type 'any' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
async function fn4(): number { } // error
|
||||
~~~~~~
|
||||
!!! error TS1055: Type 'number' is not a valid async function return type.
|
||||
!!! error TS1055: Type 'number' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
async function fn5(): PromiseLike<void> { } // error
|
||||
~~~~~~~~~~~~~~~~~
|
||||
!!! error TS1055: Type 'PromiseLike' is not a valid async function return type.
|
||||
!!! error TS1055: Type 'PromiseLike' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
async function fn6(): Thenable { } // error
|
||||
~~~~~~~~
|
||||
!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type.
|
||||
!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
~~~~~~~~
|
||||
!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type.
|
||||
!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
|
||||
!!! error TS1055: Type 'Thenable' is not assignable to type 'PromiseLike<any>'.
|
||||
!!! error TS1055: Types of property 'then' are incompatible.
|
||||
!!! error TS1055: Type '() => void' is not assignable to type '{ (onfulfilled?: (value: any) => any, onrejected?: (reason: any) => any): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => any, onrejected: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>; <TResult1, TResult2>(onfulfilled: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>; }'.
|
||||
|
||||
28
tests/baselines/reference/asyncIIFE.js
Normal file
28
tests/baselines/reference/asyncIIFE.js
Normal file
@ -0,0 +1,28 @@
|
||||
//// [asyncIIFE.ts]
|
||||
|
||||
function f1() {
|
||||
(async () => {
|
||||
await 10
|
||||
throw new Error();
|
||||
})();
|
||||
|
||||
var x = 1;
|
||||
}
|
||||
|
||||
|
||||
//// [asyncIIFE.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function f1() {
|
||||
(() => __awaiter(this, void 0, void 0, function* () {
|
||||
yield 10;
|
||||
throw new Error();
|
||||
}))();
|
||||
var x = 1;
|
||||
}
|
||||
16
tests/baselines/reference/asyncIIFE.symbols
Normal file
16
tests/baselines/reference/asyncIIFE.symbols
Normal file
@ -0,0 +1,16 @@
|
||||
=== tests/cases/compiler/asyncIIFE.ts ===
|
||||
|
||||
function f1() {
|
||||
>f1 : Symbol(f1, Decl(asyncIIFE.ts, 0, 0))
|
||||
|
||||
(async () => {
|
||||
await 10
|
||||
throw new Error();
|
||||
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
})();
|
||||
|
||||
var x = 1;
|
||||
>x : Symbol(x, Decl(asyncIIFE.ts, 7, 7))
|
||||
}
|
||||
|
||||
25
tests/baselines/reference/asyncIIFE.types
Normal file
25
tests/baselines/reference/asyncIIFE.types
Normal file
@ -0,0 +1,25 @@
|
||||
=== tests/cases/compiler/asyncIIFE.ts ===
|
||||
|
||||
function f1() {
|
||||
>f1 : () => void
|
||||
|
||||
(async () => {
|
||||
>(async () => { await 10 throw new Error(); })() : Promise<never>
|
||||
>(async () => { await 10 throw new Error(); }) : () => Promise<never>
|
||||
>async () => { await 10 throw new Error(); } : () => Promise<never>
|
||||
|
||||
await 10
|
||||
>await 10 : 10
|
||||
>10 : 10
|
||||
|
||||
throw new Error();
|
||||
>new Error() : Error
|
||||
>Error : ErrorConstructor
|
||||
|
||||
})();
|
||||
|
||||
var x = 1;
|
||||
>x : number
|
||||
>1 : 1
|
||||
}
|
||||
|
||||
@ -151,13 +151,13 @@ System.register([], function (exports_1, context_1) {
|
||||
function exportedFoo() {
|
||||
return v0 + v00 + v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8;
|
||||
}
|
||||
exports_1("exportedFoo", exportedFoo);
|
||||
//======const
|
||||
function exportedFoo2() {
|
||||
return v0_c + v00_c + v1_c + v2_c + v3_c + v4_c + v5_c + v6_c + v7_c + v8_c;
|
||||
}
|
||||
var v0, v00, v1, v2, v3, v4, v5, v6, v7, v8, v0_c, v00_c, v1_c, v2_c, v3_c, v4_c, v5_c, v6_c, v7_c, v8_c;
|
||||
exports_1("exportedFoo", exportedFoo);
|
||||
exports_1("exportedFoo2", exportedFoo2);
|
||||
var v0, v00, v1, v2, v3, v4, v5, v6, v7, v8, v0_c, v00_c, v1_c, v2_c, v3_c, v4_c, v5_c, v6_c, v7_c, v8_c;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
tests/cases/compiler/catchClauseWithBindingPattern1.ts(3,8): error TS1195: Catch clause variable name must be an identifier.
|
||||
|
||||
|
||||
==== tests/cases/compiler/catchClauseWithBindingPattern1.ts (1 errors) ====
|
||||
try {
|
||||
}
|
||||
catch ({a}) {
|
||||
~
|
||||
!!! error TS1195: Catch clause variable name must be an identifier.
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
//// [catchClauseWithBindingPattern1.ts]
|
||||
try {
|
||||
}
|
||||
catch ({a}) {
|
||||
}
|
||||
|
||||
//// [catchClauseWithBindingPattern1.js]
|
||||
try {
|
||||
}
|
||||
catch (a = (void 0).a) {
|
||||
}
|
||||
@ -63,16 +63,16 @@ module m4 {
|
||||
//// [collisionExportsRequireAndEnum_externalmodule.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
"use strict";
|
||||
var require;
|
||||
(function (require) {
|
||||
require[require["_thisVal1"] = 0] = "_thisVal1";
|
||||
require[require["_thisVal2"] = 1] = "_thisVal2";
|
||||
})(exports.require || (exports.require = {}));
|
||||
var require = exports.require;
|
||||
})(require = exports.require || (exports.require = {}));
|
||||
var exports;
|
||||
(function (exports) {
|
||||
exports[exports["_thisVal1"] = 0] = "_thisVal1";
|
||||
exports[exports["_thisVal2"] = 1] = "_thisVal2";
|
||||
})(exports.exports || (exports.exports = {}));
|
||||
var exports = exports.exports;
|
||||
})(exports = exports.exports || (exports.exports = {}));
|
||||
var m1;
|
||||
(function (m1) {
|
||||
var require;
|
||||
@ -88,16 +88,16 @@ define(["require", "exports"], function (require, exports) {
|
||||
})(m1 || (m1 = {}));
|
||||
var m2;
|
||||
(function (m2) {
|
||||
var require;
|
||||
(function (require) {
|
||||
require[require["_thisVal1"] = 0] = "_thisVal1";
|
||||
require[require["_thisVal2"] = 1] = "_thisVal2";
|
||||
})(m2.require || (m2.require = {}));
|
||||
var require = m2.require;
|
||||
})(require = m2.require || (m2.require = {}));
|
||||
var exports;
|
||||
(function (exports) {
|
||||
exports[exports["_thisVal1"] = 0] = "_thisVal1";
|
||||
exports[exports["_thisVal2"] = 1] = "_thisVal2";
|
||||
})(m2.exports || (m2.exports = {}));
|
||||
var exports = m2.exports;
|
||||
})(exports = m2.exports || (m2.exports = {}));
|
||||
})(m2 || (m2 = {}));
|
||||
});
|
||||
//// [collisionExportsRequireAndEnum_globalFile.js]
|
||||
@ -126,14 +126,14 @@ var m3;
|
||||
})(m3 || (m3 = {}));
|
||||
var m4;
|
||||
(function (m4) {
|
||||
var require;
|
||||
(function (require) {
|
||||
require[require["_thisVal1"] = 0] = "_thisVal1";
|
||||
require[require["_thisVal2"] = 1] = "_thisVal2";
|
||||
})(m4.require || (m4.require = {}));
|
||||
var require = m4.require;
|
||||
})(require = m4.require || (m4.require = {}));
|
||||
var exports;
|
||||
(function (exports) {
|
||||
exports[exports["_thisVal1"] = 0] = "_thisVal1";
|
||||
exports[exports["_thisVal2"] = 1] = "_thisVal2";
|
||||
})(m4.exports || (m4.exports = {}));
|
||||
var exports = m4.exports;
|
||||
})(exports = m4.exports || (m4.exports = {}));
|
||||
})(m4 || (m4 = {}));
|
||||
|
||||
@ -11,9 +11,9 @@ export enum Color {
|
||||
/**
|
||||
* comment
|
||||
*/
|
||||
var Color;
|
||||
(function (Color) {
|
||||
Color[Color["r"] = 0] = "r";
|
||||
Color[Color["g"] = 1] = "g";
|
||||
Color[Color["b"] = 2] = "b";
|
||||
})(exports.Color || (exports.Color = {}));
|
||||
var Color = exports.Color;
|
||||
})(Color = exports.Color || (exports.Color = {}));
|
||||
|
||||
@ -21,8 +21,8 @@ var C1 = (function () {
|
||||
}
|
||||
return C1;
|
||||
}());
|
||||
exports.C1 = C1;
|
||||
C1.s1 = true;
|
||||
exports.C1 = C1;
|
||||
//// [foo_1.js]
|
||||
"use strict";
|
||||
var foo = require("./foo_0");
|
||||
|
||||
@ -39,14 +39,14 @@ var C1 = (function () {
|
||||
}
|
||||
return C1;
|
||||
}());
|
||||
exports.C1 = C1;
|
||||
C1.s1 = true;
|
||||
exports.C1 = C1;
|
||||
var E1;
|
||||
(function (E1) {
|
||||
E1[E1["A"] = 0] = "A";
|
||||
E1[E1["B"] = 1] = "B";
|
||||
E1[E1["C"] = 2] = "C";
|
||||
})(exports.E1 || (exports.E1 = {}));
|
||||
var E1 = exports.E1;
|
||||
})(E1 = exports.E1 || (exports.E1 = {}));
|
||||
//// [foo_1.js]
|
||||
"use strict";
|
||||
var i;
|
||||
|
||||
123
tests/baselines/reference/constructorWithCapturedSuper.js
Normal file
123
tests/baselines/reference/constructorWithCapturedSuper.js
Normal file
@ -0,0 +1,123 @@
|
||||
//// [constructorWithCapturedSuper.ts]
|
||||
let oneA: A;
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
return oneA;
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
constructor(x: number) {
|
||||
super();
|
||||
if (x === 1) {
|
||||
return;
|
||||
}
|
||||
while (x < 2) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
return
|
||||
}
|
||||
catch (e) {
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class C extends A {
|
||||
constructor(x: number) {
|
||||
super();
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
() => i + x;
|
||||
if (x === 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class D extends A {
|
||||
constructor(x: number) {
|
||||
super();
|
||||
() => {
|
||||
return;
|
||||
}
|
||||
function foo() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [constructorWithCapturedSuper.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
var oneA;
|
||||
var A = (function () {
|
||||
function A() {
|
||||
return oneA;
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
var B = (function (_super) {
|
||||
__extends(B, _super);
|
||||
function B(x) {
|
||||
var _this = _super.call(this) || this;
|
||||
if (x === 1) {
|
||||
return _this;
|
||||
}
|
||||
while (x < 2) {
|
||||
return _this;
|
||||
}
|
||||
try {
|
||||
return _this;
|
||||
}
|
||||
catch (e) {
|
||||
return _this;
|
||||
}
|
||||
finally {
|
||||
return _this;
|
||||
}
|
||||
return _this;
|
||||
}
|
||||
return B;
|
||||
}(A));
|
||||
var C = (function (_super) {
|
||||
__extends(C, _super);
|
||||
function C(x) {
|
||||
var _this = _super.call(this) || this;
|
||||
var _loop_1 = function (i) {
|
||||
(function () { return i + x; });
|
||||
if (x === 1) {
|
||||
return { value: _this };
|
||||
}
|
||||
};
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
var state_1 = _loop_1(i);
|
||||
if (typeof state_1 === "object")
|
||||
return state_1.value;
|
||||
}
|
||||
return _this;
|
||||
}
|
||||
return C;
|
||||
}(A));
|
||||
var D = (function (_super) {
|
||||
__extends(D, _super);
|
||||
function D(x) {
|
||||
var _this = _super.call(this) || this;
|
||||
(function () {
|
||||
return;
|
||||
});
|
||||
function foo() {
|
||||
return;
|
||||
}
|
||||
return _this;
|
||||
}
|
||||
return D;
|
||||
}(A));
|
||||
@ -0,0 +1,96 @@
|
||||
=== tests/cases/compiler/constructorWithCapturedSuper.ts ===
|
||||
let oneA: A;
|
||||
>oneA : Symbol(oneA, Decl(constructorWithCapturedSuper.ts, 0, 3))
|
||||
>A : Symbol(A, Decl(constructorWithCapturedSuper.ts, 0, 12))
|
||||
|
||||
class A {
|
||||
>A : Symbol(A, Decl(constructorWithCapturedSuper.ts, 0, 12))
|
||||
|
||||
constructor() {
|
||||
return oneA;
|
||||
>oneA : Symbol(oneA, Decl(constructorWithCapturedSuper.ts, 0, 3))
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
>B : Symbol(B, Decl(constructorWithCapturedSuper.ts, 6, 1))
|
||||
>A : Symbol(A, Decl(constructorWithCapturedSuper.ts, 0, 12))
|
||||
|
||||
constructor(x: number) {
|
||||
>x : Symbol(x, Decl(constructorWithCapturedSuper.ts, 9, 16))
|
||||
|
||||
super();
|
||||
>super : Symbol(A, Decl(constructorWithCapturedSuper.ts, 0, 12))
|
||||
|
||||
if (x === 1) {
|
||||
>x : Symbol(x, Decl(constructorWithCapturedSuper.ts, 9, 16))
|
||||
|
||||
return;
|
||||
}
|
||||
while (x < 2) {
|
||||
>x : Symbol(x, Decl(constructorWithCapturedSuper.ts, 9, 16))
|
||||
|
||||
return;
|
||||
}
|
||||
try {
|
||||
return
|
||||
}
|
||||
catch (e) {
|
||||
>e : Symbol(e, Decl(constructorWithCapturedSuper.ts, 20, 15))
|
||||
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class C extends A {
|
||||
>C : Symbol(C, Decl(constructorWithCapturedSuper.ts, 27, 1))
|
||||
>A : Symbol(A, Decl(constructorWithCapturedSuper.ts, 0, 12))
|
||||
|
||||
constructor(x: number) {
|
||||
>x : Symbol(x, Decl(constructorWithCapturedSuper.ts, 30, 16))
|
||||
|
||||
super();
|
||||
>super : Symbol(A, Decl(constructorWithCapturedSuper.ts, 0, 12))
|
||||
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
>i : Symbol(i, Decl(constructorWithCapturedSuper.ts, 32, 16))
|
||||
>i : Symbol(i, Decl(constructorWithCapturedSuper.ts, 32, 16))
|
||||
>i : Symbol(i, Decl(constructorWithCapturedSuper.ts, 32, 16))
|
||||
|
||||
() => i + x;
|
||||
>i : Symbol(i, Decl(constructorWithCapturedSuper.ts, 32, 16))
|
||||
>x : Symbol(x, Decl(constructorWithCapturedSuper.ts, 30, 16))
|
||||
|
||||
if (x === 1) {
|
||||
>x : Symbol(x, Decl(constructorWithCapturedSuper.ts, 30, 16))
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class D extends A {
|
||||
>D : Symbol(D, Decl(constructorWithCapturedSuper.ts, 39, 1))
|
||||
>A : Symbol(A, Decl(constructorWithCapturedSuper.ts, 0, 12))
|
||||
|
||||
constructor(x: number) {
|
||||
>x : Symbol(x, Decl(constructorWithCapturedSuper.ts, 42, 16))
|
||||
|
||||
super();
|
||||
>super : Symbol(A, Decl(constructorWithCapturedSuper.ts, 0, 12))
|
||||
|
||||
() => {
|
||||
return;
|
||||
}
|
||||
function foo() {
|
||||
>foo : Symbol(foo, Decl(constructorWithCapturedSuper.ts, 46, 9))
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
113
tests/baselines/reference/constructorWithCapturedSuper.types
Normal file
113
tests/baselines/reference/constructorWithCapturedSuper.types
Normal file
@ -0,0 +1,113 @@
|
||||
=== tests/cases/compiler/constructorWithCapturedSuper.ts ===
|
||||
let oneA: A;
|
||||
>oneA : A
|
||||
>A : A
|
||||
|
||||
class A {
|
||||
>A : A
|
||||
|
||||
constructor() {
|
||||
return oneA;
|
||||
>oneA : A
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
>B : B
|
||||
>A : A
|
||||
|
||||
constructor(x: number) {
|
||||
>x : number
|
||||
|
||||
super();
|
||||
>super() : void
|
||||
>super : typeof A
|
||||
|
||||
if (x === 1) {
|
||||
>x === 1 : boolean
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
return;
|
||||
}
|
||||
while (x < 2) {
|
||||
>x < 2 : boolean
|
||||
>x : number
|
||||
>2 : 2
|
||||
|
||||
return;
|
||||
}
|
||||
try {
|
||||
return
|
||||
}
|
||||
catch (e) {
|
||||
>e : any
|
||||
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class C extends A {
|
||||
>C : C
|
||||
>A : A
|
||||
|
||||
constructor(x: number) {
|
||||
>x : number
|
||||
|
||||
super();
|
||||
>super() : void
|
||||
>super : typeof A
|
||||
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
>i : number
|
||||
>0 : 0
|
||||
>i < 10 : boolean
|
||||
>i : number
|
||||
>10 : 10
|
||||
>++i : number
|
||||
>i : number
|
||||
|
||||
() => i + x;
|
||||
>() => i + x : () => number
|
||||
>i + x : number
|
||||
>i : number
|
||||
>x : number
|
||||
|
||||
if (x === 1) {
|
||||
>x === 1 : boolean
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class D extends A {
|
||||
>D : D
|
||||
>A : A
|
||||
|
||||
constructor(x: number) {
|
||||
>x : number
|
||||
|
||||
super();
|
||||
>super() : void
|
||||
>super : typeof A
|
||||
|
||||
() => {
|
||||
>() => { return; } : () => void
|
||||
|
||||
return;
|
||||
}
|
||||
function foo() {
|
||||
>foo : () => void
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
//// [contextualTypingOfTooShortOverloads.ts]
|
||||
// small repro from #11875
|
||||
var use: Overload;
|
||||
use((req, res) => {});
|
||||
|
||||
interface Overload {
|
||||
(handler1: (req1: string) => void): void;
|
||||
(handler2: (req2: number, res2: number) => void): void;
|
||||
}
|
||||
// larger repro from #11875
|
||||
let app: MyApp;
|
||||
app.use((err: any, req, res, next) => { return; });
|
||||
|
||||
|
||||
interface MyApp {
|
||||
use: IRouterHandler<this> & IRouterMatcher<this>;
|
||||
}
|
||||
|
||||
interface IRouterHandler<T> {
|
||||
(...handlers: RequestHandler[]): T;
|
||||
(...handlers: RequestHandlerParams[]): T;
|
||||
}
|
||||
|
||||
interface IRouterMatcher<T> {
|
||||
(path: PathParams, ...handlers: RequestHandler[]): T;
|
||||
(path: PathParams, ...handlers: RequestHandlerParams[]): T;
|
||||
}
|
||||
|
||||
type PathParams = string | RegExp | (string | RegExp)[];
|
||||
type RequestHandlerParams = RequestHandler | ErrorRequestHandler | (RequestHandler | ErrorRequestHandler)[];
|
||||
|
||||
interface RequestHandler {
|
||||
(req: Request, res: Response, next: NextFunction): any;
|
||||
}
|
||||
|
||||
interface ErrorRequestHandler {
|
||||
(err: any, req: Request, res: Response, next: NextFunction): any;
|
||||
}
|
||||
|
||||
interface Request {
|
||||
method: string;
|
||||
}
|
||||
|
||||
interface Response {
|
||||
statusCode: number;
|
||||
}
|
||||
|
||||
interface NextFunction {
|
||||
(err?: any): void;
|
||||
}
|
||||
|
||||
|
||||
//// [contextualTypingOfTooShortOverloads.js]
|
||||
// small repro from #11875
|
||||
var use;
|
||||
use(function (req, res) { });
|
||||
// larger repro from #11875
|
||||
var app;
|
||||
app.use(function (err, req, res, next) { return; });
|
||||
@ -0,0 +1,139 @@
|
||||
=== tests/cases/compiler/contextualTypingOfTooShortOverloads.ts ===
|
||||
// small repro from #11875
|
||||
var use: Overload;
|
||||
>use : Symbol(use, Decl(contextualTypingOfTooShortOverloads.ts, 1, 3))
|
||||
>Overload : Symbol(Overload, Decl(contextualTypingOfTooShortOverloads.ts, 2, 22))
|
||||
|
||||
use((req, res) => {});
|
||||
>use : Symbol(use, Decl(contextualTypingOfTooShortOverloads.ts, 1, 3))
|
||||
>req : Symbol(req, Decl(contextualTypingOfTooShortOverloads.ts, 2, 5))
|
||||
>res : Symbol(res, Decl(contextualTypingOfTooShortOverloads.ts, 2, 9))
|
||||
|
||||
interface Overload {
|
||||
>Overload : Symbol(Overload, Decl(contextualTypingOfTooShortOverloads.ts, 2, 22))
|
||||
|
||||
(handler1: (req1: string) => void): void;
|
||||
>handler1 : Symbol(handler1, Decl(contextualTypingOfTooShortOverloads.ts, 5, 5))
|
||||
>req1 : Symbol(req1, Decl(contextualTypingOfTooShortOverloads.ts, 5, 16))
|
||||
|
||||
(handler2: (req2: number, res2: number) => void): void;
|
||||
>handler2 : Symbol(handler2, Decl(contextualTypingOfTooShortOverloads.ts, 6, 5))
|
||||
>req2 : Symbol(req2, Decl(contextualTypingOfTooShortOverloads.ts, 6, 16))
|
||||
>res2 : Symbol(res2, Decl(contextualTypingOfTooShortOverloads.ts, 6, 29))
|
||||
}
|
||||
// larger repro from #11875
|
||||
let app: MyApp;
|
||||
>app : Symbol(app, Decl(contextualTypingOfTooShortOverloads.ts, 9, 3))
|
||||
>MyApp : Symbol(MyApp, Decl(contextualTypingOfTooShortOverloads.ts, 10, 51))
|
||||
|
||||
app.use((err: any, req, res, next) => { return; });
|
||||
>app.use : Symbol(MyApp.use, Decl(contextualTypingOfTooShortOverloads.ts, 13, 17))
|
||||
>app : Symbol(app, Decl(contextualTypingOfTooShortOverloads.ts, 9, 3))
|
||||
>use : Symbol(MyApp.use, Decl(contextualTypingOfTooShortOverloads.ts, 13, 17))
|
||||
>err : Symbol(err, Decl(contextualTypingOfTooShortOverloads.ts, 10, 9))
|
||||
>req : Symbol(req, Decl(contextualTypingOfTooShortOverloads.ts, 10, 18))
|
||||
>res : Symbol(res, Decl(contextualTypingOfTooShortOverloads.ts, 10, 23))
|
||||
>next : Symbol(next, Decl(contextualTypingOfTooShortOverloads.ts, 10, 28))
|
||||
|
||||
|
||||
interface MyApp {
|
||||
>MyApp : Symbol(MyApp, Decl(contextualTypingOfTooShortOverloads.ts, 10, 51))
|
||||
|
||||
use: IRouterHandler<this> & IRouterMatcher<this>;
|
||||
>use : Symbol(MyApp.use, Decl(contextualTypingOfTooShortOverloads.ts, 13, 17))
|
||||
>IRouterHandler : Symbol(IRouterHandler, Decl(contextualTypingOfTooShortOverloads.ts, 15, 1))
|
||||
>IRouterMatcher : Symbol(IRouterMatcher, Decl(contextualTypingOfTooShortOverloads.ts, 20, 1))
|
||||
}
|
||||
|
||||
interface IRouterHandler<T> {
|
||||
>IRouterHandler : Symbol(IRouterHandler, Decl(contextualTypingOfTooShortOverloads.ts, 15, 1))
|
||||
>T : Symbol(T, Decl(contextualTypingOfTooShortOverloads.ts, 17, 25))
|
||||
|
||||
(...handlers: RequestHandler[]): T;
|
||||
>handlers : Symbol(handlers, Decl(contextualTypingOfTooShortOverloads.ts, 18, 5))
|
||||
>RequestHandler : Symbol(RequestHandler, Decl(contextualTypingOfTooShortOverloads.ts, 28, 108))
|
||||
>T : Symbol(T, Decl(contextualTypingOfTooShortOverloads.ts, 17, 25))
|
||||
|
||||
(...handlers: RequestHandlerParams[]): T;
|
||||
>handlers : Symbol(handlers, Decl(contextualTypingOfTooShortOverloads.ts, 19, 5))
|
||||
>RequestHandlerParams : Symbol(RequestHandlerParams, Decl(contextualTypingOfTooShortOverloads.ts, 27, 56))
|
||||
>T : Symbol(T, Decl(contextualTypingOfTooShortOverloads.ts, 17, 25))
|
||||
}
|
||||
|
||||
interface IRouterMatcher<T> {
|
||||
>IRouterMatcher : Symbol(IRouterMatcher, Decl(contextualTypingOfTooShortOverloads.ts, 20, 1))
|
||||
>T : Symbol(T, Decl(contextualTypingOfTooShortOverloads.ts, 22, 25))
|
||||
|
||||
(path: PathParams, ...handlers: RequestHandler[]): T;
|
||||
>path : Symbol(path, Decl(contextualTypingOfTooShortOverloads.ts, 23, 5))
|
||||
>PathParams : Symbol(PathParams, Decl(contextualTypingOfTooShortOverloads.ts, 25, 1))
|
||||
>handlers : Symbol(handlers, Decl(contextualTypingOfTooShortOverloads.ts, 23, 22))
|
||||
>RequestHandler : Symbol(RequestHandler, Decl(contextualTypingOfTooShortOverloads.ts, 28, 108))
|
||||
>T : Symbol(T, Decl(contextualTypingOfTooShortOverloads.ts, 22, 25))
|
||||
|
||||
(path: PathParams, ...handlers: RequestHandlerParams[]): T;
|
||||
>path : Symbol(path, Decl(contextualTypingOfTooShortOverloads.ts, 24, 5))
|
||||
>PathParams : Symbol(PathParams, Decl(contextualTypingOfTooShortOverloads.ts, 25, 1))
|
||||
>handlers : Symbol(handlers, Decl(contextualTypingOfTooShortOverloads.ts, 24, 22))
|
||||
>RequestHandlerParams : Symbol(RequestHandlerParams, Decl(contextualTypingOfTooShortOverloads.ts, 27, 56))
|
||||
>T : Symbol(T, Decl(contextualTypingOfTooShortOverloads.ts, 22, 25))
|
||||
}
|
||||
|
||||
type PathParams = string | RegExp | (string | RegExp)[];
|
||||
>PathParams : Symbol(PathParams, Decl(contextualTypingOfTooShortOverloads.ts, 25, 1))
|
||||
>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
type RequestHandlerParams = RequestHandler | ErrorRequestHandler | (RequestHandler | ErrorRequestHandler)[];
|
||||
>RequestHandlerParams : Symbol(RequestHandlerParams, Decl(contextualTypingOfTooShortOverloads.ts, 27, 56))
|
||||
>RequestHandler : Symbol(RequestHandler, Decl(contextualTypingOfTooShortOverloads.ts, 28, 108))
|
||||
>ErrorRequestHandler : Symbol(ErrorRequestHandler, Decl(contextualTypingOfTooShortOverloads.ts, 32, 1))
|
||||
>RequestHandler : Symbol(RequestHandler, Decl(contextualTypingOfTooShortOverloads.ts, 28, 108))
|
||||
>ErrorRequestHandler : Symbol(ErrorRequestHandler, Decl(contextualTypingOfTooShortOverloads.ts, 32, 1))
|
||||
|
||||
interface RequestHandler {
|
||||
>RequestHandler : Symbol(RequestHandler, Decl(contextualTypingOfTooShortOverloads.ts, 28, 108))
|
||||
|
||||
(req: Request, res: Response, next: NextFunction): any;
|
||||
>req : Symbol(req, Decl(contextualTypingOfTooShortOverloads.ts, 31, 5))
|
||||
>Request : Symbol(Request, Decl(contextualTypingOfTooShortOverloads.ts, 36, 1))
|
||||
>res : Symbol(res, Decl(contextualTypingOfTooShortOverloads.ts, 31, 18))
|
||||
>Response : Symbol(Response, Decl(contextualTypingOfTooShortOverloads.ts, 40, 1))
|
||||
>next : Symbol(next, Decl(contextualTypingOfTooShortOverloads.ts, 31, 33))
|
||||
>NextFunction : Symbol(NextFunction, Decl(contextualTypingOfTooShortOverloads.ts, 44, 1))
|
||||
}
|
||||
|
||||
interface ErrorRequestHandler {
|
||||
>ErrorRequestHandler : Symbol(ErrorRequestHandler, Decl(contextualTypingOfTooShortOverloads.ts, 32, 1))
|
||||
|
||||
(err: any, req: Request, res: Response, next: NextFunction): any;
|
||||
>err : Symbol(err, Decl(contextualTypingOfTooShortOverloads.ts, 35, 5))
|
||||
>req : Symbol(req, Decl(contextualTypingOfTooShortOverloads.ts, 35, 14))
|
||||
>Request : Symbol(Request, Decl(contextualTypingOfTooShortOverloads.ts, 36, 1))
|
||||
>res : Symbol(res, Decl(contextualTypingOfTooShortOverloads.ts, 35, 28))
|
||||
>Response : Symbol(Response, Decl(contextualTypingOfTooShortOverloads.ts, 40, 1))
|
||||
>next : Symbol(next, Decl(contextualTypingOfTooShortOverloads.ts, 35, 43))
|
||||
>NextFunction : Symbol(NextFunction, Decl(contextualTypingOfTooShortOverloads.ts, 44, 1))
|
||||
}
|
||||
|
||||
interface Request {
|
||||
>Request : Symbol(Request, Decl(contextualTypingOfTooShortOverloads.ts, 36, 1))
|
||||
|
||||
method: string;
|
||||
>method : Symbol(Request.method, Decl(contextualTypingOfTooShortOverloads.ts, 38, 19))
|
||||
}
|
||||
|
||||
interface Response {
|
||||
>Response : Symbol(Response, Decl(contextualTypingOfTooShortOverloads.ts, 40, 1))
|
||||
|
||||
statusCode: number;
|
||||
>statusCode : Symbol(Response.statusCode, Decl(contextualTypingOfTooShortOverloads.ts, 42, 20))
|
||||
}
|
||||
|
||||
interface NextFunction {
|
||||
>NextFunction : Symbol(NextFunction, Decl(contextualTypingOfTooShortOverloads.ts, 44, 1))
|
||||
|
||||
(err?: any): void;
|
||||
>err : Symbol(err, Decl(contextualTypingOfTooShortOverloads.ts, 47, 5))
|
||||
}
|
||||
|
||||
@ -0,0 +1,143 @@
|
||||
=== tests/cases/compiler/contextualTypingOfTooShortOverloads.ts ===
|
||||
// small repro from #11875
|
||||
var use: Overload;
|
||||
>use : Overload
|
||||
>Overload : Overload
|
||||
|
||||
use((req, res) => {});
|
||||
>use((req, res) => {}) : void
|
||||
>use : Overload
|
||||
>(req, res) => {} : (req: any, res: any) => void
|
||||
>req : any
|
||||
>res : any
|
||||
|
||||
interface Overload {
|
||||
>Overload : Overload
|
||||
|
||||
(handler1: (req1: string) => void): void;
|
||||
>handler1 : (req1: string) => void
|
||||
>req1 : string
|
||||
|
||||
(handler2: (req2: number, res2: number) => void): void;
|
||||
>handler2 : (req2: number, res2: number) => void
|
||||
>req2 : number
|
||||
>res2 : number
|
||||
}
|
||||
// larger repro from #11875
|
||||
let app: MyApp;
|
||||
>app : MyApp
|
||||
>MyApp : MyApp
|
||||
|
||||
app.use((err: any, req, res, next) => { return; });
|
||||
>app.use((err: any, req, res, next) => { return; }) : MyApp
|
||||
>app.use : IRouterHandler<MyApp> & IRouterMatcher<MyApp>
|
||||
>app : MyApp
|
||||
>use : IRouterHandler<MyApp> & IRouterMatcher<MyApp>
|
||||
>(err: any, req, res, next) => { return; } : (err: any, req: any, res: any, next: any) => void
|
||||
>err : any
|
||||
>req : any
|
||||
>res : any
|
||||
>next : any
|
||||
|
||||
|
||||
interface MyApp {
|
||||
>MyApp : MyApp
|
||||
|
||||
use: IRouterHandler<this> & IRouterMatcher<this>;
|
||||
>use : IRouterHandler<this> & IRouterMatcher<this>
|
||||
>IRouterHandler : IRouterHandler<T>
|
||||
>IRouterMatcher : IRouterMatcher<T>
|
||||
}
|
||||
|
||||
interface IRouterHandler<T> {
|
||||
>IRouterHandler : IRouterHandler<T>
|
||||
>T : T
|
||||
|
||||
(...handlers: RequestHandler[]): T;
|
||||
>handlers : RequestHandler[]
|
||||
>RequestHandler : RequestHandler
|
||||
>T : T
|
||||
|
||||
(...handlers: RequestHandlerParams[]): T;
|
||||
>handlers : RequestHandlerParams[]
|
||||
>RequestHandlerParams : RequestHandlerParams
|
||||
>T : T
|
||||
}
|
||||
|
||||
interface IRouterMatcher<T> {
|
||||
>IRouterMatcher : IRouterMatcher<T>
|
||||
>T : T
|
||||
|
||||
(path: PathParams, ...handlers: RequestHandler[]): T;
|
||||
>path : PathParams
|
||||
>PathParams : PathParams
|
||||
>handlers : RequestHandler[]
|
||||
>RequestHandler : RequestHandler
|
||||
>T : T
|
||||
|
||||
(path: PathParams, ...handlers: RequestHandlerParams[]): T;
|
||||
>path : PathParams
|
||||
>PathParams : PathParams
|
||||
>handlers : RequestHandlerParams[]
|
||||
>RequestHandlerParams : RequestHandlerParams
|
||||
>T : T
|
||||
}
|
||||
|
||||
type PathParams = string | RegExp | (string | RegExp)[];
|
||||
>PathParams : PathParams
|
||||
>RegExp : RegExp
|
||||
>RegExp : RegExp
|
||||
|
||||
type RequestHandlerParams = RequestHandler | ErrorRequestHandler | (RequestHandler | ErrorRequestHandler)[];
|
||||
>RequestHandlerParams : RequestHandlerParams
|
||||
>RequestHandler : RequestHandler
|
||||
>ErrorRequestHandler : ErrorRequestHandler
|
||||
>RequestHandler : RequestHandler
|
||||
>ErrorRequestHandler : ErrorRequestHandler
|
||||
|
||||
interface RequestHandler {
|
||||
>RequestHandler : RequestHandler
|
||||
|
||||
(req: Request, res: Response, next: NextFunction): any;
|
||||
>req : Request
|
||||
>Request : Request
|
||||
>res : Response
|
||||
>Response : Response
|
||||
>next : NextFunction
|
||||
>NextFunction : NextFunction
|
||||
}
|
||||
|
||||
interface ErrorRequestHandler {
|
||||
>ErrorRequestHandler : ErrorRequestHandler
|
||||
|
||||
(err: any, req: Request, res: Response, next: NextFunction): any;
|
||||
>err : any
|
||||
>req : Request
|
||||
>Request : Request
|
||||
>res : Response
|
||||
>Response : Response
|
||||
>next : NextFunction
|
||||
>NextFunction : NextFunction
|
||||
}
|
||||
|
||||
interface Request {
|
||||
>Request : Request
|
||||
|
||||
method: string;
|
||||
>method : string
|
||||
}
|
||||
|
||||
interface Response {
|
||||
>Response : Response
|
||||
|
||||
statusCode: number;
|
||||
>statusCode : number
|
||||
}
|
||||
|
||||
interface NextFunction {
|
||||
>NextFunction : NextFunction
|
||||
|
||||
(err?: any): void;
|
||||
>err : any
|
||||
}
|
||||
|
||||
@ -31,12 +31,12 @@ var m1;
|
||||
return c;
|
||||
}());
|
||||
m1.c = c;
|
||||
var e;
|
||||
(function (e) {
|
||||
e[e["weekday"] = 0] = "weekday";
|
||||
e[e["weekend"] = 1] = "weekend";
|
||||
e[e["holiday"] = 2] = "holiday";
|
||||
})(m1.e || (m1.e = {}));
|
||||
var e = m1.e;
|
||||
})(e = m1.e || (m1.e = {}));
|
||||
})(m1 || (m1 = {}));
|
||||
var a;
|
||||
var b = {
|
||||
|
||||
@ -33,9 +33,9 @@ var X;
|
||||
var M;
|
||||
(function (M) {
|
||||
})(M = base.M || (base.M = {}));
|
||||
var E;
|
||||
(function (E) {
|
||||
})(base.E || (base.E = {}));
|
||||
var E = base.E;
|
||||
})(E = base.E || (base.E = {}));
|
||||
})(base = Y.base || (Y.base = {}));
|
||||
})(Y = X.Y || (X.Y = {}));
|
||||
})(X || (X = {}));
|
||||
|
||||
@ -68,10 +68,10 @@ var M;
|
||||
return E;
|
||||
}(C));
|
||||
P.E = E;
|
||||
var D;
|
||||
(function (D) {
|
||||
D[D["f"] = 0] = "f";
|
||||
})(P.D || (P.D = {}));
|
||||
var D = P.D;
|
||||
})(D = P.D || (P.D = {}));
|
||||
P.w = M.D.f; // error, should be typeof M.D.f
|
||||
P.x = M.C.f; // error, should be typeof M.C.f
|
||||
P.x = M.E.f; // error, should be typeof M.E.f
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
//// [tests/cases/compiler/declarationFilesWithTypeReferences1.ts] ////
|
||||
|
||||
//// [index.d.ts]
|
||||
|
||||
interface Error {
|
||||
stack2: string;
|
||||
}
|
||||
|
||||
//// [app.ts]
|
||||
|
||||
function foo(): Error {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//// [app.js]
|
||||
function foo() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
//// [app.d.ts]
|
||||
declare function foo(): Error;
|
||||
@ -0,0 +1,18 @@
|
||||
=== /node_modules/@types/node/index.d.ts ===
|
||||
|
||||
interface Error {
|
||||
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(index.d.ts, 0, 0))
|
||||
|
||||
stack2: string;
|
||||
>stack2 : Symbol(Error.stack2, Decl(index.d.ts, 1, 17))
|
||||
}
|
||||
|
||||
=== /app.ts ===
|
||||
|
||||
function foo(): Error {
|
||||
>foo : Symbol(foo, Decl(app.ts, 0, 0))
|
||||
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(index.d.ts, 0, 0))
|
||||
|
||||
return undefined;
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
=== /node_modules/@types/node/index.d.ts ===
|
||||
|
||||
interface Error {
|
||||
>Error : Error
|
||||
|
||||
stack2: string;
|
||||
>stack2 : string
|
||||
}
|
||||
|
||||
=== /app.ts ===
|
||||
|
||||
function foo(): Error {
|
||||
>foo : () => Error
|
||||
>Error : Error
|
||||
|
||||
return undefined;
|
||||
>undefined : undefined
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
//// [tests/cases/compiler/declarationFilesWithTypeReferences2.ts] ////
|
||||
|
||||
//// [index.d.ts]
|
||||
|
||||
interface Error2 {
|
||||
stack2: string;
|
||||
}
|
||||
|
||||
//// [app.ts]
|
||||
|
||||
function foo(): Error2 {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//// [app.js]
|
||||
function foo() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
//// [app.d.ts]
|
||||
/// <reference types="node" />
|
||||
declare function foo(): Error2;
|
||||
@ -0,0 +1,18 @@
|
||||
=== /node_modules/@types/node/index.d.ts ===
|
||||
|
||||
interface Error2 {
|
||||
>Error2 : Symbol(Error2, Decl(index.d.ts, 0, 0))
|
||||
|
||||
stack2: string;
|
||||
>stack2 : Symbol(Error2.stack2, Decl(index.d.ts, 1, 18))
|
||||
}
|
||||
|
||||
=== /app.ts ===
|
||||
|
||||
function foo(): Error2 {
|
||||
>foo : Symbol(foo, Decl(app.ts, 0, 0))
|
||||
>Error2 : Symbol(Error2, Decl(index.d.ts, 0, 0))
|
||||
|
||||
return undefined;
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
=== /node_modules/@types/node/index.d.ts ===
|
||||
|
||||
interface Error2 {
|
||||
>Error2 : Error2
|
||||
|
||||
stack2: string;
|
||||
>stack2 : string
|
||||
}
|
||||
|
||||
=== /app.ts ===
|
||||
|
||||
function foo(): Error2 {
|
||||
>foo : () => Error2
|
||||
>Error2 : Error2
|
||||
|
||||
return undefined;
|
||||
>undefined : undefined
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
//// [tests/cases/compiler/declarationFilesWithTypeReferences3.ts] ////
|
||||
|
||||
//// [index.d.ts]
|
||||
|
||||
interface Error2 {
|
||||
stack2: string;
|
||||
}
|
||||
|
||||
//// [app.ts]
|
||||
/// <reference types="node"/>
|
||||
function foo(): Error2 {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//// [app.js]
|
||||
/// <reference types="node"/>
|
||||
function foo() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
//// [app.d.ts]
|
||||
/// <reference types="node" />
|
||||
declare function foo(): Error2;
|
||||
@ -0,0 +1,18 @@
|
||||
=== /a/node_modules/@types/node/index.d.ts ===
|
||||
|
||||
interface Error2 {
|
||||
>Error2 : Symbol(Error2, Decl(index.d.ts, 0, 0))
|
||||
|
||||
stack2: string;
|
||||
>stack2 : Symbol(Error2.stack2, Decl(index.d.ts, 1, 18))
|
||||
}
|
||||
|
||||
=== /a/app.ts ===
|
||||
/// <reference types="node"/>
|
||||
function foo(): Error2 {
|
||||
>foo : Symbol(foo, Decl(app.ts, 0, 0))
|
||||
>Error2 : Symbol(Error2, Decl(index.d.ts, 0, 0))
|
||||
|
||||
return undefined;
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
=== /a/node_modules/@types/node/index.d.ts ===
|
||||
|
||||
interface Error2 {
|
||||
>Error2 : Error2
|
||||
|
||||
stack2: string;
|
||||
>stack2 : string
|
||||
}
|
||||
|
||||
=== /a/app.ts ===
|
||||
/// <reference types="node"/>
|
||||
function foo(): Error2 {
|
||||
>foo : () => Error2
|
||||
>Error2 : Error2
|
||||
|
||||
return undefined;
|
||||
>undefined : undefined
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
//// [tests/cases/compiler/declarationFilesWithTypeReferences4.ts] ////
|
||||
|
||||
//// [index.d.ts]
|
||||
|
||||
interface Error {
|
||||
stack2: string;
|
||||
}
|
||||
|
||||
//// [app.ts]
|
||||
/// <reference types="node"/>
|
||||
function foo(): Error {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//// [app.js]
|
||||
/// <reference types="node"/>
|
||||
function foo() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
//// [app.d.ts]
|
||||
declare function foo(): Error;
|
||||
@ -0,0 +1,18 @@
|
||||
=== /a/node_modules/@types/node/index.d.ts ===
|
||||
|
||||
interface Error {
|
||||
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(index.d.ts, 0, 0))
|
||||
|
||||
stack2: string;
|
||||
>stack2 : Symbol(Error.stack2, Decl(index.d.ts, 1, 17))
|
||||
}
|
||||
|
||||
=== /a/app.ts ===
|
||||
/// <reference types="node"/>
|
||||
function foo(): Error {
|
||||
>foo : Symbol(foo, Decl(app.ts, 0, 0))
|
||||
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(index.d.ts, 0, 0))
|
||||
|
||||
return undefined;
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
=== /a/node_modules/@types/node/index.d.ts ===
|
||||
|
||||
interface Error {
|
||||
>Error : Error
|
||||
|
||||
stack2: string;
|
||||
>stack2 : string
|
||||
}
|
||||
|
||||
=== /a/app.ts ===
|
||||
/// <reference types="node"/>
|
||||
function foo(): Error {
|
||||
>foo : () => Error
|
||||
>Error : Error
|
||||
|
||||
return undefined;
|
||||
>undefined : undefined
|
||||
}
|
||||
@ -17,12 +17,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
let Testing123_1 = class Testing123 {
|
||||
let Testing123 = Testing123_1 = class Testing123 {
|
||||
};
|
||||
let Testing123 = Testing123_1;
|
||||
Testing123.prop1 = Testing123_1.prop0;
|
||||
Testing123 = Testing123_1 = __decorate([
|
||||
Something({ v: () => Testing123_1 }),
|
||||
__metadata("design:paramtypes", [])
|
||||
], Testing123);
|
||||
exports.Testing123 = Testing123;
|
||||
var Testing123_1;
|
||||
|
||||
@ -16,11 +16,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
let Testing123_1 = class Testing123 {
|
||||
let Testing123 = Testing123_1 = class Testing123 {
|
||||
};
|
||||
let Testing123 = Testing123_1;
|
||||
Testing123 = Testing123_1 = __decorate([
|
||||
Something({ v: () => Testing123_1 }),
|
||||
__metadata("design:paramtypes", [])
|
||||
], Testing123);
|
||||
exports.Testing123 = Testing123;
|
||||
var Testing123_1;
|
||||
|
||||
@ -21,13 +21,12 @@ System.register([], function (exports_1, context_1) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __moduleName = context_1 && context_1.id;
|
||||
var Testing123_1, Testing123;
|
||||
var Testing123, Testing123_1;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
Testing123_1 = class Testing123 {
|
||||
Testing123 = Testing123_1 = class Testing123 {
|
||||
};
|
||||
Testing123 = Testing123_1;
|
||||
Testing123.prop1 = Testing123_1.prop0;
|
||||
Testing123 = Testing123_1 = __decorate([
|
||||
Something({ v: () => Testing123_1 }),
|
||||
|
||||
@ -18,13 +18,12 @@ System.register([], function (exports_1, context_1) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __moduleName = context_1 && context_1.id;
|
||||
var Testing123_1, Testing123;
|
||||
var Testing123, Testing123_1;
|
||||
return {
|
||||
setters: [],
|
||||
execute: function () {
|
||||
Testing123_1 = class Testing123 {
|
||||
Testing123 = Testing123_1 = class Testing123 {
|
||||
};
|
||||
Testing123 = Testing123_1;
|
||||
Testing123 = Testing123_1 = __decorate([
|
||||
Something({ v: () => Testing123_1 }),
|
||||
__metadata("design:paramtypes", [])
|
||||
|
||||
@ -33,8 +33,8 @@ var B = (function () {
|
||||
}
|
||||
return B;
|
||||
}());
|
||||
exports.B = B;
|
||||
__decorate([
|
||||
decorator,
|
||||
__metadata("design:type", Object)
|
||||
], B.prototype, "x", void 0);
|
||||
exports.B = B;
|
||||
|
||||
@ -33,8 +33,8 @@ var B = (function () {
|
||||
}
|
||||
return B;
|
||||
}());
|
||||
exports.B = B;
|
||||
__decorate([
|
||||
decorator,
|
||||
__metadata("design:type", A)
|
||||
], B.prototype, "x", void 0);
|
||||
exports.B = B;
|
||||
|
||||
@ -16,12 +16,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
let C_1 = class C {
|
||||
let C = C_1 = class C {
|
||||
static x() { return C_1.y; }
|
||||
};
|
||||
let C = C_1;
|
||||
C.y = 1;
|
||||
C = C_1 = __decorate([
|
||||
dec
|
||||
], C);
|
||||
let c = new C();
|
||||
var C_1;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user