diff --git a/package.json b/package.json
index 7b8abfaae4..261cdfa64b 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,8 @@
"browserify": "latest",
"istanbul": "latest",
"mocha-fivemat-progress-reporter": "latest",
- "tslint": "latest",
+ "tslint": "next",
+ "typescript": "next",
"tsd": "latest"
},
"scripts": {
diff --git a/scripts/tslint/booleanTriviaRule.ts b/scripts/tslint/booleanTriviaRule.ts
index be32a870ff..93c312ab87 100644
--- a/scripts/tslint/booleanTriviaRule.ts
+++ b/scripts/tslint/booleanTriviaRule.ts
@@ -1,6 +1,5 @@
-///
-///
-
+import * as Lint from "tslint/lib/lint";
+import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING_FACTORY = (name: string, currently: string) => `Tag boolean argument as '${name}' (currently '${currently}')`;
@@ -19,7 +18,7 @@ class BooleanTriviaWalker extends Lint.RuleWalker {
visitCallExpression(node: ts.CallExpression) {
super.visitCallExpression(node);
- if (node.arguments) {
+ if (node.arguments) {
const targetCallSignature = this.checker.getResolvedSignature(node);
if (!!targetCallSignature) {
const targetParameters = targetCallSignature.getParameters();
@@ -37,7 +36,7 @@ class BooleanTriviaWalker extends Lint.RuleWalker {
let triviaContent: string;
const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0);
if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) {
- triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); //+/-2 to remove /**/
+ triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/
}
if (triviaContent !== param.getName()) {
this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent)));
@@ -45,6 +44,6 @@ class BooleanTriviaWalker extends Lint.RuleWalker {
}
}
}
- }
+ }
}
}
diff --git a/scripts/tslint/nextLineRule.ts b/scripts/tslint/nextLineRule.ts
index 6d803fc7f8..d25652f7bc 100644
--- a/scripts/tslint/nextLineRule.ts
+++ b/scripts/tslint/nextLineRule.ts
@@ -1,5 +1,5 @@
-///
-///
+import * as Lint from "tslint/lib/lint";
+import * as ts from "typescript";
const OPTION_CATCH = "check-catch";
const OPTION_ELSE = "check-else";
diff --git a/scripts/tslint/noNullRule.ts b/scripts/tslint/noNullRule.ts
index 2a2c5bc371..8e9deca996 100644
--- a/scripts/tslint/noNullRule.ts
+++ b/scripts/tslint/noNullRule.ts
@@ -1,5 +1,5 @@
-///
-///
+import * as Lint from "tslint/lib/lint";
+import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
diff --git a/scripts/tslint/preferConstRule.ts b/scripts/tslint/preferConstRule.ts
index 29160a9c63..e4ffa396fb 100644
--- a/scripts/tslint/preferConstRule.ts
+++ b/scripts/tslint/preferConstRule.ts
@@ -1,5 +1,5 @@
-///
-///
+import * as Lint from "tslint/lib/lint";
+import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
@@ -101,13 +101,13 @@ class PreferConstWalker extends Lint.RuleWalker {
this.visitBindingLiteralExpression(node as (ts.ArrayLiteralExpression | ts.ObjectLiteralExpression));
}
}
-
+
private visitBindingLiteralExpression(node: ts.ArrayLiteralExpression | ts.ObjectLiteralExpression) {
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
const pattern = node as ts.ObjectLiteralExpression;
for (const element of pattern.properties) {
if (element.name.kind === ts.SyntaxKind.Identifier) {
- this.markAssignment(element.name as ts.Identifier)
+ this.markAssignment(element.name as ts.Identifier);
}
else if (isBindingPattern(element.name)) {
this.visitBindingPatternIdentifiers(element.name as ts.BindingPattern);
diff --git a/scripts/tslint/typeOperatorSpacingRule.ts b/scripts/tslint/typeOperatorSpacingRule.ts
index 2392549334..4196d02476 100644
--- a/scripts/tslint/typeOperatorSpacingRule.ts
+++ b/scripts/tslint/typeOperatorSpacingRule.ts
@@ -1,5 +1,5 @@
-///
-///
+import * as Lint from "tslint/lib/lint";
+import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts
index 2993ec3aa0..8b88da5b74 100644
--- a/src/compiler/binder.ts
+++ b/src/compiler/binder.ts
@@ -175,9 +175,14 @@ namespace ts {
symbol.members = {};
}
- if (symbolFlags & SymbolFlags.Value && !symbol.valueDeclaration) {
- symbol.valueDeclaration = node;
- }
+ if (symbolFlags & SymbolFlags.Value) {
+ const valueDeclaration = symbol.valueDeclaration;
+ if (!valueDeclaration ||
+ (valueDeclaration.kind !== node.kind && valueDeclaration.kind === SyntaxKind.ModuleDeclaration)) {
+ // other kinds of value declarations take precedence over modules
+ symbol.valueDeclaration = node;
+ }
+ }
}
// Should not be called on a declaration with a computed property name,
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index a215eda64c..378fd85265 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -122,8 +122,8 @@ namespace ts {
const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
- const anySignature = createSignature(undefined, undefined, emptyArray, anyType, undefined, 0, false, false);
- const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, undefined, 0, false, false);
+ const anySignature = createSignature(undefined, undefined, emptyArray, anyType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
+ const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const globals: SymbolTable = {};
@@ -200,6 +200,10 @@ namespace ts {
"symbol": {
type: esSymbolType,
flags: TypeFlags.ESSymbol
+ },
+ "undefined": {
+ type: undefinedType,
+ flags: TypeFlags.ContainsUndefinedOrNull
}
};
@@ -295,7 +299,12 @@ namespace ts {
target.constEnumOnlyModule = false;
}
target.flags |= source.flags;
- if (!target.valueDeclaration && source.valueDeclaration) target.valueDeclaration = source.valueDeclaration;
+ if (source.valueDeclaration &&
+ (!target.valueDeclaration ||
+ (target.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && source.valueDeclaration.kind !== SyntaxKind.ModuleDeclaration))) {
+ // other kinds of value declarations take precedence over modules
+ target.valueDeclaration = source.valueDeclaration;
+ }
forEach(source.declarations, node => {
target.declarations.push(node);
});
@@ -2267,7 +2276,7 @@ namespace ts {
return false;
}
resolutionTargets.push(target);
- resolutionResults.push(true);
+ resolutionResults.push(/*items*/ true);
resolutionPropertyNames.push(propertyName);
return true;
}
@@ -3339,7 +3348,7 @@ namespace ts {
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
if (!hasClassBaseType(classType)) {
- return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, false, false)];
+ return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
}
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
@@ -3820,7 +3829,13 @@ namespace ts {
let minArgumentCount = -1;
for (let i = 0, n = declaration.parameters.length; i < n; i++) {
const param = declaration.parameters[i];
- parameters.push(param.symbol);
+ let paramSymbol = param.symbol;
+ // Include parameter symbol instead of property symbol in the signature
+ if (paramSymbol && !!(paramSymbol.flags & SymbolFlags.Property) && !isBindingPattern(param.name)) {
+ const resolvedSymbol = resolveName(param, paramSymbol.name, SymbolFlags.Value, undefined, undefined);
+ paramSymbol = resolvedSymbol;
+ }
+ parameters.push(paramSymbol);
if (param.type && param.type.kind === SyntaxKind.StringLiteral) {
hasStringLiterals = true;
}
@@ -3964,7 +3979,7 @@ namespace ts {
}
function getSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature {
- return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), true);
+ return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), /*eraseTypeParameters*/ true);
}
function getErasedSignature(signature: Signature): Signature {
@@ -3974,7 +3989,7 @@ namespace ts {
signature.erasedSignatureCache = instantiateSignature(getErasedSignature(signature.target), signature.mapper);
}
else {
- signature.erasedSignatureCache = instantiateSignature(signature, createTypeEraser(signature.typeParameters), true);
+ signature.erasedSignatureCache = instantiateSignature(signature, createTypeEraser(signature.typeParameters), /*eraseTypeParameters*/ true);
}
}
return signature.erasedSignatureCache;
@@ -5090,7 +5105,7 @@ namespace ts {
let result = Ternary.True;
const sourceTypes = source.types;
for (const sourceType of sourceTypes) {
- const related = typeRelatedToSomeType(sourceType, target, false);
+ const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false);
if (!related) {
return Ternary.False;
}
@@ -5488,7 +5503,7 @@ namespace ts {
const saveErrorInfo = errorInfo;
let related = isRelatedTo(s, t, reportErrors);
if (!related) {
- related = isRelatedTo(t, s, false);
+ related = isRelatedTo(t, s, /*reportErrors*/ false);
if (!related) {
if (reportErrors) {
reportError(Diagnostics.Types_of_parameters_0_and_1_are_incompatible,
@@ -5615,7 +5630,7 @@ namespace ts {
let related: Ternary;
if (sourceStringType && sourceNumberType) {
// If we know for sure we're testing both string and numeric index types then only report errors from the second one
- related = isRelatedTo(sourceStringType, targetType, false) || isRelatedTo(sourceNumberType, targetType, reportErrors);
+ related = isRelatedTo(sourceStringType, targetType, /*reportErrors*/ false) || isRelatedTo(sourceNumberType, targetType, reportErrors);
}
else {
related = isRelatedTo(sourceStringType || sourceNumberType, targetType, reportErrors);
@@ -6470,6 +6485,10 @@ namespace ts {
assumeTrue = !assumeTrue;
}
const typeInfo = primitiveTypeInfo[right.text];
+ // Don't narrow `undefined`
+ if (typeInfo && typeInfo.type === undefinedType) {
+ return type;
+ }
// If the type to be narrowed is any and we're checking a primitive with assumeTrue=true, return the primitive
if (!!(type.flags & TypeFlags.Any) && typeInfo && assumeTrue) {
return typeInfo.type;
@@ -11347,11 +11366,17 @@ namespace ts {
const errorNode: Node = (subsequentNode).name || subsequentNode;
// TODO(jfreeman): These are methods, so handle computed name case
if (node.name && (subsequentNode).name && (node.name).text === ((subsequentNode).name).text) {
- // the only situation when this is possible (same kind\same name but different symbol) - mixed static and instance class members
- Debug.assert(node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature);
- Debug.assert((node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static));
- const diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static;
- error(errorNode, diagnostic);
+ const reportError =
+ (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) &&
+ (node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static);
+ // we can get here in two cases
+ // 1. mixed static and instance class members
+ // 2. something with the same name was defined before the set of overloads that prevents them from merging
+ // here we'll report error only for the first case since for second we should already report error in binder
+ if (reportError) {
+ const diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static;
+ error(errorNode, diagnostic);
+ }
return;
}
else if (nodeIsPresent((subsequentNode).body)) {
diff --git a/src/compiler/core.ts b/src/compiler/core.ts
index c866cf41a9..2092a59a54 100644
--- a/src/compiler/core.ts
+++ b/src/compiler/core.ts
@@ -842,7 +842,7 @@ namespace ts {
}
export function fail(message?: string): void {
- Debug.assert(false, message);
+ Debug.assert(/*expression*/ false, message);
}
}
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 323a5680cc..4bddaa221e 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -1292,7 +1292,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function emitCommaList(nodes: Node[]) {
if (nodes) {
- emitList(nodes, 0, nodes.length, /*multiline*/ false, /*trailingComma*/ false);
+ emitList(nodes, 0, nodes.length, /*multiLine*/ false, /*trailingComma*/ false);
}
}
@@ -2191,7 +2191,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
else if (languageVersion >= ScriptTarget.ES6 || !forEach(elements, isSpreadElementExpression)) {
write("[");
- emitLinePreservingList(node, node.elements, elements.hasTrailingComma, /*spacesBetweenBraces:*/ false);
+ emitLinePreservingList(node, node.elements, elements.hasTrailingComma, /*spacesBetweenBraces*/ false);
write("]");
}
else {
@@ -2215,7 +2215,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// then try to preserve the original shape of the object literal.
// Otherwise just try to preserve the formatting.
if (numElements === properties.length) {
- emitLinePreservingList(node, properties, /* allowTrailingComma */ languageVersion >= ScriptTarget.ES5, /* spacesBetweenBraces */ true);
+ emitLinePreservingList(node, properties, /*allowTrailingComma*/ languageVersion >= ScriptTarget.ES5, /*spacesBetweenBraces*/ true);
}
else {
const multiLine = (node.flags & NodeFlags.MultiLine) !== 0;
@@ -2765,7 +2765,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(".bind.apply(");
emit(target);
write(", [void 0].concat(");
- emitListWithSpread(node.arguments, /*needsUniqueCopy*/ false, /*multiline*/ false, /*trailingComma*/ false, /*useConcat*/ false);
+ emitListWithSpread(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*trailingComma*/ false, /*useConcat*/ false);
write(")))");
write("()");
}
@@ -2982,7 +2982,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
synthesizedLHS = createSynthesizedNode(SyntaxKind.ElementAccessExpression, /*startsOnNewLine*/ false);
- const identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefinedTempVariablesInPlaces*/ false, /*shouldEmitCommaBeforeAssignment*/ false);
+ const identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefineTempVariablesInPlace*/ false, /*shouldEmitCommaBeforeAssignment*/ false);
synthesizedLHS.expression = identifier;
if (leftHandSideExpression.argumentExpression.kind !== SyntaxKind.NumericLiteral &&
@@ -3001,7 +3001,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write("(");
synthesizedLHS = createSynthesizedNode(SyntaxKind.PropertyAccessExpression, /*startsOnNewLine*/ false);
- const identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefinedTempVariablesInPlaces*/ false, /*shouldemitCommaBeforeAssignment*/ false);
+ const identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefineTempVariablesInPlace*/ false, /*shouldEmitCommaBeforeAssignment*/ false);
synthesizedLHS.expression = identifier;
(synthesizedLHS).dotToken = leftHandSideExpression.dotToken;
@@ -3181,10 +3181,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function emitDoStatementWorker(node: DoStatement, loop: ConvertedLoop) {
write("do");
if (loop) {
- emitConvertedLoopCall(loop, /* emitAsBlock */ true);
+ emitConvertedLoopCall(loop, /*emitAsBlock*/ true);
}
else {
- emitNormalLoopBody(node, /* emitAsEmbeddedStatement */ true);
+ emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true);
}
if (node.statement.kind === SyntaxKind.Block) {
write(" ");
@@ -3207,10 +3207,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(")");
if (loop) {
- emitConvertedLoopCall(loop, /* emitAsBlock */ true);
+ emitConvertedLoopCall(loop, /*emitAsBlock*/ true);
}
else {
- emitNormalLoopBody(node, /* emitAsEmbeddedStatement */ true);
+ emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true);
}
}
@@ -3532,8 +3532,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(`switch(${loopResultVariable}) {`);
increaseIndent();
- emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalBreaks, /* isBreak */ true, loopResultVariable, outerLoop);
- emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalContinues, /* isBreak */ false, loopResultVariable, outerLoop);
+ emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalBreaks, /*isBreak*/ true, loopResultVariable, outerLoop);
+ emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalContinues, /*isBreak*/ false, loopResultVariable, outerLoop);
decreaseIndent();
writeLine();
@@ -3597,10 +3597,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(")");
if (loop) {
- emitConvertedLoopCall(loop, /* emitAsBlock */ true);
+ emitConvertedLoopCall(loop, /*emitAsBlock*/ true);
}
else {
- emitNormalLoopBody(node, /* emitAsEmbeddedStatement */ true);
+ emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true);
}
}
@@ -3638,10 +3638,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
emitToken(SyntaxKind.CloseParenToken, node.expression.end);
if (loop) {
- emitConvertedLoopCall(loop, /* emitAsBlock */ true);
+ emitConvertedLoopCall(loop, /*emitAsBlock*/ true);
}
else {
- emitNormalLoopBody(node, /* emitAsEmbeddedStatement */ true);
+ emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true);
}
}
@@ -3781,10 +3781,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (loop) {
writeLine();
- emitConvertedLoopCall(loop, /* emitAsBlock */ false);
+ emitConvertedLoopCall(loop, /*emitAsBlock*/ false);
}
else {
- emitNormalLoopBody(node, /* emitAsEmbeddedStatement */ false);
+ emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ false);
}
writeLine();
@@ -3818,11 +3818,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
let labelMarker: string;
if (node.kind === SyntaxKind.BreakStatement) {
labelMarker = `break-${node.label.text}`;
- setLabeledJump(convertedLoopState, /* isBreak */ true, node.label.text, labelMarker);
+ setLabeledJump(convertedLoopState, /*isBreak*/ true, node.label.text, labelMarker);
}
else {
labelMarker = `continue-${node.label.text}`;
- setLabeledJump(convertedLoopState, /* isBreak */ false, node.label.text, labelMarker);
+ setLabeledJump(convertedLoopState, /*isBreak*/ false, node.label.text, labelMarker);
}
write(`return "${labelMarker}";`);
}
@@ -4248,7 +4248,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
let index: Expression;
const nameIsComputed = propName.kind === SyntaxKind.ComputedPropertyName;
if (nameIsComputed) {
- index = ensureIdentifier((propName).expression, /* reuseIdentifierExpression */ false);
+ index = ensureIdentifier((propName).expression, /*reuseIdentifierExpressions*/ false);
}
else {
// We create a synthetic copy of the identifier in order to avoid the rewriting that might
@@ -5003,8 +5003,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
increaseIndent();
writeLine();
emitLeadingComments(node.body);
+ emitStart(body);
write("return ");
emit(body);
+ emitEnd(body);
write(";");
emitTrailingComments(node.body);
@@ -5378,7 +5380,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
emitEnd(baseTypeElement);
}
}
- emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ false));
+ emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ false));
if (ctor) {
let statements: Node[] = (ctor.body).statements;
if (superCall) {
@@ -5500,7 +5502,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
//
// This keeps the expression as an expression, while ensuring that the static parts
// of it have been initialized by the time it is used.
- const staticProperties = getInitializedProperties(node, /*static:*/ true);
+ const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === SyntaxKind.ClassExpression;
let tempVariable: Identifier;
@@ -5562,7 +5564,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
for (var property of staticProperties) {
write(",");
writeLine();
- emitPropertyDeclaration(node, property, /*receiver:*/ tempVariable, /*isExpression:*/ true);
+ emitPropertyDeclaration(node, property, /*receiver*/ tempVariable, /*isExpression*/ true);
}
write(",");
writeLine();
@@ -5651,7 +5653,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
writeLine();
emitConstructor(node, baseTypeNode);
emitMemberFunctionsForES5AndLower(node);
- emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ true));
+ emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ true));
writeLine();
emitDecoratorsOfClass(node);
writeLine();
@@ -8107,11 +8109,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
* Emit comments associated with node that will not be emitted into JS file
*/
function emitCommentsOnNotEmittedNode(node: Node) {
- emitLeadingCommentsWorker(node, /*isEmittedNode:*/ false);
+ emitLeadingCommentsWorker(node, /*isEmittedNode*/ false);
}
function emitLeadingComments(node: Node) {
- return emitLeadingCommentsWorker(node, /*isEmittedNode:*/ true);
+ return emitLeadingCommentsWorker(node, /*isEmittedNode*/ true);
}
function emitLeadingCommentsWorker(node: Node, isEmittedNode: boolean) {
@@ -8140,7 +8142,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
- emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator:*/ true, newLine, writeComment);
+ emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
}
function emitTrailingComments(node: Node) {
diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts
index ac37f60841..9a72593d3b 100644
--- a/src/compiler/parser.ts
+++ b/src/compiler/parser.ts
@@ -722,10 +722,10 @@ namespace ts {
const contextFlagsToClear = context & contextFlags;
if (contextFlagsToClear) {
// clear the requested context flags
- setContextFlag(false, contextFlagsToClear);
+ setContextFlag(/*val*/ false, contextFlagsToClear);
const result = func();
// restore the context flags we just cleared
- setContextFlag(true, contextFlagsToClear);
+ setContextFlag(/*val*/ true, contextFlagsToClear);
return result;
}
@@ -743,10 +743,10 @@ namespace ts {
const contextFlagsToSet = context & ~contextFlags;
if (contextFlagsToSet) {
// set the requested context flags
- setContextFlag(true, contextFlagsToSet);
+ setContextFlag(/*val*/ true, contextFlagsToSet);
const result = func();
// reset the context flags we just set
- setContextFlag(false, contextFlagsToSet);
+ setContextFlag(/*val*/ false, contextFlagsToSet);
return result;
}
@@ -1098,11 +1098,11 @@ namespace ts {
}
function parsePropertyName(): PropertyName {
- return parsePropertyNameWorker(/*allowComputedPropertyNames:*/ true);
+ return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true);
}
function parseSimplePropertyName(): Identifier | LiteralExpression {
- return parsePropertyNameWorker(/*allowComputedPropertyNames:*/ false);
+ return parsePropertyNameWorker(/*allowComputedPropertyNames*/ false);
}
function isSimplePropertyName() {
@@ -1385,7 +1385,7 @@ namespace ts {
function isInSomeParsingContext(): boolean {
for (let kind = 0; kind < ParsingContext.Count; kind++) {
if (parsingContext & (1 << kind)) {
- if (isListElement(kind, /* inErrorRecovery */ true) || isListTerminator(kind)) {
+ if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) {
return true;
}
}
@@ -1402,7 +1402,7 @@ namespace ts {
result.pos = getNodePos();
while (!isListTerminator(kind)) {
- if (isListElement(kind, /* inErrorRecovery */ false)) {
+ if (isListElement(kind, /*inErrorRecovery*/ false)) {
const element = parseListElement(kind, parseElement);
result.push(element);
@@ -1751,7 +1751,7 @@ namespace ts {
let commaStart = -1; // Meaning the previous token was not a comma
while (true) {
- if (isListElement(kind, /* inErrorRecovery */ false)) {
+ if (isListElement(kind, /*inErrorRecovery*/ false)) {
result.push(parseListElement(kind, parseElement));
commaStart = scanner.getTokenPos();
if (parseOptional(SyntaxKind.CommaToken)) {
@@ -1859,7 +1859,7 @@ namespace ts {
// Report that we need an identifier. However, report it right after the dot,
// and not on the next token. This is because the next token might actually
// be an identifier and the error would be quite confusing.
- return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentToken*/ true, Diagnostics.Identifier_expected);
+ return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected);
}
}
@@ -2609,7 +2609,7 @@ namespace ts {
// clear the decorator context when parsing Expression, as it should be unambiguous when parsing a decorator
const saveDecoratorContext = inDecoratorContext();
if (saveDecoratorContext) {
- setDecoratorContext(false);
+ setDecoratorContext(/*val*/ false);
}
let expr = parseAssignmentExpressionOrHigher();
@@ -2619,7 +2619,7 @@ namespace ts {
}
if (saveDecoratorContext) {
- setDecoratorContext(true);
+ setDecoratorContext(/*val*/ true);
}
return expr;
}
@@ -2773,7 +2773,7 @@ namespace ts {
node.parameters.pos = parameter.pos;
node.parameters.end = parameter.end;
- node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, false, Diagnostics._0_expected, "=>");
+ node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, "=>");
node.body = parseArrowFunctionExpressionBody(/*isAsync*/ false);
return finishNode(node);
@@ -3573,7 +3573,7 @@ namespace ts {
parseExpected(SyntaxKind.GreaterThanToken);
}
else {
- parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*advance*/ false);
+ parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false);
scanJsxText();
}
node = createNode(SyntaxKind.JsxSelfClosingElement, fullStart);
@@ -3609,7 +3609,7 @@ namespace ts {
parseExpected(SyntaxKind.CloseBraceToken);
}
else {
- parseExpected(SyntaxKind.CloseBraceToken, /*message*/ undefined, /*advance*/ false);
+ parseExpected(SyntaxKind.CloseBraceToken, /*message*/ undefined, /*shouldAdvance*/ false);
scanJsxText();
}
@@ -3654,7 +3654,7 @@ namespace ts {
parseExpected(SyntaxKind.GreaterThanToken);
}
else {
- parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*advance*/ false);
+ parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false);
scanJsxText();
}
return finishNode(node);
@@ -3973,7 +3973,7 @@ namespace ts {
// function BindingIdentifier[opt](FormalParameters){ FunctionBody }
const saveDecoratorContext = inDecoratorContext();
if (saveDecoratorContext) {
- setDecoratorContext(false);
+ setDecoratorContext(/*val*/ false);
}
const node = createNode(SyntaxKind.FunctionExpression);
@@ -3993,7 +3993,7 @@ namespace ts {
node.body = parseFunctionBlock(/*allowYield*/ isGenerator, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ false);
if (saveDecoratorContext) {
- setDecoratorContext(true);
+ setDecoratorContext(/*val*/ true);
}
return finishNode(node);
@@ -4039,13 +4039,13 @@ namespace ts {
// arrow function. The body of the function is not in [Decorator] context.
const saveDecoratorContext = inDecoratorContext();
if (saveDecoratorContext) {
- setDecoratorContext(false);
+ setDecoratorContext(/*val*/ false);
}
const block = parseBlock(ignoreMissingOpenBrace, diagnosticMessage);
if (saveDecoratorContext) {
- setDecoratorContext(true);
+ setDecoratorContext(/*val*/ true);
}
setYieldContext(savedYieldContext);
@@ -6162,7 +6162,7 @@ namespace ts {
if (sourceFile.statements.length === 0) {
// If we don't have any statements in the current source file, then there's no real
// way to incrementally parse. So just do a full parse instead.
- return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setNodeParents*/ true);
+ return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true);
}
// Make sure we're not trying to incrementally update a source file more than once. Once
@@ -6226,7 +6226,7 @@ namespace ts {
// inconsistent tree. Setting the parents on the new tree should be very fast. We
// will immediately bail out of walking any subtrees when we can see that their parents
// are already correct.
- const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /* setParentNode */ true);
+ const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true);
return result;
}
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index ca0c7d9ada..57207d0564 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -364,13 +364,13 @@ namespace ts {
}
if (!tryReuseStructureFromOldProgram()) {
- forEach(rootNames, name => processRootFile(name, false));
+ forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false));
// Do not process the default library if:
// - The '--noLib' flag is used.
// - A 'no-default-lib' reference comment is encountered in
// processing the root files.
if (!skipDefaultLib) {
- processRootFile(host.getDefaultLibFileName(options), true);
+ processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true);
}
}
@@ -693,7 +693,7 @@ namespace ts {
let imports: LiteralExpression[];
for (const node of file.statements) {
- collect(node, /* allowRelativeModuleNames */ true, /* collectOnlyRequireCalls */ false);
+ collect(node, /*allowRelativeModuleNames*/ true, /*collectOnlyRequireCalls*/ false);
}
file.imports = imports || emptyArray;
@@ -729,7 +729,7 @@ namespace ts {
// TypeScript 1.0 spec (April 2014): 12.1.6
// An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules
// only through top - level external module names. Relative external module names are not permitted.
- collect(node, /* allowRelativeModuleNames */ false, collectOnlyRequireCalls);
+ collect(node, /*allowRelativeModuleNames*/ false, collectOnlyRequireCalls);
});
}
break;
@@ -741,7 +741,7 @@ namespace ts {
(imports || (imports = [])).push((node).arguments[0]);
}
else {
- forEachChild(node, node => collect(node, allowRelativeModuleNames, /* collectOnlyRequireCalls */ true));
+ forEachChild(node, node => collect(node, allowRelativeModuleNames, /*collectOnlyRequireCalls*/ true));
}
}
}
@@ -800,12 +800,12 @@ namespace ts {
}
// Get source file from normalized fileName
- function findSourceFile(fileName: string, normalizedAbsolutePath: Path, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
- if (filesByName.contains(normalizedAbsolutePath)) {
- const file = filesByName.get(normalizedAbsolutePath);
+ function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
+ if (filesByName.contains(path)) {
+ const file = filesByName.get(path);
// try to check if we've already seen this file but with a different casing in path
// NOTE: this only makes sense for case-insensitive file systems
- if (file && options.forceConsistentCasingInFileNames && getNormalizedAbsolutePath(file.fileName, currentDirectory) !== normalizedAbsolutePath) {
+ if (file && options.forceConsistentCasingInFileNames && getNormalizedAbsolutePath(file.fileName, currentDirectory) !== getNormalizedAbsolutePath(fileName, currentDirectory)) {
reportFileNamesDifferOnlyInCasingError(fileName, file.fileName, refFile, refPos, refEnd);
}
@@ -823,18 +823,18 @@ namespace ts {
}
});
- filesByName.set(normalizedAbsolutePath, file);
+ filesByName.set(path, file);
if (file) {
- file.path = normalizedAbsolutePath;
+ file.path = path;
if (host.useCaseSensitiveFileNames()) {
// for case-sensitive file systems check if we've already seen some file with similar filename ignoring case
- const existingFile = filesByNameIgnoreCase.get(normalizedAbsolutePath);
+ const existingFile = filesByNameIgnoreCase.get(path);
if (existingFile) {
reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd);
}
else {
- filesByNameIgnoreCase.set(normalizedAbsolutePath, file);
+ filesByNameIgnoreCase.set(path, file);
}
}
@@ -862,7 +862,7 @@ namespace ts {
function processReferencedFiles(file: SourceFile, basePath: string) {
forEach(file.referencedFiles, ref => {
const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
- processSourceFile(referencedFileName, /* isDefaultLib */ false, file, ref.pos, ref.end);
+ processSourceFile(referencedFileName, /*isDefaultLib*/ false, file, ref.pos, ref.end);
});
}
@@ -880,7 +880,7 @@ namespace ts {
const resolution = resolutions[i];
setResolvedModule(file, moduleNames[i], resolution);
if (resolution && !options.noResolve) {
- const importedFile = findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /* isDefaultLib */ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end);
+ const importedFile = findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /*isDefaultLib*/ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end);
if (importedFile && resolution.isExternalLibraryImport) {
if (!isExternalModule(importedFile)) {
diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts
index 9703ef8517..4289d91060 100644
--- a/src/compiler/scanner.ts
+++ b/src/compiler/scanner.ts
@@ -1634,11 +1634,11 @@ namespace ts {
}
function lookAhead(callback: () => T): T {
- return speculationHelper(callback, /*isLookahead:*/ true);
+ return speculationHelper(callback, /*isLookahead*/ true);
}
function tryScan(callback: () => T): T {
- return speculationHelper(callback, /*isLookahead:*/ false);
+ return speculationHelper(callback, /*isLookahead*/ false);
}
function setText(newText: string, start: number, length: number) {
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 8b0027c137..5f9f82d9a6 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -2179,17 +2179,17 @@ namespace ts {
/* @internal */
export interface CommandLineOptionBase {
name: string;
- type: string | Map; // "string", "number", "boolean", or an object literal mapping named values to actual values
- isFilePath?: boolean; // True if option value is a path or fileName
- shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help'
- description?: DiagnosticMessage; // The message describing what the command line switch does
- paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter
+ type: "string" | "number" | "boolean" | Map; // a value of a primitive type, or an object literal mapping named values to actual values
+ isFilePath?: boolean; // True if option value is a path or fileName
+ shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help'
+ description?: DiagnosticMessage; // The message describing what the command line switch does
+ paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter
experimental?: boolean;
}
/* @internal */
export interface CommandLineOptionOfPrimitiveType extends CommandLineOptionBase {
- type: string; // "string" | "number" | "boolean"
+ type: "string" | "number" | "boolean";
}
/* @internal */
diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts
index 848f229f10..399f8a272d 100644
--- a/src/harness/compilerRunner.ts
+++ b/src/harness/compilerRunner.ts
@@ -49,55 +49,50 @@ class CompilerBaselineRunner extends RunnerBase {
let testCaseContent: { settings: Harness.TestCaseParser.CompilerSettings; testUnitData: Harness.TestCaseParser.TestUnitData[]; };
let units: Harness.TestCaseParser.TestUnitData[];
- let tcSettings: Harness.TestCaseParser.CompilerSettings;
+ let harnessSettings: Harness.TestCaseParser.CompilerSettings;
let lastUnit: Harness.TestCaseParser.TestUnitData;
let rootDir: string;
let result: Harness.Compiler.CompilerResult;
- let program: ts.Program;
let options: ts.CompilerOptions;
// equivalent to the files that will be passed on the command line
- let toBeCompiled: { unitName: string; content: string }[];
+ let toBeCompiled: Harness.Compiler.TestFile[];
// equivalent to other files on the file system not directly passed to the compiler (ie things that are referenced by other files)
- let otherFiles: { unitName: string; content: string }[];
- let harnessCompiler: Harness.Compiler.HarnessCompiler;
+ let otherFiles: Harness.Compiler.TestFile[];
before(() => {
justName = fileName.replace(/^.*[\\\/]/, ""); // strips the fileName from the path.
content = Harness.IO.readFile(fileName);
testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName);
units = testCaseContent.testUnitData;
- tcSettings = testCaseContent.settings;
+ harnessSettings = testCaseContent.settings;
lastUnit = units[units.length - 1];
rootDir = lastUnit.originalFilePath.indexOf("conformance") === -1 ? "tests/cases/compiler/" : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf("/")) + "/";
- harnessCompiler = Harness.Compiler.getCompiler();
// We need to assemble the list of input files for the compiler and other related files on the 'filesystem' (ie in a multi-file test)
// If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references,
// otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another.
toBeCompiled = [];
otherFiles = [];
if (/require\(/.test(lastUnit.content) || /reference\spath/.test(lastUnit.content)) {
- toBeCompiled.push({ unitName: rootDir + lastUnit.name, content: lastUnit.content });
+ toBeCompiled.push({ unitName: ts.combinePaths(rootDir, lastUnit.name), content: lastUnit.content });
units.forEach(unit => {
if (unit.name !== lastUnit.name) {
- otherFiles.push({ unitName: rootDir + unit.name, content: unit.content });
+ otherFiles.push({ unitName: ts.combinePaths(rootDir, unit.name), content: unit.content });
}
});
}
else {
toBeCompiled = units.map(unit => {
- return { unitName: rootDir + unit.name, content: unit.content };
+ return { unitName: ts.combinePaths(rootDir, unit.name), content: unit.content };
});
}
- options = harnessCompiler.compileFiles(toBeCompiled, otherFiles, function (compileResult, _program) {
- result = compileResult;
- // The program will be used by typeWriter
- program = _program;
- }, function (settings) {
- harnessCompiler.setCompilerSettings(tcSettings);
- });
+ const output = Harness.Compiler.compileFiles(
+ toBeCompiled, otherFiles, harnessSettings, /* options */ undefined, /* currentDirectory */ undefined);
+
+ options = output.options;
+ result = output.result;
});
after(() => {
@@ -107,22 +102,20 @@ class CompilerBaselineRunner extends RunnerBase {
content = undefined;
testCaseContent = undefined;
units = undefined;
- tcSettings = undefined;
+ harnessSettings = undefined;
lastUnit = undefined;
rootDir = undefined;
result = undefined;
- program = undefined;
options = undefined;
toBeCompiled = undefined;
otherFiles = undefined;
- harnessCompiler = undefined;
});
function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string {
return file.writeByteOrderMark ? "\u00EF\u00BB\u00BF" : "";
}
- function getErrorBaseline(toBeCompiled: { unitName: string; content: string }[], otherFiles: { unitName: string; content: string }[], result: Harness.Compiler.CompilerResult) {
+ function getErrorBaseline(toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], result: Harness.Compiler.CompilerResult) {
return Harness.Compiler.getErrorBaseline(toBeCompiled.concat(otherFiles), result.errors);
}
@@ -184,9 +177,9 @@ class CompilerBaselineRunner extends RunnerBase {
}
}
- const declFileCompilationResult = harnessCompiler.compileDeclarationFiles(toBeCompiled, otherFiles, result, function (settings) {
- harnessCompiler.setCompilerSettings(tcSettings);
- }, options);
+ const declFileCompilationResult =
+ Harness.Compiler.compileDeclarationFiles(
+ toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined);
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
@@ -257,10 +250,11 @@ class CompilerBaselineRunner extends RunnerBase {
// These types are equivalent, but depend on what order the compiler observed
// certain parts of the program.
+ const program = result.program;
const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
- const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ true);
- const pullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ false);
+ const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
+ const pullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ false);
const fullResults: ts.Map = {};
const pullResults: ts.Map = {};
@@ -274,14 +268,14 @@ class CompilerBaselineRunner extends RunnerBase {
// The second gives symbols for all identifiers.
let e1: Error, e2: Error;
try {
- checkBaseLines(/*isSymbolBaseLine:*/ false);
+ checkBaseLines(/*isSymbolBaseLine*/ false);
}
catch (e) {
e1 = e;
}
try {
- checkBaseLines(/*isSymbolBaseLine:*/ true);
+ checkBaseLines(/*isSymbolBaseLine*/ true);
}
catch (e) {
e2 = e;
@@ -367,7 +361,6 @@ class CompilerBaselineRunner extends RunnerBase {
public initializeTests() {
describe(this.testSuiteName + " tests", () => {
describe("Setup compiler for compiler baselines", () => {
- const harnessCompiler = Harness.Compiler.getCompiler();
this.parseOptions();
});
diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts
index 1c8593a9e1..5f48a88539 100644
--- a/src/harness/fourslash.ts
+++ b/src/harness/fourslash.ts
@@ -48,12 +48,6 @@ namespace FourSlash {
ranges: Range[];
}
- export interface TestXmlData {
- invalidReason: string;
- originalName: string;
- actions: string[];
- }
-
interface MemberListData {
result: {
maybeInaccurate: boolean;
@@ -84,14 +78,14 @@ namespace FourSlash {
marker?: Marker;
}
- interface ILocationInformation {
+ interface LocationInformation {
position: number;
sourcePosition: number;
sourceLine: number;
sourceColumn: number;
}
- interface IRangeLocationInformation extends ILocationInformation {
+ interface RangeLocationInformation extends LocationInformation {
marker?: Marker;
}
@@ -134,11 +128,6 @@ namespace FourSlash {
return settings;
}
- export let currentTestState: TestState = null;
- function assertionMessage(msg: string) {
- return "\nMarker: " + currentTestState.lastKnownMarker + "\nChecking: " + msg + "\n\n";
- }
-
export class TestCancellationToken implements ts.HostCancellationToken {
// 0 - cancelled
// >0 - not cancelled
@@ -216,9 +205,6 @@ namespace FourSlash {
public formatCodeOptions: ts.FormatCodeOptions;
- private scenarioActions: string[] = [];
- private taoInvalidReason: string = null;
-
private inputFiles: ts.Map = {}; // Map between inputFile's fileName and its content for easily looking up when resolving references
// Add input file which has matched file name with the given reference-file path.
@@ -338,7 +324,6 @@ namespace FourSlash {
this.testData.files.forEach(file => {
const fileName = file.fileName.replace(Harness.IO.directoryName(file.fileName), "").substr(1);
const fileNameWithoutExtension = fileName.substr(0, fileName.lastIndexOf("."));
- this.scenarioActions.push("");
});
// Open the first file by default
@@ -367,35 +352,22 @@ namespace FourSlash {
public goToPosition(pos: number) {
this.currentCaretPosition = pos;
-
- const lineStarts = ts.computeLineStarts(this.getFileContent(this.activeFile.fileName));
- const lineCharPos = ts.computeLineAndCharacterOfPosition(lineStarts, pos);
- this.scenarioActions.push(``);
}
public moveCaretRight(count = 1) {
this.currentCaretPosition += count;
this.currentCaretPosition = Math.min(this.currentCaretPosition, this.getFileContent(this.activeFile.fileName).length);
- if (count > 0) {
- this.scenarioActions.push(``);
- }
- else {
- this.scenarioActions.push(``);
- }
}
// Opens a file given its 0-based index or fileName
- public openFile(index: number): void;
- public openFile(name: string): void;
- public openFile(indexOrName: any) {
+ public openFile(index: number, content?: string): void;
+ public openFile(name: string, content?: string): void;
+ public openFile(indexOrName: any, content?: string) {
const fileToOpen: FourSlashFile = this.findFile(indexOrName);
fileToOpen.fileName = ts.normalizeSlashes(fileToOpen.fileName);
this.activeFile = fileToOpen;
- const fileName = fileToOpen.fileName.replace(Harness.IO.directoryName(fileToOpen.fileName), "").substr(1);
- this.scenarioActions.push(``);
-
// Let the host know that this file is now open
- this.languageServiceAdapterHost.openFile(fileToOpen.fileName);
+ this.languageServiceAdapterHost.openFile(fileToOpen.fileName, content);
}
public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) {
@@ -407,8 +379,6 @@ namespace FourSlash {
const exists = this.anyErrorInRange(predicate, startMarker, endMarker);
- this.taoInvalidReason = "verifyErrorExistsBetweenMarkers NYI";
-
if (exists !== negative) {
this.printErrorLog(negative, this.getAllDiagnostics());
throw new Error("Failure between markers: " + startMarkerName + ", " + endMarkerName);
@@ -421,7 +391,11 @@ namespace FourSlash {
}
private messageAtLastKnownMarker(message: string) {
- return "Marker: " + currentTestState.lastKnownMarker + "\n" + message;
+ return "Marker: " + this.lastKnownMarker + "\n" + message;
+ }
+
+ private assertionMessageAtLastKnownMarker(msg: string) {
+ return "\nMarker: " + this.lastKnownMarker + "\nChecking: " + msg + "\n\n";
}
private getDiagnostics(fileName: string): ts.Diagnostic[] {
@@ -461,8 +435,6 @@ namespace FourSlash {
};
}
- this.taoInvalidReason = "verifyErrorExistsAfterMarker NYI";
-
const exists = this.anyErrorInRange(predicate, marker);
const diagnostics = this.getAllDiagnostics();
@@ -511,10 +483,8 @@ namespace FourSlash {
const errors = this.getDiagnostics(this.activeFile.fileName);
const actual = errors.length;
- this.scenarioActions.push(``);
-
if (actual !== expected) {
- this.printErrorLog(false, errors);
+ this.printErrorLog(/*expectErrors*/ false, errors);
const errorMsg = "Actual number of errors (" + actual + ") does not match expected number (" + expected + ")";
Harness.IO.log(errorMsg);
this.raiseError(errorMsg);
@@ -527,8 +497,6 @@ namespace FourSlash {
throw new Error("Expected exactly one output from emit of " + this.activeFile.fileName);
}
- this.taoInvalidReason = "verifyEval impossible";
-
const evaluation = new Function(`${emit.outputFiles[0].text};\r\nreturn (${expr});`)();
if (evaluation !== value) {
this.raiseError(`Expected evaluation of expression "${expr}" to equal "${value}", but got "${evaluation}"`);
@@ -540,7 +508,6 @@ namespace FourSlash {
if (emit.outputFiles.length !== 1) {
throw new Error("Expected exactly one output from emit of " + this.activeFile.fileName);
}
- this.taoInvalidReason = "verifyGetEmitOutputForCurrentFile impossible";
const actual = emit.outputFiles[0].text;
if (actual !== expected) {
this.raiseError(`Expected emit output to be "${expected}", but got "${actual}"`);
@@ -548,13 +515,6 @@ namespace FourSlash {
}
public verifyMemberListContains(symbol: string, text?: string, documentation?: string, kind?: string) {
- this.scenarioActions.push("");
- this.scenarioActions.push(``);
-
- if (text || documentation || kind) {
- this.taoInvalidReason = "verifyMemberListContains only supports the \"symbol\" parameter";
- }
-
const members = this.getMemberListAtCaret();
if (members) {
this.assertItemInCompletionList(members.entries, symbol, text, documentation, kind);
@@ -565,18 +525,9 @@ namespace FourSlash {
}
public verifyMemberListCount(expectedCount: number, negative: boolean) {
- if (expectedCount === 0) {
- if (negative) {
- this.verifyMemberListIsEmpty(false);
- return;
- }
- else {
- this.scenarioActions.push("");
- }
- }
- else {
- this.scenarioActions.push("");
- this.scenarioActions.push(``);
+ if (expectedCount === 0 && negative) {
+ this.verifyMemberListIsEmpty(/*negative*/ false);
+ return;
}
const members = this.getMemberListAtCaret();
@@ -594,9 +545,6 @@ namespace FourSlash {
}
public verifyMemberListDoesNotContain(symbol: string) {
- this.scenarioActions.push("");
- this.scenarioActions.push(``);
-
const members = this.getMemberListAtCaret();
if (members && members.entries.filter(e => e.name === symbol).length !== 0) {
this.raiseError(`Member list did contain ${symbol}`);
@@ -604,8 +552,6 @@ namespace FourSlash {
}
public verifyCompletionListItemsCountIsGreaterThan(count: number, negative: boolean) {
- this.taoInvalidReason = "verifyCompletionListItemsCountIsGreaterThan NYI";
-
const completions = this.getCompletionListAtCaret();
const itemsCount = completions.entries.length;
@@ -622,13 +568,6 @@ namespace FourSlash {
}
public verifyMemberListIsEmpty(negative: boolean) {
- if (negative) {
- this.scenarioActions.push("");
- }
- else {
- this.scenarioActions.push("");
- }
-
const members = this.getMemberListAtCaret();
if ((!members || members.entries.length === 0) && negative) {
this.raiseError("Member list is empty at Caret");
@@ -647,8 +586,6 @@ namespace FourSlash {
}
public verifyCompletionListIsEmpty(negative: boolean) {
- this.scenarioActions.push("");
-
const completions = this.getCompletionListAtCaret();
if ((!completions || completions.entries.length === 0) && negative) {
this.raiseError("Completion list is empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition);
@@ -716,8 +653,6 @@ namespace FourSlash {
// and keep it in the list of filtered entry.
return true;
}
- this.scenarioActions.push("");
- this.scenarioActions.push(``);
const completions = this.getCompletionListAtCaret();
if (completions) {
@@ -745,24 +680,20 @@ namespace FourSlash {
}
public verifyCompletionEntryDetails(entryName: string, expectedText: string, expectedDocumentation?: string, kind?: string) {
- this.taoInvalidReason = "verifyCompletionEntryDetails NYI";
-
const details = this.getCompletionEntryDetails(entryName);
- assert.equal(ts.displayPartsToString(details.displayParts), expectedText, assertionMessage("completion entry details text"));
+ assert.equal(ts.displayPartsToString(details.displayParts), expectedText, this.assertionMessageAtLastKnownMarker("completion entry details text"));
if (expectedDocumentation !== undefined) {
- assert.equal(ts.displayPartsToString(details.documentation), expectedDocumentation, assertionMessage("completion entry documentation"));
+ assert.equal(ts.displayPartsToString(details.documentation), expectedDocumentation, this.assertionMessageAtLastKnownMarker("completion entry documentation"));
}
if (kind !== undefined) {
- assert.equal(details.kind, kind, assertionMessage("completion entry kind"));
+ assert.equal(details.kind, kind, this.assertionMessageAtLastKnownMarker("completion entry kind"));
}
}
public verifyReferencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean) {
- this.taoInvalidReason = "verifyReferencesAtPositionListContains NYI";
-
const references = this.getReferencesAtCaret();
if (!references || references.length === 0) {
@@ -784,8 +715,6 @@ namespace FourSlash {
}
public verifyReferencesCountIs(count: number, localFilesOnly = true) {
- this.taoInvalidReason = "verifyReferences NYI";
-
const references = this.getReferencesAtCaret();
let referencesCount = 0;
@@ -845,13 +774,6 @@ namespace FourSlash {
}
public verifyQuickInfoString(negative: boolean, expectedText?: string, expectedDocumentation?: string) {
- [expectedText, expectedDocumentation].forEach(str => {
- if (str) {
- this.scenarioActions.push("");
- this.scenarioActions.push(``);
- }
- });
-
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const actualQuickInfoText = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.displayParts) : "";
const actualQuickInfoDocumentation = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.documentation) : "";
@@ -871,7 +793,7 @@ namespace FourSlash {
}
// TODO: should be '==='?
if (expectedDocumentation != undefined) {
- assert.equal(actualQuickInfoDocumentation, expectedDocumentation, assertionMessage("quick info doc"));
+ assert.equal(actualQuickInfoDocumentation, expectedDocumentation, this.assertionMessageAtLastKnownMarker("quick info doc"));
}
}
}
@@ -879,8 +801,6 @@ namespace FourSlash {
public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; },
displayParts: ts.SymbolDisplayPart[],
documentation: ts.SymbolDisplayPart[]) {
- this.scenarioActions.push("");
- this.scenarioActions.push(``);
function getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) {
let result = "";
@@ -947,8 +867,6 @@ namespace FourSlash {
}
public verifyQuickInfoExists(negative: boolean) {
- this.taoInvalidReason = "verifyQuickInfoExists NYI";
-
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
if (negative) {
if (actualQuickInfo) {
@@ -963,8 +881,6 @@ namespace FourSlash {
}
public verifyCurrentSignatureHelpIs(expected: string) {
- this.taoInvalidReason = "verifyCurrentSignatureHelpIs NYI";
-
const help = this.getActiveSignatureHelpItem();
assert.equal(
ts.displayPartsToString(help.prefixDisplayParts) +
@@ -973,75 +889,51 @@ namespace FourSlash {
}
public verifyCurrentParameterIsletiable(isVariable: boolean) {
- this.taoInvalidReason = "verifyCurrentParameterIsletiable NYI";
-
const signature = this.getActiveSignatureHelpItem();
assert.isNotNull(signature);
assert.equal(isVariable, signature.isVariadic);
}
public verifyCurrentParameterHelpName(name: string) {
- this.taoInvalidReason = "verifyCurrentParameterHelpName NYI";
-
const activeParameter = this.getActiveParameter();
const activeParameterName = activeParameter.name;
assert.equal(activeParameterName, name);
}
public verifyCurrentParameterSpanIs(parameter: string) {
- this.taoInvalidReason = "verifyCurrentParameterSpanIs NYI";
-
const activeSignature = this.getActiveSignatureHelpItem();
const activeParameter = this.getActiveParameter();
assert.equal(ts.displayPartsToString(activeParameter.displayParts), parameter);
}
public verifyCurrentParameterHelpDocComment(docComment: string) {
- this.taoInvalidReason = "verifyCurrentParameterHelpDocComment NYI";
-
const activeParameter = this.getActiveParameter();
const activeParameterDocComment = activeParameter.documentation;
- assert.equal(ts.displayPartsToString(activeParameterDocComment), docComment, assertionMessage("current parameter Help DocComment"));
+ assert.equal(ts.displayPartsToString(activeParameterDocComment), docComment, this.assertionMessageAtLastKnownMarker("current parameter Help DocComment"));
}
public verifyCurrentSignatureHelpParameterCount(expectedCount: number) {
- this.taoInvalidReason = "verifyCurrentSignatureHelpParameterCount NYI";
-
assert.equal(this.getActiveSignatureHelpItem().parameters.length, expectedCount);
}
- public verifyCurrentSignatureHelpTypeParameterCount(expectedCount: number) {
- this.taoInvalidReason = "verifyCurrentSignatureHelpTypeParameterCount NYI";
-
- // assert.equal(this.getActiveSignatureHelpItem().typeParameters.length, expectedCount);
- }
-
public verifyCurrentSignatureHelpDocComment(docComment: string) {
- this.taoInvalidReason = "verifyCurrentSignatureHelpDocComment NYI";
-
const actualDocComment = this.getActiveSignatureHelpItem().documentation;
- assert.equal(ts.displayPartsToString(actualDocComment), docComment, assertionMessage("current signature help doc comment"));
+ assert.equal(ts.displayPartsToString(actualDocComment), docComment, this.assertionMessageAtLastKnownMarker("current signature help doc comment"));
}
public verifySignatureHelpCount(expected: number) {
- this.scenarioActions.push("");
- this.scenarioActions.push(``);
-
const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
const actual = help && help.items ? help.items.length : 0;
assert.equal(actual, expected);
}
public verifySignatureHelpArgumentCount(expected: number) {
- this.taoInvalidReason = "verifySignatureHelpArgumentCount NYI";
const signatureHelpItems = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
const actual = signatureHelpItems.argumentCount;
assert.equal(actual, expected);
}
public verifySignatureHelpPresent(shouldBePresent = true) {
- this.taoInvalidReason = "verifySignatureHelpPresent NYI";
-
const actual = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
if (shouldBePresent) {
if (!actual) {
@@ -1184,13 +1076,10 @@ namespace FourSlash {
}
public getBreakpointStatementLocation(pos: number) {
- this.taoInvalidReason = "getBreakpointStatementLocation NYI";
return this.languageService.getBreakpointStatementAtPosition(this.activeFile.fileName, pos);
}
public baselineCurrentFileBreakpointLocations() {
- this.taoInvalidReason = "baselineCurrentFileBreakpointLocations impossible";
-
Harness.Baseline.runBaseline(
"Breakpoint Locations for " + this.activeFile.fileName,
this.testData.globalOptions[metadataOptionNames.baselineFile],
@@ -1201,7 +1090,6 @@ namespace FourSlash {
}
public baselineGetEmitOutput() {
- this.taoInvalidReason = "baselineGetEmitOutput impossible";
// Find file to be emitted
const emitFiles: FourSlashFile[] = []; // List of FourSlashFile that has emitThisFile flag on
@@ -1327,8 +1215,6 @@ namespace FourSlash {
}
public deleteChar(count = 1) {
- this.scenarioActions.push(``);
-
let offset = this.currentCaretPosition;
const ch = "";
@@ -1340,14 +1226,14 @@ namespace FourSlash {
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset + 1, ch);
if (i % checkCadence === 0) {
- this.checkPostEditInletiants();
+ this.checkPostEditInvariants();
}
// Handle post-keystroke formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
if (edits.length) {
- offset += this.applyEdits(this.activeFile.fileName, edits, true);
+ offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
// this.checkPostEditInletiants();
}
}
@@ -1357,20 +1243,16 @@ namespace FourSlash {
this.currentCaretPosition = offset;
this.fixCaretPosition();
- this.checkPostEditInletiants();
+ this.checkPostEditInvariants();
}
public replace(start: number, length: number, text: string) {
- this.taoInvalidReason = "replace NYI";
-
this.languageServiceAdapterHost.editScript(this.activeFile.fileName, start, start + length, text);
this.updateMarkersForEdit(this.activeFile.fileName, start, start + length, text);
- this.checkPostEditInletiants();
+ this.checkPostEditInvariants();
}
public deleteCharBehindMarker(count = 1) {
- this.scenarioActions.push(``);
-
let offset = this.currentCaretPosition;
const ch = "";
const checkCadence = (count >> 2) + 1;
@@ -1382,14 +1264,14 @@ namespace FourSlash {
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset + 1, ch);
if (i % checkCadence === 0) {
- this.checkPostEditInletiants();
+ this.checkPostEditInvariants();
}
// Handle post-keystroke formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
if (edits.length) {
- offset += this.applyEdits(this.activeFile.fileName, edits, true);
+ offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
}
}
}
@@ -1398,18 +1280,11 @@ namespace FourSlash {
this.currentCaretPosition = offset;
this.fixCaretPosition();
- this.checkPostEditInletiants();
+ this.checkPostEditInvariants();
}
// Enters lines of text at the current caret position
public type(text: string) {
- if (text === "") {
- this.taoInvalidReason = "Test used empty-insert workaround.";
- }
- else {
- this.scenarioActions.push(``);
- }
-
return this.typeHighFidelity(text);
}
@@ -1440,7 +1315,7 @@ namespace FourSlash {
}
if (i % checkCadence === 0) {
- this.checkPostEditInletiants();
+ this.checkPostEditInvariants();
// this.languageService.getSyntacticDiagnostics(this.activeFile.fileName);
// this.languageService.getSemanticDiagnostics(this.activeFile.fileName);
}
@@ -1449,7 +1324,7 @@ namespace FourSlash {
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
if (edits.length) {
- offset += this.applyEdits(this.activeFile.fileName, edits, true);
+ offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
// this.checkPostEditInletiants();
}
}
@@ -1459,26 +1334,24 @@ namespace FourSlash {
this.currentCaretPosition = offset;
this.fixCaretPosition();
- this.checkPostEditInletiants();
+ this.checkPostEditInvariants();
}
// Enters text as if the user had pasted it
public paste(text: string) {
- this.scenarioActions.push(``);
-
const start = this.currentCaretPosition;
let offset = this.currentCaretPosition;
this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset, text);
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, text);
- this.checkPostEditInletiants();
+ this.checkPostEditInvariants();
offset += text.length;
// Handle formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions);
if (edits.length) {
- offset += this.applyEdits(this.activeFile.fileName, edits, true);
- this.checkPostEditInletiants();
+ offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
+ this.checkPostEditInvariants();
}
}
@@ -1486,10 +1359,10 @@ namespace FourSlash {
this.currentCaretPosition = offset;
this.fixCaretPosition();
- this.checkPostEditInletiants();
+ this.checkPostEditInvariants();
}
- private checkPostEditInletiants() {
+ private checkPostEditInvariants() {
if (this.testType !== FourSlashTestType.Native) {
// getSourcefile() results can not be serialized. Only perform these verifications
// if running against a native LS object.
@@ -1560,18 +1433,14 @@ namespace FourSlash {
}
public formatDocument() {
- this.scenarioActions.push("");
-
const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeOptions);
- this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, true);
+ this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.fixCaretPosition();
}
public formatSelection(start: number, end: number) {
- this.taoInvalidReason = "formatSelection NYI";
-
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeOptions);
- this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, true);
+ this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.fixCaretPosition();
}
@@ -1603,13 +1472,6 @@ namespace FourSlash {
}
public goToDefinition(definitionIndex: number) {
- if (definitionIndex === 0) {
- this.scenarioActions.push("");
- }
- else {
- this.taoInvalidReason = "GoToDefinition not supported for non-zero definition indices";
- }
-
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
if (!definitions || !definitions.length) {
this.raiseError("goToDefinition failed - expected to at least one definition location but got 0");
@@ -1625,13 +1487,6 @@ namespace FourSlash {
}
public goToTypeDefinition(definitionIndex: number) {
- if (definitionIndex === 0) {
- this.scenarioActions.push("");
- }
- else {
- this.taoInvalidReason = "GoToTypeDefinition not supported for non-zero definition indices";
- }
-
const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
if (!definitions || !definitions.length) {
this.raiseError("goToTypeDefinition failed - expected to at least one definition location but got 0");
@@ -1647,8 +1502,6 @@ namespace FourSlash {
}
public verifyDefinitionLocationExists(negative: boolean) {
- this.taoInvalidReason = "verifyDefinitionLocationExists NYI";
-
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const foundDefinitions = definitions && definitions.length;
@@ -1680,8 +1533,6 @@ namespace FourSlash {
}
public verifyDefinitionsName(negative: boolean, expectedName: string, expectedContainerName: string) {
- this.taoInvalidReason = "verifyDefinititionsInfo NYI";
-
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
const actualDefinitionName = definitions && definitions.length ? definitions[0].name : "";
const actualDefinitionContainerName = definitions && definitions.length ? definitions[0].containerName : "";
@@ -1706,8 +1557,6 @@ namespace FourSlash {
}
public verifyCaretAtMarker(markerName = "") {
- this.taoInvalidReason = "verifyCaretAtMarker NYI";
-
const pos = this.getMarkerByName(markerName);
if (pos.fileName !== this.activeFile.fileName) {
throw new Error(`verifyCaretAtMarker failed - expected to be in file "${pos.fileName}", but was in file "${this.activeFile.fileName}"`);
@@ -1726,8 +1575,6 @@ namespace FourSlash {
}
public verifyIndentationAtCurrentPosition(numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart) {
- this.taoInvalidReason = "verifyIndentationAtCurrentPosition NYI";
-
const actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition, indentStyle);
const lineCol = this.getLineColStringAtPosition(this.currentCaretPosition);
if (actual !== numberOfSpaces) {
@@ -1736,8 +1583,6 @@ namespace FourSlash {
}
public verifyIndentationAtPosition(fileName: string, position: number, numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart) {
- this.taoInvalidReason = "verifyIndentationAtPosition NYI";
-
const actual = this.getIndentation(fileName, position, indentStyle);
const lineCol = this.getLineColStringAtPosition(position);
if (actual !== numberOfSpaces) {
@@ -1746,8 +1591,6 @@ namespace FourSlash {
}
public verifyCurrentLineContent(text: string) {
- this.taoInvalidReason = "verifyCurrentLineContent NYI";
-
const actual = this.getCurrentLineContent();
if (actual !== text) {
throw new Error("verifyCurrentLineContent\n" +
@@ -1757,8 +1600,6 @@ namespace FourSlash {
}
public verifyCurrentFileContent(text: string) {
- this.taoInvalidReason = "verifyCurrentFileContent NYI";
-
const actual = this.getFileContent(this.activeFile.fileName);
const replaceNewlines = (str: string) => str.replace(/\r\n/g, "\n");
if (replaceNewlines(actual) !== replaceNewlines(text)) {
@@ -1769,8 +1610,6 @@ namespace FourSlash {
}
public verifyTextAtCaretIs(text: string) {
- this.taoInvalidReason = "verifyCurrentFileContent NYI";
-
const actual = this.getFileContent(this.activeFile.fileName).substring(this.currentCaretPosition, this.currentCaretPosition + text.length);
if (actual !== text) {
throw new Error("verifyTextAtCaretIs\n" +
@@ -1780,8 +1619,6 @@ namespace FourSlash {
}
public verifyCurrentNameOrDottedNameSpanText(text: string) {
- this.taoInvalidReason = "verifyCurrentNameOrDottedNameSpanText NYI";
-
const span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition);
if (!span) {
this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" +
@@ -1798,13 +1635,10 @@ namespace FourSlash {
}
private getNameOrDottedNameSpan(pos: number) {
- this.taoInvalidReason = "getNameOrDottedNameSpan NYI";
return this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, pos, pos);
}
public baselineCurrentFileNameOrDottedNameSpans() {
- this.taoInvalidReason = "baselineCurrentFileNameOrDottedNameSpans impossible";
-
Harness.Baseline.runBaseline(
"Name OrDottedNameSpans for " + this.activeFile.fileName,
this.testData.globalOptions[metadataOptionNames.baselineFile],
@@ -1898,8 +1732,6 @@ namespace FourSlash {
}
public verifyOutliningSpans(spans: TextSpan[]) {
- this.taoInvalidReason = "verifyOutliningSpans NYI";
-
const actual = this.languageService.getOutliningSpans(this.activeFile.fileName);
if (actual.length !== spans.length) {
@@ -1968,8 +1800,6 @@ namespace FourSlash {
}
public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number) {
- this.taoInvalidReason = "verifyMatchingBracePosition NYI";
-
const actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition);
if (actual.length !== 2) {
@@ -1993,8 +1823,6 @@ namespace FourSlash {
}
public verifyNoMatchingBracePosition(bracePosition: number) {
- this.taoInvalidReason = "verifyNoMatchingBracePosition NYI";
-
const actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition);
if (actual.length !== 0) {
@@ -2007,8 +1835,6 @@ namespace FourSlash {
Report an error if expected value and actual value do not match.
*/
public verifyNavigationItemsCount(expected: number, searchValue: string, matchKind?: string) {
- this.taoInvalidReason = "verifyNavigationItemsCount NYI";
-
const items = this.languageService.getNavigateToItems(searchValue);
let actual = 0;
let item: ts.NavigateToItem = null;
@@ -2037,8 +1863,6 @@ namespace FourSlash {
matchKind: string,
fileName?: string,
parentName?: string) {
- this.taoInvalidReason = "verifyNavigationItemsListContains NYI";
-
const items = this.languageService.getNavigateToItems(searchValue);
if (!items || items.length === 0) {
@@ -2063,8 +1887,6 @@ namespace FourSlash {
}
public verifyGetScriptLexicalStructureListCount(expected: number) {
- this.taoInvalidReason = "verifyNavigationItemsListContains impossible";
-
const items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
const actual = this.getNavigationBarItemsCount(items);
@@ -2086,8 +1908,6 @@ namespace FourSlash {
}
public verifyGetScriptLexicalStructureListContains(name: string, kind: string) {
- this.taoInvalidReason = "verifyGetScriptLexicalStructureListContains impossible";
-
const items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
if (!items || items.length === 0) {
@@ -2148,8 +1968,6 @@ namespace FourSlash {
}
public verifyOccurrencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean) {
- this.taoInvalidReason = "verifyOccurrencesAtPositionListContains NYI";
-
const occurrences = this.getOccurrencesAtCurrentPosition();
if (!occurrences || occurrences.length === 0) {
@@ -2170,8 +1988,6 @@ namespace FourSlash {
}
public verifyOccurrencesAtPositionListCount(expectedCount: number) {
- this.taoInvalidReason = "verifyOccurrencesAtPositionListCount NYI";
-
const occurrences = this.getOccurrencesAtCurrentPosition();
const actualCount = occurrences ? occurrences.length : 0;
if (expectedCount !== actualCount) {
@@ -2185,8 +2001,6 @@ namespace FourSlash {
}
public verifyDocumentHighlightsAtPositionListContains(fileName: string, start: number, end: number, fileNamesToSearch: string[], kind?: string) {
- this.taoInvalidReason = "verifyDocumentHighlightsAtPositionListContains NYI";
-
const documentHighlights = this.getDocumentHighlightsAtCurrentPosition(fileNamesToSearch);
if (!documentHighlights || documentHighlights.length === 0) {
@@ -2213,8 +2027,6 @@ namespace FourSlash {
}
public verifyDocumentHighlightsAtPositionListCount(expectedCount: number, fileNamesToSearch: string[]) {
- this.taoInvalidReason = "verifyDocumentHighlightsAtPositionListCount NYI";
-
const documentHighlights = this.getDocumentHighlightsAtCurrentPosition(fileNamesToSearch);
const actualCount = documentHighlights
? documentHighlights.reduce((currentCount, { highlightSpans }) => currentCount + highlightSpans.length, 0)
@@ -2255,13 +2067,6 @@ namespace FourSlash {
}
private assertItemInCompletionList(items: ts.CompletionEntry[], name: string, text?: string, documentation?: string, kind?: string) {
- this.scenarioActions.push("");
- this.scenarioActions.push(``);
-
- if (text || documentation || kind) {
- this.taoInvalidReason = "assertItemInCompletionList only supports the \"name\" parameter";
- }
-
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (item.name === name) {
@@ -2269,15 +2074,15 @@ namespace FourSlash {
const details = this.getCompletionEntryDetails(item.name);
if (documentation !== undefined) {
- assert.equal(ts.displayPartsToString(details.documentation), documentation, assertionMessage("completion item documentation for " + name));
+ assert.equal(ts.displayPartsToString(details.documentation), documentation, this.assertionMessageAtLastKnownMarker("completion item documentation for " + name));
}
if (text !== undefined) {
- assert.equal(ts.displayPartsToString(details.displayParts), text, assertionMessage("completion item detail text for " + name));
+ assert.equal(ts.displayPartsToString(details.displayParts), text, this.assertionMessageAtLastKnownMarker("completion item detail text for " + name));
}
}
if (kind !== undefined) {
- assert.equal(item.kind, kind, assertionMessage("completion item kind for " + name));
+ assert.equal(item.kind, kind, this.assertionMessageAtLastKnownMarker("completion item kind for " + name));
}
return;
@@ -2352,14 +2157,6 @@ namespace FourSlash {
return text.replace(/ /g, "\u00B7").replace(/\r/g, "\u00B6").replace(/\n/g, "\u2193\n").replace(/\t/g, "\u2192\ ");
}
- public getTestXmlData(): TestXmlData {
- return {
- actions: this.scenarioActions,
- invalidReason: this.taoInvalidReason,
- originalName: ""
- };
- }
-
public setCancelled(numberOfCalls: number): void {
this.cancellationToken.setCancelled(numberOfCalls);
}
@@ -2372,43 +2169,33 @@ namespace FourSlash {
// TOOD: should these just use the Harness's stdout/stderr?
const fsOutput = new Harness.Compiler.WriterAggregator();
const fsErrors = new Harness.Compiler.WriterAggregator();
- export let xmlData: TestXmlData[] = [];
export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string) {
const content = Harness.IO.readFile(fileName);
- const xml = runFourSlashTestContent(basePath, testType, content, fileName);
- xmlData.push(xml);
+ runFourSlashTestContent(basePath, testType, content, fileName);
}
- // We don't want to recompile 'fourslash.ts' for every test, so
- // here we cache the JS output and reuse it for every test.
- let fourslashJsOutput: string;
- {
- const host = Harness.Compiler.createCompilerHost([{ unitName: Harness.Compiler.fourslashFileName, content: undefined }],
- (fn, contents) => fourslashJsOutput = contents,
- ts.ScriptTarget.Latest,
- Harness.IO.useCaseSensitiveFileNames());
-
- const program = ts.createProgram([Harness.Compiler.fourslashFileName], { noResolve: true, target: ts.ScriptTarget.ES3 }, host);
-
- program.emit(host.getSourceFile(Harness.Compiler.fourslashFileName, ts.ScriptTarget.ES3));
- }
-
-
- export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): TestXmlData {
+ export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void {
// Parse out the files and their metadata
const testData = parseTestData(basePath, content, fileName);
- currentTestState = new TestState(basePath, testType, testData);
+ const state = new TestState(basePath, testType, testData);
let result = "";
+ const fourslashFile: Harness.Compiler.TestFile = {
+ unitName: Harness.Compiler.fourslashFileName,
+ content: undefined,
+ };
+ const testFile: Harness.Compiler.TestFile = {
+ unitName: fileName,
+ content: content
+ };
+
const host = Harness.Compiler.createCompilerHost(
- [
- { unitName: Harness.Compiler.fourslashFileName, content: undefined },
- { unitName: fileName, content: content }
- ],
+ [ fourslashFile, testFile ],
(fn, contents) => result = contents,
ts.ScriptTarget.Latest,
- Harness.IO.useCaseSensitiveFileNames());
+ Harness.IO.useCaseSensitiveFileNames(),
+ Harness.IO.getCurrentDirectory());
const program = ts.createProgram([Harness.Compiler.fourslashFileName, fileName], { outFile: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host);
@@ -2421,22 +2208,32 @@ namespace FourSlash {
}
program.emit(sourceFile);
- result = result || ""; // Might have an empty fourslash file
- result = fourslashJsOutput + "\r\n" + result;
+ ts.Debug.assert(!!result);
+ runCode(result, state);
+ }
+ function runCode(code: string, state: TestState): void {
// Compile and execute the test
+ const wrappedCode =
+`(function(test, goTo, verify, edit, debug, format, cancellation, classification, verifyOperationIsCancelled) {
+${code}
+})`;
try {
- eval(result);
+ const test = new FourSlashInterface.Test(state);
+ const goTo = new FourSlashInterface.GoTo(state);
+ const verify = new FourSlashInterface.Verify(state);
+ const edit = new FourSlashInterface.Edit(state);
+ const debug = new FourSlashInterface.Debug(state);
+ 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);
}
catch (err) {
// Debugging: FourSlash.currentTestState.printCurrentFileState();
throw err;
}
-
- const xmlData = currentTestState.getTestXmlData();
- xmlData.originalName = fileName;
- return xmlData;
}
function chompLeadingSpace(content: string) {
@@ -2604,7 +2401,7 @@ namespace FourSlash {
throw new Error(errorMessage);
}
- function recordObjectMarker(fileName: string, location: ILocationInformation, text: string, markerMap: MarkerMap, markers: Marker[]): Marker {
+ function recordObjectMarker(fileName: string, location: LocationInformation, text: string, markerMap: MarkerMap, markers: Marker[]): Marker {
let markerValue: any = undefined;
try {
// Attempt to parse the marker value as JSON
@@ -2635,7 +2432,7 @@ namespace FourSlash {
return marker;
}
- function recordMarker(fileName: string, location: ILocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker {
+ function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker {
const marker: Marker = {
fileName: fileName,
position: location.position
@@ -2664,10 +2461,10 @@ namespace FourSlash {
let output = "";
/// The current marker (or maybe multi-line comment?) we're parsing, possibly
- let openMarker: ILocationInformation = null;
+ let openMarker: LocationInformation = null;
/// A stack of the open range markers that are still unclosed
- const openRanges: IRangeLocationInformation[] = [];
+ const openRanges: RangeLocationInformation[] = [];
/// A list of ranges we've collected so far */
let localRanges: Range[] = [];
@@ -2853,3 +2650,628 @@ namespace FourSlash {
};
}
}
+
+namespace FourSlashInterface {
+ export class Test {
+ constructor(private state: FourSlash.TestState) {
+ }
+
+ public markers(): FourSlash.Marker[] {
+ return this.state.getMarkers();
+ }
+
+ public marker(name?: string): FourSlash.Marker {
+ return this.state.getMarkerByName(name);
+ }
+
+ public ranges(): FourSlash.Range[] {
+ return this.state.getRanges();
+ }
+
+ public markerByName(s: string): FourSlash.Marker {
+ return this.state.getMarkerByName(s);
+ }
+ }
+
+ export class GoTo {
+ constructor(private state: FourSlash.TestState) {
+ }
+ // Moves the caret to the specified marker,
+ // or the anonymous marker ('/**/') if no name
+ // is given
+ public marker(name?: string) {
+ this.state.goToMarker(name);
+ }
+
+ public bof() {
+ this.state.goToBOF();
+ }
+
+ public eof() {
+ this.state.goToEOF();
+ }
+
+ public definition(definitionIndex = 0) {
+ this.state.goToDefinition(definitionIndex);
+ }
+
+ public type(definitionIndex = 0) {
+ this.state.goToTypeDefinition(definitionIndex);
+ }
+
+ public position(position: number, fileIndex?: number): void;
+ public position(position: number, fileName?: string): void;
+ public position(position: number, fileNameOrIndex?: any): void {
+ if (fileNameOrIndex !== undefined) {
+ this.file(fileNameOrIndex);
+ }
+ this.state.goToPosition(position);
+ }
+
+ // Opens a file, given either its index as it
+ // appears in the test source, or its filename
+ // as specified in the test metadata
+ public file(index: number, content?: string): void;
+ public file(name: string, content?: string): void;
+ public file(indexOrName: any, content?: string): void {
+ this.state.openFile(indexOrName, content);
+ }
+ }
+
+ export class VerifyNegatable {
+ public not: VerifyNegatable;
+
+ constructor(protected state: FourSlash.TestState, private negative = false) {
+ if (!negative) {
+ this.not = new VerifyNegatable(state, true);
+ }
+ }
+
+ // Verifies the member list contains the specified symbol. The
+ // member list is brought up if necessary
+ public memberListContains(symbol: string, text?: string, documenation?: string, kind?: string) {
+ if (this.negative) {
+ this.state.verifyMemberListDoesNotContain(symbol);
+ }
+ else {
+ this.state.verifyMemberListContains(symbol, text, documenation, kind);
+ }
+ }
+
+ public memberListCount(expectedCount: number) {
+ this.state.verifyMemberListCount(expectedCount, this.negative);
+ }
+
+ // Verifies the completion list contains the specified symbol. The
+ // completion list is brought up if necessary
+ public completionListContains(symbol: string, text?: string, documentation?: string, kind?: string) {
+ if (this.negative) {
+ this.state.verifyCompletionListDoesNotContain(symbol, text, documentation, kind);
+ }
+ else {
+ this.state.verifyCompletionListContains(symbol, text, documentation, kind);
+ }
+ }
+
+ // Verifies the completion list items count to be greater than the specified amount. The
+ // completion list is brought up if necessary
+ public completionListItemsCountIsGreaterThan(count: number) {
+ this.state.verifyCompletionListItemsCountIsGreaterThan(count, this.negative);
+ }
+
+ public completionListIsEmpty() {
+ this.state.verifyCompletionListIsEmpty(this.negative);
+ }
+
+ public completionListAllowsNewIdentifier() {
+ this.state.verifyCompletionListAllowsNewIdentifier(this.negative);
+ }
+
+ public memberListIsEmpty() {
+ this.state.verifyMemberListIsEmpty(this.negative);
+ }
+
+ public referencesCountIs(count: number) {
+ this.state.verifyReferencesCountIs(count, /*localFilesOnly*/ false);
+ }
+
+ public referencesAtPositionContains(range: FourSlash.Range, isWriteAccess?: boolean) {
+ this.state.verifyReferencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess);
+ }
+
+ public signatureHelpPresent() {
+ this.state.verifySignatureHelpPresent(!this.negative);
+ }
+
+ public errorExistsBetweenMarkers(startMarker: string, endMarker: string) {
+ this.state.verifyErrorExistsBetweenMarkers(startMarker, endMarker, !this.negative);
+ }
+
+ public errorExistsAfterMarker(markerName = "") {
+ this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ true);
+ }
+
+ public errorExistsBeforeMarker(markerName = "") {
+ this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ false);
+ }
+
+ public quickInfoIs(expectedText?: string, expectedDocumentation?: string) {
+ this.state.verifyQuickInfoString(this.negative, expectedText, expectedDocumentation);
+ }
+
+ public quickInfoExists() {
+ this.state.verifyQuickInfoExists(this.negative);
+ }
+
+ public definitionCountIs(expectedCount: number) {
+ this.state.verifyDefinitionsCount(this.negative, expectedCount);
+ }
+
+ public typeDefinitionCountIs(expectedCount: number) {
+ this.state.verifyTypeDefinitionsCount(this.negative, expectedCount);
+ }
+
+ public definitionLocationExists() {
+ this.state.verifyDefinitionLocationExists(this.negative);
+ }
+
+ public verifyDefinitionsName(name: string, containerName: string) {
+ this.state.verifyDefinitionsName(this.negative, name, containerName);
+ }
+ }
+
+ export class Verify extends VerifyNegatable {
+ constructor(state: FourSlash.TestState) {
+ super(state);
+ }
+
+ public caretAtMarker(markerName?: string) {
+ this.state.verifyCaretAtMarker(markerName);
+ }
+
+ public indentationIs(numberOfSpaces: number) {
+ this.state.verifyIndentationAtCurrentPosition(numberOfSpaces);
+ }
+
+ public indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle = ts.IndentStyle.Smart) {
+ this.state.verifyIndentationAtPosition(fileName, position, numberOfSpaces, indentStyle);
+ }
+
+ public textAtCaretIs(text: string) {
+ this.state.verifyTextAtCaretIs(text);
+ }
+
+ /**
+ * Compiles the current file and evaluates 'expr' in a context containing
+ * the emitted output, then compares (using ===) the result of that expression
+ * to 'value'. Do not use this function with external modules as it is not supported.
+ */
+ public eval(expr: string, value: any) {
+ this.state.verifyEval(expr, value);
+ }
+
+ public currentLineContentIs(text: string) {
+ this.state.verifyCurrentLineContent(text);
+ }
+
+ public currentFileContentIs(text: string) {
+ this.state.verifyCurrentFileContent(text);
+ }
+
+ public verifyGetEmitOutputForCurrentFile(expected: string): void {
+ this.state.verifyGetEmitOutputForCurrentFile(expected);
+ }
+
+ public currentParameterHelpArgumentNameIs(name: string) {
+ this.state.verifyCurrentParameterHelpName(name);
+ }
+
+ public currentParameterSpanIs(parameter: string) {
+ this.state.verifyCurrentParameterSpanIs(parameter);
+ }
+
+ public currentParameterHelpArgumentDocCommentIs(docComment: string) {
+ this.state.verifyCurrentParameterHelpDocComment(docComment);
+ }
+
+ public currentSignatureHelpDocCommentIs(docComment: string) {
+ this.state.verifyCurrentSignatureHelpDocComment(docComment);
+ }
+
+ public signatureHelpCountIs(expected: number) {
+ this.state.verifySignatureHelpCount(expected);
+ }
+
+ public signatureHelpArgumentCountIs(expected: number) {
+ this.state.verifySignatureHelpArgumentCount(expected);
+ }
+
+ public currentSignatureParameterCountIs(expected: number) {
+ this.state.verifyCurrentSignatureHelpParameterCount(expected);
+ }
+
+ public currentSignatureHelpIs(expected: string) {
+ this.state.verifyCurrentSignatureHelpIs(expected);
+ }
+
+ public numberOfErrorsInCurrentFile(expected: number) {
+ this.state.verifyNumberOfErrorsInCurrentFile(expected);
+ }
+
+ public baselineCurrentFileBreakpointLocations() {
+ this.state.baselineCurrentFileBreakpointLocations();
+ }
+
+ public baselineCurrentFileNameOrDottedNameSpans() {
+ this.state.baselineCurrentFileNameOrDottedNameSpans();
+ }
+
+ public baselineGetEmitOutput() {
+ this.state.baselineGetEmitOutput();
+ }
+
+ public nameOrDottedNameSpanTextIs(text: string) {
+ this.state.verifyCurrentNameOrDottedNameSpanText(text);
+ }
+
+ public outliningSpansInCurrentFile(spans: FourSlash.TextSpan[]) {
+ this.state.verifyOutliningSpans(spans);
+ }
+
+ public todoCommentsInCurrentFile(descriptors: string[]) {
+ this.state.verifyTodoComments(descriptors, this.state.getRanges());
+ }
+
+ public matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number) {
+ this.state.verifyMatchingBracePosition(bracePosition, expectedMatchPosition);
+ }
+
+ public noMatchingBracePositionInCurrentFile(bracePosition: number) {
+ this.state.verifyNoMatchingBracePosition(bracePosition);
+ }
+
+ public DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean) {
+ this.state.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, caretOffset: expectedOffset });
+ }
+
+ public noDocCommentTemplate() {
+ this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true);
+ }
+
+ public getScriptLexicalStructureListCount(count: number) {
+ this.state.verifyGetScriptLexicalStructureListCount(count);
+ }
+
+ // TODO: figure out what to do with the unused arguments.
+ public getScriptLexicalStructureListContains(
+ name: string,
+ kind: string,
+ fileName?: string,
+ parentName?: string,
+ isAdditionalSpan?: boolean,
+ markerPosition?: number) {
+ this.state.verifyGetScriptLexicalStructureListContains(name, kind);
+ }
+
+ public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) {
+ this.state.verifyNavigationItemsCount(count, searchValue, matchKind);
+ }
+
+ public navigationItemsListContains(
+ name: string,
+ kind: string,
+ searchValue: string,
+ matchKind: string,
+ fileName?: string,
+ parentName?: string) {
+ this.state.verifyNavigationItemsListContains(
+ name,
+ kind,
+ searchValue,
+ matchKind,
+ fileName,
+ parentName);
+ }
+
+ public occurrencesAtPositionContains(range: FourSlash.Range, isWriteAccess?: boolean) {
+ this.state.verifyOccurrencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess);
+ }
+
+ public occurrencesAtPositionCount(expectedCount: number) {
+ this.state.verifyOccurrencesAtPositionListCount(expectedCount);
+ }
+
+ public documentHighlightsAtPositionContains(range: FourSlash.Range, fileNamesToSearch: string[], kind?: string) {
+ this.state.verifyDocumentHighlightsAtPositionListContains(range.fileName, range.start, range.end, fileNamesToSearch, kind);
+ }
+
+ public documentHighlightsAtPositionCount(expectedCount: number, fileNamesToSearch: string[]) {
+ this.state.verifyDocumentHighlightsAtPositionListCount(expectedCount, fileNamesToSearch);
+ }
+
+ public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string) {
+ this.state.verifyCompletionEntryDetails(entryName, text, documentation, kind);
+ }
+
+ /**
+ * This method *requires* a contiguous, complete, and ordered stream of classifications for a file.
+ */
+ public syntacticClassificationsAre(...classifications: { classificationType: string; text: string }[]) {
+ this.state.verifySyntacticClassifications(classifications);
+ }
+
+ /**
+ * This method *requires* an ordered stream of classifications for a file, and spans are highly recommended.
+ */
+ public semanticClassificationsAre(...classifications: { classificationType: string; text: string; textSpan?: FourSlash.TextSpan }[]) {
+ this.state.verifySemanticClassifications(classifications);
+ }
+
+ public renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string) {
+ this.state.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers);
+ }
+
+ public renameInfoFailed(message?: string) {
+ this.state.verifyRenameInfoFailed(message);
+ }
+
+ public renameLocations(findInStrings: boolean, findInComments: boolean) {
+ this.state.verifyRenameLocations(findInStrings, findInComments);
+ }
+
+ public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; },
+ displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) {
+ this.state.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation);
+ }
+
+ public getSyntacticDiagnostics(expected: string) {
+ this.state.getSyntacticDiagnostics(expected);
+ }
+
+ public getSemanticDiagnostics(expected: string) {
+ this.state.getSemanticDiagnostics(expected);
+ }
+
+ public ProjectInfo(expected: string []) {
+ this.state.verifyProjectInfo(expected);
+ }
+ }
+
+ export class Edit {
+ constructor(private state: FourSlash.TestState) {
+ }
+ public backspace(count?: number) {
+ this.state.deleteCharBehindMarker(count);
+ }
+
+ public deleteAtCaret(times?: number) {
+ this.state.deleteChar(times);
+ }
+
+ public replace(start: number, length: number, text: string) {
+ this.state.replace(start, length, text);
+ }
+
+ public paste(text: string) {
+ this.state.paste(text);
+ }
+
+ public insert(text: string) {
+ this.insertLines(text);
+ }
+
+ public insertLine(text: string) {
+ this.insertLines(text + "\n");
+ }
+
+ public insertLines(...lines: string[]) {
+ this.state.type(lines.join("\n"));
+ }
+
+ public moveRight(count?: number) {
+ this.state.moveCaretRight(count);
+ }
+
+ public moveLeft(count?: number) {
+ if (typeof count === "undefined") {
+ count = 1;
+ }
+ this.state.moveCaretRight(count * -1);
+ }
+
+ public enableFormatting() {
+ this.state.enableFormatting = true;
+ }
+
+ public disableFormatting() {
+ this.state.enableFormatting = false;
+ }
+ }
+
+ export class Debug {
+ constructor(private state: FourSlash.TestState) {
+ }
+
+ public printCurrentParameterHelp() {
+ this.state.printCurrentParameterHelp();
+ }
+
+ public printCurrentFileState() {
+ this.state.printCurrentFileState();
+ }
+
+ public printCurrentFileStateWithWhitespace() {
+ this.state.printCurrentFileState(/*makeWhitespaceVisible*/true);
+ }
+
+ public printCurrentFileStateWithoutCaret() {
+ this.state.printCurrentFileState(/*makeWhitespaceVisible*/false, /*makeCaretVisible*/false);
+ }
+
+ public printCurrentQuickInfo() {
+ this.state.printCurrentQuickInfo();
+ }
+
+ public printCurrentSignatureHelp() {
+ this.state.printCurrentSignatureHelp();
+ }
+
+ public printMemberListMembers() {
+ this.state.printMemberListMembers();
+ }
+
+ public printCompletionListMembers() {
+ this.state.printCompletionListMembers();
+ }
+
+ public printBreakpointLocation(pos: number) {
+ this.state.printBreakpointLocation(pos);
+ }
+ public printBreakpointAtCurrentLocation() {
+ this.state.printBreakpointAtCurrentLocation();
+ }
+
+ public printNameOrDottedNameSpans(pos: number) {
+ this.state.printNameOrDottedNameSpans(pos);
+ }
+
+ public printErrorList() {
+ this.state.printErrorList();
+ }
+
+ public printNavigationItems(searchValue = ".*") {
+ this.state.printNavigationItems(searchValue);
+ }
+
+ public printScriptLexicalStructureItems() {
+ this.state.printScriptLexicalStructureItems();
+ }
+
+ public printReferences() {
+ this.state.printReferences();
+ }
+
+ public printContext() {
+ this.state.printContext();
+ }
+ }
+
+ export class Format {
+ constructor(private state: FourSlash.TestState) {
+ }
+
+ public document() {
+ this.state.formatDocument();
+ }
+
+ public copyFormatOptions(): ts.FormatCodeOptions {
+ return this.state.copyFormatOptions();
+ }
+
+ public setFormatOptions(options: ts.FormatCodeOptions) {
+ return this.state.setFormatOptions(options);
+ }
+
+ public selection(startMarker: string, endMarker: string) {
+ this.state.formatSelection(this.state.getMarkerByName(startMarker).position, this.state.getMarkerByName(endMarker).position);
+ }
+
+ public setOption(name: string, value: number): void;
+ public setOption(name: string, value: string): void;
+ public setOption(name: string, value: boolean): void;
+ public setOption(name: string, value: any): void {
+ this.state.formatCodeOptions[name] = value;
+ }
+ }
+
+ export class Cancellation {
+ constructor(private state: FourSlash.TestState) {
+ }
+
+ public resetCancelled() {
+ this.state.resetCancelled();
+ }
+
+ public setCancelled(numberOfCalls = 0) {
+ this.state.setCancelled(numberOfCalls);
+ }
+ }
+
+ export namespace Classification {
+ export function comment(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("comment", text, position);
+ }
+
+ export function identifier(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("identifier", text, position);
+ }
+
+ export function keyword(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("keyword", text, position);
+ }
+
+ export function numericLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("numericLiteral", text, position);
+ }
+
+ export function operator(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("operator", text, position);
+ }
+
+ export function stringLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("stringLiteral", text, position);
+ }
+
+ export function whiteSpace(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("whiteSpace", text, position);
+ }
+
+ export function text(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("text", text, position);
+ }
+
+ export function punctuation(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("punctuation", text, position);
+ }
+
+ export function docCommentTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("docCommentTagName", text, position);
+ }
+
+ export function className(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("className", text, position);
+ }
+
+ export function enumName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("enumName", text, position);
+ }
+
+ export function interfaceName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("interfaceName", text, position);
+ }
+
+ export function moduleName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("moduleName", text, position);
+ }
+
+ export function typeParameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("typeParameterName", text, position);
+ }
+
+ export function parameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("parameterName", text, position);
+ }
+
+ export function typeAliasName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
+ return getClassification("typeAliasName", text, position);
+ }
+
+ function getClassification(type: string, text: string, position?: number) {
+ return {
+ classificationType: type,
+ text: text,
+ textSpan: position === undefined ? undefined : { start: position, end: position + text.length }
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/harness/fourslashRunner.ts b/src/harness/fourslashRunner.ts
index 7228f06c20..84e352359c 100644
--- a/src/harness/fourslashRunner.ts
+++ b/src/harness/fourslashRunner.ts
@@ -58,56 +58,6 @@ class FourSlashRunner extends RunnerBase {
}
});
});
-
- describe("Generate Tao XML", () => {
- const invalidReasons: any = {};
- FourSlash.xmlData.forEach(xml => {
- if (xml.invalidReason !== null) {
- invalidReasons[xml.invalidReason] = (invalidReasons[xml.invalidReason] || 0) + 1;
- }
- });
- const invalidReport: { reason: string; count: number }[] = [];
- for (const reason in invalidReasons) {
- if (invalidReasons.hasOwnProperty(reason)) {
- invalidReport.push({ reason: reason, count: invalidReasons[reason] });
- }
- }
- invalidReport.sort((lhs, rhs) => lhs.count > rhs.count ? -1 : lhs.count === rhs.count ? 0 : 1);
-
- const lines: string[] = [];
- lines.push("");
- lines.push("");
- lines.push(" ");
- lines.push(" ");
- lines.push(" ");
- lines.push(" ");
- FourSlash.xmlData.forEach(xml => {
- if (xml.invalidReason !== null) {
- lines.push("");
- }
- else {
- lines.push(" ");
- xml.actions.forEach(action => {
- lines.push(" " + action);
- });
- lines.push(" ");
- }
- });
- lines.push(" ");
- lines.push(" ");
- lines.push(" ");
- lines.push(" ");
- lines.push(" ");
- lines.push(" ");
- lines.push(" ");
- lines.push(" ");
- lines.push("");
- Harness.IO.writeFile("built/local/fourslash.xml", lines.join("\r\n"));
- });
});
}
}
diff --git a/src/harness/harness.ts b/src/harness/harness.ts
index 16c3b2d348..ef0f2678e2 100644
--- a/src/harness/harness.ts
+++ b/src/harness/harness.ts
@@ -628,7 +628,7 @@ namespace Harness {
function getResolvedPathFromServer(path: string) {
const xhr = new XMLHttpRequest();
try {
- xhr.open("GET", path + "?resolve", false);
+ xhr.open("GET", path + "?resolve", /*async*/ false);
xhr.send();
}
catch (e) {
@@ -647,7 +647,7 @@ namespace Harness {
export function getFileFromServerSync(url: string): XHRResponse {
const xhr = new XMLHttpRequest();
try {
- xhr.open("GET", url, false);
+ xhr.open("GET", url, /*async*/ false);
xhr.send();
}
catch (e) {
@@ -662,7 +662,7 @@ namespace Harness {
const xhr = new XMLHttpRequest();
try {
const actionMsg = "?action=" + action;
- xhr.open("POST", url + actionMsg, false);
+ xhr.open("POST", url + actionMsg, /*async*/ false);
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.send(contents);
}
@@ -767,26 +767,9 @@ namespace Harness {
}
namespace Harness {
- let tcServicesFileName = "typescriptServices.js";
-
- export let libFolder: string;
- switch (Utils.getExecutionEnvironment()) {
- case Utils.ExecutionEnvironment.CScript:
- libFolder = "built/local/";
- tcServicesFileName = "built/local/typescriptServices.js";
- break;
- case Utils.ExecutionEnvironment.Node:
- libFolder = "built/local/";
- tcServicesFileName = "built/local/typescriptServices.js";
- break;
- case Utils.ExecutionEnvironment.Browser:
- libFolder = "built/local/";
- tcServicesFileName = "built/local/typescriptServices.js";
- break;
- default:
- throw new Error("Unknown context");
- }
- export let tcServicesFile = IO.readFile(tcServicesFileName);
+ export const libFolder = "built/local/";
+ const tcServicesFileName = ts.combinePaths(libFolder, "typescriptServices.js");
+ export const tcServicesFile = IO.readFile(tcServicesFileName);
export interface SourceMapEmitterCallback {
(emittedFile: string, emittedLine: number, emittedColumn: number, sourceFile: string, sourceLine: number, sourceColumn: number, sourceName: string): void;
@@ -827,57 +810,14 @@ namespace Harness {
}
}
- export interface IEmitterIOHost {
- writeFile(path: string, contents: string, writeByteOrderMark: boolean): void;
- resolvePath(path: string): string;
- }
-
- /** Mimics having multiple files, later concatenated to a single file. */
- export class EmitterIOHost implements IEmitterIOHost {
- private fileCollection: any = {};
-
- /** create file gets the whole path to create, so this works as expected with the --out parameter */
- public writeFile(s: string, contents: string, writeByteOrderMark: boolean): void {
- let writer: ITextWriter;
- if (this.fileCollection[s]) {
- writer = this.fileCollection[s];
- }
- else {
- writer = new Harness.Compiler.WriterAggregator();
- this.fileCollection[s] = writer;
- }
-
- writer.Write(contents);
- writer.Close();
- }
-
- public resolvePath(s: string) { return s; }
-
- public reset() { this.fileCollection = {}; }
-
- public toArray(): { fileName: string; file: WriterAggregator; }[] {
- const result: { fileName: string; file: WriterAggregator; }[] = [];
- for (const p in this.fileCollection) {
- if (this.fileCollection.hasOwnProperty(p)) {
- const current = this.fileCollection[p];
- if (current.lines.length > 0) {
- if (p.indexOf(".d.ts") !== -1) { current.lines.unshift(["////[", Path.getFileName(p), "]"].join("")); }
- result.push({ fileName: p, file: this.fileCollection[p] });
- }
- }
- }
- return result;
- }
- }
-
export function createSourceFileAndAssertInvariants(
fileName: string,
sourceText: string,
languageVersion: ts.ScriptTarget) {
- // We'll only assert inletiants outside of light mode.
+ // We'll only assert invariants outside of light mode.
const shouldAssertInvariants = !Harness.lightMode;
- // Only set the parent nodes if we're asserting inletiants. We don't need them otherwise.
+ // 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);
if (shouldAssertInvariants) {
@@ -890,12 +830,12 @@ namespace Harness {
const carriageReturnLineFeed = "\r\n";
const lineFeed = "\n";
- export let defaultLibFileName = "lib.d.ts";
- export let defaultLibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest);
- export let defaultES6LibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.es6.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest);
+ export const defaultLibFileName = "lib.d.ts";
+ export const defaultLibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest);
+ export const defaultES6LibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.es6.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest);
// Cache these between executions so we don't have to re-parse them for every test
- export let fourslashFileName = "fourslash.ts";
+ export const fourslashFileName = "fourslash.ts";
export let fourslashSourceFile: ts.SourceFile;
export function getCanonicalFileName(fileName: string): string {
@@ -903,41 +843,32 @@ namespace Harness {
}
export function createCompilerHost(
- inputFiles: { unitName: string; content: string; }[],
+ inputFiles: TestFile[],
writeFile: (fn: string, contents: string, writeByteOrderMark: boolean) => void,
scriptTarget: ts.ScriptTarget,
useCaseSensitiveFileNames: boolean,
// the currentDirectory is needed for rwcRunner to passed in specified current directory to compiler host
- currentDirectory?: string,
+ currentDirectory: string,
newLineKind?: ts.NewLineKind): ts.CompilerHost {
// Local get canonical file name function, that depends on passed in parameter for useCaseSensitiveFileNames
- function getCanonicalFileName(fileName: string): string {
- return useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
- }
+ const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames);
- const filemap: { [fileName: string]: ts.SourceFile; } = {};
- const getCurrentDirectory = currentDirectory === undefined ? Harness.IO.getCurrentDirectory : () => currentDirectory;
-
- // Register input files
- function register(file: { unitName: string; content: string; }) {
+ const fileMap: ts.FileMap = ts.createFileMap();
+ for (const file of inputFiles) {
if (file.content !== undefined) {
const fileName = ts.normalizePath(file.unitName);
const sourceFile = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget);
- filemap[getCanonicalFileName(fileName)] = sourceFile;
- filemap[getCanonicalFileName(ts.getNormalizedAbsolutePath(fileName, getCurrentDirectory()))] = sourceFile;
+ const path = ts.toPath(file.unitName, currentDirectory, getCanonicalFileName);
+ fileMap.set(path, sourceFile);
}
- };
- inputFiles.forEach(register);
+ }
function getSourceFile(fn: string, languageVersion: ts.ScriptTarget) {
fn = ts.normalizePath(fn);
- if (Object.prototype.hasOwnProperty.call(filemap, getCanonicalFileName(fn))) {
- return filemap[getCanonicalFileName(fn)];
- }
- else if (currentDirectory) {
- const canonicalAbsolutePath = getCanonicalFileName(ts.getNormalizedAbsolutePath(fn, currentDirectory));
- return Object.prototype.hasOwnProperty.call(filemap, getCanonicalFileName(canonicalAbsolutePath)) ? filemap[canonicalAbsolutePath] : undefined;
+ const path = ts.toPath(fn, currentDirectory, getCanonicalFileName);
+ if (fileMap.contains(path)) {
+ return fileMap.get(path);
}
else if (fn === fourslashFileName) {
const tsFn = "tests/cases/fourslash/" + fourslashFileName;
@@ -959,7 +890,7 @@ namespace Harness {
Harness.IO.newLine();
return {
- getCurrentDirectory,
+ getCurrentDirectory: () => currentDirectory,
getSourceFile,
getDefaultLibFileName: options => defaultLibFileName,
writeFile,
@@ -1034,177 +965,139 @@ namespace Harness {
}
}
- export class HarnessCompiler {
- private inputFiles: { unitName: string; content: string }[] = [];
- private compileOptions: ts.CompilerOptions;
- private settings: Harness.TestCaseParser.CompilerSettings = {};
+ export interface TestFile {
+ unitName: string;
+ content: string;
+ }
- private lastErrors: ts.Diagnostic[];
+ export interface CompilationOutput {
+ result: CompilerResult;
+ options: ts.CompilerOptions & HarnessOptions;
+ }
- public reset() {
- this.inputFiles = [];
- this.settings = {};
- this.lastErrors = [];
+ export function compileFiles(
+ inputFiles: TestFile[],
+ otherFiles: TestFile[],
+ harnessSettings: TestCaseParser.CompilerSettings,
+ compilerOptions: ts.CompilerOptions,
+ // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
+ currentDirectory: string): CompilationOutput {
+
+ const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.clone(compilerOptions) : { noResolve: false };
+ options.target = options.target || ts.ScriptTarget.ES3;
+ options.module = options.module || ts.ModuleKind.None;
+ options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed;
+ options.noErrorTruncation = true;
+ options.skipDefaultLibCheck = true;
+
+ currentDirectory = currentDirectory || Harness.IO.getCurrentDirectory();
+
+ // Parse settings
+ let useCaseSensitiveFileNames = Harness.IO.useCaseSensitiveFileNames();
+ if (harnessSettings) {
+ setCompilerOptionsFromHarnessSetting(harnessSettings, options);
+ }
+ if (options.useCaseSensitiveFileNames !== undefined) {
+ useCaseSensitiveFileNames = options.useCaseSensitiveFileNames;
}
- public reportCompilationErrors() {
- return this.lastErrors;
+ 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.
+ if (options.includeBuiltFile) {
+ const builtFileName = ts.combinePaths(libFolder, options.includeBuiltFile);
+ const builtFile: TestFile = {
+ unitName: builtFileName,
+ content: normalizeLineEndings(IO.readFile(builtFileName), Harness.IO.newLine()),
+ };
+ programFiles.push(builtFile);
}
- public setCompilerSettings(tcSettings: Harness.TestCaseParser.CompilerSettings) {
- this.settings = tcSettings;
+ const fileOutputs: GeneratedFile[] = [];
+
+ const programFileNames = programFiles.map(file => file.unitName);
+
+ const compilerHost = createCompilerHost(
+ programFiles.concat(otherFiles),
+ (fileName, code, writeByteOrderMark) => fileOutputs.push({ fileName, code, writeByteOrderMark }),
+ options.target,
+ useCaseSensitiveFileNames,
+ currentDirectory,
+ options.newLine);
+ const program = ts.createProgram(programFileNames, options, compilerHost);
+
+ const emitResult = program.emit();
+
+ const errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
+
+ const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps);
+ return { result, options };
+ }
+
+ export function compileDeclarationFiles(inputFiles: TestFile[],
+ otherFiles: TestFile[],
+ result: CompilerResult,
+ harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions,
+ options: ts.CompilerOptions,
+ // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
+ currentDirectory: string) {
+ if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) {
+ throw new Error("There were no errors and declFiles generated did not match number of js files generated");
}
- public addInputFiles(files: { unitName: string; content: string }[]) {
- files.forEach(file => this.addInputFile(file));
+ const declInputFiles: TestFile[] = [];
+ const declOtherFiles: TestFile[] = [];
+
+ // if the .d.ts is non-empty, confirm it compiles correctly as well
+ if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) {
+ ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles));
+ ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));
+ const output = compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory);
+
+ return { declInputFiles, declOtherFiles, declResult: output.result };
}
- public addInputFile(file: { unitName: string; content: string }) {
- this.inputFiles.push(file);
- }
-
- public setCompilerOptions(options?: ts.CompilerOptions) {
- this.compileOptions = options || { noResolve: false };
- }
-
- public emitAll(ioHost?: IEmitterIOHost) {
- this.compileFiles(this.inputFiles,
- /*otherFiles*/ [],
- /*onComplete*/ result => {
- result.files.forEach(writeFile);
- result.declFilesCode.forEach(writeFile);
- result.sourceMaps.forEach(writeFile);
- },
- /*settingsCallback*/ () => { },
- this.compileOptions);
-
- function writeFile(file: GeneratedFile) {
- ioHost.writeFile(file.fileName, file.code, false);
+ function addDtsFile(file: TestFile, dtsFiles: TestFile[]) {
+ if (isDTS(file.unitName)) {
+ dtsFiles.push(file);
}
- }
-
- public compileFiles(inputFiles: { unitName: string; content: string }[],
- otherFiles: { unitName: string; content: string }[],
- onComplete: (result: CompilerResult, program: ts.Program) => void,
- settingsCallback?: (settings: ts.CompilerOptions) => void,
- options?: ts.CompilerOptions & HarnessOptions,
- // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
- currentDirectory?: string) {
-
- options = options || { noResolve: false };
- options.target = options.target || ts.ScriptTarget.ES3;
- options.module = options.module || ts.ModuleKind.None;
- options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed;
- options.noErrorTruncation = true;
- options.skipDefaultLibCheck = true;
-
- if (settingsCallback) {
- settingsCallback(null);
- }
-
- const newLine = "\r\n";
-
- // Parse settings
- setCompilerOptionsFromHarnessSetting(this.settings, options);
-
- // 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.
- const includeBuiltFiles: { unitName: string; content: string }[] = [];
- if (options.includeBuiltFile) {
- const builtFileName = libFolder + options.includeBuiltFile;
- includeBuiltFiles.push({ unitName: builtFileName, content: normalizeLineEndings(IO.readFile(builtFileName), newLine) });
- }
-
- const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : Harness.IO.useCaseSensitiveFileNames();
-
- const fileOutputs: GeneratedFile[] = [];
-
- const programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName);
-
- const compilerHost = createCompilerHost(
- inputFiles.concat(includeBuiltFiles).concat(otherFiles),
- (fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }),
- options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine);
- const program = ts.createProgram(programFiles, options, compilerHost);
-
- const emitResult = program.emit();
-
- const errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
- this.lastErrors = errors;
-
- const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps);
- onComplete(result, program);
-
- return options;
- }
-
- public compileDeclarationFiles(inputFiles: { unitName: string; content: string; }[],
- otherFiles: { unitName: string; content: string; }[],
- result: CompilerResult,
- settingsCallback?: (settings: ts.CompilerOptions) => void,
- options?: ts.CompilerOptions,
- // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
- currentDirectory?: string) {
- if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) {
- throw new Error("There were no errors and declFiles generated did not match number of js files generated");
- }
-
- const declInputFiles: { unitName: string; content: string }[] = [];
- const declOtherFiles: { unitName: string; content: string }[] = [];
- let declResult: Harness.Compiler.CompilerResult;
-
- // if the .d.ts is non-empty, confirm it compiles correctly as well
- if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) {
- ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles));
- ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));
- this.compileFiles(declInputFiles, declOtherFiles, function (compileResult) { declResult = compileResult; },
- settingsCallback, options, currentDirectory);
-
- return { declInputFiles, declOtherFiles, declResult };
- }
-
- function addDtsFile(file: { unitName: string; content: string }, dtsFiles: { unitName: string; content: string }[]) {
- if (isDTS(file.unitName)) {
- dtsFiles.push(file);
- }
- else if (isTS(file.unitName)) {
- const declFile = findResultCodeFile(file.unitName);
- if (declFile && !findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) {
- dtsFiles.push({ unitName: declFile.fileName, content: declFile.code });
- }
- }
-
- function findResultCodeFile(fileName: string) {
- const sourceFile = result.program.getSourceFile(fileName);
- assert(sourceFile, "Program has no source file with name '" + fileName + "'");
- // Is this file going to be emitted separately
- let sourceFileName: string;
- const outFile = options.outFile || options.out;
- if (ts.isExternalModule(sourceFile) || !outFile) {
- if (options.outDir) {
- let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.currentDirectoryForProgram);
- sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), "");
- sourceFileName = ts.combinePaths(options.outDir, sourceFilePath);
- }
- else {
- sourceFileName = sourceFile.fileName;
- }
- }
- else {
- // Goes to single --out file
- sourceFileName = outFile;
- }
-
- const dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts";
-
- return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined);
- }
-
- function findUnit(fileName: string, units: { unitName: string; content: string; }[]) {
- return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined);
+ else if (isTS(file.unitName)) {
+ const declFile = findResultCodeFile(file.unitName);
+ if (declFile && !findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) {
+ dtsFiles.push({ unitName: declFile.fileName, content: declFile.code });
}
}
}
+
+ function findResultCodeFile(fileName: string) {
+ const sourceFile = result.program.getSourceFile(fileName);
+ assert(sourceFile, "Program has no source file with name '" + fileName + "'");
+ // Is this file going to be emitted separately
+ let sourceFileName: string;
+ const outFile = options.outFile || options.out;
+ if (ts.isExternalModule(sourceFile) || !outFile) {
+ if (options.outDir) {
+ let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.currentDirectoryForProgram);
+ sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), "");
+ sourceFileName = ts.combinePaths(options.outDir, sourceFilePath);
+ }
+ else {
+ sourceFileName = sourceFile.fileName;
+ }
+ }
+ else {
+ // Goes to single --out file
+ sourceFileName = outFile;
+ }
+
+ const dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts";
+
+ return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined);
+ }
+
+ function findUnit(fileName: string, units: TestFile[]) {
+ return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined);
+ }
}
function normalizeLineEndings(text: string, lineEnding: string): string {
@@ -1230,7 +1123,7 @@ namespace Harness {
return errorOutput;
}
- export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: ts.Diagnostic[]) {
+ export function getErrorBaseline(inputFiles: TestFile[], diagnostics: ts.Diagnostic[]) {
diagnostics.sort(ts.compareDiagnostics);
const outputLines: string[] = [];
// Count up all errors that were found in files other than lib.d.ts so we don't miss any
@@ -1371,16 +1264,6 @@ namespace Harness {
}
}
- /** The harness' compiler instance used when tests are actually run. Reseting or changing settings of this compiler instance must be done within a test case (i.e., describe/it) */
- let harnessCompiler: HarnessCompiler;
-
- /** Returns the singleton harness compiler instance for generating and running tests.
- If required a fresh compiler instance will be created, otherwise the existing singleton will be re-used.
- */
- export function getCompiler() {
- return harnessCompiler = harnessCompiler || new HarnessCompiler();
- }
-
// This does not need to exist strictly speaking, but many tests will need to be updated if it's removed
export function compileString(code: string, unitName: string, callback: (result: CompilerResult) => void) {
// NEWTODO: Re-implement 'compileString'
@@ -1431,7 +1314,7 @@ namespace Harness {
constructor(fileResults: GeneratedFile[], errors: ts.Diagnostic[], public program: ts.Program,
public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[]) {
- fileResults.forEach(emittedFile => {
+ for (const emittedFile of fileResults) {
if (isDTS(emittedFile.fileName)) {
// .d.ts file, add to declFiles emit
this.declFilesCode.push(emittedFile);
@@ -1446,7 +1329,7 @@ namespace Harness {
else {
throw new Error("Unrecognized file extension for file " + emittedFile.fileName);
}
- });
+ }
this.errors = errors;
}
@@ -1711,12 +1594,9 @@ namespace Harness {
return filePath.indexOf(Harness.libFolder) === 0;
}
- export function getDefaultLibraryFile(io: Harness.IO): { unitName: string, content: string } {
+ export function getDefaultLibraryFile(io: Harness.IO): Harness.Compiler.TestFile {
const libFile = Harness.userSpecifiedRoot + Harness.libFolder + "lib.d.ts";
- return {
- unitName: libFile,
- content: io.readFile(libFile)
- };
+ return { unitName: libFile, content: io.readFile(libFile) };
}
if (Error) (Error).stackTraceLimit = 1;
diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts
index faf0ad28eb..3c7814df56 100644
--- a/src/harness/harnessLanguageService.ts
+++ b/src/harness/harnessLanguageService.ts
@@ -7,7 +7,7 @@ namespace Harness.LanguageService {
export class ScriptInfo {
public version: number = 1;
public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = [];
- public lineMap: number[] = undefined;
+ private lineMap: number[] = undefined;
constructor(public fileName: string, public content: string) {
this.setContent(content);
@@ -15,7 +15,11 @@ namespace Harness.LanguageService {
private setContent(content: string): void {
this.content = content;
- this.lineMap = ts.computeLineStarts(content);
+ this.lineMap = undefined;
+ }
+
+ public getLineMap(): number[] {
+ return this.lineMap || (this.lineMap = ts.computeLineStarts(this.content));
}
public updateContent(content: string): void {
@@ -153,7 +157,7 @@ namespace Harness.LanguageService {
throw new Error("No script with name '" + fileName + "'");
}
- public openFile(fileName: string): void {
+ public openFile(fileName: string, content?: string): void {
}
/**
@@ -164,7 +168,7 @@ namespace Harness.LanguageService {
const script: ScriptInfo = this.fileNameToScript[fileName];
assert.isNotNull(script);
- return ts.computeLineAndCharacterOfPosition(script.lineMap, position);
+ return ts.computeLineAndCharacterOfPosition(script.getLineMap(), position);
}
}
@@ -493,9 +497,9 @@ namespace Harness.LanguageService {
this.client = client;
}
- openFile(fileName: string): void {
- super.openFile(fileName);
- this.client.openFile(fileName);
+ openFile(fileName: string, content?: string): void {
+ super.openFile(fileName, content);
+ this.client.openFile(fileName, content);
}
editScript(fileName: string, start: number, end: number, newText: string) {
diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts
index bf56f1aa3e..0bae91f797 100644
--- a/src/harness/loggedIO.ts
+++ b/src/harness/loggedIO.ts
@@ -174,7 +174,7 @@ namespace Playback {
return true;
}
else {
- return findResultByFields(replayLog.fileExists, { path }, false);
+ return findResultByFields(replayLog.fileExists, { path }, /*defaultValue*/ false);
}
})
);
diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts
index f48822f122..dc6cbfac64 100644
--- a/src/harness/projectsRunner.ts
+++ b/src/harness/projectsRunner.ts
@@ -349,7 +349,7 @@ class ProjectRunner extends RunnerBase {
const inputFiles = ts.map(ts.filter(compilerResult.program.getSourceFiles(),
sourceFile => sourceFile.fileName !== "lib.d.ts"),
sourceFile => {
- return { unitName: RunnerBase.removeFullPaths(sourceFile.fileName), content: sourceFile.text };
+ return { unitName: RunnerBase.removeFullPaths(sourceFile.fileName), content: sourceFile.text, };
});
return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors);
diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts
index a350eda08f..ce570a7d6a 100644
--- a/src/harness/rwcRunner.ts
+++ b/src/harness/rwcRunner.ts
@@ -27,8 +27,8 @@ namespace RWC {
export function runRWCTest(jsonPath: string) {
describe("Testing a RWC project: " + jsonPath, () => {
- let inputFiles: { unitName: string; content: string; }[] = [];
- let otherFiles: { unitName: string; content: string; }[] = [];
+ let inputFiles: Harness.Compiler.TestFile[] = [];
+ let otherFiles: Harness.Compiler.TestFile[] = [];
let compilerResult: Harness.Compiler.CompilerResult;
let compilerOptions: ts.CompilerOptions;
let baselineOpts: Harness.Baseline.BaselineOptions = {
@@ -55,7 +55,6 @@ namespace RWC {
});
it("can compile", () => {
- const harnessCompiler = Harness.Compiler.getCompiler();
let opts: ts.ParsedCommandLine;
const ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath));
@@ -71,8 +70,6 @@ namespace RWC {
});
runWithIOLog(ioLog, oldIO => {
- harnessCompiler.reset();
-
let fileNames = opts.fileNames;
const tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined);
@@ -128,17 +125,21 @@ namespace RWC {
opts.options.noLib = true;
// Emit the results
- compilerOptions = harnessCompiler.compileFiles(
+ compilerOptions = null;
+ const output = Harness.Compiler.compileFiles(
inputFiles,
otherFiles,
- newCompilerResults => { compilerResult = newCompilerResults; },
- /*settingsCallback*/ undefined, opts.options,
+ /* harnessOptions */ undefined,
+ opts.options,
// Since each RWC json file specifies its current directory in its json file, we need
// to pass this information in explicitly instead of acquiring it from the process.
currentDirectory);
+
+ compilerOptions = output.options;
+ compilerResult = output.result;
});
- function getHarnessCompilerInputUnit(fileName: string) {
+ function getHarnessCompilerInputUnit(fileName: string): Harness.Compiler.TestFile {
const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName));
let content: string = null;
try {
@@ -201,8 +202,9 @@ namespace RWC {
it("has the expected errors in generated declaration files", () => {
if (compilerOptions.declaration && !compilerResult.errors.length) {
Harness.Baseline.runBaseline("has the expected errors in generated declaration files", baseName + ".dts.errors.txt", () => {
- const declFileCompilationResult = Harness.Compiler.getCompiler().compileDeclarationFiles(inputFiles, otherFiles, compilerResult,
- /*settingscallback*/ undefined, compilerOptions, currentDirectory);
+ const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(
+ inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory);
+
if (declFileCompilationResult.declResult.errors.length === 0) {
return null;
}
diff --git a/src/harness/sourceMapRecorder.ts b/src/harness/sourceMapRecorder.ts
index ce0a6a6528..75246a9a26 100644
--- a/src/harness/sourceMapRecorder.ts
+++ b/src/harness/sourceMapRecorder.ts
@@ -190,7 +190,7 @@ namespace Harness.SourceMapRecoder {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
- createErrorIfCondition(true, "No encoded entry found");
+ createErrorIfCondition(/*condition*/ true, "No encoded entry found");
}
export function hasCompletedDecoding() {
diff --git a/src/harness/test262Runner.ts b/src/harness/test262Runner.ts
index f25e0c79b6..262145b476 100644
--- a/src/harness/test262Runner.ts
+++ b/src/harness/test262Runner.ts
@@ -5,9 +5,9 @@
class Test262BaselineRunner extends RunnerBase {
private static basePath = "internal/cases/test262";
private static helpersFilePath = "tests/cases/test262-harness/helpers.d.ts";
- private static helperFile = {
+ private static helperFile: Harness.Compiler.TestFile = {
unitName: Test262BaselineRunner.helpersFilePath,
- content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath)
+ content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath),
};
private static testFileExtensionRegex = /\.js$/;
private static options: ts.CompilerOptions = {
@@ -31,8 +31,7 @@ class Test262BaselineRunner extends RunnerBase {
let testState: {
filename: string;
compilerResult: Harness.Compiler.CompilerResult;
- inputFiles: { unitName: string; content: string }[];
- program: ts.Program;
+ inputFiles: Harness.Compiler.TestFile[];
};
before(() => {
@@ -40,8 +39,9 @@ class Test262BaselineRunner extends RunnerBase {
const testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test";
const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename);
- const inputFiles = testCaseContent.testUnitData.map(unit => {
- return { unitName: Test262BaselineRunner.getTestFilePath(unit.name), content: unit.content };
+ const inputFiles: Harness.Compiler.TestFile[] = testCaseContent.testUnitData.map(unit => {
+ const unitName = Test262BaselineRunner.getTestFilePath(unit.name);
+ return { unitName, content: unit.content };
});
// Emit the results
@@ -49,13 +49,16 @@ class Test262BaselineRunner extends RunnerBase {
filename: testFilename,
inputFiles: inputFiles,
compilerResult: undefined,
- program: undefined,
};
- Harness.Compiler.getCompiler().compileFiles([Test262BaselineRunner.helperFile].concat(inputFiles), /*otherFiles*/ [], (compilerResult, program) => {
- testState.compilerResult = compilerResult;
- testState.program = program;
- }, /*settingsCallback*/ undefined, Test262BaselineRunner.options);
+ const output = Harness.Compiler.compileFiles(
+ [Test262BaselineRunner.helperFile].concat(inputFiles),
+ /*otherFiles*/ [],
+ /* harnessOptions */ undefined,
+ Test262BaselineRunner.options,
+ /* currentDirectory */ undefined
+ );
+ testState.compilerResult = output.result;
});
after(() => {
@@ -80,14 +83,14 @@ class Test262BaselineRunner extends RunnerBase {
}, false, Test262BaselineRunner.baselineOptions);
});
- it("satisfies inletiants", () => {
- const sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
+ it("satisfies invariants", () => {
+ const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
Utils.assertInvariants(sourceFile, /*parent:*/ undefined);
});
it("has the expected AST", () => {
Harness.Baseline.runBaseline("has the expected AST", testState.filename + ".AST.txt", () => {
- const sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
+ const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
return Utils.sourceFileToJSON(sourceFile);
}, false, Test262BaselineRunner.baselineOptions);
});
diff --git a/src/server/client.ts b/src/server/client.ts
index ae234750d8..08939b2b44 100644
--- a/src/server/client.ts
+++ b/src/server/client.ts
@@ -120,8 +120,8 @@ namespace ts.server {
return response;
}
- openFile(fileName: string): void {
- var args: protocol.FileRequestArgs = { file: fileName };
+ openFile(fileName: string, content?: string): void {
+ var args: protocol.OpenRequestArgs = { file: fileName, fileContent: content };
this.processRequest(CommandNames.Open, args);
}
diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts
index 333cea2745..c3cd65e857 100644
--- a/src/server/editorServices.ts
+++ b/src/server/editorServices.ts
@@ -388,7 +388,7 @@ namespace ts.server {
}
openReferencedFile(filename: string) {
- return this.projectService.openFile(filename, false);
+ return this.projectService.openFile(filename, /*openedByClient*/ false);
}
getRootFiles() {
@@ -1006,14 +1006,15 @@ namespace ts.server {
/**
* @param filename is absolute pathname
+ * @param fileContent is a known version of the file content that is more up to date than the one on disk
*/
- openFile(fileName: string, openedByClient: boolean) {
+ openFile(fileName: string, openedByClient: boolean, fileContent?: string) {
fileName = ts.normalizePath(fileName);
let info = ts.lookUp(this.filenameToScriptInfo, fileName);
if (!info) {
let content: string;
if (this.host.fileExists(fileName)) {
- content = this.host.readFile(fileName);
+ content = fileContent || this.host.readFile(fileName);
}
if (!content) {
if (openedByClient) {
@@ -1030,6 +1031,9 @@ namespace ts.server {
}
}
if (info) {
+ if (fileContent) {
+ info.svc.reload(fileContent);
+ }
if (openedByClient) {
info.isOpen = true;
}
@@ -1060,10 +1064,11 @@ namespace ts.server {
/**
* Open file whose contents is managed by the client
* @param filename is absolute pathname
+ * @param fileContent is a known version of the file content that is more up to date than the one on disk
*/
- openClientFile(fileName: string) {
+ openClientFile(fileName: string, fileContent?: string) {
this.openOrUpdateConfiguredProjectForFile(fileName);
- const info = this.openFile(fileName, true);
+ const info = this.openFile(fileName, /*openedByClient*/ true, fileContent);
this.addOpenFile(info);
this.printProjects();
return info;
@@ -1272,7 +1277,7 @@ namespace ts.server {
for (const fileName of fileNamesToAdd) {
let info = this.getScriptInfo(fileName);
if (!info) {
- info = this.openFile(fileName, false);
+ info = this.openFile(fileName, /*openedByClient*/ false);
}
else {
// if the root file was opened by client, it would belong to either
diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts
index ad1fc5e92d..3a66975332 100644
--- a/src/server/protocol.d.ts
+++ b/src/server/protocol.d.ts
@@ -513,6 +513,11 @@ declare namespace ts.server.protocol {
* Information found in an "open" request.
*/
export interface OpenRequestArgs extends FileRequestArgs {
+ /**
+ * Used when a version of the file content is known to be more up to date than the one on disk.
+ * Then the known content will be used upon opening instead of the disk copy
+ */
+ fileContent?: string;
}
/**
diff --git a/src/server/session.ts b/src/server/session.ts
index 770256cc9f..dae2384ce5 100644
--- a/src/server/session.ts
+++ b/src/server/session.ts
@@ -532,9 +532,13 @@ namespace ts.server {
};
}
- private openClientFile(fileName: string) {
+ /**
+ * @param fileName is the name of the file to be opened
+ * @param fileContent is a version of the file content that is known to be more up to date than the one on disk
+ */
+ private openClientFile(fileName: string, fileContent?: string) {
const file = ts.normalizePath(fileName);
- this.projectService.openClientFile(file);
+ this.projectService.openClientFile(file, fileContent);
}
private getQuickInfo(line: number, offset: number, fileName: string): protocol.QuickInfoResponseBody {
@@ -897,7 +901,7 @@ namespace ts.server {
}
getDiagnosticsForProject(delay: number, fileName: string) {
- const { configFileName, fileNames } = this.getProjectInfo(fileName, true);
+ const { configFileName, fileNames } = this.getProjectInfo(fileName, /*needFileNameList*/ true);
// No need to analyze lib.d.ts
let fileNamesInProject = fileNames.filter((value, index, array) => value.indexOf("lib.d.ts") < 0);
@@ -968,7 +972,7 @@ namespace ts.server {
},
[CommandNames.Open]: (request: protocol.Request) => {
const openArgs = request.arguments;
- this.openClientFile(openArgs.file);
+ this.openClientFile(openArgs.file, openArgs.fileContent);
return {responseRequired: false};
},
[CommandNames.Quickinfo]: (request: protocol.Request) => {
diff --git a/tests/baselines/reference/ambientClassDeclarationWithExtends.js b/tests/baselines/reference/ambientClassDeclarationWithExtends.js
index 5fd4d5b4b2..940efb8899 100644
--- a/tests/baselines/reference/ambientClassDeclarationWithExtends.js
+++ b/tests/baselines/reference/ambientClassDeclarationWithExtends.js
@@ -1,6 +1,40 @@
-//// [ambientClassDeclarationWithExtends.ts]
+//// [tests/cases/compiler/ambientClassDeclarationWithExtends.ts] ////
+
+//// [ambientClassDeclarationExtends_singleFile.ts]
declare class A { }
declare class B extends A { }
+
+declare class C {
+ public foo;
+}
+namespace D { var x; }
+declare class D extends C { }
+
+var d: C = new D();
+
+//// [ambientClassDeclarationExtends_file1.ts]
+
+declare class E {
+ public bar;
+}
+namespace F { var y; }
+
+//// [ambientClassDeclarationExtends_file2.ts]
+
+declare class F extends E { }
+var f: E = new F();
-//// [ambientClassDeclarationWithExtends.js]
+//// [ambientClassDeclarationExtends_singleFile.js]
+var D;
+(function (D) {
+ var x;
+})(D || (D = {}));
+var d = new D();
+//// [ambientClassDeclarationExtends_file1.js]
+var F;
+(function (F) {
+ var y;
+})(F || (F = {}));
+//// [ambientClassDeclarationExtends_file2.js]
+var f = new F();
diff --git a/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols b/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols
index 71d1e1a66d..023ae6bf58 100644
--- a/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols
+++ b/tests/baselines/reference/ambientClassDeclarationWithExtends.symbols
@@ -1,8 +1,50 @@
-=== tests/cases/compiler/ambientClassDeclarationWithExtends.ts ===
+=== tests/cases/compiler/ambientClassDeclarationExtends_singleFile.ts ===
declare class A { }
->A : Symbol(A, Decl(ambientClassDeclarationWithExtends.ts, 0, 0))
+>A : Symbol(A, Decl(ambientClassDeclarationExtends_singleFile.ts, 0, 0))
declare class B extends A { }
->B : Symbol(B, Decl(ambientClassDeclarationWithExtends.ts, 0, 19))
->A : Symbol(A, Decl(ambientClassDeclarationWithExtends.ts, 0, 0))
+>B : Symbol(B, Decl(ambientClassDeclarationExtends_singleFile.ts, 0, 19))
+>A : Symbol(A, Decl(ambientClassDeclarationExtends_singleFile.ts, 0, 0))
+
+declare class C {
+>C : Symbol(C, Decl(ambientClassDeclarationExtends_singleFile.ts, 1, 29))
+
+ public foo;
+>foo : Symbol(foo, Decl(ambientClassDeclarationExtends_singleFile.ts, 3, 17))
+}
+namespace D { var x; }
+>D : Symbol(D, Decl(ambientClassDeclarationExtends_singleFile.ts, 5, 1), Decl(ambientClassDeclarationExtends_singleFile.ts, 6, 22))
+>x : Symbol(x, Decl(ambientClassDeclarationExtends_singleFile.ts, 6, 17))
+
+declare class D extends C { }
+>D : Symbol(D, Decl(ambientClassDeclarationExtends_singleFile.ts, 5, 1), Decl(ambientClassDeclarationExtends_singleFile.ts, 6, 22))
+>C : Symbol(C, Decl(ambientClassDeclarationExtends_singleFile.ts, 1, 29))
+
+var d: C = new D();
+>d : Symbol(d, Decl(ambientClassDeclarationExtends_singleFile.ts, 9, 3))
+>C : Symbol(C, Decl(ambientClassDeclarationExtends_singleFile.ts, 1, 29))
+>D : Symbol(D, Decl(ambientClassDeclarationExtends_singleFile.ts, 5, 1), Decl(ambientClassDeclarationExtends_singleFile.ts, 6, 22))
+
+=== tests/cases/compiler/ambientClassDeclarationExtends_file1.ts ===
+
+declare class E {
+>E : Symbol(E, Decl(ambientClassDeclarationExtends_file1.ts, 0, 0))
+
+ public bar;
+>bar : Symbol(bar, Decl(ambientClassDeclarationExtends_file1.ts, 1, 17))
+}
+namespace F { var y; }
+>F : Symbol(F, Decl(ambientClassDeclarationExtends_file1.ts, 3, 1), Decl(ambientClassDeclarationExtends_file2.ts, 0, 0))
+>y : Symbol(y, Decl(ambientClassDeclarationExtends_file1.ts, 4, 17))
+
+=== tests/cases/compiler/ambientClassDeclarationExtends_file2.ts ===
+
+declare class F extends E { }
+>F : Symbol(F, Decl(ambientClassDeclarationExtends_file1.ts, 3, 1), Decl(ambientClassDeclarationExtends_file2.ts, 0, 0))
+>E : Symbol(E, Decl(ambientClassDeclarationExtends_file1.ts, 0, 0))
+
+var f: E = new F();
+>f : Symbol(f, Decl(ambientClassDeclarationExtends_file2.ts, 2, 3))
+>E : Symbol(E, Decl(ambientClassDeclarationExtends_file1.ts, 0, 0))
+>F : Symbol(F, Decl(ambientClassDeclarationExtends_file1.ts, 3, 1), Decl(ambientClassDeclarationExtends_file2.ts, 0, 0))
diff --git a/tests/baselines/reference/ambientClassDeclarationWithExtends.types b/tests/baselines/reference/ambientClassDeclarationWithExtends.types
index 7609856882..c7f22eeb65 100644
--- a/tests/baselines/reference/ambientClassDeclarationWithExtends.types
+++ b/tests/baselines/reference/ambientClassDeclarationWithExtends.types
@@ -1,4 +1,4 @@
-=== tests/cases/compiler/ambientClassDeclarationWithExtends.ts ===
+=== tests/cases/compiler/ambientClassDeclarationExtends_singleFile.ts ===
declare class A { }
>A : A
@@ -6,3 +6,47 @@ declare class B extends A { }
>B : B
>A : A
+declare class C {
+>C : C
+
+ public foo;
+>foo : any
+}
+namespace D { var x; }
+>D : typeof D
+>x : any
+
+declare class D extends C { }
+>D : D
+>C : C
+
+var d: C = new D();
+>d : C
+>C : C
+>new D() : D
+>D : typeof D
+
+=== tests/cases/compiler/ambientClassDeclarationExtends_file1.ts ===
+
+declare class E {
+>E : E
+
+ public bar;
+>bar : any
+}
+namespace F { var y; }
+>F : typeof F
+>y : any
+
+=== tests/cases/compiler/ambientClassDeclarationExtends_file2.ts ===
+
+declare class F extends E { }
+>F : F
+>E : E
+
+var f: E = new F();
+>f : E
+>E : E
+>new F() : F
+>F : typeof F
+
diff --git a/tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt
new file mode 100644
index 0000000000..d52b17a58a
--- /dev/null
+++ b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt
@@ -0,0 +1,27 @@
+tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts(4,5): error TS2387: Function overload must be static.
+tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts(12,12): error TS2388: Function overload must not be static.
+tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts(13,5): error TS2387: Function overload must be static.
+
+
+==== tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts (3 errors) ====
+ class A {
+ f() {}
+ static m1 (a: string): void;
+ m1 (a: number): void;
+ ~~
+!!! error TS2387: Function overload must be static.
+ m1 (a: any): void {
+ }
+ }
+
+ class B {
+ f() {}
+ m1 (a: string): void;
+ static m1 (a: number): void;
+ ~~
+!!! error TS2388: Function overload must not be static.
+ m1 (a: any): void {
+ ~~
+!!! error TS2387: Function overload must be static.
+ }
+ }
\ No newline at end of file
diff --git a/tests/baselines/reference/mixedStaticAndInstanceClassMembers.js b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.js
new file mode 100644
index 0000000000..427bbf65aa
--- /dev/null
+++ b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.js
@@ -0,0 +1,34 @@
+//// [mixedStaticAndInstanceClassMembers.ts]
+class A {
+ f() {}
+ static m1 (a: string): void;
+ m1 (a: number): void;
+ m1 (a: any): void {
+ }
+}
+
+class B {
+ f() {}
+ m1 (a: string): void;
+ static m1 (a: number): void;
+ m1 (a: any): void {
+ }
+}
+
+//// [mixedStaticAndInstanceClassMembers.js]
+var A = (function () {
+ function A() {
+ }
+ A.prototype.f = function () { };
+ A.prototype.m1 = function (a) {
+ };
+ return A;
+})();
+var B = (function () {
+ function B() {
+ }
+ B.prototype.f = function () { };
+ B.prototype.m1 = function (a) {
+ };
+ return B;
+})();
diff --git a/tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt
new file mode 100644
index 0000000000..252cd6880d
--- /dev/null
+++ b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt
@@ -0,0 +1,23 @@
+tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(2,5): error TS2300: Duplicate identifier 'm1'.
+tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(4,5): error TS2300: Duplicate identifier 'm1'.
+tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(5,5): error TS2300: Duplicate identifier 'm1'.
+tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(6,5): error TS2300: Duplicate identifier 'm1'.
+
+
+==== tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts (4 errors) ====
+ class A {
+ m1: string;
+ ~~
+!!! error TS2300: Duplicate identifier 'm1'.
+ f() {}
+ m1 (a: string): void;
+ ~~
+!!! error TS2300: Duplicate identifier 'm1'.
+ m1 (a: number): void;
+ ~~
+!!! error TS2300: Duplicate identifier 'm1'.
+ m1 (a: any): void {
+ ~~
+!!! error TS2300: Duplicate identifier 'm1'.
+ }
+ }
\ No newline at end of file
diff --git a/tests/baselines/reference/nonMergedDeclarationsAndOverloads.js b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.js
new file mode 100644
index 0000000000..3ca6a96351
--- /dev/null
+++ b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.js
@@ -0,0 +1,19 @@
+//// [nonMergedDeclarationsAndOverloads.ts]
+class A {
+ m1: string;
+ f() {}
+ m1 (a: string): void;
+ m1 (a: number): void;
+ m1 (a: any): void {
+ }
+}
+
+//// [nonMergedDeclarationsAndOverloads.js]
+var A = (function () {
+ function A() {
+ }
+ A.prototype.f = function () { };
+ A.prototype.m1 = function (a) {
+ };
+ return A;
+})();
diff --git a/tests/baselines/reference/nonMergedOverloads.errors.txt b/tests/baselines/reference/nonMergedOverloads.errors.txt
new file mode 100644
index 0000000000..9a38ebdc3b
--- /dev/null
+++ b/tests/baselines/reference/nonMergedOverloads.errors.txt
@@ -0,0 +1,20 @@
+tests/cases/compiler/nonMergedOverloads.ts(1,5): error TS2300: Duplicate identifier 'f'.
+tests/cases/compiler/nonMergedOverloads.ts(3,17): error TS1148: Cannot compile modules unless the '--module' flag is provided.
+tests/cases/compiler/nonMergedOverloads.ts(3,17): error TS2300: Duplicate identifier 'f'.
+tests/cases/compiler/nonMergedOverloads.ts(4,17): error TS2300: Duplicate identifier 'f'.
+
+
+==== tests/cases/compiler/nonMergedOverloads.ts (4 errors) ====
+ var f = 10;
+ ~
+!!! error TS2300: Duplicate identifier 'f'.
+
+ export function f();
+ ~
+!!! error TS1148: Cannot compile modules unless the '--module' flag is provided.
+ ~
+!!! error TS2300: Duplicate identifier 'f'.
+ export function f() {
+ ~
+!!! error TS2300: Duplicate identifier 'f'.
+ }
\ No newline at end of file
diff --git a/tests/baselines/reference/nonMergedOverloads.js b/tests/baselines/reference/nonMergedOverloads.js
new file mode 100644
index 0000000000..2e7f7f67ee
--- /dev/null
+++ b/tests/baselines/reference/nonMergedOverloads.js
@@ -0,0 +1,12 @@
+//// [nonMergedOverloads.ts]
+var f = 10;
+
+export function f();
+export function f() {
+}
+
+//// [nonMergedOverloads.js]
+var f = 10;
+function f() {
+}
+exports.f = f;
diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js
new file mode 100644
index 0000000000..ec6b5682ed
--- /dev/null
+++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js
@@ -0,0 +1,10 @@
+//// [sourceMapValidationLambdaSpanningMultipleLines.ts]
+((item: string) =>
+ item
+)
+
+//// [sourceMapValidationLambdaSpanningMultipleLines.js]
+(function (item) {
+ return item;
+});
+//# sourceMappingURL=sourceMapValidationLambdaSpanningMultipleLines.js.map
\ No newline at end of file
diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map
new file mode 100644
index 0000000000..c0151106e7
--- /dev/null
+++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.js.map
@@ -0,0 +1,2 @@
+//// [sourceMapValidationLambdaSpanningMultipleLines.js.map]
+{"version":3,"file":"sourceMapValidationLambdaSpanningMultipleLines.js","sourceRoot":"","sources":["sourceMapValidationLambdaSpanningMultipleLines.ts"],"names":[],"mappings":"AAAA,CAAC,UAAC,IAAY;IACV,OAAA,IAAI;AAAJ,CAAI,CACP,CAAA"}
\ No newline at end of file
diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt
new file mode 100644
index 0000000000..475aa1debe
--- /dev/null
+++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.sourcemap.txt
@@ -0,0 +1,54 @@
+===================================================================
+JsFile: sourceMapValidationLambdaSpanningMultipleLines.js
+mapUrl: sourceMapValidationLambdaSpanningMultipleLines.js.map
+sourceRoot:
+sources: sourceMapValidationLambdaSpanningMultipleLines.ts
+===================================================================
+-------------------------------------------------------------------
+emittedFile:tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.js
+sourceFile:sourceMapValidationLambdaSpanningMultipleLines.ts
+-------------------------------------------------------------------
+>>>(function (item) {
+1 >
+2 >^
+3 > ^^^^^^^^^^
+4 > ^^^^
+5 > ^^->
+1 >
+2 >(
+3 > (
+4 > item: string
+1 >Emitted(1, 1) Source(1, 1) + SourceIndex(0)
+2 >Emitted(1, 2) Source(1, 2) + SourceIndex(0)
+3 >Emitted(1, 12) Source(1, 3) + SourceIndex(0)
+4 >Emitted(1, 16) Source(1, 15) + SourceIndex(0)
+---
+>>> return item;
+1->^^^^
+2 > ^^^^^^^
+3 > ^^^^
+1->) =>
+ >
+2 >
+3 > item
+1->Emitted(2, 5) Source(2, 5) + SourceIndex(0)
+2 >Emitted(2, 12) Source(2, 5) + SourceIndex(0)
+3 >Emitted(2, 16) Source(2, 9) + SourceIndex(0)
+---
+>>>});
+1 >
+2 >^
+3 > ^
+4 > ^
+5 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
+1 >
+2 >item
+3 >
+ > )
+4 >
+1 >Emitted(3, 1) Source(2, 5) + SourceIndex(0)
+2 >Emitted(3, 2) Source(2, 9) + SourceIndex(0)
+3 >Emitted(3, 3) Source(3, 2) + SourceIndex(0)
+4 >Emitted(3, 4) Source(3, 2) + SourceIndex(0)
+---
+>>>//# sourceMappingURL=sourceMapValidationLambdaSpanningMultipleLines.js.map
\ No newline at end of file
diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.symbols b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.symbols
new file mode 100644
index 0000000000..c7ff4ca9d9
--- /dev/null
+++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.symbols
@@ -0,0 +1,8 @@
+=== tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts ===
+((item: string) =>
+>item : Symbol(item, Decl(sourceMapValidationLambdaSpanningMultipleLines.ts, 0, 2))
+
+ item
+>item : Symbol(item, Decl(sourceMapValidationLambdaSpanningMultipleLines.ts, 0, 2))
+
+)
diff --git a/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.types b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.types
new file mode 100644
index 0000000000..d39119cbd9
--- /dev/null
+++ b/tests/baselines/reference/sourceMapValidationLambdaSpanningMultipleLines.types
@@ -0,0 +1,10 @@
+=== tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts ===
+((item: string) =>
+>((item: string) => item) : (item: string) => string
+>(item: string) => item : (item: string) => string
+>item : string
+
+ item
+>item : string
+
+)
diff --git a/tests/baselines/reference/typeGuardTypeOfUndefined.js b/tests/baselines/reference/typeGuardTypeOfUndefined.js
new file mode 100644
index 0000000000..a24ff2ec0d
--- /dev/null
+++ b/tests/baselines/reference/typeGuardTypeOfUndefined.js
@@ -0,0 +1,357 @@
+//// [typeGuardTypeOfUndefined.ts]
+// undefined type guard adds no new type information
+function test1(a: any) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test2(a: any) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test3(a: any) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test4(a: any) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test5(a: boolean | void) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test6(a: boolean | void) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test7(a: boolean | void) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test8(a: boolean | void) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test9(a: boolean | number) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test10(a: boolean | number) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test11(a: boolean | number) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test12(a: boolean | number) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test13(a: boolean | number | void) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test14(a: boolean | number | void) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test15(a: boolean | number | void) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test16(a: boolean | number | void) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+
+//// [typeGuardTypeOfUndefined.js]
+// undefined type guard adds no new type information
+function test1(a) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+function test2(a) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+function test3(a) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+function test4(a) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+function test5(a) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+function test6(a) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+function test7(a) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+function test8(a) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+function test9(a) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+function test10(a) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+function test11(a) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+function test12(a) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+function test13(a) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+function test14(a) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+function test15(a) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+function test16(a) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
diff --git a/tests/baselines/reference/typeGuardTypeOfUndefined.symbols b/tests/baselines/reference/typeGuardTypeOfUndefined.symbols
new file mode 100644
index 0000000000..d6d36223fe
--- /dev/null
+++ b/tests/baselines/reference/typeGuardTypeOfUndefined.symbols
@@ -0,0 +1,330 @@
+=== tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts ===
+// undefined type guard adds no new type information
+function test1(a: any) {
+>test1 : Symbol(test1, Decl(typeGuardTypeOfUndefined.ts, 0, 0))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15))
+
+ if (typeof a !== "undefined") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15))
+
+ if (typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15))
+ }
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 1, 15))
+ }
+}
+
+function test2(a: any) {
+>test2 : Symbol(test2, Decl(typeGuardTypeOfUndefined.ts, 13, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15))
+
+ if (typeof a === "undefined") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15))
+
+ if (typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15))
+ }
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 15, 15))
+ }
+}
+
+function test3(a: any) {
+>test3 : Symbol(test3, Decl(typeGuardTypeOfUndefined.ts, 27, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 29, 15))
+
+ if (typeof a === "undefined" || typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 29, 15))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 29, 15))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 29, 15))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 29, 15))
+ }
+}
+
+function test4(a: any) {
+>test4 : Symbol(test4, Decl(typeGuardTypeOfUndefined.ts, 36, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 38, 15))
+
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 38, 15))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 38, 15))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 38, 15))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 38, 15))
+ }
+}
+
+function test5(a: boolean | void) {
+>test5 : Symbol(test5, Decl(typeGuardTypeOfUndefined.ts, 45, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15))
+
+ if (typeof a !== "undefined") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15))
+
+ if (typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15))
+ }
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 47, 15))
+ }
+}
+
+function test6(a: boolean | void) {
+>test6 : Symbol(test6, Decl(typeGuardTypeOfUndefined.ts, 59, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15))
+
+ if (typeof a === "undefined") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15))
+
+ if (typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15))
+ }
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 61, 15))
+ }
+}
+
+function test7(a: boolean | void) {
+>test7 : Symbol(test7, Decl(typeGuardTypeOfUndefined.ts, 73, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 75, 15))
+
+ if (typeof a === "undefined" || typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 75, 15))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 75, 15))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 75, 15))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 75, 15))
+ }
+}
+
+function test8(a: boolean | void) {
+>test8 : Symbol(test8, Decl(typeGuardTypeOfUndefined.ts, 82, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 84, 15))
+
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 84, 15))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 84, 15))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 84, 15))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 84, 15))
+ }
+}
+
+function test9(a: boolean | number) {
+>test9 : Symbol(test9, Decl(typeGuardTypeOfUndefined.ts, 91, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15))
+
+ if (typeof a !== "undefined") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15))
+
+ if (typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15))
+ }
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 93, 15))
+ }
+}
+
+function test10(a: boolean | number) {
+>test10 : Symbol(test10, Decl(typeGuardTypeOfUndefined.ts, 105, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16))
+
+ if (typeof a === "undefined") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16))
+
+ if (typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16))
+ }
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 107, 16))
+ }
+}
+
+function test11(a: boolean | number) {
+>test11 : Symbol(test11, Decl(typeGuardTypeOfUndefined.ts, 119, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 121, 16))
+
+ if (typeof a === "undefined" || typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 121, 16))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 121, 16))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 121, 16))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 121, 16))
+ }
+}
+
+function test12(a: boolean | number) {
+>test12 : Symbol(test12, Decl(typeGuardTypeOfUndefined.ts, 128, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 130, 16))
+
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 130, 16))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 130, 16))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 130, 16))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 130, 16))
+ }
+}
+
+function test13(a: boolean | number | void) {
+>test13 : Symbol(test13, Decl(typeGuardTypeOfUndefined.ts, 137, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16))
+
+ if (typeof a !== "undefined") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16))
+
+ if (typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16))
+ }
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 139, 16))
+ }
+}
+
+function test14(a: boolean | number | void) {
+>test14 : Symbol(test14, Decl(typeGuardTypeOfUndefined.ts, 151, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16))
+
+ if (typeof a === "undefined") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16))
+
+ if (typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16))
+ }
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 153, 16))
+ }
+}
+
+function test15(a: boolean | number | void) {
+>test15 : Symbol(test15, Decl(typeGuardTypeOfUndefined.ts, 165, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 167, 16))
+
+ if (typeof a === "undefined" || typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 167, 16))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 167, 16))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 167, 16))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 167, 16))
+ }
+}
+
+function test16(a: boolean | number | void) {
+>test16 : Symbol(test16, Decl(typeGuardTypeOfUndefined.ts, 174, 1))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 176, 16))
+
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 176, 16))
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 176, 16))
+
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 176, 16))
+ }
+ else {
+ a;
+>a : Symbol(a, Decl(typeGuardTypeOfUndefined.ts, 176, 16))
+ }
+}
+
diff --git a/tests/baselines/reference/typeGuardTypeOfUndefined.types b/tests/baselines/reference/typeGuardTypeOfUndefined.types
new file mode 100644
index 0000000000..6cf57e1a1d
--- /dev/null
+++ b/tests/baselines/reference/typeGuardTypeOfUndefined.types
@@ -0,0 +1,434 @@
+=== tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts ===
+// undefined type guard adds no new type information
+function test1(a: any) {
+>test1 : (a: any) => void
+>a : any
+
+ if (typeof a !== "undefined") {
+>typeof a !== "undefined" : boolean
+>typeof a : string
+>a : any
+>"undefined" : string
+
+ if (typeof a === "boolean") {
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : any
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : any
+ }
+ }
+ else {
+ a;
+>a : any
+ }
+}
+
+function test2(a: any) {
+>test2 : (a: any) => void
+>a : any
+
+ if (typeof a === "undefined") {
+>typeof a === "undefined" : boolean
+>typeof a : string
+>a : any
+>"undefined" : string
+
+ if (typeof a === "boolean") {
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : any
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : any
+ }
+ }
+ else {
+ a;
+>a : any
+ }
+}
+
+function test3(a: any) {
+>test3 : (a: any) => void
+>a : any
+
+ if (typeof a === "undefined" || typeof a === "boolean") {
+>typeof a === "undefined" || typeof a === "boolean" : boolean
+>typeof a === "undefined" : boolean
+>typeof a : string
+>a : any
+>"undefined" : string
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : any
+>"boolean" : string
+
+ a;
+>a : any
+ }
+ else {
+ a;
+>a : any
+ }
+}
+
+function test4(a: any) {
+>test4 : (a: any) => void
+>a : any
+
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+>typeof a !== "undefined" && typeof a === "boolean" : boolean
+>typeof a !== "undefined" : boolean
+>typeof a : string
+>a : any
+>"undefined" : string
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : any
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : any
+ }
+}
+
+function test5(a: boolean | void) {
+>test5 : (a: boolean | void) => void
+>a : boolean | void
+
+ if (typeof a !== "undefined") {
+>typeof a !== "undefined" : boolean
+>typeof a : string
+>a : boolean | void
+>"undefined" : string
+
+ if (typeof a === "boolean") {
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | void
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : void
+ }
+ }
+ else {
+ a;
+>a : boolean | void
+ }
+}
+
+function test6(a: boolean | void) {
+>test6 : (a: boolean | void) => void
+>a : boolean | void
+
+ if (typeof a === "undefined") {
+>typeof a === "undefined" : boolean
+>typeof a : string
+>a : boolean | void
+>"undefined" : string
+
+ if (typeof a === "boolean") {
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | void
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : void
+ }
+ }
+ else {
+ a;
+>a : boolean | void
+ }
+}
+
+function test7(a: boolean | void) {
+>test7 : (a: boolean | void) => void
+>a : boolean | void
+
+ if (typeof a === "undefined" || typeof a === "boolean") {
+>typeof a === "undefined" || typeof a === "boolean" : boolean
+>typeof a === "undefined" : boolean
+>typeof a : string
+>a : boolean | void
+>"undefined" : string
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | void
+>"boolean" : string
+
+ a;
+>a : boolean | void
+ }
+ else {
+ a;
+>a : void
+ }
+}
+
+function test8(a: boolean | void) {
+>test8 : (a: boolean | void) => void
+>a : boolean | void
+
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+>typeof a !== "undefined" && typeof a === "boolean" : boolean
+>typeof a !== "undefined" : boolean
+>typeof a : string
+>a : boolean | void
+>"undefined" : string
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | void
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : boolean | void
+ }
+}
+
+function test9(a: boolean | number) {
+>test9 : (a: boolean | number) => void
+>a : boolean | number
+
+ if (typeof a !== "undefined") {
+>typeof a !== "undefined" : boolean
+>typeof a : string
+>a : boolean | number
+>"undefined" : string
+
+ if (typeof a === "boolean") {
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | number
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : number
+ }
+ }
+ else {
+ a;
+>a : boolean | number
+ }
+}
+
+function test10(a: boolean | number) {
+>test10 : (a: boolean | number) => void
+>a : boolean | number
+
+ if (typeof a === "undefined") {
+>typeof a === "undefined" : boolean
+>typeof a : string
+>a : boolean | number
+>"undefined" : string
+
+ if (typeof a === "boolean") {
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | number
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : number
+ }
+ }
+ else {
+ a;
+>a : boolean | number
+ }
+}
+
+function test11(a: boolean | number) {
+>test11 : (a: boolean | number) => void
+>a : boolean | number
+
+ if (typeof a === "undefined" || typeof a === "boolean") {
+>typeof a === "undefined" || typeof a === "boolean" : boolean
+>typeof a === "undefined" : boolean
+>typeof a : string
+>a : boolean | number
+>"undefined" : string
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | number
+>"boolean" : string
+
+ a;
+>a : boolean | number
+ }
+ else {
+ a;
+>a : number
+ }
+}
+
+function test12(a: boolean | number) {
+>test12 : (a: boolean | number) => void
+>a : boolean | number
+
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+>typeof a !== "undefined" && typeof a === "boolean" : boolean
+>typeof a !== "undefined" : boolean
+>typeof a : string
+>a : boolean | number
+>"undefined" : string
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | number
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : boolean | number
+ }
+}
+
+function test13(a: boolean | number | void) {
+>test13 : (a: boolean | number | void) => void
+>a : boolean | number | void
+
+ if (typeof a !== "undefined") {
+>typeof a !== "undefined" : boolean
+>typeof a : string
+>a : boolean | number | void
+>"undefined" : string
+
+ if (typeof a === "boolean") {
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | number | void
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : number | void
+ }
+ }
+ else {
+ a;
+>a : boolean | number | void
+ }
+}
+
+function test14(a: boolean | number | void) {
+>test14 : (a: boolean | number | void) => void
+>a : boolean | number | void
+
+ if (typeof a === "undefined") {
+>typeof a === "undefined" : boolean
+>typeof a : string
+>a : boolean | number | void
+>"undefined" : string
+
+ if (typeof a === "boolean") {
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | number | void
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : number | void
+ }
+ }
+ else {
+ a;
+>a : boolean | number | void
+ }
+}
+
+function test15(a: boolean | number | void) {
+>test15 : (a: boolean | number | void) => void
+>a : boolean | number | void
+
+ if (typeof a === "undefined" || typeof a === "boolean") {
+>typeof a === "undefined" || typeof a === "boolean" : boolean
+>typeof a === "undefined" : boolean
+>typeof a : string
+>a : boolean | number | void
+>"undefined" : string
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | number | void
+>"boolean" : string
+
+ a;
+>a : boolean | number | void
+ }
+ else {
+ a;
+>a : number | void
+ }
+}
+
+function test16(a: boolean | number | void) {
+>test16 : (a: boolean | number | void) => void
+>a : boolean | number | void
+
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+>typeof a !== "undefined" && typeof a === "boolean" : boolean
+>typeof a !== "undefined" : boolean
+>typeof a : string
+>a : boolean | number | void
+>"undefined" : string
+>typeof a === "boolean" : boolean
+>typeof a : string
+>a : boolean | number | void
+>"boolean" : string
+
+ a;
+>a : boolean
+ }
+ else {
+ a;
+>a : boolean | number | void
+ }
+}
+
diff --git a/tests/cases/compiler/ambientClassDeclarationWithExtends.ts b/tests/cases/compiler/ambientClassDeclarationWithExtends.ts
index 0c5d8d156b..ca26f1b2a4 100644
--- a/tests/cases/compiler/ambientClassDeclarationWithExtends.ts
+++ b/tests/cases/compiler/ambientClassDeclarationWithExtends.ts
@@ -1,2 +1,23 @@
+// @Filename: ambientClassDeclarationExtends_singleFile.ts
declare class A { }
declare class B extends A { }
+
+declare class C {
+ public foo;
+}
+namespace D { var x; }
+declare class D extends C { }
+
+var d: C = new D();
+
+// @Filename: ambientClassDeclarationExtends_file1.ts
+
+declare class E {
+ public bar;
+}
+namespace F { var y; }
+
+// @Filename: ambientClassDeclarationExtends_file2.ts
+
+declare class F extends E { }
+var f: E = new F();
diff --git a/tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts b/tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts
new file mode 100644
index 0000000000..6395813b65
--- /dev/null
+++ b/tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts
@@ -0,0 +1,15 @@
+class A {
+ f() {}
+ static m1 (a: string): void;
+ m1 (a: number): void;
+ m1 (a: any): void {
+ }
+}
+
+class B {
+ f() {}
+ m1 (a: string): void;
+ static m1 (a: number): void;
+ m1 (a: any): void {
+ }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts b/tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts
new file mode 100644
index 0000000000..6ec4c6076f
--- /dev/null
+++ b/tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts
@@ -0,0 +1,8 @@
+class A {
+ m1: string;
+ f() {}
+ m1 (a: string): void;
+ m1 (a: number): void;
+ m1 (a: any): void {
+ }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/nonMergedOverloads.ts b/tests/cases/compiler/nonMergedOverloads.ts
new file mode 100644
index 0000000000..582cd72e1f
--- /dev/null
+++ b/tests/cases/compiler/nonMergedOverloads.ts
@@ -0,0 +1,5 @@
+var f = 10;
+
+export function f();
+export function f() {
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts b/tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts
new file mode 100644
index 0000000000..57ba843a69
--- /dev/null
+++ b/tests/cases/compiler/sourceMapValidationLambdaSpanningMultipleLines.ts
@@ -0,0 +1,4 @@
+// @sourcemap: true
+((item: string) =>
+ item
+)
\ No newline at end of file
diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts
new file mode 100644
index 0000000000..766c5ed8ca
--- /dev/null
+++ b/tests/cases/conformance/expressions/typeGuards/typeGuardTypeOfUndefined.ts
@@ -0,0 +1,184 @@
+// undefined type guard adds no new type information
+function test1(a: any) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test2(a: any) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test3(a: any) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test4(a: any) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test5(a: boolean | void) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test6(a: boolean | void) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test7(a: boolean | void) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test8(a: boolean | void) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test9(a: boolean | number) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test10(a: boolean | number) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test11(a: boolean | number) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test12(a: boolean | number) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test13(a: boolean | number | void) {
+ if (typeof a !== "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test14(a: boolean | number | void) {
+ if (typeof a === "undefined") {
+ if (typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+ }
+ else {
+ a;
+ }
+}
+
+function test15(a: boolean | number | void) {
+ if (typeof a === "undefined" || typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
+
+function test16(a: boolean | number | void) {
+ if (typeof a !== "undefined" && typeof a === "boolean") {
+ a;
+ }
+ else {
+ a;
+ }
+}
diff --git a/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts b/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts
index 16d2efcd6d..d66c162075 100644
--- a/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts
+++ b/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts
@@ -3,16 +3,16 @@
//// var f4 = (x: T/**/ ) => {
//// }
-fs.goTo.marker();
+goTo.marker();
// Replace the "T" type with the non-existent type 'V'.
-fs.edit.backspace(1);
-fs.edit.insert("A");
+edit.backspace(1);
+edit.insert("A");
// Bring up completion to force a pull resolve. This will end up resolving several symbols and
// producing unreported diagnostics (i.e. that 'V' wasn't found).
-fs.verify.completionListContains("T");
-fs.verify.completionEntryDetailIs("T", "(type parameter) T in (x: any): void");
+verify.completionListContains("T");
+verify.completionEntryDetailIs("T", "(type parameter) T in (x: any): void");
// There should now be a single error.
-fs.verify.numberOfErrorsInCurrentFile(1);
\ No newline at end of file
+verify.numberOfErrorsInCurrentFile(1);
diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts
index 41e8d9005f..f93ac76d6e 100644
--- a/tests/cases/fourslash/fourslash.ts
+++ b/tests/cases/fourslash/fourslash.ts
@@ -24,10 +24,7 @@
// @Module: Node
// @Target: ES5
-// In the imperative section, you can write any valid TypeScript code. If
-// you need help finding a something in Intellisense, you can
-// type 'fs.' as an alternate way of accessing the top-level objects
-// (e.g. 'fs.goTo.eof();')
+// In the imperative section, you can write any valid TypeScript code.
//---------------------------------------
// For API editors:
@@ -45,52 +42,32 @@
//
// TODO: figure out a better solution to the API exposure problem.
-// ///
-// ///
-
-declare var FourSlash;
-module ts {
- export interface SymbolDisplayPart {
+declare module ts {
+ interface SymbolDisplayPart {
text: string;
kind: string;
}
+
+ enum IndentStyle {
+ None = 0,
+ Block = 1,
+ Smart = 2,
+ }
}
-//---------------------------------------------
-
-// Return code used by getEmitOutput function to indicate status of the function
-// It is a duplicate of the one in types.ts to expose it to testcases in fourslash
-enum EmitReturnStatus {
- Succeeded = 0, // All outputs generated if requested (.js, .map, .d.ts), no errors reported
- AllOutputGenerationSkipped = 1, // No .js generated because of syntax errors, or compiler options errors, nothing generated
- JSGeneratedWithSemanticErrors = 2, // .js and .map generated with semantic errors
- DeclarationGenerationSkipped = 3, // .d.ts generation skipped because of semantic errors or declaration emitter specific errors; Output .js with semantic errors
- EmitErrorsEncountered = 4 // Emitter errors occurred during emitting process
-}
-
-// This is a duplicate of the indentstyle in services.ts to expose it to testcases in fourslash
-enum IndentStyle {
- None,
- Block,
- Smart,
-}
-
-module FourSlashInterface {
-
- export interface Marker {
+declare namespace FourSlashInterface {
+ interface Marker {
fileName: string;
position: number;
data?: any;
}
-
- export interface EditorOptions {
+ interface EditorOptions {
IndentSize: number;
TabSize: number;
NewLineCharacter: string;
ConvertTabsToSpaces: boolean;
}
-
- export interface FormatCodeOptions extends EditorOptions {
+ interface FormatCodeOptions extends EditorOptions {
InsertSpaceAfterCommaDelimiter: boolean;
InsertSpaceAfterSemicolonInForStatements: boolean;
InsertSpaceBeforeAndAfterBinaryOperators: boolean;
@@ -100,646 +77,266 @@ module FourSlashInterface {
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean;
PlaceOpenBraceOnNewLineForFunctions: boolean;
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
- [s: string]: boolean | number| string;
+ [s: string]: boolean | number | string;
}
-
- export interface Range {
+ interface Range {
fileName: string;
start: number;
end: number;
marker?: Marker;
}
-
- export interface TextSpan {
+ interface TextSpan {
start: number;
end: number;
}
-
- export class test_ {
- public markers(): Marker[] {
- return FourSlash.currentTestState.getMarkers();
- }
-
- public marker(name?: string): Marker {
- return FourSlash.currentTestState.getMarkerByName(name);
- }
-
- public ranges(): Range[] {
- return FourSlash.currentTestState.getRanges();
- }
-
- public markerByName(s: string): Marker {
- return FourSlash.currentTestState.getMarkerByName(s);
- }
+ class test_ {
+ markers(): Marker[];
+ marker(name?: string): Marker;
+ ranges(): Range[];
+ markerByName(s: string): Marker;
}
-
- export class goTo {
- // Moves the caret to the specified marker,
- // or the anonymous marker ('/**/') if no name
- // is given
- public marker(name?: string) {
- FourSlash.currentTestState.goToMarker(name);
- }
-
- public bof() {
- FourSlash.currentTestState.goToBOF();
- }
-
- public eof() {
- FourSlash.currentTestState.goToEOF();
- }
-
- public definition(definitionIndex: number = 0) {
- FourSlash.currentTestState.goToDefinition(definitionIndex);
- }
-
- public type(definitionIndex: number = 0) {
- FourSlash.currentTestState.goToTypeDefinition(definitionIndex);
- }
-
- public position(position: number, fileIndex?: number);
- public position(position: number, fileName?: string);
- public position(position: number, fileNameOrIndex?: any) {
- if (fileNameOrIndex !== undefined) {
- this.file(fileNameOrIndex);
- }
- FourSlash.currentTestState.goToPosition(position);
- }
-
- // Opens a file, given either its index as it
- // appears in the test source, or its filename
- // as specified in the test metadata
- public file(index: number);
- public file(name: string);
- public file(indexOrName: any) {
- FourSlash.currentTestState.openFile(indexOrName);
- }
+ class goTo {
+ marker(name?: string): void;
+ bof(): void;
+ eof(): void;
+ definition(definitionIndex?: number): void;
+ type(definitionIndex?: number): void;
+ position(position: number, fileIndex?: number): any;
+ position(position: number, fileName?: string): any;
+ file(index: number, content?: string): any;
+ file(name: string, content?: string): any;
}
-
- export class verifyNegatable {
- public not: verifyNegatable;
-
- constructor(private negative = false) {
- if (!negative) {
- this.not = new verifyNegatable(true);
- }
- }
-
- // Verifies the member list contains the specified symbol. The
- // member list is brought up if necessary
- public memberListContains(symbol: string, text?: string, documenation?: string, kind?: string) {
- if (this.negative) {
- FourSlash.currentTestState.verifyMemberListDoesNotContain(symbol);
- } else {
- FourSlash.currentTestState.verifyMemberListContains(symbol, text, documenation, kind);
- }
- }
-
- public memberListCount(expectedCount: number) {
- FourSlash.currentTestState.verifyMemberListCount(expectedCount, this.negative);
- }
-
- // Verifies the completion list contains the specified symbol. The
- // completion list is brought up if necessary
- public completionListContains(symbol: string, text?: string, documentation?: string, kind?: string) {
- if (this.negative) {
- FourSlash.currentTestState.verifyCompletionListDoesNotContain(symbol, text, documentation, kind);
- } else {
- FourSlash.currentTestState.verifyCompletionListContains(symbol, text, documentation, kind);
- }
- }
-
- // Verifies the completion list items count to be greater than the specified amount. The
- // completion list is brought up if necessary
- public completionListItemsCountIsGreaterThan(count: number) {
- FourSlash.currentTestState.verifyCompletionListItemsCountIsGreaterThan(count, this.negative);
- }
-
- public completionListIsEmpty() {
- FourSlash.currentTestState.verifyCompletionListIsEmpty(this.negative);
- }
-
- public completionListAllowsNewIdentifier() {
- FourSlash.currentTestState.verifyCompletionListAllowsNewIdentifier(this.negative);
- }
-
- public memberListIsEmpty() {
- FourSlash.currentTestState.verifyMemberListIsEmpty(this.negative);
- }
-
- public referencesCountIs(count: number) {
- FourSlash.currentTestState.verifyReferencesCountIs(count, /*localFilesOnly*/ false);
- }
-
- public referencesAtPositionContains(range: Range, isWriteAccess?: boolean) {
- FourSlash.currentTestState.verifyReferencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess);
- }
-
- public signatureHelpPresent() {
- FourSlash.currentTestState.verifySignatureHelpPresent(!this.negative);
- }
-
- public errorExistsBetweenMarkers(startMarker: string, endMarker: string) {
- FourSlash.currentTestState.verifyErrorExistsBetweenMarkers(startMarker, endMarker, !this.negative);
- }
-
- public errorExistsAfterMarker(markerName = "") {
- FourSlash.currentTestState.verifyErrorExistsAfterMarker(markerName, !this.negative, true);
- }
-
- public errorExistsBeforeMarker(markerName = "") {
- FourSlash.currentTestState.verifyErrorExistsAfterMarker(markerName, !this.negative, false);
- }
-
- public quickInfoIs(expectedText?: string, expectedDocumentation?: string) {
- FourSlash.currentTestState.verifyQuickInfoString(this.negative, expectedText, expectedDocumentation);
- }
-
- public quickInfoExists() {
- FourSlash.currentTestState.verifyQuickInfoExists(this.negative);
- }
-
- public definitionCountIs(expectedCount: number) {
- FourSlash.currentTestState.verifyDefinitionsCount(this.negative, expectedCount);
- }
-
- public typeDefinitionCountIs(expectedCount: number) {
- FourSlash.currentTestState.verifyTypeDefinitionsCount(this.negative, expectedCount);
- }
-
- public definitionLocationExists() {
- FourSlash.currentTestState.verifyDefinitionLocationExists(this.negative);
- }
-
- public verifyDefinitionsName(name: string, containerName: string) {
- FourSlash.currentTestState.verifyDefinitionsName(this.negative, name, containerName);
- }
+ class verifyNegatable {
+ private negative;
+ not: verifyNegatable;
+ constructor(negative?: boolean);
+ memberListContains(symbol: string, text?: string, documenation?: string, kind?: string): void;
+ memberListCount(expectedCount: number): void;
+ completionListContains(symbol: string, text?: string, documentation?: string, kind?: string): void;
+ completionListItemsCountIsGreaterThan(count: number): void;
+ completionListIsEmpty(): void;
+ completionListAllowsNewIdentifier(): void;
+ memberListIsEmpty(): void;
+ referencesCountIs(count: number): void;
+ referencesAtPositionContains(range: Range, isWriteAccess?: boolean): void;
+ signatureHelpPresent(): void;
+ errorExistsBetweenMarkers(startMarker: string, endMarker: string): void;
+ errorExistsAfterMarker(markerName?: string): void;
+ errorExistsBeforeMarker(markerName?: string): void;
+ quickInfoIs(expectedText?: string, expectedDocumentation?: string): void;
+ quickInfoExists(): void;
+ definitionCountIs(expectedCount: number): void;
+ typeDefinitionCountIs(expectedCount: number): void;
+ definitionLocationExists(): void;
+ verifyDefinitionsName(name: string, containerName: string): void;
}
-
- export class verify extends verifyNegatable {
- public caretAtMarker(markerName?: string) {
- FourSlash.currentTestState.verifyCaretAtMarker(markerName);
- }
-
- public indentationIs(numberOfSpaces: number) {
- FourSlash.currentTestState.verifyIndentationAtCurrentPosition(numberOfSpaces);
- }
-
- public indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle = IndentStyle.Smart) {
- FourSlash.currentTestState.verifyIndentationAtPosition(fileName, position, numberOfSpaces, indentStyle);
- }
-
- public textAtCaretIs(text: string) {
- FourSlash.currentTestState.verifyTextAtCaretIs(text);
- }
-
+ class verify extends verifyNegatable {
+ caretAtMarker(markerName?: string): void;
+ indentationIs(numberOfSpaces: number): void;
+ indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle?: IndentStyle): void;
+ textAtCaretIs(text: string): void;
/**
* Compiles the current file and evaluates 'expr' in a context containing
* the emitted output, then compares (using ===) the result of that expression
* to 'value'. Do not use this function with external modules as it is not supported.
*/
- public eval(expr: string, value: any) {
- FourSlash.currentTestState.verifyEval(expr, value);
- }
-
- public currentLineContentIs(text: string) {
- FourSlash.currentTestState.verifyCurrentLineContent(text);
- }
-
- public currentFileContentIs(text: string) {
- FourSlash.currentTestState.verifyCurrentFileContent(text);
- }
-
- public verifyGetEmitOutputForCurrentFile(expected: string): void {
- FourSlash.currentTestState.verifyGetEmitOutputForCurrentFile(expected);
- }
-
- public currentParameterHelpArgumentNameIs(name: string) {
- FourSlash.currentTestState.verifyCurrentParameterHelpName(name);
- }
-
- public currentParameterSpanIs(parameter: string) {
- FourSlash.currentTestState.verifyCurrentParameterSpanIs(parameter);
- }
-
- public currentParameterHelpArgumentDocCommentIs(docComment: string) {
- FourSlash.currentTestState.verifyCurrentParameterHelpDocComment(docComment);
- }
-
- public currentSignatureHelpDocCommentIs(docComment: string) {
- FourSlash.currentTestState.verifyCurrentSignatureHelpDocComment(docComment);
- }
-
- public signatureHelpCountIs(expected: number) {
- FourSlash.currentTestState.verifySignatureHelpCount(expected);
- }
-
- public signatureHelpArgumentCountIs(expected: number) {
- FourSlash.currentTestState.verifySignatureHelpArgumentCount(expected);
- }
-
- public currentSignatureParameterCountIs(expected: number) {
- FourSlash.currentTestState.verifyCurrentSignatureHelpParameterCount(expected);
- }
-
- public currentSignatureTypeParameterCountIs(expected: number) {
- FourSlash.currentTestState.verifyCurrentSignatureHelpTypeParameterCount(expected);
- }
-
- public currentSignatureHelpIs(expected: string) {
- FourSlash.currentTestState.verifyCurrentSignatureHelpIs(expected);
- }
-
- public numberOfErrorsInCurrentFile(expected: number) {
- FourSlash.currentTestState.verifyNumberOfErrorsInCurrentFile(expected);
- }
-
- public baselineCurrentFileBreakpointLocations() {
- FourSlash.currentTestState.baselineCurrentFileBreakpointLocations();
- }
-
- public baselineCurrentFileNameOrDottedNameSpans() {
- FourSlash.currentTestState.baselineCurrentFileNameOrDottedNameSpans();
- }
-
- public baselineGetEmitOutput() {
- FourSlash.currentTestState.baselineGetEmitOutput();
- }
-
- public nameOrDottedNameSpanTextIs(text: string) {
- FourSlash.currentTestState.verifyCurrentNameOrDottedNameSpanText(text);
- }
-
- public outliningSpansInCurrentFile(spans: TextSpan[]) {
- FourSlash.currentTestState.verifyOutliningSpans(spans);
- }
-
- public todoCommentsInCurrentFile(descriptors: string[]) {
- FourSlash.currentTestState.verifyTodoComments(descriptors, test.ranges());
- }
-
- public matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number) {
- FourSlash.currentTestState.verifyMatchingBracePosition(bracePosition, expectedMatchPosition);
- }
-
- public noMatchingBracePositionInCurrentFile(bracePosition: number) {
- FourSlash.currentTestState.verifyNoMatchingBracePosition(bracePosition);
- }
-
- public DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean) {
- FourSlash.currentTestState.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, caretOffset: expectedOffset });
- }
-
- public noDocCommentTemplate() {
- this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, true);
- }
-
- public getScriptLexicalStructureListCount(count: number) {
- FourSlash.currentTestState.verifyGetScriptLexicalStructureListCount(count);
- }
-
- // TODO: figure out what to do with the unused arguments.
- public getScriptLexicalStructureListContains(
- name: string,
- kind: string,
- fileName?: string,
- parentName?: string,
- isAdditionalSpan?: boolean,
- markerPosition?: number) {
- FourSlash.currentTestState.verifyGetScriptLexicalStructureListContains(name, kind);
- }
-
- public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) {
- FourSlash.currentTestState.verifyNavigationItemsCount(count, searchValue, matchKind);
- }
-
- public navigationItemsListContains(
- name: string,
- kind: string,
- searchValue: string,
- matchKind: string,
- fileName?: string,
- parentName?: string) {
- FourSlash.currentTestState.verifyNavigationItemsListContains(
- name,
- kind,
- searchValue,
- matchKind,
- fileName,
- parentName);
- }
-
- public occurrencesAtPositionContains(range: Range, isWriteAccess?: boolean) {
- FourSlash.currentTestState.verifyOccurrencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess);
- }
-
- public occurrencesAtPositionCount(expectedCount: number) {
- FourSlash.currentTestState.verifyOccurrencesAtPositionListCount(expectedCount);
- }
-
- public documentHighlightsAtPositionContains(range: Range, fileNamesToSearch: string[], kind?: string) {
- FourSlash.currentTestState.verifyDocumentHighlightsAtPositionListContains(range.fileName, range.start, range.end, fileNamesToSearch, kind);
- }
-
- public documentHighlightsAtPositionCount(expectedCount: number, fileNamesToSearch: string[]) {
- FourSlash.currentTestState.verifyDocumentHighlightsAtPositionListCount(expectedCount, fileNamesToSearch);
- }
-
- public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string) {
- FourSlash.currentTestState.verifyCompletionEntryDetails(entryName, text, documentation, kind);
- }
-
+ eval(expr: string, value: any): void;
+ currentLineContentIs(text: string): void;
+ currentFileContentIs(text: string): void;
+ verifyGetEmitOutputForCurrentFile(expected: string): void;
+ currentParameterHelpArgumentNameIs(name: string): void;
+ currentParameterSpanIs(parameter: string): void;
+ currentParameterHelpArgumentDocCommentIs(docComment: string): void;
+ currentSignatureHelpDocCommentIs(docComment: string): void;
+ signatureHelpCountIs(expected: number): void;
+ signatureHelpArgumentCountIs(expected: number): void;
+ currentSignatureParameterCountIs(expected: number): void;
+ currentSignatureTypeParameterCountIs(expected: number): void;
+ currentSignatureHelpIs(expected: string): void;
+ numberOfErrorsInCurrentFile(expected: number): void;
+ baselineCurrentFileBreakpointLocations(): void;
+ baselineCurrentFileNameOrDottedNameSpans(): void;
+ baselineGetEmitOutput(): void;
+ nameOrDottedNameSpanTextIs(text: string): void;
+ outliningSpansInCurrentFile(spans: TextSpan[]): void;
+ todoCommentsInCurrentFile(descriptors: string[]): void;
+ matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number): void;
+ noMatchingBracePositionInCurrentFile(bracePosition: number): void;
+ DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean): void;
+ noDocCommentTemplate(): void;
+ getScriptLexicalStructureListCount(count: number): void;
+ getScriptLexicalStructureListContains(name: string, kind: string, fileName?: string, parentName?: string, isAdditionalSpan?: boolean, markerPosition?: number): void;
+ navigationItemsListCount(count: number, searchValue: string, matchKind?: string): void;
+ navigationItemsListContains(name: string, kind: string, searchValue: string, matchKind: string, fileName?: string, parentName?: string): void;
+ occurrencesAtPositionContains(range: Range, isWriteAccess?: boolean): void;
+ occurrencesAtPositionCount(expectedCount: number): void;
+ documentHighlightsAtPositionContains(range: Range, fileNamesToSearch: string[], kind?: string): void;
+ documentHighlightsAtPositionCount(expectedCount: number, fileNamesToSearch: string[]): void;
+ completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string): void;
/**
* This method *requires* a contiguous, complete, and ordered stream of classifications for a file.
*/
- public syntacticClassificationsAre(...classifications: { classificationType: string; text: string }[]) {
- FourSlash.currentTestState.verifySyntacticClassifications(classifications);
- }
-
+ syntacticClassificationsAre(...classifications: {
+ classificationType: string;
+ text: string;
+ }[]): void;
/**
* This method *requires* an ordered stream of classifications for a file, and spans are highly recommended.
*/
- public semanticClassificationsAre(...classifications: { classificationType: string; text: string; textSpan?: TextSpan }[]) {
- FourSlash.currentTestState.verifySemanticClassifications(classifications);
- }
-
- public renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string) {
- FourSlash.currentTestState.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers)
- }
-
- public renameInfoFailed(message?: string) {
- FourSlash.currentTestState.verifyRenameInfoFailed(message)
- }
-
- public renameLocations(findInStrings: boolean, findInComments: boolean) {
- FourSlash.currentTestState.verifyRenameLocations(findInStrings, findInComments);
- }
-
- public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; },
- displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) {
- FourSlash.currentTestState.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation);
- }
-
- public getSyntacticDiagnostics(expected: string) {
- FourSlash.currentTestState.getSyntacticDiagnostics(expected);
- }
-
- public getSemanticDiagnostics(expected: string) {
- FourSlash.currentTestState.getSemanticDiagnostics(expected);
- }
-
- public ProjectInfo(expected: string []) {
- FourSlash.currentTestState.verifyProjectInfo(expected);
- }
+ semanticClassificationsAre(...classifications: {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ }[]): void;
+ renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string): void;
+ renameInfoFailed(message?: string): void;
+ renameLocations(findInStrings: boolean, findInComments: boolean): void;
+ verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: {
+ start: number;
+ length: number;
+ }, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]): void;
+ getSyntacticDiagnostics(expected: string): void;
+ getSemanticDiagnostics(expected: string): void;
+ ProjectInfo(expected: string[]): void;
}
-
- export class edit {
- public backspace(count?: number) {
- FourSlash.currentTestState.deleteCharBehindMarker(count);
- }
-
- public deleteAtCaret(times?: number) {
- FourSlash.currentTestState.deleteChar(times);
- }
-
- public replace(start: number, length: number, text: string) {
- FourSlash.currentTestState.replace(start, length, text);
- }
-
- public paste(text: string) {
- FourSlash.currentTestState.paste(text);
- }
-
- public insert(text: string) {
- this.insertLines(text);
- }
-
- public insertLine(text: string) {
- this.insertLines(text + '\n');
- }
-
- public insertLines(...lines: string[]) {
- FourSlash.currentTestState.type(lines.join('\n'));
- }
-
- public moveRight(count?: number) {
- FourSlash.currentTestState.moveCaretRight(count);
- }
-
- public moveLeft(count?: number) {
- if (typeof count === 'undefined') {
- count = 1;
- }
- FourSlash.currentTestState.moveCaretRight(count * -1);
- }
-
- public enableFormatting() {
- FourSlash.currentTestState.enableFormatting = true;
- }
-
- public disableFormatting() {
- FourSlash.currentTestState.enableFormatting = false;
- }
+ class edit {
+ backspace(count?: number): void;
+ deleteAtCaret(times?: number): void;
+ replace(start: number, length: number, text: string): void;
+ paste(text: string): void;
+ insert(text: string): void;
+ insertLine(text: string): void;
+ insertLines(...lines: string[]): void;
+ moveRight(count?: number): void;
+ moveLeft(count?: number): void;
+ enableFormatting(): void;
+ disableFormatting(): void;
}
-
- export class debug {
- public printCurrentParameterHelp() {
- FourSlash.currentTestState.printCurrentParameterHelp();
- }
-
- public printCurrentFileState() {
- FourSlash.currentTestState.printCurrentFileState();
- }
-
- public printCurrentFileStateWithWhitespace() {
- FourSlash.currentTestState.printCurrentFileState(/*withWhiteSpace=*/true);
- }
-
- public printCurrentFileStateWithoutCaret() {
- FourSlash.currentTestState.printCurrentFileState(/*withWhiteSpace=*/false, /*withCaret=*/false);
- }
-
- public printCurrentQuickInfo() {
- FourSlash.currentTestState.printCurrentQuickInfo();
- }
-
- public printCurrentSignatureHelp() {
- FourSlash.currentTestState.printCurrentSignatureHelp();
- }
-
- public printMemberListMembers() {
- FourSlash.currentTestState.printMemberListMembers();
- }
-
- public printCompletionListMembers() {
- FourSlash.currentTestState.printCompletionListMembers();
- }
-
- public printBreakpointLocation(pos: number) {
- FourSlash.currentTestState.printBreakpointLocation(pos);
- }
- public printBreakpointAtCurrentLocation() {
- FourSlash.currentTestState.printBreakpointAtCurrentLocation();
- }
-
- public printNameOrDottedNameSpans(pos: number) {
- FourSlash.currentTestState.printNameOrDottedNameSpans(pos);
- }
-
- public printErrorList() {
- FourSlash.currentTestState.printErrorList();
- }
-
- public printNavigationItems(searchValue: string = ".*") {
- FourSlash.currentTestState.printNavigationItems(searchValue);
- }
-
- public printScriptLexicalStructureItems() {
- FourSlash.currentTestState.printScriptLexicalStructureItems();
- }
-
- public printReferences() {
- FourSlash.currentTestState.printReferences();
- }
-
- public printContext() {
- FourSlash.currentTestState.printContext();
- }
+ class debug {
+ printCurrentParameterHelp(): void;
+ printCurrentFileState(): void;
+ printCurrentFileStateWithWhitespace(): void;
+ printCurrentFileStateWithoutCaret(): void;
+ printCurrentQuickInfo(): void;
+ printCurrentSignatureHelp(): void;
+ printMemberListMembers(): void;
+ printCompletionListMembers(): void;
+ printBreakpointLocation(pos: number): void;
+ printBreakpointAtCurrentLocation(): void;
+ printNameOrDottedNameSpans(pos: number): void;
+ printErrorList(): void;
+ printNavigationItems(searchValue?: string): void;
+ printScriptLexicalStructureItems(): void;
+ printReferences(): void;
+ printContext(): void;
}
-
- export class format {
- public document() {
- FourSlash.currentTestState.formatDocument();
- }
-
- public copyFormatOptions(): FormatCodeOptions {
- return FourSlash.currentTestState.copyFormatOptions();
- }
-
- public setFormatOptions(options: FormatCodeOptions) {
- return FourSlash.currentTestState.setFormatOptions(options);
- }
-
- public selection(startMarker: string, endMarker: string) {
- FourSlash.currentTestState.formatSelection(FourSlash.currentTestState.getMarkerByName(startMarker).position, FourSlash.currentTestState.getMarkerByName(endMarker).position);
- }
-
- public setOption(name: string, value: number);
- public setOption(name: string, value: string);
- public setOption(name: string, value: boolean);
- public setOption(name: string, value: any) {
- FourSlash.currentTestState.formatCodeOptions[name] = value;
- }
+ class format {
+ document(): void;
+ copyFormatOptions(): FormatCodeOptions;
+ setFormatOptions(options: FormatCodeOptions): any;
+ selection(startMarker: string, endMarker: string): void;
+ setOption(name: string, value: number): any;
+ setOption(name: string, value: string): any;
+ setOption(name: string, value: boolean): any;
}
-
- export class cancellation {
- public resetCancelled() {
- FourSlash.currentTestState.resetCancelled();
- }
-
- public setCancelled(numberOfCalls: number = 0) {
- FourSlash.currentTestState.setCancelled(numberOfCalls);
- }
+ class cancellation {
+ resetCancelled(): void;
+ setCancelled(numberOfCalls?: number): void;
}
-
- export module classification {
- export function comment(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("comment", text, position);
- }
-
- export function identifier(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("identifier", text, position);
- }
-
- export function keyword(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("keyword", text, position);
- }
-
- export function numericLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("numericLiteral", text, position);
- }
-
- export function operator(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("operator", text, position);
- }
-
- export function stringLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("stringLiteral", text, position);
- }
-
- export function whiteSpace(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("whiteSpace", text, position);
- }
-
- export function text(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("text", text, position);
- }
-
- export function punctuation(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("punctuation", text, position);
- }
-
- export function docCommentTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("docCommentTagName", text, position);
- }
-
- export function className(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("className", text, position);
- }
-
- export function enumName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("enumName", text, position);
- }
-
- export function interfaceName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("interfaceName", text, position);
- }
-
- export function moduleName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("moduleName", text, position);
- }
-
- export function typeParameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("typeParameterName", text, position);
- }
-
- export function parameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("parameterName", text, position);
- }
-
- export function typeAliasName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } {
- return getClassification("typeAliasName", text, position);
- }
-
- function getClassification(type: string, text: string, position?: number) {
- return {
- classificationType: type,
- text: text,
- textSpan: position === undefined ? undefined : { start: position, end: position + text.length }
- };
- }
+ module classification {
+ function comment(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function identifier(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function keyword(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function numericLiteral(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function operator(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function stringLiteral(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function whiteSpace(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function text(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function punctuation(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function docCommentTagName(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function className(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function enumName(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function interfaceName(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function moduleName(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function typeParameterName(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function parameterName(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
+ function typeAliasName(text: string, position?: number): {
+ classificationType: string;
+ text: string;
+ textSpan?: TextSpan;
+ };
}
}
-
-module fs {
- export var test = new FourSlashInterface.test_();
- export var goTo = new FourSlashInterface.goTo();
- export var verify = new FourSlashInterface.verify();
- export var edit = new FourSlashInterface.edit();
- export var debug = new FourSlashInterface.debug();
- export var format = new FourSlashInterface.format();
- export var cancellation = new FourSlashInterface.cancellation();
-}
-
-function verifyOperationIsCancelled(f) {
- FourSlash.verifyOperationIsCancelled(f);
-}
-
-var test = new FourSlashInterface.test_();
-var goTo = new FourSlashInterface.goTo();
-var verify = new FourSlashInterface.verify();
-var edit = new FourSlashInterface.edit();
-var debug = new FourSlashInterface.debug();
-var format = new FourSlashInterface.format();
-var cancellation = new FourSlashInterface.cancellation();
-var classification = FourSlashInterface.classification;
+declare function verifyOperationIsCancelled(f: any): void;
+declare var test: FourSlashInterface.test_;
+declare var goTo: FourSlashInterface.goTo;
+declare var verify: FourSlashInterface.verify;
+declare var edit: FourSlashInterface.edit;
+declare var debug: FourSlashInterface.debug;
+declare var format: FourSlashInterface.format;
+declare var cancellation: FourSlashInterface.cancellation;
+declare var classification: typeof FourSlashInterface.classification;
diff --git a/tests/cases/fourslash/indentationBlock.ts b/tests/cases/fourslash/indentationBlock.ts
index e880c4a095..853ff43b0d 100644
--- a/tests/cases/fourslash/indentationBlock.ts
+++ b/tests/cases/fourslash/indentationBlock.ts
@@ -179,5 +179,5 @@
////{| "indent": 0 |}
test.markers().forEach(marker => {
- verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, IndentStyle.Block);
+ verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, ts.IndentStyle.Block);
});
diff --git a/tests/cases/fourslash/indentationNone.ts b/tests/cases/fourslash/indentationNone.ts
index 078f5ab35f..610a336cdd 100644
--- a/tests/cases/fourslash/indentationNone.ts
+++ b/tests/cases/fourslash/indentationNone.ts
@@ -179,5 +179,5 @@
////{| "indent": 0 |}
test.markers().forEach(marker => {
- verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, IndentStyle.None);
+ verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, ts.IndentStyle.None);
});
diff --git a/tests/cases/fourslash/recursiveClassReference.ts b/tests/cases/fourslash/recursiveClassReference.ts
index d0e96ac90e..81843711d6 100644
--- a/tests/cases/fourslash/recursiveClassReference.ts
+++ b/tests/cases/fourslash/recursiveClassReference.ts
@@ -11,4 +11,4 @@
//// }
goTo.marker();
-fs.verify.quickInfoExists();
+verify.quickInfoExists();
diff --git a/tests/cases/fourslash/renameModuleToVar.ts b/tests/cases/fourslash/renameModuleToVar.ts
index 023b0fa1c7..fc31f4040e 100644
--- a/tests/cases/fourslash/renameModuleToVar.ts
+++ b/tests/cases/fourslash/renameModuleToVar.ts
@@ -10,7 +10,7 @@
//// var z = y + 5;
////}
-fs.goTo.marker();
-fs.edit.backspace(6);
-fs.edit.insert("var");
-fs.verify.numberOfErrorsInCurrentFile(0);
\ No newline at end of file
+goTo.marker();
+edit.backspace(6);
+edit.insert("var");
+verify.numberOfErrorsInCurrentFile(0);
diff --git a/tests/cases/fourslash/server/openFile.ts b/tests/cases/fourslash/server/openFile.ts
new file mode 100644
index 0000000000..320e52c9f5
--- /dev/null
+++ b/tests/cases/fourslash/server/openFile.ts
@@ -0,0 +1,16 @@
+///
+
+// @Filename: test1.ts
+////t.
+
+// @Filename: test.ts
+////var t = '10';
+
+// @Filename: tsconfig.json
+////{ "files": ["test.ts", "test1.ts"] }
+
+var overridingContent = "var t = 10; t.";
+goTo.file("test.ts", overridingContent);
+goTo.file("test1.ts");
+goTo.eof();
+verify.completionListContains("toExponential");
diff --git a/tests/cases/fourslash/signatureHelpConstructorCallParamProperties.ts b/tests/cases/fourslash/signatureHelpConstructorCallParamProperties.ts
new file mode 100644
index 0000000000..aab276403f
--- /dev/null
+++ b/tests/cases/fourslash/signatureHelpConstructorCallParamProperties.ts
@@ -0,0 +1,18 @@
+///
+
+////class Circle {
+//// /**
+//// * Initialize a circle.
+//// * @param radius The radius of the circle.
+//// */
+//// constructor(private radius: number) {
+//// }
+////}
+////var a = new Circle(/**/
+
+goTo.marker('');
+verify.signatureHelpCountIs(1);
+verify.currentSignatureHelpIs("Circle(radius: number): Circle");
+verify.currentParameterHelpArgumentNameIs("radius");
+verify.currentParameterSpanIs("radius: number");
+verify.currentParameterHelpArgumentDocCommentIs("The radius of the circle.");
\ No newline at end of file
diff --git a/tests/cases/unittests/moduleResolution.ts b/tests/cases/unittests/moduleResolution.ts
index c53cad5725..9e316266bf 100644
--- a/tests/cases/unittests/moduleResolution.ts
+++ b/tests/cases/unittests/moduleResolution.ts
@@ -354,6 +354,31 @@ export = C;
"moduleC.ts": "export var x"
};
test(files, { module: ts.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", () => {
+ const files: Map = {
+ "/a/B/c/moduleA.ts": `import a = require("./ModuleC")`,
+ "/a/B/c/moduleB.ts": `import a = require("./moduleC")`,
+ "/a/B/c/moduleC.ts": "export var x",
+ "/a/B/c/moduleD.ts": `
+import a = require("./moduleA.ts");
+import b = require("./moduleB.ts");
+ `
+ };
+ test(files, { module: ts.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: Map = {
+ "/a/B/c/moduleA.ts": `import a = require("./moduleC")`,
+ "/a/B/c/moduleB.ts": `import a = require("./moduleC")`,
+ "/a/B/c/moduleC.ts": "export var x",
+ "/a/B/c/moduleD.ts": `
+import a = require("./moduleA.ts");
+import b = require("./moduleB.ts");
+ `
+ };
+ test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /* useCaseSensitiveFileNames */ false, ["moduleD.ts"], []);
})
});
}
\ No newline at end of file
diff --git a/tests/webTestServer.ts b/tests/webTestServer.ts
index 6bd15359e3..dab552e261 100644
--- a/tests/webTestServer.ts
+++ b/tests/webTestServer.ts
@@ -269,6 +269,9 @@ if ((browser && browser === 'chrome')) {
case "win64":
defaultChromePath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe";
break;
+ case "darwin":
+ defaultChromePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
+ break;
case "linux":
defaultChromePath = "/opt/google/chrome/chrome"
break;