Merge branch 'master' into watchOptions

This commit is contained in:
Sheetal Nandi
2018-03-03 10:51:59 -08:00
1306 changed files with 29122 additions and 28522 deletions
+5 -3
View File
@@ -143,14 +143,16 @@ const es2017LibrarySource = [
const es2017LibrarySourceMap = es2017LibrarySource.map(source =>
({ target: "lib." + source, sources: ["header.d.ts", source] }));
const es2018LibrarySource = [];
const es2018LibrarySource = [
"es2018.regexp.d.ts",
"es2018.promise.d.ts"
];
const es2018LibrarySourceMap = es2018LibrarySource.map(source =>
({ target: "lib." + source, sources: ["header.d.ts", source] }));
const esnextLibrarySource = [
"esnext.asynciterable.d.ts",
"esnext.array.d.ts",
"esnext.promise.d.ts"
"esnext.array.d.ts"
];
const esnextLibrarySourceMap = esnextLibrarySource.map(source =>
+5 -3
View File
@@ -206,7 +206,10 @@ var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
});
var es2018LibrarySource = [];
var es2018LibrarySource = [
"es2018.regexp.d.ts",
"es2018.promise.d.ts"
];
var es2018LibrarySourceMap = es2018LibrarySource.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
@@ -214,8 +217,7 @@ var es2018LibrarySourceMap = es2018LibrarySource.map(function (source) {
var esnextLibrarySource = [
"esnext.asynciterable.d.ts",
"esnext.array.d.ts",
"esnext.promise.d.ts"
"esnext.array.d.ts"
];
var esnextLibrarySourceMap = esnextLibrarySource.map(function (source) {
+7 -13
View File
@@ -427,7 +427,12 @@ namespace ts {
}
addDeclarationToSymbol(symbol, node, includes);
symbol.parent = parent;
if (symbol.parent) {
Debug.assert(symbol.parent === parent, "Existing symbol parent should match new one");
}
else {
symbol.parent = parent;
}
return symbol;
}
@@ -2071,7 +2076,7 @@ namespace ts {
seenThisKeyword = true;
return;
case SyntaxKind.TypePredicate:
return checkTypePredicate(node as TypePredicateNode);
break; // Binding the children will handle everything
case SyntaxKind.TypeParameter:
return bindTypeParameter(node as TypeParameterDeclaration);
case SyntaxKind.Parameter:
@@ -2204,17 +2209,6 @@ namespace ts {
return bindAnonymousDeclaration(<Declaration>node, SymbolFlags.TypeLiteral, InternalSymbolName.Type);
}
function checkTypePredicate(node: TypePredicateNode) {
const { parameterName, type } = node;
if (parameterName && parameterName.kind === SyntaxKind.Identifier) {
checkStrictModeIdentifier(parameterName);
}
if (parameterName && parameterName.kind === SyntaxKind.ThisType) {
seenThisKeyword = true;
}
bind(type);
}
function bindSourceFileIfExternalModule() {
setExportContextFlag(file);
if (isExternalModule(file)) {
+304 -241
View File
File diff suppressed because it is too large Load Diff
+16 -8
View File
@@ -62,6 +62,13 @@ namespace ts {
category: Diagnostics.Command_line_Options,
description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental
},
{
name: "preserveWatchOutput",
type: "boolean",
showInSimplifiedHelpView: false,
category: Diagnostics.Command_line_Options,
description: Diagnostics.Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen,
},
{
name: "watch",
shortName: "w",
@@ -144,9 +151,10 @@ namespace ts {
"es2017.string": "lib.es2017.string.d.ts",
"es2017.intl": "lib.es2017.intl.d.ts",
"es2017.typedarrays": "lib.es2017.typedarrays.d.ts",
"es2018.promise": "lib.es2018.promise.d.ts",
"es2018.regexp": "lib.es2018.regexp.d.ts",
"esnext.array": "lib.esnext.array.d.ts",
"esnext.asynciterable": "lib.esnext.asynciterable.d.ts",
"esnext.promise": "lib.esnext.promise.d.ts",
}),
},
showInSimplifiedHelpView: true,
@@ -1731,7 +1739,7 @@ namespace ts {
function getExtendedConfig(
sourceFile: JsonSourceFile,
extendedConfigPath: string,
host: ts.ParseConfigHost,
host: ParseConfigHost,
basePath: string,
resolutionStack: string[],
errors: Push<Diagnostic>,
@@ -2107,7 +2115,7 @@ namespace ts {
}
}
function specToDiagnostic(spec: string, allowTrailingRecursion: boolean): ts.DiagnosticMessage | undefined {
function specToDiagnostic(spec: string, allowTrailingRecursion: boolean): DiagnosticMessage | undefined {
if (!allowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) {
return Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0;
}
@@ -2134,7 +2142,7 @@ namespace ts {
// /a/b/a?z - Watch /a/b directly to catch any new file matching a?z
const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude");
const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i");
const wildcardDirectories: ts.MapLike<WatchDirectoryFlags> = {};
const wildcardDirectories: MapLike<WatchDirectoryFlags> = {};
if (include !== undefined) {
const recursiveKeys: string[] = [];
for (const file of include) {
@@ -2230,8 +2238,8 @@ namespace ts {
* Also converts enum values back to strings.
*/
/* @internal */
export function convertCompilerOptionsForTelemetry(opts: ts.CompilerOptions): ts.CompilerOptions {
const out: ts.CompilerOptions = {};
export function convertCompilerOptionsForTelemetry(opts: CompilerOptions): CompilerOptions {
const out: CompilerOptions = {};
for (const key in opts) {
if (opts.hasOwnProperty(key)) {
const type = getOptionFromName(key);
@@ -2255,9 +2263,9 @@ namespace ts {
return typeof value === "boolean" ? value : "";
case "list":
const elementType = (option as CommandLineOptionOfListType).element;
return ts.isArray(value) ? value.map(v => getOptionValueWithEmptyStrings(v, elementType)) : "";
return isArray(value) ? value.map(v => getOptionValueWithEmptyStrings(v, elementType)) : "";
default:
return ts.forEachEntry(option.type, (optionEnumValue, optionStringValue) => {
return forEachEntry(option.type, (optionEnumValue, optionStringValue) => {
if (optionEnumValue === value) {
return optionStringValue;
}
+1 -1
View File
@@ -2622,7 +2622,7 @@ namespace ts {
// Iterate over each include base path and include unique base paths that are not a
// subpath of an existing base path
for (const includeBasePath of includeBasePaths) {
if (ts.every(basePaths, basePath => !containsPath(basePath, includeBasePath, path, !useCaseSensitiveFileNames))) {
if (every(basePaths, basePath => !containsPath(basePath, includeBasePath, path, !useCaseSensitiveFileNames))) {
basePaths.push(includeBasePath);
}
}
+6 -1
View File
@@ -608,7 +608,12 @@ namespace ts {
"?");
}
write(": ");
emitType(node.type);
if (node.type) {
emitType(node.type);
}
else {
write("any");
}
write(";");
writeLine();
decreaseIndent();
+23 -2
View File
@@ -2317,6 +2317,10 @@
"category": "Error",
"code": 2723
},
"Module '{0}' has no exported member '{1}'. Did you mean '{2}'?": {
"category": "Error",
"code": 2724
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
@@ -2602,7 +2606,7 @@
"code": 4083
},
"Conflicting definitions for '{0}' found at '{1}' and '{2}'. Consider installing a specific version of this library to resolve the conflict.": {
"category": "Message",
"category": "Error",
"code": 4090
},
"Parameter '{0}' of index signature from exported interface has or is using name '{1}' from private module '{2}'.": {
@@ -3296,7 +3300,7 @@
"category": "Message",
"code": 6146
},
"Resolution for module '{0}' was found in cache.": {
"Resolution for module '{0}' was found in cache from location '{1}'.": {
"category": "Message",
"code": 6147
},
@@ -3472,6 +3476,10 @@
"category": "Message",
"code": 6190
},
"Whether to keep outdated console output in watch mode instead of clearing the screen.": {
"category": "Message",
"code": 6191
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
@@ -3788,6 +3796,10 @@
"category": "Error",
"code": 17016
},
"JSX fragment is not supported when using an inline JSX factory pragma": {
"category": "Error",
"code": 17017
},
"Circularity detected while resolving configuration: {0}": {
"category": "Error",
@@ -3806,6 +3818,15 @@
"code": 18003
},
"File is a CommonJS module; it may be converted to an ES6 module.": {
"category": "Suggestion",
"code": 80001
},
"This constructor function may be converted to a class declaration.": {
"category": "Suggestion",
"code": 80002
},
"Add missing 'super()' call": {
"category": "Message",
"code": 90001
+119 -115
View File
@@ -998,7 +998,8 @@ namespace ts {
else {
emitTypeAnnotation(node.type);
}
emitInitializer(node.initializer);
// The comment position has to fallback to any present node within the parameterdeclaration because as it turns out, the parser can make parameter declarations with _just_ an initializer.
emitInitializer(node.initializer, node.type ? node.type.end : node.questionToken ? node.questionToken.end : node.name ? node.name.end : node.modifiers ? node.modifiers.end : node.decorators ? node.decorators.end : node.pos, node);
}
function emitDecorator(decorator: Decorator) {
@@ -1026,7 +1027,7 @@ namespace ts {
emitIfPresent(node.questionToken);
emitIfPresent(node.exclamationToken);
emitTypeAnnotation(node.type);
emitInitializer(node.initializer);
emitInitializer(node.initializer, node.type ? node.type.end : node.questionToken ? node.questionToken.end : node.name.end, node);
writeSemicolon();
}
@@ -1308,7 +1309,7 @@ namespace ts {
writeSpace();
}
emit(node.name);
emitInitializer(node.initializer);
emitInitializer(node.initializer, node.name.end, node);
}
//
@@ -1353,7 +1354,10 @@ namespace ts {
increaseIndentIf(indentBeforeDot);
const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression);
writePunctuation(shouldEmitDotDot ? ".." : ".");
if (shouldEmitDotDot) {
writePunctuation(".");
}
emitTokenWithComment(SyntaxKind.DotToken, node.expression.end, writePunctuation, node);
increaseIndentIf(indentAfterDot);
emit(node.name);
@@ -1382,9 +1386,9 @@ namespace ts {
function emitElementAccessExpression(node: ElementAccessExpression) {
emitExpression(node.expression);
writePunctuation("[");
const openPos = emitTokenWithComment(SyntaxKind.OpenBracketToken, node.expression.end, writePunctuation, node);
emitExpression(node.argumentExpression);
writePunctuation("]");
emitTokenWithComment(SyntaxKind.CloseBracketToken, node.argumentExpression ? node.argumentExpression.end : openPos, writePunctuation, node);
}
function emitCallExpression(node: CallExpression) {
@@ -1394,7 +1398,7 @@ namespace ts {
}
function emitNewExpression(node: NewExpression) {
writeKeyword("new");
emitTokenWithComment(SyntaxKind.NewKeyword, node.pos, writeKeyword, node);
writeSpace();
emitExpression(node.expression);
emitTypeArguments(node, node.typeArguments);
@@ -1415,9 +1419,9 @@ namespace ts {
}
function emitParenthesizedExpression(node: ParenthesizedExpression) {
writePunctuation("(");
const openParenPos = emitTokenWithComment(SyntaxKind.OpenParenToken, node.pos, writePunctuation, node);
emitExpression(node.expression);
writePunctuation(")");
emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression ? node.expression.end : openParenPos, writePunctuation, node);
}
function emitFunctionExpression(node: FunctionExpression) {
@@ -1439,25 +1443,25 @@ namespace ts {
}
function emitDeleteExpression(node: DeleteExpression) {
writeKeyword("delete");
emitTokenWithComment(SyntaxKind.DeleteKeyword, node.pos, writeKeyword, node);
writeSpace();
emitExpression(node.expression);
}
function emitTypeOfExpression(node: TypeOfExpression) {
writeKeyword("typeof");
emitTokenWithComment(SyntaxKind.TypeOfKeyword, node.pos, writeKeyword, node);
writeSpace();
emitExpression(node.expression);
}
function emitVoidExpression(node: VoidExpression) {
writeKeyword("void");
emitTokenWithComment(SyntaxKind.VoidKeyword, node.pos, writeKeyword, node);
writeSpace();
emitExpression(node.expression);
}
function emitAwaitExpression(node: AwaitExpression) {
writeKeyword("await");
emitTokenWithComment(SyntaxKind.AwaitKeyword, node.pos, writeKeyword, node);
writeSpace();
emitExpression(node.expression);
}
@@ -1535,7 +1539,7 @@ namespace ts {
}
function emitYieldExpression(node: YieldExpression) {
writeKeyword("yield");
emitTokenWithComment(SyntaxKind.YieldKeyword, node.pos, writeKeyword, node);
emit(node.asteriskToken);
emitExpressionWithLeadingSpace(node.expression);
}
@@ -1589,18 +1593,14 @@ namespace ts {
//
function emitBlock(node: Block) {
writeToken(SyntaxKind.OpenBraceToken, node.pos, writePunctuation, /*contextNode*/ node);
emitBlockStatements(node, /*forceSingleLine*/ !node.multiLine && isEmptyBlock(node));
// We have to call emitLeadingComments explicitly here because otherwise leading comments of the close brace token will not be emitted
increaseIndent();
emitLeadingCommentsOfPosition(node.statements.end);
decreaseIndent();
writeToken(SyntaxKind.CloseBraceToken, node.statements.end, writePunctuation, /*contextNode*/ node);
}
function emitBlockStatements(node: BlockLike, forceSingleLine: boolean) {
emitTokenWithComment(SyntaxKind.OpenBraceToken, node.pos, writePunctuation, /*contextNode*/ node);
const format = forceSingleLine || getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineBlockStatements : ListFormat.MultiLineBlockStatements;
emitList(node, node.statements, format);
emitTokenWithComment(SyntaxKind.CloseBraceToken, node.statements.end, writePunctuation, /*contextNode*/ node, /*indentLeading*/ !!(format & ListFormat.MultiLine));
}
function emitVariableStatement(node: VariableStatement) {
@@ -1619,15 +1619,15 @@ namespace ts {
}
function emitIfStatement(node: IfStatement) {
const openParenPos = writeToken(SyntaxKind.IfKeyword, node.pos, writeKeyword, node);
const openParenPos = emitTokenWithComment(SyntaxKind.IfKeyword, node.pos, writeKeyword, node);
writeSpace();
writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node);
emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node);
emitExpression(node.expression);
writeToken(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node);
emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node);
emitEmbeddedStatement(node, node.thenStatement);
if (node.elseStatement) {
writeLineOrSpace(node);
writeToken(SyntaxKind.ElseKeyword, node.thenStatement.end, writeKeyword, node);
emitTokenWithComment(SyntaxKind.ElseKeyword, node.thenStatement.end, writeKeyword, node);
if (node.elseStatement.kind === SyntaxKind.IfStatement) {
writeSpace();
emit(node.elseStatement);
@@ -1638,8 +1638,16 @@ namespace ts {
}
}
function emitWhileClause(node: WhileStatement | DoStatement, startPos: number) {
const openParenPos = emitTokenWithComment(SyntaxKind.WhileKeyword, startPos, writeKeyword, node);
writeSpace();
emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node);
emitExpression(node.expression);
emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node);
}
function emitDoStatement(node: DoStatement) {
writeKeyword("do");
emitTokenWithComment(SyntaxKind.DoKeyword, node.pos, writeKeyword, node);
emitEmbeddedStatement(node, node.statement);
if (isBlock(node.statement)) {
writeSpace();
@@ -1648,59 +1656,52 @@ namespace ts {
writeLineOrSpace(node);
}
writeKeyword("while");
writeSpace();
writePunctuation("(");
emitExpression(node.expression);
writePunctuation(");");
emitWhileClause(node, node.statement.end);
writePunctuation(";");
}
function emitWhileStatement(node: WhileStatement) {
writeKeyword("while");
writeSpace();
writePunctuation("(");
emitExpression(node.expression);
writePunctuation(")");
emitWhileClause(node, node.pos);
emitEmbeddedStatement(node, node.statement);
}
function emitForStatement(node: ForStatement) {
const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos, writeKeyword);
const openParenPos = emitTokenWithComment(SyntaxKind.ForKeyword, node.pos, writeKeyword, node);
writeSpace();
writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, /*contextNode*/ node);
let pos = emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, /*contextNode*/ node);
emitForBinding(node.initializer);
writeSemicolon();
pos = emitTokenWithComment(SyntaxKind.SemicolonToken, node.initializer ? node.initializer.end : pos, writeSemicolon, node);
emitExpressionWithLeadingSpace(node.condition);
writeSemicolon();
pos = emitTokenWithComment(SyntaxKind.SemicolonToken, node.condition ? node.condition.end : pos, writeSemicolon, node);
emitExpressionWithLeadingSpace(node.incrementor);
writePunctuation(")");
emitTokenWithComment(SyntaxKind.CloseParenToken, node.incrementor ? node.incrementor.end : pos, writePunctuation, node);
emitEmbeddedStatement(node, node.statement);
}
function emitForInStatement(node: ForInStatement) {
const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos, writeKeyword);
const openParenPos = emitTokenWithComment(SyntaxKind.ForKeyword, node.pos, writeKeyword, node);
writeSpace();
writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation);
emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node);
emitForBinding(node.initializer);
writeSpace();
writeKeyword("in");
emitTokenWithComment(SyntaxKind.InKeyword, node.initializer.end, writeKeyword, node);
writeSpace();
emitExpression(node.expression);
writeToken(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation);
emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node);
emitEmbeddedStatement(node, node.statement);
}
function emitForOfStatement(node: ForOfStatement) {
const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos, writeKeyword);
const openParenPos = emitTokenWithComment(SyntaxKind.ForKeyword, node.pos, writeKeyword, node);
writeSpace();
emitWithTrailingSpace(node.awaitModifier);
writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation);
emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node);
emitForBinding(node.initializer);
writeSpace();
writeKeyword("of");
emitTokenWithComment(SyntaxKind.OfKeyword, node.initializer.end, writeKeyword, node);
writeSpace();
emitExpression(node.expression);
writeToken(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation);
emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node);
emitEmbeddedStatement(node, node.statement);
}
@@ -1716,24 +1717,36 @@ namespace ts {
}
function emitContinueStatement(node: ContinueStatement) {
writeToken(SyntaxKind.ContinueKeyword, node.pos, writeKeyword);
emitTokenWithComment(SyntaxKind.ContinueKeyword, node.pos, writeKeyword, node);
emitWithLeadingSpace(node.label);
writeSemicolon();
}
function emitBreakStatement(node: BreakStatement) {
writeToken(SyntaxKind.BreakKeyword, node.pos, writeKeyword);
emitTokenWithComment(SyntaxKind.BreakKeyword, node.pos, writeKeyword, node);
emitWithLeadingSpace(node.label);
writeSemicolon();
}
function emitTokenWithComment(token: SyntaxKind, pos: number, writer: (s: string) => void, contextNode?: Node) {
function emitTokenWithComment(token: SyntaxKind, pos: number, writer: (s: string) => void, contextNode?: Node, indentLeading?: boolean) {
const node = contextNode && getParseTreeNode(contextNode);
if (node && node.kind === contextNode.kind) {
const isSimilarNode = node && node.kind === contextNode.kind;
const startPos = pos;
if (isSimilarNode) {
pos = skipTrivia(currentSourceFile.text, pos);
}
pos = writeToken(token, pos, writer, /*contextNode*/ contextNode);
if (node && node.kind === contextNode.kind) {
if (emitLeadingCommentsOfPosition && isSimilarNode) {
const needsIndent = indentLeading && !positionsAreOnSameLine(startPos, pos, currentSourceFile);
if (needsIndent) {
increaseIndent();
}
emitLeadingCommentsOfPosition(startPos);
if (needsIndent) {
decreaseIndent();
}
}
pos = writeTokenText(token, writer, pos);
if (emitTrailingCommentsOfPosition && isSimilarNode) {
emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ true);
}
return pos;
@@ -1746,39 +1759,39 @@ namespace ts {
}
function emitWithStatement(node: WithStatement) {
writeKeyword("with");
const openParenPos = emitTokenWithComment(SyntaxKind.WithKeyword, node.pos, writeKeyword, node);
writeSpace();
writePunctuation("(");
emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node);
emitExpression(node.expression);
writePunctuation(")");
emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node);
emitEmbeddedStatement(node, node.statement);
}
function emitSwitchStatement(node: SwitchStatement) {
const openParenPos = writeToken(SyntaxKind.SwitchKeyword, node.pos, writeKeyword);
const openParenPos = emitTokenWithComment(SyntaxKind.SwitchKeyword, node.pos, writeKeyword, node);
writeSpace();
writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation);
emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node);
emitExpression(node.expression);
writeToken(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation);
emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node);
writeSpace();
emit(node.caseBlock);
}
function emitLabeledStatement(node: LabeledStatement) {
emit(node.label);
writePunctuation(":");
emitTokenWithComment(SyntaxKind.ColonToken, node.label.end, writePunctuation, node);
writeSpace();
emit(node.statement);
}
function emitThrowStatement(node: ThrowStatement) {
writeKeyword("throw");
emitTokenWithComment(SyntaxKind.ThrowKeyword, node.pos, writeKeyword, node);
emitExpressionWithLeadingSpace(node.expression);
writeSemicolon();
}
function emitTryStatement(node: TryStatement) {
writeKeyword("try");
emitTokenWithComment(SyntaxKind.TryKeyword, node.pos, writeKeyword, node);
writeSpace();
emit(node.tryBlock);
if (node.catchClause) {
@@ -1787,7 +1800,7 @@ namespace ts {
}
if (node.finallyBlock) {
writeLineOrSpace(node);
writeKeyword("finally");
emitTokenWithComment(SyntaxKind.FinallyKeyword, (node.catchClause || node.tryBlock).end, writeKeyword, node);
writeSpace();
emit(node.finallyBlock);
}
@@ -1805,7 +1818,7 @@ namespace ts {
function emitVariableDeclaration(node: VariableDeclaration) {
emit(node.name);
emitTypeAnnotation(node.type);
emitInitializer(node.initializer);
emitInitializer(node.initializer, node.type ? node.type.end : node.name.end, node);
}
function emitVariableDeclarationList(node: VariableDeclarationList) {
@@ -2043,25 +2056,23 @@ namespace ts {
function emitModuleBlock(node: ModuleBlock) {
pushNameGenerationScope(node);
writePunctuation("{");
emitBlockStatements(node, /*forceSingleLine*/ isEmptyBlock(node));
writePunctuation("}");
popNameGenerationScope(node);
}
function emitCaseBlock(node: CaseBlock) {
writeToken(SyntaxKind.OpenBraceToken, node.pos, writePunctuation);
emitTokenWithComment(SyntaxKind.OpenBraceToken, node.pos, writePunctuation, node);
emitList(node, node.clauses, ListFormat.CaseBlockClauses);
writeToken(SyntaxKind.CloseBraceToken, node.clauses.end, writePunctuation);
emitTokenWithComment(SyntaxKind.CloseBraceToken, node.clauses.end, writePunctuation, node, /*indentLeading*/ true);
}
function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) {
emitModifiers(node, node.modifiers);
writeKeyword("import");
emitTokenWithComment(SyntaxKind.ImportKeyword, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node);
writeSpace();
emit(node.name);
writeSpace();
writePunctuation("=");
emitTokenWithComment(SyntaxKind.EqualsToken, node.name.end, writePunctuation, node);
writeSpace();
emitModuleReference(node.moduleReference);
writeSemicolon();
@@ -2078,12 +2089,12 @@ namespace ts {
function emitImportDeclaration(node: ImportDeclaration) {
emitModifiers(node, node.modifiers);
writeKeyword("import");
emitTokenWithComment(SyntaxKind.ImportKeyword, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node);
writeSpace();
if (node.importClause) {
emit(node.importClause);
writeSpace();
writeKeyword("from");
emitTokenWithComment(SyntaxKind.FromKeyword, node.importClause.end, writeKeyword, node);
writeSpace();
}
emitExpression(node.moduleSpecifier);
@@ -2093,16 +2104,16 @@ namespace ts {
function emitImportClause(node: ImportClause) {
emit(node.name);
if (node.name && node.namedBindings) {
writePunctuation(",");
emitTokenWithComment(SyntaxKind.CommaToken, node.name.end, writePunctuation, node);
writeSpace();
}
emit(node.namedBindings);
}
function emitNamespaceImport(node: NamespaceImport) {
writePunctuation("*");
const asPos = emitTokenWithComment(SyntaxKind.AsteriskToken, node.pos, writePunctuation, node);
writeSpace();
writeKeyword("as");
emitTokenWithComment(SyntaxKind.AsKeyword, asPos, writeKeyword, node);
writeSpace();
emit(node.name);
}
@@ -2116,13 +2127,13 @@ namespace ts {
}
function emitExportAssignment(node: ExportAssignment) {
writeKeyword("export");
const nextPos = emitTokenWithComment(SyntaxKind.ExportKeyword, node.pos, writeKeyword, node);
writeSpace();
if (node.isExportEquals) {
writeOperator("=");
emitTokenWithComment(SyntaxKind.EqualsToken, nextPos, writeOperator, node);
}
else {
writeKeyword("default");
emitTokenWithComment(SyntaxKind.DefaultKeyword, nextPos, writeKeyword, node);
}
writeSpace();
emitExpression(node.expression);
@@ -2130,17 +2141,18 @@ namespace ts {
}
function emitExportDeclaration(node: ExportDeclaration) {
writeKeyword("export");
let nextPos = emitTokenWithComment(SyntaxKind.ExportKeyword, node.pos, writeKeyword, node);
writeSpace();
if (node.exportClause) {
emit(node.exportClause);
}
else {
writePunctuation("*");
nextPos = emitTokenWithComment(SyntaxKind.AsteriskToken, nextPos, writePunctuation, node);
}
if (node.moduleSpecifier) {
writeSpace();
writeKeyword("from");
const fromPos = node.exportClause ? node.exportClause.end : nextPos;
emitTokenWithComment(SyntaxKind.FromKeyword, fromPos, writeKeyword, node);
writeSpace();
emitExpression(node.moduleSpecifier);
}
@@ -2148,11 +2160,11 @@ namespace ts {
}
function emitNamespaceExportDeclaration(node: NamespaceExportDeclaration) {
writeKeyword("export");
let nextPos = emitTokenWithComment(SyntaxKind.ExportKeyword, node.pos, writeKeyword, node);
writeSpace();
writeKeyword("as");
nextPos = emitTokenWithComment(SyntaxKind.AsKeyword, nextPos, writeKeyword, node);
writeSpace();
writeKeyword("namespace");
nextPos = emitTokenWithComment(SyntaxKind.NamespaceKeyword, nextPos, writeKeyword, node);
writeSpace();
emit(node.name);
writeSemicolon();
@@ -2176,7 +2188,7 @@ namespace ts {
if (node.propertyName) {
emit(node.propertyName);
writeSpace();
writeKeyword("as");
emitTokenWithComment(SyntaxKind.AsKeyword, node.propertyName.end, writeKeyword, node);
writeSpace();
}
@@ -2287,21 +2299,19 @@ namespace ts {
//
function emitCaseClause(node: CaseClause) {
writeKeyword("case");
emitTokenWithComment(SyntaxKind.CaseKeyword, node.pos, writeKeyword, node);
writeSpace();
emitExpression(node.expression);
writePunctuation(":");
emitCaseOrDefaultClauseStatements(node, node.statements);
emitCaseOrDefaultClauseRest(node, node.statements, node.expression.end);
}
function emitDefaultClause(node: DefaultClause) {
writeKeyword("default");
writePunctuation(":");
emitCaseOrDefaultClauseStatements(node, node.statements);
const pos = emitTokenWithComment(SyntaxKind.DefaultKeyword, node.pos, writeKeyword, node);
emitCaseOrDefaultClauseRest(node, node.statements, pos);
}
function emitCaseOrDefaultClauseStatements(parentNode: Node, statements: NodeArray<Statement>) {
function emitCaseOrDefaultClauseRest(parentNode: Node, statements: NodeArray<Statement>, colonPos: number) {
const emitAsSingleStatement =
statements.length === 1 &&
(
@@ -2311,27 +2321,15 @@ namespace ts {
rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile)
);
// e.g:
// case 0: // Zero
// case 1: // One
// case 2: // two
// return "hi";
// If there is no statements, emitNodeWithComments of the parentNode which is caseClause will take care of trailing comment.
// So in example above, comment "// Zero" and "// One" will be emit in emitTrailingComments in emitNodeWithComments.
// However, for "case 2", because parentNode which is caseClause has an "end" property to be end of the statements (in this case return statement)
// comment "// two" will not be emitted in emitNodeWithComments.
// Therefore, we have to do the check here to emit such comment.
if (statements.length > 0) {
// We use emitTrailingCommentsOfPosition instead of emitLeadingCommentsOfPosition because leading comments is defined as comments before the node after newline character separating it from previous line
// Note: we can't use parentNode.end as such position includes statements.
emitTrailingCommentsOfPosition(statements.pos);
}
let format = ListFormat.CaseOrDefaultClauseStatements;
if (emitAsSingleStatement) {
writeToken(SyntaxKind.ColonToken, colonPos, writePunctuation, parentNode);
writeSpace();
format &= ~(ListFormat.MultiLine | ListFormat.Indented);
}
else {
emitTokenWithComment(SyntaxKind.ColonToken, colonPos, writePunctuation, parentNode);
}
emitList(parentNode, statements, format);
}
@@ -2343,12 +2341,12 @@ namespace ts {
}
function emitCatchClause(node: CatchClause) {
const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos, writeKeyword);
const openParenPos = emitTokenWithComment(SyntaxKind.CatchKeyword, node.pos, writeKeyword, node);
writeSpace();
if (node.variableDeclaration) {
writeToken(SyntaxKind.OpenParenToken, openParenPos, writePunctuation);
emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node);
emit(node.variableDeclaration);
writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration.end, writePunctuation);
emitTokenWithComment(SyntaxKind.CloseParenToken, node.variableDeclaration.end, writePunctuation, node);
writeSpace();
}
emit(node.block);
@@ -2400,7 +2398,7 @@ namespace ts {
function emitEnumMember(node: EnumMember) {
emit(node.name);
emitInitializer(node.initializer);
emitInitializer(node.initializer, node.name.end, node);
}
//
@@ -2530,10 +2528,10 @@ namespace ts {
}
}
function emitInitializer(node: Expression | undefined) {
function emitInitializer(node: Expression | undefined, equalCommentStartPos: number, container: Node) {
if (node) {
writeSpace();
writeOperator("=");
emitTokenWithComment(SyntaxKind.EqualsToken, equalCommentStartPos, writeOperator, container);
writeSpace();
emitExpression(node);
}
@@ -2674,6 +2672,9 @@ namespace ts {
if (format & ListFormat.BracketsMask) {
writePunctuation(getOpeningBracket(format));
if (isEmpty) {
emitTrailingCommentsOfPosition(children.pos, /*prefixSpace*/ true); // Emit comments within empty bracketed lists
}
}
if (onBeforeEmitNodeArray) {
@@ -2799,6 +2800,9 @@ namespace ts {
}
if (format & ListFormat.BracketsMask) {
if (isEmpty) {
emitLeadingCommentsOfPosition(children.end); // Emit leading comments within empty lists
}
writePunctuation(getClosingBracket(format));
}
}
+12 -2
View File
@@ -230,9 +230,16 @@ namespace ts {
: node;
}
function parenthesizeForComputedName(expression: Expression): Expression {
return (isBinaryExpression(expression) && expression.operatorToken.kind === SyntaxKind.CommaToken) ||
expression.kind === SyntaxKind.CommaListExpression ?
createParen(expression) :
expression;
}
export function createComputedPropertyName(expression: Expression) {
const node = <ComputedPropertyName>createSynthesizedNode(SyntaxKind.ComputedPropertyName);
node.expression = expression;
node.expression = parenthesizeForComputedName(expression);
return node;
}
@@ -2287,7 +2294,7 @@ namespace ts {
const node = <PropertyAssignment>createSynthesizedNode(SyntaxKind.PropertyAssignment);
node.name = asName(name);
node.questionToken = undefined;
node.initializer = initializer !== undefined ? parenthesizeExpressionForList(initializer) : undefined;
node.initializer = parenthesizeExpressionForList(initializer);
return node;
}
@@ -2375,6 +2382,9 @@ namespace ts {
if (node.resolvedTypeReferenceDirectiveNames !== undefined) updated.resolvedTypeReferenceDirectiveNames = node.resolvedTypeReferenceDirectiveNames;
if (node.imports !== undefined) updated.imports = node.imports;
if (node.moduleAugmentations !== undefined) updated.moduleAugmentations = node.moduleAugmentations;
if (node.pragmas !== undefined) updated.pragmas = node.pragmas;
if (node.localJsxFactory !== undefined) updated.localJsxFactory = node.localJsxFactory;
if (node.localJsxNamespace !== undefined) updated.localJsxNamespace = node.localJsxNamespace;
return updateNode(updated, node);
}
+22 -9
View File
@@ -161,7 +161,7 @@ namespace ts {
}
let typeRoots: string[];
forEachAncestorDirectory(ts.normalizePath(currentDirectory), directory => {
forEachAncestorDirectory(normalizePath(currentDirectory), directory => {
const atTypes = combinePaths(directory, nodeModulesAtTypes);
if (host.directoryExists(atTypes)) {
(typeRoots || (typeRoots = [])).push(atTypes);
@@ -335,8 +335,20 @@ namespace ts {
}
export function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache {
const directoryToModuleNameMap = createMap<Map<ResolvedModuleWithFailedLookupLocations>>();
const moduleNameToDirectoryMap = createMap<PerModuleNameCache>();
return createModuleResolutionCacheWithMaps(
createMap<Map<ResolvedModuleWithFailedLookupLocations>>(),
createMap<PerModuleNameCache>(),
currentDirectory,
getCanonicalFileName
);
}
/*@internal*/
export function createModuleResolutionCacheWithMaps(
directoryToModuleNameMap: Map<Map<ResolvedModuleWithFailedLookupLocations>>,
moduleNameToDirectoryMap: Map<PerModuleNameCache>,
currentDirectory: string,
getCanonicalFileName: GetCanonicalFileName): ModuleResolutionCache {
return { getOrCreateCacheForDirectory, getOrCreateCacheForModuleName };
@@ -445,7 +457,7 @@ namespace ts {
if (result) {
if (traceEnabled) {
trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache, moduleName);
trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory);
}
}
else {
@@ -717,7 +729,7 @@ namespace ts {
/* @internal */
export function resolveJavaScriptModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string {
const { resolvedModule, failedLookupLocations } =
nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ts.ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true);
nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true);
if (!resolvedModule) {
throw new Error(`Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${failedLookupLocations.join(", ")}`);
}
@@ -1157,9 +1169,10 @@ namespace ts {
return `@types/${getMangledNameForScopedPackage(packageName)}`;
}
function getMangledNameForScopedPackage(packageName: string): string {
/* @internal */
export function getMangledNameForScopedPackage(packageName: string): string {
if (startsWith(packageName, "@")) {
const replaceSlash = packageName.replace(ts.directorySeparator, mangledScopedPackageSeparator);
const replaceSlash = packageName.replace(directorySeparator, mangledScopedPackageSeparator);
if (replaceSlash !== packageName) {
return replaceSlash.slice(1); // Take off the "@"
}
@@ -1179,7 +1192,7 @@ namespace ts {
/* @internal */
export function getUnmangledNameForScopedPackage(typesPackageName: string): string {
return stringContains(typesPackageName, mangledScopedPackageSeparator) ?
"@" + typesPackageName.replace(mangledScopedPackageSeparator, ts.directorySeparator) :
"@" + typesPackageName.replace(mangledScopedPackageSeparator, directorySeparator) :
typesPackageName;
}
@@ -1187,7 +1200,7 @@ namespace ts {
const result = cache && cache.get(containingDirectory);
if (result) {
if (traceEnabled) {
trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache, moduleName);
trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory);
}
return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, extension: result.resolvedModule.extension, packageId: result.resolvedModule.packageId } };
}
+231 -91
View File
@@ -769,7 +769,9 @@ namespace ts {
// Prime the scanner.
nextToken();
processReferenceComments(sourceFile);
// A member of ReadonlyArray<T> isn't assignable to a member of T[] (and prevents a direct cast) - but this is where we set up those members so they can be readonly in the future
processCommentPragmas(sourceFile as {} as PragmaContext, sourceText);
processPragmasIntoFields(sourceFile as {} as PragmaContext, reportPragmaDiagnostic);
sourceFile.statements = parseList(ParsingContext.SourceElements, parseStatement);
Debug.assert(token() === SyntaxKind.EndOfFileToken);
@@ -787,6 +789,10 @@ namespace ts {
}
return sourceFile;
function reportPragmaDiagnostic(pos: number, end: number, diagnostic: DiagnosticMessage) {
parseDiagnostics.push(createFileDiagnostic(sourceFile, pos, end, diagnostic));
}
}
function addJSDocComment<T extends HasJSDoc>(node: T): T {
@@ -4176,8 +4182,9 @@ namespace ts {
parseExpected(SyntaxKind.LessThanToken);
if (token() === SyntaxKind.GreaterThanToken) {
parseExpected(SyntaxKind.GreaterThanToken);
// See below for explanation of scanJsxText
const node: JsxOpeningFragment = <JsxOpeningFragment>createNode(SyntaxKind.JsxOpeningFragment, fullStart);
scanJsxText();
return finishNode(node);
}
@@ -5921,7 +5928,7 @@ namespace ts {
return finishNode(node);
}
function parseImportEqualsDeclaration(node: ImportEqualsDeclaration, identifier: ts.Identifier): ImportEqualsDeclaration {
function parseImportEqualsDeclaration(node: ImportEqualsDeclaration, identifier: Identifier): ImportEqualsDeclaration {
node.kind = SyntaxKind.ImportEqualsDeclaration;
node.name = identifier;
parseExpected(SyntaxKind.EqualsToken);
@@ -6084,94 +6091,6 @@ namespace ts {
return finishNode(node);
}
function processReferenceComments(sourceFile: SourceFile): void {
const triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
const referencedFiles: FileReference[] = [];
const typeReferenceDirectives: FileReference[] = [];
const amdDependencies: { path: string; name: string }[] = [];
let amdModuleName: string;
let checkJsDirective: CheckJsDirective = undefined;
// Keep scanning all the leading trivia in the file until we get to something that
// isn't trivia. Any single line comment will be analyzed to see if it is a
// reference comment.
while (true) {
const kind = triviaScanner.scan();
if (kind !== SyntaxKind.SingleLineCommentTrivia) {
if (isTrivia(kind)) {
continue;
}
else {
break;
}
}
const range = {
kind: <SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia>triviaScanner.getToken(),
pos: triviaScanner.getTokenPos(),
end: triviaScanner.getTextPos(),
};
const comment = sourceText.substring(range.pos, range.end);
const referencePathMatchResult = getFileReferenceFromReferencePath(comment, range);
if (referencePathMatchResult) {
const fileReference = referencePathMatchResult.fileReference;
sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
const diagnosticMessage = referencePathMatchResult.diagnosticMessage;
if (fileReference) {
if (referencePathMatchResult.isTypeReferenceDirective) {
typeReferenceDirectives.push(fileReference);
}
else {
referencedFiles.push(fileReference);
}
}
if (diagnosticMessage) {
parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage));
}
}
else {
const amdModuleNameRegEx = /^\/\/\/\s*<amd-module\s+name\s*=\s*('|")(.+?)\1/gim;
const amdModuleNameMatchResult = amdModuleNameRegEx.exec(comment);
if (amdModuleNameMatchResult) {
if (amdModuleName) {
parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments));
}
amdModuleName = amdModuleNameMatchResult[2];
}
const amdDependencyRegEx = /^\/\/\/\s*<amd-dependency\s/gim;
const pathRegex = /\spath\s*=\s*('|")(.+?)\1/gim;
const nameRegex = /\sname\s*=\s*('|")(.+?)\1/gim;
const amdDependencyMatchResult = amdDependencyRegEx.exec(comment);
if (amdDependencyMatchResult) {
const pathMatchResult = pathRegex.exec(comment);
const nameMatchResult = nameRegex.exec(comment);
if (pathMatchResult) {
const amdDependency = { path: pathMatchResult[2], name: nameMatchResult ? nameMatchResult[2] : undefined };
amdDependencies.push(amdDependency);
}
}
const checkJsDirectiveRegEx = /^\/\/\/?\s*(@ts-check|@ts-nocheck)\s*$/gim;
const checkJsDirectiveMatchResult = checkJsDirectiveRegEx.exec(comment);
if (checkJsDirectiveMatchResult) {
checkJsDirective = {
enabled: equateStringsCaseInsensitive(checkJsDirectiveMatchResult[1], "@ts-check"),
end: range.end,
pos: range.pos
};
}
}
}
sourceFile.referencedFiles = referencedFiles;
sourceFile.typeReferenceDirectives = typeReferenceDirectives;
sourceFile.amdDependencies = amdDependencies;
sourceFile.moduleName = amdModuleName;
sourceFile.checkJsDirective = checkJsDirective;
}
function setExternalModuleIndicator(sourceFile: SourceFile) {
sourceFile.externalModuleIndicator = forEach(sourceFile.statements, node =>
hasModifier(node, ModifierFlags.Export)
@@ -7552,4 +7471,225 @@ namespace ts {
function isDeclarationFileName(fileName: string): boolean {
return fileExtensionIs(fileName, Extension.Dts);
}
/*@internal*/
export interface PragmaContext {
languageVersion: ScriptTarget;
pragmas?: PragmaMap;
checkJsDirective?: CheckJsDirective;
referencedFiles: FileReference[];
typeReferenceDirectives: FileReference[];
amdDependencies: AmdDependency[];
hasNoDefaultLib?: boolean;
moduleName?: string;
}
/*@internal*/
export function processCommentPragmas(context: PragmaContext, sourceText: string): void {
const triviaScanner = createScanner(context.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
const pragmas: PragmaPsuedoMapEntry[] = [];
// Keep scanning all the leading trivia in the file until we get to something that
// isn't trivia. Any single line comment will be analyzed to see if it is a
// reference comment.
while (true) {
const kind = triviaScanner.scan();
if (!isTrivia(kind)) {
break;
}
const range = {
kind: <SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia>triviaScanner.getToken(),
pos: triviaScanner.getTokenPos(),
end: triviaScanner.getTextPos(),
};
const comment = sourceText.substring(range.pos, range.end);
extractPragmas(pragmas, range, comment);
}
context.pragmas = createMap() as PragmaMap;
for (const pragma of pragmas) {
if (context.pragmas.has(pragma.name)) {
const currentValue = context.pragmas.get(pragma.name);
if (currentValue instanceof Array) {
currentValue.push(pragma.args);
}
else {
context.pragmas.set(pragma.name, [currentValue, pragma.args]);
}
continue;
}
context.pragmas.set(pragma.name, pragma.args);
}
}
/*@internal*/
type PragmaDiagnosticReporter = (pos: number, length: number, message: DiagnosticMessage) => void;
/*@internal*/
export function processPragmasIntoFields(context: PragmaContext, reportDiagnostic: PragmaDiagnosticReporter): void {
context.checkJsDirective = undefined;
context.referencedFiles = [];
context.typeReferenceDirectives = [];
context.amdDependencies = [];
context.hasNoDefaultLib = false;
context.pragmas.forEach((entryOrList, key) => {
// TODO: The below should be strongly type-guarded and not need casts/explicit annotations, since entryOrList is related to
// key and key is constrained to a union; but it's not (see GH#21483 for at least partial fix) :(
switch (key) {
case "reference": {
const referencedFiles = context.referencedFiles;
const typeReferenceDirectives = context.typeReferenceDirectives;
forEach(toArray(entryOrList), (arg: PragmaPsuedoMap["reference"]) => {
if (arg.arguments["no-default-lib"]) {
context.hasNoDefaultLib = true;
}
else if (arg.arguments.types) {
typeReferenceDirectives.push({ pos: arg.arguments.types.pos, end: arg.arguments.types.end, fileName: arg.arguments.types.value });
}
else if (arg.arguments.path) {
referencedFiles.push({ pos: arg.arguments.path.pos, end: arg.arguments.path.end, fileName: arg.arguments.path.value });
}
else {
reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax);
}
});
break;
}
case "amd-dependency": {
context.amdDependencies = map(
toArray(entryOrList),
({ arguments: { name, path } }: PragmaPsuedoMap["amd-dependency"]) => ({ name, path })
);
break;
}
case "amd-module": {
if (entryOrList instanceof Array) {
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);
}
context.moduleName = (entry as PragmaPsuedoMap["amd-module"]).arguments.name;
}
}
else {
context.moduleName = (entryOrList as PragmaPsuedoMap["amd-module"]).arguments.name;
}
break;
}
case "ts-nocheck":
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) {
context.checkJsDirective = {
enabled: key === "ts-check",
end: entry.range.end,
pos: entry.range.pos
};
}
});
break;
}
case "jsx": return; // Accessed directly
default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future?
}
});
}
const namedArgRegExCache = createMap<RegExp>();
function getNamedArgRegEx(name: string) {
if (namedArgRegExCache.has(name)) {
return namedArgRegExCache.get(name);
}
const result = new RegExp(`(\\s${name}\\s*=\\s*)('|")(.+?)\\2`, "im");
namedArgRegExCache.set(name, result);
return result;
}
const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im;
const singleLinePragmaRegEx = /^\/\/\/?\s*@(\S+)\s*(.*)\s*$/im;
function extractPragmas(pragmas: PragmaPsuedoMapEntry[], range: CommentRange, text: string) {
const tripleSlash = tripleSlashXMLCommentStartRegEx.exec(text);
if (tripleSlash) {
const name = tripleSlash[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks
const pragma = commentPragmas[name] as PragmaDefinition;
if (!pragma || !(pragma.kind & PragmaKindFlags.TripleSlashXML)) {
return;
}
if (pragma.args) {
const argument: {[index: string]: string | {value: string, pos: number, end: number}} = {};
for (const arg of pragma.args) {
const matcher = getNamedArgRegEx(arg.name);
const matchResult = matcher.exec(text);
if (!matchResult && !arg.optional) {
return; // Missing required argument, don't parse
}
else if (matchResult) {
if (arg.captureSpan) {
const startPos = range.pos + matchResult.index + matchResult[1].length + matchResult[2].length;
argument[arg.name] = {
value: matchResult[3],
pos: startPos,
end: startPos + matchResult[3].length
};
}
else {
argument[arg.name] = matchResult[3];
}
}
}
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPsuedoMapEntry);
}
else {
pragmas.push({ name, args: { arguments: {}, range } } as PragmaPsuedoMapEntry);
}
return;
}
const singleLine = singleLinePragmaRegEx.exec(text);
if (singleLine) {
return addPragmaForMatch(pragmas, range, PragmaKindFlags.SingleLine, singleLine);
}
const multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating)
let multiLineMatch: RegExpExecArray;
while (multiLineMatch = multiLinePragmaRegEx.exec(text)) {
addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch);
}
}
function addPragmaForMatch(pragmas: PragmaPsuedoMapEntry[], range: CommentRange, kind: PragmaKindFlags, match: RegExpExecArray) {
if (!match) return;
const name = match[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks
const pragma = commentPragmas[name] as PragmaDefinition;
if (!pragma || !(pragma.kind & kind)) {
return;
}
const args = match[2]; // Split on spaces and match up positionally with definition
const argument = getNamedPragmaArguments(pragma, args);
if (argument === "fail") return; // Missing required argument, fail to parse it
pragmas.push({ name, args: { arguments: argument, range } } as PragmaPsuedoMapEntry);
return;
}
function getNamedPragmaArguments(pragma: PragmaDefinition, text: string | undefined): {[index: string]: string} | "fail" {
if (!text) return {};
if (!pragma.args) return {};
const args = text.split(/\s+/);
const argMap: {[index: string]: string} = {};
for (let i = 0; i < pragma.args.length; i++) {
const argument = pragma.args[i];
if (!args[i] && !argument.optional) {
return "fail";
}
if (argument.captureSpan) {
return Debug.fail("Capture spans not yet implemented for non-xml pragmas");
}
argMap[argument.name] = args[i];
}
return argMap;
}
}
+4 -6
View File
@@ -227,8 +227,7 @@ namespace ts {
}
export function formatDiagnostic(diagnostic: Diagnostic, host: FormatDiagnosticsHost): string {
const category = DiagnosticCategory[diagnostic.category].toLowerCase();
const errorMessage = `${category} TS${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine())}${host.getNewLine()}`;
const errorMessage = `${diagnosticCategoryName(diagnostic)} TS${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine())}${host.getNewLine()}`;
if (diagnostic.file) {
const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
@@ -254,8 +253,9 @@ namespace ts {
const ellipsis = "...";
function getCategoryFormat(category: DiagnosticCategory): string {
switch (category) {
case DiagnosticCategory.Warning: return ForegroundColorEscapeSequences.Yellow;
case DiagnosticCategory.Error: return ForegroundColorEscapeSequences.Red;
case DiagnosticCategory.Warning: return ForegroundColorEscapeSequences.Yellow;
case DiagnosticCategory.Suggestion: return Debug.fail("Should never get an Info diagnostic on the command line.");
case DiagnosticCategory.Message: return ForegroundColorEscapeSequences.Blue;
}
}
@@ -337,9 +337,7 @@ namespace ts {
output += " - ";
}
const categoryColor = getCategoryFormat(diagnostic.category);
const category = DiagnosticCategory[diagnostic.category].toLowerCase();
output += formatColorAndReset(category, categoryColor);
output += formatColorAndReset(diagnosticCategoryName(diagnostic), getCategoryFormat(diagnostic.category));
output += formatColorAndReset(` TS${ diagnostic.code }: `, ForegroundColorEscapeSequences.Grey);
output += flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine());
+97 -75
View File
@@ -28,6 +28,7 @@ namespace ts {
interface ResolutionWithFailedLookupLocations {
readonly failedLookupLocations: ReadonlyArray<string>;
isInvalidated?: boolean;
refCount?: number;
}
interface ResolutionWithResolvedFileName {
@@ -42,6 +43,7 @@ namespace ts {
export interface ResolutionCacheHost extends ModuleResolutionHost {
toPath(fileName: string): Path;
getCanonicalFileName: GetCanonicalFileName;
getCompilationSettings(): CompilerOptions;
watchDirectoryOfFailedLookupLocation(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher;
onInvalidatedResolution(): void;
@@ -78,18 +80,25 @@ namespace ts {
let filesWithInvalidatedResolutions: Map<true> | undefined;
let allFilesHaveInvalidatedResolution = false;
const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory());
const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost();
// The resolvedModuleNames and resolvedTypeReferenceDirectives are the cache of resolutions per file.
// The key in the map is source file's path.
// The values are Map of resolutions with key being name lookedup.
const resolvedModuleNames = createMap<Map<ResolvedModuleWithFailedLookupLocations>>();
const perDirectoryResolvedModuleNames = createMap<Map<ResolvedModuleWithFailedLookupLocations>>();
const nonRelaticeModuleNameCache = createMap<PerModuleNameCache>();
const moduleResolutionCache = createModuleResolutionCacheWithMaps(
perDirectoryResolvedModuleNames,
nonRelaticeModuleNameCache,
getCurrentDirectory(),
resolutionHost.getCanonicalFileName
);
const resolvedTypeReferenceDirectives = createMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
const perDirectoryResolvedTypeReferenceDirectives = createMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory());
const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost();
/**
* These are the extensions that failed lookup files will have by default,
* any other extension of failed lookup will be store that path in custom failed lookup path
@@ -173,6 +182,7 @@ namespace ts {
function clearPerDirectoryResolutions() {
perDirectoryResolvedModuleNames.clear();
nonRelaticeModuleNameCache.clear();
perDirectoryResolvedTypeReferenceDirectives.clear();
}
@@ -189,7 +199,7 @@ namespace ts {
}
function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
const primaryResult = ts.resolveModuleName(moduleName, containingFile, compilerOptions, host);
const primaryResult = ts.resolveModuleName(moduleName, containingFile, compilerOptions, host, moduleResolutionCache);
// return result immediately only if global cache support is not enabled or if it is .ts, .tsx or .d.ts
if (!resolutionHost.getGlobalCache) {
return primaryResult;
@@ -248,17 +258,11 @@ namespace ts {
perDirectoryResolution.set(name, resolution);
}
resolutionsInFile.set(name, resolution);
if (resolution.failedLookupLocations) {
if (existingResolution && existingResolution.failedLookupLocations) {
watchAndStopWatchDiffFailedLookupLocations(resolution, existingResolution);
}
else {
watchFailedLookupLocationOfResolution(resolution, 0);
}
}
else if (existingResolution) {
watchFailedLookupLocationOfResolution(resolution);
if (existingResolution) {
stopWatchFailedLookupLocationOfResolution(existingResolution);
}
if (logChanges && filesWithChangedSetOfUnresolvedImports && !resolutionIsEqualTo(existingResolution, resolution)) {
filesWithChangedSetOfUnresolvedImports.push(path);
// reset log changes to avoid recording the same file multiple times
@@ -390,80 +394,98 @@ namespace ts {
return fileExtensionIsOneOf(path, failedLookupDefaultExtensions);
}
function watchAndStopWatchDiffFailedLookupLocations(resolution: ResolutionWithFailedLookupLocations, existingResolution: ResolutionWithFailedLookupLocations) {
const failedLookupLocations = resolution.failedLookupLocations;
const existingFailedLookupLocations = existingResolution.failedLookupLocations;
for (let index = 0; index < failedLookupLocations.length; index++) {
if (index === existingFailedLookupLocations.length) {
// Additional failed lookup locations, watch from this index
watchFailedLookupLocationOfResolution(resolution, index);
return;
}
else if (failedLookupLocations[index] !== existingFailedLookupLocations[index]) {
// Different failed lookup locations,
// Watch new resolution failed lookup locations from this index and
// stop watching existing resolutions from this index
watchFailedLookupLocationOfResolution(resolution, index);
stopWatchFailedLookupLocationOfResolutionFrom(existingResolution, index);
return;
function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
// No need to set the resolution refCount
if (!resolution.failedLookupLocations || !resolution.failedLookupLocations.length) {
return;
}
if (resolution.refCount !== undefined) {
resolution.refCount++;
return;
}
resolution.refCount = 1;
const { failedLookupLocations } = resolution;
let setAtRoot = false;
for (const failedLookupLocation of failedLookupLocations) {
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
if (!ignore) {
// If the failed lookup location path is not one of the supported extensions,
// store it in the custom path
if (!isPathWithDefaultFailedLookupExtension(failedLookupLocationPath)) {
const refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0;
customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1);
}
if (dirPath === rootPath) {
setAtRoot = true;
}
else {
setDirectoryWatcher(dir, dirPath);
}
}
}
// All new failed lookup locations are already watched (and are same),
// Stop watching failed lookup locations of existing resolution after failed lookup locations length
stopWatchFailedLookupLocationOfResolutionFrom(existingResolution, failedLookupLocations.length);
if (setAtRoot) {
setDirectoryWatcher(rootDir, rootPath);
}
}
function watchFailedLookupLocationOfResolution({ failedLookupLocations }: ResolutionWithFailedLookupLocations, startIndex: number) {
for (let i = startIndex; i < failedLookupLocations.length; i++) {
const failedLookupLocation = failedLookupLocations[i];
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
// If the failed lookup location path is not one of the supported extensions,
// store it in the custom path
if (!isPathWithDefaultFailedLookupExtension(failedLookupLocationPath)) {
const refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0;
customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1);
}
const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
if (!ignore) {
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
if (dirWatcher) {
dirWatcher.refCount++;
}
else {
directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 });
}
}
function setDirectoryWatcher(dir: string, dirPath: Path) {
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
if (dirWatcher) {
dirWatcher.refCount++;
}
else {
directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 });
}
}
function stopWatchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
if (resolution.failedLookupLocations) {
stopWatchFailedLookupLocationOfResolutionFrom(resolution, 0);
if (!resolution.failedLookupLocations || !resolution.failedLookupLocations.length) {
return;
}
resolution.refCount!--;
if (resolution.refCount) {
return;
}
const { failedLookupLocations } = resolution;
let removeAtRoot = false;
for (const failedLookupLocation of failedLookupLocations) {
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
if (!ignore) {
const refCount = customFailedLookupPaths.get(failedLookupLocationPath);
if (refCount) {
if (refCount === 1) {
customFailedLookupPaths.delete(failedLookupLocationPath);
}
else {
Debug.assert(refCount > 1);
customFailedLookupPaths.set(failedLookupLocationPath, refCount - 1);
}
}
if (dirPath === rootPath) {
removeAtRoot = true;
}
else {
removeDirectoryWatcher(dirPath);
}
}
}
if (removeAtRoot) {
removeDirectoryWatcher(rootPath);
}
}
function stopWatchFailedLookupLocationOfResolutionFrom({ failedLookupLocations }: ResolutionWithFailedLookupLocations, startIndex: number) {
for (let i = startIndex; i < failedLookupLocations.length; i++) {
const failedLookupLocation = failedLookupLocations[i];
const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation);
const refCount = customFailedLookupPaths.get(failedLookupLocationPath);
if (refCount) {
if (refCount === 1) {
customFailedLookupPaths.delete(failedLookupLocationPath);
}
else {
Debug.assert(refCount > 1);
customFailedLookupPaths.set(failedLookupLocationPath, refCount - 1);
}
}
const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
if (!ignore) {
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
// Do not close the watcher yet since it might be needed by other failed lookup locations.
dirWatcher.refCount--;
}
}
function removeDirectoryWatcher(dirPath: string) {
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
// Do not close the watcher yet since it might be needed by other failed lookup locations.
dirWatcher.refCount--;
}
function createDirectoryWatcher(directory: string, dirPath: Path) {
+1 -1
View File
@@ -159,7 +159,7 @@ namespace ts {
// Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the
// relative paths of the sources list in the sourcemap
sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
sourceMapData.sourceMapSourceRoot = normalizeSlashes(sourceMapData.sourceMapSourceRoot);
if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== CharacterCodes.slash) {
sourceMapData.sourceMapSourceRoot += directorySeparator;
}
+1 -1
View File
@@ -734,7 +734,7 @@ namespace ts {
// When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined"
const fileName = !isString(relativeFileName)
? undefined
: ts.getNormalizedAbsolutePath(relativeFileName, dirName);
: getNormalizedAbsolutePath(relativeFileName, dirName);
// Some applications save a working file via rename operations
const callbacks = fileWatcherCallbacks.get(toCanonicalName(fileName));
if (callbacks) {
+10 -7
View File
@@ -1311,24 +1311,27 @@ namespace ts {
setTextRange(
createBlock([
createStatement(
setTextRange(
createAssignment(
setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap),
setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer))
setEmitFlags(
setTextRange(
createAssignment(
setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap),
setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer) | EmitFlags.NoComments)
),
parameter
),
parameter
EmitFlags.NoComments
)
)
]),
parameter
),
EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps
EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments
)
);
startOnNewLine(statement);
setTextRange(statement, parameter);
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue);
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue | EmitFlags.NoComments);
statements.push(statement);
}
+2 -2
View File
@@ -122,7 +122,7 @@ namespace ts {
}
const element = createExpressionForJsxElement(
context.getEmitResolver().getJsxFactoryEntity(),
context.getEmitResolver().getJsxFactoryEntity(currentSourceFile),
compilerOptions.reactNamespace,
tagName,
objectProperties,
@@ -140,7 +140,7 @@ namespace ts {
function visitJsxOpeningFragment(node: JsxOpeningFragment, children: ReadonlyArray<JsxChild>, isChild: boolean, location: TextRange) {
const element = createExpressionForJsxFragment(
context.getEmitResolver().getJsxFactoryEntity(),
context.getEmitResolver().getJsxFactoryEntity(currentSourceFile),
compilerOptions.reactNamespace,
mapDefined(children, transformJsxChildToExpression),
node,
+2 -2
View File
@@ -1728,7 +1728,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
}`
};`
};
// emit helper for `import Name from "foo"`
@@ -1738,6 +1738,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
text: `
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
}`
};`
};
}
+15 -12
View File
@@ -1147,20 +1147,23 @@ namespace ts {
setEmitFlags(localName, EmitFlags.NoComments);
return startOnNewLine(
setTextRange(
createStatement(
createAssignment(
setTextRange(
createPropertyAccess(
createThis(),
propertyName
setEmitFlags(
setTextRange(
createStatement(
createAssignment(
setTextRange(
createPropertyAccess(
createThis(),
propertyName
),
node.name
),
node.name
),
localName
)
localName
)
),
moveRangePos(node, -1)
),
moveRangePos(node, -1)
EmitFlags.NoComments
)
);
}
+3 -3
View File
@@ -167,7 +167,7 @@ namespace ts {
}
function createWatchOfConfigFile(configParseResult: ParsedCommandLine, optionsToExtend: CompilerOptions) {
const watchCompilerHost = ts.createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath, optionsToExtend, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(configParseResult.options));
const watchCompilerHost = createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath, optionsToExtend, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(configParseResult.options));
updateWatchCompilationHost(watchCompilerHost);
watchCompilerHost.rootFiles = configParseResult.fileNames;
watchCompilerHost.options = configParseResult.options;
@@ -177,7 +177,7 @@ namespace ts {
}
function createWatchOfFilesAndCompilerOptions(rootFiles: string[], options: CompilerOptions) {
const watchCompilerHost = ts.createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles, options, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(options));
const watchCompilerHost = createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles, options, sys, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(options));
updateWatchCompilationHost(watchCompilerHost);
createWatchProgram(watchCompilerHost);
}
@@ -262,7 +262,7 @@ namespace ts {
}
function printVersion() {
sys.write(getDiagnosticText(Diagnostics.Version_0, ts.version) + sys.newLine);
sys.write(getDiagnosticText(Diagnostics.Version_0, version) + sys.newLine);
}
function printHelp(showAllOptions: boolean) {
+163 -9
View File
@@ -2473,7 +2473,7 @@ namespace ts {
*/
export interface SourceFileLike {
readonly text: string;
lineMap: ReadonlyArray<number>;
lineMap?: ReadonlyArray<number>;
}
@@ -2568,6 +2568,9 @@ namespace ts {
/* @internal */ ambientModuleNames: ReadonlyArray<string>;
/* @internal */ checkJsDirective: CheckJsDirective | undefined;
/* @internal */ version: string;
/* @internal */ pragmas: PragmaMap;
/* @internal */ localJsxNamespace?: __String;
/* @internal */ localJsxFactory?: EntityName;
}
export interface Bundle extends Node {
@@ -2868,7 +2871,7 @@ namespace ts {
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
getJsxIntrinsicTagNames(): Symbol[];
getJsxIntrinsicTagNamesAt(location: Node): Symbol[];
isOptionalParameter(node: ParameterDeclaration): boolean;
getAmbientModules(): Symbol[];
@@ -2934,7 +2937,7 @@ namespace ts {
/* @internal */ isArrayLikeType(type: Type): boolean;
/* @internal */ getAllPossiblePropertiesOfTypes(type: ReadonlyArray<Type>): Symbol[];
/* @internal */ resolveName(name: string, location: Node, meaning: SymbolFlags, excludeGlobals: boolean): Symbol | undefined;
/* @internal */ getJsxNamespace(): string;
/* @internal */ getJsxNamespace(location?: Node): string;
/**
* Note that this will return undefined in the following case:
@@ -2951,6 +2954,12 @@ namespace ts {
/** @param node A location where we might consider accessing `this`. Not necessarily a ThisExpression. */
/* @internal */ tryGetThisTypeAt(node: Node): Type | undefined;
/* @internal */ getTypeArgumentConstraint(node: TypeNode): Type | undefined;
/**
* Does *not* get *all* suggestion diagnostics, just the ones that were convenient to report in the checker.
* Others are added in computeSuggestionDiagnostics.
*/
/* @internal */ getSuggestionDiagnostics(file: SourceFile): ReadonlyArray<Diagnostic>;
}
/* @internal */
@@ -3208,7 +3217,7 @@ namespace ts {
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[];
isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean;
writeLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, writer: EmitTextWriter): void;
getJsxFactoryEntity(): EntityName;
getJsxFactoryEntity(location?: Node): EntityName;
}
export const enum SymbolFlags {
@@ -3818,16 +3827,27 @@ namespace ts {
type: InstantiableType | UnionOrIntersectionType;
}
// T extends U ? X : Y (TypeFlags.Conditional)
export interface ConditionalType extends InstantiableType {
export interface ConditionalRoot {
node: ConditionalTypeNode;
checkType: Type;
extendsType: Type;
trueType: Type;
falseType: Type;
/* @internal */
isDistributive: boolean;
inferTypeParameters: TypeParameter[];
/* @internal */
target?: ConditionalType;
outerTypeParameters?: TypeParameter[];
instantiations?: Map<Type>;
aliasSymbol: Symbol;
aliasTypeArguments: Type[];
}
// T extends U ? X : Y (TypeFlags.Conditional)
export interface ConditionalType extends InstantiableType {
root: ConditionalRoot;
checkType: Type;
extendsType: Type;
resolvedTrueType?: Type;
resolvedFalseType?: Type;
/* @internal */
mapper?: TypeMapper;
}
@@ -3906,6 +3926,7 @@ namespace ts {
AlwaysStrict = 1 << 4, // Always use strict rules for contravariant inferences
}
/* @internal */
export interface InferenceInfo {
typeParameter: TypeParameter; // Type parameter for which inferences are being made
candidates: Type[]; // Candidates in covariant positions (or undefined)
@@ -3916,6 +3937,7 @@ namespace ts {
isFixed: boolean; // True if inferences are fixed
}
/* @internal */
export const enum InferenceFlags {
None = 0, // No special inference behaviors
InferUnionTypes = 1 << 0, // Infer union types for disjoint candidates (otherwise unknownType)
@@ -3932,12 +3954,14 @@ namespace ts {
* x | y is Maybe if either x or y is Maybe, but neither x or y is True.
* x | y is True if either x or y is True.
*/
/* @internal */
export const enum Ternary {
False = 0,
Maybe = 1,
True = -1
}
/* @internal */
export type TypeComparer = (s: Type, t: Type, reportErrors?: boolean) => Ternary;
/* @internal */
@@ -4010,8 +4034,14 @@ namespace ts {
export enum DiagnosticCategory {
Warning,
Error,
Suggestion,
Message
}
/* @internal */
export function diagnosticCategoryName(d: { category: DiagnosticCategory }, lowerCase = true): string {
const name = DiagnosticCategory[d.category];
return lowerCase ? name.toLowerCase() : name;
}
export enum ModuleResolutionKind {
Classic = 1,
@@ -4087,6 +4117,7 @@ namespace ts {
/*@internal*/ plugins?: PluginImport[];
preserveConstEnums?: boolean;
preserveSymlinks?: boolean;
/* @internal */ preserveWatchOutput?: boolean;
project?: string;
/* @internal */ pretty?: DiagnosticStyle;
reactNamespace?: string;
@@ -5123,4 +5154,127 @@ namespace ts {
Parameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis,
IndexSignatureParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | SquareBrackets,
}
/* @internal */
export const enum PragmaKindFlags {
None = 0,
/**
* Triple slash comment of the form
* /// <pragma-name argname="value" />
*/
TripleSlashXML = 1 << 0,
/**
* Single line comment of the form
* // @pragma-name argval1 argval2
* or
* /// @pragma-name argval1 argval2
*/
SingleLine = 1 << 1,
/**
* Multiline non-jsdoc pragma of the form
* /* @pragma-name argval1 argval2 * /
*/
MultiLine = 1 << 2,
All = TripleSlashXML | SingleLine | MultiLine,
Default = All,
}
/* @internal */
interface PragmaArgumentSpecification<TName extends string> {
name: TName; // Determines the name of the key in the resulting parsed type, type parameter to cause literal type inference
optional?: boolean;
captureSpan?: boolean;
}
/* @internal */
export interface PragmaDefinition<T1 extends string = string, T2 extends string = string, T3 extends string = string> {
args?: [PragmaArgumentSpecification<T1>] | [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>] | [PragmaArgumentSpecification<T1>, PragmaArgumentSpecification<T2>, PragmaArgumentSpecification<T3>];
// 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>}, K1 extends string, K2 extends string, K3 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({
"reference": {
args: [
{ name: "types", optional: true, captureSpan: true },
{ name: "path", optional: true, captureSpan: true },
{ name: "no-default-lib", optional: true }
],
kind: PragmaKindFlags.TripleSlashXML
},
"amd-dependency": {
args: [{ name: "path" }, { name: "name", optional: true }],
kind: PragmaKindFlags.TripleSlashXML
},
"amd-module": {
args: [{ name: "name" }],
kind: PragmaKindFlags.TripleSlashXML
},
"ts-check": {
kind: PragmaKindFlags.SingleLine
},
"ts-nocheck": {
kind: PragmaKindFlags.SingleLine
},
"jsx": {
args: [{ name: "factory" }],
kind: PragmaKindFlags.MultiLine
},
});
/* @internal */
type PragmaArgTypeMaybeCapture<TDesc> = TDesc extends {captureSpan: true} ? {value: string, pos: number, end: number} : string;
/* @internal */
type PragmaArgTypeOptional<TDesc, TName extends string> =
TDesc extends {optional: true}
? {[K in TName]?: PragmaArgTypeMaybeCapture<TDesc>}
: {[K in TName]: PragmaArgTypeMaybeCapture<TDesc>};
/**
* 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>] }
? 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 ConcretePragmaSpecs = typeof commentPragmas;
/* @internal */
export type PragmaPsuedoMap = {[K in keyof ConcretePragmaSpecs]?: {arguments: PragmaArgumentType<ConcretePragmaSpecs[K]>, range: CommentRange}};
/* @internal */
export type PragmaPsuedoMapEntry = {[K in keyof PragmaPsuedoMap]: {name: K, args: PragmaPsuedoMap[K]}}[keyof PragmaPsuedoMap];
/**
* A strongly-typed es6 map of pragma entries, the values of which are either a single argument
* value (if only one was found), or an array of multiple argument values if the pragma is present
* in multiple places
*/
/* @internal */
export interface PragmaMap extends Map<PragmaPsuedoMap[keyof PragmaPsuedoMap] | PragmaPsuedoMap[keyof PragmaPsuedoMap][]> {
set<TKey extends keyof PragmaPsuedoMap>(key: TKey, value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][]): this;
get<TKey extends keyof PragmaPsuedoMap>(key: TKey): PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][];
forEach(action: <TKey extends keyof PragmaPsuedoMap>(value: PragmaPsuedoMap[TKey] | PragmaPsuedoMap[TKey][], key: TKey) => void): void;
}
}
+17 -58
View File
@@ -425,8 +425,8 @@ namespace ts {
}
export function isAmbientModule(node: Node): boolean {
return node && node.kind === SyntaxKind.ModuleDeclaration &&
((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(<ModuleDeclaration>node));
return node && isModuleDeclaration(node) &&
(node.name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(node));
}
export function isModuleWithStringLiteralName(node: Node): node is ModuleDeclaration {
@@ -1545,7 +1545,7 @@ namespace ts {
return SpecialPropertyAssignmentKind.None;
}
export function isSpecialPropertyDeclaration(expr: ts.PropertyAccessExpression): boolean {
export function isSpecialPropertyDeclaration(expr: PropertyAccessExpression): boolean {
return isInJavaScriptFile(expr) &&
expr.parent && expr.parent.kind === SyntaxKind.ExpressionStatement &&
!!getJSDocTypeTag(expr.parent);
@@ -1619,10 +1619,10 @@ namespace ts {
function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node: Node): Expression | undefined {
switch (node.kind) {
case ts.SyntaxKind.VariableStatement:
case SyntaxKind.VariableStatement:
const v = getSingleVariableOfVariableStatement(node);
return v && v.initializer;
case ts.SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertyDeclaration:
return (node as PropertyDeclaration).initializer;
}
}
@@ -1717,7 +1717,7 @@ namespace ts {
export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { parent: JSDocTemplateTag }): TypeParameterDeclaration | undefined {
const name = node.name.escapedText;
const { typeParameters } = (node.parent.parent.parent as ts.SignatureDeclaration | ts.InterfaceDeclaration | ts.ClassDeclaration);
const { typeParameters } = (node.parent.parent.parent as SignatureDeclaration | InterfaceDeclaration | ClassDeclaration);
return find(typeParameters, p => p.name.escapedText === name);
}
@@ -1989,40 +1989,6 @@ namespace ts {
return undefined;
}
export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult {
const simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
const isNoDefaultLibRegEx = new RegExp(defaultLibReferenceRegEx.source, "gim");
if (simpleReferenceRegEx.test(comment)) {
if (isNoDefaultLibRegEx.test(comment)) {
return { isNoDefaultLib: true };
}
else {
const refMatchResult = fullTripleSlashReferencePathRegEx.exec(comment);
const refLibResult = !refMatchResult && fullTripleSlashReferenceTypeReferenceDirectiveRegEx.exec(comment);
const match = refMatchResult || refLibResult;
if (match) {
const pos = commentRange.pos + match[1].length + match[2].length;
return {
fileReference: {
pos,
end: pos + match[3].length,
fileName: match[3]
},
isNoDefaultLib: false,
isTypeReferenceDirective: !!refLibResult
};
}
return {
diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax,
isNoDefaultLib: false
};
}
}
return undefined;
}
export function isKeyword(token: SyntaxKind): boolean {
return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword;
}
@@ -3793,27 +3759,20 @@ namespace ts {
}
export function textSpanOverlapsWith(span: TextSpan, other: TextSpan) {
const overlapStart = Math.max(span.start, other.start);
const overlapEnd = Math.min(textSpanEnd(span), textSpanEnd(other));
return overlapStart < overlapEnd;
return textSpanOverlap(span, other) !== undefined;
}
export function textSpanOverlap(span1: TextSpan, span2: TextSpan) {
const overlapStart = Math.max(span1.start, span2.start);
const overlapEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
if (overlapStart < overlapEnd) {
return createTextSpanFromBounds(overlapStart, overlapEnd);
}
return undefined;
const overlap = textSpanIntersection(span1, span2);
return overlap && overlap.length === 0 ? undefined : overlap;
}
export function textSpanIntersectsWithTextSpan(span: TextSpan, other: TextSpan) {
return other.start <= textSpanEnd(span) && textSpanEnd(other) >= span.start;
return decodedTextSpanIntersectsWith(span.start, span.length, other.start, other.length);
}
export function textSpanIntersectsWith(span: TextSpan, start: number, length: number) {
const end = start + length;
return start <= textSpanEnd(span) && end >= span.start;
return decodedTextSpanIntersectsWith(span.start, span.length, start, length);
}
export function decodedTextSpanIntersectsWith(start1: number, length1: number, start2: number, length2: number) {
@@ -3827,12 +3786,9 @@ namespace ts {
}
export function textSpanIntersection(span1: TextSpan, span2: TextSpan) {
const intersectStart = Math.max(span1.start, span2.start);
const intersectEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
if (intersectStart <= intersectEnd) {
return createTextSpanFromBounds(intersectStart, intersectEnd);
}
return undefined;
const start = Math.max(span1.start, span2.start);
const end = Math.min(textSpanEnd(span1), textSpanEnd(span2));
return start <= end ? createTextSpanFromBounds(start, end) : undefined;
}
export function createTextSpan(start: number, length: number): TextSpan {
@@ -4131,6 +4087,7 @@ namespace ts {
return false;
}
try {
// tslint:disable-next-line no-unnecessary-qualifier (making clear this is a global mutation!)
ts.localizedDiagnosticMessages = JSON.parse(fileContents);
}
catch (e) {
@@ -5612,6 +5569,8 @@ namespace ts {
// Statement
export function isIterationStatement(node: Node, lookInLabeledStatements: false): node is IterationStatement;
export function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement | LabeledStatement;
export function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement {
switch (node.kind) {
case SyntaxKind.ForStatement:
+2 -2
View File
@@ -1545,10 +1545,10 @@ namespace ts {
let isDebugInfoEnabled = false;
export const failBadSyntaxKind = shouldAssert(AssertionLevel.Normal)
? (node: Node, message?: string): void => fail(
? (node: Node, message?: string): never => fail(
`${message || "Unexpected node."}\r\nNode ${formatSyntaxKind(node.kind)} was unexpected.`,
failBadSyntaxKind)
: noop;
: noop as () => never; // TODO: GH#22091
export const assertEachNode = shouldAssert(AssertionLevel.Normal)
? (nodes: Node[], test: (node: Node) => boolean, message?: string): void => assert(
+5 -5
View File
@@ -20,7 +20,7 @@ namespace ts {
getCanonicalFileName: createGetCanonicalFileName(system.useCaseSensitiveFileNames),
};
if (!pretty) {
return diagnostic => system.write(ts.formatDiagnostic(diagnostic, host));
return diagnostic => system.write(formatDiagnostic(diagnostic, host));
}
const diagnostics: Diagnostic[] = new Array(1);
@@ -33,6 +33,7 @@ namespace ts {
function clearScreenIfNotWatchingForFileChanges(system: System, diagnostic: Diagnostic, options: CompilerOptions) {
if (system.clearScreen &&
!options.preserveWatchOutput &&
diagnostic.code !== Diagnostics.Compilation_complete_Watching_for_file_changes.code &&
!options.extendedDiagnostics &&
!options.diagnostics) {
@@ -482,9 +483,8 @@ namespace ts {
}
const trace = host.trace && ((s: string) => { host.trace(s + newLine); });
const watchLogLevel = compilerOptions.extendedDiagnostics ? WatchLogLevel.Verbose :
compilerOptions.diagnostics ? WatchLogLevel.TriggerOnly : WatchLogLevel.None;
const watchLogLevel = trace ? compilerOptions.extendedDiagnostics ? WatchLogLevel.Verbose :
compilerOptions.diagnostis ? WatchLogLevel.TriggerOnly : WatchLogLevel.None : WatchLogLevel.None;
const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? trace : noop;
const { watchFile, watchFilePath, watchDirectory: watchDirectoryWorker } = getWatchFactory(watchLogLevel, writeLog);
@@ -826,7 +826,7 @@ namespace ts {
}
function parseConfigFile() {
const configParseResult = ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost);
const configParseResult = getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost);
rootFileNames = configParseResult.fileNames;
compilerOptions = configParseResult.options;
configFileSpecs = configParseResult.configFileSpecs;
+37 -20
View File
@@ -418,7 +418,7 @@ namespace FourSlash {
this.goToPosition(marker.position);
}
public goToEachMarker(markers: ReadonlyArray<Marker>, action: (marker: FourSlash.Marker, index: number) => void) {
public goToEachMarker(markers: ReadonlyArray<Marker>, action: (marker: Marker, index: number) => void) {
assert(markers.length);
for (let i = 0; i < markers.length; i++) {
this.goToMarker(markers[i]);
@@ -505,9 +505,12 @@ namespace FourSlash {
return "\nMarker: " + this.lastKnownMarker + "\nChecking: " + msg + "\n\n";
}
private getDiagnostics(fileName: string): ts.Diagnostic[] {
return ts.concatenate(this.languageService.getSyntacticDiagnostics(fileName),
this.languageService.getSemanticDiagnostics(fileName));
private getDiagnostics(fileName: string, includeSuggestions = false): ts.Diagnostic[] {
return [
...this.languageService.getSyntacticDiagnostics(fileName),
...this.languageService.getSemanticDiagnostics(fileName),
...(includeSuggestions ? this.languageService.getSuggestionDiagnostics(fileName) : ts.emptyArray),
];
}
private getAllDiagnostics(): ts.Diagnostic[] {
@@ -580,8 +583,9 @@ namespace FourSlash {
public verifyNoErrors() {
ts.forEachKey(this.inputFiles, fileName => {
if (!ts.isAnySupportedFileExtension(fileName)) return;
const errors = this.getDiagnostics(fileName);
if (!ts.isAnySupportedFileExtension(fileName)
|| !this.getProgram().getCompilerOptions().allowJs && !ts.extensionIsTypeScript(ts.extensionFromPath(fileName))) return;
const errors = this.getDiagnostics(fileName).filter(e => e.category !== ts.DiagnosticCategory.Suggestion);
if (errors.length) {
this.printErrorLog(/*expectErrors*/ false, errors);
const error = errors[0];
@@ -1236,20 +1240,23 @@ Actual: ${stringify(fullActual)}`);
return this.languageService.findReferences(this.activeFile.fileName, this.currentCaretPosition);
}
public getSyntacticDiagnostics(expected: string) {
public getSyntacticDiagnostics(expected: ReadonlyArray<FourSlashInterface.Diagnostic>) {
const diagnostics = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName);
this.testDiagnostics(expected, diagnostics);
this.testDiagnostics(expected, diagnostics, "error");
}
public getSemanticDiagnostics(expected: string) {
public getSemanticDiagnostics(expected: ReadonlyArray<FourSlashInterface.Diagnostic>) {
const diagnostics = this.languageService.getSemanticDiagnostics(this.activeFile.fileName);
this.testDiagnostics(expected, diagnostics);
this.testDiagnostics(expected, diagnostics, "error");
}
private testDiagnostics(expected: string, diagnostics: ReadonlyArray<ts.Diagnostic>) {
const realized = ts.realizeDiagnostics(diagnostics, "\r\n");
const actual = stringify(realized);
assert.equal(actual, expected);
public getSuggestionDiagnostics(expected: ReadonlyArray<FourSlashInterface.Diagnostic>): void {
this.testDiagnostics(expected, this.languageService.getSuggestionDiagnostics(this.activeFile.fileName), "suggestion");
}
private testDiagnostics(expected: ReadonlyArray<FourSlashInterface.Diagnostic>, diagnostics: ReadonlyArray<ts.Diagnostic>, category: string) {
assert.deepEqual(ts.realizeDiagnostics(diagnostics, ts.newLineCharacter), expected.map<ts.RealizedDiagnostic>(e => (
{ message: e.message, category, code: e.code, ...ts.createTextSpanFromRange(e.range || this.getRanges()[0]) })));
}
public verifyQuickInfoAt(markerName: string, expectedText: string, expectedDocumentation?: string) {
@@ -2350,7 +2357,7 @@ Actual: ${stringify(fullActual)}`);
this.verifyClassifications(expected, actual, this.activeFile.content);
}
public verifyOutliningSpans(spans: FourSlash.Range[]) {
public verifyOutliningSpans(spans: Range[]) {
const actual = this.languageService.getOutliningSpans(this.activeFile.fileName);
if (actual.length !== spans.length) {
@@ -2516,7 +2523,7 @@ Actual: ${stringify(fullActual)}`);
* @param fileName Path to file where error should be retrieved from.
*/
private getCodeFixes(fileName: string, errorCode?: number): ts.CodeFixAction[] {
const diagnosticsForCodeFix = this.getDiagnostics(fileName).map(diagnostic => ({
const diagnosticsForCodeFix = this.getDiagnostics(fileName, /*includeSuggestions*/ true).map(diagnostic => ({
start: diagnostic.start,
length: diagnostic.length,
code: diagnostic.code
@@ -3284,7 +3291,7 @@ ${code}
const format = new FourSlashInterface.Format(state);
const cancellation = new FourSlashInterface.Cancellation(state);
const f = eval(wrappedCode);
f(test, goTo, verify, edit, debug, format, cancellation, FourSlashInterface.Classification, FourSlash.verifyOperationIsCancelled);
f(test, goTo, verify, edit, debug, format, cancellation, FourSlashInterface.Classification, verifyOperationIsCancelled);
}
catch (err) {
throw err;
@@ -3957,7 +3964,7 @@ namespace FourSlashInterface {
this.state.verifySpanOfEnclosingComment(this.negative, onlyMultiLineDiverges);
}
public codeFix(options: FourSlashInterface.VerifyCodeFixOptions) {
public codeFix(options: VerifyCodeFixOptions) {
this.state.verifyCodeFix(options);
}
@@ -4321,14 +4328,18 @@ namespace FourSlashInterface {
this.state.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation, tags);
}
public getSyntacticDiagnostics(expected: string) {
public getSyntacticDiagnostics(expected: ReadonlyArray<ts.RealizedDiagnostic>) {
this.state.getSyntacticDiagnostics(expected);
}
public getSemanticDiagnostics(expected: string) {
public getSemanticDiagnostics(expected: ReadonlyArray<ts.RealizedDiagnostic>) {
this.state.getSemanticDiagnostics(expected);
}
public getSuggestionDiagnostics(expected: ReadonlyArray<ts.RealizedDiagnostic>) {
this.state.getSuggestionDiagnostics(expected);
}
public ProjectInfo(expected: string[]) {
this.state.verifyProjectInfo(expected);
}
@@ -4667,4 +4678,10 @@ namespace FourSlashInterface {
source?: string;
description: string;
}
export interface Diagnostic {
message: string;
range?: FourSlash.Range;
code: number;
}
}
+38 -38
View File
@@ -242,7 +242,7 @@ namespace Utils {
start: diagnostic.start,
length: diagnostic.length,
messageText: ts.flattenDiagnosticMessageText(diagnostic.messageText, Harness.IO.newLine()),
category: (<any>ts).DiagnosticCategory[diagnostic.category],
category: ts.diagnosticCategoryName(diagnostic, /*lowerCase*/ false),
code: diagnostic.code
};
}
@@ -336,7 +336,7 @@ namespace Utils {
case "referenceDiagnostics":
case "parseDiagnostics":
o[propertyName] = Utils.convertDiagnostics((<any>n)[propertyName]);
o[propertyName] = convertDiagnostics((<any>n)[propertyName]);
break;
case "nextContainer":
@@ -852,7 +852,7 @@ namespace Harness {
sourceText: string,
languageVersion: ts.ScriptTarget) {
// We'll only assert invariants outside of light mode.
const shouldAssertInvariants = !Harness.lightMode;
const shouldAssertInvariants = !lightMode;
// Only set the parent nodes if we're asserting invariants. We don't need them otherwise.
const result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ shouldAssertInvariants);
@@ -984,7 +984,7 @@ namespace Harness {
}
else if (fileName === fourslashFileName) {
const tsFn = "tests/cases/fourslash/" + fourslashFileName;
fourslashSourceFile = fourslashSourceFile || createSourceFileAndAssertInvariants(tsFn, Harness.IO.readFile(tsFn), scriptTarget);
fourslashSourceFile = fourslashSourceFile || createSourceFileAndAssertInvariants(tsFn, IO.readFile(tsFn), scriptTarget);
return fourslashSourceFile;
}
else if (ts.startsWith(fileName, "tests/lib/")) {
@@ -1000,7 +1000,7 @@ namespace Harness {
const newLine =
newLineKind === ts.NewLineKind.CarriageReturnLineFeed ? carriageReturnLineFeed :
newLineKind === ts.NewLineKind.LineFeed ? lineFeed :
Harness.IO.newLine();
IO.newLine();
function toPath(fileName: string): ts.Path {
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
@@ -1103,7 +1103,7 @@ namespace Harness {
return optionsIndex.get(name.toLowerCase());
}
export function setCompilerOptionsFromHarnessSetting(settings: Harness.TestCaseParser.CompilerSettings, options: ts.CompilerOptions & HarnessOptions): void {
export function setCompilerOptionsFromHarnessSetting(settings: TestCaseParser.CompilerSettings, options: ts.CompilerOptions & HarnessOptions): void {
for (const name in settings) {
if (settings.hasOwnProperty(name)) {
const value = settings[name];
@@ -1171,7 +1171,7 @@ namespace Harness {
options.skipDefaultLibCheck = typeof options.skipDefaultLibCheck === "undefined" ? true : options.skipDefaultLibCheck;
if (typeof currentDirectory === "undefined") {
currentDirectory = Harness.IO.getCurrentDirectory();
currentDirectory = IO.getCurrentDirectory();
}
// Parse settings
@@ -1182,7 +1182,7 @@ namespace Harness {
options.rootDirs = ts.map(options.rootDirs, d => ts.getNormalizedAbsolutePath(d, currentDirectory));
}
const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : Harness.IO.useCaseSensitiveFileNames();
const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : IO.useCaseSensitiveFileNames();
const programFiles: TestFile[] = inputFiles.slice();
// Files from built\local that are requested by test "@includeBuiltFiles" to be in the context.
// Treat them as library files, so include them in build, but not in baselines.
@@ -1190,7 +1190,7 @@ namespace Harness {
const builtFileName = ts.combinePaths(libFolder, options.includeBuiltFile);
const builtFile: TestFile = {
unitName: builtFileName,
content: normalizeLineEndings(IO.readFile(builtFileName), Harness.IO.newLine()),
content: normalizeLineEndings(IO.readFile(builtFileName), IO.newLine()),
};
programFiles.push(builtFile);
}
@@ -1232,7 +1232,7 @@ namespace Harness {
const errors = ts.getPreEmitDiagnostics(program);
const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps, traceResults);
const result = new CompilerResult(fileOutputs, errors, program, IO.getCurrentDirectory(), emitResult.sourceMaps, traceResults);
return { result, options };
}
@@ -1336,7 +1336,7 @@ namespace Harness {
}
export function minimalDiagnosticsToString(diagnostics: ReadonlyArray<ts.Diagnostic>, pretty?: boolean) {
const host = { getCanonicalFileName, getCurrentDirectory: () => "", getNewLine: () => Harness.IO.newLine() };
const host = { getCanonicalFileName, getCurrentDirectory: () => "", getNewLine: () => IO.newLine() };
return (pretty ? ts.formatDiagnosticsWithColorAndContext : ts.formatDiagnostics)(diagnostics, host);
}
@@ -1370,13 +1370,13 @@ namespace Harness {
}
function outputErrorText(error: ts.Diagnostic) {
const message = ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine());
const message = ts.flattenDiagnosticMessageText(error.messageText, IO.newLine());
const errLines = RunnerBase.removeFullPaths(message)
.split("\n")
.map(s => s.length > 0 && s.charAt(s.length - 1) === "\r" ? s.substr(0, s.length - 1) : s)
.filter(s => s.length > 0)
.map(s => "!!! " + ts.DiagnosticCategory[error.category].toLowerCase() + " TS" + error.code + ": " + s);
.map(s => "!!! " + ts.diagnosticCategoryName(error) + " TS" + error.code + ": " + s);
errLines.forEach(e => outputLines += (newLine() + e));
errorsReported++;
@@ -1390,7 +1390,7 @@ namespace Harness {
}
}
yield [diagnosticSummaryMarker, minimalDiagnosticsToString(diagnostics, pretty) + Harness.IO.newLine() + Harness.IO.newLine(), diagnostics.length];
yield [diagnosticSummaryMarker, minimalDiagnosticsToString(diagnostics, pretty) + IO.newLine() + IO.newLine(), diagnostics.length];
// Report global errors
const globalErrors = diagnostics.filter(err => !err.file);
@@ -1486,7 +1486,7 @@ namespace Harness {
}
export function doErrorBaseline(baselinePath: string, inputFiles: TestFile[], errors: ts.Diagnostic[], pretty?: boolean) {
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), (): string => {
Baseline.runBaseline(baselinePath.replace(/\.tsx?$/, ".errors.txt"), (): string => {
if (!errors || (errors.length === 0)) {
/* tslint:disable:no-null-keyword */
return null;
@@ -1496,7 +1496,7 @@ namespace Harness {
});
}
export function doTypeAndSymbolBaseline(baselinePath: string, program: ts.Program, allFiles: {unitName: string, content: string}[], opts?: Harness.Baseline.BaselineOptions, multifile?: boolean, skipTypeBaselines?: boolean, skipSymbolBaselines?: boolean) {
export function doTypeAndSymbolBaseline(baselinePath: string, program: ts.Program, allFiles: {unitName: string, content: string}[], opts?: Baseline.BaselineOptions, multifile?: boolean, skipTypeBaselines?: boolean, skipSymbolBaselines?: boolean) {
// The full walker simulates the types that you would get from doing a full
// compile. The pull walker simulates the types you get when you just do
// a type query for a random node (like how the LS would do it). Most of the
@@ -1532,7 +1532,7 @@ namespace Harness {
}
if (typesError && symbolsError) {
throw new Error(typesError.stack + Harness.IO.newLine() + symbolsError.stack);
throw new Error(typesError.stack + IO.newLine() + symbolsError.stack);
}
if (typesError) {
@@ -1555,10 +1555,10 @@ namespace Harness {
if (!multifile) {
const fullBaseLine = generateBaseLine(isSymbolBaseLine, isSymbolBaseLine ? skipSymbolBaselines : skipTypeBaselines);
Harness.Baseline.runBaseline(outputFileName + fullExtension, () => fullBaseLine, opts);
Baseline.runBaseline(outputFileName + fullExtension, () => fullBaseLine, opts);
}
else {
Harness.Baseline.runMultifileBaseline(outputFileName, fullExtension, () => {
Baseline.runMultifileBaseline(outputFileName, fullExtension, () => {
return iterateBaseLine(isSymbolBaseLine, isSymbolBaseLine ? skipSymbolBaselines : skipTypeBaselines);
}, opts);
}
@@ -1627,11 +1627,11 @@ namespace Harness {
}
}
function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string {
function getByteOrderMarkText(file: GeneratedFile): string {
return file.writeByteOrderMark ? "\u00EF\u00BB\u00BF" : "";
}
export function doSourcemapBaseline(baselinePath: string, options: ts.CompilerOptions, result: CompilerResult, harnessSettings: Harness.TestCaseParser.CompilerSettings) {
export function doSourcemapBaseline(baselinePath: string, options: ts.CompilerOptions, result: CompilerResult, harnessSettings: TestCaseParser.CompilerSettings) {
if (options.inlineSourceMap) {
if (result.sourceMaps.length > 0) {
throw new Error("No sourcemap files should be generated if inlineSourceMaps was set.");
@@ -1643,7 +1643,7 @@ namespace Harness {
throw new Error("Number of sourcemap files should be same as js files.");
}
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ".js.map"), () => {
Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ".js.map"), () => {
if ((options.noEmitOnError && result.errors.length !== 0) || result.sourceMaps.length === 0) {
// We need to return null here or the runBaseLine will actually create a empty file.
// Baselining isn't required here because there is no output.
@@ -1662,13 +1662,13 @@ namespace Harness {
}
}
export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: CompilerResult, tsConfigFiles: Harness.Compiler.TestFile[], toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], harnessSettings: Harness.TestCaseParser.CompilerSettings) {
export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: CompilerResult, tsConfigFiles: TestFile[], toBeCompiled: TestFile[], otherFiles: TestFile[], harnessSettings: TestCaseParser.CompilerSettings) {
if (!options.noEmit && !options.emitDeclarationOnly && result.files.length === 0 && result.errors.length === 0) {
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
}
// check js output
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ts.Extension.Js), () => {
Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ts.Extension.Js), () => {
let tsCode = "";
const tsSources = otherFiles.concat(toBeCompiled);
if (tsSources.length > 1) {
@@ -1691,15 +1691,15 @@ namespace Harness {
}
}
const declFileContext = Harness.Compiler.prepareDeclarationCompilationContext(
const declFileContext = prepareDeclarationCompilationContext(
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined
);
const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(declFileContext);
const declFileCompilationResult = compileDeclarationFiles(declFileContext);
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
jsCode += "\r\n\r\n";
jsCode += Harness.Compiler.getErrorBaseline(tsConfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
jsCode += getErrorBaseline(tsConfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors);
}
if (jsCode.length > 0) {
@@ -1713,12 +1713,12 @@ namespace Harness {
});
}
function fileOutput(file: GeneratedFile, harnessSettings: Harness.TestCaseParser.CompilerSettings): string {
function fileOutput(file: GeneratedFile, harnessSettings: TestCaseParser.CompilerSettings): string {
const fileName = harnessSettings.fullEmitPaths ? file.fileName : ts.getBaseFileName(file.fileName);
return "//// [" + fileName + "]\r\n" + getByteOrderMarkText(file) + file.code;
}
export function collateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): string {
export function collateOutputs(outputFiles: GeneratedFile[]): string {
const gen = iterateOutputs(outputFiles);
// Emit them
let result = "";
@@ -1734,7 +1734,7 @@ namespace Harness {
return result;
}
export function *iterateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): IterableIterator<[string, string]> {
export function *iterateOutputs(outputFiles: GeneratedFile[]): IterableIterator<[string, string]> {
// Collect, test, and sort the fileNames
outputFiles.sort((a, b) => ts.compareStringsCaseSensitive(cleanName(a.fileName), cleanName(b.fileName)));
const dupeCase = ts.createMap<number>();
@@ -1839,7 +1839,7 @@ namespace Harness {
public getSourceMapRecord() {
if (this.sourceMapData && this.sourceMapData.length > 0) {
return Harness.SourceMapRecorder.getSourceMapRecord(this.sourceMapData, this.program, this.files);
return SourceMapRecorder.getSourceMapRecord(this.sourceMapData, this.program, this.files);
}
}
}
@@ -2020,10 +2020,10 @@ namespace Harness {
function baselinePath(fileName: string, type: string, baselineFolder: string, subfolder?: string) {
if (subfolder !== undefined) {
return Harness.userSpecifiedRoot + baselineFolder + "/" + subfolder + "/" + type + "/" + fileName;
return userSpecifiedRoot + baselineFolder + "/" + subfolder + "/" + type + "/" + fileName;
}
else {
return Harness.userSpecifiedRoot + baselineFolder + "/" + type + "/" + fileName;
return userSpecifiedRoot + baselineFolder + "/" + type + "/" + fileName;
}
}
@@ -2082,7 +2082,7 @@ namespace Harness {
}
// Create folders if needed
createDirectoryStructure(Harness.IO.directoryName(actualFileName));
createDirectoryStructure(IO.directoryName(actualFileName));
// Delete the actual file in case it fails
if (IO.fileExists(actualFileName)) {
@@ -2131,7 +2131,7 @@ namespace Harness {
}
const referenceDir = referencePath(relativeFileBase, opts && opts.Baselinefolder, opts && opts.Subfolder);
let existing = Harness.IO.readDirectory(referenceDir, referencedExtensions || [extension]);
let existing = IO.readDirectory(referenceDir, referencedExtensions || [extension]);
if (extension === ".ts" || referencedExtensions && referencedExtensions.indexOf(".ts") > -1 && referencedExtensions.indexOf(".d.ts") === -1) {
// special-case and filter .d.ts out of .ts results
existing = existing.filter(f => !ts.endsWith(f, ".d.ts"));
@@ -2173,11 +2173,11 @@ namespace Harness {
}
export function isBuiltFile(filePath: string): boolean {
return filePath.indexOf(Harness.libFolder) === 0;
return ts.startsWith(filePath, libFolder);
}
export function getDefaultLibraryFile(filePath: string, io: Harness.Io): Harness.Compiler.TestFile {
const libFile = Harness.userSpecifiedRoot + Harness.libFolder + ts.getBaseFileName(ts.normalizeSlashes(filePath));
export function getDefaultLibraryFile(filePath: string, io: Io): Compiler.TestFile {
const libFile = userSpecifiedRoot + libFolder + ts.getBaseFileName(ts.normalizeSlashes(filePath));
return { unitName: libFile, content: io.readFile(libFile) };
}
+6 -3
View File
@@ -192,7 +192,7 @@ namespace Harness.LanguageService {
return dir && dir.isDirectory() ? dir.getDirectories().map(d => d.name) : [];
}
getCurrentDirectory(): string { return virtualFileSystemRoot; }
getDefaultLibFileName(): string { return Harness.Compiler.defaultLibFileName; }
getDefaultLibFileName(): string { return Compiler.defaultLibFileName; }
getScriptFileNames(): string[] {
return this.getFilenames().filter(ts.isAnySupportedFileExtension);
}
@@ -402,6 +402,9 @@ namespace Harness.LanguageService {
getSemanticDiagnostics(fileName: string): ts.Diagnostic[] {
return unwrapJSONCallResult(this.shim.getSemanticDiagnostics(fileName));
}
getSuggestionDiagnostics(fileName: string): ts.Diagnostic[] {
return unwrapJSONCallResult(this.shim.getSuggestionDiagnostics(fileName));
}
getCompilerOptionsDiagnostics(): ts.Diagnostic[] {
return unwrapJSONCallResult(this.shim.getCompilerOptionsDiagnostics());
}
@@ -638,8 +641,8 @@ namespace Harness.LanguageService {
}
readFile(fileName: string): string | undefined {
if (fileName.indexOf(Harness.Compiler.defaultLibFileName) >= 0) {
fileName = Harness.Compiler.defaultLibFileName;
if (ts.stringContains(fileName, Compiler.defaultLibFileName)) {
fileName = Compiler.defaultLibFileName;
}
const snapshot = this.host.getScriptSnapshot(fileName);
+5 -5
View File
@@ -33,7 +33,7 @@ namespace Harness.Parallel.Host {
return `${perfdataFileNameFragment}${target ? `.${target}` : ""}.json`;
}
function readSavedPerfData(target?: string): {[testHash: string]: number} {
const perfDataContents = Harness.IO.readFile(perfdataFileName(target));
const perfDataContents = IO.readFile(perfdataFileName(target));
if (perfDataContents) {
return JSON.parse(perfDataContents);
}
@@ -90,7 +90,7 @@ namespace Harness.Parallel.Host {
catch {
// May be a directory
try {
size = Harness.IO.listFiles(path.join(runner.workingDirectory, file), /.*/g, { recursive: true }).reduce((acc, elem) => acc + statSync(elem).size, 0);
size = IO.listFiles(path.join(runner.workingDirectory, file), /.*/g, { recursive: true }).reduce((acc, elem) => acc + statSync(elem).size, 0);
}
catch {
// Unknown test kind, just return 0 and let the historical analysis take over after one run
@@ -144,9 +144,9 @@ namespace Harness.Parallel.Host {
let closedWorkers = 0;
for (let i = 0; i < workerCount; i++) {
// TODO: Just send the config over the IPC channel or in the command line arguments
const config: TestConfig = { light: Harness.lightMode, listenForWork: true, runUnitTests };
const config: TestConfig = { light: lightMode, listenForWork: true, runUnitTests };
const configPath = ts.combinePaths(taskConfigsFolder, `task-config${i}.json`);
Harness.IO.writeFile(configPath, JSON.stringify(config));
IO.writeFile(configPath, JSON.stringify(config));
const child = fork(__filename, [`--config="${configPath}"`]);
let currentTimeout = defaultTimeout;
const killChild = () => {
@@ -364,7 +364,7 @@ namespace Harness.Parallel.Host {
reporter.epilogue();
}
Harness.IO.writeFile(perfdataFileName(configOption), JSON.stringify(newPerfData, null, 4)); // tslint:disable-line:no-null-keyword
IO.writeFile(perfdataFileName(configOption), JSON.stringify(newPerfData, null, 4)); // tslint:disable-line:no-null-keyword
process.exit(errorResults.length);
}
+2 -2
View File
@@ -55,7 +55,7 @@ namespace RWC {
});
it("can compile", function(this: Mocha.ITestCallbackContext) {
this.timeout(800000); // Allow long timeouts for RWC compilations
this.timeout(800_000); // Allow long timeouts for RWC compilations
let opts: ts.ParsedCommandLine;
const ioLog: IoLog = Playback.newStyleLogIntoOldStyleLog(JSON.parse(Harness.IO.readFile(`internal/cases/rwc/${jsonPath}/test.json`)), Harness.IO, `internal/cases/rwc/${baseName}`);
@@ -171,7 +171,7 @@ namespace RWC {
it("has the expected emitted code", function(this: Mocha.ITestCallbackContext) {
this.timeout(10000); // Allow long timeouts for RWC js verification
this.timeout(100_000); // Allow longer timeouts for RWC js verification
Harness.Baseline.runMultifileBaseline(baseName, "", () => {
return Harness.Compiler.iterateOutputs(compilerResult.files);
}, baselineOpts, [".js", ".jsx"]);
+1 -1
View File
@@ -79,7 +79,7 @@ class TypeWriterWalker {
// Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions
// let type = this.checker.getTypeAtLocation(node);
const type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node);
const typeString = type ? this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation) : "No type information available!";
const typeString = type ? this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.AllowUniqueESSymbolType) : "No type information available!";
return {
line: lineAndCharacter.line,
syntaxKind: node.kind,
+40 -43
View File
@@ -4,8 +4,8 @@
namespace ts {
describe("parseCommandLine", () => {
function assertParseResult(commandLine: string[], expectedParsedCommandLine: ts.ParsedCommandLine) {
const parsed = ts.parseCommandLine(commandLine);
function assertParseResult(commandLine: string[], expectedParsedCommandLine: ParsedCommandLine) {
const parsed = parseCommandLine(commandLine);
const parsedCompilerOptions = JSON.stringify(parsed.options);
const expectedCompilerOptions = JSON.stringify(expectedParsedCommandLine.options);
assert.equal(parsedCompilerOptions, expectedCompilerOptions);
@@ -60,10 +60,9 @@ namespace ts {
assertParseResult(["--lib", "es5,invalidOption", "0.ts"],
{
errors: [{
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.asynciterable'.",
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
file: undefined,
start: undefined,
length: undefined,
@@ -80,16 +79,16 @@ namespace ts {
{
errors: [{
messageText: "Compiler option 'jsx' expects an argument.",
category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category,
code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code,
category: Diagnostics.Compiler_option_0_expects_an_argument.category,
code: Diagnostics.Compiler_option_0_expects_an_argument.code,
file: undefined,
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
file: undefined,
start: undefined,
@@ -106,16 +105,16 @@ namespace ts {
{
errors: [{
messageText: "Compiler option 'module' expects an argument.",
category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category,
code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code,
category: Diagnostics.Compiler_option_0_expects_an_argument.category,
code: Diagnostics.Compiler_option_0_expects_an_argument.code,
file: undefined,
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'esnext'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
file: undefined,
start: undefined,
@@ -132,16 +131,16 @@ namespace ts {
{
errors: [{
messageText: "Compiler option 'newLine' expects an argument.",
category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category,
code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code,
category: Diagnostics.Compiler_option_0_expects_an_argument.category,
code: Diagnostics.Compiler_option_0_expects_an_argument.code,
file: undefined,
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
file: undefined,
start: undefined,
@@ -158,16 +157,16 @@ namespace ts {
{
errors: [{
messageText: "Compiler option 'target' expects an argument.",
category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category,
code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code,
category: Diagnostics.Compiler_option_0_expects_an_argument.category,
code: Diagnostics.Compiler_option_0_expects_an_argument.code,
file: undefined,
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'esnext'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
file: undefined,
start: undefined,
@@ -184,16 +183,16 @@ namespace ts {
{
errors: [{
messageText: "Compiler option 'moduleResolution' expects an argument.",
category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category,
code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code,
category: Diagnostics.Compiler_option_0_expects_an_argument.category,
code: Diagnostics.Compiler_option_0_expects_an_argument.code,
file: undefined,
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
file: undefined,
start: undefined,
@@ -210,8 +209,8 @@ namespace ts {
{
errors: [{
messageText: "Compiler option 'lib' expects an argument.",
category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category,
code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code,
category: Diagnostics.Compiler_option_0_expects_an_argument.category,
code: Diagnostics.Compiler_option_0_expects_an_argument.code,
file: undefined,
start: undefined,
@@ -231,8 +230,8 @@ namespace ts {
{
errors: [{
messageText: "Compiler option 'lib' expects an argument.",
category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category,
code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code,
category: Diagnostics.Compiler_option_0_expects_an_argument.category,
code: Diagnostics.Compiler_option_0_expects_an_argument.code,
file: undefined,
start: undefined,
@@ -263,10 +262,9 @@ namespace ts {
assertParseResult(["--lib", "es5,", "es7", "0.ts"],
{
errors: [{
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.asynciterable'.",
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
file: undefined,
start: undefined,
length: undefined,
@@ -283,10 +281,9 @@ namespace ts {
assertParseResult(["--lib", "es5, ", "es7", "0.ts"],
{
errors: [{
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.asynciterable'.",
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
file: undefined,
start: undefined,
length: undefined,
@@ -306,7 +303,7 @@ namespace ts {
fileNames: ["0.ts"],
options: {
lib: ["lib.es5.d.ts", "lib.es2015.symbol.wellknown.d.ts"],
target: ts.ScriptTarget.ES5,
target: ScriptTarget.ES5,
}
});
});
@@ -318,8 +315,8 @@ namespace ts {
errors: [],
fileNames: ["0.ts"],
options: {
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES5,
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
lib: ["lib.es5.d.ts", "lib.es2015.symbol.wellknown.d.ts"],
}
});
@@ -332,8 +329,8 @@ namespace ts {
errors: [],
fileNames: ["0.ts"],
options: {
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES5,
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
lib: ["lib.es2015.core.d.ts", "lib.es2015.symbol.wellknown.d.ts"],
}
});
+4 -4
View File
@@ -13,8 +13,8 @@ namespace ts.projectSystem {
describe("CompileOnSave affected list", () => {
function sendAffectedFileRequestAndCheckResult(session: server.Session, request: server.protocol.Request, expectedFileList: { projectFileName: string, files: FileOrFolder[] }[]) {
const response = session.executeCommand(request).response as server.protocol.CompileOnSaveAffectedFileListSingleProject[];
const actualResult = response.sort((list1, list2) => ts.compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName));
expectedFileList = expectedFileList.sort((list1, list2) => ts.compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName));
const actualResult = response.sort((list1, list2) => compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName));
expectedFileList = expectedFileList.sort((list1, list2) => compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName));
assert.equal(actualResult.length, expectedFileList.length, `Actual result project number is different from the expected project number`);
@@ -517,7 +517,7 @@ namespace ts.projectSystem {
const lines = ["var x = 1;", "var y = 2;"];
const path = "/a/app";
const f = {
path: path + ts.Extension.Ts,
path: path + Extension.Ts,
content: lines.join(newLine)
};
const host = createServerHost([f], { newLine });
@@ -536,7 +536,7 @@ namespace ts.projectSystem {
arguments: { file: f.path }
};
session.executeCommand(emitFileRequest);
const emitOutput = host.readFile(path + ts.Extension.Js);
const emitOutput = host.readFile(path + Extension.Js);
assert.equal(emitOutput, f.content + newLine, "content of emit output should be identical with the input + newline");
}
});
@@ -129,17 +129,17 @@ namespace ts {
["under a case sensitive host", caseSensitiveBasePath, caseSensitiveHost]
], ([testName, basePath, host]) => {
function getParseCommandLine(entry: string) {
const {config, error} = ts.readConfigFile(entry, name => host.readFile(name));
const {config, error} = readConfigFile(entry, name => host.readFile(name));
assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n"));
return ts.parseJsonConfigFileContent(config, host, basePath, {}, entry);
return parseJsonConfigFileContent(config, host, basePath, {}, entry);
}
function getParseCommandLineJsonSourceFile(entry: string) {
const jsonSourceFile = ts.readJsonConfigFile(entry, name => host.readFile(name));
const jsonSourceFile = readJsonConfigFile(entry, name => host.readFile(name));
assert(jsonSourceFile.endOfFileToken && !jsonSourceFile.parseDiagnostics.length, flattenDiagnosticMessageText(jsonSourceFile.parseDiagnostics[0] && jsonSourceFile.parseDiagnostics[0].messageText, "\n"));
return {
jsonSourceFile,
parsed: ts.parseJsonSourceFileConfigFileContent(jsonSourceFile, host, basePath, {}, entry)
parsed: parseJsonSourceFileConfigFileContent(jsonSourceFile, host, basePath, {}, entry)
};
}
@@ -266,7 +266,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.asynciterable'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -297,7 +297,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.asynciterable'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -328,7 +328,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.asynciterable'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -359,7 +359,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.array', 'esnext.asynciterable', 'esnext.promise'.",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.asynciterable'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
+1 -1
View File
@@ -3,7 +3,7 @@
namespace ts {
describe("convertToBase64", () => {
function runTest(input: string): void {
const actual = ts.convertToBase64(input);
const actual = convertToBase64(input);
const expected = new Buffer(input).toString("base64");
assert.equal(actual, expected, "Encoded string using convertToBase64 does not match buffer.toString('base64')");
}
+2 -2
View File
@@ -27,9 +27,9 @@ namespace ts {
const expectedRange = t.ranges.get("extracted");
if (expectedRange) {
let pos: number, end: number;
if (ts.isArray(result.targetRange.range)) {
if (isArray(result.targetRange.range)) {
pos = result.targetRange.range[0].getStart(f);
end = ts.lastOrUndefined(result.targetRange.range).getEnd();
end = lastOrUndefined(result.targetRange.range).getEnd();
}
else {
pos = result.targetRange.range.getStart(f);
+2 -2
View File
@@ -67,12 +67,12 @@ namespace ts {
}
export const newLineCharacter = "\n";
export const testFormatOptions: ts.FormatCodeSettings = {
export const testFormatOptions: FormatCodeSettings = {
indentSize: 4,
tabSize: 4,
newLineCharacter,
convertTabsToSpaces: true,
indentStyle: ts.IndentStyle.Smart,
indentStyle: IndentStyle.Smart,
insertSpaceAfterConstructor: false,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
+1 -1
View File
@@ -17,7 +17,7 @@ namespace ts {
getDefaultLibFileName: () => "lib.d.ts",
getCurrentDirectory: () => "",
};
return ts.createLanguageService(lshost);
return createLanguageService(lshost);
}
function verifyNewLines(content: string, options: CompilerOptions) {
+1 -1
View File
@@ -2,7 +2,7 @@
/// <reference path="..\..\compiler\parser.ts" />
namespace ts {
ts.disableIncrementalParsing = false;
ts.disableIncrementalParsing = false; // tslint:disable-line no-unnecessary-qualifier (make clear this is a global mutation!)
function withChange(text: IScriptSnapshot, start: number, length: number, newText: string): { text: IScriptSnapshot; textChangeRange: TextChangeRange; } {
const contents = getSnapshotText(text);
+7 -7
View File
@@ -6,7 +6,7 @@ namespace ts {
describe("TypeExpressions", () => {
function parsesCorrectly(name: string, content: string) {
it(name, () => {
const typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content);
const typeAndDiagnostics = parseJSDocTypeExpressionForTests(content);
assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0, "no errors issued");
Harness.Baseline.runBaseline("JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json",
@@ -16,7 +16,7 @@ namespace ts {
function parsesIncorrectly(name: string, content: string) {
it(name, () => {
const type = ts.parseJSDocTypeExpressionForTests(content);
const type = parseJSDocTypeExpressionForTests(content);
assert.isTrue(!type || type.diagnostics.length > 0);
});
}
@@ -309,21 +309,21 @@ namespace ts {
});
describe("getFirstToken", () => {
it("gets jsdoc", () => {
const root = ts.createSourceFile("foo.ts", "/** comment */var a = true;", ts.ScriptTarget.ES5, /*setParentNodes*/ true);
const root = createSourceFile("foo.ts", "/** comment */var a = true;", ScriptTarget.ES5, /*setParentNodes*/ true);
assert.isDefined(root);
assert.equal(root.kind, ts.SyntaxKind.SourceFile);
assert.equal(root.kind, SyntaxKind.SourceFile);
const first = root.getFirstToken();
assert.isDefined(first);
assert.equal(first.kind, ts.SyntaxKind.VarKeyword);
assert.equal(first.kind, SyntaxKind.VarKeyword);
});
});
describe("getLastToken", () => {
it("gets jsdoc", () => {
const root = ts.createSourceFile("foo.ts", "var a = true;/** comment */", ts.ScriptTarget.ES5, /*setParentNodes*/ true);
const root = createSourceFile("foo.ts", "var a = true;/** comment */", ScriptTarget.ES5, /*setParentNodes*/ true);
assert.isDefined(root);
const last = root.getLastToken();
assert.isDefined(last);
assert.equal(last.kind, ts.SyntaxKind.EndOfFileToken);
assert.equal(last.kind, SyntaxKind.EndOfFileToken);
});
});
});
+4 -4
View File
@@ -20,7 +20,7 @@ export function Component(x: Config): any;`
// Regression test for GH #18245 - bug in single line comment writer caused a debug assertion when attempting
// to write an alias to a module's default export was referrenced across files and had no default export
it("should be able to create a language service which can respond to deinition requests without throwing", () => {
const languageService = ts.createLanguageService({
const languageService = createLanguageService({
getCompilationSettings() {
return {};
},
@@ -32,13 +32,13 @@ export function Component(x: Config): any;`
},
getScriptSnapshot(fileName) {
if (fileName === ".ts") {
return ts.ScriptSnapshot.fromString("");
return ScriptSnapshot.fromString("");
}
return ts.ScriptSnapshot.fromString(files[fileName] || "");
return ScriptSnapshot.fromString(files[fileName] || "");
},
getCurrentDirectory: () => ".",
getDefaultLibFileName(options) {
return ts.getDefaultLibFilePath(options);
return getDefaultLibFilePath(options);
},
});
const definitions = languageService.getDefinitionAtPosition("foo.ts", 160); // 160 is the latter `vueTemplateHtml` position
+130 -130
View File
@@ -91,17 +91,17 @@ namespace ts {
"c:/dev/g.min.js/.g/g.ts"
]);
function assertParsed(actual: ts.ParsedCommandLine, expected: ts.ParsedCommandLine): void {
function assertParsed(actual: ParsedCommandLine, expected: ParsedCommandLine): void {
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
}
function validateMatches(expected: ts.ParsedCommandLine, json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]) {
function validateMatches(expected: ParsedCommandLine, json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]) {
{
const jsonText = JSON.stringify(json);
const result = parseJsonText(caseInsensitiveTsconfigPath, jsonText);
const actual = ts.parseJsonSourceFileConfigFileContent(result, host, basePath, existingOptions, configFileName, resolutionStack);
const actual = parseJsonSourceFileConfigFileContent(result, host, basePath, existingOptions, configFileName, resolutionStack);
for (const error of expected.errors) {
if (error.file) {
error.file = result;
@@ -110,7 +110,7 @@ namespace ts {
assertParsed(actual, expected);
}
{
const actual = ts.parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack);
const actual = parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack);
expected.errors = expected.errors.map<Diagnostic>(error => ({
category: error.category,
code: error.code,
@@ -130,13 +130,13 @@ namespace ts {
kind: SyntaxKind.SourceFile,
text
};
return ts.createFileDiagnostic(file, start, length, diagnosticMessage, arg0);
return createFileDiagnostic(file, start, length, diagnosticMessage, arg0);
}
describe("matchFiles", () => {
it("with defaults", () => {
const json = {};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -145,7 +145,7 @@ namespace ts {
"c:/dev/x/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
@@ -159,7 +159,7 @@ namespace ts {
"b.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -177,7 +177,7 @@ namespace ts {
"x.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -198,7 +198,7 @@ namespace ts {
"b.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -219,7 +219,7 @@ namespace ts {
"b.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -237,10 +237,10 @@ namespace ts {
"b.js"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
@@ -255,10 +255,10 @@ namespace ts {
"x.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
@@ -276,7 +276,7 @@ namespace ts {
"b.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -302,7 +302,7 @@ namespace ts {
"*/b.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -327,7 +327,7 @@ namespace ts {
"**/b.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -348,7 +348,7 @@ namespace ts {
"**/b.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -368,7 +368,7 @@ namespace ts {
"jspm_packages/a.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -396,7 +396,7 @@ namespace ts {
"b.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -418,7 +418,7 @@ namespace ts {
"jspm_packages/a.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -442,7 +442,7 @@ namespace ts {
"x/*.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -457,8 +457,8 @@ namespace ts {
"c:/dev/x/b.ts"
],
wildcardDirectories: {
"c:/dev/z": ts.WatchDirectoryFlags.None,
"c:/dev/x": ts.WatchDirectoryFlags.None
"c:/dev/z": WatchDirectoryFlags.None,
"c:/dev/x": WatchDirectoryFlags.None
},
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -469,7 +469,7 @@ namespace ts {
"*.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -478,7 +478,7 @@ namespace ts {
"c:/dev/c.d.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.None
"c:/dev": WatchDirectoryFlags.None
},
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -489,7 +489,7 @@ namespace ts {
"*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -498,7 +498,7 @@ namespace ts {
"c:/dev/c.d.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.None
"c:/dev": WatchDirectoryFlags.None
},
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -509,7 +509,7 @@ namespace ts {
"x/?.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -517,7 +517,7 @@ namespace ts {
"c:/dev/x/b.ts"
],
wildcardDirectories: {
"c:/dev/x": ts.WatchDirectoryFlags.None
"c:/dev/x": WatchDirectoryFlags.None
},
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -528,7 +528,7 @@ namespace ts {
"**/a.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -538,7 +538,7 @@ namespace ts {
"c:/dev/z/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -551,7 +551,7 @@ namespace ts {
"z/**/a.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -560,8 +560,8 @@ namespace ts {
"c:/dev/z/a.ts"
],
wildcardDirectories: {
"c:/dev/x": ts.WatchDirectoryFlags.Recursive,
"c:/dev/z": ts.WatchDirectoryFlags.Recursive
"c:/dev/x": WatchDirectoryFlags.Recursive,
"c:/dev/z": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -572,14 +572,14 @@ namespace ts {
"**/A.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
"/dev/A.ts"
],
wildcardDirectories: {
"/dev": ts.WatchDirectoryFlags.Recursive
"/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
@@ -590,15 +590,15 @@ namespace ts {
"*/z.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
@@ -615,14 +615,14 @@ namespace ts {
"**/a.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
"c:/dev/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -637,7 +637,7 @@ namespace ts {
"x"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -646,7 +646,7 @@ namespace ts {
"c:/dev/c.d.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -658,7 +658,7 @@ namespace ts {
"**/a.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -666,7 +666,7 @@ namespace ts {
"c:/dev/x/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
@@ -680,7 +680,7 @@ namespace ts {
"a.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -688,7 +688,7 @@ namespace ts {
"c:/dev/x/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
@@ -700,7 +700,7 @@ namespace ts {
],
exclude: <string[]>[]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -708,7 +708,7 @@ namespace ts {
"c:/dev/x/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
@@ -720,7 +720,7 @@ namespace ts {
"**/node_modules/a.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -729,7 +729,7 @@ namespace ts {
"c:/dev/node_modules/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
@@ -740,14 +740,14 @@ namespace ts {
"*/a.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
"c:/dev/x/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
@@ -759,7 +759,7 @@ namespace ts {
"node_modules/a.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -767,7 +767,7 @@ namespace ts {
"c:/dev/node_modules/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
},
};
validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
@@ -782,17 +782,17 @@ namespace ts {
"js/*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {
allowJs: false
},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
wildcardDirectories: {
"c:/dev/js": ts.WatchDirectoryFlags.None
"c:/dev/js": WatchDirectoryFlags.None
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
@@ -806,7 +806,7 @@ namespace ts {
"js/*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {
allowJs: true
},
@@ -816,7 +816,7 @@ namespace ts {
"c:/dev/js/b.js"
],
wildcardDirectories: {
"c:/dev/js": ts.WatchDirectoryFlags.None
"c:/dev/js": WatchDirectoryFlags.None
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -830,7 +830,7 @@ namespace ts {
"js/*.min.js"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {
allowJs: true
},
@@ -840,7 +840,7 @@ namespace ts {
"c:/dev/js/d.min.js"
],
wildcardDirectories: {
"c:/dev/js": ts.WatchDirectoryFlags.None
"c:/dev/js": WatchDirectoryFlags.None
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -852,7 +852,7 @@ namespace ts {
"c:/ext/*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -862,8 +862,8 @@ namespace ts {
"c:/ext/ext.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.None,
"c:/ext": ts.WatchDirectoryFlags.None
"c:/dev": WatchDirectoryFlags.None,
"c:/ext": WatchDirectoryFlags.None
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -878,14 +878,14 @@ namespace ts {
"**"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
"c:/ext/ext.ts"
],
wildcardDirectories: {
"c:/ext": ts.WatchDirectoryFlags.None
"c:/ext": WatchDirectoryFlags.None
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -899,10 +899,10 @@ namespace ts {
"../**"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))]
,
fileNames: [],
@@ -919,7 +919,7 @@ namespace ts {
"**"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -938,14 +938,14 @@ namespace ts {
"c:/ext/b/a..b.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
"c:/ext/ext.ts",
],
wildcardDirectories: {
"c:/ext": ts.WatchDirectoryFlags.Recursive
"c:/ext": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -956,7 +956,7 @@ namespace ts {
allowJs: false
}
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {
allowJs: false
},
@@ -967,7 +967,7 @@ namespace ts {
"c:/dev/c.tsx",
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
@@ -979,9 +979,9 @@ namespace ts {
allowJs: false
}
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {
jsx: ts.JsxEmit.Preserve,
jsx: JsxEmit.Preserve,
allowJs: false
},
errors: [],
@@ -991,7 +991,7 @@ namespace ts {
"c:/dev/c.tsx",
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
@@ -1003,9 +1003,9 @@ namespace ts {
allowJs: false
}
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {
jsx: ts.JsxEmit.ReactNative,
jsx: JsxEmit.ReactNative,
allowJs: false
},
errors: [],
@@ -1015,7 +1015,7 @@ namespace ts {
"c:/dev/c.tsx",
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
@@ -1026,7 +1026,7 @@ namespace ts {
allowJs: true
}
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {
allowJs: true
},
@@ -1039,7 +1039,7 @@ namespace ts {
"c:/dev/e.jsx",
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
@@ -1051,9 +1051,9 @@ namespace ts {
allowJs: true
}
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {
jsx: ts.JsxEmit.Preserve,
jsx: JsxEmit.Preserve,
allowJs: true
},
errors: [],
@@ -1065,7 +1065,7 @@ namespace ts {
"c:/dev/e.jsx",
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
@@ -1077,9 +1077,9 @@ namespace ts {
allowJs: true
}
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {
jsx: ts.JsxEmit.ReactNative,
jsx: JsxEmit.ReactNative,
allowJs: true
},
errors: [],
@@ -1091,7 +1091,7 @@ namespace ts {
"c:/dev/e.jsx",
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
@@ -1108,7 +1108,7 @@ namespace ts {
"js/a*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {
allowJs: true
},
@@ -1117,7 +1117,7 @@ namespace ts {
"c:/dev/js/d.min.js"
],
wildcardDirectories: {
"c:/dev/js": ts.WatchDirectoryFlags.None
"c:/dev/js": WatchDirectoryFlags.None
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -1130,11 +1130,11 @@ namespace ts {
"**"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
createDiagnosticForConfigFile(json, 12, 4, ts.Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
createDiagnosticForConfigFile(json, 12, 4, Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**"),
createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
@@ -1151,10 +1151,10 @@ namespace ts {
"**"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))
],
fileNames: [],
@@ -1170,7 +1170,7 @@ namespace ts {
"**/x/**/*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -1181,7 +1181,7 @@ namespace ts {
"c:/dev/x/y/b.ts",
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
@@ -1195,7 +1195,7 @@ namespace ts {
"**/x/**"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -1203,7 +1203,7 @@ namespace ts {
"c:/dev/z/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -1217,11 +1217,11 @@ namespace ts {
"**/../*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
createDiagnosticForConfigFile(json, 12, 9, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
createDiagnosticForConfigFile(json, 12, 9, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*"),
createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
@@ -1236,11 +1236,11 @@ namespace ts {
"**/y/../*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
createDiagnosticForConfigFile(json, 12, 11, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
createDiagnosticForConfigFile(json, 12, 11, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*"),
createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
],
fileNames: [],
@@ -1258,10 +1258,10 @@ namespace ts {
"**/.."
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
createDiagnosticForConfigFile(json, 34, 7, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/..")
createDiagnosticForConfigFile(json, 34, 7, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/..")
],
fileNames: [
"c:/dev/a.ts",
@@ -1270,7 +1270,7 @@ namespace ts {
"c:/dev/z/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -1285,10 +1285,10 @@ namespace ts {
"**/y/.."
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
createDiagnosticForConfigFile(json, 34, 9, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..")
createDiagnosticForConfigFile(json, 34, 9, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..")
],
fileNames: [
"c:/dev/a.ts",
@@ -1297,7 +1297,7 @@ namespace ts {
"c:/dev/z/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -1309,12 +1309,12 @@ namespace ts {
const json = {
include: ["z"]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [ "a.ts", "aba.ts", "abz.ts", "b.ts", "bba.ts", "bbz.ts" ].map(x => `c:/dev/z/${x}`),
wildcardDirectories: {
"c:/dev/z": ts.WatchDirectoryFlags.Recursive
"c:/dev/z": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
@@ -1330,7 +1330,7 @@ namespace ts {
"w/*/*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -1338,8 +1338,8 @@ namespace ts {
"c:/dev/x/y/d.ts",
],
wildcardDirectories: {
"c:/dev/x": ts.WatchDirectoryFlags.Recursive,
"c:/dev/w": ts.WatchDirectoryFlags.Recursive
"c:/dev/x": WatchDirectoryFlags.Recursive,
"c:/dev/w": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
@@ -1352,7 +1352,7 @@ namespace ts {
"c:/dev/.z/.b.ts"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -1369,7 +1369,7 @@ namespace ts {
"**/.*/*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -1379,7 +1379,7 @@ namespace ts {
"c:/dev/x/.y/a.ts"
],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
"c:/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
@@ -1391,7 +1391,7 @@ namespace ts {
".z/**/.*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -1399,8 +1399,8 @@ namespace ts {
"c:/dev/.z/.b.ts"
],
wildcardDirectories: {
"c:/dev/.z": ts.WatchDirectoryFlags.Recursive,
"c:/dev/x": ts.WatchDirectoryFlags.Recursive
"c:/dev/.z": WatchDirectoryFlags.Recursive,
"c:/dev/x": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
@@ -1414,10 +1414,10 @@ namespace ts {
"**/*"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))
],
fileNames: [],
@@ -1435,7 +1435,7 @@ namespace ts {
"**/x"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -1453,7 +1453,7 @@ namespace ts {
"/dev/z/bbz.ts",
],
wildcardDirectories: {
"/dev": ts.WatchDirectoryFlags.Recursive
"/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
@@ -1465,7 +1465,7 @@ namespace ts {
"**/a/**/b"
]
};
const expected: ts.ParsedCommandLine = {
const expected: ParsedCommandLine = {
options: {},
errors: [],
fileNames: [
@@ -1476,7 +1476,7 @@ namespace ts {
"/dev/q/a/c/b/d.ts",
],
wildcardDirectories: {
"/dev": ts.WatchDirectoryFlags.Recursive
"/dev": WatchDirectoryFlags.Recursive
}
};
validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
+8 -8
View File
@@ -441,7 +441,7 @@ export = C;
"/a/b/c.ts": `/// <reference path="d.ts"/>`,
"/a/b/d.ts": "var x"
});
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "/a/b/d.ts"], []);
test(files, { module: ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "/a/b/d.ts"], []);
});
it("should fail when two files used in program differ only in casing (tripleslash references)", () => {
@@ -449,7 +449,7 @@ export = C;
"/a/b/c.ts": `/// <reference path="D.ts"/>`,
"/a/b/d.ts": "var x"
});
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
test(files, { module: ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
});
it("should fail when two files used in program differ only in casing (imports)", () => {
@@ -457,7 +457,7 @@ export = C;
"/a/b/c.ts": `import {x} from "D"`,
"/a/b/d.ts": "export var x"
});
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
test(files, { module: ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
});
it("should fail when two files used in program differ only in casing (imports, relative module names)", () => {
@@ -465,7 +465,7 @@ export = C;
"moduleA.ts": `import {x} from "./ModuleB"`,
"moduleB.ts": "export var x"
});
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts"], [1149]);
test(files, { module: ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts"], [1149]);
});
it("should fail when two files exist on disk that differs only in casing", () => {
@@ -474,7 +474,7 @@ export = C;
"/a/b/D.ts": "export var x",
"/a/b/d.ts": "export var y"
});
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ true, ["c.ts", "d.ts"], [1149]);
test(files, { module: ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ true, ["c.ts", "d.ts"], [1149]);
});
it("should fail when module name in 'require' calls has inconsistent casing", () => {
@@ -483,7 +483,7 @@ export = C;
"moduleB.ts": `import a = require("./moduleC")`,
"moduleC.ts": "export var x"
});
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts", "moduleC.ts"], [1149, 1149]);
test(files, { module: ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts", "moduleC.ts"], [1149, 1149]);
});
it("should fail when module names in 'require' calls has inconsistent casing and current directory has uppercase chars", () => {
@@ -496,7 +496,7 @@ import a = require("./moduleA");
import b = require("./moduleB");
`
});
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], [1149]);
test(files, { module: ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], [1149]);
});
it("should not fail when module names in 'require' calls has consistent casing and current directory has uppercase chars", () => {
const files = createMapFromTemplate({
@@ -508,7 +508,7 @@ import a = require("./moduleA");
import b = require("./moduleB");
`
});
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], []);
test(files, { module: ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], []);
});
});
+37
View File
@@ -325,6 +325,43 @@ F2();
/*A*/import /*B*/ { /*C*/ F1 /*D*/, /*E*/ F2 /*F*/ } /*G*/ from /*H*/ "lib" /*I*/;/*J*/ //K
F1();
`,
},
libFile);
testOrganizeImports("AmbientModule",
{
path: "/test.ts",
content: `
declare module "mod" {
import { F1 } from "lib";
import * as NS from "lib";
import { F2 } from "lib";
function F(f1: {} = F1, f2: {} = F2) {}
}
`,
},
libFile);
testOrganizeImports("TopLevelAndAmbientModule",
{
path: "/test.ts",
content: `
import D from "lib";
declare module "mod" {
import { F1 } from "lib";
import * as NS from "lib";
import { F2 } from "lib";
function F(f1: {} = F1, f2: {} = F2) {}
}
import E from "lib";
import "lib";
D();
`,
},
libFile);
@@ -884,9 +884,9 @@ namespace ts {
});
});
type FileOrFolder = ts.TestFSWithWatch.FileOrFolder;
import createTestSystem = ts.TestFSWithWatch.createWatchedSystem;
import libFile = ts.TestFSWithWatch.libFile;
type FileOrFolder = TestFSWithWatch.FileOrFolder;
import createTestSystem = TestFSWithWatch.createWatchedSystem;
import libFile = TestFSWithWatch.libFile;
describe("isProgramUptoDate should return true when there is no change in compiler options and", () => {
function verifyProgramIsUptoDate(
+7 -8
View File
@@ -42,7 +42,7 @@ namespace ts.server {
let lastSent: protocol.Message;
function createSession(): TestSession {
const opts: server.SessionOptions = {
const opts: SessionOptions = {
host: mockHost,
cancellationToken: nullCancellationToken,
useSingleInferredProject: false,
@@ -181,9 +181,7 @@ namespace ts.server {
type: "request"
};
const expected: protocol.StatusResponseBody = {
version: ts.version
};
const expected: protocol.StatusResponseBody = { version };
assert.deepEqual(session.executeCommand(req).response, expected);
});
});
@@ -216,6 +214,7 @@ namespace ts.server {
CommandNames.GeterrForProject,
CommandNames.SemanticDiagnosticsSync,
CommandNames.SyntacticDiagnosticsSync,
CommandNames.SuggestionDiagnosticsSync,
CommandNames.NavBar,
CommandNames.NavBarFull,
CommandNames.Navto,
@@ -329,7 +328,7 @@ namespace ts.server {
describe("send", () => {
it("is an overrideable handle which sends protocol messages over the wire", () => {
const msg: server.protocol.Request = { seq: 0, type: "request", command: "" };
const msg: protocol.Request = { seq: 0, type: "request", command: "" };
const strmsg = JSON.stringify(msg);
const len = 1 + Utils.byteLength(strmsg, "utf8");
const resultMsg = `Content-Length: ${len}\r\n\r\n${strmsg}\n`;
@@ -347,7 +346,7 @@ namespace ts.server {
item: false
};
const command = "newhandle";
const result: ts.server.HandlerResponse = {
const result: HandlerResponse = {
response: respBody,
responseRequired: true
};
@@ -364,7 +363,7 @@ namespace ts.server {
const respBody = {
item: false
};
const resp: ts.server.HandlerResponse = {
const resp: HandlerResponse = {
response: respBody,
responseRequired: true
};
@@ -711,7 +710,7 @@ namespace ts.server {
const text = `// blank line\nconst x = 0;`;
const renameLocationInOldText = text.indexOf("0");
const fileName = "/a.ts";
const edits: ts.FileTextChanges = {
const edits: FileTextChanges = {
fileName,
textChanges: [
{
+8 -8
View File
@@ -7,7 +7,7 @@ namespace ts.projectSystem {
const file = makeFile("/a.js");
const et = new TestServerEventManager([file]);
et.service.openClientFile(file.path);
et.hasZeroEvent(ts.server.ProjectInfoTelemetryEvent);
et.hasZeroEvent(server.ProjectInfoTelemetryEvent);
});
it("only sends an event once", () => {
@@ -25,18 +25,18 @@ namespace ts.projectSystem {
et.service.openClientFile(file2.path);
checkNumberOfProjects(et.service, { inferredProjects: 1 });
et.hasZeroEvent(ts.server.ProjectInfoTelemetryEvent);
et.hasZeroEvent(server.ProjectInfoTelemetryEvent);
et.service.openClientFile(file.path);
checkNumberOfProjects(et.service, { configuredProjects: 1, inferredProjects: 1 });
et.hasZeroEvent(ts.server.ProjectInfoTelemetryEvent);
et.hasZeroEvent(server.ProjectInfoTelemetryEvent);
});
it("counts files by extension", () => {
const files = ["ts.ts", "tsx.tsx", "moo.ts", "dts.d.ts", "jsx.jsx", "js.js", "badExtension.badExtension"].map(f => makeFile(`/src/${f}`));
const notIncludedFile = makeFile("/bin/ts.js");
const compilerOptions: ts.CompilerOptions = { allowJs: true };
const compilerOptions: CompilerOptions = { allowJs: true };
const tsconfig = makeFile("/tsconfig.json", { compilerOptions, include: ["src"] });
const et = new TestServerEventManager([...files, notIncludedFile, tsconfig]);
@@ -51,7 +51,7 @@ namespace ts.projectSystem {
it("works with external project", () => {
const file1 = makeFile("/a.ts");
const et = new TestServerEventManager([file1]);
const compilerOptions: ts.server.protocol.CompilerOptions = { strict: true };
const compilerOptions: server.protocol.CompilerOptions = { strict: true };
const projectFileName = "/hunter2/foo.csproj";
@@ -92,7 +92,7 @@ namespace ts.projectSystem {
it("does not expose paths", () => {
const file = makeFile("/a.ts");
const compilerOptions: ts.CompilerOptions = {
const compilerOptions: CompilerOptions = {
project: "",
outFile: "hunter2.js",
outDir: "hunter2",
@@ -122,7 +122,7 @@ namespace ts.projectSystem {
// Sensitive data doesn't get through even if sent to an option of safe type
checkJs: "hunter2" as any as boolean,
};
const safeCompilerOptions: ts.CompilerOptions = {
const safeCompilerOptions: CompilerOptions = {
project: "",
outFile: "",
outDir: "",
@@ -236,7 +236,7 @@ namespace ts.projectSystem {
});
});
function makeFile(path: string, content: {} = ""): projectSystem.FileOrFolder {
function makeFile(path: string, content: {} = ""): FileOrFolder {
return { path, content: isString(content) ? "" : JSON.stringify(content) };
}
}
+5 -8
View File
@@ -28,17 +28,14 @@ namespace ts {
}
// validate that positions that were recovered from the printed text actually match positions that will be created if the same text is parsed.
function verifyPositions({ text, node }: textChanges.NonFormattedText): void {
function verifyPositions(node: Node, text: string): void {
const nodeList = flattenNodes(node);
const sourceFile = createSourceFile("f.ts", text, ScriptTarget.ES2015);
const parsedNodeList = flattenNodes(sourceFile.statements[0]);
Debug.assert(nodeList.length === parsedNodeList.length);
for (let i = 0; i < nodeList.length; i++) {
const left = nodeList[i];
const right = parsedNodeList[i];
zipWith(nodeList, parsedNodeList, (left, right) => {
Debug.assert(left.pos === right.pos);
Debug.assert(left.end === right.end);
}
});
function flattenNodes(n: Node) {
const data: (Node | NodeArray<Node>)[] = [];
@@ -57,9 +54,9 @@ namespace ts {
Harness.Baseline.runBaseline(`textChanges/${caption}.js`, () => {
const sourceFile = createSourceFile("source.ts", text, ScriptTarget.ES2015, /*setParentNodes*/ true);
const rulesProvider = getRuleProvider(placeOpenBraceOnNewLineForFunctions);
const changeTracker = new textChanges.ChangeTracker(newLineCharacter, rulesProvider, validateNodes ? verifyPositions : undefined);
const changeTracker = new textChanges.ChangeTracker(newLineCharacter, rulesProvider);
testBlock(sourceFile, changeTracker);
const changes = changeTracker.getChanges();
const changes = changeTracker.getChanges(validateNodes ? verifyPositions : undefined);
assert.equal(changes.length, 1);
assert.equal(changes[0].fileName, sourceFile.fileName);
const modified = textChanges.applyChanges(sourceFile.text, changes[0].textChanges);
+2 -2
View File
@@ -16,7 +16,7 @@ namespace ts.textStorage {
it("text based storage should be have exactly the same as script version cache", () => {
const host = ts.projectSystem.createServerHost([f]);
const host = projectSystem.createServerHost([f]);
const ts1 = new server.TextStorage(host, server.asNormalizedPath(f.path));
const ts2 = new server.TextStorage(host, server.asNormalizedPath(f.path));
@@ -51,7 +51,7 @@ namespace ts.textStorage {
});
it("should switch to script version cache if necessary", () => {
const host = ts.projectSystem.createServerHost([f]);
const host = projectSystem.createServerHost([f]);
const ts1 = new server.TextStorage(host, server.asNormalizedPath(f.path));
ts1.getSnapshot();
+57 -57
View File
@@ -3,7 +3,7 @@
namespace ts {
describe("TransformAPI", () => {
function replaceUndefinedWithVoid0(context: ts.TransformationContext) {
function replaceUndefinedWithVoid0(context: TransformationContext) {
const previousOnSubstituteNode = context.onSubstituteNode;
context.enableSubstitution(SyntaxKind.Identifier);
context.onSubstituteNode = (hint, node) => {
@@ -18,19 +18,19 @@ namespace ts {
}
return node;
};
return (file: ts.SourceFile) => file;
return (file: SourceFile) => file;
}
function replaceNumberWith2(context: ts.TransformationContext) {
function replaceNumberWith2(context: TransformationContext) {
function visitor(node: Node): Node {
if (isNumericLiteral(node)) {
return createNumericLiteral("2");
}
return visitEachChild(node, visitor, context);
}
return (file: ts.SourceFile) => visitNode(file, visitor);
return (file: SourceFile) => visitNode(file, visitor);
}
function replaceIdentifiersNamedOldNameWithNewName(context: ts.TransformationContext) {
function replaceIdentifiersNamedOldNameWithNewName(context: TransformationContext) {
const previousOnSubstituteNode = context.onSubstituteNode;
context.enableSubstitution(SyntaxKind.Identifier);
context.onSubstituteNode = (hint, node) => {
@@ -40,7 +40,7 @@ namespace ts {
}
return node;
};
return (file: ts.SourceFile) => file;
return (file: SourceFile) => file;
}
function transformSourceFile(sourceText: string, transformers: TransformerFactory<SourceFile>[]) {
@@ -73,7 +73,7 @@ namespace ts {
});
testBaseline("fromTranspileModule", () => {
return ts.transpileModule(`var oldName = undefined;`, {
return transpileModule(`var oldName = undefined;`, {
transformers: {
before: [replaceUndefinedWithVoid0],
after: [replaceIdentifiersNamedOldNameWithNewName]
@@ -85,7 +85,7 @@ namespace ts {
});
testBaseline("rewrittenNamespace", () => {
return ts.transpileModule(`namespace Reflect { const x = 1; }`, {
return transpileModule(`namespace Reflect { const x = 1; }`, {
transformers: {
before: [forceNamespaceRewrite],
},
@@ -96,7 +96,7 @@ namespace ts {
});
testBaseline("rewrittenNamespaceFollowingClass", () => {
return ts.transpileModule(`
return transpileModule(`
class C { foo = 10; static bar = 20 }
namespace C { export let x = 10; }
`, {
@@ -104,90 +104,90 @@ namespace ts {
before: [forceNamespaceRewrite],
},
compilerOptions: {
target: ts.ScriptTarget.ESNext,
target: ScriptTarget.ESNext,
newLine: NewLineKind.CarriageReturnLineFeed,
}
}).outputText;
});
testBaseline("transformTypesInExportDefault", () => {
return ts.transpileModule(`
return transpileModule(`
export default (foo: string) => { return 1; }
`, {
transformers: {
before: [replaceNumberWith2],
},
compilerOptions: {
target: ts.ScriptTarget.ESNext,
target: ScriptTarget.ESNext,
newLine: NewLineKind.CarriageReturnLineFeed,
}
}).outputText;
});
testBaseline("synthesizedClassAndNamespaceCombination", () => {
return ts.transpileModule("", {
return transpileModule("", {
transformers: {
before: [replaceWithClassAndNamespace],
},
compilerOptions: {
target: ts.ScriptTarget.ESNext,
target: ScriptTarget.ESNext,
newLine: NewLineKind.CarriageReturnLineFeed,
}
}).outputText;
function replaceWithClassAndNamespace() {
return (sourceFile: ts.SourceFile) => {
return (sourceFile: SourceFile) => {
const result = getMutableClone(sourceFile);
result.statements = ts.createNodeArray([
ts.createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined),
ts.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()]))
result.statements = createNodeArray([
createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined),
createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()]))
]);
return result;
};
}
});
function forceNamespaceRewrite(context: ts.TransformationContext) {
return (sourceFile: ts.SourceFile): ts.SourceFile => {
function forceNamespaceRewrite(context: TransformationContext) {
return (sourceFile: SourceFile): SourceFile => {
return visitNode(sourceFile);
function visitNode<T extends ts.Node>(node: T): T {
if (node.kind === ts.SyntaxKind.ModuleBlock) {
const block = node as T & ts.ModuleBlock;
const statements = ts.createNodeArray([...block.statements]);
return ts.updateModuleBlock(block, statements) as typeof block;
function visitNode<T extends Node>(node: T): T {
if (node.kind === SyntaxKind.ModuleBlock) {
const block = node as T & ModuleBlock;
const statements = createNodeArray([...block.statements]);
return updateModuleBlock(block, statements) as typeof block;
}
return ts.visitEachChild(node, visitNode, context);
return visitEachChild(node, visitNode, context);
}
};
}
testBaseline("transformAwayExportStar", () => {
return ts.transpileModule("export * from './helper';", {
return transpileModule("export * from './helper';", {
transformers: {
before: [expandExportStar],
},
compilerOptions: {
target: ts.ScriptTarget.ESNext,
target: ScriptTarget.ESNext,
newLine: NewLineKind.CarriageReturnLineFeed,
}
}).outputText;
function expandExportStar(context: ts.TransformationContext) {
return (sourceFile: ts.SourceFile): ts.SourceFile => {
function expandExportStar(context: TransformationContext) {
return (sourceFile: SourceFile): SourceFile => {
return visitNode(sourceFile);
function visitNode<T extends ts.Node>(node: T): T {
if (node.kind === ts.SyntaxKind.ExportDeclaration) {
const ed = node as ts.Node as ts.ExportDeclaration;
function visitNode<T extends Node>(node: T): T {
if (node.kind === SyntaxKind.ExportDeclaration) {
const ed = node as Node as ExportDeclaration;
const exports = [{ name: "x" }];
const exportSpecifiers = exports.map(e => ts.createExportSpecifier(e.name, e.name));
const exportClause = ts.createNamedExports(exportSpecifiers);
const newEd = ts.updateExportDeclaration(ed, ed.decorators, ed.modifiers, exportClause, ed.moduleSpecifier);
const exportSpecifiers = exports.map(e => createExportSpecifier(e.name, e.name));
const exportClause = createNamedExports(exportSpecifiers);
const newEd = updateExportDeclaration(ed, ed.decorators, ed.modifiers, exportClause, ed.moduleSpecifier);
return newEd as ts.Node as T;
return newEd as Node as T;
}
return ts.visitEachChild(node, visitNode, context);
return visitEachChild(node, visitNode, context);
}
};
}
@@ -195,58 +195,58 @@ namespace ts {
// https://github.com/Microsoft/TypeScript/issues/19618
testBaseline("transformAddImportStar", () => {
return ts.transpileModule("", {
return transpileModule("", {
transformers: {
before: [transformAddImportStar],
},
compilerOptions: {
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.System,
target: ScriptTarget.ES5,
module: ModuleKind.System,
newLine: NewLineKind.CarriageReturnLineFeed,
}
}).outputText;
function transformAddImportStar(_context: ts.TransformationContext) {
return (sourceFile: ts.SourceFile): ts.SourceFile => {
function transformAddImportStar(_context: TransformationContext) {
return (sourceFile: SourceFile): SourceFile => {
return visitNode(sourceFile);
};
function visitNode(sf: ts.SourceFile) {
function visitNode(sf: SourceFile) {
// produce `import * as i0 from './comp';
const importStar = ts.createImportDeclaration(
const importStar = createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*importClause*/ ts.createImportClause(
/*importClause*/ createImportClause(
/*name*/ undefined,
ts.createNamespaceImport(ts.createIdentifier("i0"))
createNamespaceImport(createIdentifier("i0"))
),
/*moduleSpecifier*/ ts.createLiteral("./comp1"));
return ts.updateSourceFileNode(sf, [importStar]);
/*moduleSpecifier*/ createLiteral("./comp1"));
return updateSourceFileNode(sf, [importStar]);
}
}
});
// https://github.com/Microsoft/TypeScript/issues/17384
testBaseline("transformAddDecoratedNode", () => {
return ts.transpileModule("", {
return transpileModule("", {
transformers: {
before: [transformAddDecoratedNode],
},
compilerOptions: {
target: ts.ScriptTarget.ES5,
target: ScriptTarget.ES5,
newLine: NewLineKind.CarriageReturnLineFeed,
}
}).outputText;
function transformAddDecoratedNode(_context: ts.TransformationContext) {
return (sourceFile: ts.SourceFile): ts.SourceFile => {
function transformAddDecoratedNode(_context: TransformationContext) {
return (sourceFile: SourceFile): SourceFile => {
return visitNode(sourceFile);
};
function visitNode(sf: ts.SourceFile) {
function visitNode(sf: SourceFile) {
// produce `class Foo { @Bar baz() {} }`;
const classDecl = ts.createClassDeclaration([], [], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [
ts.createMethod([ts.createDecorator(ts.createIdentifier("Bar"))], [], /**/ undefined, "baz", /**/ undefined, /**/ undefined, [], /**/ undefined, ts.createBlock([]))
const classDecl = createClassDeclaration([], [], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [
createMethod([createDecorator(createIdentifier("Bar"))], [], /**/ undefined, "baz", /**/ undefined, /**/ undefined, [], /**/ undefined, createBlock([]))
]);
return ts.updateSourceFileNode(sf, [classDecl]);
return updateSourceFileNode(sf, [classDecl]);
}
}
});
+2 -2
View File
@@ -24,7 +24,7 @@ namespace ts {
if (transpileOptions.compilerOptions.newLine === undefined) {
// use \r\n as default new line
transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed;
transpileOptions.compilerOptions.newLine = NewLineKind.CarriageReturnLineFeed;
}
transpileOptions.compilerOptions.sourceMap = true;
@@ -85,7 +85,7 @@ namespace ts {
}
it("Correct output for " + justName, () => {
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ts.Extension.Js), () => {
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, Extension.Js), () => {
if (transpileResult.outputText) {
return transpileResult.outputText;
}
+28 -20
View File
@@ -3,16 +3,15 @@
/// <reference path="..\virtualFileSystemWithWatch.ts" />
namespace ts.tscWatch {
import WatchedSystem = ts.TestFSWithWatch.TestServerHost;
type FileOrFolder = ts.TestFSWithWatch.FileOrFolder;
import createWatchedSystem = ts.TestFSWithWatch.createWatchedSystem;
import checkArray = ts.TestFSWithWatch.checkArray;
import libFile = ts.TestFSWithWatch.libFile;
import checkWatchedFiles = ts.TestFSWithWatch.checkWatchedFiles;
import checkWatchedDirectories = ts.TestFSWithWatch.checkWatchedDirectories;
import checkOutputContains = ts.TestFSWithWatch.checkOutputContains;
import checkOutputDoesNotContain = ts.TestFSWithWatch.checkOutputDoesNotContain;
import WatchedSystem = TestFSWithWatch.TestServerHost;
type FileOrFolder = TestFSWithWatch.FileOrFolder;
import createWatchedSystem = TestFSWithWatch.createWatchedSystem;
import checkArray = TestFSWithWatch.checkArray;
import libFile = TestFSWithWatch.libFile;
import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles;
import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories;
import checkOutputContains = TestFSWithWatch.checkOutputContains;
import checkOutputDoesNotContain = TestFSWithWatch.checkOutputDoesNotContain;
export function checkProgramActualFiles(program: Program, expectedFiles: string[]) {
checkArray(`Program actual files`, program.getSourceFiles().map(file => file.fileName), expectedFiles);
@@ -23,7 +22,7 @@ namespace ts.tscWatch {
}
function createWatchOfConfigFile(configFileName: string, host: WatchedSystem, maxNumberOfFilesToIterateForInvalidation?: number) {
const compilerHost = ts.createWatchCompilerHostOfConfigFile(configFileName, {}, host);
const compilerHost = createWatchCompilerHostOfConfigFile(configFileName, {}, host);
compilerHost.maxNumberOfFilesToIterateForInvalidation = maxNumberOfFilesToIterateForInvalidation;
const watch = createWatchProgram(compilerHost);
return () => watch.getCurrentProgram().getProgram();
@@ -2157,7 +2156,7 @@ declare module "fs" {
});
describe("tsc-watch console clearing", () => {
function checkConsoleClearing(diagnostics: boolean, extendedDiagnostics: boolean) {
function checkConsoleClearing(options: CompilerOptions = {}) {
const file = {
path: "f.ts",
content: ""
@@ -2167,7 +2166,7 @@ declare module "fs" {
let clearCount: number | undefined;
checkConsoleClears();
createWatchOfFilesAndCompilerOptions([file.path], host, { diagnostics, extendedDiagnostics });
createWatchOfFilesAndCompilerOptions([file.path], host, options);
checkConsoleClears();
file.content = "//";
@@ -2177,10 +2176,10 @@ declare module "fs" {
checkConsoleClears();
function checkConsoleClears() {
if (clearCount === undefined) {
if (clearCount === undefined || options.preserveWatchOutput) {
clearCount = 0;
}
else if (!diagnostics && !extendedDiagnostics) {
else if (!options.diagnostics && !options.extendedDiagnostics) {
clearCount++;
}
host.checkScreenClears(clearCount);
@@ -2189,13 +2188,22 @@ declare module "fs" {
}
it("without --diagnostics or --extendedDiagnostics", () => {
checkConsoleClearing(/*diagnostics*/ false, /*extendedDiagnostics*/ false);
checkConsoleClearing();
});
it("with --diagnostics", () => {
checkConsoleClearing(/*diagnostics*/ true, /*extendedDiagnostics*/ false);
checkConsoleClearing({
diagnostics: true,
});
});
it("with --extendedDiagnostics", () => {
checkConsoleClearing(/*diagnostics*/ false, /*extendedDiagnostics*/ true);
checkConsoleClearing({
extendedDiagnostics: true,
});
});
it("with --preserveWatchOutput", () => {
checkConsoleClearing({
preserveWatchOutput: true,
});
});
});
@@ -2312,8 +2320,8 @@ declare module "fs" {
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
// Watching config file, file, lib file and directories
ts.TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedFiles", host.watchedFiles, expectedWatchedFiles, 1);
ts.TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedDirectories", host.watchedDirectories, expectedWatchedDirectories, 1);
TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedFiles", host.watchedFiles, expectedWatchedFiles, 1);
TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedDirectories", host.watchedDirectories, expectedWatchedDirectories, 1);
}
}
+12 -12
View File
@@ -4,41 +4,41 @@
namespace ts {
describe("parseConfigFileTextToJson", () => {
function assertParseResult(jsonText: string, expectedConfigObject: { config?: any; error?: Diagnostic[] }) {
const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
const parsed = parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
assert.equal(JSON.stringify(parsed), JSON.stringify(expectedConfigObject));
}
function assertParseError(jsonText: string) {
const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
const parsed = parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
assert.deepEqual(parsed.config, {});
assert.isTrue(undefined !== parsed.error);
}
function assertParseErrorWithExcludesKeyword(jsonText: string) {
{
const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
const parsedCommand = ts.parseJsonConfigFileContent(parsed.config, ts.sys, "tests/cases/unittests");
const parsed = parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
const parsedCommand = parseJsonConfigFileContent(parsed.config, sys, "tests/cases/unittests");
assert.isTrue(parsedCommand.errors && parsedCommand.errors.length === 1 &&
parsedCommand.errors[0].code === ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude.code);
parsedCommand.errors[0].code === Diagnostics.Unknown_option_excludes_Did_you_mean_exclude.code);
}
{
const parsed = ts.parseJsonText("/apath/tsconfig.json", jsonText);
const parsedCommand = ts.parseJsonSourceFileConfigFileContent(parsed, ts.sys, "tests/cases/unittests");
const parsed = parseJsonText("/apath/tsconfig.json", jsonText);
const parsedCommand = parseJsonSourceFileConfigFileContent(parsed, sys, "tests/cases/unittests");
assert.isTrue(parsedCommand.errors && parsedCommand.errors.length === 1 &&
parsedCommand.errors[0].code === ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude.code);
parsedCommand.errors[0].code === Diagnostics.Unknown_option_excludes_Did_you_mean_exclude.code);
}
}
function getParsedCommandJson(jsonText: string, configFileName: string, basePath: string, allFileList: string[]) {
const parsed = ts.parseConfigFileTextToJson(configFileName, jsonText);
const parsed = parseConfigFileTextToJson(configFileName, jsonText);
const host: ParseConfigHost = new Utils.MockParseConfigHost(basePath, true, allFileList);
return ts.parseJsonConfigFileContent(parsed.config, host, basePath, /*existingOptions*/ undefined, configFileName);
return parseJsonConfigFileContent(parsed.config, host, basePath, /*existingOptions*/ undefined, configFileName);
}
function getParsedCommandJsonNode(jsonText: string, configFileName: string, basePath: string, allFileList: string[]) {
const parsed = ts.parseJsonText(configFileName, jsonText);
const parsed = parseJsonText(configFileName, jsonText);
const host: ParseConfigHost = new Utils.MockParseConfigHost(basePath, true, allFileList);
return ts.parseJsonSourceFileConfigFileContent(parsed, host, basePath, /*existingOptions*/ undefined, configFileName);
return parseJsonSourceFileConfigFileContent(parsed, host, basePath, /*existingOptions*/ undefined, configFileName);
}
function assertParseFileList(jsonText: string, configFileName: string, basePath: string, allFileList: string[], expectedFileList: string[]) {
+508 -41
View File
@@ -7,14 +7,14 @@ namespace ts.projectSystem {
import protocol = server.protocol;
import CommandNames = server.CommandNames;
export import TestServerHost = ts.TestFSWithWatch.TestServerHost;
export type FileOrFolder = ts.TestFSWithWatch.FileOrFolder;
export import createServerHost = ts.TestFSWithWatch.createServerHost;
export import checkArray = ts.TestFSWithWatch.checkArray;
export import libFile = ts.TestFSWithWatch.libFile;
export import checkWatchedFiles = ts.TestFSWithWatch.checkWatchedFiles;
import checkWatchedDirectories = ts.TestFSWithWatch.checkWatchedDirectories;
import safeList = ts.TestFSWithWatch.safeList;
export import TestServerHost = TestFSWithWatch.TestServerHost;
export type FileOrFolder = TestFSWithWatch.FileOrFolder;
export import createServerHost = TestFSWithWatch.createServerHost;
export import checkArray = TestFSWithWatch.checkArray;
export import libFile = TestFSWithWatch.libFile;
export import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles;
import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories;
import safeList = TestFSWithWatch.safeList;
export const customTypesMap = {
path: <Path>"/typesMap.json",
@@ -145,6 +145,12 @@ namespace ts.projectSystem {
return map;
}
function createHostModuleResolutionTrace(host: TestServerHost & ModuleResolutionHost) {
const resolutionTrace: string[] = [];
host.trace = resolutionTrace.push.bind(resolutionTrace);
return resolutionTrace;
}
export function toExternalFile(fileName: string): protocol.ExternalFile {
return { fileName };
}
@@ -161,8 +167,8 @@ namespace ts.projectSystem {
private events: server.ProjectServiceEvent[] = [];
readonly session: TestSession;
readonly service: server.ProjectService;
readonly host: projectSystem.TestServerHost;
constructor(files: projectSystem.FileOrFolder[]) {
readonly host: TestServerHost;
constructor(files: FileOrFolder[]) {
this.host = createServerHost(files);
this.session = createSession(this.host, {
canUseEvents: true,
@@ -204,7 +210,7 @@ namespace ts.projectSystem {
}
assertProjectInfoTelemetryEvent(partial: Partial<server.ProjectInfoTelemetryEventData>, configFile?: string): void {
assert.deepEqual(this.getEvent<server.ProjectInfoTelemetryEvent>(ts.server.ProjectInfoTelemetryEvent), {
assert.deepEqual(this.getEvent<server.ProjectInfoTelemetryEvent>(server.ProjectInfoTelemetryEvent), {
projectId: Harness.mockHash(configFile || "/tsconfig.json"),
fileStats: fileStats({ ts: 1 }),
compilerOptions: {},
@@ -221,7 +227,7 @@ namespace ts.projectSystem {
configFileName: "tsconfig.json",
projectType: "configured",
languageServiceEnabled: true,
version: ts.version,
version,
...partial,
});
}
@@ -467,16 +473,16 @@ namespace ts.projectSystem {
verifyDiagnostics(actual, []);
}
function checkErrorMessage(session: TestSession, eventName: "syntaxDiag" | "semanticDiag", diagnostics: protocol.DiagnosticEventBody) {
checkNthEvent(session, ts.server.toEvent(eventName, diagnostics), 0, /*isMostRecent*/ false);
function checkErrorMessage(session: TestSession, eventName: protocol.DiagnosticEventKind, diagnostics: protocol.DiagnosticEventBody, isMostRecent = false): void {
checkNthEvent(session, server.toEvent(eventName, diagnostics), 0, isMostRecent);
}
function checkCompleteEvent(session: TestSession, numberOfCurrentEvents: number, expectedSequenceId: number) {
checkNthEvent(session, ts.server.toEvent("requestCompleted", { request_seq: expectedSequenceId }), numberOfCurrentEvents - 1, /*isMostRecent*/ true);
function checkCompleteEvent(session: TestSession, numberOfCurrentEvents: number, expectedSequenceId: number, isMostRecent = true): void {
checkNthEvent(session, server.toEvent("requestCompleted", { request_seq: expectedSequenceId }), numberOfCurrentEvents - 1, isMostRecent);
}
function checkProjectUpdatedInBackgroundEvent(session: TestSession, openFiles: string[]) {
checkNthEvent(session, ts.server.toEvent("projectsUpdatedInBackground", { openFiles }), 0, /*isMostRecent*/ true);
checkNthEvent(session, server.toEvent("projectsUpdatedInBackground", { openFiles }), 0, /*isMostRecent*/ true);
}
function checkNthEvent(session: TestSession, expectedEvent: protocol.Event, index: number, isMostRecent: boolean) {
@@ -2978,6 +2984,47 @@ namespace ts.projectSystem {
checkProjectActualFiles(configuredProject, [file.path, filesFile1.path, libFile.path, config.path]);
}
});
it("requests are done on file on pendingReload but has svc for previous version", () => {
const projectLocation = "/user/username/projects/project";
const file1: FileOrFolder = {
path: `${projectLocation}/src/file1.ts`,
content: `import { y } from "./file1"; let x = 10;`
};
const file2: FileOrFolder = {
path: `${projectLocation}/src/file2.ts`,
content: "export let y = 10;"
};
const config: FileOrFolder = {
path: `${projectLocation}/tsconfig.json`,
content: "{}"
};
const files = [file1, file2, libFile, config];
const host = createServerHost(files);
const session = createSession(host);
session.executeCommandSeq<protocol.OpenRequest>({
command: protocol.CommandTypes.Open,
arguments: { file: file2.path, fileContent: file2.content }
});
session.executeCommandSeq<protocol.OpenRequest>({
command: protocol.CommandTypes.Open,
arguments: { file: file1.path }
});
session.executeCommandSeq<protocol.CloseRequest>({
command: protocol.CommandTypes.Close,
arguments: { file: file2.path }
});
file2.content += "export let z = 10;";
host.reloadFS(files);
// Do not let the timeout runs, before executing command
const startOffset = file2.content.indexOf("y") + 1;
session.executeCommandSeq<protocol.GetApplicableRefactorsRequest>({
command: protocol.CommandTypes.GetApplicableRefactors,
arguments: { file: file2.path, startLine: 1, startOffset, endLine: 1, endOffset: startOffset + 1 }
});
});
});
describe("tsserverProjectSystem Proper errors", () => {
@@ -3076,8 +3123,13 @@ namespace ts.projectSystem {
host.runQueuedImmediateCallbacks();
assert.isFalse(hasError());
checkErrorMessage(session, "semanticDiag", { file: untitledFile, diagnostics: [] });
session.clearMessages();
host.runQueuedImmediateCallbacks(1);
assert.isFalse(hasError());
checkErrorMessage(session, "suggestionDiag", { file: untitledFile, diagnostics: [] });
checkCompleteEvent(session, 2, expectedSequenceId);
session.clearMessages();
}
it("has projectRoot", () => {
@@ -3136,6 +3188,10 @@ namespace ts.projectSystem {
host.runQueuedImmediateCallbacks();
checkErrorMessage(session, "semanticDiag", { file: app.path, diagnostics: [] });
session.clearMessages();
host.runQueuedImmediateCallbacks(1);
checkErrorMessage(session, "suggestionDiag", { file: app.path, diagnostics: [] });
checkCompleteEvent(session, 2, expectedSequenceId);
session.clearMessages();
}
@@ -3201,8 +3257,7 @@ namespace ts.projectSystem {
content: "export let x = 1"
};
const host: TestServerHost & ModuleResolutionHost = createServerHost([file1, lib]);
const resolutionTrace: string[] = [];
host.trace = resolutionTrace.push.bind(resolutionTrace);
const resolutionTrace = createHostModuleResolutionTrace(host);
const projectService = createProjectService(host, { typingsInstaller: new TestTypingsInstaller("/a/cache", /*throttleLimit*/5, host) });
projectService.setCompilerOptionsForInferredProjects({ traceResolution: true, allowJs: true });
@@ -3934,18 +3989,17 @@ namespace ts.projectSystem {
session.clearMessages();
host.runQueuedImmediateCallbacks();
const moduleNotFound = Diagnostics.Cannot_find_module_0;
const startOffset = file1.content.indexOf('"') + 1;
checkErrorMessage(session, "semanticDiag", {
file: file1.path, diagnostics: [{
start: { line: 1, offset: startOffset },
end: { line: 1, offset: startOffset + '"pad"'.length },
text: formatStringFromArgs(moduleNotFound.message, ["pad"]),
code: moduleNotFound.code,
category: DiagnosticCategory[moduleNotFound.category].toLowerCase(),
source: undefined
}]
file: file1.path,
diagnostics: [
createDiagnostic({ line: 1, offset: startOffset }, { line: 1, offset: startOffset + '"pad"'.length }, Diagnostics.Cannot_find_module_0, ["pad"])
],
});
session.clearMessages();
host.runQueuedImmediateCallbacks(1);
checkErrorMessage(session, "suggestionDiag", { file: file1.path, diagnostics: [] });
checkCompleteEvent(session, 2, expectedSequenceId);
session.clearMessages();
@@ -3966,6 +4020,63 @@ namespace ts.projectSystem {
host.runQueuedImmediateCallbacks();
checkErrorMessage(session, "semanticDiag", { file: file1.path, diagnostics: [] });
});
it("info diagnostics", () => {
const file: FileOrFolder = {
path: "/a.js",
content: 'require("b")',
};
const host = createServerHost([file]);
const session = createSession(host, { canUseEvents: true });
const service = session.getProjectService();
session.executeCommandSeq<protocol.OpenRequest>({
command: server.CommandNames.Open,
arguments: { file: file.path, fileContent: file.content },
});
checkNumberOfProjects(service, { inferredProjects: 1 });
session.clearMessages();
const expectedSequenceId = session.getNextSeq();
host.checkTimeoutQueueLengthAndRun(2);
checkProjectUpdatedInBackgroundEvent(session, [file.path]);
session.clearMessages();
session.executeCommandSeq<protocol.GeterrRequest>({
command: server.CommandNames.Geterr,
arguments: {
delay: 0,
files: [file.path],
}
});
host.checkTimeoutQueueLengthAndRun(1);
checkErrorMessage(session, "syntaxDiag", { file: file.path, diagnostics: [] }, /*isMostRecent*/ true);
session.clearMessages();
host.runQueuedImmediateCallbacks(1);
checkErrorMessage(session, "semanticDiag", { file: file.path, diagnostics: [] });
session.clearMessages();
host.runQueuedImmediateCallbacks(1);
checkErrorMessage(session, "suggestionDiag", {
file: file.path,
diagnostics: [
createDiagnostic({ line: 1, offset: 1 }, { line: 1, offset: 13 }, Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES6_module)
],
});
checkCompleteEvent(session, 2, expectedSequenceId);
session.clearMessages();
});
function createDiagnostic(start: protocol.Location, end: protocol.Location, message: DiagnosticMessage, args: ReadonlyArray<string> = []): protocol.Diagnostic {
return { start, end, text: formatStringFromArgs(message.message, args), code: message.code, category: diagnosticCategoryName(message), source: undefined };
}
});
describe("tsserverProjectSystem Configure file diagnostics events", () => {
@@ -4820,7 +4931,7 @@ namespace ts.projectSystem {
command: server.CommandNames.CompilerOptionsDiagnosticsFull,
seq: 2,
arguments: { projectFileName }
}).response as ReadonlyArray<ts.server.protocol.DiagnosticWithLinePosition>;
}).response as ReadonlyArray<server.protocol.DiagnosticWithLinePosition>;
assert.isTrue(diags.length === 0);
session.executeCommand(<server.protocol.OpenExternalProjectRequest>{
@@ -4838,7 +4949,7 @@ namespace ts.projectSystem {
command: server.CommandNames.CompilerOptionsDiagnosticsFull,
seq: 4,
arguments: { projectFileName }
}).response as ReadonlyArray<ts.server.protocol.DiagnosticWithLinePosition>;
}).response as ReadonlyArray<server.protocol.DiagnosticWithLinePosition>;
assert.isTrue(diagsAfterUpdate.length === 0);
});
});
@@ -5002,7 +5113,7 @@ namespace ts.projectSystem {
describe("tsserverProjectSystem cancellationToken", () => {
// Disable sourcemap support for the duration of the test, as sourcemapping the errors generated during this test is slow and not something we care to test
let oldPrepare: ts.AnyFunction;
let oldPrepare: AnyFunction;
before(() => {
oldPrepare = (Error as any).prepareStackTrace;
delete (Error as any).prepareStackTrace;
@@ -5154,9 +5265,15 @@ namespace ts.projectSystem {
// the semanticDiag message
host.runQueuedImmediateCallbacks();
assert.equal(host.getOutput().length, 2, "expect 2 messages");
assert.equal(host.getOutput().length, 1);
const e2 = <protocol.Event>getMessage(0);
assert.equal(e2.event, "semanticDiag");
session.clearMessages();
host.runQueuedImmediateCallbacks(1);
assert.equal(host.getOutput().length, 2);
const e3 = <protocol.Event>getMessage(0);
assert.equal(e3.event, "suggestionDiag");
verifyRequestCompleted(getErrId, 1);
cancellationToken.resetToken();
@@ -5194,6 +5311,7 @@ namespace ts.projectSystem {
return JSON.parse(server.extractMessage(host.getOutput()[n]));
}
});
it("Lower priority tasks are cancellable", () => {
const f1 = {
path: "/a/app.ts",
@@ -5495,7 +5613,7 @@ namespace ts.projectSystem {
}
type CalledMaps = CalledMapsWithSingleArg | CalledMapsWithFiveArgs;
function createCallsTrackingHost(host: TestServerHost) {
const calledMaps: Record<CalledMapsWithSingleArg, MultiMap<true>> & Record<CalledMapsWithFiveArgs, MultiMap<[ReadonlyArray<string>, ReadonlyArray<string>, ReadonlyArray<string>, number]>> = {
const calledMaps: Record<CalledMapsWithSingleArg, MultiMap<true>> & Record<CalledMapsWithFiveArgs, MultiMap<[ReadonlyArray<string>, ReadonlyArray<string>, ReadonlyArray<string>, number]>> = {
fileExists: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.fileExists),
directoryExists: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.directoryExists),
getDirectories: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.getDirectories),
@@ -5545,11 +5663,11 @@ namespace ts.projectSystem {
}
function verifyCalledOnEachEntry(callback: CalledMaps, expectedKeys: Map<number>) {
ts.TestFSWithWatch.checkMultiMapKeyCount(callback, calledMaps[callback], expectedKeys);
TestFSWithWatch.checkMultiMapKeyCount(callback, calledMaps[callback], expectedKeys);
}
function verifyCalledOnEachEntryNTimes(callback: CalledMaps, expectedKeys: string[], nTimes: number) {
ts.TestFSWithWatch.checkMultiMapEachKeyWithCount(callback, calledMaps[callback], expectedKeys, nTimes);
TestFSWithWatch.checkMultiMapEachKeyWithCount(callback, calledMaps[callback], expectedKeys, nTimes);
}
function verifyNoHostCalls() {
@@ -5592,7 +5710,7 @@ namespace ts.projectSystem {
const host = createServerHost([root, imported]);
const projectService = createProjectService(host);
projectService.setCompilerOptionsForInferredProjects({ module: ts.ModuleKind.AMD, noLib: true });
projectService.setCompilerOptionsForInferredProjects({ module: ModuleKind.AMD, noLib: true });
projectService.openClientFile(root.path);
checkNumberOfProjects(projectService, { inferredProjects: 1 });
const project = projectService.inferredProjects[0];
@@ -5638,7 +5756,7 @@ namespace ts.projectSystem {
// setting compiler options discards module resolution cache
callsTrackingHost.clear();
projectService.setCompilerOptionsForInferredProjects({ module: ts.ModuleKind.AMD, noLib: true, target: ts.ScriptTarget.ES5 });
projectService.setCompilerOptionsForInferredProjects({ module: ModuleKind.AMD, noLib: true, target: ScriptTarget.ES5 });
verifyImportedDiagnostics();
vertifyF1Lookups();
@@ -5708,7 +5826,7 @@ namespace ts.projectSystem {
const host = createServerHost([root]);
const projectService = createProjectService(host);
projectService.setCompilerOptionsForInferredProjects({ module: ts.ModuleKind.AMD, noLib: true });
projectService.setCompilerOptionsForInferredProjects({ module: ModuleKind.AMD, noLib: true });
const callsTrackingHost = createCallsTrackingHost(host);
projectService.openClientFile(root.path);
checkNumberOfProjects(projectService, { inferredProjects: 1 });
@@ -6672,7 +6790,7 @@ namespace ts.projectSystem {
const events: protocol.ProjectsUpdatedInBackgroundEvent[] = filter(
map(
host.getOutput(), s => convertToObject(
ts.parseJsonText("json.json", s.replace(outputEventRegex, "")),
parseJsonText("json.json", s.replace(outputEventRegex, "")),
[]
)
),
@@ -6966,6 +7084,355 @@ namespace ts.projectSystem {
});
});
describe("tsserverProjectSystem module resolution caching", () => {
const projectLocation = "/user/username/projects/myproject";
const configFile: FileOrFolder = {
path: `${projectLocation}/tsconfig.json`,
content: JSON.stringify({ compilerOptions: { traceResolution: true } })
};
function getModules(module1Path: string, module2Path: string) {
const module1: FileOrFolder = {
path: module1Path,
content: `export function module1() {}`
};
const module2: FileOrFolder = {
path: module2Path,
content: `export function module2() {}`
};
return { module1, module2 };
}
function verifyTrace(resolutionTrace: string[], expected: string[]) {
assert.deepEqual(resolutionTrace, expected);
resolutionTrace.length = 0;
}
function getExpectedFileDoesNotExistResolutionTrace(host: TestServerHost, expectedTrace: string[], foundModule: boolean, module: FileOrFolder, directory: string, file: string, ignoreIfParentMissing?: boolean) {
if (!foundModule) {
const path = combinePaths(directory, file);
if (!ignoreIfParentMissing || host.directoryExists(getDirectoryPath(path))) {
if (module.path === path) {
foundModule = true;
}
else {
expectedTrace.push(`File '${path}' does not exist.`);
}
}
}
return foundModule;
}
function getExpectedMissedLocationResolutionTrace(host: TestServerHost, expectedTrace: string[], dirPath: string, module: FileOrFolder, moduleName: string, useNodeModules: boolean, cacheLocation?: string) {
let foundModule = false;
forEachAncestorDirectory(dirPath, dirPath => {
if (dirPath === cacheLocation) {
return foundModule;
}
const directory = useNodeModules ? combinePaths(dirPath, nodeModules) : dirPath;
if (useNodeModules && !foundModule && !host.directoryExists(directory)) {
expectedTrace.push(`Directory '${directory}' does not exist, skipping all lookups in it.`);
return undefined;
}
foundModule = getExpectedFileDoesNotExistResolutionTrace(host, expectedTrace, foundModule, module, directory, `${moduleName}/package.json`, /*ignoreIfParentMissing*/ true);
foundModule = getExpectedFileDoesNotExistResolutionTrace(host, expectedTrace, foundModule, module, directory, `${moduleName}.ts`);
foundModule = getExpectedFileDoesNotExistResolutionTrace(host, expectedTrace, foundModule, module, directory, `${moduleName}.tsx`);
foundModule = getExpectedFileDoesNotExistResolutionTrace(host, expectedTrace, foundModule, module, directory, `${moduleName}.d.ts`);
foundModule = getExpectedFileDoesNotExistResolutionTrace(host, expectedTrace, foundModule, module, directory, `${moduleName}/index.ts`, /*ignoreIfParentMissing*/ true);
if (useNodeModules && !foundModule) {
expectedTrace.push(`Directory '${directory}/@types' does not exist, skipping all lookups in it.`);
}
return foundModule ? true : undefined;
});
}
function getExpectedResolutionTraceHeader(expectedTrace: string[], file: FileOrFolder, moduleName: string) {
expectedTrace.push(
`======== Resolving module '${moduleName}' from '${file.path}'. ========`,
`Module resolution kind is not specified, using 'NodeJs'.`
);
}
function getExpectedResolutionTraceFooter(expectedTrace: string[], module: FileOrFolder, moduleName: string, addRealPathTrace: boolean, ignoreModuleFileFound?: boolean) {
if (!ignoreModuleFileFound) {
expectedTrace.push(`File '${module.path}' exist - use it as a name resolution result.`);
}
if (addRealPathTrace) {
expectedTrace.push(`Resolving real path for '${module.path}', result '${module.path}'.`);
}
expectedTrace.push(`======== Module name '${moduleName}' was successfully resolved to '${module.path}'. ========`);
}
function getExpectedRelativeModuleResolutionTrace(host: TestServerHost, file: FileOrFolder, module: FileOrFolder, moduleName: string, expectedTrace: string[] = []) {
getExpectedResolutionTraceHeader(expectedTrace, file, moduleName);
expectedTrace.push(`Loading module as file / folder, candidate module location '${removeFileExtension(module.path)}', target file type 'TypeScript'.`);
getExpectedMissedLocationResolutionTrace(host, expectedTrace, getDirectoryPath(normalizePath(combinePaths(getDirectoryPath(file.path), moduleName))), module, moduleName.substring(moduleName.lastIndexOf("/") + 1), /*useNodeModules*/ false);
getExpectedResolutionTraceFooter(expectedTrace, module, moduleName, /*addRealPathTrace*/ false);
return expectedTrace;
}
function getExpectedNonRelativeModuleResolutionTrace(host: TestServerHost, file: FileOrFolder, module: FileOrFolder, moduleName: string, expectedTrace: string[] = []) {
getExpectedResolutionTraceHeader(expectedTrace, file, moduleName);
expectedTrace.push(`Loading module '${moduleName}' from 'node_modules' folder, target file type 'TypeScript'.`);
getExpectedMissedLocationResolutionTrace(host, expectedTrace, getDirectoryPath(file.path), module, moduleName, /*useNodeModules*/ true);
getExpectedResolutionTraceFooter(expectedTrace, module, moduleName, /*addRealPathTrace*/ true);
return expectedTrace;
}
function getExpectedNonRelativeModuleResolutionFromCacheTrace(host: TestServerHost, file: FileOrFolder, module: FileOrFolder, moduleName: string, cacheLocation: string, expectedTrace: string[] = []) {
getExpectedResolutionTraceHeader(expectedTrace, file, moduleName);
expectedTrace.push(`Loading module '${moduleName}' from 'node_modules' folder, target file type 'TypeScript'.`);
getExpectedMissedLocationResolutionTrace(host, expectedTrace, getDirectoryPath(file.path), module, moduleName, /*useNodeModules*/ true, cacheLocation);
expectedTrace.push(`Resolution for module '${moduleName}' was found in cache from location '${cacheLocation}'.`);
getExpectedResolutionTraceFooter(expectedTrace, module, moduleName, /*addRealPathTrace*/ true, /*ignoreModuleFileFound*/ true);
return expectedTrace;
}
function getExpectedReusingResolutionFromOldProgram(file: FileOrFolder, moduleName: string) {
return `Reusing resolution of module '${moduleName}' to file '${file.path}' from old program.`;
}
function verifyWatchesWithConfigFile(host: TestServerHost, files: FileOrFolder[], openFile: FileOrFolder) {
checkWatchedFiles(host, mapDefined(files, f => f === openFile ? undefined : f.path));
checkWatchedDirectories(host, [], /*recursive*/ false);
const configDirectory = getDirectoryPath(configFile.path);
checkWatchedDirectories(host, [configDirectory, `${configDirectory}/${nodeModulesAtTypes}`], /*recursive*/ true);
}
describe("from files in same folder", () => {
function getFiles(fileContent: string) {
const file1: FileOrFolder = {
path: `${projectLocation}/src/file1.ts`,
content: fileContent
};
const file2: FileOrFolder = {
path: `${projectLocation}/src/file2.ts`,
content: fileContent
};
return { file1, file2 };
}
it("relative module name", () => {
const module1Name = "./module1";
const module2Name = "../module2";
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
const { file1, file2 } = getFiles(fileContent);
const { module1, module2 } = getModules(`${projectLocation}/src/module1.ts`, `${projectLocation}/module2.ts`);
const files = [module1, module2, file1, file2, configFile, libFile];
const host = createServerHost(files);
const resolutionTrace = createHostModuleResolutionTrace(host);
const service = createProjectService(host);
service.openClientFile(file1.path);
const expectedTrace = getExpectedRelativeModuleResolutionTrace(host, file1, module1, module1Name);
getExpectedRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
verifyTrace(resolutionTrace, expectedTrace);
verifyWatchesWithConfigFile(host, files, file1);
file1.content += fileContent;
file2.content += fileContent;
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
verifyTrace(resolutionTrace, [
getExpectedReusingResolutionFromOldProgram(file1, module1Name),
getExpectedReusingResolutionFromOldProgram(file1, module2Name)
]);
verifyWatchesWithConfigFile(host, files, file1);
});
it("non relative module name", () => {
const module1Name = "module1";
const module2Name = "module2";
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
const { file1, file2 } = getFiles(fileContent);
const { module1, module2 } = getModules(`${projectLocation}/src/node_modules/module1/index.ts`, `${projectLocation}/node_modules/module2/index.ts`);
const files = [module1, module2, file1, file2, configFile, libFile];
const host = createServerHost(files);
const resolutionTrace = createHostModuleResolutionTrace(host);
const service = createProjectService(host);
service.openClientFile(file1.path);
const expectedTrace = getExpectedNonRelativeModuleResolutionTrace(host, file1, module1, module1Name);
getExpectedNonRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
verifyTrace(resolutionTrace, expectedTrace);
verifyWatchesWithConfigFile(host, files, file1);
file1.content += fileContent;
file2.content += fileContent;
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
verifyTrace(resolutionTrace, [
getExpectedReusingResolutionFromOldProgram(file1, module1Name),
getExpectedReusingResolutionFromOldProgram(file1, module2Name)
]);
verifyWatchesWithConfigFile(host, files, file1);
});
});
describe("from files in different folders", () => {
function getFiles(fileContent1: string, fileContent2 = fileContent1, fileContent3 = fileContent1, fileContent4 = fileContent1) {
const file1: FileOrFolder = {
path: `${projectLocation}/product/src/file1.ts`,
content: fileContent1
};
const file2: FileOrFolder = {
path: `${projectLocation}/product/src/feature/file2.ts`,
content: fileContent2
};
const file3: FileOrFolder = {
path: `${projectLocation}/product/test/src/file3.ts`,
content: fileContent3
};
const file4: FileOrFolder = {
path: `${projectLocation}/product/test/file4.ts`,
content: fileContent4
};
return { file1, file2, file3, file4 };
}
it("relative module name", () => {
const module1Name = "./module1";
const module2Name = "../module2";
const module3Name = "../module1";
const module4Name = "../../module2";
const module5Name = "../../src/module1";
const module6Name = "../src/module1";
const fileContent1 = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
const fileContent2 = `import { module1 } from "${module3Name}";import { module2 } from "${module4Name}";`;
const fileContent3 = `import { module1 } from "${module5Name}";import { module2 } from "${module4Name}";`;
const fileContent4 = `import { module1 } from "${module6Name}";import { module2 } from "${module2Name}";`;
const { file1, file2, file3, file4 } = getFiles(fileContent1, fileContent2, fileContent3, fileContent4);
const { module1, module2 } = getModules(`${projectLocation}/product/src/module1.ts`, `${projectLocation}/product/module2.ts`);
const files = [module1, module2, file1, file2, file3, file4, configFile, libFile];
const host = createServerHost(files);
const resolutionTrace = createHostModuleResolutionTrace(host);
const service = createProjectService(host);
service.openClientFile(file1.path);
const expectedTrace = getExpectedRelativeModuleResolutionTrace(host, file1, module1, module1Name);
getExpectedRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
getExpectedRelativeModuleResolutionTrace(host, file2, module1, module3Name, expectedTrace);
getExpectedRelativeModuleResolutionTrace(host, file2, module2, module4Name, expectedTrace);
getExpectedRelativeModuleResolutionTrace(host, file4, module1, module6Name, expectedTrace);
getExpectedRelativeModuleResolutionTrace(host, file4, module2, module2Name, expectedTrace);
getExpectedRelativeModuleResolutionTrace(host, file3, module1, module5Name, expectedTrace);
getExpectedRelativeModuleResolutionTrace(host, file3, module2, module4Name, expectedTrace);
verifyTrace(resolutionTrace, expectedTrace);
verifyWatchesWithConfigFile(host, files, file1);
file1.content += fileContent1;
file2.content += fileContent2;
file3.content += fileContent3;
file4.content += fileContent4;
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
verifyTrace(resolutionTrace, [
getExpectedReusingResolutionFromOldProgram(file1, module1Name),
getExpectedReusingResolutionFromOldProgram(file1, module2Name)
]);
verifyWatchesWithConfigFile(host, files, file1);
});
it("non relative module name", () => {
const module1Name = "module1";
const module2Name = "module2";
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
const { file1, file2, file3, file4 } = getFiles(fileContent);
const { module1, module2 } = getModules(`${projectLocation}/product/node_modules/module1/index.ts`, `${projectLocation}/node_modules/module2/index.ts`);
const files = [module1, module2, file1, file2, file3, file4, configFile, libFile];
const host = createServerHost(files);
const resolutionTrace = createHostModuleResolutionTrace(host);
const service = createProjectService(host);
service.openClientFile(file1.path);
const expectedTrace = getExpectedNonRelativeModuleResolutionTrace(host, file1, module1, module1Name);
getExpectedNonRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module1, module1Name, getDirectoryPath(file1.path), expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module2, module2Name, getDirectoryPath(file1.path), expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module1, module1Name, `${projectLocation}/product`, expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module2, module2Name, `${projectLocation}/product`, expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module1, module1Name, getDirectoryPath(file4.path), expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module2, module2Name, getDirectoryPath(file4.path), expectedTrace);
verifyTrace(resolutionTrace, expectedTrace);
verifyWatchesWithConfigFile(host, files, file1);
file1.content += fileContent;
file2.content += fileContent;
file3.content += fileContent;
file4.content += fileContent;
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
verifyTrace(resolutionTrace, [
getExpectedReusingResolutionFromOldProgram(file1, module1Name),
getExpectedReusingResolutionFromOldProgram(file1, module2Name)
]);
verifyWatchesWithConfigFile(host, files, file1);
});
it("non relative module name from inferred project", () => {
const module1Name = "module1";
const module2Name = "module2";
const file2Name = "./feature/file2";
const file3Name = "../test/src/file3";
const file4Name = "../test/file4";
const importModuleContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
const { file1, file2, file3, file4 } = getFiles(`import "${file2Name}"; import "${file4Name}"; import "${file3Name}"; ${importModuleContent}`, importModuleContent, importModuleContent, importModuleContent);
const { module1, module2 } = getModules(`${projectLocation}/product/node_modules/module1/index.ts`, `${projectLocation}/node_modules/module2/index.ts`);
const files = [module1, module2, file1, file2, file3, file4, libFile];
const host = createServerHost(files);
const resolutionTrace = createHostModuleResolutionTrace(host);
const service = createProjectService(host);
service.setCompilerOptionsForInferredProjects({ traceResolution: true });
service.openClientFile(file1.path);
const expectedTrace = getExpectedRelativeModuleResolutionTrace(host, file1, file2, file2Name);
getExpectedRelativeModuleResolutionTrace(host, file1, file4, file4Name, expectedTrace);
getExpectedRelativeModuleResolutionTrace(host, file1, file3, file3Name, expectedTrace);
getExpectedNonRelativeModuleResolutionTrace(host, file1, module1, module1Name, expectedTrace);
getExpectedNonRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module1, module1Name, getDirectoryPath(file1.path), expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module2, module2Name, getDirectoryPath(file1.path), expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module1, module1Name, `${projectLocation}/product`, expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module2, module2Name, `${projectLocation}/product`, expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module1, module1Name, getDirectoryPath(file4.path), expectedTrace);
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module2, module2Name, getDirectoryPath(file4.path), expectedTrace);
verifyTrace(resolutionTrace, expectedTrace);
const currentDirectory = getDirectoryPath(file1.path);
const watchedFiles = mapDefined(files, f => f === file1 ? undefined : f.path);
forEachAncestorDirectory(currentDirectory, d => {
watchedFiles.push(combinePaths(d, "tsconfig.json"), combinePaths(d, "jsconfig.json"));
});
const watchedRecursiveDirectories = getTypeRootsFromLocation(currentDirectory).concat([
currentDirectory, `${projectLocation}/product/${nodeModules}`,
`${projectLocation}/${nodeModules}`, `${projectLocation}/product/test/${nodeModules}`,
`${projectLocation}/product/test/src/${nodeModules}`
]);
checkWatches();
file1.content += importModuleContent;
file2.content += importModuleContent;
file3.content += importModuleContent;
file4.content += importModuleContent;
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
verifyTrace(resolutionTrace, [
getExpectedReusingResolutionFromOldProgram(file1, file2Name),
getExpectedReusingResolutionFromOldProgram(file1, file4Name),
getExpectedReusingResolutionFromOldProgram(file1, file3Name),
getExpectedReusingResolutionFromOldProgram(file1, module1Name),
getExpectedReusingResolutionFromOldProgram(file1, module2Name)
]);
checkWatches();
function checkWatches() {
checkWatchedFiles(host, watchedFiles);
checkWatchedDirectories(host, [], /*recursive*/ false);
checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true);
}
});
});
});
describe("watchDirectories implementation", () => {
function verifyCompletionListWithNewFileInSubFolder(tscWatchDirectory: TestFSWithWatch.Tsc_WatchDirectory) {
const projectFolder = "/a/username/project";
@@ -7031,8 +7498,8 @@ namespace ts.projectSystem {
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
ts.TestFSWithWatch.checkMultiMapKeyCount("watchedFiles", host.watchedFiles, expectedWatchedFiles);
ts.TestFSWithWatch.checkMultiMapKeyCount("watchedDirectories", host.watchedDirectories, expectedWatchedDirectories);
TestFSWithWatch.checkMultiMapKeyCount("watchedFiles", host.watchedFiles, expectedWatchedFiles);
TestFSWithWatch.checkMultiMapKeyCount("watchedDirectories", host.watchedDirectories, expectedWatchedDirectories);
checkProjectActualFiles(project, fileNames);
}
}
+2 -2
View File
@@ -1387,7 +1387,7 @@ namespace ts.projectSystem {
node: { typingLocation: node.path, version: Semver.parse("1.0.0") }
});
const registry = createTypesRegistry("node");
registry.delete(`ts${ts.versionMajorMinor}`);
registry.delete(`ts${versionMajorMinor}`);
const logger = trackingLogger();
const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(<Path>app.path), emptySafeList, cache, { enable: true }, ["http"], registry);
assert.deepEqual(logger.finish(), [
@@ -1419,7 +1419,7 @@ namespace ts.projectSystem {
commander: { typingLocation: commander.path, version: Semver.parse("1.3.0-next.0") }
});
const registry = createTypesRegistry("node", "commander");
registry.get("node")[`ts${ts.versionMajorMinor}`] = "1.3.0-next.1";
registry.get("node")[`ts${versionMajorMinor}`] = "1.3.0-next.1";
const logger = trackingLogger();
const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(<Path>app.path), emptySafeList, cache, { enable: true }, ["http", "commander"], registry);
assert.deepEqual(logger.finish(), [
+1 -1
View File
@@ -302,7 +302,7 @@ and grew 1cm per day`;
it("Line/offset from pos", () => {
for (let i = 0; i < iterationCount; i++) {
const lp = lineIndex.positionToLineOffset(rsa[i]);
const lac = ts.computeLineAndCharacterOfPosition(lineMap, rsa[i]);
const lac = 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 - 1, "Character offset mismatch " + lac.character + " " + (lp.offset - 1) + " " + i);
}
+5 -2
View File
@@ -689,7 +689,7 @@ interface Array<T> {}`
}
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[] {
return ts.matchFiles(path, extensions, exclude, include, this.useCaseSensitiveFileNames, this.getCurrentDirectory(), depth, (dir) => {
return matchFiles(path, extensions, exclude, include, this.useCaseSensitiveFileNames, this.getCurrentDirectory(), depth, (dir) => {
const directories: string[] = [];
const files: string[] = [];
const folder = this.getRealFolder(this.toPath(dir));
@@ -780,7 +780,10 @@ interface Array<T> {}`
}
}
runQueuedImmediateCallbacks() {
runQueuedImmediateCallbacks(checkCount?: number) {
if (checkCount !== undefined) {
assert.equal(this.immediateCallbacks.count(), checkCount);
}
this.immediateCallbacks.invoke();
}
+2
View File
@@ -1 +1,3 @@
/// <reference path="lib.es2017.d.ts" />
/// <reference path="lib.es2018.promise.d.ts" />
/// <reference path="lib.es2018.regexp.d.ts" />
+11
View File
@@ -0,0 +1,11 @@
interface RegExpMatchArray {
groups?: {
[key: string]: string
}
}
interface RegExpExecArray {
groups?: {
[key: string]: string
}
}
-1
View File
@@ -1,4 +1,3 @@
/// <reference path="lib.es2018.d.ts" />
/// <reference path="lib.esnext.asynciterable.d.ts" />
/// <reference path="lib.esnext.array.d.ts" />
/// <reference path="lib.esnext.promise.d.ts" />
@@ -903,6 +903,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[向属性“{0}”添加明确的赋值断言]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -915,6 +924,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[向属性“{0}”添加初始值设定项]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -939,6 +957,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[向属性“{0}”添加“未定义”类型]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -903,6 +903,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[將明確指派判斷提示新增至屬性 '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -915,6 +924,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[將初始設定式新增至屬性 '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -939,6 +957,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[將 'undefined' 類型新增至屬性 '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -912,6 +912,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Přidat kontrolní výraz jednoznačného přiřazení k vlastnosti {0}]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -924,6 +933,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Přidat inicializační výraz k vlastnosti {0}]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -948,6 +966,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Přidat typ undefined k vlastnosti {0}]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -912,6 +912,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Agregar aserción de asignación definitiva a la propiedad "{0}"]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -924,6 +933,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Agregar inicializador a la propiedad "{0}"]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -948,6 +966,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Agregar un tipo "undefined" a la propiedad "{0}"]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -912,6 +912,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Ajouter une assertion d'assignation définie à la propriété '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -924,6 +933,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Ajouter un initialiseur à la propriété '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -948,6 +966,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Ajouter un type 'undefined' à la propriété '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -903,6 +903,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Aggiungere l'asserzione di assegnazione definita alla proprietà '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -915,6 +924,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Aggiungere l'inizializzatore alla proprietà '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -939,6 +957,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Aggiungere il tipo 'undefined' alla proprietà '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -903,6 +903,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[プロパティ '{0}' に限定代入アサーションを追加します]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -915,6 +924,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[プロパティ '{0}' に初期化子を追加します]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -939,6 +957,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[プロパティ '{0}' に '未定義' の型を追加します]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -903,6 +903,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['{0}' 속성에 한정된 할당 어설션 추가]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -915,6 +924,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['{0}' 속성에 이니셜라이저 추가]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -939,6 +957,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['{0}' 속성에 '정의되지 않은' 형식 추가]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -893,6 +893,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Dodaj asercję określonego przypisania do właściwości „{0}”]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -905,6 +914,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Dodaj inicjator do właściwości „{0}”]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -929,6 +947,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Dodaj typ „undefined” do właściwości „{0}”]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -893,6 +893,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Adicionar a asserção de atribuição definitiva à propriedade '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -905,6 +914,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Adicionar inicializador à propriedade '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -929,6 +947,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Adicionar tipo 'indefinido' à propriedade '{0}']]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -902,6 +902,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Добавить утверждение определенного присваивания к свойству "{0}"]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -914,6 +923,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Добавить инициализатор к свойству "{0}"]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -938,6 +956,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Добавить тип "undefined" к свойству "{0}"]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
@@ -896,6 +896,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_definite_assignment_assertion_to_property_0_95020" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add definite assignment assertion to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['{0}' özelliğine belirli atama onayı ekle]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_index_signature_for_property_0_90017" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add index signature for property '{0}']]></Val>
@@ -908,6 +917,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_initializer_to_property_0_95019" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add initializer to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['{0}' özelliğine başlatıcı ekle]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_missing_super_call_90001" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add missing 'super()' call]]></Val>
@@ -932,6 +950,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Add_undefined_type_to_property_0_95018" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Add 'undefined' type to property '{0}']]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA['{0}' özelliğine 'undefined' türünü ekle]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript__5068" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.]]></Val>
+26 -36
View File
@@ -71,11 +71,11 @@ namespace ts.server {
};
}
private convertCodeEditsToTextChange(fileName: string, codeEdit: protocol.CodeEdit): ts.TextChange {
private convertCodeEditsToTextChange(fileName: string, codeEdit: protocol.CodeEdit): TextChange {
return { span: this.decodeSpan(codeEdit, fileName), newText: codeEdit.newText };
}
private processRequest<T extends protocol.Request>(command: string, args?: any): T {
private processRequest<T extends protocol.Request>(command: string, args?: T["arguments"]): T {
const request: protocol.Request = {
seq: this.sequence,
type: "request",
@@ -229,7 +229,7 @@ namespace ts.server {
}));
}
getFormattingEditsForRange(file: string, start: number, end: number, _options: FormatCodeOptions): ts.TextChange[] {
getFormattingEditsForRange(file: string, start: number, end: number, _options: FormatCodeOptions): TextChange[] {
const args: protocol.FormatRequestArgs = this.createFileLocationRequestArgsWithEndLineAndOffset(file, start, end);
@@ -240,11 +240,11 @@ namespace ts.server {
return response.body.map(entry => this.convertCodeEditsToTextChange(file, entry));
}
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): ts.TextChange[] {
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] {
return this.getFormattingEditsForRange(fileName, 0, this.host.getScriptSnapshot(fileName).getLength(), options);
}
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, _options: FormatCodeOptions): ts.TextChange[] {
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, _options: FormatCodeOptions): TextChange[] {
const args: protocol.FormatOnKeyRequestArgs = { ...this.createFileLocationRequestArgs(fileName, position), key };
// TODO: handle FormatCodeOptions
@@ -343,41 +343,31 @@ namespace ts.server {
}
getSyntacticDiagnostics(file: string): Diagnostic[] {
const args: protocol.SyntacticDiagnosticsSyncRequestArgs = { file, includeLinePosition: true };
const request = this.processRequest<protocol.SyntacticDiagnosticsSyncRequest>(CommandNames.SyntacticDiagnosticsSync, args);
const response = this.processResponse<protocol.SyntacticDiagnosticsSyncResponse>(request);
return (<protocol.DiagnosticWithLinePosition[]>response.body).map(entry => this.convertDiagnostic(entry, file));
return this.getDiagnostics(file, CommandNames.SyntacticDiagnosticsSync);
}
getSemanticDiagnostics(file: string): Diagnostic[] {
const args: protocol.SemanticDiagnosticsSyncRequestArgs = { file, includeLinePosition: true };
const request = this.processRequest<protocol.SemanticDiagnosticsSyncRequest>(CommandNames.SemanticDiagnosticsSync, args);
const response = this.processResponse<protocol.SemanticDiagnosticsSyncResponse>(request);
return (<protocol.DiagnosticWithLinePosition[]>response.body).map(entry => this.convertDiagnostic(entry, file));
return this.getDiagnostics(file, CommandNames.SemanticDiagnosticsSync);
}
getSuggestionDiagnostics(file: string): Diagnostic[] {
return this.getDiagnostics(file, CommandNames.SuggestionDiagnosticsSync);
}
convertDiagnostic(entry: protocol.DiagnosticWithLinePosition, _fileName: string): Diagnostic {
let category: DiagnosticCategory;
for (const id in DiagnosticCategory) {
if (isString(id) && entry.category === id.toLowerCase()) {
category = (<any>DiagnosticCategory)[id];
}
}
private getDiagnostics(file: string, command: CommandNames) {
const request = this.processRequest<protocol.SyntacticDiagnosticsSyncRequest | protocol.SemanticDiagnosticsSyncRequest | protocol.SuggestionDiagnosticsSyncRequest>(command, { file, includeLinePosition: true });
const response = this.processResponse<protocol.SyntacticDiagnosticsSyncResponse | protocol.SemanticDiagnosticsSyncResponse | protocol.SuggestionDiagnosticsSyncResponse>(request);
Debug.assert(category !== undefined, "convertDiagnostic: category should not be undefined");
return {
file: undefined,
start: entry.start,
length: entry.length,
messageText: entry.message,
category,
code: entry.code
};
return (<protocol.DiagnosticWithLinePosition[]>response.body).map(entry => {
const category = firstDefined(Object.keys(DiagnosticCategory), id =>
isString(id) && entry.category === id.toLowerCase() ? (<any>DiagnosticCategory)[id] : undefined);
return {
file: undefined,
start: entry.start,
length: entry.length,
messageText: entry.message,
category: Debug.assertDefined(category, "convertDiagnostic: category should not be undefined"),
code: entry.code
};
});
}
getCompilerOptionsDiagnostics(): Diagnostic[] {
@@ -650,7 +640,7 @@ namespace ts.server {
}));
}
convertTextChangeToCodeEdit(change: protocol.CodeEdit, fileName: string): ts.TextChange {
convertTextChangeToCodeEdit(change: protocol.CodeEdit, fileName: string): TextChange {
return {
span: this.decodeSpan(change, fileName),
newText: change.newText ? change.newText : ""
+5 -5
View File
@@ -1393,7 +1393,7 @@ namespace ts.server {
return project;
}
private sendProjectTelemetry(projectKey: string, project: server.ExternalProject | server.ConfiguredProject, projectOptions?: ProjectOptions): void {
private sendProjectTelemetry(projectKey: string, project: ExternalProject | ConfiguredProject, projectOptions?: ProjectOptions): void {
if (this.seenProjects.has(projectKey)) {
return;
}
@@ -1414,18 +1414,18 @@ namespace ts.server {
exclude: projectOptions && projectOptions.configHasExcludeProperty,
compileOnSave: project.compileOnSaveEnabled,
configFileName: configFileName(),
projectType: project instanceof server.ExternalProject ? "external" : "configured",
projectType: project instanceof ExternalProject ? "external" : "configured",
languageServiceEnabled: project.languageServiceEnabled,
version,
};
this.eventHandler({ eventName: ProjectInfoTelemetryEvent, data });
function configFileName(): ProjectInfoTelemetryEventData["configFileName"] {
if (!(project instanceof server.ConfiguredProject)) {
if (!(project instanceof ConfiguredProject)) {
return "other";
}
const configFilePath = project instanceof server.ConfiguredProject && project.getConfigFilePath();
const configFilePath = project instanceof ConfiguredProject && project.getConfigFilePath();
return getBaseConfigFileName(configFilePath) || "other";
}
@@ -2240,7 +2240,7 @@ namespace ts.server {
}
const excludeRegexes = excludeRules.map(e => new RegExp(e, "i"));
const filesToKeep: ts.server.protocol.ExternalFile[] = [];
const filesToKeep: protocol.ExternalFile[] = [];
for (let i = 0; i < proj.rootFiles.length; i++) {
if (excludeRegexes.some(re => re.test(normalizedNames[i]))) {
excludedFiles.push(normalizedNames[i]);
+9 -2
View File
@@ -210,6 +210,9 @@ namespace ts.server {
/*@internal*/
public directoryStructureHost: DirectoryStructureHost;
/*@internal*/
public readonly getCanonicalFileName: GetCanonicalFileName;
/*@internal*/
constructor(
/*@internal*/readonly projectName: string,
@@ -224,6 +227,7 @@ namespace ts.server {
currentDirectory: string | undefined) {
this.directoryStructureHost = directoryStructureHost;
this.currentDirectory = this.projectService.getNormalizedAbsolutePath(currentDirectory || "");
this.getCanonicalFileName = this.projectService.toCanonicalFileName;
this.cancellationToken = new ThrottledCancellationToken(this.projectService.cancellationToken, this.projectService.throttleWaitMilliseconds);
if (!this.compilerOptions) {
@@ -238,7 +242,10 @@ namespace ts.server {
this.setInternalCompilerOptionsForEmittingJsFiles();
const host = this.projectService.host;
if (host.trace) {
if (this.projectService.logger.loggingEnabled()) {
this.trace = s => this.writeLog(s);
}
else if (host.trace) {
this.trace = s => host.trace(s);
}
@@ -853,7 +860,7 @@ namespace ts.server {
}
protected removeExistingTypings(include: string[]): string[] {
const existing = ts.getAutomaticTypeDirectiveNames(this.getCompilerOptions(), this.directoryStructureHost);
const existing = getAutomaticTypeDirectiveNames(this.getCompilerOptions(), this.directoryStructureHost);
return include.filter(i => existing.indexOf(i) < 0);
}
+15 -2
View File
@@ -1,3 +1,5 @@
// tslint:disable no-unnecessary-qualifier
/**
* Declaration module describing the TypeScript Server protocol
*/
@@ -42,6 +44,7 @@ namespace ts.server.protocol {
GeterrForProject = "geterrForProject",
SemanticDiagnosticsSync = "semanticDiagnosticsSync",
SyntacticDiagnosticsSync = "syntacticDiagnosticsSync",
SuggestionDiagnosticsSync = "suggestionDiagnosticsSync",
NavBar = "navbar",
/* @internal */
NavBarFull = "navbar-full",
@@ -2010,6 +2013,14 @@ namespace ts.server.protocol {
body?: Diagnostic[] | DiagnosticWithLinePosition[];
}
export interface SuggestionDiagnosticsSyncRequest extends FileRequest {
command: CommandTypes.SuggestionDiagnosticsSync;
arguments: SuggestionDiagnosticsSyncRequestArgs;
}
export type SuggestionDiagnosticsSyncRequestArgs = SemanticDiagnosticsSyncRequestArgs;
export type SuggestionDiagnosticsSyncResponse = SemanticDiagnosticsSyncResponse;
/**
* Synchronous request for syntactic diagnostics of one file.
*/
@@ -2121,7 +2132,7 @@ namespace ts.server.protocol {
text: string;
/**
* The category of the diagnostic message, e.g. "error" vs. "warning"
* The category of the diagnostic message, e.g. "error", "warning", or "suggestion".
*/
category: string;
@@ -2155,8 +2166,10 @@ namespace ts.server.protocol {
diagnostics: Diagnostic[];
}
export type DiagnosticEventKind = "semanticDiag" | "syntaxDiag" | "suggestionDiag";
/**
* Event message for "syntaxDiag" and "semanticDiag" event types.
* Event message for DiagnosticEventKind event types.
* These events provide syntactic and semantic errors for a file.
*/
export interface DiagnosticEvent extends Event {
+7 -2
View File
@@ -176,8 +176,13 @@ namespace ts.server {
return this.switchToScriptVersionCache();
}
// Else if the svc is uptodate with the text, we are good
return !this.pendingReloadFromDisk && this.svc;
// If there is pending reload from the disk then, reload the text
if (this.pendingReloadFromDisk) {
this.reloadWithFileText();
}
// At this point if svc is present its valid
return this.svc;
}
private getOrLoadText() {
+3 -3
View File
@@ -142,7 +142,7 @@ namespace ts.server {
terminal: false,
});
class Logger implements server.Logger {
class Logger implements server.Logger { // tslint:disable-line no-unnecessary-qualifier
private fd = -1;
private seq = 0;
private inGroup = false;
@@ -266,7 +266,7 @@ namespace ts.server {
constructor(
private readonly telemetryEnabled: boolean,
private readonly logger: server.Logger,
private readonly logger: Logger,
private readonly host: ServerHost,
readonly globalTypingsCacheLocation: string,
readonly typingSafeListLocation: string,
@@ -391,7 +391,7 @@ namespace ts.server {
switch (response.kind) {
case EventTypesRegistry:
this.typesRegistryCache = ts.createMapFromTemplate(response.typesRegistry);
this.typesRegistryCache = createMapFromTemplate(response.typesRegistry);
break;
case ActionPackageInstalled: {
const { success, message } = response;
+61 -39
View File
@@ -79,7 +79,7 @@ namespace ts.server {
end: scriptInfo.positionToLineOffset(diag.start + diag.length),
text: flattenDiagnosticMessageText(diag.messageText, "\n"),
code: diag.code,
category: DiagnosticCategory[diag.category].toLowerCase(),
category: diagnosticCategoryName(diag),
source: diag.source
};
}
@@ -95,7 +95,7 @@ namespace ts.server {
const end = diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start + diag.length));
const text = flattenDiagnosticMessageText(diag.messageText, "\n");
const { code, source } = diag;
const category = DiagnosticCategory[diag.category].toLowerCase();
const category = diagnosticCategoryName(diag);
return includeFileName ? { start, end, text, code, category, source, fileName: diag.file && diag.file.fileName } :
{ start, end, text, code, category, source };
}
@@ -105,7 +105,7 @@ namespace ts.server {
project: Project;
}
function allEditsBeforePos(edits: ts.TextChange[], pos: number) {
function allEditsBeforePos(edits: TextChange[], pos: number) {
for (const edit of edits) {
if (textSpanEnd(edit.span) >= pos) {
return false;
@@ -122,7 +122,7 @@ namespace ts.server {
export type CommandNames = protocol.CommandTypes;
export const CommandNames = (<any>protocol).CommandTypes; // tslint:disable-line variable-name
export function formatMessage<T extends protocol.Message>(msg: T, logger: server.Logger, byteLength: (s: string, encoding: string) => number, newLine: string): string {
export function formatMessage<T extends protocol.Message>(msg: T, logger: Logger, byteLength: (s: string, encoding: string) => number, newLine: string): string {
const verboseLogging = logger.hasLevel(LogLevel.verbose);
const json = JSON.stringify(msg);
@@ -466,30 +466,26 @@ namespace ts.server {
}
private semanticCheck(file: NormalizedPath, project: Project) {
try {
let diags: ReadonlyArray<Diagnostic> = emptyArray;
if (!isDeclarationFileInJSOnlyNonConfiguredProject(project, file)) {
diags = project.getLanguageService().getSemanticDiagnostics(file);
}
const bakedDiags = diags.map((diag) => formatDiag(file, project, diag));
this.event<protocol.DiagnosticEventBody>({ file, diagnostics: bakedDiags }, "semanticDiag");
}
catch (err) {
this.logError(err, "semantic check");
}
const diags = isDeclarationFileInJSOnlyNonConfiguredProject(project, file)
? emptyArray
: project.getLanguageService().getSemanticDiagnostics(file);
this.sendDiagnosticsEvent(file, project, diags, "semanticDiag");
}
private syntacticCheck(file: NormalizedPath, project: Project) {
this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSyntacticDiagnostics(file), "syntaxDiag");
}
private infoCheck(file: NormalizedPath, project: Project) {
this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSuggestionDiagnostics(file), "suggestionDiag");
}
private sendDiagnosticsEvent(file: NormalizedPath, project: Project, diagnostics: ReadonlyArray<Diagnostic>, kind: protocol.DiagnosticEventKind): void {
try {
const diags = project.getLanguageService().getSyntacticDiagnostics(file);
if (diags) {
const bakedDiags = diags.map((diag) => formatDiag(file, project, diag));
this.event<protocol.DiagnosticEventBody>({ file, diagnostics: bakedDiags }, "syntaxDiag");
}
this.event<protocol.DiagnosticEventBody>({ file, diagnostics: diagnostics.map(diag => formatDiag(file, project, diag)) }, kind);
}
catch (err) {
this.logError(err, "syntactic check");
this.logError(err, kind);
}
}
@@ -499,21 +495,34 @@ namespace ts.server {
let index = 0;
const checkOne = () => {
if (this.changeSeq === seq) {
const checkSpec = checkList[index];
index++;
if (checkSpec.project.containsFile(checkSpec.fileName, requireOpen)) {
this.syntacticCheck(checkSpec.fileName, checkSpec.project);
if (this.changeSeq === seq) {
next.immediate(() => {
this.semanticCheck(checkSpec.fileName, checkSpec.project);
if (checkList.length > index) {
next.delay(followMs, checkOne);
}
});
}
}
if (this.changeSeq !== seq) {
return;
}
const { fileName, project } = checkList[index];
index++;
if (!project.containsFile(fileName, requireOpen)) {
return;
}
this.syntacticCheck(fileName, project);
if (this.changeSeq !== seq) {
return;
}
next.immediate(() => {
this.semanticCheck(fileName, project);
if (this.changeSeq !== seq) {
return;
}
next.immediate(() => {
this.infoCheck(fileName, project);
if (checkList.length > index) {
next.delay(followMs, checkOne);
}
});
});
};
if (checkList.length > index && this.changeSeq === seq) {
@@ -580,7 +589,7 @@ namespace ts.server {
message: flattenDiagnosticMessageText(d.messageText, this.host.newLine),
start: d.start,
length: d.length,
category: DiagnosticCategory[d.category].toLowerCase(),
category: diagnosticCategoryName(d),
code: d.code,
startLocation: d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start)),
endLocation: d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start + d.length))
@@ -606,7 +615,7 @@ namespace ts.server {
message: flattenDiagnosticMessageText(d.messageText, this.host.newLine),
start: d.start,
length: d.length,
category: DiagnosticCategory[d.category].toLowerCase(),
category: diagnosticCategoryName(d),
code: d.code,
source: d.source,
startLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start),
@@ -756,6 +765,16 @@ namespace ts.server {
return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), args.includeLinePosition);
}
private getSuggestionDiagnosticsSync(args: protocol.SuggestionDiagnosticsSyncRequestArgs): ReadonlyArray<protocol.Diagnostic> | ReadonlyArray<protocol.DiagnosticWithLinePosition> {
const { configFile } = this.getConfigFileAndProject(args);
if (configFile) {
// Currently there are no info diagnostics for config files.
return emptyArray;
}
// isSemantic because we don't want to info diagnostics in declaration files for JS-only users
return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSuggestionDiagnostics(file), args.includeLinePosition);
}
private getDocumentHighlights(args: protocol.DocumentHighlightsRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.DocumentHighlightsItem> | ReadonlyArray<DocumentHighlights> {
const { file, project } = this.getFileAndProject(args);
const position = this.getPositionInFile(args, file);
@@ -1694,7 +1713,7 @@ namespace ts.server {
};
}
private convertTextChangeToCodeEdit(change: ts.TextChange, scriptInfo: ScriptInfo): protocol.CodeEdit {
private convertTextChangeToCodeEdit(change: TextChange, scriptInfo: ScriptInfo): protocol.CodeEdit {
return {
start: scriptInfo.positionToLineOffset(change.span.start),
end: scriptInfo.positionToLineOffset(change.span.start + change.span.length),
@@ -1953,6 +1972,9 @@ namespace ts.server {
[CommandNames.SyntacticDiagnosticsSync]: (request: protocol.SyntacticDiagnosticsSyncRequest) => {
return this.requiredResponse(this.getSyntacticDiagnosticsSync(request.arguments));
},
[CommandNames.SuggestionDiagnosticsSync]: (request: protocol.SuggestionDiagnosticsSyncRequest) => {
return this.requiredResponse(this.getSuggestionDiagnosticsSync(request.arguments));
},
[CommandNames.Geterr]: (request: protocol.GeterrRequest) => {
this.errorCheck.startNew(next => this.getDiagnostics(next, request.arguments.delay, request.arguments.files));
return this.notRequired();
@@ -221,11 +221,11 @@ namespace ts.server.typingsInstaller {
});
}
const logFilePath = findArgument(server.Arguments.LogFile);
const globalTypingsCacheLocation = findArgument(server.Arguments.GlobalCacheLocation);
const typingSafeListLocation = findArgument(server.Arguments.TypingSafeListLocation);
const typesMapLocation = findArgument(server.Arguments.TypesMapLocation);
const npmLocation = findArgument(server.Arguments.NpmLocation);
const logFilePath = findArgument(Arguments.LogFile);
const globalTypingsCacheLocation = findArgument(Arguments.GlobalCacheLocation);
const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation);
const typesMapLocation = findArgument(Arguments.TypesMapLocation);
const npmLocation = findArgument(Arguments.NpmLocation);
const log = new FileLog(logFilePath);
if (log.isEnabled()) {
@@ -277,7 +277,7 @@ namespace ts.server.typingsInstaller {
this.sendResponse(<BeginInstallTypes>{
kind: EventBeginInstallTypes,
eventId: requestId,
typingsInstallerVersion: ts.version, // qualified explicitly to prevent occasional shadowing
typingsInstallerVersion: ts.version, // tslint:disable-line no-unnecessary-qualifier (qualified explicitly to prevent occasional shadowing)
projectName: req.projectName
});
@@ -308,7 +308,7 @@ namespace ts.server.typingsInstaller {
// packageName is guaranteed to exist in typesRegistry by filterTypings
const distTags = this.typesRegistry.get(packageName);
const newVersion = Semver.parse(distTags[`ts${ts.versionMajorMinor}`] || distTags[latestDistTag]);
const newVersion = Semver.parse(distTags[`ts${versionMajorMinor}`] || distTags[latestDistTag]);
const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion };
this.packageNameToTypingLocation.set(packageName, newTyping);
installedTypingFiles.push(typingFile);
@@ -326,7 +326,7 @@ namespace ts.server.typingsInstaller {
projectName: req.projectName,
packagesToInstall: scopedTypings,
installSuccess: ok,
typingsInstallerVersion: ts.version // qualified explicitly to prevent occasional shadowing
typingsInstallerVersion: ts.version // tslint:disable-line no-unnecessary-qualifier (qualified explicitly to prevent occasional shadowing)
};
this.sendResponse(response);
}
@@ -359,7 +359,7 @@ namespace ts.server.typingsInstaller {
this.log.writeLine(`Got FS notification for ${f}, handler is already invoked '${isInvoked}'`);
}
if (!isInvoked) {
this.sendResponse({ projectName, kind: server.ActionInvalidate });
this.sendResponse({ projectName, kind: ActionInvalidate });
isInvoked = true;
}
}, /*pollingInterval*/ 2000);
+1 -1
View File
@@ -83,7 +83,7 @@ namespace ts.server {
};
}
export function mergeMapLikes(target: MapLike<any>, source: MapLike<any>): void {
export function mergeMapLikes<T extends object>(target: T, source: Partial<T>): void {
for (const key in source) {
if (hasProperty(source, key)) {
target[key] = source[key];
+45 -47
View File
@@ -78,7 +78,7 @@ namespace ts.BreakpointResolver {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
return spanInVariableDeclaration(<VariableDeclaration>node);
return spanInVariableDeclaration(<VariableDeclaration | PropertyDeclaration | PropertySignature>node);
case SyntaxKind.Parameter:
return spanInParameterDeclaration(<ParameterDeclaration>node);
@@ -273,18 +273,17 @@ namespace ts.BreakpointResolver {
}
if (node.kind === SyntaxKind.BinaryExpression) {
const binaryExpression = <BinaryExpression>node;
const { left, operatorToken } = <BinaryExpression>node;
// Set breakpoint in destructuring pattern if its destructuring assignment
// [a, b, c] or {a, b, c} of
// [a, b, c] = expression or
// {a, b, c} = expression
if (isArrayLiteralOrObjectLiteralDestructuringPattern(binaryExpression.left)) {
if (isArrayLiteralOrObjectLiteralDestructuringPattern(left)) {
return spanInArrayLiteralOrObjectLiteralDestructuringPattern(
<ArrayLiteralExpression | ObjectLiteralExpression>binaryExpression.left);
<ArrayLiteralExpression | ObjectLiteralExpression>left);
}
if (binaryExpression.operatorToken.kind === SyntaxKind.EqualsToken &&
isArrayLiteralOrObjectLiteralDestructuringPattern(binaryExpression.parent)) {
if (operatorToken.kind === SyntaxKind.EqualsToken && isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) {
// Set breakpoint on assignment expression element of destructuring pattern
// a = expression of
// [a = expression, b, c] = someExpression or
@@ -292,8 +291,8 @@ namespace ts.BreakpointResolver {
return textSpan(node);
}
if (binaryExpression.operatorToken.kind === SyntaxKind.CommaToken) {
return spanInNode(binaryExpression.left);
if (operatorToken.kind === SyntaxKind.CommaToken) {
return spanInNode(left);
}
}
@@ -327,42 +326,42 @@ namespace ts.BreakpointResolver {
}
}
// If this is name of property assignment, set breakpoint in the initializer
if (node.parent.kind === SyntaxKind.PropertyAssignment &&
(<PropertyDeclaration>node.parent).name === node &&
!isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.parent)) {
return spanInNode((<PropertyDeclaration>node.parent).initializer);
}
// Breakpoint in type assertion goes to its operand
if (node.parent.kind === SyntaxKind.TypeAssertionExpression && (<TypeAssertion>node.parent).type === node) {
return spanInNextNode((<TypeAssertion>node.parent).type);
}
// return type of function go to previous token
if (isFunctionLike(node.parent) && (<FunctionLikeDeclaration>node.parent).type === node) {
return spanInPreviousNode(node);
}
// initializer of variable/parameter declaration go to previous node
if ((node.parent.kind === SyntaxKind.VariableDeclaration ||
node.parent.kind === SyntaxKind.Parameter)) {
const paramOrVarDecl = <VariableDeclaration | ParameterDeclaration>node.parent;
if (paramOrVarDecl.initializer === node ||
paramOrVarDecl.type === node ||
isAssignmentOperator(node.kind)) {
return spanInPreviousNode(node);
switch (node.parent.kind) {
case SyntaxKind.PropertyAssignment:
// If this is name of property assignment, set breakpoint in the initializer
if ((<PropertyAssignment>node.parent).name === node &&
!isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.parent)) {
return spanInNode((<PropertyAssignment>node.parent).initializer);
}
break;
case SyntaxKind.TypeAssertionExpression:
// Breakpoint in type assertion goes to its operand
if ((<TypeAssertion>node.parent).type === node) {
return spanInNextNode((<TypeAssertion>node.parent).type);
}
break;
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter: {
// initializer of variable/parameter declaration go to previous node
const { initializer, type } = <VariableDeclaration | ParameterDeclaration>node.parent;
if (initializer === node || type === node || isAssignmentOperator(node.kind)) {
return spanInPreviousNode(node);
}
break;
}
}
if (node.parent.kind === SyntaxKind.BinaryExpression) {
const binaryExpression = <BinaryExpression>node.parent;
if (isArrayLiteralOrObjectLiteralDestructuringPattern(binaryExpression.left) &&
(binaryExpression.right === node ||
binaryExpression.operatorToken === node)) {
// If initializer of destructuring assignment move to previous token
return spanInPreviousNode(node);
case SyntaxKind.BinaryExpression: {
const { left } = <BinaryExpression>node.parent;
if (isArrayLiteralOrObjectLiteralDestructuringPattern(left) && node !== left) {
// If initializer of destructuring assignment move to previous token
return spanInPreviousNode(node);
}
break;
}
default:
// return type of function go to previous token
if (isFunctionLike(node.parent) && node.parent.type === node) {
return spanInPreviousNode(node);
}
}
// Default go to parent to set the breakpoint
@@ -370,9 +369,8 @@ namespace ts.BreakpointResolver {
}
}
function textSpanFromVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan {
if (variableDeclaration.parent.kind === SyntaxKind.VariableDeclarationList &&
variableDeclaration.parent.declarations[0] === variableDeclaration) {
function textSpanFromVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan {
if (isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] === variableDeclaration) {
// First declaration - include let keyword
return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration);
}
@@ -382,7 +380,7 @@ namespace ts.BreakpointResolver {
}
}
function spanInVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan {
function spanInVariableDeclaration(variableDeclaration: VariableDeclaration | PropertyDeclaration | PropertySignature): TextSpan {
// If declaration of for in statement, just set the span in parent
if (variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) {
return spanInNode(variableDeclaration.parent.parent);
@@ -401,7 +399,7 @@ namespace ts.BreakpointResolver {
return textSpanFromVariableDeclaration(variableDeclaration);
}
if (variableDeclaration.parent.kind === SyntaxKind.VariableDeclarationList &&
if (isVariableDeclarationList(variableDeclaration.parent) &&
variableDeclaration.parent.declarations[0] !== variableDeclaration) {
// If we cannot set breakpoint on this declaration, set it on previous one
// Because the variable declaration may be binding pattern and
+3 -3
View File
@@ -178,7 +178,7 @@ namespace ts {
/// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where
/// we have a series of divide operator. this list allows us to be more accurate by ruling out
/// locations where a regexp cannot exist.
const noRegexTable: true[] = ts.arrayToNumericMap<SyntaxKind, true>([
const noRegexTable: true[] = arrayToNumericMap<SyntaxKind, true>([
SyntaxKind.Identifier,
SyntaxKind.StringLiteral,
SyntaxKind.NumericLiteral,
@@ -224,7 +224,7 @@ namespace ts {
case SyntaxKind.NoSubstitutionTemplateLiteral:
return EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate;
default:
throw Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token);
return Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token);
}
}
return lastOnTemplateStack === SyntaxKind.TemplateHead ? EndOfLineState.InTemplateSubstitutionPosition : undefined;
@@ -343,7 +343,7 @@ namespace ts {
case EndOfLineState.None:
return { prefix: "" };
default:
throw Debug.assertNever(lexState);
return Debug.assertNever(lexState);
}
}
@@ -1,59 +1,28 @@
/* @internal */
namespace ts.codefix {
const fixId = "convertFunctionToEs6Class";
const errorCodes = [Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration.code];
registerCodeFix({
errorCodes,
getCodeActions(context: CodeFixContext) {
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, context.span.start, context.program.getTypeChecker()));
return [{ description: getLocaleSpecificMessage(Diagnostics.Convert_function_to_an_ES2015_class), changes, fixId }];
},
fixIds: [fixId],
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => doChange(changes, err.file!, err.start, context.program.getTypeChecker())),
});
namespace ts.refactor.convertFunctionToES6Class {
const refactorName = "Convert to ES2015 class";
const actionName = "convert";
const description = Diagnostics.Convert_function_to_an_ES2015_class.message;
registerRefactor(refactorName, { getEditsForAction, getAvailableActions });
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
if (!isInJavaScriptFile(context.file)) {
return undefined;
}
let symbol = getConstructorSymbol(context);
if (!symbol) {
return undefined;
}
if (isDeclarationOfFunctionOrClassExpression(symbol)) {
symbol = (symbol.valueDeclaration as VariableDeclaration).initializer.symbol;
}
if ((symbol.flags & SymbolFlags.Function) && symbol.members && (symbol.members.size > 0)) {
return [
{
name: refactorName,
description,
actions: [
{
description,
name: actionName
}
]
}
];
}
}
function getEditsForAction(context: RefactorContext, action: string): RefactorEditInfo | undefined {
// Somehow wrong action got invoked?
if (actionName !== action) {
return undefined;
}
const { file: sourceFile } = context;
const ctorSymbol = getConstructorSymbol(context);
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, checker: TypeChecker): void {
const deletedNodes: Node[] = [];
const deletes: (() => any)[] = [];
const deletes: (() => void)[] = [];
const ctorSymbol = checker.getSymbolAtLocation(getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false));
if (!(ctorSymbol.flags & (SymbolFlags.Function | SymbolFlags.Variable))) {
if (!ctorSymbol || !(ctorSymbol.flags & (SymbolFlags.Function | SymbolFlags.Variable))) {
// Bad input
return undefined;
}
const ctorDeclaration = ctorSymbol.valueDeclaration;
const changeTracker = textChanges.ChangeTracker.fromContext(context);
let precedingNode: Node;
let newClassDeclaration: ClassDeclaration;
@@ -81,17 +50,11 @@ namespace ts.refactor.convertFunctionToES6Class {
}
// Because the preceding node could be touched, we need to insert nodes before delete nodes.
changeTracker.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration);
changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration);
for (const deleteCallback of deletes) {
deleteCallback();
}
return {
edits: changeTracker.getChanges(),
renameFilename: undefined,
renameLocation: undefined,
};
function deleteNode(node: Node, inList = false) {
if (deletedNodes.some(n => isNodeDescendantOf(node, n))) {
// Parent node has already been deleted; do nothing
@@ -99,10 +62,10 @@ namespace ts.refactor.convertFunctionToES6Class {
}
deletedNodes.push(node);
if (inList) {
deletes.push(() => changeTracker.deleteNodeInList(sourceFile, node));
deletes.push(() => changes.deleteNodeInList(sourceFile, node));
}
else {
deletes.push(() => changeTracker.deleteNode(sourceFile, node));
deletes.push(() => changes.deleteNode(sourceFile, node));
}
}
@@ -165,7 +128,7 @@ namespace ts.refactor.convertFunctionToES6Class {
const fullModifiers = concatenate(modifiers, getModifierKindFromSource(functionExpression, SyntaxKind.AsyncKeyword));
const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined,
/*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body);
copyComments(assignmentBinaryExpression, method);
copyComments(assignmentBinaryExpression, method, sourceFile);
return method;
}
@@ -185,7 +148,7 @@ namespace ts.refactor.convertFunctionToES6Class {
const fullModifiers = concatenate(modifiers, getModifierKindFromSource(arrowFunction, SyntaxKind.AsyncKeyword));
const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined,
/*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock);
copyComments(assignmentBinaryExpression, method);
copyComments(assignmentBinaryExpression, method, sourceFile);
return method;
}
@@ -196,29 +159,13 @@ namespace ts.refactor.convertFunctionToES6Class {
}
const prop = createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined,
/*type*/ undefined, assignmentBinaryExpression.right);
copyComments(assignmentBinaryExpression.parent, prop);
copyComments(assignmentBinaryExpression.parent, prop, sourceFile);
return prop;
}
}
}
}
function copyComments(sourceNode: Node, targetNode: Node) {
forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, (pos, end, kind, htnl) => {
if (kind === SyntaxKind.MultiLineCommentTrivia) {
// Remove leading /*
pos += 2;
// Remove trailing */
end -= 2;
}
else {
// Remove leading //
pos += 2;
}
addSyntheticLeadingComment(targetNode, kind, sourceFile.text.slice(pos, end), htnl);
});
}
function createClassFromVariableDeclaration(node: VariableDeclaration): ClassDeclaration {
const initializer = node.initializer as FunctionExpression;
if (!initializer || initializer.kind !== SyntaxKind.FunctionExpression) {
@@ -253,15 +200,25 @@ namespace ts.refactor.convertFunctionToES6Class {
// Don't call copyComments here because we'll already leave them in place
return cls;
}
function getModifierKindFromSource(source: Node, kind: SyntaxKind) {
return filter(source.modifiers, modifier => modifier.kind === kind);
}
}
function getConstructorSymbol({ startPosition, file, program }: RefactorContext): Symbol {
const checker = program.getTypeChecker();
const token = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false);
return checker.getSymbolAtLocation(token);
function copyComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile) {
forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, (pos, end, kind, htnl) => {
if (kind === SyntaxKind.MultiLineCommentTrivia) {
// Remove leading /*
pos += 2;
// Remove trailing */
end -= 2;
}
else {
// Remove leading //
pos += 2;
}
addSyntheticLeadingComment(targetNode, kind, sourceFile.text.slice(pos, end), htnl);
});
}
function getModifierKindFromSource(source: Node, kind: SyntaxKind): ReadonlyArray<Modifier> {
return filter(source.modifiers, modifier => modifier.kind === kind);
}
}
@@ -1,87 +1,24 @@
/* @internal */
namespace ts.refactor {
const actionName = "Convert to ES6 module";
const description = getLocaleSpecificMessage(Diagnostics.Convert_to_ES6_module);
registerRefactor(actionName, { getEditsForAction, getAvailableActions });
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
const { file, startPosition } = context;
if (!isSourceFileJavaScript(file) || !file.commonJsModuleIndicator) {
return undefined;
}
const node = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false);
return !isAtTriggerLocation(file, node) ? undefined : [
{
name: actionName,
description,
actions: [
{
description,
name: actionName,
},
],
},
];
}
function isAtTriggerLocation(sourceFile: SourceFile, node: Node, onSecondTry = false): boolean {
switch (node.kind) {
case SyntaxKind.CallExpression:
return isAtTopLevelRequire(node as CallExpression);
case SyntaxKind.PropertyAccessExpression:
return isExportsOrModuleExportsOrAlias(sourceFile, node as PropertyAccessExpression)
|| isExportsOrModuleExportsOrAlias(sourceFile, (node as PropertyAccessExpression).expression);
case SyntaxKind.VariableDeclarationList:
return isVariableDeclarationTriggerLocation(firstOrUndefined((node as VariableDeclarationList).declarations));
case SyntaxKind.VariableDeclaration:
return isVariableDeclarationTriggerLocation(node as VariableDeclaration);
default:
return isExpression(node) && isExportsOrModuleExportsOrAlias(sourceFile, node)
|| !onSecondTry && isAtTriggerLocation(sourceFile, node.parent, /*onSecondTry*/ true);
}
function isVariableDeclarationTriggerLocation(decl: VariableDeclaration | undefined) {
return !!decl && !!decl.initializer && isExportsOrModuleExportsOrAlias(sourceFile, decl.initializer);
}
}
function isAtTopLevelRequire(call: CallExpression): boolean {
if (!isRequireCall(call, /*checkArgumentIsStringLiteral*/ true)) {
return false;
}
const { parent: propAccess } = call;
const varDecl = isPropertyAccessExpression(propAccess) ? propAccess.parent : propAccess;
if (isExpressionStatement(varDecl) && isSourceFile(varDecl.parent)) { // `require("x");` as a statement
return true;
}
if (!isVariableDeclaration(varDecl)) {
return false;
}
const { parent: varDeclList } = varDecl;
if (varDeclList.kind !== SyntaxKind.VariableDeclarationList) {
return false;
}
const { parent: varStatement } = varDeclList;
return varStatement.kind === SyntaxKind.VariableStatement && varStatement.parent.kind === SyntaxKind.SourceFile;
}
function getEditsForAction(context: RefactorContext, _actionName: string): RefactorEditInfo | undefined {
Debug.assertEqual(actionName, _actionName);
const { file, program } = context;
Debug.assert(isSourceFileJavaScript(file));
const edits = textChanges.ChangeTracker.with(context, changes => {
const moduleExportsChangedToDefault = convertFileToEs6Module(file, program.getTypeChecker(), changes, program.getCompilerOptions().target);
if (moduleExportsChangedToDefault) {
for (const importingFile of program.getSourceFiles()) {
fixImportOfModuleExports(importingFile, file, changes);
namespace ts.codefix {
registerCodeFix({
errorCodes: [Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES6_module.code],
getCodeActions(context) {
const description = getLocaleSpecificMessage(Diagnostics.Convert_to_ES6_module);
const { sourceFile, program } = context;
const changes = textChanges.ChangeTracker.with(context, changes => {
const moduleExportsChangedToDefault = convertFileToEs6Module(sourceFile, program.getTypeChecker(), changes, program.getCompilerOptions().target);
if (moduleExportsChangedToDefault) {
for (const importingFile of program.getSourceFiles()) {
fixImportOfModuleExports(importingFile, sourceFile, changes);
}
}
}
});
return { edits, renameFilename: undefined, renameLocation: undefined };
}
});
// No support for fix-all since this applies to the whole file at once anyway.
return [{ description, changes, fixId: undefined }];
},
});
function fixImportOfModuleExports(importingFile: ts.SourceFile, exportingFile: ts.SourceFile, changes: textChanges.ChangeTracker) {
function fixImportOfModuleExports(importingFile: SourceFile, exportingFile: SourceFile, changes: textChanges.ChangeTracker) {
for (const moduleSpecifier of importingFile.imports) {
const imported = getResolvedModule(importingFile, moduleSpecifier.text);
if (!imported || imported.resolvedFileName !== exportingFile.fileName) {
@@ -428,7 +365,7 @@ namespace ts.refactor {
import x from "x";
const [a, b, c] = x;
*/
const tmp = makeUniqueName(codefix.moduleSpecifierToValidIdentifier(moduleSpecifier, target), identifiers);
const tmp = makeUniqueName(moduleSpecifierToValidIdentifier(moduleSpecifier, target), identifiers);
return [
makeImport(createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier),
makeConst(/*modifiers*/ undefined, getSynthesizedDeepClone(name), createIdentifier(tmp)),
@@ -31,7 +31,7 @@ namespace ts.codefix {
return host.isKnownTypesPackageName(packageName) ? getTypesPackageName(packageName) : undefined;
}
export function tryGetCodeActionForInstallPackageTypes(host: LanguageServiceHost, fileName: string, moduleName: string): CodeAction | undefined {
function tryGetCodeActionForInstallPackageTypes(host: LanguageServiceHost, fileName: string, moduleName: string): CodeAction | undefined {
const packageName = getTypesPackageNameToInstall(host, moduleName);
return packageName === undefined ? undefined : {
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Install_0), [packageName]),
@@ -42,7 +42,7 @@ namespace ts.codefix {
// (Trailing because leading might be indentation, which is more sensitive.)
const text = sourceFile.text;
let end = implementsToken.end;
while (end < text.length && ts.isWhiteSpaceSingleLine(text.charCodeAt(end))) {
while (end < text.length && isWhiteSpaceSingleLine(text.charCodeAt(end))) {
end++;
}
+2
View File
@@ -1,4 +1,6 @@
/// <reference path="addMissingInvocationForDecorator.ts" />
/// <reference path="convertFunctionToEs6Class.ts" />
/// <reference path="convertToEs6Module.ts" />
/// <reference path="correctQualifiedNameToIndexedAccessType.ts" />
/// <reference path="fixClassIncorrectlyImplementsInterface.ts" />
/// <reference path="fixAddMissingMember.ts" />
+7 -7
View File
@@ -88,11 +88,11 @@ namespace ts.codefix {
sourceFile: SourceFile,
symbolName: string,
host: LanguageServiceHost,
program: ts.Program,
checker: ts.TypeChecker,
compilerOptions: ts.CompilerOptions,
allSourceFiles: ReadonlyArray<ts.SourceFile>,
formatContext: ts.formatting.FormatContext,
program: Program,
checker: TypeChecker,
compilerOptions: CompilerOptions,
allSourceFiles: ReadonlyArray<SourceFile>,
formatContext: formatting.FormatContext,
getCanonicalFileName: GetCanonicalFileName,
symbolToken: Node | undefined,
): { readonly moduleSpecifier: string, readonly codeAction: CodeAction } {
@@ -663,7 +663,7 @@ namespace ts.codefix {
const parent = token.parent;
const isNodeOpeningLikeElement = isJsxOpeningLikeElement(parent);
if ((isJsxOpeningLikeElement && (<JsxOpeningLikeElement>parent).tagName === token) || parent.kind === SyntaxKind.JsxOpeningFragment) {
umdSymbol = checker.resolveName(checker.getJsxNamespace(),
umdSymbol = checker.resolveName(checker.getJsxNamespace(parent),
isNodeOpeningLikeElement ? (<JsxOpeningLikeElement>parent).tagName : parent, SymbolFlags.Value, /*excludeGlobals*/ false);
}
}
@@ -699,7 +699,7 @@ namespace ts.codefix {
// Fall back to the `import * as ns` style import.
return ImportKind.Namespace;
default:
throw Debug.assertNever(moduleKind);
return Debug.assertNever(moduleKind);
}
}
+4 -4
View File
@@ -109,7 +109,7 @@ namespace ts.codefix {
return isSetAccessor(containingFunction) ? getCodeActionForSetAccessor(containingFunction, program, cancellationToken) : undefined;
default:
throw Debug.fail(String(errorCode));
return Debug.fail(String(errorCode));
}
}
@@ -310,13 +310,13 @@ namespace ts.codefix {
const callContexts = isConstructor ? usageContext.constructContexts : usageContext.callContexts;
return callContexts && declaration.parameters.map((parameter, parameterIndex) => {
const types: Type[] = [];
const isRestParameter = ts.isRestParameter(parameter);
const isRest = isRestParameter(parameter);
for (const callContext of callContexts) {
if (callContext.argumentTypes.length <= parameterIndex) {
continue;
}
if (isRestParameter) {
if (isRest) {
for (let i = parameterIndex; i < callContext.argumentTypes.length; i++) {
types.push(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[i]));
}
@@ -329,7 +329,7 @@ namespace ts.codefix {
return undefined;
}
const type = checker.getWidenedType(checker.getUnionType(types, UnionReduction.Subtype));
return isRestParameter ? checker.createArrayType(type) : type;
return isRest ? checker.createArrayType(type) : type;
});
}
+20 -20
View File
@@ -69,7 +69,7 @@ namespace ts.Completions {
case CompletionDataKind.JsDocParameterName:
return jsdocCompletionInfo(JsDoc.getJSDocParameterNameCompletions(completionData.tag));
default:
throw Debug.assertNever(completionData);
return Debug.assertNever(completionData);
}
}
@@ -673,11 +673,11 @@ namespace ts.Completions {
return getContextualTypeFromParent(currentToken as Identifier, checker);
case SyntaxKind.EqualsToken:
switch (parent.kind) {
case ts.SyntaxKind.VariableDeclaration:
case SyntaxKind.VariableDeclaration:
return checker.getContextualType((parent as VariableDeclaration).initializer);
case ts.SyntaxKind.BinaryExpression:
case SyntaxKind.BinaryExpression:
return checker.getTypeAtLocation((parent as BinaryExpression).left);
case ts.SyntaxKind.JsxAttribute:
case SyntaxKind.JsxAttribute:
return checker.getContextualTypeForJsxAttribute(parent as JsxAttribute);
default:
return undefined;
@@ -700,25 +700,25 @@ namespace ts.Completions {
}
}
function getContextualTypeFromParent(node: ts.Expression, checker: ts.TypeChecker): Type | undefined {
function getContextualTypeFromParent(node: Expression, checker: TypeChecker): Type | undefined {
const { parent } = node;
switch (parent.kind) {
case ts.SyntaxKind.NewExpression:
return checker.getContextualType(parent as ts.NewExpression);
case ts.SyntaxKind.BinaryExpression: {
const { left, operatorToken, right } = parent as ts.BinaryExpression;
case SyntaxKind.NewExpression:
return checker.getContextualType(parent as NewExpression);
case SyntaxKind.BinaryExpression: {
const { left, operatorToken, right } = parent as BinaryExpression;
return isEqualityOperatorKind(operatorToken.kind)
? checker.getTypeAtLocation(node === right ? left : right)
: checker.getContextualType(node);
}
case ts.SyntaxKind.CaseClause:
return (parent as ts.CaseClause).expression === node ? getSwitchedType(parent as ts.CaseClause, checker) : undefined;
case SyntaxKind.CaseClause:
return (parent as CaseClause).expression === node ? getSwitchedType(parent as CaseClause, checker) : undefined;
default:
return checker.getContextualType(node);
}
}
function getSwitchedType(caseClause: ts.CaseClause, checker: ts.TypeChecker): ts.Type {
function getSwitchedType(caseClause: CaseClause, checker: TypeChecker): Type {
return checker.getTypeAtLocation(caseClause.parent.parent.expression);
}
@@ -943,7 +943,7 @@ namespace ts.Completions {
getTypeScriptMemberSymbols();
}
else if (isRightOfOpenTag) {
const tagSymbols = Debug.assertEachDefined(typeChecker.getJsxIntrinsicTagNames(), "getJsxIntrinsicTagNames() should all be defined");
const tagSymbols = Debug.assertEachDefined(typeChecker.getJsxIntrinsicTagNamesAt(location), "getJsxIntrinsicTagNames() should all be defined");
if (tryGetGlobalSymbols()) {
symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & (SymbolFlags.Value | SymbolFlags.Alias))));
}
@@ -1453,7 +1453,7 @@ namespace ts.Completions {
isNewIdentifierLocation = false;
const rootDeclaration = getRootDeclaration(objectLikeContainer.parent);
if (!isVariableLike(rootDeclaration)) throw Debug.fail("Root declaration is not variable-like.");
if (!isVariableLike(rootDeclaration)) return Debug.fail("Root declaration is not variable-like.");
// We don't want to complete using the type acquired by the shape
// of the binding pattern; we are only interested in types acquired
@@ -2140,7 +2140,7 @@ namespace ts.Completions {
// A cache of completion entries for keywords, these do not change between sessions
const _keywordCompletions: ReadonlyArray<CompletionEntry>[] = [];
const allKeywordsCompletions: () => ReadonlyArray<CompletionEntry> = ts.memoize(() => {
const allKeywordsCompletions: () => ReadonlyArray<CompletionEntry> = memoize(() => {
const res: CompletionEntry[] = [];
for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) {
res.push({
@@ -2224,12 +2224,12 @@ namespace ts.Completions {
return true;
}
function isEqualityOperatorKind(kind: ts.SyntaxKind): kind is EqualityOperator {
function isEqualityOperatorKind(kind: SyntaxKind): kind is EqualityOperator {
switch (kind) {
case ts.SyntaxKind.EqualsEqualsEqualsToken:
case ts.SyntaxKind.EqualsEqualsToken:
case ts.SyntaxKind.ExclamationEqualsEqualsToken:
case ts.SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
return true;
default:
return false;
+1 -5
View File
@@ -30,11 +30,7 @@ namespace ts.DocumentHighlights {
function getSyntacticDocumentHighlights(node: Node, sourceFile: SourceFile): DocumentHighlights[] {
const highlightSpans = getHighlightSpans(node, sourceFile);
if (!highlightSpans || highlightSpans.length === 0) {
return undefined;
}
return [{ fileName: sourceFile.fileName, highlightSpans }];
return highlightSpans && [{ fileName: sourceFile.fileName, highlightSpans }];
}
function getHighlightSpans(node: Node, sourceFile: SourceFile): HighlightSpan[] | undefined {
+68 -63
View File
@@ -8,11 +8,11 @@ namespace ts.FindAllReferences {
}
export type Definition =
| { type: "symbol"; symbol: Symbol; node: Node }
| { type: "symbol"; symbol: Symbol }
| { type: "label"; node: Identifier }
| { type: "keyword"; node: ts.Node }
| { type: "this"; node: ts.Node }
| { type: "string"; node: ts.StringLiteral };
| { type: "keyword"; node: Node }
| { type: "this"; node: Node }
| { type: "string"; node: StringLiteral };
export type Entry = NodeEntry | SpanEntry;
export interface NodeEntry {
@@ -25,7 +25,7 @@ namespace ts.FindAllReferences {
fileName: string;
textSpan: TextSpan;
}
export function nodeEntry(node: ts.Node, isInString?: true): NodeEntry {
export function nodeEntry(node: Node, isInString?: true): NodeEntry {
return { type: "node", node, isInString };
}
@@ -42,11 +42,12 @@ namespace ts.FindAllReferences {
}
export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined {
const referencedSymbols = findAllReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position);
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
const referencedSymbols = Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, /*options*/ {});
const checker = program.getTypeChecker();
return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined<SymbolAndEntries, ReferencedSymbol>(referencedSymbols, ({ definition, references }) =>
// Only include referenced symbols that have a valid definition.
definition && { definition: definitionToReferencedSymbolDefinitionInfo(definition, checker), references: references.map(toReferenceEntry) });
definition && { definition: definitionToReferencedSymbolDefinitionInfo(definition, checker, node), references: references.map(toReferenceEntry) });
}
export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ImplementationLocation[] {
@@ -83,31 +84,26 @@ namespace ts.FindAllReferences {
}
export function findReferencedEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number, options?: Options): ReferenceEntry[] | undefined {
const x = flattenEntries(findAllReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position, options));
return map(x, toReferenceEntry);
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
return map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), toReferenceEntry);
}
export function getReferenceEntriesForNode(position: number, node: Node, program: Program, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken, options: Options = {}): Entry[] | undefined {
return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options));
}
function findAllReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number, options?: Options): SymbolAndEntries[] | undefined {
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
return Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options);
}
function flattenEntries(referenceSymbols: SymbolAndEntries[]): Entry[] {
return referenceSymbols && flatMap(referenceSymbols, r => r.references);
}
function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: TypeChecker): ReferencedSymbolDefinitionInfo | undefined {
function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: TypeChecker, originalNode: Node): ReferencedSymbolDefinitionInfo | undefined {
const info = (() => {
switch (def.type) {
case "symbol": {
const { symbol, node } = def;
const { displayParts, kind } = getDefinitionKindAndDisplayParts(symbol, node, checker);
const { symbol } = def;
const { displayParts, kind } = getDefinitionKindAndDisplayParts(symbol, checker, originalNode);
const name = displayParts.map(p => p.text).join("");
return { node, name, kind, displayParts };
return { node: symbol.declarations ? getNameOfDeclaration(first(symbol.declarations)) || first(symbol.declarations) : originalNode, name, kind, displayParts };
}
case "label": {
const { node } = def;
@@ -129,13 +125,11 @@ namespace ts.FindAllReferences {
const { node } = def;
return { node, name: node.text, kind: ScriptElementKind.variableElement, displayParts: [displayPart(getTextOfNode(node), SymbolDisplayPartKind.stringLiteral)] };
}
default:
return Debug.assertNever(def);
}
})();
if (!info) {
return undefined;
}
const { node, name, kind, displayParts } = info;
const sourceFile = node.getSourceFile();
return {
@@ -149,9 +143,11 @@ namespace ts.FindAllReferences {
};
}
function getDefinitionKindAndDisplayParts(symbol: Symbol, node: Node, checker: TypeChecker): { displayParts: SymbolDisplayPart[], kind: ScriptElementKind } {
function getDefinitionKindAndDisplayParts(symbol: Symbol, checker: TypeChecker, node: Node): { displayParts: SymbolDisplayPart[], kind: ScriptElementKind } {
const meaning = Core.getIntersectingMeaningFromDeclarations(node, symbol);
const enclosingDeclaration = firstOrUndefined(symbol.declarations) || node;
const { displayParts, symbolKind } =
SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, node.getSourceFile(), getContainerNode(node), node);
SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, enclosingDeclaration.getSourceFile(), enclosingDeclaration, enclosingDeclaration, meaning);
return { displayParts, kind: symbolKind };
}
@@ -172,7 +168,7 @@ namespace ts.FindAllReferences {
};
}
function toImplementationLocation(entry: Entry, checker: ts.TypeChecker): ImplementationLocation {
function toImplementationLocation(entry: Entry, checker: TypeChecker): ImplementationLocation {
if (entry.type === "node") {
const { node } = entry;
return { textSpan: getTextSpan(node), fileName: node.getSourceFile().fileName, ...implementationKindDisplayParts(node, checker) };
@@ -183,10 +179,10 @@ namespace ts.FindAllReferences {
}
}
function implementationKindDisplayParts(node: ts.Node, checker: ts.TypeChecker): { kind: ScriptElementKind, displayParts: SymbolDisplayPart[] } {
function implementationKindDisplayParts(node: Node, checker: TypeChecker): { kind: ScriptElementKind, displayParts: SymbolDisplayPart[] } {
const symbol = checker.getSymbolAtLocation(isDeclaration(node) && node.name ? node.name : node);
if (symbol) {
return getDefinitionKindAndDisplayParts(symbol, node, checker);
return getDefinitionKindAndDisplayParts(symbol, checker, node);
}
else if (node.kind === SyntaxKind.ObjectLiteralExpression) {
return {
@@ -205,7 +201,7 @@ namespace ts.FindAllReferences {
}
}
export function toHighlightSpan(entry: FindAllReferences.Entry): { fileName: string, span: HighlightSpan } {
export function toHighlightSpan(entry: Entry): { fileName: string, span: HighlightSpan } {
if (entry.type === "span") {
const { fileName, textSpan } = entry;
return { fileName, span: { textSpan, kind: HighlightSpanKind.reference } };
@@ -271,7 +267,7 @@ namespace ts.FindAllReferences.Core {
return getReferencedSymbolsForSymbol(symbol, node, sourceFiles, checker, cancellationToken, options);
}
function isModuleReferenceLocation(node: ts.Node): boolean {
function isModuleReferenceLocation(node: Node): boolean {
if (!isStringLiteralLike(node)) {
return false;
}
@@ -306,21 +302,18 @@ namespace ts.FindAllReferences.Core {
for (const decl of symbol.declarations) {
switch (decl.kind) {
case ts.SyntaxKind.SourceFile:
case SyntaxKind.SourceFile:
// Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.)
break;
case ts.SyntaxKind.ModuleDeclaration:
references.push({ type: "node", node: (decl as ts.ModuleDeclaration).name });
case SyntaxKind.ModuleDeclaration:
references.push({ type: "node", node: (decl as ModuleDeclaration).name });
break;
default:
Debug.fail("Expected a module symbol to be declared by a SourceFile or ModuleDeclaration.");
}
}
return [{
definition: { type: "symbol", symbol, node: symbol.valueDeclaration },
references
}];
return [{ definition: { type: "symbol", symbol }, references }];
}
/** getReferencedSymbols for special node kinds. */
@@ -357,13 +350,13 @@ namespace ts.FindAllReferences.Core {
symbol = skipPastExportOrImportSpecifierOrUnion(symbol, node, checker) || symbol;
// Compute the meaning from the location and the symbol it references
const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), symbol.declarations);
const searchMeaning = getIntersectingMeaningFromDeclarations(node, symbol);
const result: SymbolAndEntries[] = [];
const state = new State(sourceFiles, getSpecialSearchKind(node), checker, cancellationToken, searchMeaning, options, result);
if (node.kind === SyntaxKind.DefaultKeyword) {
addReference(node, symbol, node, state);
addReference(node, symbol, state);
searchForImportsOfExport(node, symbol, { exportingModuleSymbol: Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: ExportKind.Default }, state);
}
else {
@@ -434,7 +427,6 @@ namespace ts.FindAllReferences.Core {
/** If coming from an export, we will not recursively search for the imported symbol (since that's where we came from). */
readonly comingFrom?: ImportExport;
readonly location: Node;
readonly symbol: Symbol;
readonly text: string;
readonly escapedText: __String;
@@ -484,6 +476,8 @@ namespace ts.FindAllReferences.Core {
*/
readonly markSeenReExportRHS = nodeSeenTracker();
private readonly includedSourceFiles: Map<true>;
constructor(
readonly sourceFiles: ReadonlyArray<SourceFile>,
/** True if we're searching for constructor references. */
@@ -492,7 +486,13 @@ namespace ts.FindAllReferences.Core {
readonly cancellationToken: CancellationToken,
readonly searchMeaning: SemanticMeaning,
readonly options: Options,
private readonly result: Push<SymbolAndEntries>) {}
private readonly result: Push<SymbolAndEntries>) {
this.includedSourceFiles = arrayToSet(sourceFiles, s => s.fileName);
}
includesSourceFile(sourceFile: SourceFile): boolean {
return this.includedSourceFiles.has(sourceFile.fileName);
}
private importTracker: ImportTracker | undefined;
/** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */
@@ -514,7 +514,7 @@ namespace ts.FindAllReferences.Core {
const escapedText = escapeLeadingUnderscores(text);
const parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker);
return {
location, symbol, comingFrom, text, escapedText, parents,
symbol, comingFrom, text, escapedText, parents,
includes: referenceSymbol => allSearchSymbols ? contains(allSearchSymbols, referenceSymbol) : referenceSymbol === symbol,
};
}
@@ -524,12 +524,12 @@ namespace ts.FindAllReferences.Core {
* Callback to add references for a particular searched symbol.
* This initializes a reference group, so only call this if you will add at least one reference.
*/
referenceAdder(searchSymbol: Symbol, searchLocation: Node): (node: Node) => void {
referenceAdder(searchSymbol: Symbol): (node: Node) => void {
const symbolId = getSymbolId(searchSymbol);
let references = this.symbolIdToReferences[symbolId];
if (!references) {
references = this.symbolIdToReferences[symbolId] = [];
this.result.push({ definition: { type: "symbol", symbol: searchSymbol, node: searchLocation }, references });
this.result.push({ definition: { type: "symbol", symbol: searchSymbol }, references });
}
return node => references.push(nodeEntry(node));
}
@@ -559,7 +559,7 @@ namespace ts.FindAllReferences.Core {
// For `import { foo as bar }` just add the reference to `foo`, and don't otherwise search in the file.
if (singleReferences.length) {
const addRef = state.referenceAdder(exportSymbol, exportLocation);
const addRef = state.referenceAdder(exportSymbol);
for (const singleRef of singleReferences) {
addRef(singleRef);
}
@@ -594,7 +594,10 @@ namespace ts.FindAllReferences.Core {
// Go to the symbol we imported from and find references for it.
function searchForImportedSymbol(symbol: Symbol, state: State): void {
for (const declaration of symbol.declarations) {
getReferencesInSourceFile(declaration.getSourceFile(), state.createSearch(declaration, symbol, ImportExport.Import), state);
const exportingFile = declaration.getSourceFile();
if (state.includesSourceFile(exportingFile)) {
getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, ImportExport.Import), state);
}
}
}
@@ -784,7 +787,7 @@ namespace ts.FindAllReferences.Core {
}
}
function getAllReferencesForKeyword(sourceFiles: ReadonlyArray<SourceFile>, keywordKind: ts.SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] {
function getAllReferencesForKeyword(sourceFiles: ReadonlyArray<SourceFile>, keywordKind: SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] {
const references = flatMap(sourceFiles, sourceFile => {
cancellationToken.throwIfCancellationRequested();
return mapDefined(getPossibleSymbolReferencePositions(sourceFile, tokenToString(keywordKind), sourceFile), position => {
@@ -795,7 +798,7 @@ namespace ts.FindAllReferences.Core {
return references.length ? [{ definition: { type: "keyword", node: references[0].node }, references }] : undefined;
}
function getReferencesInSourceFile(sourceFile: ts.SourceFile, search: Search, state: State): void {
function getReferencesInSourceFile(sourceFile: SourceFile, search: Search, state: State): void {
state.cancellationToken.throwIfCancellationRequested();
return getReferencesInContainer(sourceFile, sourceFile, search, state);
}
@@ -805,7 +808,7 @@ namespace ts.FindAllReferences.Core {
* tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
* searchLocation: a node where the search value
*/
function getReferencesInContainer(container: Node, sourceFile: ts.SourceFile, search: Search, state: State): void {
function getReferencesInContainer(container: Node, sourceFile: SourceFile, search: Search, state: State): void {
if (!state.markSearchedSymbol(sourceFile, search.symbol)) {
return;
}
@@ -862,7 +865,7 @@ namespace ts.FindAllReferences.Core {
switch (state.specialSearchKind) {
case SpecialSearchKind.None:
addReference(referenceLocation, relatedSymbol, search.location, state);
addReference(referenceLocation, relatedSymbol, state);
break;
case SpecialSearchKind.Constructor:
addConstructorReferences(referenceLocation, sourceFile, search, state);
@@ -896,7 +899,7 @@ namespace ts.FindAllReferences.Core {
}
if (!state.options.isForRename && state.markSeenReExportRHS(name)) {
addReference(name, referenceSymbol, name, state);
addReference(name, referenceSymbol, state);
}
}
else {
@@ -907,7 +910,7 @@ namespace ts.FindAllReferences.Core {
// For `export { foo as bar }`, rename `foo`, but not `bar`.
if (!(referenceLocation === propertyName && state.options.isForRename)) {
const exportKind = referenceLocation.originalKeywordKind === ts.SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named;
const exportKind = referenceLocation.originalKeywordKind === SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named;
const exportInfo = getExportInfo(referenceSymbol, exportKind, state.checker);
Debug.assert(!!exportInfo);
searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo, state);
@@ -920,7 +923,7 @@ namespace ts.FindAllReferences.Core {
}
function addRef() {
addReference(referenceLocation, localSymbol, search.location, state);
addReference(referenceLocation, localSymbol, state);
}
}
@@ -969,12 +972,12 @@ namespace ts.FindAllReferences.Core {
* position of property accessing, the referenceEntry of such position will be handled in the first case.
*/
if (!(flags & SymbolFlags.Transient) && search.includes(shorthandValueSymbol)) {
addReference(getNameOfDeclaration(valueDeclaration), shorthandValueSymbol, search.location, state);
addReference(getNameOfDeclaration(valueDeclaration), shorthandValueSymbol, state);
}
}
function addReference(referenceLocation: Node, relatedSymbol: Symbol, searchLocation: Node, state: State): void {
const addRef = state.referenceAdder(relatedSymbol, searchLocation);
function addReference(referenceLocation: Node, relatedSymbol: Symbol, state: State): void {
const addRef = state.referenceAdder(relatedSymbol);
if (state.options.implementations) {
addImplementationReferences(referenceLocation, addRef, state);
}
@@ -986,10 +989,10 @@ namespace ts.FindAllReferences.Core {
/** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */
function addConstructorReferences(referenceLocation: Node, sourceFile: SourceFile, search: Search, state: State): void {
if (isNewExpressionTarget(referenceLocation)) {
addReference(referenceLocation, search.symbol, search.location, state);
addReference(referenceLocation, search.symbol, state);
}
const pusher = () => state.referenceAdder(search.symbol, search.location);
const pusher = () => state.referenceAdder(search.symbol);
if (isClassLike(referenceLocation.parent)) {
Debug.assert(referenceLocation.kind === SyntaxKind.DefaultKeyword || referenceLocation.parent.name === referenceLocation);
@@ -1006,11 +1009,11 @@ namespace ts.FindAllReferences.Core {
}
function addClassStaticThisReferences(referenceLocation: Node, search: Search, state: State): void {
addReference(referenceLocation, search.symbol, search.location, state);
if (isClassLike(referenceLocation.parent)) {
addReference(referenceLocation, search.symbol, state);
if (!state.options.isForRename && isClassLike(referenceLocation.parent)) {
Debug.assert(referenceLocation.parent.name === referenceLocation);
// This is the class declaration.
addStaticThisReferences(referenceLocation.parent, state.referenceAdder(search.symbol, search.location));
addStaticThisReferences(referenceLocation.parent, state.referenceAdder(search.symbol));
}
}
@@ -1040,7 +1043,7 @@ namespace ts.FindAllReferences.Core {
*/
function findOwnConstructorReferences(classSymbol: Symbol, sourceFile: SourceFile, addNode: (node: Node) => void): void {
for (const decl of classSymbol.members.get(InternalSymbolName.Constructor).declarations) {
const ctrKeyword = findChildOfKind(decl, ts.SyntaxKind.ConstructorKeyword, sourceFile)!;
const ctrKeyword = findChildOfKind(decl, SyntaxKind.ConstructorKeyword, sourceFile)!;
Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword);
addNode(ctrKeyword);
}
@@ -1300,7 +1303,7 @@ namespace ts.FindAllReferences.Core {
return container && (ModifierFlags.Static & getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol ? nodeEntry(node) : undefined;
});
return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol, node: superKeyword }, references }];
return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol }, references }];
}
function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken): SymbolAndEntries[] {
@@ -1645,7 +1648,9 @@ namespace ts.FindAllReferences.Core {
* module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
* do not intersect in any of the three spaces.
*/
function getIntersectingMeaningFromDeclarations(meaning: SemanticMeaning, declarations: Declaration[]): SemanticMeaning {
export function getIntersectingMeaningFromDeclarations(node: Node, symbol: Symbol): SemanticMeaning {
let meaning = getMeaningFromLocation(node);
const { declarations } = symbol;
if (declarations) {
let lastIterationMeaning: SemanticMeaning;
do {
+2 -2
View File
@@ -6,8 +6,8 @@
/* @internal */
namespace ts.formatting {
export interface FormatContext {
readonly options: ts.FormatCodeSettings;
readonly getRule: ts.formatting.RulesMap;
readonly options: FormatCodeSettings;
readonly getRule: RulesMap;
}
export interface TextRangeWithKind extends TextRange {
+1 -1
View File
@@ -22,7 +22,7 @@ namespace ts.formatting {
private contextNodeBlockIsOnOneLine: boolean;
private nextNodeBlockIsOnOneLine: boolean;
constructor(public readonly sourceFile: SourceFileLike, public formattingRequestKind: FormattingRequestKind, public options: ts.FormatCodeSettings) {
constructor(public readonly sourceFile: SourceFileLike, public formattingRequestKind: FormattingRequestKind, public options: FormatCodeSettings) {
}
public updateContext(currentRange: TextRangeWithKind, currentTokenParent: Node, nextRange: TextRangeWithKind, nextTokenParent: Node, commonParent: Node) {
+1 -1
View File
@@ -2,7 +2,7 @@
/* @internal */
namespace ts.formatting {
export function getFormatContext(options: FormatCodeSettings): formatting.FormatContext {
export function getFormatContext(options: FormatCodeSettings): FormatContext {
return { options, getRule: getRulesMap() };
}
+8 -20
View File
@@ -102,7 +102,7 @@ namespace ts.formatting {
current--;
}
const lineStart = ts.getLineStartPositionForPosition(current, sourceFile);
const lineStart = getLineStartPositionForPosition(current, sourceFile);
return findFirstNonWhitespaceColumn(lineStart, current, sourceFile, options);
}
@@ -565,26 +565,14 @@ namespace ts.formatting {
function isControlFlowEndingStatement(kind: SyntaxKind, parent: TextRangeWithKind): boolean {
switch (kind) {
case SyntaxKind.ReturnStatement:
case SyntaxKind.ThrowStatement:
switch (parent.kind) {
case SyntaxKind.Block:
const grandParent = (parent as Node).parent;
switch (grandParent && grandParent.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
// We may want to write inner functions after this.
return false;
default:
return true;
}
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.SourceFile:
case SyntaxKind.ModuleBlock:
return true;
default:
throw Debug.fail();
case SyntaxKind.ThrowStatement: {
if (parent.kind !== SyntaxKind.Block) {
return true;
}
const grandParent = (parent as Node).parent;
// In a function, we may want to write inner functions after this.
return !(grandParent && grandParent.kind === SyntaxKind.FunctionExpression || grandParent.kind === SyntaxKind.FunctionDeclaration);
}
case SyntaxKind.ContinueStatement:
case SyntaxKind.BreakStatement:
return true;

Some files were not shown because too many files have changed in this diff Show More