mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into master-16763
This commit is contained in:
@@ -27,7 +27,7 @@ function walk(ctx: Lint.WalkContext<void>): void {
|
||||
/** Skip certain function/method names whose parameter names are not informative. */
|
||||
function shouldIgnoreCalledExpression(expression: ts.Expression): boolean {
|
||||
if (expression.kind === ts.SyntaxKind.PropertyAccessExpression) {
|
||||
const methodName = (expression as ts.PropertyAccessExpression).name.text;
|
||||
const methodName = (expression as ts.PropertyAccessExpression).name.text as string;
|
||||
if (methodName.indexOf("set") === 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -44,7 +44,7 @@ function walk(ctx: Lint.WalkContext<void>): void {
|
||||
}
|
||||
}
|
||||
else if (expression.kind === ts.SyntaxKind.Identifier) {
|
||||
const functionName = (expression as ts.Identifier).text;
|
||||
const functionName = (expression as ts.Identifier).text as string;
|
||||
if (functionName.indexOf("set") === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
+60
-27
@@ -56,7 +56,6 @@ namespace ts {
|
||||
let enumCount = 0;
|
||||
let symbolInstantiationDepth = 0;
|
||||
|
||||
const emptyArray: any[] = [];
|
||||
const emptySymbols = createSymbolTable();
|
||||
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
@@ -84,9 +83,9 @@ namespace ts {
|
||||
// extra cost of calling `getParseTreeNode` when calling these functions from inside the
|
||||
// checker.
|
||||
const checker: TypeChecker = {
|
||||
getNodeCount: () => sum(host.getSourceFiles(), "nodeCount"),
|
||||
getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"),
|
||||
getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount") + symbolCount,
|
||||
getNodeCount: () => sum<"nodeCount">(host.getSourceFiles(), "nodeCount"),
|
||||
getIdentifierCount: () => sum<"identifierCount">(host.getSourceFiles(), "identifierCount"),
|
||||
getSymbolCount: () => sum<"symbolCount">(host.getSourceFiles(), "symbolCount") + symbolCount,
|
||||
getTypeCount: () => typeCount,
|
||||
isUndefinedSymbol: symbol => symbol === undefinedSymbol,
|
||||
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
|
||||
@@ -8735,11 +8734,12 @@ namespace ts {
|
||||
containingMessageChain?: DiagnosticMessageChain): boolean {
|
||||
|
||||
let errorInfo: DiagnosticMessageChain;
|
||||
let maybeKeys: string[];
|
||||
let sourceStack: Type[];
|
||||
let targetStack: Type[];
|
||||
let maybeStack: Map<RelationComparisonResult>[];
|
||||
let expandingFlags: number;
|
||||
let maybeCount = 0;
|
||||
let depth = 0;
|
||||
let expandingFlags = 0;
|
||||
let overflow = false;
|
||||
let isIntersectionConstituent = false;
|
||||
|
||||
@@ -9107,10 +9107,15 @@ namespace ts {
|
||||
return related === RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False;
|
||||
}
|
||||
}
|
||||
if (depth > 0) {
|
||||
for (let i = 0; i < depth; i++) {
|
||||
if (!maybeKeys) {
|
||||
maybeKeys = [];
|
||||
sourceStack = [];
|
||||
targetStack = [];
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < maybeCount; i++) {
|
||||
// If source and target are already being compared, consider them related with assumptions
|
||||
if (maybeStack[i].get(id)) {
|
||||
if (id === maybeKeys[i]) {
|
||||
return Ternary.Maybe;
|
||||
}
|
||||
}
|
||||
@@ -9119,16 +9124,11 @@ namespace ts {
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sourceStack = [];
|
||||
targetStack = [];
|
||||
maybeStack = [];
|
||||
expandingFlags = 0;
|
||||
}
|
||||
const maybeStart = maybeCount;
|
||||
maybeKeys[maybeCount] = id;
|
||||
maybeCount++;
|
||||
sourceStack[depth] = source;
|
||||
targetStack[depth] = target;
|
||||
maybeStack[depth] = createMap<RelationComparisonResult>();
|
||||
maybeStack[depth].set(id, RelationComparisonResult.Succeeded);
|
||||
depth++;
|
||||
const saveExpandingFlags = expandingFlags;
|
||||
if (!(expandingFlags & 1) && isDeeplyNestedType(source, sourceStack, depth)) expandingFlags |= 1;
|
||||
@@ -9137,15 +9137,19 @@ namespace ts {
|
||||
expandingFlags = saveExpandingFlags;
|
||||
depth--;
|
||||
if (result) {
|
||||
const maybeCache = maybeStack[depth];
|
||||
// If result is definitely true, copy assumptions to global cache, else copy to next level up
|
||||
const destinationCache = (result === Ternary.True || depth === 0) ? relation : maybeStack[depth - 1];
|
||||
copyEntries(maybeCache, destinationCache);
|
||||
if (result === Ternary.True || depth === 0) {
|
||||
// If result is definitely true, record all maybe keys as having succeeded
|
||||
for (let i = maybeStart; i < maybeCount; i++) {
|
||||
relation.set(maybeKeys[i], RelationComparisonResult.Succeeded);
|
||||
}
|
||||
maybeCount = maybeStart;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// A false result goes straight into global cache (when something is false under assumptions it
|
||||
// will also be false without assumptions)
|
||||
// A false result goes straight into global cache (when something is false under
|
||||
// assumptions it will also be false without assumptions)
|
||||
relation.set(id, reportErrors ? RelationComparisonResult.FailedAndReported : RelationComparisonResult.Failed);
|
||||
maybeCount = maybeStart;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -12004,9 +12008,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
|
||||
let declaration = localOrExportSymbol.valueDeclaration;
|
||||
|
||||
if (localOrExportSymbol.flags & SymbolFlags.Class) {
|
||||
const declaration = localOrExportSymbol.valueDeclaration;
|
||||
// Due to the emit for class decorators, any reference to the class from inside of the class body
|
||||
// must instead be rewritten to point to a temporary variable to avoid issues with the double-bind
|
||||
// behavior of class names in ES6.
|
||||
@@ -12048,7 +12052,6 @@ namespace ts {
|
||||
checkNestedBlockScopedBinding(node, symbol);
|
||||
|
||||
const type = getDeclaredOrApparentType(localOrExportSymbol, node);
|
||||
const declaration = localOrExportSymbol.valueDeclaration;
|
||||
const assignmentKind = getAssignmentTargetKind(node);
|
||||
|
||||
if (assignmentKind) {
|
||||
@@ -12062,11 +12065,26 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const isAlias = localOrExportSymbol.flags & SymbolFlags.Alias;
|
||||
|
||||
// We only narrow variables and parameters occurring in a non-assignment position. For all other
|
||||
// entities we simply return the declared type.
|
||||
if (!(localOrExportSymbol.flags & SymbolFlags.Variable) || assignmentKind === AssignmentKind.Definite || !declaration) {
|
||||
if (localOrExportSymbol.flags & SymbolFlags.Variable) {
|
||||
if (assignmentKind === AssignmentKind.Definite) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
else if (isAlias) {
|
||||
declaration = find<Declaration>(symbol.declarations, isSomeImportDeclaration);
|
||||
}
|
||||
else {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (!declaration) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// The declaration container is the innermost function that encloses the declaration of the variable
|
||||
// or parameter. The flow container is the innermost function starting with which we analyze the control
|
||||
// flow graph to determine the control flow based type.
|
||||
@@ -12085,7 +12103,7 @@ namespace ts {
|
||||
// We only look for uninitialized variables in strict null checking mode, and only when we can analyze
|
||||
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
|
||||
// declaration container are the same).
|
||||
const assumeInitialized = isParameter || isOuterVariable ||
|
||||
const assumeInitialized = isParameter || isAlias || isOuterVariable ||
|
||||
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) ||
|
||||
node.parent.kind === SyntaxKind.NonNullExpression ||
|
||||
isInAmbientContext(declaration);
|
||||
@@ -24771,4 +24789,19 @@ namespace ts {
|
||||
return isDeclarationName(name);
|
||||
}
|
||||
}
|
||||
|
||||
function isSomeImportDeclaration(decl: Node): boolean {
|
||||
switch (decl.kind) {
|
||||
case SyntaxKind.ImportClause: // For default import
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
case SyntaxKind.NamespaceImport:
|
||||
case SyntaxKind.ImportSpecifier: // For rename import `x as y`
|
||||
return true;
|
||||
case SyntaxKind.Identifier:
|
||||
// For regular import, `decl` is an Identifier under the ImportSpecifier.
|
||||
return decl.parent.kind === SyntaxKind.ImportSpecifier;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-45
@@ -162,50 +162,6 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export function createFileMap<T>(keyMapper: (key: string) => string): FileMap<T> {
|
||||
const files = createMap<T>();
|
||||
return {
|
||||
get,
|
||||
set,
|
||||
contains,
|
||||
remove,
|
||||
forEachValue: forEachValueInMap,
|
||||
getKeys,
|
||||
clear,
|
||||
};
|
||||
|
||||
function forEachValueInMap(f: (key: Path, value: T) => void) {
|
||||
files.forEach((file, key) => {
|
||||
f(<Path>key, file);
|
||||
});
|
||||
}
|
||||
|
||||
function getKeys() {
|
||||
return arrayFrom(files.keys()) as Path[];
|
||||
}
|
||||
|
||||
// path should already be well-formed so it does not need to be normalized
|
||||
function get(path: Path): T {
|
||||
return files.get(keyMapper(path));
|
||||
}
|
||||
|
||||
function set(path: Path, value: T) {
|
||||
files.set(keyMapper(path), value);
|
||||
}
|
||||
|
||||
function contains(path: Path) {
|
||||
return files.has(keyMapper(path));
|
||||
}
|
||||
|
||||
function remove(path: Path) {
|
||||
files.delete(keyMapper(path));
|
||||
}
|
||||
|
||||
function clear() {
|
||||
files.clear();
|
||||
}
|
||||
}
|
||||
|
||||
export function toPath(fileName: string, basePath: string, getCanonicalFileName: (path: string) => string): Path {
|
||||
const nonCanonicalizedPath = isRootedDiskPath(fileName)
|
||||
? normalizePath(fileName)
|
||||
@@ -744,7 +700,7 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function sum(array: any[], prop: string): number {
|
||||
export function sum<K extends string>(array: { [x in K]: number }[], prop: K): number {
|
||||
let result = 0;
|
||||
for (const v of array) {
|
||||
result += v[prop];
|
||||
|
||||
+79
-89
@@ -22,20 +22,15 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function visitNode<T>(cbNode: (node: Node) => T, node?: Node): T | undefined {
|
||||
if (node) {
|
||||
return cbNode(node);
|
||||
}
|
||||
function visitNode<T>(cbNode: (node: Node) => T, node: Node): T | undefined {
|
||||
return node && cbNode(node);
|
||||
}
|
||||
|
||||
function visitNodeArray<T>(cbNodes: (nodes: Node[]) => T, nodes?: Node[]): T | undefined {
|
||||
if (nodes) {
|
||||
return cbNodes(nodes);
|
||||
}
|
||||
}
|
||||
|
||||
function visitEachNode<T>(cbNode: (node: Node) => T, nodes?: Node[]): T | undefined {
|
||||
function visitNodes<T>(cbNode: (node: Node) => T, cbNodes: (node: NodeArray<Node>) => T | undefined, nodes: NodeArray<Node>): T | undefined {
|
||||
if (nodes) {
|
||||
if (cbNodes) {
|
||||
return cbNodes(nodes);
|
||||
}
|
||||
for (const node of nodes) {
|
||||
const result = cbNode(node);
|
||||
if (result) {
|
||||
@@ -53,17 +48,12 @@ namespace ts {
|
||||
*
|
||||
* @param node a given node to visit its children
|
||||
* @param cbNode a callback to be invoked for all child nodes
|
||||
* @param cbNodeArray a callback to be invoked for embedded array
|
||||
* @param cbNodes a callback to be invoked for embedded array
|
||||
*/
|
||||
export function forEachChild<T>(node: Node, cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
|
||||
if (!node) {
|
||||
export function forEachChild<T>(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
|
||||
if (!node || node.kind <= SyntaxKind.LastToken) {
|
||||
return;
|
||||
}
|
||||
// The visitXXX functions could be written as local functions that close over the cbNode and cbNodeArray
|
||||
// callback parameters, but that causes a closure allocation for each invocation with noticeable effects
|
||||
// on performance.
|
||||
const visitNodes: (cb: ((node?: Node) => T | undefined) | ((node?: Node[]) => T | undefined), nodes?: Node[]) => T | undefined = cbNodeArray ? visitNodeArray : visitEachNode;
|
||||
const cbNodes = cbNodeArray || cbNode;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.QualifiedName:
|
||||
return visitNode(cbNode, (<QualifiedName>node).left) ||
|
||||
@@ -74,8 +64,8 @@ namespace ts {
|
||||
visitNode(cbNode, (<TypeParameterDeclaration>node).default) ||
|
||||
visitNode(cbNode, (<TypeParameterDeclaration>node).expression);
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).name) ||
|
||||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).questionToken) ||
|
||||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).equalsToken) ||
|
||||
@@ -88,8 +78,8 @@ namespace ts {
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.BindingElement:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<VariableLikeDeclaration>node).propertyName) ||
|
||||
visitNode(cbNode, (<VariableLikeDeclaration>node).dotDotDotToken) ||
|
||||
visitNode(cbNode, (<VariableLikeDeclaration>node).name) ||
|
||||
@@ -101,10 +91,10 @@ namespace ts {
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.IndexSignature:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
visitNodes(cbNodes, (<SignatureDeclaration>node).typeParameters) ||
|
||||
visitNodes(cbNodes, (<SignatureDeclaration>node).parameters) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNodes(cbNode, cbNodes, (<SignatureDeclaration>node).typeParameters) ||
|
||||
visitNodes(cbNode, cbNodes, (<SignatureDeclaration>node).parameters) ||
|
||||
visitNode(cbNode, (<SignatureDeclaration>node).type);
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
@@ -114,33 +104,33 @@ namespace ts {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<FunctionLikeDeclaration>node).asteriskToken) ||
|
||||
visitNode(cbNode, (<FunctionLikeDeclaration>node).name) ||
|
||||
visitNode(cbNode, (<FunctionLikeDeclaration>node).questionToken) ||
|
||||
visitNodes(cbNodes, (<FunctionLikeDeclaration>node).typeParameters) ||
|
||||
visitNodes(cbNodes, (<FunctionLikeDeclaration>node).parameters) ||
|
||||
visitNodes(cbNode, cbNodes, (<FunctionLikeDeclaration>node).typeParameters) ||
|
||||
visitNodes(cbNode, cbNodes, (<FunctionLikeDeclaration>node).parameters) ||
|
||||
visitNode(cbNode, (<FunctionLikeDeclaration>node).type) ||
|
||||
visitNode(cbNode, (<ArrowFunction>node).equalsGreaterThanToken) ||
|
||||
visitNode(cbNode, (<FunctionLikeDeclaration>node).body);
|
||||
case SyntaxKind.TypeReference:
|
||||
return visitNode(cbNode, (<TypeReferenceNode>node).typeName) ||
|
||||
visitNodes(cbNodes, (<TypeReferenceNode>node).typeArguments);
|
||||
visitNodes(cbNode, cbNodes, (<TypeReferenceNode>node).typeArguments);
|
||||
case SyntaxKind.TypePredicate:
|
||||
return visitNode(cbNode, (<TypePredicateNode>node).parameterName) ||
|
||||
visitNode(cbNode, (<TypePredicateNode>node).type);
|
||||
case SyntaxKind.TypeQuery:
|
||||
return visitNode(cbNode, (<TypeQueryNode>node).exprName);
|
||||
case SyntaxKind.TypeLiteral:
|
||||
return visitNodes(cbNodes, (<TypeLiteralNode>node).members);
|
||||
return visitNodes(cbNode, cbNodes, (<TypeLiteralNode>node).members);
|
||||
case SyntaxKind.ArrayType:
|
||||
return visitNode(cbNode, (<ArrayTypeNode>node).elementType);
|
||||
case SyntaxKind.TupleType:
|
||||
return visitNodes(cbNodes, (<TupleTypeNode>node).elementTypes);
|
||||
return visitNodes(cbNode, cbNodes, (<TupleTypeNode>node).elementTypes);
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
return visitNodes(cbNodes, (<UnionOrIntersectionTypeNode>node).types);
|
||||
return visitNodes(cbNode, cbNodes, (<UnionOrIntersectionTypeNode>node).types);
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
case SyntaxKind.TypeOperator:
|
||||
return visitNode(cbNode, (<ParenthesizedTypeNode | TypeOperatorNode>node).type);
|
||||
@@ -156,11 +146,11 @@ namespace ts {
|
||||
return visitNode(cbNode, (<LiteralTypeNode>node).literal);
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return visitNodes(cbNodes, (<BindingPattern>node).elements);
|
||||
return visitNodes(cbNode, cbNodes, (<BindingPattern>node).elements);
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return visitNodes(cbNodes, (<ArrayLiteralExpression>node).elements);
|
||||
return visitNodes(cbNode, cbNodes, (<ArrayLiteralExpression>node).elements);
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return visitNodes(cbNodes, (<ObjectLiteralExpression>node).properties);
|
||||
return visitNodes(cbNode, cbNodes, (<ObjectLiteralExpression>node).properties);
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return visitNode(cbNode, (<PropertyAccessExpression>node).expression) ||
|
||||
visitNode(cbNode, (<PropertyAccessExpression>node).name);
|
||||
@@ -170,8 +160,8 @@ namespace ts {
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.NewExpression:
|
||||
return visitNode(cbNode, (<CallExpression>node).expression) ||
|
||||
visitNodes(cbNodes, (<CallExpression>node).typeArguments) ||
|
||||
visitNodes(cbNodes, (<CallExpression>node).arguments);
|
||||
visitNodes(cbNode, cbNodes, (<CallExpression>node).typeArguments) ||
|
||||
visitNodes(cbNode, cbNodes, (<CallExpression>node).arguments);
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
return visitNode(cbNode, (<TaggedTemplateExpression>node).tag) ||
|
||||
visitNode(cbNode, (<TaggedTemplateExpression>node).template);
|
||||
@@ -216,16 +206,16 @@ namespace ts {
|
||||
return visitNode(cbNode, (<SpreadElement>node).expression);
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return visitNodes(cbNodes, (<Block>node).statements);
|
||||
return visitNodes(cbNode, cbNodes, (<Block>node).statements);
|
||||
case SyntaxKind.SourceFile:
|
||||
return visitNodes(cbNodes, (<SourceFile>node).statements) ||
|
||||
return visitNodes(cbNode, cbNodes, (<SourceFile>node).statements) ||
|
||||
visitNode(cbNode, (<SourceFile>node).endOfFileToken);
|
||||
case SyntaxKind.VariableStatement:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<VariableStatement>node).declarationList);
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
return visitNodes(cbNodes, (<VariableDeclarationList>node).declarations);
|
||||
return visitNodes(cbNode, cbNodes, (<VariableDeclarationList>node).declarations);
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
return visitNode(cbNode, (<ExpressionStatement>node).expression);
|
||||
case SyntaxKind.IfStatement:
|
||||
@@ -264,12 +254,12 @@ namespace ts {
|
||||
return visitNode(cbNode, (<SwitchStatement>node).expression) ||
|
||||
visitNode(cbNode, (<SwitchStatement>node).caseBlock);
|
||||
case SyntaxKind.CaseBlock:
|
||||
return visitNodes(cbNodes, (<CaseBlock>node).clauses);
|
||||
return visitNodes(cbNode, cbNodes, (<CaseBlock>node).clauses);
|
||||
case SyntaxKind.CaseClause:
|
||||
return visitNode(cbNode, (<CaseClause>node).expression) ||
|
||||
visitNodes(cbNodes, (<CaseClause>node).statements);
|
||||
visitNodes(cbNode, cbNodes, (<CaseClause>node).statements);
|
||||
case SyntaxKind.DefaultClause:
|
||||
return visitNodes(cbNodes, (<DefaultClause>node).statements);
|
||||
return visitNodes(cbNode, cbNodes, (<DefaultClause>node).statements);
|
||||
case SyntaxKind.LabeledStatement:
|
||||
return visitNode(cbNode, (<LabeledStatement>node).label) ||
|
||||
visitNode(cbNode, (<LabeledStatement>node).statement);
|
||||
@@ -286,46 +276,46 @@ namespace ts {
|
||||
return visitNode(cbNode, (<Decorator>node).expression);
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<ClassLikeDeclaration>node).name) ||
|
||||
visitNodes(cbNodes, (<ClassLikeDeclaration>node).typeParameters) ||
|
||||
visitNodes(cbNodes, (<ClassLikeDeclaration>node).heritageClauses) ||
|
||||
visitNodes(cbNodes, (<ClassLikeDeclaration>node).members);
|
||||
visitNodes(cbNode, cbNodes, (<ClassLikeDeclaration>node).typeParameters) ||
|
||||
visitNodes(cbNode, cbNodes, (<ClassLikeDeclaration>node).heritageClauses) ||
|
||||
visitNodes(cbNode, cbNodes, (<ClassLikeDeclaration>node).members);
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<InterfaceDeclaration>node).name) ||
|
||||
visitNodes(cbNodes, (<InterfaceDeclaration>node).typeParameters) ||
|
||||
visitNodes(cbNodes, (<ClassDeclaration>node).heritageClauses) ||
|
||||
visitNodes(cbNodes, (<InterfaceDeclaration>node).members);
|
||||
visitNodes(cbNode, cbNodes, (<InterfaceDeclaration>node).typeParameters) ||
|
||||
visitNodes(cbNode, cbNodes, (<ClassDeclaration>node).heritageClauses) ||
|
||||
visitNodes(cbNode, cbNodes, (<InterfaceDeclaration>node).members);
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<TypeAliasDeclaration>node).name) ||
|
||||
visitNodes(cbNodes, (<TypeAliasDeclaration>node).typeParameters) ||
|
||||
visitNodes(cbNode, cbNodes, (<TypeAliasDeclaration>node).typeParameters) ||
|
||||
visitNode(cbNode, (<TypeAliasDeclaration>node).type);
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<EnumDeclaration>node).name) ||
|
||||
visitNodes(cbNodes, (<EnumDeclaration>node).members);
|
||||
visitNodes(cbNode, cbNodes, (<EnumDeclaration>node).members);
|
||||
case SyntaxKind.EnumMember:
|
||||
return visitNode(cbNode, (<EnumMember>node).name) ||
|
||||
visitNode(cbNode, (<EnumMember>node).initializer);
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<ModuleDeclaration>node).name) ||
|
||||
visitNode(cbNode, (<ModuleDeclaration>node).body);
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<ImportEqualsDeclaration>node).name) ||
|
||||
visitNode(cbNode, (<ImportEqualsDeclaration>node).moduleReference);
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<ImportDeclaration>node).importClause) ||
|
||||
visitNode(cbNode, (<ImportDeclaration>node).moduleSpecifier);
|
||||
case SyntaxKind.ImportClause:
|
||||
@@ -338,10 +328,10 @@ namespace ts {
|
||||
return visitNode(cbNode, (<NamespaceImport>node).name);
|
||||
case SyntaxKind.NamedImports:
|
||||
case SyntaxKind.NamedExports:
|
||||
return visitNodes(cbNodes, (<NamedImportsOrExports>node).elements);
|
||||
return visitNodes(cbNode, cbNodes, (<NamedImportsOrExports>node).elements);
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<ExportDeclaration>node).exportClause) ||
|
||||
visitNode(cbNode, (<ExportDeclaration>node).moduleSpecifier);
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
@@ -349,37 +339,37 @@ namespace ts {
|
||||
return visitNode(cbNode, (<ImportOrExportSpecifier>node).propertyName) ||
|
||||
visitNode(cbNode, (<ImportOrExportSpecifier>node).name);
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
visitNodes(cbNodes, node.modifiers) ||
|
||||
return visitNodes(cbNode, cbNodes, node.decorators) ||
|
||||
visitNodes(cbNode, cbNodes, node.modifiers) ||
|
||||
visitNode(cbNode, (<ExportAssignment>node).expression);
|
||||
case SyntaxKind.TemplateExpression:
|
||||
return visitNode(cbNode, (<TemplateExpression>node).head) || visitNodes(cbNodes, (<TemplateExpression>node).templateSpans);
|
||||
return visitNode(cbNode, (<TemplateExpression>node).head) || visitNodes(cbNode, cbNodes, (<TemplateExpression>node).templateSpans);
|
||||
case SyntaxKind.TemplateSpan:
|
||||
return visitNode(cbNode, (<TemplateSpan>node).expression) || visitNode(cbNode, (<TemplateSpan>node).literal);
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
return visitNode(cbNode, (<ComputedPropertyName>node).expression);
|
||||
case SyntaxKind.HeritageClause:
|
||||
return visitNodes(cbNodes, (<HeritageClause>node).types);
|
||||
return visitNodes(cbNode, cbNodes, (<HeritageClause>node).types);
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return visitNode(cbNode, (<ExpressionWithTypeArguments>node).expression) ||
|
||||
visitNodes(cbNodes, (<ExpressionWithTypeArguments>node).typeArguments);
|
||||
visitNodes(cbNode, cbNodes, (<ExpressionWithTypeArguments>node).typeArguments);
|
||||
case SyntaxKind.ExternalModuleReference:
|
||||
return visitNode(cbNode, (<ExternalModuleReference>node).expression);
|
||||
case SyntaxKind.MissingDeclaration:
|
||||
return visitNodes(cbNodes, node.decorators);
|
||||
return visitNodes(cbNode, cbNodes, node.decorators);
|
||||
case SyntaxKind.CommaListExpression:
|
||||
return visitNodes(cbNodes, (<CommaListExpression>node).elements);
|
||||
return visitNodes(cbNode, cbNodes, (<CommaListExpression>node).elements);
|
||||
|
||||
case SyntaxKind.JsxElement:
|
||||
return visitNode(cbNode, (<JsxElement>node).openingElement) ||
|
||||
visitNodes(cbNodes, (<JsxElement>node).children) ||
|
||||
visitNodes(cbNode, cbNodes, (<JsxElement>node).children) ||
|
||||
visitNode(cbNode, (<JsxElement>node).closingElement);
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
return visitNode(cbNode, (<JsxOpeningLikeElement>node).tagName) ||
|
||||
visitNode(cbNode, (<JsxOpeningLikeElement>node).attributes);
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return visitNodes(cbNodes, (<JsxAttributes>node).properties);
|
||||
return visitNodes(cbNode, cbNodes, (<JsxAttributes>node).properties);
|
||||
case SyntaxKind.JsxAttribute:
|
||||
return visitNode(cbNode, (<JsxAttribute>node).name) ||
|
||||
visitNode(cbNode, (<JsxAttribute>node).initializer);
|
||||
@@ -394,9 +384,9 @@ namespace ts {
|
||||
case SyntaxKind.JSDocTypeExpression:
|
||||
return visitNode(cbNode, (<JSDocTypeExpression>node).type);
|
||||
case SyntaxKind.JSDocUnionType:
|
||||
return visitNodes(cbNodes, (<JSDocUnionType>node).types);
|
||||
return visitNodes(cbNode, cbNodes, (<JSDocUnionType>node).types);
|
||||
case SyntaxKind.JSDocTupleType:
|
||||
return visitNodes(cbNodes, (<JSDocTupleType>node).types);
|
||||
return visitNodes(cbNode, cbNodes, (<JSDocTupleType>node).types);
|
||||
case SyntaxKind.JSDocArrayType:
|
||||
return visitNode(cbNode, (<JSDocArrayType>node).elementType);
|
||||
case SyntaxKind.JSDocNonNullableType:
|
||||
@@ -407,11 +397,11 @@ namespace ts {
|
||||
return visitNode(cbNode, (<JSDocRecordType>node).literal);
|
||||
case SyntaxKind.JSDocTypeReference:
|
||||
return visitNode(cbNode, (<JSDocTypeReference>node).name) ||
|
||||
visitNodes(cbNodes, (<JSDocTypeReference>node).typeArguments);
|
||||
visitNodes(cbNode, cbNodes, (<JSDocTypeReference>node).typeArguments);
|
||||
case SyntaxKind.JSDocOptionalType:
|
||||
return visitNode(cbNode, (<JSDocOptionalType>node).type);
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
return visitNodes(cbNodes, (<JSDocFunctionType>node).parameters) ||
|
||||
return visitNodes(cbNode, cbNodes, (<JSDocFunctionType>node).parameters) ||
|
||||
visitNode(cbNode, (<JSDocFunctionType>node).type);
|
||||
case SyntaxKind.JSDocVariadicType:
|
||||
return visitNode(cbNode, (<JSDocVariadicType>node).type);
|
||||
@@ -423,7 +413,7 @@ namespace ts {
|
||||
return visitNode(cbNode, (<JSDocRecordMember>node).name) ||
|
||||
visitNode(cbNode, (<JSDocRecordMember>node).type);
|
||||
case SyntaxKind.JSDocComment:
|
||||
return visitNodes(cbNodes, (<JSDoc>node).tags);
|
||||
return visitNodes(cbNode, cbNodes, (<JSDoc>node).tags);
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
return visitNode(cbNode, (<JSDocParameterTag>node).preParameterName) ||
|
||||
visitNode(cbNode, (<JSDocParameterTag>node).typeExpression) ||
|
||||
@@ -435,14 +425,14 @@ namespace ts {
|
||||
case SyntaxKind.JSDocAugmentsTag:
|
||||
return visitNode(cbNode, (<JSDocAugmentsTag>node).typeExpression);
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
return visitNodes(cbNodes, (<JSDocTemplateTag>node).typeParameters);
|
||||
return visitNodes(cbNode, cbNodes, (<JSDocTemplateTag>node).typeParameters);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression) ||
|
||||
visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
|
||||
visitNode(cbNode, (<JSDocTypedefTag>node).name) ||
|
||||
visitNode(cbNode, (<JSDocTypedefTag>node).jsDocTypeLiteral);
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
return visitNodes(cbNodes, (<JSDocTypeLiteral>node).jsDocPropertyTags);
|
||||
return visitNodes(cbNode, cbNodes, (<JSDocTypeLiteral>node).jsDocPropertyTags);
|
||||
case SyntaxKind.JSDocPropertyTag:
|
||||
return visitNode(cbNode, (<JSDocPropertyTag>node).typeExpression) ||
|
||||
visitNode(cbNode, (<JSDocPropertyTag>node).name);
|
||||
|
||||
+21
-15
@@ -441,7 +441,7 @@ namespace ts {
|
||||
const supportedExtensions = getSupportedExtensions(options);
|
||||
|
||||
// Map storing if there is emit blocking diagnostics for given input
|
||||
const hasEmitBlockingDiagnostics = createFileMap<boolean>(getCanonicalFileName);
|
||||
const hasEmitBlockingDiagnostics = createMap<boolean>();
|
||||
let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression;
|
||||
|
||||
let moduleResolutionCache: ModuleResolutionCache;
|
||||
@@ -475,7 +475,7 @@ namespace ts {
|
||||
const filesByName = createMap<SourceFile | undefined>();
|
||||
// stores 'filename -> file association' ignoring case
|
||||
// used to track cases when two file names differ only in casing
|
||||
const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createFileMap<SourceFile>(fileName => fileName.toLowerCase()) : undefined;
|
||||
const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createMap<SourceFile>() : undefined;
|
||||
|
||||
const structuralIsReused = tryReuseStructureFromOldProgram();
|
||||
if (structuralIsReused !== StructureIsReused.Completely) {
|
||||
@@ -556,6 +556,10 @@ namespace ts {
|
||||
|
||||
return program;
|
||||
|
||||
function toPath(fileName: string): Path {
|
||||
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
function getCommonSourceDirectory() {
|
||||
if (commonSourceDirectory === undefined) {
|
||||
const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary));
|
||||
@@ -934,7 +938,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isEmitBlocked(emitFileName: string): boolean {
|
||||
return hasEmitBlockingDiagnostics.contains(toPath(emitFileName, currentDirectory, getCanonicalFileName));
|
||||
return hasEmitBlockingDiagnostics.has(toPath(emitFileName));
|
||||
}
|
||||
|
||||
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
|
||||
@@ -993,7 +997,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string): SourceFile {
|
||||
return getSourceFileByPath(toPath(fileName, currentDirectory, getCanonicalFileName));
|
||||
return getSourceFileByPath(toPath(fileName));
|
||||
}
|
||||
|
||||
function getSourceFileByPath(path: Path): SourceFile {
|
||||
@@ -1484,7 +1488,7 @@ namespace ts {
|
||||
|
||||
/** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */
|
||||
function getSourceFileFromReference(referencingFile: SourceFile, ref: FileReference): SourceFile | undefined {
|
||||
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), fileName => filesByName.get(toPath(fileName, currentDirectory, getCanonicalFileName)));
|
||||
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), fileName => filesByName.get(toPath(fileName)));
|
||||
}
|
||||
|
||||
function getSourceFileFromReferenceWorker(
|
||||
@@ -1528,7 +1532,7 @@ namespace ts {
|
||||
/** This has side effects through `findSourceFile`. */
|
||||
function processSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): void {
|
||||
getSourceFileFromReferenceWorker(fileName,
|
||||
fileName => findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd),
|
||||
fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, refFile, refPos, refEnd),
|
||||
(diagnostic, ...args) => {
|
||||
fileProcessingDiagnostics.add(refFile !== undefined && refEnd !== undefined && refPos !== undefined
|
||||
? createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...args)
|
||||
@@ -1597,13 +1601,14 @@ namespace ts {
|
||||
file.path = path;
|
||||
|
||||
if (host.useCaseSensitiveFileNames()) {
|
||||
const pathLowerCase = path.toLowerCase();
|
||||
// for case-sensitive file systems check if we've already seen some file with similar filename ignoring case
|
||||
const existingFile = filesByNameIgnoreCase.get(path);
|
||||
const existingFile = filesByNameIgnoreCase.get(pathLowerCase);
|
||||
if (existingFile) {
|
||||
reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd);
|
||||
}
|
||||
else {
|
||||
filesByNameIgnoreCase.set(path, file);
|
||||
filesByNameIgnoreCase.set(pathLowerCase, file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1750,7 +1755,7 @@ namespace ts {
|
||||
modulesWithElidedImports.set(file.path, true);
|
||||
}
|
||||
else if (shouldAddFile) {
|
||||
const path = toPath(resolvedFileName, currentDirectory, getCanonicalFileName);
|
||||
const path = toPath(resolvedFileName);
|
||||
const pos = skipTrivia(file.text, file.imports[i].pos);
|
||||
findSourceFile(resolvedFileName, path, /*isDefaultLib*/ false, file, pos, file.imports[i].end);
|
||||
}
|
||||
@@ -1969,7 +1974,7 @@ namespace ts {
|
||||
// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
|
||||
if (!options.noEmit && !options.suppressOutputPathCheck) {
|
||||
const emitHost = getEmitHost();
|
||||
const emitFilesSeen = createFileMap<boolean>(!host.useCaseSensitiveFileNames() ? key => key.toLocaleLowerCase() : key => key);
|
||||
const emitFilesSeen = createMap<true>();
|
||||
forEachEmittedFile(emitHost, (emitFileNames) => {
|
||||
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
|
||||
verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen);
|
||||
@@ -1977,9 +1982,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Verify that all the emit files are unique and don't overwrite input files
|
||||
function verifyEmitFilePath(emitFileName: string, emitFilesSeen: FileMap<boolean>) {
|
||||
function verifyEmitFilePath(emitFileName: string, emitFilesSeen: Map<true>) {
|
||||
if (emitFileName) {
|
||||
const emitFilePath = toPath(emitFileName, currentDirectory, getCanonicalFileName);
|
||||
const emitFilePath = toPath(emitFileName);
|
||||
// Report error if the output overwrites input file
|
||||
if (filesByName.has(emitFilePath)) {
|
||||
let chain: DiagnosticMessageChain;
|
||||
@@ -1991,13 +1996,14 @@ namespace ts {
|
||||
blockEmittingOfFile(emitFileName, createCompilerDiagnosticFromMessageChain(chain));
|
||||
}
|
||||
|
||||
const emitFileKey = !host.useCaseSensitiveFileNames() ? emitFilePath.toLocaleLowerCase() : emitFilePath;
|
||||
// Report error if multiple files write into same file
|
||||
if (emitFilesSeen.contains(emitFilePath)) {
|
||||
if (emitFilesSeen.has(emitFileKey)) {
|
||||
// Already seen the same emit file - report error
|
||||
blockEmittingOfFile(emitFileName, createCompilerDiagnostic(Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, emitFileName));
|
||||
}
|
||||
else {
|
||||
emitFilesSeen.set(emitFilePath, true);
|
||||
emitFilesSeen.set(emitFileKey, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2089,7 +2095,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function blockEmittingOfFile(emitFileName: string, diag: Diagnostic) {
|
||||
hasEmitBlockingDiagnostics.set(toPath(emitFileName, currentDirectory, getCanonicalFileName), true);
|
||||
hasEmitBlockingDiagnostics.set(toPath(emitFileName), true);
|
||||
programDiagnostics.add(diag);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-13
@@ -31,17 +31,6 @@ namespace ts {
|
||||
// arbitrary file name can be converted to Path via toPath function
|
||||
export type Path = string & { __pathBrand: any };
|
||||
|
||||
export interface FileMap<T> {
|
||||
get(fileName: Path): T;
|
||||
set(fileName: Path, value: T): void;
|
||||
contains(fileName: Path): boolean;
|
||||
remove(fileName: Path): void;
|
||||
|
||||
forEachValue(f: (key: Path, v: T) => void): void;
|
||||
getKeys(): Path[];
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
export interface TextRange {
|
||||
pos: number;
|
||||
end: number;
|
||||
@@ -527,7 +516,7 @@ namespace ts {
|
||||
/* @internal */ original?: Node; // The original node if this is an updated node.
|
||||
/* @internal */ startsOnNewLine?: boolean; // Whether a synthesized node should start on a new line (used by transforms).
|
||||
/* @internal */ jsDoc?: JSDoc[]; // JSDoc that directly precedes this node
|
||||
/* @internal */ jsDocCache?: (JSDoc | JSDocTag)[]; // All JSDoc that applies to the node, including parent docs and @param tags
|
||||
/* @internal */ jsDocCache?: JSDocTag[]; // Cache for getJSDocTags
|
||||
/* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding)
|
||||
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
|
||||
/* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)
|
||||
@@ -4350,7 +4339,7 @@ namespace ts {
|
||||
*/
|
||||
export type Visitor = (node: Node) => VisitResult<Node>;
|
||||
|
||||
export type VisitResult<T extends Node> = T | T[];
|
||||
export type VisitResult<T extends Node> = T | T[] | undefined;
|
||||
|
||||
export interface Printer {
|
||||
/**
|
||||
|
||||
+44
-36
@@ -2,6 +2,8 @@
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export const emptyArray: never[] = [] as never[];
|
||||
|
||||
export const externalHelpersModuleNameText = "tslib";
|
||||
|
||||
export interface ReferencePathMatchResult {
|
||||
@@ -1445,39 +1447,37 @@ namespace ts {
|
||||
(<JSDocFunctionType>node).parameters[0].type.kind === SyntaxKind.JSDocConstructorType;
|
||||
}
|
||||
|
||||
export function getCommentsFromJSDoc(node: Node): string[] {
|
||||
return map(getJSDocs(node), doc => doc.comment);
|
||||
export function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration): boolean {
|
||||
return !!getFirstJSDocTag(node, SyntaxKind.JSDocParameterTag);
|
||||
}
|
||||
|
||||
export function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration) {
|
||||
const parameterTags = getJSDocTags(node, SyntaxKind.JSDocParameterTag);
|
||||
return parameterTags && parameterTags.length > 0;
|
||||
function getFirstJSDocTag(node: Node, kind: SyntaxKind): JSDocTag | undefined {
|
||||
const tags = getJSDocTags(node);
|
||||
return find(tags, doc => doc.kind === kind);
|
||||
}
|
||||
|
||||
function getJSDocTags(node: Node, kind: SyntaxKind): JSDocTag[] {
|
||||
return flatMap(getJSDocs(node), doc =>
|
||||
doc.kind === SyntaxKind.JSDocComment
|
||||
? filter((doc as JSDoc).tags, tag => tag.kind === kind)
|
||||
: doc.kind === kind && doc);
|
||||
}
|
||||
|
||||
function getFirstJSDocTag(node: Node, kind: SyntaxKind): JSDocTag {
|
||||
return node && firstOrUndefined(getJSDocTags(node, kind));
|
||||
}
|
||||
|
||||
export function getJSDocs(node: Node): (JSDoc | JSDocTag)[] {
|
||||
export function getAllJSDocs(node: Node): (JSDoc | JSDocTag)[] {
|
||||
if (isJSDocTypedefTag(node)) {
|
||||
return [node.parent];
|
||||
}
|
||||
return getJSDocCommentsAndTags(node);
|
||||
}
|
||||
|
||||
let cache: (JSDoc | JSDocTag)[] = node.jsDocCache;
|
||||
if (!cache) {
|
||||
getJSDocsWorker(node);
|
||||
node.jsDocCache = cache;
|
||||
export function getJSDocTags(node: Node): JSDocTag[] | undefined {
|
||||
let tags = node.jsDocCache;
|
||||
// If cache is 'null', that means we did the work of searching for JSDoc tags and came up with nothing.
|
||||
if (tags === undefined) {
|
||||
node.jsDocCache = tags = flatMap(getJSDocCommentsAndTags(node), j => isJSDoc(j) ? j.tags : j);
|
||||
}
|
||||
return cache;
|
||||
return tags;
|
||||
}
|
||||
|
||||
function getJSDocsWorker(node: Node) {
|
||||
function getJSDocCommentsAndTags(node: Node): (JSDoc | JSDocTag)[] {
|
||||
let result: Array<JSDoc | JSDocTag> | undefined;
|
||||
getJSDocCommentsAndTagsWorker(node);
|
||||
return result || emptyArray;
|
||||
|
||||
function getJSDocCommentsAndTagsWorker(node: Node): void {
|
||||
const parent = node.parent;
|
||||
// Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement.
|
||||
// /**
|
||||
@@ -1496,7 +1496,7 @@ namespace ts {
|
||||
isVariableOfVariableDeclarationStatement ? parent.parent :
|
||||
undefined;
|
||||
if (variableStatementNode) {
|
||||
getJSDocsWorker(variableStatementNode);
|
||||
getJSDocCommentsAndTagsWorker(variableStatementNode);
|
||||
}
|
||||
|
||||
// Also recognize when the node is the RHS of an assignment expression
|
||||
@@ -1506,43 +1506,51 @@ namespace ts {
|
||||
(parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken &&
|
||||
parent.parent.kind === SyntaxKind.ExpressionStatement;
|
||||
if (isSourceOfAssignmentExpressionStatement) {
|
||||
getJSDocsWorker(parent.parent);
|
||||
getJSDocCommentsAndTagsWorker(parent.parent);
|
||||
}
|
||||
|
||||
const isModuleDeclaration = node.kind === SyntaxKind.ModuleDeclaration &&
|
||||
parent && parent.kind === SyntaxKind.ModuleDeclaration;
|
||||
const isPropertyAssignmentExpression = parent && parent.kind === SyntaxKind.PropertyAssignment;
|
||||
if (isModuleDeclaration || isPropertyAssignmentExpression) {
|
||||
getJSDocsWorker(parent);
|
||||
getJSDocCommentsAndTagsWorker(parent);
|
||||
}
|
||||
|
||||
// Pull parameter comments from declaring function as well
|
||||
if (node.kind === SyntaxKind.Parameter) {
|
||||
cache = concatenate(cache, getJSDocParameterTags(node as ParameterDeclaration));
|
||||
result = addRange(result, getJSDocParameterTags(node as ParameterDeclaration));
|
||||
}
|
||||
|
||||
if (isVariableLike(node) && node.initializer) {
|
||||
cache = concatenate(cache, node.initializer.jsDoc);
|
||||
result = addRange(result, node.initializer.jsDoc);
|
||||
}
|
||||
|
||||
cache = concatenate(cache, node.jsDoc);
|
||||
result = addRange(result, node.jsDoc);
|
||||
}
|
||||
}
|
||||
|
||||
export function getJSDocParameterTags(param: ParameterDeclaration): JSDocParameterTag[] {
|
||||
export function getJSDocParameterTags(param: ParameterDeclaration): JSDocParameterTag[] | undefined {
|
||||
const func = param.parent;
|
||||
const tags = getJSDocTags(func, SyntaxKind.JSDocParameterTag) as JSDocParameterTag[];
|
||||
const tags = getJSDocTags(func);
|
||||
if (!tags) return undefined;
|
||||
|
||||
if (!param.name) {
|
||||
// this is an anonymous jsdoc param from a `function(type1, type2): type3` specification
|
||||
const i = func.parameters.indexOf(param);
|
||||
const paramTags = filter(tags, tag => tag.kind === SyntaxKind.JSDocParameterTag);
|
||||
if (paramTags && 0 <= i && i < paramTags.length) {
|
||||
return [paramTags[i]];
|
||||
const paramIndex = func.parameters.indexOf(param);
|
||||
Debug.assert(paramIndex !== -1);
|
||||
let curParamIndex = 0;
|
||||
for (const tag of tags) {
|
||||
if (isJSDocParameterTag(tag)) {
|
||||
if (curParamIndex === paramIndex) {
|
||||
return [tag];
|
||||
}
|
||||
curParamIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (param.name.kind === SyntaxKind.Identifier) {
|
||||
const name = (param.name as Identifier).text;
|
||||
return filter(tags, tag => tag.kind === SyntaxKind.JSDocParameterTag && tag.name.text === name);
|
||||
return tags.filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && tag.name.text === name) as JSDocParameterTag[];
|
||||
}
|
||||
else {
|
||||
// TODO: it's a destructured parameter, so it should look up an "object type" series of multiple lines
|
||||
|
||||
@@ -7,8 +7,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function lineColToPosition(lineIndex: server.LineIndex, line: number, col: number) {
|
||||
const lineInfo = lineIndex.lineNumberToInfo(line);
|
||||
return (lineInfo.offset + col - 1);
|
||||
return lineIndex.absolutePositionOfStartOfLine(line) + (col - 1);
|
||||
}
|
||||
|
||||
function validateEdit(lineIndex: server.LineIndex, sourceText: string, position: number, deleteLength: number, insertString: string): void {
|
||||
@@ -298,20 +297,17 @@ and grew 1cm per day`;
|
||||
|
||||
it("Line/offset from pos", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
const lp = lineIndex.charOffsetToLineNumberAndPos(rsa[i]);
|
||||
const lp = lineIndex.positionToLineOffset(rsa[i]);
|
||||
const lac = ts.computeLineAndCharacterOfPosition(lineMap, rsa[i]);
|
||||
assert.equal(lac.line + 1, lp.line, "Line number mismatch " + (lac.line + 1) + " " + lp.line + " " + i);
|
||||
assert.equal(lac.character, (lp.offset), "Charachter offset mismatch " + lac.character + " " + lp.offset + " " + i);
|
||||
assert.equal(lac.character, lp.offset - 1, "Character offset mismatch " + lac.character + " " + (lp.offset - 1) + " " + i);
|
||||
}
|
||||
});
|
||||
|
||||
it("Start pos from line", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
for (let j = 0; j < lines.length; j++) {
|
||||
const lineInfo = lineIndex.lineNumberToInfo(j + 1);
|
||||
const lineIndexOffset = lineInfo.offset;
|
||||
const lineMapOffset = lineMap[j];
|
||||
assert.equal(lineIndexOffset, lineMapOffset);
|
||||
assert.equal(lineIndex.absolutePositionOfStartOfLine(j + 1), lineMap[j]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -640,7 +640,7 @@ namespace ts.server.protocol {
|
||||
}
|
||||
|
||||
/**
|
||||
* Location in source code expressed as (one-based) line and character offset.
|
||||
* Location in source code expressed as (one-based) line and (one-based) column offset.
|
||||
*/
|
||||
export interface Location {
|
||||
line: number;
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace ts.server {
|
||||
: ScriptSnapshot.fromString(this.getOrLoadText());
|
||||
}
|
||||
|
||||
public getLineInfo(line: number) {
|
||||
public getLineInfo(line: number): AbsolutePositionAndLineText {
|
||||
return this.switchToScriptVersionCache().getSnapshot().index.lineNumberToInfo(line);
|
||||
}
|
||||
/**
|
||||
@@ -75,16 +75,9 @@ namespace ts.server {
|
||||
return ts.createTextSpanFromBounds(start, end);
|
||||
}
|
||||
const index = this.svc.getSnapshot().index;
|
||||
const lineInfo = index.lineNumberToInfo(line + 1);
|
||||
let len: number;
|
||||
if (lineInfo.leaf) {
|
||||
len = lineInfo.leaf.text.length;
|
||||
}
|
||||
else {
|
||||
const nextLineInfo = index.lineNumberToInfo(line + 2);
|
||||
len = nextLineInfo.offset - lineInfo.offset;
|
||||
}
|
||||
return ts.createTextSpan(lineInfo.offset, len);
|
||||
const { lineText, absolutePosition } = index.lineNumberToInfo(line + 1);
|
||||
const len = lineText !== undefined ? lineText.length : index.absolutePositionOfStartOfLine(line + 2) - absolutePosition;
|
||||
return ts.createTextSpan(absolutePosition, len);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,25 +88,17 @@ namespace ts.server {
|
||||
if (!this.svc) {
|
||||
return computePositionOfLineAndCharacter(this.getLineMap(), line - 1, offset - 1);
|
||||
}
|
||||
const index = this.svc.getSnapshot().index;
|
||||
|
||||
const lineInfo = index.lineNumberToInfo(line);
|
||||
// TODO: assert this offset is actually on the line
|
||||
return (lineInfo.offset + offset - 1);
|
||||
return this.svc.getSnapshot().index.absolutePositionOfStartOfLine(line) + (offset - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param line 1-based index
|
||||
* @param offset 1-based index
|
||||
*/
|
||||
positionToLineOffset(position: number): ILineInfo {
|
||||
positionToLineOffset(position: number): protocol.Location {
|
||||
if (!this.svc) {
|
||||
const { line, character } = computeLineAndCharacterOfPosition(this.getLineMap(), position);
|
||||
return { line: line + 1, offset: character + 1 };
|
||||
}
|
||||
const index = this.svc.getSnapshot().index;
|
||||
const lineOffset = index.charOffsetToLineNumberAndPos(position);
|
||||
return { line: lineOffset.line, offset: lineOffset.offset + 1 };
|
||||
return this.svc.getSnapshot().index.positionToLineOffset(position);
|
||||
}
|
||||
|
||||
private getFileText(tempFileName?: string) {
|
||||
@@ -334,7 +319,7 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
getLineInfo(line: number) {
|
||||
getLineInfo(line: number): AbsolutePositionAndLineText {
|
||||
return this.textStorage.getLineInfo(line);
|
||||
}
|
||||
|
||||
@@ -364,11 +349,7 @@ namespace ts.server {
|
||||
return this.textStorage.lineOffsetToPosition(line, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param line 1-based index
|
||||
* @param offset 1-based index
|
||||
*/
|
||||
positionToLineOffset(position: number): ILineInfo {
|
||||
positionToLineOffset(position: number): protocol.Location {
|
||||
return this.textStorage.positionToLineOffset(position);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,15 +8,13 @@ namespace ts.server {
|
||||
export interface LineCollection {
|
||||
charCount(): number;
|
||||
lineCount(): number;
|
||||
isLeaf(): boolean;
|
||||
isLeaf(): this is LineLeaf;
|
||||
walk(rangeStart: number, rangeLength: number, walkFns: ILineIndexWalker): void;
|
||||
}
|
||||
|
||||
export interface ILineInfo {
|
||||
line: number;
|
||||
offset: number;
|
||||
text?: string;
|
||||
leaf?: LineLeaf;
|
||||
export interface AbsolutePositionAndLineText {
|
||||
absolutePosition: number;
|
||||
lineText: string | undefined;
|
||||
}
|
||||
|
||||
export enum CharRangeSection {
|
||||
@@ -397,22 +395,27 @@ namespace ts.server {
|
||||
// set this to true to check each edit for accuracy
|
||||
checkEdits = false;
|
||||
|
||||
charOffsetToLineNumberAndPos(charOffset: number) {
|
||||
return this.root.charOffsetToLineNumberAndPos(1, charOffset);
|
||||
absolutePositionOfStartOfLine(oneBasedLine: number): number {
|
||||
return this.lineNumberToInfo(oneBasedLine).absolutePosition;
|
||||
}
|
||||
|
||||
lineNumberToInfo(lineNumber: number): ILineInfo {
|
||||
positionToLineOffset(position: number): protocol.Location {
|
||||
const { oneBasedLine, zeroBasedColumn } = this.root.charOffsetToLineInfo(1, position);
|
||||
return { line: oneBasedLine, offset: zeroBasedColumn + 1 };
|
||||
}
|
||||
|
||||
private positionToColumnAndLineText(position: number): { zeroBasedColumn: number, lineText: string } {
|
||||
return this.root.charOffsetToLineInfo(1, position);
|
||||
}
|
||||
|
||||
lineNumberToInfo(oneBasedLine: number): AbsolutePositionAndLineText {
|
||||
const lineCount = this.root.lineCount();
|
||||
if (lineNumber <= lineCount) {
|
||||
const lineInfo = this.root.lineNumberToInfo(lineNumber, 0);
|
||||
lineInfo.line = lineNumber;
|
||||
return lineInfo;
|
||||
if (oneBasedLine <= lineCount) {
|
||||
const { position, leaf } = this.root.lineNumberToInfo(oneBasedLine, 0);
|
||||
return { absolutePosition: position, lineText: leaf && leaf.text };
|
||||
}
|
||||
else {
|
||||
return {
|
||||
line: lineNumber,
|
||||
offset: this.root.charCount()
|
||||
};
|
||||
return { absolutePosition: this.root.charCount(), lineText: undefined };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,17 +505,12 @@ namespace ts.server {
|
||||
else if (deleteLength > 0) {
|
||||
// check whether last characters deleted are line break
|
||||
const e = pos + deleteLength;
|
||||
const lineInfo = this.charOffsetToLineNumberAndPos(e);
|
||||
if ((lineInfo && (lineInfo.offset === 0))) {
|
||||
const { zeroBasedColumn, lineText } = this.positionToColumnAndLineText(e);
|
||||
if (zeroBasedColumn === 0) {
|
||||
// move range end just past line that will merge with previous line
|
||||
deleteLength += lineInfo.text.length;
|
||||
deleteLength += lineText.length;
|
||||
// store text by appending to end of insertedText
|
||||
if (newText) {
|
||||
newText = newText + lineInfo.text;
|
||||
}
|
||||
else {
|
||||
newText = lineInfo.text;
|
||||
}
|
||||
newText = newText ? newText + lineText : lineText;
|
||||
}
|
||||
}
|
||||
if (pos < this.root.charCount()) {
|
||||
@@ -676,90 +674,88 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
charOffsetToLineNumberAndPos(lineNumber: number, charOffset: number): ILineInfo {
|
||||
const childInfo = this.childFromCharOffset(lineNumber, charOffset);
|
||||
// Input position is relative to the start of this node.
|
||||
// Output line number is absolute.
|
||||
charOffsetToLineInfo(lineNumberAccumulator: number, relativePosition: number): { oneBasedLine: number, zeroBasedColumn: number, lineText: string | undefined } {
|
||||
const childInfo = this.childFromCharOffset(lineNumberAccumulator, relativePosition);
|
||||
if (!childInfo.child) {
|
||||
return {
|
||||
line: lineNumber,
|
||||
offset: charOffset,
|
||||
oneBasedLine: lineNumberAccumulator,
|
||||
zeroBasedColumn: relativePosition,
|
||||
lineText: undefined,
|
||||
};
|
||||
}
|
||||
else if (childInfo.childIndex < this.children.length) {
|
||||
if (childInfo.child.isLeaf()) {
|
||||
return {
|
||||
line: childInfo.lineNumber,
|
||||
offset: childInfo.charOffset,
|
||||
text: (<LineLeaf>(childInfo.child)).text,
|
||||
leaf: (<LineLeaf>(childInfo.child))
|
||||
oneBasedLine: childInfo.lineNumberAccumulator,
|
||||
zeroBasedColumn: childInfo.relativePosition,
|
||||
lineText: childInfo.child.text,
|
||||
};
|
||||
}
|
||||
else {
|
||||
const lineNode = <LineNode>(childInfo.child);
|
||||
return lineNode.charOffsetToLineNumberAndPos(childInfo.lineNumber, childInfo.charOffset);
|
||||
return lineNode.charOffsetToLineInfo(childInfo.lineNumberAccumulator, childInfo.relativePosition);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const lineInfo = this.lineNumberToInfo(this.lineCount(), 0);
|
||||
return { line: this.lineCount(), offset: lineInfo.leaf.charCount() };
|
||||
return { oneBasedLine: this.lineCount(), zeroBasedColumn: lineInfo.leaf.charCount(), lineText: undefined };
|
||||
}
|
||||
}
|
||||
|
||||
lineNumberToInfo(lineNumber: number, charOffset: number): ILineInfo {
|
||||
const childInfo = this.childFromLineNumber(lineNumber, charOffset);
|
||||
lineNumberToInfo(relativeOneBasedLine: number, positionAccumulator: number): { position: number, leaf: LineLeaf | undefined } {
|
||||
const childInfo = this.childFromLineNumber(relativeOneBasedLine, positionAccumulator);
|
||||
if (!childInfo.child) {
|
||||
return {
|
||||
line: lineNumber,
|
||||
offset: charOffset
|
||||
};
|
||||
return { position: positionAccumulator, leaf: undefined };
|
||||
}
|
||||
else if (childInfo.child.isLeaf()) {
|
||||
return {
|
||||
line: lineNumber,
|
||||
offset: childInfo.charOffset,
|
||||
text: (<LineLeaf>(childInfo.child)).text,
|
||||
leaf: (<LineLeaf>(childInfo.child))
|
||||
};
|
||||
return { position: childInfo.positionAccumulator, leaf: childInfo.child };
|
||||
}
|
||||
else {
|
||||
const lineNode = <LineNode>(childInfo.child);
|
||||
return lineNode.lineNumberToInfo(childInfo.relativeLineNumber, childInfo.charOffset);
|
||||
return lineNode.lineNumberToInfo(childInfo.relativeOneBasedLine, childInfo.positionAccumulator);
|
||||
}
|
||||
}
|
||||
|
||||
childFromLineNumber(lineNumber: number, charOffset: number) {
|
||||
/**
|
||||
* Input line number is relative to the start of this node.
|
||||
* Output line number is relative to the child.
|
||||
* positionAccumulator will be an absolute position once relativeLineNumber reaches 0.
|
||||
*/
|
||||
private childFromLineNumber(relativeOneBasedLine: number, positionAccumulator: number): { child: LineCollection, relativeOneBasedLine: number, positionAccumulator: number } {
|
||||
let child: LineCollection;
|
||||
let relativeLineNumber = lineNumber;
|
||||
let i: number;
|
||||
let len: number;
|
||||
for (i = 0, len = this.children.length; i < len; i++) {
|
||||
for (i = 0; i < this.children.length; i++) {
|
||||
child = this.children[i];
|
||||
const childLineCount = child.lineCount();
|
||||
if (childLineCount >= relativeLineNumber) {
|
||||
if (childLineCount >= relativeOneBasedLine) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
relativeLineNumber -= childLineCount;
|
||||
charOffset += child.charCount();
|
||||
relativeOneBasedLine -= childLineCount;
|
||||
positionAccumulator += child.charCount();
|
||||
}
|
||||
}
|
||||
return { child, childIndex: i, relativeLineNumber, charOffset };
|
||||
return { child, relativeOneBasedLine, positionAccumulator };
|
||||
}
|
||||
|
||||
childFromCharOffset(lineNumber: number, charOffset: number) {
|
||||
private childFromCharOffset(lineNumberAccumulator: number, relativePosition: number
|
||||
): { child: LineCollection, childIndex: number, relativePosition: number, lineNumberAccumulator: number } {
|
||||
let child: LineCollection;
|
||||
let i: number;
|
||||
let len: number;
|
||||
for (i = 0, len = this.children.length; i < len; i++) {
|
||||
child = this.children[i];
|
||||
if (child.charCount() > charOffset) {
|
||||
if (child.charCount() > relativePosition) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
charOffset -= child.charCount();
|
||||
lineNumber += child.lineCount();
|
||||
relativePosition -= child.charCount();
|
||||
lineNumberAccumulator += child.lineCount();
|
||||
}
|
||||
}
|
||||
return { child, childIndex: i, charOffset, lineNumber };
|
||||
return { child, childIndex: i, relativePosition, lineNumberAccumulator };
|
||||
}
|
||||
|
||||
private splitAfter(childIndex: number) {
|
||||
|
||||
+28
-31
@@ -49,7 +49,7 @@ namespace ts.server {
|
||||
|
||||
interface FileStart {
|
||||
file: string;
|
||||
start: ILineInfo;
|
||||
start: protocol.Location;
|
||||
}
|
||||
|
||||
function compareNumber(a: number, b: number) {
|
||||
@@ -84,15 +84,15 @@ namespace ts.server {
|
||||
};
|
||||
}
|
||||
|
||||
function convertToILineInfo(lineAndCharacter: LineAndCharacter): ILineInfo {
|
||||
function convertToLocation(lineAndCharacter: LineAndCharacter): protocol.Location {
|
||||
return { line: lineAndCharacter.line + 1, offset: lineAndCharacter.character + 1 };
|
||||
}
|
||||
|
||||
function formatConfigFileDiag(diag: ts.Diagnostic, includeFileName: true): protocol.DiagnosticWithFileName;
|
||||
function formatConfigFileDiag(diag: ts.Diagnostic, includeFileName: false): protocol.Diagnostic;
|
||||
function formatConfigFileDiag(diag: ts.Diagnostic, includeFileName: boolean): protocol.Diagnostic | protocol.DiagnosticWithFileName {
|
||||
const start = diag.file && convertToILineInfo(getLineAndCharacterOfPosition(diag.file, diag.start));
|
||||
const end = diag.file && convertToILineInfo(getLineAndCharacterOfPosition(diag.file, diag.start + diag.length));
|
||||
const start = diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start));
|
||||
const end = diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start + diag.length));
|
||||
const text = ts.flattenDiagnosticMessageText(diag.messageText, "\n");
|
||||
const { code, source } = diag;
|
||||
const category = DiagnosticCategory[diag.category].toLowerCase();
|
||||
@@ -555,8 +555,8 @@ namespace ts.server {
|
||||
length: d.length,
|
||||
category: DiagnosticCategory[d.category].toLowerCase(),
|
||||
code: d.code,
|
||||
startLocation: d.file && convertToILineInfo(getLineAndCharacterOfPosition(d.file, d.start)),
|
||||
endLocation: d.file && convertToILineInfo(getLineAndCharacterOfPosition(d.file, d.start + d.length))
|
||||
startLocation: d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start)),
|
||||
endLocation: d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start + d.length))
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1131,32 +1131,29 @@ namespace ts.server {
|
||||
// only to the previous line. If all this is true, then
|
||||
// add edits necessary to properly indent the current line.
|
||||
if ((args.key === "\n") && ((!edits) || (edits.length === 0) || allEditsBeforePos(edits, position))) {
|
||||
const lineInfo = scriptInfo.getLineInfo(args.line);
|
||||
if (lineInfo && (lineInfo.leaf) && (lineInfo.leaf.text)) {
|
||||
const lineText = lineInfo.leaf.text;
|
||||
if (lineText.search("\\S") < 0) {
|
||||
const preferredIndent = project.getLanguageService(/*ensureSynchronized*/ false).getIndentationAtPosition(file, position, formatOptions);
|
||||
let hasIndent = 0;
|
||||
let i: number, len: number;
|
||||
for (i = 0, len = lineText.length; i < len; i++) {
|
||||
if (lineText.charAt(i) === " ") {
|
||||
hasIndent++;
|
||||
}
|
||||
else if (lineText.charAt(i) === "\t") {
|
||||
hasIndent += formatOptions.tabSize;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
const { lineText, absolutePosition } = scriptInfo.getLineInfo(args.line);
|
||||
if (lineText && lineText.search("\\S") < 0) {
|
||||
const preferredIndent = project.getLanguageService(/*ensureSynchronized*/ false).getIndentationAtPosition(file, position, formatOptions);
|
||||
let hasIndent = 0;
|
||||
let i: number, len: number;
|
||||
for (i = 0, len = lineText.length; i < len; i++) {
|
||||
if (lineText.charAt(i) === " ") {
|
||||
hasIndent++;
|
||||
}
|
||||
// i points to the first non whitespace character
|
||||
if (preferredIndent !== hasIndent) {
|
||||
const firstNoWhiteSpacePosition = lineInfo.offset + i;
|
||||
edits.push({
|
||||
span: ts.createTextSpanFromBounds(lineInfo.offset, firstNoWhiteSpacePosition),
|
||||
newText: formatting.getIndentationString(preferredIndent, formatOptions)
|
||||
});
|
||||
else if (lineText.charAt(i) === "\t") {
|
||||
hasIndent += formatOptions.tabSize;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// i points to the first non whitespace character
|
||||
if (preferredIndent !== hasIndent) {
|
||||
const firstNoWhiteSpacePosition = absolutePosition + i;
|
||||
edits.push({
|
||||
span: ts.createTextSpanFromBounds(absolutePosition, firstNoWhiteSpacePosition),
|
||||
newText: formatting.getIndentationString(preferredIndent, formatOptions)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1514,7 +1511,7 @@ namespace ts.server {
|
||||
|
||||
if (simplifiedResult) {
|
||||
const file = result.renameFilename;
|
||||
let location: ILineInfo | undefined = undefined;
|
||||
let location: protocol.Location | undefined;
|
||||
if (file !== undefined && result.renameLocation !== undefined) {
|
||||
const renameScriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(file));
|
||||
location = renameScriptInfo.positionToLineOffset(result.renameLocation);
|
||||
|
||||
+7
-20
@@ -53,18 +53,14 @@ namespace ts.JsDoc {
|
||||
// from Array<T> - Array<string> and Array<number>
|
||||
const documentationComment = <SymbolDisplayPart[]>[];
|
||||
forEachUnique(declarations, declaration => {
|
||||
const comments = getCommentsFromJSDoc(declaration);
|
||||
if (!comments) {
|
||||
return;
|
||||
}
|
||||
for (const comment of comments) {
|
||||
if (comment) {
|
||||
forEach(getAllJSDocs(declaration), doc => {
|
||||
if (doc.comment) {
|
||||
if (documentationComment.length) {
|
||||
documentationComment.push(lineBreakPart());
|
||||
}
|
||||
documentationComment.push(textPart(comment));
|
||||
documentationComment.push(textPart(doc.comment));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return documentationComment;
|
||||
}
|
||||
@@ -73,18 +69,9 @@ namespace ts.JsDoc {
|
||||
// Only collect doc comments from duplicate declarations once.
|
||||
const tags: JSDocTagInfo[] = [];
|
||||
forEachUnique(declarations, declaration => {
|
||||
const jsDocs = getJSDocs(declaration);
|
||||
if (!jsDocs) {
|
||||
return;
|
||||
}
|
||||
for (const doc of jsDocs) {
|
||||
const tagsForDoc = (doc as JSDoc).tags;
|
||||
if (tagsForDoc) {
|
||||
tags.push(...tagsForDoc.filter(tag => tag.kind === SyntaxKind.JSDocTag).map(jsDocTag => {
|
||||
return {
|
||||
name: unescapeLeadingUnderscores(jsDocTag.tagName.text),
|
||||
text: jsDocTag.comment
|
||||
}; }));
|
||||
for (const tag of getJSDocTags(declaration)) {
|
||||
if (tag.kind === SyntaxKind.JSDocTag) {
|
||||
tags.push({ name: unescapeLeadingUnderscores(tag.tagName.text), text: tag.comment });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -29,8 +29,6 @@ namespace ts.JsTyping {
|
||||
// that we are confident require typings
|
||||
let safeList: Map<string>;
|
||||
|
||||
const EmptySafeList: Map<string> = createMap<string>();
|
||||
|
||||
/* @internal */
|
||||
export const nodeCoreModuleList: ReadonlyArray<string> = [
|
||||
"buffer", "querystring", "events", "http", "cluster",
|
||||
@@ -177,16 +175,14 @@ namespace ts.JsTyping {
|
||||
* @param fileNames are the names for source files in the project
|
||||
*/
|
||||
function getTypingNamesFromSourceFileNames(fileNames: string[]) {
|
||||
if (safeList !== EmptySafeList) {
|
||||
for (const j of fileNames) {
|
||||
if (!hasJavaScriptFileExtension(j)) continue;
|
||||
for (const j of fileNames) {
|
||||
if (!hasJavaScriptFileExtension(j)) continue;
|
||||
|
||||
const inferredTypingName = removeFileExtension(getBaseFileName(j.toLowerCase()));
|
||||
const cleanedTypingName = inferredTypingName.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, "");
|
||||
const safe = safeList.get(cleanedTypingName);
|
||||
if (safe !== undefined) {
|
||||
addInferredTyping(safe);
|
||||
}
|
||||
const inferredTypingName = removeFileExtension(getBaseFileName(j.toLowerCase()));
|
||||
const cleanedTypingName = inferredTypingName.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, "");
|
||||
const safe = safeList.get(cleanedTypingName);
|
||||
if (safe !== undefined) {
|
||||
addInferredTyping(safe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
|
||||
export const emptyArray: any[] = [];
|
||||
|
||||
export const enum SemanticMeaning {
|
||||
None = 0x0,
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//// [tests/cases/compiler/narrowedImports.ts] ////
|
||||
|
||||
//// [a.d.ts]
|
||||
declare const a0: number | undefined;
|
||||
export default a0;
|
||||
export const a1: number | undefined;
|
||||
|
||||
//// [b.d.ts]
|
||||
declare const b: number | undefined;
|
||||
declare namespace b {}
|
||||
export = b;
|
||||
|
||||
//// [x.ts]
|
||||
import a0, { a1, a1 as a2 } from "./a";
|
||||
import * as b0 from "./b";
|
||||
import b1 = require("./b");
|
||||
|
||||
let x: number;
|
||||
|
||||
if (a0) x = a0;
|
||||
if (a1) x = a1;
|
||||
if (a2) x = a2;
|
||||
if (b0) x = b0;
|
||||
if (b1) x = b1;
|
||||
|
||||
|
||||
//// [x.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var a_1 = require("./a");
|
||||
var b0 = require("./b");
|
||||
var b1 = require("./b");
|
||||
var x;
|
||||
if (a_1["default"])
|
||||
x = a_1["default"];
|
||||
if (a_1.a1)
|
||||
x = a_1.a1;
|
||||
if (a_1.a1)
|
||||
x = a_1.a1;
|
||||
if (b0)
|
||||
x = b0;
|
||||
if (b1)
|
||||
x = b1;
|
||||
@@ -0,0 +1,61 @@
|
||||
=== /x.ts ===
|
||||
import a0, { a1, a1 as a2 } from "./a";
|
||||
>a0 : Symbol(a0, Decl(x.ts, 0, 6))
|
||||
>a1 : Symbol(a1, Decl(x.ts, 0, 12))
|
||||
>a1 : Symbol(a2, Decl(x.ts, 0, 16))
|
||||
>a2 : Symbol(a2, Decl(x.ts, 0, 16))
|
||||
|
||||
import * as b0 from "./b";
|
||||
>b0 : Symbol(b0, Decl(x.ts, 1, 6))
|
||||
|
||||
import b1 = require("./b");
|
||||
>b1 : Symbol(b1, Decl(x.ts, 1, 26))
|
||||
|
||||
let x: number;
|
||||
>x : Symbol(x, Decl(x.ts, 4, 3))
|
||||
|
||||
if (a0) x = a0;
|
||||
>a0 : Symbol(a0, Decl(x.ts, 0, 6))
|
||||
>x : Symbol(x, Decl(x.ts, 4, 3))
|
||||
>a0 : Symbol(a0, Decl(x.ts, 0, 6))
|
||||
|
||||
if (a1) x = a1;
|
||||
>a1 : Symbol(a1, Decl(x.ts, 0, 12))
|
||||
>x : Symbol(x, Decl(x.ts, 4, 3))
|
||||
>a1 : Symbol(a1, Decl(x.ts, 0, 12))
|
||||
|
||||
if (a2) x = a2;
|
||||
>a2 : Symbol(a2, Decl(x.ts, 0, 16))
|
||||
>x : Symbol(x, Decl(x.ts, 4, 3))
|
||||
>a2 : Symbol(a2, Decl(x.ts, 0, 16))
|
||||
|
||||
if (b0) x = b0;
|
||||
>b0 : Symbol(b0, Decl(x.ts, 1, 6))
|
||||
>x : Symbol(x, Decl(x.ts, 4, 3))
|
||||
>b0 : Symbol(b0, Decl(x.ts, 1, 6))
|
||||
|
||||
if (b1) x = b1;
|
||||
>b1 : Symbol(b1, Decl(x.ts, 1, 26))
|
||||
>x : Symbol(x, Decl(x.ts, 4, 3))
|
||||
>b1 : Symbol(b1, Decl(x.ts, 1, 26))
|
||||
|
||||
=== /a.d.ts ===
|
||||
declare const a0: number | undefined;
|
||||
>a0 : Symbol(a0, Decl(a.d.ts, 0, 13))
|
||||
|
||||
export default a0;
|
||||
>a0 : Symbol(a0, Decl(a.d.ts, 0, 13))
|
||||
|
||||
export const a1: number | undefined;
|
||||
>a1 : Symbol(a1, Decl(a.d.ts, 2, 12))
|
||||
|
||||
=== /b.d.ts ===
|
||||
declare const b: number | undefined;
|
||||
>b : Symbol(b, Decl(b.d.ts, 0, 13), Decl(b.d.ts, 0, 36))
|
||||
|
||||
declare namespace b {}
|
||||
>b : Symbol(b, Decl(b.d.ts, 0, 13), Decl(b.d.ts, 0, 36))
|
||||
|
||||
export = b;
|
||||
>b : Symbol(b, Decl(b.d.ts, 0, 13), Decl(b.d.ts, 0, 36))
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
=== /x.ts ===
|
||||
import a0, { a1, a1 as a2 } from "./a";
|
||||
>a0 : number | undefined
|
||||
>a1 : number | undefined
|
||||
>a1 : number | undefined
|
||||
>a2 : number | undefined
|
||||
|
||||
import * as b0 from "./b";
|
||||
>b0 : number | undefined
|
||||
|
||||
import b1 = require("./b");
|
||||
>b1 : number | undefined
|
||||
|
||||
let x: number;
|
||||
>x : number
|
||||
|
||||
if (a0) x = a0;
|
||||
>a0 : number | undefined
|
||||
>x = a0 : number
|
||||
>x : number
|
||||
>a0 : number
|
||||
|
||||
if (a1) x = a1;
|
||||
>a1 : number | undefined
|
||||
>x = a1 : number
|
||||
>x : number
|
||||
>a1 : number
|
||||
|
||||
if (a2) x = a2;
|
||||
>a2 : number | undefined
|
||||
>x = a2 : number
|
||||
>x : number
|
||||
>a2 : number
|
||||
|
||||
if (b0) x = b0;
|
||||
>b0 : number | undefined
|
||||
>x = b0 : number
|
||||
>x : number
|
||||
>b0 : number
|
||||
|
||||
if (b1) x = b1;
|
||||
>b1 : number | undefined
|
||||
>x = b1 : number
|
||||
>x : number
|
||||
>b1 : number
|
||||
|
||||
=== /a.d.ts ===
|
||||
declare const a0: number | undefined;
|
||||
>a0 : number | undefined
|
||||
|
||||
export default a0;
|
||||
>a0 : number | undefined
|
||||
|
||||
export const a1: number | undefined;
|
||||
>a1 : number | undefined
|
||||
|
||||
=== /b.d.ts ===
|
||||
declare const b: number | undefined;
|
||||
>b : number | undefined
|
||||
|
||||
declare namespace b {}
|
||||
>b : number | undefined
|
||||
|
||||
export = b;
|
||||
>b : number | undefined
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//// [tests/cases/compiler/narrowedImports_assumeInitialized.ts] ////
|
||||
|
||||
//// [a.d.ts]
|
||||
declare namespace a {
|
||||
export const x: number;
|
||||
}
|
||||
export = a;
|
||||
|
||||
//// [b.ts]
|
||||
import a = require("./a");
|
||||
a.x;
|
||||
|
||||
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var a = require("./a");
|
||||
a.x;
|
||||
@@ -0,0 +1,19 @@
|
||||
=== /b.ts ===
|
||||
import a = require("./a");
|
||||
>a : Symbol(a, Decl(b.ts, 0, 0))
|
||||
|
||||
a.x;
|
||||
>a.x : Symbol(a.x, Decl(a.d.ts, 1, 16))
|
||||
>a : Symbol(a, Decl(b.ts, 0, 0))
|
||||
>x : Symbol(a.x, Decl(a.d.ts, 1, 16))
|
||||
|
||||
=== /a.d.ts ===
|
||||
declare namespace a {
|
||||
>a : Symbol(a, Decl(a.d.ts, 0, 0))
|
||||
|
||||
export const x: number;
|
||||
>x : Symbol(x, Decl(a.d.ts, 1, 16))
|
||||
}
|
||||
export = a;
|
||||
>a : Symbol(a, Decl(a.d.ts, 0, 0))
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
=== /b.ts ===
|
||||
import a = require("./a");
|
||||
>a : typeof a
|
||||
|
||||
a.x;
|
||||
>a.x : number
|
||||
>a : typeof a
|
||||
>x : number
|
||||
|
||||
=== /a.d.ts ===
|
||||
declare namespace a {
|
||||
>a : typeof a
|
||||
|
||||
export const x: number;
|
||||
>x : number
|
||||
}
|
||||
export = a;
|
||||
>a : typeof a
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// @strictNullChecks: true
|
||||
|
||||
// @Filename: /a.d.ts
|
||||
declare const a0: number | undefined;
|
||||
export default a0;
|
||||
export const a1: number | undefined;
|
||||
|
||||
// @Filename: /b.d.ts
|
||||
declare const b: number | undefined;
|
||||
declare namespace b {}
|
||||
export = b;
|
||||
|
||||
// @Filename: /x.ts
|
||||
import a0, { a1, a1 as a2 } from "./a";
|
||||
import * as b0 from "./b";
|
||||
import b1 = require("./b");
|
||||
|
||||
let x: number;
|
||||
|
||||
if (a0) x = a0;
|
||||
if (a1) x = a1;
|
||||
if (a2) x = a2;
|
||||
if (b0) x = b0;
|
||||
if (b1) x = b1;
|
||||
@@ -0,0 +1,11 @@
|
||||
// @strictNullChecks: true
|
||||
|
||||
// @Filename: /a.d.ts
|
||||
declare namespace a {
|
||||
export const x: number;
|
||||
}
|
||||
export = a;
|
||||
|
||||
// @Filename: /b.ts
|
||||
import a = require("./a");
|
||||
a.x;
|
||||
Reference in New Issue
Block a user