mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into property-use-before-declare
This commit is contained in:
+124
-152
@@ -100,6 +100,8 @@ namespace ts {
|
||||
IsObjectLiteralOrClassExpressionMethod = 1 << 7,
|
||||
}
|
||||
|
||||
let flowNodeCreated: <T extends FlowNode>(node: T) => T = identity;
|
||||
|
||||
const binder = createBinder();
|
||||
|
||||
export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
|
||||
@@ -401,13 +403,15 @@ namespace ts {
|
||||
messageNeedsName = false;
|
||||
}
|
||||
|
||||
if (symbol.declarations && symbol.declarations.length) {
|
||||
let multipleDefaultExports = false;
|
||||
if (length(symbol.declarations)) {
|
||||
// If the current node is a default export of some sort, then check if
|
||||
// there are any other default exports that we need to error on.
|
||||
// We'll know whether we have other default exports depending on if `symbol` already has a declaration list set.
|
||||
if (isDefaultExport) {
|
||||
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
|
||||
messageNeedsName = false;
|
||||
multipleDefaultExports = true;
|
||||
}
|
||||
else {
|
||||
// This is to properly report an error in the case "export default { }" is after export default of class declaration or function declaration.
|
||||
@@ -418,15 +422,26 @@ namespace ts {
|
||||
(node.kind === SyntaxKind.ExportAssignment && !(<ExportAssignment>node).isExportEquals)) {
|
||||
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
|
||||
messageNeedsName = false;
|
||||
multipleDefaultExports = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const addError = (decl: Declaration): void => {
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(getNameOfDeclaration(decl) || decl, message, messageNeedsName ? getDisplayName(decl) : undefined));
|
||||
};
|
||||
forEach(symbol.declarations, addError);
|
||||
addError(node);
|
||||
const declarationName = getNameOfDeclaration(node) || node;
|
||||
const relatedInformation: DiagnosticRelatedInformation[] = [];
|
||||
forEach(symbol.declarations, (declaration, index) => {
|
||||
const decl = getNameOfDeclaration(declaration) || declaration;
|
||||
const diag = createDiagnosticForNode(decl, message, messageNeedsName ? getDisplayName(declaration) : undefined);
|
||||
file.bindDiagnostics.push(
|
||||
multipleDefaultExports ? addRelatedInfo(diag, createDiagnosticForNode(declarationName, index === 0 ? Diagnostics.Another_export_default_is_here : Diagnostics.and_here)) : diag
|
||||
);
|
||||
if (multipleDefaultExports) {
|
||||
relatedInformation.push(createDiagnosticForNode(decl, Diagnostics.The_first_export_default_is_here));
|
||||
}
|
||||
});
|
||||
|
||||
const diag = createDiagnosticForNode(declarationName, message, messageNeedsName ? getDisplayName(node) : undefined);
|
||||
file.bindDiagnostics.push(multipleDefaultExports ? addRelatedInfo(diag, ...relatedInformation) : diag);
|
||||
|
||||
symbol = createSymbol(SymbolFlags.None, name);
|
||||
}
|
||||
@@ -530,6 +545,7 @@ namespace ts {
|
||||
blockScopeContainer.locals = undefined;
|
||||
}
|
||||
if (containerFlags & ContainerFlags.IsControlFlowContainer) {
|
||||
const saveFlowNodeCreated = flowNodeCreated;
|
||||
const saveCurrentFlow = currentFlow;
|
||||
const saveBreakTarget = currentBreakTarget;
|
||||
const saveContinueTarget = currentContinueTarget;
|
||||
@@ -547,12 +563,13 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
// We create a return control flow graph for IIFEs and constructors. For constructors
|
||||
// we use the return control flow graph in strict property intialization checks.
|
||||
// we use the return control flow graph in strict property initialization checks.
|
||||
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor ? createBranchLabel() : undefined;
|
||||
currentBreakTarget = undefined;
|
||||
currentContinueTarget = undefined;
|
||||
activeLabels = undefined;
|
||||
hasExplicitReturn = false;
|
||||
flowNodeCreated = identity;
|
||||
bindChildren(node);
|
||||
// Reset all reachability check related flags on node (for incremental scenarios)
|
||||
node.flags &= ~NodeFlags.ReachabilityAndEmitFlags;
|
||||
@@ -579,6 +596,7 @@ namespace ts {
|
||||
currentReturnTarget = saveReturnTarget;
|
||||
activeLabels = saveActiveLabels;
|
||||
hasExplicitReturn = saveHasExplicitReturn;
|
||||
flowNodeCreated = saveFlowNodeCreated;
|
||||
}
|
||||
else if (containerFlags & ContainerFlags.IsInterface) {
|
||||
seenThisKeyword = false;
|
||||
@@ -858,7 +876,7 @@ namespace ts {
|
||||
return antecedent;
|
||||
}
|
||||
setFlowNodeReferenced(antecedent);
|
||||
return { flags, expression, antecedent };
|
||||
return flowNodeCreated({ flags, expression, antecedent });
|
||||
}
|
||||
|
||||
function createFlowSwitchClause(antecedent: FlowNode, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): FlowNode {
|
||||
@@ -866,17 +884,17 @@ namespace ts {
|
||||
return antecedent;
|
||||
}
|
||||
setFlowNodeReferenced(antecedent);
|
||||
return { flags: FlowFlags.SwitchClause, switchStatement, clauseStart, clauseEnd, antecedent };
|
||||
return flowNodeCreated({ flags: FlowFlags.SwitchClause, switchStatement, clauseStart, clauseEnd, antecedent });
|
||||
}
|
||||
|
||||
function createFlowAssignment(antecedent: FlowNode, node: Expression | VariableDeclaration | BindingElement): FlowNode {
|
||||
setFlowNodeReferenced(antecedent);
|
||||
return { flags: FlowFlags.Assignment, antecedent, node };
|
||||
return flowNodeCreated({ flags: FlowFlags.Assignment, antecedent, node });
|
||||
}
|
||||
|
||||
function createFlowArrayMutation(antecedent: FlowNode, node: CallExpression | BinaryExpression): FlowNode {
|
||||
setFlowNodeReferenced(antecedent);
|
||||
const res: FlowArrayMutation = { flags: FlowFlags.ArrayMutation, antecedent, node };
|
||||
const res: FlowArrayMutation = flowNodeCreated({ flags: FlowFlags.ArrayMutation, antecedent, node });
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1080,8 +1098,16 @@ namespace ts {
|
||||
function bindTryStatement(node: TryStatement): void {
|
||||
const preFinallyLabel = createBranchLabel();
|
||||
const preTryFlow = currentFlow;
|
||||
// TODO: Every statement in try block is potentially an exit point!
|
||||
const tryPriors: FlowNode[] = [];
|
||||
const oldFlowNodeCreated = flowNodeCreated;
|
||||
// We hook the creation of all flow nodes within the `try` scope and store them so we can add _all_ of them
|
||||
// as possible antecedents of the start of the `catch` or `finally` blocks.
|
||||
// Don't bother intercepting the call if there's no finally or catch block that needs the information
|
||||
if (node.catchClause || node.finallyBlock) {
|
||||
flowNodeCreated = node => (tryPriors.push(node), node);
|
||||
}
|
||||
bind(node.tryBlock);
|
||||
flowNodeCreated = oldFlowNodeCreated;
|
||||
addAntecedent(preFinallyLabel, currentFlow);
|
||||
|
||||
const flowAfterTry = currentFlow;
|
||||
@@ -1089,12 +1115,36 @@ namespace ts {
|
||||
|
||||
if (node.catchClause) {
|
||||
currentFlow = preTryFlow;
|
||||
if (tryPriors.length) {
|
||||
const preCatchFlow = createBranchLabel();
|
||||
addAntecedent(preCatchFlow, currentFlow);
|
||||
for (const p of tryPriors) {
|
||||
addAntecedent(preCatchFlow, p);
|
||||
}
|
||||
currentFlow = finishFlowLabel(preCatchFlow);
|
||||
}
|
||||
|
||||
bind(node.catchClause);
|
||||
addAntecedent(preFinallyLabel, currentFlow);
|
||||
|
||||
flowAfterCatch = currentFlow;
|
||||
}
|
||||
if (node.finallyBlock) {
|
||||
// We add the nodes within the `try` block to the `finally`'s antecedents if there's no catch block
|
||||
// (If there is a `catch` block, it will have all these antecedents instead, and the `finally` will
|
||||
// have the end of the `try` block and the end of the `catch` block)
|
||||
let preFinallyPrior = preTryFlow;
|
||||
if (!node.catchClause) {
|
||||
if (tryPriors.length) {
|
||||
const preFinallyFlow = createBranchLabel();
|
||||
addAntecedent(preFinallyFlow, preTryFlow);
|
||||
for (const p of tryPriors) {
|
||||
addAntecedent(preFinallyFlow, p);
|
||||
}
|
||||
preFinallyPrior = finishFlowLabel(preFinallyFlow);
|
||||
}
|
||||
}
|
||||
|
||||
// in finally flow is combined from pre-try/flow from try/flow from catch
|
||||
// pre-flow is necessary to make sure that finally is reachable even if finally flows in both try and finally blocks are unreachable
|
||||
|
||||
@@ -1123,7 +1173,7 @@ namespace ts {
|
||||
//
|
||||
// extra edges that we inject allows to control this behavior
|
||||
// if when walking the flow we step on post-finally edge - we can mark matching pre-finally edge as locked so it will be skipped.
|
||||
const preFinallyFlow: PreFinallyFlow = { flags: FlowFlags.PreFinally, antecedent: preTryFlow, lock: {} };
|
||||
const preFinallyFlow: PreFinallyFlow = { flags: FlowFlags.PreFinally, antecedent: preFinallyPrior, lock: {} };
|
||||
addAntecedent(preFinallyLabel, preFinallyFlow);
|
||||
|
||||
currentFlow = finishFlowLabel(preFinallyLabel);
|
||||
@@ -1142,7 +1192,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
if (!(currentFlow.flags & FlowFlags.Unreachable)) {
|
||||
const afterFinallyFlow: AfterFinallyFlow = { flags: FlowFlags.AfterFinally, antecedent: currentFlow };
|
||||
const afterFinallyFlow: AfterFinallyFlow = flowNodeCreated({ flags: FlowFlags.AfterFinally, antecedent: currentFlow });
|
||||
preFinallyFlow.lock = afterFinallyFlow;
|
||||
currentFlow = afterFinallyFlow;
|
||||
}
|
||||
@@ -2462,8 +2512,13 @@ namespace ts {
|
||||
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true);
|
||||
break;
|
||||
case SyntaxKind.SourceFile:
|
||||
// this.foo assignment in a source file
|
||||
// Do not bind. It would be nice to support this someday though.
|
||||
// this.property = assignment in a source file -- declare symbol in exports for a module, in locals for a script
|
||||
if ((thisContainer as SourceFile).commonJsModuleIndicator) {
|
||||
declareSymbol(thisContainer.symbol.exports!, thisContainer.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None);
|
||||
}
|
||||
else {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -3051,32 +3106,24 @@ namespace ts {
|
||||
|
||||
function computeCallExpression(node: CallExpression, subtreeFlags: TransformFlags) {
|
||||
let transformFlags = subtreeFlags;
|
||||
const callee = skipOuterExpressions(node.expression);
|
||||
const expression = node.expression;
|
||||
|
||||
if (node.typeArguments) {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
if (subtreeFlags & TransformFlags.ContainsRestOrSpread
|
||||
|| (expression.transformFlags & (TransformFlags.Super | TransformFlags.ContainsSuper))) {
|
||||
if (subtreeFlags & TransformFlags.ContainsRestOrSpread || isSuperOrSuperProperty(callee)) {
|
||||
// If the this node contains a SpreadExpression, or is a super call, then it is an ES6
|
||||
// node.
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
// super property or element accesses could be inside lambdas, etc, and need a captured `this`,
|
||||
// while super keyword for super calls (indicated by TransformFlags.Super) does not (since it can only be top-level in a constructor)
|
||||
if (expression.transformFlags & TransformFlags.ContainsSuper) {
|
||||
if (isSuperProperty(callee)) {
|
||||
transformFlags |= TransformFlags.ContainsLexicalThis;
|
||||
}
|
||||
}
|
||||
|
||||
if (expression.kind === SyntaxKind.ImportKeyword) {
|
||||
transformFlags |= TransformFlags.ContainsDynamicImport;
|
||||
|
||||
// A dynamic 'import()' call that contains a lexical 'this' will
|
||||
// require a captured 'this' when emitting down-level.
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
|
||||
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
|
||||
}
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
@@ -3104,8 +3151,8 @@ namespace ts {
|
||||
|
||||
if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) {
|
||||
// Destructuring object assignments with are ES2015 syntax
|
||||
// and possibly ESNext if they contain rest
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment;
|
||||
// and possibly ES2018 if they contain rest
|
||||
transformFlags |= TransformFlags.AssertES2018 | TransformFlags.AssertES2015 | TransformFlags.AssertDestructuringAssignment;
|
||||
}
|
||||
else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ArrayLiteralExpression) {
|
||||
// Destructuring assignments are ES2015 syntax.
|
||||
@@ -3141,15 +3188,15 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsTypeScriptClassSyntax;
|
||||
}
|
||||
|
||||
// parameters with object rest destructuring are ES Next syntax
|
||||
// parameters with object rest destructuring are ES2018 syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
transformFlags |= TransformFlags.AssertES2018;
|
||||
}
|
||||
|
||||
// If a parameter has an initializer, a binding pattern or a dotDotDot token, then
|
||||
// it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel.
|
||||
if (subtreeFlags & TransformFlags.ContainsBindingPattern || initializer || dotDotDotToken) {
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsDefaultValueAssignments;
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
@@ -3160,7 +3207,6 @@ namespace ts {
|
||||
let transformFlags = subtreeFlags;
|
||||
const expression = node.expression;
|
||||
const expressionKind = expression.kind;
|
||||
const expressionTransformFlags = expression.transformFlags;
|
||||
|
||||
// If the node is synthesized, it means the emitter put the parentheses there,
|
||||
// not the user. If we didn't want them, the emitter would not have put them
|
||||
@@ -3170,12 +3216,6 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
// If the expression of a ParenthesizedExpression is a destructuring assignment,
|
||||
// then the ParenthesizedExpression is a destructuring assignment.
|
||||
if (expressionTransformFlags & TransformFlags.DestructuringAssignment) {
|
||||
transformFlags |= TransformFlags.DestructuringAssignment;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
return transformFlags & ~TransformFlags.OuterExpressionExcludes;
|
||||
}
|
||||
@@ -3199,12 +3239,6 @@ namespace ts {
|
||||
|| node.typeParameters) {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
|
||||
// A computed property name containing `this` might need to be rewritten,
|
||||
// so propagate the ContainsLexicalThis flag upward.
|
||||
transformFlags |= TransformFlags.ContainsLexicalThis;
|
||||
}
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
@@ -3222,12 +3256,6 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
|
||||
// A computed property name containing `this` might need to be rewritten,
|
||||
// so propagate the ContainsLexicalThis flag upward.
|
||||
transformFlags |= TransformFlags.ContainsLexicalThis;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
return transformFlags & ~TransformFlags.ClassExcludes;
|
||||
}
|
||||
@@ -3259,7 +3287,7 @@ namespace ts {
|
||||
let transformFlags = subtreeFlags;
|
||||
|
||||
if (!node.variableDeclaration) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
transformFlags |= TransformFlags.AssertES2019;
|
||||
}
|
||||
else if (isBindingPattern(node.variableDeclaration.name)) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
@@ -3293,9 +3321,9 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
// function declarations with object rest destructuring are ES Next syntax
|
||||
// function declarations with object rest destructuring are ES2018 syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
transformFlags |= TransformFlags.AssertES2018;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
@@ -3317,14 +3345,14 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
// function declarations with object rest destructuring are ES Next syntax
|
||||
// function declarations with object rest destructuring are ES2018 syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
transformFlags |= TransformFlags.AssertES2018;
|
||||
}
|
||||
|
||||
// An async method declaration is ES2017 syntax.
|
||||
if (hasModifier(node, ModifierFlags.Async)) {
|
||||
transformFlags |= node.asteriskToken ? TransformFlags.AssertESNext : TransformFlags.AssertES2017;
|
||||
transformFlags |= node.asteriskToken ? TransformFlags.AssertES2018 : TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
if (node.asteriskToken) {
|
||||
@@ -3332,7 +3360,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
return transformFlags & ~TransformFlags.MethodOrAccessorExcludes;
|
||||
return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.MethodOrAccessorExcludes);
|
||||
}
|
||||
|
||||
function computeAccessor(node: AccessorDeclaration, subtreeFlags: TransformFlags) {
|
||||
@@ -3348,13 +3376,13 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
// function declarations with object rest destructuring are ES Next syntax
|
||||
// function declarations with object rest destructuring are ES2018 syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
transformFlags |= TransformFlags.AssertES2018;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
return transformFlags & ~TransformFlags.MethodOrAccessorExcludes;
|
||||
return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.MethodOrAccessorExcludes);
|
||||
}
|
||||
|
||||
function computePropertyDeclaration(node: PropertyDeclaration, subtreeFlags: TransformFlags) {
|
||||
@@ -3368,7 +3396,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
return transformFlags & ~TransformFlags.NodeExcludes;
|
||||
return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.PropertyExcludes);
|
||||
}
|
||||
|
||||
function computeFunctionDeclaration(node: FunctionDeclaration, subtreeFlags: TransformFlags) {
|
||||
@@ -3394,25 +3422,18 @@ namespace ts {
|
||||
|
||||
// An async function declaration is ES2017 syntax.
|
||||
if (modifierFlags & ModifierFlags.Async) {
|
||||
transformFlags |= node.asteriskToken ? TransformFlags.AssertESNext : TransformFlags.AssertES2017;
|
||||
transformFlags |= node.asteriskToken ? TransformFlags.AssertES2018 : TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// function declarations with object rest destructuring are ES Next syntax
|
||||
// function declarations with object rest destructuring are ES2018 syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
// If a FunctionDeclaration's subtree has marked the container as needing to capture the
|
||||
// lexical this, or the function contains parameters with initializers, then this node is
|
||||
// ES6 syntax.
|
||||
if (subtreeFlags & TransformFlags.ES2015FunctionSyntaxMask) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
transformFlags |= TransformFlags.AssertES2018;
|
||||
}
|
||||
|
||||
// If a FunctionDeclaration is generator function and is the body of a
|
||||
// transformed async function, then this node can be transformed to a
|
||||
// down-level generator.
|
||||
// Currently we do not support transforming any other generator fucntions
|
||||
// Currently we do not support transforming any other generator functions
|
||||
// down level.
|
||||
if (node.asteriskToken) {
|
||||
transformFlags |= TransformFlags.AssertGenerator;
|
||||
@@ -3436,20 +3457,12 @@ namespace ts {
|
||||
|
||||
// An async function expression is ES2017 syntax.
|
||||
if (hasModifier(node, ModifierFlags.Async)) {
|
||||
transformFlags |= node.asteriskToken ? TransformFlags.AssertESNext : TransformFlags.AssertES2017;
|
||||
transformFlags |= node.asteriskToken ? TransformFlags.AssertES2018 : TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// function expressions with object rest destructuring are ES Next syntax
|
||||
// function expressions with object rest destructuring are ES2018 syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
|
||||
// If a FunctionExpression's subtree has marked the container as needing to capture the
|
||||
// lexical this, or the function contains parameters with initializers, then this node is
|
||||
// ES6 syntax.
|
||||
if (subtreeFlags & TransformFlags.ES2015FunctionSyntaxMask) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
transformFlags |= TransformFlags.AssertES2018;
|
||||
}
|
||||
|
||||
// If a FunctionExpression is generator function and is the body of a
|
||||
@@ -3480,14 +3493,9 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// arrow functions with object rest destructuring are ES Next syntax
|
||||
// arrow functions with object rest destructuring are ES2018 syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
// If an ArrowFunction contains a lexical this, its container must capture the lexical this.
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
|
||||
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
|
||||
transformFlags |= TransformFlags.AssertES2018;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
@@ -3499,11 +3507,10 @@ namespace ts {
|
||||
|
||||
// If a PropertyAccessExpression starts with a super keyword, then it is
|
||||
// ES6 syntax, and requires a lexical `this` binding.
|
||||
if (transformFlags & TransformFlags.Super) {
|
||||
transformFlags ^= TransformFlags.Super;
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
// super inside of an async function requires hoisting the super access (ES2017).
|
||||
// same for super inside of an async generator, which is ESNext.
|
||||
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsESNext;
|
||||
// same for super inside of an async generator, which is ES2018.
|
||||
transformFlags |= TransformFlags.ContainsES2017 | TransformFlags.ContainsES2018;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
@@ -3512,16 +3519,13 @@ namespace ts {
|
||||
|
||||
function computeElementAccess(node: ElementAccessExpression, subtreeFlags: TransformFlags) {
|
||||
let transformFlags = subtreeFlags;
|
||||
const expression = node.expression;
|
||||
const expressionFlags = expression.transformFlags; // We do not want to aggregate flags from the argument expression for super/this capturing
|
||||
|
||||
// If an ElementAccessExpression starts with a super keyword, then it is
|
||||
// ES6 syntax, and requires a lexical `this` binding.
|
||||
if (expressionFlags & TransformFlags.Super) {
|
||||
transformFlags &= ~TransformFlags.Super;
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
// super inside of an async function requires hoisting the super access (ES2017).
|
||||
// same for super inside of an async generator, which is ESNext.
|
||||
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsESNext;
|
||||
// same for super inside of an async generator, which is ES2018.
|
||||
transformFlags |= TransformFlags.ContainsES2017 | TransformFlags.ContainsES2018;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
@@ -3530,11 +3534,11 @@ namespace ts {
|
||||
|
||||
function computeVariableDeclaration(node: VariableDeclaration, subtreeFlags: TransformFlags) {
|
||||
let transformFlags = subtreeFlags;
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern; // TODO(rbuckton): Why are these set unconditionally?
|
||||
|
||||
// A VariableDeclaration containing ObjectRest is ESNext syntax
|
||||
// A VariableDeclaration containing ObjectRest is ES2018 syntax
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
transformFlags |= TransformFlags.AssertES2018;
|
||||
}
|
||||
|
||||
// Type annotations are TypeScript syntax.
|
||||
@@ -3592,15 +3596,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function computeExpressionStatement(node: ExpressionStatement, subtreeFlags: TransformFlags) {
|
||||
let transformFlags = subtreeFlags;
|
||||
|
||||
// If the expression of an expression statement is a destructuring assignment,
|
||||
// then we treat the statement as ES6 so that we can indicate that we do not
|
||||
// need to hold on to the right-hand side.
|
||||
if (node.expression.transformFlags & TransformFlags.DestructuringAssignment) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
|
||||
const transformFlags = subtreeFlags;
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
return transformFlags & ~TransformFlags.NodeExcludes;
|
||||
}
|
||||
@@ -3641,8 +3637,8 @@ namespace ts {
|
||||
switch (kind) {
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
case SyntaxKind.AwaitExpression:
|
||||
// async/await is ES2017 syntax, but may be ESNext syntax (for async generators)
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2017;
|
||||
// async/await is ES2017 syntax, but may be ES2018 syntax (for async generators)
|
||||
transformFlags |= TransformFlags.AssertES2018 | TransformFlags.AssertES2017;
|
||||
break;
|
||||
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
@@ -3714,7 +3710,7 @@ namespace ts {
|
||||
case SyntaxKind.ForOfStatement:
|
||||
// This node is either ES2015 syntax or ES2017 syntax (if it is a for-await-of).
|
||||
if ((<ForOfStatement>node).awaitModifier) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
transformFlags |= TransformFlags.AssertES2018;
|
||||
}
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
break;
|
||||
@@ -3722,7 +3718,7 @@ namespace ts {
|
||||
case SyntaxKind.YieldExpression:
|
||||
// This node is either ES2015 syntax (in a generator) or ES2017 syntax (in an async
|
||||
// generator).
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2015 | TransformFlags.ContainsYield;
|
||||
transformFlags |= TransformFlags.AssertES2018 | TransformFlags.AssertES2015 | TransformFlags.ContainsYield;
|
||||
break;
|
||||
|
||||
case SyntaxKind.AnyKeyword:
|
||||
@@ -3773,17 +3769,6 @@ namespace ts {
|
||||
// This is so that they can flow through PropertyName transforms unaffected.
|
||||
// Instead, we mark the container as ES6, so that it can properly handle the transform.
|
||||
transformFlags |= TransformFlags.ContainsComputedPropertyName;
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
|
||||
// A computed method name like `[this.getName()](x: string) { ... }` needs to
|
||||
// distinguish itself from the normal case of a method body containing `this`:
|
||||
// `this` inside a method doesn't need to be rewritten (the method provides `this`),
|
||||
// whereas `this` inside a computed name *might* need to be rewritten if the class/object
|
||||
// is inside an arrow function:
|
||||
// `_this = this; () => class K { [_this.getName()]() { ... } }`
|
||||
// To make this distinction, use ContainsLexicalThisInComputedPropertyName
|
||||
// instead of ContainsLexicalThis for computed property names
|
||||
transformFlags |= TransformFlags.ContainsLexicalThisInComputedPropertyName;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.SpreadElement:
|
||||
@@ -3791,12 +3776,12 @@ namespace ts {
|
||||
break;
|
||||
|
||||
case SyntaxKind.SpreadAssignment:
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsObjectRestOrSpread;
|
||||
transformFlags |= TransformFlags.AssertES2018 | TransformFlags.ContainsObjectRestOrSpread;
|
||||
break;
|
||||
|
||||
case SyntaxKind.SuperKeyword:
|
||||
// This node is ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.Super;
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
excludeFlags = TransformFlags.OuterExpressionExcludes; // must be set to persist `Super`
|
||||
break;
|
||||
|
||||
@@ -3808,7 +3793,7 @@ namespace ts {
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
|
||||
if (subtreeFlags & TransformFlags.ContainsRestOrSpread) {
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsObjectRestOrSpread;
|
||||
transformFlags |= TransformFlags.AssertES2018 | TransformFlags.ContainsObjectRestOrSpread;
|
||||
}
|
||||
excludeFlags = TransformFlags.BindingPatternExcludes;
|
||||
break;
|
||||
@@ -3838,29 +3823,16 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
|
||||
// A computed property name containing `this` might need to be rewritten,
|
||||
// so propagate the ContainsLexicalThis flag upward.
|
||||
transformFlags |= TransformFlags.ContainsLexicalThis;
|
||||
}
|
||||
|
||||
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
// If an ObjectLiteralExpression contains a spread element, then it
|
||||
// is an ES next node.
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
// is an ES2018 node.
|
||||
transformFlags |= TransformFlags.AssertES2018;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
case SyntaxKind.NewExpression:
|
||||
excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExcludes;
|
||||
if (subtreeFlags & TransformFlags.ContainsRestOrSpread) {
|
||||
// If the this node contains a SpreadExpression, then it is an ES6
|
||||
// node.
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.DoStatement:
|
||||
@@ -3875,15 +3847,11 @@ namespace ts {
|
||||
break;
|
||||
|
||||
case SyntaxKind.SourceFile:
|
||||
if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ReturnStatement:
|
||||
// Return statements may require an `await` in ESNext.
|
||||
transformFlags |= TransformFlags.ContainsHoistedDeclarationOrCompletion | TransformFlags.AssertESNext;
|
||||
// Return statements may require an `await` in ES2018.
|
||||
transformFlags |= TransformFlags.ContainsHoistedDeclarationOrCompletion | TransformFlags.AssertES2018;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ContinueStatement:
|
||||
@@ -3896,6 +3864,10 @@ namespace ts {
|
||||
return transformFlags & ~excludeFlags;
|
||||
}
|
||||
|
||||
function propagatePropertyNameFlags(node: PropertyName, transformFlags: TransformFlags) {
|
||||
return transformFlags | (node.transformFlags & TransformFlags.PropertyNamePropagatingFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the transform flags to exclude when unioning the transform flags of a subtree.
|
||||
*
|
||||
|
||||
+512
-70
@@ -1,5 +1,80 @@
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
export interface ReusableDiagnostic extends ReusableDiagnosticRelatedInformation {
|
||||
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
|
||||
reportsUnnecessary?: {};
|
||||
source?: string;
|
||||
relatedInformation?: ReusableDiagnosticRelatedInformation[];
|
||||
}
|
||||
|
||||
export interface ReusableDiagnosticRelatedInformation {
|
||||
category: DiagnosticCategory;
|
||||
code: number;
|
||||
file: Path | undefined;
|
||||
start: number | undefined;
|
||||
length: number | undefined;
|
||||
messageText: string | ReusableDiagnosticMessageChain;
|
||||
}
|
||||
|
||||
export interface ReusableDiagnosticMessageChain {
|
||||
messageText: string;
|
||||
category: DiagnosticCategory;
|
||||
code: number;
|
||||
next?: ReusableDiagnosticMessageChain;
|
||||
}
|
||||
|
||||
export interface ReusableBuilderProgramState extends ReusableBuilderState {
|
||||
/**
|
||||
* Cache of semantic diagnostics for files with their Path being the key
|
||||
*/
|
||||
semanticDiagnosticsPerFile?: ReadonlyMap<ReadonlyArray<ReusableDiagnostic> | ReadonlyArray<Diagnostic>> | undefined;
|
||||
/**
|
||||
* The map has key by source file's path that has been changed
|
||||
*/
|
||||
changedFilesSet?: ReadonlyMap<true>;
|
||||
/**
|
||||
* Set of affected files being iterated
|
||||
*/
|
||||
affectedFiles?: ReadonlyArray<SourceFile> | undefined;
|
||||
/**
|
||||
* Current changed file for iterating over affected files
|
||||
*/
|
||||
currentChangedFilePath?: Path | undefined;
|
||||
/**
|
||||
* Map of file signatures, with key being file path, calculated while getting current changed file's affected files
|
||||
* These will be committed whenever the iteration through affected files of current changed file is complete
|
||||
*/
|
||||
currentAffectedFilesSignatures?: ReadonlyMap<string> | undefined;
|
||||
/**
|
||||
* Newly computed visible to outside referencedSet
|
||||
*/
|
||||
currentAffectedFilesExportedModulesMap?: Readonly<BuilderState.ComputingExportedModulesMap> | undefined;
|
||||
/**
|
||||
* True if the semantic diagnostics were copied from the old state
|
||||
*/
|
||||
semanticDiagnosticsFromOldState?: Map<true>;
|
||||
/**
|
||||
* program corresponding to this state
|
||||
*/
|
||||
program?: Program | undefined;
|
||||
/**
|
||||
* compilerOptions for the program
|
||||
*/
|
||||
compilerOptions: CompilerOptions;
|
||||
/**
|
||||
* Files pending to be emitted
|
||||
*/
|
||||
affectedFilesPendingEmit?: ReadonlyArray<Path> | undefined;
|
||||
/**
|
||||
* Current index to retrieve pending affected file
|
||||
*/
|
||||
affectedFilesPendingEmitIndex?: number | undefined;
|
||||
/*
|
||||
* true if semantic diagnostics are ReusableDiagnostic instead of Diagnostic
|
||||
*/
|
||||
hasReusableDiagnostic?: true;
|
||||
}
|
||||
|
||||
/**
|
||||
* State to store the changed files, affected files and cache semantic diagnostics
|
||||
*/
|
||||
@@ -27,7 +102,7 @@ namespace ts {
|
||||
currentChangedFilePath: Path | undefined;
|
||||
/**
|
||||
* Map of file signatures, with key being file path, calculated while getting current changed file's affected files
|
||||
* These will be commited whenever the iteration through affected files of current changed file is complete
|
||||
* These will be committed whenever the iteration through affected files of current changed file is complete
|
||||
*/
|
||||
currentAffectedFilesSignatures: Map<string> | undefined;
|
||||
/**
|
||||
@@ -49,7 +124,31 @@ namespace ts {
|
||||
/**
|
||||
* program corresponding to this state
|
||||
*/
|
||||
program: Program;
|
||||
program: Program | undefined;
|
||||
/**
|
||||
* compilerOptions for the program
|
||||
*/
|
||||
compilerOptions: CompilerOptions;
|
||||
/**
|
||||
* Files pending to be emitted
|
||||
*/
|
||||
affectedFilesPendingEmit: ReadonlyArray<Path> | undefined;
|
||||
/**
|
||||
* Current index to retrieve pending affected file
|
||||
*/
|
||||
affectedFilesPendingEmitIndex: number | undefined;
|
||||
/**
|
||||
* true if build info is emitted
|
||||
*/
|
||||
emittedBuildInfo?: boolean;
|
||||
/**
|
||||
* Already seen affected files
|
||||
*/
|
||||
seenEmittedFiles: Map<true> | undefined;
|
||||
/**
|
||||
* true if program has been emitted
|
||||
*/
|
||||
programEmitComplete?: true;
|
||||
}
|
||||
|
||||
function hasSameKeys<T, U>(map1: ReadonlyMap<T> | undefined, map2: ReadonlyMap<U> | undefined): boolean {
|
||||
@@ -60,10 +159,11 @@ namespace ts {
|
||||
/**
|
||||
* Create the state so that we can iterate on changedFiles/affected files
|
||||
*/
|
||||
function createBuilderProgramState(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState?: Readonly<BuilderProgramState>): BuilderProgramState {
|
||||
function createBuilderProgramState(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState?: Readonly<ReusableBuilderProgramState>): BuilderProgramState {
|
||||
const state = BuilderState.create(newProgram, getCanonicalFileName, oldState) as BuilderProgramState;
|
||||
state.program = newProgram;
|
||||
const compilerOptions = newProgram.getCompilerOptions();
|
||||
state.compilerOptions = compilerOptions;
|
||||
// With --out or --outFile, any change affects all semantic diagnostics so no need to cache them
|
||||
// With --isolatedModules, emitting changed file doesnt emit dependent files so we cant know of dependent files to retrieve errors so dont cache the errors
|
||||
if (!compilerOptions.outFile && !compilerOptions.out && !compilerOptions.isolatedModules) {
|
||||
@@ -72,7 +172,7 @@ namespace ts {
|
||||
state.changedFilesSet = createMap<true>();
|
||||
|
||||
const useOldState = BuilderState.canReuseOldState(state.referencedMap, oldState);
|
||||
const oldCompilerOptions = useOldState ? oldState!.program.getCompilerOptions() : undefined;
|
||||
const oldCompilerOptions = useOldState ? oldState!.compilerOptions : undefined;
|
||||
const canCopySemanticDiagnostics = useOldState && oldState!.semanticDiagnosticsPerFile && !!state.semanticDiagnosticsPerFile &&
|
||||
!compilerOptionsAffectSemanticDiagnostics(compilerOptions, oldCompilerOptions!);
|
||||
if (useOldState) {
|
||||
@@ -81,12 +181,19 @@ namespace ts {
|
||||
const affectedSignatures = oldState!.currentAffectedFilesSignatures;
|
||||
Debug.assert(!oldState!.affectedFiles && (!affectedSignatures || !affectedSignatures.size), "Cannot reuse if only few affected files of currentChangedFile were iterated");
|
||||
}
|
||||
const changedFilesSet = oldState!.changedFilesSet;
|
||||
if (canCopySemanticDiagnostics) {
|
||||
Debug.assert(!forEachKey(oldState!.changedFilesSet, path => oldState!.semanticDiagnosticsPerFile!.has(path)), "Semantic diagnostics shouldnt be available for changed files");
|
||||
Debug.assert(!changedFilesSet || !forEachKey(changedFilesSet, path => oldState!.semanticDiagnosticsPerFile!.has(path)), "Semantic diagnostics shouldnt be available for changed files");
|
||||
}
|
||||
|
||||
// Copy old state's changed files set
|
||||
copyEntries(oldState!.changedFilesSet, state.changedFilesSet);
|
||||
if (changedFilesSet) {
|
||||
copyEntries(changedFilesSet, state.changedFilesSet);
|
||||
}
|
||||
if (!compilerOptions.outFile && !compilerOptions.out && oldState!.affectedFilesPendingEmit) {
|
||||
state.affectedFilesPendingEmit = oldState!.affectedFilesPendingEmit;
|
||||
state.affectedFilesPendingEmitIndex = oldState!.affectedFilesPendingEmitIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// Update changed files and copy semantic diagnostics if we can
|
||||
@@ -112,7 +219,7 @@ namespace ts {
|
||||
state.changedFilesSet.set(sourceFilePath, true);
|
||||
}
|
||||
else if (canCopySemanticDiagnostics) {
|
||||
const sourceFile = state.program.getSourceFileByPath(sourceFilePath as Path)!;
|
||||
const sourceFile = newProgram.getSourceFileByPath(sourceFilePath as Path)!;
|
||||
|
||||
if (sourceFile.isDeclarationFile && !copyDeclarationFileDiagnostics) { return; }
|
||||
if (sourceFile.hasNoDefaultLib && !copyLibFileDiagnostics) { return; }
|
||||
@@ -120,7 +227,7 @@ namespace ts {
|
||||
// Unchanged file copy diagnostics
|
||||
const diagnostics = oldState!.semanticDiagnosticsPerFile!.get(sourceFilePath);
|
||||
if (diagnostics) {
|
||||
state.semanticDiagnosticsPerFile!.set(sourceFilePath, diagnostics);
|
||||
state.semanticDiagnosticsPerFile!.set(sourceFilePath, oldState!.hasReusableDiagnostic ? convertToDiagnostics(diagnostics as ReadonlyArray<ReusableDiagnostic>, newProgram) : diagnostics as ReadonlyArray<Diagnostic>);
|
||||
if (!state.semanticDiagnosticsFromOldState) {
|
||||
state.semanticDiagnosticsFromOldState = createMap<true>();
|
||||
}
|
||||
@@ -129,9 +236,88 @@ namespace ts {
|
||||
}
|
||||
});
|
||||
|
||||
if (oldCompilerOptions &&
|
||||
(oldCompilerOptions.outDir !== compilerOptions.outDir ||
|
||||
oldCompilerOptions.declarationDir !== compilerOptions.declarationDir ||
|
||||
(oldCompilerOptions.outFile || oldCompilerOptions.out) !== (compilerOptions.outFile || compilerOptions.out))) {
|
||||
// Add all files to affectedFilesPendingEmit since emit changed
|
||||
state.affectedFilesPendingEmit = concatenate(state.affectedFilesPendingEmit, newProgram.getSourceFiles().map(f => f.path));
|
||||
if (state.affectedFilesPendingEmitIndex === undefined) {
|
||||
state.affectedFilesPendingEmitIndex = 0;
|
||||
}
|
||||
Debug.assert(state.seenAffectedFiles === undefined);
|
||||
state.seenAffectedFiles = createMap<true>();
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function convertToDiagnostics(diagnostics: ReadonlyArray<ReusableDiagnostic>, newProgram: Program): ReadonlyArray<Diagnostic> {
|
||||
if (!diagnostics.length) return emptyArray;
|
||||
return diagnostics.map(diagnostic => {
|
||||
const result: Diagnostic = convertToDiagnosticRelatedInformation(diagnostic, newProgram);
|
||||
result.reportsUnnecessary = diagnostic.reportsUnnecessary;
|
||||
result.source = diagnostic.source;
|
||||
const { relatedInformation } = diagnostic;
|
||||
result.relatedInformation = relatedInformation ?
|
||||
relatedInformation.length ?
|
||||
relatedInformation.map(r => convertToDiagnosticRelatedInformation(r, newProgram)) :
|
||||
emptyArray :
|
||||
undefined;
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function convertToDiagnosticRelatedInformation(diagnostic: ReusableDiagnosticRelatedInformation, newProgram: Program): DiagnosticRelatedInformation {
|
||||
const { file, messageText } = diagnostic;
|
||||
return {
|
||||
...diagnostic,
|
||||
file: file && newProgram.getSourceFileByPath(file),
|
||||
messageText: messageText === undefined || isString(messageText) ?
|
||||
messageText :
|
||||
convertToDiagnosticMessageChain(messageText, newProgram)
|
||||
};
|
||||
}
|
||||
|
||||
function convertToDiagnosticMessageChain(diagnostic: ReusableDiagnosticMessageChain, newProgram: Program): DiagnosticMessageChain {
|
||||
return {
|
||||
...diagnostic,
|
||||
next: diagnostic.next && convertToDiagnosticMessageChain(diagnostic.next, newProgram)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases program and other related not needed properties
|
||||
*/
|
||||
function releaseCache(state: BuilderProgramState) {
|
||||
BuilderState.releaseCache(state);
|
||||
state.program = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a clone of the state
|
||||
*/
|
||||
function cloneBuilderProgramState(state: Readonly<BuilderProgramState>): BuilderProgramState {
|
||||
const newState = BuilderState.clone(state) as BuilderProgramState;
|
||||
newState.semanticDiagnosticsPerFile = cloneMapOrUndefined(state.semanticDiagnosticsPerFile);
|
||||
newState.changedFilesSet = cloneMap(state.changedFilesSet);
|
||||
newState.affectedFiles = state.affectedFiles;
|
||||
newState.affectedFilesIndex = state.affectedFilesIndex;
|
||||
newState.currentChangedFilePath = state.currentChangedFilePath;
|
||||
newState.currentAffectedFilesSignatures = cloneMapOrUndefined(state.currentAffectedFilesSignatures);
|
||||
newState.currentAffectedFilesExportedModulesMap = cloneMapOrUndefined(state.currentAffectedFilesExportedModulesMap);
|
||||
newState.seenAffectedFiles = cloneMapOrUndefined(state.seenAffectedFiles);
|
||||
newState.cleanedDiagnosticsOfLibFiles = state.cleanedDiagnosticsOfLibFiles;
|
||||
newState.semanticDiagnosticsFromOldState = cloneMapOrUndefined(state.semanticDiagnosticsFromOldState);
|
||||
newState.program = state.program;
|
||||
newState.compilerOptions = state.compilerOptions;
|
||||
newState.affectedFilesPendingEmit = state.affectedFilesPendingEmit;
|
||||
newState.affectedFilesPendingEmitIndex = state.affectedFilesPendingEmitIndex;
|
||||
newState.seenEmittedFiles = cloneMapOrUndefined(state.seenEmittedFiles);
|
||||
newState.programEmitComplete = state.programEmitComplete;
|
||||
return newState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that source file is ok to be used in calls that arent handled by next
|
||||
*/
|
||||
@@ -182,10 +368,11 @@ namespace ts {
|
||||
|
||||
// With --out or --outFile all outputs go into single file
|
||||
// so operations are performed directly on program, return program
|
||||
const compilerOptions = state.program.getCompilerOptions();
|
||||
const program = Debug.assertDefined(state.program);
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
if (compilerOptions.outFile || compilerOptions.out) {
|
||||
Debug.assert(!state.semanticDiagnosticsPerFile);
|
||||
return state.program;
|
||||
return program;
|
||||
}
|
||||
|
||||
// Get next batch of affected files
|
||||
@@ -193,13 +380,34 @@ namespace ts {
|
||||
if (state.exportedModulesMap) {
|
||||
state.currentAffectedFilesExportedModulesMap = state.currentAffectedFilesExportedModulesMap || createMap<BuilderState.ReferencedSet | false>();
|
||||
}
|
||||
state.affectedFiles = BuilderState.getFilesAffectedBy(state, state.program, nextKey.value as Path, cancellationToken, computeHash, state.currentAffectedFilesSignatures, state.currentAffectedFilesExportedModulesMap);
|
||||
state.affectedFiles = BuilderState.getFilesAffectedBy(state, program, nextKey.value as Path, cancellationToken, computeHash, state.currentAffectedFilesSignatures, state.currentAffectedFilesExportedModulesMap);
|
||||
state.currentChangedFilePath = nextKey.value as Path;
|
||||
state.affectedFilesIndex = 0;
|
||||
state.seenAffectedFiles = state.seenAffectedFiles || createMap<true>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next file to be emitted from files that retrieved semantic diagnostics but did not emit yet
|
||||
*/
|
||||
function getNextAffectedFilePendingEmit(state: BuilderProgramState): SourceFile | undefined {
|
||||
const { affectedFilesPendingEmit } = state;
|
||||
if (affectedFilesPendingEmit) {
|
||||
const seenEmittedFiles = state.seenEmittedFiles || (state.seenEmittedFiles = createMap());
|
||||
for (let i = state.affectedFilesPendingEmitIndex!; i < affectedFilesPendingEmit.length; i++) {
|
||||
const affectedFile = Debug.assertDefined(state.program).getSourceFileByPath(affectedFilesPendingEmit[i]);
|
||||
if (affectedFile && !seenEmittedFiles.has(affectedFile.path)) {
|
||||
// emit this file
|
||||
state.affectedFilesPendingEmitIndex = i;
|
||||
return affectedFile;
|
||||
}
|
||||
}
|
||||
state.affectedFilesPendingEmit = undefined;
|
||||
state.affectedFilesPendingEmitIndex = undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the semantic diagnostics cached from old state for affected File and the files that are referencing modules that export entities from affected file
|
||||
*/
|
||||
@@ -212,9 +420,10 @@ namespace ts {
|
||||
// Clean lib file diagnostics if its all files excluding default files to emit
|
||||
if (state.allFilesExcludingDefaultLibraryFile === state.affectedFiles && !state.cleanedDiagnosticsOfLibFiles) {
|
||||
state.cleanedDiagnosticsOfLibFiles = true;
|
||||
const options = state.program.getCompilerOptions();
|
||||
if (forEach(state.program.getSourceFiles(), f =>
|
||||
state.program.isSourceFileDefaultLibrary(f) &&
|
||||
const program = Debug.assertDefined(state.program);
|
||||
const options = program.getCompilerOptions();
|
||||
if (forEach(program.getSourceFiles(), f =>
|
||||
program.isSourceFileDefaultLibrary(f) &&
|
||||
!skipTypeChecking(f, options) &&
|
||||
removeSemanticDiagnosticsOf(state, f.path)
|
||||
)) {
|
||||
@@ -317,21 +526,30 @@ namespace ts {
|
||||
* This is called after completing operation on the next affected file.
|
||||
* The operations here are postponed to ensure that cancellation during the iteration is handled correctly
|
||||
*/
|
||||
function doneWithAffectedFile(state: BuilderProgramState, affected: SourceFile | Program) {
|
||||
if (affected === state.program) {
|
||||
function doneWithAffectedFile(state: BuilderProgramState, affected: SourceFile | Program, isPendingEmit?: boolean, isBuildInfoEmit?: boolean) {
|
||||
if (isBuildInfoEmit) {
|
||||
state.emittedBuildInfo = true;
|
||||
}
|
||||
else if (affected === state.program) {
|
||||
state.changedFilesSet.clear();
|
||||
state.programEmitComplete = true;
|
||||
}
|
||||
else {
|
||||
state.seenAffectedFiles!.set((affected as SourceFile).path, true);
|
||||
state.affectedFilesIndex!++;
|
||||
if (isPendingEmit) {
|
||||
state.affectedFilesPendingEmitIndex!++;
|
||||
}
|
||||
else {
|
||||
state.affectedFilesIndex!++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result with affected file
|
||||
*/
|
||||
function toAffectedFileResult<T>(state: BuilderProgramState, result: T, affected: SourceFile | Program): AffectedFileResult<T> {
|
||||
doneWithAffectedFile(state, affected);
|
||||
function toAffectedFileResult<T>(state: BuilderProgramState, result: T, affected: SourceFile | Program, isPendingEmit?: boolean, isBuildInfoEmit?: boolean): AffectedFileResult<T> {
|
||||
doneWithAffectedFile(state, affected, isPendingEmit, isBuildInfoEmit);
|
||||
return { result, affected };
|
||||
}
|
||||
|
||||
@@ -350,13 +568,107 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Diagnostics werent cached, get them from program, and cache the result
|
||||
const diagnostics = state.program.getSemanticDiagnostics(sourceFile, cancellationToken);
|
||||
const diagnostics = Debug.assertDefined(state.program).getSemanticDiagnostics(sourceFile, cancellationToken);
|
||||
if (state.semanticDiagnosticsPerFile) {
|
||||
state.semanticDiagnosticsPerFile.set(path, diagnostics);
|
||||
}
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
export type ProgramBuildInfoDiagnostic = string | [string, ReadonlyArray<ReusableDiagnostic>];
|
||||
export interface ProgramBuildInfo {
|
||||
fileInfos: MapLike<BuilderState.FileInfo>;
|
||||
options: CompilerOptions;
|
||||
referencedMap?: MapLike<string[]>;
|
||||
exportedModulesMap?: MapLike<string[]>;
|
||||
semanticDiagnosticsPerFile?: ProgramBuildInfoDiagnostic[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the program information to be emitted in buildInfo so that we can use it to create new program
|
||||
*/
|
||||
function getProgramBuildInfo(state: Readonly<ReusableBuilderProgramState>): ProgramBuildInfo | undefined {
|
||||
if (state.compilerOptions.outFile || state.compilerOptions.out) return undefined;
|
||||
const fileInfos: MapLike<BuilderState.FileInfo> = {};
|
||||
state.fileInfos.forEach((value, key) => {
|
||||
const signature = state.currentAffectedFilesSignatures && state.currentAffectedFilesSignatures.get(key);
|
||||
fileInfos[key] = signature === undefined ? value : { version: value.version, signature };
|
||||
});
|
||||
|
||||
const result: ProgramBuildInfo = { fileInfos, options: state.compilerOptions };
|
||||
if (state.referencedMap) {
|
||||
const referencedMap: MapLike<string[]> = {};
|
||||
state.referencedMap.forEach((value, key) => {
|
||||
referencedMap[key] = arrayFrom(value.keys());
|
||||
});
|
||||
result.referencedMap = referencedMap;
|
||||
}
|
||||
|
||||
if (state.exportedModulesMap) {
|
||||
const exportedModulesMap: MapLike<string[]> = {};
|
||||
state.exportedModulesMap.forEach((value, key) => {
|
||||
const newValue = state.currentAffectedFilesExportedModulesMap && state.currentAffectedFilesExportedModulesMap.get(key);
|
||||
// Not in temporary cache, use existing value
|
||||
if (newValue === undefined) exportedModulesMap[key] = arrayFrom(value.keys());
|
||||
// Value in cache and has updated value map, use that
|
||||
else if (newValue) exportedModulesMap[key] = arrayFrom(newValue.keys());
|
||||
});
|
||||
result.exportedModulesMap = exportedModulesMap;
|
||||
}
|
||||
|
||||
if (state.semanticDiagnosticsPerFile) {
|
||||
const semanticDiagnosticsPerFile: ProgramBuildInfoDiagnostic[] = [];
|
||||
// Currently not recording actual errors since those mean no emit for tsc --build
|
||||
state.semanticDiagnosticsPerFile.forEach((value, key) => semanticDiagnosticsPerFile.push(
|
||||
value.length ?
|
||||
[
|
||||
key,
|
||||
state.hasReusableDiagnostic ?
|
||||
value as ReadonlyArray<ReusableDiagnostic> :
|
||||
convertToReusableDiagnostics(value as ReadonlyArray<Diagnostic>)
|
||||
] :
|
||||
key
|
||||
));
|
||||
result.semanticDiagnosticsPerFile = semanticDiagnosticsPerFile;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertToReusableDiagnostics(diagnostics: ReadonlyArray<Diagnostic>): ReadonlyArray<ReusableDiagnostic> {
|
||||
Debug.assert(!!diagnostics.length);
|
||||
return diagnostics.map(diagnostic => {
|
||||
const result: ReusableDiagnostic = convertToReusableDiagnosticRelatedInformation(diagnostic);
|
||||
result.reportsUnnecessary = diagnostic.reportsUnnecessary;
|
||||
result.source = diagnostic.source;
|
||||
const { relatedInformation } = diagnostic;
|
||||
result.relatedInformation = relatedInformation ?
|
||||
relatedInformation.length ?
|
||||
relatedInformation.map(r => convertToReusableDiagnosticRelatedInformation(r)) :
|
||||
emptyArray :
|
||||
undefined;
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function convertToReusableDiagnosticRelatedInformation(diagnostic: DiagnosticRelatedInformation): ReusableDiagnosticRelatedInformation {
|
||||
const { file, messageText } = diagnostic;
|
||||
return {
|
||||
...diagnostic,
|
||||
file: file && file.path,
|
||||
messageText: messageText === undefined || isString(messageText) ?
|
||||
messageText :
|
||||
convertToReusableDiagnosticMessageChain(messageText)
|
||||
};
|
||||
}
|
||||
|
||||
function convertToReusableDiagnosticMessageChain(diagnostic: DiagnosticMessageChain): ReusableDiagnosticMessageChain {
|
||||
return {
|
||||
...diagnostic,
|
||||
next: diagnostic.next && convertToReusableDiagnosticMessageChain(diagnostic.next)
|
||||
};
|
||||
}
|
||||
|
||||
export enum BuilderProgramKind {
|
||||
SemanticDiagnosticsBuilderProgram,
|
||||
EmitAndSemanticDiagnosticsBuilderProgram
|
||||
@@ -386,7 +698,7 @@ namespace ts {
|
||||
rootNames: newProgramOrRootNames,
|
||||
options: hostOrOptions as CompilerOptions,
|
||||
host: oldProgramOrHost as CompilerHost,
|
||||
oldProgram: oldProgram && oldProgram.getProgram(),
|
||||
oldProgram: oldProgram && oldProgram.getProgramOrUndefined(),
|
||||
configFileParsingDiagnostics,
|
||||
projectReferences
|
||||
});
|
||||
@@ -419,28 +731,32 @@ namespace ts {
|
||||
/**
|
||||
* Computing hash to for signature verification
|
||||
*/
|
||||
const computeHash = host.createHash || identity;
|
||||
const state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState);
|
||||
const computeHash = host.createHash || generateDjb2Hash;
|
||||
let state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState);
|
||||
let backupState: BuilderProgramState | undefined;
|
||||
newProgram.getProgramBuildInfo = () => getProgramBuildInfo(state);
|
||||
|
||||
// To ensure that we arent storing any references to old program or new program without state
|
||||
newProgram = undefined!; // TODO: GH#18217
|
||||
oldProgram = undefined;
|
||||
oldState = undefined;
|
||||
|
||||
const result: BuilderProgram = {
|
||||
getState: () => state,
|
||||
getProgram: () => state.program,
|
||||
getCompilerOptions: () => state.program.getCompilerOptions(),
|
||||
getSourceFile: fileName => state.program.getSourceFile(fileName),
|
||||
getSourceFiles: () => state.program.getSourceFiles(),
|
||||
getOptionsDiagnostics: cancellationToken => state.program.getOptionsDiagnostics(cancellationToken),
|
||||
getGlobalDiagnostics: cancellationToken => state.program.getGlobalDiagnostics(cancellationToken),
|
||||
getConfigFileParsingDiagnostics: () => configFileParsingDiagnostics || state.program.getConfigFileParsingDiagnostics(),
|
||||
getSyntacticDiagnostics: (sourceFile, cancellationToken) => state.program.getSyntacticDiagnostics(sourceFile, cancellationToken),
|
||||
getSemanticDiagnostics,
|
||||
emit,
|
||||
getAllDependencies: sourceFile => BuilderState.getAllDependencies(state, state.program, sourceFile),
|
||||
getCurrentDirectory: () => state.program.getCurrentDirectory()
|
||||
const result = createRedirectedBuilderProgram(state, configFileParsingDiagnostics);
|
||||
result.getState = () => state;
|
||||
result.backupState = () => {
|
||||
Debug.assert(backupState === undefined);
|
||||
backupState = cloneBuilderProgramState(state);
|
||||
};
|
||||
result.restoreState = () => {
|
||||
state = Debug.assertDefined(backupState);
|
||||
backupState = undefined;
|
||||
};
|
||||
result.getAllDependencies = sourceFile => BuilderState.getAllDependencies(state, Debug.assertDefined(state.program), sourceFile);
|
||||
result.getSemanticDiagnostics = getSemanticDiagnostics;
|
||||
result.emit = emit;
|
||||
result.releaseProgram = () => {
|
||||
releaseCache(state);
|
||||
backupState = undefined;
|
||||
};
|
||||
|
||||
if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) {
|
||||
@@ -461,18 +777,52 @@ namespace ts {
|
||||
* in that order would be used to write the files
|
||||
*/
|
||||
function emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult<EmitResult> {
|
||||
const affected = getNextAffectedFile(state, cancellationToken, computeHash);
|
||||
let affected = getNextAffectedFile(state, cancellationToken, computeHash);
|
||||
let isPendingEmitFile = false;
|
||||
if (!affected) {
|
||||
// Done
|
||||
return undefined;
|
||||
if (!state.compilerOptions.out && !state.compilerOptions.outFile) {
|
||||
affected = getNextAffectedFilePendingEmit(state);
|
||||
if (!affected) {
|
||||
if (state.emittedBuildInfo) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const affected = Debug.assertDefined(state.program);
|
||||
return toAffectedFileResult(
|
||||
state,
|
||||
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
|
||||
// Otherwise just affected file
|
||||
affected.emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken),
|
||||
affected,
|
||||
/*isPendingEmitFile*/ false,
|
||||
/*isBuildInfoEmit*/ true
|
||||
);
|
||||
}
|
||||
isPendingEmitFile = true;
|
||||
}
|
||||
else {
|
||||
const program = Debug.assertDefined(state.program);
|
||||
// Check if program uses any prepend project references, if thats the case we cant track of the js files of those, so emit even though there are no changes
|
||||
if (state.programEmitComplete || !some(program.getProjectReferences(), ref => !!ref.prepend)) {
|
||||
state.programEmitComplete = true;
|
||||
return undefined;
|
||||
}
|
||||
affected = program;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark seen emitted files if there are pending files to be emitted
|
||||
if (state.affectedFilesPendingEmit && state.program !== affected) {
|
||||
(state.seenEmittedFiles || (state.seenEmittedFiles = createMap())).set((affected as SourceFile).path, true);
|
||||
}
|
||||
|
||||
return toAffectedFileResult(
|
||||
state,
|
||||
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
|
||||
// Otherwise just affected file
|
||||
state.program.emit(affected === state.program ? undefined : affected as SourceFile, writeFile || host.writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers),
|
||||
affected
|
||||
Debug.assertDefined(state.program).emit(affected === state.program ? undefined : affected as SourceFile, writeFile || maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers),
|
||||
affected,
|
||||
isPendingEmitFile
|
||||
);
|
||||
}
|
||||
|
||||
@@ -512,7 +862,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
}
|
||||
return state.program.emit(targetSourceFile, writeFile || host.writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
|
||||
return Debug.assertDefined(state.program).emit(targetSourceFile, writeFile || maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,33 +910,121 @@ namespace ts {
|
||||
*/
|
||||
function getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic> {
|
||||
assertSourceFileOkWithoutNextAffectedCall(state, sourceFile);
|
||||
const compilerOptions = state.program.getCompilerOptions();
|
||||
const compilerOptions = Debug.assertDefined(state.program).getCompilerOptions();
|
||||
if (compilerOptions.outFile || compilerOptions.out) {
|
||||
Debug.assert(!state.semanticDiagnosticsPerFile);
|
||||
// We dont need to cache the diagnostics just return them from program
|
||||
return state.program.getSemanticDiagnostics(sourceFile, cancellationToken);
|
||||
return Debug.assertDefined(state.program).getSemanticDiagnostics(sourceFile, cancellationToken);
|
||||
}
|
||||
|
||||
if (sourceFile) {
|
||||
return getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken);
|
||||
}
|
||||
|
||||
if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) {
|
||||
// When semantic builder asks for diagnostics of the whole program,
|
||||
// ensure that all the affected files are handled
|
||||
let affected: SourceFile | Program | undefined;
|
||||
while (affected = getNextAffectedFile(state, cancellationToken, computeHash)) {
|
||||
doneWithAffectedFile(state, affected);
|
||||
// When semantic builder asks for diagnostics of the whole program,
|
||||
// ensure that all the affected files are handled
|
||||
let affected: SourceFile | Program | undefined;
|
||||
let affectedFilesPendingEmit: Path[] | undefined;
|
||||
while (affected = getNextAffectedFile(state, cancellationToken, computeHash)) {
|
||||
if (affected !== state.program && kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) {
|
||||
(affectedFilesPendingEmit || (affectedFilesPendingEmit = [])).push((affected as SourceFile).path);
|
||||
}
|
||||
doneWithAffectedFile(state, affected);
|
||||
}
|
||||
|
||||
// In case of emit builder, cache the files to be emitted
|
||||
if (affectedFilesPendingEmit) {
|
||||
state.affectedFilesPendingEmit = concatenate(state.affectedFilesPendingEmit, affectedFilesPendingEmit);
|
||||
// affectedFilesPendingEmitIndex === undefined
|
||||
// - means the emit state.affectedFilesPendingEmit was undefined before adding current affected files
|
||||
// so start from 0 as array would be affectedFilesPendingEmit
|
||||
// else, continue to iterate from existing index, the current set is appended to existing files
|
||||
if (state.affectedFilesPendingEmitIndex === undefined) {
|
||||
state.affectedFilesPendingEmitIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
let diagnostics: Diagnostic[] | undefined;
|
||||
for (const sourceFile of state.program.getSourceFiles()) {
|
||||
for (const sourceFile of Debug.assertDefined(state.program).getSourceFiles()) {
|
||||
diagnostics = addRange(diagnostics, getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken));
|
||||
}
|
||||
return diagnostics || emptyArray;
|
||||
}
|
||||
}
|
||||
|
||||
function getMapOfReferencedSet(mapLike: MapLike<ReadonlyArray<string>> | undefined): ReadonlyMap<BuilderState.ReferencedSet> | undefined {
|
||||
if (!mapLike) return undefined;
|
||||
const map = createMap<BuilderState.ReferencedSet>();
|
||||
// Copies keys/values from template. Note that for..in will not throw if
|
||||
// template is undefined, and instead will just exit the loop.
|
||||
for (const key in mapLike) {
|
||||
if (hasProperty(mapLike, key)) {
|
||||
map.set(key, arrayToSet(mapLike[key]));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
export function createBuildProgramUsingProgramBuildInfo(program: ProgramBuildInfo): EmitAndSemanticDiagnosticsBuilderProgram & SemanticDiagnosticsBuilderProgram {
|
||||
const fileInfos = createMapFromTemplate(program.fileInfos);
|
||||
const state: ReusableBuilderProgramState = {
|
||||
fileInfos,
|
||||
compilerOptions: program.options,
|
||||
referencedMap: getMapOfReferencedSet(program.referencedMap),
|
||||
exportedModulesMap: getMapOfReferencedSet(program.exportedModulesMap),
|
||||
semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile && arrayToMap(program.semanticDiagnosticsPerFile, value => isString(value) ? value : value[0], value => isString(value) ? emptyArray : value[1]),
|
||||
hasReusableDiagnostic: true
|
||||
};
|
||||
return {
|
||||
getState: () => state,
|
||||
backupState: noop,
|
||||
restoreState: noop,
|
||||
getProgram: notImplemented,
|
||||
getProgramOrUndefined: returnUndefined,
|
||||
releaseProgram: noop,
|
||||
getCompilerOptions: () => state.compilerOptions,
|
||||
getSourceFile: notImplemented,
|
||||
getSourceFiles: notImplemented,
|
||||
getOptionsDiagnostics: notImplemented,
|
||||
getGlobalDiagnostics: notImplemented,
|
||||
getConfigFileParsingDiagnostics: notImplemented,
|
||||
getSyntacticDiagnostics: notImplemented,
|
||||
getDeclarationDiagnostics: notImplemented,
|
||||
getSemanticDiagnostics: notImplemented,
|
||||
emit: notImplemented,
|
||||
getAllDependencies: notImplemented,
|
||||
getCurrentDirectory: notImplemented,
|
||||
emitNextAffectedFile: notImplemented,
|
||||
getSemanticDiagnosticsOfNextAffectedFile: notImplemented,
|
||||
};
|
||||
}
|
||||
|
||||
export function createRedirectedBuilderProgram(state: { program: Program | undefined; compilerOptions: CompilerOptions; }, configFileParsingDiagnostics: ReadonlyArray<Diagnostic>): BuilderProgram {
|
||||
return {
|
||||
getState: notImplemented,
|
||||
backupState: noop,
|
||||
restoreState: noop,
|
||||
getProgram,
|
||||
getProgramOrUndefined: () => state.program,
|
||||
releaseProgram: () => state.program = undefined,
|
||||
getCompilerOptions: () => state.compilerOptions,
|
||||
getSourceFile: fileName => getProgram().getSourceFile(fileName),
|
||||
getSourceFiles: () => getProgram().getSourceFiles(),
|
||||
getOptionsDiagnostics: cancellationToken => getProgram().getOptionsDiagnostics(cancellationToken),
|
||||
getGlobalDiagnostics: cancellationToken => getProgram().getGlobalDiagnostics(cancellationToken),
|
||||
getConfigFileParsingDiagnostics: () => configFileParsingDiagnostics,
|
||||
getSyntacticDiagnostics: (sourceFile, cancellationToken) => getProgram().getSyntacticDiagnostics(sourceFile, cancellationToken),
|
||||
getDeclarationDiagnostics: (sourceFile, cancellationToken) => getProgram().getDeclarationDiagnostics(sourceFile, cancellationToken),
|
||||
getSemanticDiagnostics: (sourceFile, cancellationToken) => getProgram().getSemanticDiagnostics(sourceFile, cancellationToken),
|
||||
emit: (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) => getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers),
|
||||
getAllDependencies: notImplemented,
|
||||
getCurrentDirectory: () => getProgram().getCurrentDirectory(),
|
||||
};
|
||||
|
||||
function getProgram() {
|
||||
return Debug.assertDefined(state.program);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace ts {
|
||||
@@ -613,11 +1051,25 @@ namespace ts {
|
||||
*/
|
||||
export interface BuilderProgram {
|
||||
/*@internal*/
|
||||
getState(): BuilderProgramState;
|
||||
getState(): ReusableBuilderProgramState;
|
||||
/*@internal*/
|
||||
backupState(): void;
|
||||
/*@internal*/
|
||||
restoreState(): void;
|
||||
/**
|
||||
* Returns current program
|
||||
*/
|
||||
getProgram(): Program;
|
||||
/**
|
||||
* Returns current program that could be undefined if the program was released
|
||||
*/
|
||||
/*@internal*/
|
||||
getProgramOrUndefined(): Program | undefined;
|
||||
/**
|
||||
* Releases reference to the program, making all the other operations that need program to fail.
|
||||
*/
|
||||
/*@internal*/
|
||||
releaseProgram(): void;
|
||||
/**
|
||||
* Get compiler options of the program
|
||||
*/
|
||||
@@ -646,10 +1098,15 @@ namespace ts {
|
||||
* Get the syntax diagnostics, for all source files if source file is not supplied
|
||||
*/
|
||||
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
/**
|
||||
* Get the declaration diagnostics, for all source files if source file is not supplied
|
||||
*/
|
||||
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<DiagnosticWithLocation>;
|
||||
/**
|
||||
* Get all the dependencies of the file
|
||||
*/
|
||||
getAllDependencies(sourceFile: SourceFile): ReadonlyArray<string>;
|
||||
|
||||
/**
|
||||
* Gets the semantic diagnostics from the program corresponding to this state of file (if provided) or whole program
|
||||
* The semantic diagnostics are cached and managed here
|
||||
@@ -726,22 +1183,7 @@ namespace ts {
|
||||
export function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): BuilderProgram;
|
||||
export function createAbstractBuilder(rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): BuilderProgram;
|
||||
export function createAbstractBuilder(newProgramOrRootNames: Program | ReadonlyArray<string> | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | BuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray<Diagnostic> | BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference>): BuilderProgram {
|
||||
const { newProgram: program } = getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences);
|
||||
return {
|
||||
// Only return program, all other methods are not implemented
|
||||
getProgram: () => program,
|
||||
getState: notImplemented,
|
||||
getCompilerOptions: notImplemented,
|
||||
getSourceFile: notImplemented,
|
||||
getSourceFiles: notImplemented,
|
||||
getOptionsDiagnostics: notImplemented,
|
||||
getGlobalDiagnostics: notImplemented,
|
||||
getConfigFileParsingDiagnostics: notImplemented,
|
||||
getSyntacticDiagnostics: notImplemented,
|
||||
getSemanticDiagnostics: notImplemented,
|
||||
emit: notImplemented,
|
||||
getAllDependencies: notImplemented,
|
||||
getCurrentDirectory: notImplemented
|
||||
};
|
||||
const { newProgram, configFileParsingDiagnostics: newConfigFileParsingDiagnostics } = getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences);
|
||||
return createRedirectedBuilderProgram({ program: newProgram, compilerOptions: newProgram.getCompilerOptions() }, newConfigFileParsingDiagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,24 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export interface ReusableBuilderState {
|
||||
/**
|
||||
* Information of the file eg. its version, signature etc
|
||||
*/
|
||||
fileInfos: ReadonlyMap<BuilderState.FileInfo>;
|
||||
/**
|
||||
* Contains the map of ReferencedSet=Referenced files of the file if module emit is enabled
|
||||
* Otherwise undefined
|
||||
* Thus non undefined value indicates, module emit
|
||||
*/
|
||||
readonly referencedMap?: ReadonlyMap<BuilderState.ReferencedSet> | undefined;
|
||||
/**
|
||||
* Contains the map of exported modules ReferencedSet=exported module files from the file if module emit is enabled
|
||||
* Otherwise undefined
|
||||
*/
|
||||
readonly exportedModulesMap?: ReadonlyMap<BuilderState.ReferencedSet> | undefined;
|
||||
}
|
||||
|
||||
export interface BuilderState {
|
||||
/**
|
||||
* Information of the file eg. its version, signature etc
|
||||
@@ -37,7 +55,7 @@ namespace ts {
|
||||
*/
|
||||
readonly referencedMap: ReadonlyMap<BuilderState.ReferencedSet> | undefined;
|
||||
/**
|
||||
* Contains the map of exported modules ReferencedSet=exorted module files from the file if module emit is enabled
|
||||
* Contains the map of exported modules ReferencedSet=exported module files from the file if module emit is enabled
|
||||
* Otherwise undefined
|
||||
*/
|
||||
readonly exportedModulesMap: Map<BuilderState.ReferencedSet> | undefined;
|
||||
@@ -50,11 +68,15 @@ namespace ts {
|
||||
/**
|
||||
* Cache of all files excluding default library file for the current program
|
||||
*/
|
||||
allFilesExcludingDefaultLibraryFile: ReadonlyArray<SourceFile> | undefined;
|
||||
allFilesExcludingDefaultLibraryFile?: ReadonlyArray<SourceFile>;
|
||||
/**
|
||||
* Cache of all the file names
|
||||
*/
|
||||
allFileNames: ReadonlyArray<string> | undefined;
|
||||
allFileNames?: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
export function cloneMapOrUndefined<T>(map: ReadonlyMap<T> | undefined) {
|
||||
return map ? cloneMap(map) : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,14 +214,14 @@ namespace ts.BuilderState {
|
||||
/**
|
||||
* Returns true if oldState is reusable, that is the emitKind = module/non module has not changed
|
||||
*/
|
||||
export function canReuseOldState(newReferencedMap: ReadonlyMap<ReferencedSet> | undefined, oldState: Readonly<BuilderState> | undefined) {
|
||||
export function canReuseOldState(newReferencedMap: ReadonlyMap<ReferencedSet> | undefined, oldState: Readonly<ReusableBuilderState> | undefined) {
|
||||
return oldState && !oldState.referencedMap === !newReferencedMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the state of file references and signature for the new program from oldState if it is safe
|
||||
*/
|
||||
export function create(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState?: Readonly<BuilderState>): BuilderState {
|
||||
export function create(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState?: Readonly<ReusableBuilderState>): BuilderState {
|
||||
const fileInfos = createMap<FileInfo>();
|
||||
const referencedMap = newProgram.getCompilerOptions().module !== ModuleKind.None ? createMap<ReferencedSet>() : undefined;
|
||||
const exportedModulesMap = referencedMap ? createMap<ReferencedSet>() : undefined;
|
||||
@@ -208,7 +230,7 @@ namespace ts.BuilderState {
|
||||
|
||||
// Create the reference map, and set the file infos
|
||||
for (const sourceFile of newProgram.getSourceFiles()) {
|
||||
const version = sourceFile.version;
|
||||
const version = Debug.assertDefined(sourceFile.version, "Program intended to be used with Builder should have source files with versions set");
|
||||
const oldInfo = useOldState ? oldState!.fileInfos.get(sourceFile.path) : undefined;
|
||||
if (referencedMap) {
|
||||
const newReferences = getReferencedFiles(newProgram, sourceFile, getCanonicalFileName);
|
||||
@@ -230,9 +252,32 @@ namespace ts.BuilderState {
|
||||
fileInfos,
|
||||
referencedMap,
|
||||
exportedModulesMap,
|
||||
hasCalledUpdateShapeSignature,
|
||||
allFilesExcludingDefaultLibraryFile: undefined,
|
||||
allFileNames: undefined
|
||||
hasCalledUpdateShapeSignature
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases needed properties
|
||||
*/
|
||||
export function releaseCache(state: BuilderState) {
|
||||
state.allFilesExcludingDefaultLibraryFile = undefined;
|
||||
state.allFileNames = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a clone of the state
|
||||
*/
|
||||
export function clone(state: Readonly<BuilderState>): BuilderState {
|
||||
const fileInfos = createMap<FileInfo>();
|
||||
state.fileInfos.forEach((value, key) => {
|
||||
fileInfos.set(key, { ...value });
|
||||
});
|
||||
// Dont need to backup allFiles info since its cache anyway
|
||||
return {
|
||||
fileInfos,
|
||||
referencedMap: cloneMapOrUndefined(state.referencedMap),
|
||||
exportedModulesMap: cloneMapOrUndefined(state.exportedModulesMap),
|
||||
hasCalledUpdateShapeSignature: cloneMap(state.hasCalledUpdateShapeSignature),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -241,9 +286,9 @@ namespace ts.BuilderState {
|
||||
*/
|
||||
export function getFilesAffectedBy(state: BuilderState, programOfThisState: Program, path: Path, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, cacheToUpdateSignature?: Map<string>, exportedModulesMapCache?: ComputingExportedModulesMap): ReadonlyArray<SourceFile> {
|
||||
// Since the operation could be cancelled, the signatures are always stored in the cache
|
||||
// They will be commited once it is safe to use them
|
||||
// They will be committed once it is safe to use them
|
||||
// eg when calling this api from tsserver, if there is no cancellation of the operation
|
||||
// In the other cases the affected files signatures are commited only after the iteration through the result is complete
|
||||
// In the other cases the affected files signatures are committed only after the iteration through the result is complete
|
||||
const signatureCache = cacheToUpdateSignature || createMap();
|
||||
const sourceFile = programOfThisState.getSourceFileByPath(path);
|
||||
if (!sourceFile) {
|
||||
@@ -505,14 +550,14 @@ namespace ts.BuilderState {
|
||||
|
||||
// Start with the paths this file was referenced by
|
||||
seenFileNamesMap.set(sourceFileWithUpdatedShape.path, sourceFileWithUpdatedShape);
|
||||
const queue = getReferencedByPaths(state, sourceFileWithUpdatedShape.path);
|
||||
const queue = getReferencedByPaths(state, sourceFileWithUpdatedShape.resolvedPath);
|
||||
while (queue.length > 0) {
|
||||
const currentPath = queue.pop()!;
|
||||
if (!seenFileNamesMap.has(currentPath)) {
|
||||
const currentSourceFile = programOfThisState.getSourceFileByPath(currentPath)!;
|
||||
seenFileNamesMap.set(currentPath, currentSourceFile);
|
||||
if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash!, exportedModulesMapCache)) { // TODO: GH#18217
|
||||
queue.push(...getReferencedByPaths(state, currentPath));
|
||||
queue.push(...getReferencedByPaths(state, currentSourceFile.resolvedPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1627
-887
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,7 @@ namespace ts {
|
||||
["es2016", "lib.es2016.d.ts"],
|
||||
["es2017", "lib.es2017.d.ts"],
|
||||
["es2018", "lib.es2018.d.ts"],
|
||||
["es2019", "lib.es2019.d.ts"],
|
||||
["esnext", "lib.esnext.d.ts"],
|
||||
// Host only
|
||||
["dom", "lib.dom.d.ts"],
|
||||
@@ -38,12 +39,16 @@ namespace ts {
|
||||
["es2017.string", "lib.es2017.string.d.ts"],
|
||||
["es2017.intl", "lib.es2017.intl.d.ts"],
|
||||
["es2017.typedarrays", "lib.es2017.typedarrays.d.ts"],
|
||||
["es2018.asynciterable", "lib.es2018.asynciterable.d.ts"],
|
||||
["es2018.intl", "lib.es2018.intl.d.ts"],
|
||||
["es2018.promise", "lib.es2018.promise.d.ts"],
|
||||
["es2018.regexp", "lib.es2018.regexp.d.ts"],
|
||||
["esnext.array", "lib.esnext.array.d.ts"],
|
||||
["esnext.symbol", "lib.esnext.symbol.d.ts"],
|
||||
["esnext.asynciterable", "lib.esnext.asynciterable.d.ts"],
|
||||
["es2019.array", "lib.es2019.array.d.ts"],
|
||||
["es2019.string", "lib.es2019.string.d.ts"],
|
||||
["es2019.symbol", "lib.es2019.symbol.d.ts"],
|
||||
["esnext.array", "lib.es2019.array.d.ts"],
|
||||
["esnext.symbol", "lib.es2019.symbol.d.ts"],
|
||||
["esnext.asynciterable", "lib.es2018.asynciterable.d.ts"],
|
||||
["esnext.intl", "lib.esnext.intl.d.ts"],
|
||||
["esnext.bigint", "lib.esnext.bigint.d.ts"]
|
||||
];
|
||||
@@ -131,6 +136,13 @@ namespace ts {
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.Show_verbose_diagnostic_information
|
||||
},
|
||||
{
|
||||
name: "incremental",
|
||||
shortName: "i",
|
||||
type: "boolean",
|
||||
category: Diagnostics.Basic_Options,
|
||||
description: Diagnostics.Enable_incremental_compilation,
|
||||
},
|
||||
];
|
||||
|
||||
/* @internal */
|
||||
@@ -197,6 +209,7 @@ namespace ts {
|
||||
es2016: ScriptTarget.ES2016,
|
||||
es2017: ScriptTarget.ES2017,
|
||||
es2018: ScriptTarget.ES2018,
|
||||
es2019: ScriptTarget.ES2019,
|
||||
esnext: ScriptTarget.ESNext,
|
||||
}),
|
||||
affectsSourceFile: true,
|
||||
@@ -204,7 +217,7 @@ namespace ts {
|
||||
paramType: Diagnostics.VERSION,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Basic_Options,
|
||||
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_ES2015_ES2016_ES2017_ES2018_or_ESNEXT,
|
||||
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_ES2015_ES2016_ES2017_ES2018_ES2019_or_ESNEXT,
|
||||
},
|
||||
{
|
||||
name: "module",
|
||||
@@ -325,6 +338,14 @@ namespace ts {
|
||||
category: Diagnostics.Basic_Options,
|
||||
description: Diagnostics.Enable_project_compilation,
|
||||
},
|
||||
{
|
||||
name: "tsBuildInfoFile",
|
||||
type: "string",
|
||||
isFilePath: true,
|
||||
paramType: Diagnostics.FILE,
|
||||
category: Diagnostics.Basic_Options,
|
||||
description: Diagnostics.Specify_file_to_store_incremental_compilation_information,
|
||||
},
|
||||
{
|
||||
name: "removeComments",
|
||||
type: "boolean",
|
||||
@@ -1421,6 +1442,7 @@ namespace ts {
|
||||
return _tsconfigRootOptions;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
interface JsonConversionNotifier {
|
||||
/**
|
||||
* Notifies parent option object is being set with the optionKey and a valid optionValue
|
||||
@@ -1935,7 +1957,7 @@ namespace ts {
|
||||
|
||||
function directoryOfCombinedPath(fileName: string, basePath: string) {
|
||||
// Use the `getNormalizedAbsolutePath` function to avoid canonicalizing the path, as it must remain noncanonical
|
||||
// until consistient casing errors are reported
|
||||
// until consistent casing errors are reported
|
||||
return getDirectoryPath(getNormalizedAbsolutePath(fileName, basePath));
|
||||
}
|
||||
|
||||
|
||||
+176
-30
@@ -1,7 +1,7 @@
|
||||
namespace ts {
|
||||
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
|
||||
// If changing the text in this section, be sure to test `configureNightly` too.
|
||||
export const versionMajorMinor = "3.3";
|
||||
export const versionMajorMinor = "3.4";
|
||||
/** The version of the TypeScript compiler release */
|
||||
export const version = `${versionMajorMinor}.0-dev`;
|
||||
}
|
||||
@@ -118,42 +118,105 @@ namespace ts {
|
||||
export const MapCtr = typeof Map !== "undefined" && "entries" in Map.prototype ? Map : shimMap();
|
||||
|
||||
// Keep the class inside a function so it doesn't get compiled if it's not used.
|
||||
function shimMap(): new <T>() => Map<T> {
|
||||
export function shimMap(): new <T>() => Map<T> {
|
||||
|
||||
interface MapEntry<T> {
|
||||
readonly key?: string;
|
||||
value?: T;
|
||||
|
||||
// Linked list references for iterators.
|
||||
nextEntry?: MapEntry<T>;
|
||||
previousEntry?: MapEntry<T>;
|
||||
|
||||
/**
|
||||
* Specifies if iterators should skip the next entry.
|
||||
* This will be set when an entry is deleted.
|
||||
* See https://github.com/Microsoft/TypeScript/pull/27292 for more information.
|
||||
*/
|
||||
skipNext?: boolean;
|
||||
}
|
||||
|
||||
class MapIterator<T, U extends (string | T | [string, T])> {
|
||||
private data: MapLike<T>;
|
||||
private keys: ReadonlyArray<string>;
|
||||
private index = 0;
|
||||
private selector: (data: MapLike<T>, key: string) => U;
|
||||
constructor(data: MapLike<T>, selector: (data: MapLike<T>, key: string) => U) {
|
||||
this.data = data;
|
||||
private currentEntry?: MapEntry<T>;
|
||||
private selector: (key: string, value: T) => U;
|
||||
|
||||
constructor(currentEntry: MapEntry<T>, selector: (key: string, value: T) => U) {
|
||||
this.currentEntry = currentEntry;
|
||||
this.selector = selector;
|
||||
this.keys = Object.keys(data);
|
||||
}
|
||||
|
||||
public next(): { value: U, done: false } | { value: never, done: true } {
|
||||
const index = this.index;
|
||||
if (index < this.keys.length) {
|
||||
this.index++;
|
||||
return { value: this.selector(this.data, this.keys[index]), done: false };
|
||||
// Navigate to the next entry.
|
||||
while (this.currentEntry) {
|
||||
const skipNext = !!this.currentEntry.skipNext;
|
||||
this.currentEntry = this.currentEntry.nextEntry;
|
||||
|
||||
if (!skipNext) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.currentEntry) {
|
||||
return { value: this.selector(this.currentEntry.key!, this.currentEntry.value!), done: false };
|
||||
}
|
||||
else {
|
||||
return { value: undefined as never, done: true };
|
||||
}
|
||||
return { value: undefined as never, done: true };
|
||||
}
|
||||
}
|
||||
|
||||
return class <T> implements Map<T> {
|
||||
private data = createDictionaryObject<T>();
|
||||
private data = createDictionaryObject<MapEntry<T>>();
|
||||
public size = 0;
|
||||
|
||||
// Linked list references for iterators.
|
||||
// See https://github.com/Microsoft/TypeScript/pull/27292
|
||||
// for more information.
|
||||
|
||||
/**
|
||||
* The first entry in the linked list.
|
||||
* Note that this is only a stub that serves as starting point
|
||||
* for iterators and doesn't contain a key and a value.
|
||||
*/
|
||||
private readonly firstEntry: MapEntry<T>;
|
||||
private lastEntry: MapEntry<T>;
|
||||
|
||||
constructor() {
|
||||
// Create a first (stub) map entry that will not contain a key
|
||||
// and value but serves as starting point for iterators.
|
||||
this.firstEntry = {};
|
||||
// When the map is empty, the last entry is the same as the
|
||||
// first one.
|
||||
this.lastEntry = this.firstEntry;
|
||||
}
|
||||
|
||||
get(key: string): T | undefined {
|
||||
return this.data[key];
|
||||
const entry = this.data[key] as MapEntry<T> | undefined;
|
||||
return entry && entry.value!;
|
||||
}
|
||||
|
||||
set(key: string, value: T): this {
|
||||
if (!this.has(key)) {
|
||||
this.size++;
|
||||
|
||||
// Create a new entry that will be appended at the
|
||||
// end of the linked list.
|
||||
const newEntry: MapEntry<T> = {
|
||||
key,
|
||||
value
|
||||
};
|
||||
this.data[key] = newEntry;
|
||||
|
||||
// Adjust the references.
|
||||
const previousLastEntry = this.lastEntry;
|
||||
previousLastEntry.nextEntry = newEntry;
|
||||
newEntry.previousEntry = previousLastEntry;
|
||||
this.lastEntry = newEntry;
|
||||
}
|
||||
this.data[key] = value;
|
||||
else {
|
||||
this.data[key].value = value;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -165,32 +228,81 @@ namespace ts {
|
||||
delete(key: string): boolean {
|
||||
if (this.has(key)) {
|
||||
this.size--;
|
||||
const entry = this.data[key];
|
||||
delete this.data[key];
|
||||
|
||||
// Adjust the linked list references of the neighbor entries.
|
||||
const previousEntry = entry.previousEntry!;
|
||||
previousEntry.nextEntry = entry.nextEntry;
|
||||
if (entry.nextEntry) {
|
||||
entry.nextEntry.previousEntry = previousEntry;
|
||||
}
|
||||
|
||||
// When the deleted entry was the last one, we need to
|
||||
// adust the lastEntry reference.
|
||||
if (this.lastEntry === entry) {
|
||||
this.lastEntry = previousEntry;
|
||||
}
|
||||
|
||||
// Adjust the forward reference of the deleted entry
|
||||
// in case an iterator still references it. This allows us
|
||||
// to throw away the entry, but when an active iterator
|
||||
// (which points to the current entry) continues, it will
|
||||
// navigate to the entry that originally came before the
|
||||
// current one and skip it.
|
||||
entry.previousEntry = undefined;
|
||||
entry.nextEntry = previousEntry;
|
||||
entry.skipNext = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.data = createDictionaryObject<T>();
|
||||
this.data = createDictionaryObject<MapEntry<T>>();
|
||||
this.size = 0;
|
||||
|
||||
// Reset the linked list. Note that we must adjust the forward
|
||||
// references of the deleted entries to ensure iterators stuck
|
||||
// in the middle of the list don't continue with deleted entries,
|
||||
// but can continue with new entries added after the clear()
|
||||
// operation.
|
||||
const firstEntry = this.firstEntry;
|
||||
let currentEntry = firstEntry.nextEntry;
|
||||
while (currentEntry) {
|
||||
const nextEntry = currentEntry.nextEntry;
|
||||
currentEntry.previousEntry = undefined;
|
||||
currentEntry.nextEntry = firstEntry;
|
||||
currentEntry.skipNext = true;
|
||||
|
||||
currentEntry = nextEntry;
|
||||
}
|
||||
firstEntry.nextEntry = undefined;
|
||||
this.lastEntry = firstEntry;
|
||||
}
|
||||
|
||||
keys(): Iterator<string> {
|
||||
return new MapIterator(this.data, (_data, key) => key);
|
||||
return new MapIterator(this.firstEntry, key => key);
|
||||
}
|
||||
|
||||
values(): Iterator<T> {
|
||||
return new MapIterator(this.data, (data, key) => data[key]);
|
||||
return new MapIterator(this.firstEntry, (_key, value) => value);
|
||||
}
|
||||
|
||||
entries(): Iterator<[string, T]> {
|
||||
return new MapIterator(this.data, (data, key) => [key, data[key]] as [string, T]);
|
||||
return new MapIterator(this.firstEntry, (key, value) => [key, value] as [string, T]);
|
||||
}
|
||||
|
||||
forEach(action: (value: T, key: string) => void): void {
|
||||
for (const key in this.data) {
|
||||
action(this.data[key], key);
|
||||
const iterator = this.entries();
|
||||
while (true) {
|
||||
const { value: entry, done } = iterator.next();
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
|
||||
action(entry[1], entry[0]);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -805,7 +917,7 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Deduplicates an unsorted array.
|
||||
* @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates.
|
||||
* @param equalityComparer An `EqualityComparer` used to determine if two values are duplicates.
|
||||
* @param comparer An optional `Comparer` used to sort entries before comparison, though the
|
||||
* result will remain in the original order in `array`.
|
||||
*/
|
||||
@@ -884,8 +996,11 @@ namespace ts {
|
||||
/**
|
||||
* Compacts an array, removing any falsey elements.
|
||||
*/
|
||||
export function compact<T>(array: T[]): T[];
|
||||
export function compact<T>(array: ReadonlyArray<T>): ReadonlyArray<T>;
|
||||
export function compact<T>(array: (T | undefined | null | false | 0 | "")[]): T[];
|
||||
export function compact<T>(array: ReadonlyArray<T | undefined | null | false | 0 | "">): ReadonlyArray<T>;
|
||||
// TSLint thinks these can be combined with the above - they cannot; they'd produce higher-priority inferences and prevent the falsey types from being stripped
|
||||
export function compact<T>(array: T[]): T[]; // tslint:disable-line unified-signatures
|
||||
export function compact<T>(array: ReadonlyArray<T>): ReadonlyArray<T>; // tslint:disable-line unified-signatures
|
||||
export function compact<T>(array: T[]): T[] {
|
||||
let result: T[] | undefined;
|
||||
if (array) {
|
||||
@@ -1058,6 +1173,21 @@ namespace ts {
|
||||
}};
|
||||
}
|
||||
|
||||
export function arrayReverseIterator<T>(array: ReadonlyArray<T>): Iterator<T> {
|
||||
let i = array.length;
|
||||
return {
|
||||
next: () => {
|
||||
if (i === 0) {
|
||||
return { value: undefined as never, done: true };
|
||||
}
|
||||
else {
|
||||
i--;
|
||||
return { value: array[i], done: false };
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Stable sort of an array. Elements equal to each other maintain their relative position in the array.
|
||||
*/
|
||||
@@ -1281,9 +1411,10 @@ namespace ts {
|
||||
|
||||
export function assign<T extends object>(t: T, ...args: (T | undefined)[]) {
|
||||
for (const arg of args) {
|
||||
for (const p in arg!) {
|
||||
if (hasProperty(arg!, p)) {
|
||||
t![p] = arg![p]; // TODO: GH#23368
|
||||
if (arg === undefined) continue;
|
||||
for (const p in arg) {
|
||||
if (hasProperty(arg, p)) {
|
||||
t[p] = arg[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1387,6 +1518,18 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function copyProperties<T1 extends T2, T2>(first: T1, second: T2) {
|
||||
for (const id in second) {
|
||||
if (hasOwnProperty.call(second, id)) {
|
||||
(first as any)[id] = second[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function maybeBind<T, A extends any[], R>(obj: T, fn: ((this: T, ...args: A) => R) | undefined): ((...args: A) => R) | undefined {
|
||||
return fn ? fn.bind(obj) : undefined;
|
||||
}
|
||||
|
||||
export interface MultiMap<T> extends Map<T[]> {
|
||||
/**
|
||||
* Adds the value to an array of values associated with the key, and returns the array.
|
||||
@@ -1471,6 +1614,9 @@ namespace ts {
|
||||
/** Do nothing and return true */
|
||||
export function returnTrue(): true { return true; }
|
||||
|
||||
/** Do nothing and return undefined */
|
||||
export function returnUndefined(): undefined { return undefined; }
|
||||
|
||||
/** Returns its argument. */
|
||||
export function identity<T>(x: T) { return x; }
|
||||
|
||||
@@ -1637,7 +1783,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function assertNever(member: never, message = "Illegal value:", stackCrawlMark?: AnyFunction): never {
|
||||
const detail = "kind" in member && "pos" in member ? "SyntaxKind: " + showSyntaxKind(member as Node) : JSON.stringify(member);
|
||||
const detail = typeof member === "object" && "kind" in member && "pos" in member ? "SyntaxKind: " + showSyntaxKind(member as Node) : JSON.stringify(member);
|
||||
return fail(`${message} ${detail}`, stackCrawlMark || assertNever);
|
||||
}
|
||||
|
||||
|
||||
@@ -659,10 +659,6 @@
|
||||
"category": "Error",
|
||||
"code": 1208
|
||||
},
|
||||
"Ambient const enums are not allowed when the '--isolatedModules' flag is provided.": {
|
||||
"category": "Error",
|
||||
"code": 1209
|
||||
},
|
||||
"Invalid use of '{0}'. Class definitions are automatically in strict mode.": {
|
||||
"category": "Error",
|
||||
"code": 1210
|
||||
@@ -1023,6 +1019,14 @@
|
||||
"category": "Error",
|
||||
"code": 1353
|
||||
},
|
||||
"'readonly' type modifier is only permitted on array and tuple literal types.": {
|
||||
"category": "Error",
|
||||
"code": 1354
|
||||
},
|
||||
"A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.": {
|
||||
"category": "Error",
|
||||
"code": 1355
|
||||
},
|
||||
|
||||
"Duplicate identifier '{0}'.": {
|
||||
"category": "Error",
|
||||
@@ -1400,7 +1404,7 @@
|
||||
"category": "Error",
|
||||
"code": 2393
|
||||
},
|
||||
"Overload signature is not compatible with function implementation.": {
|
||||
"This overload signature is not compatible with its implementation signature.": {
|
||||
"category": "Error",
|
||||
"code": 2394
|
||||
},
|
||||
@@ -2056,10 +2060,6 @@
|
||||
"category": "Error",
|
||||
"code": 2567
|
||||
},
|
||||
"Type '{0}' is not an array type. Use compiler option '--downlevelIteration' to allow iterating of iterators.": {
|
||||
"category": "Error",
|
||||
"code": 2568
|
||||
},
|
||||
"Type '{0}' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators.": {
|
||||
"category": "Error",
|
||||
"code": 2569
|
||||
@@ -2096,15 +2096,15 @@
|
||||
"category": "Error",
|
||||
"code": 2577
|
||||
},
|
||||
"Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.": {
|
||||
"Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node`.": {
|
||||
"category": "Error",
|
||||
"code": 2580
|
||||
},
|
||||
"Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery` and then add `jquery` to the types field in your tsconfig.": {
|
||||
"Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery`.": {
|
||||
"category": "Error",
|
||||
"code": 2581
|
||||
},
|
||||
"Cannot find name '{0}'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig.": {
|
||||
"Cannot find name '{0}'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`.": {
|
||||
"category": "Error",
|
||||
"code": 2582
|
||||
},
|
||||
@@ -2132,6 +2132,26 @@
|
||||
"category": "Error",
|
||||
"code": 2588
|
||||
},
|
||||
"Type instantiation is excessively deep and possibly infinite.": {
|
||||
"category": "Error",
|
||||
"code": 2589
|
||||
},
|
||||
"Expression produces a union type that is too complex to represent.": {
|
||||
"category": "Error",
|
||||
"code": 2590
|
||||
},
|
||||
"Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.": {
|
||||
"category": "Error",
|
||||
"code": 2591
|
||||
},
|
||||
"Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery` and then add `jquery` to the types field in your tsconfig.": {
|
||||
"category": "Error",
|
||||
"code": 2592
|
||||
},
|
||||
"Cannot find name '{0}'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig.": {
|
||||
"category": "Error",
|
||||
"code": 2593
|
||||
},
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
@@ -2437,7 +2457,7 @@
|
||||
"category": "Error",
|
||||
"code": 2717
|
||||
},
|
||||
"Duplicate declaration '{0}'.": {
|
||||
"Duplicate property '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2718
|
||||
},
|
||||
@@ -2497,6 +2517,10 @@
|
||||
"category": "Error",
|
||||
"code": 2732
|
||||
},
|
||||
"Property '{0}' was also declared here.": {
|
||||
"category": "Error",
|
||||
"code": 2733
|
||||
},
|
||||
"It is highly likely that you are missing a semicolon.": {
|
||||
"category": "Error",
|
||||
"code": 2734
|
||||
@@ -2541,6 +2565,42 @@
|
||||
"category": "Error",
|
||||
"code": 2744
|
||||
},
|
||||
"This JSX tag's '{0}' prop expects type '{1}' which requires multiple children, but only a single child was provided.": {
|
||||
"category": "Error",
|
||||
"code": 2745
|
||||
},
|
||||
"This JSX tag's '{0}' prop expects a single child of type '{1}', but multiple children were provided.": {
|
||||
"category": "Error",
|
||||
"code": 2746
|
||||
},
|
||||
"'{0}' components don't accept text as child elements. Text in JSX has the type 'string', but the expected type of '{1}' is '{2}'.": {
|
||||
"category": "Error",
|
||||
"code": 2747
|
||||
},
|
||||
"Cannot access ambient const enums when the '--isolatedModules' flag is provided.": {
|
||||
"category": "Error",
|
||||
"code": 2748
|
||||
},
|
||||
"'{0}' refers to a value, but is being used as a type here.": {
|
||||
"category": "Error",
|
||||
"code": 2749
|
||||
},
|
||||
"The implementation signature is declared here.": {
|
||||
"category": "Error",
|
||||
"code": 2750
|
||||
},
|
||||
"Circularity originates in type at this location.": {
|
||||
"category": "Error",
|
||||
"code": 2751
|
||||
},
|
||||
"The first export default is here.": {
|
||||
"category": "Error",
|
||||
"code": 2752
|
||||
},
|
||||
"Another export default is here.": {
|
||||
"category": "Error",
|
||||
"code": 2753
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
@@ -2875,6 +2935,10 @@
|
||||
"category": "Error",
|
||||
"code": 4102
|
||||
},
|
||||
"Type parameter '{0}' of exported mapped object type is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4103
|
||||
},
|
||||
|
||||
"The current host does not support the '{0}' option.": {
|
||||
"category": "Error",
|
||||
@@ -3008,6 +3072,10 @@
|
||||
"category": "Error",
|
||||
"code": 5073
|
||||
},
|
||||
"Option '--incremental' can only be specified using tsconfig, emitting to single file or when option `--tsBuildInfoFile` is specified.": {
|
||||
"category": "Error",
|
||||
"code": 5074
|
||||
},
|
||||
|
||||
"Generates a sourcemap for each corresponding '.d.ts' file.": {
|
||||
"category": "Message",
|
||||
@@ -3069,7 +3137,7 @@
|
||||
"category": "Message",
|
||||
"code": 6014
|
||||
},
|
||||
"Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'.": {
|
||||
"Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'.": {
|
||||
"category": "Message",
|
||||
"code": 6015
|
||||
},
|
||||
@@ -3880,7 +3948,6 @@
|
||||
"category": "Message",
|
||||
"code": 6353
|
||||
},
|
||||
|
||||
"Project '{0}' is up to date with .d.ts files from its dependencies": {
|
||||
"category": "Message",
|
||||
"code": 6354
|
||||
@@ -3949,6 +4016,50 @@
|
||||
"category": "Error",
|
||||
"code": 6370
|
||||
},
|
||||
"Updating unchanged output timestamps of project '{0}'...": {
|
||||
"category": "Message",
|
||||
"code": 6371
|
||||
},
|
||||
"Project '{0}' is out of date because output of its dependency '{1}' has changed": {
|
||||
"category": "Message",
|
||||
"code": 6372
|
||||
},
|
||||
"Updating output of project '{0}'...": {
|
||||
"category": "Message",
|
||||
"code": 6373
|
||||
},
|
||||
"A non-dry build would update timestamps for output of project '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 6374
|
||||
},
|
||||
"A non-dry build would update output of project '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 6375
|
||||
},
|
||||
"Cannot update output of project '{0}' because there was error reading file '{1}'": {
|
||||
"category": "Message",
|
||||
"code": 6376
|
||||
},
|
||||
"Cannot write file '{0}' because it will overwrite '.tsbuildinfo' file generated by referenced project '{1}'": {
|
||||
"category": "Error",
|
||||
"code": 6377
|
||||
},
|
||||
"Enable incremental compilation": {
|
||||
"category": "Message",
|
||||
"code": 6378
|
||||
},
|
||||
"Composite projects may not disable incremental compilation.": {
|
||||
"category": "Error",
|
||||
"code": 6379
|
||||
},
|
||||
"Specify file to store incremental compilation information": {
|
||||
"category": "Message",
|
||||
"code": 6380
|
||||
},
|
||||
"Project '{0}' is out of date because output for it was generated with version '{1}' that differs with current version '{2}'": {
|
||||
"category": "Message",
|
||||
"code": 6381
|
||||
},
|
||||
|
||||
"The expected type comes from property '{0}' which is declared here on type '{1}'": {
|
||||
"category": "Message",
|
||||
@@ -4097,7 +4208,7 @@
|
||||
"category": "Error",
|
||||
"code": 7040
|
||||
},
|
||||
"The containing arrow function captures the global value of 'this' which implicitly has type 'any'.": {
|
||||
"The containing arrow function captures the global value of 'this'.": {
|
||||
"category": "Error",
|
||||
"code": 7041
|
||||
},
|
||||
@@ -4266,6 +4377,10 @@
|
||||
"category": "Error",
|
||||
"code": 8031
|
||||
},
|
||||
"Qualified name '{0}' is not allowed without a leading '@param {object} {1}'.": {
|
||||
"category": "Error",
|
||||
"code": 8032
|
||||
},
|
||||
"Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": {
|
||||
"category": "Error",
|
||||
"code": 9002
|
||||
@@ -4815,5 +4930,9 @@
|
||||
"Enable the 'experimentalDecorators' option in your configuration file": {
|
||||
"category": "Message",
|
||||
"code": 95074
|
||||
},
|
||||
"Convert parameters to destructured object": {
|
||||
"category": "Message",
|
||||
"code": 95075
|
||||
}
|
||||
}
|
||||
|
||||
+659
-93
File diff suppressed because it is too large
Load Diff
+312
-31
@@ -89,10 +89,10 @@ namespace ts {
|
||||
return createLiteralFromNode(value);
|
||||
}
|
||||
|
||||
export function createNumericLiteral(value: string): NumericLiteral {
|
||||
export function createNumericLiteral(value: string, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral {
|
||||
const node = <NumericLiteral>createSynthesizedNode(SyntaxKind.NumericLiteral);
|
||||
node.text = value;
|
||||
node.numericLiteralFlags = 0;
|
||||
node.numericLiteralFlags = numericLiteralFlags;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -143,8 +143,8 @@ namespace ts {
|
||||
export function updateIdentifier(node: Identifier, typeArguments: NodeArray<TypeNode | TypeParameterDeclaration> | undefined): Identifier; // tslint:disable-line unified-signatures
|
||||
export function updateIdentifier(node: Identifier, typeArguments?: NodeArray<TypeNode | TypeParameterDeclaration> | undefined): Identifier {
|
||||
return node.typeArguments !== typeArguments
|
||||
? updateNode(createIdentifier(idText(node), typeArguments), node)
|
||||
: node;
|
||||
? updateNode(createIdentifier(idText(node), typeArguments), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
let nextAutoGenerateId = 0;
|
||||
@@ -876,8 +876,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createTypeOperatorNode(type: TypeNode): TypeOperatorNode;
|
||||
export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword, type: TypeNode): TypeOperatorNode;
|
||||
export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | TypeNode, type?: TypeNode) {
|
||||
export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode;
|
||||
export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | TypeNode, type?: TypeNode) {
|
||||
const node = createSynthesizedNode(SyntaxKind.TypeOperator) as TypeOperatorNode;
|
||||
node.operator = typeof operatorOrType === "number" ? operatorOrType : SyntaxKind.KeyOfKeyword;
|
||||
node.type = parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type! : operatorOrType);
|
||||
@@ -2299,6 +2299,28 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean) {
|
||||
const node = <JsxText>createSynthesizedNode(SyntaxKind.JsxText);
|
||||
node.text = text;
|
||||
node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) {
|
||||
return node.text !== text
|
||||
|| node.containsOnlyTriviaWhiteSpaces !== containsOnlyTriviaWhiteSpaces
|
||||
? updateNode(createJsxText(text, containsOnlyTriviaWhiteSpaces), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createJsxOpeningFragment() {
|
||||
return <JsxOpeningFragment>createSynthesizedNode(SyntaxKind.JsxOpeningFragment);
|
||||
}
|
||||
|
||||
export function createJsxJsxClosingFragment() {
|
||||
return <JsxClosingFragment>createSynthesizedNode(SyntaxKind.JsxClosingFragment);
|
||||
}
|
||||
|
||||
export function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: ReadonlyArray<JsxChild>, closingFragment: JsxClosingFragment) {
|
||||
return node.openingFragment !== openingFragment
|
||||
|| node.children !== children
|
||||
@@ -2629,42 +2651,301 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createUnparsedSourceFile(text: string): UnparsedSource;
|
||||
export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource;
|
||||
export function createUnparsedSourceFile(text: string, mapPath?: string, map?: string): UnparsedSource {
|
||||
let allUnscopedEmitHelpers: ReadonlyMap<UnscopedEmitHelper> | undefined;
|
||||
function getAllUnscopedEmitHelpers() {
|
||||
return allUnscopedEmitHelpers || (allUnscopedEmitHelpers = arrayToMap([
|
||||
valuesHelper,
|
||||
readHelper,
|
||||
spreadHelper,
|
||||
restHelper,
|
||||
decorateHelper,
|
||||
metadataHelper,
|
||||
paramHelper,
|
||||
awaiterHelper,
|
||||
assignHelper,
|
||||
awaitHelper,
|
||||
asyncGeneratorHelper,
|
||||
asyncDelegator,
|
||||
asyncValues,
|
||||
extendsHelper,
|
||||
templateObjectHelper,
|
||||
generatorHelper,
|
||||
importStarHelper,
|
||||
importDefaultHelper
|
||||
], helper => helper.name));
|
||||
}
|
||||
|
||||
function createUnparsedSource() {
|
||||
const node = <UnparsedSource>createNode(SyntaxKind.UnparsedSource);
|
||||
node.text = text;
|
||||
node.sourceMapPath = mapPath;
|
||||
node.sourceMapText = map;
|
||||
node.prologues = emptyArray;
|
||||
node.referencedFiles = emptyArray;
|
||||
node.libReferenceDirectives = emptyArray;
|
||||
node.getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createUnparsedSourceFile(text: string): UnparsedSource;
|
||||
export function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource;
|
||||
export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource;
|
||||
export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, mapPathOrType?: string, mapTextOrStripInternal?: string | boolean): UnparsedSource {
|
||||
const node = createUnparsedSource();
|
||||
let stripInternal: boolean | undefined;
|
||||
let bundleFileInfo: BundleFileInfo | undefined;
|
||||
if (!isString(textOrInputFiles)) {
|
||||
Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts");
|
||||
node.fileName = (mapPathOrType === "js" ? textOrInputFiles.javascriptPath : textOrInputFiles.declarationPath) || "";
|
||||
node.sourceMapPath = mapPathOrType === "js" ? textOrInputFiles.javascriptMapPath : textOrInputFiles.declarationMapPath;
|
||||
Object.defineProperties(node, {
|
||||
text: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptText : textOrInputFiles.declarationText; } },
|
||||
sourceMapText: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText; } },
|
||||
});
|
||||
|
||||
|
||||
if (textOrInputFiles.buildInfo && textOrInputFiles.buildInfo.bundle) {
|
||||
node.oldFileOfCurrentEmit = textOrInputFiles.oldFileOfCurrentEmit;
|
||||
Debug.assert(mapTextOrStripInternal === undefined || typeof mapTextOrStripInternal === "boolean");
|
||||
stripInternal = mapTextOrStripInternal as boolean | undefined;
|
||||
bundleFileInfo = mapPathOrType === "js" ? textOrInputFiles.buildInfo.bundle.js : textOrInputFiles.buildInfo.bundle.dts;
|
||||
if (node.oldFileOfCurrentEmit) {
|
||||
parseOldFileOfCurrentEmit(node, Debug.assertDefined(bundleFileInfo));
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
node.fileName = "";
|
||||
node.text = textOrInputFiles;
|
||||
node.sourceMapPath = mapPathOrType;
|
||||
node.sourceMapText = mapTextOrStripInternal as string;
|
||||
}
|
||||
Debug.assert(!node.oldFileOfCurrentEmit);
|
||||
parseUnparsedSourceFile(node, bundleFileInfo, stripInternal);
|
||||
return node;
|
||||
}
|
||||
|
||||
function parseUnparsedSourceFile(node: UnparsedSource, bundleFileInfo: BundleFileInfo | undefined, stripInternal: boolean | undefined) {
|
||||
let prologues: UnparsedPrologue[] | undefined;
|
||||
let helpers: UnscopedEmitHelper[] | undefined;
|
||||
let referencedFiles: FileReference[] | undefined;
|
||||
let typeReferenceDirectives: string[] | undefined;
|
||||
let libReferenceDirectives: FileReference[] | undefined;
|
||||
let texts: UnparsedSourceText[] | undefined;
|
||||
|
||||
for (const section of bundleFileInfo ? bundleFileInfo.sections : emptyArray) {
|
||||
switch (section.kind) {
|
||||
case BundleFileSectionKind.Prologue:
|
||||
(prologues || (prologues = [])).push(createUnparsedNode(section, node) as UnparsedPrologue);
|
||||
break;
|
||||
case BundleFileSectionKind.EmitHelpers:
|
||||
(helpers || (helpers = [])).push(getAllUnscopedEmitHelpers().get(section.data)!);
|
||||
break;
|
||||
case BundleFileSectionKind.NoDefaultLib:
|
||||
node.hasNoDefaultLib = true;
|
||||
break;
|
||||
case BundleFileSectionKind.Reference:
|
||||
(referencedFiles || (referencedFiles = [])).push({ pos: -1, end: -1, fileName: section.data });
|
||||
break;
|
||||
case BundleFileSectionKind.Type:
|
||||
(typeReferenceDirectives || (typeReferenceDirectives = [])).push(section.data);
|
||||
break;
|
||||
case BundleFileSectionKind.Lib:
|
||||
(libReferenceDirectives || (libReferenceDirectives = [])).push({ pos: -1, end: -1, fileName: section.data });
|
||||
break;
|
||||
case BundleFileSectionKind.Prepend:
|
||||
const prependNode = createUnparsedNode(section, node) as UnparsedPrepend;
|
||||
let prependTexts: UnparsedTextLike[] | undefined;
|
||||
for (const text of section.texts) {
|
||||
if (!stripInternal || text.kind !== BundleFileSectionKind.Internal) {
|
||||
(prependTexts || (prependTexts = [])).push(createUnparsedNode(text, node) as UnparsedTextLike);
|
||||
}
|
||||
}
|
||||
prependNode.texts = prependTexts || emptyArray;
|
||||
(texts || (texts = [])).push(prependNode);
|
||||
break;
|
||||
case BundleFileSectionKind.Internal:
|
||||
if (stripInternal) break;
|
||||
// falls through
|
||||
case BundleFileSectionKind.Text:
|
||||
(texts || (texts = [])).push(createUnparsedNode(section, node) as UnparsedTextLike);
|
||||
break;
|
||||
default:
|
||||
Debug.assertNever(section);
|
||||
}
|
||||
}
|
||||
|
||||
node.prologues = prologues || emptyArray;
|
||||
node.helpers = helpers;
|
||||
node.referencedFiles = referencedFiles || emptyArray;
|
||||
node.typeReferenceDirectives = typeReferenceDirectives;
|
||||
node.libReferenceDirectives = libReferenceDirectives || emptyArray;
|
||||
node.texts = texts || [<UnparsedTextLike>createUnparsedNode({ kind: BundleFileSectionKind.Text, pos: 0, end: node.text.length }, node)];
|
||||
}
|
||||
|
||||
function parseOldFileOfCurrentEmit(node: UnparsedSource, bundleFileInfo: BundleFileInfo) {
|
||||
Debug.assert(!!node.oldFileOfCurrentEmit);
|
||||
let texts: UnparsedTextLike[] | undefined;
|
||||
let syntheticReferences: UnparsedSyntheticReference[] | undefined;
|
||||
for (const section of bundleFileInfo.sections) {
|
||||
switch (section.kind) {
|
||||
case BundleFileSectionKind.Internal:
|
||||
case BundleFileSectionKind.Text:
|
||||
(texts || (texts = [])).push(createUnparsedNode(section, node) as UnparsedTextLike);
|
||||
break;
|
||||
|
||||
case BundleFileSectionKind.NoDefaultLib:
|
||||
case BundleFileSectionKind.Reference:
|
||||
case BundleFileSectionKind.Type:
|
||||
case BundleFileSectionKind.Lib:
|
||||
(syntheticReferences || (syntheticReferences = [])).push(createUnparsedSyntheticReference(section, node));
|
||||
break;
|
||||
|
||||
// Ignore
|
||||
case BundleFileSectionKind.Prologue:
|
||||
case BundleFileSectionKind.EmitHelpers:
|
||||
case BundleFileSectionKind.Prepend:
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.assertNever(section);
|
||||
}
|
||||
}
|
||||
node.texts = texts || emptyArray;
|
||||
node.helpers = map(bundleFileInfo.sources && bundleFileInfo.sources.helpers, name => getAllUnscopedEmitHelpers().get(name)!);
|
||||
node.syntheticReferences = syntheticReferences;
|
||||
return node;
|
||||
}
|
||||
|
||||
function mapBundleFileSectionKindToSyntaxKind(kind: BundleFileSectionKind): SyntaxKind {
|
||||
switch (kind) {
|
||||
case BundleFileSectionKind.Prologue: return SyntaxKind.UnparsedPrologue;
|
||||
case BundleFileSectionKind.Prepend: return SyntaxKind.UnparsedPrepend;
|
||||
case BundleFileSectionKind.Internal: return SyntaxKind.UnparsedInternalText;
|
||||
case BundleFileSectionKind.Text: return SyntaxKind.UnparsedText;
|
||||
|
||||
case BundleFileSectionKind.EmitHelpers:
|
||||
case BundleFileSectionKind.NoDefaultLib:
|
||||
case BundleFileSectionKind.Reference:
|
||||
case BundleFileSectionKind.Type:
|
||||
case BundleFileSectionKind.Lib:
|
||||
return Debug.fail(`BundleFileSectionKind: ${kind} not yet mapped to SyntaxKind`);
|
||||
|
||||
default:
|
||||
return Debug.assertNever(kind);
|
||||
}
|
||||
}
|
||||
|
||||
function createUnparsedNode(section: BundleFileSection, parent: UnparsedSource): UnparsedNode {
|
||||
const node = createNode(mapBundleFileSectionKindToSyntaxKind(section.kind), section.pos, section.end) as UnparsedNode;
|
||||
node.parent = parent;
|
||||
node.data = section.data;
|
||||
return node;
|
||||
}
|
||||
|
||||
function createUnparsedSyntheticReference(section: BundleFileHasNoDefaultLib | BundleFileReference, parent: UnparsedSource) {
|
||||
const node = createNode(SyntaxKind.UnparsedSyntheticReference, section.pos, section.end) as UnparsedSyntheticReference;
|
||||
node.parent = parent;
|
||||
node.data = section.data;
|
||||
node.section = section;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createInputFiles(
|
||||
javascript: string,
|
||||
declaration: string
|
||||
javascriptText: string,
|
||||
declarationText: string
|
||||
): InputFiles;
|
||||
export function createInputFiles(
|
||||
javascript: string,
|
||||
declaration: string,
|
||||
readFileText: (path: string) => string | undefined,
|
||||
javascriptPath: string,
|
||||
javascriptMapPath: string | undefined,
|
||||
declarationPath: string,
|
||||
declarationMapPath: string | undefined,
|
||||
buildInfoPath: string | undefined
|
||||
): InputFiles;
|
||||
export function createInputFiles(
|
||||
javascriptText: string,
|
||||
declarationText: string,
|
||||
javascriptMapPath: string | undefined,
|
||||
javascriptMapText: string | undefined,
|
||||
declarationMapPath: string | undefined,
|
||||
declarationMapText: string | undefined
|
||||
): InputFiles;
|
||||
/*@internal*/
|
||||
export function createInputFiles(
|
||||
javascript: string,
|
||||
declaration: string,
|
||||
javascriptText: string,
|
||||
declarationText: string,
|
||||
javascriptMapPath: string | undefined,
|
||||
javascriptMapText: string | undefined,
|
||||
declarationMapPath: string | undefined,
|
||||
declarationMapText: string | undefined,
|
||||
javascriptPath: string | undefined,
|
||||
declarationPath: string | undefined,
|
||||
buildInfoPath?: string | undefined,
|
||||
buildInfo?: BuildInfo,
|
||||
oldFileOfCurrentEmit?: boolean
|
||||
): InputFiles;
|
||||
export function createInputFiles(
|
||||
javascriptTextOrReadFileText: string | ((path: string) => string | undefined),
|
||||
declarationTextOrJavascriptPath: string,
|
||||
javascriptMapPath?: string,
|
||||
javascriptMapText?: string,
|
||||
javascriptMapTextOrDeclarationPath?: string,
|
||||
declarationMapPath?: string,
|
||||
declarationMapText?: string
|
||||
declarationMapTextOrBuildInfoPath?: string,
|
||||
javascriptPath?: string | undefined,
|
||||
declarationPath?: string | undefined,
|
||||
buildInfoPath?: string | undefined,
|
||||
buildInfo?: BuildInfo,
|
||||
oldFileOfCurrentEmit?: boolean
|
||||
): InputFiles {
|
||||
const node = <InputFiles>createNode(SyntaxKind.InputFiles);
|
||||
node.javascriptText = javascript;
|
||||
node.javascriptMapPath = javascriptMapPath;
|
||||
node.javascriptMapText = javascriptMapText;
|
||||
node.declarationText = declaration;
|
||||
node.declarationMapPath = declarationMapPath;
|
||||
node.declarationMapText = declarationMapText;
|
||||
if (!isString(javascriptTextOrReadFileText)) {
|
||||
const cache = createMap<string | false>();
|
||||
const textGetter = (path: string | undefined) => {
|
||||
if (path === undefined) return undefined;
|
||||
let value = cache.get(path);
|
||||
if (value === undefined) {
|
||||
value = javascriptTextOrReadFileText(path);
|
||||
cache.set(path, value !== undefined ? value : false);
|
||||
}
|
||||
return value !== false ? value as string : undefined;
|
||||
};
|
||||
const definedTextGetter = (path: string) => {
|
||||
const result = textGetter(path);
|
||||
return result !== undefined ? result : `/* Input file ${path} was missing */\r\n`;
|
||||
};
|
||||
let buildInfo: BuildInfo | false;
|
||||
const getAndCacheBuildInfo = (getText: () => string | undefined) => {
|
||||
if (buildInfo === undefined) {
|
||||
const result = getText();
|
||||
buildInfo = result !== undefined ? getBuildInfo(result) : false;
|
||||
}
|
||||
return buildInfo || undefined;
|
||||
};
|
||||
node.javascriptPath = declarationTextOrJavascriptPath;
|
||||
node.javascriptMapPath = javascriptMapPath;
|
||||
node.declarationPath = Debug.assertDefined(javascriptMapTextOrDeclarationPath);
|
||||
node.declarationMapPath = declarationMapPath;
|
||||
node.buildInfoPath = declarationMapTextOrBuildInfoPath;
|
||||
Object.defineProperties(node, {
|
||||
javascriptText: { get() { return definedTextGetter(declarationTextOrJavascriptPath); } },
|
||||
javascriptMapText: { get() { return textGetter(javascriptMapPath); } }, // TODO:: if there is inline sourceMap in jsFile, use that
|
||||
declarationText: { get() { return definedTextGetter(Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } },
|
||||
declarationMapText: { get() { return textGetter(declarationMapPath); } }, // TODO:: if there is inline sourceMap in dtsFile, use that
|
||||
buildInfo: { get() { return getAndCacheBuildInfo(() => textGetter(declarationMapTextOrBuildInfoPath)); } }
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.javascriptText = javascriptTextOrReadFileText;
|
||||
node.javascriptMapPath = javascriptMapPath;
|
||||
node.javascriptMapText = javascriptMapTextOrDeclarationPath;
|
||||
node.declarationText = declarationTextOrJavascriptPath;
|
||||
node.declarationMapPath = declarationMapPath;
|
||||
node.declarationMapText = declarationMapTextOrBuildInfoPath;
|
||||
node.javascriptPath = javascriptPath;
|
||||
node.declarationPath = declarationPath,
|
||||
node.buildInfoPath = buildInfoPath;
|
||||
node.buildInfo = buildInfo;
|
||||
node.oldFileOfCurrentEmit = oldFileOfCurrentEmit;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -2827,7 +3108,7 @@ namespace ts {
|
||||
return node.emitNode = { annotatedNodes: [node] } as EmitNode;
|
||||
}
|
||||
|
||||
const sourceFile = getSourceFileOfNode(node);
|
||||
const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node)));
|
||||
getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node);
|
||||
}
|
||||
|
||||
@@ -3124,7 +3405,7 @@ namespace ts {
|
||||
export const nullTransformationContext: TransformationContext = {
|
||||
enableEmitNotification: noop,
|
||||
enableSubstitution: noop,
|
||||
endLexicalEnvironment: () => undefined,
|
||||
endLexicalEnvironment: returnUndefined,
|
||||
getCompilerOptions: notImplemented,
|
||||
getEmitHost: notImplemented,
|
||||
getEmitResolver: notImplemented,
|
||||
@@ -3325,7 +3606,7 @@ namespace ts {
|
||||
return setEmitFlags(createIdentifier(name), EmitFlags.HelperName | EmitFlags.AdviseOnEmitNode);
|
||||
}
|
||||
|
||||
const valuesHelper: EmitHelper = {
|
||||
export const valuesHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:values",
|
||||
scoped: false,
|
||||
text: `
|
||||
@@ -3353,7 +3634,7 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
const readHelper: EmitHelper = {
|
||||
export const readHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:read",
|
||||
scoped: false,
|
||||
text: `
|
||||
@@ -3389,7 +3670,7 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
const spreadHelper: EmitHelper = {
|
||||
export const spreadHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:spread",
|
||||
scoped: false,
|
||||
text: `
|
||||
|
||||
@@ -437,6 +437,8 @@ namespace ts.moduleSpecifiers {
|
||||
case Extension.Jsx:
|
||||
case Extension.Json:
|
||||
return ext;
|
||||
case Extension.TsBuildInfo:
|
||||
return Debug.fail(`Extension ${Extension.TsBuildInfo} is unsupported:: FileName:: ${fileName}`);
|
||||
default:
|
||||
return Debug.assertNever(ext);
|
||||
}
|
||||
|
||||
+33
-22
@@ -1093,6 +1093,10 @@ namespace ts {
|
||||
return currentToken = scanner.reScanTemplateToken();
|
||||
}
|
||||
|
||||
function reScanLessThanToken(): SyntaxKind {
|
||||
return currentToken = scanner.reScanLessThanToken();
|
||||
}
|
||||
|
||||
function scanJsxIdentifier(): SyntaxKind {
|
||||
return currentToken = scanner.scanJsxIdentifier();
|
||||
}
|
||||
@@ -2276,7 +2280,7 @@ namespace ts {
|
||||
function parseTypeReference(): TypeReferenceNode {
|
||||
const node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
|
||||
node.typeName = parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected);
|
||||
if (!scanner.hasPrecedingLineBreak() && token() === SyntaxKind.LessThanToken) {
|
||||
if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === SyntaxKind.LessThanToken) {
|
||||
node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
|
||||
}
|
||||
return finishNode(node);
|
||||
@@ -2962,6 +2966,7 @@ namespace ts {
|
||||
case SyntaxKind.NumberKeyword:
|
||||
case SyntaxKind.BigIntKeyword:
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
case SyntaxKind.ReadonlyKeyword:
|
||||
case SyntaxKind.SymbolKeyword:
|
||||
case SyntaxKind.UniqueKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
@@ -3051,7 +3056,7 @@ namespace ts {
|
||||
return finishNode(postfix);
|
||||
}
|
||||
|
||||
function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword) {
|
||||
function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) {
|
||||
const node = <TypeOperatorNode>createNode(SyntaxKind.TypeOperator);
|
||||
parseExpected(operator);
|
||||
node.operator = operator;
|
||||
@@ -3073,6 +3078,7 @@ namespace ts {
|
||||
switch (operator) {
|
||||
case SyntaxKind.KeyOfKeyword:
|
||||
case SyntaxKind.UniqueKeyword:
|
||||
case SyntaxKind.ReadonlyKeyword:
|
||||
return parseTypeOperator(operator);
|
||||
case SyntaxKind.InferKeyword:
|
||||
return parseInferType();
|
||||
@@ -3687,9 +3693,11 @@ namespace ts {
|
||||
// - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
|
||||
// - "(x,y)" is a comma expression parsed as a signature with two parameters.
|
||||
// - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
|
||||
// - "a ? (b): function() {}" will too, since function() is a valid JSDoc function type.
|
||||
//
|
||||
// So we need just a bit of lookahead to ensure that it can only be a signature.
|
||||
if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && token() !== SyntaxKind.OpenBraceToken) {
|
||||
const hasJSDocFunctionType = node.type && isJSDocFunctionType(node.type);
|
||||
if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && (hasJSDocFunctionType || token() !== SyntaxKind.OpenBraceToken)) {
|
||||
// Returning undefined here will cause our caller to rewind to where we started from.
|
||||
return undefined;
|
||||
}
|
||||
@@ -4250,7 +4258,8 @@ namespace ts {
|
||||
|
||||
function parseJsxText(): JsxText {
|
||||
const node = <JsxText>createNode(SyntaxKind.JsxText);
|
||||
node.containsOnlyWhiteSpaces = currentToken === SyntaxKind.JsxTextAllWhiteSpaces;
|
||||
node.text = scanner.getTokenValue();
|
||||
node.containsOnlyTriviaWhiteSpaces = currentToken === SyntaxKind.JsxTextAllWhiteSpaces;
|
||||
currentToken = scanner.scanJsxToken();
|
||||
return finishNode(node);
|
||||
}
|
||||
@@ -4523,7 +4532,8 @@ namespace ts {
|
||||
function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression {
|
||||
while (true) {
|
||||
expression = parseMemberExpressionRest(expression);
|
||||
if (token() === SyntaxKind.LessThanToken) {
|
||||
// handle 'foo<<T>()'
|
||||
if (token() === SyntaxKind.LessThanToken || token() === SyntaxKind.LessThanLessThanToken) {
|
||||
// See if this is the start of a generic invocation. If so, consume it and
|
||||
// keep checking for postfix expressions. Otherwise, it's just a '<' that's
|
||||
// part of an arithmetic expression. Break out so we consume it higher in the
|
||||
@@ -4565,9 +4575,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function parseTypeArgumentsInExpression() {
|
||||
if (!parseOptional(SyntaxKind.LessThanToken)) {
|
||||
if (reScanLessThanToken() !== SyntaxKind.LessThanToken) {
|
||||
return undefined;
|
||||
}
|
||||
nextToken();
|
||||
|
||||
const typeArguments = parseDelimitedList(ParsingContext.TypeArguments, parseType);
|
||||
if (!parseExpected(SyntaxKind.GreaterThanToken)) {
|
||||
@@ -7740,20 +7751,21 @@ namespace ts {
|
||||
|
||||
context.pragmas = createMap() as PragmaMap;
|
||||
for (const pragma of pragmas) {
|
||||
if (context.pragmas.has(pragma!.name)) { // TODO: GH#18217
|
||||
const currentValue = context.pragmas.get(pragma!.name);
|
||||
if (context.pragmas.has(pragma.name)) {
|
||||
const currentValue = context.pragmas.get(pragma.name);
|
||||
if (currentValue instanceof Array) {
|
||||
currentValue.push(pragma!.args);
|
||||
currentValue.push(pragma.args);
|
||||
}
|
||||
else {
|
||||
context.pragmas.set(pragma!.name, [currentValue, pragma!.args]);
|
||||
context.pragmas.set(pragma.name, [currentValue, pragma.args]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
context.pragmas.set(pragma!.name, pragma!.args);
|
||||
context.pragmas.set(pragma.name, pragma.args);
|
||||
}
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
type PragmaDiagnosticReporter = (pos: number, length: number, message: DiagnosticMessage) => void;
|
||||
|
||||
/*@internal*/
|
||||
@@ -7773,9 +7785,8 @@ namespace ts {
|
||||
const typeReferenceDirectives = context.typeReferenceDirectives;
|
||||
const libReferenceDirectives = context.libReferenceDirectives;
|
||||
forEach(toArray(entryOrList), (arg: PragmaPseudoMap["reference"]) => {
|
||||
// TODO: GH#18217
|
||||
const { types, lib, path } = arg!.arguments;
|
||||
if (arg!.arguments["no-default-lib"]) {
|
||||
const { types, lib, path } = arg.arguments;
|
||||
if (arg.arguments["no-default-lib"]) {
|
||||
context.hasNoDefaultLib = true;
|
||||
}
|
||||
else if (types) {
|
||||
@@ -7788,7 +7799,7 @@ namespace ts {
|
||||
referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value });
|
||||
}
|
||||
else {
|
||||
reportDiagnostic(arg!.range.pos, arg!.range.end - arg!.range.pos, Diagnostics.Invalid_reference_directive_syntax);
|
||||
reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax);
|
||||
}
|
||||
});
|
||||
break;
|
||||
@@ -7796,7 +7807,7 @@ namespace ts {
|
||||
case "amd-dependency": {
|
||||
context.amdDependencies = map(
|
||||
toArray(entryOrList),
|
||||
(x: PragmaPseudoMap["amd-dependency"]) => ({ name: x!.arguments.name!, path: x!.arguments.path })); // TODO: GH#18217
|
||||
(x: PragmaPseudoMap["amd-dependency"]) => ({ name: x.arguments.name, path: x.arguments.path }));
|
||||
break;
|
||||
}
|
||||
case "amd-module": {
|
||||
@@ -7804,13 +7815,13 @@ namespace ts {
|
||||
for (const entry of entryOrList) {
|
||||
if (context.moduleName) {
|
||||
// TODO: It's probably fine to issue this diagnostic on all instances of the pragma
|
||||
reportDiagnostic(entry!.range.pos, entry!.range.end - entry!.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
|
||||
reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
|
||||
}
|
||||
context.moduleName = (entry as PragmaPseudoMap["amd-module"])!.arguments.name;
|
||||
context.moduleName = (entry as PragmaPseudoMap["amd-module"]).arguments.name;
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"])!.arguments.name;
|
||||
context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"]).arguments.name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -7818,11 +7829,11 @@ namespace ts {
|
||||
case "ts-check": {
|
||||
// _last_ of either nocheck or check in a file is the "winner"
|
||||
forEach(toArray(entryOrList), entry => {
|
||||
if (!context.checkJsDirective || entry!.range.pos > context.checkJsDirective.pos) { // TODO: GH#18217
|
||||
if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) {
|
||||
context.checkJsDirective = {
|
||||
enabled: key === "ts-check",
|
||||
end: entry!.range.end,
|
||||
pos: entry!.range.pos
|
||||
end: entry.range.end,
|
||||
pos: entry.range.pos
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
+159
-93
@@ -69,16 +69,12 @@ namespace ts {
|
||||
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
|
||||
return createCompilerHostWorker(options, setParentNodes);
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
// TODO(shkamat): update this after reworking ts build API
|
||||
export function createCompilerHostWorker(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost {
|
||||
const existingDirectories = createMap<boolean>();
|
||||
function getCanonicalFileName(fileName: string): string {
|
||||
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
|
||||
// otherwise use toLowerCase as a canonical form.
|
||||
return system.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
|
||||
}
|
||||
|
||||
const getCanonicalFileName = createGetCanonicalFileName(system.useCaseSensitiveFileNames);
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined {
|
||||
let text: string | undefined;
|
||||
try {
|
||||
@@ -93,7 +89,6 @@ namespace ts {
|
||||
}
|
||||
text = "";
|
||||
}
|
||||
|
||||
return text !== undefined ? createSourceFile(fileName, text, languageVersion, setParentNodes) : undefined;
|
||||
}
|
||||
|
||||
@@ -198,23 +193,32 @@ namespace ts {
|
||||
getDirectories: (path: string) => system.getDirectories(path),
|
||||
realpath,
|
||||
readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth),
|
||||
createDirectory: d => system.createDirectory(d)
|
||||
createDirectory: d => system.createDirectory(d),
|
||||
createHash: maybeBind(system, system.createHash)
|
||||
};
|
||||
return compilerHost;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function changeCompilerHostToUseCache(
|
||||
host: CompilerHost,
|
||||
interface CompilerHostLikeForCache {
|
||||
fileExists(fileName: string): boolean;
|
||||
readFile(fileName: string, encoding?: string): string | undefined;
|
||||
directoryExists?(directory: string): boolean;
|
||||
createDirectory?(directory: string): void;
|
||||
writeFile?: WriteFileCallback;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function changeCompilerHostLikeToUseCache(
|
||||
host: CompilerHostLikeForCache,
|
||||
toPath: (fileName: string) => Path,
|
||||
useCacheForSourceFile: boolean
|
||||
getSourceFile?: CompilerHost["getSourceFile"]
|
||||
) {
|
||||
const originalReadFile = host.readFile;
|
||||
const originalFileExists = host.fileExists;
|
||||
const originalDirectoryExists = host.directoryExists;
|
||||
const originalCreateDirectory = host.createDirectory;
|
||||
const originalWriteFile = host.writeFile;
|
||||
const originalGetSourceFile = host.getSourceFile;
|
||||
const readFileCache = createMap<string | false>();
|
||||
const fileExistsCache = createMap<boolean>();
|
||||
const directoryExistsCache = createMap<boolean>();
|
||||
@@ -223,38 +227,37 @@ namespace ts {
|
||||
const readFileWithCache = (fileName: string): string | undefined => {
|
||||
const key = toPath(fileName);
|
||||
const value = readFileCache.get(key);
|
||||
if (value !== undefined) return value || undefined;
|
||||
if (value !== undefined) return value !== false ? value : undefined;
|
||||
return setReadFileCache(key, fileName);
|
||||
};
|
||||
const setReadFileCache = (key: Path, fileName: string) => {
|
||||
const newValue = originalReadFile.call(host, fileName);
|
||||
readFileCache.set(key, newValue || false);
|
||||
readFileCache.set(key, newValue !== undefined ? newValue : false);
|
||||
return newValue;
|
||||
};
|
||||
host.readFile = fileName => {
|
||||
const key = toPath(fileName);
|
||||
const value = readFileCache.get(key);
|
||||
if (value !== undefined) return value; // could be .d.ts from output
|
||||
if (!fileExtensionIs(fileName, Extension.Json)) {
|
||||
if (value !== undefined) return value !== false ? value : undefined; // could be .d.ts from output
|
||||
// Cache json or buildInfo
|
||||
if (!fileExtensionIs(fileName, Extension.Json) && !isBuildInfoFile(fileName)) {
|
||||
return originalReadFile.call(host, fileName);
|
||||
}
|
||||
|
||||
return setReadFileCache(key, fileName);
|
||||
};
|
||||
|
||||
if (useCacheForSourceFile) {
|
||||
host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
|
||||
const key = toPath(fileName);
|
||||
const value = sourceFileCache.get(key);
|
||||
if (value) return value;
|
||||
const getSourceFileWithCache: CompilerHost["getSourceFile"] | undefined = getSourceFile ? (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
|
||||
const key = toPath(fileName);
|
||||
const value = sourceFileCache.get(key);
|
||||
if (value) return value;
|
||||
|
||||
const sourceFile = originalGetSourceFile.call(host, fileName, languageVersion, onError, shouldCreateNewSourceFile);
|
||||
if (sourceFile && (isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json))) {
|
||||
sourceFileCache.set(key, sourceFile);
|
||||
}
|
||||
return sourceFile;
|
||||
};
|
||||
}
|
||||
const sourceFile = getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);
|
||||
if (sourceFile && (isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json))) {
|
||||
sourceFileCache.set(key, sourceFile);
|
||||
}
|
||||
return sourceFile;
|
||||
} : undefined;
|
||||
|
||||
// fileExists for any kind of extension
|
||||
host.fileExists = fileName => {
|
||||
@@ -265,23 +268,25 @@ namespace ts {
|
||||
fileExistsCache.set(key, !!newValue);
|
||||
return newValue;
|
||||
};
|
||||
host.writeFile = (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
|
||||
const key = toPath(fileName);
|
||||
fileExistsCache.delete(key);
|
||||
if (originalWriteFile) {
|
||||
host.writeFile = (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
|
||||
const key = toPath(fileName);
|
||||
fileExistsCache.delete(key);
|
||||
|
||||
const value = readFileCache.get(key);
|
||||
if (value && value !== data) {
|
||||
readFileCache.delete(key);
|
||||
sourceFileCache.delete(key);
|
||||
}
|
||||
else if (useCacheForSourceFile) {
|
||||
const sourceFile = sourceFileCache.get(key);
|
||||
if (sourceFile && sourceFile.text !== data) {
|
||||
const value = readFileCache.get(key);
|
||||
if (value !== undefined && value !== data) {
|
||||
readFileCache.delete(key);
|
||||
sourceFileCache.delete(key);
|
||||
}
|
||||
}
|
||||
originalWriteFile.call(host, fileName, data, writeByteOrderMark, onError, sourceFiles);
|
||||
};
|
||||
else if (getSourceFileWithCache) {
|
||||
const sourceFile = sourceFileCache.get(key);
|
||||
if (sourceFile && sourceFile.text !== data) {
|
||||
sourceFileCache.delete(key);
|
||||
}
|
||||
}
|
||||
originalWriteFile.call(host, fileName, data, writeByteOrderMark, onError, sourceFiles);
|
||||
};
|
||||
}
|
||||
|
||||
// directoryExists
|
||||
if (originalDirectoryExists && originalCreateDirectory) {
|
||||
@@ -306,12 +311,15 @@ namespace ts {
|
||||
originalDirectoryExists,
|
||||
originalCreateDirectory,
|
||||
originalWriteFile,
|
||||
originalGetSourceFile,
|
||||
getSourceFileWithCache,
|
||||
readFileWithCache
|
||||
};
|
||||
}
|
||||
|
||||
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic> {
|
||||
// tslint:disable unified-signatures
|
||||
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
/*@internal*/ export function getPreEmitDiagnostics(program: BuilderProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
export function getPreEmitDiagnostics(program: Program | BuilderProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic> {
|
||||
const diagnostics = [
|
||||
...program.getConfigFileParsingDiagnostics(),
|
||||
...program.getOptionsDiagnostics(cancellationToken),
|
||||
@@ -326,6 +334,7 @@ namespace ts {
|
||||
|
||||
return sortAndDeduplicateDiagnostics(diagnostics);
|
||||
}
|
||||
// tslint:enable unified-signatures
|
||||
|
||||
export interface FormatDiagnosticsHost {
|
||||
getCurrentDirectory(): string;
|
||||
@@ -735,7 +744,7 @@ namespace ts {
|
||||
performance.mark("beforeProgram");
|
||||
|
||||
const host = createProgramOptions.host || createCompilerHost(options);
|
||||
const configParsingHost = parseConfigHostFromCompilerHost(host);
|
||||
const configParsingHost = parseConfigHostFromCompilerHostLike(host);
|
||||
|
||||
let skipDefaultLib = options.noLib;
|
||||
const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options));
|
||||
@@ -816,11 +825,16 @@ namespace ts {
|
||||
}
|
||||
if (rootNames.length) {
|
||||
for (const parsedRef of resolvedProjectReferences) {
|
||||
if (parsedRef) {
|
||||
const out = parsedRef.commandLine.options.outFile || parsedRef.commandLine.options.out;
|
||||
if (out) {
|
||||
const dtsOutfile = changeExtension(out, ".d.ts");
|
||||
processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
if (!parsedRef) continue;
|
||||
const out = parsedRef.commandLine.options.outFile || parsedRef.commandLine.options.out;
|
||||
if (out) {
|
||||
processSourceFile(changeExtension(out, ".d.ts"), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
else if (getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) {
|
||||
for (const fileName of parsedRef.commandLine.fileNames) {
|
||||
if (!fileExtensionIs(fileName, Extension.Dts) && hasTSFileExtension(fileName)) {
|
||||
processSourceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames()), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -930,7 +944,8 @@ namespace ts {
|
||||
getProjectReferenceRedirect,
|
||||
getResolvedProjectReferenceToRedirect,
|
||||
getResolvedProjectReferenceByPath,
|
||||
forEachResolvedProjectReference
|
||||
forEachResolvedProjectReference,
|
||||
emitBuildInfo
|
||||
};
|
||||
|
||||
verifyCompilerOptions();
|
||||
@@ -964,7 +979,7 @@ namespace ts {
|
||||
|
||||
function getCommonSourceDirectory() {
|
||||
if (commonSourceDirectory === undefined) {
|
||||
const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary));
|
||||
const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary, getResolvedProjectReferenceToRedirect));
|
||||
if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) {
|
||||
// If a rootDir is specified use it as the commonSourceDirectory
|
||||
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
|
||||
@@ -1410,6 +1425,7 @@ namespace ts {
|
||||
getSourceFiles: program.getSourceFiles,
|
||||
getLibFileFromReference: program.getLibFileFromReference,
|
||||
isSourceFileFromExternalLibrary,
|
||||
getResolvedProjectReferenceToRedirect,
|
||||
writeFile: writeFileCallback || (
|
||||
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
|
||||
isEmitBlocked,
|
||||
@@ -1424,9 +1440,28 @@ namespace ts {
|
||||
},
|
||||
...(host.directoryExists ? { directoryExists: f => host.directoryExists!(f) } : {}),
|
||||
useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(),
|
||||
getProgramBuildInfo: () => program.getProgramBuildInfo && program.getProgramBuildInfo()
|
||||
};
|
||||
}
|
||||
|
||||
function emitBuildInfo(writeFileCallback?: WriteFileCallback): EmitResult {
|
||||
Debug.assert(!options.out && !options.outFile);
|
||||
performance.mark("beforeEmit");
|
||||
const emitResult = emitFiles(
|
||||
notImplementedResolver,
|
||||
getEmitHost(writeFileCallback),
|
||||
/*targetSourceFile*/ undefined,
|
||||
/*emitOnlyDtsFiles*/ false,
|
||||
/*transformers*/ undefined,
|
||||
/*declaraitonTransformers*/ undefined,
|
||||
/*onlyBuildInfo*/ true
|
||||
);
|
||||
|
||||
performance.mark("afterEmit");
|
||||
performance.measure("Emit", "beforeEmit", "afterEmit");
|
||||
return emitResult;
|
||||
}
|
||||
|
||||
function getResolvedProjectReferences() {
|
||||
return resolvedProjectReferences;
|
||||
}
|
||||
@@ -1435,32 +1470,16 @@ namespace ts {
|
||||
return projectReferences;
|
||||
}
|
||||
|
||||
function getPrependNodes(): InputFiles[] {
|
||||
if (!projectReferences) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
const nodes: InputFiles[] = [];
|
||||
for (let i = 0; i < projectReferences.length; i++) {
|
||||
const ref = projectReferences[i];
|
||||
const resolvedRefOpts = resolvedProjectReferences![i]!.commandLine;
|
||||
if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) {
|
||||
const out = resolvedRefOpts.options.outFile || resolvedRefOpts.options.out;
|
||||
// Upstream project didn't have outFile set -- skip (error will have been issued earlier)
|
||||
if (!out) continue;
|
||||
|
||||
const dtsFilename = changeExtension(out, ".d.ts");
|
||||
const js = host.readFile(out) || `/* Input file ${out} was missing */\r\n`;
|
||||
const jsMapPath = out + ".map"; // TODO: try to read sourceMappingUrl comment from the file
|
||||
const jsMap = host.readFile(jsMapPath);
|
||||
const dts = host.readFile(dtsFilename) || `/* Input file ${dtsFilename} was missing */\r\n`;
|
||||
const dtsMapPath = dtsFilename + ".map";
|
||||
const dtsMap = host.readFile(dtsMapPath);
|
||||
const node = createInputFiles(js, dts, jsMap && jsMapPath, jsMap, dtsMap && dtsMapPath, dtsMap);
|
||||
nodes.push(node);
|
||||
function getPrependNodes() {
|
||||
return createPrependNodes(
|
||||
projectReferences,
|
||||
(_ref, index) => resolvedProjectReferences![index]!.commandLine,
|
||||
fileName => {
|
||||
const path = toPath(fileName);
|
||||
const sourceFile = getSourceFileByPath(path);
|
||||
return sourceFile ? sourceFile.text : filesByName.has(path) ? undefined : host.readFile(path);
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
);
|
||||
}
|
||||
|
||||
function isSourceFileFromExternalLibrary(file: SourceFile): boolean {
|
||||
@@ -1557,7 +1576,7 @@ namespace ts {
|
||||
const emitResult = emitFiles(
|
||||
emitResolver,
|
||||
getEmitHost(writeFileCallback),
|
||||
sourceFile!, // TODO: GH#18217
|
||||
sourceFile,
|
||||
emitOnlyDtsFiles,
|
||||
transformers,
|
||||
customTransformers && customTransformers.afterDeclarations
|
||||
@@ -2249,7 +2268,6 @@ namespace ts {
|
||||
if (refFile) {
|
||||
const redirect = getProjectReferenceRedirect(fileName);
|
||||
if (redirect) {
|
||||
((refFile.redirectedReferences || (refFile.redirectedReferences = [])) as string[]).push(fileName);
|
||||
fileName = redirect;
|
||||
// Once we start redirecting to a file, we can potentially come back to it
|
||||
// via a back-reference from another file in the .d.ts folder. If that happens we'll
|
||||
@@ -2360,7 +2378,7 @@ namespace ts {
|
||||
const out = referencedProject.commandLine.options.outFile || referencedProject.commandLine.options.out;
|
||||
return out ?
|
||||
changeExtension(out, Extension.Dts) :
|
||||
getOutputDeclarationFileName(fileName, referencedProject.commandLine);
|
||||
getOutputDeclarationFileName(fileName, referencedProject.commandLine, !host.useCaseSensitiveFileNames());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2707,19 +2725,32 @@ namespace ts {
|
||||
if (options.declaration === false) {
|
||||
createDiagnosticForOptionName(Diagnostics.Composite_projects_may_not_disable_declaration_emit, "declaration");
|
||||
}
|
||||
if (options.incremental === false) {
|
||||
createDiagnosticForOptionName(Diagnostics.Composite_projects_may_not_disable_incremental_compilation, "declaration");
|
||||
}
|
||||
}
|
||||
|
||||
if (options.tsBuildInfoFile) {
|
||||
if (!isIncrementalCompilation(options)) {
|
||||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "tsBuildInfoFile", "incremental", "composite");
|
||||
}
|
||||
}
|
||||
else if (options.incremental && !options.outFile && !options.out && !options.configFilePath) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_incremental_can_only_be_specified_using_tsconfig_emitting_to_single_file_or_when_option_tsBuildInfoFile_is_specified));
|
||||
}
|
||||
|
||||
verifyProjectReferences();
|
||||
|
||||
// List of collected files is complete; validate exhautiveness if this is a project with a file list
|
||||
if (options.composite) {
|
||||
const sourceFiles = files.filter(f => !f.isDeclarationFile);
|
||||
if (rootNames.length < sourceFiles.length) {
|
||||
const normalizedRootNames = rootNames.map(r => normalizePath(r).toLowerCase());
|
||||
for (const file of sourceFiles.map(f => normalizePath(f.path).toLowerCase())) {
|
||||
if (normalizedRootNames.indexOf(file) === -1) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_in_project_file_list_Projects_must_list_all_files_or_use_an_include_pattern, file));
|
||||
}
|
||||
const rootPaths = rootNames.map(toPath);
|
||||
for (const file of files) {
|
||||
// Ignore declaration files
|
||||
if (file.isDeclarationFile) continue;
|
||||
// Ignore json file thats from project reference
|
||||
if (isJsonSourceFile(file) && getResolvedProjectReferenceToRedirect(file.fileName)) continue;
|
||||
if (rootPaths.indexOf(file.path) === -1) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_in_project_file_list_Projects_must_list_all_files_or_use_an_include_pattern, file.fileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2928,6 +2959,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function verifyProjectReferences() {
|
||||
const buildInfoPath = !options.noEmit && !options.suppressOutputPathCheck ? getOutputPathForBuildInfo(options) : undefined;
|
||||
forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, index, parent) => {
|
||||
const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index];
|
||||
const parentFile = parent && parent.sourceFile as JsonSourceFile;
|
||||
@@ -2954,6 +2986,10 @@ namespace ts {
|
||||
createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set, ref.path);
|
||||
}
|
||||
}
|
||||
if (!parent && buildInfoPath && buildInfoPath === getOutputPathForBuildInfo(options)) {
|
||||
createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_write_file_0_because_it_will_overwrite_tsbuildinfo_file_generated_by_referenced_project_1, buildInfoPath, ref.path);
|
||||
hasEmitBlockingDiagnostics.set(toPath(buildInfoPath), true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3104,18 +3140,29 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
interface CompilerHostLike {
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
getCurrentDirectory(): string;
|
||||
fileExists(fileName: string): boolean;
|
||||
readFile(fileName: string): string | undefined;
|
||||
readDirectory?(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string>, depth?: number): string[];
|
||||
trace?(s: string): void;
|
||||
onUnRecoverableConfigFileDiagnostic?: DiagnosticReporter;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function parseConfigHostFromCompilerHost(host: CompilerHost): ParseConfigFileHost {
|
||||
export function parseConfigHostFromCompilerHostLike(host: CompilerHostLike, directoryStructureHost: DirectoryStructureHost = host): ParseConfigFileHost {
|
||||
return {
|
||||
fileExists: f => host.fileExists(f),
|
||||
fileExists: f => directoryStructureHost.fileExists(f),
|
||||
readDirectory(root, extensions, excludes, includes, depth) {
|
||||
Debug.assertDefined(host.readDirectory, "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'");
|
||||
return host.readDirectory!(root, extensions, excludes, includes, depth);
|
||||
Debug.assertDefined(directoryStructureHost.readDirectory, "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'");
|
||||
return directoryStructureHost.readDirectory!(root, extensions, excludes, includes, depth);
|
||||
},
|
||||
readFile: f => host.readFile(f),
|
||||
readFile: f => directoryStructureHost.readFile(f),
|
||||
useCaseSensitiveFileNames: host.useCaseSensitiveFileNames(),
|
||||
getCurrentDirectory: () => host.getCurrentDirectory(),
|
||||
onUnRecoverableConfigFileDiagnostic: () => undefined,
|
||||
onUnRecoverableConfigFileDiagnostic: host.onUnRecoverableConfigFileDiagnostic || returnUndefined,
|
||||
trace: host.trace ? (s) => host.trace!(s) : undefined
|
||||
};
|
||||
}
|
||||
@@ -3125,6 +3172,25 @@ namespace ts {
|
||||
fileExists(fileName: string): boolean;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function createPrependNodes(projectReferences: ReadonlyArray<ProjectReference> | undefined, getCommandLine: (ref: ProjectReference, index: number) => ParsedCommandLine | undefined, readFile: (path: string) => string | undefined) {
|
||||
if (!projectReferences) return emptyArray;
|
||||
let nodes: InputFiles[] | undefined;
|
||||
for (let i = 0; i < projectReferences.length; i++) {
|
||||
const ref = projectReferences[i];
|
||||
const resolvedRefOpts = getCommandLine(ref, i);
|
||||
if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) {
|
||||
const out = resolvedRefOpts.options.outFile || resolvedRefOpts.options.out;
|
||||
// Upstream project didn't have outFile set -- skip (error will have been issued earlier)
|
||||
if (!out) continue;
|
||||
|
||||
const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true);
|
||||
const node = createInputFiles(readFile, jsFilePath!, sourceMapFilePath, declarationFilePath!, declarationMapPath, buildInfoPath);
|
||||
(nodes || (nodes = [])).push(node);
|
||||
}
|
||||
}
|
||||
return nodes || emptyArray;
|
||||
}
|
||||
/**
|
||||
* Returns the target config filename of a project reference.
|
||||
* Note: The file might not exist.
|
||||
|
||||
@@ -71,8 +71,8 @@ namespace ts {
|
||||
nonRecursive?: boolean;
|
||||
}
|
||||
|
||||
export function isPathInNodeModulesStartingWithDot(path: Path) {
|
||||
return stringContains(path, "/node_modules/.");
|
||||
export function isPathIgnored(path: Path) {
|
||||
return some(ignoredPaths, searchPath => stringContains(path, searchPath));
|
||||
}
|
||||
|
||||
export const maxNumberOfFilesToIterateForInvalidation = 256;
|
||||
@@ -696,7 +696,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
// If something to do with folder/file starting with "." in node_modules folder, skip it
|
||||
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return false;
|
||||
if (isPathIgnored(fileOrDirectoryPath)) return false;
|
||||
|
||||
// Some file or directory in the watching directory is created
|
||||
// Return early if it does not have any of the watching extension or not the custom failed lookup path
|
||||
|
||||
+23
-3
@@ -31,6 +31,7 @@ namespace ts {
|
||||
scanJsxIdentifier(): SyntaxKind;
|
||||
scanJsxAttributeValue(): SyntaxKind;
|
||||
reScanJsxToken(): JsxTokenSyntaxKind;
|
||||
reScanLessThanToken(): SyntaxKind;
|
||||
scanJsxToken(): JsxTokenSyntaxKind;
|
||||
scanJSDocToken(): JsDocSyntaxKind;
|
||||
scan(): SyntaxKind;
|
||||
@@ -622,13 +623,15 @@ namespace ts {
|
||||
|
||||
const shebangTriviaRegex = /^#!.*/;
|
||||
|
||||
function isShebangTrivia(text: string, pos: number) {
|
||||
/*@internal*/
|
||||
export function isShebangTrivia(text: string, pos: number) {
|
||||
// Shebangs check must only be done at the start of the file
|
||||
Debug.assert(pos === 0);
|
||||
return shebangTriviaRegex.test(text);
|
||||
}
|
||||
|
||||
function scanShebangTrivia(text: string, pos: number) {
|
||||
/*@internal*/
|
||||
export function scanShebangTrivia(text: string, pos: number) {
|
||||
const shebang = shebangTriviaRegex.exec(text)![0];
|
||||
pos = pos + shebang.length;
|
||||
return pos;
|
||||
@@ -660,8 +663,15 @@ namespace ts {
|
||||
let pendingKind!: CommentKind;
|
||||
let pendingHasTrailingNewLine!: boolean;
|
||||
let hasPendingCommentRange = false;
|
||||
let collecting = trailing || pos === 0;
|
||||
let collecting = trailing;
|
||||
let accumulator = initial;
|
||||
if (pos === 0) {
|
||||
collecting = true;
|
||||
const shebang = getShebang(text);
|
||||
if (shebang) {
|
||||
pos = shebang.length;
|
||||
}
|
||||
}
|
||||
scan: while (pos >= 0 && pos < text.length) {
|
||||
const ch = text.charCodeAt(pos);
|
||||
switch (ch) {
|
||||
@@ -874,6 +884,7 @@ namespace ts {
|
||||
scanJsxIdentifier,
|
||||
scanJsxAttributeValue,
|
||||
reScanJsxToken,
|
||||
reScanLessThanToken,
|
||||
scanJsxToken,
|
||||
scanJSDocToken,
|
||||
scan,
|
||||
@@ -1939,6 +1950,14 @@ namespace ts {
|
||||
return token = scanJsxToken();
|
||||
}
|
||||
|
||||
function reScanLessThanToken(): SyntaxKind {
|
||||
if (token === SyntaxKind.LessThanLessThanToken) {
|
||||
pos = tokenPos + 1;
|
||||
return token = SyntaxKind.LessThanToken;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
function scanJsxToken(): JsxTokenSyntaxKind {
|
||||
startPos = tokenPos = pos;
|
||||
|
||||
@@ -1994,6 +2013,7 @@ namespace ts {
|
||||
pos++;
|
||||
}
|
||||
|
||||
tokenValue = text.substring(startPos, pos);
|
||||
return firstNonWhitespace === -1 ? SyntaxKind.JsxTextAllWhiteSpaces : SyntaxKind.JsxText;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace ts {
|
||||
exit();
|
||||
}
|
||||
|
||||
function appendSourceMap(generatedLine: number, generatedCharacter: number, map: RawSourceMap, sourceMapPath: string) {
|
||||
function appendSourceMap(generatedLine: number, generatedCharacter: number, map: RawSourceMap, sourceMapPath: string, start?: LineAndCharacter, end?: LineAndCharacter) {
|
||||
Debug.assert(generatedLine >= pendingGeneratedLine, "generatedLine cannot backtrack");
|
||||
Debug.assert(generatedCharacter >= 0, "generatedCharacter cannot be negative");
|
||||
enter();
|
||||
@@ -149,6 +149,17 @@ namespace ts {
|
||||
let nameIndexToNewNameIndexMap: number[] | undefined;
|
||||
const mappingIterator = decodeMappings(map.mappings);
|
||||
for (let { value: raw, done } = mappingIterator.next(); !done; { value: raw, done } = mappingIterator.next()) {
|
||||
if (end && (
|
||||
raw.generatedLine > end.line ||
|
||||
(raw.generatedLine === end.line && raw.generatedCharacter > end.character))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (start && (
|
||||
raw.generatedLine < start.line ||
|
||||
(start.line === raw.generatedLine && raw.generatedCharacter < start.character))) {
|
||||
continue;
|
||||
}
|
||||
// Then reencode all the updated mappings into the overall map
|
||||
let newSourceIndex: number | undefined;
|
||||
let newSourceLine: number | undefined;
|
||||
@@ -178,8 +189,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const newGeneratedLine = raw.generatedLine + generatedLine;
|
||||
const newGeneratedCharacter = raw.generatedLine === 0 ? raw.generatedCharacter + generatedCharacter : raw.generatedCharacter;
|
||||
const rawGeneratedLine = raw.generatedLine - (start ? start.line : 0);
|
||||
const newGeneratedLine = rawGeneratedLine + generatedLine;
|
||||
const rawGeneratedCharacter = start && start.line === raw.generatedLine ? raw.generatedCharacter - start.character : raw.generatedCharacter;
|
||||
const newGeneratedCharacter = rawGeneratedLine === 0 ? rawGeneratedCharacter + generatedCharacter : rawGeneratedCharacter;
|
||||
addMapping(newGeneratedLine, newGeneratedCharacter, newSourceIndex, newSourceLine, newSourceCharacter, newNameIndex);
|
||||
}
|
||||
exit();
|
||||
|
||||
+102
-19
@@ -2,6 +2,19 @@ declare function setTimeout(handler: (...args: any[]) => void, timeout: number):
|
||||
declare function clearTimeout(handle: any): void;
|
||||
|
||||
namespace ts {
|
||||
/**
|
||||
* djb2 hashing algorithm
|
||||
* http://www.cse.yorku.ca/~oz/hash.html
|
||||
*/
|
||||
/* @internal */
|
||||
export function generateDjb2Hash(data: string): string {
|
||||
let acc = 5381;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
acc = ((acc << 5) + acc) + data.charCodeAt(i);
|
||||
}
|
||||
return acc.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a high stack trace limit to provide more information in case of an error.
|
||||
* Called for command-line and server use cases.
|
||||
@@ -316,6 +329,9 @@ namespace ts {
|
||||
: FileWatcherEventKind.Changed;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export const ignoredPaths = ["/node_modules/.", "/.git"];
|
||||
|
||||
/*@internal*/
|
||||
export interface RecursiveDirectoryWatcherHost {
|
||||
watchDirectory: HostWatchDirectory;
|
||||
@@ -361,6 +377,8 @@ namespace ts {
|
||||
else {
|
||||
directoryWatcher = {
|
||||
watcher: host.watchDirectory(dirName, fileName => {
|
||||
if (isIgnoredPath(fileName)) return;
|
||||
|
||||
// Call the actual callback
|
||||
callbackCache.forEach((callbacks, rootDirName) => {
|
||||
if (rootDirName === dirPath || (startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === directorySeparator)) {
|
||||
@@ -416,7 +434,7 @@ namespace ts {
|
||||
const childFullName = getNormalizedAbsolutePath(child, parentDir);
|
||||
// Filter our the symbolic link directories since those arent included in recursive watch
|
||||
// which is same behaviour when recursive: true is passed to fs.watch
|
||||
return filePathComparer(childFullName, normalizePath(host.realpath(childFullName))) === Comparison.EqualTo ? childFullName : undefined;
|
||||
return !isIgnoredPath(childFullName) && filePathComparer(childFullName, normalizePath(host.realpath(childFullName))) === Comparison.EqualTo ? childFullName : undefined;
|
||||
}) : emptyArray,
|
||||
existingChildWatches,
|
||||
(child, childWatcher) => filePathComparer(child, childWatcher.dirName),
|
||||
@@ -442,8 +460,78 @@ namespace ts {
|
||||
(newChildWatches || (newChildWatches = [])).push(childWatcher);
|
||||
}
|
||||
}
|
||||
|
||||
function isIgnoredPath(path: string) {
|
||||
return some(ignoredPaths, searchPath => isInPath(path, searchPath));
|
||||
}
|
||||
|
||||
function isInPath(path: string, searchPath: string) {
|
||||
if (stringContains(path, searchPath)) return true;
|
||||
if (host.useCaseSensitiveFileNames) return false;
|
||||
return stringContains(toCanonicalFilePath(path), searchPath);
|
||||
}
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
interface NodeBuffer extends Uint8Array {
|
||||
write(str: string, offset?: number, length?: number, encoding?: string): number;
|
||||
toString(encoding?: string, start?: number, end?: number): string;
|
||||
toJSON(): { type: "Buffer", data: any[] };
|
||||
equals(otherBuffer: Buffer): boolean;
|
||||
compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;
|
||||
copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
|
||||
slice(start?: number, end?: number): Buffer;
|
||||
writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readUInt8(offset: number, noAssert?: boolean): number;
|
||||
readUInt16LE(offset: number, noAssert?: boolean): number;
|
||||
readUInt16BE(offset: number, noAssert?: boolean): number;
|
||||
readUInt32LE(offset: number, noAssert?: boolean): number;
|
||||
readUInt32BE(offset: number, noAssert?: boolean): number;
|
||||
readInt8(offset: number, noAssert?: boolean): number;
|
||||
readInt16LE(offset: number, noAssert?: boolean): number;
|
||||
readInt16BE(offset: number, noAssert?: boolean): number;
|
||||
readInt32LE(offset: number, noAssert?: boolean): number;
|
||||
readInt32BE(offset: number, noAssert?: boolean): number;
|
||||
readFloatLE(offset: number, noAssert?: boolean): number;
|
||||
readFloatBE(offset: number, noAssert?: boolean): number;
|
||||
readDoubleLE(offset: number, noAssert?: boolean): number;
|
||||
readDoubleBE(offset: number, noAssert?: boolean): number;
|
||||
swap16(): Buffer;
|
||||
swap32(): Buffer;
|
||||
swap64(): Buffer;
|
||||
writeUInt8(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt8(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt16LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt16BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt32LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt32BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeFloatLE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeFloatBE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;
|
||||
fill(value: any, offset?: number, end?: number): this;
|
||||
indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
|
||||
lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;
|
||||
keys(): IterableIterator<number>;
|
||||
values(): IterableIterator<number>;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
interface Buffer extends NodeBuffer { }
|
||||
|
||||
// TODO: GH#18217 Methods on System are often used as if they are certainly defined
|
||||
export interface System {
|
||||
args: string[];
|
||||
@@ -605,7 +693,17 @@ namespace ts {
|
||||
directoryExists,
|
||||
createDirectory(directoryName: string) {
|
||||
if (!nodeSystem.directoryExists(directoryName)) {
|
||||
_fs.mkdirSync(directoryName);
|
||||
// Wrapped in a try-catch to prevent crashing if we are in a race
|
||||
// with another copy of ourselves to create the same directory
|
||||
try {
|
||||
_fs.mkdirSync(directoryName);
|
||||
}
|
||||
catch (e) {
|
||||
if (e.code !== "EEXIST") {
|
||||
// Failed for some other reason (access denied?); still throw
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
getExecutingFilePath() {
|
||||
@@ -622,7 +720,7 @@ namespace ts {
|
||||
getModifiedTime,
|
||||
setModifiedTime,
|
||||
deleteFile,
|
||||
createHash: _crypto ? createMD5HashUsingNativeCrypto : generateDjb2Hash,
|
||||
createHash: _crypto ? createSHA256Hash : generateDjb2Hash,
|
||||
createSHA256Hash: _crypto ? createSHA256Hash : undefined,
|
||||
getMemoryUsage() {
|
||||
if (global.gc) {
|
||||
@@ -1050,7 +1148,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extensions?: ReadonlyArray<string>, excludes?: ReadonlyArray<string>, includes?: ReadonlyArray<string>, depth?: number): string[] {
|
||||
return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries);
|
||||
return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath);
|
||||
}
|
||||
|
||||
function fileSystemEntryExists(path: string, entryKind: FileSystemEntryKind): boolean {
|
||||
@@ -1115,21 +1213,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* djb2 hashing algorithm
|
||||
* http://www.cse.yorku.ca/~oz/hash.html
|
||||
*/
|
||||
function generateDjb2Hash(data: string): string {
|
||||
const chars = data.split("").map(str => str.charCodeAt(0));
|
||||
return `${chars.reduce((prev, curr) => ((prev << 5) + prev) + curr, 5381)}`;
|
||||
}
|
||||
|
||||
function createMD5HashUsingNativeCrypto(data: string): string {
|
||||
const hash = _crypto!.createHash("md5");
|
||||
hash.update(data);
|
||||
return hash.digest("hex");
|
||||
}
|
||||
|
||||
function createSHA256Hash(data: string): string {
|
||||
const hash = _crypto!.createHash("sha256");
|
||||
hash.update(data);
|
||||
|
||||
@@ -42,6 +42,14 @@ namespace ts {
|
||||
transformers.push(transformESNext);
|
||||
}
|
||||
|
||||
if (languageVersion < ScriptTarget.ES2019) {
|
||||
transformers.push(transformES2019);
|
||||
}
|
||||
|
||||
if (languageVersion < ScriptTarget.ES2018) {
|
||||
transformers.push(transformES2018);
|
||||
}
|
||||
|
||||
if (languageVersion < ScriptTarget.ES2017) {
|
||||
transformers.push(transformES2017);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,34 @@ namespace ts {
|
||||
return result.diagnostics;
|
||||
}
|
||||
|
||||
function hasInternalAnnotation(range: CommentRange, currentSourceFile: SourceFile) {
|
||||
const comment = currentSourceFile.text.substring(range.pos, range.end);
|
||||
return stringContains(comment, "@internal");
|
||||
}
|
||||
|
||||
export function isInternalDeclaration(node: Node, currentSourceFile: SourceFile) {
|
||||
const parseTreeNode = getParseTreeNode(node);
|
||||
if (parseTreeNode && parseTreeNode.kind === SyntaxKind.Parameter) {
|
||||
const paramIdx = (parseTreeNode.parent as FunctionLike).parameters.indexOf(parseTreeNode as ParameterDeclaration);
|
||||
const previousSibling = paramIdx > 0 ? (parseTreeNode.parent as FunctionLike).parameters[paramIdx - 1] : undefined;
|
||||
const text = currentSourceFile.text;
|
||||
const commentRanges = previousSibling
|
||||
? concatenate(
|
||||
// to handle
|
||||
// ... parameters, /* @internal */
|
||||
// public param: string
|
||||
getTrailingCommentRanges(text, skipTrivia(text, previousSibling.end + 1, /* stopAfterLineBreak */ false, /* stopAtComments */ true)),
|
||||
getLeadingCommentRanges(text, node.pos)
|
||||
)
|
||||
: getTrailingCommentRanges(text, skipTrivia(text, node.pos, /* stopAfterLineBreak */ false, /* stopAtComments */ true));
|
||||
return commentRanges && commentRanges.length && hasInternalAnnotation(last(commentRanges), currentSourceFile);
|
||||
}
|
||||
const leadingCommentRanges = parseTreeNode && getLeadingCommentRangesOfNode(parseTreeNode, currentSourceFile);
|
||||
return !!forEach(leadingCommentRanges, range => {
|
||||
return hasInternalAnnotation(range, currentSourceFile);
|
||||
});
|
||||
}
|
||||
|
||||
const declarationEmitNodeBuilderFlags =
|
||||
NodeBuilderFlags.MultilineObjectLiterals |
|
||||
NodeBuilderFlags.WriteClassExpressionAsTypeLiteral |
|
||||
@@ -61,7 +89,7 @@ namespace ts {
|
||||
const { noResolve, stripInternal } = options;
|
||||
return transformRoot;
|
||||
|
||||
function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: string[] | undefined): void {
|
||||
function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: ReadonlyArray<string> | undefined): void {
|
||||
if (!typeReferenceDirectives) {
|
||||
return;
|
||||
}
|
||||
@@ -207,8 +235,14 @@ namespace ts {
|
||||
}
|
||||
), mapDefined(node.prepends, prepend => {
|
||||
if (prepend.kind === SyntaxKind.InputFiles) {
|
||||
return createUnparsedSourceFile(prepend.declarationText, prepend.declarationMapPath, prepend.declarationMapText);
|
||||
const sourceFile = createUnparsedSourceFile(prepend, "dts", stripInternal);
|
||||
hasNoDefaultLib = hasNoDefaultLib || !!sourceFile.hasNoDefaultLib;
|
||||
collectReferences(sourceFile, refs);
|
||||
recordTypeReferenceDirectivesIfNecessary(sourceFile.typeReferenceDirectives);
|
||||
collectLibs(sourceFile, libs);
|
||||
return sourceFile;
|
||||
}
|
||||
return prepend;
|
||||
}));
|
||||
bundle.syntheticFileReferences = [];
|
||||
bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences();
|
||||
@@ -311,8 +345,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function collectReferences(sourceFile: SourceFile, ret: Map<SourceFile>) {
|
||||
if (noResolve || isSourceFileJS(sourceFile)) return ret;
|
||||
function collectReferences(sourceFile: SourceFile | UnparsedSource, ret: Map<SourceFile>) {
|
||||
if (noResolve || (!isUnparsedSource(sourceFile) && isSourceFileJS(sourceFile))) return ret;
|
||||
forEach(sourceFile.referencedFiles, f => {
|
||||
const elem = tryResolveScriptReference(host, sourceFile, f);
|
||||
if (elem) {
|
||||
@@ -322,7 +356,7 @@ namespace ts {
|
||||
return ret;
|
||||
}
|
||||
|
||||
function collectLibs(sourceFile: SourceFile, ret: Map<boolean>) {
|
||||
function collectLibs(sourceFile: SourceFile | UnparsedSource, ret: Map<boolean>) {
|
||||
forEach(sourceFile.libReferenceDirectives, ref => {
|
||||
const lib = host.getLibFileFromReference(ref);
|
||||
if (lib) {
|
||||
@@ -634,7 +668,10 @@ namespace ts {
|
||||
if (!isLateVisibilityPaintedStatement(i)) {
|
||||
return Debug.fail(`Late replaced statement was found which is not handled by the declaration transformer!: ${(ts as any).SyntaxKind ? (ts as any).SyntaxKind[(i as any).kind] : (i as any).kind}`);
|
||||
}
|
||||
const priorNeedsDeclare = needsDeclare;
|
||||
needsDeclare = i.parent && isSourceFile(i.parent) && !(isExternalModule(i.parent) && isBundledEmit);
|
||||
const result = transformTopLevelDeclaration(i, /*privateDeclaration*/ true);
|
||||
needsDeclare = priorNeedsDeclare;
|
||||
lateStatementReplacementMap.set("" + getOriginalNodeId(i), result);
|
||||
}
|
||||
|
||||
@@ -1003,7 +1040,9 @@ namespace ts {
|
||||
if (!isPropertyAccessExpression(p.valueDeclaration)) {
|
||||
return undefined;
|
||||
}
|
||||
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration);
|
||||
const type = resolver.createTypeOfDeclaration(p.valueDeclaration, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker);
|
||||
getSymbolAccessibilityDiagnostic = oldDiag;
|
||||
const varDecl = createVariableDeclaration(unescapeLeadingUnderscores(p.escapedName), type, /*initializer*/ undefined);
|
||||
return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([varDecl]));
|
||||
});
|
||||
@@ -1055,8 +1094,8 @@ namespace ts {
|
||||
let parameterProperties: ReadonlyArray<PropertyDeclaration> | undefined;
|
||||
if (ctor) {
|
||||
const oldDiag = getSymbolAccessibilityDiagnostic;
|
||||
parameterProperties = compact(flatMap(ctor.parameters, param => {
|
||||
if (!hasModifier(param, ModifierFlags.ParameterPropertyModifier)) return;
|
||||
parameterProperties = compact(flatMap(ctor.parameters, (param) => {
|
||||
if (!hasModifier(param, ModifierFlags.ParameterPropertyModifier) || shouldStripInternal(param)) return;
|
||||
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(param);
|
||||
if (param.name.kind === SyntaxKind.Identifier) {
|
||||
return preserveJsDoc(createProperty(
|
||||
@@ -1217,19 +1256,8 @@ namespace ts {
|
||||
errorNameNode = undefined;
|
||||
}
|
||||
|
||||
function hasInternalAnnotation(range: CommentRange) {
|
||||
const comment = currentSourceFile.text.substring(range.pos, range.end);
|
||||
return stringContains(comment, "@internal");
|
||||
}
|
||||
|
||||
function shouldStripInternal(node: Node) {
|
||||
if (stripInternal && node) {
|
||||
const leadingCommentRanges = getLeadingCommentRangesOfNode(getParseTreeNode(node), currentSourceFile);
|
||||
if (forEach(leadingCommentRanges, hasInternalAnnotation)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return !!stripInternal && !!node && isInternalDeclaration(node, currentSourceFile);
|
||||
}
|
||||
|
||||
function isScopeMarker(node: Node) {
|
||||
|
||||
@@ -26,7 +26,8 @@ namespace ts {
|
||||
| ImportEqualsDeclaration
|
||||
| TypeAliasDeclaration
|
||||
| ConstructorDeclaration
|
||||
| IndexSignatureDeclaration;
|
||||
| IndexSignatureDeclaration
|
||||
| PropertyAccessExpression;
|
||||
|
||||
export function canProduceDiagnostics(node: Node): node is DeclarationDiagnosticProducing {
|
||||
return isVariableDeclaration(node) ||
|
||||
@@ -46,7 +47,8 @@ namespace ts {
|
||||
isImportEqualsDeclaration(node) ||
|
||||
isTypeAliasDeclaration(node) ||
|
||||
isConstructorDeclaration(node) ||
|
||||
isIndexSignatureDeclaration(node);
|
||||
isIndexSignatureDeclaration(node) ||
|
||||
isPropertyAccessExpression(node);
|
||||
}
|
||||
|
||||
export function createGetSymbolAccessibilityDiagnosticForNodeName(node: DeclarationDiagnosticProducing) {
|
||||
@@ -123,7 +125,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationDiagnosticProducing): (symbolAccessibilityResult: SymbolAccessibilityResult) => SymbolAccessibilityDiagnostic | undefined {
|
||||
if (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isBindingElement(node) || isConstructorDeclaration(node)) {
|
||||
if (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isPropertyAccessExpression(node) || isBindingElement(node) || isConstructorDeclaration(node)) {
|
||||
return getVariableDeclarationTypeVisibilityError;
|
||||
}
|
||||
else if (isSetAccessor(node) || isGetAccessor(node)) {
|
||||
@@ -164,7 +166,7 @@ namespace ts {
|
||||
}
|
||||
// This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit
|
||||
// The only exception here is if the constructor was marked as private. we are not emitting the constructor parameters at all.
|
||||
else if (node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature ||
|
||||
else if (node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.PropertySignature ||
|
||||
(node.kind === SyntaxKind.Parameter && hasModifier(node.parent, ModifierFlags.Private))) {
|
||||
// TODO(jfreeman): Deal with computed properties in error reporting.
|
||||
if (hasModifier(node, ModifierFlags.Static)) {
|
||||
@@ -389,6 +391,10 @@ namespace ts {
|
||||
diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1;
|
||||
break;
|
||||
|
||||
case SyntaxKind.MappedType:
|
||||
diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
diagnosticMessage = Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
|
||||
|
||||
@@ -512,7 +512,7 @@ namespace ts {
|
||||
return name;
|
||||
}
|
||||
|
||||
const restHelper: EmitHelper = {
|
||||
export const restHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:rest",
|
||||
scoped: false,
|
||||
text: `
|
||||
|
||||
+282
-309
File diff suppressed because it is too large
Load Diff
@@ -420,8 +420,10 @@ namespace ts {
|
||||
|
||||
const savedCapturedSuperProperties = capturedSuperProperties;
|
||||
const savedHasSuperElementAccess = hasSuperElementAccess;
|
||||
capturedSuperProperties = createUnderscoreEscapedMap<true>();
|
||||
hasSuperElementAccess = false;
|
||||
if (!isArrowFunction) {
|
||||
capturedSuperProperties = createUnderscoreEscapedMap<true>();
|
||||
hasSuperElementAccess = false;
|
||||
}
|
||||
|
||||
let result: ConciseBody;
|
||||
if (!isArrowFunction) {
|
||||
@@ -438,7 +440,7 @@ namespace ts {
|
||||
)
|
||||
);
|
||||
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
|
||||
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
|
||||
// This step isn't needed if we eventually transform this to ES5.
|
||||
@@ -446,9 +448,11 @@ namespace ts {
|
||||
|
||||
if (emitSuperHelpers) {
|
||||
enableSubstitutionForAsyncMethodsWithSuper();
|
||||
const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties);
|
||||
substitutedSuperAccessors[getNodeId(variableStatement)] = true;
|
||||
addStatementsAfterPrologue(statements, [variableStatement]);
|
||||
if (hasEntries(capturedSuperProperties)) {
|
||||
const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties);
|
||||
substitutedSuperAccessors[getNodeId(variableStatement)] = true;
|
||||
insertStatementsAfterStandardPrologue(statements, [variableStatement]);
|
||||
}
|
||||
}
|
||||
|
||||
const block = createBlock(statements, /*multiLine*/ true);
|
||||
@@ -485,8 +489,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
enclosingFunctionParameterNames = savedEnclosingFunctionParameterNames;
|
||||
capturedSuperProperties = savedCapturedSuperProperties;
|
||||
hasSuperElementAccess = savedHasSuperElementAccess;
|
||||
if (!isArrowFunction) {
|
||||
capturedSuperProperties = savedCapturedSuperProperties;
|
||||
hasSuperElementAccess = savedHasSuperElementAccess;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -684,9 +690,15 @@ namespace ts {
|
||||
/* parameters */ [],
|
||||
/* type */ undefined,
|
||||
/* equalsGreaterThanToken */ undefined,
|
||||
createPropertyAccess(
|
||||
createSuper(),
|
||||
name
|
||||
setEmitFlags(
|
||||
createPropertyAccess(
|
||||
setEmitFlags(
|
||||
createSuper(),
|
||||
EmitFlags.NoSubstitution
|
||||
),
|
||||
name
|
||||
),
|
||||
EmitFlags.NoSubstitution
|
||||
)
|
||||
)
|
||||
));
|
||||
@@ -711,9 +723,16 @@ namespace ts {
|
||||
/* type */ undefined,
|
||||
/* equalsGreaterThanToken */ undefined,
|
||||
createAssignment(
|
||||
createPropertyAccess(
|
||||
createSuper(),
|
||||
name),
|
||||
setEmitFlags(
|
||||
createPropertyAccess(
|
||||
setEmitFlags(
|
||||
createSuper(),
|
||||
EmitFlags.NoSubstitution
|
||||
),
|
||||
name
|
||||
),
|
||||
EmitFlags.NoSubstitution
|
||||
),
|
||||
createIdentifier("v")
|
||||
)
|
||||
)
|
||||
@@ -750,7 +769,7 @@ namespace ts {
|
||||
NodeFlags.Const));
|
||||
}
|
||||
|
||||
const awaiterHelper: EmitHelper = {
|
||||
export const awaiterHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:awaiter",
|
||||
scoped: false,
|
||||
priority: 5,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
export function transformES2019(context: TransformationContext) {
|
||||
return chainBundle(transformSourceFile);
|
||||
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
if (node.isDeclarationFile) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function visitor(node: Node): VisitResult<Node> {
|
||||
if ((node.transformFlags & TransformFlags.ContainsES2019) === 0) {
|
||||
return node;
|
||||
}
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.CatchClause:
|
||||
return visitCatchClause(node as CatchClause);
|
||||
default:
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
}
|
||||
|
||||
function visitCatchClause(node: CatchClause): CatchClause {
|
||||
if (!node.variableDeclaration) {
|
||||
return updateCatchClause(
|
||||
node,
|
||||
createVariableDeclaration(createTempVariable(/*recordTempVariable*/ undefined)),
|
||||
visitNode(node.block, visitor, isBlock)
|
||||
);
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -316,7 +316,7 @@ namespace ts {
|
||||
else if (inGeneratorFunctionBody) {
|
||||
return visitJavaScriptInGeneratorFunctionBody(node);
|
||||
}
|
||||
else if (transformFlags & TransformFlags.Generator) {
|
||||
else if (isFunctionLikeDeclaration(node) && node.asteriskToken) {
|
||||
return visitGenerator(node);
|
||||
}
|
||||
else if (transformFlags & TransformFlags.ContainsGenerator) {
|
||||
@@ -587,7 +587,7 @@ namespace ts {
|
||||
transformAndEmitStatements(body.statements, statementOffset);
|
||||
|
||||
const buildResult = build();
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
statements.push(createReturn(buildResult));
|
||||
|
||||
// Restore previous generator state
|
||||
@@ -3240,7 +3240,7 @@ namespace ts {
|
||||
// entering a finally block.
|
||||
//
|
||||
// For examples of how these are used, see the comments in ./transformers/generators.ts
|
||||
const generatorHelper: EmitHelper = {
|
||||
export const generatorHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:generator",
|
||||
scoped: false,
|
||||
priority: 6,
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitJsxText(node: JsxText): StringLiteral | undefined {
|
||||
const fixed = fixupWhitespaceAndDecodeEntities(getTextOfNode(node, /*includeTrivia*/ true));
|
||||
const fixed = fixupWhitespaceAndDecodeEntities(node.text);
|
||||
return fixed === undefined ? undefined : createLiteral(fixed);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace ts {
|
||||
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement));
|
||||
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
|
||||
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false);
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
|
||||
const updated = updateSourceFileNode(node, setTextRange(createNodeArray(statements), node.statements));
|
||||
if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) {
|
||||
@@ -432,7 +432,7 @@ namespace ts {
|
||||
|
||||
// End the lexical environment for the module body
|
||||
// and merge any new lexical declarations.
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
|
||||
const body = createBlock(statements, /*multiLine*/ true);
|
||||
if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) {
|
||||
@@ -537,8 +537,8 @@ namespace ts {
|
||||
if (isImportCall(node)) {
|
||||
return visitImportCallExpression(node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.DestructuringAssignment && isBinaryExpression(node)) {
|
||||
return visitDestructuringAssignment(node as DestructuringAssignment);
|
||||
else if (isDestructuringAssignment(node)) {
|
||||
return visitDestructuringAssignment(node);
|
||||
}
|
||||
else {
|
||||
return visitEachChild(node, moduleExpressionElementVisitor, context);
|
||||
@@ -1806,7 +1806,7 @@ namespace ts {
|
||||
};
|
||||
|
||||
// emit helper for `import * as Name from "foo"`
|
||||
const importStarHelper: EmitHelper = {
|
||||
export const importStarHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:commonjsimportstar",
|
||||
scoped: false,
|
||||
text: `
|
||||
@@ -1820,7 +1820,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
};
|
||||
|
||||
// emit helper for `import Name from "foo"`
|
||||
const importDefaultHelper: EmitHelper = {
|
||||
export const importDefaultHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:commonjsimportdefault",
|
||||
scoped: false,
|
||||
text: `
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace ts {
|
||||
// We emit hoisted variables early to align roughly with our previous emit output.
|
||||
// Two key differences in this approach are:
|
||||
// - Temporary variables will appear at the top rather than at the bottom of the file
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
|
||||
const exportStarFunction = addExportStarIfNeeded(statements)!; // TODO: GH#18217
|
||||
const moduleObject = createObjectLiteral([
|
||||
@@ -1463,9 +1463,8 @@ namespace ts {
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function destructuringAndImportCallVisitor(node: Node): VisitResult<Node> {
|
||||
if (node.transformFlags & TransformFlags.DestructuringAssignment
|
||||
&& node.kind === SyntaxKind.BinaryExpression) {
|
||||
return visitDestructuringAssignment(<DestructuringAssignment>node);
|
||||
if (isDestructuringAssignment(node)) {
|
||||
return visitDestructuringAssignment(node);
|
||||
}
|
||||
else if (isImportCall(node)) {
|
||||
return visitImportCallExpression(node);
|
||||
|
||||
+63
-148
@@ -101,7 +101,7 @@ namespace ts {
|
||||
function transformBundle(node: Bundle) {
|
||||
return createBundle(node.sourceFiles.map(transformSourceFile), mapDefined(node.prepends, prepend => {
|
||||
if (prepend.kind === SyntaxKind.InputFiles) {
|
||||
return createUnparsedSourceFile(prepend.javascriptText, prepend.javascriptMapPath, prepend.javascriptMapText);
|
||||
return createUnparsedSourceFile(prepend, "js");
|
||||
}
|
||||
return prepend;
|
||||
}));
|
||||
@@ -208,15 +208,9 @@ namespace ts {
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitorWorker(node: Node): VisitResult<Node> {
|
||||
if (node.transformFlags & TransformFlags.TypeScript) {
|
||||
// This node is explicitly marked as TypeScript, so we should transform the node.
|
||||
if (node.transformFlags & TransformFlags.ContainsTypeScript) {
|
||||
return visitTypeScript(node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.ContainsTypeScript) {
|
||||
// This node contains TypeScript, so we should visit its children.
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -296,15 +290,9 @@ namespace ts {
|
||||
(<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference)) {
|
||||
// do not emit ES6 imports and exports since they are illegal inside a namespace
|
||||
return undefined;
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) {
|
||||
// This node is explicitly marked as TypeScript, or is exported at the namespace
|
||||
// level, so we should transform the node.
|
||||
return visitTypeScript(node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.ContainsTypeScript) {
|
||||
// This node contains TypeScript, so we should visit its children.
|
||||
return visitEachChild(node, visitor, context);
|
||||
else if (node.transformFlags & TransformFlags.ContainsTypeScript || hasModifier(node, ModifierFlags.Export)) {
|
||||
return visitTypeScript(node);
|
||||
}
|
||||
|
||||
return node;
|
||||
@@ -365,7 +353,7 @@ namespace ts {
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitTypeScript(node: Node): VisitResult<Node> {
|
||||
if (hasModifier(node, ModifierFlags.Ambient) && isStatement(node)) {
|
||||
if (isStatement(node) && hasModifier(node, ModifierFlags.Ambient)) {
|
||||
// TypeScript ambient declarations are elided, but some comments may be preserved.
|
||||
// See the implementation of `getLeadingComments` in comments.ts for more details.
|
||||
return createNotEmittedStatement(node);
|
||||
@@ -443,7 +431,7 @@ namespace ts {
|
||||
return createNotEmittedStatement(node);
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
// This is a class declaration with TypeScript syntax extensions.
|
||||
// This may be a class declaration with TypeScript syntax extensions.
|
||||
//
|
||||
// TypeScript class syntax extensions include:
|
||||
// - decorators
|
||||
@@ -455,7 +443,7 @@ namespace ts {
|
||||
return visitClassDeclaration(<ClassDeclaration>node);
|
||||
|
||||
case SyntaxKind.ClassExpression:
|
||||
// This is a class expression with TypeScript syntax extensions.
|
||||
// This may be a class expression with TypeScript syntax extensions.
|
||||
//
|
||||
// TypeScript class syntax extensions include:
|
||||
// - decorators
|
||||
@@ -467,7 +455,7 @@ namespace ts {
|
||||
return visitClassExpression(<ClassExpression>node);
|
||||
|
||||
case SyntaxKind.HeritageClause:
|
||||
// This is a heritage clause with TypeScript syntax extensions.
|
||||
// This may be a heritage clause with TypeScript syntax extensions.
|
||||
//
|
||||
// TypeScript heritage clause extensions include:
|
||||
// - `implements` clause
|
||||
@@ -503,7 +491,7 @@ namespace ts {
|
||||
return visitArrowFunction(<ArrowFunction>node);
|
||||
|
||||
case SyntaxKind.Parameter:
|
||||
// This is a parameter declaration with TypeScript syntax extensions.
|
||||
// This may be a parameter declaration with TypeScript syntax extensions.
|
||||
//
|
||||
// TypeScript parameter declaration syntax extensions include:
|
||||
// - decorators
|
||||
@@ -556,7 +544,8 @@ namespace ts {
|
||||
return visitImportEqualsDeclaration(<ImportEqualsDeclaration>node);
|
||||
|
||||
default:
|
||||
return Debug.failBadSyntaxKind(node);
|
||||
// node contains some other TypeScript syntax
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -607,18 +596,22 @@ namespace ts {
|
||||
return facts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a class declaration with TypeScript syntax into compatible ES6.
|
||||
*
|
||||
* This function will only be called when one of the following conditions are met:
|
||||
* - The class has decorators.
|
||||
* - The class has property declarations with initializers.
|
||||
* - The class contains a constructor that contains parameters with accessibility modifiers.
|
||||
* - The class is an export in a TypeScript namespace.
|
||||
*
|
||||
* @param node The node to transform.
|
||||
*/
|
||||
function hasTypeScriptClassSyntax(node: Node) {
|
||||
return !!(node.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax);
|
||||
}
|
||||
|
||||
function isClassLikeDeclarationWithTypeScriptSyntax(node: ClassLikeDeclaration) {
|
||||
return some(node.decorators)
|
||||
|| some(node.typeParameters)
|
||||
|| some(node.heritageClauses, hasTypeScriptClassSyntax)
|
||||
|| some(node.members, hasTypeScriptClassSyntax);
|
||||
}
|
||||
|
||||
function visitClassDeclaration(node: ClassDeclaration): VisitResult<Statement> {
|
||||
if (!isClassLikeDeclarationWithTypeScriptSyntax(node) && !(currentNamespace && hasModifier(node, ModifierFlags.Export))) {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
const savedPendingExpressions = pendingExpressions;
|
||||
pendingExpressions = undefined;
|
||||
|
||||
@@ -682,7 +675,7 @@ namespace ts {
|
||||
setEmitFlags(statement, EmitFlags.NoComments | EmitFlags.NoTokenSourceMaps);
|
||||
statements.push(statement);
|
||||
|
||||
addStatementsAfterPrologue(statements, context.endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, context.endLexicalEnvironment());
|
||||
|
||||
const iife = createImmediatelyInvokedArrowFunction(statements);
|
||||
setEmitFlags(iife, EmitFlags.TypeScriptClassWrapper);
|
||||
@@ -890,16 +883,11 @@ namespace ts {
|
||||
return statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a class expression with TypeScript syntax into compatible ES6.
|
||||
*
|
||||
* This function will only be called when one of the following conditions are met:
|
||||
* - The class has property declarations with initializers.
|
||||
* - The class contains a constructor that contains parameters with accessibility modifiers.
|
||||
*
|
||||
* @param node The node to transform.
|
||||
*/
|
||||
function visitClassExpression(node: ClassExpression): Expression {
|
||||
if (!isClassLikeDeclarationWithTypeScriptSyntax(node)) {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
const savedPendingExpressions = pendingExpressions;
|
||||
pendingExpressions = undefined;
|
||||
|
||||
@@ -1350,11 +1338,14 @@ namespace ts {
|
||||
let decorators: (ReadonlyArray<Decorator> | undefined)[] | undefined;
|
||||
if (node) {
|
||||
const parameters = node.parameters;
|
||||
for (let i = 0; i < parameters.length; i++) {
|
||||
const parameter = parameters[i];
|
||||
const firstParameterIsThis = parameters.length > 0 && parameterIsThisKeyword(parameters[0]);
|
||||
const firstParameterOffset = firstParameterIsThis ? 1 : 0;
|
||||
const numParameters = firstParameterIsThis ? parameters.length - 1 : parameters.length;
|
||||
for (let i = 0; i < numParameters; i++) {
|
||||
const parameter = parameters[i + firstParameterOffset];
|
||||
if (decorators || parameter.decorators) {
|
||||
if (!decorators) {
|
||||
decorators = new Array(parameters.length);
|
||||
decorators = new Array(numParameters);
|
||||
}
|
||||
|
||||
decorators[i] = parameter.decorators;
|
||||
@@ -1934,8 +1925,13 @@ namespace ts {
|
||||
case SyntaxKind.ConditionalType:
|
||||
return serializeTypeList([(<ConditionalTypeNode>node).trueType, (<ConditionalTypeNode>node).falseType]);
|
||||
|
||||
case SyntaxKind.TypeQuery:
|
||||
case SyntaxKind.TypeOperator:
|
||||
if ((<TypeOperatorNode>node).operator === SyntaxKind.ReadonlyKeyword) {
|
||||
return serializeTypeNode((<TypeOperatorNode>node).type);
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.TypeQuery:
|
||||
case SyntaxKind.IndexedAccessType:
|
||||
case SyntaxKind.MappedType:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
@@ -2232,18 +2228,11 @@ namespace ts {
|
||||
* @param node The HeritageClause to transform.
|
||||
*/
|
||||
function visitHeritageClause(node: HeritageClause): HeritageClause | undefined {
|
||||
if (node.token === SyntaxKind.ExtendsKeyword) {
|
||||
const types = visitNodes(node.types, visitor, isExpressionWithTypeArguments, 0, 1);
|
||||
return setTextRange(
|
||||
createHeritageClause(
|
||||
SyntaxKind.ExtendsKeyword,
|
||||
types
|
||||
),
|
||||
node
|
||||
);
|
||||
if (node.token === SyntaxKind.ImplementsKeyword) {
|
||||
// implements clauses are elided
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2294,16 +2283,6 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a method declaration of a class.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is an overload
|
||||
* - The node is marked as abstract, public, private, protected, or readonly
|
||||
* - The node has a computed property name
|
||||
*
|
||||
* @param node The method node.
|
||||
*/
|
||||
function visitMethodDeclaration(node: MethodDeclaration) {
|
||||
if (!shouldEmitFunctionLikeDeclaration(node)) {
|
||||
return undefined;
|
||||
@@ -2339,15 +2318,6 @@ namespace ts {
|
||||
return !(nodeIsMissing(node.body) && hasModifier(node, ModifierFlags.Abstract));
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a get accessor declaration of a class.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is marked as abstract, public, private, or protected
|
||||
* - The node has a computed property name
|
||||
*
|
||||
* @param node The get accessor node.
|
||||
*/
|
||||
function visitGetAccessor(node: GetAccessorDeclaration) {
|
||||
if (!shouldEmitAccessorDeclaration(node)) {
|
||||
return undefined;
|
||||
@@ -2370,15 +2340,6 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a set accessor declaration of a class.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is marked as abstract, public, private, or protected
|
||||
* - The node has a computed property name
|
||||
*
|
||||
* @param node The set accessor node.
|
||||
*/
|
||||
function visitSetAccessor(node: SetAccessorDeclaration) {
|
||||
if (!shouldEmitAccessorDeclaration(node)) {
|
||||
return undefined;
|
||||
@@ -2400,16 +2361,6 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a function declaration.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is an overload
|
||||
* - The node is exported from a TypeScript namespace
|
||||
* - The node has decorators
|
||||
*
|
||||
* @param node The function node.
|
||||
*/
|
||||
function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult<Statement> {
|
||||
if (!shouldEmitFunctionLikeDeclaration(node)) {
|
||||
return createNotEmittedStatement(node);
|
||||
@@ -2433,14 +2384,6 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a function expression node.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node has type annotations
|
||||
*
|
||||
* @param node The function expression node.
|
||||
*/
|
||||
function visitFunctionExpression(node: FunctionExpression): Expression {
|
||||
if (!shouldEmitFunctionLikeDeclaration(node)) {
|
||||
return createOmittedExpression();
|
||||
@@ -2458,11 +2401,6 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node has type annotations
|
||||
*/
|
||||
function visitArrowFunction(node: ArrowFunction) {
|
||||
const updated = updateArrowFunction(
|
||||
node,
|
||||
@@ -2476,22 +2414,12 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a parameter declaration node.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node has an accessibility modifier.
|
||||
* - The node has a questionToken.
|
||||
* - The node's kind is ThisKeyword.
|
||||
*
|
||||
* @param node The parameter declaration node.
|
||||
*/
|
||||
function visitParameter(node: ParameterDeclaration) {
|
||||
if (parameterIsThisKeyword(node)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const parameter = createParameter(
|
||||
const updated = updateParameter(
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
node.dotDotDotToken,
|
||||
@@ -2500,24 +2428,17 @@ namespace ts {
|
||||
/*type*/ undefined,
|
||||
visitNode(node.initializer, visitor, isExpression)
|
||||
);
|
||||
|
||||
// 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(parameter, node);
|
||||
setTextRange(parameter, moveRangePastModifiers(node));
|
||||
setCommentRange(parameter, node);
|
||||
setSourceMapRange(parameter, moveRangePastModifiers(node));
|
||||
setEmitFlags(parameter.name, EmitFlags.NoTrailingSourceMap);
|
||||
|
||||
return parameter;
|
||||
if (updated !== node) {
|
||||
// While we emit the source map for the node after skipping decorators and modifiers,
|
||||
// we need to emit the comments for the original range.
|
||||
setCommentRange(updated, node);
|
||||
setTextRange(updated, moveRangePastModifiers(node));
|
||||
setSourceMapRange(updated, moveRangePastModifiers(node));
|
||||
setEmitFlags(updated.name, EmitFlags.NoTrailingSourceMap);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a variable statement in a namespace.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is exported from a TypeScript namespace.
|
||||
*/
|
||||
function visitVariableStatement(node: VariableStatement): Statement | undefined {
|
||||
if (isExportOfNamespace(node)) {
|
||||
const variables = getInitializedVariables(node.declarationList);
|
||||
@@ -2571,12 +2492,6 @@ namespace ts {
|
||||
visitNode(node.initializer, visitor, isExpression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a parenthesized expression that contains either a type assertion or an `as`
|
||||
* expression.
|
||||
*
|
||||
* @param node The parenthesized expression node.
|
||||
*/
|
||||
function visitParenthesizedExpression(node: ParenthesizedExpression): Expression {
|
||||
const innerExpression = skipOuterExpressions(node.expression, ~OuterExpressionKinds.Assertions);
|
||||
if (isAssertionExpression(innerExpression)) {
|
||||
@@ -2760,7 +2675,7 @@ namespace ts {
|
||||
const statements: Statement[] = [];
|
||||
startLexicalEnvironment();
|
||||
const members = map(node.members, transformEnumMember);
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
addRange(statements, members);
|
||||
|
||||
currentNamespaceContainerName = savedCurrentNamespaceLocalName;
|
||||
@@ -3081,7 +2996,7 @@ namespace ts {
|
||||
statementsLocation = moveRangePos(moduleBlock.statements, -1);
|
||||
}
|
||||
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
currentNamespaceContainerName = savedCurrentNamespaceContainerName;
|
||||
currentNamespace = savedCurrentNamespace;
|
||||
currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName;
|
||||
@@ -3675,7 +3590,7 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
const decorateHelper: EmitHelper = {
|
||||
export const decorateHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:decorate",
|
||||
scoped: false,
|
||||
priority: 2,
|
||||
@@ -3700,7 +3615,7 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
const metadataHelper: EmitHelper = {
|
||||
export const metadataHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:metadata",
|
||||
scoped: false,
|
||||
priority: 3,
|
||||
@@ -3725,7 +3640,7 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
const paramHelper: EmitHelper = {
|
||||
export const paramHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:param",
|
||||
scoped: false,
|
||||
priority: 4,
|
||||
|
||||
+359
-192
@@ -30,6 +30,7 @@ namespace ts {
|
||||
listEmittedFiles?: boolean;
|
||||
listFiles?: boolean;
|
||||
pretty?: boolean;
|
||||
incremental?: boolean;
|
||||
|
||||
traceResolution?: boolean;
|
||||
/* @internal */ diagnostics?: boolean;
|
||||
@@ -67,12 +68,19 @@ namespace ts {
|
||||
* This means we can Pseudo-build (just touch timestamps), as if we had actually built this project.
|
||||
*/
|
||||
UpToDateWithUpstreamTypes,
|
||||
/**
|
||||
* The project appears out of date because its upstream inputs are newer than its outputs,
|
||||
* but all of its outputs are actually newer than the previous identical outputs of its (.d.ts) inputs.
|
||||
* This means we can Pseudo-build (just manipulate outputs), as if we had actually built this project.
|
||||
*/
|
||||
OutOfDateWithPrepend,
|
||||
OutputMissing,
|
||||
OutOfDateWithSelf,
|
||||
OutOfDateWithUpstream,
|
||||
UpstreamOutOfDate,
|
||||
UpstreamBlocked,
|
||||
ComputingUpstream,
|
||||
TsVersionOutputOfDate,
|
||||
|
||||
/**
|
||||
* Projects with no outputs (i.e. "solution" files)
|
||||
@@ -83,12 +91,14 @@ namespace ts {
|
||||
export type UpToDateStatus =
|
||||
| Status.Unbuildable
|
||||
| Status.UpToDate
|
||||
| Status.OutOfDateWithPrepend
|
||||
| Status.OutputMissing
|
||||
| Status.OutOfDateWithSelf
|
||||
| Status.OutOfDateWithUpstream
|
||||
| Status.UpstreamOutOfDate
|
||||
| Status.UpstreamBlocked
|
||||
| Status.ComputingUpstream
|
||||
| Status.TsVersionOutOfDate
|
||||
| Status.ContainerOnly;
|
||||
|
||||
export namespace Status {
|
||||
@@ -119,7 +129,16 @@ namespace ts {
|
||||
newestDeclarationFileContentChangedTime?: Date;
|
||||
newestOutputFileTime?: Date;
|
||||
newestOutputFileName?: string;
|
||||
oldestOutputFileName?: string;
|
||||
oldestOutputFileName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The project is up to date with respect to its inputs except for prepend output changed (no declaration file change in prepend).
|
||||
*/
|
||||
export interface OutOfDateWithPrepend {
|
||||
type: UpToDateStatusType.OutOfDateWithPrepend;
|
||||
outOfDateOutputFileName: string;
|
||||
newerProjectName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,6 +184,11 @@ namespace ts {
|
||||
type: UpToDateStatusType.ComputingUpstream;
|
||||
}
|
||||
|
||||
export interface TsVersionOutOfDate {
|
||||
type: UpToDateStatusType.TsVersionOutputOfDate;
|
||||
version: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* One or more of the project's outputs is older than the newest output of
|
||||
* an upstream project.
|
||||
@@ -253,66 +277,6 @@ namespace ts {
|
||||
return getOrCreateValueFromConfigFileMap<Map<T>>(configFileMap, resolved, createMap);
|
||||
}
|
||||
|
||||
export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine) {
|
||||
const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath!), inputFileName, /*ignoreCase*/ true);
|
||||
const outputPath = resolvePath(configFile.options.declarationDir || configFile.options.outDir || getDirectoryPath(configFile.options.configFilePath!), relativePath);
|
||||
return changeExtension(outputPath, Extension.Dts);
|
||||
}
|
||||
|
||||
function getOutputJSFileName(inputFileName: string, configFile: ParsedCommandLine) {
|
||||
const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath!), inputFileName, /*ignoreCase*/ true);
|
||||
const outputPath = resolvePath(configFile.options.outDir || getDirectoryPath(configFile.options.configFilePath!), relativePath);
|
||||
const newExtension = fileExtensionIs(inputFileName, Extension.Json) ? Extension.Json :
|
||||
fileExtensionIs(inputFileName, Extension.Tsx) && configFile.options.jsx === JsxEmit.Preserve ? Extension.Jsx : Extension.Js;
|
||||
return changeExtension(outputPath, newExtension);
|
||||
}
|
||||
|
||||
function getOutputFileNames(inputFileName: string, configFile: ParsedCommandLine): ReadonlyArray<string> {
|
||||
// outFile is handled elsewhere; .d.ts files don't generate outputs
|
||||
if (configFile.options.outFile || configFile.options.out || fileExtensionIs(inputFileName, Extension.Dts)) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
const outputs: string[] = [];
|
||||
const js = getOutputJSFileName(inputFileName, configFile);
|
||||
outputs.push(js);
|
||||
if (configFile.options.sourceMap) {
|
||||
outputs.push(`${js}.map`);
|
||||
}
|
||||
if (getEmitDeclarations(configFile.options) && !fileExtensionIs(inputFileName, Extension.Json)) {
|
||||
const dts = getOutputDeclarationFileName(inputFileName, configFile);
|
||||
outputs.push(dts);
|
||||
if (configFile.options.declarationMap) {
|
||||
outputs.push(`${dts}.map`);
|
||||
}
|
||||
}
|
||||
return outputs;
|
||||
}
|
||||
|
||||
function getOutFileOutputs(project: ParsedCommandLine): ReadonlyArray<string> {
|
||||
const out = project.options.outFile || project.options.out;
|
||||
if (!out) {
|
||||
return Debug.fail("outFile must be set");
|
||||
}
|
||||
const outputs: string[] = [];
|
||||
outputs.push(out);
|
||||
if (project.options.sourceMap) {
|
||||
outputs.push(`${out}.map`);
|
||||
}
|
||||
if (getEmitDeclarations(project.options)) {
|
||||
const dts = changeExtension(out, Extension.Dts);
|
||||
outputs.push(dts);
|
||||
if (project.options.declarationMap) {
|
||||
outputs.push(`${dts}.map`);
|
||||
}
|
||||
}
|
||||
return outputs;
|
||||
}
|
||||
|
||||
function rootDirOfOptions(opts: CompilerOptions, configFileName: string) {
|
||||
return opts.rootDir || getDirectoryPath(configFileName);
|
||||
}
|
||||
|
||||
function newer(date1: Date, date2: Date): Date {
|
||||
return date2 > date1 ? date2 : date1;
|
||||
}
|
||||
@@ -321,7 +285,7 @@ namespace ts {
|
||||
return fileExtensionIs(fileName, Extension.Dts);
|
||||
}
|
||||
|
||||
export interface SolutionBuilderHostBase extends CompilerHost {
|
||||
export interface SolutionBuilderHostBase<T extends BuilderProgram> extends ProgramHost<T> {
|
||||
getModifiedTime(fileName: string): Date | undefined;
|
||||
setModifiedTime(fileName: string, date: Date): void;
|
||||
deleteFile(fileName: string): void;
|
||||
@@ -331,15 +295,17 @@ namespace ts {
|
||||
|
||||
// TODO: To do better with watch mode and normal build mode api that creates program and emits files
|
||||
// This currently helps enable --diagnostics and --extendedDiagnostics
|
||||
beforeCreateProgram?(options: CompilerOptions): void;
|
||||
afterProgramEmitAndDiagnostics?(program: Program): void;
|
||||
afterProgramEmitAndDiagnostics?(program: T): void;
|
||||
|
||||
// For testing
|
||||
now?(): Date;
|
||||
}
|
||||
|
||||
export interface SolutionBuilderHost extends SolutionBuilderHostBase {
|
||||
export interface SolutionBuilderHost<T extends BuilderProgram> extends SolutionBuilderHostBase<T> {
|
||||
reportErrorSummary?: ReportEmitErrorSummary;
|
||||
}
|
||||
|
||||
export interface SolutionBuilderWithWatchHost extends SolutionBuilderHostBase, WatchHost {
|
||||
export interface SolutionBuilderWithWatchHost<T extends BuilderProgram> extends SolutionBuilderHostBase<T>, WatchHost {
|
||||
}
|
||||
|
||||
export interface SolutionBuilder {
|
||||
@@ -372,9 +338,9 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function createSolutionBuilderHostBase(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter) {
|
||||
const host = createCompilerHostWorker({}, /*setParentNodes*/ undefined, system) as SolutionBuilderHostBase;
|
||||
host.getModifiedTime = system.getModifiedTime ? path => system.getModifiedTime!(path) : () => undefined;
|
||||
function createSolutionBuilderHostBase<T extends BuilderProgram>(system: System, createProgram: CreateProgram<T> | undefined, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter) {
|
||||
const host = createProgramHost(system, createProgram) as SolutionBuilderHostBase<T>;
|
||||
host.getModifiedTime = system.getModifiedTime ? path => system.getModifiedTime!(path) : returnUndefined;
|
||||
host.setModifiedTime = system.setModifiedTime ? (path, date) => system.setModifiedTime!(path, date) : noop;
|
||||
host.deleteFile = system.deleteFile ? path => system.deleteFile!(path) : noop;
|
||||
host.reportDiagnostic = reportDiagnostic || createDiagnosticReporter(system);
|
||||
@@ -382,27 +348,23 @@ namespace ts {
|
||||
return host;
|
||||
}
|
||||
|
||||
export function createSolutionBuilderHost(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary) {
|
||||
const host = createSolutionBuilderHostBase(system, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderHost;
|
||||
export function createSolutionBuilderHost<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(system = sys, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary) {
|
||||
const host = createSolutionBuilderHostBase(system, createProgram, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderHost<T>;
|
||||
host.reportErrorSummary = reportErrorSummary;
|
||||
return host;
|
||||
}
|
||||
|
||||
export function createSolutionBuilderWithWatchHost(system?: System, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter) {
|
||||
const host = createSolutionBuilderHostBase(system, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderWithWatchHost;
|
||||
export function createSolutionBuilderWithWatchHost<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(system = sys, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter) {
|
||||
const host = createSolutionBuilderHostBase(system, createProgram, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderWithWatchHost<T>;
|
||||
const watchHost = createWatchHost(system, reportWatchStatus);
|
||||
host.onWatchStatusChange = watchHost.onWatchStatusChange;
|
||||
host.watchFile = watchHost.watchFile;
|
||||
host.watchDirectory = watchHost.watchDirectory;
|
||||
host.setTimeout = watchHost.setTimeout;
|
||||
host.clearTimeout = watchHost.clearTimeout;
|
||||
copyProperties(host, watchHost);
|
||||
return host;
|
||||
}
|
||||
|
||||
function getCompilerOptionsOfBuildOptions(buildOptions: BuildOptions): CompilerOptions {
|
||||
const result = {} as CompilerOptions;
|
||||
commonOptionsWithBuild.forEach(option => {
|
||||
result[option.name] = buildOptions[option.name];
|
||||
if (hasProperty(buildOptions, option.name)) result[option.name] = buildOptions[option.name];
|
||||
});
|
||||
return result;
|
||||
}
|
||||
@@ -413,13 +375,13 @@ namespace ts {
|
||||
* TODO: use SolutionBuilderWithWatchHost => watchedSolution
|
||||
* use SolutionBuilderHost => Solution
|
||||
*/
|
||||
export function createSolutionBuilder(host: SolutionBuilderHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilder;
|
||||
export function createSolutionBuilder(host: SolutionBuilderWithWatchHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilderWithWatch;
|
||||
export function createSolutionBuilder(host: SolutionBuilderHost | SolutionBuilderWithWatchHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilderWithWatch {
|
||||
const hostWithWatch = host as SolutionBuilderWithWatchHost;
|
||||
export function createSolutionBuilder<T extends BuilderProgram>(host: SolutionBuilderHost<T>, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilder;
|
||||
export function createSolutionBuilder<T extends BuilderProgram>(host: SolutionBuilderWithWatchHost<T>, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilderWithWatch;
|
||||
export function createSolutionBuilder<T extends BuilderProgram>(host: SolutionBuilderHost<T> | SolutionBuilderWithWatchHost<T>, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilderWithWatch {
|
||||
const hostWithWatch = host as SolutionBuilderWithWatchHost<T>;
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
|
||||
const parseConfigFileHost = parseConfigHostFromCompilerHost(host);
|
||||
const parseConfigFileHost = parseConfigHostFromCompilerHostLike(host);
|
||||
|
||||
// State of the solution
|
||||
let options = defaultOptions;
|
||||
@@ -434,8 +396,14 @@ namespace ts {
|
||||
let globalDependencyGraph: DependencyGraph | undefined;
|
||||
const writeFileName = (s: string) => host.trace && host.trace(s);
|
||||
let readFileWithCache = (f: string) => host.readFile(f);
|
||||
let projectCompilerOptions = baseCompilerOptions;
|
||||
const compilerHost = createCompilerHostFromProgramHost(host, () => projectCompilerOptions);
|
||||
setGetSourceFileAsHashVersioned(compilerHost, host);
|
||||
|
||||
const buildInfoChecked = createFileMap<true>(toPath);
|
||||
|
||||
// Watch state
|
||||
const builderPrograms = createFileMap<T>(toPath);
|
||||
const diagnostics = createFileMap<ReadonlyArray<Diagnostic>>(toPath);
|
||||
const projectPendingBuild = createFileMap<ConfigFileProgramReloadLevel>(toPath);
|
||||
const projectErrorsReported = createFileMap<true>(toPath);
|
||||
@@ -443,6 +411,7 @@ namespace ts {
|
||||
let nextProjectToBuild = 0;
|
||||
let timerToBuildInvalidatedProject: any;
|
||||
let reportFileChangeDetected = false;
|
||||
const { watchFile, watchFilePath, watchDirectory, writeLog } = createWatchFactory<ResolvedConfigFileName>(host, options);
|
||||
|
||||
// Watches for the solution
|
||||
const allWatchedWildcardDirectories = createFileMap<Map<WildcardDirectoryWatcher>>(toPath);
|
||||
@@ -478,6 +447,7 @@ namespace ts {
|
||||
projectStatus.clear();
|
||||
missingRoots.clear();
|
||||
globalDependencyGraph = undefined;
|
||||
buildInfoChecked.clear();
|
||||
|
||||
diagnostics.clear();
|
||||
projectPendingBuild.clear();
|
||||
@@ -492,6 +462,7 @@ namespace ts {
|
||||
clearMap(allWatchedWildcardDirectories, wildCardWatches => clearMap(wildCardWatches, closeFileWatcherOf));
|
||||
clearMap(allWatchedInputFiles, inputFileWatches => clearMap(inputFileWatches, closeFileWatcher));
|
||||
clearMap(allWatchedConfigFiles, closeFileWatcher);
|
||||
builderPrograms.clear();
|
||||
}
|
||||
|
||||
function isParsedCommandLine(entry: ConfigFileCacheEntry): entry is ParsedCommandLine {
|
||||
@@ -542,9 +513,16 @@ namespace ts {
|
||||
|
||||
function watchConfigFile(resolved: ResolvedConfigFileName) {
|
||||
if (options.watch && !allWatchedConfigFiles.hasKey(resolved)) {
|
||||
allWatchedConfigFiles.setValue(resolved, hostWithWatch.watchFile(resolved, () => {
|
||||
invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Full);
|
||||
}));
|
||||
allWatchedConfigFiles.setValue(resolved, watchFile(
|
||||
hostWithWatch,
|
||||
resolved,
|
||||
() => {
|
||||
invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Full);
|
||||
},
|
||||
PollingInterval.High,
|
||||
WatchType.ConfigFile,
|
||||
resolved
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,20 +532,27 @@ namespace ts {
|
||||
getOrCreateValueMapFromConfigFileMap(allWatchedWildcardDirectories, resolved),
|
||||
createMapFromTemplate(parsed.configFileSpecs!.wildcardDirectories),
|
||||
(dir, flags) => {
|
||||
return hostWithWatch.watchDirectory(dir, fileOrDirectory => {
|
||||
const fileOrDirectoryPath = toPath(fileOrDirectory);
|
||||
if (fileOrDirectoryPath !== toPath(dir) && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, parsed.options)) {
|
||||
// writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrDirectory}`);
|
||||
return;
|
||||
}
|
||||
return watchDirectory(
|
||||
hostWithWatch,
|
||||
dir,
|
||||
fileOrDirectory => {
|
||||
const fileOrDirectoryPath = toPath(fileOrDirectory);
|
||||
if (fileOrDirectoryPath !== toPath(dir) && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, parsed.options)) {
|
||||
writeLog(`Project: ${resolved} Detected file add/remove of non supported extension: ${fileOrDirectory}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isOutputFile(fileOrDirectory, parsed)) {
|
||||
// writeLog(`${fileOrDirectory} is output file`);
|
||||
return;
|
||||
}
|
||||
if (isOutputFile(fileOrDirectory, parsed)) {
|
||||
writeLog(`${fileOrDirectory} is output file`);
|
||||
return;
|
||||
}
|
||||
|
||||
invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Partial);
|
||||
}, !!(flags & WatchDirectoryFlags.Recursive));
|
||||
invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Partial);
|
||||
},
|
||||
flags,
|
||||
WatchType.WildcardDirectory,
|
||||
resolved
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -578,9 +563,15 @@ namespace ts {
|
||||
getOrCreateValueMapFromConfigFileMap(allWatchedInputFiles, resolved),
|
||||
arrayToMap(parsed.fileNames, toPath),
|
||||
{
|
||||
createNewValue: (_key, input) => hostWithWatch.watchFile(input, () => {
|
||||
invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.None);
|
||||
}),
|
||||
createNewValue: (path, input) => watchFilePath(
|
||||
hostWithWatch,
|
||||
input,
|
||||
() => invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.None),
|
||||
PollingInterval.Low,
|
||||
path as Path,
|
||||
WatchType.SourceFile,
|
||||
resolved
|
||||
),
|
||||
onDeleteValue: closeFileWatcher,
|
||||
}
|
||||
);
|
||||
@@ -670,15 +661,16 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// Collect the expected outputs of this project
|
||||
const outputs = getAllProjectOutputs(project);
|
||||
|
||||
if (outputs.length === 0) {
|
||||
// Container if no files are specified in the project
|
||||
if (!project.fileNames.length && !canJsonReportNoInutFiles(project.raw)) {
|
||||
return {
|
||||
type: UpToDateStatusType.ContainerOnly
|
||||
};
|
||||
}
|
||||
|
||||
// Collect the expected outputs of this project
|
||||
const outputs = getAllProjectOutputs(project, !host.useCaseSensitiveFileNames());
|
||||
|
||||
// Now see if all outputs are newer than the newest input
|
||||
let oldestOutputFileName = "(none)";
|
||||
let oldestOutputFileTime = maximumDate;
|
||||
@@ -760,27 +752,30 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
// If the upstream project's newest file is older than our oldest output, we
|
||||
// can't be out of date because of it
|
||||
if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
|
||||
continue;
|
||||
}
|
||||
// Check oldest output file name only if there is no missing output file name
|
||||
if (!missingOutputFileName) {
|
||||
// If the upstream project's newest file is older than our oldest output, we
|
||||
// can't be out of date because of it
|
||||
if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the upstream project has only change .d.ts files, and we've built
|
||||
// *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
|
||||
if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
|
||||
pseudoUpToDate = true;
|
||||
upstreamChangedProject = ref.path;
|
||||
continue;
|
||||
}
|
||||
// If the upstream project has only change .d.ts files, and we've built
|
||||
// *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
|
||||
if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
|
||||
pseudoUpToDate = true;
|
||||
upstreamChangedProject = ref.path;
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have an output older than an upstream output - we are out of date
|
||||
Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
|
||||
return {
|
||||
type: UpToDateStatusType.OutOfDateWithUpstream,
|
||||
outOfDateOutputFileName: oldestOutputFileName,
|
||||
newerProjectName: ref.path
|
||||
};
|
||||
// We have an output older than an upstream output - we are out of date
|
||||
Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
|
||||
return {
|
||||
type: UpToDateStatusType.OutOfDateWithUpstream,
|
||||
outOfDateOutputFileName: oldestOutputFileName,
|
||||
newerProjectName: ref.path
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,10 +793,34 @@ namespace ts {
|
||||
newerInputFileName: newestInputFileName
|
||||
};
|
||||
}
|
||||
else {
|
||||
// Check tsconfig time
|
||||
const configStatus = checkConfigFileUpToDateStatus(project.options.configFilePath!, oldestOutputFileTime, oldestOutputFileName);
|
||||
if (configStatus) return configStatus;
|
||||
|
||||
// Check extended config time
|
||||
const extendedConfigStatus = forEach(project.options.configFile!.extendedSourceFiles || emptyArray, configFile => checkConfigFileUpToDateStatus(configFile, oldestOutputFileTime, oldestOutputFileName));
|
||||
if (extendedConfigStatus) return extendedConfigStatus;
|
||||
}
|
||||
|
||||
if (!buildInfoChecked.hasKey(project.options.configFilePath as ResolvedConfigFileName)) {
|
||||
buildInfoChecked.setValue(project.options.configFilePath as ResolvedConfigFileName, true);
|
||||
const buildInfoPath = getOutputPathForBuildInfo(project.options);
|
||||
if (buildInfoPath) {
|
||||
const value = readFileWithCache(buildInfoPath);
|
||||
const buildInfo = value && getBuildInfo(value);
|
||||
if (buildInfo && buildInfo.version !== version) {
|
||||
return {
|
||||
type: UpToDateStatusType.TsVersionOutputOfDate,
|
||||
version: buildInfo.version
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usesPrepend && pseudoUpToDate) {
|
||||
return {
|
||||
type: UpToDateStatusType.OutOfDateWithUpstream,
|
||||
type: UpToDateStatusType.OutOfDateWithPrepend,
|
||||
outOfDateOutputFileName: oldestOutputFileName,
|
||||
newerProjectName: upstreamChangedProject!
|
||||
};
|
||||
@@ -819,6 +838,18 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function checkConfigFileUpToDateStatus(configFile: string, oldestOutputFileTime: Date, oldestOutputFileName: string): Status.OutOfDateWithSelf | undefined {
|
||||
// Check tsconfig time
|
||||
const tsconfigTime = host.getModifiedTime(configFile) || missingFileModifiedTime;
|
||||
if (oldestOutputFileTime < tsconfigTime) {
|
||||
return {
|
||||
type: UpToDateStatusType.OutOfDateWithSelf,
|
||||
outOfDateOutputFileName: oldestOutputFileName,
|
||||
newerInputFileName: configFile
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function invalidateProject(configFileName: string, reloadLevel?: ConfigFileProgramReloadLevel) {
|
||||
invalidateResolvedProject(resolveProjectName(configFileName), reloadLevel);
|
||||
}
|
||||
@@ -898,7 +929,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function reportErrorSummary() {
|
||||
if (options.watch || (host as SolutionBuilderHost).reportErrorSummary) {
|
||||
if (options.watch || (host as SolutionBuilderHost<T>).reportErrorSummary) {
|
||||
// Report errors from the other projects
|
||||
getGlobalDependencyGraph().buildQueue.forEach(project => {
|
||||
if (!projectErrorsReported.hasKey(project)) {
|
||||
@@ -911,7 +942,7 @@ namespace ts {
|
||||
reportWatchStatus(getWatchErrorSummaryDiagnosticMessage(totalErrors), totalErrors);
|
||||
}
|
||||
else {
|
||||
(host as SolutionBuilderHost).reportErrorSummary!(totalErrors);
|
||||
(host as SolutionBuilderHost<T>).reportErrorSummary!(totalErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -944,16 +975,51 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
|
||||
const buildResult = buildSingleProject(resolved);
|
||||
const dependencyGraph = getGlobalDependencyGraph();
|
||||
const referencingProjects = dependencyGraph.referencingProjectsMap.getValue(resolved);
|
||||
if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes) {
|
||||
// Fake that files have been built by updating output file stamps
|
||||
updateOutputTimestamps(proj);
|
||||
return;
|
||||
}
|
||||
|
||||
const buildResult = needsBuild(status, resolved) ?
|
||||
buildSingleProject(resolved) : // Actual build
|
||||
updateBundle(resolved); // Fake that files have been built by manipulating prepend and existing output
|
||||
if (buildResult & BuildResultFlags.AnyErrors) return;
|
||||
|
||||
const { referencingProjectsMap, buildQueue } = getGlobalDependencyGraph();
|
||||
const referencingProjects = referencingProjectsMap.getValue(resolved);
|
||||
if (!referencingProjects) return;
|
||||
|
||||
// Always use build order to queue projects
|
||||
for (const project of dependencyGraph.buildQueue) {
|
||||
for (let index = buildQueue.indexOf(resolved) + 1; index < buildQueue.length; index++) {
|
||||
const project = buildQueue[index];
|
||||
const prepend = referencingProjects.getValue(project);
|
||||
// If the project is referenced with prepend, always build downstream projectm,
|
||||
// otherwise queue it only if declaration output changed
|
||||
if (prepend || (prepend !== undefined && !(buildResult & BuildResultFlags.DeclarationOutputUnchanged))) {
|
||||
if (prepend !== undefined) {
|
||||
// If the project is referenced with prepend, always build downstream projects,
|
||||
// If declaration output is changed, build the project
|
||||
// otherwise mark the project UpToDateWithUpstreamTypes so it updates output time stamps
|
||||
const status = projectStatus.getValue(project);
|
||||
if (!(buildResult & BuildResultFlags.DeclarationOutputUnchanged)) {
|
||||
if (status && (status.type === UpToDateStatusType.UpToDate || status.type === UpToDateStatusType.UpToDateWithUpstreamTypes || status.type === UpToDateStatusType.OutOfDateWithPrepend)) {
|
||||
projectStatus.setValue(project, {
|
||||
type: UpToDateStatusType.OutOfDateWithUpstream,
|
||||
outOfDateOutputFileName: status.type === UpToDateStatusType.OutOfDateWithPrepend ? status.outOfDateOutputFileName : status.oldestOutputFileName,
|
||||
newerProjectName: resolved
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (status && status.type === UpToDateStatusType.UpToDate) {
|
||||
if (prepend) {
|
||||
projectStatus.setValue(project, {
|
||||
type: UpToDateStatusType.OutOfDateWithPrepend,
|
||||
outOfDateOutputFileName: status.oldestOutputFileName,
|
||||
newerProjectName: resolved
|
||||
});
|
||||
}
|
||||
else {
|
||||
status.type = UpToDateStatusType.UpToDateWithUpstreamTypes;
|
||||
}
|
||||
}
|
||||
addProjToQueue(project);
|
||||
}
|
||||
}
|
||||
@@ -1013,8 +1079,7 @@ namespace ts {
|
||||
|
||||
if (options.verbose) reportStatus(Diagnostics.Building_project_0, proj);
|
||||
|
||||
let resultFlags = BuildResultFlags.None;
|
||||
resultFlags |= BuildResultFlags.DeclarationOutputUnchanged;
|
||||
let resultFlags = BuildResultFlags.DeclarationOutputUnchanged;
|
||||
|
||||
const configFile = parseConfigFile(proj);
|
||||
if (!configFile) {
|
||||
@@ -1030,22 +1095,22 @@ namespace ts {
|
||||
return BuildResultFlags.None;
|
||||
}
|
||||
|
||||
const programOptions: CreateProgramOptions = {
|
||||
projectReferences: configFile.projectReferences,
|
||||
host,
|
||||
rootNames: configFile.fileNames,
|
||||
options: configFile.options,
|
||||
configFileParsingDiagnostics: configFile.errors
|
||||
};
|
||||
if (host.beforeCreateProgram) {
|
||||
host.beforeCreateProgram(options);
|
||||
}
|
||||
const program = createProgram(programOptions);
|
||||
// TODO: handle resolve module name to cache result in project reference redirect
|
||||
projectCompilerOptions = configFile.options;
|
||||
const program = host.createProgram(
|
||||
configFile.fileNames,
|
||||
configFile.options,
|
||||
compilerHost,
|
||||
getOldProgram(proj, configFile),
|
||||
configFile.errors,
|
||||
configFile.projectReferences
|
||||
);
|
||||
|
||||
// Don't emit anything in the presence of syntactic errors or options diagnostics
|
||||
const syntaxDiagnostics = [
|
||||
...program.getOptionsDiagnostics(),
|
||||
...program.getConfigFileParsingDiagnostics(),
|
||||
...program.getOptionsDiagnostics(),
|
||||
...program.getGlobalDiagnostics(),
|
||||
...program.getSyntacticDiagnostics()];
|
||||
if (syntaxDiagnostics.length) {
|
||||
return buildErrors(syntaxDiagnostics, BuildResultFlags.SyntaxErrors, "Syntactic");
|
||||
@@ -1057,6 +1122,8 @@ namespace ts {
|
||||
return buildErrors(semanticDiagnostics, BuildResultFlags.TypeErrors, "Semantic");
|
||||
}
|
||||
|
||||
// Before emitting lets backup state, so we can revert it back if there are declaration errors to handle emit and declaration errors correctly
|
||||
program.backupState();
|
||||
let newestDeclarationFileContentChangedTime = minimumDate;
|
||||
let anyDtsChanged = false;
|
||||
let declDiagnostics: Diagnostic[] | undefined;
|
||||
@@ -1065,11 +1132,13 @@ namespace ts {
|
||||
emitFilesAndReportErrors(program, reportDeclarationDiagnostics, writeFileName, /*reportSummary*/ undefined, (name, text, writeByteOrderMark) => outputFiles.push({ name, text, writeByteOrderMark }));
|
||||
// Don't emit .d.ts if there are decl file errors
|
||||
if (declDiagnostics) {
|
||||
program.restoreState();
|
||||
return buildErrors(declDiagnostics, BuildResultFlags.DeclarationEmitErrors, "Declaration file");
|
||||
}
|
||||
|
||||
// Actual Emit
|
||||
const emitterDiagnostics = createDiagnosticCollection();
|
||||
const emittedOutputs = createFileMap<true>(toPath as ToPath);
|
||||
outputFiles.forEach(({ name, text, writeByteOrderMark }) => {
|
||||
let priorChangeTime: Date | undefined;
|
||||
if (!anyDtsChanged && isDeclarationFile(name)) {
|
||||
@@ -1083,7 +1152,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
writeFile(host, emitterDiagnostics, name, text, writeByteOrderMark);
|
||||
emittedOutputs.setValue(name, true);
|
||||
writeFile(compilerHost, emitterDiagnostics, name, text, writeByteOrderMark);
|
||||
if (priorChangeTime !== undefined) {
|
||||
newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime);
|
||||
unchangedOutputs.setValue(name, priorChangeTime);
|
||||
@@ -1095,49 +1165,135 @@ namespace ts {
|
||||
return buildErrors(emitDiagnostics, BuildResultFlags.EmitErrors, "Emit");
|
||||
}
|
||||
|
||||
const status: UpToDateStatus = {
|
||||
// Update time stamps for rest of the outputs
|
||||
newestDeclarationFileContentChangedTime = updateOutputTimestampsWorker(configFile, newestDeclarationFileContentChangedTime, Diagnostics.Updating_unchanged_output_timestamps_of_project_0, emittedOutputs);
|
||||
|
||||
const status: Status.UpToDate = {
|
||||
type: UpToDateStatusType.UpToDate,
|
||||
newestDeclarationFileContentChangedTime: anyDtsChanged ? maximumDate : newestDeclarationFileContentChangedTime
|
||||
newestDeclarationFileContentChangedTime: anyDtsChanged ? maximumDate : newestDeclarationFileContentChangedTime,
|
||||
oldestOutputFileName: outputFiles.length ? outputFiles[0].name : getFirstProjectOutput(configFile, !host.useCaseSensitiveFileNames())
|
||||
};
|
||||
diagnostics.removeKey(proj);
|
||||
projectStatus.setValue(proj, status);
|
||||
if (host.afterProgramEmitAndDiagnostics) {
|
||||
host.afterProgramEmitAndDiagnostics(program);
|
||||
}
|
||||
afterProgramCreate(proj, program);
|
||||
projectCompilerOptions = baseCompilerOptions;
|
||||
return resultFlags;
|
||||
|
||||
function buildErrors(diagnostics: ReadonlyArray<Diagnostic>, errorFlags: BuildResultFlags, errorType: string) {
|
||||
resultFlags |= errorFlags;
|
||||
reportAndStoreErrors(proj, diagnostics);
|
||||
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: `${errorType} errors` });
|
||||
if (host.afterProgramEmitAndDiagnostics) {
|
||||
host.afterProgramEmitAndDiagnostics(program);
|
||||
}
|
||||
afterProgramCreate(proj, program);
|
||||
projectCompilerOptions = baseCompilerOptions;
|
||||
return resultFlags;
|
||||
}
|
||||
}
|
||||
|
||||
function afterProgramCreate(proj: ResolvedConfigFileName, program: T) {
|
||||
if (host.afterProgramEmitAndDiagnostics) {
|
||||
host.afterProgramEmitAndDiagnostics(program);
|
||||
}
|
||||
if (options.watch) {
|
||||
program.releaseProgram();
|
||||
builderPrograms.setValue(proj, program);
|
||||
}
|
||||
}
|
||||
|
||||
function getOldProgram(proj: ResolvedConfigFileName, parsed: ParsedCommandLine) {
|
||||
if (options.force) return undefined;
|
||||
const value = builderPrograms.getValue(proj);
|
||||
if (value) return value;
|
||||
return readBuilderProgram(parsed.options, readFileWithCache) as any as T;
|
||||
}
|
||||
|
||||
function updateBundle(proj: ResolvedConfigFileName): BuildResultFlags {
|
||||
if (options.dry) {
|
||||
reportStatus(Diagnostics.A_non_dry_build_would_update_output_of_project_0, proj);
|
||||
return BuildResultFlags.Success;
|
||||
}
|
||||
|
||||
if (options.verbose) reportStatus(Diagnostics.Updating_output_of_project_0, proj);
|
||||
|
||||
// Update js, and source map
|
||||
const config = Debug.assertDefined(parseConfigFile(proj));
|
||||
projectCompilerOptions = config.options;
|
||||
const outputFiles = emitUsingBuildInfo(
|
||||
config,
|
||||
compilerHost,
|
||||
ref => parseConfigFile(resolveProjectName(ref.path)));
|
||||
if (isString(outputFiles)) {
|
||||
reportStatus(Diagnostics.Cannot_update_output_of_project_0_because_there_was_error_reading_file_1, proj, relName(outputFiles));
|
||||
return buildSingleProject(proj);
|
||||
}
|
||||
|
||||
// Actual Emit
|
||||
Debug.assert(!!outputFiles.length);
|
||||
const emitterDiagnostics = createDiagnosticCollection();
|
||||
const emittedOutputs = createFileMap<true>(toPath as ToPath);
|
||||
outputFiles.forEach(({ name, text, writeByteOrderMark }) => {
|
||||
emittedOutputs.setValue(name, true);
|
||||
writeFile(compilerHost, emitterDiagnostics, name, text, writeByteOrderMark);
|
||||
});
|
||||
const emitDiagnostics = emitterDiagnostics.getDiagnostics();
|
||||
if (emitDiagnostics.length) {
|
||||
reportAndStoreErrors(proj, emitDiagnostics);
|
||||
projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Emit errors" });
|
||||
projectCompilerOptions = baseCompilerOptions;
|
||||
return BuildResultFlags.DeclarationOutputUnchanged | BuildResultFlags.EmitErrors;
|
||||
}
|
||||
|
||||
// Update timestamps for dts
|
||||
const newestDeclarationFileContentChangedTime = updateOutputTimestampsWorker(config, minimumDate, Diagnostics.Updating_unchanged_output_timestamps_of_project_0, emittedOutputs);
|
||||
|
||||
const status: Status.UpToDate = {
|
||||
type: UpToDateStatusType.UpToDate,
|
||||
newestDeclarationFileContentChangedTime,
|
||||
oldestOutputFileName: outputFiles[0].name
|
||||
};
|
||||
|
||||
diagnostics.removeKey(proj);
|
||||
projectStatus.setValue(proj, status);
|
||||
projectCompilerOptions = baseCompilerOptions;
|
||||
return BuildResultFlags.DeclarationOutputUnchanged;
|
||||
}
|
||||
|
||||
function updateOutputTimestamps(proj: ParsedCommandLine) {
|
||||
if (options.dry) {
|
||||
return reportStatus(Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath!);
|
||||
return reportStatus(Diagnostics.A_non_dry_build_would_update_timestamps_for_output_of_project_0, proj.options.configFilePath!);
|
||||
}
|
||||
const priorNewestUpdateTime = updateOutputTimestampsWorker(proj, minimumDate, Diagnostics.Updating_output_timestamps_of_project_0);
|
||||
const status: Status.UpToDate = {
|
||||
type: UpToDateStatusType.UpToDate,
|
||||
newestDeclarationFileContentChangedTime: priorNewestUpdateTime,
|
||||
oldestOutputFileName: getFirstProjectOutput(proj, !host.useCaseSensitiveFileNames())
|
||||
};
|
||||
projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, status);
|
||||
}
|
||||
|
||||
if (options.verbose) {
|
||||
reportStatus(Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath!);
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const outputs = getAllProjectOutputs(proj);
|
||||
let priorNewestUpdateTime = minimumDate;
|
||||
for (const file of outputs) {
|
||||
if (isDeclarationFile(file)) {
|
||||
priorNewestUpdateTime = newer(priorNewestUpdateTime, host.getModifiedTime(file) || missingFileModifiedTime);
|
||||
function updateOutputTimestampsWorker(proj: ParsedCommandLine, priorNewestUpdateTime: Date, verboseMessage: DiagnosticMessage, skipOutputs?: FileMap<true>) {
|
||||
const outputs = getAllProjectOutputs(proj, !host.useCaseSensitiveFileNames());
|
||||
if (!skipOutputs || outputs.length !== skipOutputs.getSize()) {
|
||||
if (options.verbose) {
|
||||
reportStatus(verboseMessage, proj.options.configFilePath!);
|
||||
}
|
||||
const now = host.now ? host.now() : new Date();
|
||||
for (const file of outputs) {
|
||||
if (skipOutputs && skipOutputs.hasKey(file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
host.setModifiedTime(file, now);
|
||||
if (isDeclarationFile(file)) {
|
||||
priorNewestUpdateTime = newer(priorNewestUpdateTime, host.getModifiedTime(file) || missingFileModifiedTime);
|
||||
}
|
||||
|
||||
host.setModifiedTime(file, now);
|
||||
if (proj.options.listEmittedFiles) {
|
||||
writeFileName(`TSFILE: ${file}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime } as UpToDateStatus);
|
||||
return priorNewestUpdateTime;
|
||||
}
|
||||
|
||||
function getFilesToClean(): string[] {
|
||||
@@ -1151,7 +1307,7 @@ namespace ts {
|
||||
reportParseConfigFileDiagnostic(proj);
|
||||
continue;
|
||||
}
|
||||
const outputs = getAllProjectOutputs(parsed);
|
||||
const outputs = getAllProjectOutputs(parsed, !host.useCaseSensitiveFileNames());
|
||||
for (const output of outputs) {
|
||||
if (host.fileExists(output)) {
|
||||
filesToDelete.push(output);
|
||||
@@ -1187,12 +1343,15 @@ namespace ts {
|
||||
if (options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); }
|
||||
// TODO:: In watch mode as well to use caches for incremental build once we can invalidate caches correctly and have right api
|
||||
// Override readFile for json files and output .d.ts to cache the text
|
||||
const { originalReadFile, originalFileExists, originalDirectoryExists,
|
||||
originalCreateDirectory, originalWriteFile, originalGetSourceFile,
|
||||
readFileWithCache: newReadFileWithCache
|
||||
} = changeCompilerHostToUseCache(host, toPath, /*useCacheForSourceFile*/ true);
|
||||
const savedReadFileWithCache = readFileWithCache;
|
||||
const savedGetSourceFile = compilerHost.getSourceFile;
|
||||
|
||||
const { originalReadFile, originalFileExists, originalDirectoryExists,
|
||||
originalCreateDirectory, originalWriteFile, getSourceFileWithCache,
|
||||
readFileWithCache: newReadFileWithCache
|
||||
} = changeCompilerHostLikeToUseCache(host, toPath, (...args) => savedGetSourceFile.call(compilerHost, ...args));
|
||||
readFileWithCache = newReadFileWithCache;
|
||||
compilerHost.getSourceFile = getSourceFileWithCache!;
|
||||
|
||||
const graph = getGlobalDependencyGraph();
|
||||
reportBuildQueue(graph);
|
||||
@@ -1240,7 +1399,10 @@ namespace ts {
|
||||
continue;
|
||||
}
|
||||
|
||||
const buildResult = buildSingleProject(next);
|
||||
const buildResult = needsBuild(status, next) ?
|
||||
buildSingleProject(next) : // Actual build
|
||||
updateBundle(next); // Fake that files have been built by manipulating prepend and existing output
|
||||
|
||||
anyFailed = anyFailed || !!(buildResult & BuildResultFlags.AnyErrors);
|
||||
}
|
||||
reportErrorSummary();
|
||||
@@ -1249,11 +1411,20 @@ namespace ts {
|
||||
host.directoryExists = originalDirectoryExists;
|
||||
host.createDirectory = originalCreateDirectory;
|
||||
host.writeFile = originalWriteFile;
|
||||
compilerHost.getSourceFile = savedGetSourceFile;
|
||||
readFileWithCache = savedReadFileWithCache;
|
||||
host.getSourceFile = originalGetSourceFile;
|
||||
return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success;
|
||||
}
|
||||
|
||||
function needsBuild(status: UpToDateStatus, configFile: ResolvedConfigFileName) {
|
||||
if (status.type !== UpToDateStatusType.OutOfDateWithPrepend || options.force) return true;
|
||||
const config = parseConfigFile(configFile);
|
||||
return !config ||
|
||||
config.fileNames.length === 0 ||
|
||||
!!config.errors.length ||
|
||||
!isIncrementalCompilation(config.options);
|
||||
}
|
||||
|
||||
function reportParseConfigFileDiagnostic(proj: ResolvedConfigFileName) {
|
||||
reportAndStoreErrors(proj, [configFileCache.getValue(proj) as Diagnostic]);
|
||||
}
|
||||
@@ -1278,7 +1449,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function relName(path: string): string {
|
||||
return convertToRelativePath(path, host.getCurrentDirectory(), f => host.getCanonicalFileName(f));
|
||||
return convertToRelativePath(path, host.getCurrentDirectory(), f => compilerHost.getCanonicalFileName(f));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1298,19 +1469,6 @@ namespace ts {
|
||||
return combinePaths(project, "tsconfig.json") as ResolvedConfigFileName;
|
||||
}
|
||||
|
||||
export function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray<string> {
|
||||
if (project.options.outFile || project.options.out) {
|
||||
return getOutFileOutputs(project);
|
||||
}
|
||||
else {
|
||||
const outputs: string[] = [];
|
||||
for (const inputFile of project.fileNames) {
|
||||
outputs.push(...getOutputFileNames(inputFile, project));
|
||||
}
|
||||
return outputs;
|
||||
}
|
||||
}
|
||||
|
||||
export function formatUpToDateStatus<T>(configFileName: string, status: UpToDateStatus, relName: (fileName: string) => string, formatMessage: (message: DiagnosticMessage, ...args: string[]) => T) {
|
||||
switch (status.type) {
|
||||
case UpToDateStatusType.OutOfDateWithSelf:
|
||||
@@ -1336,6 +1494,10 @@ namespace ts {
|
||||
}
|
||||
// Don't report anything for "up to date because it was already built" -- too verbose
|
||||
break;
|
||||
case UpToDateStatusType.OutOfDateWithPrepend:
|
||||
return formatMessage(Diagnostics.Project_0_is_out_of_date_because_output_of_its_dependency_1_has_changed,
|
||||
relName(configFileName),
|
||||
relName(status.newerProjectName));
|
||||
case UpToDateStatusType.UpToDateWithUpstreamTypes:
|
||||
return formatMessage(Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies,
|
||||
relName(configFileName));
|
||||
@@ -1351,6 +1513,11 @@ namespace ts {
|
||||
return formatMessage(Diagnostics.Failed_to_parse_file_0_Colon_1,
|
||||
relName(configFileName),
|
||||
status.reason);
|
||||
case UpToDateStatusType.TsVersionOutputOfDate:
|
||||
return formatMessage(Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2,
|
||||
relName(configFileName),
|
||||
status.version,
|
||||
version);
|
||||
case UpToDateStatusType.ContainerOnly:
|
||||
// Don't report status on "solution" projects
|
||||
case UpToDateStatusType.ComputingUpstream:
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
"transformers/destructuring.ts",
|
||||
"transformers/ts.ts",
|
||||
"transformers/es2017.ts",
|
||||
"transformers/es2018.ts",
|
||||
"transformers/es2019.ts",
|
||||
"transformers/esnext.ts",
|
||||
"transformers/jsx.ts",
|
||||
"transformers/es2016.ts",
|
||||
|
||||
+347
-154
@@ -428,6 +428,13 @@ namespace ts {
|
||||
|
||||
// Enum
|
||||
EnumMember,
|
||||
// Unparsed
|
||||
UnparsedPrologue,
|
||||
UnparsedPrepend,
|
||||
UnparsedText,
|
||||
UnparsedInternalText,
|
||||
UnparsedSyntheticReference,
|
||||
|
||||
// Top-level nodes
|
||||
SourceFile,
|
||||
Bundle,
|
||||
@@ -609,7 +616,7 @@ namespace ts {
|
||||
export interface Node extends TextRange {
|
||||
kind: SyntaxKind;
|
||||
flags: NodeFlags;
|
||||
/* @internal */ modifierFlagsCache?: ModifierFlags;
|
||||
/* @internal */ modifierFlagsCache: ModifierFlags;
|
||||
/* @internal */ transformFlags: TransformFlags; // Flags for transforms, possibly undefined
|
||||
decorators?: NodeArray<Decorator>; // Array of decorators (in document order)
|
||||
modifiers?: ModifiersArray; // Array of modifiers
|
||||
@@ -623,7 +630,7 @@ namespace ts {
|
||||
/* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding)
|
||||
/* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms)
|
||||
/* @internal */ contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
|
||||
/* @internal */ contextualMapper?: TypeMapper; // Mapper for contextual type
|
||||
/* @internal */ inferenceContext?: InferenceContext; // Inference context for contextual type
|
||||
}
|
||||
|
||||
export interface JSDocContainer {
|
||||
@@ -1233,7 +1240,7 @@ namespace ts {
|
||||
|
||||
export interface TypeOperatorNode extends TypeNode {
|
||||
kind: SyntaxKind.TypeOperator;
|
||||
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword;
|
||||
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
@@ -1648,20 +1655,26 @@ namespace ts {
|
||||
kind: SyntaxKind.NoSubstitutionTemplateLiteral;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const enum TokenFlags {
|
||||
None = 0,
|
||||
/* @internal */
|
||||
PrecedingLineBreak = 1 << 0,
|
||||
/* @internal */
|
||||
PrecedingJSDocComment = 1 << 1,
|
||||
/* @internal */
|
||||
Unterminated = 1 << 2,
|
||||
/* @internal */
|
||||
ExtendedUnicodeEscape = 1 << 3,
|
||||
Scientific = 1 << 4, // e.g. `10e2`
|
||||
Octal = 1 << 5, // e.g. `0777`
|
||||
HexSpecifier = 1 << 6, // e.g. `0x00000000`
|
||||
BinarySpecifier = 1 << 7, // e.g. `0b0110010000000000`
|
||||
OctalSpecifier = 1 << 8, // e.g. `0o777`
|
||||
/* @internal */
|
||||
ContainsSeparator = 1 << 9, // e.g. `0b1100_0101`
|
||||
/* @internal */
|
||||
BinaryOrOctalSpecifier = BinarySpecifier | OctalSpecifier,
|
||||
/* @internal */
|
||||
NumericLiteralFlags = Scientific | Octal | HexSpecifier | BinaryOrOctalSpecifier | ContainsSeparator
|
||||
}
|
||||
|
||||
@@ -1932,9 +1945,9 @@ namespace ts {
|
||||
expression?: Expression;
|
||||
}
|
||||
|
||||
export interface JsxText extends Node {
|
||||
export interface JsxText extends LiteralLikeNode {
|
||||
kind: SyntaxKind.JsxText;
|
||||
containsOnlyWhiteSpaces: boolean;
|
||||
containsOnlyTriviaWhiteSpaces: boolean;
|
||||
parent: JsxElement;
|
||||
}
|
||||
|
||||
@@ -2727,12 +2740,6 @@ namespace ts {
|
||||
/* @internal */ resolvedModules?: Map<ResolvedModuleFull | undefined>;
|
||||
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective | undefined>;
|
||||
/* @internal */ imports: ReadonlyArray<StringLiteralLike>;
|
||||
/**
|
||||
* When a file's references are redirected due to project reference directives,
|
||||
* the original names of the references are stored in this array
|
||||
*/
|
||||
/* @internal*/
|
||||
redirectedReferences?: ReadonlyArray<string>;
|
||||
// Identifier only if `declare global`
|
||||
/* @internal */ moduleAugmentations: ReadonlyArray<StringLiteral | Identifier>;
|
||||
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
|
||||
@@ -2761,19 +2768,74 @@ namespace ts {
|
||||
|
||||
export interface InputFiles extends Node {
|
||||
kind: SyntaxKind.InputFiles;
|
||||
javascriptPath?: string;
|
||||
javascriptText: string;
|
||||
javascriptMapPath?: string;
|
||||
javascriptMapText?: string;
|
||||
declarationPath?: string;
|
||||
declarationText: string;
|
||||
declarationMapPath?: string;
|
||||
declarationMapText?: string;
|
||||
/*@internal*/ buildInfoPath?: string;
|
||||
/*@internal*/ buildInfo?: BuildInfo;
|
||||
/*@internal*/ oldFileOfCurrentEmit?: boolean;
|
||||
}
|
||||
|
||||
export interface UnparsedSource extends Node {
|
||||
kind: SyntaxKind.UnparsedSource;
|
||||
fileName: string;
|
||||
text: string;
|
||||
prologues: ReadonlyArray<UnparsedPrologue>;
|
||||
helpers: ReadonlyArray<UnscopedEmitHelper> | undefined;
|
||||
|
||||
// References and noDefaultLibAre Dts only
|
||||
referencedFiles: ReadonlyArray<FileReference>;
|
||||
typeReferenceDirectives: ReadonlyArray<string> | undefined;
|
||||
libReferenceDirectives: ReadonlyArray<FileReference>;
|
||||
hasNoDefaultLib?: boolean;
|
||||
|
||||
sourceMapPath?: string;
|
||||
sourceMapText?: string;
|
||||
syntheticReferences?: ReadonlyArray<UnparsedSyntheticReference>;
|
||||
texts: ReadonlyArray<UnparsedSourceText>;
|
||||
/*@internal*/ oldFileOfCurrentEmit?: boolean;
|
||||
/*@internal*/ parsedSourceMap?: RawSourceMap | false | undefined;
|
||||
// Adding this to satisfy services, fix later
|
||||
/*@internal*/
|
||||
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
|
||||
}
|
||||
|
||||
export type UnparsedSourceText = UnparsedPrepend | UnparsedTextLike;
|
||||
export type UnparsedNode = UnparsedPrologue | UnparsedSourceText | UnparsedSyntheticReference;
|
||||
|
||||
export interface UnparsedSection extends Node {
|
||||
kind: SyntaxKind;
|
||||
data?: string;
|
||||
parent: UnparsedSource;
|
||||
}
|
||||
|
||||
export interface UnparsedPrologue extends UnparsedSection {
|
||||
kind: SyntaxKind.UnparsedPrologue;
|
||||
data: string;
|
||||
parent: UnparsedSource;
|
||||
}
|
||||
|
||||
export interface UnparsedPrepend extends UnparsedSection {
|
||||
kind: SyntaxKind.UnparsedPrepend;
|
||||
data: string;
|
||||
parent: UnparsedSource;
|
||||
texts: ReadonlyArray<UnparsedTextLike>;
|
||||
}
|
||||
|
||||
export interface UnparsedTextLike extends UnparsedSection {
|
||||
kind: SyntaxKind.UnparsedText | SyntaxKind.UnparsedInternalText;
|
||||
parent: UnparsedSource;
|
||||
}
|
||||
|
||||
export interface UnparsedSyntheticReference extends UnparsedSection {
|
||||
kind: SyntaxKind.UnparsedSyntheticReference;
|
||||
parent: UnparsedSource;
|
||||
/*@internal*/ section: BundleFileHasNoDefaultLib | BundleFileReference;
|
||||
}
|
||||
|
||||
export interface JsonSourceFile extends SourceFile {
|
||||
@@ -2827,7 +2889,7 @@ namespace ts {
|
||||
fileName: string,
|
||||
data: string,
|
||||
writeByteOrderMark: boolean,
|
||||
onError: ((message: string) => void) | undefined,
|
||||
onError?: (message: string) => void,
|
||||
sourceFiles?: ReadonlyArray<SourceFile>,
|
||||
) => void;
|
||||
|
||||
@@ -2926,6 +2988,8 @@ namespace ts {
|
||||
/*@internal*/ getResolvedProjectReferenceToRedirect(fileName: string): ResolvedProjectReference | undefined;
|
||||
/*@internal*/ forEachResolvedProjectReference<T>(cb: (resolvedProjectReference: ResolvedProjectReference | undefined, resolvedProjectReferencePath: Path) => T | undefined): T | undefined;
|
||||
/*@internal*/ getResolvedProjectReferenceByPath(projectReferencePath: Path): ResolvedProjectReference | undefined;
|
||||
/*@internal*/ getProgramBuildInfo?(): ProgramBuildInfo | undefined;
|
||||
/*@internal*/ emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -3004,6 +3068,7 @@ namespace ts {
|
||||
getSourceFiles(): ReadonlyArray<SourceFile>;
|
||||
getSourceFile(fileName: string): SourceFile | undefined;
|
||||
getResolvedTypeReferenceDirectives(): ReadonlyMap<ResolvedTypeReferenceDirective | undefined>;
|
||||
getProjectReferenceRedirect(fileName: string): string | undefined;
|
||||
|
||||
readonly redirectTargetsMap: RedirectTargetsMap;
|
||||
}
|
||||
@@ -3037,8 +3102,10 @@ namespace ts {
|
||||
/* @internal */ typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker): TypeNode | undefined; // tslint:disable-line unified-signatures
|
||||
/** Note that the resulting nodes cannot be checked. */
|
||||
signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): SignatureDeclaration & {typeArguments?: NodeArray<TypeNode>} | undefined;
|
||||
/* @internal */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker): SignatureDeclaration & {typeArguments?: NodeArray<TypeNode>} | undefined; // tslint:disable-line unified-signatures
|
||||
/** Note that the resulting nodes cannot be checked. */
|
||||
indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): IndexSignatureDeclaration | undefined;
|
||||
/* @internal */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker): IndexSignatureDeclaration | undefined; // tslint:disable-line unified-signatures
|
||||
/** Note that the resulting nodes cannot be checked. */
|
||||
symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): EntityName | undefined;
|
||||
/** Note that the resulting nodes cannot be checked. */
|
||||
@@ -3098,6 +3165,8 @@ namespace ts {
|
||||
*/
|
||||
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
|
||||
/* @internal */ getResolvedSignatureForSignatureHelp(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
|
||||
/* @internal */ getExpandedParameters(sig: Signature): ReadonlyArray<Symbol>;
|
||||
/* @internal */ hasEffectiveRestParameter(sig: Signature): boolean;
|
||||
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined;
|
||||
isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined;
|
||||
isUndefinedSymbol(symbol: Symbol): boolean;
|
||||
@@ -3178,6 +3247,8 @@ namespace ts {
|
||||
/* @internal */ getSymbolCount(): number;
|
||||
/* @internal */ getTypeCount(): number;
|
||||
|
||||
/* @internal */ isArrayType(type: Type): boolean;
|
||||
/* @internal */ isTupleType(type: Type): boolean;
|
||||
/* @internal */ isArrayLikeType(type: Type): boolean;
|
||||
/* @internal */ getObjectFlags(type: Type): ObjectFlags;
|
||||
|
||||
@@ -3212,7 +3283,7 @@ namespace ts {
|
||||
*/
|
||||
/* @internal */ resolveExternalModuleSymbol(symbol: Symbol): Symbol;
|
||||
/** @param node A location where we might consider accessing `this`. Not necessarily a ThisExpression. */
|
||||
/* @internal */ tryGetThisTypeAt(node: Node): Type | undefined;
|
||||
/* @internal */ tryGetThisTypeAt(node: Node, includeGlobalThis?: boolean): Type | undefined;
|
||||
/* @internal */ getTypeArgumentConstraint(node: TypeNode): Type | undefined;
|
||||
|
||||
/**
|
||||
@@ -3812,39 +3883,33 @@ namespace ts {
|
||||
}
|
||||
|
||||
export const enum TypeFlags {
|
||||
Any = 1 << 0,
|
||||
Unknown = 1 << 1,
|
||||
String = 1 << 2,
|
||||
Number = 1 << 3,
|
||||
Boolean = 1 << 4,
|
||||
Enum = 1 << 5,
|
||||
BigInt = 1 << 6,
|
||||
StringLiteral = 1 << 7,
|
||||
NumberLiteral = 1 << 8,
|
||||
BooleanLiteral = 1 << 9,
|
||||
EnumLiteral = 1 << 10, // Always combined with StringLiteral, NumberLiteral, or Union
|
||||
BigIntLiteral = 1 << 11,
|
||||
ESSymbol = 1 << 12, // Type of symbol primitive introduced in ES6
|
||||
UniqueESSymbol = 1 << 13, // unique symbol
|
||||
Void = 1 << 14,
|
||||
Undefined = 1 << 15,
|
||||
Null = 1 << 16,
|
||||
Never = 1 << 17, // Never type
|
||||
TypeParameter = 1 << 18, // Type parameter
|
||||
Object = 1 << 19, // Object type
|
||||
Union = 1 << 20, // Union (T | U)
|
||||
Intersection = 1 << 21, // Intersection (T & U)
|
||||
Index = 1 << 22, // keyof T
|
||||
IndexedAccess = 1 << 23, // T[K]
|
||||
Conditional = 1 << 24, // T extends U ? X : Y
|
||||
Substitution = 1 << 25, // Type parameter substitution
|
||||
NonPrimitive = 1 << 26, // intrinsic object type
|
||||
/* @internal */
|
||||
ContainsWideningType = 1 << 27, // Type is or contains undefined or null widening type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 1 << 28, // Type is or contains object literal type
|
||||
/* @internal */
|
||||
ContainsAnyFunctionType = 1 << 29, // Type is or contains the anyFunctionType
|
||||
Any = 1 << 0,
|
||||
Unknown = 1 << 1,
|
||||
String = 1 << 2,
|
||||
Number = 1 << 3,
|
||||
Boolean = 1 << 4,
|
||||
Enum = 1 << 5,
|
||||
BigInt = 1 << 6,
|
||||
StringLiteral = 1 << 7,
|
||||
NumberLiteral = 1 << 8,
|
||||
BooleanLiteral = 1 << 9,
|
||||
EnumLiteral = 1 << 10, // Always combined with StringLiteral, NumberLiteral, or Union
|
||||
BigIntLiteral = 1 << 11,
|
||||
ESSymbol = 1 << 12, // Type of symbol primitive introduced in ES6
|
||||
UniqueESSymbol = 1 << 13, // unique symbol
|
||||
Void = 1 << 14,
|
||||
Undefined = 1 << 15,
|
||||
Null = 1 << 16,
|
||||
Never = 1 << 17, // Never type
|
||||
TypeParameter = 1 << 18, // Type parameter
|
||||
Object = 1 << 19, // Object type
|
||||
Union = 1 << 20, // Union (T | U)
|
||||
Intersection = 1 << 21, // Intersection (T & U)
|
||||
Index = 1 << 22, // keyof T
|
||||
IndexedAccess = 1 << 23, // T[K]
|
||||
Conditional = 1 << 24, // T extends U ? X : Y
|
||||
Substitution = 1 << 25, // Type parameter substitution
|
||||
NonPrimitive = 1 << 26, // intrinsic object type
|
||||
|
||||
/* @internal */
|
||||
AnyOrUnknown = Any | Unknown,
|
||||
@@ -3878,29 +3943,29 @@ namespace ts {
|
||||
InstantiablePrimitive = Index,
|
||||
Instantiable = InstantiableNonPrimitive | InstantiablePrimitive,
|
||||
StructuredOrInstantiable = StructuredType | Instantiable,
|
||||
|
||||
/* @internal */
|
||||
ObjectFlagsType = Nullable | Object | Union | Intersection,
|
||||
// 'Narrowable' types are types where narrowing actually narrows.
|
||||
// This *should* be every type other than null, undefined, void, and never
|
||||
Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive,
|
||||
NotUnionOrUnit = Any | Unknown | ESSymbol | Object | NonPrimitive,
|
||||
/* @internal */
|
||||
NotPrimitiveUnion = Any | Unknown | Enum | Void | Never | StructuredOrInstantiable,
|
||||
// The following flags are aggregated during union and intersection type construction
|
||||
/* @internal */
|
||||
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
|
||||
/* @internal */
|
||||
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType,
|
||||
IncludesMask = Any | Unknown | Primitive | Never | Object | Union,
|
||||
// The following flags are used for different purposes during union and intersection type construction
|
||||
/* @internal */
|
||||
NonWideningType = ContainsWideningType,
|
||||
IncludesStructuredOrInstantiable = TypeParameter,
|
||||
/* @internal */
|
||||
Wildcard = ContainsObjectLiteral,
|
||||
IncludesNonWideningType = Intersection,
|
||||
/* @internal */
|
||||
EmptyObject = ContainsAnyFunctionType,
|
||||
IncludesWildcard = Index,
|
||||
/* @internal */
|
||||
ConstructionFlags = NonWideningType | Wildcard | EmptyObject,
|
||||
IncludesEmptyObject = IndexedAccess,
|
||||
// The following flag is used for different purposes by maybeTypeOfKind
|
||||
/* @internal */
|
||||
GenericMappedType = ContainsWideningType
|
||||
GenericMappedType = Never,
|
||||
}
|
||||
|
||||
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
|
||||
@@ -3927,6 +3992,12 @@ namespace ts {
|
||||
// Intrinsic types (TypeFlags.Intrinsic)
|
||||
export interface IntrinsicType extends Type {
|
||||
intrinsicName: string; // Name of intrinsic type
|
||||
objectFlags: ObjectFlags;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface NullableType extends IntrinsicType {
|
||||
objectFlags: ObjectFlags;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -3950,6 +4021,7 @@ namespace ts {
|
||||
// Unique symbol types (TypeFlags.UniqueESSymbol)
|
||||
export interface UniqueESSymbolType extends Type {
|
||||
symbol: Symbol;
|
||||
escapedName: __String;
|
||||
}
|
||||
|
||||
export interface StringLiteralType extends LiteralType {
|
||||
@@ -3985,9 +4057,24 @@ namespace ts {
|
||||
MarkerType = 1 << 13, // Marker type used for variance probing
|
||||
JSLiteral = 1 << 14, // Object type declared in JS - disables errors on read/write of nonexisting members
|
||||
FreshLiteral = 1 << 15, // Fresh object literal
|
||||
ClassOrInterface = Class | Interface
|
||||
/* @internal */
|
||||
PrimitiveUnion = 1 << 16, // Union of only primitive types
|
||||
/* @internal */
|
||||
ContainsWideningType = 1 << 17, // Type is or contains undefined or null widening type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 1 << 18, // Type is or contains object literal type
|
||||
/* @internal */
|
||||
ContainsAnyFunctionType = 1 << 19, // Type is or contains the anyFunctionType
|
||||
ClassOrInterface = Class | Interface,
|
||||
/* @internal */
|
||||
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
|
||||
/* @internal */
|
||||
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export type ObjectFlagsType = NullableType | ObjectType | UnionType | IntersectionType;
|
||||
|
||||
// Object types (TypeFlags.ObjectType)
|
||||
export interface ObjectType extends Type {
|
||||
objectFlags: ObjectFlags;
|
||||
@@ -4057,6 +4144,7 @@ namespace ts {
|
||||
export interface TupleType extends GenericType {
|
||||
minLength: number;
|
||||
hasRestElement: boolean;
|
||||
readonly: boolean;
|
||||
associatedNames?: __String[];
|
||||
}
|
||||
|
||||
@@ -4067,6 +4155,8 @@ namespace ts {
|
||||
export interface UnionOrIntersectionType extends Type {
|
||||
types: Type[]; // Constituent types
|
||||
/* @internal */
|
||||
objectFlags: ObjectFlags;
|
||||
/* @internal */
|
||||
propertyCache: SymbolTable; // Cache of resolved properties
|
||||
/* @internal */
|
||||
resolvedProperties: Symbol[];
|
||||
@@ -4081,8 +4171,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface UnionType extends UnionOrIntersectionType {
|
||||
/* @internal */
|
||||
primitiveTypesOnly: boolean;
|
||||
}
|
||||
|
||||
export interface IntersectionType extends UnionOrIntersectionType {
|
||||
@@ -4107,7 +4195,6 @@ namespace ts {
|
||||
templateType?: Type;
|
||||
modifiersType?: Type;
|
||||
resolvedApparentType?: Type;
|
||||
instantiating?: boolean;
|
||||
}
|
||||
|
||||
export interface EvolvingArrayType extends ObjectType {
|
||||
@@ -4223,8 +4310,10 @@ namespace ts {
|
||||
root: ConditionalRoot;
|
||||
checkType: Type;
|
||||
extendsType: Type;
|
||||
resolvedTrueType?: Type;
|
||||
resolvedFalseType?: Type;
|
||||
trueType: Type;
|
||||
falseType: Type;
|
||||
/* @internal */
|
||||
resolvedInferredTrueType?: Type; // The `trueType` instantiated with the `combinedMapper`, if present
|
||||
/* @internal */
|
||||
resolvedDefaultConstraint?: Type;
|
||||
/* @internal */
|
||||
@@ -4334,6 +4423,7 @@ namespace ts {
|
||||
None = 0, // No special inference behaviors
|
||||
NoDefault = 1 << 0, // Infer unknownType for no inferences (otherwise anyType or emptyObjectType)
|
||||
AnyDefault = 1 << 1, // Infer anyType for no inferences (otherwise emptyObjectType)
|
||||
SkippedGenericFunction = 1 << 2, // A generic function was skipped during inference
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4356,12 +4446,15 @@ namespace ts {
|
||||
export type TypeComparer = (s: Type, t: Type, reportErrors?: boolean) => Ternary;
|
||||
|
||||
/* @internal */
|
||||
export interface InferenceContext extends TypeMapper {
|
||||
typeParameters: ReadonlyArray<TypeParameter>; // Type parameters for which inferences are made
|
||||
signature?: Signature; // Generic signature for which inferences are made (if any)
|
||||
export interface InferenceContext {
|
||||
inferences: InferenceInfo[]; // Inferences made for each type parameter
|
||||
signature?: Signature; // Generic signature for which inferences are made (if any)
|
||||
flags: InferenceFlags; // Inference flags
|
||||
compareTypes: TypeComparer; // Type comparer function
|
||||
mapper: TypeMapper; // Mapper that fixes inferences
|
||||
nonFixingMapper: TypeMapper; // Mapper that doesn't fix inferences
|
||||
returnMapper?: TypeMapper; // Type mapper for inferences from return types (if any)
|
||||
inferredTypeParameters?: ReadonlyArray<TypeParameter>; // Inferred type parameters for function result
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -4556,6 +4649,8 @@ namespace ts {
|
||||
reactNamespace?: string;
|
||||
jsxFactory?: string;
|
||||
composite?: boolean;
|
||||
incremental?: boolean;
|
||||
tsBuildInfoFile?: string;
|
||||
removeComments?: boolean;
|
||||
rootDir?: string;
|
||||
rootDirs?: string[];
|
||||
@@ -4650,7 +4745,8 @@ namespace ts {
|
||||
ES2016 = 3,
|
||||
ES2017 = 4,
|
||||
ES2018 = 5,
|
||||
ESNext = 6,
|
||||
ES2019 = 6,
|
||||
ESNext = 7,
|
||||
JSON = 100,
|
||||
Latest = ESNext,
|
||||
}
|
||||
@@ -4965,7 +5061,8 @@ namespace ts {
|
||||
Dts = ".d.ts",
|
||||
Js = ".js",
|
||||
Jsx = ".jsx",
|
||||
Json = ".json"
|
||||
Json = ".json",
|
||||
TsBuildInfo = ".tsbuildinfo"
|
||||
}
|
||||
|
||||
export interface ResolvedModuleWithFailedLookupLocations {
|
||||
@@ -5000,7 +5097,6 @@ namespace ts {
|
||||
getDefaultLibLocation?(): string;
|
||||
writeFile: WriteFileCallback;
|
||||
getCurrentDirectory(): string;
|
||||
getDirectories(path: string): string[];
|
||||
getCanonicalFileName(fileName: string): string;
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
getNewLine(): string;
|
||||
@@ -5034,36 +5130,29 @@ namespace ts {
|
||||
|
||||
// Facts
|
||||
// - Flags used to indicate that a node or subtree contains syntax that requires transformation.
|
||||
TypeScript = 1 << 0,
|
||||
ContainsTypeScript = 1 << 1,
|
||||
ContainsJsx = 1 << 2,
|
||||
ContainsESNext = 1 << 3,
|
||||
ContainsES2017 = 1 << 4,
|
||||
ContainsES2016 = 1 << 5,
|
||||
ES2015 = 1 << 6,
|
||||
ContainsTypeScript = 1 << 0,
|
||||
ContainsJsx = 1 << 1,
|
||||
ContainsESNext = 1 << 2,
|
||||
ContainsES2019 = 1 << 3,
|
||||
ContainsES2018 = 1 << 4,
|
||||
ContainsES2017 = 1 << 5,
|
||||
ContainsES2016 = 1 << 6,
|
||||
ContainsES2015 = 1 << 7,
|
||||
Generator = 1 << 8,
|
||||
ContainsGenerator = 1 << 9,
|
||||
DestructuringAssignment = 1 << 10,
|
||||
ContainsDestructuringAssignment = 1 << 11,
|
||||
ContainsGenerator = 1 << 8,
|
||||
ContainsDestructuringAssignment = 1 << 9,
|
||||
|
||||
// Markers
|
||||
// - Flags used to indicate that a subtree contains a specific transformation.
|
||||
ContainsTypeScriptClassSyntax = 1 << 12, // Decorators, Property Initializers, Parameter Property Initializers
|
||||
ContainsLexicalThis = 1 << 13,
|
||||
ContainsCapturedLexicalThis = 1 << 14,
|
||||
ContainsLexicalThisInComputedPropertyName = 1 << 15,
|
||||
ContainsDefaultValueAssignments = 1 << 16,
|
||||
ContainsRestOrSpread = 1 << 17,
|
||||
ContainsObjectRestOrSpread = 1 << 18,
|
||||
ContainsComputedPropertyName = 1 << 19,
|
||||
ContainsBlockScopedBinding = 1 << 20,
|
||||
ContainsBindingPattern = 1 << 21,
|
||||
ContainsYield = 1 << 22,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 23,
|
||||
ContainsDynamicImport = 1 << 24,
|
||||
Super = 1 << 25,
|
||||
ContainsSuper = 1 << 26,
|
||||
ContainsTypeScriptClassSyntax = 1 << 10, // Decorators, Property Initializers, Parameter Property Initializers
|
||||
ContainsLexicalThis = 1 << 11,
|
||||
ContainsRestOrSpread = 1 << 12,
|
||||
ContainsObjectRestOrSpread = 1 << 13,
|
||||
ContainsComputedPropertyName = 1 << 14,
|
||||
ContainsBlockScopedBinding = 1 << 15,
|
||||
ContainsBindingPattern = 1 << 16,
|
||||
ContainsYield = 1 << 17,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 18,
|
||||
ContainsDynamicImport = 1 << 19,
|
||||
|
||||
// Please leave this as 1 << 29.
|
||||
// It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system.
|
||||
@@ -5072,38 +5161,44 @@ namespace ts {
|
||||
|
||||
// Assertions
|
||||
// - Bitmasks that are used to assert facts about the syntax of a node and its subtree.
|
||||
AssertTypeScript = TypeScript | ContainsTypeScript,
|
||||
AssertTypeScript = ContainsTypeScript,
|
||||
AssertJsx = ContainsJsx,
|
||||
AssertESNext = ContainsESNext,
|
||||
AssertES2019 = ContainsES2019,
|
||||
AssertES2018 = ContainsES2018,
|
||||
AssertES2017 = ContainsES2017,
|
||||
AssertES2016 = ContainsES2016,
|
||||
AssertES2015 = ES2015 | ContainsES2015,
|
||||
AssertGenerator = Generator | ContainsGenerator,
|
||||
AssertDestructuringAssignment = DestructuringAssignment | ContainsDestructuringAssignment,
|
||||
AssertES2015 = ContainsES2015,
|
||||
AssertGenerator = ContainsGenerator,
|
||||
AssertDestructuringAssignment = ContainsDestructuringAssignment,
|
||||
|
||||
// Scope Exclusions
|
||||
// - Bitmasks that exclude flags from propagating out of a specific context
|
||||
// into the subtree flags of their container.
|
||||
OuterExpressionExcludes = TypeScript | ES2015 | DestructuringAssignment | Generator | HasComputedFlags,
|
||||
PropertyAccessExcludes = OuterExpressionExcludes | Super,
|
||||
NodeExcludes = PropertyAccessExcludes | ContainsSuper,
|
||||
ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
ClassExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName,
|
||||
ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
|
||||
OuterExpressionExcludes = HasComputedFlags,
|
||||
PropertyAccessExcludes = OuterExpressionExcludes,
|
||||
NodeExcludes = PropertyAccessExcludes,
|
||||
ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
ConstructorExcludes = NodeExcludes | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
MethodOrAccessorExcludes = NodeExcludes | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
PropertyExcludes = NodeExcludes | ContainsLexicalThis,
|
||||
ClassExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName,
|
||||
ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
|
||||
TypeExcludes = ~ContainsTypeScript,
|
||||
ObjectLiteralExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName | ContainsObjectRestOrSpread,
|
||||
ObjectLiteralExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName | ContainsObjectRestOrSpread,
|
||||
ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsRestOrSpread,
|
||||
VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
ParameterExcludes = NodeExcludes,
|
||||
CatchClauseExcludes = NodeExcludes | ContainsObjectRestOrSpread,
|
||||
BindingPatternExcludes = NodeExcludes | ContainsRestOrSpread,
|
||||
|
||||
// Propagating flags
|
||||
// - Bitmasks for flags that should propagate from a child
|
||||
PropertyNamePropagatingFlags = ContainsLexicalThis,
|
||||
|
||||
// Masks
|
||||
// - Additional bitmasks
|
||||
ES2015FunctionSyntaxMask = ContainsCapturedLexicalThis | ContainsDefaultValueAssignments,
|
||||
}
|
||||
|
||||
export interface SourceMapRange extends TextRange {
|
||||
@@ -5173,6 +5268,11 @@ namespace ts {
|
||||
readonly priority?: number; // Helpers with a higher priority are emitted earlier than other helpers on the node.
|
||||
}
|
||||
|
||||
export interface UnscopedEmitHelper extends EmitHelper {
|
||||
readonly scoped: false; // Indicates whether the helper MUST be emitted in the current scope.
|
||||
readonly text: string; // ES3-compatible raw script text, or a function yielding such a string
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export type UniqueNameHandler = (baseName: string, checkFn?: (name: string) => boolean, optimistic?: boolean) => string;
|
||||
|
||||
@@ -5237,6 +5337,7 @@ namespace ts {
|
||||
getCurrentDirectory(): string;
|
||||
|
||||
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
|
||||
getResolvedProjectReferenceToRedirect(fileName: string): ResolvedProjectReference | undefined;
|
||||
getLibFileFromReference(ref: FileReference): SourceFile | undefined;
|
||||
|
||||
getCommonSourceDirectory(): string;
|
||||
@@ -5245,9 +5346,10 @@ namespace ts {
|
||||
|
||||
isEmitBlocked(emitFileName: string): boolean;
|
||||
|
||||
getPrependNodes(): ReadonlyArray<InputFiles>;
|
||||
getPrependNodes(): ReadonlyArray<InputFiles | UnparsedSource>;
|
||||
|
||||
writeFile: WriteFileCallback;
|
||||
getProgramBuildInfo(): ProgramBuildInfo | undefined;
|
||||
}
|
||||
|
||||
export interface TransformationContext {
|
||||
@@ -5398,23 +5500,116 @@ namespace ts {
|
||||
/*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
|
||||
/*@internal*/ writeList<T extends Node>(format: ListFormat, list: NodeArray<T> | undefined, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
|
||||
/*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined): void;
|
||||
/*@internal*/ writeBundle(bundle: Bundle, info: BundleInfo | undefined, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined): void;
|
||||
/*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined): void;
|
||||
/*@internal*/ bundleFileInfo?: BundleFileInfo;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export const enum BundleFileSectionKind {
|
||||
Prologue = "prologue",
|
||||
EmitHelpers = "emitHelpers",
|
||||
NoDefaultLib = "no-default-lib",
|
||||
Reference = "reference",
|
||||
Type = "type",
|
||||
Lib = "lib",
|
||||
Prepend = "prepend",
|
||||
Text = "text",
|
||||
Internal = "internal",
|
||||
// comments?
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface BundleFileSectionBase extends TextRange {
|
||||
kind: BundleFileSectionKind;
|
||||
data?: string;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface BundleFilePrologue extends BundleFileSectionBase {
|
||||
kind: BundleFileSectionKind.Prologue;
|
||||
data: string;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface BundleFileEmitHelpers extends BundleFileSectionBase {
|
||||
kind: BundleFileSectionKind.EmitHelpers;
|
||||
data: string;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface BundleFileHasNoDefaultLib extends BundleFileSectionBase {
|
||||
kind: BundleFileSectionKind.NoDefaultLib;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface BundleFileReference extends BundleFileSectionBase {
|
||||
kind: BundleFileSectionKind.Reference | BundleFileSectionKind.Type | BundleFileSectionKind.Lib;
|
||||
data: string;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface BundleFilePrepend extends BundleFileSectionBase {
|
||||
kind: BundleFileSectionKind.Prepend;
|
||||
data: string;
|
||||
texts: BundleFileTextLike[];
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export type BundleFileTextLikeKind = BundleFileSectionKind.Text | BundleFileSectionKind.Internal;
|
||||
|
||||
/*@internal*/
|
||||
export interface BundleFileTextLike extends BundleFileSectionBase {
|
||||
kind: BundleFileTextLikeKind;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export type BundleFileSection = BundleFilePrologue | BundleFileEmitHelpers |
|
||||
BundleFileHasNoDefaultLib | BundleFileReference | BundleFilePrepend |
|
||||
BundleFileTextLike;
|
||||
|
||||
/*@internal*/
|
||||
export interface SourceFilePrologueDirectiveExpression extends TextRange {
|
||||
text: string;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface SourceFilePrologueDirective extends TextRange {
|
||||
expression: SourceFilePrologueDirectiveExpression;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface SourceFilePrologueInfo {
|
||||
file: number;
|
||||
text: string;
|
||||
directives: SourceFilePrologueDirective[];
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface SourceFileInfo {
|
||||
// List of helpers in own source files emitted if no prepend is present
|
||||
helpers?: string[];
|
||||
prologues?: SourceFilePrologueInfo[];
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface BundleFileInfo {
|
||||
sections: BundleFileSection[];
|
||||
sources?: SourceFileInfo;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface BundleBuildInfo {
|
||||
js?: BundleFileInfo;
|
||||
dts?: BundleFileInfo;
|
||||
commonSourceDirectory: string;
|
||||
sourceFiles: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* When a bundle contains prepended content, we store a file on disk indicating where the non-prepended
|
||||
* content of that file starts. On a subsequent build where there are no upstream .d.ts changes, we
|
||||
* read the bundle info file and the original .js file to quickly re-use portion of the file
|
||||
* that didn't originate in prepended content.
|
||||
*/
|
||||
/* @internal */
|
||||
export interface BundleInfo {
|
||||
// The offset (in characters, i.e. suitable for .substr) at which the
|
||||
// non-prepended portion of the emitted file starts.
|
||||
originalOffset: number;
|
||||
// The total length of this bundle. Used to ensure we're pulling from
|
||||
// the same source as we originally wrote.
|
||||
totalLength: number;
|
||||
export interface BuildInfo {
|
||||
bundle?: BundleBuildInfo;
|
||||
program?: ProgramBuildInfo;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export interface PrintHandlers {
|
||||
@@ -5482,6 +5677,9 @@ namespace ts {
|
||||
/*@internal*/ extendedDiagnostics?: boolean;
|
||||
/*@internal*/ onlyPrintJsDocStyle?: boolean;
|
||||
/*@internal*/ neverAsciiEscape?: boolean;
|
||||
/*@internal*/ writeBundleFileInfo?: boolean;
|
||||
/*@internal*/ recordInternalSection?: boolean;
|
||||
/*@internal*/ stripInternal?: boolean;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -5524,7 +5722,7 @@ namespace ts {
|
||||
/**
|
||||
* Appends a source map.
|
||||
*/
|
||||
appendSourceMap(generatedLine: number, generatedCharacter: number, sourceMap: RawSourceMap, sourceMapPath: string): void;
|
||||
appendSourceMap(generatedLine: number, generatedCharacter: number, sourceMap: RawSourceMap, sourceMapPath: string, start?: LineAndCharacter, end?: LineAndCharacter): void;
|
||||
/**
|
||||
* Gets the source map as a `RawSourceMap` object.
|
||||
*/
|
||||
@@ -5570,6 +5768,7 @@ namespace ts {
|
||||
getColumn(): number;
|
||||
getIndent(): number;
|
||||
isAtStartOfLine(): boolean;
|
||||
getTextPosWithWriteLine?(): number;
|
||||
}
|
||||
|
||||
export interface GetEffectiveTypeRootsHost {
|
||||
@@ -5751,26 +5950,18 @@ namespace ts {
|
||||
/* @internal */
|
||||
export interface PragmaDefinition<T1 extends string = string, T2 extends string = string, T3 extends string = string, T4 extends string = string> {
|
||||
args?:
|
||||
| [PragmaArgumentSpecification<T1>]
|
||||
| [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>]
|
||||
| [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>]
|
||||
| [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>, PragmaArgumentSpecification<T4>];
|
||||
| readonly [PragmaArgumentSpecification<T1>]
|
||||
| readonly [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>]
|
||||
| readonly [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>]
|
||||
| readonly [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>, PragmaArgumentSpecification<T4>];
|
||||
// If not present, defaults to PragmaKindFlags.Default
|
||||
kind?: PragmaKindFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function only exists to cause exact types to be inferred for all the literals within `commentPragmas`
|
||||
*/
|
||||
/* @internal */
|
||||
function _contextuallyTypePragmas<T extends {[name: string]: PragmaDefinition<K1, K2, K3, K4>}, K1 extends string, K2 extends string, K3 extends string, K4 extends string>(args: T): T {
|
||||
return args;
|
||||
}
|
||||
|
||||
// While not strictly a type, this is here because `PragmaMap` needs to be here to be used with `SourceFile`, and we don't
|
||||
// fancy effectively defining it twice, once in value-space and once in type-space
|
||||
/* @internal */
|
||||
export const commentPragmas = _contextuallyTypePragmas({
|
||||
export const commentPragmas = {
|
||||
"reference": {
|
||||
args: [
|
||||
{ name: "types", optional: true, captureSpan: true },
|
||||
@@ -5798,7 +5989,7 @@ namespace ts {
|
||||
args: [{ name: "factory" }],
|
||||
kind: PragmaKindFlags.MultiLine
|
||||
},
|
||||
});
|
||||
} as const;
|
||||
|
||||
/* @internal */
|
||||
type PragmaArgTypeMaybeCapture<TDesc> = TDesc extends {captureSpan: true} ? {value: string, pos: number, end: number} : string;
|
||||
@@ -5809,28 +6000,29 @@ namespace ts {
|
||||
? {[K in TName]?: PragmaArgTypeMaybeCapture<TDesc>}
|
||||
: {[K in TName]: PragmaArgTypeMaybeCapture<TDesc>};
|
||||
|
||||
/* @internal */
|
||||
type UnionToIntersection<U> =
|
||||
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
||||
|
||||
/* @internal */
|
||||
type ArgumentDefinitionToFieldUnion<T extends readonly PragmaArgumentSpecification<any>[]> = {
|
||||
[K in keyof T]: PragmaArgTypeOptional<T[K], T[K] extends {name: infer TName} ? TName extends string ? TName : never : never>
|
||||
}[Extract<keyof T, number>]; // The mapped type maps over only the tuple members, but this reindex gets _all_ members - by extracting only `number` keys, we get only the tuple members
|
||||
|
||||
/**
|
||||
* Maps a pragma definition into the desired shape for its arguments object
|
||||
* Maybe the below is a good argument for types being iterable on struture in some way.
|
||||
*/
|
||||
/* @internal */
|
||||
type PragmaArgumentType<T extends PragmaDefinition> =
|
||||
T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>, PragmaArgumentSpecification<infer TName3>, PragmaArgumentSpecification<infer TName4>] }
|
||||
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2> & PragmaArgTypeOptional<T["args"][2], TName3> & PragmaArgTypeOptional<T["args"][2], TName4>
|
||||
: T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>, PragmaArgumentSpecification<infer TName3>] }
|
||||
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2> & PragmaArgTypeOptional<T["args"][2], TName3>
|
||||
: T extends { args: [PragmaArgumentSpecification<infer TName1>, PragmaArgumentSpecification<infer TName2>] }
|
||||
? PragmaArgTypeOptional<T["args"][0], TName1> & PragmaArgTypeOptional<T["args"][1], TName2>
|
||||
: T extends { args: [PragmaArgumentSpecification<infer TName>] }
|
||||
? PragmaArgTypeOptional<T["args"][0], TName>
|
||||
: object;
|
||||
// The above fallback to `object` when there's no args to allow `{}` (as intended), but not the number 2, for example
|
||||
// TODO: Swap to `undefined` for a cleaner API once strictNullChecks is enabled
|
||||
type PragmaArgumentType<KPrag extends keyof ConcretePragmaSpecs> =
|
||||
ConcretePragmaSpecs[KPrag] extends { args: readonly PragmaArgumentSpecification<any>[] }
|
||||
? UnionToIntersection<ArgumentDefinitionToFieldUnion<ConcretePragmaSpecs[KPrag]["args"]>>
|
||||
: never;
|
||||
|
||||
/* @internal */
|
||||
type ConcretePragmaSpecs = typeof commentPragmas;
|
||||
|
||||
/* @internal */
|
||||
export type PragmaPseudoMap = {[K in keyof ConcretePragmaSpecs]?: {arguments: PragmaArgumentType<ConcretePragmaSpecs[K]>, range: CommentRange}};
|
||||
export type PragmaPseudoMap = {[K in keyof ConcretePragmaSpecs]: {arguments: PragmaArgumentType<K>, range: CommentRange}};
|
||||
|
||||
/* @internal */
|
||||
export type PragmaPseudoMapEntry = {[K in keyof PragmaPseudoMap]: {name: K, args: PragmaPseudoMap[K]}}[keyof PragmaPseudoMap];
|
||||
@@ -5855,13 +6047,14 @@ namespace ts {
|
||||
|
||||
export interface UserPreferences {
|
||||
readonly disableSuggestions?: boolean;
|
||||
readonly quotePreference?: "double" | "single";
|
||||
readonly quotePreference?: "auto" | "double" | "single";
|
||||
readonly includeCompletionsForModuleExports?: boolean;
|
||||
readonly includeCompletionsWithInsertText?: boolean;
|
||||
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
|
||||
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */
|
||||
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
|
||||
readonly allowTextChangesInNewFiles?: boolean;
|
||||
readonly providePrefixAndSuffixTextForRename?: boolean;
|
||||
}
|
||||
|
||||
/** Represents a bigint literal value without requiring bigint support */
|
||||
|
||||
+143
-27
@@ -401,10 +401,7 @@ namespace ts {
|
||||
return !nodeIsMissing(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends statements to an array while taking care of prologue directives.
|
||||
*/
|
||||
export function addStatementsAfterPrologue<T extends Statement>(to: T[], from: ReadonlyArray<T> | undefined): T[] {
|
||||
function insertStatementsAfterPrologue<T extends Statement>(to: T[], from: ReadonlyArray<T> | undefined, isPrologueDirective: (node: Node) => boolean): T[] {
|
||||
if (from === undefined || from.length === 0) return to;
|
||||
let statementIndex = 0;
|
||||
// skip all prologue directives to insert at the correct position
|
||||
@@ -417,6 +414,46 @@ namespace ts {
|
||||
return to;
|
||||
}
|
||||
|
||||
function insertStatementAfterPrologue<T extends Statement>(to: T[], statement: T | undefined, isPrologueDirective: (node: Node) => boolean): T[] {
|
||||
if (statement === undefined) return to;
|
||||
let statementIndex = 0;
|
||||
// skip all prologue directives to insert at the correct position
|
||||
for (; statementIndex < to.length; ++statementIndex) {
|
||||
if (!isPrologueDirective(to[statementIndex])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
to.splice(statementIndex, 0, statement);
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
function isAnyPrologueDirective(node: Node) {
|
||||
return isPrologueDirective(node) || !!(getEmitFlags(node) & EmitFlags.CustomPrologue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends statements to an array while taking care of prologue directives.
|
||||
*/
|
||||
export function insertStatementsAfterStandardPrologue<T extends Statement>(to: T[], from: ReadonlyArray<T> | undefined): T[] {
|
||||
return insertStatementsAfterPrologue(to, from, isPrologueDirective);
|
||||
}
|
||||
|
||||
export function insertStatementsAfterCustomPrologue<T extends Statement>(to: T[], from: ReadonlyArray<T> | undefined): T[] {
|
||||
return insertStatementsAfterPrologue(to, from, isAnyPrologueDirective);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends statements to an array while taking care of prologue directives.
|
||||
*/
|
||||
export function insertStatementAfterStandardPrologue<T extends Statement>(to: T[], statement: T | undefined): T[] {
|
||||
return insertStatementAfterPrologue(to, statement, isPrologueDirective);
|
||||
}
|
||||
|
||||
export function insertStatementAfterCustomPrologue<T extends Statement>(to: T[], statement: T | undefined): T[] {
|
||||
return insertStatementAfterPrologue(to, statement, isAnyPrologueDirective);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given comment is a triple-slash
|
||||
*
|
||||
@@ -778,7 +815,8 @@ namespace ts {
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
return escapeLeadingUnderscores(name.text);
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
return isStringOrNumericLiteralLike(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined!; // TODO: GH#18217 Almost all uses of this assume the result to be defined!
|
||||
if (isStringOrNumericLiteralLike(name.expression)) return escapeLeadingUnderscores(name.expression.text);
|
||||
return Debug.fail("Text of property name cannot be read from non-literal-valued ComputedPropertyNames");
|
||||
default:
|
||||
return Debug.assertNever(name);
|
||||
}
|
||||
@@ -888,7 +926,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const isMissing = nodeIsMissing(errorNode);
|
||||
const pos = isMissing
|
||||
const pos = isMissing || isJsxText(node)
|
||||
? errorNode.pos
|
||||
: skipTrivia(sourceFile.text, errorNode.pos);
|
||||
|
||||
@@ -1292,6 +1330,10 @@ namespace ts {
|
||||
return findAncestor(node.parent, isFunctionLike);
|
||||
}
|
||||
|
||||
export function getContainingFunctionDeclaration(node: Node): FunctionLikeDeclaration | undefined {
|
||||
return findAncestor(node.parent, isFunctionLikeDeclaration);
|
||||
}
|
||||
|
||||
export function getContainingClass(node: Node): ClassLikeDeclaration | undefined {
|
||||
return findAncestor(node.parent, isClassLike);
|
||||
}
|
||||
@@ -1435,6 +1477,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function isSuperOrSuperProperty(node: Node): node is SuperExpression | SuperProperty {
|
||||
return node.kind === SyntaxKind.SuperKeyword
|
||||
|| isSuperProperty(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is a property or element access expression for `super`.
|
||||
*/
|
||||
@@ -2513,14 +2560,15 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getEffectiveBaseTypeNode(node: ClassLikeDeclaration | InterfaceDeclaration) {
|
||||
if (isInJSFile(node)) {
|
||||
const baseType = getClassExtendsHeritageElement(node);
|
||||
if (baseType && isInJSFile(node)) {
|
||||
// Prefer an @augments tag because it may have type parameters.
|
||||
const tag = getJSDocAugmentsTag(node);
|
||||
if (tag) {
|
||||
return tag.class;
|
||||
}
|
||||
}
|
||||
return getClassExtendsHeritageElement(node);
|
||||
return baseType;
|
||||
}
|
||||
|
||||
export function getClassExtendsHeritageElement(node: ClassLikeDeclaration | InterfaceDeclaration) {
|
||||
@@ -2557,7 +2605,7 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function tryResolveScriptReference(host: ScriptReferenceHost, sourceFile: SourceFile, reference: FileReference) {
|
||||
export function tryResolveScriptReference(host: ScriptReferenceHost, sourceFile: SourceFile | UnparsedSource, reference: FileReference) {
|
||||
if (!host.getCompilerOptions().noResolve) {
|
||||
const referenceFileName = isRootedDiskPath(reference.fileName) ? reference.fileName : combinePaths(getDirectoryPath(sourceFile.fileName), reference.fileName);
|
||||
return host.getSourceFile(referenceFileName);
|
||||
@@ -3200,6 +3248,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getTextPosWithWriteLine() {
|
||||
return lineStart ? output.length : (output.length + newLine.length);
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
return {
|
||||
@@ -3229,7 +3281,8 @@ namespace ts {
|
||||
writeStringLiteral: write,
|
||||
writeSymbol: (s, _) => write(s),
|
||||
writeTrailingSemicolon: write,
|
||||
writeComment: write
|
||||
writeComment: write,
|
||||
getTextPosWithWriteLine
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3354,11 +3407,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface EmitFileNames {
|
||||
jsFilePath: string | undefined;
|
||||
sourceMapFilePath: string | undefined;
|
||||
declarationFilePath: string | undefined;
|
||||
declarationMapPath: string | undefined;
|
||||
bundleInfoPath: string | undefined;
|
||||
jsFilePath?: string | undefined;
|
||||
sourceMapFilePath?: string | undefined;
|
||||
declarationFilePath?: string | undefined;
|
||||
declarationMapPath?: string | undefined;
|
||||
buildInfoPath?: string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3373,22 +3426,31 @@ namespace ts {
|
||||
export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile): ReadonlyArray<SourceFile> {
|
||||
const options = host.getCompilerOptions();
|
||||
const isSourceFileFromExternalLibrary = (file: SourceFile) => host.isSourceFileFromExternalLibrary(file);
|
||||
const getResolvedProjectReferenceToRedirect = (fileName: string) => host.getResolvedProjectReferenceToRedirect(fileName);
|
||||
if (options.outFile || options.out) {
|
||||
const moduleKind = getEmitModuleKind(options);
|
||||
const moduleEmitEnabled = options.emitDeclarationOnly || moduleKind === ModuleKind.AMD || moduleKind === ModuleKind.System;
|
||||
// Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified
|
||||
return filter(host.getSourceFiles(), sourceFile =>
|
||||
(moduleEmitEnabled || !isExternalModule(sourceFile)) && sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary));
|
||||
(moduleEmitEnabled || !isExternalModule(sourceFile)) && sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary, getResolvedProjectReferenceToRedirect));
|
||||
}
|
||||
else {
|
||||
const sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile];
|
||||
return filter(sourceFiles, sourceFile => sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary));
|
||||
return filter(sourceFiles, sourceFile => sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary, getResolvedProjectReferenceToRedirect));
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't call this for `--outFile`, just for `--outDir` or plain emit. `--outFile` needs additional checks. */
|
||||
export function sourceFileMayBeEmitted(sourceFile: SourceFile, options: CompilerOptions, isSourceFileFromExternalLibrary: (file: SourceFile) => boolean) {
|
||||
return !(options.noEmitForJsFiles && isSourceFileJS(sourceFile)) && !sourceFile.isDeclarationFile && !isSourceFileFromExternalLibrary(sourceFile);
|
||||
export function sourceFileMayBeEmitted(
|
||||
sourceFile: SourceFile,
|
||||
options: CompilerOptions,
|
||||
isSourceFileFromExternalLibrary: (file: SourceFile) => boolean,
|
||||
getResolvedProjectReferenceToRedirect: (fileName: string) => ResolvedProjectReference | undefined
|
||||
) {
|
||||
return !(options.noEmitForJsFiles && isSourceFileJS(sourceFile)) &&
|
||||
!sourceFile.isDeclarationFile &&
|
||||
!isSourceFileFromExternalLibrary(sourceFile) &&
|
||||
!(isJsonSourceFile(sourceFile) && getResolvedProjectReferenceToRedirect(sourceFile.fileName));
|
||||
}
|
||||
|
||||
export function getSourceFilePathInNewDir(fileName: string, host: EmitHost, newDirPath: string): string {
|
||||
@@ -3416,8 +3478,8 @@ namespace ts {
|
||||
return computeLineAndCharacterOfPosition(lineMap, pos).line;
|
||||
}
|
||||
|
||||
export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration | undefined {
|
||||
return find(node.members, (member): member is ConstructorDeclaration => isConstructorDeclaration(member) && nodeIsPresent(member.body));
|
||||
export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration & { body: FunctionBody } | undefined {
|
||||
return find(node.members, (member): member is ConstructorDeclaration & { body: FunctionBody } => isConstructorDeclaration(member) && nodeIsPresent(member.body));
|
||||
}
|
||||
|
||||
function getSetAccessorValueParameter(accessor: SetAccessorDeclaration): ParameterDeclaration | undefined {
|
||||
@@ -3790,8 +3852,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getModifierFlags(node: Node): ModifierFlags {
|
||||
if (node.modifierFlagsCache! & ModifierFlags.HasComputedFlags) {
|
||||
return node.modifierFlagsCache! & ~ModifierFlags.HasComputedFlags;
|
||||
if (node.modifierFlagsCache & ModifierFlags.HasComputedFlags) {
|
||||
return node.modifierFlagsCache & ~ModifierFlags.HasComputedFlags;
|
||||
}
|
||||
|
||||
const flags = getModifierFlagsNoCache(node);
|
||||
@@ -4513,7 +4575,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getObjectFlags(type: Type): ObjectFlags {
|
||||
return type.flags & TypeFlags.Object ? (<ObjectType>type).objectFlags : 0;
|
||||
return type.flags & TypeFlags.ObjectFlagsType ? (<ObjectFlagsType>type).objectFlags : 0;
|
||||
}
|
||||
|
||||
export function typeHasCallOrConstructSignatures(type: Type, checker: TypeChecker) {
|
||||
@@ -4594,6 +4656,16 @@ namespace ts {
|
||||
export function isAccessExpression(node: Node): node is AccessExpression {
|
||||
return node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.ElementAccessExpression;
|
||||
}
|
||||
|
||||
export function isBundleFileTextLike(section: BundleFileSection): section is BundleFileTextLike {
|
||||
switch (section.kind) {
|
||||
case BundleFileSectionKind.Text:
|
||||
case BundleFileSectionKind.Internal:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace ts {
|
||||
@@ -4601,6 +4673,8 @@ namespace ts {
|
||||
switch (options.target) {
|
||||
case ScriptTarget.ESNext:
|
||||
return "lib.esnext.full.d.ts";
|
||||
case ScriptTarget.ES2019:
|
||||
return "lib.es2019.full.d.ts";
|
||||
case ScriptTarget.ES2018:
|
||||
return "lib.es2018.full.d.ts";
|
||||
case ScriptTarget.ES2017:
|
||||
@@ -5606,6 +5680,11 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.TypeAssertionExpression;
|
||||
}
|
||||
|
||||
export function isConstTypeReference(node: Node) {
|
||||
return isTypeReferenceNode(node) && isIdentifier(node.typeName) &&
|
||||
node.typeName.escapedText === "const" && !node.typeArguments;
|
||||
}
|
||||
|
||||
export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression {
|
||||
return node.kind === SyntaxKind.ParenthesizedExpression;
|
||||
}
|
||||
@@ -5979,6 +6058,26 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.UnparsedSource;
|
||||
}
|
||||
|
||||
export function isUnparsedPrepend(node: Node): node is UnparsedPrepend {
|
||||
return node.kind === SyntaxKind.UnparsedPrepend;
|
||||
}
|
||||
|
||||
export function isUnparsedTextLike(node: Node): node is UnparsedTextLike {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.UnparsedText:
|
||||
case SyntaxKind.UnparsedInternalText:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function isUnparsedNode(node: Node): node is UnparsedNode {
|
||||
return isUnparsedTextLike(node) ||
|
||||
node.kind === SyntaxKind.UnparsedPrologue ||
|
||||
node.kind === SyntaxKind.UnparsedSyntheticReference;
|
||||
}
|
||||
|
||||
// JSDoc
|
||||
|
||||
export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression {
|
||||
@@ -6734,7 +6833,7 @@ namespace ts {
|
||||
/* @internal */
|
||||
export function isDeclaration(node: Node): node is NamedDeclaration {
|
||||
if (node.kind === SyntaxKind.TypeParameter) {
|
||||
return node.parent.kind !== SyntaxKind.JSDocTemplateTag || isInJSFile(node);
|
||||
return (node.parent && node.parent.kind !== SyntaxKind.JSDocTemplateTag) || isInJSFile(node);
|
||||
}
|
||||
|
||||
return isDeclarationKind(node.kind);
|
||||
@@ -7024,6 +7123,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export function formatMessage(_dummy: any, message: DiagnosticMessage, ...args: (string | number | undefined)[]): string;
|
||||
export function formatMessage(_dummy: any, message: DiagnosticMessage): string {
|
||||
let text = getLocaleSpecificMessage(message);
|
||||
|
||||
@@ -7205,6 +7305,10 @@ namespace ts {
|
||||
return !!(compilerOptions.declaration || compilerOptions.composite);
|
||||
}
|
||||
|
||||
export function isIncrementalCompilation(options: CompilerOptions) {
|
||||
return !!(options.incremental || options.composite);
|
||||
}
|
||||
|
||||
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictBindCallApply" | "strictPropertyInitialization" | "alwaysStrict";
|
||||
|
||||
export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean {
|
||||
@@ -8010,7 +8114,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** @param path directory of the tsconfig.json */
|
||||
export function matchFiles(path: string, extensions: ReadonlyArray<string> | undefined, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string> | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string, depth: number | undefined, getFileSystemEntries: (path: string) => FileSystemEntries): string[] {
|
||||
export function matchFiles(path: string, extensions: ReadonlyArray<string> | undefined, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string> | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string, depth: number | undefined, getFileSystemEntries: (path: string) => FileSystemEntries, realpath: (path: string) => string): string[] {
|
||||
path = normalizePath(path);
|
||||
currentDirectory = normalizePath(currentDirectory);
|
||||
|
||||
@@ -8023,7 +8127,8 @@ namespace ts {
|
||||
// Associate an array of results with each include regex. This keeps results in order of the "include" order.
|
||||
// If there are no "includes", then just put everything in results[0].
|
||||
const results: string[][] = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]];
|
||||
|
||||
const visited = createMap<true>();
|
||||
const toCanonical = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
for (const basePath of patterns.basePaths) {
|
||||
visitDirectory(basePath, combinePaths(currentDirectory, basePath), depth);
|
||||
}
|
||||
@@ -8031,6 +8136,9 @@ namespace ts {
|
||||
return flatten<string>(results);
|
||||
|
||||
function visitDirectory(path: string, absolutePath: string, depth: number | undefined) {
|
||||
const canonicalPath = toCanonical(realpath(absolutePath));
|
||||
if (visited.has(canonicalPath)) return;
|
||||
visited.set(canonicalPath, true);
|
||||
const { files, directories } = getFileSystemEntries(path);
|
||||
|
||||
for (const current of sort<string>(files, compareStringsCaseSensitive)) {
|
||||
@@ -8425,6 +8533,14 @@ namespace ts {
|
||||
return arr.slice(index);
|
||||
}
|
||||
|
||||
export function addRelatedInfo<T extends Diagnostic>(diagnostic: T, ...relatedInformation: DiagnosticRelatedInformation[]): T {
|
||||
if (!diagnostic.relatedInformation) {
|
||||
diagnostic.relatedInformation = [];
|
||||
}
|
||||
diagnostic.relatedInformation.push(...relatedInformation);
|
||||
return diagnostic;
|
||||
}
|
||||
|
||||
export function minAndMax<T>(arr: ReadonlyArray<T>, getValue: (value: T) => number): { readonly min: number, readonly max: number } {
|
||||
Debug.assert(arr.length !== 0);
|
||||
let min = getValue(arr[0]);
|
||||
|
||||
@@ -1478,8 +1478,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
return isNodeArray(statements)
|
||||
? setTextRange(createNodeArray(addStatementsAfterPrologue(statements.slice(), declarations)), statements)
|
||||
: addStatementsAfterPrologue(statements, declarations);
|
||||
? setTextRange(createNodeArray(insertStatementsAfterStandardPrologue(statements.slice(), declarations)), statements)
|
||||
: insertStatementsAfterStandardPrologue(statements, declarations);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+307
-207
@@ -88,21 +88,6 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Program structure needed to emit the files and report diagnostics
|
||||
*/
|
||||
export interface ProgramToEmitFilesAndReportErrors {
|
||||
getCurrentDirectory(): string;
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
getSourceFiles(): ReadonlyArray<SourceFile>;
|
||||
getSyntacticDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getOptionsDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getGlobalDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getSemanticDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getConfigFileParsingDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
|
||||
}
|
||||
|
||||
export type ReportEmitErrorSummary = (errorCount: number) => void;
|
||||
|
||||
export function getErrorCountForSummary(diagnostics: ReadonlyArray<Diagnostic>) {
|
||||
@@ -121,6 +106,21 @@ namespace ts {
|
||||
return `${newLine}${flattenDiagnosticMessageText(d.messageText, newLine)}${newLine}${newLine}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Program structure needed to emit the files and report diagnostics
|
||||
*/
|
||||
export interface ProgramToEmitFilesAndReportErrors {
|
||||
getCurrentDirectory(): string;
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
getSourceFiles(): ReadonlyArray<SourceFile>;
|
||||
getSyntacticDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getOptionsDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getGlobalDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getSemanticDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getConfigFileParsingDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options
|
||||
*/
|
||||
@@ -129,7 +129,6 @@ namespace ts {
|
||||
const diagnostics = program.getConfigFileParsingDiagnostics().slice();
|
||||
const configFileParsingDiagnosticsLength = diagnostics.length;
|
||||
addRange(diagnostics, program.getSyntacticDiagnostics());
|
||||
let reportSemanticDiagnostics = false;
|
||||
|
||||
// If we didn't have any syntactic errors, then also try getting the global and
|
||||
// semantic errors.
|
||||
@@ -138,7 +137,7 @@ namespace ts {
|
||||
addRange(diagnostics, program.getGlobalDiagnostics());
|
||||
|
||||
if (diagnostics.length === configFileParsingDiagnosticsLength) {
|
||||
reportSemanticDiagnostics = true;
|
||||
addRange(diagnostics, program.getSemanticDiagnostics());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,10 +145,6 @@ namespace ts {
|
||||
const { emittedFiles, emitSkipped, diagnostics: emitDiagnostics } = program.emit(/*targetSourceFile*/ undefined, writeFile);
|
||||
addRange(diagnostics, emitDiagnostics);
|
||||
|
||||
if (reportSemanticDiagnostics) {
|
||||
addRange(diagnostics, program.getSemanticDiagnostics());
|
||||
}
|
||||
|
||||
sortAndDeduplicateDiagnostics(diagnostics).forEach(reportDiagnostic);
|
||||
if (writeFileName) {
|
||||
const currentDir = program.getCurrentDirectory();
|
||||
@@ -187,30 +182,122 @@ namespace ts {
|
||||
const onWatchStatusChange = reportWatchStatus || createWatchStatusReporter(system);
|
||||
return {
|
||||
onWatchStatusChange,
|
||||
watchFile: system.watchFile ? ((path, callback, pollingInterval) => system.watchFile!(path, callback, pollingInterval)) : () => noopFileWatcher,
|
||||
watchDirectory: system.watchDirectory ? ((path, callback, recursive) => system.watchDirectory!(path, callback, recursive)) : () => noopFileWatcher,
|
||||
setTimeout: system.setTimeout ? ((callback, ms, ...args: any[]) => system.setTimeout!.call(system, callback, ms, ...args)) : noop,
|
||||
clearTimeout: system.clearTimeout ? (timeoutId => system.clearTimeout!(timeoutId)) : noop
|
||||
watchFile: maybeBind(system, system.watchFile) || (() => noopFileWatcher),
|
||||
watchDirectory: maybeBind(system, system.watchDirectory) || (() => noopFileWatcher),
|
||||
setTimeout: maybeBind(system, system.setTimeout) || noop,
|
||||
clearTimeout: maybeBind(system, system.clearTimeout) || noop
|
||||
};
|
||||
}
|
||||
|
||||
export const enum WatchType {
|
||||
ConfigFile = "Config file",
|
||||
SourceFile = "Source file",
|
||||
MissingFile = "Missing file",
|
||||
WildcardDirectory = "Wild card directory",
|
||||
FailedLookupLocations = "Failed Lookup Locations",
|
||||
TypeRoots = "Type roots"
|
||||
}
|
||||
|
||||
interface WatchFactory<X, Y = undefined> extends ts.WatchFactory<X, Y> {
|
||||
writeLog: (s: string) => void;
|
||||
}
|
||||
|
||||
export function createWatchFactory<Y = undefined>(host: { trace?(s: string): void; }, options: { extendedDiagnostics?: boolean; diagnostics?: boolean; }) {
|
||||
const watchLogLevel = host.trace ? options.extendedDiagnostics ? WatchLogLevel.Verbose : options.diagnostics ? WatchLogLevel.TriggerOnly : WatchLogLevel.None : WatchLogLevel.None;
|
||||
const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? (s => host.trace!(s)) : noop;
|
||||
const result = getWatchFactory<WatchType, Y>(watchLogLevel, writeLog) as WatchFactory<WatchType, Y>;
|
||||
result.writeLog = writeLog;
|
||||
return result;
|
||||
}
|
||||
|
||||
export function createCompilerHostFromProgramHost(host: ProgramHost<any>, getCompilerOptions: () => CompilerOptions, directoryStructureHost: DirectoryStructureHost = host): CompilerHost {
|
||||
const useCaseSensitiveFileNames = host.useCaseSensitiveFileNames();
|
||||
const hostGetNewLine = memoize(() => host.getNewLine());
|
||||
return {
|
||||
getSourceFile: (fileName, languageVersion, onError) => {
|
||||
let text: string | undefined;
|
||||
try {
|
||||
performance.mark("beforeIORead");
|
||||
text = host.readFile(fileName, getCompilerOptions().charset);
|
||||
performance.mark("afterIORead");
|
||||
performance.measure("I/O Read", "beforeIORead", "afterIORead");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
onError(e.message);
|
||||
}
|
||||
text = "";
|
||||
}
|
||||
|
||||
return text !== undefined ? createSourceFile(fileName, text, languageVersion) : undefined;
|
||||
},
|
||||
getDefaultLibLocation: maybeBind(host, host.getDefaultLibLocation),
|
||||
getDefaultLibFileName: options => host.getDefaultLibFileName(options),
|
||||
writeFile,
|
||||
getCurrentDirectory: memoize(() => host.getCurrentDirectory()),
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
getCanonicalFileName: createGetCanonicalFileName(useCaseSensitiveFileNames),
|
||||
getNewLine: () => getNewLineCharacter(getCompilerOptions(), hostGetNewLine),
|
||||
fileExists: f => host.fileExists(f),
|
||||
readFile: f => host.readFile(f),
|
||||
trace: maybeBind(host, host.trace),
|
||||
directoryExists: maybeBind(directoryStructureHost, directoryStructureHost.directoryExists),
|
||||
getDirectories: maybeBind(directoryStructureHost, directoryStructureHost.getDirectories),
|
||||
realpath: maybeBind(host, host.realpath),
|
||||
getEnvironmentVariable: maybeBind(host, host.getEnvironmentVariable) || (() => ""),
|
||||
createHash: maybeBind(host, host.createHash),
|
||||
readDirectory: maybeBind(host, host.readDirectory),
|
||||
};
|
||||
|
||||
function ensureDirectoriesExist(directoryPath: string) {
|
||||
if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists!(directoryPath)) {
|
||||
const parentDirectory = getDirectoryPath(directoryPath);
|
||||
ensureDirectoriesExist(parentDirectory);
|
||||
if (host.createDirectory) host.createDirectory(directoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, onError: (message: string) => void) {
|
||||
try {
|
||||
performance.mark("beforeIOWrite");
|
||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
||||
|
||||
host.writeFile!(fileName, text, writeByteOrderMark);
|
||||
|
||||
performance.mark("afterIOWrite");
|
||||
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
onError(e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function setGetSourceFileAsHashVersioned(compilerHost: CompilerHost, host: { createHash?(data: string): string; }) {
|
||||
const originalGetSourceFile = compilerHost.getSourceFile;
|
||||
const computeHash = host.createHash || generateDjb2Hash;
|
||||
compilerHost.getSourceFile = (...args) => {
|
||||
const result = originalGetSourceFile.call(compilerHost, ...args);
|
||||
if (result) {
|
||||
result.version = computeHash.call(host, result.text);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the watch compiler host that can be extended with config file or root file names and options host
|
||||
*/
|
||||
function createWatchCompilerHost<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(system = sys, createProgram: CreateProgram<T> | undefined, reportDiagnostic: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHost<T> {
|
||||
if (!createProgram) {
|
||||
createProgram = createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>;
|
||||
}
|
||||
|
||||
export function createProgramHost<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(system: System, createProgram: CreateProgram<T> | undefined): ProgramHost<T> {
|
||||
const getDefaultLibLocation = memoize(() => getDirectoryPath(normalizePath(system.getExecutingFilePath())));
|
||||
let host: DirectoryStructureHost = system;
|
||||
host; // tslint:disable-line no-unused-expression (TODO: `host` is unused!)
|
||||
const useCaseSensitiveFileNames = () => system.useCaseSensitiveFileNames;
|
||||
const writeFileName = (s: string) => system.write(s + system.newLine);
|
||||
const { onWatchStatusChange, watchFile, watchDirectory, setTimeout, clearTimeout } = createWatchHost(system, reportWatchStatus);
|
||||
return {
|
||||
useCaseSensitiveFileNames,
|
||||
useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames,
|
||||
getNewLine: () => system.newLine,
|
||||
getCurrentDirectory: () => system.getCurrentDirectory(),
|
||||
getCurrentDirectory: memoize(() => system.getCurrentDirectory()),
|
||||
getDefaultLibLocation,
|
||||
getDefaultLibFileName: options => combinePaths(getDefaultLibLocation(), getDefaultLibFileName(options)),
|
||||
fileExists: path => system.fileExists(path),
|
||||
@@ -218,27 +305,25 @@ namespace ts {
|
||||
directoryExists: path => system.directoryExists(path),
|
||||
getDirectories: path => system.getDirectories(path),
|
||||
readDirectory: (path, extensions, exclude, include, depth) => system.readDirectory(path, extensions, exclude, include, depth),
|
||||
realpath: system.realpath && (path => system.realpath!(path)),
|
||||
getEnvironmentVariable: system.getEnvironmentVariable && (name => system.getEnvironmentVariable(name)),
|
||||
watchFile,
|
||||
watchDirectory,
|
||||
setTimeout,
|
||||
clearTimeout,
|
||||
trace: s => system.write(s),
|
||||
onWatchStatusChange,
|
||||
realpath: maybeBind(system, system.realpath),
|
||||
getEnvironmentVariable: maybeBind(system, system.getEnvironmentVariable),
|
||||
trace: s => system.write(s + system.newLine),
|
||||
createDirectory: path => system.createDirectory(path),
|
||||
writeFile: (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark),
|
||||
onCachedDirectoryStructureHostCreate: cacheHost => host = cacheHost || system,
|
||||
createHash: system.createHash && (s => system.createHash!(s)),
|
||||
createProgram,
|
||||
afterProgramCreate: emitFilesAndReportErrorUsingBuilder
|
||||
createHash: maybeBind(system, system.createHash),
|
||||
createProgram: createProgram || createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>
|
||||
};
|
||||
}
|
||||
|
||||
function getDefaultLibLocation() {
|
||||
return getDirectoryPath(normalizePath(system.getExecutingFilePath()));
|
||||
}
|
||||
|
||||
function emitFilesAndReportErrorUsingBuilder(builderProgram: BuilderProgram) {
|
||||
/**
|
||||
* Creates the watch compiler host that can be extended with config file or root file names and options host
|
||||
*/
|
||||
function createWatchCompilerHost<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(system = sys, createProgram: CreateProgram<T> | undefined, reportDiagnostic: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHost<T> {
|
||||
const writeFileName = (s: string) => system.write(s + system.newLine);
|
||||
const result = createProgramHost(system, createProgram) as WatchCompilerHost<T>;
|
||||
copyProperties(result, createWatchHost(system, reportWatchStatus));
|
||||
result.afterProgramCreate = builderProgram => {
|
||||
const compilerOptions = builderProgram.getCompilerOptions();
|
||||
const newLine = getNewLineCharacter(compilerOptions, () => system.newLine);
|
||||
|
||||
@@ -246,13 +331,14 @@ namespace ts {
|
||||
builderProgram,
|
||||
reportDiagnostic,
|
||||
writeFileName,
|
||||
errorCount => onWatchStatusChange!(
|
||||
errorCount => result.onWatchStatusChange!(
|
||||
createCompilerDiagnostic(getWatchErrorSummaryDiagnosticMessage(errorCount), errorCount),
|
||||
newLine,
|
||||
compilerOptions
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,12 +371,75 @@ namespace ts {
|
||||
host.projectReferences = projectReferences;
|
||||
return host;
|
||||
}
|
||||
|
||||
export function readBuilderProgram(compilerOptions: CompilerOptions, readFile: (path: string) => string | undefined) {
|
||||
if (compilerOptions.out || compilerOptions.outFile) return undefined;
|
||||
const buildInfoPath = getOutputPathForBuildInfo(compilerOptions);
|
||||
if (!buildInfoPath) return undefined;
|
||||
const content = readFile(buildInfoPath);
|
||||
if (!content) return undefined;
|
||||
const buildInfo = getBuildInfo(content);
|
||||
if (buildInfo.version !== version) return undefined;
|
||||
if (!buildInfo.program) return undefined;
|
||||
return createBuildProgramUsingProgramBuildInfo(buildInfo.program);
|
||||
}
|
||||
|
||||
export function createIncrementalCompilerHost(options: CompilerOptions, system = sys): CompilerHost {
|
||||
const host = createCompilerHostWorker(options, /*setParentNodes*/ undefined, system);
|
||||
host.createHash = maybeBind(system, system.createHash);
|
||||
setGetSourceFileAsHashVersioned(host, system);
|
||||
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, host.getCurrentDirectory(), host.getCanonicalFileName));
|
||||
return host;
|
||||
}
|
||||
|
||||
interface IncrementalProgramOptions<T extends BuilderProgram> {
|
||||
rootNames: ReadonlyArray<string>;
|
||||
options: CompilerOptions;
|
||||
configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>;
|
||||
projectReferences?: ReadonlyArray<ProjectReference>;
|
||||
host?: CompilerHost;
|
||||
createProgram?: CreateProgram<T>;
|
||||
}
|
||||
function createIncrementalProgram<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>({
|
||||
rootNames, options, configFileParsingDiagnostics, projectReferences, host, createProgram
|
||||
}: IncrementalProgramOptions<T>): T {
|
||||
host = host || createIncrementalCompilerHost(options);
|
||||
createProgram = createProgram || createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>;
|
||||
const oldProgram = readBuilderProgram(options, path => host!.readFile(path)) as any as T;
|
||||
return createProgram(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences);
|
||||
}
|
||||
|
||||
export interface IncrementalCompilationOptions {
|
||||
rootNames: ReadonlyArray<string>;
|
||||
options: CompilerOptions;
|
||||
configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>;
|
||||
projectReferences?: ReadonlyArray<ProjectReference>;
|
||||
host?: CompilerHost;
|
||||
reportDiagnostic?: DiagnosticReporter;
|
||||
reportErrorSummary?: ReportEmitErrorSummary;
|
||||
afterProgramEmitAndDiagnostics?(program: EmitAndSemanticDiagnosticsBuilderProgram): void;
|
||||
system?: System;
|
||||
}
|
||||
export function performIncrementalCompilation(input: IncrementalCompilationOptions) {
|
||||
const system = input.system || sys;
|
||||
const host = input.host || (input.host = createIncrementalCompilerHost(input.options, system));
|
||||
const builderProgram = createIncrementalProgram(input);
|
||||
const exitStatus = emitFilesAndReportErrors(
|
||||
builderProgram,
|
||||
input.reportDiagnostic || createDiagnosticReporter(system),
|
||||
s => host.trace && host.trace(s),
|
||||
input.reportErrorSummary || input.options.pretty ? errorCount => system.write(getErrorSummaryText(errorCount, system.newLine)) : undefined
|
||||
);
|
||||
if (input.afterProgramEmitAndDiagnostics) input.afterProgramEmitAndDiagnostics(builderProgram);
|
||||
return exitStatus;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ts {
|
||||
export type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void;
|
||||
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
|
||||
export type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference> | undefined) => T;
|
||||
|
||||
/** Host that has watch functionality used in --watch mode */
|
||||
export interface WatchHost {
|
||||
/** If provided, called with Diagnostic message that informs about change in watch status */
|
||||
@@ -305,19 +454,11 @@ namespace ts {
|
||||
/** If provided, will be used to reset existing delayed compilation */
|
||||
clearTimeout?(timeoutId: any): void;
|
||||
}
|
||||
export interface WatchCompilerHost<T extends BuilderProgram> extends WatchHost {
|
||||
// TODO: GH#18217 Optional methods are frequently asserted
|
||||
|
||||
export interface ProgramHost<T extends BuilderProgram> {
|
||||
/**
|
||||
* Used to create the program when need for program creation or recreation detected
|
||||
*/
|
||||
createProgram: CreateProgram<T>;
|
||||
/** If provided, callback to invoke after every new program creation */
|
||||
afterProgramCreate?(program: T): void;
|
||||
|
||||
// Only for testing
|
||||
/*@internal*/
|
||||
maxNumberOfFilesToIterateForInvalidation?: number;
|
||||
|
||||
// Sub set of compiler host methods to read and generate new program
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
@@ -357,16 +498,25 @@ namespace ts {
|
||||
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
}
|
||||
|
||||
/** Internal interface used to wire emit through same host */
|
||||
|
||||
/*@internal*/
|
||||
export interface WatchCompilerHost<T extends BuilderProgram> {
|
||||
export interface ProgramHost<T extends BuilderProgram> {
|
||||
// TODO: GH#18217 Optional methods are frequently asserted
|
||||
createDirectory?(path: string): void;
|
||||
writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void;
|
||||
onCachedDirectoryStructureHostCreate?(host: CachedDirectoryStructureHost): void;
|
||||
}
|
||||
|
||||
export interface WatchCompilerHost<T extends BuilderProgram> extends ProgramHost<T>, WatchHost {
|
||||
/** If provided, callback to invoke after every new program creation */
|
||||
afterProgramCreate?(program: T): void;
|
||||
|
||||
// Only for testing
|
||||
/*@internal*/
|
||||
maxNumberOfFilesToIterateForInvalidation?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Host to create watch with root files and options
|
||||
*/
|
||||
@@ -413,6 +563,9 @@ namespace ts {
|
||||
/** Gets the existing program without synchronizing with changes on host */
|
||||
/*@internal*/
|
||||
getCurrentProgram(): T;
|
||||
/** Closes the watch */
|
||||
/*@internal*/
|
||||
close(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,8 +596,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const initialVersion = 1;
|
||||
|
||||
/**
|
||||
* Creates the watch from the host for root files and compiler options
|
||||
*/
|
||||
@@ -455,13 +606,14 @@ namespace ts {
|
||||
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfConfigFile<T>): WatchOfConfigFile<T>;
|
||||
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfFilesAndCompilerOptions<T> & WatchCompilerHostOfConfigFile<T>): WatchOfFilesAndCompilerOptions<T> | WatchOfConfigFile<T> {
|
||||
interface FilePresentOnHost {
|
||||
version: number;
|
||||
version: string;
|
||||
sourceFile: SourceFile;
|
||||
fileWatcher: FileWatcher;
|
||||
}
|
||||
type FileMissingOnHost = number;
|
||||
type FileMissingOnHost = false;
|
||||
interface FilePresenceUnknownOnHost {
|
||||
version: number;
|
||||
version: false;
|
||||
fileWatcher?: FileWatcher;
|
||||
}
|
||||
type FileMayBePresentOnHost = FilePresentOnHost | FilePresenceUnknownOnHost;
|
||||
type HostFileInfo = FilePresentOnHost | FileMissingOnHost | FilePresenceUnknownOnHost;
|
||||
@@ -479,8 +631,6 @@ namespace ts {
|
||||
|
||||
const useCaseSensitiveFileNames = host.useCaseSensitiveFileNames();
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const getCurrentDirectory = () => currentDirectory;
|
||||
const readFile: (path: string, encoding?: string) => string | undefined = (path, encoding) => host.readFile(path, encoding);
|
||||
const { configFileName, optionsToExtend: optionsToExtendForConfigFile = {}, createProgram } = host;
|
||||
let { rootFiles: rootFileNames, options: compilerOptions, projectReferences } = host;
|
||||
let configFileSpecs: ConfigFileSpecs;
|
||||
@@ -493,15 +643,7 @@ namespace ts {
|
||||
host.onCachedDirectoryStructureHostCreate(cachedDirectoryStructureHost);
|
||||
}
|
||||
const directoryStructureHost: DirectoryStructureHost = cachedDirectoryStructureHost || host;
|
||||
const parseConfigFileHost: ParseConfigFileHost = {
|
||||
useCaseSensitiveFileNames,
|
||||
readDirectory: (path, extensions, exclude, include, depth) => directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth),
|
||||
fileExists: path => host.fileExists(path),
|
||||
readFile,
|
||||
getCurrentDirectory,
|
||||
onUnRecoverableConfigFileDiagnostic: host.onUnRecoverableConfigFileDiagnostic,
|
||||
trace: host.trace ? s => host.trace!(s) : undefined
|
||||
};
|
||||
const parseConfigFileHost = parseConfigHostFromCompilerHostLike(host, directoryStructureHost);
|
||||
|
||||
// From tsc we want to get already parsed result and hence check for rootFileNames
|
||||
let newLine = updateNewLine();
|
||||
@@ -517,55 +659,39 @@ namespace ts {
|
||||
newLine = updateNewLine();
|
||||
}
|
||||
|
||||
const trace = host.trace && ((s: string) => { host.trace!(s + newLine); });
|
||||
const watchLogLevel = trace ? compilerOptions.extendedDiagnostics ? WatchLogLevel.Verbose :
|
||||
compilerOptions.diagnostics ? WatchLogLevel.TriggerOnly : WatchLogLevel.None : WatchLogLevel.None;
|
||||
const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? trace! : noop; // TODO: GH#18217
|
||||
const { watchFile, watchFilePath, watchDirectory } = getWatchFactory<string>(watchLogLevel, writeLog);
|
||||
|
||||
const { watchFile, watchFilePath, watchDirectory, writeLog } = createWatchFactory<string>(host, compilerOptions);
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
|
||||
writeLog(`Current directory: ${currentDirectory} CaseSensitiveFileNames: ${useCaseSensitiveFileNames}`);
|
||||
let configFileWatcher: FileWatcher | undefined;
|
||||
if (configFileName) {
|
||||
watchFile(host, configFileName, scheduleProgramReload, PollingInterval.High, "Config file");
|
||||
configFileWatcher = watchFile(host, configFileName, scheduleProgramReload, PollingInterval.High, WatchType.ConfigFile);
|
||||
}
|
||||
|
||||
const compilerHost: CompilerHost & ResolutionCacheHost = {
|
||||
// Members for CompilerHost
|
||||
getSourceFile: (fileName, languageVersion, onError?, shouldCreateNewSourceFile?) => getVersionedSourceFileByPath(fileName, toPath(fileName), languageVersion, onError, shouldCreateNewSourceFile),
|
||||
getSourceFileByPath: getVersionedSourceFileByPath,
|
||||
getDefaultLibLocation: host.getDefaultLibLocation && (() => host.getDefaultLibLocation!()),
|
||||
getDefaultLibFileName: options => host.getDefaultLibFileName(options),
|
||||
writeFile,
|
||||
getCurrentDirectory,
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
getCanonicalFileName,
|
||||
getNewLine: () => newLine,
|
||||
fileExists,
|
||||
readFile,
|
||||
trace,
|
||||
directoryExists: directoryStructureHost.directoryExists && (path => directoryStructureHost.directoryExists!(path)),
|
||||
getDirectories: (directoryStructureHost.getDirectories && ((path: string) => directoryStructureHost.getDirectories!(path)))!, // TODO: GH#18217
|
||||
realpath: host.realpath && (s => host.realpath!(s)),
|
||||
getEnvironmentVariable: host.getEnvironmentVariable ? (name => host.getEnvironmentVariable!(name)) : (() => ""),
|
||||
onReleaseOldSourceFile,
|
||||
createHash: host.createHash && (data => host.createHash!(data)),
|
||||
// Members for ResolutionCacheHost
|
||||
toPath,
|
||||
getCompilationSettings: () => compilerOptions,
|
||||
watchDirectoryOfFailedLookupLocation: (dir, cb, flags) => watchDirectory(host, dir, cb, flags, "Failed Lookup Locations"),
|
||||
watchTypeRootsDirectory: (dir, cb, flags) => watchDirectory(host, dir, cb, flags, "Type roots"),
|
||||
getCachedDirectoryStructureHost: () => cachedDirectoryStructureHost,
|
||||
onInvalidatedResolution: scheduleProgramUpdate,
|
||||
onChangedAutomaticTypeDirectiveNames: () => {
|
||||
hasChangedAutomaticTypeDirectiveNames = true;
|
||||
scheduleProgramUpdate();
|
||||
},
|
||||
maxNumberOfFilesToIterateForInvalidation: host.maxNumberOfFilesToIterateForInvalidation,
|
||||
getCurrentProgram,
|
||||
writeLog,
|
||||
readDirectory: (path, extensions, exclude, include, depth?) => directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth),
|
||||
const compilerHost = createCompilerHostFromProgramHost(host, () => compilerOptions, directoryStructureHost) as CompilerHost & ResolutionCacheHost;
|
||||
setGetSourceFileAsHashVersioned(compilerHost, host);
|
||||
// Members for CompilerHost
|
||||
const getNewSourceFile = compilerHost.getSourceFile;
|
||||
compilerHost.getSourceFile = (fileName, ...args) => getVersionedSourceFileByPath(fileName, toPath(fileName), ...args);
|
||||
compilerHost.getSourceFileByPath = getVersionedSourceFileByPath;
|
||||
compilerHost.getNewLine = () => newLine;
|
||||
compilerHost.fileExists = fileExists;
|
||||
compilerHost.onReleaseOldSourceFile = onReleaseOldSourceFile;
|
||||
// Members for ResolutionCacheHost
|
||||
compilerHost.toPath = toPath;
|
||||
compilerHost.getCompilationSettings = () => compilerOptions;
|
||||
compilerHost.watchDirectoryOfFailedLookupLocation = (dir, cb, flags) => watchDirectory(host, dir, cb, flags, WatchType.FailedLookupLocations);
|
||||
compilerHost.watchTypeRootsDirectory = (dir, cb, flags) => watchDirectory(host, dir, cb, flags, WatchType.TypeRoots);
|
||||
compilerHost.getCachedDirectoryStructureHost = () => cachedDirectoryStructureHost;
|
||||
compilerHost.onInvalidatedResolution = scheduleProgramUpdate;
|
||||
compilerHost.onChangedAutomaticTypeDirectiveNames = () => {
|
||||
hasChangedAutomaticTypeDirectiveNames = true;
|
||||
scheduleProgramUpdate();
|
||||
};
|
||||
compilerHost.maxNumberOfFilesToIterateForInvalidation = host.maxNumberOfFilesToIterateForInvalidation;
|
||||
compilerHost.getCurrentProgram = getCurrentProgram;
|
||||
compilerHost.writeLog = writeLog;
|
||||
|
||||
// Cache for the module resolution
|
||||
const resolutionCache = createResolutionCache(compilerHost, configFileName ?
|
||||
getDirectoryPath(getNormalizedAbsolutePath(configFileName, currentDirectory)) :
|
||||
@@ -581,27 +707,50 @@ namespace ts {
|
||||
((typeDirectiveNames, containingFile, redirectedReference) => resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile, redirectedReference));
|
||||
const userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives;
|
||||
|
||||
builderProgram = readBuilderProgram(compilerOptions, path => compilerHost.readFile(path)) as any as T;
|
||||
synchronizeProgram();
|
||||
|
||||
// Update the wild card directory watch
|
||||
watchConfigFileWildCardDirectories();
|
||||
|
||||
return configFileName ?
|
||||
{ getCurrentProgram: getCurrentBuilderProgram, getProgram: synchronizeProgram } :
|
||||
{ getCurrentProgram: getCurrentBuilderProgram, getProgram: synchronizeProgram, updateRootFileNames };
|
||||
{ getCurrentProgram: getCurrentBuilderProgram, getProgram: synchronizeProgram, close } :
|
||||
{ getCurrentProgram: getCurrentBuilderProgram, getProgram: synchronizeProgram, updateRootFileNames, close };
|
||||
|
||||
function close() {
|
||||
resolutionCache.clear();
|
||||
clearMap(sourceFilesCache, value => {
|
||||
if (value && value.fileWatcher) {
|
||||
value.fileWatcher.close();
|
||||
value.fileWatcher = undefined;
|
||||
}
|
||||
});
|
||||
if (configFileWatcher) {
|
||||
configFileWatcher.close();
|
||||
configFileWatcher = undefined;
|
||||
}
|
||||
if (watchedWildcardDirectories) {
|
||||
clearMap(watchedWildcardDirectories, closeFileWatcherOf);
|
||||
watchedWildcardDirectories = undefined!;
|
||||
}
|
||||
if (missingFilesMap) {
|
||||
clearMap(missingFilesMap, closeFileWatcher);
|
||||
missingFilesMap = undefined!;
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentBuilderProgram() {
|
||||
return builderProgram;
|
||||
}
|
||||
|
||||
function getCurrentProgram() {
|
||||
return builderProgram && builderProgram.getProgram();
|
||||
return builderProgram && builderProgram.getProgramOrUndefined();
|
||||
}
|
||||
|
||||
function synchronizeProgram() {
|
||||
writeLog(`Synchronizing program`);
|
||||
|
||||
const program = getCurrentProgram();
|
||||
const program = getCurrentBuilderProgram();
|
||||
if (hasChangedCompilerOptions) {
|
||||
newLine = updateNewLine();
|
||||
if (program && changesAffectModuleResolution(program.getCompilerOptions(), compilerOptions)) {
|
||||
@@ -618,7 +767,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
createNewProgram(program, hasInvalidatedResolution);
|
||||
createNewProgram(hasInvalidatedResolution);
|
||||
}
|
||||
|
||||
if (host.afterProgramCreate) {
|
||||
@@ -628,15 +777,13 @@ namespace ts {
|
||||
return builderProgram;
|
||||
}
|
||||
|
||||
function createNewProgram(program: Program, hasInvalidatedResolution: HasInvalidatedResolution) {
|
||||
function createNewProgram(hasInvalidatedResolution: HasInvalidatedResolution) {
|
||||
// Compile the program
|
||||
if (watchLogLevel !== WatchLogLevel.None) {
|
||||
writeLog("CreatingProgramWith::");
|
||||
writeLog(` roots: ${JSON.stringify(rootFileNames)}`);
|
||||
writeLog(` options: ${JSON.stringify(compilerOptions)}`);
|
||||
}
|
||||
writeLog("CreatingProgramWith::");
|
||||
writeLog(` roots: ${JSON.stringify(rootFileNames)}`);
|
||||
writeLog(` options: ${JSON.stringify(compilerOptions)}`);
|
||||
|
||||
const needsUpdateInTypeRootWatch = hasChangedCompilerOptions || !program;
|
||||
const needsUpdateInTypeRootWatch = hasChangedCompilerOptions || !getCurrentProgram();
|
||||
hasChangedCompilerOptions = false;
|
||||
hasChangedConfigFileParsingErrors = false;
|
||||
resolutionCache.startCachingPerDirectoryResolution();
|
||||
@@ -680,19 +827,19 @@ namespace ts {
|
||||
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
function isFileMissingOnHost(hostSourceFile: HostFileInfo): hostSourceFile is FileMissingOnHost {
|
||||
return typeof hostSourceFile === "number";
|
||||
function isFileMissingOnHost(hostSourceFile: HostFileInfo | undefined): hostSourceFile is FileMissingOnHost {
|
||||
return typeof hostSourceFile === "boolean";
|
||||
}
|
||||
|
||||
function isFilePresentOnHost(hostSourceFile: FileMayBePresentOnHost): hostSourceFile is FilePresentOnHost {
|
||||
return !!(hostSourceFile as FilePresentOnHost).sourceFile;
|
||||
function isFilePresenceUnknownOnHost(hostSourceFile: FileMayBePresentOnHost): hostSourceFile is FilePresenceUnknownOnHost {
|
||||
return typeof (hostSourceFile as FilePresenceUnknownOnHost).version === "boolean";
|
||||
}
|
||||
|
||||
function fileExists(fileName: string) {
|
||||
const path = toPath(fileName);
|
||||
// If file is missing on host from cache, we can definitely say file doesnt exist
|
||||
// otherwise we need to ensure from the disk
|
||||
if (isFileMissingOnHost(sourceFilesCache.get(path)!)) {
|
||||
if (isFileMissingOnHost(sourceFilesCache.get(path))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -700,66 +847,44 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
|
||||
const hostSourceFile = sourceFilesCache.get(path)!;
|
||||
const hostSourceFile = sourceFilesCache.get(path);
|
||||
// No source file on the host
|
||||
if (isFileMissingOnHost(hostSourceFile)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Create new source file if requested or the versions dont match
|
||||
if (!hostSourceFile || shouldCreateNewSourceFile || !isFilePresentOnHost(hostSourceFile) || hostSourceFile.version.toString() !== hostSourceFile.sourceFile.version) {
|
||||
const sourceFile = getNewSourceFile();
|
||||
if (hostSourceFile === undefined || shouldCreateNewSourceFile || isFilePresenceUnknownOnHost(hostSourceFile)) {
|
||||
const sourceFile = getNewSourceFile(fileName, languageVersion, onError);
|
||||
if (hostSourceFile) {
|
||||
if (shouldCreateNewSourceFile) {
|
||||
hostSourceFile.version++;
|
||||
}
|
||||
|
||||
if (sourceFile) {
|
||||
// Set the source file and create file watcher now that file was present on the disk
|
||||
(hostSourceFile as FilePresentOnHost).sourceFile = sourceFile;
|
||||
sourceFile.version = hostSourceFile.version.toString();
|
||||
if (!(hostSourceFile as FilePresentOnHost).fileWatcher) {
|
||||
(hostSourceFile as FilePresentOnHost).fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, "Source file");
|
||||
hostSourceFile.version = sourceFile.version;
|
||||
if (!hostSourceFile.fileWatcher) {
|
||||
hostSourceFile.fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// There is no source file on host any more, close the watch, missing file paths will track it
|
||||
if (isFilePresentOnHost(hostSourceFile)) {
|
||||
if (hostSourceFile.fileWatcher) {
|
||||
hostSourceFile.fileWatcher.close();
|
||||
}
|
||||
sourceFilesCache.set(path, hostSourceFile.version);
|
||||
sourceFilesCache.set(path, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sourceFile) {
|
||||
sourceFile.version = initialVersion.toString();
|
||||
const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, "Source file");
|
||||
sourceFilesCache.set(path, { sourceFile, version: initialVersion, fileWatcher });
|
||||
const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
|
||||
sourceFilesCache.set(path, { sourceFile, version: sourceFile.version, fileWatcher });
|
||||
}
|
||||
else {
|
||||
sourceFilesCache.set(path, initialVersion);
|
||||
sourceFilesCache.set(path, false);
|
||||
}
|
||||
}
|
||||
return sourceFile;
|
||||
}
|
||||
return hostSourceFile.sourceFile;
|
||||
|
||||
function getNewSourceFile() {
|
||||
let text: string | undefined;
|
||||
try {
|
||||
performance.mark("beforeIORead");
|
||||
text = host.readFile(fileName, compilerOptions.charset);
|
||||
performance.mark("afterIORead");
|
||||
performance.measure("I/O Read", "beforeIORead", "afterIORead");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
onError(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
return text !== undefined ? createSourceFile(fileName, text, languageVersion) : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function nextSourceFileVersion(path: Path) {
|
||||
@@ -767,17 +892,17 @@ namespace ts {
|
||||
if (hostSourceFile !== undefined) {
|
||||
if (isFileMissingOnHost(hostSourceFile)) {
|
||||
// The next version, lets set it as presence unknown file
|
||||
sourceFilesCache.set(path, { version: Number(hostSourceFile) + 1 });
|
||||
sourceFilesCache.set(path, { version: false });
|
||||
}
|
||||
else {
|
||||
hostSourceFile.version++;
|
||||
(hostSourceFile as FilePresenceUnknownOnHost).version = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSourceVersion(path: Path): string | undefined {
|
||||
const hostSourceFile = sourceFilesCache.get(path);
|
||||
return !hostSourceFile || isFileMissingOnHost(hostSourceFile) ? undefined : hostSourceFile.version.toString();
|
||||
return !hostSourceFile || !hostSourceFile.version ? undefined : hostSourceFile.version;
|
||||
}
|
||||
|
||||
function onReleaseOldSourceFile(oldSourceFile: SourceFile, _oldOptions: CompilerOptions, hasSourceFileByPath: boolean) {
|
||||
@@ -786,14 +911,14 @@ namespace ts {
|
||||
// remove the cached entry.
|
||||
// Note we arent deleting entry if file became missing in new program or
|
||||
// there was version update and new source file was created.
|
||||
if (hostSourceFileInfo) {
|
||||
if (hostSourceFileInfo !== undefined) {
|
||||
// record the missing file paths so they can be removed later if watchers arent tracking them
|
||||
if (isFileMissingOnHost(hostSourceFileInfo)) {
|
||||
(missingFilePathsRequestedForRelease || (missingFilePathsRequestedForRelease = [])).push(oldSourceFile.path);
|
||||
}
|
||||
else if ((hostSourceFileInfo as FilePresentOnHost).sourceFile === oldSourceFile) {
|
||||
if ((hostSourceFileInfo as FilePresentOnHost).fileWatcher) {
|
||||
(hostSourceFileInfo as FilePresentOnHost).fileWatcher.close();
|
||||
if (hostSourceFileInfo.fileWatcher) {
|
||||
hostSourceFileInfo.fileWatcher.close();
|
||||
}
|
||||
sourceFilesCache.delete(oldSourceFile.resolvedPath);
|
||||
if (!hasSourceFileByPath) {
|
||||
@@ -890,7 +1015,7 @@ namespace ts {
|
||||
updateCachedSystemWithFile(fileName, path, eventKind);
|
||||
|
||||
// Update the source file cache
|
||||
if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.get(path)) {
|
||||
if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.has(path)) {
|
||||
resolutionCache.invalidateResolutionOfFile(path);
|
||||
}
|
||||
resolutionCache.removeResolutionsFromProjectReferenceRedirects(path);
|
||||
@@ -907,7 +1032,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function watchMissingFilePath(missingFilePath: Path) {
|
||||
return watchFilePath(host, missingFilePath, onMissingFileChange, PollingInterval.Medium, missingFilePath, "Missing file");
|
||||
return watchFilePath(host, missingFilePath, onMissingFileChange, PollingInterval.Medium, missingFilePath, WatchType.MissingFile);
|
||||
}
|
||||
|
||||
function onMissingFileChange(fileName: string, eventKind: FileWatcherEventKind, missingFilePath: Path) {
|
||||
@@ -953,7 +1078,7 @@ namespace ts {
|
||||
}
|
||||
nextSourceFileVersion(fileOrDirectoryPath);
|
||||
|
||||
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return;
|
||||
if (isPathIgnored(fileOrDirectoryPath)) return;
|
||||
|
||||
// If the the added or created file or directory is not supported file name, ignore the file
|
||||
// But when watched directory is added/removed, we need to reload the file list
|
||||
@@ -971,33 +1096,8 @@ namespace ts {
|
||||
}
|
||||
},
|
||||
flags,
|
||||
"Wild card directories"
|
||||
WatchType.WildcardDirectory
|
||||
);
|
||||
}
|
||||
|
||||
function ensureDirectoriesExist(directoryPath: string) {
|
||||
if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists!(directoryPath)) {
|
||||
const parentDirectory = getDirectoryPath(directoryPath);
|
||||
ensureDirectoriesExist(parentDirectory);
|
||||
host.createDirectory!(directoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, onError: (message: string) => void) {
|
||||
try {
|
||||
performance.mark("beforeIOWrite");
|
||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
||||
|
||||
host.writeFile!(fileName, text, writeByteOrderMark);
|
||||
|
||||
performance.mark("afterIOWrite");
|
||||
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
onError(e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace ts {
|
||||
directoryExists?(path: string): boolean;
|
||||
getDirectories?(path: string): string[];
|
||||
readDirectory?(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
|
||||
realpath?(path: string): string;
|
||||
|
||||
createDirectory?(path: string): void;
|
||||
writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void;
|
||||
@@ -56,7 +57,8 @@ namespace ts {
|
||||
writeFile: host.writeFile && writeFile,
|
||||
addOrDeleteFileOrDirectory,
|
||||
addOrDeleteFile,
|
||||
clearCache
|
||||
clearCache,
|
||||
realpath: host.realpath && realpath
|
||||
};
|
||||
|
||||
function toPath(fileName: string) {
|
||||
@@ -170,7 +172,7 @@ namespace ts {
|
||||
const rootDirPath = toPath(rootDir);
|
||||
const result = tryReadDirectory(rootDir, rootDirPath);
|
||||
if (result) {
|
||||
return matchFiles(rootDir, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries);
|
||||
return matchFiles(rootDir, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries, realpath);
|
||||
}
|
||||
return host.readDirectory!(rootDir, extensions, excludes, includes, depth);
|
||||
|
||||
@@ -183,6 +185,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function realpath(s: string) {
|
||||
return host.realpath ? host.realpath(s) : s;
|
||||
}
|
||||
|
||||
function addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path) {
|
||||
const existingResult = getCachedFileSystemEntries(fileOrDirectoryPath);
|
||||
if (existingResult) {
|
||||
@@ -343,10 +349,10 @@ namespace ts {
|
||||
export interface WatchDirectoryHost {
|
||||
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
|
||||
}
|
||||
export type WatchFile<X, Y> = (host: WatchFileHost, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type WatchFile<X, Y> = (host: WatchFileHost, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, detailInfo1: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type FilePathWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind, filePath: Path) => void;
|
||||
export type WatchFilePath<X, Y> = (host: WatchFileHost, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type WatchDirectory<X, Y> = (host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type WatchFilePath<X, Y> = (host: WatchFileHost, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path, detailInfo1: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type WatchDirectory<X, Y> = (host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags, detailInfo1: X, detailInfo2?: Y) => FileWatcher;
|
||||
|
||||
export interface WatchFactory<X, Y> {
|
||||
watchFile: WatchFile<X, Y>;
|
||||
@@ -361,9 +367,9 @@ namespace ts {
|
||||
function getWatchFactoryWith<X, Y = undefined>(watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined,
|
||||
watchFile: (host: WatchFileHost, file: string, callback: FileWatcherCallback, watchPriority: PollingInterval) => FileWatcher,
|
||||
watchDirectory: (host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags) => FileWatcher): WatchFactory<X, Y> {
|
||||
const createFileWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchFile);
|
||||
const createFileWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, never, X, Y> = getCreateFileWatcher(watchLogLevel, watchFile);
|
||||
const createFilePathWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, Path, X, Y> = watchLogLevel === WatchLogLevel.None ? watchFilePath : createFileWatcher;
|
||||
const createDirectoryWatcher: CreateFileWatcher<WatchDirectoryHost, WatchDirectoryFlags, undefined, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchDirectory);
|
||||
const createDirectoryWatcher: CreateFileWatcher<WatchDirectoryHost, WatchDirectoryFlags, undefined, never, X, Y> = getCreateFileWatcher(watchLogLevel, watchDirectory);
|
||||
return {
|
||||
watchFile: (host, file, callback, pollingInterval, detailInfo1, detailInfo2) =>
|
||||
createFileWatcher(host, file, callback, pollingInterval, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo),
|
||||
@@ -402,7 +408,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createFileWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
function createFileWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, V>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
log(`${watchCaption}:: Added:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`);
|
||||
const watcher = createFileWatcherWithTriggerLogging(host, file, cb, flags, passThrough, detailInfo1, detailInfo2, addWatch, log, watchCaption, getDetailWatchInfo);
|
||||
return {
|
||||
@@ -413,7 +419,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function createDirectoryWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
function createDirectoryWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, V>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
const watchInfo = `${watchCaption}:: Added:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
|
||||
log(watchInfo);
|
||||
const start = timestamp();
|
||||
@@ -432,7 +438,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function createFileWatcherWithTriggerLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
function createFileWatcherWithTriggerLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, V>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
return addWatch(host, file, (fileName, cbOptional) => {
|
||||
const triggerredInfo = `${watchCaption}:: Triggered with ${fileName} ${cbOptional !== undefined ? cbOptional : ""}:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
|
||||
log(triggerredInfo);
|
||||
@@ -444,7 +450,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getWatchInfo<T, X, Y>(file: string, flags: T, detailInfo1: X, detailInfo2: Y | undefined, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined) {
|
||||
return `WatchInfo: ${file} ${flags} ${getDetailWatchInfo ? getDetailWatchInfo(detailInfo1, detailInfo2) : detailInfo1}`;
|
||||
return `WatchInfo: ${file} ${flags} ${getDetailWatchInfo ? getDetailWatchInfo(detailInfo1, detailInfo2) : detailInfo2 === undefined ? detailInfo1 : `${detailInfo1} ${detailInfo2}`}`;
|
||||
}
|
||||
|
||||
export function closeFileWatcherOf<T extends { watcher: FileWatcher; }>(objWithWatcher: T) {
|
||||
|
||||
Reference in New Issue
Block a user