Merge remote-tracking branch 'upstream/master'

This commit is contained in:
about-code
2017-01-14 12:24:07 +01:00
909 changed files with 37555 additions and 33544 deletions
+2
View File
@@ -3146,6 +3146,7 @@ namespace ts {
case SyntaxKind.AnyKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.ObjectKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
@@ -3344,6 +3345,7 @@ namespace ts {
case SyntaxKind.NumberKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.ObjectKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.VoidKeyword:
+224 -195
View File
@@ -108,6 +108,7 @@ namespace ts {
getAliasedSymbol: resolveAlias,
getEmitResolver,
getExportsOfModule: getExportsOfModuleAsArray,
getExportsAndPropertiesOfModule,
getAmbientModules,
getJsxElementAttributesType,
getJsxIntrinsicTagNames,
@@ -148,6 +149,7 @@ namespace ts {
const voidType = createIntrinsicType(TypeFlags.Void, "void");
const neverType = createIntrinsicType(TypeFlags.Never, "never");
const silentNeverType = createIntrinsicType(TypeFlags.Never, "never");
const nonPrimitiveType = createIntrinsicType(TypeFlags.NonPrimitive, "object");
const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
@@ -164,6 +166,7 @@ namespace ts {
anyFunctionType.flags |= TypeFlags.ContainsAnyFunctionType;
const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const circularConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
@@ -1525,6 +1528,15 @@ namespace ts {
return symbolsToArray(getExportsOfModule(moduleSymbol));
}
function getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[] {
const exports = getExportsOfModuleAsArray(moduleSymbol);
const exportEquals = resolveExternalModuleSymbol(moduleSymbol);
if (exportEquals !== moduleSymbol) {
addRange(exports, getPropertiesOfType(getTypeOfSymbol(exportEquals)));
}
return exports;
}
function tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined {
const symbolTable = getExportsOfModule(moduleSymbol);
if (symbolTable) {
@@ -3124,9 +3136,8 @@ namespace ts {
for (const prop of getPropertiesOfType(source)) {
const inNamesToRemove = prop.name in names;
const isPrivate = getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected);
const isMethod = prop.flags & SymbolFlags.Method;
const isSetOnlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
if (!inNamesToRemove && !isPrivate && !isMethod && !isSetOnlyAccessor) {
if (!inNamesToRemove && !isPrivate && !isClassMethod(prop) && !isSetOnlyAccessor) {
members[prop.name] = prop;
}
}
@@ -4136,9 +4147,6 @@ namespace ts {
if (!links.declaredType) {
const type = <TypeParameter>createType(TypeFlags.TypeParameter);
type.symbol = symbol;
if (!(<TypeParameterDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter)).constraint) {
type.constraint = noConstraintType;
}
links.declaredType = type;
}
return <TypeParameter>links.declaredType;
@@ -4197,6 +4205,7 @@ namespace ts {
case SyntaxKind.NumberKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.ObjectKeyword:
case SyntaxKind.VoidKeyword:
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.NullKeyword:
@@ -4605,7 +4614,7 @@ namespace ts {
// Create a mapper from T to the current iteration type constituent. Then, if the
// mapped type is itself an instantiated type, combine the iteration mapper with the
// instantiation mapper.
const iterationMapper = createUnaryTypeMapper(typeParameter, t);
const iterationMapper = createTypeMapper([typeParameter], [t]);
const templateMapper = type.mapper ? combineTypeMappers(type.mapper, iterationMapper) : iterationMapper;
const propType = instantiateType(templateType, templateMapper);
// If the current iteration type constituent is a string literal type, create a property.
@@ -4664,10 +4673,6 @@ namespace ts {
return type.modifiersType;
}
function getErasedTemplateTypeFromMappedType(type: MappedType) {
return instantiateType(getTemplateTypeFromMappedType(type), createUnaryTypeMapper(getTypeParameterFromMappedType(type), anyType));
}
function isGenericMappedType(type: Type) {
if (getObjectFlags(type) & ObjectFlags.Mapped) {
const constraintType = getConstraintTypeFromMappedType(<MappedType>type);
@@ -4755,19 +4760,79 @@ namespace ts {
getPropertiesOfObjectType(type);
}
function getConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type {
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) : getBaseConstraintOfType(type);
}
function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type {
return hasNonCircularBaseConstraint(typeParameter) ? getConstraintFromTypeParameter(typeParameter) : undefined;
}
function getBaseConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type {
const constraint = getResolvedBaseConstraint(type);
return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined;
}
function hasNonCircularBaseConstraint(type: TypeVariable): boolean {
return getResolvedBaseConstraint(type) !== circularConstraintType;
}
/**
* The apparent type of a type parameter is the base constraint instantiated with the type parameter
* as the type argument for the 'this' type.
* Return the resolved base constraint of a type variable. The noConstraintType singleton is returned if the
* type variable has no constraint, and the circularConstraintType singleton is returned if the constraint
* circularly references the type variable.
*/
function getApparentTypeOfTypeVariable(type: TypeVariable) {
if (!type.resolvedApparentType) {
let constraintType = getConstraintOfTypeVariable(type);
while (constraintType && constraintType.flags & TypeFlags.TypeParameter) {
constraintType = getConstraintOfTypeVariable(<TypeVariable>constraintType);
function getResolvedBaseConstraint(type: TypeVariable | UnionOrIntersectionType): Type {
let typeStack: Type[];
let circular: boolean;
if (!type.resolvedBaseConstraint) {
typeStack = [];
const constraint = getBaseConstraint(type);
type.resolvedBaseConstraint = circular ? circularConstraintType : getTypeWithThisArgument(constraint || noConstraintType, type);
}
return type.resolvedBaseConstraint;
function getBaseConstraint(t: Type): Type {
if (contains(typeStack, t)) {
circular = true;
return undefined;
}
type.resolvedApparentType = getTypeWithThisArgument(constraintType || emptyObjectType, type);
typeStack.push(t);
const result = computeBaseConstraint(t);
typeStack.pop();
return result;
}
function computeBaseConstraint(t: Type): Type {
if (t.flags & TypeFlags.TypeParameter) {
const constraint = getConstraintFromTypeParameter(<TypeParameter>t);
return (<TypeParameter>t).isThisType ? constraint :
constraint ? getBaseConstraint(constraint) : undefined;
}
if (t.flags & TypeFlags.UnionOrIntersection) {
const types = (<UnionOrIntersectionType>t).types;
const baseTypes: Type[] = [];
for (const type of types) {
const baseType = getBaseConstraint(type);
if (baseType) {
baseTypes.push(baseType);
}
}
return t.flags & TypeFlags.Union && baseTypes.length === types.length ? getUnionType(baseTypes) :
t.flags & TypeFlags.Intersection && baseTypes.length ? getIntersectionType(baseTypes) :
undefined;
}
if (t.flags & TypeFlags.Index) {
return stringType;
}
if (t.flags & TypeFlags.IndexedAccess) {
const baseObjectType = getBaseConstraint((<IndexedAccessType>t).objectType);
const baseIndexType = getBaseConstraint((<IndexedAccessType>t).indexType);
const baseIndexedAccess = baseObjectType && baseIndexType ? getIndexedAccessType(baseObjectType, baseIndexType) : undefined;
return baseIndexedAccess && baseIndexedAccess !== unknownType ? getBaseConstraint(baseIndexedAccess) : undefined;
}
return t;
}
return type.resolvedApparentType;
}
/**
@@ -4776,11 +4841,12 @@ namespace ts {
* type itself. Note that the apparent type of a union type is the union type itself.
*/
function getApparentType(type: Type): Type {
const t = type.flags & TypeFlags.TypeVariable ? getApparentTypeOfTypeVariable(<TypeVariable>type) : type;
const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfType(<TypeVariable>type) || emptyObjectType : type;
return t.flags & TypeFlags.StringLike ? globalStringType :
t.flags & TypeFlags.NumberLike ? globalNumberType :
t.flags & TypeFlags.BooleanLike ? globalBooleanType :
t.flags & TypeFlags.ESSymbol ? getGlobalESSymbolType() :
t.flags & TypeFlags.NonPrimitive ? globalObjectType :
t;
}
@@ -5056,9 +5122,10 @@ namespace ts {
if (!links.resolvedSignature) {
const parameters: Symbol[] = [];
let hasLiteralTypes = false;
let minArgumentCount = -1;
let minArgumentCount = 0;
let thisParameter: Symbol = undefined;
let hasThisParameter: boolean;
const iife = getImmediatelyInvokedFunctionExpression(declaration);
const isJSConstructSignature = isJSDocConstructSignature(declaration);
// If this is a JSDoc construct signature, then skip the first parameter in the
@@ -5085,14 +5152,12 @@ namespace ts {
hasLiteralTypes = true;
}
if (param.initializer || param.questionToken || param.dotDotDotToken || isJSDocOptionalParameter(param)) {
if (minArgumentCount < 0) {
minArgumentCount = i - (hasThisParameter ? 1 : 0);
}
}
else {
// If we see any required parameters, it means the prior ones were not in fact optional.
minArgumentCount = -1;
// Record a new minimum argument count if this is not an optional parameter
const isOptionalParameter = param.initializer || param.questionToken || param.dotDotDotToken ||
iife && parameters.length > iife.arguments.length && !param.type ||
isJSDocOptionalParameter(param);
if (!isOptionalParameter) {
minArgumentCount = parameters.length;
}
}
@@ -5107,13 +5172,6 @@ namespace ts {
}
}
if (minArgumentCount < 0) {
minArgumentCount = declaration.parameters.length - (hasThisParameter ? 1 : 0);
}
if (isJSConstructSignature) {
minArgumentCount--;
}
const classType = declaration.kind === SyntaxKind.Constructor ?
getDeclaredTypeOfClassOrInterface(getMergedSymbol((<ClassDeclaration>declaration.parent).symbol))
: undefined;
@@ -5330,20 +5388,7 @@ namespace ts {
return (<TypeParameterDeclaration>getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter)).constraint;
}
function hasConstraintReferenceTo(type: Type, target: TypeParameter): boolean {
let checked: Type[];
while (type && type.flags & TypeFlags.TypeParameter && !((type as TypeParameter).isThisType) && !contains(checked, type)) {
if (type === target) {
return true;
}
(checked || (checked = [])).push(type);
const constraintDeclaration = getConstraintDeclaration(<TypeParameter>type);
type = constraintDeclaration && getTypeFromTypeNode(constraintDeclaration);
}
return false;
}
function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type {
function getConstraintFromTypeParameter(typeParameter: TypeParameter): Type {
if (!typeParameter.constraint) {
if (typeParameter.target) {
const targetConstraint = getConstraintOfTypeParameter(typeParameter.target);
@@ -5351,23 +5396,12 @@ namespace ts {
}
else {
const constraintDeclaration = getConstraintDeclaration(typeParameter);
let constraint = getTypeFromTypeNode(constraintDeclaration);
if (hasConstraintReferenceTo(constraint, typeParameter)) {
error(constraintDeclaration, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(typeParameter));
constraint = unknownType;
}
typeParameter.constraint = constraint;
typeParameter.constraint = constraintDeclaration ? getTypeFromTypeNode(constraintDeclaration) : noConstraintType;
}
}
return typeParameter.constraint === noConstraintType ? undefined : typeParameter.constraint;
}
function getConstraintOfTypeVariable(type: TypeVariable): Type {
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) :
type.flags & TypeFlags.IndexedAccess ? (<IndexedAccessType>type).constraint :
undefined;
}
function getParentSymbolOfTypeParameter(typeParameter: TypeParameter): Symbol {
return getSymbolOfNode(getDeclarationOfKind(typeParameter.symbol, SyntaxKind.TypeParameter).parent);
}
@@ -6043,24 +6077,6 @@ namespace ts {
const type = <IndexedAccessType>createType(TypeFlags.IndexedAccess);
type.objectType = objectType;
type.indexType = indexType;
// We eagerly compute the constraint of the indexed access type such that circularity
// errors are immediately caught and reported. For example, class C { x: this["x"] }
// becomes an error only when the constraint is eagerly computed.
if (type.objectType.flags & TypeFlags.StructuredType) {
// The constraint of T[K], where T is an object, union, or intersection type,
// is the type of the string index signature of T, if any.
type.constraint = getIndexTypeOfType(type.objectType, IndexKind.String);
}
else if (type.objectType.flags & TypeFlags.TypeVariable) {
// The constraint of T[K], where T is a type variable, is A[K], where A is the
// apparent type of T.
const apparentType = getApparentTypeOfTypeVariable(<TypeVariable>type.objectType);
if (apparentType !== emptyObjectType) {
type.constraint = isTypeOfKind((<IndexedAccessType>type).indexType, TypeFlags.StringLike) ?
getIndexedAccessType(apparentType, (<IndexedAccessType>type).indexType) :
getIndexTypeOfType(apparentType, IndexKind.String);
}
}
return type;
}
@@ -6133,7 +6149,7 @@ namespace ts {
error(accessExpression, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(type));
return unknownType;
}
const mapper = createUnaryTypeMapper(getTypeParameterFromMappedType(type), indexType);
const mapper = createTypeMapper([getTypeParameterFromMappedType(type)], [indexType]);
const templateMapper = type.mapper ? combineTypeMappers(type.mapper, mapper) : mapper;
return instantiateType(getTemplateTypeFromMappedType(type), templateMapper);
}
@@ -6151,13 +6167,6 @@ namespace ts {
if (objectType.flags & TypeFlags.Any) {
return objectType;
}
// We first check that the index type is assignable to 'keyof T' for the object type.
if (accessNode) {
if (!isTypeAssignableTo(indexType, getIndexType(objectType))) {
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));
return unknownType;
}
}
// If the object type is a mapped type { [P in K]: E }, we instantiate E using a mapper that substitutes
// the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we construct the
// type Box<T[X]>.
@@ -6239,7 +6248,7 @@ namespace ts {
* this function should be called in a left folding style, with left = previous result of getSpreadType
* and right = the new element to be spread.
*/
function getSpreadType(left: Type, right: Type, isFromObjectLiteral: boolean): Type {
function getSpreadType(left: Type, right: Type): Type {
if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) {
return anyType;
}
@@ -6252,10 +6261,10 @@ namespace ts {
return left;
}
if (left.flags & TypeFlags.Union) {
return mapType(left, t => getSpreadType(t, right, isFromObjectLiteral));
return mapType(left, t => getSpreadType(t, right));
}
if (right.flags & TypeFlags.Union) {
return mapType(right, t => getSpreadType(left, t, isFromObjectLiteral));
return mapType(right, t => getSpreadType(left, t));
}
const members = createMap<Symbol>();
@@ -6274,18 +6283,18 @@ namespace ts {
for (const rightProp of getPropertiesOfType(right)) {
// we approximate own properties as non-methods plus methods that are inside the object literal
const isOwnProperty = !(rightProp.flags & SymbolFlags.Method) || isFromObjectLiteral;
const isSetterWithoutGetter = rightProp.flags & SymbolFlags.SetAccessor && !(rightProp.flags & SymbolFlags.GetAccessor);
if (getDeclarationModifierFlagsFromSymbol(rightProp) & (ModifierFlags.Private | ModifierFlags.Protected)) {
skippedPrivateMembers[rightProp.name] = true;
}
else if (isOwnProperty && !isSetterWithoutGetter) {
else if (!isClassMethod(rightProp) && !isSetterWithoutGetter) {
members[rightProp.name] = rightProp;
}
}
for (const leftProp of getPropertiesOfType(left)) {
if (leftProp.flags & SymbolFlags.SetAccessor && !(leftProp.flags & SymbolFlags.GetAccessor)
|| leftProp.name in skippedPrivateMembers) {
|| leftProp.name in skippedPrivateMembers
|| isClassMethod(leftProp)) {
continue;
}
if (leftProp.name in members) {
@@ -6310,6 +6319,10 @@ namespace ts {
return createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
}
function isClassMethod(prop: Symbol) {
return prop.flags & SymbolFlags.Method && find(prop.declarations, decl => isClassLike(decl.parent));
}
function createLiteralType(flags: TypeFlags, text: string) {
const type = <LiteralType>createType(flags);
type.text = text;
@@ -6406,6 +6419,8 @@ namespace ts {
return nullType;
case SyntaxKind.NeverKeyword:
return neverType;
case SyntaxKind.ObjectKeyword:
return nonPrimitiveType;
case SyntaxKind.JSDocNullKeyword:
return nullType;
case SyntaxKind.JSDocUndefinedKeyword:
@@ -6498,16 +6513,16 @@ namespace ts {
return <T>instantiations[type.id] || (instantiations[type.id] = instantiator(type, mapper));
}
function createUnaryTypeMapper(source: Type, target: Type): TypeMapper {
return t => t === source ? target : t;
function makeUnaryTypeMapper(source: Type, target: Type) {
return (t: Type) => t === source ? target : t;
}
function createBinaryTypeMapper(source1: Type, target1: Type, source2: Type, target2: Type): TypeMapper {
return t => t === source1 ? target1 : t === source2 ? target2 : t;
function makeBinaryTypeMapper(source1: Type, target1: Type, source2: Type, target2: Type) {
return (t: Type) => t === source1 ? target1 : t === source2 ? target2 : t;
}
function createArrayTypeMapper(sources: Type[], targets: Type[]): TypeMapper {
return t => {
function makeArrayTypeMapper(sources: Type[], targets: Type[]) {
return (t: Type) => {
for (let i = 0; i < sources.length; i++) {
if (t === sources[i]) {
return targets ? targets[i] : anyType;
@@ -6518,11 +6533,9 @@ namespace ts {
}
function createTypeMapper(sources: Type[], targets: Type[]): TypeMapper {
const count = sources.length;
const mapper: TypeMapper =
count == 1 ? createUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) :
count == 2 ? createBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) :
createArrayTypeMapper(sources, targets);
const mapper: TypeMapper = sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) :
sources.length === 2 ? makeBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) :
makeArrayTypeMapper(sources, targets);
mapper.mappedTypes = sources;
return mapper;
}
@@ -6556,7 +6569,13 @@ namespace ts {
function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
const mapper: TypeMapper = t => instantiateType(mapper1(t), mapper2);
mapper.mappedTypes = mapper1.mappedTypes;
mapper.mappedTypes = concatenate(mapper1.mappedTypes, mapper2.mappedTypes);
return mapper;
}
function createReplacementMapper(source: Type, target: Type, baseMapper: TypeMapper) {
const mapper: TypeMapper = t => t === source ? target : baseMapper(t);
mapper.mappedTypes = baseMapper.mappedTypes;
return mapper;
}
@@ -6658,10 +6677,7 @@ namespace ts {
if (typeVariable !== mappedTypeVariable) {
return mapType(mappedTypeVariable, t => {
if (isMappableType(t)) {
const replacementMapper = createUnaryTypeMapper(typeVariable, t);
const combinedMapper = mapper.mappedTypes && mapper.mappedTypes.length === 1 ? replacementMapper : combineTypeMappers(replacementMapper, mapper);
combinedMapper.mappedTypes = mapper.mappedTypes;
return instantiateMappedObjectType(type, combinedMapper);
return instantiateMappedObjectType(type, createReplacementMapper(typeVariable, t, mapper));
}
return t;
});
@@ -6921,7 +6937,7 @@ namespace ts {
// subtype of T but not structurally identical to T. This specifically means that two distinct but
// structurally identical types (such as two classes) are not considered instances of each other.
function isTypeInstanceOf(source: Type, target: Type): boolean {
return source === target || isTypeSubtypeOf(source, target) && !isTypeIdenticalTo(source, target);
return getTargetType(source) === getTargetType(target) || isTypeSubtypeOf(source, target) && !isTypeIdenticalTo(source, target);
}
/**
@@ -7163,6 +7179,7 @@ namespace ts {
if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum && isEnumTypeRelatedTo(<EnumType>source, <EnumType>target, errorReporter)) return true;
if (source.flags & TypeFlags.Undefined && (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void))) return true;
if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true;
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.NonPrimitive) return true;
if (relation === assignableRelation || relation === comparableRelation) {
if (source.flags & TypeFlags.Any) return true;
if ((source.flags & TypeFlags.Number | source.flags & TypeFlags.NumberLiteral) && target.flags & TypeFlags.EnumLike) return true;
@@ -7198,7 +7215,7 @@ namespace ts {
return related === RelationComparisonResult.Succeeded;
}
}
if (source.flags & TypeFlags.StructuredOrTypeParameter || target.flags & TypeFlags.StructuredOrTypeParameter) {
if (source.flags & TypeFlags.StructuredOrTypeVariable || target.flags & TypeFlags.StructuredOrTypeVariable) {
return checkTypeRelatedTo(source, target, relation, undefined, undefined, undefined);
}
return false;
@@ -7398,16 +7415,6 @@ namespace ts {
}
}
}
else {
// Given a type parameter K with a constraint keyof T, a type S is
// assignable to K if S is assignable to keyof T.
const constraint = getConstraintOfTypeParameter(<TypeParameter>target);
if (constraint && constraint.flags & TypeFlags.Index) {
if (result = isRelatedTo(source, constraint, reportErrors)) {
return result;
}
}
}
}
else if (target.flags & TypeFlags.Index) {
// A keyof S is related to a keyof T if T is related to S.
@@ -7416,14 +7423,12 @@ namespace ts {
return result;
}
}
// Given a type variable T with a constraint C, a type S is assignable to
// keyof T if S is assignable to keyof C.
if ((<IndexType>target).type.flags & TypeFlags.TypeVariable) {
const constraint = getConstraintOfTypeVariable(<TypeVariable>(<IndexType>target).type);
if (constraint) {
if (result = isRelatedTo(source, getIndexType(constraint), reportErrors)) {
return result;
}
// A type S is assignable to keyof T if S is assignable to keyof C, where C is the
// constraint of T.
const constraint = getConstraintOfType((<IndexType>target).type);
if (constraint) {
if (result = isRelatedTo(source, getIndexType(constraint), reportErrors)) {
return result;
}
}
}
@@ -7437,8 +7442,9 @@ namespace ts {
}
// A type S is related to a type T[K] if S is related to A[K], where K is string-like and
// A is the apparent type of S.
if ((<IndexedAccessType>target).constraint) {
if (result = isRelatedTo(source, (<IndexedAccessType>target).constraint, reportErrors)) {
const constraint = getBaseConstraintOfType(<IndexedAccessType>target);
if (constraint) {
if (result = isRelatedTo(source, constraint, reportErrors)) {
errorInfo = saveErrorInfo;
return result;
}
@@ -7457,27 +7463,28 @@ namespace ts {
}
else {
let constraint = getConstraintOfTypeParameter(<TypeParameter>source);
if (!constraint || constraint.flags & TypeFlags.Any) {
constraint = emptyObjectType;
}
// The constraint may need to be further instantiated with its 'this' type.
constraint = getTypeWithThisArgument(constraint, source);
// Report constraint errors only if the constraint is not the empty object type
const reportConstraintErrors = reportErrors && constraint !== emptyObjectType;
if (result = isRelatedTo(constraint, target, reportConstraintErrors)) {
errorInfo = saveErrorInfo;
return result;
// A type parameter with no constraint is not related to the non-primitive object type.
if (constraint || !(target.flags & TypeFlags.NonPrimitive)) {
if (!constraint || constraint.flags & TypeFlags.Any) {
constraint = emptyObjectType;
}
// The constraint may need to be further instantiated with its 'this' type.
constraint = getTypeWithThisArgument(constraint, source);
// Report constraint errors only if the constraint is not the empty object type
const reportConstraintErrors = reportErrors && constraint !== emptyObjectType;
if (result = isRelatedTo(constraint, target, reportConstraintErrors)) {
errorInfo = saveErrorInfo;
return result;
}
}
}
}
else if (source.flags & TypeFlags.IndexedAccess) {
// A type S[K] is related to a type T if A[K] is related to T, where K is string-like and
// A is the apparent type of S.
if ((<IndexedAccessType>source).constraint) {
if (result = isRelatedTo((<IndexedAccessType>source).constraint, target, reportErrors)) {
const constraint = getBaseConstraintOfType(<IndexedAccessType>source);
if (constraint) {
if (result = isRelatedTo(constraint, target, reportErrors)) {
errorInfo = saveErrorInfo;
return result;
}
@@ -7764,25 +7771,24 @@ namespace ts {
return result;
}
// A type [P in S]: X is related to a type [P in T]: Y if T is related to S and X is related to Y.
// A type [P in S]: X is related to a type [Q in T]: Y if T is related to S and X' is
// related to Y, where X' is an instantiation of X in which P is replaced with Q. Notice
// that S and T are contra-variant whereas X and Y are co-variant.
function mappedTypeRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
if (isGenericMappedType(target)) {
if (isGenericMappedType(source)) {
let result: Ternary;
if (relation === identityRelation) {
const readonlyMatches = !(<MappedType>source).declaration.readonlyToken === !(<MappedType>target).declaration.readonlyToken;
const optionalMatches = !(<MappedType>source).declaration.questionToken === !(<MappedType>target).declaration.questionToken;
if (readonlyMatches && optionalMatches) {
if (result = isRelatedTo(getConstraintTypeFromMappedType(<MappedType>target), getConstraintTypeFromMappedType(<MappedType>source), reportErrors)) {
return result & isRelatedTo(getErasedTemplateTypeFromMappedType(<MappedType>source), getErasedTemplateTypeFromMappedType(<MappedType>target), reportErrors);
}
}
}
else {
if (relation === comparableRelation || !(<MappedType>source).declaration.questionToken || (<MappedType>target).declaration.questionToken) {
if (result = isRelatedTo(getConstraintTypeFromMappedType(<MappedType>target), getConstraintTypeFromMappedType(<MappedType>source), reportErrors)) {
return result & isRelatedTo(getTemplateTypeFromMappedType(<MappedType>source), getTemplateTypeFromMappedType(<MappedType>target), reportErrors);
}
const sourceReadonly = !!(<MappedType>source).declaration.readonlyToken;
const sourceOptional = !!(<MappedType>source).declaration.questionToken;
const targetReadonly = !!(<MappedType>target).declaration.readonlyToken;
const targetOptional = !!(<MappedType>target).declaration.questionToken;
const modifiersRelated = relation === identityRelation ?
sourceReadonly === targetReadonly && sourceOptional === targetOptional :
relation === comparableRelation || !sourceOptional || targetOptional;
if (modifiersRelated) {
let result: Ternary;
if (result = isRelatedTo(getConstraintTypeFromMappedType(<MappedType>target), getConstraintTypeFromMappedType(<MappedType>source), reportErrors)) {
const mapper = createTypeMapper([getTypeParameterFromMappedType(<MappedType>source)], [getTypeParameterFromMappedType(<MappedType>target)]);
return result & isRelatedTo(instantiateType(getTemplateTypeFromMappedType(<MappedType>source), mapper), getTemplateTypeFromMappedType(<MappedType>target), reportErrors);
}
}
}
@@ -9276,6 +9282,9 @@ namespace ts {
if (flags & TypeFlags.ESSymbol) {
return strictNullChecks ? TypeFacts.SymbolStrictFacts : TypeFacts.SymbolFacts;
}
if (flags & TypeFlags.NonPrimitive) {
return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
}
if (flags & TypeFlags.TypeParameter) {
const constraint = getConstraintOfTypeParameter(<TypeParameter>type);
return getTypeFacts(constraint || emptyObjectType);
@@ -10924,23 +10933,23 @@ namespace ts {
const func = parameter.parent;
if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
const iife = getImmediatelyInvokedFunctionExpression(func);
if (iife) {
if (iife && iife.arguments) {
const indexOfParameter = indexOf(func.parameters, parameter);
if (iife.arguments && indexOfParameter < iife.arguments.length) {
if (parameter.dotDotDotToken) {
const restTypes: Type[] = [];
for (let i = indexOfParameter; i < iife.arguments.length; i++) {
restTypes.push(getWidenedLiteralType(checkExpression(iife.arguments[i])));
}
return createArrayType(getUnionType(restTypes));
if (parameter.dotDotDotToken) {
const restTypes: Type[] = [];
for (let i = indexOfParameter; i < iife.arguments.length; i++) {
restTypes.push(getWidenedLiteralType(checkExpression(iife.arguments[i])));
}
const links = getNodeLinks(iife);
const cached = links.resolvedSignature;
links.resolvedSignature = anySignature;
const type = getWidenedLiteralType(checkExpression(iife.arguments[indexOfParameter]));
links.resolvedSignature = cached;
return type;
return restTypes.length ? createArrayType(getUnionType(restTypes)) : undefined;
}
const links = getNodeLinks(iife);
const cached = links.resolvedSignature;
links.resolvedSignature = anySignature;
const type = indexOfParameter < iife.arguments.length ?
getWidenedLiteralType(checkExpression(iife.arguments[indexOfParameter])) :
parameter.initializer ? undefined : undefinedWideningType;
links.resolvedSignature = cached;
return type;
}
const contextualSignature = getContextualSignature(func);
if (contextualSignature) {
@@ -11649,7 +11658,7 @@ namespace ts {
checkExternalEmitHelpers(memberDecl, ExternalEmitHelpers.Assign);
}
if (propertiesArray.length > 0) {
spread = getSpreadType(spread, createObjectLiteralType(), /*isFromObjectLiteral*/ true);
spread = getSpreadType(spread, createObjectLiteralType());
propertiesArray = [];
propertiesTable = createMap<Symbol>();
hasComputedStringProperty = false;
@@ -11661,7 +11670,7 @@ namespace ts {
error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types);
return unknownType;
}
spread = getSpreadType(spread, type, /*isFromObjectLiteral*/ false);
spread = getSpreadType(spread, type);
offset = i + 1;
continue;
}
@@ -11706,7 +11715,7 @@ namespace ts {
if (spread !== emptyObjectType) {
if (propertiesArray.length > 0) {
spread = getSpreadType(spread, createObjectLiteralType(), /*isFromObjectLiteral*/ true);
spread = getSpreadType(spread, createObjectLiteralType());
}
if (spread.flags & TypeFlags.Object) {
// only set the symbol and flags if this is a (fresh) object type
@@ -12529,7 +12538,7 @@ namespace ts {
return unknownType;
}
return getIndexedAccessType(objectType, indexType, node);
return checkIndexedAccessIndexType(getIndexedAccessType(objectType, indexType, node), node);
}
function checkThatExpressionIsProperSymbolReference(expression: Expression, expressionType: Type, reportError: boolean): boolean {
@@ -14577,14 +14586,18 @@ namespace ts {
}
// TypeScript 1.0 spec (April 2014): 4.15.4
// The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type,
// and the right operand to be of type Any or a subtype of the 'Function' interface type.
// and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature.
// The result is always of the Boolean primitive type.
// NOTE: do not raise error if leftType is unknown as related error was already reported
if (isTypeOfKind(leftType, TypeFlags.Primitive)) {
error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
}
// NOTE: do not raise error if right is unknown as related error was already reported
if (!(isTypeAny(rightType) || isTypeSubtypeOf(rightType, globalFunctionType))) {
if (!(isTypeAny(rightType) ||
rightType.flags & TypeFlags.Nullable ||
getSignaturesOfType(rightType, SignatureKind.Call).length ||
getSignaturesOfType(rightType, SignatureKind.Construct).length ||
isTypeSubtypeOf(rightType, globalFunctionType))) {
error(right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type);
}
return booleanType;
@@ -15187,14 +15200,14 @@ namespace ts {
function isLiteralContextualType(contextualType: Type) {
if (contextualType) {
if (contextualType.flags & TypeFlags.TypeVariable) {
const apparentType = getApparentTypeOfTypeVariable(<TypeVariable>contextualType);
const constraint = getBaseConstraintOfType(<TypeVariable>contextualType) || emptyObjectType;
// If the type parameter is constrained to the base primitive type we're checking for,
// consider this a literal context. For example, given a type parameter 'T extends string',
// this causes us to infer string literal types for T.
if (apparentType.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.Boolean | TypeFlags.Enum)) {
if (constraint.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.Boolean | TypeFlags.Enum)) {
return true;
}
contextualType = apparentType;
contextualType = constraint;
}
return maybeTypeOfKind(contextualType, (TypeFlags.Literal | TypeFlags.Index));
}
@@ -15392,6 +15405,10 @@ namespace ts {
}
checkSourceElement(node.constraint);
const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node));
if (!hasNonCircularBaseConstraint(typeParameter)) {
error(node.constraint, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(typeParameter));
}
getConstraintOfTypeParameter(getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)));
if (produceDiagnostics) {
checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0);
@@ -16063,8 +16080,20 @@ namespace ts {
forEach(node.types, checkSourceElement);
}
function checkIndexedAccessIndexType(type: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode) {
if (type.flags & TypeFlags.IndexedAccess) {
// Check that the index type is assignable to 'keyof T' for the object type.
const objectType = (<IndexedAccessType>type).objectType;
const indexType = (<IndexedAccessType>type).indexType;
if (!isTypeAssignableTo(indexType, getIndexType(objectType))) {
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));
}
}
return type;
}
function checkIndexedAccessType(node: IndexedAccessTypeNode) {
getTypeFromIndexedAccessTypeNode(node);
checkIndexedAccessIndexType(getTypeFromIndexedAccessTypeNode(node), node);
}
function checkMappedType(node: MappedTypeNode) {
@@ -16072,8 +16101,7 @@ namespace ts {
checkSourceElement(node.type);
const type = <MappedType>getTypeFromMappedTypeNode(node);
const constraintType = getConstraintTypeFromMappedType(type);
const keyType = constraintType.flags & TypeFlags.TypeVariable ? getApparentTypeOfTypeVariable(<TypeVariable>constraintType) : constraintType;
checkTypeAssignableTo(keyType, stringType, node.typeParameter.constraint);
checkTypeAssignableTo(constraintType, stringType, node.typeParameter.constraint);
}
function isPrivateWithinAmbient(node: Node): boolean {
@@ -17943,27 +17971,27 @@ namespace ts {
if (func.kind === SyntaxKind.SetAccessor) {
if (node.expression) {
error(node.expression, Diagnostics.Setters_cannot_return_a_value);
error(node, Diagnostics.Setters_cannot_return_a_value);
}
}
else if (func.kind === SyntaxKind.Constructor) {
if (node.expression && !checkTypeAssignableTo(exprType, returnType, node.expression)) {
error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
if (node.expression && !checkTypeAssignableTo(exprType, returnType, node)) {
error(node, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
}
}
else if (func.type || isGetAccessorWithAnnotatedSetAccessor(func)) {
if (isAsyncFunctionLike(func)) {
const promisedType = getPromisedType(returnType);
const awaitedType = checkAwaitedType(exprType, node.expression || node, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member);
const awaitedType = checkAwaitedType(exprType, node, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member);
if (promisedType) {
// If the function has a return type, but promisedType is
// undefined, an error will be reported in checkAsyncFunctionReturnType
// so we don't need to report one here.
checkTypeAssignableTo(awaitedType, promisedType, node.expression || node);
checkTypeAssignableTo(awaitedType, promisedType, node);
}
}
else {
checkTypeAssignableTo(exprType, returnType, node.expression || node);
checkTypeAssignableTo(exprType, returnType, node);
}
}
}
@@ -18208,6 +18236,7 @@ namespace ts {
case "string":
case "symbol":
case "void":
case "object":
error(name, message, (<Identifier>name).text);
}
}
+3 -3
View File
@@ -212,8 +212,8 @@ namespace ts {
shortName: "p",
type: "string",
isFilePath: true,
description: Diagnostics.Compile_the_project_in_the_given_directory,
paramType: Diagnostics.DIRECTORY
description: Diagnostics.Compile_the_project_given_the_path_to_its_configuration_file_or_to_a_folder_with_a_tsconfig_json,
paramType: Diagnostics.FILE_OR_DIRECTORY
},
{
name: "removeComments",
@@ -517,7 +517,7 @@ namespace ts {
include: typeAcquisition.include || [],
exclude: typeAcquisition.exclude || []
};
return result;
return result;
}
return typeAcquisition;
}
+6 -2
View File
@@ -2517,7 +2517,7 @@
"category": "Message",
"code": 6019
},
"Compile the project in the given directory.": {
"Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'": {
"category": "Message",
"code": 6020
},
@@ -2577,6 +2577,10 @@
"category": "Message",
"code": 6039
},
"FILE OR DIRECTORY": {
"category": "Message",
"code": 6040
},
"Compilation complete. Watching for file changes.": {
"category": "Message",
"code": 6042
@@ -3247,7 +3251,7 @@
"category": "Message",
"code": 90003
},
"Remove unused identifiers.": {
"Remove declaration for: {0}": {
"category": "Message",
"code": 90004
},
+6 -6
View File
@@ -15,7 +15,7 @@ namespace ts {
}
/** Array that is only intended to be pushed to, never read. */
interface Push<T> {
export interface Push<T> {
push(value: T): void;
}
@@ -357,7 +357,7 @@ namespace ts {
* Then it computes the set of parent folders for 'directory' that should have the same module resolution result
* and for every parent folder in set it adds entry: parent -> module resolution. .
* Lets say we first directory name: /a/b/c/d/e and resolution result is: /a/b/bar.ts.
* Set of parent folders that should have the same result will be:
* Set of parent folders that should have the same result will be:
* [
* /a/b/c/d, /a/b/c, /a/b
* ]
@@ -391,7 +391,7 @@ namespace ts {
}
}
}
function getCommonPrefix(directory: Path, resolution: string) {
if (resolution === undefined) {
return undefined;
@@ -421,7 +421,7 @@ namespace ts {
trace(host, Diagnostics.Resolving_module_0_from_1, moduleName, containingFile);
}
const containingDirectory = getDirectoryPath(containingFile);
let perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory);
const perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory);
let result = perFolderCache && perFolderCache[moduleName];
if (result) {
@@ -1022,7 +1022,7 @@ namespace ts {
/**
* Represents result of search. Normally when searching among several alternatives we treat value `undefined` as indicator
* that search fails and we should try another option.
* that search fails and we should try another option.
* However this does not allow us to represent final result that should be used instead of further searching (i.e. a final result that was found in cache).
* SearchResult is used to deal with this issue, its values represents following outcomes:
* - undefined - not found, continue searching
@@ -1030,7 +1030,7 @@ namespace ts {
* - { value: <some-value> } - found - stop searching
*/
type SearchResult<T> = { value: T | undefined } | undefined;
/**
* Wraps value to SearchResult.
* @returns undefined if value is undefined or { value } otherwise
+3
View File
@@ -2510,6 +2510,7 @@ namespace ts {
case SyntaxKind.SymbolKeyword:
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.ObjectKeyword:
// If these are followed by a dot, then parse these out as a dotted type reference instead.
const node = tryParse(parseKeywordAndNoDot);
return node || parseTypeReference();
@@ -2568,6 +2569,7 @@ namespace ts {
case SyntaxKind.NumericLiteral:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.ObjectKeyword:
return true;
case SyntaxKind.MinusToken:
return lookAhead(nextTokenIsNumericLiteral);
@@ -6037,6 +6039,7 @@ namespace ts {
case SyntaxKind.NullKeyword:
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.ObjectKeyword:
return parseTokenNode<JSDocType>();
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
+3 -2
View File
@@ -98,6 +98,7 @@ namespace ts {
"new": SyntaxKind.NewKeyword,
"null": SyntaxKind.NullKeyword,
"number": SyntaxKind.NumberKeyword,
"object": SyntaxKind.ObjectKeyword,
"package": SyntaxKind.PackageKeyword,
"private": SyntaxKind.PrivateKeyword,
"protected": SyntaxKind.ProtectedKeyword,
@@ -733,11 +734,11 @@ namespace ts {
return comments;
}
export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] {
export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined {
return reduceEachLeadingCommentRange(text, pos, appendCommentRange, undefined, undefined);
}
export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] {
export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined {
return reduceEachTrailingCommentRange(text, pos, appendCommentRange, undefined, undefined);
}
+1 -1
View File
@@ -18,7 +18,7 @@ namespace ts {
getFileSize?(path: string): number;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
/**
* @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that
* @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that
* use native OS file watching
*/
watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
+35 -17
View File
@@ -925,7 +925,10 @@ namespace ts {
}
const superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, !!extendsClauseElement, hasSynthesizedSuper, statementOffset);
// determine whether the class is known syntactically to be a derived class (e.g. a
// class that extends a value that is not syntactically known to be `null`).
const isDerivedClass = extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword;
const superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, isDerivedClass, hasSynthesizedSuper, statementOffset);
// The last statement expression was replaced. Skip it.
if (superCaptureStatus === SuperCaptureResult.ReplaceSuperCapture || superCaptureStatus === SuperCaptureResult.ReplaceWithReturn) {
@@ -942,7 +945,7 @@ namespace ts {
// Return `_this` unless we're sure enough that it would be pointless to add a return statement.
// If there's a constructor that we can tell returns in enough places, then we *do not* want to add a return.
if (extendsClauseElement
if (isDerivedClass
&& superCaptureStatus !== SuperCaptureResult.ReplaceWithReturn
&& !(constructor && isSufficientlyCoveredByReturnStatements(constructor.body))) {
statements.push(
@@ -1011,11 +1014,11 @@ namespace ts {
function declareOrCaptureOrReturnThisForConstructorIfNeeded(
statements: Statement[],
ctor: ConstructorDeclaration | undefined,
hasExtendsClause: boolean,
isDerivedClass: boolean,
hasSynthesizedSuper: boolean,
statementOffset: number) {
// If this isn't a derived class, just capture 'this' for arrow functions if necessary.
if (!hasExtendsClause) {
if (!isDerivedClass) {
if (ctor) {
addCaptureThisForNodeIfNeeded(statements, ctor);
}
@@ -1091,7 +1094,7 @@ namespace ts {
}
// Perform the capture.
captureThisForNode(statements, ctor, superCallExpression, firstStatement);
captureThisForNode(statements, ctor, superCallExpression || createActualThis(), firstStatement);
// If we're actually replacing the original statement, we need to signal this to the caller.
if (superCallExpression) {
@@ -1101,15 +1104,25 @@ namespace ts {
return SuperCaptureResult.NoReplacement;
}
function createActualThis() {
return setEmitFlags(createThis(), EmitFlags.NoSubstitution);
}
function createDefaultSuperCallOrThis() {
const actualThis = createThis();
setEmitFlags(actualThis, EmitFlags.NoSubstitution);
const superCall = createFunctionApply(
createIdentifier("_super"),
actualThis,
createIdentifier("arguments"),
return createLogicalOr(
createLogicalAnd(
createStrictInequality(
createIdentifier("_super"),
createNull()
),
createFunctionApply(
createIdentifier("_super"),
createActualThis(),
createIdentifier("arguments"),
)
),
createActualThis()
);
return createLogicalOr(superCall, actualThis);
}
/**
@@ -3627,10 +3640,15 @@ namespace ts {
scoped: false,
priority: 0,
text: `
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 __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();`
};
}
+47 -38
View File
@@ -150,6 +150,9 @@ namespace ts {
return decoded ? createLiteral(decoded, /*location*/ node) : node;
}
else if (node.kind === SyntaxKind.JsxExpression) {
if (node.expression === undefined) {
return createLiteral(true);
}
return visitJsxExpression(<JsxExpression>node);
}
else {
@@ -157,33 +160,50 @@ namespace ts {
}
}
function visitJsxText(node: JsxText) {
const text = getTextOfNode(node, /*includeTrivia*/ true);
let parts: Expression[];
function visitJsxText(node: JsxText): StringLiteral | undefined {
const fixed = fixupWhitespaceAndDecodeEntities(getTextOfNode(node, /*includeTrivia*/ true));
return fixed === undefined ? undefined : createLiteral(fixed);
}
/**
* JSX trims whitespace at the end and beginning of lines, except that the
* start/end of a tag is considered a start/end of a line only if that line is
* on the same line as the closing tag. See examples in
* tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx
* See also https://www.w3.org/TR/html4/struct/text.html#h-9.1 and https://www.w3.org/TR/CSS2/text.html#white-space-model
*
* An equivalent algorithm would be:
* - If there is only one line, return it.
* - If there is only whitespace (but multiple lines), return `undefined`.
* - Split the text into lines.
* - 'trimRight' the first line, 'trimLeft' the last line, 'trim' middle lines.
* - Decode entities on each line (individually).
* - Remove empty lines and join the rest with " ".
*/
function fixupWhitespaceAndDecodeEntities(text: string): string | undefined {
let acc: string | undefined;
// First non-whitespace character on this line.
let firstNonWhitespace = 0;
// Last non-whitespace character on this line.
let lastNonWhitespace = -1;
// These initial values are special because the first line is:
// firstNonWhitespace = 0 to indicate that we want leading whitsepace,
// but lastNonWhitespace = -1 as a special flag to indicate that we *don't* include the line if it's all whitespace.
// JSX trims whitespace at the end and beginning of lines, except that the
// start/end of a tag is considered a start/end of a line only if that line is
// on the same line as the closing tag. See examples in
// tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx
for (let i = 0; i < text.length; i++) {
const c = text.charCodeAt(i);
if (isLineBreak(c)) {
if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) {
const part = text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1);
if (!parts) {
parts = [];
}
// We do not escape the string here as that is handled by the printer
// when it emits the literal. We do, however, need to decode JSX entities.
parts.push(createLiteral(decodeEntities(part)));
// If we've seen any non-whitespace characters on this line, add the 'trim' of the line.
// (lastNonWhitespace === -1 is a special flag to detect whether the first line is all whitespace.)
if (firstNonWhitespace !== -1 && lastNonWhitespace !== -1) {
acc = addLineOfJsxText(acc, text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1));
}
// Reset firstNonWhitespace for the next line.
// Don't bother to reset lastNonWhitespace because we ignore it if firstNonWhitespace = -1.
firstNonWhitespace = -1;
}
else if (!isWhiteSpace(c)) {
else if (!isWhiteSpaceSingleLine(c)) {
lastNonWhitespace = i;
if (firstNonWhitespace === -1) {
firstNonWhitespace = i;
@@ -191,29 +211,18 @@ namespace ts {
}
}
if (firstNonWhitespace !== -1) {
const part = text.substr(firstNonWhitespace);
if (!parts) {
parts = [];
}
// We do not escape the string here as that is handled by the printer
// when it emits the literal. We do, however, need to decode JSX entities.
parts.push(createLiteral(decodeEntities(part)));
}
if (parts) {
return reduceLeft(parts, aggregateJsxTextParts);
}
return undefined;
return firstNonWhitespace !== -1
// Last line had a non-whitespace character. Emit the 'trimLeft', meaning keep trailing whitespace.
? addLineOfJsxText(acc, text.substr(firstNonWhitespace))
// Last line was all whitespace, so ignore it
: acc;
}
/**
* Aggregates two expressions by interpolating them with a whitespace literal.
*/
function aggregateJsxTextParts(left: Expression, right: Expression) {
return createAdd(createAdd(left, createLiteral(" ")), right);
function addLineOfJsxText(acc: string | undefined, trimmedLine: string): string {
// We do not escape the string here as that is handled by the printer
// when it emits the literal. We do, however, need to decode JSX entities.
const decoded = decodeEntities(trimmedLine);
return acc === undefined ? decoded : acc + " " + decoded;
}
/**
+1 -9
View File
@@ -1,17 +1,9 @@
{
"extends": "../tsconfig-base",
"compilerOptions": {
"noImplicitAny": true,
"noImplicitThis": true,
"removeComments": true,
"preserveConstEnums": true,
"pretty": true,
"outFile": "../../built/local/tsc.js",
"sourceMap": true,
"declaration": true,
"stripInternal": true,
"target": "es5",
"noUnusedLocals": true,
"noUnusedParameters": true,
"types": [ ]
},
"files": [
+14 -6
View File
@@ -175,6 +175,7 @@ namespace ts {
ReadonlyKeyword,
RequireKeyword,
NumberKeyword,
ObjectKeyword,
SetKeyword,
StringKeyword,
SymbolKeyword,
@@ -816,6 +817,7 @@ namespace ts {
export interface KeywordTypeNode extends TypeNode {
kind: SyntaxKind.AnyKeyword
| SyntaxKind.NumberKeyword
| SyntaxKind.ObjectKeyword
| SyntaxKind.BooleanKeyword
| SyntaxKind.StringKeyword
| SyntaxKind.SymbolKeyword
@@ -1550,7 +1552,7 @@ namespace ts {
name?: Identifier;
}
export type BlockLike = SourceFile | Block | ModuleBlock | CaseClause;
export type BlockLike = SourceFile | Block | ModuleBlock | CaseOrDefaultClause;
export interface Block extends Statement {
kind: SyntaxKind.Block;
@@ -2368,6 +2370,8 @@ namespace ts {
isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean;
getAliasedSymbol(symbol: Symbol): Symbol;
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
/** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];
getJsxElementAttributesType(elementNode: JsxOpeningLikeElement): Type;
getJsxIntrinsicTagNames(): Symbol[];
@@ -2785,6 +2789,7 @@ namespace ts {
ContainsObjectLiteral = 1 << 22, // Type is or contains object literal type
/* @internal */
ContainsAnyFunctionType = 1 << 23, // Type is or contains object literal type
NonPrimitive = 1 << 24, // intrinsic object type
/* @internal */
Nullable = Undefined | Null,
@@ -2794,7 +2799,7 @@ namespace ts {
DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null,
PossiblyFalsy = DefinitelyFalsy | String | Number | Boolean,
/* @internal */
Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never,
Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never | NonPrimitive,
/* @internal */
Primitive = String | Number | Boolean | Enum | ESSymbol | Void | Undefined | Null | Literal,
StringLike = String | StringLiteral | Index,
@@ -2803,13 +2808,13 @@ namespace ts {
EnumLike = Enum | EnumLiteral,
UnionOrIntersection = Union | Intersection,
StructuredType = Object | Union | Intersection,
StructuredOrTypeParameter = StructuredType | TypeParameter | Index,
StructuredOrTypeVariable = StructuredType | TypeParameter | Index | IndexedAccess,
TypeVariable = TypeParameter | IndexedAccess,
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol,
NotUnionOrUnit = Any | ESSymbol | Object,
Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol | NonPrimitive,
NotUnionOrUnit = Any | ESSymbol | Object | NonPrimitive,
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
/* @internal */
@@ -2863,6 +2868,7 @@ namespace ts {
ObjectLiteral = 1 << 7, // Originates in an object literal
EvolvingArray = 1 << 8, // Evolving array type
ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties
NonPrimitive = 1 << 10, // NonPrimitive object type
ClassOrInterface = Class | Interface
}
@@ -2919,6 +2925,8 @@ namespace ts {
/* @internal */
resolvedIndexType: IndexType;
/* @internal */
resolvedBaseConstraint: Type;
/* @internal */
couldContainTypeVariables: boolean;
}
@@ -2978,7 +2986,7 @@ namespace ts {
export interface TypeVariable extends Type {
/* @internal */
resolvedApparentType: Type;
resolvedBaseConstraint: Type;
/* @internal */
resolvedIndexType: IndexType;
}
+78 -34
View File
@@ -47,9 +47,9 @@ namespace FourSlash {
/**
* Inserted in source files by surrounding desired text
* in a range with `[|` and `|]`. For example,
*
*
* [|text in range|]
*
*
* is a range with `text in range` "selected".
*/
ranges: Range[];
@@ -262,23 +262,12 @@ namespace FourSlash {
// Initialize the language service with all the scripts
let startResolveFileRef: FourSlashFile;
let configFileName: string;
ts.forEach(testData.files, file => {
// Create map between fileName and its content for easily looking up when resolveReference flag is specified
this.inputFiles[file.fileName] = file.content;
if (ts.getBaseFileName(file.fileName).toLowerCase() === "tsconfig.json") {
const configJson = ts.parseConfigFileTextToJson(file.fileName, file.content);
assert.isTrue(configJson.config !== undefined);
// Extend our existing compiler options so that we can also support tsconfig only options
if (configJson.config.compilerOptions) {
const baseDirectory = ts.normalizePath(ts.getDirectoryPath(file.fileName));
const tsConfig = ts.convertCompilerOptionsFromJson(configJson.config.compilerOptions, baseDirectory, file.fileName);
if (!tsConfig.errors || !tsConfig.errors.length) {
compilationOptions = ts.extend(compilationOptions, tsConfig.options);
}
}
configFileName = file.fileName;
}
if (!startResolveFileRef && file.fileOptions[metadataOptionNames.resolveReference] === "true") {
@@ -290,6 +279,21 @@ namespace FourSlash {
}
});
if (configFileName) {
const baseDir = ts.normalizePath(ts.getDirectoryPath(configFileName));
const host = new Utils.MockParseConfigHost(baseDir, /*ignoreCase*/ false, this.inputFiles);
const configJsonObj = ts.parseConfigFileTextToJson(configFileName, this.inputFiles[configFileName]);
assert.isTrue(configJsonObj.config !== undefined);
const { options, errors } = ts.parseJsonConfigFileContent(configJsonObj.config, host, baseDir);
// Extend our existing compiler options so that we can also support tsconfig only options
if (!errors || errors.length === 0) {
compilationOptions = ts.extend(compilationOptions, options);
}
}
if (compilationOptions.typeRoots) {
compilationOptions.typeRoots = compilationOptions.typeRoots.map(p => ts.getNormalizedAbsolutePath(p, this.basePath));
@@ -421,8 +425,7 @@ namespace FourSlash {
}
private raiseError(message: string) {
message = this.messageAtLastKnownMarker(message);
throw new Error(message);
throw new Error(this.messageAtLastKnownMarker(message));
}
private messageAtLastKnownMarker(message: string) {
@@ -536,53 +539,66 @@ namespace FourSlash {
}
public verifyGoToDefinitionIs(endMarker: string | string[]) {
this.verifyGoToDefinitionWorker(endMarker instanceof Array ? endMarker : [endMarker]);
this.verifyGoToXWorker(endMarker instanceof Array ? endMarker : [endMarker], () => this.getGoToDefinition());
}
public verifyGoToDefinition(arg0: any, endMarkerNames?: string | string[]) {
this.verifyGoToX(arg0, endMarkerNames, () => this.getGoToDefinition());
}
private getGoToDefinition(): ts.DefinitionInfo[] {
return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition)
}
public verifyGoToType(arg0: any, endMarkerNames?: string | string[]) {
this.verifyGoToX(arg0, endMarkerNames, () =>
this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition));
}
private verifyGoToX(arg0: any, endMarkerNames: string | string[] | undefined, getDefs: () => ts.DefinitionInfo[] | undefined) {
if (endMarkerNames) {
this.verifyGoToDefinitionPlain(arg0, endMarkerNames);
this.verifyGoToXPlain(arg0, endMarkerNames, getDefs);
}
else if (arg0 instanceof Array) {
const pairs: [string | string[], string | string[]][] = arg0;
for (const [start, end] of pairs) {
this.verifyGoToDefinitionPlain(start, end);
this.verifyGoToXPlain(start, end, getDefs);
}
}
else {
const obj: { [startMarkerName: string]: string | string[] } = arg0;
for (const startMarkerName in obj) {
if (ts.hasProperty(obj, startMarkerName)) {
this.verifyGoToDefinitionPlain(startMarkerName, obj[startMarkerName]);
this.verifyGoToXPlain(startMarkerName, obj[startMarkerName], getDefs);
}
}
}
}
private verifyGoToDefinitionPlain(startMarkerNames: string | string[], endMarkerNames: string | string[]) {
private verifyGoToXPlain(startMarkerNames: string | string[], endMarkerNames: string | string[], getDefs: () => ts.DefinitionInfo[] | undefined) {
if (startMarkerNames instanceof Array) {
for (const start of startMarkerNames) {
this.verifyGoToDefinitionSingle(start, endMarkerNames);
this.verifyGoToXSingle(start, endMarkerNames, getDefs);
}
}
else {
this.verifyGoToDefinitionSingle(startMarkerNames, endMarkerNames);
this.verifyGoToXSingle(startMarkerNames, endMarkerNames, getDefs);
}
}
public verifyGoToDefinitionForMarkers(markerNames: string[]) {
for (const markerName of markerNames) {
this.verifyGoToDefinitionSingle(`${markerName}Reference`, `${markerName}Definition`);
this.verifyGoToXSingle(`${markerName}Reference`, `${markerName}Definition`, () => this.getGoToDefinition());
}
}
private verifyGoToDefinitionSingle(startMarkerName: string, endMarkerNames: string | string[]) {
private verifyGoToXSingle(startMarkerName: string, endMarkerNames: string | string[], getDefs: () => ts.DefinitionInfo[] | undefined) {
this.goToMarker(startMarkerName);
this.verifyGoToDefinitionWorker(endMarkerNames instanceof Array ? endMarkerNames : [endMarkerNames]);
this.verifyGoToXWorker(endMarkerNames instanceof Array ? endMarkerNames : [endMarkerNames], getDefs);
}
private verifyGoToDefinitionWorker(endMarkers: string[]) {
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition) || [];
private verifyGoToXWorker(endMarkers: string[], getDefs: () => ts.DefinitionInfo[] | undefined) {
const definitions = getDefs() || [];
if (endMarkers.length !== definitions.length) {
this.raiseError(`goToDefinitions failed - expected to find ${endMarkers.length} definitions but got ${definitions.length}`);
@@ -706,6 +722,27 @@ namespace FourSlash {
}
}
public verifyCompletionsAt(markerName: string, expected: string[]) {
this.goToMarker(markerName);
const actualCompletions = this.getCompletionListAtCaret();
if (!actualCompletions) {
this.raiseError(`No completions at position '${this.currentCaretPosition}'.`);
}
const actual = actualCompletions.entries;
if (actual.length !== expected.length) {
this.raiseError(`Expected ${expected.length} completions, got ${actual.map(a => a.name)}.`);
}
ts.zipWith(actual, expected, (completion, expectedCompletion, index) => {
if (completion.name !== expectedCompletion) {
this.raiseError(`Expected completion at index ${index} to be ${expectedCompletion}, got ${completion.name}`);
}
});
}
public verifyCompletionListContains(symbol: string, text?: string, documentation?: string, kind?: string, spanIndex?: number) {
const completions = this.getCompletionListAtCaret();
if (completions) {
@@ -1983,7 +2020,7 @@ namespace FourSlash {
* Compares expected text to the text that would be in the sole range
* (ie: [|...|]) in the file after applying the codefix sole codefix
* in the source file.
*
*
* Because codefixes are only applied on the working file, it is unsafe
* to apply this more than once (consider a refactoring across files).
*/
@@ -3038,10 +3075,6 @@ namespace FourSlashInterface {
this.state.goToEOF();
}
public type(definitionIndex = 0) {
this.state.goToTypeDefinition(definitionIndex);
}
public implementation() {
this.state.goToImplementation();
}
@@ -3153,6 +3186,10 @@ namespace FourSlashInterface {
super(state);
}
public completionsAt(markerName: string, completions: string[]) {
this.state.verifyCompletionsAt(markerName, completions);
}
public quickInfoIs(expectedText: string, expectedDocumentation?: string) {
this.state.verifyQuickInfoString(expectedText, expectedDocumentation);
}
@@ -3209,6 +3246,13 @@ namespace FourSlashInterface {
this.state.verifyGoToDefinition(arg0, endMarkerName);
}
public goToType(startMarkerName: string | string[], endMarkerName: string | string[]): void;
public goToType(startsAndEnds: [string | string[], string | string[]][]): void;
public goToType(startsAndEnds: { [startMarkerName: string]: string | string[] }): void;
public goToType(arg0: any, endMarkerName?: string | string[]) {
this.state.verifyGoToType(arg0, endMarkerName);
}
public goToDefinitionForMarkers(...markerNames: string[]) {
this.state.verifyGoToDefinitionForMarkers(markerNames);
}
+3 -10
View File
@@ -1,19 +1,12 @@
{
"extends": "../tsconfig-base",
"compilerOptions": {
"noImplicitAny": true,
"pretty": true,
"removeComments": false,
"preserveConstEnums": true,
"outFile": "../../built/local/run.js",
"sourceMap": true,
"declaration": false,
"stripInternal": true,
"types": [
"node", "mocha", "chai"
],
"target": "es5",
"noUnusedLocals": true,
"noUnusedParameters": true
]
},
"files": [
"../compiler/core.ts",
@@ -85,7 +78,7 @@
"../services/codefixes/importFixes.ts",
"../services/codefixes/unusedIdentifierFixes.ts",
"../services/harness.ts",
"sourceMapRecorder.ts",
"harnessLanguageService.ts",
"fourslash.ts",
+56 -1
View File
@@ -1620,7 +1620,7 @@ namespace ts.projectSystem {
const configureHostRequest = makeSessionRequest<protocol.ConfigureRequestArguments>(CommandNames.Configure, { extraFileExtensions });
session.executeCommand(configureHostRequest).response;
// HTML file still not included in the project as it is closed
// HTML file still not included in the project as it is closed
checkNumberOfProjects(projectService, { configuredProjects: 1 });
checkProjectActualFiles(projectService.configuredProjects[0], [file1.path]);
@@ -3051,4 +3051,59 @@ namespace ts.projectSystem {
service.checkNumberOfProjects({ externalProjects: 1 });
});
});
describe("maxNodeModuleJsDepth for inferred projects", () => {
it("should be set to 2 if the project has js root files", () => {
const file1: FileOrFolder = {
path: "/a/b/file1.js",
content: `var t = require("test"); t.`
};
const moduleFile: FileOrFolder = {
path: "/a/b/node_modules/test/index.js",
content: `var v = 10; module.exports = v;`
};
const host = createServerHost([file1, moduleFile]);
const projectService = createProjectService(host);
projectService.openClientFile(file1.path);
let project = projectService.inferredProjects[0];
let options = project.getCompilerOptions();
assert.isTrue(options.maxNodeModuleJsDepth === 2);
// Assert the option sticks
projectService.setCompilerOptionsForInferredProjects({ target: ScriptTarget.ES2016 });
project = projectService.inferredProjects[0];
options = project.getCompilerOptions();
assert.isTrue(options.maxNodeModuleJsDepth === 2);
});
it("should return to normal state when all js root files are removed from project", () => {
const file1 = {
path: "/a/file1.ts",
content: "let x =1;"
};
const file2 = {
path: "/a/file2.js",
content: "let x =1;"
};
const host = createServerHost([file1, file2, libFile]);
const projectService = createProjectService(host, { useSingleInferredProject: true });
projectService.openClientFile(file1.path);
checkNumberOfInferredProjects(projectService, 1);
let project = projectService.inferredProjects[0];
assert.isUndefined(project.getCompilerOptions().maxNodeModuleJsDepth);
projectService.openClientFile(file2.path);
project = projectService.inferredProjects[0];
assert.isTrue(project.getCompilerOptions().maxNodeModuleJsDepth === 2);
projectService.closeClientFile(file2.path);
project = projectService.inferredProjects[0];
assert.isUndefined(project.getCompilerOptions().maxNodeModuleJsDepth);
});
});
}
+2 -10
View File
@@ -1,19 +1,11 @@
{
"extends": "../../tsconfig-base",
"compilerOptions": {
"noImplicitAny": true,
"noImplicitThis": true,
"removeComments": true,
"preserveConstEnums": true,
"pretty": true,
"module": "commonjs",
"sourceMap": true,
"stripInternal": true,
"types": [
"node"
],
"target": "es5",
"noUnusedLocals": true,
"noUnusedParameters": true
]
},
"files": [
"cancellationToken.ts"
+3
View File
@@ -293,6 +293,7 @@ namespace ts.server {
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames, host.getCurrentDirectory());
}
/* @internal */
getChangedFiles_TestOnly() {
return this.changedFiles;
}
@@ -1274,6 +1275,7 @@ namespace ts.server {
}
}
/* @internal */
synchronizeProjectList(knownProjects: protocol.ProjectVersionInfo[]): ProjectFilesWithTSDiagnostics[] {
const files: ProjectFilesWithTSDiagnostics[] = [];
this.collectChanges(knownProjects, this.externalProjects, files);
@@ -1282,6 +1284,7 @@ namespace ts.server {
return files;
}
/* @internal */
applyChangesInOpenFiles(openFiles: protocol.ExternalFile[], changedFiles: protocol.ChangedOpenFile[], closedFiles: string[]): void {
const recordChangedFiles = changedFiles && !openFiles && !closedFiles;
if (openFiles) {
+50 -9
View File
@@ -58,6 +58,7 @@ namespace ts.server {
return counts.ts === 0 && counts.tsx === 0;
}
/* @internal */
export interface ProjectFilesWithTSDiagnostics extends protocol.ProjectFiles {
projectErrors: Diagnostic[];
}
@@ -395,7 +396,9 @@ namespace ts.server {
}
removeFile(info: ScriptInfo, detachFromProject = true) {
this.removeRootFileIfNecessary(info);
if (this.isRoot(info)) {
this.removeRoot(info);
}
this.lsHost.notifyFileRemoved(info);
this.cachedUnresolvedImportsPerFile.remove(info.path);
@@ -566,9 +569,6 @@ namespace ts.server {
setCompilerOptions(compilerOptions: CompilerOptions) {
if (compilerOptions) {
if (this.projectKind === ProjectKind.Inferred) {
compilerOptions.allowJs = true;
}
compilerOptions.allowNonTsExtensions = true;
if (changesAffectModuleResolution(this.compilerOptions, compilerOptions)) {
// reset cached unresolved imports if changes in compiler options affected module resolution
@@ -593,6 +593,7 @@ namespace ts.server {
return false;
}
/* @internal */
getChangesSinceVersion(lastKnownVersion?: number): ProjectFilesWithTSDiagnostics {
this.updateGraph();
@@ -696,11 +697,9 @@ namespace ts.server {
}
// remove a root file from project
private removeRootFileIfNecessary(info: ScriptInfo): void {
if (this.isRoot(info)) {
remove(this.rootFiles, info);
this.rootFilesMap.remove(info.path);
}
protected removeRoot(info: ScriptInfo): void {
remove(this.rootFiles, info);
this.rootFilesMap.remove(info.path);
}
}
@@ -715,6 +714,32 @@ namespace ts.server {
}
})();
private _isJsInferredProject = false;
toggleJsInferredProject(isJsInferredProject: boolean) {
if (isJsInferredProject !== this._isJsInferredProject) {
this._isJsInferredProject = isJsInferredProject;
this.setCompilerOptions();
}
}
setCompilerOptions(options?: CompilerOptions) {
// Avoid manipulating the given options directly
const newOptions = options ? clone(options) : this.getCompilerOptions();
if (!newOptions) {
return;
}
if (this._isJsInferredProject && typeof newOptions.maxNodeModuleJsDepth !== "number") {
newOptions.maxNodeModuleJsDepth = 2;
}
else if (!this._isJsInferredProject) {
newOptions.maxNodeModuleJsDepth = undefined;
}
newOptions.allowJs = true;
super.setCompilerOptions(newOptions);
}
// Used to keep track of what directories are watched for this project
directoriesWatchedForTsconfig: string[] = [];
@@ -729,6 +754,22 @@ namespace ts.server {
/*compileOnSaveEnabled*/ false);
}
addRoot(info: ScriptInfo) {
if (!this._isJsInferredProject && info.isJavaScript()) {
this.toggleJsInferredProject(/*isJsInferredProject*/ true);
}
super.addRoot(info);
}
removeRoot(info: ScriptInfo) {
if (this._isJsInferredProject && info.isJavaScript()) {
if (filter(this.getRootScriptInfos(), info => info.isJavaScript()).length === 0) {
this.toggleJsInferredProject(/*isJsInferredProject*/ false);
}
}
super.removeRoot(info);
}
getProjectRootPath() {
// Single inferred project does not have a project root.
if (this.projectService.useSingleInferredProject) {
+4
View File
@@ -355,5 +355,9 @@ namespace ts.server {
positionToLineOffset(position: number): ILineInfo {
return this.textStorage.positionToLineOffset(position);
}
public isJavaScript() {
return this.scriptKind === ScriptKind.JS || this.scriptKind === ScriptKind.JSX;
}
}
}
+24
View File
@@ -88,50 +88,65 @@ namespace ts.server {
export namespace CommandNames {
export const Brace: protocol.CommandTypes.Brace = "brace";
/* @internal */
export const BraceFull: protocol.CommandTypes.BraceFull = "brace-full";
export const BraceCompletion: protocol.CommandTypes.BraceCompletion = "braceCompletion";
export const Change: protocol.CommandTypes.Change = "change";
export const Close: protocol.CommandTypes.Close = "close";
export const Completions: protocol.CommandTypes.Completions = "completions";
/* @internal */
export const CompletionsFull: protocol.CommandTypes.CompletionsFull = "completions-full";
export const CompletionDetails: protocol.CommandTypes.CompletionDetails = "completionEntryDetails";
export const CompileOnSaveAffectedFileList: protocol.CommandTypes.CompileOnSaveAffectedFileList = "compileOnSaveAffectedFileList";
export const CompileOnSaveEmitFile: protocol.CommandTypes.CompileOnSaveEmitFile = "compileOnSaveEmitFile";
export const Configure: protocol.CommandTypes.Configure = "configure";
export const Definition: protocol.CommandTypes.Definition = "definition";
/* @internal */
export const DefinitionFull: protocol.CommandTypes.DefinitionFull = "definition-full";
export const Exit: protocol.CommandTypes.Exit = "exit";
export const Format: protocol.CommandTypes.Format = "format";
export const Formatonkey: protocol.CommandTypes.Formatonkey = "formatonkey";
/* @internal */
export const FormatFull: protocol.CommandTypes.FormatFull = "format-full";
/* @internal */
export const FormatonkeyFull: protocol.CommandTypes.FormatonkeyFull = "formatonkey-full";
/* @internal */
export const FormatRangeFull: protocol.CommandTypes.FormatRangeFull = "formatRange-full";
export const Geterr: protocol.CommandTypes.Geterr = "geterr";
export const GeterrForProject: protocol.CommandTypes.GeterrForProject = "geterrForProject";
export const Implementation: protocol.CommandTypes.Implementation = "implementation";
/* @internal */
export const ImplementationFull: protocol.CommandTypes.ImplementationFull = "implementation-full";
export const SemanticDiagnosticsSync: protocol.CommandTypes.SemanticDiagnosticsSync = "semanticDiagnosticsSync";
export const SyntacticDiagnosticsSync: protocol.CommandTypes.SyntacticDiagnosticsSync = "syntacticDiagnosticsSync";
export const NavBar: protocol.CommandTypes.NavBar = "navbar";
/* @internal */
export const NavBarFull: protocol.CommandTypes.NavBarFull = "navbar-full";
export const NavTree: protocol.CommandTypes.NavTree = "navtree";
export const NavTreeFull: protocol.CommandTypes.NavTreeFull = "navtree-full";
export const Navto: protocol.CommandTypes.Navto = "navto";
/* @internal */
export const NavtoFull: protocol.CommandTypes.NavtoFull = "navto-full";
export const Occurrences: protocol.CommandTypes.Occurrences = "occurrences";
export const DocumentHighlights: protocol.CommandTypes.DocumentHighlights = "documentHighlights";
/* @internal */
export const DocumentHighlightsFull: protocol.CommandTypes.DocumentHighlightsFull = "documentHighlights-full";
export const Open: protocol.CommandTypes.Open = "open";
export const Quickinfo: protocol.CommandTypes.Quickinfo = "quickinfo";
/* @internal */
export const QuickinfoFull: protocol.CommandTypes.QuickinfoFull = "quickinfo-full";
export const References: protocol.CommandTypes.References = "references";
/* @internal */
export const ReferencesFull: protocol.CommandTypes.ReferencesFull = "references-full";
export const Reload: protocol.CommandTypes.Reload = "reload";
export const Rename: protocol.CommandTypes.Rename = "rename";
/* @internal */
export const RenameInfoFull: protocol.CommandTypes.RenameInfoFull = "rename-full";
/* @internal */
export const RenameLocationsFull: protocol.CommandTypes.RenameLocationsFull = "renameLocations-full";
export const Saveto: protocol.CommandTypes.Saveto = "saveto";
export const SignatureHelp: protocol.CommandTypes.SignatureHelp = "signatureHelp";
/* @internal */
export const SignatureHelpFull: protocol.CommandTypes.SignatureHelpFull = "signatureHelp-full";
export const TypeDefinition: protocol.CommandTypes.TypeDefinition = "typeDefinition";
export const ProjectInfo: protocol.CommandTypes.ProjectInfo = "projectInfo";
@@ -140,19 +155,28 @@ namespace ts.server {
export const OpenExternalProject: protocol.CommandTypes.OpenExternalProject = "openExternalProject";
export const OpenExternalProjects: protocol.CommandTypes.OpenExternalProjects = "openExternalProjects";
export const CloseExternalProject: protocol.CommandTypes.CloseExternalProject = "closeExternalProject";
/* @internal */
export const SynchronizeProjectList: protocol.CommandTypes.SynchronizeProjectList = "synchronizeProjectList";
/* @internal */
export const ApplyChangedToOpenFiles: protocol.CommandTypes.ApplyChangedToOpenFiles = "applyChangedToOpenFiles";
/* @internal */
export const EncodedSemanticClassificationsFull: protocol.CommandTypes.EncodedSemanticClassificationsFull = "encodedSemanticClassifications-full";
/* @internal */
export const Cleanup: protocol.CommandTypes.Cleanup = "cleanup";
/* @internal */
export const OutliningSpans: protocol.CommandTypes.OutliningSpans = "outliningSpans";
export const TodoComments: protocol.CommandTypes.TodoComments = "todoComments";
export const Indentation: protocol.CommandTypes.Indentation = "indentation";
export const DocCommentTemplate: protocol.CommandTypes.DocCommentTemplate = "docCommentTemplate";
/* @internal */
export const CompilerOptionsDiagnosticsFull: protocol.CommandTypes.CompilerOptionsDiagnosticsFull = "compilerOptionsDiagnostics-full";
/* @internal */
export const NameOrDottedNameSpan: protocol.CommandTypes.NameOrDottedNameSpan = "nameOrDottedNameSpan";
/* @internal */
export const BreakpointStatement: protocol.CommandTypes.BreakpointStatement = "breakpointStatement";
export const CompilerOptionsForInferredProjects: protocol.CommandTypes.CompilerOptionsForInferredProjects = "compilerOptionsForInferredProjects";
export const GetCodeFixes: protocol.CommandTypes.GetCodeFixes = "getCodeFixes";
/* @internal */
export const GetCodeFixesFull: protocol.CommandTypes.GetCodeFixesFull = "getCodeFixes-full";
export const GetSupportedCodeFixes: protocol.CommandTypes.GetSupportedCodeFixes = "getSupportedCodeFixes";
}
+1 -1
View File
@@ -1,4 +1,4 @@
/// <reference path="types.d.ts" />
/// <reference path="types.ts" />
namespace ts.server {
export const ActionSet: ActionSet = "action::set";
+2 -10
View File
@@ -1,19 +1,11 @@
{
"extends": "../tsconfig-base",
"compilerOptions": {
"noImplicitAny": true,
"noImplicitThis": true,
"removeComments": true,
"preserveConstEnums": true,
"pretty": true,
"outFile": "../../built/local/tsserver.js",
"sourceMap": true,
"stripInternal": true,
"types": [
"node"
],
"target": "es5",
"noUnusedLocals": true,
"noUnusedParameters": true
]
},
"files": [
"../services/shims.ts",
+16 -15
View File
@@ -1,29 +1,30 @@
{
"compilerOptions": {
"noImplicitAny": true,
"removeComments": true,
"noImplicitThis": true,
"preserveConstEnums": true,
"pretty": true,
"outFile": "../../built/local/tsserverlibrary.js",
"sourceMap": true,
"stripInternal": true,
"declaration": true,
"types": [],
"target": "es5",
"noUnusedLocals": true,
"noUnusedParameters": true
"noUnusedParameters": true,
"declaration": true
},
"files": [
"../services/shims.ts",
"../services/utilities.ts",
"shared.ts",
"utilities.ts",
"scriptVersionCache.ts",
"scriptInfo.ts",
"lshost.ts",
"typingsCache.ts",
"project.ts",
"editorServices.ts",
"protocol.d.ts",
"session.ts"
"lsHost.ts",
"project.ts",
"protocol.ts",
"scriptInfo.ts",
"scriptVersionCache.ts",
"session.ts",
"shared.ts",
"types.ts",
"typingsCache.ts",
"utilities.ts",
"../services/shims.ts",
"../services/utilities.ts"
]
}
@@ -82,6 +82,7 @@ declare namespace ts.server {
readonly installSuccess: boolean;
}
/* @internal */
export interface InstallTypingHost extends JsTyping.TypingResolutionHost {
writeFile(path: string, content: string): void;
createDirectory(path: string): void;
+3 -11
View File
@@ -1,22 +1,14 @@
{
"extends": "../../tsconfig-base",
"compilerOptions": {
"noImplicitAny": true,
"noImplicitThis": true,
"removeComments": true,
"preserveConstEnums": true,
"pretty": true,
"outFile": "../../../built/local/typingsInstaller.js",
"sourceMap": true,
"stripInternal": true,
"types": [
"node"
],
"target": "es5",
"noUnusedLocals": true,
"noUnusedParameters": true
]
},
"files": [
"../types.d.ts",
"../types.ts",
"../shared.ts",
"typingsInstaller.ts",
"nodeTypingsInstaller.ts"
@@ -1,7 +1,7 @@
/// <reference path="../../compiler/core.ts" />
/// <reference path="../../compiler/moduleNameResolver.ts" />
/// <reference path="../../services/jsTyping.ts"/>
/// <reference path="../types.d.ts"/>
/// <reference path="../types.ts"/>
/// <reference path="../shared.ts"/>
namespace ts.server.typingsInstaller {
+1 -1
View File
@@ -1,4 +1,4 @@
/// <reference path="types.d.ts" />
/// <reference path="types.ts" />
/// <reference path="shared.ts" />
namespace ts.server {
+4 -3
View File
@@ -420,10 +420,10 @@ namespace ts.codefix {
const options = context.program.getCompilerOptions();
return tryGetModuleNameFromAmbientModule() ||
tryGetModuleNameFromBaseUrl() ||
tryGetModuleNameFromRootDirs() ||
tryGetModuleNameFromTypeRoots() ||
tryGetModuleNameAsNodeModule() ||
tryGetModuleNameFromBaseUrl() ||
tryGetModuleNameFromRootDirs() ||
removeFileExtension(getRelativePath(moduleFileName, sourceDirectory));
function tryGetModuleNameFromAmbientModule(): string {
@@ -443,6 +443,7 @@ namespace ts.codefix {
return undefined;
}
const relativeNameWithIndex = removeFileExtension(relativeName);
relativeName = removeExtensionAndIndexPostFix(relativeName);
if (options.paths) {
@@ -462,7 +463,7 @@ namespace ts.codefix {
return key.replace("\*", matchedStar);
}
}
else if (pattern === relativeName) {
else if (pattern === relativeName || pattern === relativeNameWithIndex) {
return key;
}
}
@@ -146,7 +146,7 @@ namespace ts.codefix {
function createCodeFix(newText: string, start: number, length: number): CodeAction[] {
return [{
description: getLocaleSpecificMessage(Diagnostics.Remove_unused_identifiers),
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Remove_declaration_for_Colon_0), { 0: token.getText() }),
changes: [{
fileName: sourceFile.fileName,
textChanges: [{ newText, span: { start, length } }]
+24 -26
View File
@@ -1,8 +1,6 @@
/// <reference path='../compiler/utilities.ts' />
/* @internal */
namespace ts.Completions {
export function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo {
export function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo | undefined {
if (isInReferenceComment(sourceFile, position)) {
return getTripleSlashReferenceCompletion(sourceFile, position);
}
@@ -134,7 +132,7 @@ namespace ts.Completions {
return uniqueNames;
}
function getStringLiteralCompletionEntries(sourceFile: SourceFile, position: number) {
function getStringLiteralCompletionEntries(sourceFile: SourceFile, position: number): CompletionInfo | undefined {
const node = findPrecedingToken(position, sourceFile);
if (!node || node.kind !== SyntaxKind.StringLiteral) {
return undefined;
@@ -174,7 +172,7 @@ namespace ts.Completions {
return getStringLiteralCompletionEntriesFromModuleNames(<StringLiteral>node);
}
else {
const argumentInfo = SignatureHelp.getContainingArgumentInfo(node, position, sourceFile);
const argumentInfo = SignatureHelp.getImmediatelyContainingArgumentInfo(node, position, sourceFile);
if (argumentInfo) {
// Get string literal completions from specialized signatures of the target
// i.e. declare function f(a: 'A');
@@ -188,7 +186,7 @@ namespace ts.Completions {
}
}
function getStringLiteralCompletionEntriesFromPropertyAssignment(element: ObjectLiteralElement) {
function getStringLiteralCompletionEntriesFromPropertyAssignment(element: ObjectLiteralElement): CompletionInfo | undefined {
const type = typeChecker.getContextualType((<ObjectLiteralExpression>element.parent));
const entries: CompletionEntry[] = [];
if (type) {
@@ -199,7 +197,7 @@ namespace ts.Completions {
}
}
function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo) {
function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo): CompletionInfo | undefined {
const candidates: Signature[] = [];
const entries: CompletionEntry[] = [];
@@ -219,7 +217,7 @@ namespace ts.Completions {
return undefined;
}
function getStringLiteralCompletionEntriesFromElementAccess(node: ElementAccessExpression) {
function getStringLiteralCompletionEntriesFromElementAccess(node: ElementAccessExpression): CompletionInfo | undefined {
const type = typeChecker.getTypeAtLocation(node.expression);
const entries: CompletionEntry[] = [];
if (type) {
@@ -231,7 +229,7 @@ namespace ts.Completions {
return undefined;
}
function getStringLiteralCompletionEntriesFromContextualType(node: StringLiteral) {
function getStringLiteralCompletionEntriesFromContextualType(node: StringLiteral): CompletionInfo | undefined {
const type = typeChecker.getContextualType(node);
if (type) {
const entries: CompletionEntry[] = [];
@@ -243,7 +241,7 @@ namespace ts.Completions {
return undefined;
}
function addStringLiteralCompletionsFromType(type: Type, result: CompletionEntry[]): void {
function addStringLiteralCompletionsFromType(type: Type, result: Push<CompletionEntry>): void {
if (type && type.flags & TypeFlags.TypeParameter) {
type = typeChecker.getApparentType(type);
}
@@ -251,18 +249,18 @@ namespace ts.Completions {
return;
}
if (type.flags & TypeFlags.Union) {
forEach((<UnionType>type).types, t => addStringLiteralCompletionsFromType(t, result));
}
else {
if (type.flags & TypeFlags.StringLiteral) {
result.push({
name: (<LiteralType>type).text,
kindModifiers: ScriptElementKindModifier.none,
kind: ScriptElementKind.variableElement,
sortText: "0"
});
for (const t of (<UnionType>type).types) {
addStringLiteralCompletionsFromType(t, result);
}
}
else if (type.flags & TypeFlags.StringLiteral) {
result.push({
name: (<LiteralType>type).text,
kindModifiers: ScriptElementKindModifier.none,
kind: ScriptElementKind.variableElement,
sortText: "0"
});
}
}
function getStringLiteralCompletionEntriesFromModuleNames(node: StringLiteral): CompletionInfo {
@@ -1320,14 +1318,14 @@ namespace ts.Completions {
isMemberCompletion = true;
isNewIdentifierLocation = false;
let exports: Symbol[];
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier);
if (moduleSpecifierSymbol) {
exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol);
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier);
if (!moduleSpecifierSymbol) {
symbols = emptyArray;
return true;
}
symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : emptyArray;
const exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol);
symbols = filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements);
return true;
}
+5 -6
View File
@@ -325,7 +325,7 @@ namespace ts.FindAllReferences {
fileName: targetLabel.getSourceFile().fileName,
kind: ScriptElementKind.label,
name: labelName,
textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()),
textSpan: createTextSpanFromNode(targetLabel, sourceFile),
displayParts: [displayPart(labelName, SymbolDisplayPartKind.text)]
};
@@ -502,9 +502,8 @@ namespace ts.FindAllReferences {
const result: Node[] = [];
for (const decl of classSymbol.members["__constructor"].declarations) {
Debug.assert(decl.kind === SyntaxKind.Constructor);
const ctrKeyword = decl.getChildAt(0);
Debug.assert(ctrKeyword.kind === SyntaxKind.ConstructorKeyword);
const ctrKeyword = ts.findChildOfKind(decl, ts.SyntaxKind.ConstructorKeyword, sourceFile)!
Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword);
result.push(ctrKeyword);
}
@@ -871,7 +870,7 @@ namespace ts.FindAllReferences {
fileName: node.getSourceFile().fileName,
kind: ScriptElementKind.variableElement,
name: "this",
textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()),
textSpan: createTextSpanFromNode(node),
displayParts
},
references: references
@@ -942,7 +941,7 @@ namespace ts.FindAllReferences {
fileName: node.getSourceFile().fileName,
kind: ScriptElementKind.variableElement,
name: type.text,
textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()),
textSpan: createTextSpanFromNode(node),
displayParts: [displayPart(getTextOfNode(node), SymbolDisplayPartKind.stringLiteral)]
},
references: references
+24 -21
View File
@@ -15,10 +15,8 @@ namespace ts.GoToDefinition {
const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
if (typeReferenceDirective) {
const referenceFile = program.getResolvedTypeReferenceDirectives()[typeReferenceDirective.fileName];
if (referenceFile && referenceFile.resolvedFileName) {
return [getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)];
}
return undefined;
return referenceFile && referenceFile.resolvedFileName &&
[getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)];
}
const node = getTouchingPropertyName(sourceFile, position);
@@ -30,7 +28,7 @@ namespace ts.GoToDefinition {
if (isJumpStatementTarget(node)) {
const labelName = (<Identifier>node).text;
const label = getTargetLabel((<BreakOrContinueStatement>node.parent), (<Identifier>node).text);
return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined;
return label ? [createDefinitionInfoFromName(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined;
}
const typeChecker = program.getTypeChecker();
@@ -171,33 +169,38 @@ namespace ts.GoToDefinition {
function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) {
const declarations: Declaration[] = [];
let definition: Declaration;
let definition: Declaration | undefined;
forEach(signatureDeclarations, d => {
if ((selectConstructors && d.kind === SyntaxKind.Constructor) ||
(!selectConstructors && (d.kind === SyntaxKind.FunctionDeclaration || d.kind === SyntaxKind.MethodDeclaration || d.kind === SyntaxKind.MethodSignature))) {
for (const d of signatureDeclarations) {
if (selectConstructors ? d.kind === SyntaxKind.Constructor : isSignatureDeclaration(d)) {
declarations.push(d);
if ((<FunctionLikeDeclaration>d).body) definition = d;
}
});
if (definition) {
result.push(createDefinitionInfo(definition, symbolKind, symbolName, containerName));
return true;
}
else if (declarations.length) {
result.push(createDefinitionInfo(lastOrUndefined(declarations), symbolKind, symbolName, containerName));
return true;
}
if (declarations.length) {
result.push(createDefinitionInfo(definition || lastOrUndefined(declarations), symbolKind, symbolName, containerName));
return true;
}
return false;
}
}
function createDefinitionInfo(node: Node, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo {
function isSignatureDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature
}
/** Creates a DefinitionInfo from a Declaration, using the declaration's name if possible. */
function createDefinitionInfo(node: Declaration, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo {
return createDefinitionInfoFromName(node.name || node, symbolKind, symbolName, containerName);
}
/** Creates a DefinitionInfo directly from the name of a declaration. */
function createDefinitionInfoFromName(name: Node, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo {
const sourceFile = name.getSourceFile();
return {
fileName: node.getSourceFile().fileName,
textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()),
fileName: sourceFile.fileName,
textSpan: createTextSpanFromNode(name, sourceFile),
kind: symbolKind,
name: symbolName,
containerKind: undefined,
+1 -1
View File
@@ -199,7 +199,7 @@ namespace ts.NavigateTo {
matchKind: PatternMatchKind[rawItem.matchKind],
isCaseSensitive: rawItem.isCaseSensitive,
fileName: rawItem.fileName,
textSpan: createTextSpanFromBounds(declaration.getStart(), declaration.getEnd()),
textSpan: createTextSpanFromNode(declaration),
// TODO(jfreeman): What should be the containerName when the container has a computed name?
containerName: container && container.name ? (<Identifier>container.name).text : "",
containerKind: container && container.name ? getNodeKind(container) : ""
+15 -8
View File
@@ -514,7 +514,7 @@ namespace ts.NavigationBar {
return {
text: getItemName(n.node),
kind: getNodeKind(n.node),
kindModifiers: getNodeModifiers(n.node),
kindModifiers: getModifiers(n.node),
spans: getSpans(n),
childItems: map(n.children, convertToTree)
};
@@ -524,7 +524,7 @@ namespace ts.NavigationBar {
return {
text: getItemName(n.node),
kind: getNodeKind(n.node),
kindModifiers: getNodeModifiers(n.node),
kindModifiers: getModifiers(n.node),
spans: getSpans(n),
childItems: map(n.children, convertToChildItem) || emptyChildItemArray,
indent: n.indent,
@@ -591,7 +591,14 @@ namespace ts.NavigationBar {
function getNodeSpan(node: Node): TextSpan {
return node.kind === SyntaxKind.SourceFile
? createTextSpanFromBounds(node.getFullStart(), node.getEnd())
: createTextSpanFromBounds(node.getStart(curSourceFile), node.getEnd());
: createTextSpanFromNode(node, curSourceFile);
}
function getModifiers(node: ts.Node): string {
if (node.parent && node.parent.kind === SyntaxKind.VariableDeclaration) {
node = node.parent;
}
return getNodeModifiers(node);
}
function getFunctionOrClassName(node: FunctionExpression | FunctionDeclaration | ArrowFunction | ClassLikeDeclaration): string {
@@ -626,15 +633,15 @@ namespace ts.NavigationBar {
/**
* Matches all whitespace characters in a string. Eg:
*
*
* "app.
*
*
* onactivated"
*
*
* matches because of the newline, whereas
*
*
* "app.onactivated"
*
*
* does not match.
*/
const whiteSpaceRegex = /\s+/g;
+2 -2
View File
@@ -8,7 +8,7 @@ namespace ts.OutliningElementsCollector {
if (hintSpanNode && startElement && endElement) {
const span: OutliningSpan = {
textSpan: createTextSpanFromBounds(startElement.pos, endElement.end),
hintSpan: createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end),
hintSpan: createTextSpanFromNode(hintSpanNode, sourceFile),
bannerText: collapseText,
autoCollapse: autoCollapse
};
@@ -135,7 +135,7 @@ namespace ts.OutliningElementsCollector {
// Block was a standalone block. In this case we want to only collapse
// the span of the block, independent of any parent span.
const span = createTextSpanFromBounds(n.getStart(), n.end);
const span = createTextSpanFromNode(n);
elements.push({
textSpan: span,
hintSpan: span,
+1 -1
View File
@@ -260,7 +260,7 @@ namespace ts.SignatureHelp {
* Returns relevant information for the argument list and the current argument if we are
* in the argument of an invocation; returns undefined otherwise.
*/
function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo {
export function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo {
if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) {
const callExpression = <CallExpression>node.parent;
// There are 3 cases to handle:
+1 -10
View File
@@ -1,18 +1,9 @@
{
"extends": "../tsconfig-base",
"compilerOptions": {
"noImplicitAny": true,
"noImplicitThis": true,
"removeComments": false,
"preserveConstEnums": true,
"pretty": true,
"outFile": "../../built/local/typescriptServices.js",
"sourceMap": true,
"stripInternal": true,
"noResolve": false,
"declaration": true,
"target": "es5",
"noUnusedLocals": true,
"noUnusedParameters": true,
"types": []
},
"files": [
+5 -1
View File
@@ -600,7 +600,7 @@ namespace ts {
return !!findChildOfKind(n, kind, sourceFile);
}
export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node {
export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node | undefined {
return forEach(n.getChildren(sourceFile), c => c.kind === kind && c);
}
@@ -1112,6 +1112,10 @@ namespace ts {
return !tripleSlashDirectivePrefixRegex.test(commentText);
}
}
export function createTextSpanFromNode(node: Node, sourceFile?: SourceFile): TextSpan {
return createTextSpanFromBounds(node.getStart(sourceFile), node.getEnd());
}
}
// Display-part writer helpers
+14
View File
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"noEmitOnError": true,
"noImplicitAny": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"pretty": true,
"preserveConstEnums": true,
"stripInternal": true,
"sourceMap": true,
"target": "es5"
}
}