mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into errorForUseSuperInNullExtension
This commit is contained in:
+196
-104
@@ -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;
|
||||
@@ -2177,35 +2190,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 +2321,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 +2350,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 +2358,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 +2383,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 +2484,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 +2515,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 +2556,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 +2772,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 +2899,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);
|
||||
@@ -3534,7 +3586,7 @@ namespace ts {
|
||||
|
||||
function getReturnTypeOfSignature(signature: Signature): Type {
|
||||
if (!signature.resolvedReturnType) {
|
||||
if (!pushTypeResolution(signature)) {
|
||||
if (!pushTypeResolution(signature, TypeSystemPropertyName.ResolvedReturnType)) {
|
||||
return unknownType;
|
||||
}
|
||||
let type: Type;
|
||||
@@ -4179,7 +4231,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 +4296,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 {
|
||||
@@ -5463,7 +5518,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 +5888,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 +6780,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
|
||||
@@ -8487,6 +8516,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;
|
||||
}
|
||||
}
|
||||
@@ -8856,13 +8888,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 +9153,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9792,7 +9872,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 +10117,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
checkTypeAssignableTo(typePredicate.type,
|
||||
getTypeAtLocation(node.parameters[typePredicate.parameterIndex]),
|
||||
getTypeOfNode(node.parameters[typePredicate.parameterIndex]),
|
||||
typePredicateNode.type);
|
||||
}
|
||||
}
|
||||
@@ -13667,7 +13747,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;
|
||||
@@ -13678,10 +13758,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) {
|
||||
@@ -13758,24 +13850,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);
|
||||
}
|
||||
|
||||
@@ -13784,7 +13876,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);
|
||||
}
|
||||
|
||||
+35
-3
@@ -3012,6 +3012,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 +3054,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 +3271,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 +4241,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 +4284,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();
|
||||
@@ -5529,6 +5560,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
write(")");
|
||||
}
|
||||
else {
|
||||
emitEs6ExportDefaultCompat(node);
|
||||
emitContainingModuleName(node);
|
||||
if (languageVersion === ScriptTarget.ES3) {
|
||||
write("[\"default\"] = ");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1912,6 +1912,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 */
|
||||
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -671,20 +671,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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+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}) {
|
||||
|
||||
@@ -3234,8 +3234,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);
|
||||
|
||||
+19
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user