Merge branch 'tsserverVS-WIP' into reuseTrees

This commit is contained in:
Mohamed Hegazy
2016-06-21 11:35:25 -07:00
264 changed files with 8927 additions and 2933 deletions
+3 -1
View File
@@ -128,6 +128,7 @@ var languageServiceLibrarySources = [
var harnessCoreSources = [
"harness.ts",
"virtualFileSystem.ts",
"sourceMapRecorder.ts",
"harnessLanguageService.ts",
"fourslash.ts",
@@ -162,7 +163,8 @@ var harnessSources = harnessCoreSources.concat([
"commandLineParsing.ts",
"convertCompilerOptionsFromJson.ts",
"convertTypingOptionsFromJson.ts",
"tsserverProjectSystem.ts"
"tsserverProjectSystem.ts",
"matchFiles.ts"
].map(function (f) {
return path.join(unittestsDirectory, f);
})).concat([
+90 -48
View File
@@ -578,12 +578,6 @@ namespace ts {
}
}
function isNarrowableReference(expr: Expression): boolean {
return expr.kind === SyntaxKind.Identifier ||
expr.kind === SyntaxKind.ThisKeyword ||
expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
}
function isNarrowingExpression(expr: Expression): boolean {
switch (expr.kind) {
case SyntaxKind.Identifier:
@@ -591,7 +585,7 @@ namespace ts {
case SyntaxKind.PropertyAccessExpression:
return isNarrowableReference(expr);
case SyntaxKind.CallExpression:
return true;
return hasNarrowableArgument(<CallExpression>expr);
case SyntaxKind.ParenthesizedExpression:
return isNarrowingExpression((<ParenthesizedExpression>expr).expression);
case SyntaxKind.BinaryExpression:
@@ -602,6 +596,39 @@ namespace ts {
return false;
}
function isNarrowableReference(expr: Expression): boolean {
return expr.kind === SyntaxKind.Identifier ||
expr.kind === SyntaxKind.ThisKeyword ||
expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
}
function hasNarrowableArgument(expr: CallExpression) {
if (expr.arguments) {
for (const argument of expr.arguments) {
if (isNarrowableReference(argument)) {
return true;
}
}
}
if (expr.expression.kind === SyntaxKind.PropertyAccessExpression &&
isNarrowableReference((<PropertyAccessExpression>expr.expression).expression)) {
return true;
}
return false;
}
function isNarrowingNullCheckOperands(expr1: Expression, expr2: Expression) {
return (expr1.kind === SyntaxKind.NullKeyword || expr1.kind === SyntaxKind.Identifier && (<Identifier>expr1).text === "undefined") && isNarrowableOperand(expr2);
}
function isNarrowingTypeofOperands(expr1: Expression, expr2: Expression) {
return expr1.kind === SyntaxKind.TypeOfExpression && isNarrowableOperand((<TypeOfExpression>expr1).expression) && expr2.kind === SyntaxKind.StringLiteral;
}
function isNarrowingDiscriminant(expr: Expression) {
return expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
}
function isNarrowingBinaryExpression(expr: BinaryExpression) {
switch (expr.operatorToken.kind) {
case SyntaxKind.EqualsToken:
@@ -610,34 +637,35 @@ namespace ts {
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
if ((isNarrowingExpression(expr.left) && (expr.right.kind === SyntaxKind.NullKeyword || expr.right.kind === SyntaxKind.Identifier)) ||
(isNarrowingExpression(expr.right) && (expr.left.kind === SyntaxKind.NullKeyword || expr.left.kind === SyntaxKind.Identifier))) {
return true;
}
if (isTypeOfNarrowingBinaryExpression(expr)) {
return true;
}
return false;
return isNarrowingNullCheckOperands(expr.right, expr.left) || isNarrowingNullCheckOperands(expr.left, expr.right) ||
isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right) ||
isNarrowingDiscriminant(expr.left) || isNarrowingDiscriminant(expr.right);
case SyntaxKind.InstanceOfKeyword:
return isNarrowingExpression(expr.left);
return isNarrowableOperand(expr.left);
case SyntaxKind.CommaToken:
return isNarrowingExpression(expr.right);
}
return false;
}
function isTypeOfNarrowingBinaryExpression(expr: BinaryExpression) {
let typeOf: Expression;
if (expr.left.kind === SyntaxKind.StringLiteral) {
typeOf = expr.right;
function isNarrowableOperand(expr: Expression): boolean {
switch (expr.kind) {
case SyntaxKind.ParenthesizedExpression:
return isNarrowableOperand((<ParenthesizedExpression>expr).expression);
case SyntaxKind.BinaryExpression:
switch ((<BinaryExpression>expr).operatorToken.kind) {
case SyntaxKind.EqualsToken:
return isNarrowableOperand((<BinaryExpression>expr).left);
case SyntaxKind.CommaToken:
return isNarrowableOperand((<BinaryExpression>expr).right);
}
}
else if (expr.right.kind === SyntaxKind.StringLiteral) {
typeOf = expr.left;
}
else {
typeOf = undefined;
}
return typeOf && typeOf.kind === SyntaxKind.TypeOfExpression && isNarrowingExpression((<TypeOfExpression>typeOf).expression);
return isNarrowableReference(expr);
}
function isNarrowingSwitchStatement(switchStatement: SwitchStatement) {
const expr = switchStatement.expression;
return expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
}
function createBranchLabel(): FlowLabel {
@@ -683,8 +711,22 @@ namespace ts {
setFlowNodeReferenced(antecedent);
return <FlowCondition>{
flags,
antecedent,
expression,
antecedent
};
}
function createFlowSwitchClause(antecedent: FlowNode, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): FlowNode {
if (!isNarrowingSwitchStatement(switchStatement)) {
return antecedent;
}
setFlowNodeReferenced(antecedent);
return <FlowSwitchClause>{
flags: FlowFlags.SwitchClause,
switchStatement,
clauseStart,
clauseEnd,
antecedent
};
}
@@ -913,9 +955,12 @@ namespace ts {
preSwitchCaseFlow = currentFlow;
bind(node.caseBlock);
addAntecedent(postSwitchLabel, currentFlow);
const hasNonEmptyDefault = forEach(node.caseBlock.clauses, c => c.kind === SyntaxKind.DefaultClause && c.statements.length);
if (!hasNonEmptyDefault) {
addAntecedent(postSwitchLabel, preSwitchCaseFlow);
const hasDefault = forEach(node.caseBlock.clauses, c => c.kind === SyntaxKind.DefaultClause);
// We mark a switch statement as possibly exhaustive if it has no default clause and if all
// case clauses have unreachable end points (e.g. they all return).
node.possiblyExhaustive = !hasDefault && !postSwitchLabel.antecedents;
if (!hasDefault) {
addAntecedent(postSwitchLabel, createFlowSwitchClause(preSwitchCaseFlow, node, 0, 0));
}
currentBreakTarget = saveBreakTarget;
preSwitchCaseFlow = savePreSwitchCaseFlow;
@@ -924,25 +969,22 @@ namespace ts {
function bindCaseBlock(node: CaseBlock): void {
const clauses = node.clauses;
let fallthroughFlow = unreachableFlow;
for (let i = 0; i < clauses.length; i++) {
const clause = clauses[i];
if (clause.statements.length) {
if (currentFlow.flags & FlowFlags.Unreachable) {
currentFlow = preSwitchCaseFlow;
}
else {
const preCaseLabel = createBranchLabel();
addAntecedent(preCaseLabel, preSwitchCaseFlow);
addAntecedent(preCaseLabel, currentFlow);
currentFlow = finishFlowLabel(preCaseLabel);
}
bind(clause);
if (!(currentFlow.flags & FlowFlags.Unreachable) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) {
errorOnFirstToken(clause, Diagnostics.Fallthrough_case_in_switch);
}
const clauseStart = i;
while (!clauses[i].statements.length && i + 1 < clauses.length) {
bind(clauses[i]);
i++;
}
else {
bind(clause);
const preCaseLabel = createBranchLabel();
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow, <SwitchStatement>node.parent, clauseStart, i + 1));
addAntecedent(preCaseLabel, fallthroughFlow);
currentFlow = finishFlowLabel(preCaseLabel);
const clause = clauses[i];
bind(clause);
fallthroughFlow = currentFlow;
if (!(currentFlow.flags & FlowFlags.Unreachable) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) {
errorOnFirstToken(clause, Diagnostics.Fallthrough_case_in_switch);
}
}
}
+196 -39
View File
@@ -562,7 +562,8 @@ namespace ts {
const declarationFile = getSourceFileOfNode(declaration);
const useFile = getSourceFileOfNode(usage);
if (declarationFile !== useFile) {
if (modulekind || (!compilerOptions.outFile && !compilerOptions.out)) {
if ((modulekind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) ||
(!compilerOptions.outFile && !compilerOptions.out)) {
// nodes are in different files and order cannot be determines
return true;
}
@@ -852,7 +853,8 @@ namespace ts {
if (!result) {
if (nameNotFoundMessage) {
if (!checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg)) {
if (!checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) &&
!checkAndReportErrorForExtendingInterface(errorLocation)) {
error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg));
}
}
@@ -936,6 +938,31 @@ namespace ts {
return false;
}
function checkAndReportErrorForExtendingInterface(errorLocation: Node): boolean {
let parentClassExpression = errorLocation;
while (parentClassExpression) {
const kind = parentClassExpression.kind;
if (kind === SyntaxKind.Identifier || kind === SyntaxKind.PropertyAccessExpression) {
parentClassExpression = parentClassExpression.parent;
continue;
}
if (kind === SyntaxKind.ExpressionWithTypeArguments) {
break;
}
return false;
}
if (!parentClassExpression) {
return false;
}
const expression = (<ExpressionWithTypeArguments>parentClassExpression).expression;
if (resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)) {
error(errorLocation, Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, getTextOfNode(expression));
return true;
}
return false;
}
function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0);
// Block-scoped variables cannot be used before their definition
@@ -5185,7 +5212,6 @@ namespace ts {
if (hasProperty(stringLiteralTypes, text)) {
return stringLiteralTypes[text];
}
const type = stringLiteralTypes[text] = <StringLiteralType>createType(TypeFlags.StringLiteral);
type.text = text;
return type;
@@ -5650,6 +5676,10 @@ namespace ts {
return checkTypeComparableTo(source, target, /*errorNode*/ undefined);
}
function areTypesComparable(type1: Type, type2: Type): boolean {
return isTypeComparableTo(type1, type2) || isTypeComparableTo(type2, type1);
}
function checkTypeSubtypeOf(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean {
return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain);
}
@@ -6830,8 +6860,10 @@ namespace ts {
return !!getPropertyOfType(type, "0");
}
function isStringLiteralType(type: Type) {
return type.flags & TypeFlags.StringLiteral;
function isStringLiteralUnionType(type: Type): boolean {
return type.flags & TypeFlags.StringLiteral ? true :
type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, isStringLiteralUnionType) :
false;
}
/**
@@ -7696,6 +7728,35 @@ namespace ts {
return node;
}
function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) {
if (clause.kind === SyntaxKind.CaseClause) {
const expr = (<CaseClause>clause).expression;
return expr.kind === SyntaxKind.StringLiteral ? getStringLiteralTypeForText((<StringLiteral>expr).text) : checkExpression(expr);
}
return undefined;
}
function getSwitchClauseTypes(switchStatement: SwitchStatement): Type[] {
const links = getNodeLinks(switchStatement);
if (!links.switchTypes) {
// If all case clauses specify expressions that have unit types, we return an array
// of those unit types. Otherwise we return an empty array.
const types = map(switchStatement.caseBlock.clauses, getTypeOfSwitchClause);
links.switchTypes = forEach(types, t => !t || t.flags & TypeFlags.StringLiteral) ? types : emptyArray;
}
return links.switchTypes;
}
function eachTypeContainedIn(source: Type, types: Type[]) {
return source.flags & TypeFlags.Union ? !forEach((<UnionType>source).types, t => !contains(types, t)) : contains(types, source);
}
function filterType(type: Type, f: (t: Type) => boolean): Type {
return type.flags & TypeFlags.Union ?
getUnionType(filter((<UnionType>type).types, f)) :
f(type) ? type : neverType;
}
function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, includeOuterFunctions: boolean) {
let key: string;
if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
@@ -7733,6 +7794,9 @@ namespace ts {
else if (flow.flags & FlowFlags.Condition) {
type = getTypeAtFlowCondition(<FlowCondition>flow);
}
else if (flow.flags & FlowFlags.SwitchClause) {
type = getTypeAtSwitchClause(<FlowSwitchClause>flow);
}
else if (flow.flags & FlowFlags.Label) {
if ((<FlowLabel>flow).antecedents.length === 1) {
flow = (<FlowLabel>flow).antecedents[0];
@@ -7816,6 +7880,11 @@ namespace ts {
return type;
}
function getTypeAtSwitchClause(flow: FlowSwitchClause) {
const type = getTypeAtFlowNode(flow.antecedent);
return narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
}
function getTypeAtFlowBranchLabel(flow: FlowLabel) {
const antecedentTypes: Type[] = [];
for (const antecedent of flow.antecedents) {
@@ -7895,12 +7964,26 @@ namespace ts {
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
if (isNullOrUndefinedLiteral(expr.left) || isNullOrUndefinedLiteral(expr.right)) {
return narrowTypeByNullCheck(type, expr, assumeTrue);
const left = expr.left;
const operator = expr.operatorToken.kind;
const right = expr.right;
if (isNullOrUndefinedLiteral(right)) {
return narrowTypeByNullCheck(type, left, operator, right, assumeTrue);
}
if (expr.left.kind === SyntaxKind.TypeOfExpression && expr.right.kind === SyntaxKind.StringLiteral ||
expr.left.kind === SyntaxKind.StringLiteral && expr.right.kind === SyntaxKind.TypeOfExpression) {
return narrowTypeByTypeof(type, expr, assumeTrue);
if (isNullOrUndefinedLiteral(left)) {
return narrowTypeByNullCheck(type, right, operator, left, assumeTrue);
}
if (left.kind === SyntaxKind.TypeOfExpression && right.kind === SyntaxKind.StringLiteral) {
return narrowTypeByTypeof(type, <TypeOfExpression>left, operator, <LiteralExpression>right, assumeTrue);
}
if (right.kind === SyntaxKind.TypeOfExpression && left.kind === SyntaxKind.StringLiteral) {
return narrowTypeByTypeof(type, <TypeOfExpression>right, operator, <LiteralExpression>left, assumeTrue);
}
if (left.kind === SyntaxKind.PropertyAccessExpression) {
return narrowTypeByDiscriminant(type, <PropertyAccessExpression>left, operator, right, assumeTrue);
}
if (right.kind === SyntaxKind.PropertyAccessExpression) {
return narrowTypeByDiscriminant(type, <PropertyAccessExpression>right, operator, left, assumeTrue);
}
break;
case SyntaxKind.InstanceOfKeyword:
@@ -7911,41 +7994,35 @@ namespace ts {
return type;
}
function narrowTypeByNullCheck(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
// We have '==', '!=', '===', or '!==' operator with 'null' or 'undefined' on one side
const operator = expr.operatorToken.kind;
const nullLike = isNullOrUndefinedLiteral(expr.left) ? expr.left : expr.right;
const narrowed = isNullOrUndefinedLiteral(expr.left) ? expr.right : expr.left;
function narrowTypeByNullCheck(type: Type, target: Expression, operator: SyntaxKind, literal: Expression, assumeTrue: boolean): Type {
// We have '==', '!=', '===', or '!==' operator with 'null' or 'undefined' as value
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
assumeTrue = !assumeTrue;
}
if (!strictNullChecks || !isMatchingReference(reference, getReferenceFromExpression(narrowed))) {
if (!strictNullChecks || !isMatchingReference(reference, getReferenceFromExpression(target))) {
return type;
}
const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken;
const facts = doubleEquals ?
assumeTrue ? TypeFacts.EQUndefinedOrNull : TypeFacts.NEUndefinedOrNull :
nullLike.kind === SyntaxKind.NullKeyword ?
literal.kind === SyntaxKind.NullKeyword ?
assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull :
assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined;
return getTypeWithFacts(type, facts);
}
function narrowTypeByTypeof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
// We have '==', '!=', '====', or !==' operator with 'typeof xxx' on the left
// and string literal on the right
const narrowed = getReferenceFromExpression((<TypeOfExpression>(expr.left.kind === SyntaxKind.TypeOfExpression ? expr.left : expr.right)).expression);
const literal = <LiteralExpression>(expr.right.kind === SyntaxKind.StringLiteral ? expr.right : expr.left);
if (!isMatchingReference(reference, narrowed)) {
function narrowTypeByTypeof(type: Type, typeOfExpr: TypeOfExpression, operator: SyntaxKind, literal: LiteralExpression, assumeTrue: boolean): Type {
// We have '==', '!=', '====', or !==' operator with 'typeof xxx' and string literal operands
const target = getReferenceFromExpression(typeOfExpr.expression);
if (!isMatchingReference(reference, target)) {
// For a reference of the form 'x.y', a 'typeof x === ...' type guard resets the
// narrowed type of 'y' to its declared type.
if (containsMatchingReference(reference, narrowed)) {
if (containsMatchingReference(reference, target)) {
return declaredType;
}
return type;
}
if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsToken ||
expr.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken) {
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
assumeTrue = !assumeTrue;
}
if (assumeTrue && !(type.flags & TypeFlags.Union)) {
@@ -7963,6 +8040,58 @@ namespace ts {
return getTypeWithFacts(type, facts);
}
function narrowTypeByDiscriminant(type: Type, propAccess: PropertyAccessExpression, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
// We have '==', '!=', '===', or '!==' operator with property access as target
if (!isMatchingReference(reference, propAccess.expression)) {
return type;
}
const propName = propAccess.name.text;
const propType = getTypeOfPropertyOfType(type, propName);
if (!propType || !isStringLiteralUnionType(propType)) {
return type;
}
const discriminantType = value.kind === SyntaxKind.StringLiteral ? getStringLiteralTypeForText((<StringLiteral>value).text) : checkExpression(value);
if (!isStringLiteralUnionType(discriminantType)) {
return type;
}
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
assumeTrue = !assumeTrue;
}
if (assumeTrue) {
return filterType(type, t => areTypesComparable(getTypeOfPropertyOfType(t, propName), discriminantType));
}
if (discriminantType.flags & TypeFlags.StringLiteral) {
return filterType(type, t => getTypeOfPropertyOfType(t, propName) !== discriminantType);
}
return type;
}
function narrowTypeBySwitchOnDiscriminant(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) {
// We have switch statement with property access expression
if (!isMatchingReference(reference, (<PropertyAccessExpression>switchStatement.expression).expression)) {
return type;
}
const propName = (<PropertyAccessExpression>switchStatement.expression).name.text;
const propType = getTypeOfPropertyOfType(type, propName);
if (!propType || !isStringLiteralUnionType(propType)) {
return type;
}
const switchTypes = getSwitchClauseTypes(switchStatement);
if (!switchTypes.length) {
return type;
}
const clauseTypes = switchTypes.slice(clauseStart, clauseEnd);
const hasDefaultClause = clauseStart === clauseEnd || contains(clauseTypes, undefined);
const caseTypes = hasDefaultClause ? filter(clauseTypes, t => !!t) : clauseTypes;
const discriminantType = caseTypes.length ? getUnionType(caseTypes) : undefined;
const caseType = discriminantType && filterType(type, t => isTypeComparableTo(discriminantType, getTypeOfPropertyOfType(t, propName)));
if (!hasDefaultClause) {
return caseType;
}
const defaultType = filterType(type, t => !eachTypeContainedIn(getTypeOfPropertyOfType(t, propName), switchTypes));
return caseType ? getUnionType([caseType, defaultType]) : defaultType;
}
function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
const left = getReferenceFromExpression(expr.left);
if (!isMatchingReference(reference, left)) {
@@ -8933,10 +9062,6 @@ namespace ts {
return applyToContextualType(type, t => getIndexTypeOfStructuredType(t, kind));
}
function contextualTypeIsStringLiteralType(type: Type): boolean {
return !!(type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, isStringLiteralType) : isStringLiteralType(type));
}
// Return true if the given contextual type is a tuple-like type
function contextualTypeIsTupleLikeType(type: Type): boolean {
return !!(type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, isTupleLikeType) : isTupleLikeType(type));
@@ -10038,7 +10163,7 @@ namespace ts {
}
const prop = getPropertyOfType(apparentType, right.text);
if (!prop) {
if (right.text) {
if (right.text && !checkAndReportErrorForExtendingInterface(node)) {
error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type.flags & TypeFlags.ThisType ? apparentType : type));
}
return unknownType;
@@ -11524,7 +11649,10 @@ namespace ts {
function checkAssertion(node: AssertionExpression) {
const exprType = getRegularTypeOfObjectLiteral(checkExpression(node.expression));
checkSourceElement(node.type);
const targetType = getTypeFromTypeNode(node.type);
if (produceDiagnostics && targetType !== unknownType) {
const widenedType = getWidenedType(exprType);
if (!isTypeComparableTo(targetType, widenedType)) {
@@ -11764,10 +11892,42 @@ namespace ts {
return aggregatedTypes;
}
function isExhaustiveSwitchStatement(node: SwitchStatement): boolean {
const expr = node.expression;
if (!node.possiblyExhaustive || expr.kind !== SyntaxKind.PropertyAccessExpression) {
return false;
}
const type = checkExpression((<PropertyAccessExpression>expr).expression);
if (!(type.flags & TypeFlags.Union)) {
return false;
}
const propName = (<PropertyAccessExpression>expr).name.text;
const propType = getTypeOfPropertyOfType(type, propName);
if (!propType || !isStringLiteralUnionType(propType)) {
return false;
}
const switchTypes = getSwitchClauseTypes(node);
if (!switchTypes.length) {
return false;
}
return eachTypeContainedIn(propType, switchTypes);
}
function functionHasImplicitReturn(func: FunctionLikeDeclaration) {
if (!(func.flags & NodeFlags.HasImplicitReturn)) {
return false;
}
const lastStatement = lastOrUndefined((<Block>func.body).statements);
if (lastStatement && lastStatement.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(<SwitchStatement>lastStatement)) {
return false;
}
return true;
}
function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, contextualMapper: TypeMapper): Type[] {
const isAsync = isAsyncFunctionLike(func);
const aggregatedTypes: Type[] = [];
let hasReturnWithNoExpression = !!(func.flags & NodeFlags.HasImplicitReturn);
let hasReturnWithNoExpression = functionHasImplicitReturn(func);
let hasReturnOfTypeNever = false;
forEachReturnStatement(<Block>func.body, returnStatement => {
const expr = returnStatement.expression;
@@ -11824,7 +11984,7 @@ namespace ts {
// If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check.
// also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw
if (nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block || !(func.flags & NodeFlags.HasImplicitReturn)) {
if (nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block || !functionHasImplicitReturn(func)) {
return;
}
@@ -12602,7 +12762,7 @@ namespace ts {
function checkStringLiteralExpression(node: StringLiteral): Type {
const contextualType = getContextualType(node);
if (contextualType && contextualTypeIsStringLiteralType(contextualType)) {
if (contextualType && isStringLiteralUnionType(contextualType)) {
return getStringLiteralTypeForText(node.text);
}
@@ -13559,9 +13719,6 @@ namespace ts {
}
}
// when checking exported function declarations across modules check only duplicate implementations
// names and consistency of modifiers are verified when we check local symbol
const isExportSymbolInsideModule = symbol.parent && symbol.parent.flags & SymbolFlags.Module;
let duplicateFunctionDeclaration = false;
let multipleConstructorImplementation = false;
for (const current of declarations) {
@@ -13594,7 +13751,7 @@ namespace ts {
duplicateFunctionDeclaration = true;
}
}
else if (!isExportSymbolInsideModule && previousDeclaration && previousDeclaration.parent === node.parent && previousDeclaration.end !== node.pos) {
else if (previousDeclaration && previousDeclaration.parent === node.parent && previousDeclaration.end !== node.pos) {
reportImplementationExpectedError(previousDeclaration);
}
@@ -13628,7 +13785,7 @@ namespace ts {
}
// Abstract methods can't have an implementation -- in particular, they don't need one.
if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
!(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) {
reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
}
+335 -51
View File
@@ -412,6 +412,10 @@ namespace ts {
},
description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation_Colon
},
{
name: "disableProjectSizeLimit",
type: "boolean"
},
{
name: "strictNullChecks",
type: "boolean",
@@ -682,7 +686,7 @@ namespace ts {
// Skip over any minified JavaScript files (ending in ".min.js")
// Skip over dotted files and folders as well
const IgnoreFileNamePattern = /(\.min\.js$)|([\\/]\.[\w.])/;
const ignoreFileNamePattern = /(\.min\.js$)|([\\/]\.[\w.])/;
/**
* Parse the contents of a config file (tsconfig.json).
* @param json The contents of the config file to parse
@@ -698,78 +702,66 @@ namespace ts {
options.configFilePath = configFileName;
const fileNames = getFileNames(errors);
const { fileNames, wildcardDirectories } = getFileNames(errors);
return {
options,
fileNames,
typingOptions,
raw: json,
errors
errors,
wildcardDirectories
};
function getFileNames(errors: Diagnostic[]): string[] {
let fileNames: string[] = [];
function getFileNames(errors: Diagnostic[]): ExpandResult {
let fileNames: string[];
if (hasProperty(json, "files")) {
if (isArray(json["files"])) {
fileNames = map(<string[]>json["files"], s => combinePaths(basePath, s));
fileNames = <string[]>json["files"];
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "files", "Array"));
}
}
else {
const filesSeen: Map<boolean> = {};
let exclude: string[] = [];
if (isArray(json["exclude"])) {
exclude = json["exclude"];
let includeSpecs: string[];
if (hasProperty(json, "include")) {
if (isArray(json["include"])) {
includeSpecs = <string[]>json["include"];
}
else {
// by default exclude node_modules, and any specificied output directory
exclude = ["node_modules", "bower_components", "jspm_packages"];
}
const outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"];
if (outDir) {
exclude.push(outDir);
}
exclude = map(exclude, e => getNormalizedAbsolutePath(e, basePath));
const supportedExtensions = getSupportedExtensions(options);
Debug.assert(indexOf(supportedExtensions, ".ts") < indexOf(supportedExtensions, ".d.ts"), "Changed priority of extensions to pick");
// Get files of supported extensions in their order of resolution
for (const extension of supportedExtensions) {
const filesInDirWithExtension = host.readDirectory(basePath, extension, exclude);
for (const fileName of filesInDirWithExtension) {
// .ts extension would read the .d.ts extension files too but since .d.ts is lower priority extension,
// lets pick them when its turn comes up
if (extension === ".ts" && fileExtensionIs(fileName, ".d.ts")) {
continue;
}
if (IgnoreFileNamePattern.test(fileName)) {
continue;
}
// If this is one of the output extension (which would be .d.ts and .js if we are allowing compilation of js files)
// do not include this file if we included .ts or .tsx file with same base name as it could be output of the earlier compilation
if (extension === ".d.ts" || (options.allowJs && contains(supportedJavascriptExtensions, extension))) {
const baseName = fileName.substr(0, fileName.length - extension.length);
if (hasProperty(filesSeen, baseName + ".ts") || hasProperty(filesSeen, baseName + ".tsx")) {
continue;
}
}
filesSeen[fileName] = true;
fileNames.push(fileName);
}
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "include", "Array"));
}
}
if (hasProperty(json, "excludes") && !hasProperty(json, "exclude")) {
let excludeSpecs: string[];
if (hasProperty(json, "exclude")) {
if (isArray(json["exclude"])) {
excludeSpecs = <string[]>json["exclude"];
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "exclude", "Array"));
}
}
else if (hasProperty(json, "excludes")) {
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_option_excludes_Did_you_mean_exclude));
}
return fileNames;
else {
// By default, exclude common package folders
excludeSpecs = ["node_modules", "bower_components", "jspm_packages"];
}
// Always exclude the output directory unless explicitly included
const outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"];
if (outDir) {
excludeSpecs.push(outDir);
}
if (fileNames === undefined && includeSpecs === undefined) {
includeSpecs = ["**/*"];
}
return matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors);
}
}
@@ -865,4 +857,296 @@ namespace ts {
function trimString(s: string) {
return typeof s.trim === "function" ? s.trim() : s.replace(/^[\s]+|[\s]+$/g, "");
}
/**
* Tests for a path that ends in a recursive directory wildcard.
* Matches **, \**, **\, and \**\, but not a**b.
*
* NOTE: used \ in place of / above to avoid issues with multiline comments.
*
* Breakdown:
* (^|\/) # matches either the beginning of the string or a directory separator.
* \*\* # matches the recursive directory wildcard "**".
* \/?$ # matches an optional trailing directory separator at the end of the string.
*/
const invalidTrailingRecursionPattern = /(^|\/)\*\*\/?$/;
/**
* Tests for a path with multiple recursive directory wildcards.
* Matches **\** and **\a\**, but not **\a**b.
*
* NOTE: used \ in place of / above to avoid issues with multiline comments.
*
* Breakdown:
* (^|\/) # matches either the beginning of the string or a directory separator.
* \*\*\/ # matches a recursive directory wildcard "**" followed by a directory separator.
* (.*\/)? # optionally matches any number of characters followed by a directory separator.
* \*\* # matches a recursive directory wildcard "**"
* ($|\/) # matches either the end of the string or a directory separator.
*/
const invalidMultipleRecursionPatterns = /(^|\/)\*\*\/(.*\/)?\*\*($|\/)/;
/**
* Tests for a path containing a wildcard character in a directory component of the path.
* Matches \*\, \?\, and \a*b\, but not \a\ or \a\*.
*
* NOTE: used \ in place of / above to avoid issues with multiline comments.
*
* Breakdown:
* \/ # matches a directory separator.
* [^/]*? # matches any number of characters excluding directory separators (non-greedy).
* [*?] # matches either a wildcard character (* or ?)
* [^/]* # matches any number of characters excluding directory separators (greedy).
* \/ # matches a directory separator.
*/
const watchRecursivePattern = /\/[^/]*?[*?][^/]*\//;
/**
* Matches the portion of a wildcard path that does not contain wildcards.
* Matches \a of \a\*, or \a\b\c of \a\b\c\?\d.
*
* NOTE: used \ in place of / above to avoid issues with multiline comments.
*
* Breakdown:
* ^ # matches the beginning of the string
* [^*?]* # matches any number of non-wildcard characters
* (?=\/[^/]*[*?]) # lookahead that matches a directory separator followed by
* # a path component that contains at least one wildcard character (* or ?).
*/
const wildcardDirectoryPattern = /^[^*?]*(?=\/[^/]*[*?])/;
/**
* Expands an array of file specifications.
*
* @param fileNames The literal file names to include.
* @param include The wildcard file specifications to include.
* @param exclude The wildcard file specifications to exclude.
* @param basePath The base path for any relative file specifications.
* @param options Compiler options.
* @param host The host used to resolve files and directories.
* @param errors An array for diagnostic reporting.
*/
function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[]): ExpandResult {
basePath = normalizePath(basePath);
// The exclude spec list is converted into a regular expression, which allows us to quickly
// test whether a file or directory should be excluded before recursively traversing the
// file system.
const keyMapper = host.useCaseSensitiveFileNames ? caseSensitiveKeyMapper : caseInsensitiveKeyMapper;
// Literal file names (provided via the "files" array in tsconfig.json) are stored in a
// file map with a possibly case insensitive key. We use this map later when when including
// wildcard paths.
const literalFileMap: Map<string> = {};
// Wildcard paths (provided via the "includes" array in tsconfig.json) are stored in a
// file map with a possibly case insensitive key. We use this map to store paths matched
// via wildcard, and to handle extension priority.
const wildcardFileMap: Map<string> = {};
if (include) {
include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false);
}
if (exclude) {
exclude = validateSpecs(exclude, errors, /*allowTrailingRecursion*/ true);
}
// Wildcard directories (provided as part of a wildcard path) are stored in a
// file map that marks whether it was a regular wildcard match (with a `*` or `?` token),
// or a recursive directory. This information is used by filesystem watchers to monitor for
// new entries in these paths.
const wildcardDirectories: Map<WatchDirectoryFlags> = getWildcardDirectories(include, exclude, basePath, host.useCaseSensitiveFileNames);
// Rather than requery this for each file and filespec, we query the supported extensions
// once and store it on the expansion context.
const supportedExtensions = getSupportedExtensions(options);
// Literal files are always included verbatim. An "include" or "exclude" specification cannot
// remove a literal file.
if (fileNames) {
for (const fileName of fileNames) {
const file = combinePaths(basePath, fileName);
literalFileMap[keyMapper(file)] = file;
}
}
if (include && include.length > 0) {
for (const file of host.readDirectory(basePath, supportedExtensions, exclude, include)) {
// If we have already included a literal or wildcard path with a
// higher priority extension, we should skip this file.
//
// This handles cases where we may encounter both <file>.ts and
// <file>.d.ts (or <file>.js if "allowJs" is enabled) in the same
// directory when they are compilation outputs.
if (hasFileWithHigherPriorityExtension(file, literalFileMap, wildcardFileMap, supportedExtensions, keyMapper)) {
continue;
}
if (ignoreFileNamePattern.test(file)) {
continue;
}
// We may have included a wildcard path with a lower priority
// extension due to the user-defined order of entries in the
// "include" array. If there is a lower priority extension in the
// same directory, we should remove it.
removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMapper);
const key = keyMapper(file);
if (!hasProperty(literalFileMap, key) && !hasProperty(wildcardFileMap, key)) {
wildcardFileMap[key] = file;
}
}
}
const literalFiles = reduceProperties(literalFileMap, addFileToOutput, []);
const wildcardFiles = reduceProperties(wildcardFileMap, addFileToOutput, []);
wildcardFiles.sort(host.useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive);
return {
fileNames: literalFiles.concat(wildcardFiles),
wildcardDirectories
};
}
function validateSpecs(specs: string[], errors: Diagnostic[], allowTrailingRecursion: boolean) {
const validSpecs: string[] = [];
for (const spec of specs) {
if (!allowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) {
errors.push(createCompilerDiagnostic(Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec));
}
else if (invalidMultipleRecursionPatterns.test(spec)) {
errors.push(createCompilerDiagnostic(Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, spec));
}
else {
validSpecs.push(spec);
}
}
return validSpecs;
}
/**
* Gets directories in a set of include patterns that should be watched for changes.
*/
function getWildcardDirectories(include: string[], exclude: string[], path: string, useCaseSensitiveFileNames: boolean) {
// We watch a directory recursively if it contains a wildcard anywhere in a directory segment
// of the pattern:
//
// /a/b/**/d - Watch /a/b recursively to catch changes to any d in any subfolder recursively
// /a/b/*/d - Watch /a/b recursively to catch any d in any immediate subfolder, even if a new subfolder is added
//
// We watch a directory without recursion if it contains a wildcard in the file segment of
// the pattern:
//
// /a/b/* - Watch /a/b directly to catch any new file
// /a/b/a?z - Watch /a/b directly to catch any new file matching a?z
const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude");
const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i");
const wildcardDirectories: Map<WatchDirectoryFlags> = {};
if (include !== undefined) {
const recursiveKeys: string[] = [];
for (const file of include) {
const name = combinePaths(path, file);
if (excludeRegex && excludeRegex.test(name)) {
continue;
}
const match = wildcardDirectoryPattern.exec(name);
if (match) {
const key = useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase();
const flags = watchRecursivePattern.test(name) ? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None;
const existingFlags = getProperty(wildcardDirectories, key);
if (existingFlags === undefined || existingFlags < flags) {
wildcardDirectories[key] = flags;
if (flags === WatchDirectoryFlags.Recursive) {
recursiveKeys.push(key);
}
}
}
}
// Remove any subpaths under an existing recursively watched directory.
for (const key in wildcardDirectories) {
if (hasProperty(wildcardDirectories, key)) {
for (const recursiveKey of recursiveKeys) {
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
delete wildcardDirectories[key];
}
}
}
}
}
return wildcardDirectories;
}
/**
* Determines whether a literal or wildcard file has already been included that has a higher
* extension priority.
*
* @param file The path to the file.
* @param extensionPriority The priority of the extension.
* @param context The expansion context.
*/
function hasFileWithHigherPriorityExtension(file: string, literalFiles: Map<string>, wildcardFiles: Map<string>, extensions: string[], keyMapper: (value: string) => string) {
const extensionPriority = getExtensionPriority(file, extensions);
const adjustedExtensionPriority = adjustExtensionPriority(extensionPriority);
for (let i = ExtensionPriority.Highest; i < adjustedExtensionPriority; i++) {
const higherPriorityExtension = extensions[i];
const higherPriorityPath = keyMapper(changeExtension(file, higherPriorityExtension));
if (hasProperty(literalFiles, higherPriorityPath) || hasProperty(wildcardFiles, higherPriorityPath)) {
return true;
}
}
return false;
}
/**
* Removes files included via wildcard expansion with a lower extension priority that have
* already been included.
*
* @param file The path to the file.
* @param extensionPriority The priority of the extension.
* @param context The expansion context.
*/
function removeWildcardFilesWithLowerPriorityExtension(file: string, wildcardFiles: Map<string>, extensions: string[], keyMapper: (value: string) => string) {
const extensionPriority = getExtensionPriority(file, extensions);
const nextExtensionPriority = getNextLowestExtensionPriority(extensionPriority);
for (let i = nextExtensionPriority; i < extensions.length; i++) {
const lowerPriorityExtension = extensions[i];
const lowerPriorityPath = keyMapper(changeExtension(file, lowerPriorityExtension));
delete wildcardFiles[lowerPriorityPath];
}
}
/**
* Adds a file to an array of files.
*
* @param output The output array.
* @param file The file path.
*/
function addFileToOutput(output: string[], file: string) {
output.push(file);
return output;
}
/**
* Gets a case sensitive key.
*
* @param key The original key.
*/
function caseSensitiveKeyMapper(key: string) {
return key;
}
/**
* Gets a case insensitive key.
*
* @param key The original key.
*/
function caseInsensitiveKeyMapper(key: string) {
return key.toLowerCase();
}
}
+364 -1
View File
@@ -25,7 +25,7 @@ namespace ts {
contains,
remove,
forEachValue: forEachValueInMap,
clear
clear,
};
function forEachValueInMap(f: (key: Path, value: T) => void) {
@@ -113,6 +113,15 @@ namespace ts {
return -1;
}
export function indexOfAnyCharCode(text: string, charCodes: number[], start?: number): number {
for (let i = start || 0, len = text.length; i < len; i++) {
if (contains(charCodes, text.charCodeAt(i))) {
return i;
}
}
return -1;
}
export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number {
let count = 0;
if (array) {
@@ -138,6 +147,17 @@ namespace ts {
return result;
}
export function filterMutate<T>(array: T[], f: (x: T) => boolean): void {
let outIndex = 0;
for (const item of array) {
if (f(item)) {
array[outIndex] = item;
outIndex++;
}
}
array.length = outIndex;
}
export function map<T, U>(array: T[], f: (x: T) => U): U[] {
let result: U[];
if (array) {
@@ -156,6 +176,7 @@ namespace ts {
return array1.concat(array2);
}
// TODO: fixme (N^2) - add optional comparer so collection can be sorted before deduplication.
export function deduplicate<T>(array: T[], areEqual?: (a: T, b: T) => boolean): T[] {
let result: T[];
if (array) {
@@ -523,6 +544,28 @@ namespace ts {
return a < b ? Comparison.LessThan : Comparison.GreaterThan;
}
export function compareStrings(a: string, b: string, ignoreCase?: boolean): Comparison {
if (a === b) return Comparison.EqualTo;
if (a === undefined) return Comparison.LessThan;
if (b === undefined) return Comparison.GreaterThan;
if (ignoreCase) {
if (String.prototype.localeCompare) {
const result = a.localeCompare(b, /*locales*/ undefined, { usage: "sort", sensitivity: "accent" });
return result < 0 ? Comparison.LessThan : result > 0 ? Comparison.GreaterThan : Comparison.EqualTo;
}
a = a.toUpperCase();
b = b.toUpperCase();
if (a === b) return Comparison.EqualTo;
}
return a < b ? Comparison.LessThan : Comparison.GreaterThan;
}
export function compareStringsCaseInsensitive(a: string, b: string) {
return compareStrings(a, b, /*ignoreCase*/ true);
}
function getDiagnosticFileName(diagnostic: Diagnostic): string {
return diagnostic.file ? diagnostic.file.fileName : undefined;
}
@@ -792,12 +835,275 @@ namespace ts {
return path1 + directorySeparator + path2;
}
/**
* Removes a trailing directory separator from a path.
* @param path The path.
*/
export function removeTrailingDirectorySeparator(path: string) {
if (path.charAt(path.length - 1) === directorySeparator) {
return path.substr(0, path.length - 1);
}
return path;
}
/**
* Adds a trailing directory separator to a path, if it does not already have one.
* @param path The path.
*/
export function ensureTrailingDirectorySeparator(path: string) {
if (path.charAt(path.length - 1) !== directorySeparator) {
return path + directorySeparator;
}
return path;
}
export function comparePaths(a: string, b: string, currentDirectory: string, ignoreCase?: boolean) {
if (a === b) return Comparison.EqualTo;
if (a === undefined) return Comparison.LessThan;
if (b === undefined) return Comparison.GreaterThan;
a = removeTrailingDirectorySeparator(a);
b = removeTrailingDirectorySeparator(b);
const aComponents = getNormalizedPathComponents(a, currentDirectory);
const bComponents = getNormalizedPathComponents(b, currentDirectory);
const sharedLength = Math.min(aComponents.length, bComponents.length);
for (let i = 0; i < sharedLength; i++) {
const result = compareStrings(aComponents[i], bComponents[i], ignoreCase);
if (result !== Comparison.EqualTo) {
return result;
}
}
return compareValues(aComponents.length, bComponents.length);
}
export function containsPath(parent: string, child: string, currentDirectory: string, ignoreCase?: boolean) {
if (parent === undefined || child === undefined) return false;
if (parent === child) return true;
parent = removeTrailingDirectorySeparator(parent);
child = removeTrailingDirectorySeparator(child);
if (parent === child) return true;
const parentComponents = getNormalizedPathComponents(parent, currentDirectory);
const childComponents = getNormalizedPathComponents(child, currentDirectory);
if (childComponents.length < parentComponents.length) {
return false;
}
for (let i = 0; i < parentComponents.length; i++) {
const result = compareStrings(parentComponents[i], childComponents[i], ignoreCase);
if (result !== Comparison.EqualTo) {
return false;
}
}
return true;
}
export function fileExtensionIs(path: string, extension: string): boolean {
const pathLen = path.length;
const extLen = extension.length;
return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension;
}
export function fileExtensionIsAny(path: string, extensions: string[]): boolean {
for (const extension of extensions) {
if (fileExtensionIs(path, extension)) {
return true;
}
}
return false;
}
// Reserved characters, forces escaping of any non-word (or digit), non-whitespace character.
// It may be inefficient (we could just match (/[-[\]{}()*+?.,\\^$|#\s]/g), but this is future
// proof.
const reservedCharacterPattern = /[^\w\s\/]/g;
const wildcardCharCodes = [CharacterCodes.asterisk, CharacterCodes.question];
export function getRegularExpressionForWildcard(specs: string[], basePath: string, usage: "files" | "directories" | "exclude") {
if (specs === undefined || specs.length === 0) {
return undefined;
}
let pattern = "";
let hasWrittenSubpattern = false;
spec: for (const spec of specs) {
if (!spec) {
continue;
}
let subpattern = "";
let hasRecursiveDirectoryWildcard = false;
let hasWrittenComponent = false;
const components = getNormalizedPathComponents(spec, basePath);
if (usage !== "exclude" && components[components.length - 1] === "**") {
continue spec;
}
// getNormalizedPathComponents includes the separator for the root component.
// We need to remove to create our regex correctly.
components[0] = removeTrailingDirectorySeparator(components[0]);
let optionalCount = 0;
for (const component of components) {
if (component === "**") {
if (hasRecursiveDirectoryWildcard) {
continue spec;
}
subpattern += "(/.+?)?";
hasRecursiveDirectoryWildcard = true;
hasWrittenComponent = true;
}
else {
if (usage === "directories") {
subpattern += "(";
optionalCount++;
}
if (hasWrittenComponent) {
subpattern += directorySeparator;
}
subpattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter);
hasWrittenComponent = true;
}
}
while (optionalCount > 0) {
subpattern += ")?";
optionalCount--;
}
if (hasWrittenSubpattern) {
pattern += "|";
}
pattern += "(" + subpattern + ")";
hasWrittenSubpattern = true;
}
if (!pattern) {
return undefined;
}
return "^(" + pattern + (usage === "exclude" ? ")($|/)" : ")$");
}
function replaceWildcardCharacter(match: string) {
return match === "*" ? "[^/]*" : match === "?" ? "[^/]" : "\\" + match;
}
export interface FileSystemEntries {
files: string[];
directories: string[];
}
export interface FileMatcherPatterns {
includeFilePattern: string;
includeDirectoryPattern: string;
excludePattern: string;
basePaths: string[];
}
export function getFileMatcherPatterns(path: string, extensions: string[], excludes: string[], includes: string[], useCaseSensitiveFileNames: boolean, currentDirectory: string): FileMatcherPatterns {
path = normalizePath(path);
currentDirectory = normalizePath(currentDirectory);
const absolutePath = combinePaths(currentDirectory, path);
return {
includeFilePattern: getRegularExpressionForWildcard(includes, absolutePath, "files"),
includeDirectoryPattern: getRegularExpressionForWildcard(includes, absolutePath, "directories"),
excludePattern: getRegularExpressionForWildcard(excludes, absolutePath, "exclude"),
basePaths: getBasePaths(path, includes, useCaseSensitiveFileNames)
};
}
export function matchFiles(path: string, extensions: string[], excludes: string[], includes: string[], useCaseSensitiveFileNames: boolean, currentDirectory: string, getFileSystemEntries: (path: string) => FileSystemEntries): string[] {
path = normalizePath(path);
currentDirectory = normalizePath(currentDirectory);
const patterns = getFileMatcherPatterns(path, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory);
const regexFlag = useCaseSensitiveFileNames ? "" : "i";
const includeFileRegex = patterns.includeFilePattern && new RegExp(patterns.includeFilePattern, regexFlag);
const includeDirectoryRegex = patterns.includeDirectoryPattern && new RegExp(patterns.includeDirectoryPattern, regexFlag);
const excludeRegex = patterns.excludePattern && new RegExp(patterns.excludePattern, regexFlag);
const result: string[] = [];
for (const basePath of patterns.basePaths) {
visitDirectory(basePath, combinePaths(currentDirectory, basePath));
}
return result;
function visitDirectory(path: string, absolutePath: string) {
const { files, directories } = getFileSystemEntries(path);
for (const current of files) {
const name = combinePaths(path, current);
const absoluteName = combinePaths(absolutePath, current);
if ((!extensions || fileExtensionIsAny(name, extensions)) &&
(!includeFileRegex || includeFileRegex.test(absoluteName)) &&
(!excludeRegex || !excludeRegex.test(absoluteName))) {
result.push(name);
}
}
for (const current of directories) {
const name = combinePaths(path, current);
const absoluteName = combinePaths(absolutePath, current);
if ((!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) &&
(!excludeRegex || !excludeRegex.test(absoluteName))) {
visitDirectory(name, absoluteName);
}
}
}
}
/**
* Computes the unique non-wildcard base paths amongst the provided include patterns.
*/
function getBasePaths(path: string, includes: string[], useCaseSensitiveFileNames: boolean) {
// Storage for our results in the form of literal paths (e.g. the paths as written by the user).
const basePaths: string[] = [path];
if (includes) {
// Storage for literal base paths amongst the include patterns.
const includeBasePaths: string[] = [];
for (const include of includes) {
if (isRootedDiskPath(include)) {
const wildcardOffset = indexOfAnyCharCode(include, wildcardCharCodes);
const includeBasePath = wildcardOffset < 0
? removeTrailingDirectorySeparator(getDirectoryPath(include))
: include.substring(0, include.lastIndexOf(directorySeparator, wildcardOffset));
// Append the literal and canonical candidate base paths.
includeBasePaths.push(includeBasePath);
}
}
// Sort the offsets array using either the literal or canonical path representations.
includeBasePaths.sort(useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive);
// Iterate over each include base path and include unique base paths that are not a
// subpath of an existing base path
include: for (let i = 0; i < includeBasePaths.length; i++) {
const includeBasePath = includeBasePaths[i];
for (let j = 0; j < basePaths.length; j++) {
if (containsPath(basePaths[j], includeBasePath, path, !useCaseSensitiveFileNames)) {
continue include;
}
}
basePaths.push(includeBasePath);
}
}
return basePaths;
}
export function ensureScriptKind(fileName: string, scriptKind?: ScriptKind): ScriptKind {
// Using scriptKind as a condition handles both:
// - 'scriptKind' is unspecified and thus it is `undefined`
@@ -846,6 +1152,59 @@ namespace ts {
return false;
}
/**
* Extension boundaries by priority. Lower numbers indicate higher priorities, and are
* aligned to the offset of the highest priority extension in the
* allSupportedExtensions array.
*/
export const enum ExtensionPriority {
TypeScriptFiles = 0,
DeclarationAndJavaScriptFiles = 2,
Limit = 5,
Highest = TypeScriptFiles,
Lowest = DeclarationAndJavaScriptFiles,
}
export function getExtensionPriority(path: string, supportedExtensions: string[]): ExtensionPriority {
for (let i = supportedExtensions.length - 1; i >= 0; i--) {
if (fileExtensionIs(path, supportedExtensions[i])) {
return adjustExtensionPriority(<ExtensionPriority>i);
}
}
// If its not in the list of supported extensions, this is likely a
// TypeScript file with a non-ts extension
return ExtensionPriority.Highest;
}
/**
* Adjusts an extension priority to be the highest priority within the same range.
*/
export function adjustExtensionPriority(extensionPriority: ExtensionPriority): ExtensionPriority {
if (extensionPriority < ExtensionPriority.DeclarationAndJavaScriptFiles) {
return ExtensionPriority.TypeScriptFiles;
}
else if (extensionPriority < ExtensionPriority.Limit) {
return ExtensionPriority.DeclarationAndJavaScriptFiles;
}
else {
return ExtensionPriority.Limit;
}
}
/**
* Gets the next lowest extension priority for a given priority.
*/
export function getNextLowestExtensionPriority(extensionPriority: ExtensionPriority): ExtensionPriority {
if (extensionPriority < ExtensionPriority.DeclarationAndJavaScriptFiles) {
return ExtensionPriority.DeclarationAndJavaScriptFiles;
}
else {
return ExtensionPriority.Limit;
}
}
const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"];
export function removeFileExtension(path: string): string {
for (const ext of extensionsToRemove) {
@@ -865,6 +1224,10 @@ namespace ts {
return ext === ".jsx" || ext === ".tsx";
}
export function changeExtension<T extends string | Path>(path: T, newExtension: string): T {
return <T>(removeFileExtension(path) + newExtension);
}
export interface ObjectAllocator {
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile;
+12 -4
View File
@@ -1935,6 +1935,10 @@
"category": "Error",
"code": 2688
},
"Cannot extend an interface '{0}'. Did you mean 'implements'?": {
"category": "Error",
"code": 2689
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
@@ -2228,6 +2232,14 @@
"category": "Error",
"code": 5009
},
"File specification cannot end in a recursive directory wildcard ('**'): '{0}'.": {
"category": "Error",
"code": 5010
},
"File specification cannot contain multiple recursive directory wildcards ('**'): '{0}'.": {
"category": "Error",
"code": 5011
},
"Cannot read file '{0}': {1}": {
"category": "Error",
"code": 5012
@@ -2921,10 +2933,6 @@
"category": "Error",
"code": 8012
},
"'property declarations' can only be used in a .ts file.": {
"category": "Error",
"code": 8014
},
"'enum declarations' can only be used in a .ts file.": {
"category": "Error",
"code": 8015
+8 -7
View File
@@ -2076,7 +2076,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function createPropertyAccessExpression(expression: Expression, name: Identifier): PropertyAccessExpression {
const result = <PropertyAccessExpression>createSynthesizedNode(SyntaxKind.PropertyAccessExpression);
result.expression = parenthesizeForAccess(expression);
result.dotToken = createSynthesizedNode(SyntaxKind.DotToken);
result.name = name;
return result;
}
@@ -2223,11 +2222,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
// Returns 'true' if the code was actually indented, false otherwise.
// If the code is not indented, an optional valueToWriteWhenNotIndenting will be
// emitted instead.
function indentIfOnDifferentLines(parent: Node, node1: Node, node2: Node, valueToWriteWhenNotIndenting?: string): boolean {
function indentIfOnDifferentLines(parent: Node, node1: TextRange, node2: TextRange, valueToWriteWhenNotIndenting?: string): boolean {
const realNodesAreOnDifferentLines = !nodeIsSynthesized(parent) && !nodeEndIsOnSameLineAsNodeStart(node1, node2);
// Always use a newline for synthesized code if the synthesizer desires it.
const synthesizedNodeIsOnDifferentLine = synthesizedNodeStartsOnNewLine(node2);
const synthesizedNodeIsOnDifferentLine = synthesizedNodeStartsOnNewLine(node2 as Node);
if (realNodesAreOnDifferentLines || synthesizedNodeIsOnDifferentLine) {
increaseIndent();
@@ -2257,7 +2256,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
emit(node.expression);
const indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken);
const dotRangeStart = nodeIsSynthesized(node.expression) ? -1 : node.expression.end;
const dotRangeEnd = nodeIsSynthesized(node.expression) ? -1 : skipTrivia(currentText, node.expression.end) + 1;
const dotToken = <TextRange>{ pos: dotRangeStart, end: dotRangeEnd };
const indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, dotToken);
// 1 .toString is a valid property access, emit a space after the literal
// Also emit a space if expression is a integer const enum value - it will appear in generated code as numeric literal
@@ -2283,7 +2285,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
write(".");
}
const indentedAfterDot = indentIfOnDifferentLines(node, node.dotToken, node.name);
const indentedAfterDot = indentIfOnDifferentLines(node, dotToken, node.name);
emit(node.name);
decreaseIndentIf(indentedBeforeDot, indentedAfterDot);
}
@@ -2780,7 +2782,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
const identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefineTempVariablesInPlace*/ false, /*shouldEmitCommaBeforeAssignment*/ false);
synthesizedLHS.expression = identifier;
(<PropertyAccessExpression>synthesizedLHS).dotToken = leftHandSideExpression.dotToken;
(<PropertyAccessExpression>synthesizedLHS).name = leftHandSideExpression.name;
write(", ");
}
@@ -3758,7 +3759,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
getLineOfLocalPositionFromLineMap(currentLineMap, node2.end);
}
function nodeEndIsOnSameLineAsNodeStart(node1: Node, node2: Node) {
function nodeEndIsOnSameLineAsNodeStart(node1: TextRange, node2: TextRange) {
return getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) ===
getLineOfLocalPositionFromLineMap(currentLineMap, skipTrivia(currentText, node2.pos));
}
+1 -3
View File
@@ -137,7 +137,6 @@ namespace ts {
return visitNodes(cbNodes, (<ObjectLiteralExpression>node).properties);
case SyntaxKind.PropertyAccessExpression:
return visitNode(cbNode, (<PropertyAccessExpression>node).expression) ||
visitNode(cbNode, (<PropertyAccessExpression>node).dotToken) ||
visitNode(cbNode, (<PropertyAccessExpression>node).name);
case SyntaxKind.ElementAccessExpression:
return visitNode(cbNode, (<ElementAccessExpression>node).expression) ||
@@ -3572,7 +3571,7 @@ namespace ts {
// If it wasn't then just try to parse out a '.' and report an error.
const node = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, expression.pos);
node.expression = expression;
node.dotToken = parseExpectedToken(SyntaxKind.DotToken, /*reportAtCurrentPosition*/ false, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access);
parseExpectedToken(SyntaxKind.DotToken, /*reportAtCurrentPosition*/ false, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access);
node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true);
return finishNode(node);
}
@@ -3808,7 +3807,6 @@ namespace ts {
if (dotToken) {
const propertyAccess = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, expression.pos);
propertyAccess.expression = expression;
propertyAccess.dotToken = dotToken;
propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true);
expression = finishNode(propertyAccess);
continue;
+20 -4
View File
@@ -180,7 +180,7 @@ namespace ts {
function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) {
return options.typeRoots ||
defaultTypeRoots.map(d => combinePaths(options.configFilePath ? getDirectoryPath(options.configFilePath) : host.getCurrentDirectory(), d));
map(defaultTypeRoots, d => combinePaths(options.configFilePath ? getDirectoryPath(options.configFilePath) : host.getCurrentDirectory(), d));
}
/**
@@ -1151,7 +1151,8 @@ namespace ts {
getSymbolCount: () => getDiagnosticsProducingTypeChecker().getSymbolCount(),
getTypeCount: () => getDiagnosticsProducingTypeChecker().getTypeCount(),
getFileProcessingDiagnostics: () => fileProcessingDiagnostics,
getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives
getResolvedTypeReferenceDirectives: () => resolvedTypeReferenceDirectives,
dropDiagnosticsProducingTypeChecker
};
verifyCompilerOptions();
@@ -1345,6 +1346,10 @@ namespace ts {
return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true));
}
function dropDiagnosticsProducingTypeChecker() {
diagnosticsProducingTypeChecker = undefined;
}
function getTypeChecker() {
return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false));
}
@@ -1601,8 +1606,19 @@ namespace ts {
}
break;
case SyntaxKind.PropertyDeclaration:
diagnostics.push(createDiagnosticForNode(node, Diagnostics.property_declarations_can_only_be_used_in_a_ts_file));
return true;
const propertyDeclaration = <PropertyDeclaration>node;
if (propertyDeclaration.modifiers) {
for (const modifier of propertyDeclaration.modifiers) {
if (modifier.kind !== SyntaxKind.StaticKeyword) {
diagnostics.push(createDiagnosticForNode(modifier, Diagnostics._0_can_only_be_used_in_a_ts_file, tokenToString(modifier.kind)));
return true;
}
}
}
if (checkTypeAnnotation((<PropertyDeclaration>node).type)) {
return true;
}
break;
case SyntaxKind.EnumDeclaration:
diagnostics.push(createDiagnosticForNode(node, Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file));
return true;
+69 -64
View File
@@ -15,6 +15,7 @@ namespace ts {
useCaseSensitiveFileNames: boolean;
write(s: string): void;
readFile(path: string, encoding?: string): string;
getFileSize?(path: string): number;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
watchFile?(path: string, callback: FileWatcherCallback): FileWatcher;
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
@@ -25,7 +26,7 @@ namespace ts {
getExecutingFilePath(): string;
getCurrentDirectory(): string;
getDirectories(path: string): string[];
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[];
getModifiedTime?(path: string): Date;
createHash?(data: string): string;
getMemoryUsage?(): number;
@@ -73,17 +74,18 @@ namespace ts {
readFile(path: string): string;
writeFile(path: string, contents: string): void;
getDirectories(path: string): string[];
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
readDirectory(path: string, extensions?: string[], basePaths?: string[], excludeEx?: string, includeFileEx?: string, includeDirEx?: string): string[];
watchFile?(path: string, callback: FileWatcherCallback): FileWatcher;
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
realpath(path: string): string;
};
export var sys: System = (function () {
export var sys: System = (function() {
function getWScriptSystem(): System {
const fso = new ActiveXObject("Scripting.FileSystemObject");
const shell = new ActiveXObject("WScript.Shell");
const fileStream = new ActiveXObject("ADODB.Stream");
fileStream.Type = 2 /*text*/;
@@ -151,10 +153,6 @@ namespace ts {
}
}
function getCanonicalPath(path: string): string {
return path.toLowerCase();
}
function getNames(collection: any): string[] {
const result: string[] = [];
for (let e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
@@ -168,28 +166,20 @@ namespace ts {
return getNames(folder.subfolders);
}
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
const result: string[] = [];
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
visitDirectory(path);
return result;
function visitDirectory(path: string) {
function getAccessibleFileSystemEntries(path: string): FileSystemEntries {
try {
const folder = fso.GetFolder(path || ".");
const files = getNames(folder.files);
for (const current of files) {
const name = combinePaths(path, current);
if ((!extension || fileExtensionIs(name, extension)) && !contains(exclude, getCanonicalPath(name))) {
result.push(name);
}
}
const subfolders = getNames(folder.subfolders);
for (const current of subfolders) {
const name = combinePaths(path, current);
if (!contains(exclude, getCanonicalPath(name))) {
visitDirectory(name);
}
}
const directories = getNames(folder.subfolders);
return { files, directories };
}
catch (e) {
return { files: [], directories: [] };
}
}
function readDirectory(path: string, extensions?: string[], excludes?: string[], includes?: string[]): string[] {
return matchFiles(path, extensions, excludes, includes, /*useCaseSensitiveFileNames*/ false, shell.CurrentDirectory, getAccessibleFileSystemEntries);
}
return {
@@ -219,7 +209,7 @@ namespace ts {
return WScript.ScriptFullName;
},
getCurrentDirectory() {
return new ActiveXObject("WScript.Shell").CurrentDirectory;
return shell.CurrentDirectory;
},
getDirectories,
readDirectory,
@@ -380,8 +370,43 @@ namespace ts {
}
}
function getCanonicalPath(path: string): string {
return useCaseSensitiveFileNames ? path : path.toLowerCase();
function getAccessibleFileSystemEntries(path: string): FileSystemEntries {
try {
const entries = _fs.readdirSync(path || ".").sort();
const files: string[] = [];
const directories: string[] = [];
for (const entry of entries) {
// This is necessary because on some file system node fails to exclude
// "." and "..". See https://github.com/nodejs/node/issues/4002
if (entry === "." || entry === "..") {
continue;
}
const name = combinePaths(path, entry);
let stat: any;
try {
stat = _fs.statSync(name);
}
catch (e) {
continue;
}
if (stat.isFile()) {
files.push(entry);
}
else if (stat.isDirectory()) {
directories.push(entry);
}
}
return { files, directories };
}
catch (e) {
return { files: [], directories: [] };
}
}
function readDirectory(path: string, extensions?: string[], excludes?: string[], includes?: string[]): string[] {
return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), getAccessibleFileSystemEntries);
}
const enum FileSystemEntryKind {
@@ -414,39 +439,6 @@ namespace ts {
return filter<string>(_fs.readdirSync(path), p => fileSystemEntryExists(combinePaths(path, p), FileSystemEntryKind.Directory));
}
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
const result: string[] = [];
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
visitDirectory(path);
return result;
function visitDirectory(path: string) {
const files = _fs.readdirSync(path || ".").sort();
const directories: string[] = [];
for (const current of files) {
// This is necessary because on some file system node fails to exclude
// "." and "..". See https://github.com/nodejs/node/issues/4002
if (current === "." || current === "..") {
continue;
}
const name = combinePaths(path, current);
if (!contains(exclude, getCanonicalPath(name))) {
const stat = _fs.statSync(name);
if (stat.isFile()) {
if (!extension || fileExtensionIs(name, extension)) {
result.push(name);
}
}
else if (stat.isDirectory()) {
directories.push(name);
}
}
}
for (const current of directories) {
visitDirectory(current);
}
}
}
return {
args: process.argv.slice(2),
newLine: _os.EOL,
@@ -503,7 +495,7 @@ namespace ts {
}
);
},
resolvePath: function (path: string): string {
resolvePath: function(path: string): string {
return _path.resolve(path);
},
fileExists,
@@ -540,6 +532,16 @@ namespace ts {
}
return process.memoryUsage().heapUsed;
},
getFileSize(path) {
try {
const stat = _fs.statSync(path);
if (stat.isFile()) {
return stat.size;
}
}
catch (e) { }
return 0;
},
exit(exitCode?: number): void {
process.exit(exitCode);
},
@@ -575,7 +577,10 @@ namespace ts {
getExecutingFilePath: () => ChakraHost.executingFile,
getCurrentDirectory: () => ChakraHost.currentDirectory,
getDirectories: ChakraHost.getDirectories,
readDirectory: ChakraHost.readDirectory,
readDirectory: (path: string, extensions?: string[], excludes?: string[], includes?: string[]) => {
const pattern = getFileMatcherPatterns(path, extensions, excludes, includes, !!ChakraHost.useCaseSensitiveFileNames, ChakraHost.currentDirectory);
return ChakraHost.readDirectory(path, extensions, pattern.basePaths, pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern);
},
exit: ChakraHost.quit,
realpath
};
+36 -5
View File
@@ -980,7 +980,6 @@ namespace ts {
// @kind(SyntaxKind.PropertyAccessExpression)
export interface PropertyAccessExpression extends MemberExpression, Declaration {
expression: LeftHandSideExpression;
dotToken: Node;
name: Identifier;
}
@@ -1188,6 +1187,7 @@ namespace ts {
export interface SwitchStatement extends Statement {
expression: Expression;
caseBlock: CaseBlock;
possiblyExhaustive?: boolean;
}
// @kind(SyntaxKind.CaseBlock)
@@ -1554,8 +1554,9 @@ namespace ts {
Assignment = 1 << 4, // Assignment
TrueCondition = 1 << 5, // Condition known to be true
FalseCondition = 1 << 6, // Condition known to be false
Referenced = 1 << 7, // Referenced as antecedent once
Shared = 1 << 8, // Referenced as antecedent more than once
SwitchClause = 1 << 7, // Switch statement clause
Referenced = 1 << 8, // Referenced as antecedent once
Shared = 1 << 9, // Referenced as antecedent more than once
Label = BranchLabel | LoopLabel,
Condition = TrueCondition | FalseCondition
}
@@ -1591,6 +1592,13 @@ namespace ts {
antecedent: FlowNode;
}
export interface FlowSwitchClause extends FlowNode {
switchStatement: SwitchStatement;
clauseStart: number; // Start index of case/default clause range
clauseEnd: number; // End index of case/default clause range
antecedent: FlowNode;
}
export interface AmdDependency {
path: string;
name: string;
@@ -1669,7 +1677,15 @@ namespace ts {
}
export interface ParseConfigHost {
readDirectory(rootDir: string, extension: string, exclude: string[]): string[];
useCaseSensitiveFileNames: boolean;
readDirectory(rootDir: string, extensions: string[], excludes: string[], includes: string[]): string[];
/**
* Gets a value indicating whether the specified path exists and is a file.
* @param path The path to test.
*/
fileExists(path: string): boolean;
}
export interface WriteFileCallback {
@@ -1725,6 +1741,7 @@ namespace ts {
// For testing purposes only. Should not be used by any other consumers (including the
// language service).
/* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker;
/* @internal */ dropDiagnosticsProducingTypeChecker(): void;
/* @internal */ getClassifiableNames(): Map<string>;
@@ -2185,6 +2202,7 @@ namespace ts {
resolvedJsxType?: Type; // resolved element attributes type of a JSX openinglike element
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
switchTypes?: Type[]; // Cached array of switch case expression types
}
export const enum TypeFlags {
@@ -2224,7 +2242,8 @@ namespace ts {
/* @internal */
Nullable = Undefined | Null,
Falsy = String | Number | Boolean | Void | Undefined | Null,
/* @internal */
Falsy = Void | Undefined | Null, // TODO: Add false, 0, and ""
/* @internal */
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null | Never,
/* @internal */
@@ -2561,6 +2580,7 @@ namespace ts {
/* @internal */ suppressOutputPathCheck?: boolean;
target?: ScriptTarget;
traceResolution?: boolean;
disableSizeLimit?: boolean;
types?: string[];
/** Paths used to used to compute primary types search locations */
typeRoots?: string[];
@@ -2649,6 +2669,17 @@ namespace ts {
fileNames: string[];
raw?: any;
errors: Diagnostic[];
wildcardDirectories?: Map<WatchDirectoryFlags>;
}
export const enum WatchDirectoryFlags {
None = 0,
Recursive = 1 << 0,
}
export interface ExpandResult {
fileNames: string[];
wildcardDirectories: Map<WatchDirectoryFlags>;
}
/* @internal */
+7 -1
View File
@@ -2330,7 +2330,9 @@ namespace ts {
export function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) {
let sourceFilePath = getNormalizedAbsolutePath(sourceFile.fileName, host.getCurrentDirectory());
sourceFilePath = sourceFilePath.replace(host.getCommonSourceDirectory(), "");
const commonSourceDirectory = host.getCommonSourceDirectory();
const isSourceFileInCommonSourceDirectory = host.getCanonicalFileName(sourceFilePath).indexOf(host.getCanonicalFileName(commonSourceDirectory)) === 0;
sourceFilePath = isSourceFileInCommonSourceDirectory ? sourceFilePath.substring(commonSourceDirectory.length) : sourceFilePath;
return combinePaths(newDirPath, sourceFilePath);
}
@@ -2714,6 +2716,10 @@ namespace ts {
return forEach(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension));
}
export function hasTypeScriptFileExtension(fileName: string) {
return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension));
}
/**
* Replace each instance of non-ascii characters by one, two, three, or four escape sequences
* representing the UTF-8 encoding of the character, and return the expanded char code list.
+5
View File
@@ -167,8 +167,13 @@ declare module chai {
module assert {
function equal(actual: any, expected: any, message?: string): void;
function notEqual(actual: any, expected: any, message?: string): void;
function deepEqual<T>(actual: T, expected: T, message?: string): void;
function notDeepEqual<T>(actual: T, expected: T, message?: string): void;
function lengthOf(object: any[], length: number, message?: string): void;
function isTrue(value: any, message?: string): void;
function isFalse(value: any, message?: string): void;
function isOk(actual: any, message?: string): void;
function isUndefined(value: any, message?: string): void;
function isDefined(value: any, message?: string): void;
}
}
+116 -65
View File
@@ -202,7 +202,7 @@ namespace FourSlash {
// Whether or not we should format on keystrokes
public enableFormatting = true;
public formatCodeOptions: ts.FormatCodeOptions;
public formatCodeSettings: ts.FormatCodeSettings;
private inputFiles: ts.Map<string> = {}; // Map between inputFile's fileName and its content for easily looking up when resolving references
@@ -309,22 +309,22 @@ namespace FourSlash {
Harness.Compiler.getDefaultLibrarySourceFile().text, /*isRootFile*/ false);
}
this.formatCodeOptions = {
IndentSize: 4,
TabSize: 4,
NewLineCharacter: Harness.IO.newLine(),
ConvertTabsToSpaces: true,
IndentStyle: ts.IndentStyle.Smart,
InsertSpaceAfterCommaDelimiter: true,
InsertSpaceAfterSemicolonInForStatements: true,
InsertSpaceBeforeAndAfterBinaryOperators: true,
InsertSpaceAfterKeywordsInControlFlowStatements: true,
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
PlaceOpenBraceOnNewLineForFunctions: false,
PlaceOpenBraceOnNewLineForControlBlocks: false,
this.formatCodeSettings = {
indentSize: 4,
tabSize: 4,
newLineCharacter: Harness.IO.newLine(),
convertTabsToSpaces: true,
indentStyle: ts.IndentStyle.Smart,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
};
// Open the first file by default
@@ -730,30 +730,6 @@ namespace FourSlash {
}
}
public verifyReferencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) {
const references = this.getReferencesAtCaret();
if (!references || references.length === 0) {
this.raiseError("verifyReferencesAtPositionListContains failed - found 0 references, expected at least one.");
}
for (let i = 0; i < references.length; i++) {
const reference = references[i];
if (reference && reference.fileName === fileName && reference.textSpan.start === start && ts.textSpanEnd(reference.textSpan) === end) {
if (typeof isWriteAccess !== "undefined" && reference.isWriteAccess !== isWriteAccess) {
this.raiseError(`verifyReferencesAtPositionListContains failed - item isWriteAccess value does not match, actual: ${reference.isWriteAccess}, expected: ${isWriteAccess}.`);
}
if (typeof isDefinition !== "undefined" && reference.isDefinition !== isDefinition) {
this.raiseError(`verifyReferencesAtPositionListContains failed - item isDefinition value does not match, actual: ${reference.isDefinition}, expected: ${isDefinition}.`);
}
return;
}
}
const missingItem = { fileName, start, end, isWriteAccess, isDefinition };
this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(references)})`);
}
public verifyReferencesCountIs(count: number, localFilesOnly = true) {
const references = this.getReferencesAtCaret();
let referencesCount = 0;
@@ -777,6 +753,73 @@ namespace FourSlash {
}
}
public verifyReferencesAre(expectedReferences: Range[]) {
const actualReferences = this.getReferencesAtCaret() || [];
if (actualReferences.length > expectedReferences.length) {
// Find the unaccounted-for reference.
for (const actual of actualReferences) {
if (!ts.forEach(expectedReferences, r => r.start === actual.textSpan.start)) {
this.raiseError(`A reference ${actual} is unaccounted for.`);
}
}
// Probably will never reach here.
this.raiseError(`There are ${actualReferences.length} references but only ${expectedReferences.length} were expected.`);
}
for (const reference of expectedReferences) {
const {fileName, start, end} = reference;
if (reference.marker) {
const {isWriteAccess, isDefinition} = reference.marker.data;
this.verifyReferencesWorker(actualReferences, fileName, start, end, isWriteAccess, isDefinition);
}
else {
this.verifyReferencesWorker(actualReferences, fileName, start, end);
}
}
}
public verifyReferencesOf({fileName, start}: Range, references: Range[]) {
this.openFile(fileName);
this.goToPosition(start);
this.verifyReferencesAre(references);
}
public verifyRangesReferenceEachOther(ranges?: Range[]) {
ranges = ranges || this.getRanges();
assert(ranges.length);
for (const range of ranges) {
this.verifyReferencesOf(range, ranges);
}
}
public verifyReferencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) {
const references = this.getReferencesAtCaret();
if (!references || references.length === 0) {
this.raiseError("verifyReferencesAtPositionListContains failed - found 0 references, expected at least one.");
}
this.verifyReferencesWorker(references, fileName, start, end, isWriteAccess, isDefinition);
}
private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) {
for (let i = 0; i < references.length; i++) {
const reference = references[i];
if (reference && reference.fileName === fileName && reference.textSpan.start === start && ts.textSpanEnd(reference.textSpan) === end) {
if (typeof isWriteAccess !== "undefined" && reference.isWriteAccess !== isWriteAccess) {
this.raiseError(`verifyReferencesAtPositionListContains failed - item isWriteAccess value does not match, actual: ${reference.isWriteAccess}, expected: ${isWriteAccess}.`);
}
if (typeof isDefinition !== "undefined" && reference.isDefinition !== isDefinition) {
this.raiseError(`verifyReferencesAtPositionListContains failed - item isDefinition value does not match, actual: ${reference.isDefinition}, expected: ${isDefinition}.`);
}
return;
}
}
const missingItem = { fileName, start, end, isWriteAccess, isDefinition };
this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(references)})`);
}
private getMemberListAtCaret() {
return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition);
}
@@ -1278,7 +1321,7 @@ namespace FourSlash {
// Handle post-keystroke formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeSettings);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
// this.checkPostEditInvariants();
@@ -1316,7 +1359,7 @@ namespace FourSlash {
// Handle post-keystroke formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeSettings);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
}
@@ -1369,7 +1412,7 @@ namespace FourSlash {
// Handle post-keystroke formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeSettings);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
// this.checkPostEditInvariants();
@@ -1395,7 +1438,7 @@ namespace FourSlash {
// Handle formatting
if (this.enableFormatting) {
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeSettings);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.checkPostEditInvariants();
@@ -1469,30 +1512,30 @@ namespace FourSlash {
return runningOffset;
}
public copyFormatOptions(): ts.FormatCodeOptions {
return ts.clone(this.formatCodeOptions);
public copyFormatOptions(): ts.FormatCodeSettings {
return ts.clone(this.formatCodeSettings);
}
public setFormatOptions(formatCodeOptions: ts.FormatCodeOptions): ts.FormatCodeOptions {
const oldFormatCodeOptions = this.formatCodeOptions;
this.formatCodeOptions = formatCodeOptions;
public setFormatOptions(formatCodeOptions: ts.FormatCodeOptions | ts.FormatCodeSettings): ts.FormatCodeSettings {
const oldFormatCodeOptions = this.formatCodeSettings;
this.formatCodeSettings = ts.toEditorSettings(formatCodeOptions);
return oldFormatCodeOptions;
}
public formatDocument() {
const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeSettings);
this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.fixCaretPosition();
}
public formatSelection(start: number, end: number) {
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeSettings);
this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.fixCaretPosition();
}
public formatOnType(pos: number, key: string) {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, pos, key, this.formatCodeOptions);
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, pos, key, this.formatCodeSettings);
this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.fixCaretPosition();
}
@@ -1621,8 +1664,8 @@ namespace FourSlash {
private getIndentation(fileName: string, position: number, indentStyle: ts.IndentStyle): number {
const formatOptions = ts.clone(this.formatCodeOptions);
formatOptions.IndentStyle = indentStyle;
const formatOptions = ts.clone(this.formatCodeSettings);
formatOptions.indentStyle = indentStyle;
return this.languageService.getIndentationAtPosition(fileName, position, formatOptions);
}
@@ -2836,14 +2879,6 @@ namespace FourSlashInterface {
this.state.verifyMemberListIsEmpty(this.negative);
}
public referencesCountIs(count: number) {
this.state.verifyReferencesCountIs(count, /*localFilesOnly*/ false);
}
public referencesAtPositionContains(range: FourSlash.Range, isWriteAccess?: boolean, isDefinition?: boolean) {
this.state.verifyReferencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess, isDefinition);
}
public signatureHelpPresent() {
this.state.verifySignatureHelpPresent(!this.negative);
}
@@ -2935,6 +2970,22 @@ namespace FourSlashInterface {
this.state.verifyGetEmitOutputContentsForCurrentFile(expected);
}
public referencesCountIs(count: number) {
this.state.verifyReferencesCountIs(count, /*localFilesOnly*/ false);
}
public referencesAre(ranges: FourSlash.Range[]) {
this.state.verifyReferencesAre(ranges);
}
public referencesOf(start: FourSlash.Range, references: FourSlash.Range[]) {
this.state.verifyReferencesOf(start, references);
}
public rangesReferenceEachOther(ranges?: FourSlash.Range[]) {
this.state.verifyRangesReferenceEachOther(ranges);
}
public currentParameterHelpArgumentNameIs(name: string) {
this.state.verifyCurrentParameterHelpName(name);
}
@@ -3226,7 +3277,7 @@ namespace FourSlashInterface {
this.state.formatDocument();
}
public copyFormatOptions(): ts.FormatCodeOptions {
public copyFormatOptions(): ts.FormatCodeSettings {
return this.state.copyFormatOptions();
}
@@ -3246,7 +3297,7 @@ namespace FourSlashInterface {
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;
(<any>this.state.formatCodeSettings)[name] = value;
}
}
+24 -7
View File
@@ -23,6 +23,7 @@
/// <reference path="external\chai.d.ts"/>
/// <reference path="sourceMapRecorder.ts"/>
/// <reference path="runnerbase.ts"/>
/// <reference path="virtualFileSystem.ts" />
// Block scoped definitions work poorly for global variables, temporarily enable var
/* tslint:disable:no-var-keyword */
@@ -443,7 +444,7 @@ namespace Harness {
args(): string[];
getExecutingFilePath(): string;
exit(exitCode?: number): void;
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[]): string[];
}
export var IO: IO;
@@ -482,7 +483,7 @@ namespace Harness {
export const directoryExists: typeof IO.directoryExists = fso.FolderExists;
export const fileExists: typeof IO.fileExists = fso.FileExists;
export const log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine;
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude);
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude, include) => ts.sys.readDirectory(path, extension, exclude, include);
export function createDirectory(path: string) {
if (directoryExists(path)) {
@@ -552,7 +553,7 @@ namespace Harness {
export const fileExists: typeof IO.fileExists = fs.existsSync;
export const log: typeof IO.log = s => console.log(s);
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude);
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude, include) => ts.sys.readDirectory(path, extension, exclude, include);
export function createDirectory(path: string) {
if (!directoryExists(path)) {
@@ -740,8 +741,22 @@ namespace Harness {
Http.writeToServerSync(serverRoot + path, "WRITE", contents);
}
export function readDirectory(path: string, extension?: string, exclude?: string[]) {
return listFiles(path).filter(f => !extension || ts.fileExtensionIs(f, extension));
export function readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[]) {
const fs = new Utils.VirtualFileSystem(path, useCaseSensitiveFileNames());
for (const file in listFiles(path)) {
fs.addFile(file);
}
return ts.matchFiles(path, extension, exclude, include, useCaseSensitiveFileNames(), getCurrentDirectory(), path => {
const entry = fs.traversePath(path);
if (entry && entry.isDirectory()) {
const directory = <Utils.VirtualDirectory>entry;
return {
files: ts.map(directory.getFiles(), f => f.name),
directories: ts.map(directory.getDirectories(), d => d.name)
};
}
return { files: [], directories: [] };
});
}
}
}
@@ -1051,7 +1066,7 @@ namespace Harness {
options.target = options.target || ts.ScriptTarget.ES3;
options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed;
options.noErrorTruncation = true;
options.skipDefaultLibCheck = true;
options.skipDefaultLibCheck = typeof options.skipDefaultLibCheck === "undefined" ? true : options.skipDefaultLibCheck;
if (typeof currentDirectory === "undefined") {
currentDirectory = Harness.IO.getCurrentDirectory();
@@ -1531,7 +1546,9 @@ namespace Harness {
// unit tests always list files explicitly
const parseConfigHost: ts.ParseConfigHost = {
readDirectory: (name) => []
useCaseSensitiveFileNames: false,
readDirectory: (name) => [],
fileExists: (name) => true
};
// check if project has tsconfig.json in the list of files
+7 -2
View File
@@ -288,6 +288,12 @@ namespace Harness.LanguageService {
readDirectory(rootDir: string, extension: string): string {
throw new Error("NYI");
}
readDirectoryNames(path: string): string {
throw new Error("Not implemented.");
}
readFileNames(path: string): string {
throw new Error("Not implemented.");
}
fileExists(fileName: string) { return this.getScriptInfo(fileName) !== undefined; }
readFile(fileName: string) {
const snapshot = this.nativeHost.getScriptSnapshot(fileName);
@@ -611,7 +617,7 @@ namespace Harness.LanguageService {
return [];
}
readDirectory(path: string, extension?: string): string[] {
readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[]): string[] {
throw new Error("Not implemented Yet.");
}
@@ -696,4 +702,3 @@ namespace Harness.LanguageService {
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { throw new Error("getPreProcessedFileInfo is not available using the server interface."); }
}
}
+5 -4
View File
@@ -61,8 +61,9 @@ interface IOLog {
}[];
directoriesRead: {
path: string,
extension: string,
extension: string[],
exclude: string[],
include: string[],
result: string[]
}[];
}
@@ -217,9 +218,9 @@ namespace Playback {
memoize(path => findResultByPath(wrapper, replayLog.filesRead, path).contents));
wrapper.readDirectory = recordReplay(wrapper.readDirectory, underlying)(
(path, extension, exclude) => {
const result = (<ts.System>underlying).readDirectory(path, extension, exclude);
const logEntry = { path, extension, exclude, result };
(path, extension, exclude, include) => {
const result = (<ts.System>underlying).readDirectory(path, extension, exclude, include);
const logEntry = { path, extension, exclude, include, result };
recordLog.directoriesRead.push(logEntry);
return result;
},
+8 -3
View File
@@ -218,7 +218,12 @@ class ProjectRunner extends RunnerBase {
}
const configObject = result.config;
const configParseResult = ts.parseJsonConfigFileContent(configObject, { readDirectory }, ts.getDirectoryPath(configFileName), compilerOptions);
const configParseHost: ts.ParseConfigHost = {
useCaseSensitiveFileNames: Harness.IO.useCaseSensitiveFileNames(),
fileExists,
readDirectory,
};
const configParseResult = ts.parseJsonConfigFileContent(configObject, configParseHost, ts.getDirectoryPath(configFileName), compilerOptions);
if (configParseResult.errors.length > 0) {
return {
moduleKind,
@@ -276,8 +281,8 @@ class ProjectRunner extends RunnerBase {
: ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName);
}
function readDirectory(rootDir: string, extension: string, exclude: string[]): string[] {
const harnessReadDirectoryResult = Harness.IO.readDirectory(getFileNameInTheProjectTest(rootDir), extension, exclude);
function readDirectory(rootDir: string, extension: string[], exclude: string[], include: string[]): string[] {
const harnessReadDirectoryResult = Harness.IO.readDirectory(getFileNameInTheProjectTest(rootDir), extension, exclude, include);
const result: string[] = [];
for (let i = 0; i < harnessReadDirectoryResult.length; i++) {
result[i] = ts.getRelativePathToDirectoryOrUrl(testCase.projectRoot, harnessReadDirectoryResult[i],
+6 -1
View File
@@ -75,7 +75,12 @@ namespace RWC {
if (tsconfigFile) {
const tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path);
const parsedTsconfigFileContents = ts.parseConfigFileTextToJson(tsconfigFile.path, tsconfigFileContents.content);
const configParseResult = ts.parseJsonConfigFileContent(parsedTsconfigFileContents.config, Harness.IO, ts.getDirectoryPath(tsconfigFile.path));
const configParseHost: ts.ParseConfigHost = {
useCaseSensitiveFileNames: Harness.IO.useCaseSensitiveFileNames(),
fileExists: Harness.IO.fileExists,
readDirectory: Harness.IO.readDirectory,
};
const configParseResult = ts.parseJsonConfigFileContent(parsedTsconfigFileContents.config, configParseHost, ts.getDirectoryPath(tsconfigFile.path));
fileNames = configParseResult.fileNames;
opts.options = ts.extend(opts.options, configParseResult.options);
}
+186
View File
@@ -0,0 +1,186 @@
/// <reference path="harness.ts" />
/// <reference path="..\compiler\commandLineParser.ts"/>
namespace Utils {
export class VirtualFileSystemEntry {
fileSystem: VirtualFileSystem;
name: string;
constructor(fileSystem: VirtualFileSystem, name: string) {
this.fileSystem = fileSystem;
this.name = name;
}
isDirectory() { return false; }
isFile() { return false; }
isFileSystem() { return false; }
}
export class VirtualFile extends VirtualFileSystemEntry {
content: string;
isFile() { return true; }
}
export abstract class VirtualFileSystemContainer extends VirtualFileSystemEntry {
abstract getFileSystemEntries(): VirtualFileSystemEntry[];
getFileSystemEntry(name: string): VirtualFileSystemEntry {
for (const entry of this.getFileSystemEntries()) {
if (this.fileSystem.sameName(entry.name, name)) {
return entry;
}
}
return undefined;
}
getDirectories(): VirtualDirectory[] {
return <VirtualDirectory[]>ts.filter(this.getFileSystemEntries(), entry => entry.isDirectory());
}
getFiles(): VirtualFile[] {
return <VirtualFile[]>ts.filter(this.getFileSystemEntries(), entry => entry.isFile());
}
getDirectory(name: string): VirtualDirectory {
const entry = this.getFileSystemEntry(name);
return entry.isDirectory() ? <VirtualDirectory>entry : undefined;
}
getFile(name: string): VirtualFile {
const entry = this.getFileSystemEntry(name);
return entry.isFile() ? <VirtualFile>entry : undefined;
}
}
export class VirtualDirectory extends VirtualFileSystemContainer {
private entries: VirtualFileSystemEntry[] = [];
isDirectory() { return true; }
getFileSystemEntries() { return this.entries.slice(); }
addDirectory(name: string): VirtualDirectory {
const entry = this.getFileSystemEntry(name);
if (entry === undefined) {
const directory = new VirtualDirectory(this.fileSystem, name);
this.entries.push(directory);
return directory;
}
else if (entry.isDirectory()) {
return <VirtualDirectory>entry;
}
else {
return undefined;
}
}
addFile(name: string, content?: string): VirtualFile {
const entry = this.getFileSystemEntry(name);
if (entry === undefined) {
const file = new VirtualFile(this.fileSystem, name);
file.content = content;
this.entries.push(file);
return file;
}
else if (entry.isFile()) {
const file = <VirtualFile>entry;
file.content = content;
return file;
}
else {
return undefined;
}
}
}
export class VirtualFileSystem extends VirtualFileSystemContainer {
private root: VirtualDirectory;
currentDirectory: string;
useCaseSensitiveFileNames: boolean;
constructor(currentDirectory: string, useCaseSensitiveFileNames: boolean) {
super(undefined, "");
this.fileSystem = this;
this.root = new VirtualDirectory(this, "");
this.currentDirectory = currentDirectory;
this.useCaseSensitiveFileNames = useCaseSensitiveFileNames;
}
isFileSystem() { return true; }
getFileSystemEntries() { return this.root.getFileSystemEntries(); }
addDirectory(path: string) {
const components = ts.getNormalizedPathComponents(path, this.currentDirectory);
let directory: VirtualDirectory = this.root;
for (const component of components) {
directory = directory.addDirectory(component);
if (directory === undefined) {
break;
}
}
return directory;
}
addFile(path: string, content?: string) {
const absolutePath = ts.getNormalizedAbsolutePath(path, this.currentDirectory);
const fileName = ts.getBaseFileName(path);
const directoryPath = ts.getDirectoryPath(absolutePath);
const directory = this.addDirectory(directoryPath);
return directory ? directory.addFile(fileName, content) : undefined;
}
fileExists(path: string) {
const entry = this.traversePath(path);
return entry !== undefined && entry.isFile();
}
sameName(a: string, b: string) {
return this.useCaseSensitiveFileNames ? a === b : a.toLowerCase() === b.toLowerCase();
}
traversePath(path: string) {
let directory: VirtualDirectory = this.root;
for (const component of ts.getNormalizedPathComponents(path, this.currentDirectory)) {
const entry = directory.getFileSystemEntry(component);
if (entry === undefined) {
return undefined;
}
else if (entry.isDirectory()) {
directory = <VirtualDirectory>entry;
}
else {
return entry;
}
}
return directory;
}
}
export class MockParseConfigHost extends VirtualFileSystem implements ts.ParseConfigHost {
constructor(currentDirectory: string, ignoreCase: boolean, files: string[]) {
super(currentDirectory, ignoreCase);
for (const file of files) {
this.addFile(file);
}
}
readDirectory(path: string, extensions: string[], excludes: string[], includes: string[]) {
return ts.matchFiles(path, extensions, excludes, includes, this.useCaseSensitiveFileNames, this.currentDirectory, (path: string) => this.getAccessibleFileSystemEntries(path));
}
getAccessibleFileSystemEntries(path: string) {
const entry = this.traversePath(path);
if (entry && entry.isDirectory()) {
const directory = <VirtualDirectory>entry;
return {
files: ts.map(directory.getFiles(), f => f.name),
directories: ts.map(directory.getDirectories(), d => d.name)
};
}
return { files: [], directories: [] };
}
}
}
+671 -131
View File
File diff suppressed because it is too large Load Diff
+211 -12
View File
@@ -3,6 +3,10 @@
/// IE Worker APIs
/////////////////////////////
interface Algorithm {
name: string;
}
interface EventInit {
bubbles?: boolean;
cancelable?: boolean;
@@ -18,6 +22,10 @@ interface IDBObjectStoreParameters {
keyPath?: IDBKeyPath;
}
interface KeyAlgorithm {
name?: string;
}
interface EventListener {
(evt: Event): void;
}
@@ -107,6 +115,18 @@ declare var Coordinates: {
new(): Coordinates;
}
interface CryptoKey {
readonly algorithm: KeyAlgorithm;
readonly extractable: boolean;
readonly type: string;
readonly usages: string[];
}
declare var CryptoKey: {
prototype: CryptoKey;
new(): CryptoKey;
}
interface DOMError {
readonly name: string;
toString(): string;
@@ -323,7 +343,7 @@ interface IDBDatabase extends EventTarget {
readonly name: string;
readonly objectStoreNames: DOMStringList;
onabort: (ev: Event) => any;
onerror: (ev: Event) => any;
onerror: (ev: ErrorEvent) => any;
version: number;
onversionchange: (ev: IDBVersionChangeEvent) => any;
close(): void;
@@ -426,7 +446,7 @@ declare var IDBOpenDBRequest: {
interface IDBRequest extends EventTarget {
readonly error: DOMError;
onerror: (ev: Event) => any;
onerror: (ev: ErrorEvent) => any;
onsuccess: (ev: Event) => any;
readonly readyState: string;
readonly result: any;
@@ -448,7 +468,7 @@ interface IDBTransaction extends EventTarget {
readonly mode: string;
onabort: (ev: Event) => any;
oncomplete: (ev: Event) => any;
onerror: (ev: Event) => any;
onerror: (ev: ErrorEvent) => any;
abort(): void;
objectStore(name: string): IDBObjectStore;
readonly READ_ONLY: string;
@@ -516,7 +536,7 @@ declare var MSApp: MSApp;
interface MSAppAsyncOperation extends EventTarget {
readonly error: DOMError;
oncomplete: (ev: Event) => any;
onerror: (ev: Event) => any;
onerror: (ev: ErrorEvent) => any;
readonly readyState: number;
readonly result: any;
start(): void;
@@ -665,7 +685,7 @@ interface WebSocket extends EventTarget {
readonly bufferedAmount: number;
readonly extensions: string;
onclose: (ev: CloseEvent) => any;
onerror: (ev: Event) => any;
onerror: (ev: ErrorEvent) => any;
onmessage: (ev: MessageEvent) => any;
onopen: (ev: Event) => any;
readonly protocol: string;
@@ -708,7 +728,6 @@ declare var Worker: {
}
interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget {
msCaching: string;
onreadystatechange: (ev: ProgressEvent) => any;
readonly readyState: number;
readonly response: any;
@@ -720,6 +739,7 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget {
timeout: number;
readonly upload: XMLHttpRequestUpload;
withCredentials: boolean;
msCaching?: string;
abort(): void;
getAllResponseHeaders(): string;
getResponseHeader(header: string): string | null;
@@ -766,14 +786,14 @@ declare var XMLHttpRequestUpload: {
}
interface AbstractWorker {
onerror: (ev: Event) => any;
onerror: (ev: ErrorEvent) => any;
addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
interface MSBaseReader {
onabort: (ev: Event) => any;
onerror: (ev: Event) => any;
onerror: (ev: ErrorEvent) => any;
onload: (ev: Event) => any;
onloadend: (ev: ProgressEvent) => any;
onloadstart: (ev: Event) => any;
@@ -819,7 +839,7 @@ interface WindowConsole {
interface XMLHttpRequestEventTarget {
onabort: (ev: Event) => any;
onerror: (ev: Event) => any;
onerror: (ev: ErrorEvent) => any;
onload: (ev: Event) => any;
onloadend: (ev: ProgressEvent) => any;
onloadstart: (ev: Event) => any;
@@ -849,7 +869,7 @@ declare var FileReaderSync: {
interface WorkerGlobalScope extends EventTarget, WorkerUtils, DedicatedWorkerGlobalScope, WindowConsole {
readonly location: WorkerLocation;
onerror: (ev: Event) => any;
onerror: (ev: ErrorEvent) => any;
readonly self: WorkerGlobalScope;
close(): void;
msWriteProfilerMark(profilerMarkName: string): void;
@@ -905,8 +925,11 @@ interface WorkerUtils extends Object, WindowBase64 {
clearInterval(handle: number): void;
clearTimeout(handle: number): void;
importScripts(...urls: string[]): void;
setImmediate(handler: (...args: any[]) => void): number;
setImmediate(handler: any, ...args: any[]): number;
setInterval(handler: (...args: any[]) => void, timeout: number): number;
setInterval(handler: any, timeout?: any, ...args: any[]): number;
setTimeout(handler: (...args: any[]) => void, timeout: number): number;
setTimeout(handler: any, timeout?: any, ...args: any[]): number;
}
@@ -942,6 +965,177 @@ interface ProgressEventInit extends EventInit {
interface IDBArrayKey extends Array<IDBValidKey> {
}
interface RsaKeyGenParams extends Algorithm {
modulusLength: number;
publicExponent: Uint8Array;
}
interface RsaHashedKeyGenParams extends RsaKeyGenParams {
hash: AlgorithmIdentifier;
}
interface RsaKeyAlgorithm extends KeyAlgorithm {
modulusLength: number;
publicExponent: Uint8Array;
}
interface RsaHashedKeyAlgorithm extends RsaKeyAlgorithm {
hash: AlgorithmIdentifier;
}
interface RsaHashedImportParams {
hash: AlgorithmIdentifier;
}
interface RsaPssParams {
saltLength: number;
}
interface RsaOaepParams extends Algorithm {
label?: BufferSource;
}
interface EcdsaParams extends Algorithm {
hash: AlgorithmIdentifier;
}
interface EcKeyGenParams extends Algorithm {
typedCurve: string;
}
interface EcKeyAlgorithm extends KeyAlgorithm {
typedCurve: string;
}
interface EcKeyImportParams {
namedCurve: string;
}
interface EcdhKeyDeriveParams extends Algorithm {
public: CryptoKey;
}
interface AesCtrParams extends Algorithm {
counter: BufferSource;
length: number;
}
interface AesKeyAlgorithm extends KeyAlgorithm {
length: number;
}
interface AesKeyGenParams extends Algorithm {
length: number;
}
interface AesDerivedKeyParams extends Algorithm {
length: number;
}
interface AesCbcParams extends Algorithm {
iv: BufferSource;
}
interface AesCmacParams extends Algorithm {
length: number;
}
interface AesGcmParams extends Algorithm {
iv: BufferSource;
additionalData?: BufferSource;
tagLength?: number;
}
interface AesCfbParams extends Algorithm {
iv: BufferSource;
}
interface HmacImportParams extends Algorithm {
hash?: AlgorithmIdentifier;
length?: number;
}
interface HmacKeyAlgorithm extends KeyAlgorithm {
hash: AlgorithmIdentifier;
length: number;
}
interface HmacKeyGenParams extends Algorithm {
hash: AlgorithmIdentifier;
length?: number;
}
interface DhKeyGenParams extends Algorithm {
prime: Uint8Array;
generator: Uint8Array;
}
interface DhKeyAlgorithm extends KeyAlgorithm {
prime: Uint8Array;
generator: Uint8Array;
}
interface DhKeyDeriveParams extends Algorithm {
public: CryptoKey;
}
interface DhImportKeyParams extends Algorithm {
prime: Uint8Array;
generator: Uint8Array;
}
interface ConcatParams extends Algorithm {
hash?: AlgorithmIdentifier;
algorithmId: Uint8Array;
partyUInfo: Uint8Array;
partyVInfo: Uint8Array;
publicInfo?: Uint8Array;
privateInfo?: Uint8Array;
}
interface HkdfCtrParams extends Algorithm {
hash: AlgorithmIdentifier;
label: BufferSource;
context: BufferSource;
}
interface Pbkdf2Params extends Algorithm {
salt: BufferSource;
iterations: number;
hash: AlgorithmIdentifier;
}
interface RsaOtherPrimesInfo {
r: string;
d: string;
t: string;
}
interface JsonWebKey {
kty: string;
use?: string;
key_ops?: string[];
alg?: string;
kid?: string;
x5u?: string;
x5c?: string;
x5t?: string;
ext?: boolean;
crv?: string;
x?: string;
y?: string;
d?: string;
n?: string;
e?: string;
p?: string;
q?: string;
dp?: string;
dq?: string;
qi?: string;
oth?: RsaOtherPrimesInfo[];
k?: string;
}
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
interface ErrorEventHandler {
@@ -975,7 +1169,7 @@ interface FunctionStringCallback {
(data: string): void;
}
declare var location: WorkerLocation;
declare var onerror: (ev: Event) => any;
declare var onerror: (ev: ErrorEvent) => any;
declare var self: WorkerGlobalScope;
declare function close(): void;
declare function msWriteProfilerMark(profilerMarkName: string): void;
@@ -990,8 +1184,11 @@ declare function clearImmediate(handle: number): void;
declare function clearInterval(handle: number): void;
declare function clearTimeout(handle: number): void;
declare function importScripts(...urls: string[]): void;
declare function setImmediate(handler: (...args: any[]) => void): number;
declare function setImmediate(handler: any, ...args: any[]): number;
declare function setInterval(handler: (...args: any[]) => void, timeout: number): number;
declare function setInterval(handler: any, timeout?: any, ...args: any[]): number;
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): number;
declare function setTimeout(handler: any, timeout?: any, ...args: any[]): number;
declare function atob(encodedString: string): string;
declare function btoa(rawString: string): string;
@@ -1001,5 +1198,7 @@ declare var console: Console;
declare function addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
declare function addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void;
declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
type AlgorithmIdentifier = string | Algorithm;
type IDBKeyPath = string;
type IDBValidKey = number | string | Date | IDBArrayKey;
type IDBValidKey = number | string | Date | IDBArrayKey;
type BufferSource = ArrayBuffer | ArrayBufferView;
+11 -6
View File
@@ -45,8 +45,9 @@ namespace ts.server {
return lineMap;
}
private lineOffsetToPosition(fileName: string, lineOffset: protocol.Location): number {
return ts.computePositionOfLineAndCharacter(this.getLineMap(fileName), lineOffset.line - 1, lineOffset.offset - 1);
private lineOffsetToPosition(fileName: string, lineOffset: protocol.Location, lineMap?: number[]): number {
lineMap = lineMap || this.getLineMap(fileName);
return ts.computePositionOfLineAndCharacter(lineMap, lineOffset.line - 1, lineOffset.offset - 1);
}
private positionToOneBasedLineOffset(fileName: string, position: number): protocol.Location {
@@ -449,7 +450,7 @@ namespace ts.server {
return this.lastRenameEntry.locations;
}
decodeNavigationBarItems(items: protocol.NavigationBarItem[], fileName: string): NavigationBarItem[] {
decodeNavigationBarItems(items: protocol.NavigationBarItem[], fileName: string, lineMap: number[]): NavigationBarItem[] {
if (!items) {
return [];
}
@@ -458,8 +459,11 @@ namespace ts.server {
text: item.text,
kind: item.kind,
kindModifiers: item.kindModifiers || "",
spans: item.spans.map(span => createTextSpanFromBounds(this.lineOffsetToPosition(fileName, span.start), this.lineOffsetToPosition(fileName, span.end))),
childItems: this.decodeNavigationBarItems(item.childItems, fileName),
spans: item.spans.map(span =>
createTextSpanFromBounds(
this.lineOffsetToPosition(fileName, span.start, lineMap),
this.lineOffsetToPosition(fileName, span.end, lineMap))),
childItems: this.decodeNavigationBarItems(item.childItems, fileName, lineMap),
indent: item.indent,
bolded: false,
grayed: false
@@ -474,7 +478,8 @@ namespace ts.server {
const request = this.processRequest<protocol.NavBarRequest>(CommandNames.NavBar, args);
const response = this.processResponse<protocol.NavBarResponse>(request);
return this.decodeNavigationBarItems(response.body, fileName);
const lineMap = this.getLineMap(fileName);
return this.decodeNavigationBarItems(response.body, fileName, lineMap);
}
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan {
+330 -90
View File
@@ -16,53 +16,53 @@ namespace ts.server {
msg(s: string, type?: string): void;
}
function getDefaultFormatCodeOptions(host: ServerHost): ts.FormatCodeOptions {
return ts.clone(<ts.FormatCodeOptions>{
IndentSize: 4,
TabSize: 4,
NewLineCharacter: host.newLine || "\n",
ConvertTabsToSpaces: true,
IndentStyle: ts.IndentStyle.Smart,
InsertSpaceAfterCommaDelimiter: true,
InsertSpaceAfterSemicolonInForStatements: true,
InsertSpaceBeforeAndAfterBinaryOperators: true,
InsertSpaceAfterKeywordsInControlFlowStatements: true,
InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
PlaceOpenBraceOnNewLineForFunctions: false,
PlaceOpenBraceOnNewLineForControlBlocks: false,
function getDefaultFormatCodeSettings(host: ServerHost): ts.FormatCodeSettings {
return ts.clone(<ts.FormatCodeSettings>{
indentSize: 4,
tabSize: 4,
newLineCharacter: host.newLine || "\n",
convertTabsToSpaces: true,
indentStyle: ts.IndentStyle.Smart,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
});
}
function mergeFormatOptions(formatCodeOptions: FormatCodeOptions, formatOptions: protocol.FormatOptions): void {
const hasOwnProperty = Object.prototype.hasOwnProperty;
Object.keys(formatOptions).forEach((key) => {
const codeKey = key.charAt(0).toUpperCase() + key.substring(1);
if (hasOwnProperty.call(formatCodeOptions, codeKey)) {
formatCodeOptions[codeKey] = formatOptions[key];
function mergeMaps(target: Map<any>, source: Map<any>): void {
for (const key in source) {
if (hasProperty(source, key)) {
target[key] = source[key];
}
});
}
}
export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024;
export class ScriptInfo {
svc: ScriptVersionCache;
defaultProject: Project; // project to use by default for file
fileWatcher: FileWatcher;
formatCodeOptions: ts.FormatCodeOptions;
formatCodeSettings: ts.FormatCodeSettings;
path: Path;
scriptKind: ScriptKind;
constructor(private host: ServerHost, public fileName: string, public content: string, public isOpen = false) {
this.path = toPath(fileName, host.getCurrentDirectory(), createGetCanonicalFileName(host.useCaseSensitiveFileNames));
this.svc = ScriptVersionCache.fromString(host, content);
this.formatCodeOptions = getDefaultFormatCodeOptions(this.host);
this.formatCodeSettings = getDefaultFormatCodeSettings(this.host);
}
setFormatOptions(formatOptions: protocol.FormatOptions): void {
if (formatOptions) {
mergeFormatOptions(this.formatCodeOptions, formatOptions);
setFormatOptions(formatSettings: protocol.FormatOptions): void {
if (formatSettings) {
mergeMaps(this.formatCodeSettings, formatSettings);
}
}
@@ -123,7 +123,66 @@ namespace ts.server {
}
}
export class LSHost implements ts.LanguageServiceHost, ModuleResolutionHost {
function throwLanguageServiceIsDisabledError() {;
throw new Error("LanguageService is disabled");
}
const nullLanguageService: ts.LanguageService = {
cleanupSemanticCache: (): any => throwLanguageServiceIsDisabledError(),
getSyntacticDiagnostics: (): any => throwLanguageServiceIsDisabledError(),
getSemanticDiagnostics: (): any => throwLanguageServiceIsDisabledError(),
getCompilerOptionsDiagnostics: (): any => throwLanguageServiceIsDisabledError(),
getSyntacticClassifications: (): any => throwLanguageServiceIsDisabledError(),
getEncodedSyntacticClassifications: (): any => throwLanguageServiceIsDisabledError(),
getSemanticClassifications: (): any => throwLanguageServiceIsDisabledError(),
getEncodedSemanticClassifications: (): any => throwLanguageServiceIsDisabledError(),
getCompletionsAtPosition: (): any => throwLanguageServiceIsDisabledError(),
findReferences: (): any => throwLanguageServiceIsDisabledError(),
getCompletionEntryDetails: (): any => throwLanguageServiceIsDisabledError(),
getQuickInfoAtPosition: (): any => throwLanguageServiceIsDisabledError(),
findRenameLocations: (): any => throwLanguageServiceIsDisabledError(),
getNameOrDottedNameSpan: (): any => throwLanguageServiceIsDisabledError(),
getBreakpointStatementAtPosition: (): any => throwLanguageServiceIsDisabledError(),
getBraceMatchingAtPosition: (): any => throwLanguageServiceIsDisabledError(),
getSignatureHelpItems: (): any => throwLanguageServiceIsDisabledError(),
getDefinitionAtPosition: (): any => throwLanguageServiceIsDisabledError(),
getRenameInfo: (): any => throwLanguageServiceIsDisabledError(),
getTypeDefinitionAtPosition: (): any => throwLanguageServiceIsDisabledError(),
getReferencesAtPosition: (): any => throwLanguageServiceIsDisabledError(),
getDocumentHighlights: (): any => throwLanguageServiceIsDisabledError(),
getOccurrencesAtPosition: (): any => throwLanguageServiceIsDisabledError(),
getNavigateToItems: (): any => throwLanguageServiceIsDisabledError(),
getNavigationBarItems: (): any => throwLanguageServiceIsDisabledError(),
getOutliningSpans: (): any => throwLanguageServiceIsDisabledError(),
getTodoComments: (): any => throwLanguageServiceIsDisabledError(),
getIndentationAtPosition: (): any => throwLanguageServiceIsDisabledError(),
getFormattingEditsForRange: (): any => throwLanguageServiceIsDisabledError(),
getFormattingEditsForDocument: (): any => throwLanguageServiceIsDisabledError(),
getFormattingEditsAfterKeystroke: (): any => throwLanguageServiceIsDisabledError(),
getDocCommentTemplateAtPosition: (): any => throwLanguageServiceIsDisabledError(),
isValidBraceCompletionAtPostion: (): any => throwLanguageServiceIsDisabledError(),
getEmitOutput: (): any => throwLanguageServiceIsDisabledError(),
getProgram: (): any => throwLanguageServiceIsDisabledError(),
getNonBoundSourceFile: (): any => throwLanguageServiceIsDisabledError(),
dispose: (): any => throwLanguageServiceIsDisabledError(),
};
interface ServerLanguageServiceHost {
getCompilationSettings(): CompilerOptions;
setCompilationSettings(options: CompilerOptions): void;
removeRoot(info: ScriptInfo): void;
removeReferencedFile(info: ScriptInfo): void;
}
const nullLanguageServiceHost: ServerLanguageServiceHost = {
getCompilationSettings: () => undefined,
setCompilationSettings: () => undefined,
removeRoot: () => undefined,
removeReferencedFile: () => undefined
};
export class LSHost implements ts.LanguageServiceHost, ModuleResolutionHost, ServerLanguageServiceHost {
private compilationSettings: ts.CompilerOptions;
private resolvedModuleNames: ts.FileMap<Map<ResolvedModuleWithFailedLookupLocations>>;
private resolvedTypeReferenceDirectives: ts.FileMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>;
@@ -290,7 +349,8 @@ namespace ts.server {
* these fields can be present in the project file
**/
files?: string[];
compilerOptions?: ts.CompilerOptions;
wildcardDirectories?: Map<WatchDirectoryFlags>;
compilerOptions?: CompilerOptions;
}
export enum ProjectKind {
@@ -302,31 +362,61 @@ namespace ts.server {
export abstract class Project {
private rootFiles: ScriptInfo[] = [];
private rootFilesMap: FileMap<ScriptInfo> = createFileMap<ScriptInfo>();
private readonly lsHost: LSHost;
readonly languageService: LanguageService;
private lsHost: ServerLanguageServiceHost;
languageService: LanguageService;
protected program: ts.Program;
constructor(
readonly projectKind: ProjectKind,
readonly projectService: ProjectService,
documentRegistry: ts.DocumentRegistry,
private documentRegistry: ts.DocumentRegistry,
hasExplicitListOfFiles: boolean,
compilerOptions: CompilerOptions) {
public languageServiceEnabled: boolean,
private compilerOptions: CompilerOptions) {
if (!compilerOptions) {
compilerOptions = ts.getDefaultCompilerOptions();
compilerOptions.allowNonTsExtensions = true;
compilerOptions.allowJs = true;
if (!this.compilerOptions) {
this.compilerOptions = ts.getDefaultCompilerOptions();
this.compilerOptions.allowNonTsExtensions = true;
this.compilerOptions.allowJs = true;
}
else if (hasExplicitListOfFiles) {
// If files are listed explicitly, allow all extensions
compilerOptions.allowNonTsExtensions = true;
this.compilerOptions.allowNonTsExtensions = true;
}
this.lsHost = new LSHost(this.projectService.host, this, this.projectService.cancellationToken);
this.lsHost.setCompilationSettings(compilerOptions);
this.languageService = ts.createLanguageService(this.lsHost, documentRegistry);
if (languageServiceEnabled) {
this.enableLanguageServiceWorker();
}
else {
this.disableLanguageServiceWorker();
}
}
enableLanguageService() {
if (!this.languageServiceEnabled) {
this.enableLanguageServiceWorker();
}
}
private enableLanguageServiceWorker() {
const lsHost = new LSHost(this.projectService.host, this, this.projectService.cancellationToken);
lsHost.setCompilationSettings(this.compilerOptions);
this.languageService = ts.createLanguageService(lsHost, this.documentRegistry);
this.lsHost = lsHost;
this.languageServiceEnabled = true;
}
disableLanguageService() {
if (this.languageServiceEnabled) {
this.disableLanguageServiceWorker();
}
}
private disableLanguageServiceWorker() {
this.languageService = nullLanguageService;
this.lsHost = nullLanguageServiceHost;
this.languageServiceEnabled = false;
}
getProjectFileName(): string {
@@ -343,16 +433,29 @@ namespace ts.server {
}
getRootFiles() {
if (!this.languageServiceEnabled && this.projectKind === ProjectKind.Inferred) {
return undefined;
}
return this.rootFiles.map(info => info.fileName);
}
getFileNames() {
if (!this.languageServiceEnabled) {
let rootFiles = this.getRootFiles();
if (this.compilerOptions) {
const defaultLibrary = getDefaultLibFilePath(this.compilerOptions);
if (defaultLibrary) {
(rootFiles || (rootFiles = [])).push(defaultLibrary);
}
}
return rootFiles;
}
const sourceFiles = this.program.getSourceFiles();
return sourceFiles.map(sourceFile => sourceFile.fileName);
}
containsScriptInfo(info: ScriptInfo): boolean {
return this.program.getSourceFileByPath(info.path) !== undefined;
return this.program && this.program.getSourceFileByPath(info.path) !== undefined;
}
containsFile(filename: string, requireOpen?: boolean) {
@@ -397,7 +500,7 @@ namespace ts.server {
}
getScriptInfo(fileName: string) {
const scriptInfo = this.projectService.getOrCreateScriptInfo(fileName, /*openedByClient*/ false);
const scriptInfo = this.projectService.getOrCreateScriptInfo(fileName, /*openedByClient*/ false, this);
if (scriptInfo && !scriptInfo.defaultProject) {
scriptInfo.defaultProject = this;
}
@@ -442,8 +545,13 @@ namespace ts.server {
// Used to keep track of what directories are watched for this project
directoriesWatchedForTsconfig: string[] = [];
constructor(projectService: ProjectService, documentRegistry: ts.DocumentRegistry) {
super(ProjectKind.Inferred, projectService, documentRegistry, /*files*/ undefined, /*compilerOptions*/ undefined);
constructor(projectService: ProjectService, documentRegistry: ts.DocumentRegistry, languageServiceEnabled: boolean) {
super(ProjectKind.Inferred,
projectService,
documentRegistry,
/*files*/ undefined,
languageServiceEnabled,
/*compilerOptions*/ undefined);
}
close() {
@@ -470,6 +578,9 @@ namespace ts.server {
currentVersion: number = 1;
updateGraph() {
if (!this.languageServiceEnabled) {
return;
}
const oldProgram = this.program;
super.updateGraph();
@@ -522,11 +633,18 @@ namespace ts.server {
class ConfiguredProject extends VersionedProject {
private projectFileWatcher: FileWatcher;
private directoryWatcher: FileWatcher;
private directoriesWatchedForWildcards: Map<FileWatcher>;
/** Used for configured projects which may have multiple open roots */
openRefCount = 0;
constructor(readonly configFileName: string, projectService: ProjectService, documentRegistry: ts.DocumentRegistry, hasExplicitListOfFiles: boolean, compilerOptions: CompilerOptions) {
super(ProjectKind.Configured, projectService, documentRegistry, hasExplicitListOfFiles, compilerOptions);
constructor(readonly configFileName: string,
projectService: ProjectService,
documentRegistry: ts.DocumentRegistry,
hasExplicitListOfFiles: boolean,
compilerOptions: CompilerOptions,
private wildcardDirectories: Map<WatchDirectoryFlags>,
languageServiceEnabled: boolean) {
super(ProjectKind.Configured, projectService, documentRegistry, hasExplicitListOfFiles, languageServiceEnabled, compilerOptions);
}
getProjectFileName() {
@@ -538,20 +656,52 @@ namespace ts.server {
}
watchConfigDirectory(callback: (project: ConfiguredProject, path: string) => void) {
const directoryToWatch = ts.getDirectoryPath(this.configFileName);
if (this.directoryWatcher) {
return;
}
const directoryToWatch = getDirectoryPath(this.configFileName);
this.projectService.log(`Add recursive watcher for: ${directoryToWatch}`);
this.directoryWatcher = this.projectService.host.watchDirectory(directoryToWatch, path => callback(this, path), /*recursive*/ true);
}
watchWildcards(callback: (project: ConfiguredProject, path: string) => void) {
if (!this.wildcardDirectories) {
return;
}
const configDirectoryPath = getDirectoryPath(this.configFileName);
this.directoriesWatchedForWildcards = reduceProperties(this.wildcardDirectories, (watchers, flag, directory) => {
if (comparePaths(configDirectoryPath, directory, ".", !this.projectService.host.useCaseSensitiveFileNames) !== Comparison.EqualTo) {
const recursive = (flag & WatchDirectoryFlags.Recursive) !== 0;
this.projectService.log(`Add ${recursive ? "recursive " : ""}watcher for: ${directory}`);
watchers[directory] = this.projectService.host.watchDirectory(
directory,
path => callback(this, path),
recursive
);
}
return watchers;
}, <Map<FileWatcher>>{});
}
stopWatchingDirectory() {
if (this.directoryWatcher) {
this.directoryWatcher.close();
this.directoryWatcher = undefined;
}
}
close() {
super.close();
if (this.projectFileWatcher) {
this.projectFileWatcher.close();
}
if (this.directoryWatcher) {
this.directoryWatcher.close();
}
forEachValue(this.directoriesWatchedForWildcards, watcher => { watcher.close(); });
this.directoriesWatchedForWildcards = undefined;
this.stopWatchingDirectory();
}
addOpenRef() {
@@ -565,8 +715,12 @@ namespace ts.server {
}
class ExternalProject extends VersionedProject {
constructor(readonly projectFileName: string, projectService: ProjectService, documentRegistry: ts.DocumentRegistry, compilerOptions: CompilerOptions) {
super(ProjectKind.External, projectService, documentRegistry, /*hasExplicitListOfFiles*/ true, compilerOptions);
constructor(readonly projectFileName: string,
projectService: ProjectService,
documentRegistry: ts.DocumentRegistry,
compilerOptions: CompilerOptions,
languageServiceEnabled: boolean) {
super(ProjectKind.External, projectService, documentRegistry, /*hasExplicitListOfFiles*/ true, languageServiceEnabled, compilerOptions);
}
getProjectFileName() {
@@ -603,7 +757,7 @@ namespace ts.server {
}
export interface HostConfiguration {
formatCodeOptions: ts.FormatCodeOptions;
formatCodeOptions: ts.FormatCodeSettings;
hostInfo: string;
}
@@ -665,7 +819,7 @@ namespace ts.server {
private setDefaultHostConfiguration() {
this.hostConfiguration = {
formatCodeOptions: getDefaultFormatCodeOptions(this.host),
formatCodeOptions: getDefaultFormatCodeSettings(this.host),
hostInfo: "Unknown host"
};
}
@@ -686,14 +840,14 @@ namespace ts.server {
// TODO: fixme
return this.inferredProjects.length ? this.inferredProjects[0] : undefined;
}
return this.findExternalProjectByProjectFileName(projectFileName) || this.findConfiguredProjectByConfigFile(projectFileName);
return this.findExternalProjectByProjectFileName(projectFileName) || this.findConfiguredProjectByConfigFile(normalizePath(projectFileName));
}
getFormatCodeOptions(file?: string) {
if (file) {
const info = this.filenameToScriptInfo[file];
if (info) {
return info.formatCodeOptions;
return info.formatCodeSettings;
}
}
return this.hostConfiguration.formatCodeOptions;
@@ -893,6 +1047,9 @@ namespace ts.server {
this.findReferencingProjects(info);
if (info.defaultProject) {
if (info.defaultProject.projectKind === ProjectKind.Configured) {
(<ConfiguredProject>info.defaultProject).addOpenRef();
}
this.openFilesReferenced.push(info);
}
else {
@@ -1129,37 +1286,75 @@ namespace ts.server {
const projectOptions: ProjectOptions = {
files: parsedCommandLine.fileNames,
compilerOptions: parsedCommandLine.options,
configHasFilesProperty
configHasFilesProperty,
wildcardDirectories: parsedCommandLine.wildcardDirectories,
};
return { succeeded: true, projectOptions };
}
}
}
private exceedTotalNonTsFileSizeLimit(options: CompilerOptions, fileNames: string[]) {
if (options && options.disableSizeLimit) {
return false;
}
let totalNonTsFileSize = 0;
if (!this.host.getFileSize) {
return false;
}
for (const fileName of fileNames) {
if (hasTypeScriptFileExtension(fileName)) {
continue;
}
totalNonTsFileSize += this.host.getFileSize(fileName);
if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) {
return true;
}
}
return false;
}
private createAndAddExternalProject(projectFileName: string, files: string[], compilerOptions: CompilerOptions, clientFileName?: string) {
const project = new ExternalProject(projectFileName, this, this.documentRegistry, compilerOptions);
const sizeLimitExceeded = this.exceedTotalNonTsFileSizeLimit(compilerOptions, files);
const project = new ExternalProject(projectFileName, this, this.documentRegistry, compilerOptions, !sizeLimitExceeded);
const errors = this.addFilesToProject(project, files, clientFileName);
this.externalProjects.push(project);
return { project, errors };
}
private createAndAddConfiguredProject(configFileName: string, projectOptions: ProjectOptions, clientFileName?: string) {
const project = new ConfiguredProject(configFileName, this, this.documentRegistry, projectOptions.configHasFilesProperty, projectOptions.compilerOptions);
const sizeLimitExceeded = this.exceedTotalNonTsFileSizeLimit(projectOptions.compilerOptions, projectOptions.files);
const project = new ConfiguredProject(
configFileName,
this,
this.documentRegistry,
projectOptions.configHasFilesProperty,
projectOptions.compilerOptions,
projectOptions.wildcardDirectories,
!sizeLimitExceeded);
const errors = this.addFilesToProject(project, projectOptions.files, clientFileName);
project.watchConfigFile(project => this.onConfigChangedForConfiguredProject(project));
if (!projectOptions.configHasFilesProperty) {
project.watchConfigDirectory((project, path) => this.onSourceFileInDirectoryChangedForConfiguredProject(project, path));
if (!sizeLimitExceeded) {
this.watchConfigDirectoryForProject(project, projectOptions);
}
project.watchWildcards((project, path) => this.onSourceFileInDirectoryChangedForConfiguredProject(project, path));
this.configuredProjects.push(project);
return { project, errors };
}
private watchConfigDirectoryForProject(project: ConfiguredProject, options: ProjectOptions) {
if (!options.configHasFilesProperty) {
project.watchConfigDirectory((project, path) => this.onSourceFileInDirectoryChangedForConfiguredProject(project, path));
}
}
private addFilesToProject(project: ConfiguredProject | ExternalProject, files: string[], clientFileName: string): Diagnostic[] {
let errors: Diagnostic[];
for (const rootFilename of files) {
if (this.host.fileExists(rootFilename)) {
const info = this.getOrCreateScriptInfo(rootFilename, /*openedByClient*/ clientFileName == rootFilename);
const info = this.getOrCreateScriptInfo(rootFilename, /*openedByClient*/ clientFileName == rootFilename, project);
project.addRoot(info);
}
else {
@@ -1197,7 +1392,7 @@ namespace ts.server {
for (const fileName of fileNamesToAdd) {
let info = this.getScriptInfo(fileName);
if (!info) {
info = this.getOrCreateScriptInfo(fileName, /*openedByClient*/ false);
info = this.getOrCreateScriptInfo(fileName, /*openedByClient*/ false, project);
}
else {
// if the root file was opened by client, it would belong to either
@@ -1219,6 +1414,35 @@ namespace ts.server {
}
}
project.addRoot(info);
// =======
// project.finishGraph();
// project.projectFileWatcher = this.host.watchFile(configFilename, _ => this.watchedProjectConfigFileChanged(project));
// const configDirectoryPath = ts.getDirectoryPath(configFilename);
// this.log("Add recursive watcher for: " + configDirectoryPath);
// project.directoryWatcher = this.host.watchDirectory(
// configDirectoryPath,
// path => this.directoryWatchedForSourceFilesChanged(project, path),
// /*recursive*/ true
// );
// project.directoriesWatchedForWildcards = reduceProperties(projectOptions.wildcardDirectories, (watchers, flag, directory) => {
// if (comparePaths(configDirectoryPath, directory, ".", !this.host.useCaseSensitiveFileNames) !== Comparison.EqualTo) {
// const recursive = (flag & WatchDirectoryFlags.Recursive) !== 0;
// this.log(`Add ${ recursive ? "recursive " : ""}watcher for: ${directory}`);
// watchers[directory] = this.host.watchDirectory(
// directory,
// path => this.directoryWatchedForSourceFilesChanged(project, path),
// recursive
// );
// }
// return watchers;
// }, <Map<FileWatcher>>{});
// return { success: true, project: project, errors };
// >>>>>>> origin/master
}
project.setCompilerOptions(newOptions);
@@ -1236,13 +1460,28 @@ namespace ts.server {
return errors;
}
else {
this.updateVersionedProjectWorker(project, projectOptions.files, projectOptions.compilerOptions);
if (this.exceedTotalNonTsFileSizeLimit(projectOptions.compilerOptions, projectOptions.files)) {
project.setCompilerOptions(projectOptions.compilerOptions);
if (!project.languageServiceEnabled) {
// language service is already disabled
return;
}
project.disableLanguageService();
project.stopWatchingDirectory();
}
else {
if (!project.languageServiceEnabled) {
project.enableLanguageService();
}
this.watchConfigDirectoryForProject(project, projectOptions);
this.updateVersionedProjectWorker(project, projectOptions.files, projectOptions.compilerOptions);
}
}
}
}
createAndAddInferredProject(root: ScriptInfo) {
const project = new InferredProject(this, this.documentRegistry);
const project = new InferredProject(this, this.documentRegistry, /*languageServiceEnabled*/ true);
project.addRoot(root);
let currentPath = ts.getDirectoryPath(root.fileName);
@@ -1270,7 +1509,7 @@ 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
*/
getOrCreateScriptInfo(fileName: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind) {
getOrCreateScriptInfo(fileName: string, openedByClient: boolean, containingProject: Project, fileContent?: string, scriptKind?: ScriptKind) {
fileName = ts.normalizePath(fileName);
let info = ts.lookUp(this.filenameToScriptInfo, fileName);
if (!info) {
@@ -1286,7 +1525,8 @@ namespace ts.server {
if (content !== undefined) {
info = new ScriptInfo(this.host, fileName, content, openedByClient);
info.scriptKind = scriptKind;
info.setFormatOptions(this.getFormatCodeOptions());
info.defaultProject = containingProject;
info.setFormatOptions(toEditorSettings(this.getFormatCodeOptions()));
this.filenameToScriptInfo[fileName] = info;
if (!info.isOpen) {
info.fileWatcher = this.host.watchFile(fileName, _ => { this.onSourceFileChanged(fileName); });
@@ -1322,7 +1562,7 @@ namespace ts.server {
this.log("Host information " + args.hostInfo, "Info");
}
if (args.formatOptions) {
mergeFormatOptions(this.hostConfiguration.formatCodeOptions, args.formatOptions);
mergeMaps(this.hostConfiguration.formatCodeOptions, args.formatOptions);
this.log("Format host information updated", "Info");
}
}
@@ -1335,27 +1575,27 @@ namespace ts.server {
findReferencingProjects(info: ScriptInfo, excludedProject?: Project) {
const referencingProjects: Project[] = [];
info.defaultProject = undefined;
for (let i = 0, len = this.inferredProjects.length; i < len; i++) {
const inferredProject = this.inferredProjects[i];
inferredProject.updateGraph();
if (inferredProject !== excludedProject) {
if (inferredProject.containsScriptInfo(info)) {
info.defaultProject = inferredProject;
referencingProjects.push(inferredProject);
}
}
}
for (let i = 0, len = this.configuredProjects.length; i < len; i++) {
const configuredProject = this.configuredProjects[i];
configuredProject.updateGraph();
if (configuredProject.containsScriptInfo(info)) {
info.defaultProject = configuredProject;
referencingProjects.push(configuredProject);
}
this.collectContainingProjects(info, referencingProjects, this.inferredProjects, excludedProject);
this.collectContainingProjects(info, referencingProjects, this.configuredProjects);
this.collectContainingProjects(info, referencingProjects, this.externalProjects);
if (referencingProjects.length) {
info.defaultProject = referencingProjects[0];
}
return referencingProjects;
}
private collectContainingProjects(info: ScriptInfo, result: Project[], projects: Project[], excludedProject?: Project) {
for (const p of projects) {
if (p === excludedProject) {
continue;
}
p.updateGraph();
if (p.containsScriptInfo(info)) {
result.push(p);
}
}
}
/**
* This function rebuilds the project for every file opened by the client
*/
@@ -1466,7 +1706,7 @@ namespace ts.server {
if (!this.findContainingExternalProject(fileName)) {
({ configFileName, configFileErrors } = this.openOrUpdateConfiguredProjectForFile(fileName));
}
const info = this.getOrCreateScriptInfo(fileName, /*openedByClient*/ true, fileContent, scriptKind);
const info = this.getOrCreateScriptInfo(fileName, /*openedByClient*/ true, /*containingProject*/ undefined, fileContent, scriptKind);
this.addOpenFile(info);
this.printProjects();
return { configFileName, configFileErrors };
+36 -3
View File
@@ -98,6 +98,22 @@ declare namespace ts.server.protocol {
projectFileName?: string;
}
export interface TodoCommentRequest extends FileRequest {
arguments: TodoCommentRequestArgs;
}
export interface TodoCommentRequestArgs extends FileRequestArgs {
descriptors: TodoCommentDescriptor[];
}
export interface IndentationRequest extends FileLocationRequest {
arguments: IndentationRequestArgs;
}
export interface IndentationRequestArgs extends FileLocationRequestArgs {
options: EditorSettings;
}
/**
* Arguments for ProjectInfoRequest request.
*/
@@ -115,6 +131,14 @@ declare namespace ts.server.protocol {
arguments: ProjectInfoRequestArgs;
}
export interface ProjectRequest extends Request {
arguments: ProjectRequestArgs;
}
export interface ProjectRequestArgs {
projectFileName: string;
}
/**
* Response message body for "projectInfo" request
*/
@@ -128,6 +152,10 @@ declare namespace ts.server.protocol {
* The list of normalized file name in the project, including 'lib.d.ts'
*/
fileNames?: string[];
/**
* Indicates if the project has a active language service instance
*/
languageServiceDisabled?: boolean;
}
export interface DiagnosticWithLinePosition {
@@ -265,6 +293,14 @@ declare namespace ts.server.protocol {
body?: FileSpan[];
}
export interface BraceCompletionRequest extends FileLocationRequest {
arguments: BraceCompletionRequestArgs;
}
export interface BraceCompletionRequestArgs extends FileLocationRequestArgs {
openingBrace: string;
}
/**
* Get occurrences request; value of command field is
* "occurrences". Return response giving spans that are relevant
@@ -544,9 +580,6 @@ declare namespace ts.server.protocol {
/** Defines whether an open brace is put onto a new line for control blocks or not. Default value is false. */
placeOpenBraceOnNewLineForControlBlocks?: boolean;
/** Index operator */
[key: string]: string | number | boolean;
}
/**
+434 -202
View File
@@ -101,6 +101,8 @@ namespace ts.server {
export namespace CommandNames {
export const Brace = "brace";
export const BraceFull = "brace-full";
export const BraceCompletion = "braceCompletion";
export const Change = "change";
export const Close = "close";
export const Completions = "completions";
@@ -119,7 +121,9 @@ namespace ts.server {
export const GeterrForProject = "geterrForProject";
export const SemanticDiagnosticsFull = "semanticDiagnostics-full";
export const NavBar = "navbar";
export const NavBarFull = "navbar-full";
export const Navto = "navto";
export const NavtoFull = "navto-full";
export const Occurrences = "occurrences";
export const DocumentHighlights = "documentHighlights";
export const DocumentHighlightsFull = "documentHighlights-full";
@@ -127,8 +131,11 @@ namespace ts.server {
export const Quickinfo = "quickinfo";
export const QuickinfoFull = "quickinfo-full";
export const References = "references";
export const ReferencesFull = "references-full";
export const Reload = "reload";
export const Rename = "rename";
export const RenameInfoFull = "rename-full";
export const RenameLocationsFull = "renameLocations-full";
export const Saveto = "saveto";
export const SignatureHelp = "signatureHelp";
export const SignatureHelpFull = "signatureHelp-full";
@@ -142,6 +149,15 @@ namespace ts.server {
export const SynchronizeProjectList = "synchronizeProjectList";
export const ApplyChangedToOpenFiles = "applyChangedToOpenFiles";
export const EncodedSemanticClassificationsFull = "encodedSemanticClassifications-full";
export const Cleanup = "cleanup";
export const OutliningSpans = "outliningSpans";
export const TodoComments = "todoComments";
export const Indentation = "indentation";
export const DocCommentTemplate = "docCommentTemplate";
export const SyntacticDiagnosticsFull = "syntacticDiagnostics-full";
export const CompilerOptionsDiagnosticsFull = "compilerOptionsDiagnostics-full";
export const NameOrDottedNameSpan = "nameOrDottedNameSpan";
export const BreakpointStatement = "breakpointStatement";
}
namespace Errors {
@@ -331,6 +347,28 @@ namespace ts.server {
}
}
private cleanProjects(caption: string, projects: Project[]) {
if (!projects) {
return;
}
this.projectService.log(`cleaning ${caption}`);
for (const p of projects) {
p.languageService.cleanupSemanticCache();
}
}
private cleanup() {
this.cleanProjects("inferred projects", this.projectService.inferredProjects);
this.cleanProjects("configured projects", this.projectService.configuredProjects);
this.cleanProjects("external projects", this.projectService.externalProjects);
if (typeof global !== "undefined" && global.gc) {
this.projectService.log(`global.gc()`);
global.gc();
global.gc();
global.gc();
}
}
private getEncodedSemanticClassifications(args: protocol.FileSpanRequestArgs) {
const file = normalizePath(args.file);
const project = this.projectService.getProjectForFile(file);
@@ -340,25 +378,46 @@ namespace ts.server {
return project.languageService.getEncodedSemanticClassifications(file, args);
}
private getSemanticDiagnostics(args: protocol.FileRequestArgs): protocol.DiagnosticWithLinePosition[] {
const file = normalizePath(args.file);
const project = (args.projectFileName && this.projectService.getProject(normalizePath(args.projectFileName))) || this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
const scriptInfo = project.getScriptInfo(file);
const diagnostics = project.languageService.getSemanticDiagnostics(file);
private getProject(projectFileName: string) {
return projectFileName && this.projectService.getProject(projectFileName);
}
private getCompilerOptionsDiagnostics(args: protocol.ProjectRequestArgs) {
const project = this.getProject(args.projectFileName);
return this.convertDiagnostics(project.languageService.getCompilerOptionsDiagnostics(), /*scriptInfo*/ undefined);
}
private convertDiagnostics(diagnostics: Diagnostic[], scriptInfo: ScriptInfo) {
return diagnostics.map(d => <protocol.DiagnosticWithLinePosition>{
message: flattenDiagnosticMessageText(d.messageText, this.host.newLine),
start: d.start,
length: d.length,
category: DiagnosticCategory[d.category].toLowerCase(),
code: d.code,
startLocation: this.getLocation(d.start, scriptInfo),
endLocation: this.getLocation(d.start + d.length, scriptInfo)
startLocation: scriptInfo && this.getLocation(d.start, scriptInfo),
endLocation: scriptInfo && this.getLocation(d.start + d.length, scriptInfo)
});
}
private getDiagnosticsWorker(args: protocol.FileRequestArgs, selector: (project: Project, file: string) => Diagnostic[]) {
const file = normalizePath(args.file);
const project = this.getProject(args.projectFileName) || this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
const scriptInfo = project.getScriptInfo(file);
const diagnostics = selector(project, file);
return this.convertDiagnostics(diagnostics, scriptInfo);
}
private getSyntacticDiagnostics(args: protocol.FileRequestArgs): protocol.DiagnosticWithLinePosition[] {
return this.getDiagnosticsWorker(args, (project, file) => project.languageService.getSyntacticDiagnostics(file));
}
private getSemanticDiagnostics(args: protocol.FileRequestArgs): protocol.DiagnosticWithLinePosition[] {
return this.getDiagnosticsWorker(args, (project, file) => project.languageService.getSemanticDiagnostics(file));
}
private getDefinition(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.FileSpan[] | DefinitionInfo[] {
const file = ts.normalizePath(args.file);
const project = this.projectService.getProjectForFile(file);
@@ -454,7 +513,7 @@ namespace ts.server {
}
const scriptInfo = project.getScriptInfo(fileName);
const position = this.getPosition(args, scriptInfo);
const position = this.getPosition(args, scriptInfo);
const documentHighlights = project.languageService.getDocumentHighlights(fileName, position, args.filesToSearch);
@@ -490,80 +549,128 @@ namespace ts.server {
private getProjectInfo(fileName: string, needFileNameList: boolean): protocol.ProjectInfo {
fileName = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(fileName);
if (!project) {
throw Errors.NoProject;
}
const projectInfo: protocol.ProjectInfo = {
configFileName: project.getProjectFileName()
configFileName: project.getProjectFileName(),
languageServiceDisabled: !project.languageServiceEnabled
};
if (needFileNameList) {
projectInfo.fileNames = project.getFileNames();
}
return projectInfo;
}
private getRenameLocations(line: number, offset: number, fileName: string, findInComments: boolean, findInStrings: boolean): protocol.RenameResponseBody {
const file = ts.normalizePath(fileName);
const info = this.projectService.getScriptInfo(file);
const projects = this.projectService.findReferencingProjects(info);
if (!projects.length) {
private getRenameInfo(args: protocol.FileLocationRequestArgs) {
const { file, project } = this.getFileAndProject(args.file);
const scriptInfo = project.getScriptInfo(file);
const position = this.getPosition(args, scriptInfo);
return project.languageService.getRenameInfo(file, position);
}
private getProjects(args: protocol.FileRequestArgs) {
let projects: Project[];
if (args.projectFileName) {
const project = this.getProject(args.projectFileName);
if (project) {
projects = [project];
}
}
else {
const file = normalizePath(args.file);
const info = this.projectService.getScriptInfo(file);
projects = this.projectService.findReferencingProjects(info);
}
projects = filter(projects, p => p.languageServiceEnabled);
if (!projects || !projects.length) {
throw Errors.NoProject;
}
return projects;
}
const defaultProject = projects[0];
// The rename info should be the same for every project
const scriptInfo = defaultProject.getScriptInfo(file);
const position = scriptInfo.lineOffsetToPosition(line, offset);
const renameInfo = defaultProject.languageService.getRenameInfo(file, position);
if (!renameInfo) {
return undefined;
private getRenameLocations(args: protocol.RenameRequestArgs, simplifiedResult: boolean): protocol.RenameResponseBody | RenameLocation[] {
const file = ts.normalizePath(args.file);
const info = this.projectService.getScriptInfo(file);
const position = this.getPosition(args, info);
const projects = this.getProjects(args);
if (simplifiedResult) {
const defaultProject = projects[0];
// The rename info should be the same for every project
const renameInfo = defaultProject.languageService.getRenameInfo(file, position);
if (!renameInfo) {
return undefined;
}
if (!renameInfo.canRename) {
return {
info: renameInfo,
locs: []
};
}
const fileSpans = combineProjectOutput(
projects,
(project: Project) => {
const renameLocations = project.languageService.findRenameLocations(file, position, args.findInStrings, args.findInComments);
if (!renameLocations) {
return [];
}
return renameLocations.map(location => {
const locationScriptInfo = project.getScriptInfo(location.fileName);
return <protocol.FileSpan>{
file: location.fileName,
start: locationScriptInfo.positionToLineOffset(location.textSpan.start),
end: locationScriptInfo.positionToLineOffset(ts.textSpanEnd(location.textSpan)),
};
});
},
compareRenameLocation,
(a, b) => a.file === b.file && a.start.line === b.start.line && a.start.offset === b.start.offset
);
const locs = fileSpans.reduce<protocol.SpanGroup[]>((accum, cur) => {
let curFileAccum: protocol.SpanGroup;
if (accum.length > 0) {
curFileAccum = accum[accum.length - 1];
if (curFileAccum.file !== cur.file) {
curFileAccum = undefined;
}
}
if (!curFileAccum) {
curFileAccum = { file: cur.file, locs: [] };
accum.push(curFileAccum);
}
curFileAccum.locs.push({ start: cur.start, end: cur.end });
return accum;
}, []);
return { info: renameInfo, locs };
}
else {
return combineProjectOutput(
projects,
p => p.languageService.findRenameLocations(file, position, args.findInStrings, args.findInComments),
/*comparer*/ undefined,
renameLocationIsEqualTo
);
}
if (!renameInfo.canRename) {
return {
info: renameInfo,
locs: []
};
function renameLocationIsEqualTo(a: RenameLocation, b: RenameLocation) {
if (a === b) {
return true;
}
if (!a || !b) {
return false;
}
return a.fileName === b.fileName &&
a.textSpan.start === b.textSpan.start &&
a.textSpan.length === b.textSpan.length;
}
const fileSpans = combineProjectOutput(
projects,
(project: Project) => {
const renameLocations = project.languageService.findRenameLocations(file, position, findInStrings, findInComments);
if (!renameLocations) {
return [];
}
return renameLocations.map(location => {
const locationScriptInfo = project.getScriptInfo(location.fileName);
return <protocol.FileSpan>{
file: location.fileName,
start: locationScriptInfo.positionToLineOffset(location.textSpan.start),
end: locationScriptInfo.positionToLineOffset(ts.textSpanEnd(location.textSpan)),
};
});
},
compareRenameLocation,
(a, b) => a.file === b.file && a.start.line === b.start.line && a.start.offset === b.start.offset
);
const locs = fileSpans.reduce<protocol.SpanGroup[]>((accum, cur) => {
let curFileAccum: protocol.SpanGroup;
if (accum.length > 0) {
curFileAccum = accum[accum.length - 1];
if (curFileAccum.file !== cur.file) {
curFileAccum = undefined;
}
}
if (!curFileAccum) {
curFileAccum = { file: cur.file, locs: [] };
accum.push(curFileAccum);
}
curFileAccum.locs.push({ start: cur.start, end: cur.end });
return accum;
}, []);
return { info: renameInfo, locs };
function compareRenameLocation(a: protocol.FileSpan, b: protocol.FileSpan) {
if (a.file < b.file) {
return -1;
@@ -586,59 +693,66 @@ namespace ts.server {
}
}
private getReferences(line: number, offset: number, fileName: string): protocol.ReferencesResponseBody {
const file = ts.normalizePath(fileName);
const info = this.projectService.getScriptInfo(file);
const projects = this.projectService.findReferencingProjects(info);
if (!projects.length) {
throw Errors.NoProject;
}
private getReferences(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.ReferencesResponseBody | ReferencedSymbol[] {
const file = ts.normalizePath(args.file);
const projects = this.getProjects(args);
const defaultProject = projects[0];
const scriptInfo = defaultProject.getScriptInfo(file);
const position = scriptInfo.lineOffsetToPosition(line, offset);
const nameInfo = defaultProject.languageService.getQuickInfoAtPosition(file, position);
if (!nameInfo) {
return undefined;
const position = this.getPosition(args, scriptInfo);
if (simplifiedResult) {
const nameInfo = defaultProject.languageService.getQuickInfoAtPosition(file, position);
if (!nameInfo) {
return undefined;
}
const displayString = ts.displayPartsToString(nameInfo.displayParts);
const nameSpan = nameInfo.textSpan;
const nameColStart = scriptInfo.positionToLineOffset(nameSpan.start).offset;
const nameText = scriptInfo.snap().getText(nameSpan.start, ts.textSpanEnd(nameSpan));
const refs = combineProjectOutput<protocol.ReferencesResponseItem>(
projects,
(project: Project) => {
const references = project.languageService.getReferencesAtPosition(file, position);
if (!references) {
return [];
}
return references.map(ref => {
const refScriptInfo = project.getScriptInfo(ref.fileName);
const start = refScriptInfo.positionToLineOffset(ref.textSpan.start);
const refLineSpan = refScriptInfo.lineToTextSpan(start.line - 1);
const lineText = refScriptInfo.snap().getText(refLineSpan.start, ts.textSpanEnd(refLineSpan)).replace(/\r|\n/g, "");
return {
file: ref.fileName,
start: start,
lineText: lineText,
end: refScriptInfo.positionToLineOffset(ts.textSpanEnd(ref.textSpan)),
isWriteAccess: ref.isWriteAccess,
isDefinition: ref.isDefinition
};
});
},
compareFileStart,
areReferencesResponseItemsForTheSameLocation
);
return {
refs,
symbolName: nameText,
symbolStartOffset: nameColStart,
symbolDisplayString: displayString
};
}
else {
return combineProjectOutput(
projects,
project => project.languageService.findReferences(file, position),
undefined,
// TODO: fixme
undefined
);
}
const displayString = ts.displayPartsToString(nameInfo.displayParts);
const nameSpan = nameInfo.textSpan;
const nameColStart = scriptInfo.positionToLineOffset(nameSpan.start).offset;
const nameText = scriptInfo.snap().getText(nameSpan.start, ts.textSpanEnd(nameSpan));
const refs = combineProjectOutput<protocol.ReferencesResponseItem>(
projects,
(project: Project) => {
const references = project.languageService.getReferencesAtPosition(file, position);
if (!references) {
return [];
}
return references.map(ref => {
const refScriptInfo = project.getScriptInfo(ref.fileName);
const start = refScriptInfo.positionToLineOffset(ref.textSpan.start);
const refLineSpan = refScriptInfo.lineToTextSpan(start.line - 1);
const lineText = refScriptInfo.snap().getText(refLineSpan.start, ts.textSpanEnd(refLineSpan)).replace(/\r|\n/g, "");
return {
file: ref.fileName,
start: start,
lineText: lineText,
end: refScriptInfo.positionToLineOffset(ts.textSpanEnd(ref.textSpan)),
isWriteAccess: ref.isWriteAccess,
isDefinition: ref.isDefinition
};
});
},
compareFileStart,
areReferencesResponseItemsForTheSameLocation
);
return {
refs,
symbolName: nameText,
symbolStartOffset: nameColStart,
symbolDisplayString: displayString
};
function areReferencesResponseItemsForTheSameLocation(a: protocol.ReferencesResponseItem, b: protocol.ReferencesResponseItem) {
if (a && b) {
@@ -666,6 +780,57 @@ namespace ts.server {
return args.position !== undefined ? args.position : scriptInfo.lineOffsetToPosition(args.line, args.offset);
}
private getFileAndProject(fileName: string) {
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
return { file, project };
}
private getOutliningSpans(args: protocol.FileRequestArgs) {
const { file, project } = this.getFileAndProject(args.file);
return project.languageService.getOutliningSpans(file);
}
private getTodoComments(args: protocol.TodoCommentRequestArgs) {
const { file, project } = this.getFileAndProject(args.file);
return project.languageService.getTodoComments(file, args.descriptors);
}
private getDocCommentTemplate(args: protocol.FileLocationRequestArgs) {
const { file, project } = this.getFileAndProject(args.file);
const scriptInfo = project.getScriptInfo(file);
const position = this.getPosition(args, scriptInfo);
return project.languageService.getDocCommentTemplateAtPosition(file, position);
}
private getIndentation(args: protocol.IndentationRequestArgs) {
const { file, project } = this.getFileAndProject(args.file);
const position = this.getPosition(args, project.getScriptInfo(file));
const indentation = project.languageService.getIndentationAtPosition(file, position, args.options);
return { position, indentation };
}
private getBreakpointStatement(args: protocol.FileLocationRequestArgs) {
const { file, project } = this.getFileAndProject(args.file);
const position = this.getPosition(args, project.getScriptInfo(file));
return project.languageService.getBreakpointStatementAtPosition(file, position);
}
private getNameOrDottedNameSpan(args: protocol.FileLocationRequestArgs) {
const { file, project } = this.getFileAndProject(args.file);
const position = this.getPosition(args, project.getScriptInfo(file));
return project.languageService.getNameOrDottedNameSpan(file, position, position);
}
private isValidBraceCompletion(args: protocol.BraceCompletionRequestArgs) {
const { file, project } = this.getFileAndProject(args.file);
const position = this.getPosition(args, project.getScriptInfo(file));
return project.languageService.isValidBraceCompletionAtPostion(file, position, args.openingBrace.charCodeAt(0));
}
private getQuickInfoWorker(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.QuickInfoResponseBody | QuickInfo {
const file = ts.normalizePath(args.file);
const project = this.projectService.getProjectForFile(file);
@@ -778,10 +943,10 @@ namespace ts.server {
if (lineText.search("\\S") < 0) {
// TODO: get these options from host
const editorOptions: ts.EditorOptions = {
IndentSize: formatOptions.IndentSize,
TabSize: formatOptions.TabSize,
NewLineCharacter: formatOptions.NewLineCharacter,
ConvertTabsToSpaces: formatOptions.ConvertTabsToSpaces,
IndentSize: formatOptions.indentSize,
TabSize: formatOptions.tabSize,
NewLineCharacter: formatOptions.newLineCharacter,
ConvertTabsToSpaces: formatOptions.convertTabsToSpaces,
IndentStyle: ts.IndentStyle.Smart,
};
const preferredIndent = project.languageService.getIndentationAtPosition(file, position, editorOptions);
@@ -983,68 +1148,87 @@ namespace ts.server {
}));
}
private getNavigationBarItems(fileName: string): protocol.NavigationBarItem[] {
const file = ts.normalizePath(fileName);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
private getNavigationBarItems(fileName: string, simplifiedResult: boolean): protocol.NavigationBarItem[] | NavigationBarItem[] {
const { file, project } = this.getFileAndProject(fileName);
const items = project.languageService.getNavigationBarItems(file);
if (!items) {
return undefined;
}
return this.decorateNavigationBarItem(project, fileName, items);
return simplifiedResult
? this.decorateNavigationBarItem(project, fileName, items)
: items;
}
private getNavigateToItems(searchValue: string, fileName: string, maxResultCount?: number): protocol.NavtoItem[] {
const file = ts.normalizePath(fileName);
const info = this.projectService.getScriptInfo(file);
const projects = this.projectService.findReferencingProjects(info);
const defaultProject = projects[0];
if (!defaultProject) {
throw Errors.NoProject;
private getNavigateToItems(args: protocol.NavtoRequestArgs, simplifiedResult: boolean): protocol.NavtoItem[] | NavigateToItem[] {
const projects = this.getProjects(args);
if (simplifiedResult) {
return combineProjectOutput(
projects,
project => {
const navItems = project.languageService.getNavigateToItems(args.searchValue, args.maxResultCount);
if (!navItems) {
return [];
}
return navItems.map((navItem) => {
const scriptInfo = project.getScriptInfo(navItem.fileName);
const start = scriptInfo.positionToLineOffset(navItem.textSpan.start);
const end = scriptInfo.positionToLineOffset(ts.textSpanEnd(navItem.textSpan));
const bakedItem: protocol.NavtoItem = {
name: navItem.name,
kind: navItem.kind,
file: navItem.fileName,
start: start,
end: end,
};
if (navItem.kindModifiers && (navItem.kindModifiers !== "")) {
bakedItem.kindModifiers = navItem.kindModifiers;
}
if (navItem.matchKind !== "none") {
bakedItem.matchKind = navItem.matchKind;
}
if (navItem.containerName && (navItem.containerName.length > 0)) {
bakedItem.containerName = navItem.containerName;
}
if (navItem.containerKind && (navItem.containerKind.length > 0)) {
bakedItem.containerKind = navItem.containerKind;
}
return bakedItem;
});
},
/*comparer*/ undefined,
areNavToItemsForTheSameLocation
);
}
else {
return combineProjectOutput(
projects,
project => project.languageService.getNavigateToItems(args.searchValue, args.maxResultCount),
/*comparer*/ undefined,
navigateToItemIsEqualTo);
}
const allNavToItems = combineProjectOutput(
projects,
(project: Project) => {
const navItems = project.languageService.getNavigateToItems(searchValue, maxResultCount);
if (!navItems) {
return [];
}
return navItems.map((navItem) => {
const scriptInfo = project.getScriptInfo(navItem.fileName);
const start = scriptInfo.positionToLineOffset(navItem.textSpan.start);
const end = scriptInfo.positionToLineOffset(ts.textSpanEnd(navItem.textSpan));
const bakedItem: protocol.NavtoItem = {
name: navItem.name,
kind: navItem.kind,
file: navItem.fileName,
start: start,
end: end,
};
if (navItem.kindModifiers && (navItem.kindModifiers !== "")) {
bakedItem.kindModifiers = navItem.kindModifiers;
}
if (navItem.matchKind !== "none") {
bakedItem.matchKind = navItem.matchKind;
}
if (navItem.containerName && (navItem.containerName.length > 0)) {
bakedItem.containerName = navItem.containerName;
}
if (navItem.containerKind && (navItem.containerKind.length > 0)) {
bakedItem.containerKind = navItem.containerKind;
}
return bakedItem;
});
},
/*comparer*/ undefined,
areNavToItemsForTheSameLocation
);
return allNavToItems;
function navigateToItemIsEqualTo(a: NavigateToItem, b: NavigateToItem): boolean {
if (a === b) {
return true;
}
if (!a || !b) {
return false;
}
return a.containerKind === b.containerKind &&
a.containerName === b.containerName &&
a.fileName === b.fileName &&
a.isCaseSensitive === b.isCaseSensitive &&
a.kind === b.kind &&
a.kindModifiers === b.containerName &&
a.matchKind === b.matchKind &&
a.name === b.name &&
a.textSpan.start === b.textSpan.start &&
a.textSpan.length === b.textSpan.length;
}
function areNavToItemsForTheSameLocation(a: protocol.NavtoItem, b: protocol.NavtoItem) {
if (a && b) {
@@ -1056,30 +1240,34 @@ namespace ts.server {
}
}
private getBraceMatching(line: number, offset: number, fileName: string): protocol.TextSpan[] {
const file = ts.normalizePath(fileName);
private getBraceMatching(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.TextSpan[] | TextSpan[] {
const { file, project } = this.getFileAndProject(args.file);
const project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
}
const scriptInfo = project.getScriptInfo(fileName);
const position = scriptInfo.lineOffsetToPosition(line, offset);
const scriptInfo = project.getScriptInfo(file);
const position = this.getPosition(args, scriptInfo);
const spans = project.languageService.getBraceMatchingAtPosition(file, position);
if (!spans) {
return undefined;
}
if (simplifiedResult) {
return spans.map(span => ({
start: scriptInfo.positionToLineOffset(span.start),
end: scriptInfo.positionToLineOffset(span.start + span.length)
}));
return spans.map(span => ({
start: scriptInfo.positionToLineOffset(span.start),
end: scriptInfo.positionToLineOffset(span.start + span.length)
}));
}
else {
return spans;
}
}
getDiagnosticsForProject(delay: number, fileName: string) {
const { fileNames } = this.getProjectInfo(fileName, /*needFileNameList*/ true);
const { fileNames, languageServiceDisabled } = this.getProjectInfo(fileName, /*needFileNameList*/ true);
if (languageServiceDisabled) {
return;
}
// No need to analyze lib.d.ts
let fileNamesInProject = fileNames.filter((value, index, array) => value.indexOf("lib.d.ts") < 0);
@@ -1176,13 +1364,20 @@ namespace ts.server {
const defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return this.requiredResponse(this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file));
},
[CommandNames.References]: (request: protocol.Request) => {
const defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return this.requiredResponse(this.getReferences(defArgs.line, defArgs.offset, defArgs.file));
[CommandNames.References]: (request: protocol.FileLocationRequest) => {
return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ true));
},
[CommandNames.ReferencesFull]: (request: protocol.FileLocationRequest) => {
return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ false));
},
[CommandNames.Rename]: (request: protocol.Request) => {
const renameArgs = <protocol.RenameRequestArgs>request.arguments;
return this.requiredResponse(this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings));
return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ true));
},
[CommandNames.RenameLocationsFull]: (request: protocol.RenameRequest) => {
return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ false));
},
[CommandNames.RenameInfoFull]: (request: protocol.FileLocationRequest) => {
return this.requiredResponse(this.getRenameInfo(request.arguments));
},
[CommandNames.Open]: (request: protocol.Request) => {
const openArgs = <protocol.OpenRequestArgs>request.arguments;
@@ -1210,6 +1405,27 @@ namespace ts.server {
[CommandNames.QuickinfoFull]: (request: protocol.QuickInfoRequest) => {
return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ false));
},
[CommandNames.OutliningSpans]: (request: protocol.FileRequest) => {
return this.requiredResponse(this.getOutliningSpans(request.arguments));
},
[CommandNames.TodoComments]: (request: protocol.TodoCommentRequest) => {
return this.requiredResponse(this.getTodoComments(request.arguments));
},
[CommandNames.Indentation]: (request: protocol.IndentationRequest) => {
return this.requiredResponse(this.getIndentation(request.arguments));
},
[CommandNames.NameOrDottedNameSpan]: (request: protocol.FileLocationRequest) => {
return this.requiredResponse(this.getNameOrDottedNameSpan(request.arguments));
},
[CommandNames.BreakpointStatement]: (request: protocol.FileLocationRequest) => {
return this.requiredResponse(this.getBreakpointStatement(request.arguments));
},
[CommandNames.BraceCompletion]: (request: protocol.BraceCompletionRequest) => {
return this.requiredResponse(this.isValidBraceCompletion(request.arguments));
},
[CommandNames.DocCommentTemplate]: (request: protocol.FileLocationRequest) => {
return this.requiredResponse(this.getDocCommentTemplate(request.arguments));
},
[CommandNames.Format]: (request: protocol.Request) => {
const formatArgs = <protocol.FormatRequestArgs>request.arguments;
return this.requiredResponse(this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file));
@@ -1245,9 +1461,19 @@ namespace ts.server {
[CommandNames.SemanticDiagnosticsFull]: (request: protocol.FileRequest) => {
return this.requiredResponse(this.getSemanticDiagnostics(request.arguments));
},
[CommandNames.SyntacticDiagnosticsFull]: (request: protocol.FileRequest) => {
return this.requiredResponse(this.getSyntacticDiagnostics(request.arguments));
},
[CommandNames.CompilerOptionsDiagnosticsFull]: (request: protocol.ProjectRequest) => {
return this.requiredResponse(this.getCompilerOptionsDiagnostics(request.arguments));
},
[CommandNames.EncodedSemanticClassificationsFull]: (request: protocol.FileSpanRequest) => {
return this.requiredResponse(this.getEncodedSemanticClassifications(request.arguments));
},
[CommandNames.Cleanup]: (request: protocol.Request) => {
this.cleanup();
return this.requiredResponse(true);
},
[CommandNames.Geterr]: (request: protocol.Request) => {
const geterrArgs = <protocol.GeterrRequestArgs>request.arguments;
return { response: this.getDiagnostics(geterrArgs.delay, geterrArgs.files), responseRequired: false };
@@ -1271,7 +1497,7 @@ namespace ts.server {
[CommandNames.Reload]: (request: protocol.Request) => {
const reloadArgs = <protocol.ReloadRequestArgs>request.arguments;
this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq);
return {response: { reloadFinished: true }, responseRequired: true};
return { response: { reloadFinished: true }, responseRequired: true };
},
[CommandNames.Saveto]: (request: protocol.Request) => {
const savetoArgs = <protocol.SavetoRequestArgs>request.arguments;
@@ -1283,17 +1509,23 @@ namespace ts.server {
this.closeClientFile(closeArgs.file);
return { responseRequired: false };
},
[CommandNames.Navto]: (request: protocol.Request) => {
const navtoArgs = <protocol.NavtoRequestArgs>request.arguments;
return { response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount), responseRequired: true };
[CommandNames.Navto]: (request: protocol.NavtoRequest) => {
return this.requiredResponse(this.getNavigateToItems(request.arguments, /*simplifiedResult*/ true));
},
[CommandNames.Brace]: (request: protocol.Request) => {
const braceArguments = <protocol.FileLocationRequestArgs>request.arguments;
return { response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file), responseRequired: true };
[CommandNames.NavtoFull]: (request: protocol.NavtoRequest) => {
return this.requiredResponse(this.getNavigateToItems(request.arguments, /*simplifiedResult*/ false));
},
[CommandNames.NavBar]: (request: protocol.Request) => {
const navBarArgs = <protocol.FileRequestArgs>request.arguments;
return { response: this.getNavigationBarItems(navBarArgs.file), responseRequired: true };
[CommandNames.Brace]: (request: protocol.FileLocationRequest) => {
return this.requiredResponse(this.getBraceMatching(request.arguments, /*simplifiedResult*/ true));
},
[CommandNames.BraceFull]: (request: protocol.FileLocationRequest) => {
return this.requiredResponse(this.getBraceMatching(request.arguments, /*simplifiedResult*/ false));
},
[CommandNames.NavBar]: (request: protocol.FileRequest) => {
return this.requiredResponse(this.getNavigationBarItems(request.arguments.file, /*simplifiedResult*/ true));
},
[CommandNames.NavBarFull]: (request: protocol.FileRequest) => {
return this.requiredResponse(this.getNavigationBarItems(request.arguments.file, /*simplifiedResult*/ false));
},
[CommandNames.Occurrences]: (request: protocol.Request) => {
const { line, offset, file: fileName } = <protocol.FileLocationRequestArgs>request.arguments;
+24 -24
View File
@@ -67,7 +67,7 @@ namespace ts.formatting {
delta: number;
}
export function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
export function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] {
const line = sourceFile.getLineAndCharacterOfPosition(position).line;
if (line === 0) {
return [];
@@ -96,15 +96,15 @@ namespace ts.formatting {
return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnEnter);
}
export function formatOnSemicolon(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
export function formatOnSemicolon(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] {
return formatOutermostParent(position, SyntaxKind.SemicolonToken, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnSemicolon);
}
export function formatOnClosingCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
export function formatOnClosingCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] {
return formatOutermostParent(position, SyntaxKind.CloseBraceToken, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnClosingCurlyBrace);
}
export function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
export function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] {
const span = {
pos: 0,
end: sourceFile.text.length
@@ -112,7 +112,7 @@ namespace ts.formatting {
return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatDocument);
}
export function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
export function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] {
// format from the beginning of the line
const span = {
pos: getLineStartPositionForPosition(start, sourceFile),
@@ -121,7 +121,7 @@ namespace ts.formatting {
return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatSelection);
}
function formatOutermostParent(position: number, expectedLastToken: SyntaxKind, sourceFile: SourceFile, options: FormatCodeOptions, rulesProvider: RulesProvider, requestKind: FormattingRequestKind): TextChange[] {
function formatOutermostParent(position: number, expectedLastToken: SyntaxKind, sourceFile: SourceFile, options: FormatCodeSettings, rulesProvider: RulesProvider, requestKind: FormattingRequestKind): TextChange[] {
const parent = findOutermostParent(position, expectedLastToken, sourceFile);
if (!parent) {
return [];
@@ -294,7 +294,7 @@ namespace ts.formatting {
* if parent is on the different line - its delta was already contributed
* to the initial indentation.
*/
function getOwnOrInheritedDelta(n: Node, options: FormatCodeOptions, sourceFile: SourceFile): number {
function getOwnOrInheritedDelta(n: Node, options: FormatCodeSettings, sourceFile: SourceFile): number {
let previousLine = Constants.Unknown;
let child: Node;
while (n) {
@@ -304,7 +304,7 @@ namespace ts.formatting {
}
if (SmartIndenter.shouldIndentChildNode(n, child)) {
return options.IndentSize;
return options.indentSize;
}
previousLine = line;
@@ -316,7 +316,7 @@ namespace ts.formatting {
function formatSpan(originalRange: TextRange,
sourceFile: SourceFile,
options: FormatCodeOptions,
options: FormatCodeSettings,
rulesProvider: RulesProvider,
requestKind: FormattingRequestKind): TextChange[] {
@@ -410,7 +410,7 @@ namespace ts.formatting {
effectiveParentStartLine: number): Indentation {
let indentation = inheritedIndentation;
let delta = SmartIndenter.shouldIndentChildNode(node) ? options.IndentSize : 0;
let delta = SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0;
if (effectiveParentStartLine === startLine) {
// if node is located on the same line with the parent
@@ -419,7 +419,7 @@ namespace ts.formatting {
indentation = startLine === lastIndentedLine
? indentationOnLastIndentedLine
: parentDynamicIndentation.getIndentation();
delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta(node) + delta);
delta = Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta);
}
else if (indentation === Constants.Unknown) {
if (SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
@@ -503,14 +503,14 @@ namespace ts.formatting {
recomputeIndentation: lineAdded => {
if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent, node)) {
if (lineAdded) {
indentation += options.IndentSize;
indentation += options.indentSize;
}
else {
indentation -= options.IndentSize;
indentation -= options.indentSize;
}
if (SmartIndenter.shouldIndentChildNode(node)) {
delta = options.IndentSize;
delta = options.indentSize;
}
else {
delta = 0;
@@ -1036,7 +1036,7 @@ namespace ts.formatting {
// edit should not be applied only if we have one line feed between elements
const lineDelta = currentStartLine - previousStartLine;
if (lineDelta !== 1) {
recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.NewLineCharacter);
recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter);
}
break;
case RuleAction.Space:
@@ -1102,19 +1102,19 @@ namespace ts.formatting {
let internedTabsIndentation: string[];
let internedSpacesIndentation: string[];
export function getIndentationString(indentation: number, options: FormatCodeOptions): string {
export function getIndentationString(indentation: number, options: EditorSettings): string {
// reset interned strings if FormatCodeOptions were changed
const resetInternedStrings =
!internedSizes || (internedSizes.tabSize !== options.TabSize || internedSizes.indentSize !== options.IndentSize);
!internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize);
if (resetInternedStrings) {
internedSizes = { tabSize: options.TabSize, indentSize: options.IndentSize };
internedSizes = { tabSize: options.tabSize, indentSize: options.indentSize };
internedTabsIndentation = internedSpacesIndentation = undefined;
}
if (!options.ConvertTabsToSpaces) {
const tabs = Math.floor(indentation / options.TabSize);
const spaces = indentation - tabs * options.TabSize;
if (!options.convertTabsToSpaces) {
const tabs = Math.floor(indentation / options.tabSize);
const spaces = indentation - tabs * options.tabSize;
let tabString: string;
if (!internedTabsIndentation) {
@@ -1132,14 +1132,14 @@ namespace ts.formatting {
}
else {
let spacesString: string;
const quotient = Math.floor(indentation / options.IndentSize);
const remainder = indentation % options.IndentSize;
const quotient = Math.floor(indentation / options.indentSize);
const remainder = indentation % options.indentSize;
if (!internedSpacesIndentation) {
internedSpacesIndentation = [];
}
if (internedSpacesIndentation[quotient] === undefined) {
spacesString = repeat(" ", options.IndentSize * quotient);
spacesString = repeat(" ", options.indentSize * quotient);
internedSpacesIndentation[quotient] = spacesString;
}
else {
+13 -13
View File
@@ -4,7 +4,7 @@
namespace ts.formatting {
export class RulesProvider {
private globalRules: Rules;
private options: ts.FormatCodeOptions;
private options: ts.FormatCodeSettings;
private activeRules: Rule[];
private rulesMap: RulesMap;
@@ -24,7 +24,7 @@ namespace ts.formatting {
return this.rulesMap;
}
public ensureUpToDate(options: ts.FormatCodeOptions) {
public ensureUpToDate(options: ts.FormatCodeSettings) {
if (!this.options || !ts.compareDataObjects(this.options, options)) {
const activeRules = this.createActiveRules(options);
const rulesMap = RulesMap.create(activeRules);
@@ -35,31 +35,31 @@ namespace ts.formatting {
}
}
private createActiveRules(options: ts.FormatCodeOptions): Rule[] {
private createActiveRules(options: ts.FormatCodeSettings): Rule[] {
let rules = this.globalRules.HighPriorityCommonRules.slice(0);
if (options.InsertSpaceAfterCommaDelimiter) {
if (options.insertSpaceAfterCommaDelimiter) {
rules.push(this.globalRules.SpaceAfterComma);
}
else {
rules.push(this.globalRules.NoSpaceAfterComma);
}
if (options.InsertSpaceAfterFunctionKeywordForAnonymousFunctions) {
if (options.insertSpaceAfterFunctionKeywordForAnonymousFunctions) {
rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword);
}
else {
rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword);
}
if (options.InsertSpaceAfterKeywordsInControlFlowStatements) {
if (options.insertSpaceAfterKeywordsInControlFlowStatements) {
rules.push(this.globalRules.SpaceAfterKeywordInControl);
}
else {
rules.push(this.globalRules.NoSpaceAfterKeywordInControl);
}
if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) {
if (options.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) {
rules.push(this.globalRules.SpaceAfterOpenParen);
rules.push(this.globalRules.SpaceBeforeCloseParen);
rules.push(this.globalRules.NoSpaceBetweenParens);
@@ -70,7 +70,7 @@ namespace ts.formatting {
rules.push(this.globalRules.NoSpaceBetweenParens);
}
if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets) {
if (options.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets) {
rules.push(this.globalRules.SpaceAfterOpenBracket);
rules.push(this.globalRules.SpaceBeforeCloseBracket);
rules.push(this.globalRules.NoSpaceBetweenBrackets);
@@ -81,7 +81,7 @@ namespace ts.formatting {
rules.push(this.globalRules.NoSpaceBetweenBrackets);
}
if (options.InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces) {
if (options.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces) {
rules.push(this.globalRules.SpaceAfterTemplateHeadAndMiddle);
rules.push(this.globalRules.SpaceBeforeTemplateMiddleAndTail);
}
@@ -90,14 +90,14 @@ namespace ts.formatting {
rules.push(this.globalRules.NoSpaceBeforeTemplateMiddleAndTail);
}
if (options.InsertSpaceAfterSemicolonInForStatements) {
if (options.insertSpaceAfterSemicolonInForStatements) {
rules.push(this.globalRules.SpaceAfterSemicolonInFor);
}
else {
rules.push(this.globalRules.NoSpaceAfterSemicolonInFor);
}
if (options.InsertSpaceBeforeAndAfterBinaryOperators) {
if (options.insertSpaceBeforeAndAfterBinaryOperators) {
rules.push(this.globalRules.SpaceBeforeBinaryOperator);
rules.push(this.globalRules.SpaceAfterBinaryOperator);
}
@@ -106,11 +106,11 @@ namespace ts.formatting {
rules.push(this.globalRules.NoSpaceAfterBinaryOperator);
}
if (options.PlaceOpenBraceOnNewLineForControlBlocks) {
if (options.placeOpenBraceOnNewLineForControlBlocks) {
rules.push(this.globalRules.NewLineBeforeOpenBraceInControl);
}
if (options.PlaceOpenBraceOnNewLineForFunctions) {
if (options.placeOpenBraceOnNewLineForFunctions) {
rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction);
rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock);
}
+17 -17
View File
@@ -8,14 +8,14 @@ namespace ts.formatting {
Unknown = -1
}
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorOptions): number {
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings): number {
if (position > sourceFile.text.length) {
return 0; // past EOF
}
// no indentation when the indent style is set to none,
// so we can return fast
if (options.IndentStyle === IndentStyle.None) {
if (options.indentStyle === IndentStyle.None) {
return 0;
}
@@ -35,7 +35,7 @@ namespace ts.formatting {
// indentation is first non-whitespace character in a previous line
// for block indentation, we should look for a line which contains something that's not
// whitespace.
if (options.IndentStyle === IndentStyle.Block) {
if (options.indentStyle === IndentStyle.Block) {
// move backwards until we find a line with a non-whitespace character,
// then find the first non-whitespace character for that line.
@@ -75,7 +75,7 @@ namespace ts.formatting {
indentationDelta = 0;
}
else {
indentationDelta = lineAtPosition !== currentStart.line ? options.IndentSize : 0;
indentationDelta = lineAtPosition !== currentStart.line ? options.indentSize : 0;
}
break;
@@ -88,7 +88,7 @@ namespace ts.formatting {
}
actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options);
if (actualIndentation !== Value.Unknown) {
return actualIndentation + options.IndentSize;
return actualIndentation + options.indentSize;
}
previous = current;
@@ -103,7 +103,7 @@ namespace ts.formatting {
return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, options);
}
export function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: FormatCodeOptions): number {
export function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: EditorSettings): number {
const start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, options);
}
@@ -114,7 +114,7 @@ namespace ts.formatting {
ignoreActualIndentationRange: TextRange,
indentationDelta: number,
sourceFile: SourceFile,
options: EditorOptions): number {
options: EditorSettings): number {
let parent: Node = current.parent;
let parentStart: LineAndCharacter;
@@ -154,7 +154,7 @@ namespace ts.formatting {
// increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
if (shouldIndentChildNode(parent, current) && !parentAndChildShareLine) {
indentationDelta += options.IndentSize;
indentationDelta += options.indentSize;
}
current = parent;
@@ -178,7 +178,7 @@ namespace ts.formatting {
/*
* Function returns Value.Unknown if indentation cannot be determined
*/
function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: EditorOptions): number {
function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: EditorSettings): number {
// previous token is comma that separates items in list - find the previous item and try to derive indentation from it
const commaItemInfo = findListItemInfo(commaToken);
if (commaItemInfo && commaItemInfo.listItemIndex > 0) {
@@ -198,7 +198,7 @@ namespace ts.formatting {
currentLineAndChar: LineAndCharacter,
parentAndChildShareLine: boolean,
sourceFile: SourceFile,
options: EditorOptions): number {
options: EditorSettings): number {
// actual indentation is used for statements\declarations if one of cases below is true:
// - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually
@@ -305,7 +305,7 @@ namespace ts.formatting {
return undefined;
}
function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorOptions): number {
function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorSettings): number {
const containingList = getContainingList(node, sourceFile);
return containingList ? getActualIndentationFromList(containingList) : Value.Unknown;
@@ -315,7 +315,7 @@ namespace ts.formatting {
}
}
function getLineIndentationWhenExpressionIsInMultiLine(node: Node, sourceFile: SourceFile, options: EditorOptions): number {
function getLineIndentationWhenExpressionIsInMultiLine(node: Node, sourceFile: SourceFile, options: EditorSettings): number {
// actual indentation should not be used when:
// - node is close parenthesis - this is the end of the expression
if (node.kind === SyntaxKind.CloseParenToken) {
@@ -363,7 +363,7 @@ namespace ts.formatting {
}
}
function deriveActualIndentationFromList(list: Node[], index: number, sourceFile: SourceFile, options: EditorOptions): number {
function deriveActualIndentationFromList(list: Node[], index: number, sourceFile: SourceFile, options: EditorSettings): number {
Debug.assert(index >= 0 && index < list.length);
const node = list[index];
@@ -385,7 +385,7 @@ namespace ts.formatting {
return Value.Unknown;
}
function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: LineAndCharacter, sourceFile: SourceFile, options: EditorOptions): number {
function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: LineAndCharacter, sourceFile: SourceFile, options: EditorSettings): number {
const lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0);
return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options);
}
@@ -397,7 +397,7 @@ namespace ts.formatting {
value of 'character' for '$' is 3
value of 'column' for '$' is 6 (assuming that tab size is 4)
*/
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions) {
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings) {
let character = 0;
let column = 0;
for (let pos = startPos; pos < endPos; pos++) {
@@ -407,7 +407,7 @@ namespace ts.formatting {
}
if (ch === CharacterCodes.tab) {
column += options.TabSize + (column % options.TabSize);
column += options.tabSize + (column % options.tabSize);
}
else {
column++;
@@ -418,7 +418,7 @@ namespace ts.formatting {
return { column, character };
}
export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions): number {
export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings): number {
return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
}
+2 -2
View File
@@ -10,7 +10,7 @@ namespace ts.JsTyping {
directoryExists: (path: string) => boolean;
fileExists: (fileName: string) => boolean;
readFile: (path: string, encoding?: string) => string;
readDirectory: (path: string, extension?: string, exclude?: string[], depth?: number) => string[];
readDirectory: (rootDir: string, extensions: string[], excludes: string[], includes: string[], depth?: number) => string[];
};
interface PackageJson {
@@ -187,7 +187,7 @@ namespace ts.JsTyping {
}
const typingNames: string[] = [];
const fileNames = host.readDirectory(nodeModulesPath, "*.json", /*exclude*/ undefined, /*depth*/ 2);
const fileNames = host.readDirectory(nodeModulesPath, ["*.json"], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 2);
for (const fileName of fileNames) {
const normalizedFileName = normalizePath(fileName);
if (getBaseFileName(normalizedFileName) !== "package.json") {
File diff suppressed because it is too large Load Diff
+90 -19
View File
@@ -1,4 +1,5 @@
/// <reference path="..\compiler\program.ts"/>
/// <reference path="..\compiler\commandLineParser.ts"/>
/// <reference path='breakpoints.ts' />
/// <reference path='outliningElementsCollector.ts' />
@@ -1154,11 +1155,11 @@ namespace ts {
getOutliningSpans(fileName: string): OutliningSpan[];
getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number;
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number;
getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[];
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[];
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[];
getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[];
getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion;
@@ -1258,6 +1259,7 @@ namespace ts {
containerKind: string;
}
/* @deprecated - consider using EditorSettings instead */
export interface EditorOptions {
IndentSize: number;
TabSize: number;
@@ -1266,12 +1268,21 @@ namespace ts {
IndentStyle: IndentStyle;
}
export interface EditorSettings {
indentSize: number;
tabSize: number;
newLineCharacter: string;
convertTabsToSpaces: boolean;
indentStyle: IndentStyle;
}
export enum IndentStyle {
None = 0,
Block = 1,
Smart = 2,
}
/* @deprecated - consider using FormatCodeSettings instead */
export interface FormatCodeOptions extends EditorOptions {
InsertSpaceAfterCommaDelimiter: boolean;
InsertSpaceAfterSemicolonInForStatements: boolean;
@@ -1283,9 +1294,50 @@ namespace ts {
InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean;
PlaceOpenBraceOnNewLineForFunctions: boolean;
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
[s: string]: boolean | number | string;
}
export interface FormatCodeSettings extends EditorSettings {
insertSpaceAfterCommaDelimiter: boolean;
insertSpaceAfterSemicolonInForStatements: boolean;
insertSpaceBeforeAndAfterBinaryOperators: boolean;
insertSpaceAfterKeywordsInControlFlowStatements: boolean;
insertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean;
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean;
placeOpenBraceOnNewLineForFunctions: boolean;
placeOpenBraceOnNewLineForControlBlocks: boolean;
}
/* @internal */
export function toEditorSettings(options: FormatCodeOptions | FormatCodeSettings): FormatCodeSettings;
export function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings;
export function toEditorSettings(optionsAsMap: Map<any>): Map<any> {
let allPropertiesAreCamelCased = true;
for (const key in optionsAsMap) {
if (hasProperty(optionsAsMap, key) && !isCamelCase(key)) {
allPropertiesAreCamelCased = false;
break;
}
}
if (allPropertiesAreCamelCased) {
return optionsAsMap;
}
const settings: Map<any> = {};
for (const key in optionsAsMap) {
if (hasProperty(optionsAsMap, key)) {
const newKey = isCamelCase(key) ? key : key.charAt(0).toLowerCase() + key.substr(1);
settings[newKey] = optionsAsMap[key];
}
}
return settings;
}
function isCamelCase(s: string) {
return !s.length || s.charAt(0) === s.charAt(0).toLowerCase();
}
export interface DefinitionInfo {
fileName: string;
textSpan: TextSpan;
@@ -1973,6 +2025,18 @@ namespace ts {
// so pass --noLib to avoid reporting a file not found error.
options.noLib = true;
// Clear out other settings that would not be used in transpiling this module
options.lib = undefined;
options.types = undefined;
options.noEmit = undefined;
options.noEmitOnError = undefined;
options.paths = undefined;
options.rootDirs = undefined;
options.declaration = undefined;
options.declarationDir = undefined;
options.out = undefined;
options.outFile = undefined;
// We are not doing a full typecheck, we are not resolving the whole context,
// so pass --noResolve to avoid reporting missing file errors.
options.noResolve = true;
@@ -2905,7 +2969,7 @@ namespace ts {
return sourceFile;
}
function getRuleProvider(options: FormatCodeOptions) {
function getRuleProvider(options: FormatCodeSettings) {
// Ensure rules are initialized and up to date wrt to formatting options
if (!ruleProvider) {
ruleProvider = new formatting.RulesProvider();
@@ -2950,7 +3014,8 @@ namespace ts {
oldSettings.moduleResolution !== newSettings.moduleResolution ||
oldSettings.noResolve !== newSettings.noResolve ||
oldSettings.jsx !== newSettings.jsx ||
oldSettings.allowJs !== newSettings.allowJs);
oldSettings.allowJs !== newSettings.allowJs ||
oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit);
// Now create a new compiler
const compilerHost: CompilerHost = {
@@ -3175,6 +3240,7 @@ namespace ts {
function cleanupSemanticCache(): void {
// TODO: Should we jettison the program (or it's type checker) here?
program.dropDiagnosticsProducingTypeChecker();
}
function dispose(): void {
@@ -7066,7 +7132,7 @@ namespace ts {
function getNavigationBarItems(fileName: string): NavigationBarItem[] {
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
return NavigationBar.getNavigationBarItems(sourceFile, host.getCompilationSettings());
return NavigationBar.getNavigationBarItems(sourceFile);
}
function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
@@ -7560,7 +7626,8 @@ namespace ts {
return;
case SyntaxKind.Parameter:
if ((<ParameterDeclaration>token.parent).name === token) {
return ClassificationType.parameterName;
const isThis = token.kind === SyntaxKind.Identifier && (<Identifier>token).originalKeywordKind === SyntaxKind.ThisKeyword;
return isThis ? ClassificationType.keyword : ClassificationType.parameterName;
}
return;
}
@@ -7647,40 +7714,44 @@ namespace ts {
}
}
function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) {
function getIndentationAtPosition(fileName: string, position: number, optionsOrSettings: EditorOptions | EditorSettings) {
let start = new Date().getTime();
const settings = toEditorSettings(optionsOrSettings);
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
start = new Date().getTime();
const result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions);
const result = formatting.SmartIndenter.getIndentation(position, sourceFile, settings);
log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start));
return result;
}
function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] {
function getFormattingEditsForRange(fileName: string, start: number, end: number, optionsOrSettings: FormatCodeOptions | FormatCodeSettings): TextChange[] {
const settings = toEditorSettings(optionsOrSettings);
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options);
return formatting.formatSelection(start, end, sourceFile, getRuleProvider(settings), settings);
}
function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] {
function getFormattingEditsForDocument(fileName: string, optionsOrSettings: FormatCodeOptions | FormatCodeSettings): TextChange[] {
const settings = toEditorSettings(optionsOrSettings);
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
return formatting.formatDocument(sourceFile, getRuleProvider(options), options);
return formatting.formatDocument(sourceFile, getRuleProvider(settings), settings);
}
function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] {
function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, optionsOrSettings: FormatCodeOptions | FormatCodeSettings): TextChange[] {
const settings = toEditorSettings(optionsOrSettings);
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
if (key === "}") {
return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options);
return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(settings), settings);
}
else if (key === ";") {
return formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(options), options);
return formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(settings), settings);
}
else if (key === "\n") {
return formatting.formatOnEnter(position, sourceFile, getRuleProvider(options), options);
return formatting.formatOnEnter(position, sourceFile, getRuleProvider(settings), settings);
}
return [];
+31 -7
View File
@@ -80,8 +80,9 @@ namespace ts {
* @param exclude A JSON encoded string[] containing the paths to exclude
* when enumerating the directory.
*/
readDirectory(rootDir: string, extension: string, exclude?: string, depth?: number): string;
readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string;
useCaseSensitiveFileNames?(): boolean;
getCurrentDirectory(): string;
trace(s: string): void;
}
@@ -437,8 +438,10 @@ namespace ts {
public directoryExists: (directoryName: string) => boolean;
public realpath: (path: string) => string;
public useCaseSensitiveFileNames: boolean;
constructor(private shimHost: CoreServicesShimHost) {
this.useCaseSensitiveFileNames = this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false;
if ("directoryExists" in this.shimHost) {
this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName);
}
@@ -447,17 +450,34 @@ namespace ts {
}
}
public readDirectory(rootDir: string, extension: string, exclude: string[], depth?: number): string[] {
public readDirectory(rootDir: string, extensions: string[], exclude: string[], include: string[], depth?: number): string[] {
// Wrap the API changes for 2.0 release. This try/catch
// should be removed once TypeScript 2.0 has shipped.
let encoded: string;
try {
encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude), depth);
const pattern = getFileMatcherPatterns(rootDir, extensions, exclude, include,
this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory());
return JSON.parse(this.shimHost.readDirectory(
rootDir,
JSON.stringify(extensions),
JSON.stringify(pattern.basePaths),
pattern.excludePattern,
pattern.includeFilePattern,
pattern.includeDirectoryPattern,
depth
));
}
catch (e) {
encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude));
const results: string[] = [];
for (const extension of extensions) {
for (const file of this.readDirectoryFallback(rootDir, extension, exclude))
{
if (!contains(results, file)) {
results.push(file);
}
}
}
return results;
}
return JSON.parse(encoded);
}
public fileExists(fileName: string): boolean {
@@ -467,6 +487,10 @@ namespace ts {
public readFile(fileName: string): string {
return this.shimHost.readFile(fileName);
}
private readDirectoryFallback(rootDir: string, extension: string, exclude: string[]) {
return JSON.parse(this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)));
}
}
function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any, logPerformance: boolean): any {
@@ -1,4 +1,4 @@
tests/cases/conformance/classes/classDeclarations/classExtendingClassLikeType.ts(7,18): error TS2304: Cannot find name 'Base'.
tests/cases/conformance/classes/classDeclarations/classExtendingClassLikeType.ts(7,18): error TS2689: Cannot extend an interface 'Base'. Did you mean 'implements'?
tests/cases/conformance/classes/classDeclarations/classExtendingClassLikeType.ts(45,18): error TS2508: No base constructor has the specified number of type arguments.
tests/cases/conformance/classes/classDeclarations/classExtendingClassLikeType.ts(56,18): error TS2510: Base constructors must all have the same return type.
@@ -12,7 +12,7 @@ tests/cases/conformance/classes/classDeclarations/classExtendingClassLikeType.ts
// Error, no Base constructor function
class D0 extends Base<string, string> {
~~~~
!!! error TS2304: Cannot find name 'Base'.
!!! error TS2689: Cannot extend an interface 'Base'. Did you mean 'implements'?
}
interface BaseConstructor {
@@ -1,4 +1,4 @@
tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendsEveryObjectType.ts(4,17): error TS2304: Cannot find name 'I'.
tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendsEveryObjectType.ts(4,17): error TS2689: Cannot extend an interface 'I'. Did you mean 'implements'?
tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendsEveryObjectType.ts(6,18): error TS2507: Type '{ foo: any; }' is not a constructor function type.
tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendsEveryObjectType.ts(6,25): error TS2304: Cannot find name 'string'.
tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendsEveryObjectType.ts(6,31): error TS1005: ',' expected.
@@ -14,7 +14,7 @@ tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/cla
}
class C extends I { } // error
~
!!! error TS2304: Cannot find name 'I'.
!!! error TS2689: Cannot extend an interface 'I'. Did you mean 'implements'?
class C2 extends { foo: string; } { } // error
~~~~~~~~~~~~~~~~
@@ -1,17 +1,17 @@
tests/cases/compiler/classExtendsInterface.ts(2,17): error TS2304: Cannot find name 'Comparable'.
tests/cases/compiler/classExtendsInterface.ts(6,21): error TS2304: Cannot find name 'Comparable2'.
tests/cases/compiler/classExtendsInterface.ts(2,17): error TS2689: Cannot extend an interface 'Comparable'. Did you mean 'implements'?
tests/cases/compiler/classExtendsInterface.ts(6,21): error TS2689: Cannot extend an interface 'Comparable2'. Did you mean 'implements'?
==== tests/cases/compiler/classExtendsInterface.ts (2 errors) ====
interface Comparable {}
class A extends Comparable {}
~~~~~~~~~~
!!! error TS2304: Cannot find name 'Comparable'.
!!! error TS2689: Cannot extend an interface 'Comparable'. Did you mean 'implements'?
class B implements Comparable {}
interface Comparable2<T> {}
class A2<T> extends Comparable2<T> {}
~~~~~~~~~~~
!!! error TS2304: Cannot find name 'Comparable2'.
!!! error TS2689: Cannot extend an interface 'Comparable2'. Did you mean 'implements'?
class B2<T> implements Comparable2<T> {}
@@ -2,7 +2,7 @@
interface Comparable {}
class A extends Comparable {}
class B implements Comparable {}
interface Comparable2<T> {}
class A2<T> extends Comparable2<T> {}
class B2<T> implements Comparable2<T> {}
@@ -0,0 +1,14 @@
tests/cases/compiler/classExtendsInterfaceInExpression.ts(7,25): error TS2304: Cannot find name 'A'.
==== tests/cases/compiler/classExtendsInterfaceInExpression.ts (1 errors) ====
interface A {}
function factory(a: any): {new(): Object} {
return null;
}
class C extends factory(A) {}
~
!!! error TS2304: Cannot find name 'A'.
@@ -0,0 +1,26 @@
//// [classExtendsInterfaceInExpression.ts]
interface A {}
function factory(a: any): {new(): Object} {
return null;
}
class C extends factory(A) {}
//// [classExtendsInterfaceInExpression.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
function factory(a) {
return null;
}
var C = (function (_super) {
__extends(C, _super);
function C() {
_super.apply(this, arguments);
}
return C;
}(factory(A)));
@@ -0,0 +1,27 @@
tests/cases/compiler/classExtendsInterfaceInModule.ts(5,18): error TS2689: Cannot extend an interface 'M.I1'. Did you mean 'implements'?
tests/cases/compiler/classExtendsInterfaceInModule.ts(6,21): error TS2689: Cannot extend an interface 'M.I2'. Did you mean 'implements'?
tests/cases/compiler/classExtendsInterfaceInModule.ts(14,17): error TS2689: Cannot extend an interface 'Mod.Nested.I'. Did you mean 'implements'?
==== tests/cases/compiler/classExtendsInterfaceInModule.ts (3 errors) ====
module M {
export interface I1 {}
export interface I2<T> {}
}
class C1 extends M.I1 {}
~
!!! error TS2689: Cannot extend an interface 'M.I1'. Did you mean 'implements'?
class C2<T> extends M.I2<T> {}
~
!!! error TS2689: Cannot extend an interface 'M.I2'. Did you mean 'implements'?
module Mod {
export namespace Nested {
export interface I {}
}
}
class D extends Mod.Nested.I {}
~~~
!!! error TS2689: Cannot extend an interface 'Mod.Nested.I'. Did you mean 'implements'?
@@ -0,0 +1,44 @@
//// [classExtendsInterfaceInModule.ts]
module M {
export interface I1 {}
export interface I2<T> {}
}
class C1 extends M.I1 {}
class C2<T> extends M.I2<T> {}
module Mod {
export namespace Nested {
export interface I {}
}
}
class D extends Mod.Nested.I {}
//// [classExtendsInterfaceInModule.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var C1 = (function (_super) {
__extends(C1, _super);
function C1() {
_super.apply(this, arguments);
}
return C1;
}(M.I1));
var C2 = (function (_super) {
__extends(C2, _super);
function C2() {
_super.apply(this, arguments);
}
return C2;
}(M.I2));
var D = (function (_super) {
__extends(D, _super);
function D() {
_super.apply(this, arguments);
}
return D;
}(Mod.Nested.I));
@@ -0,0 +1,11 @@
tests/cases/compiler/file1.ts(2,1): error TS2448: Block-scoped variable 'c' used before its declaration.
==== tests/cases/compiler/file1.ts (1 errors) ====
c;
~
!!! error TS2448: Block-scoped variable 'c' used before its declaration.
==== tests/cases/compiler/file2.ts (0 errors) ====
const c = 0;
@@ -1,8 +1,11 @@
tests/cases/compiler/defaultValueInFunctionTypes.ts(1,9): error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
tests/cases/compiler/defaultValueInFunctionTypes.ts(2,11): error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
==== tests/cases/compiler/defaultValueInFunctionTypes.ts (1 errors) ====
==== tests/cases/compiler/defaultValueInFunctionTypes.ts (2 errors) ====
var x: (a: number = 1) => number;
~~~~~~~~~~~~~
!!! error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
var y = <(a : string = "") => any>(undefined)
var y = <(a : string = "") => any>(undefined)
~~~~~~~~~~~~~~~
!!! error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
@@ -0,0 +1,252 @@
//// [discriminatedUnionTypes1.ts]
interface Square {
kind: "square";
size: number;
}
interface Rectangle {
kind: "rectangle";
width: number;
height: number;
}
interface Circle {
kind: "circle";
radius: number;
}
type Shape = Square | Rectangle | Circle;
function area1(s: Shape) {
if (s.kind === "square") {
return s.size * s.size;
}
else if (s.kind === "circle") {
return Math.PI * s.radius * s.radius;
}
else if (s.kind === "rectangle") {
return s.width * s.height;
}
else {
return 0;
}
}
function area2(s: Shape) {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
}
}
function assertNever(x: never): never {
throw new Error("Unexpected object: " + x);
}
function area3(s: Shape) {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
default: return assertNever(s);
}
}
function area4(s: Shape) {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
}
return assertNever(s);
}
type Message =
{ kind: "A", x: string } |
{ kind: "B" | "C", y: number } |
{ kind: "D" };
function f1(m: Message) {
if (m.kind === "A") {
m; // { kind: "A", x: string }
}
else if (m.kind === "D") {
m; // { kind: "D" }
}
else {
m; // { kind: "B" | "C", y: number }
}
}
function f2(m: Message) {
if (m.kind === "A") {
return;
}
m; // { kind: "B" | "C", y: number } | { kind: "D" }
}
function f3(m: Message) {
if (m.kind === "X") {
m; // never
}
}
function f4(m: Message, x: "A" | "D") {
if (m.kind == x) {
m; // { kind: "A", x: string } | { kind: "D" }
}
}
function f5(m: Message) {
switch (m.kind) {
case "A":
m; // { kind: "A", x: string }
break;
case "D":
m; // { kind: "D" }
break;
default:
m; // { kind: "B" | "C", y: number }
}
}
function f6(m: Message) {
switch (m.kind) {
case "A":
m; // { kind: "A", x: string }
case "D":
m; // { kind: "A", x: string } | { kind: "D" }
break;
default:
m; // { kind: "B" | "C", y: number }
}
}
function f7(m: Message) {
switch (m.kind) {
case "A":
case "B":
return;
}
m; // { kind: "B" | "C", y: number } | { kind: "D" }
}
function f8(m: Message) {
switch (m.kind) {
case "A":
return;
case "D":
throw new Error();
}
m; // { kind: "B" | "C", y: number }
}
//// [discriminatedUnionTypes1.js]
function area1(s) {
if (s.kind === "square") {
return s.size * s.size;
}
else if (s.kind === "circle") {
return Math.PI * s.radius * s.radius;
}
else if (s.kind === "rectangle") {
return s.width * s.height;
}
else {
return 0;
}
}
function area2(s) {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
}
}
function assertNever(x) {
throw new Error("Unexpected object: " + x);
}
function area3(s) {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
default: return assertNever(s);
}
}
function area4(s) {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
}
return assertNever(s);
}
function f1(m) {
if (m.kind === "A") {
m; // { kind: "A", x: string }
}
else if (m.kind === "D") {
m; // { kind: "D" }
}
else {
m; // { kind: "B" | "C", y: number }
}
}
function f2(m) {
if (m.kind === "A") {
return;
}
m; // { kind: "B" | "C", y: number } | { kind: "D" }
}
function f3(m) {
if (m.kind === "X") {
m; // never
}
}
function f4(m, x) {
if (m.kind == x) {
m; // { kind: "A", x: string } | { kind: "D" }
}
}
function f5(m) {
switch (m.kind) {
case "A":
m; // { kind: "A", x: string }
break;
case "D":
m; // { kind: "D" }
break;
default:
m; // { kind: "B" | "C", y: number }
}
}
function f6(m) {
switch (m.kind) {
case "A":
m; // { kind: "A", x: string }
case "D":
m; // { kind: "A", x: string } | { kind: "D" }
break;
default:
m; // { kind: "B" | "C", y: number }
}
}
function f7(m) {
switch (m.kind) {
case "A":
case "B":
return;
}
m; // { kind: "B" | "C", y: number } | { kind: "D" }
}
function f8(m) {
switch (m.kind) {
case "A":
return;
case "D":
throw new Error();
}
m; // { kind: "B" | "C", y: number }
}
@@ -0,0 +1,402 @@
=== tests/cases/conformance/types/union/discriminatedUnionTypes1.ts ===
interface Square {
>Square : Symbol(Square, Decl(discriminatedUnionTypes1.ts, 0, 0))
kind: "square";
>kind : Symbol(Square.kind, Decl(discriminatedUnionTypes1.ts, 0, 18))
size: number;
>size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
}
interface Rectangle {
>Rectangle : Symbol(Rectangle, Decl(discriminatedUnionTypes1.ts, 3, 1))
kind: "rectangle";
>kind : Symbol(Rectangle.kind, Decl(discriminatedUnionTypes1.ts, 5, 21))
width: number;
>width : Symbol(Rectangle.width, Decl(discriminatedUnionTypes1.ts, 6, 22))
height: number;
>height : Symbol(Rectangle.height, Decl(discriminatedUnionTypes1.ts, 7, 18))
}
interface Circle {
>Circle : Symbol(Circle, Decl(discriminatedUnionTypes1.ts, 9, 1))
kind: "circle";
>kind : Symbol(Circle.kind, Decl(discriminatedUnionTypes1.ts, 11, 18))
radius: number;
>radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
}
type Shape = Square | Rectangle | Circle;
>Shape : Symbol(Shape, Decl(discriminatedUnionTypes1.ts, 14, 1))
>Square : Symbol(Square, Decl(discriminatedUnionTypes1.ts, 0, 0))
>Rectangle : Symbol(Rectangle, Decl(discriminatedUnionTypes1.ts, 3, 1))
>Circle : Symbol(Circle, Decl(discriminatedUnionTypes1.ts, 9, 1))
function area1(s: Shape) {
>area1 : Symbol(area1, Decl(discriminatedUnionTypes1.ts, 16, 41))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 18, 15))
>Shape : Symbol(Shape, Decl(discriminatedUnionTypes1.ts, 14, 1))
if (s.kind === "square") {
>s.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 0, 18), Decl(discriminatedUnionTypes1.ts, 5, 21), Decl(discriminatedUnionTypes1.ts, 11, 18))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 18, 15))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 0, 18), Decl(discriminatedUnionTypes1.ts, 5, 21), Decl(discriminatedUnionTypes1.ts, 11, 18))
return s.size * s.size;
>s.size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 18, 15))
>size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s.size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 18, 15))
>size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
}
else if (s.kind === "circle") {
>s.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 5, 21), Decl(discriminatedUnionTypes1.ts, 11, 18))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 18, 15))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 5, 21), Decl(discriminatedUnionTypes1.ts, 11, 18))
return Math.PI * s.radius * s.radius;
>Math.PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
>s.radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 18, 15))
>radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s.radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 18, 15))
>radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
}
else if (s.kind === "rectangle") {
>s.kind : Symbol(Rectangle.kind, Decl(discriminatedUnionTypes1.ts, 5, 21))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 18, 15))
>kind : Symbol(Rectangle.kind, Decl(discriminatedUnionTypes1.ts, 5, 21))
return s.width * s.height;
>s.width : Symbol(Rectangle.width, Decl(discriminatedUnionTypes1.ts, 6, 22))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 18, 15))
>width : Symbol(Rectangle.width, Decl(discriminatedUnionTypes1.ts, 6, 22))
>s.height : Symbol(Rectangle.height, Decl(discriminatedUnionTypes1.ts, 7, 18))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 18, 15))
>height : Symbol(Rectangle.height, Decl(discriminatedUnionTypes1.ts, 7, 18))
}
else {
return 0;
}
}
function area2(s: Shape) {
>area2 : Symbol(area2, Decl(discriminatedUnionTypes1.ts, 31, 1))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 33, 15))
>Shape : Symbol(Shape, Decl(discriminatedUnionTypes1.ts, 14, 1))
switch (s.kind) {
>s.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 0, 18), Decl(discriminatedUnionTypes1.ts, 5, 21), Decl(discriminatedUnionTypes1.ts, 11, 18))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 33, 15))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 0, 18), Decl(discriminatedUnionTypes1.ts, 5, 21), Decl(discriminatedUnionTypes1.ts, 11, 18))
case "square": return s.size * s.size;
>s.size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 33, 15))
>size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s.size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 33, 15))
>size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
case "rectangle": return s.width * s.height;
>s.width : Symbol(Rectangle.width, Decl(discriminatedUnionTypes1.ts, 6, 22))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 33, 15))
>width : Symbol(Rectangle.width, Decl(discriminatedUnionTypes1.ts, 6, 22))
>s.height : Symbol(Rectangle.height, Decl(discriminatedUnionTypes1.ts, 7, 18))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 33, 15))
>height : Symbol(Rectangle.height, Decl(discriminatedUnionTypes1.ts, 7, 18))
case "circle": return Math.PI * s.radius * s.radius;
>Math.PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
>s.radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 33, 15))
>radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s.radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 33, 15))
>radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
}
}
function assertNever(x: never): never {
>assertNever : Symbol(assertNever, Decl(discriminatedUnionTypes1.ts, 39, 1))
>x : Symbol(x, Decl(discriminatedUnionTypes1.ts, 41, 21))
throw new Error("Unexpected object: " + x);
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(discriminatedUnionTypes1.ts, 41, 21))
}
function area3(s: Shape) {
>area3 : Symbol(area3, Decl(discriminatedUnionTypes1.ts, 43, 1))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 45, 15))
>Shape : Symbol(Shape, Decl(discriminatedUnionTypes1.ts, 14, 1))
switch (s.kind) {
>s.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 0, 18), Decl(discriminatedUnionTypes1.ts, 5, 21), Decl(discriminatedUnionTypes1.ts, 11, 18))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 45, 15))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 0, 18), Decl(discriminatedUnionTypes1.ts, 5, 21), Decl(discriminatedUnionTypes1.ts, 11, 18))
case "square": return s.size * s.size;
>s.size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 45, 15))
>size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s.size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 45, 15))
>size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
case "rectangle": return s.width * s.height;
>s.width : Symbol(Rectangle.width, Decl(discriminatedUnionTypes1.ts, 6, 22))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 45, 15))
>width : Symbol(Rectangle.width, Decl(discriminatedUnionTypes1.ts, 6, 22))
>s.height : Symbol(Rectangle.height, Decl(discriminatedUnionTypes1.ts, 7, 18))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 45, 15))
>height : Symbol(Rectangle.height, Decl(discriminatedUnionTypes1.ts, 7, 18))
case "circle": return Math.PI * s.radius * s.radius;
>Math.PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
>s.radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 45, 15))
>radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s.radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 45, 15))
>radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
default: return assertNever(s);
>assertNever : Symbol(assertNever, Decl(discriminatedUnionTypes1.ts, 39, 1))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 45, 15))
}
}
function area4(s: Shape) {
>area4 : Symbol(area4, Decl(discriminatedUnionTypes1.ts, 52, 1))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 54, 15))
>Shape : Symbol(Shape, Decl(discriminatedUnionTypes1.ts, 14, 1))
switch (s.kind) {
>s.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 0, 18), Decl(discriminatedUnionTypes1.ts, 5, 21), Decl(discriminatedUnionTypes1.ts, 11, 18))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 54, 15))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 0, 18), Decl(discriminatedUnionTypes1.ts, 5, 21), Decl(discriminatedUnionTypes1.ts, 11, 18))
case "square": return s.size * s.size;
>s.size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 54, 15))
>size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s.size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 54, 15))
>size : Symbol(Square.size, Decl(discriminatedUnionTypes1.ts, 1, 19))
case "rectangle": return s.width * s.height;
>s.width : Symbol(Rectangle.width, Decl(discriminatedUnionTypes1.ts, 6, 22))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 54, 15))
>width : Symbol(Rectangle.width, Decl(discriminatedUnionTypes1.ts, 6, 22))
>s.height : Symbol(Rectangle.height, Decl(discriminatedUnionTypes1.ts, 7, 18))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 54, 15))
>height : Symbol(Rectangle.height, Decl(discriminatedUnionTypes1.ts, 7, 18))
case "circle": return Math.PI * s.radius * s.radius;
>Math.PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
>s.radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 54, 15))
>radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s.radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 54, 15))
>radius : Symbol(Circle.radius, Decl(discriminatedUnionTypes1.ts, 12, 19))
}
return assertNever(s);
>assertNever : Symbol(assertNever, Decl(discriminatedUnionTypes1.ts, 39, 1))
>s : Symbol(s, Decl(discriminatedUnionTypes1.ts, 54, 15))
}
type Message =
>Message : Symbol(Message, Decl(discriminatedUnionTypes1.ts, 61, 1))
{ kind: "A", x: string } |
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5))
>x : Symbol(x, Decl(discriminatedUnionTypes1.ts, 64, 16))
{ kind: "B" | "C", y: number } |
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 65, 5))
>y : Symbol(y, Decl(discriminatedUnionTypes1.ts, 65, 22))
{ kind: "D" };
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 66, 5))
function f1(m: Message) {
>f1 : Symbol(f1, Decl(discriminatedUnionTypes1.ts, 66, 18))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 68, 12))
>Message : Symbol(Message, Decl(discriminatedUnionTypes1.ts, 61, 1))
if (m.kind === "A") {
>m.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 68, 12))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
m; // { kind: "A", x: string }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 68, 12))
}
else if (m.kind === "D") {
>m.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 68, 12))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
m; // { kind: "D" }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 68, 12))
}
else {
m; // { kind: "B" | "C", y: number }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 68, 12))
}
}
function f2(m: Message) {
>f2 : Symbol(f2, Decl(discriminatedUnionTypes1.ts, 78, 1))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 80, 12))
>Message : Symbol(Message, Decl(discriminatedUnionTypes1.ts, 61, 1))
if (m.kind === "A") {
>m.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 80, 12))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
return;
}
m; // { kind: "B" | "C", y: number } | { kind: "D" }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 80, 12))
}
function f3(m: Message) {
>f3 : Symbol(f3, Decl(discriminatedUnionTypes1.ts, 85, 1))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 87, 12))
>Message : Symbol(Message, Decl(discriminatedUnionTypes1.ts, 61, 1))
if (m.kind === "X") {
>m.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 87, 12))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
m; // never
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 87, 12))
}
}
function f4(m: Message, x: "A" | "D") {
>f4 : Symbol(f4, Decl(discriminatedUnionTypes1.ts, 91, 1))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 93, 12))
>Message : Symbol(Message, Decl(discriminatedUnionTypes1.ts, 61, 1))
>x : Symbol(x, Decl(discriminatedUnionTypes1.ts, 93, 23))
if (m.kind == x) {
>m.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 93, 12))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
>x : Symbol(x, Decl(discriminatedUnionTypes1.ts, 93, 23))
m; // { kind: "A", x: string } | { kind: "D" }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 93, 12))
}
}
function f5(m: Message) {
>f5 : Symbol(f5, Decl(discriminatedUnionTypes1.ts, 97, 1))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 99, 12))
>Message : Symbol(Message, Decl(discriminatedUnionTypes1.ts, 61, 1))
switch (m.kind) {
>m.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 99, 12))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
case "A":
m; // { kind: "A", x: string }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 99, 12))
break;
case "D":
m; // { kind: "D" }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 99, 12))
break;
default:
m; // { kind: "B" | "C", y: number }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 99, 12))
}
}
function f6(m: Message) {
>f6 : Symbol(f6, Decl(discriminatedUnionTypes1.ts, 110, 1))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 112, 12))
>Message : Symbol(Message, Decl(discriminatedUnionTypes1.ts, 61, 1))
switch (m.kind) {
>m.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 112, 12))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
case "A":
m; // { kind: "A", x: string }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 112, 12))
case "D":
m; // { kind: "A", x: string } | { kind: "D" }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 112, 12))
break;
default:
m; // { kind: "B" | "C", y: number }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 112, 12))
}
}
function f7(m: Message) {
>f7 : Symbol(f7, Decl(discriminatedUnionTypes1.ts, 122, 1))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 124, 12))
>Message : Symbol(Message, Decl(discriminatedUnionTypes1.ts, 61, 1))
switch (m.kind) {
>m.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 124, 12))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
case "A":
case "B":
return;
}
m; // { kind: "B" | "C", y: number } | { kind: "D" }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 124, 12))
}
function f8(m: Message) {
>f8 : Symbol(f8, Decl(discriminatedUnionTypes1.ts, 131, 1))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 133, 12))
>Message : Symbol(Message, Decl(discriminatedUnionTypes1.ts, 61, 1))
switch (m.kind) {
>m.kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 133, 12))
>kind : Symbol(kind, Decl(discriminatedUnionTypes1.ts, 64, 5), Decl(discriminatedUnionTypes1.ts, 65, 5), Decl(discriminatedUnionTypes1.ts, 66, 5))
case "A":
return;
case "D":
throw new Error();
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
}
m; // { kind: "B" | "C", y: number }
>m : Symbol(m, Decl(discriminatedUnionTypes1.ts, 133, 12))
}
@@ -0,0 +1,465 @@
=== tests/cases/conformance/types/union/discriminatedUnionTypes1.ts ===
interface Square {
>Square : Square
kind: "square";
>kind : "square"
size: number;
>size : number
}
interface Rectangle {
>Rectangle : Rectangle
kind: "rectangle";
>kind : "rectangle"
width: number;
>width : number
height: number;
>height : number
}
interface Circle {
>Circle : Circle
kind: "circle";
>kind : "circle"
radius: number;
>radius : number
}
type Shape = Square | Rectangle | Circle;
>Shape : Square | Rectangle | Circle
>Square : Square
>Rectangle : Rectangle
>Circle : Circle
function area1(s: Shape) {
>area1 : (s: Square | Rectangle | Circle) => number
>s : Square | Rectangle | Circle
>Shape : Square | Rectangle | Circle
if (s.kind === "square") {
>s.kind === "square" : boolean
>s.kind : "square" | "rectangle" | "circle"
>s : Square | Rectangle | Circle
>kind : "square" | "rectangle" | "circle"
>"square" : string
return s.size * s.size;
>s.size * s.size : number
>s.size : number
>s : Square
>size : number
>s.size : number
>s : Square
>size : number
}
else if (s.kind === "circle") {
>s.kind === "circle" : boolean
>s.kind : "rectangle" | "circle"
>s : Rectangle | Circle
>kind : "rectangle" | "circle"
>"circle" : string
return Math.PI * s.radius * s.radius;
>Math.PI * s.radius * s.radius : number
>Math.PI * s.radius : number
>Math.PI : number
>Math : Math
>PI : number
>s.radius : number
>s : Circle
>radius : number
>s.radius : number
>s : Circle
>radius : number
}
else if (s.kind === "rectangle") {
>s.kind === "rectangle" : boolean
>s.kind : "rectangle"
>s : Rectangle
>kind : "rectangle"
>"rectangle" : string
return s.width * s.height;
>s.width * s.height : number
>s.width : number
>s : Rectangle
>width : number
>s.height : number
>s : Rectangle
>height : number
}
else {
return 0;
>0 : number
}
}
function area2(s: Shape) {
>area2 : (s: Square | Rectangle | Circle) => number
>s : Square | Rectangle | Circle
>Shape : Square | Rectangle | Circle
switch (s.kind) {
>s.kind : "square" | "rectangle" | "circle"
>s : Square | Rectangle | Circle
>kind : "square" | "rectangle" | "circle"
case "square": return s.size * s.size;
>"square" : string
>s.size * s.size : number
>s.size : number
>s : Square
>size : number
>s.size : number
>s : Square
>size : number
case "rectangle": return s.width * s.height;
>"rectangle" : string
>s.width * s.height : number
>s.width : number
>s : Rectangle
>width : number
>s.height : number
>s : Rectangle
>height : number
case "circle": return Math.PI * s.radius * s.radius;
>"circle" : string
>Math.PI * s.radius * s.radius : number
>Math.PI * s.radius : number
>Math.PI : number
>Math : Math
>PI : number
>s.radius : number
>s : Circle
>radius : number
>s.radius : number
>s : Circle
>radius : number
}
}
function assertNever(x: never): never {
>assertNever : (x: never) => never
>x : never
throw new Error("Unexpected object: " + x);
>new Error("Unexpected object: " + x) : Error
>Error : ErrorConstructor
>"Unexpected object: " + x : string
>"Unexpected object: " : string
>x : never
}
function area3(s: Shape) {
>area3 : (s: Square | Rectangle | Circle) => number
>s : Square | Rectangle | Circle
>Shape : Square | Rectangle | Circle
switch (s.kind) {
>s.kind : "square" | "rectangle" | "circle"
>s : Square | Rectangle | Circle
>kind : "square" | "rectangle" | "circle"
case "square": return s.size * s.size;
>"square" : string
>s.size * s.size : number
>s.size : number
>s : Square
>size : number
>s.size : number
>s : Square
>size : number
case "rectangle": return s.width * s.height;
>"rectangle" : string
>s.width * s.height : number
>s.width : number
>s : Rectangle
>width : number
>s.height : number
>s : Rectangle
>height : number
case "circle": return Math.PI * s.radius * s.radius;
>"circle" : string
>Math.PI * s.radius * s.radius : number
>Math.PI * s.radius : number
>Math.PI : number
>Math : Math
>PI : number
>s.radius : number
>s : Circle
>radius : number
>s.radius : number
>s : Circle
>radius : number
default: return assertNever(s);
>assertNever(s) : never
>assertNever : (x: never) => never
>s : never
}
}
function area4(s: Shape) {
>area4 : (s: Square | Rectangle | Circle) => number
>s : Square | Rectangle | Circle
>Shape : Square | Rectangle | Circle
switch (s.kind) {
>s.kind : "square" | "rectangle" | "circle"
>s : Square | Rectangle | Circle
>kind : "square" | "rectangle" | "circle"
case "square": return s.size * s.size;
>"square" : string
>s.size * s.size : number
>s.size : number
>s : Square
>size : number
>s.size : number
>s : Square
>size : number
case "rectangle": return s.width * s.height;
>"rectangle" : string
>s.width * s.height : number
>s.width : number
>s : Rectangle
>width : number
>s.height : number
>s : Rectangle
>height : number
case "circle": return Math.PI * s.radius * s.radius;
>"circle" : string
>Math.PI * s.radius * s.radius : number
>Math.PI * s.radius : number
>Math.PI : number
>Math : Math
>PI : number
>s.radius : number
>s : Circle
>radius : number
>s.radius : number
>s : Circle
>radius : number
}
return assertNever(s);
>assertNever(s) : never
>assertNever : (x: never) => never
>s : never
}
type Message =
>Message : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
{ kind: "A", x: string } |
>kind : "A"
>x : string
{ kind: "B" | "C", y: number } |
>kind : "B" | "C"
>y : number
{ kind: "D" };
>kind : "D"
function f1(m: Message) {
>f1 : (m: { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }) => void
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>Message : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
if (m.kind === "A") {
>m.kind === "A" : boolean
>m.kind : "A" | "B" | "C" | "D"
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>kind : "A" | "B" | "C" | "D"
>"A" : string
m; // { kind: "A", x: string }
>m : { kind: "A"; x: string; }
}
else if (m.kind === "D") {
>m.kind === "D" : boolean
>m.kind : "B" | "C" | "D"
>m : { kind: "B" | "C"; y: number; } | { kind: "D"; }
>kind : "B" | "C" | "D"
>"D" : string
m; // { kind: "D" }
>m : { kind: "D"; }
}
else {
m; // { kind: "B" | "C", y: number }
>m : { kind: "B" | "C"; y: number; }
}
}
function f2(m: Message) {
>f2 : (m: { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }) => void
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>Message : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
if (m.kind === "A") {
>m.kind === "A" : boolean
>m.kind : "A" | "B" | "C" | "D"
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>kind : "A" | "B" | "C" | "D"
>"A" : string
return;
}
m; // { kind: "B" | "C", y: number } | { kind: "D" }
>m : { kind: "B" | "C"; y: number; } | { kind: "D"; }
}
function f3(m: Message) {
>f3 : (m: { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }) => void
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>Message : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
if (m.kind === "X") {
>m.kind === "X" : boolean
>m.kind : "A" | "B" | "C" | "D"
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>kind : "A" | "B" | "C" | "D"
>"X" : string
m; // never
>m : never
}
}
function f4(m: Message, x: "A" | "D") {
>f4 : (m: { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }, x: "A" | "D") => void
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>Message : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>x : "A" | "D"
if (m.kind == x) {
>m.kind == x : boolean
>m.kind : "A" | "B" | "C" | "D"
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>kind : "A" | "B" | "C" | "D"
>x : "A" | "D"
m; // { kind: "A", x: string } | { kind: "D" }
>m : { kind: "A"; x: string; } | { kind: "D"; }
}
}
function f5(m: Message) {
>f5 : (m: { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }) => void
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>Message : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
switch (m.kind) {
>m.kind : "A" | "B" | "C" | "D"
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>kind : "A" | "B" | "C" | "D"
case "A":
>"A" : string
m; // { kind: "A", x: string }
>m : { kind: "A"; x: string; }
break;
case "D":
>"D" : string
m; // { kind: "D" }
>m : { kind: "D"; }
break;
default:
m; // { kind: "B" | "C", y: number }
>m : { kind: "B" | "C"; y: number; }
}
}
function f6(m: Message) {
>f6 : (m: { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }) => void
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>Message : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
switch (m.kind) {
>m.kind : "A" | "B" | "C" | "D"
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>kind : "A" | "B" | "C" | "D"
case "A":
>"A" : string
m; // { kind: "A", x: string }
>m : { kind: "A"; x: string; }
case "D":
>"D" : string
m; // { kind: "A", x: string } | { kind: "D" }
>m : { kind: "D"; } | { kind: "A"; x: string; }
break;
default:
m; // { kind: "B" | "C", y: number }
>m : { kind: "B" | "C"; y: number; }
}
}
function f7(m: Message) {
>f7 : (m: { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }) => void
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>Message : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
switch (m.kind) {
>m.kind : "A" | "B" | "C" | "D"
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>kind : "A" | "B" | "C" | "D"
case "A":
>"A" : string
case "B":
>"B" : string
return;
}
m; // { kind: "B" | "C", y: number } | { kind: "D" }
>m : { kind: "B" | "C"; y: number; } | { kind: "D"; }
}
function f8(m: Message) {
>f8 : (m: { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }) => void
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>Message : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
switch (m.kind) {
>m.kind : "A" | "B" | "C" | "D"
>m : { kind: "A"; x: string; } | { kind: "B" | "C"; y: number; } | { kind: "D"; }
>kind : "A" | "B" | "C" | "D"
case "A":
>"A" : string
return;
case "D":
>"D" : string
throw new Error();
>new Error() : Error
>Error : ErrorConstructor
}
m; // { kind: "B" | "C", y: number }
>m : { kind: "B" | "C"; y: number; }
}
@@ -0,0 +1,11 @@
tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts(2,11): error TS2300: Duplicate identifier 'a'.
tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts(2,22): error TS2300: Duplicate identifier 'a'.
==== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions01.ts (2 errors) ====
let x = <{a: number; a: number}>{};
~
!!! error TS2300: Duplicate identifier 'a'.
~
!!! error TS2300: Duplicate identifier 'a'.
@@ -0,0 +1,12 @@
//// [duplicatePropertiesInTypeAssertions01.ts]
let x = <{a: number; a: number}>{};
//// [duplicatePropertiesInTypeAssertions01.js]
var x = {};
//// [duplicatePropertiesInTypeAssertions01.d.ts]
declare let x: {
a: number;
};
@@ -0,0 +1,11 @@
tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts(2,16): error TS2300: Duplicate identifier 'a'.
tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts(2,27): error TS2300: Duplicate identifier 'a'.
==== tests/cases/conformance/expressions/typeAssertions/duplicatePropertiesInTypeAssertions02.ts (2 errors) ====
let x = {} as {a: number; a: number};
~
!!! error TS2300: Duplicate identifier 'a'.
~
!!! error TS2300: Duplicate identifier 'a'.
@@ -0,0 +1,12 @@
//// [duplicatePropertiesInTypeAssertions02.ts]
let x = {} as {a: number; a: number};
//// [duplicatePropertiesInTypeAssertions02.js]
var x = {};
//// [duplicatePropertiesInTypeAssertions02.d.ts]
declare let x: {
a: number;
};
@@ -0,0 +1,9 @@
tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts(2,10): error TS1122: A tuple type element list cannot be empty.
==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts (1 errors) ====
let x = <[]>[];
~~
!!! error TS1122: A tuple type element list cannot be empty.
let y = x[0];
@@ -0,0 +1,13 @@
//// [emptyTuplesTypeAssertion01.ts]
let x = <[]>[];
let y = x[0];
//// [emptyTuplesTypeAssertion01.js]
var x = [];
var y = x[0];
//// [emptyTuplesTypeAssertion01.d.ts]
declare let x: [];
declare let y: never;
@@ -0,0 +1,9 @@
tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts(2,15): error TS1122: A tuple type element list cannot be empty.
==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts (1 errors) ====
let x = [] as [];
~~
!!! error TS1122: A tuple type element list cannot be empty.
let y = x[0];
@@ -0,0 +1,13 @@
//// [emptyTuplesTypeAssertion02.ts]
let x = [] as [];
let y = x[0];
//// [emptyTuplesTypeAssertion02.js]
var x = [];
var y = x[0];
//// [emptyTuplesTypeAssertion02.d.ts]
declare let x: [];
declare let y: never;
@@ -13,7 +13,7 @@ tests/cases/conformance/types/specifyingTypes/typeReferences/genericTypeReferenc
tests/cases/conformance/types/specifyingTypes/typeReferences/genericTypeReferenceWithoutTypeArgument2.ts(18,23): error TS2314: Generic type 'I<T>' requires 1 type argument(s).
tests/cases/conformance/types/specifyingTypes/typeReferences/genericTypeReferenceWithoutTypeArgument2.ts(18,27): error TS2314: Generic type 'I<T>' requires 1 type argument(s).
tests/cases/conformance/types/specifyingTypes/typeReferences/genericTypeReferenceWithoutTypeArgument2.ts(18,38): error TS2314: Generic type 'I<T>' requires 1 type argument(s).
tests/cases/conformance/types/specifyingTypes/typeReferences/genericTypeReferenceWithoutTypeArgument2.ts(20,17): error TS2304: Cannot find name 'I'.
tests/cases/conformance/types/specifyingTypes/typeReferences/genericTypeReferenceWithoutTypeArgument2.ts(20,17): error TS2689: Cannot extend an interface 'I'. Did you mean 'implements'?
tests/cases/conformance/types/specifyingTypes/typeReferences/genericTypeReferenceWithoutTypeArgument2.ts(23,21): error TS2314: Generic type 'I<T>' requires 1 type argument(s).
tests/cases/conformance/types/specifyingTypes/typeReferences/genericTypeReferenceWithoutTypeArgument2.ts(29,18): error TS2304: Cannot find name 'M'.
tests/cases/conformance/types/specifyingTypes/typeReferences/genericTypeReferenceWithoutTypeArgument2.ts(30,24): error TS2314: Generic type 'E<T>' requires 1 type argument(s).
@@ -76,7 +76,7 @@ tests/cases/conformance/types/specifyingTypes/typeReferences/genericTypeReferenc
class D extends I {
~
!!! error TS2304: Cannot find name 'I'.
!!! error TS2689: Cannot extend an interface 'I'. Did you mean 'implements'?
}
interface U extends I {}
@@ -1,10 +1,13 @@
error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
tests/cases/compiler/a.ts(2,1): error TS2448: Block-scoped variable 'a' used before its declaration.
!!! error TS5053: Option 'allowJs' cannot be specified with option 'declaration'.
==== tests/cases/compiler/a.ts (0 errors) ====
==== tests/cases/compiler/a.ts (1 errors) ====
let b = 30;
a = 10;
~
!!! error TS2448: Block-scoped variable 'a' used before its declaration.
==== tests/cases/compiler/b.js (0 errors) ====
let a = 10;
b = 30;
@@ -1,9 +0,0 @@
error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file.
tests/cases/compiler/a.js(1,11): error TS8014: 'property declarations' can only be used in a .ts file.
!!! error TS5055: Cannot write file 'tests/cases/compiler/a.js' because it would overwrite input file.
==== tests/cases/compiler/a.js (1 errors) ====
class C { v }
~
!!! error TS8014: 'property declarations' can only be used in a .ts file.
@@ -0,0 +1,11 @@
tests/cases/compiler/file1.ts(2,1): error TS2448: Block-scoped variable 'l' used before its declaration.
==== tests/cases/compiler/file1.ts (1 errors) ====
l;
~
!!! error TS2448: Block-scoped variable 'l' used before its declaration.
==== tests/cases/compiler/file2.ts (0 errors) ====
const l = 0;
@@ -86,8 +86,8 @@ const a8 = a && z;
>z : string | number | undefined
const s1 = s && a;
>s1 : number[] | string
>s && a : number[] | string
>s1 : number[]
>s && a : number[]
>s : string
>a : number[]
@@ -98,32 +98,32 @@ const s2 = s && s;
>s : string
const s3 = s && x;
>s3 : number | string
>s && x : number | string
>s3 : number
>s && x : number
>s : string
>x : number
const s4 = s && b;
>s4 : boolean | string
>s && b : boolean | string
>s4 : boolean
>s && b : boolean
>s : string
>b : boolean
const s5 = s && v;
>s5 : void | string
>s && v : void | string
>s5 : void
>s && v : void
>s : string
>v : void
const s6 = s && u;
>s6 : string | undefined
>s && u : string | undefined
>s6 : undefined
>s && u : undefined
>s : string
>u : undefined
const s7 = s && n;
>s7 : string | null
>s && n : string | null
>s7 : null
>s && n : null
>s : string
>n : null
@@ -134,14 +134,14 @@ const s8 = s && z;
>z : string | number | undefined
const x1 = x && a;
>x1 : number[] | number
>x && a : number[] | number
>x1 : number[]
>x && a : number[]
>x : number
>a : number[]
const x2 = x && s;
>x2 : string | number
>x && s : string | number
>x2 : string
>x && s : string
>x : number
>s : string
@@ -152,26 +152,26 @@ const x3 = x && x;
>x : number
const x4 = x && b;
>x4 : boolean | number
>x && b : boolean | number
>x4 : boolean
>x && b : boolean
>x : number
>b : boolean
const x5 = x && v;
>x5 : void | number
>x && v : void | number
>x5 : void
>x && v : void
>x : number
>v : void
const x6 = x && u;
>x6 : number | undefined
>x && u : number | undefined
>x6 : undefined
>x && u : undefined
>x : number
>u : undefined
const x7 = x && n;
>x7 : number | null
>x && n : number | null
>x7 : null
>x && n : null
>x : number
>n : null
@@ -182,20 +182,20 @@ const x8 = x && z;
>z : string | number | undefined
const b1 = b && a;
>b1 : number[] | boolean
>b && a : number[] | boolean
>b1 : number[]
>b && a : number[]
>b : boolean
>a : number[]
const b2 = b && s;
>b2 : string | boolean
>b && s : string | boolean
>b2 : string
>b && s : string
>b : boolean
>s : string
const b3 = b && x;
>b3 : number | boolean
>b && x : number | boolean
>b3 : number
>b && x : number
>b : boolean
>x : number
@@ -206,26 +206,26 @@ const b4 = b && b;
>b : boolean
const b5 = b && v;
>b5 : void | boolean
>b && v : void | boolean
>b5 : void
>b && v : void
>b : boolean
>v : void
const b6 = b && u;
>b6 : boolean | undefined
>b && u : boolean | undefined
>b6 : undefined
>b && u : undefined
>b : boolean
>u : undefined
const b7 = b && n;
>b7 : boolean | null
>b && n : boolean | null
>b7 : null
>b && n : null
>b : boolean
>n : null
const b8 = b && z;
>b8 : string | number | boolean | undefined
>b && z : string | number | boolean | undefined
>b8 : string | number | undefined
>b && z : string | number | undefined
>b : boolean
>z : string | number | undefined
@@ -374,44 +374,44 @@ const n8 = n && z;
>z : string | number | undefined
const z1 = z && a;
>z1 : number[] | string | number | undefined
>z && a : number[] | string | number | undefined
>z1 : number[] | undefined
>z && a : number[] | undefined
>z : string | number | undefined
>a : number[]
const z2 = z && s;
>z2 : string | number | undefined
>z && s : string | number | undefined
>z2 : string | undefined
>z && s : string | undefined
>z : string | number | undefined
>s : string
const z3 = z && x;
>z3 : number | string | undefined
>z && x : number | string | undefined
>z3 : number | undefined
>z && x : number | undefined
>z : string | number | undefined
>x : number
const z4 = z && b;
>z4 : boolean | string | number | undefined
>z && b : boolean | string | number | undefined
>z4 : boolean | undefined
>z && b : boolean | undefined
>z : string | number | undefined
>b : boolean
const z5 = z && v;
>z5 : void | string | number
>z && v : void | string | number
>z5 : void
>z && v : void
>z : string | number | undefined
>v : void
const z6 = z && u;
>z6 : string | number | undefined
>z && u : string | number | undefined
>z6 : undefined
>z && u : undefined
>z : string | number | undefined
>u : undefined
const z7 = z && n;
>z7 : string | number | null | undefined
>z && n : string | number | null | undefined
>z7 : null | undefined
>z && n : null | undefined
>z : string | number | undefined
>n : null
@@ -0,0 +1,140 @@
tests/cases/compiler/missingFunctionImplementation.ts(3,3): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/missingFunctionImplementation.ts(8,3): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/missingFunctionImplementation.ts(16,3): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/missingFunctionImplementation.ts(22,10): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/missingFunctionImplementation.ts(28,10): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/missingFunctionImplementation.ts(33,10): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/missingFunctionImplementation.ts(41,10): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/missingFunctionImplementation.ts(48,10): error TS2300: Duplicate identifier 'm'.
tests/cases/compiler/missingFunctionImplementation.ts(49,10): error TS2300: Duplicate identifier 'm'.
tests/cases/compiler/missingFunctionImplementation.ts(49,10): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/missingFunctionImplementation.ts(52,19): error TS2300: Duplicate identifier 'm'.
tests/cases/compiler/missingFunctionImplementation.ts(57,10): error TS2300: Duplicate identifier 'm'.
tests/cases/compiler/missingFunctionImplementation.ts(60,19): error TS2300: Duplicate identifier 'm'.
tests/cases/compiler/missingFunctionImplementation.ts(60,19): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/missingFunctionImplementation.ts(65,19): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/compiler/missingFunctionImplementation.ts(73,19): error TS2393: Duplicate function implementation.
tests/cases/compiler/missingFunctionImplementation.ts(74,19): error TS2393: Duplicate function implementation.
tests/cases/compiler/missingFunctionImplementation.ts(75,19): error TS2393: Duplicate function implementation.
tests/cases/compiler/missingFunctionImplementation.ts(78,19): error TS2393: Duplicate function implementation.
==== tests/cases/compiler/missingFunctionImplementation.ts (19 errors) ====
export class C1 {
m(): void;
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
// merged with a namespace
export class C2 {
m(): void;
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
export namespace C2 { }
// merged with a namespace, multiple overloads
class C3 {
m(a, b);
m(a);
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
namespace C3 { }
// static methods, multiple overloads
class C4 {
static m(a): void;
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
// static methods, multiple overloads
class C5 {
static m(a): void;
static m(): void;
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
// merged with namespace, static methods
class C6 {
static m(): void;
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
namespace C6 {
}
// merged with namespace, static methods, multiple overloads
class C7 {
static m(a): void;
static m(): void;
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
namespace C7 {
}
// merged with namespace, static methods, duplicate declarations
class C8 {
static m(a): void;
~
!!! error TS2300: Duplicate identifier 'm'.
static m(a, b): void;
~
!!! error TS2300: Duplicate identifier 'm'.
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
namespace C8 {
export function m(a?, b?): void { }
~
!!! error TS2300: Duplicate identifier 'm'.
}
// merged with namespace, static methods, duplicate declarations
class C9 {
static m(a): void { }
~
!!! error TS2300: Duplicate identifier 'm'.
}
namespace C9 {
export function m(a): void;
~
!!! error TS2300: Duplicate identifier 'm'.
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
// merged namespaces
namespace N10 {
export function m(a): void;
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
namespace N10 {
export function m(a): void { }
}
// merged namespaces, duplicate defintions
namespace N12 {
export function m(a): void;
~
!!! error TS2393: Duplicate function implementation.
export function m(): void;
~
!!! error TS2393: Duplicate function implementation.
export function m(a?): void { }
~
!!! error TS2393: Duplicate function implementation.
}
namespace N12 {
export function m(a): void { }
~
!!! error TS2393: Duplicate function implementation.
}
@@ -0,0 +1,168 @@
//// [missingFunctionImplementation.ts]
export class C1 {
m(): void;
}
// merged with a namespace
export class C2 {
m(): void;
}
export namespace C2 { }
// merged with a namespace, multiple overloads
class C3 {
m(a, b);
m(a);
}
namespace C3 { }
// static methods, multiple overloads
class C4 {
static m(a): void;
}
// static methods, multiple overloads
class C5 {
static m(a): void;
static m(): void;
}
// merged with namespace, static methods
class C6 {
static m(): void;
}
namespace C6 {
}
// merged with namespace, static methods, multiple overloads
class C7 {
static m(a): void;
static m(): void;
}
namespace C7 {
}
// merged with namespace, static methods, duplicate declarations
class C8 {
static m(a): void;
static m(a, b): void;
}
namespace C8 {
export function m(a?, b?): void { }
}
// merged with namespace, static methods, duplicate declarations
class C9 {
static m(a): void { }
}
namespace C9 {
export function m(a): void;
}
// merged namespaces
namespace N10 {
export function m(a): void;
}
namespace N10 {
export function m(a): void { }
}
// merged namespaces, duplicate defintions
namespace N12 {
export function m(a): void;
export function m(): void;
export function m(a?): void { }
}
namespace N12 {
export function m(a): void { }
}
//// [missingFunctionImplementation.js]
"use strict";
var C1 = (function () {
function C1() {
}
return C1;
}());
exports.C1 = C1;
// merged with a namespace
var C2 = (function () {
function C2() {
}
return C2;
}());
exports.C2 = C2;
// merged with a namespace, multiple overloads
var C3 = (function () {
function C3() {
}
return C3;
}());
// static methods, multiple overloads
var C4 = (function () {
function C4() {
}
return C4;
}());
// static methods, multiple overloads
var C5 = (function () {
function C5() {
}
return C5;
}());
// merged with namespace, static methods
var C6 = (function () {
function C6() {
}
return C6;
}());
// merged with namespace, static methods, multiple overloads
var C7 = (function () {
function C7() {
}
return C7;
}());
// merged with namespace, static methods, duplicate declarations
var C8 = (function () {
function C8() {
}
return C8;
}());
var C8;
(function (C8) {
function m(a, b) { }
C8.m = m;
})(C8 || (C8 = {}));
// merged with namespace, static methods, duplicate declarations
var C9 = (function () {
function C9() {
}
C9.m = function (a) { };
return C9;
}());
var C9;
(function (C9) {
})(C9 || (C9 = {}));
// merged namespaces
var N10;
(function (N10) {
})(N10 || (N10 = {}));
var N10;
(function (N10) {
function m(a) { }
N10.m = m;
})(N10 || (N10 = {}));
// merged namespaces, duplicate defintions
var N12;
(function (N12) {
function m(a) { }
N12.m = m;
})(N12 || (N12 = {}));
var N12;
(function (N12) {
function m(a) { }
N12.m = m;
})(N12 || (N12 = {}));
@@ -0,0 +1,16 @@
tests/cases/compiler/missingFunctionImplementation2_a.ts(3,19): error TS2384: Overload signatures must all be ambient or non-ambient.
tests/cases/compiler/missingFunctionImplementation2_b.ts(1,17): error TS2391: Function implementation is missing or not immediately following the declaration.
==== tests/cases/compiler/missingFunctionImplementation2_a.ts (1 errors) ====
export {};
declare module "./missingFunctionImplementation2_b.ts" {
export function f(a, b): void;
~
!!! error TS2384: Overload signatures must all be ambient or non-ambient.
}
==== tests/cases/compiler/missingFunctionImplementation2_b.ts (1 errors) ====
export function f(a?, b?);
~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
@@ -0,0 +1,15 @@
//// [tests/cases/compiler/missingFunctionImplementation2.ts] ////
//// [missingFunctionImplementation2_a.ts]
export {};
declare module "./missingFunctionImplementation2_b.ts" {
export function f(a, b): void;
}
//// [missingFunctionImplementation2_b.ts]
export function f(a?, b?);
//// [missingFunctionImplementation2_a.js]
"use strict";
//// [missingFunctionImplementation2_b.js]
"use strict";
@@ -0,0 +1,26 @@
//// [strictNullLogicalAndOr.ts]
// Repro from #9113
let sinOrCos = Math.random() < .5;
let choice = sinOrCos && Math.sin || Math.cos;
choice(Math.PI);
function sq(n?: number): number {
const r = n !== undefined && n*n || 0;
return r;
}
sq(3);
//// [strictNullLogicalAndOr.js]
// Repro from #9113
var sinOrCos = Math.random() < .5;
var choice = sinOrCos && Math.sin || Math.cos;
choice(Math.PI);
function sq(n) {
var r = n !== undefined && n * n || 0;
return r;
}
sq(3);
@@ -0,0 +1,44 @@
=== tests/cases/compiler/strictNullLogicalAndOr.ts ===
// Repro from #9113
let sinOrCos = Math.random() < .5;
>sinOrCos : Symbol(sinOrCos, Decl(strictNullLogicalAndOr.ts, 3, 3))
>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.d.ts, --, --))
let choice = sinOrCos && Math.sin || Math.cos;
>choice : Symbol(choice, Decl(strictNullLogicalAndOr.ts, 4, 3))
>sinOrCos : Symbol(sinOrCos, Decl(strictNullLogicalAndOr.ts, 3, 3))
>Math.sin : Symbol(Math.sin, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>sin : Symbol(Math.sin, Decl(lib.d.ts, --, --))
>Math.cos : Symbol(Math.cos, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>cos : Symbol(Math.cos, Decl(lib.d.ts, --, --))
choice(Math.PI);
>choice : Symbol(choice, Decl(strictNullLogicalAndOr.ts, 4, 3))
>Math.PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>PI : Symbol(Math.PI, Decl(lib.d.ts, --, --))
function sq(n?: number): number {
>sq : Symbol(sq, Decl(strictNullLogicalAndOr.ts, 6, 16))
>n : Symbol(n, Decl(strictNullLogicalAndOr.ts, 8, 12))
const r = n !== undefined && n*n || 0;
>r : Symbol(r, Decl(strictNullLogicalAndOr.ts, 9, 7))
>n : Symbol(n, Decl(strictNullLogicalAndOr.ts, 8, 12))
>undefined : Symbol(undefined)
>n : Symbol(n, Decl(strictNullLogicalAndOr.ts, 8, 12))
>n : Symbol(n, Decl(strictNullLogicalAndOr.ts, 8, 12))
return r;
>r : Symbol(r, Decl(strictNullLogicalAndOr.ts, 9, 7))
}
sq(3);
>sq : Symbol(sq, Decl(strictNullLogicalAndOr.ts, 6, 16))
@@ -0,0 +1,57 @@
=== tests/cases/compiler/strictNullLogicalAndOr.ts ===
// Repro from #9113
let sinOrCos = Math.random() < .5;
>sinOrCos : boolean
>Math.random() < .5 : boolean
>Math.random() : number
>Math.random : () => number
>Math : Math
>random : () => number
>.5 : number
let choice = sinOrCos && Math.sin || Math.cos;
>choice : (x: number) => number
>sinOrCos && Math.sin || Math.cos : (x: number) => number
>sinOrCos && Math.sin : (x: number) => number
>sinOrCos : boolean
>Math.sin : (x: number) => number
>Math : Math
>sin : (x: number) => number
>Math.cos : (x: number) => number
>Math : Math
>cos : (x: number) => number
choice(Math.PI);
>choice(Math.PI) : number
>choice : (x: number) => number
>Math.PI : number
>Math : Math
>PI : number
function sq(n?: number): number {
>sq : (n?: number | undefined) => number
>n : number | undefined
const r = n !== undefined && n*n || 0;
>r : number
>n !== undefined && n*n || 0 : number
>n !== undefined && n*n : number
>n !== undefined : boolean
>n : number | undefined
>undefined : undefined
>n*n : number
>n : number
>n : number
>0 : number
return r;
>r : number
}
sq(3);
>sq(3) : number
>sq : (n?: number | undefined) => number
>3 : number
@@ -0,0 +1,2 @@
export const x = 0;
//# sourceMappingURL=file.js.map
@@ -0,0 +1,3 @@
"use strict";
var x = 0;
//# sourceMappingURL=file.js.map
@@ -0,0 +1,7 @@
file.ts(1,3): error TS1005: ';' expected.
==== file.ts (1 errors) ====
a b
~
!!! error TS1005: ';' expected.
@@ -0,0 +1,4 @@
"use strict";
a;
b;
//# sourceMappingURL=file.js.map
@@ -0,0 +1,5 @@
define(["require", "exports"], function (require, exports) {
"use strict";
var x = 0;
});
//# sourceMappingURL=file.js.map
@@ -0,0 +1,4 @@
"use strict";
/// <reference path="file2.ts" />
var x = 0;
//# sourceMappingURL=file.js.map
@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=file.js.map
@@ -0,0 +1,3 @@
"use strict";
var x = 0;
//# sourceMappingURL=file.js.map
@@ -0,0 +1,3 @@
"use strict";
var x = 0;
//# sourceMappingURL=file.js.map
@@ -0,0 +1,5 @@
define(["require", "exports", "SomeOtherName"], function (require, exports, SomeName_1) {
"use strict";
use(SomeName_1.foo);
});
//# sourceMappingURL=file.js.map
@@ -0,0 +1,15 @@
System.register(["SomeOtherName"], function(exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
var SomeName_1;
return {
setters:[
function (SomeName_1_1) {
SomeName_1 = SomeName_1_1;
}],
execute: function() {
use(SomeName_1.foo);
}
}
});
//# sourceMappingURL=file.js.map
@@ -0,0 +1,13 @@
(function (factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports); if (v !== undefined) module.exports = v;
}
else if (typeof define === 'function' && define.amd) {
define(["require", "exports", "SomeOtherName"], factory);
}
})(function (require, exports) {
"use strict";
var SomeName_1 = require("SomeOtherName");
use(SomeName_1.foo);
});
//# sourceMappingURL=file.js.map
@@ -0,0 +1,6 @@
error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
!!! error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
==== file.ts (0 errors) ====
@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=file.js.map
@@ -0,0 +1,6 @@
error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
!!! error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
==== file.ts (0 errors) ====
@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=file.js.map
@@ -0,0 +1,6 @@
error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
!!! error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
==== file.ts (0 errors) ====
@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=file.js.map
@@ -0,0 +1,6 @@
error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
!!! error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
==== file.ts (0 errors) ====
@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=file.js.map
@@ -0,0 +1,12 @@
System.register("NamedModule", [], function(exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
var x;
return {
setters:[],
execute: function() {
var x = 1;
}
}
});
//# sourceMappingURL=file.js.map
@@ -0,0 +1,3 @@
"use strict";
var a = 10;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
var a = 10;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
var x;
//# sourceMappingURL=b.js.map
@@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map
@@ -0,0 +1,3 @@
"use strict";
x;
//# sourceMappingURL=input.js.map

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