Skip to content

Commit

Permalink
Merge pull request #10679 from Microsoft/mergeMaster_09/01
Browse files Browse the repository at this point in the history
[Transforms] Merge master 09/01
  • Loading branch information
yuit authored Sep 6, 2016
2 parents d7a20f5 + e1be0bc commit 7daf2e3
Show file tree
Hide file tree
Showing 250 changed files with 7,952 additions and 2,976 deletions.
1 change: 1 addition & 0 deletions Jakefile.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ var servicesSources = [
"services.ts",
"shims.ts",
"signatureHelp.ts",
"types.ts",
"utilities.ts",
"formatting/formatting.ts",
"formatting/formattingContext.ts",
Expand Down
76 changes: 55 additions & 21 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ namespace ts {

const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);

const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);

Expand Down Expand Up @@ -1024,8 +1025,8 @@ namespace ts {
}
}

function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration {
return findMap(symbol.declarations, d => isAliasSymbolDeclaration(d) ? d : undefined);
function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration | undefined {
return forEach(symbol.declarations, d => isAliasSymbolDeclaration(d) ? d : undefined);
}

function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration): Symbol {
Expand Down Expand Up @@ -1192,6 +1193,7 @@ namespace ts {
if (!links.target) {
links.target = resolvingSymbol;
const node = getDeclarationOfAliasSymbol(symbol);
Debug.assert(!!node);
const target = getTargetOfAliasDeclaration(node);
if (links.target === resolvingSymbol) {
links.target = target || unknownSymbol;
Expand Down Expand Up @@ -1227,6 +1229,7 @@ namespace ts {
if (!links.referenced) {
links.referenced = true;
const node = getDeclarationOfAliasSymbol(symbol);
Debug.assert(!!node);
if (node.kind === SyntaxKind.ExportAssignment) {
// export default <symbol>
checkExpressionCached((<ExportAssignment>node).expression);
Expand Down Expand Up @@ -3348,7 +3351,13 @@ namespace ts {
// Otherwise, fall back to 'any'.
else {
if (compilerOptions.noImplicitAny) {
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol));
if (setter) {
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
}
else {
Debug.assert(!!getter, "there must existed getter as we are current checking either setter or getter in this function");
error(getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol));
}
}
type = anyType;
}
Expand Down Expand Up @@ -5374,7 +5383,7 @@ namespace ts {
while (i > 0) {
i--;
if (isSubtypeOfAny(types[i], types)) {
types.splice(i, 1);
orderedRemoveItemAt(types, i);
}
}
}
Expand Down Expand Up @@ -8758,7 +8767,7 @@ namespace ts {
// The location isn't a reference to the given symbol, meaning we're being asked
// a hypothetical question of what type the symbol would have if there was a reference
// to it at the given location. Since we have no control flow information for the
// hypotherical reference (control flow information is created and attached by the
// hypothetical reference (control flow information is created and attached by the
// binder), we simply return the declared type of the symbol.
return getTypeOfSymbol(symbol);
}
Expand Down Expand Up @@ -11993,18 +12002,12 @@ namespace ts {
// Function interface, since they have none by default. This is a bit of a leap of faith
// that the user will not add any.
const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);

const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
// TS 1.0 spec: 4.12
// If FuncExpr is of type Any, or of an object type that has no call or construct signatures
// but is a subtype of the Function interface, the call is an untyped function call. In an
// untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual

// TS 1.0 Spec: 4.12
// In an untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual
// types are provided for the argument expressions, and the result is always of type Any.
// We exclude union types because we may have a union of function types that happen to have
// no common signatures.
if (isTypeAny(funcType) ||
(isTypeAny(apparentType) && funcType.flags & TypeFlags.TypeParameter) ||
(!callSignatures.length && !constructSignatures.length && !(funcType.flags & TypeFlags.Union) && isTypeAssignableTo(funcType, globalFunctionType))) {
if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) {
// The unknownType indicates that an error already occurred (and was reported). No
// need to report another error in this case.
if (funcType !== unknownType && node.typeArguments) {
Expand All @@ -12027,6 +12030,29 @@ namespace ts {
return resolveCall(node, callSignatures, candidatesOutArray);
}

/**
* TS 1.0 spec: 4.12
* If FuncExpr is of type Any, or of an object type that has no call or construct signatures
* but is a subtype of the Function interface, the call is an untyped function call.
*/
function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number) {
if (isTypeAny(funcType)) {
return true;
}
if (isTypeAny(apparentFuncType) && funcType.flags & TypeFlags.TypeParameter) {
return true;
}
if (!numCallSignatures && !numConstructSignatures) {
// We exclude union types because we may have a union of function types that happen to have
// no common signatures.
if (funcType.flags & TypeFlags.Union) {
return false;
}
return isTypeAssignableTo(funcType, globalFunctionType);
}
return false;
}

function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[]): Signature {
if (node.arguments && languageVersion < ScriptTarget.ES5) {
const spreadIndex = getSpreadArgumentIndex(node.arguments);
Expand Down Expand Up @@ -12152,8 +12178,9 @@ namespace ts {
}

const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);

if (isTypeAny(tagType) || (!callSignatures.length && !(tagType.flags & TypeFlags.Union) && isTypeAssignableTo(tagType, globalFunctionType))) {
if (isUntypedFunctionCall(tagType, apparentType, callSignatures.length, constructSignatures.length)) {
return resolveUntypedCall(node);
}

Expand Down Expand Up @@ -12198,7 +12225,8 @@ namespace ts {
}

const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
if (funcType === anyType || (!callSignatures.length && !(funcType.flags & TypeFlags.Union) && isTypeAssignableTo(funcType, globalFunctionType))) {
const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) {
return resolveUntypedCall(node);
}

Expand Down Expand Up @@ -12237,10 +12265,10 @@ namespace ts {
// or that a different candidatesOutArray was passed in. Therefore, we need to redo the work
// to correctly fill the candidatesOutArray.
const cached = links.resolvedSignature;
if (cached && cached !== anySignature && !candidatesOutArray) {
if (cached && cached !== resolvingSignature && !candidatesOutArray) {
return cached;
}
links.resolvedSignature = anySignature;
links.resolvedSignature = resolvingSignature;
const result = resolveSignature(node, candidatesOutArray);
// If signature resolution originated in control flow type analysis (for example to compute the
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
Expand All @@ -12252,7 +12280,7 @@ namespace ts {
function getResolvedOrAnySignature(node: CallLikeExpression) {
// If we're already in the process of resolving the given signature, don't resolve again as
// that could cause infinite recursion. Instead, return anySignature.
return getNodeLinks(node).resolvedSignature === anySignature ? anySignature : getResolvedSignature(node);
return getNodeLinks(node).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(node);
}

function getInferredClassType(symbol: Symbol) {
Expand Down Expand Up @@ -18885,7 +18913,13 @@ namespace ts {
(augmentations || (augmentations = [])).push(file.moduleAugmentations);
}
if (file.symbol && file.symbol.globalExports) {
mergeSymbolTable(globals, file.symbol.globalExports);
// Merge in UMD exports with first-in-wins semantics (see #9771)
const source = file.symbol.globalExports;
for (const id in source) {
if (!(id in globals)) {
globals[id] = source[id];
}
}
}
if ((compilerOptions.isolatedModules || isExternalModule(file)) && !file.isDeclarationFile) {
const fileRequestedExternalEmitHelpers = file.flags & NodeFlags.EmitHelperFlags;
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ namespace ts {
function convertCompilerOptionsFromJsonWorker(jsonOptions: any,
basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions {

const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true } : {};
const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true, maxNodeModuleJsDepth: 2 } : {};
convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors);
return options;
}
Expand Down
71 changes: 62 additions & 9 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ namespace ts {
return count;
}

/**
* Filters an array by a predicate function. Returns the same array instance if the predicate is
* true for all elements, otherwise returns a new array instance containing the filtered subset.
*/
export function filter<T, U extends T>(array: T[], f: (x: T) => x is U): U[];
export function filter<T>(array: T[], f: (x: T) => boolean): T[]
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
Expand Down Expand Up @@ -746,6 +750,36 @@ namespace ts {
return result;
}

/**
* Adds the value to an array of values associated with the key, and returns the array.
* Creates the array if it does not already exist.
*/
export function multiMapAdd<V>(map: Map<V[]>, key: string, value: V): V[] {
const values = map[key];
if (values) {
values.push(value);
return values;
}
else {
return map[key] = [value];
}
}

/**
* Removes a value from an array of values associated with the key.
* Does not preserve the order of those values.
* Does nothing if `key` is not in `map`, or `value` is not in `map[key]`.
*/
export function multiMapRemove<V>(map: Map<V[]>, key: string, value: V): void {
const values = map[key];
if (values) {
unorderedRemoveItem(values, value);
if (!values.length) {
delete map[key];
}
}
}

/**
* Tests whether a value is an array.
*/
Expand Down Expand Up @@ -1717,20 +1751,39 @@ namespace ts {
return "";
}

export function copyListRemovingItem<T>(item: T, list: T[]) {
const copiedList: T[] = [];
for (const e of list) {
if (e !== item) {
copiedList.push(e);
/** Remove an item from an array, moving everything to its right one space left. */
export function orderedRemoveItemAt<T>(array: T[], index: number): void {
// This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`.
for (let i = index; i < array.length - 1; i++) {
array[i] = array[i + 1];
}
array.pop();
}

export function unorderedRemoveItemAt<T>(array: T[], index: number): void {
// Fill in the "hole" left at `index`.
array[index] = array[array.length - 1];
array.pop();
}

/** Remove the *first* occurrence of `item` from the array. */
export function unorderedRemoveItem<T>(array: T[], item: T): void {
unorderedRemoveFirstItemWhere(array, element => element === item);
}

/** Remove the *first* element satisfying `predicate`. */
function unorderedRemoveFirstItemWhere<T>(array: T[], predicate: (element: T) => boolean): void {
for (let i = 0; i < array.length; i++) {
if (predicate(array[i])) {
unorderedRemoveItemAt(array, i);
break;
}
}
return copiedList;
}

export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string {
return useCaseSensitivefileNames
export function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean): (fileName: string) => string {
return useCaseSensitiveFileNames
? ((fileName) => fileName)
: ((fileName) => fileName.toLowerCase());
}

}
6 changes: 4 additions & 2 deletions src/compiler/declarationEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1133,8 +1133,10 @@ namespace ts {
// it if it's not a well known symbol. In that case, the text of the name will be exactly
// what we want, namely the name expression enclosed in brackets.
writeTextOfNode(currentText, node.name);
// If optional property emit ?
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.Parameter) && hasQuestionToken(node)) {
// If optional property emit ? but in the case of parameterProperty declaration with "?" indicating optional parameter for the constructor
// we don't want to emit property declaration with "?"
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature ||
(node.kind === SyntaxKind.Parameter && !isParameterPropertyDeclaration(node))) && hasQuestionToken(node)) {
write("?");
}
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) {
Expand Down
14 changes: 9 additions & 5 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2871,11 +2871,7 @@
"Element implicitly has an 'any' type because index expression is not of type 'number'.": {
"category": "Error",
"code": 7015
},
"Property '{0}' implicitly has type 'any', because its 'set' accessor lacks a type annotation.": {
"category": "Error",
"code": 7016
},
},
"Index signature of object type implicitly has an 'any' type.": {
"category": "Error",
"code": 7017
Expand Down Expand Up @@ -2932,6 +2928,14 @@
"category": "Error",
"code": 7031
},
"Property '{0}' implicitly has type 'any', because its set accessor lacks a parameter type annotation.": {
"category": "Error",
"code": 7032
},
"Property '{0}' implicitly has type 'any', because its get accessor lacks a return type annotation.": {
"category": "Error",
"code": 7033
},
"You cannot rename this element.": {
"category": "Error",
"code": 8000
Expand Down
1 change: 1 addition & 0 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2338,6 +2338,7 @@ namespace ts {
token() === SyntaxKind.LessThanToken ||
token() === SyntaxKind.QuestionToken ||
token() === SyntaxKind.ColonToken ||
token() === SyntaxKind.CommaToken ||
canParseSemicolon();
}
return false;
Expand Down
Loading

0 comments on commit 7daf2e3

Please sign in to comment.