mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge remote-tracking branch 'origin/master' into disallowDefaultExportDeclMerging
This commit is contained in:
+14
-8
@@ -518,15 +518,21 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
|
||||
|
||||
let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
|
||||
if (node.symbol.constEnumOnlyModule === undefined) {
|
||||
// non-merged case - use the current state
|
||||
node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
|
||||
if (node.symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum)) {
|
||||
// if module was already merged with some function, class or non-const enum
|
||||
// treat is a non-const-enum-only
|
||||
node.symbol.constEnumOnlyModule = false;
|
||||
}
|
||||
else {
|
||||
// merged case: module is const enum only if all its pieces are non-instantiated or const enum
|
||||
node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly;
|
||||
let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
|
||||
if (node.symbol.constEnumOnlyModule === undefined) {
|
||||
// non-merged case - use the current state
|
||||
node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
|
||||
}
|
||||
else {
|
||||
// merged case: module is const enum only if all its pieces are non-instantiated or const enum
|
||||
node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1056,4 +1062,4 @@ namespace ts {
|
||||
: declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+396
-192
@@ -59,7 +59,10 @@ namespace ts {
|
||||
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
|
||||
getDiagnostics,
|
||||
getGlobalDiagnostics,
|
||||
getTypeOfSymbolAtLocation,
|
||||
|
||||
// The language service will always care about the narrowed type of a symbol, because that is
|
||||
// the type the language says the symbol should have.
|
||||
getTypeOfSymbolAtLocation: getNarrowedTypeOfSymbol,
|
||||
getDeclaredTypeOfSymbol,
|
||||
getPropertiesOfType,
|
||||
getPropertyOfType,
|
||||
@@ -69,7 +72,7 @@ namespace ts {
|
||||
getSymbolsInScope,
|
||||
getSymbolAtLocation,
|
||||
getShorthandAssignmentValueSymbol,
|
||||
getTypeAtLocation,
|
||||
getTypeAtLocation: getTypeOfNode,
|
||||
typeToString,
|
||||
getSymbolDisplayBuilder,
|
||||
symbolToString,
|
||||
@@ -159,8 +162,9 @@ namespace ts {
|
||||
let emitAwaiter = false;
|
||||
let emitGenerator = false;
|
||||
|
||||
let resolutionTargets: Object[] = [];
|
||||
let resolutionTargets: TypeSystemEntity[] = [];
|
||||
let resolutionResults: boolean[] = [];
|
||||
let resolutionPropertyNames: TypeSystemPropertyName[] = [];
|
||||
|
||||
let mergedSymbols: Symbol[] = [];
|
||||
let symbolLinks: SymbolLinks[] = [];
|
||||
@@ -201,6 +205,15 @@ namespace ts {
|
||||
let assignableRelation: Map<RelationComparisonResult> = {};
|
||||
let identityRelation: Map<RelationComparisonResult> = {};
|
||||
|
||||
type TypeSystemEntity = Symbol | Type | Signature;
|
||||
|
||||
const enum TypeSystemPropertyName {
|
||||
Type,
|
||||
ResolvedBaseConstructorType,
|
||||
DeclaredType,
|
||||
ResolvedReturnType
|
||||
}
|
||||
|
||||
initializeTypeChecker();
|
||||
|
||||
return checker;
|
||||
@@ -1980,15 +1993,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
return _displayBuilder || (_displayBuilder = {
|
||||
symbolToString: symbolToString,
|
||||
typeToString: typeToString,
|
||||
buildSymbolDisplay: buildSymbolDisplay,
|
||||
buildTypeDisplay: buildTypeDisplay,
|
||||
buildTypeParameterDisplay: buildTypeParameterDisplay,
|
||||
buildParameterDisplay: buildParameterDisplay,
|
||||
buildDisplayForParametersAndDelimiters: buildDisplayForParametersAndDelimiters,
|
||||
buildDisplayForTypeParametersAndDelimiters: buildDisplayForTypeParametersAndDelimiters,
|
||||
buildDisplayForTypeArgumentsAndDelimiters: buildDisplayForTypeArgumentsAndDelimiters,
|
||||
buildTypeParameterDisplayFromSymbol: buildTypeParameterDisplayFromSymbol,
|
||||
buildSignatureDisplay: buildSignatureDisplay,
|
||||
buildReturnTypeDisplay: buildReturnTypeDisplay
|
||||
@@ -2177,35 +2187,69 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// Push an entry on the type resolution stack. If an entry with the given target is not already on the stack,
|
||||
// a new entry with that target and an associated result value of true is pushed on the stack, and the value
|
||||
// true is returned. Otherwise, a circularity has occurred and the result values of the existing entry and
|
||||
// all entries pushed after it are changed to false, and the value false is returned. The target object provides
|
||||
// a unique identity for a particular type resolution result: Symbol instances are used to track resolution of
|
||||
// SymbolLinks.type, SymbolLinks instances are used to track resolution of SymbolLinks.declaredType, and
|
||||
// Signature instances are used to track resolution of Signature.resolvedReturnType.
|
||||
function pushTypeResolution(target: Object): boolean {
|
||||
let i = 0;
|
||||
let count = resolutionTargets.length;
|
||||
while (i < count && resolutionTargets[i] !== target) {
|
||||
i++;
|
||||
}
|
||||
if (i < count) {
|
||||
do {
|
||||
resolutionResults[i++] = false;
|
||||
/**
|
||||
* Push an entry on the type resolution stack. If an entry with the given target and the given property name
|
||||
* is already on the stack, and no entries in between already have a type, then a circularity has occurred.
|
||||
* In this case, the result values of the existing entry and all entries pushed after it are changed to false,
|
||||
* and the value false is returned. Otherwise, the new entry is just pushed onto the stack, and true is returned.
|
||||
* In order to see if the same query has already been done before, the target object and the propertyName both
|
||||
* must match the one passed in.
|
||||
*
|
||||
* @param target The symbol, type, or signature whose type is being queried
|
||||
* @param propertyName The property name that should be used to query the target for its type
|
||||
*/
|
||||
function pushTypeResolution(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean {
|
||||
let resolutionCycleStartIndex = findResolutionCycleStartIndex(target, propertyName);
|
||||
if (resolutionCycleStartIndex >= 0) {
|
||||
// A cycle was found
|
||||
let { length } = resolutionTargets;
|
||||
for (let i = resolutionCycleStartIndex; i < length; i++) {
|
||||
resolutionResults[i] = false;
|
||||
}
|
||||
while (i < count);
|
||||
return false;
|
||||
}
|
||||
resolutionTargets.push(target);
|
||||
resolutionResults.push(true);
|
||||
resolutionPropertyNames.push(propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
function findResolutionCycleStartIndex(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): number {
|
||||
for (let i = resolutionTargets.length - 1; i >= 0; i--) {
|
||||
if (hasType(resolutionTargets[i], resolutionPropertyNames[i])) {
|
||||
return -1;
|
||||
}
|
||||
if (resolutionTargets[i] === target && resolutionPropertyNames[i] === propertyName) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): Type {
|
||||
if (propertyName === TypeSystemPropertyName.Type) {
|
||||
return getSymbolLinks(<Symbol>target).type;
|
||||
}
|
||||
if (propertyName === TypeSystemPropertyName.DeclaredType) {
|
||||
return getSymbolLinks(<Symbol>target).declaredType;
|
||||
}
|
||||
if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) {
|
||||
Debug.assert(!!((<Type>target).flags & TypeFlags.Class));
|
||||
return (<InterfaceType>target).resolvedBaseConstructorType;
|
||||
}
|
||||
if (propertyName === TypeSystemPropertyName.ResolvedReturnType) {
|
||||
return (<Signature>target).resolvedReturnType;
|
||||
}
|
||||
|
||||
Debug.fail("Unhandled TypeSystemPropertyName " + propertyName);
|
||||
}
|
||||
|
||||
// Pop an entry from the type resolution stack and return its associated result value. The result value will
|
||||
// be true if no circularities were detected, or false if a circularity was found.
|
||||
function popTypeResolution(): boolean {
|
||||
resolutionTargets.pop();
|
||||
resolutionPropertyNames.pop();
|
||||
return resolutionResults.pop();
|
||||
}
|
||||
|
||||
@@ -2274,10 +2318,6 @@ namespace ts {
|
||||
// fact an iterable or array (depending on target language).
|
||||
let elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false);
|
||||
if (!declaration.dotDotDotToken) {
|
||||
if (isTypeAny(elementType)) {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
// Use specific property type when parent is a tuple or numeric index type when parent is an array
|
||||
let propName = "" + indexOf(pattern.elements, declaration);
|
||||
type = isTupleLikeType(parentType)
|
||||
@@ -2307,6 +2347,7 @@ namespace ts {
|
||||
if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) {
|
||||
return anyType;
|
||||
}
|
||||
|
||||
if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
|
||||
// checkRightHandSideOfForOf will return undefined if the for-of expression type was
|
||||
// missing properties/signatures required to get its iteratedType (like
|
||||
@@ -2314,13 +2355,16 @@ namespace ts {
|
||||
// or it may have led to an error inside getElementTypeOfIterable.
|
||||
return checkRightHandSideOfForOf((<ForOfStatement>declaration.parent.parent).expression) || anyType;
|
||||
}
|
||||
|
||||
if (isBindingPattern(declaration.parent)) {
|
||||
return getTypeForBindingElement(<BindingElement>declaration);
|
||||
}
|
||||
|
||||
// Use type from type annotation if one is present
|
||||
if (declaration.type) {
|
||||
return getTypeFromTypeNode(declaration.type);
|
||||
}
|
||||
|
||||
if (declaration.kind === SyntaxKind.Parameter) {
|
||||
let func = <FunctionLikeDeclaration>declaration.parent;
|
||||
// For a parameter of a set accessor, use the type of the get accessor if one is present
|
||||
@@ -2336,14 +2380,22 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the type of the initializer expression if one is present
|
||||
if (declaration.initializer) {
|
||||
return checkExpressionCached(declaration.initializer);
|
||||
}
|
||||
|
||||
// If it is a short-hand property assignment, use the type of the identifier
|
||||
if (declaration.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
||||
return checkIdentifier(<Identifier>declaration.name);
|
||||
}
|
||||
|
||||
// If the declaration specifies a binding pattern, use the type implied by the binding pattern
|
||||
if (isBindingPattern(declaration.name)) {
|
||||
return getTypeFromBindingPattern(<BindingPattern>declaration.name);
|
||||
}
|
||||
|
||||
// No type specified and nothing can be inferred
|
||||
return undefined;
|
||||
}
|
||||
@@ -2429,13 +2481,10 @@ namespace ts {
|
||||
// tools see the actual type.
|
||||
return declaration.kind !== SyntaxKind.PropertyAssignment ? getWidenedType(type) : type;
|
||||
}
|
||||
// If no type was specified and nothing could be inferred, and if the declaration specifies a binding pattern, use
|
||||
// the type implied by the binding pattern
|
||||
if (isBindingPattern(declaration.name)) {
|
||||
return getTypeFromBindingPattern(<BindingPattern>declaration.name);
|
||||
}
|
||||
|
||||
// Rest parameters default to type any[], other parameters default to type any
|
||||
type = declaration.dotDotDotToken ? anyArrayType : anyType;
|
||||
|
||||
// Report implicit any errors unless this is a private property within an ambient declaration
|
||||
if (reportErrors && compilerOptions.noImplicitAny) {
|
||||
let root = getRootDeclaration(declaration);
|
||||
@@ -2463,7 +2512,7 @@ namespace ts {
|
||||
return links.type = checkExpression((<ExportAssignment>declaration).expression);
|
||||
}
|
||||
// Handle variable, parameter or property
|
||||
if (!pushTypeResolution(symbol)) {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
return unknownType;
|
||||
}
|
||||
let type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
|
||||
@@ -2504,7 +2553,7 @@ namespace ts {
|
||||
function getTypeOfAccessors(symbol: Symbol): Type {
|
||||
let links = getSymbolLinks(symbol);
|
||||
if (!links.type) {
|
||||
if (!pushTypeResolution(symbol)) {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
return unknownType;
|
||||
}
|
||||
let getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
|
||||
@@ -2720,7 +2769,7 @@ namespace ts {
|
||||
if (!baseTypeNode) {
|
||||
return type.resolvedBaseConstructorType = undefinedType;
|
||||
}
|
||||
if (!pushTypeResolution(type)) {
|
||||
if (!pushTypeResolution(type, TypeSystemPropertyName.ResolvedBaseConstructorType)) {
|
||||
return unknownType;
|
||||
}
|
||||
let baseConstructorType = checkExpression(baseTypeNode.expression);
|
||||
@@ -2847,7 +2896,7 @@ namespace ts {
|
||||
if (!links.declaredType) {
|
||||
// Note that we use the links object as the target here because the symbol object is used as the unique
|
||||
// identity for resolution of the 'type' property in SymbolLinks.
|
||||
if (!pushTypeResolution(links)) {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.DeclaredType)) {
|
||||
return unknownType;
|
||||
}
|
||||
let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
|
||||
@@ -3063,44 +3112,57 @@ namespace ts {
|
||||
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
|
||||
}
|
||||
|
||||
function signatureListsIdentical(s: Signature[], t: Signature[]): boolean {
|
||||
if (s.length !== t.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
if (!compareSignatures(s[i], t[i], /*compareReturnTypes*/ false, compareTypes)) {
|
||||
return false;
|
||||
function findMatchingSignature(signature: Signature, signatureList: Signature[]): Signature {
|
||||
for (let s of signatureList) {
|
||||
// Only signatures with no type parameters may differ in return types
|
||||
if (compareSignatures(signature, s, /*compareReturnTypes*/ !!signature.typeParameters, compareTypes)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the lists of call or construct signatures in the given types are all identical except for return types,
|
||||
// and if none of the signatures are generic, return a list of signatures that has substitutes a union of the
|
||||
// return types of the corresponding signatures in each resulting signature.
|
||||
function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] {
|
||||
let signatureLists = map(types, t => getSignaturesOfType(t, kind));
|
||||
let signatures = signatureLists[0];
|
||||
for (let signature of signatures) {
|
||||
if (signature.typeParameters) {
|
||||
return emptyArray;
|
||||
}
|
||||
}
|
||||
function findMatchingSignatures(signature: Signature, signatureLists: Signature[][]): Signature[] {
|
||||
let result: Signature[] = undefined;
|
||||
for (let i = 1; i < signatureLists.length; i++) {
|
||||
if (!signatureListsIdentical(signatures, signatureLists[i])) {
|
||||
return emptyArray;
|
||||
let match = findMatchingSignature(signature, signatureLists[i]);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
if (!result) {
|
||||
result = [signature];
|
||||
}
|
||||
if (match !== signature) {
|
||||
result.push(match);
|
||||
}
|
||||
}
|
||||
let result = map(signatures, cloneSignature);
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
let s = result[i];
|
||||
// Clear resolved return type we possibly got from cloneSignature
|
||||
s.resolvedReturnType = undefined;
|
||||
s.unionSignatures = map(signatureLists, signatures => signatures[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// The signatures of a union type are those signatures that are present and identical in each of the
|
||||
// constituent types, except that non-generic signatures may differ in return types. When signatures
|
||||
// differ in return types, the resulting return type is the union of the constituent return types.
|
||||
function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] {
|
||||
let signatureLists = map(types, t => getSignaturesOfType(t, kind));
|
||||
let result: Signature[] = undefined;
|
||||
for (let source of signatureLists[0]) {
|
||||
let unionSignatures = findMatchingSignatures(source, signatureLists);
|
||||
if (unionSignatures) {
|
||||
let signature: Signature = undefined;
|
||||
if (unionSignatures.length === 1 || source.typeParameters) {
|
||||
signature = source;
|
||||
}
|
||||
else {
|
||||
signature = cloneSignature(source);
|
||||
// Clear resolved return type we possibly got from cloneSignature
|
||||
signature.resolvedReturnType = undefined;
|
||||
signature.unionSignatures = unionSignatures;
|
||||
}
|
||||
(result || (result = [])).push(signature);
|
||||
}
|
||||
}
|
||||
return result || emptyArray;
|
||||
}
|
||||
|
||||
function getUnionIndexType(types: Type[], kind: IndexKind): Type {
|
||||
let indexTypes: Type[] = [];
|
||||
for (let type of types) {
|
||||
@@ -3258,9 +3320,6 @@ namespace ts {
|
||||
* type itself. Note that the apparent type of a union type is the union type itself.
|
||||
*/
|
||||
function getApparentType(type: Type): Type {
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
type = getReducedTypeOfUnionType(<UnionType>type);
|
||||
}
|
||||
if (type.flags & TypeFlags.TypeParameter) {
|
||||
do {
|
||||
type = getConstraintOfTypeParameter(<TypeParameter>type);
|
||||
@@ -3365,6 +3424,29 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Check if a property with the given name is known anywhere in the given type. In an object
|
||||
// type, a property is considered known if the object type is empty, if it has any index
|
||||
// signatures, or if the property is actually declared in the type. In a union or intersection
|
||||
// type, a property is considered known if it is known in any constituent type.
|
||||
function isKnownProperty(type: Type, name: string): boolean {
|
||||
if (type.flags & TypeFlags.ObjectType && type !== globalObjectType) {
|
||||
var resolved = resolveStructuredTypeMembers(type);
|
||||
return !!(resolved.properties.length === 0 ||
|
||||
resolved.stringIndexType ||
|
||||
resolved.numberIndexType ||
|
||||
getPropertyOfType(type, name));
|
||||
}
|
||||
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
for (let t of (<UnionOrIntersectionType>type).types) {
|
||||
if (isKnownProperty(t, name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSignaturesOfStructuredType(type: Type, kind: SignatureKind): Signature[] {
|
||||
if (type.flags & TypeFlags.StructuredType) {
|
||||
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
@@ -3534,7 +3616,7 @@ namespace ts {
|
||||
|
||||
function getReturnTypeOfSignature(signature: Signature): Type {
|
||||
if (!signature.resolvedReturnType) {
|
||||
if (!pushTypeResolution(signature)) {
|
||||
if (!pushTypeResolution(signature, TypeSystemPropertyName.ResolvedReturnType)) {
|
||||
return unknownType;
|
||||
}
|
||||
let type: Type;
|
||||
@@ -3974,26 +4056,79 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function isSubtypeOfAny(candidate: Type, types: Type[]): boolean {
|
||||
function isObjectLiteralTypeDuplicateOf(source: ObjectType, target: ObjectType): boolean {
|
||||
let sourceProperties = getPropertiesOfObjectType(source);
|
||||
let targetProperties = getPropertiesOfObjectType(target);
|
||||
if (sourceProperties.length !== targetProperties.length) {
|
||||
return false;
|
||||
}
|
||||
for (let sourceProp of sourceProperties) {
|
||||
let targetProp = getPropertyOfObjectType(target, sourceProp.name);
|
||||
if (!targetProp ||
|
||||
getDeclarationFlagsFromSymbol(targetProp) & (NodeFlags.Private | NodeFlags.Protected) ||
|
||||
!isTypeDuplicateOf(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isTupleTypeDuplicateOf(source: TupleType, target: TupleType): boolean {
|
||||
let sourceTypes = source.elementTypes;
|
||||
let targetTypes = target.elementTypes;
|
||||
if (sourceTypes.length !== targetTypes.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < sourceTypes.length; i++) {
|
||||
if (!isTypeDuplicateOf(sourceTypes[i], targetTypes[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true if the source type is a duplicate of the target type. A source type is a duplicate of
|
||||
// a target type if the the two are identical, with the exception that the source type may have null or
|
||||
// undefined in places where the target type doesn't. This is by design an asymmetric relationship.
|
||||
function isTypeDuplicateOf(source: Type, target: Type): boolean {
|
||||
if (source === target) {
|
||||
return true;
|
||||
}
|
||||
if (source.flags & TypeFlags.Undefined || source.flags & TypeFlags.Null && !(target.flags & TypeFlags.Undefined)) {
|
||||
return true;
|
||||
}
|
||||
if (source.flags & TypeFlags.ObjectLiteral && target.flags & TypeFlags.ObjectType) {
|
||||
return isObjectLiteralTypeDuplicateOf(<ObjectType>source, <ObjectType>target);
|
||||
}
|
||||
if (isArrayType(source) && isArrayType(target)) {
|
||||
return isTypeDuplicateOf((<TypeReference>source).typeArguments[0], (<TypeReference>target).typeArguments[0]);
|
||||
}
|
||||
if (isTupleType(source) && isTupleType(target)) {
|
||||
return isTupleTypeDuplicateOf(<TupleType>source, <TupleType>target);
|
||||
}
|
||||
return isTypeIdenticalTo(source, target);
|
||||
}
|
||||
|
||||
function isTypeDuplicateOfSomeType(candidate: Type, types: Type[]): boolean {
|
||||
for (let type of types) {
|
||||
if (candidate !== type && isTypeSubtypeOf(candidate, type)) {
|
||||
if (candidate !== type && isTypeDuplicateOf(candidate, type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function removeSubtypes(types: Type[]) {
|
||||
function removeDuplicateTypes(types: Type[]) {
|
||||
let i = types.length;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
if (isSubtypeOfAny(types[i], types)) {
|
||||
if (isTypeDuplicateOfSomeType(types[i], types)) {
|
||||
types.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function containsTypeAny(types: Type[]) {
|
||||
function containsTypeAny(types: Type[]): boolean {
|
||||
for (let type of types) {
|
||||
if (isTypeAny(type)) {
|
||||
return true;
|
||||
@@ -4012,30 +4147,26 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function compareTypeIds(type1: Type, type2: Type): number {
|
||||
return type1.id - type2.id;
|
||||
}
|
||||
|
||||
// The noSubtypeReduction flag is there because it isn't possible to always do subtype reduction. The flag
|
||||
// is true when creating a union type from a type node and when instantiating a union type. In both of those
|
||||
// cases subtype reduction has to be deferred to properly support recursive union types. For example, a
|
||||
// type alias of the form "type Item = string | (() => Item)" cannot be reduced during its declaration.
|
||||
function getUnionType(types: Type[], noSubtypeReduction?: boolean): Type {
|
||||
// We always deduplicate the constituent type set based on object identity, but we'll also deduplicate
|
||||
// based on the structure of the types unless the noDeduplication flag is true, which is the case when
|
||||
// creating a union type from a type node and when instantiating a union type. In both of those cases,
|
||||
// structural deduplication has to be deferred to properly support recursive union types. For example,
|
||||
// a type of the form "type Item = string | (() => Item)" cannot be deduplicated during its declaration.
|
||||
function getUnionType(types: Type[], noDeduplication?: boolean): Type {
|
||||
if (types.length === 0) {
|
||||
return emptyObjectType;
|
||||
}
|
||||
let typeSet: Type[] = [];
|
||||
addTypesToSet(typeSet, types, TypeFlags.Union);
|
||||
typeSet.sort(compareTypeIds);
|
||||
if (noSubtypeReduction) {
|
||||
if (containsTypeAny(typeSet)) {
|
||||
return anyType;
|
||||
}
|
||||
if (containsTypeAny(typeSet)) {
|
||||
return anyType;
|
||||
}
|
||||
if (noDeduplication) {
|
||||
removeAllButLast(typeSet, undefinedType);
|
||||
removeAllButLast(typeSet, nullType);
|
||||
}
|
||||
else {
|
||||
removeSubtypes(typeSet);
|
||||
removeDuplicateTypes(typeSet);
|
||||
}
|
||||
if (typeSet.length === 1) {
|
||||
return typeSet[0];
|
||||
@@ -4045,38 +4176,19 @@ namespace ts {
|
||||
if (!type) {
|
||||
type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getWideningFlagsOfTypes(typeSet));
|
||||
type.types = typeSet;
|
||||
type.reducedType = noSubtypeReduction ? undefined : type;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// Subtype reduction is basically an optimization we do to avoid excessively large union types, which take longer
|
||||
// to process and look strange in quick info and error messages. Semantically there is no difference between the
|
||||
// reduced type and the type itself. So, when we detect a circularity we simply say that the reduced type is the
|
||||
// type itself.
|
||||
function getReducedTypeOfUnionType(type: UnionType): Type {
|
||||
if (!type.reducedType) {
|
||||
type.reducedType = circularType;
|
||||
let reducedType = getUnionType(type.types, /*noSubtypeReduction*/ false);
|
||||
if (type.reducedType === circularType) {
|
||||
type.reducedType = reducedType;
|
||||
}
|
||||
}
|
||||
else if (type.reducedType === circularType) {
|
||||
type.reducedType = type;
|
||||
}
|
||||
return type.reducedType;
|
||||
}
|
||||
|
||||
function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
|
||||
let links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), /*noSubtypeReduction*/ true);
|
||||
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), /*noDeduplication*/ true);
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
// We do not perform supertype reduction on intersection types. Intersection types are created only by the &
|
||||
// We do not perform structural deduplication on intersection types. Intersection types are created only by the &
|
||||
// type operator and we can't reduce those because we want to support recursive intersection types. For example,
|
||||
// a type alias of the form "type List<T> = T & { next: List<T> }" cannot be reduced during its declaration.
|
||||
// Also, unlike union types, the order of the constituent types is preserved in order that overload resolution
|
||||
@@ -4179,7 +4291,7 @@ namespace ts {
|
||||
// Callers should first ensure this by calling isTypeNode
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.QualifiedName:
|
||||
let symbol = getSymbolInfo(node);
|
||||
let symbol = getSymbolAtLocation(node);
|
||||
return symbol && getDeclaredTypeOfSymbol(symbol);
|
||||
default:
|
||||
return unknownType;
|
||||
@@ -4244,15 +4356,18 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createInferenceMapper(context: InferenceContext): TypeMapper {
|
||||
return t => {
|
||||
let mapper: TypeMapper = t => {
|
||||
for (let i = 0; i < context.typeParameters.length; i++) {
|
||||
if (t === context.typeParameters[i]) {
|
||||
context.inferences[i].isFixed = true;
|
||||
return getInferredType(context, i);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
return t;
|
||||
};
|
||||
|
||||
mapper.context = context;
|
||||
return mapper;
|
||||
}
|
||||
|
||||
function identityMapper(type: Type): Type {
|
||||
@@ -4354,7 +4469,7 @@ namespace ts {
|
||||
return createTupleType(instantiateList((<TupleType>type).elementTypes, mapper, instantiateType));
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*noSubtypeReduction*/ true);
|
||||
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*noDeduplication*/ true);
|
||||
}
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType));
|
||||
@@ -4499,6 +4614,16 @@ namespace ts {
|
||||
errorInfo = chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function reportRelationError(message: DiagnosticMessage, source: Type, target: Type) {
|
||||
let sourceType = typeToString(source);
|
||||
let targetType = typeToString(target);
|
||||
if (sourceType === targetType) {
|
||||
sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
|
||||
targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
|
||||
}
|
||||
reportError(message || Diagnostics.Type_0_is_not_assignable_to_type_1, sourceType, targetType);
|
||||
}
|
||||
|
||||
// Compare two types and return
|
||||
// Ternary.True if they are related with no assumptions,
|
||||
// Ternary.Maybe if they are related with assumptions of other relationships, or
|
||||
@@ -4518,7 +4643,23 @@ namespace ts {
|
||||
if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
|
||||
}
|
||||
}
|
||||
|
||||
if (relation !== identityRelation && source.flags & TypeFlags.FreshObjectLiteral) {
|
||||
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
|
||||
if (reportErrors) {
|
||||
reportRelationError(headMessage, source, target);
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
// Above we check for excess properties with respect to the entire target type. When union
|
||||
// and intersection types are further deconstructed on the target side, we don't want to
|
||||
// make the check again (as it might fail for a partial target type). Therefore we obtain
|
||||
// the regular source type and proceed with that.
|
||||
source = getRegularTypeOfObjectLiteral(source);
|
||||
}
|
||||
|
||||
let saveErrorInfo = errorInfo;
|
||||
|
||||
if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
||||
// We have type references to same target type, see if relationship holds for all type arguments
|
||||
if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
|
||||
@@ -4595,18 +4736,22 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (reportErrors) {
|
||||
headMessage = headMessage || Diagnostics.Type_0_is_not_assignable_to_type_1;
|
||||
let sourceType = typeToString(source);
|
||||
let targetType = typeToString(target);
|
||||
if (sourceType === targetType) {
|
||||
sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
|
||||
targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
|
||||
}
|
||||
reportError(headMessage, sourceType, targetType);
|
||||
reportRelationError(headMessage, source, target);
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
|
||||
for (let prop of getPropertiesOfObjectType(source)) {
|
||||
if (!isKnownProperty(target, prop.name)) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, symbolToString(prop), typeToString(target));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary {
|
||||
let result = Ternary.True;
|
||||
let sourceTypes = source.types;
|
||||
@@ -5303,6 +5448,24 @@ namespace ts {
|
||||
return !!(type.flags & TypeFlags.Tuple);
|
||||
}
|
||||
|
||||
function getRegularTypeOfObjectLiteral(type: Type): Type {
|
||||
if (type.flags & TypeFlags.FreshObjectLiteral) {
|
||||
let regularType = (<FreshObjectLiteralType>type).regularType;
|
||||
if (!regularType) {
|
||||
regularType = <ResolvedType>createType((<ResolvedType>type).flags & ~TypeFlags.FreshObjectLiteral);
|
||||
regularType.symbol = (<ResolvedType>type).symbol;
|
||||
regularType.members = (<ResolvedType>type).members;
|
||||
regularType.properties = (<ResolvedType>type).properties;
|
||||
regularType.callSignatures = (<ResolvedType>type).callSignatures;
|
||||
regularType.constructSignatures = (<ResolvedType>type).constructSignatures;
|
||||
regularType.stringIndexType = (<ResolvedType>type).stringIndexType;
|
||||
regularType.numberIndexType = (<ResolvedType>type).numberIndexType;
|
||||
}
|
||||
return regularType;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function getWidenedTypeOfObjectLiteral(type: Type): Type {
|
||||
let properties = getPropertiesOfObjectType(type);
|
||||
let members: SymbolTable = {};
|
||||
@@ -5463,7 +5626,9 @@ namespace ts {
|
||||
function createInferenceContext(typeParameters: TypeParameter[], inferUnionTypes: boolean): InferenceContext {
|
||||
let inferences: TypeInferences[] = [];
|
||||
for (let unused of typeParameters) {
|
||||
inferences.push({ primary: undefined, secondary: undefined, isFixed: false });
|
||||
inferences.push({
|
||||
primary: undefined, secondary: undefined, isFixed: false
|
||||
});
|
||||
}
|
||||
return {
|
||||
typeParameters,
|
||||
@@ -5831,47 +5996,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function resolveLocation(node: Node) {
|
||||
// Resolve location from top down towards node if it is a context sensitive expression
|
||||
// That helps in making sure not assigning types as any when resolved out of order
|
||||
let containerNodes: Node[] = [];
|
||||
for (let parent = node.parent; parent; parent = parent.parent) {
|
||||
if ((isExpression(parent) || isObjectLiteralMethod(node)) &&
|
||||
isContextSensitive(<Expression>parent)) {
|
||||
containerNodes.unshift(parent);
|
||||
}
|
||||
}
|
||||
|
||||
ts.forEach(containerNodes, node => { getTypeOfNode(node); });
|
||||
}
|
||||
|
||||
function getSymbolAtLocation(node: Node): Symbol {
|
||||
resolveLocation(node);
|
||||
return getSymbolInfo(node);
|
||||
}
|
||||
|
||||
function getTypeAtLocation(node: Node): Type {
|
||||
resolveLocation(node);
|
||||
return getTypeOfNode(node);
|
||||
}
|
||||
|
||||
function getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type {
|
||||
resolveLocation(node);
|
||||
// Get the narrowed type of symbol at given location instead of just getting
|
||||
// the type of the symbol.
|
||||
// eg.
|
||||
// function foo(a: string | number) {
|
||||
// if (typeof a === "string") {
|
||||
// a/**/
|
||||
// }
|
||||
// }
|
||||
// getTypeOfSymbol for a would return type of parameter symbol string | number
|
||||
// Unless we provide location /**/, checker wouldn't know how to narrow the type
|
||||
// By using getNarrowedTypeOfSymbol would return string since it would be able to narrow
|
||||
// it by typeguard in the if true condition
|
||||
return getNarrowedTypeOfSymbol(symbol, node);
|
||||
}
|
||||
|
||||
// Get the narrowed type of a given symbol at a given location
|
||||
function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) {
|
||||
let type = getTypeOfSymbol(symbol);
|
||||
@@ -6764,10 +6888,23 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Presence of a contextual type mapper indicates inferential typing, except the identityMapper object is
|
||||
// used as a special marker for other purposes.
|
||||
/**
|
||||
* Detect if the mapper implies an inference context. Specifically, there are 4 possible values
|
||||
* for a mapper. Let's go through each one of them:
|
||||
*
|
||||
* 1. undefined - this means we are not doing inferential typing, but we may do contextual typing,
|
||||
* which could cause us to assign a parameter a type
|
||||
* 2. identityMapper - means we want to avoid assigning a parameter a type, whether or not we are in
|
||||
* inferential typing (context is undefined for the identityMapper)
|
||||
* 3. a mapper created by createInferenceMapper - we are doing inferential typing, we want to assign
|
||||
* types to parameters and fix type parameters (context is defined)
|
||||
* 4. an instantiation mapper created by createTypeMapper or createTypeEraser - this should never be
|
||||
* passed as the contextual mapper when checking an expression (context is undefined for these)
|
||||
*
|
||||
* isInferentialContext is detecting if we are in case 3
|
||||
*/
|
||||
function isInferentialContext(mapper: TypeMapper) {
|
||||
return mapper && mapper !== identityMapper;
|
||||
return mapper && mapper.context;
|
||||
}
|
||||
|
||||
// A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property
|
||||
@@ -6955,7 +7092,7 @@ namespace ts {
|
||||
let stringIndexType = getIndexType(IndexKind.String);
|
||||
let numberIndexType = getIndexType(IndexKind.Number);
|
||||
let result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
|
||||
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | (typeFlags & TypeFlags.ContainsUndefinedOrNull);
|
||||
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.FreshObjectLiteral | TypeFlags.ContainsObjectLiteral | (typeFlags & TypeFlags.ContainsUndefinedOrNull);
|
||||
return result;
|
||||
|
||||
function getIndexType(kind: IndexKind) {
|
||||
@@ -8487,6 +8624,9 @@ namespace ts {
|
||||
if (!produceDiagnostics) {
|
||||
for (let candidate of candidates) {
|
||||
if (hasCorrectArity(node, args, candidate)) {
|
||||
if (candidate.typeParameters && typeArguments) {
|
||||
candidate = getSignatureInstantiation(candidate, map(typeArguments, getTypeFromTypeNode));
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
@@ -8835,7 +8975,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkAssertion(node: AssertionExpression) {
|
||||
let exprType = checkExpression(node.expression);
|
||||
let exprType = getRegularTypeOfObjectLiteral(checkExpression(node.expression));
|
||||
let targetType = getTypeFromTypeNode(node.type);
|
||||
if (produceDiagnostics && targetType !== unknownType) {
|
||||
let widenedType = getWidenedType(exprType);
|
||||
@@ -8856,13 +8996,52 @@ namespace ts {
|
||||
let len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
|
||||
for (let i = 0; i < len; i++) {
|
||||
let parameter = signature.parameters[i];
|
||||
let links = getSymbolLinks(parameter);
|
||||
links.type = instantiateType(getTypeAtPosition(context, i), mapper);
|
||||
let contextualParameterType = getTypeAtPosition(context, i);
|
||||
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
|
||||
}
|
||||
if (signature.hasRestParameter && context.hasRestParameter && signature.parameters.length >= context.parameters.length) {
|
||||
let parameter = lastOrUndefined(signature.parameters);
|
||||
let links = getSymbolLinks(parameter);
|
||||
links.type = instantiateType(getTypeOfSymbol(lastOrUndefined(context.parameters)), mapper);
|
||||
let contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
|
||||
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
|
||||
}
|
||||
}
|
||||
|
||||
function assignTypeToParameterAndFixTypeParameters(parameter: Symbol, contextualType: Type, mapper: TypeMapper) {
|
||||
let links = getSymbolLinks(parameter);
|
||||
if (!links.type) {
|
||||
links.type = instantiateType(contextualType, mapper);
|
||||
}
|
||||
else if (isInferentialContext(mapper)) {
|
||||
// Even if the parameter already has a type, it might be because it was given a type while
|
||||
// processing the function as an argument to a prior signature during overload resolution.
|
||||
// If this was the case, it may have caused some type parameters to be fixed. So here,
|
||||
// we need to ensure that type parameters at the same positions get fixed again. This is
|
||||
// done by calling instantiateType to attach the mapper to the contextualType, and then
|
||||
// calling inferTypes to force a walk of contextualType so that all the correct fixing
|
||||
// happens. The choice to pass in links.type may seem kind of arbitrary, but it serves
|
||||
// to make sure that all the correct positions in contextualType are reached by the walk.
|
||||
// Here is an example:
|
||||
//
|
||||
// interface Base {
|
||||
// baseProp;
|
||||
// }
|
||||
// interface Derived extends Base {
|
||||
// toBase(): Base;
|
||||
// }
|
||||
//
|
||||
// var derived: Derived;
|
||||
//
|
||||
// declare function foo<T>(x: T, func: (p: T) => T): T;
|
||||
// declare function foo<T>(x: T, func: (p: T) => T): T;
|
||||
//
|
||||
// var result = foo(derived, d => d.toBase());
|
||||
//
|
||||
// We are typing d while checking the second overload. But we've already given d
|
||||
// a type (Derived) from the first overload. However, we still want to fix the
|
||||
// T in the second overload so that we do not infer Base as a candidate for T
|
||||
// (inferring Base would make type argument inference inconsistent between the two
|
||||
// overloads).
|
||||
inferTypes(mapper.context, links.type, instantiateType(contextualType, mapper));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9082,27 +9261,36 @@ namespace ts {
|
||||
|
||||
let links = getNodeLinks(node);
|
||||
let type = getTypeOfSymbol(node.symbol);
|
||||
// Check if function expression is contextually typed and assign parameter types if so
|
||||
if (!(links.flags & NodeCheckFlags.ContextChecked)) {
|
||||
let contextSensitive = isContextSensitive(node);
|
||||
let mightFixTypeParameters = contextSensitive && isInferentialContext(contextualMapper);
|
||||
|
||||
// Check if function expression is contextually typed and assign parameter types if so.
|
||||
// See the comment in assignTypeToParameterAndFixTypeParameters to understand why we need to
|
||||
// check mightFixTypeParameters.
|
||||
if (mightFixTypeParameters || !(links.flags & NodeCheckFlags.ContextChecked)) {
|
||||
let contextualSignature = getContextualSignature(node);
|
||||
// If a type check is started at a function expression that is an argument of a function call, obtaining the
|
||||
// contextual type may recursively get back to here during overload resolution of the call. If so, we will have
|
||||
// already assigned contextual types.
|
||||
if (!(links.flags & NodeCheckFlags.ContextChecked)) {
|
||||
let contextChecked = !!(links.flags & NodeCheckFlags.ContextChecked);
|
||||
if (mightFixTypeParameters || !contextChecked) {
|
||||
links.flags |= NodeCheckFlags.ContextChecked;
|
||||
if (contextualSignature) {
|
||||
let signature = getSignaturesOfType(type, SignatureKind.Call)[0];
|
||||
if (isContextSensitive(node)) {
|
||||
if (contextSensitive) {
|
||||
assignContextualParameterTypes(signature, contextualSignature, contextualMapper || identityMapper);
|
||||
}
|
||||
if (!node.type && !signature.resolvedReturnType) {
|
||||
if (mightFixTypeParameters || !node.type && !signature.resolvedReturnType) {
|
||||
let returnType = getReturnTypeFromBody(node, contextualMapper);
|
||||
if (!signature.resolvedReturnType) {
|
||||
signature.resolvedReturnType = returnType;
|
||||
}
|
||||
}
|
||||
}
|
||||
checkSignatureDeclaration(node);
|
||||
|
||||
if (!contextChecked) {
|
||||
checkSignatureDeclaration(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9612,7 +9800,7 @@ namespace ts {
|
||||
return getUnionType([leftType, rightType]);
|
||||
case SyntaxKind.EqualsToken:
|
||||
checkAssignmentOperator(rightType);
|
||||
return rightType;
|
||||
return getRegularTypeOfObjectLiteral(rightType);
|
||||
case SyntaxKind.CommaToken:
|
||||
return rightType;
|
||||
}
|
||||
@@ -9792,7 +9980,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration, type: Type, contextualMapper?: TypeMapper) {
|
||||
if (contextualMapper && contextualMapper !== identityMapper) {
|
||||
if (isInferentialContext(contextualMapper)) {
|
||||
let signature = getSingleCallSignature(type);
|
||||
if (signature && signature.typeParameters) {
|
||||
let contextualType = getContextualType(<Expression>node);
|
||||
@@ -10037,7 +10225,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
checkTypeAssignableTo(typePredicate.type,
|
||||
getTypeAtLocation(node.parameters[typePredicate.parameterIndex]),
|
||||
getTypeOfNode(node.parameters[typePredicate.parameterIndex]),
|
||||
typePredicateNode.type);
|
||||
}
|
||||
}
|
||||
@@ -13669,7 +13857,7 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getSymbolInfo(node: Node) {
|
||||
function getSymbolAtLocation(node: Node) {
|
||||
if (isInsideWithStatementBody(node)) {
|
||||
// We cannot answer semantic questions within a with block, do not proceed any further
|
||||
return undefined;
|
||||
@@ -13680,10 +13868,22 @@ namespace ts {
|
||||
return getSymbolOfNode(node.parent);
|
||||
}
|
||||
|
||||
if (node.kind === SyntaxKind.Identifier && isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
|
||||
return node.parent.kind === SyntaxKind.ExportAssignment
|
||||
? getSymbolOfEntityNameOrPropertyAccessExpression(<Identifier>node)
|
||||
: getSymbolOfPartOfRightHandSideOfImportEquals(<Identifier>node);
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
if (isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
|
||||
return node.parent.kind === SyntaxKind.ExportAssignment
|
||||
? getSymbolOfEntityNameOrPropertyAccessExpression(<Identifier>node)
|
||||
: getSymbolOfPartOfRightHandSideOfImportEquals(<Identifier>node);
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.BindingElement &&
|
||||
node.parent.parent.kind === SyntaxKind.ObjectBindingPattern &&
|
||||
node === (<BindingElement>node.parent).propertyName) {
|
||||
let typeOfPattern = getTypeOfNode(node.parent.parent);
|
||||
let propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (<Identifier>node).text);
|
||||
|
||||
if (propertyDeclaration) {
|
||||
return propertyDeclaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
@@ -13760,24 +13960,24 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (isTypeDeclaration(node)) {
|
||||
// In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration
|
||||
// In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration
|
||||
let symbol = getSymbolOfNode(node);
|
||||
return getDeclaredTypeOfSymbol(symbol);
|
||||
}
|
||||
|
||||
if (isTypeDeclarationName(node)) {
|
||||
let symbol = getSymbolInfo(node);
|
||||
let symbol = getSymbolAtLocation(node);
|
||||
return symbol && getDeclaredTypeOfSymbol(symbol);
|
||||
}
|
||||
|
||||
if (isDeclaration(node)) {
|
||||
// In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration
|
||||
// In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration
|
||||
let symbol = getSymbolOfNode(node);
|
||||
return getTypeOfSymbol(symbol);
|
||||
}
|
||||
|
||||
if (isDeclarationName(node)) {
|
||||
let symbol = getSymbolInfo(node);
|
||||
let symbol = getSymbolAtLocation(node);
|
||||
return symbol && getTypeOfSymbol(symbol);
|
||||
}
|
||||
|
||||
@@ -13786,7 +13986,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
|
||||
let symbol = getSymbolInfo(node);
|
||||
let symbol = getSymbolAtLocation(node);
|
||||
let declaredType = symbol && getDeclaredTypeOfSymbol(symbol);
|
||||
return declaredType !== unknownType ? declaredType : getTypeOfSymbol(symbol);
|
||||
}
|
||||
@@ -13955,7 +14155,11 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
// const enums and modules that contain only const enums are not considered values from the emit perespective
|
||||
return target !== unknownSymbol && target && target.flags & SymbolFlags.Value && !isConstEnumOrConstEnumOnlyModule(target);
|
||||
// unless 'preserveConstEnums' option is set to true
|
||||
return target !== unknownSymbol &&
|
||||
target &&
|
||||
target.flags & SymbolFlags.Value &&
|
||||
(compilerOptions.preserveConstEnums || !isConstEnumOrConstEnumOnlyModule(target));
|
||||
}
|
||||
|
||||
function isConstEnumOrConstEnumOnlyModule(s: Symbol): boolean {
|
||||
|
||||
@@ -254,6 +254,7 @@ namespace ts {
|
||||
Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: DiagnosticCategory.Error, key: "Only a void function can be called with the 'new' keyword." },
|
||||
Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: DiagnosticCategory.Error, key: "Cannot use 'new' with an expression whose type lacks a call or construct signature." },
|
||||
Neither_type_0_nor_type_1_is_assignable_to_the_other: { code: 2352, category: DiagnosticCategory.Error, key: "Neither type '{0}' nor type '{1}' is assignable to the other." },
|
||||
Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1: { code: 2353, category: DiagnosticCategory.Error, key: "Object literal may only specify known properties, and '{0}' does not exist in type '{1}'." },
|
||||
No_best_common_type_exists_among_return_expressions: { code: 2354, category: DiagnosticCategory.Error, key: "No best common type exists among return expressions." },
|
||||
A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2355, category: DiagnosticCategory.Error, key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement." },
|
||||
An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: DiagnosticCategory.Error, key: "An arithmetic operand must be of type 'any', 'number' or an enum type." },
|
||||
|
||||
@@ -1005,6 +1005,10 @@
|
||||
"category": "Error",
|
||||
"code": 2352
|
||||
},
|
||||
"Object literal may only specify known properties, and '{0}' does not exist in type '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2353
|
||||
},
|
||||
"No best common type exists among return expressions.": {
|
||||
"category": "Error",
|
||||
"code": 2354
|
||||
|
||||
+100
-18
@@ -1425,6 +1425,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
case SyntaxKind.IfStatement:
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
case SyntaxKind.JsxExpression:
|
||||
case SyntaxKind.NewExpression:
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
@@ -3012,6 +3013,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
return result;
|
||||
}
|
||||
|
||||
function emitEs6ExportDefaultCompat(node: Node) {
|
||||
if (node.parent.kind === SyntaxKind.SourceFile) {
|
||||
Debug.assert(!!(node.flags & NodeFlags.Default) || node.kind === SyntaxKind.ExportAssignment);
|
||||
// only allow export default at a source file level
|
||||
if (compilerOptions.module === ModuleKind.CommonJS || compilerOptions.module === ModuleKind.AMD || compilerOptions.module === ModuleKind.UMD) {
|
||||
if (!currentSourceFile.symbol.exports["___esModule"]) {
|
||||
if (languageVersion === ScriptTarget.ES5) {
|
||||
// default value of configurable, enumerable, writable are `false`.
|
||||
write("Object.defineProperty(exports, \"__esModule\", { value: true });");
|
||||
writeLine();
|
||||
}
|
||||
else if (languageVersion === ScriptTarget.ES3) {
|
||||
write("exports.__esModule = true;");
|
||||
writeLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitExportMemberAssignment(node: FunctionLikeDeclaration | ClassDeclaration) {
|
||||
if (node.flags & NodeFlags.Export) {
|
||||
writeLine();
|
||||
@@ -3034,9 +3055,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
else {
|
||||
if (node.flags & NodeFlags.Default) {
|
||||
emitEs6ExportDefaultCompat(node);
|
||||
if (languageVersion === ScriptTarget.ES3) {
|
||||
write("exports[\"default\"]");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
write("exports.default");
|
||||
}
|
||||
}
|
||||
@@ -3249,7 +3272,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
function emitAssignmentExpression(root: BinaryExpression) {
|
||||
let target = root.left;
|
||||
let value = root.right;
|
||||
if (isAssignmentExpressionStatement) {
|
||||
|
||||
if (isEmptyObjectLiteralOrArrayLiteral(target)) {
|
||||
emit(value);
|
||||
}
|
||||
else if (isAssignmentExpressionStatement) {
|
||||
emitDestructuringAssignment(target, value);
|
||||
}
|
||||
else {
|
||||
@@ -4215,10 +4242,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
}
|
||||
|
||||
let startIndex = 0;
|
||||
|
||||
write(" {");
|
||||
scopeEmitStart(node, "constructor");
|
||||
increaseIndent();
|
||||
if (ctor) {
|
||||
// Emit all the directive prologues (like "use strict"). These have to come before
|
||||
// any other preamble code we write (like parameter initializers).
|
||||
startIndex = emitDirectivePrologues(ctor.body.statements, /*startWithNewLine*/ true);
|
||||
emitDetachedComments(ctor.body.statements);
|
||||
}
|
||||
emitCaptureThisForNodeIfNecessary(node);
|
||||
@@ -4253,7 +4285,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
if (superCall) {
|
||||
statements = statements.slice(1);
|
||||
}
|
||||
emitLines(statements);
|
||||
emitLinesStartingAt(statements, startIndex);
|
||||
}
|
||||
emitTempDeclarations(/*newLine*/ true);
|
||||
writeLine();
|
||||
@@ -5398,17 +5430,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
(!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
|
||||
emitLeadingComments(node);
|
||||
emitStart(node);
|
||||
if (isES6ExportedDeclaration(node)) {
|
||||
write("export ");
|
||||
write("var ");
|
||||
|
||||
// variable declaration for import-equals declaration can be hoisted in system modules
|
||||
// in this case 'var' should be omitted and emit should contain only initialization
|
||||
let variableDeclarationIsHoisted = shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ true);
|
||||
|
||||
// is it top level export import v = a.b.c in system module?
|
||||
// if yes - it needs to be rewritten as exporter('v', v = a.b.c)
|
||||
let isExported = isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ true);
|
||||
|
||||
if (!variableDeclarationIsHoisted) {
|
||||
Debug.assert(!isExported);
|
||||
|
||||
if (isES6ExportedDeclaration(node)) {
|
||||
write("export ");
|
||||
write("var ");
|
||||
}
|
||||
else if (!(node.flags & NodeFlags.Export)) {
|
||||
write("var ");
|
||||
}
|
||||
}
|
||||
else if (!(node.flags & NodeFlags.Export)) {
|
||||
write("var ");
|
||||
|
||||
|
||||
if (isExported) {
|
||||
write(`${exportFunctionForFile}("`);
|
||||
emitNodeWithoutSourceMap(node.name);
|
||||
write(`", `);
|
||||
}
|
||||
|
||||
emitModuleMemberName(node);
|
||||
write(" = ");
|
||||
emit(node.moduleReference);
|
||||
write(";");
|
||||
|
||||
if (isExported) {
|
||||
write(")");
|
||||
}
|
||||
|
||||
write(";");
|
||||
emitEnd(node);
|
||||
emitExportImportAssignments(node);
|
||||
emitTrailingComments(node);
|
||||
@@ -5529,6 +5587,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
write(")");
|
||||
}
|
||||
else {
|
||||
emitEs6ExportDefaultCompat(node);
|
||||
emitContainingModuleName(node);
|
||||
if (languageVersion === ScriptTarget.ES3) {
|
||||
write("[\"default\"] = ");
|
||||
@@ -5747,6 +5806,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
write(`function ${exportStarFunction}(m) {`);
|
||||
increaseIndent();
|
||||
writeLine();
|
||||
write(`var exports = {};`);
|
||||
writeLine();
|
||||
write(`for(var n in m) {`);
|
||||
increaseIndent();
|
||||
writeLine();
|
||||
@@ -5754,10 +5815,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
if (localNames) {
|
||||
write(`&& !${localNames}.hasOwnProperty(n)`);
|
||||
}
|
||||
write(`) ${exportFunctionForFile}(n, m[n]);`);
|
||||
write(`) exports[n] = m[n];`);
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("}");
|
||||
writeLine();
|
||||
write(`${exportFunctionForFile}(exports);`)
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("}");
|
||||
@@ -5929,6 +5992,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInternalModuleImportEqualsDeclaration(node)) {
|
||||
if (!hoistedVars) {
|
||||
hoistedVars = [];
|
||||
}
|
||||
|
||||
hoistedVars.push(node.name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBindingPattern(node)) {
|
||||
forEach((<BindingPattern>node).elements, visit);
|
||||
@@ -6090,16 +6162,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
if ((<ExportDeclaration>importNode).exportClause) {
|
||||
// export {a, b as c} from 'foo'
|
||||
// emit as:
|
||||
// exports('a', _foo["a"])
|
||||
// exports('c', _foo["b"])
|
||||
// var reexports = {}
|
||||
// reexports['a'] = _foo["a"];
|
||||
// reexports['c'] = _foo["b"];
|
||||
// exports_(reexports);
|
||||
let reexportsVariableName = makeUniqueName("reexports");
|
||||
writeLine();
|
||||
write(`var ${reexportsVariableName} = {};`)
|
||||
writeLine();
|
||||
for (let e of (<ExportDeclaration>importNode).exportClause.elements) {
|
||||
writeLine();
|
||||
write(`${exportFunctionForFile}("`);
|
||||
write(`${reexportsVariableName}["`);
|
||||
emitNodeWithoutSourceMap(e.name);
|
||||
write(`", ${parameterName}["`);
|
||||
write(`"] = ${parameterName}["`);
|
||||
emitNodeWithoutSourceMap(e.propertyName || e.name);
|
||||
write(`"]);`);
|
||||
write(`"];`);
|
||||
writeLine();
|
||||
}
|
||||
write(`${exportFunctionForFile}(${reexportsVariableName});`);
|
||||
}
|
||||
else {
|
||||
writeLine();
|
||||
@@ -6126,14 +6205,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
writeLine();
|
||||
for (let i = startIndex; i < node.statements.length; ++i) {
|
||||
let statement = node.statements[i];
|
||||
// - imports/exports are not emitted for system modules
|
||||
// - external module related imports/exports are not emitted for system modules
|
||||
// - function declarations are not emitted because they were already hoisted
|
||||
switch (statement.kind) {
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
continue;
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
if (!isInternalModuleImportEqualsDeclaration(statement)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
writeLine();
|
||||
emit(statement);
|
||||
|
||||
@@ -3295,7 +3295,7 @@ namespace ts {
|
||||
|
||||
function parseSuperExpression(): MemberExpression {
|
||||
let expression = parseTokenNode<PrimaryExpression>();
|
||||
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.DotToken) {
|
||||
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.DotToken || token === SyntaxKind.OpenBracketToken) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
|
||||
+17
-3
@@ -1762,10 +1762,12 @@ namespace ts {
|
||||
FromSignature = 0x00040000, // Created for signature assignment check
|
||||
ObjectLiteral = 0x00080000, // Originates in an object literal
|
||||
/* @internal */
|
||||
ContainsUndefinedOrNull = 0x00100000, // Type is or contains Undefined or Null type
|
||||
FreshObjectLiteral = 0x00100000, // Fresh object literal type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 0x00200000, // Type is or contains object literal type
|
||||
ESSymbol = 0x00400000, // Type of symbol primitive introduced in ES6
|
||||
ContainsUndefinedOrNull = 0x00200000, // Type is or contains Undefined or Null type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type
|
||||
ESSymbol = 0x00800000, // Type of symbol primitive introduced in ES6
|
||||
|
||||
/* @internal */
|
||||
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
|
||||
@@ -1858,6 +1860,14 @@ namespace ts {
|
||||
numberIndexType?: Type; // Numeric index type
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
// Object literals are initially marked fresh. Freshness disappears following an assignment,
|
||||
// before a type assertion, or when when an object literal's type is widened. The regular
|
||||
// version of a fresh type is identical except for the TypeFlags.FreshObjectLiteral flag.
|
||||
export interface FreshObjectLiteralType extends ResolvedType {
|
||||
regularType: ResolvedType; // Regular version of fresh type
|
||||
}
|
||||
|
||||
// Just a place to cache element types of iterables and iterators
|
||||
/* @internal */
|
||||
export interface IterableOrIteratorType extends ObjectType, UnionType {
|
||||
@@ -1912,6 +1922,9 @@ namespace ts {
|
||||
/* @internal */
|
||||
export interface TypeMapper {
|
||||
(t: TypeParameter): Type;
|
||||
context?: InferenceContext; // The inference context this mapper was created from.
|
||||
// Only inference mappers have this set (in createInferenceMapper).
|
||||
// The identity mapper and regular instantiation mappers do not need it.
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -2208,6 +2221,7 @@ namespace ts {
|
||||
|
||||
export interface CompilerHost {
|
||||
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
|
||||
getCancellationToken?(): CancellationToken;
|
||||
getDefaultLibFileName(options: CompilerOptions): string;
|
||||
writeFile: WriteFileCallback;
|
||||
getCurrentDirectory(): string;
|
||||
|
||||
@@ -568,7 +568,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function isVariableLike(node: Node): boolean {
|
||||
export function isVariableLike(node: Node): node is VariableLikeDeclaration {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.BindingElement:
|
||||
@@ -965,7 +965,7 @@ namespace ts {
|
||||
return (<ExternalModuleReference>(<ImportEqualsDeclaration>node).moduleReference).expression;
|
||||
}
|
||||
|
||||
export function isInternalModuleImportEqualsDeclaration(node: Node) {
|
||||
export function isInternalModuleImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration {
|
||||
return node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind !== SyntaxKind.ExternalModuleReference;
|
||||
}
|
||||
|
||||
@@ -1981,6 +1981,17 @@ namespace ts {
|
||||
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node);
|
||||
}
|
||||
|
||||
export function isEmptyObjectLiteralOrArrayLiteral(expression: Node): boolean {
|
||||
let kind = expression.kind;
|
||||
if (kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
return (<ObjectLiteralExpression>expression).properties.length === 0;
|
||||
}
|
||||
if (kind === SyntaxKind.ArrayLiteralExpression) {
|
||||
return (<ArrayLiteralExpression>expression).elements.length === 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getLocalSymbolForExportDefault(symbol: Symbol) {
|
||||
return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined;
|
||||
}
|
||||
|
||||
@@ -26,9 +26,8 @@ module FourSlash {
|
||||
export interface FourSlashFile {
|
||||
// The contents of the file (with markers, etc stripped out)
|
||||
content: string;
|
||||
|
||||
fileName: string;
|
||||
|
||||
version: number;
|
||||
// File-specific options (name/value pairs)
|
||||
fileOptions: { [index: string]: string; };
|
||||
}
|
||||
@@ -671,20 +670,20 @@ module FourSlash {
|
||||
|
||||
let completions = this.getCompletionListAtCaret();
|
||||
if ((!completions || completions.entries.length === 0) && negative) {
|
||||
this.raiseError("Completion list is empty at Caret");
|
||||
} else if ((completions && completions.entries.length !== 0) && !negative) {
|
||||
|
||||
this.raiseError("Completion list is empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition);
|
||||
}
|
||||
else if (completions && completions.entries.length !== 0 && !negative) {
|
||||
let errorMsg = "\n" + "Completion List contains: [" + completions.entries[0].name;
|
||||
for (let i = 1; i < completions.entries.length; i++) {
|
||||
errorMsg += ", " + completions.entries[i].name;
|
||||
}
|
||||
errorMsg += "]\n";
|
||||
|
||||
Harness.IO.log(errorMsg);
|
||||
this.raiseError("Completion list is not empty at Caret");
|
||||
this.raiseError("Completion list is not empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition + errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public verifyCompletionListAllowsNewIdentifier(negative: boolean) {
|
||||
let completions = this.getCompletionListAtCaret();
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ interface FindFileResult {
|
||||
}
|
||||
|
||||
interface IOLog {
|
||||
timestamp: string;
|
||||
arguments: string[];
|
||||
executingPath: string;
|
||||
currentDirectory: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path="harness.ts" />
|
||||
|
||||
class RunnerBase {
|
||||
abstract class RunnerBase {
|
||||
constructor() { }
|
||||
|
||||
// contains the tests to run
|
||||
@@ -18,9 +18,7 @@ class RunnerBase {
|
||||
/** Setup the runner's tests so that they are ready to be executed by the harness
|
||||
* The first test should be a describe/it block that sets up the harness's compiler instance appropriately
|
||||
*/
|
||||
public initializeTests(): void {
|
||||
throw new Error('method not implemented');
|
||||
}
|
||||
public abstract initializeTests(): void;
|
||||
|
||||
/** Replaces instances of full paths with fileNames only */
|
||||
static removeFullPaths(path: string) {
|
||||
|
||||
@@ -123,7 +123,7 @@ module RWC {
|
||||
content = ts.sys.readFile(unitName);
|
||||
}
|
||||
catch (e) {
|
||||
// Leave content undefined.
|
||||
content = ts.sys.readFile(fileName);
|
||||
}
|
||||
return { unitName, content };
|
||||
}
|
||||
|
||||
Vendored
+3
-3
@@ -971,14 +971,14 @@ interface JSON {
|
||||
* @param replacer A function that transforms the results.
|
||||
* @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
|
||||
*/
|
||||
stringify(value: any, replacer: (key: string, value: any) => any, space: any): string;
|
||||
stringify(value: any, replacer: (key: string, value: any) => any, space: string | number): string;
|
||||
/**
|
||||
* Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
|
||||
* @param value A JavaScript value, usually an object or array, to be converted.
|
||||
* @param replacer Array that transforms the results.
|
||||
* @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
|
||||
*/
|
||||
stringify(value: any, replacer: any[], space: any): string;
|
||||
stringify(value: any, replacer: any[], space: string | number): string;
|
||||
}
|
||||
/**
|
||||
* An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
|
||||
@@ -1181,4 +1181,4 @@ interface PromiseLike<T> {
|
||||
*/
|
||||
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>;
|
||||
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): PromiseLike<TResult>;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -377,7 +377,7 @@ interface String {
|
||||
* @param searchString search string
|
||||
* @param position If position is undefined, 0 is assumed, so as to search all of the String.
|
||||
*/
|
||||
contains(searchString: string, position?: number): boolean;
|
||||
includes(searchString: string, position?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
||||
|
||||
@@ -202,9 +202,7 @@ namespace ts.server {
|
||||
return {
|
||||
isMemberCompletion: false,
|
||||
isNewIdentifierLocation: false,
|
||||
entries: response.body,
|
||||
fileName: fileName,
|
||||
position: position
|
||||
entries: response.body
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+17
-17
@@ -842,53 +842,53 @@ namespace ts.server {
|
||||
private handlers : Map<(request: protocol.Request) => {response?: any, responseRequired?: boolean}> = {
|
||||
[CommandNames.Exit]: () => {
|
||||
this.exit();
|
||||
return {};
|
||||
return { responseRequired: false};
|
||||
},
|
||||
[CommandNames.Definition]: (request: protocol.Request) => {
|
||||
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return {response: this.getDefinition(defArgs.line, defArgs.offset, defArgs.file)};
|
||||
return {response: this.getDefinition(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true};
|
||||
},
|
||||
[CommandNames.TypeDefinition]: (request: protocol.Request) => {
|
||||
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return {response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file)};
|
||||
return {response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true};
|
||||
},
|
||||
[CommandNames.References]: (request: protocol.Request) => {
|
||||
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return {response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file)};
|
||||
return {response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true};
|
||||
},
|
||||
[CommandNames.Rename]: (request: protocol.Request) => {
|
||||
var renameArgs = <protocol.RenameRequestArgs>request.arguments;
|
||||
return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings)}
|
||||
return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings), responseRequired: true}
|
||||
},
|
||||
[CommandNames.Open]: (request: protocol.Request) => {
|
||||
var openArgs = <protocol.OpenRequestArgs>request.arguments;
|
||||
this.openClientFile(openArgs.file);
|
||||
return {}
|
||||
return {responseRequired: false}
|
||||
},
|
||||
[CommandNames.Quickinfo]: (request: protocol.Request) => {
|
||||
var quickinfoArgs = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return {response: this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file)};
|
||||
return {response: this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file), responseRequired: true};
|
||||
},
|
||||
[CommandNames.Format]: (request: protocol.Request) => {
|
||||
var formatArgs = <protocol.FormatRequestArgs>request.arguments;
|
||||
return {response: this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file)};
|
||||
return {response: this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file), responseRequired: true};
|
||||
},
|
||||
[CommandNames.Formatonkey]: (request: protocol.Request) => {
|
||||
var formatOnKeyArgs = <protocol.FormatOnKeyRequestArgs>request.arguments;
|
||||
return {response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file)};
|
||||
return {response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file), responseRequired: true};
|
||||
},
|
||||
[CommandNames.Completions]: (request: protocol.Request) => {
|
||||
var completionsArgs = <protocol.CompletionsRequestArgs>request.arguments;
|
||||
return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file)}
|
||||
return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file), responseRequired: true}
|
||||
},
|
||||
[CommandNames.CompletionDetails]: (request: protocol.Request) => {
|
||||
var completionDetailsArgs = <protocol.CompletionDetailsRequestArgs>request.arguments;
|
||||
return {response: this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset,
|
||||
completionDetailsArgs.entryNames,completionDetailsArgs.file)}
|
||||
completionDetailsArgs.entryNames,completionDetailsArgs.file), responseRequired: true}
|
||||
},
|
||||
[CommandNames.SignatureHelp]: (request: protocol.Request) => {
|
||||
var signatureHelpArgs = <protocol.SignatureHelpRequestArgs>request.arguments;
|
||||
return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file)}
|
||||
return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file), responseRequired: true}
|
||||
},
|
||||
[CommandNames.Geterr]: (request: protocol.Request) => {
|
||||
var geterrArgs = <protocol.GeterrRequestArgs>request.arguments;
|
||||
@@ -923,23 +923,23 @@ namespace ts.server {
|
||||
},
|
||||
[CommandNames.Navto]: (request: protocol.Request) => {
|
||||
var navtoArgs = <protocol.NavtoRequestArgs>request.arguments;
|
||||
return {response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount)};
|
||||
return {response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount), responseRequired: true};
|
||||
},
|
||||
[CommandNames.Brace]: (request: protocol.Request) => {
|
||||
var braceArguments = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return {response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file)};
|
||||
return {response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file), responseRequired: true};
|
||||
},
|
||||
[CommandNames.NavBar]: (request: protocol.Request) => {
|
||||
var navBarArgs = <protocol.FileRequestArgs>request.arguments;
|
||||
return {response: this.getNavigationBarItems(navBarArgs.file)};
|
||||
return {response: this.getNavigationBarItems(navBarArgs.file), responseRequired: true};
|
||||
},
|
||||
[CommandNames.Occurrences]: (request: protocol.Request) => {
|
||||
var { line, offset, file: fileName } = <protocol.FileLocationRequestArgs>request.arguments;
|
||||
return {response: this.getOccurrences(line, offset, fileName)};
|
||||
return {response: this.getOccurrences(line, offset, fileName), responseRequired: true};
|
||||
},
|
||||
[CommandNames.ProjectInfo]: (request: protocol.Request) => {
|
||||
var { file, needFileNameList } = <protocol.ProjectInfoRequestArgs>request.arguments;
|
||||
return {response: this.getProjectInfo(file, needFileNameList)};
|
||||
return {response: this.getProjectInfo(file, needFileNameList), responseRequired: true};
|
||||
},
|
||||
};
|
||||
addProtocolHandler(command: string, handler: (request: protocol.Request) => {response?: any, responseRequired: boolean}) {
|
||||
|
||||
@@ -1105,6 +1105,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface HighlightSpan {
|
||||
fileName?: string;
|
||||
textSpan: TextSpan;
|
||||
kind: string;
|
||||
}
|
||||
@@ -1411,7 +1412,9 @@ namespace ts {
|
||||
* @param fileName The name of the file to be released
|
||||
* @param compilationSettings The compilation settings used to acquire the file
|
||||
*/
|
||||
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void
|
||||
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void;
|
||||
|
||||
reportStats(): string;
|
||||
}
|
||||
|
||||
// TODO: move these to enums
|
||||
@@ -3234,8 +3237,19 @@ namespace ts {
|
||||
// We are *only* completing on properties from the type being destructured.
|
||||
isNewIdentifierLocation = false;
|
||||
|
||||
typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
|
||||
existingMembers = (<BindingPattern>objectLikeContainer).elements;
|
||||
let rootDeclaration = getRootDeclaration(objectLikeContainer.parent);
|
||||
if (isVariableLike(rootDeclaration)) {
|
||||
// We don't want to complete using the type acquired by the shape
|
||||
// of the binding pattern; we are only interested in types acquired
|
||||
// through type declaration or inference.
|
||||
if (rootDeclaration.initializer || rootDeclaration.type) {
|
||||
typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
|
||||
existingMembers = (<BindingPattern>objectLikeContainer).elements;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.fail("Root declaration is not variable-like.")
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind);
|
||||
|
||||
+21
-6
@@ -64,8 +64,13 @@ namespace ts {
|
||||
|
||||
/** Public interface of the the of a config service shim instance.*/
|
||||
export interface CoreServicesShimHost extends Logger {
|
||||
/** Returns a JSON-encoded value of the type: string[] */
|
||||
readDirectory(rootDir: string, extension: string): string;
|
||||
/**
|
||||
* Returns a JSON-encoded value of the type: string[]
|
||||
*
|
||||
* @param exclude A JSON encoded string[] containing the paths to exclude
|
||||
* when enumerating the directory.
|
||||
*/
|
||||
readDirectory(rootDir: string, extension: string, exclude?: string): string;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -386,8 +391,18 @@ namespace ts {
|
||||
constructor(private shimHost: CoreServicesShimHost) {
|
||||
}
|
||||
|
||||
public readDirectory(rootDir: string, extension: string): string[] {
|
||||
var encoded = this.shimHost.readDirectory(rootDir, extension);
|
||||
public readDirectory(rootDir: string, extension: string, exclude: string[]): string[] {
|
||||
// Wrap the API changes for 1.5 release. This try/catch
|
||||
// should be removed once TypeScript 1.5 has shipped.
|
||||
// Also consider removing the optional designation for
|
||||
// the exclude param at this time.
|
||||
var encoded: string;
|
||||
try {
|
||||
encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude));
|
||||
}
|
||||
catch (e) {
|
||||
encoded = this.shimHost.readDirectory(rootDir, extension);
|
||||
}
|
||||
return JSON.parse(encoded);
|
||||
}
|
||||
}
|
||||
@@ -439,11 +454,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function realizeDiagnostics(diagnostics: Diagnostic[], newLine: string): { message: string; start: number; length: number; category: string; } []{
|
||||
export function realizeDiagnostics(diagnostics: Diagnostic[], newLine: string): { message: string; start: number; length: number; category: string; code: number; } []{
|
||||
return diagnostics.map(d => realizeDiagnostic(d, newLine));
|
||||
}
|
||||
|
||||
function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; } {
|
||||
function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; code: number; } {
|
||||
return {
|
||||
message: flattenDiagnosticMessageText(diagnostic.messageText, newLine),
|
||||
start: diagnostic.start,
|
||||
|
||||
Reference in New Issue
Block a user