diff --git a/TypeScript b/TypeScript index 10d1e02..80c04f8 160000 --- a/TypeScript +++ b/TypeScript @@ -1 +1 @@ -Subproject commit 10d1e02916578e4ece7bd24352f144be1eb72305 +Subproject commit 80c04f8e97aa7ab6c0e1fb604bf1551e7057183c diff --git a/bin/lib.es2015.core.d.ts b/bin/lib.es2015.core.d.ts index 49c5de6..f8eba59 100644 --- a/bin/lib.es2015.core.d.ts +++ b/bin/lib.es2015.core.d.ts @@ -84,6 +84,10 @@ interface ArrayConstructor { of(...items: T[]): Array; } +interface DateConstructor { + new (value: Date): Date; +} + interface Function { /** * Returns the name of the function. Function names are read-only and can not be changed. diff --git a/bin/lib.es6.d.ts b/bin/lib.es6.d.ts index b7ac7de..35c84ee 100644 --- a/bin/lib.es6.d.ts +++ b/bin/lib.es6.d.ts @@ -4195,6 +4195,10 @@ interface ArrayConstructor { of(...items: T[]): Array; } +interface DateConstructor { + new (value: Date): Date; +} + interface Function { /** * Returns the name of the function. Function names are read-only and can not be changed. diff --git a/bin/ntypescript.d.ts b/bin/ntypescript.d.ts index 208316e..9e133e0 100644 --- a/bin/ntypescript.d.ts +++ b/bin/ntypescript.d.ts @@ -2184,52 +2184,45 @@ declare namespace ts { /** Gets a timestamp with (at least) ms resolution */ const timestamp: () => number; } +/** Performance measurements for the compiler. */ declare namespace ts.performance { /** - * Emit a performance event if ts-profiler is connected. This is primarily used - * to generate heap snapshots. + * Marks a performance event. * - * @param eventName A name for the event. + * @param markName The name of the mark. */ - function emit(eventName: string): void; + function mark(markName: string): void; /** - * Increments a counter with the specified name. + * Adds a performance measurement with the specified name. * - * @param counterName The name of the counter. + * @param measureName The name of the performance measurement. + * @param startMarkName The name of the starting mark. If not supplied, the point at which the + * profiler was enabled is used. + * @param endMarkName The name of the ending mark. If not supplied, the current timestamp is + * used. */ - function increment(counterName: string): void; + function measure(measureName: string, startMarkName?: string, endMarkName?: string): void; /** - * Gets the value of the counter with the specified name. + * Gets the number of times a marker was encountered. * - * @param counterName The name of the counter. + * @param markName The name of the mark. */ - function getCount(counterName: string): number; + function getCount(markName: string): number; /** - * Marks the start of a performance measurement. - */ - function mark(): number; - /** - * Adds a performance measurement with the specified name. + * Gets the total duration of all measurements with the supplied name. * - * @param measureName The name of the performance measurement. - * @param marker The timestamp of the starting mark. + * @param measureName The name of the measure whose durations should be accumulated. */ - function measure(measureName: string, marker: number): void; + function getDuration(measureName: string): number; /** * Iterate over each measure, performing some action * * @param cb The action to perform for each measure */ function forEachMeasure(cb: (measureName: string, duration: number) => void): void; - /** - * Gets the total duration of all measurements with the supplied name. - * - * @param measureName The name of the measure whose durations should be accumulated. - */ - function getDuration(measureName: string): number; /** Enables (and resets) performance measurements for the compiler. */ function enable(): void; - /** Disables (and clears) performance measurements for the compiler. */ + /** Disables performance measurements for the compiler. */ function disable(): void; } declare namespace ts { @@ -7071,6 +7064,12 @@ declare namespace ts { key: string; message: string; }; + Property_0_is_declared_but_never_used: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; Variable_0_implicitly_has_an_1_type: { code: number; category: DiagnosticCategory; diff --git a/bin/ntypescript.js b/bin/ntypescript.js index 8da11f0..6eca38e 100644 --- a/bin/ntypescript.js +++ b/bin/ntypescript.js @@ -894,104 +894,90 @@ var ts; ts.timestamp = typeof performance !== "undefined" && performance.now ? function () { return performance.now(); } : Date.now ? Date.now : function () { return +(new Date()); }; })(ts || (ts = {})); /*@internal*/ +/** Performance measurements for the compiler. */ var ts; (function (ts) { var performance; (function (performance) { - var profilerEvent; - var counters; + var profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true + ? onProfilerEvent + : function (markName) { }; + var enabled = false; + var profilerStart = 0; + var counts; + var marks; var measures; /** - * Emit a performance event if ts-profiler is connected. This is primarily used - * to generate heap snapshots. + * Marks a performance event. * - * @param eventName A name for the event. + * @param markName The name of the mark. */ - function emit(eventName) { - if (profilerEvent) { - profilerEvent(eventName); + function mark(markName) { + if (enabled) { + marks[markName] = ts.timestamp(); + counts[markName] = (counts[markName] || 0) + 1; + profilerEvent(markName); } } - performance.emit = emit; + performance.mark = mark; /** - * Increments a counter with the specified name. + * Adds a performance measurement with the specified name. * - * @param counterName The name of the counter. + * @param measureName The name of the performance measurement. + * @param startMarkName The name of the starting mark. If not supplied, the point at which the + * profiler was enabled is used. + * @param endMarkName The name of the ending mark. If not supplied, the current timestamp is + * used. */ - function increment(counterName) { - if (counters) { - counters[counterName] = (ts.getProperty(counters, counterName) || 0) + 1; + function measure(measureName, startMarkName, endMarkName) { + if (enabled) { + var end = endMarkName && marks[endMarkName] || ts.timestamp(); + var start = startMarkName && marks[startMarkName] || profilerStart; + measures[measureName] = (measures[measureName] || 0) + (end - start); } } - performance.increment = increment; + performance.measure = measure; /** - * Gets the value of the counter with the specified name. + * Gets the number of times a marker was encountered. * - * @param counterName The name of the counter. + * @param markName The name of the mark. */ - function getCount(counterName) { - return counters && ts.getProperty(counters, counterName) || 0; + function getCount(markName) { + return counts && counts[markName] || 0; } performance.getCount = getCount; /** - * Marks the start of a performance measurement. - */ - function mark() { - return measures ? ts.timestamp() : 0; - } - performance.mark = mark; - /** - * Adds a performance measurement with the specified name. + * Gets the total duration of all measurements with the supplied name. * - * @param measureName The name of the performance measurement. - * @param marker The timestamp of the starting mark. + * @param measureName The name of the measure whose durations should be accumulated. */ - function measure(measureName, marker) { - if (measures) { - measures[measureName] = (ts.getProperty(measures, measureName) || 0) + (ts.timestamp() - marker); - } + function getDuration(measureName) { + return measures && measures[measureName] || 0; } - performance.measure = measure; + performance.getDuration = getDuration; /** * Iterate over each measure, performing some action * * @param cb The action to perform for each measure */ function forEachMeasure(cb) { - return ts.forEachKey(measures, function (key) { return cb(key, measures[key]); }); + for (var key in measures) { + cb(key, measures[key]); + } } performance.forEachMeasure = forEachMeasure; - /** - * Gets the total duration of all measurements with the supplied name. - * - * @param measureName The name of the measure whose durations should be accumulated. - */ - function getDuration(measureName) { - return measures && ts.getProperty(measures, measureName) || 0; - } - performance.getDuration = getDuration; /** Enables (and resets) performance measurements for the compiler. */ function enable() { - counters = {}; - measures = { - "I/O Read": 0, - "I/O Write": 0, - "Program": 0, - "Parse": 0, - "Bind": 0, - "Check": 0, - "Emit": 0, - }; - profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true - ? onProfilerEvent - : undefined; + counts = ts.createMap(); + marks = ts.createMap(); + measures = ts.createMap(); + enabled = true; + profilerStart = ts.timestamp(); } performance.enable = enable; - /** Disables (and clears) performance measurements for the compiler. */ + /** Disables performance measurements for the compiler. */ function disable() { - counters = undefined; - measures = undefined; - profilerEvent = undefined; + enabled = false; } performance.disable = disable; })(performance = ts.performance || (ts.performance = {})); @@ -6391,6 +6377,7 @@ var ts; Report_errors_on_unused_parameters: { code: 6135, category: ts.DiagnosticCategory.Message, key: "Report_errors_on_unused_parameters_6135", message: "Report errors on unused parameters." }, The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files: { code: 6136, category: ts.DiagnosticCategory.Message, key: "The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files_6136", message: "The maximum dependency depth to search under node_modules and load JavaScript files" }, No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0: { code: 6137, category: ts.DiagnosticCategory.Message, key: "No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0_6137", message: "No types specified in 'package.json' but 'allowJs' is set, so returning 'main' value of '{0}'" }, + Property_0_is_declared_but_never_used: { code: 6138, category: ts.DiagnosticCategory.Error, key: "Property_0_is_declared_but_never_used_6138", message: "Property '{0}' is declared but never used." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable_0_implicitly_has_an_1_type_7005", message: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter_0_implicitly_has_an_1_type_7006", message: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member_0_implicitly_has_an_1_type_7008", message: "Member '{0}' implicitly has an '{1}' type." }, @@ -8517,9 +8504,10 @@ var ts; ts.forEachChild = forEachChild; function createSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind) { if (setParentNodes === void 0) { setParentNodes = false; } - var start = ts.performance.mark(); + ts.performance.mark("beforeParse"); var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); - ts.performance.measure("Parse", start); + ts.performance.mark("afterParse"); + ts.performance.measure("Parse", "beforeParse", "afterParse"); return result; } ts.createSourceFile = createSourceFile; @@ -14398,9 +14386,10 @@ var ts; })(ContainerFlags || (ContainerFlags = {})); var binder = createBinder(); function bindSourceFile(file, options) { - var start = ts.performance.mark(); + ts.performance.mark("beforeBind"); binder(file, options); - ts.performance.measure("Bind", start); + ts.performance.mark("afterBind"); + ts.performance.measure("Bind", "beforeBind", "afterBind"); } ts.bindSourceFile = bindSourceFile; function createBinder() { @@ -16109,7 +16098,18 @@ var ts; assignee = container; } else if (container.kind === 148 /* Constructor */) { - assignee = container.parent; + if (ts.isInJavaScriptFile(node)) { + // this.foo assignment in a JavaScript class + // Bind this property to the containing class + var saveContainer = container; + container = container.parent; + bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* None */); + container = saveContainer; + return; + } + else { + assignee = container.parent; + } } else { return; @@ -19275,6 +19275,13 @@ var ts; // * className.prototype.method = expr if (declaration.kind === 187 /* BinaryExpression */ || declaration.kind === 172 /* PropertyAccessExpression */ && declaration.parent.kind === 187 /* BinaryExpression */) { + // Use JS Doc type if present on parent expression statement + if (declaration.flags & 134217728 /* JavaScriptFile */) { + var typeTag = ts.getJSDocTypeTag(declaration.parent); + if (typeTag && typeTag.typeExpression) { + return links.type = getTypeFromTypeNode(typeTag.typeExpression.type); + } + } var declaredTypes = ts.map(symbol.declarations, function (decl) { return decl.kind === 187 /* BinaryExpression */ ? checkExpressionCached(decl.right) : checkExpressionCached(decl.parent.right); }); @@ -24182,10 +24189,6 @@ var ts; } return type; } - // We never narrow type any in an instanceof guard - if (isTypeAny(type)) { - return type; - } // Check that right operand is a function type with a prototype property var rightType = checkExpression(expr.right); if (!isTypeSubtypeOf(rightType, globalFunctionType)) { @@ -24200,6 +24203,10 @@ var ts; targetType = prototypePropertyType; } } + // Don't narrow from 'any' if the target type is exactly 'Object' or 'Function' + if (isTypeAny(type) && (targetType === globalObjectType || targetType === globalFunctionType)) { + return type; + } if (!targetType) { // Target type is type of construct signature var constructSignatures = void 0; @@ -24242,7 +24249,7 @@ var ts; getIntersectionType([type, candidate]); } function narrowTypeByTypePredicate(type, callExpression, assumeTrue) { - if (type.flags & 1 /* Any */ || !hasMatchingArgument(callExpression, reference)) { + if (!hasMatchingArgument(callExpression, reference)) { return type; } var signature = getResolvedSignature(callExpression); @@ -24250,6 +24257,10 @@ var ts; if (!predicate) { return type; } + // Don't narrow from 'any' if the predicate type is exactly 'Object' or 'Function' + if (isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType)) { + return type; + } if (ts.isIdentifierTypePredicate(predicate)) { var predicateArgument = callExpression.arguments[predicate.parameterIndex]; if (predicateArgument) { @@ -24987,6 +24998,10 @@ var ts; var binaryExpression = node.parent; var operator = binaryExpression.operatorToken.kind; if (operator >= 56 /* FirstAssignment */ && operator <= 68 /* LastAssignment */) { + // Don't do this for special property assignments to avoid circularity + if (ts.getSpecialPropertyAssignmentKind(binaryExpression) !== 0 /* None */) { + return undefined; + } // In an assignment expression, the right operand is contextually typed by the type of the left operand. if (node === binaryExpression.right) { return checkExpression(binaryExpression.left); @@ -28891,7 +28906,12 @@ var ts; } } function checkClassForDuplicateDeclarations(node) { - var getter = 1, setter = 2, property = getter | setter; + var Accessor; + (function (Accessor) { + Accessor[Accessor["Getter"] = 1] = "Getter"; + Accessor[Accessor["Setter"] = 2] = "Setter"; + Accessor[Accessor["Property"] = 3] = "Property"; + })(Accessor || (Accessor = {})); var instanceNames = ts.createMap(); var staticNames = ts.createMap(); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { @@ -28900,7 +28920,7 @@ var ts; for (var _b = 0, _c = member.parameters; _b < _c.length; _b++) { var param = _c[_b]; if (ts.isParameterPropertyDeclaration(param)) { - addName(instanceNames, param.name, param.name.text, property); + addName(instanceNames, param.name, param.name.text, 3 /* Property */); } } } @@ -28911,13 +28931,13 @@ var ts; if (memberName) { switch (member.kind) { case 149 /* GetAccessor */: - addName(names, member.name, memberName, getter); + addName(names, member.name, memberName, 1 /* Getter */); break; case 150 /* SetAccessor */: - addName(names, member.name, memberName, setter); + addName(names, member.name, memberName, 2 /* Setter */); break; case 145 /* PropertyDeclaration */: - addName(names, member.name, memberName, property); + addName(names, member.name, memberName, 3 /* Property */); break; } } @@ -30061,7 +30081,7 @@ var ts; for (var _b = 0, _c = member.parameters; _b < _c.length; _b++) { var parameter = _c[_b]; if (!parameter.symbol.isReferenced && parameter.flags & 8 /* Private */) { - error(parameter.name, ts.Diagnostics._0_is_declared_but_never_used, parameter.symbol.name); + error(parameter.name, ts.Diagnostics.Property_0_is_declared_but_never_used, parameter.symbol.name); } } } @@ -32253,9 +32273,10 @@ var ts; } } function checkSourceFile(node) { - var start = ts.performance.mark(); + ts.performance.mark("beforeCheck"); checkSourceFileWorker(node); - ts.performance.measure("Check", start); + ts.performance.mark("afterCheck"); + ts.performance.measure("Check", "beforeCheck", "afterCheck"); } // Fully type check a source file and collect the relevant diagnostics. function checkSourceFileWorker(node) { @@ -37074,6 +37095,7 @@ var ts; ts.getNullSourceMapWriter = getNullSourceMapWriter; function createSourceMapWriter(host, writer) { var compilerOptions = host.getCompilerOptions(); + var extendedDiagnostics = compilerOptions.extendedDiagnostics; var currentSourceFile; var sourceMapDir; // The directory in which sourcemap will be var stopOverridingSpan = false; @@ -37237,7 +37259,9 @@ var ts; if (pos === -1) { return; } - var start = ts.performance.mark(); + if (extendedDiagnostics) { + ts.performance.mark("beforeSourcemap"); + } var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos); // Convert the location to be one-based. sourceLinePos.line++; @@ -37270,7 +37294,10 @@ var ts; lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex; } updateLastEncodedAndRecordedSpans(); - ts.performance.measure("Source Map", start); + if (extendedDiagnostics) { + ts.performance.mark("afterSourcemap"); + ts.performance.measure("Source Map", "beforeSourcemap", "afterSourcemap"); + } } function getStartPos(range) { var rangeHasDecorators = !!range.decorators; @@ -45504,9 +45531,10 @@ var ts; function getSourceFile(fileName, languageVersion, onError) { var text; try { - var start = ts.performance.mark(); + ts.performance.mark("beforeIORead"); text = ts.sys.readFile(fileName, options.charset); - ts.performance.measure("I/O Read", start); + ts.performance.mark("afterIORead"); + ts.performance.measure("I/O Read", "beforeIORead", "afterIORead"); } catch (e) { if (onError) { @@ -45561,7 +45589,7 @@ var ts; } function writeFile(fileName, data, writeByteOrderMark, onError) { try { - var start = ts.performance.mark(); + ts.performance.mark("beforeIOWrite"); ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName))); if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) { writeFileIfUpdated(fileName, data, writeByteOrderMark); @@ -45569,7 +45597,8 @@ var ts; else { ts.sys.writeFile(fileName, data, writeByteOrderMark); } - ts.performance.measure("I/O Write", start); + ts.performance.mark("afterIOWrite"); + ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite"); } catch (e) { if (onError) { @@ -45729,7 +45758,7 @@ var ts; var modulesWithElidedImports = ts.createMap(); // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. var sourceFilesFoundSearchingNodeModules = ts.createMap(); - var start = ts.performance.mark(); + ts.performance.mark("beforeProgram"); host = host || createCompilerHost(options); var skipDefaultLib = options.noLib; var programDiagnostics = ts.createDiagnosticCollection(); @@ -45814,7 +45843,8 @@ var ts; getResolvedTypeReferenceDirectives: function () { return resolvedTypeReferenceDirectives; } }; verifyCompilerOptions(); - ts.performance.measure("Program", start); + ts.performance.mark("afterProgram"); + ts.performance.measure("Program", "beforeProgram", "afterProgram"); return program; function getCommonSourceDirectory() { if (typeof commonSourceDirectory === "undefined") { @@ -46020,9 +46050,10 @@ var ts; // files need to be type checked. And the way to specify that all files need to be type // checked is to not pass the file to getEmitResolver. var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile); - var start = ts.performance.mark(); + ts.performance.mark("beforeEmit"); var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile); - ts.performance.measure("Emit", start); + ts.performance.mark("afterEmit"); + ts.performance.measure("Emit", "beforeEmit", "afterEmit"); return emitResult; } function getSourceFile(fileName) { @@ -46174,16 +46205,16 @@ var ts; case 175 /* NewExpression */: var expression = node; if (expression.typeArguments && expression.typeArguments.length > 0) { - var start_2 = expression.typeArguments.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start_2, expression.typeArguments.end - start_2, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file)); + var start = expression.typeArguments.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file)); return true; } break; case 142 /* Parameter */: var parameter = node; if (parameter.modifiers) { - var start_3 = parameter.modifiers.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start_3, parameter.modifiers.end - start_3, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file)); + var start = parameter.modifiers.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file)); return true; } if (parameter.questionToken) { @@ -46227,8 +46258,8 @@ var ts; } function checkTypeParameters(typeParameters) { if (typeParameters) { - var start_4 = typeParameters.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start_4, typeParameters.end - start_4, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file)); + var start = typeParameters.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, typeParameters.end - start, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file)); return true; } return false; @@ -55775,9 +55806,9 @@ var ts; // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && ts.isWord(contextToken.kind)) { - var start_5 = ts.timestamp(); + var start_2 = ts.timestamp(); contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile); - log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_5)); + log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_2)); } // Find the node where completion is requested on. // Also determine whether we are trying to complete with members of that node @@ -56056,13 +56087,13 @@ var ts; if (contextToken.kind === 9 /* StringLiteral */ || contextToken.kind === 10 /* RegularExpressionLiteral */ || ts.isTemplateLiteralKind(contextToken.kind)) { - var start_6 = contextToken.getStart(); + var start_3 = contextToken.getStart(); var end = contextToken.getEnd(); // To be "in" one of these literals, the position has to be: // 1. entirely within the token text. // 2. at the end position of an unterminated token. // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). - if (start_6 < position && position < end) { + if (start_3 < position && position < end) { return true; } if (position === end) { diff --git a/bin/typescript.d.ts b/bin/typescript.d.ts index 1353e13..5e04e47 100644 --- a/bin/typescript.d.ts +++ b/bin/typescript.d.ts @@ -2184,52 +2184,45 @@ declare namespace ts { /** Gets a timestamp with (at least) ms resolution */ const timestamp: () => number; } +/** Performance measurements for the compiler. */ declare namespace ts.performance { /** - * Emit a performance event if ts-profiler is connected. This is primarily used - * to generate heap snapshots. + * Marks a performance event. * - * @param eventName A name for the event. + * @param markName The name of the mark. */ - function emit(eventName: string): void; + function mark(markName: string): void; /** - * Increments a counter with the specified name. + * Adds a performance measurement with the specified name. * - * @param counterName The name of the counter. + * @param measureName The name of the performance measurement. + * @param startMarkName The name of the starting mark. If not supplied, the point at which the + * profiler was enabled is used. + * @param endMarkName The name of the ending mark. If not supplied, the current timestamp is + * used. */ - function increment(counterName: string): void; + function measure(measureName: string, startMarkName?: string, endMarkName?: string): void; /** - * Gets the value of the counter with the specified name. + * Gets the number of times a marker was encountered. * - * @param counterName The name of the counter. + * @param markName The name of the mark. */ - function getCount(counterName: string): number; + function getCount(markName: string): number; /** - * Marks the start of a performance measurement. - */ - function mark(): number; - /** - * Adds a performance measurement with the specified name. + * Gets the total duration of all measurements with the supplied name. * - * @param measureName The name of the performance measurement. - * @param marker The timestamp of the starting mark. + * @param measureName The name of the measure whose durations should be accumulated. */ - function measure(measureName: string, marker: number): void; + function getDuration(measureName: string): number; /** * Iterate over each measure, performing some action * * @param cb The action to perform for each measure */ function forEachMeasure(cb: (measureName: string, duration: number) => void): void; - /** - * Gets the total duration of all measurements with the supplied name. - * - * @param measureName The name of the measure whose durations should be accumulated. - */ - function getDuration(measureName: string): number; /** Enables (and resets) performance measurements for the compiler. */ function enable(): void; - /** Disables (and clears) performance measurements for the compiler. */ + /** Disables performance measurements for the compiler. */ function disable(): void; } declare namespace ts { @@ -7071,6 +7064,12 @@ declare namespace ts { key: string; message: string; }; + Property_0_is_declared_but_never_used: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; Variable_0_implicitly_has_an_1_type: { code: number; category: DiagnosticCategory; diff --git a/bin/typescript.js b/bin/typescript.js index 1167f6b..4ce3b4d 100644 --- a/bin/typescript.js +++ b/bin/typescript.js @@ -894,104 +894,90 @@ var ts; ts.timestamp = typeof performance !== "undefined" && performance.now ? function () { return performance.now(); } : Date.now ? Date.now : function () { return +(new Date()); }; })(ts || (ts = {})); /*@internal*/ +/** Performance measurements for the compiler. */ var ts; (function (ts) { var performance; (function (performance) { - var profilerEvent; - var counters; + var profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true + ? onProfilerEvent + : function (markName) { }; + var enabled = false; + var profilerStart = 0; + var counts; + var marks; var measures; /** - * Emit a performance event if ts-profiler is connected. This is primarily used - * to generate heap snapshots. + * Marks a performance event. * - * @param eventName A name for the event. + * @param markName The name of the mark. */ - function emit(eventName) { - if (profilerEvent) { - profilerEvent(eventName); + function mark(markName) { + if (enabled) { + marks[markName] = ts.timestamp(); + counts[markName] = (counts[markName] || 0) + 1; + profilerEvent(markName); } } - performance.emit = emit; + performance.mark = mark; /** - * Increments a counter with the specified name. + * Adds a performance measurement with the specified name. * - * @param counterName The name of the counter. + * @param measureName The name of the performance measurement. + * @param startMarkName The name of the starting mark. If not supplied, the point at which the + * profiler was enabled is used. + * @param endMarkName The name of the ending mark. If not supplied, the current timestamp is + * used. */ - function increment(counterName) { - if (counters) { - counters[counterName] = (ts.getProperty(counters, counterName) || 0) + 1; + function measure(measureName, startMarkName, endMarkName) { + if (enabled) { + var end = endMarkName && marks[endMarkName] || ts.timestamp(); + var start = startMarkName && marks[startMarkName] || profilerStart; + measures[measureName] = (measures[measureName] || 0) + (end - start); } } - performance.increment = increment; + performance.measure = measure; /** - * Gets the value of the counter with the specified name. + * Gets the number of times a marker was encountered. * - * @param counterName The name of the counter. + * @param markName The name of the mark. */ - function getCount(counterName) { - return counters && ts.getProperty(counters, counterName) || 0; + function getCount(markName) { + return counts && counts[markName] || 0; } performance.getCount = getCount; /** - * Marks the start of a performance measurement. - */ - function mark() { - return measures ? ts.timestamp() : 0; - } - performance.mark = mark; - /** - * Adds a performance measurement with the specified name. + * Gets the total duration of all measurements with the supplied name. * - * @param measureName The name of the performance measurement. - * @param marker The timestamp of the starting mark. + * @param measureName The name of the measure whose durations should be accumulated. */ - function measure(measureName, marker) { - if (measures) { - measures[measureName] = (ts.getProperty(measures, measureName) || 0) + (ts.timestamp() - marker); - } + function getDuration(measureName) { + return measures && measures[measureName] || 0; } - performance.measure = measure; + performance.getDuration = getDuration; /** * Iterate over each measure, performing some action * * @param cb The action to perform for each measure */ function forEachMeasure(cb) { - return ts.forEachKey(measures, function (key) { return cb(key, measures[key]); }); + for (var key in measures) { + cb(key, measures[key]); + } } performance.forEachMeasure = forEachMeasure; - /** - * Gets the total duration of all measurements with the supplied name. - * - * @param measureName The name of the measure whose durations should be accumulated. - */ - function getDuration(measureName) { - return measures && ts.getProperty(measures, measureName) || 0; - } - performance.getDuration = getDuration; /** Enables (and resets) performance measurements for the compiler. */ function enable() { - counters = {}; - measures = { - "I/O Read": 0, - "I/O Write": 0, - "Program": 0, - "Parse": 0, - "Bind": 0, - "Check": 0, - "Emit": 0, - }; - profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true - ? onProfilerEvent - : undefined; + counts = ts.createMap(); + marks = ts.createMap(); + measures = ts.createMap(); + enabled = true; + profilerStart = ts.timestamp(); } performance.enable = enable; - /** Disables (and clears) performance measurements for the compiler. */ + /** Disables performance measurements for the compiler. */ function disable() { - counters = undefined; - measures = undefined; - profilerEvent = undefined; + enabled = false; } performance.disable = disable; })(performance = ts.performance || (ts.performance = {})); @@ -6391,6 +6377,7 @@ var ts; Report_errors_on_unused_parameters: { code: 6135, category: ts.DiagnosticCategory.Message, key: "Report_errors_on_unused_parameters_6135", message: "Report errors on unused parameters." }, The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files: { code: 6136, category: ts.DiagnosticCategory.Message, key: "The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files_6136", message: "The maximum dependency depth to search under node_modules and load JavaScript files" }, No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0: { code: 6137, category: ts.DiagnosticCategory.Message, key: "No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0_6137", message: "No types specified in 'package.json' but 'allowJs' is set, so returning 'main' value of '{0}'" }, + Property_0_is_declared_but_never_used: { code: 6138, category: ts.DiagnosticCategory.Error, key: "Property_0_is_declared_but_never_used_6138", message: "Property '{0}' is declared but never used." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable_0_implicitly_has_an_1_type_7005", message: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter_0_implicitly_has_an_1_type_7006", message: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member_0_implicitly_has_an_1_type_7008", message: "Member '{0}' implicitly has an '{1}' type." }, @@ -8517,9 +8504,10 @@ var ts; ts.forEachChild = forEachChild; function createSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind) { if (setParentNodes === void 0) { setParentNodes = false; } - var start = ts.performance.mark(); + ts.performance.mark("beforeParse"); var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); - ts.performance.measure("Parse", start); + ts.performance.mark("afterParse"); + ts.performance.measure("Parse", "beforeParse", "afterParse"); return result; } ts.createSourceFile = createSourceFile; @@ -14398,9 +14386,10 @@ var ts; })(ContainerFlags || (ContainerFlags = {})); var binder = createBinder(); function bindSourceFile(file, options) { - var start = ts.performance.mark(); + ts.performance.mark("beforeBind"); binder(file, options); - ts.performance.measure("Bind", start); + ts.performance.mark("afterBind"); + ts.performance.measure("Bind", "beforeBind", "afterBind"); } ts.bindSourceFile = bindSourceFile; function createBinder() { @@ -16109,7 +16098,18 @@ var ts; assignee = container; } else if (container.kind === 148 /* Constructor */) { - assignee = container.parent; + if (ts.isInJavaScriptFile(node)) { + // this.foo assignment in a JavaScript class + // Bind this property to the containing class + var saveContainer = container; + container = container.parent; + bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* None */); + container = saveContainer; + return; + } + else { + assignee = container.parent; + } } else { return; @@ -19275,6 +19275,13 @@ var ts; // * className.prototype.method = expr if (declaration.kind === 187 /* BinaryExpression */ || declaration.kind === 172 /* PropertyAccessExpression */ && declaration.parent.kind === 187 /* BinaryExpression */) { + // Use JS Doc type if present on parent expression statement + if (declaration.flags & 134217728 /* JavaScriptFile */) { + var typeTag = ts.getJSDocTypeTag(declaration.parent); + if (typeTag && typeTag.typeExpression) { + return links.type = getTypeFromTypeNode(typeTag.typeExpression.type); + } + } var declaredTypes = ts.map(symbol.declarations, function (decl) { return decl.kind === 187 /* BinaryExpression */ ? checkExpressionCached(decl.right) : checkExpressionCached(decl.parent.right); }); @@ -24182,10 +24189,6 @@ var ts; } return type; } - // We never narrow type any in an instanceof guard - if (isTypeAny(type)) { - return type; - } // Check that right operand is a function type with a prototype property var rightType = checkExpression(expr.right); if (!isTypeSubtypeOf(rightType, globalFunctionType)) { @@ -24200,6 +24203,10 @@ var ts; targetType = prototypePropertyType; } } + // Don't narrow from 'any' if the target type is exactly 'Object' or 'Function' + if (isTypeAny(type) && (targetType === globalObjectType || targetType === globalFunctionType)) { + return type; + } if (!targetType) { // Target type is type of construct signature var constructSignatures = void 0; @@ -24242,7 +24249,7 @@ var ts; getIntersectionType([type, candidate]); } function narrowTypeByTypePredicate(type, callExpression, assumeTrue) { - if (type.flags & 1 /* Any */ || !hasMatchingArgument(callExpression, reference)) { + if (!hasMatchingArgument(callExpression, reference)) { return type; } var signature = getResolvedSignature(callExpression); @@ -24250,6 +24257,10 @@ var ts; if (!predicate) { return type; } + // Don't narrow from 'any' if the predicate type is exactly 'Object' or 'Function' + if (isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType)) { + return type; + } if (ts.isIdentifierTypePredicate(predicate)) { var predicateArgument = callExpression.arguments[predicate.parameterIndex]; if (predicateArgument) { @@ -24987,6 +24998,10 @@ var ts; var binaryExpression = node.parent; var operator = binaryExpression.operatorToken.kind; if (operator >= 56 /* FirstAssignment */ && operator <= 68 /* LastAssignment */) { + // Don't do this for special property assignments to avoid circularity + if (ts.getSpecialPropertyAssignmentKind(binaryExpression) !== 0 /* None */) { + return undefined; + } // In an assignment expression, the right operand is contextually typed by the type of the left operand. if (node === binaryExpression.right) { return checkExpression(binaryExpression.left); @@ -28891,7 +28906,12 @@ var ts; } } function checkClassForDuplicateDeclarations(node) { - var getter = 1, setter = 2, property = getter | setter; + var Accessor; + (function (Accessor) { + Accessor[Accessor["Getter"] = 1] = "Getter"; + Accessor[Accessor["Setter"] = 2] = "Setter"; + Accessor[Accessor["Property"] = 3] = "Property"; + })(Accessor || (Accessor = {})); var instanceNames = ts.createMap(); var staticNames = ts.createMap(); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { @@ -28900,7 +28920,7 @@ var ts; for (var _b = 0, _c = member.parameters; _b < _c.length; _b++) { var param = _c[_b]; if (ts.isParameterPropertyDeclaration(param)) { - addName(instanceNames, param.name, param.name.text, property); + addName(instanceNames, param.name, param.name.text, 3 /* Property */); } } } @@ -28911,13 +28931,13 @@ var ts; if (memberName) { switch (member.kind) { case 149 /* GetAccessor */: - addName(names, member.name, memberName, getter); + addName(names, member.name, memberName, 1 /* Getter */); break; case 150 /* SetAccessor */: - addName(names, member.name, memberName, setter); + addName(names, member.name, memberName, 2 /* Setter */); break; case 145 /* PropertyDeclaration */: - addName(names, member.name, memberName, property); + addName(names, member.name, memberName, 3 /* Property */); break; } } @@ -30061,7 +30081,7 @@ var ts; for (var _b = 0, _c = member.parameters; _b < _c.length; _b++) { var parameter = _c[_b]; if (!parameter.symbol.isReferenced && parameter.flags & 8 /* Private */) { - error(parameter.name, ts.Diagnostics._0_is_declared_but_never_used, parameter.symbol.name); + error(parameter.name, ts.Diagnostics.Property_0_is_declared_but_never_used, parameter.symbol.name); } } } @@ -32253,9 +32273,10 @@ var ts; } } function checkSourceFile(node) { - var start = ts.performance.mark(); + ts.performance.mark("beforeCheck"); checkSourceFileWorker(node); - ts.performance.measure("Check", start); + ts.performance.mark("afterCheck"); + ts.performance.measure("Check", "beforeCheck", "afterCheck"); } // Fully type check a source file and collect the relevant diagnostics. function checkSourceFileWorker(node) { @@ -37074,6 +37095,7 @@ var ts; ts.getNullSourceMapWriter = getNullSourceMapWriter; function createSourceMapWriter(host, writer) { var compilerOptions = host.getCompilerOptions(); + var extendedDiagnostics = compilerOptions.extendedDiagnostics; var currentSourceFile; var sourceMapDir; // The directory in which sourcemap will be var stopOverridingSpan = false; @@ -37237,7 +37259,9 @@ var ts; if (pos === -1) { return; } - var start = ts.performance.mark(); + if (extendedDiagnostics) { + ts.performance.mark("beforeSourcemap"); + } var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos); // Convert the location to be one-based. sourceLinePos.line++; @@ -37270,7 +37294,10 @@ var ts; lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex; } updateLastEncodedAndRecordedSpans(); - ts.performance.measure("Source Map", start); + if (extendedDiagnostics) { + ts.performance.mark("afterSourcemap"); + ts.performance.measure("Source Map", "beforeSourcemap", "afterSourcemap"); + } } function getStartPos(range) { var rangeHasDecorators = !!range.decorators; @@ -45504,9 +45531,10 @@ var ts; function getSourceFile(fileName, languageVersion, onError) { var text; try { - var start = ts.performance.mark(); + ts.performance.mark("beforeIORead"); text = ts.sys.readFile(fileName, options.charset); - ts.performance.measure("I/O Read", start); + ts.performance.mark("afterIORead"); + ts.performance.measure("I/O Read", "beforeIORead", "afterIORead"); } catch (e) { if (onError) { @@ -45561,7 +45589,7 @@ var ts; } function writeFile(fileName, data, writeByteOrderMark, onError) { try { - var start = ts.performance.mark(); + ts.performance.mark("beforeIOWrite"); ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName))); if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) { writeFileIfUpdated(fileName, data, writeByteOrderMark); @@ -45569,7 +45597,8 @@ var ts; else { ts.sys.writeFile(fileName, data, writeByteOrderMark); } - ts.performance.measure("I/O Write", start); + ts.performance.mark("afterIOWrite"); + ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite"); } catch (e) { if (onError) { @@ -45729,7 +45758,7 @@ var ts; var modulesWithElidedImports = ts.createMap(); // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. var sourceFilesFoundSearchingNodeModules = ts.createMap(); - var start = ts.performance.mark(); + ts.performance.mark("beforeProgram"); host = host || createCompilerHost(options); var skipDefaultLib = options.noLib; var programDiagnostics = ts.createDiagnosticCollection(); @@ -45814,7 +45843,8 @@ var ts; getResolvedTypeReferenceDirectives: function () { return resolvedTypeReferenceDirectives; } }; verifyCompilerOptions(); - ts.performance.measure("Program", start); + ts.performance.mark("afterProgram"); + ts.performance.measure("Program", "beforeProgram", "afterProgram"); return program; function getCommonSourceDirectory() { if (typeof commonSourceDirectory === "undefined") { @@ -46020,9 +46050,10 @@ var ts; // files need to be type checked. And the way to specify that all files need to be type // checked is to not pass the file to getEmitResolver. var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile); - var start = ts.performance.mark(); + ts.performance.mark("beforeEmit"); var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile); - ts.performance.measure("Emit", start); + ts.performance.mark("afterEmit"); + ts.performance.measure("Emit", "beforeEmit", "afterEmit"); return emitResult; } function getSourceFile(fileName) { @@ -46174,16 +46205,16 @@ var ts; case 175 /* NewExpression */: var expression = node; if (expression.typeArguments && expression.typeArguments.length > 0) { - var start_2 = expression.typeArguments.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start_2, expression.typeArguments.end - start_2, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file)); + var start = expression.typeArguments.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file)); return true; } break; case 142 /* Parameter */: var parameter = node; if (parameter.modifiers) { - var start_3 = parameter.modifiers.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start_3, parameter.modifiers.end - start_3, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file)); + var start = parameter.modifiers.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file)); return true; } if (parameter.questionToken) { @@ -46227,8 +46258,8 @@ var ts; } function checkTypeParameters(typeParameters) { if (typeParameters) { - var start_4 = typeParameters.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start_4, typeParameters.end - start_4, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file)); + var start = typeParameters.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, typeParameters.end - start, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file)); return true; } return false; @@ -55775,9 +55806,9 @@ var ts; // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && ts.isWord(contextToken.kind)) { - var start_5 = ts.timestamp(); + var start_2 = ts.timestamp(); contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile); - log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_5)); + log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_2)); } // Find the node where completion is requested on. // Also determine whether we are trying to complete with members of that node @@ -56056,13 +56087,13 @@ var ts; if (contextToken.kind === 9 /* StringLiteral */ || contextToken.kind === 10 /* RegularExpressionLiteral */ || ts.isTemplateLiteralKind(contextToken.kind)) { - var start_6 = contextToken.getStart(); + var start_3 = contextToken.getStart(); var end = contextToken.getEnd(); // To be "in" one of these literals, the position has to be: // 1. entirely within the token text. // 2. at the end position of an unterminated token. // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). - if (start_6 < position && position < end) { + if (start_3 < position && position < end) { return true; } if (position === end) { diff --git a/kicktravis b/kicktravis index 0f0f80a..96c8680 100644 --- a/kicktravis +++ b/kicktravis @@ -1 +1 @@ -2016-08-15 [ci skip] Version: 1.201608150004.1+10d1e02916578e4ece7bd24352f144be1eb72305 +2016-08-16 [ci skip] Version: 1.201608160007.1+80c04f8e97aa7ab6c0e1fb604bf1551e7057183c diff --git a/package.json b/package.json index b5c61ea..5536a6d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ntypescript", - "version": "1.201608150004.1+10d1e02916578e4ece7bd24352f144be1eb72305", + "version": "1.201608160007.1+80c04f8e97aa7ab6c0e1fb604bf1551e7057183c", "description": "A nicer version of microsoft/typescript packaged and released for API developers", "main": "./bin/ntypescript.js", "bin": { diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index c355d6c..b3f02dc 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -89,9 +89,10 @@ namespace ts { const binder = createBinder(); export function bindSourceFile(file: SourceFile, options: CompilerOptions) { - const start = performance.mark(); + performance.mark("beforeBind"); binder(file, options); - performance.measure("Bind", start); + performance.mark("afterBind"); + performance.measure("Bind", "beforeBind", "afterBind"); } function createBinder(): (file: SourceFile, options: CompilerOptions) => void { @@ -1971,7 +1972,18 @@ namespace ts { assignee = container; } else if (container.kind === SyntaxKind.Constructor) { - assignee = container.parent; + if (isInJavaScriptFile(node)) { + // this.foo assignment in a JavaScript class + // Bind this property to the containing class + const saveContainer = container; + container = container.parent; + bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property, SymbolFlags.None); + container = saveContainer; + return; + } + else { + assignee = container.parent; + } } else { return; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1b7b659..984cedb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3248,6 +3248,13 @@ namespace ts { // * className.prototype.method = expr if (declaration.kind === SyntaxKind.BinaryExpression || declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) { + // Use JS Doc type if present on parent expression statement + if (declaration.flags & NodeFlags.JavaScriptFile) { + const typeTag = getJSDocTypeTag(declaration.parent); + if (typeTag && typeTag.typeExpression) { + return links.type = getTypeFromTypeNode(typeTag.typeExpression.type); + } + } const declaredTypes = map(symbol.declarations, decl => decl.kind === SyntaxKind.BinaryExpression ? checkExpressionCached((decl).right) : @@ -8548,10 +8555,6 @@ namespace ts { } return type; } - // We never narrow type any in an instanceof guard - if (isTypeAny(type)) { - return type; - } // Check that right operand is a function type with a prototype property const rightType = checkExpression(expr.right); @@ -8569,6 +8572,11 @@ namespace ts { } } + // Don't narrow from 'any' if the target type is exactly 'Object' or 'Function' + if (isTypeAny(type) && (targetType === globalObjectType || targetType === globalFunctionType)) { + return type; + } + if (!targetType) { // Target type is type of construct signature let constructSignatures: Signature[]; @@ -8615,7 +8623,7 @@ namespace ts { } function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type { - if (type.flags & TypeFlags.Any || !hasMatchingArgument(callExpression, reference)) { + if (!hasMatchingArgument(callExpression, reference)) { return type; } const signature = getResolvedSignature(callExpression); @@ -8623,6 +8631,12 @@ namespace ts { if (!predicate) { return type; } + + // Don't narrow from 'any' if the predicate type is exactly 'Object' or 'Function' + if (isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType)) { + return type; + } + if (isIdentifierTypePredicate(predicate)) { const predicateArgument = callExpression.arguments[predicate.parameterIndex]; if (predicateArgument) { @@ -9449,6 +9463,11 @@ namespace ts { const binaryExpression = node.parent; const operator = binaryExpression.operatorToken.kind; if (operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) { + // Don't do this for special property assignments to avoid circularity + if (getSpecialPropertyAssignmentKind(binaryExpression) !== SpecialPropertyAssignmentKind.None) { + return undefined; + } + // In an assignment expression, the right operand is contextually typed by the type of the left operand. if (node === binaryExpression.right) { return checkExpression(binaryExpression.left); @@ -13787,15 +13806,19 @@ namespace ts { } function checkClassForDuplicateDeclarations(node: ClassLikeDeclaration) { - const getter = 1, setter = 2, property = getter | setter; + const enum Accessor { + Getter = 1, + Setter = 2, + Property = Getter | Setter + } - const instanceNames = createMap(); - const staticNames = createMap(); + const instanceNames = createMap(); + const staticNames = createMap(); for (const member of node.members) { if (member.kind === SyntaxKind.Constructor) { for (const param of (member as ConstructorDeclaration).parameters) { if (isParameterPropertyDeclaration(param)) { - addName(instanceNames, param.name, (param.name as Identifier).text, property); + addName(instanceNames, param.name, (param.name as Identifier).text, Accessor.Property); } } } @@ -13807,22 +13830,22 @@ namespace ts { if (memberName) { switch (member.kind) { case SyntaxKind.GetAccessor: - addName(names, member.name, memberName, getter); + addName(names, member.name, memberName, Accessor.Getter); break; case SyntaxKind.SetAccessor: - addName(names, member.name, memberName, setter); + addName(names, member.name, memberName, Accessor.Setter); break; case SyntaxKind.PropertyDeclaration: - addName(names, member.name, memberName, property); + addName(names, member.name, memberName, Accessor.Property); break; } } } } - function addName(names: Map, location: Node, name: string, meaning: number) { + function addName(names: Map, location: Node, name: string, meaning: Accessor) { const prev = names[name]; if (prev) { if (prev & meaning) { @@ -15104,7 +15127,7 @@ namespace ts { else if (member.kind === SyntaxKind.Constructor) { for (const parameter of (member).parameters) { if (!parameter.symbol.isReferenced && parameter.flags & NodeFlags.Private) { - error(parameter.name, Diagnostics._0_is_declared_but_never_used, parameter.symbol.name); + error(parameter.name, Diagnostics.Property_0_is_declared_but_never_used, parameter.symbol.name); } } } @@ -17535,11 +17558,10 @@ namespace ts { } function checkSourceFile(node: SourceFile) { - const start = performance.mark(); - + performance.mark("beforeCheck"); checkSourceFileWorker(node); - - performance.measure("Check", start); + performance.mark("afterCheck"); + performance.measure("Check", "beforeCheck", "afterCheck"); } // Fully type check a source file and collect the relevant diagnostics. diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 41c0847..f24d958 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -710,6 +710,7 @@ namespace ts { Report_errors_on_unused_parameters: { code: 6135, category: DiagnosticCategory.Message, key: "Report_errors_on_unused_parameters_6135", message: "Report errors on unused parameters." }, The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files: { code: 6136, category: DiagnosticCategory.Message, key: "The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files_6136", message: "The maximum dependency depth to search under node_modules and load JavaScript files" }, No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0: { code: 6137, category: DiagnosticCategory.Message, key: "No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0_6137", message: "No types specified in 'package.json' but 'allowJs' is set, so returning 'main' value of '{0}'" }, + Property_0_is_declared_but_never_used: { code: 6138, category: DiagnosticCategory.Error, key: "Property_0_is_declared_but_never_used_6138", message: "Property '{0}' is declared but never used." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable_0_implicitly_has_an_1_type_7005", message: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter_0_implicitly_has_an_1_type_7006", message: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member_0_implicitly_has_an_1_type_7008", message: "Member '{0}' implicitly has an '{1}' type." }, diff --git a/src/compiler/diagnosticMessages.generated.json b/src/compiler/diagnosticMessages.generated.json index f4c9139..0c92b7f 100644 --- a/src/compiler/diagnosticMessages.generated.json +++ b/src/compiler/diagnosticMessages.generated.json @@ -706,6 +706,7 @@ "Report_errors_on_unused_parameters_6135" : "Report errors on unused parameters.", "The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files_6136" : "The maximum dependency depth to search under node_modules and load JavaScript files", "No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0_6137" : "No types specified in 'package.json' but 'allowJs' is set, so returning 'main' value of '{0}'", + "Property_0_is_declared_but_never_used_6138" : "Property '{0}' is declared but never used.", "Variable_0_implicitly_has_an_1_type_7005" : "Variable '{0}' implicitly has an '{1}' type.", "Parameter_0_implicitly_has_an_1_type_7006" : "Parameter '{0}' implicitly has an '{1}' type.", "Member_0_implicitly_has_an_1_type_7008" : "Member '{0}' implicitly has an '{1}' type.", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 8126d5c..c1eead9 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2828,6 +2828,10 @@ "category": "Message", "code": 6137 }, + "Property '{0}' is declared but never used.": { + "category": "Error", + "code": 6138 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6f38783..aca7d74 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -421,10 +421,10 @@ namespace ts { } export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile { - const start = performance.mark(); + performance.mark("beforeParse"); const result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); - - performance.measure("Parse", start); + performance.mark("afterParse"); + performance.measure("Parse", "beforeParse", "afterParse"); return result; } diff --git a/src/compiler/performance.ts b/src/compiler/performance.ts index e496353..e8f064e 100644 --- a/src/compiler/performance.ts +++ b/src/compiler/performance.ts @@ -6,104 +6,90 @@ namespace ts { } /*@internal*/ +/** Performance measurements for the compiler. */ namespace ts.performance { - /** Performance measurements for the compiler. */ declare const onProfilerEvent: { (markName: string): void; profiler: boolean; }; - let profilerEvent: (markName: string) => void; - let counters: MapLike; - let measures: MapLike; + + const profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true + ? onProfilerEvent + : (markName: string) => { }; + + let enabled = false; + let profilerStart = 0; + let counts: Map; + let marks: Map; + let measures: Map; /** - * Emit a performance event if ts-profiler is connected. This is primarily used - * to generate heap snapshots. + * Marks a performance event. * - * @param eventName A name for the event. + * @param markName The name of the mark. */ - export function emit(eventName: string) { - if (profilerEvent) { - profilerEvent(eventName); + export function mark(markName: string) { + if (enabled) { + marks[markName] = timestamp(); + counts[markName] = (counts[markName] || 0) + 1; + profilerEvent(markName); } } /** - * Increments a counter with the specified name. + * Adds a performance measurement with the specified name. * - * @param counterName The name of the counter. + * @param measureName The name of the performance measurement. + * @param startMarkName The name of the starting mark. If not supplied, the point at which the + * profiler was enabled is used. + * @param endMarkName The name of the ending mark. If not supplied, the current timestamp is + * used. */ - export function increment(counterName: string) { - if (counters) { - counters[counterName] = (getProperty(counters, counterName) || 0) + 1; + export function measure(measureName: string, startMarkName?: string, endMarkName?: string) { + if (enabled) { + const end = endMarkName && marks[endMarkName] || timestamp(); + const start = startMarkName && marks[startMarkName] || profilerStart; + measures[measureName] = (measures[measureName] || 0) + (end - start); } } /** - * Gets the value of the counter with the specified name. + * Gets the number of times a marker was encountered. * - * @param counterName The name of the counter. - */ - export function getCount(counterName: string) { - return counters && getProperty(counters, counterName) || 0; - } - - /** - * Marks the start of a performance measurement. + * @param markName The name of the mark. */ - export function mark() { - return measures ? timestamp() : 0; + export function getCount(markName: string) { + return counts && counts[markName] || 0; } /** - * Adds a performance measurement with the specified name. + * Gets the total duration of all measurements with the supplied name. * - * @param measureName The name of the performance measurement. - * @param marker The timestamp of the starting mark. + * @param measureName The name of the measure whose durations should be accumulated. */ - export function measure(measureName: string, marker: number) { - if (measures) { - measures[measureName] = (getProperty(measures, measureName) || 0) + (timestamp() - marker); - } + export function getDuration(measureName: string) { + return measures && measures[measureName] || 0; } /** * Iterate over each measure, performing some action - * + * * @param cb The action to perform for each measure */ export function forEachMeasure(cb: (measureName: string, duration: number) => void) { - return forEachKey(measures, key => cb(key, measures[key])); - } - - /** - * Gets the total duration of all measurements with the supplied name. - * - * @param measureName The name of the measure whose durations should be accumulated. - */ - export function getDuration(measureName: string) { - return measures && getProperty(measures, measureName) || 0; + for (const key in measures) { + cb(key, measures[key]); + } } /** Enables (and resets) performance measurements for the compiler. */ export function enable() { - counters = { }; - measures = { - "I/O Read": 0, - "I/O Write": 0, - "Program": 0, - "Parse": 0, - "Bind": 0, - "Check": 0, - "Emit": 0, - }; - - profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true - ? onProfilerEvent - : undefined; + counts = createMap(); + marks = createMap(); + measures = createMap(); + enabled = true; + profilerStart = timestamp(); } - /** Disables (and clears) performance measurements for the compiler. */ + /** Disables performance measurements for the compiler. */ export function disable() { - counters = undefined; - measures = undefined; - profilerEvent = undefined; + enabled = false; } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index eb50548..767fcb4 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -857,9 +857,10 @@ namespace ts { function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile { let text: string; try { - const start = performance.mark(); + performance.mark("beforeIORead"); text = sys.readFile(fileName, options.charset); - performance.measure("I/O Read", start); + performance.mark("afterIORead"); + performance.measure("I/O Read", "beforeIORead", "afterIORead"); } catch (e) { if (onError) { @@ -926,7 +927,7 @@ namespace ts { function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { try { - const start = performance.mark(); + performance.mark("beforeIOWrite"); ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); if (isWatchSet(options) && sys.createHash && sys.getModifiedTime) { @@ -936,7 +937,8 @@ namespace ts { sys.writeFile(fileName, data, writeByteOrderMark); } - performance.measure("I/O Write", start); + performance.mark("afterIOWrite"); + performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite"); } catch (e) { if (onError) { @@ -1118,7 +1120,7 @@ namespace ts { // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. const sourceFilesFoundSearchingNodeModules = createMap(); - const start = performance.mark(); + performance.mark("beforeProgram"); host = host || createCompilerHost(options); @@ -1216,8 +1218,8 @@ namespace ts { }; verifyCompilerOptions(); - - performance.measure("Program", start); + performance.mark("afterProgram"); + performance.measure("Program", "beforeProgram", "afterProgram"); return program; @@ -1460,14 +1462,15 @@ namespace ts { // checked is to not pass the file to getEmitResolver. const emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile); - const start = performance.mark(); + performance.mark("beforeEmit"); const emitResult = emitFiles( emitResolver, getEmitHost(writeFileCallback), sourceFile); - performance.measure("Emit", start); + performance.mark("afterEmit"); + performance.measure("Emit", "beforeEmit", "afterEmit"); return emitResult; } diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 2d8c36a..4046867 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -46,6 +46,7 @@ namespace ts { export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter { const compilerOptions = host.getCompilerOptions(); + const extendedDiagnostics = compilerOptions.extendedDiagnostics; let currentSourceFile: SourceFile; let sourceMapDir: string; // The directory in which sourcemap will be let stopOverridingSpan = false; @@ -240,7 +241,9 @@ namespace ts { return; } - const start = performance.mark(); + if (extendedDiagnostics) { + performance.mark("beforeSourcemap"); + } const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos); @@ -282,7 +285,10 @@ namespace ts { updateLastEncodedAndRecordedSpans(); - performance.measure("Source Map", start); + if (extendedDiagnostics) { + performance.mark("afterSourcemap"); + performance.measure("Source Map", "beforeSourcemap", "afterSourcemap"); + } } function getStartPos(range: TextRange) {