Merge branch 'master' of github.com:Microsoft/TypeScript into multiple-prologue-directives

This commit is contained in:
Klaus Meinhardt
2018-07-11 18:47:23 +02:00
103 changed files with 3508 additions and 7430 deletions
+2 -2
View File
@@ -225,11 +225,11 @@ namespace ts {
node.symbol = symbol;
symbol.declarations = append(symbol.declarations, node);
if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) {
if (symbolFlags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.Module | SymbolFlags.Variable) && !symbol.exports) {
symbol.exports = createSymbolTable();
}
if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) {
if (symbolFlags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && !symbol.members) {
symbol.members = createSymbolTable();
}
+107 -39
View File
@@ -2417,12 +2417,12 @@ namespace ts {
// The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example,
// module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error.
function visit(symbol: Symbol | undefined): SymbolTable | undefined {
if (!(symbol && symbol.flags & SymbolFlags.HasExports && pushIfUnique(visitedSymbols, symbol))) {
if (!(symbol && symbol.exports && pushIfUnique(visitedSymbols, symbol))) {
return;
}
const symbols = cloneMap(symbol.exports!);
const symbols = cloneMap(symbol.exports);
// All export * declarations are collected in an __export symbol by the binder
const exportStars = symbol.exports!.get(InternalSymbolName.ExportStar);
const exportStars = symbol.exports.get(InternalSymbolName.ExportStar);
if (exportStars) {
const nestedSymbols = createSymbolTable();
const lookupTable = createMap<ExportCollisionTracker>() as ExportCollisionTrackerTable;
@@ -7702,9 +7702,13 @@ namespace ts {
return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, TypeSystemPropertyName.ResolvedReturnType) >= 0;
}
function getRestTypeOfSignature(signature: Signature) {
function getRestTypeOfSignature(signature: Signature): Type {
return tryGetRestTypeOfSignature(signature) || anyType;
}
function tryGetRestTypeOfSignature(signature: Signature): Type | undefined {
const type = getTypeOfRestParameter(signature);
return type && getIndexTypeOfType(type, IndexKind.Number) || anyType;
return type && getIndexTypeOfType(type, IndexKind.Number);
}
function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature {
@@ -19069,38 +19073,7 @@ namespace ts {
diagnostics.add(createDiagnosticForNode(node, fallbackError));
}
// No signature was applicable. We have already reported the errors for the invalid signature.
// If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
// Pick the longest signature. This way we can get a contextual type for cases like:
// declare function f(a: { xa: number; xb: number; }, b: number);
// f({ |
// Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
// declare function f<T>(k: keyof T);
// f<Foo>("
if (!produceDiagnostics) {
Debug.assert(candidates.length > 0); // Else would have exited above.
const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args!.length : apparentArgumentCount);
const candidate = candidates[bestIndex];
const { typeParameters } = candidate;
if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) {
const typeArguments = node.typeArguments.map(getTypeOfNode) as Type[]; // TODO: GH#18217
while (typeArguments.length > typeParameters.length) {
typeArguments.pop();
}
while (typeArguments.length < typeParameters.length) {
typeArguments.push(getDefaultTypeArgumentType(isInJavaScriptFile(node)));
}
const instantiated = createSignatureInstantiation(candidate, typeArguments);
candidates[bestIndex] = instantiated;
return instantiated;
}
return candidate;
}
return resolveErrorCall(node);
return produceDiagnostics || !args ? resolveErrorCall(node) : getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray);
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
candidateForArgumentError = undefined;
@@ -19171,6 +19144,97 @@ namespace ts {
}
}
// No signature was applicable. We have already reported the errors for the invalid signature.
// If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
function getCandidateForOverloadFailure(
node: CallLikeExpression,
candidates: Signature[],
args: ReadonlyArray<Expression>,
hasCandidatesOutArray: boolean,
): Signature {
Debug.assert(candidates.length > 0); // Else should not have called this.
// Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
// Don't do this if there is a `candidatesOutArray`,
// because then we want the chosen best candidate to be one of the overloads, not a combination.
return hasCandidatesOutArray || candidates.length === 1 || candidates.some(c => !!c.typeParameters)
? pickLongestCandidateSignature(node, candidates, args)
: createUnionOfSignaturesForOverloadFailure(candidates);
}
function createUnionOfSignaturesForOverloadFailure(candidates: ReadonlyArray<Signature>): Signature {
const thisParameters = mapDefined(candidates, c => c.thisParameter);
let thisParameter: Symbol | undefined;
if (thisParameters.length) {
thisParameter = createCombinedSymbolFromTypes(thisParameters, thisParameters.map(getTypeOfParameter));
}
const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters);
const parameters: Symbol[] = [];
for (let i = 0; i < maxNonRestParam; i++) {
const symbols = mapDefined(candidates, ({ parameters, hasRestParameter }) => hasRestParameter ?
i < parameters.length - 1 ? parameters[i] : last(parameters) :
i < parameters.length ? parameters[i] : undefined);
Debug.assert(symbols.length !== 0);
parameters.push(createCombinedSymbolFromTypes(symbols, mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i))));
}
const restParameterSymbols = mapDefined(candidates, c => c.hasRestParameter ? last(c.parameters) : undefined);
const hasRestParameter = restParameterSymbols.length !== 0;
if (hasRestParameter) {
const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), UnionReduction.Subtype));
parameters.push(createCombinedSymbolForOverloadFailure(restParameterSymbols, type));
}
return createSignature(
candidates[0].declaration,
/*typeParameters*/ undefined, // Before calling this we tested for `!candidates.some(c => !!c.typeParameters)`.
thisParameter,
parameters,
/*resolvedReturnType*/ getIntersectionType(candidates.map(getReturnTypeOfSignature)),
/*typePredicate*/ undefined,
minArgumentCount,
hasRestParameter,
/*hasLiteralTypes*/ candidates.some(c => c.hasLiteralTypes));
}
function getNumNonRestParameters(signature: Signature): number {
const numParams = signature.parameters.length;
return signature.hasRestParameter ? numParams - 1 : numParams;
}
function createCombinedSymbolFromTypes(sources: ReadonlyArray<Symbol>, types: Type[]): Symbol {
return createCombinedSymbolForOverloadFailure(sources, getUnionType(types, UnionReduction.Subtype));
}
function createCombinedSymbolForOverloadFailure(sources: ReadonlyArray<Symbol>, type: Type): Symbol {
// This function is currently only used for erroneous overloads, so it's good enough to just use the first source.
return createSymbolWithType(first(sources), type);
}
function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: ReadonlyArray<Expression>): Signature {
// Pick the longest signature. This way we can get a contextual type for cases like:
// declare function f(a: { xa: number; xb: number; }, b: number);
// f({ |
// Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
// declare function f<T>(k: keyof T);
// f<Foo>("
const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount);
const candidate = candidates[bestIndex];
const { typeParameters } = candidate;
if (!typeParameters) {
return candidate;
}
const typeArgumentNodes: ReadonlyArray<TypeNode> = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments || emptyArray : emptyArray;
const typeArguments = typeArgumentNodes.map(n => getTypeOfNode(n) || anyType);
while (typeArguments.length > typeParameters.length) {
typeArguments.pop();
}
while (typeArguments.length < typeParameters.length) {
typeArguments.push(getConstraintFromTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isInJavaScriptFile(node)));
}
const instantiated = createSignatureInstantiation(candidate, typeArguments);
candidates[bestIndex] = instantiated;
return instantiated;
}
function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number {
let maxParamsIndex = -1;
let maxParams = -1;
@@ -19955,6 +20019,10 @@ namespace ts {
}
function getTypeAtPosition(signature: Signature, pos: number): Type {
return tryGetTypeAtPosition(signature, pos) || anyType;
}
function tryGetTypeAtPosition(signature: Signature, pos: number): Type | undefined {
const paramCount = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
if (pos < paramCount) {
return getTypeOfParameter(signature.parameters[pos]);
@@ -19970,9 +20038,9 @@ namespace ts {
return tupleRestType;
}
}
return getIndexTypeOfType(restType, IndexKind.Number) || anyType;
return getIndexTypeOfType(restType, IndexKind.Number);
}
return anyType;
return undefined;
}
function getRestTypeAtPosition(source: Signature, pos: number): Type {
+4
View File
@@ -2864,6 +2864,10 @@
"category": "Error",
"code": 5070
},
"Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs'.": {
"category": "Error",
"code": 5071
},
"Generates a sourcemap for each corresponding '.d.ts' file.": {
"category": "Message",
+4
View File
@@ -2548,6 +2548,10 @@ namespace ts {
if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs) {
createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy, "resolveJsonModule");
}
// Any emit other than common js is error
else if (getEmitModuleKind(options) !== ModuleKind.CommonJS) {
createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs, "resolveJsonModule", "module");
}
}
// there has to be common source directory if user specified --outdir || --sourceRoot
+2 -2
View File
@@ -171,8 +171,8 @@ namespace ts {
}
const t = getTypeOfSymbol(symbol);
visitType(t); // Should handle members on classes and such
if (symbol.flags & SymbolFlags.HasExports) {
symbol.exports!.forEach(visitSymbol);
if (symbol.exports) {
symbol.exports.forEach(visitSymbol);
}
forEach(symbol.declarations, d => {
// Type queries are too far resolved when we just visit the symbol's type
+65 -31
View File
@@ -332,9 +332,9 @@ namespace ts {
/*@internal*/
export interface RecursiveDirectoryWatcherHost {
watchDirectory: HostWatchDirectory;
useCaseSensitiveFileNames: boolean;
getAccessibleSortedChildDirectories(path: string): ReadonlyArray<string>;
directoryExists(dir: string): boolean;
filePathComparer: Comparer<string>;
realpath(s: string): string;
}
@@ -345,60 +345,94 @@ namespace ts {
*/
/*@internal*/
export function createRecursiveDirectoryWatcher(host: RecursiveDirectoryWatcherHost): (directoryName: string, callback: DirectoryWatcherCallback) => FileWatcher {
type ChildWatches = ReadonlyArray<DirectoryWatcher>;
interface DirectoryWatcher extends FileWatcher {
childWatches: ChildWatches;
interface ChildDirectoryWatcher extends FileWatcher {
dirName: string;
}
type ChildWatches = ReadonlyArray<ChildDirectoryWatcher>;
interface HostDirectoryWatcher {
watcher: FileWatcher;
childWatches: ChildWatches;
refCount: number;
}
const cache = createMap<HostDirectoryWatcher>();
const callbackCache = createMultiMap<DirectoryWatcherCallback>();
const filePathComparer = getStringComparer(!host.useCaseSensitiveFileNames);
const toCanonicalFilePath = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
return createDirectoryWatcher;
/**
* Create the directory watcher for the dirPath.
*/
function createDirectoryWatcher(dirName: string, callback: DirectoryWatcherCallback): DirectoryWatcher {
const watcher = host.watchDirectory(dirName, fileName => {
// Call the actual callback
callback(fileName);
function createDirectoryWatcher(dirName: string, callback?: DirectoryWatcherCallback): ChildDirectoryWatcher {
const dirPath = toCanonicalFilePath(dirName) as Path;
let directoryWatcher = cache.get(dirPath);
if (directoryWatcher) {
directoryWatcher.refCount++;
}
else {
directoryWatcher = {
watcher: host.watchDirectory(dirName, fileName => {
// Call the actual callback
callbackCache.forEach((callbacks, rootDirName) => {
if (rootDirName === dirPath || (startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === directorySeparator)) {
callbacks.forEach(callback => callback(fileName));
}
});
// Iterate through existing children and update the watches if needed
updateChildWatches(result, callback);
});
// Iterate through existing children and update the watches if needed
updateChildWatches(dirName, dirPath);
}),
refCount: 1,
childWatches: emptyArray
};
cache.set(dirPath, directoryWatcher);
updateChildWatches(dirName, dirPath);
}
let result: DirectoryWatcher = {
close: () => {
watcher.close();
result.childWatches.forEach(closeFileWatcher);
result = undefined!;
},
if (callback) {
callbackCache.add(dirPath, callback);
}
return {
dirName,
childWatches: emptyArray
close: () => {
const directoryWatcher = Debug.assertDefined(cache.get(dirPath));
if (callback) callbackCache.remove(dirPath, callback);
directoryWatcher.refCount--;
if (directoryWatcher.refCount) return;
cache.delete(dirPath);
closeFileWatcherOf(directoryWatcher);
directoryWatcher.childWatches.forEach(closeFileWatcher);
}
};
updateChildWatches(result, callback);
return result;
}
function updateChildWatches(watcher: DirectoryWatcher, callback: DirectoryWatcherCallback) {
function updateChildWatches(dirName: string, dirPath: Path) {
// Iterate through existing children and update the watches if needed
if (watcher) {
watcher.childWatches = watchChildDirectories(watcher.dirName, watcher.childWatches, callback);
const parentWatcher = cache.get(dirPath);
if (parentWatcher) {
parentWatcher.childWatches = watchChildDirectories(dirName, parentWatcher.childWatches);
}
}
/**
* Watch the directories in the parentDir
*/
function watchChildDirectories(parentDir: string, existingChildWatches: ChildWatches, callback: DirectoryWatcherCallback): ChildWatches {
let newChildWatches: DirectoryWatcher[] | undefined;
enumerateInsertsAndDeletes<string, DirectoryWatcher>(
function watchChildDirectories(parentDir: string, existingChildWatches: ChildWatches): ChildWatches {
let newChildWatches: ChildDirectoryWatcher[] | undefined;
enumerateInsertsAndDeletes<string, ChildDirectoryWatcher>(
host.directoryExists(parentDir) ? mapDefined(host.getAccessibleSortedChildDirectories(parentDir), child => {
const childFullName = getNormalizedAbsolutePath(child, parentDir);
// Filter our the symbolic link directories since those arent included in recursive watch
// which is same behaviour when recursive: true is passed to fs.watch
return host.filePathComparer(childFullName, host.realpath(childFullName)) === Comparison.EqualTo ? childFullName : undefined;
return filePathComparer(childFullName, normalizePath(host.realpath(childFullName))) === Comparison.EqualTo ? childFullName : undefined;
}) : emptyArray,
existingChildWatches,
(child, childWatcher) => host.filePathComparer(child, childWatcher.dirName),
(child, childWatcher) => filePathComparer(child, childWatcher.dirName),
createAndAddChildDirectoryWatcher,
closeFileWatcher,
addChildDirectoryWatcher
@@ -410,14 +444,14 @@ namespace ts {
* Create new childDirectoryWatcher and add it to the new ChildDirectoryWatcher list
*/
function createAndAddChildDirectoryWatcher(childName: string) {
const result = createDirectoryWatcher(childName, callback);
const result = createDirectoryWatcher(childName);
addChildDirectoryWatcher(result);
}
/**
* Add child directory watcher to the new ChildDirectoryWatcher list
*/
function addChildDirectoryWatcher(childWatcher: DirectoryWatcher) {
function addChildDirectoryWatcher(childWatcher: ChildDirectoryWatcher) {
(newChildWatches || (newChildWatches = [])).push(childWatcher);
}
}
@@ -710,7 +744,7 @@ namespace ts {
createWatchDirectoryUsing(dynamicPollingWatchFile || createDynamicPriorityPollingWatchFile({ getModifiedTime, setTimeout })) :
watchDirectoryUsingFsWatch;
const watchDirectoryRecursively = createRecursiveDirectoryWatcher({
filePathComparer: getStringComparer(!useCaseSensitiveFileNames),
useCaseSensitiveFileNames,
directoryExists,
getAccessibleSortedChildDirectories: path => getAccessibleFileSystemEntries(path).directories,
watchDirectory,
+3 -6
View File
@@ -2994,9 +2994,9 @@ namespace ts {
*/
/* @internal */ tryGetMemberInModuleExportsAndProperties(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
getApparentType(type: Type): Type;
getSuggestionForNonexistentProperty(name: Identifier | string, containingType: Type): string | undefined;
getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined;
getSuggestionForNonexistentExport(node: Identifier, target: Symbol): string | undefined;
/* @internal */ getSuggestionForNonexistentProperty(name: Identifier | string, containingType: Type): string | undefined;
/* @internal */ getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined;
/* @internal */ getSuggestionForNonexistentExport(node: Identifier, target: Symbol): string | undefined;
getBaseConstraintOfType(type: Type): Type | undefined;
getDefaultFromTypeParameter(type: Type): Type | undefined;
@@ -3439,9 +3439,6 @@ namespace ts {
ExportHasLocal = Function | Class | Enum | ValueModule,
HasExports = Class | Enum | Module | Variable,
HasMembers = Class | Interface | TypeLiteral | ObjectLiteral,
BlockScoped = BlockScopedVariable | Class | Enum,
PropertyOrAccessor = Property | Accessor,
+16
View File
@@ -8087,4 +8087,20 @@ namespace ts {
Debug.assert(index !== -1);
return arr.slice(index);
}
export function minAndMax<T>(arr: ReadonlyArray<T>, getValue: (value: T) => number): { readonly min: number, readonly max: number } {
Debug.assert(arr.length !== 0);
let min = getValue(arr[0]);
let max = min;
for (let i = 1; i < arr.length; i++) {
const value = getValue(arr[i]);
if (value < min) {
min = value;
}
else if (value > max) {
max = value;
}
}
return { min, max };
}
}
+20 -1
View File
@@ -398,7 +398,7 @@ namespace ts {
case WatchLogLevel.TriggerOnly:
return createFileWatcherWithTriggerLogging;
case WatchLogLevel.Verbose:
return createFileWatcherWithLogging;
return addWatch === <any>watchDirectory ? createDirectoryWatcherWithLogging : createFileWatcherWithLogging;
}
}
@@ -413,6 +413,25 @@ namespace ts {
};
}
function createDirectoryWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
const watchInfo = `${watchCaption}:: Added:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
log(watchInfo);
const start = timestamp();
const watcher = createFileWatcherWithTriggerLogging(host, file, cb, flags, passThrough, detailInfo1, detailInfo2, addWatch, log, watchCaption, getDetailWatchInfo);
const elapsed = timestamp() - start;
log(`Elapsed:: ${elapsed}ms ${watchInfo}`);
return {
close: () => {
const watchInfo = `${watchCaption}:: Close:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
log(watchInfo);
const start = timestamp();
watcher.close();
const elapsed = timestamp() - start;
log(`Elapsed:: ${elapsed}ms ${watchInfo}`);
}
};
}
function createFileWatcherWithTriggerLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
return addWatch(host, file, (fileName, cbOptional) => {
const triggerredInfo = `${watchCaption}:: Triggered with ${fileName}${cbOptional !== undefined ? cbOptional : ""}:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;