diff --git a/Jakefile.js b/Jakefile.js index 7b85aacaa89..a0a001d7679 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -920,6 +920,7 @@ var servicesLintTargets = [ "patternMatcher.ts", "services.ts", "shims.ts", + "jsTyping.ts" ].map(function (s) { return path.join(servicesDirectory, s); }); diff --git a/lib/tsc.js b/lib/tsc.js index 8e330ebb650..b007d40e3b7 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -280,6 +280,14 @@ var ts; return hasOwnProperty.call(map, key); } ts.hasProperty = hasProperty; + function getKeys(map) { + var keys = []; + for (var key in map) { + keys.push(key); + } + return keys; + } + ts.getKeys = getKeys; function getProperty(map, key) { return hasOwnProperty.call(map, key) ? map[key] : undefined; } @@ -685,6 +693,26 @@ var ts; return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension; } ts.fileExtensionIs = fileExtensionIs; + function ensureScriptKind(fileName, scriptKind) { + return (scriptKind || getScriptKindFromFileName(fileName)) || 3; + } + ts.ensureScriptKind = ensureScriptKind; + function getScriptKindFromFileName(fileName) { + var ext = fileName.substr(fileName.lastIndexOf(".")); + switch (ext.toLowerCase()) { + case ".js": + return 1; + case ".jsx": + return 2; + case ".ts": + return 3; + case ".tsx": + return 4; + default: + return 0; + } + } + ts.getScriptKindFromFileName = getScriptKindFromFileName; ts.supportedTypeScriptExtensions = [".ts", ".tsx", ".d.ts"]; ts.supportedJavascriptExtensions = [".js", ".jsx"]; var allSupportedExtensions = ts.supportedTypeScriptExtensions.concat(ts.supportedJavascriptExtensions); @@ -1844,6 +1872,7 @@ var ts; Only_amd_and_system_modules_are_supported_alongside_0: { code: 6082, category: ts.DiagnosticCategory.Error, key: "Only_amd_and_system_modules_are_supported_alongside_0_6082", message: "Only 'amd' and 'system' modules are supported alongside --{0}." }, Allow_javascript_files_to_be_compiled: { code: 6083, category: ts.DiagnosticCategory.Message, key: "Allow_javascript_files_to_be_compiled_6083", message: "Allow javascript files to be compiled." }, Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit: { code: 6084, category: ts.DiagnosticCategory.Message, key: "Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit_6084", message: "Specifies the object invoked for createElement and __spread when targeting 'react' JSX emit" }, + Option_0_should_have_array_of_strings_as_a_value: { code: 6103, category: ts.DiagnosticCategory.Error, key: "Option_0_should_have_array_of_strings_as_a_value_6103", message: "Option '{0}' should have array of strings as a value." }, Do_not_emit_use_strict_directives_in_module_output: { code: 6112, category: ts.DiagnosticCategory.Message, key: "Do_not_emit_use_strict_directives_in_module_output_6112", message: "Do not emit 'use strict' directives in module output." }, 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." }, @@ -1894,7 +1923,8 @@ var ts; An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses: { code: 17006, category: ts.DiagnosticCategory.Error, key: "An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_ex_17006", message: "An unary expression with the '{0}' operator is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses." }, A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses: { code: 17007, category: ts.DiagnosticCategory.Error, key: "A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Con_17007", message: "A type assertion expression is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses." }, JSX_element_0_has_no_corresponding_closing_tag: { code: 17008, category: ts.DiagnosticCategory.Error, key: "JSX_element_0_has_no_corresponding_closing_tag_17008", message: "JSX element '{0}' has no corresponding closing tag." }, - super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: ts.DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." } + super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: ts.DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." }, + Unknown_typing_option_0: { code: 17010, category: ts.DiagnosticCategory.Error, key: "Unknown_typing_option_0_17010", message: "Unknown typing option '{0}'." } }; })(ts || (ts = {})); var ts; @@ -4288,6 +4318,9 @@ var ts; } ts.isRequireCall = isRequireCall; function getSpecialPropertyAssignmentKind(expression) { + if (!isInJavaScriptFile(expression)) { + return 0; + } if (expression.kind !== 184) { return 0; } @@ -6052,10 +6085,10 @@ var ts; } } ts.forEachChild = forEachChild; - function createSourceFile(fileName, sourceText, languageVersion, setParentNodes) { + function createSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind) { if (setParentNodes === void 0) { setParentNodes = false; } var start = new Date().getTime(); - var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, undefined, setParentNodes); + var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, undefined, setParentNodes, scriptKind); ts.parseTime += new Date().getTime() - start; return result; } @@ -6089,18 +6122,18 @@ var ts; var parsingContext; var contextFlags; var parseErrorBeforeNextFinishedNode = false; - function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes) { - var isJavaScriptFile = ts.hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0; - initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor); - var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes); + function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes, scriptKind) { + scriptKind = ts.ensureScriptKind(fileName, scriptKind); + initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind); + var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); clearState(); return result; } Parser.parseSourceFile = parseSourceFile; - function getLanguageVariant(fileName) { - return ts.fileExtensionIs(fileName, ".tsx") || ts.fileExtensionIs(fileName, ".jsx") || ts.fileExtensionIs(fileName, ".js") ? 1 : 0; + function getLanguageVariant(scriptKind) { + return scriptKind === 4 || scriptKind === 2 || scriptKind === 1 ? 1 : 0; } - function initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor) { + function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind) { NodeConstructor = ts.objectAllocator.getNodeConstructor(); SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); sourceText = _sourceText; @@ -6110,12 +6143,12 @@ var ts; identifiers = {}; identifierCount = 0; nodeCount = 0; - contextFlags = isJavaScriptFile ? 32 : 0; + contextFlags = scriptKind === 1 || scriptKind === 2 ? 32 : 0; parseErrorBeforeNextFinishedNode = false; scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(getLanguageVariant(fileName)); + scanner.setLanguageVariant(getLanguageVariant(scriptKind)); } function clearState() { scanner.setText(""); @@ -6126,8 +6159,8 @@ var ts; syntaxCursor = undefined; sourceText = undefined; } - function parseSourceFileWorker(fileName, languageVersion, setParentNodes) { - sourceFile = createSourceFile(fileName, languageVersion); + function parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind) { + sourceFile = createSourceFile(fileName, languageVersion, scriptKind); if (contextFlags & 32) { sourceFile.parserContextFlags = 32; } @@ -6176,7 +6209,7 @@ var ts; } } Parser.fixupParentReferences = fixupParentReferences; - function createSourceFile(fileName, languageVersion) { + function createSourceFile(fileName, languageVersion, scriptKind) { var sourceFile = new SourceFileConstructor(251, 0, sourceText.length); nodeCount++; sourceFile.text = sourceText; @@ -6184,7 +6217,8 @@ var ts; sourceFile.languageVersion = languageVersion; sourceFile.fileName = ts.normalizePath(fileName); sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 4096 : 0; - sourceFile.languageVariant = getLanguageVariant(sourceFile.fileName); + sourceFile.languageVariant = getLanguageVariant(scriptKind); + sourceFile.scriptKind = scriptKind; return sourceFile; } function setContextFlag(val, flag) { @@ -6720,7 +6754,7 @@ var ts; if (ts.containsParseError(node)) { return undefined; } - var nodeContextFlags = node.parserContextFlags & 31; + var nodeContextFlags = node.parserContextFlags & 63; if (nodeContextFlags !== contextFlags) { return undefined; } @@ -9597,7 +9631,7 @@ var ts; } JSDocParser.isJSDocType = isJSDocType; function parseJSDocTypeExpressionForTests(content, start, length) { - initializeState("file.js", content, 2, true, undefined); + initializeState("file.js", content, 2, undefined, 1); scanner.setText(content, start, length); token = scanner.scan(); var jsDocTypeExpression = parseJSDocTypeExpression(); @@ -9850,7 +9884,7 @@ var ts; } } function parseIsolatedJSDocComment(content, start, length) { - initializeState("file.js", content, 2, true, undefined); + initializeState("file.js", content, 2, undefined, 1); sourceFile = { languageVariant: 0, text: content }; var jsDocComment = parseJSDocCommentWorker(start, length); var diagnostics = parseDiagnostics; @@ -10103,7 +10137,7 @@ var ts; return sourceFile; } if (sourceFile.statements.length === 0) { - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, undefined, true); + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, undefined, true, sourceFile.scriptKind); } var incrementalSourceFile = sourceFile; ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); @@ -10117,7 +10151,7 @@ var ts; ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange))); var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length; updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); - var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, true); + var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, true, sourceFile.scriptKind); return result; } IncrementalParser.updateSourceFile = updateSourceFile; @@ -10872,6 +10906,7 @@ var ts; case 146: case 147: case 153: + case 264: case 154: case 176: case 177: @@ -11362,7 +11397,7 @@ var ts; } function bindModuleExportsAssignment(node) { setCommonJsModuleIndicator(node); - bindExportAssignment(node); + declareSymbol(file.symbol.exports, file.symbol, node, 4 | 7340032 | 512, 0); } function bindThisPropertyAssignment(node) { if (container.kind === 176 || container.kind === 216) { @@ -11384,7 +11419,7 @@ var ts; if (!funcSymbol.members) { funcSymbol.members = {}; } - declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4, 107455); + declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4, 107455 & ~4); } function bindCallExpression(node) { if (!file.commonJsModuleIndicator && ts.isRequireCall(node, false)) { @@ -12267,7 +12302,9 @@ var ts; function getTargetOfImportClause(node) { var moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier); if (moduleSymbol) { - var exportDefaultSymbol = resolveSymbol(moduleSymbol.exports["default"]); + var exportDefaultSymbol = moduleSymbol.exports["export="] ? + getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") : + resolveSymbol(moduleSymbol.exports["default"]); if (!exportDefaultSymbol && !allowSyntheticDefaultImports) { error(node.name, ts.Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); } @@ -12318,8 +12355,14 @@ var ts; if (targetSymbol) { var name_9 = specifier.propertyName || specifier.name; if (name_9.text) { + var symbolFromVariable = void 0; + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports["export="]) { + symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name_9.text); + } + else { + symbolFromVariable = getPropertyOfVariable(targetSymbol, name_9.text); + } var symbolFromModule = getExportOfModule(targetSymbol, name_9.text); - var symbolFromVariable = getPropertyOfVariable(targetSymbol, name_9.text); var symbol = symbolFromModule && symbolFromVariable ? combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) : symbolFromModule || symbolFromVariable; @@ -15780,7 +15823,7 @@ var ts; for (var i = 0; i < checkCount; i++) { var s = i < sourceMax ? getTypeOfSymbol(sourceParams[i]) : getRestTypeOfSignature(source); var t = i < targetMax ? getTypeOfSymbol(targetParams[i]) : getRestTypeOfSignature(target); - var related = compareTypes(t, s, false) || compareTypes(s, t, reportErrors); + var related = compareTypes(s, t, false) || compareTypes(t, s, reportErrors); if (!related) { if (reportErrors) { errorReporter(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, sourceParams[i < sourceMax ? i : sourceMax].name, targetParams[i < targetMax ? i : targetMax].name); @@ -16778,8 +16821,10 @@ var ts; function inferTypes(context, source, target) { var sourceStack; var targetStack; + var maxDepth = 5; var depth = 0; var inferiority = 0; + var visited = {}; inferFromTypes(source, target); function isInProcess(source, target) { for (var i = 0; i < depth; i++) { @@ -16875,9 +16920,17 @@ var ts; if (isInProcess(source, target)) { return; } + if (depth > maxDepth) { + return; + } if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { return; } + var key = source.id + "," + target.id; + if (ts.hasProperty(visited, key)) { + return; + } + visited[key] = true; if (depth === 0) { sourceStack = []; targetStack = []; @@ -32466,7 +32519,7 @@ var ts; ts.ioReadTime = 0; ts.ioWriteTime = 0; var emptyArray = []; - ts.version = "1.8.5"; + ts.version = "1.8.9"; function findConfigFile(searchPath, fileExists) { var fileName = "tsconfig.json"; while (true) { @@ -34025,6 +34078,7 @@ var ts; return { options: options, fileNames: getFileNames(), + typingOptions: getTypingOptions(), errors: errors }; function getFileNames() { @@ -34077,6 +34131,34 @@ var ts; } return fileNames; } + function getTypingOptions() { + var options = ts.getBaseFileName(configFileName) === "jsconfig.json" + ? { enableAutoDiscovery: true, include: [], exclude: [] } + : { enableAutoDiscovery: false, include: [], exclude: [] }; + var jsonTypingOptions = json["typingOptions"]; + if (jsonTypingOptions) { + for (var id in jsonTypingOptions) { + if (id === "enableAutoDiscovery") { + if (typeof jsonTypingOptions[id] === "boolean") { + options.enableAutoDiscovery = jsonTypingOptions[id]; + } + else { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_typing_option_0, id)); + } + } + else if (id === "include") { + options.include = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); + } + else if (id === "exclude") { + options.exclude = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); + } + else { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_typing_option_0, id)); + } + } + } + return options; + } } ts.parseJsonConfigFileContent = parseJsonConfigFileContent; function convertCompilerOptionsFromJson(jsonOptions, basePath, configFileName) { @@ -34125,6 +34207,30 @@ var ts; return { options: options, errors: errors }; } ts.convertCompilerOptionsFromJson = convertCompilerOptionsFromJson; + function convertJsonOptionToStringArray(optionName, optionJson, errors, func) { + var items = []; + var invalidOptionType = false; + if (!ts.isArray(optionJson)) { + invalidOptionType = true; + } + else { + for (var _i = 0, _a = optionJson; _i < _a.length; _i++) { + var element = _a[_i]; + if (typeof element === "string") { + var item = func ? func(element) : element; + items.push(item); + } + else { + invalidOptionType = true; + break; + } + } + } + if (invalidOptionType) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_should_have_array_of_strings_as_a_value, optionName)); + } + return items; + } })(ts || (ts = {})); var ts; (function (ts) { diff --git a/lib/tsserver.js b/lib/tsserver.js index 32bf7274dc3..33675d32c9a 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -285,6 +285,14 @@ var ts; return hasOwnProperty.call(map, key); } ts.hasProperty = hasProperty; + function getKeys(map) { + var keys = []; + for (var key in map) { + keys.push(key); + } + return keys; + } + ts.getKeys = getKeys; function getProperty(map, key) { return hasOwnProperty.call(map, key) ? map[key] : undefined; } @@ -690,6 +698,26 @@ var ts; return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension; } ts.fileExtensionIs = fileExtensionIs; + function ensureScriptKind(fileName, scriptKind) { + return (scriptKind || getScriptKindFromFileName(fileName)) || 3; + } + ts.ensureScriptKind = ensureScriptKind; + function getScriptKindFromFileName(fileName) { + var ext = fileName.substr(fileName.lastIndexOf(".")); + switch (ext.toLowerCase()) { + case ".js": + return 1; + case ".jsx": + return 2; + case ".ts": + return 3; + case ".tsx": + return 4; + default: + return 0; + } + } + ts.getScriptKindFromFileName = getScriptKindFromFileName; ts.supportedTypeScriptExtensions = [".ts", ".tsx", ".d.ts"]; ts.supportedJavascriptExtensions = [".js", ".jsx"]; var allSupportedExtensions = ts.supportedTypeScriptExtensions.concat(ts.supportedJavascriptExtensions); @@ -1849,6 +1877,7 @@ var ts; Only_amd_and_system_modules_are_supported_alongside_0: { code: 6082, category: ts.DiagnosticCategory.Error, key: "Only_amd_and_system_modules_are_supported_alongside_0_6082", message: "Only 'amd' and 'system' modules are supported alongside --{0}." }, Allow_javascript_files_to_be_compiled: { code: 6083, category: ts.DiagnosticCategory.Message, key: "Allow_javascript_files_to_be_compiled_6083", message: "Allow javascript files to be compiled." }, Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit: { code: 6084, category: ts.DiagnosticCategory.Message, key: "Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit_6084", message: "Specifies the object invoked for createElement and __spread when targeting 'react' JSX emit" }, + Option_0_should_have_array_of_strings_as_a_value: { code: 6103, category: ts.DiagnosticCategory.Error, key: "Option_0_should_have_array_of_strings_as_a_value_6103", message: "Option '{0}' should have array of strings as a value." }, Do_not_emit_use_strict_directives_in_module_output: { code: 6112, category: ts.DiagnosticCategory.Message, key: "Do_not_emit_use_strict_directives_in_module_output_6112", message: "Do not emit 'use strict' directives in module output." }, 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." }, @@ -1899,7 +1928,8 @@ var ts; An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses: { code: 17006, category: ts.DiagnosticCategory.Error, key: "An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_ex_17006", message: "An unary expression with the '{0}' operator is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses." }, A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses: { code: 17007, category: ts.DiagnosticCategory.Error, key: "A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Con_17007", message: "A type assertion expression is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses." }, JSX_element_0_has_no_corresponding_closing_tag: { code: 17008, category: ts.DiagnosticCategory.Error, key: "JSX_element_0_has_no_corresponding_closing_tag_17008", message: "JSX element '{0}' has no corresponding closing tag." }, - super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: ts.DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." } + super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: ts.DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." }, + Unknown_typing_option_0: { code: 17010, category: ts.DiagnosticCategory.Error, key: "Unknown_typing_option_0_17010", message: "Unknown typing option '{0}'." } }; })(ts || (ts = {})); var ts; @@ -3840,6 +3870,7 @@ var ts; return { options: options, fileNames: getFileNames(), + typingOptions: getTypingOptions(), errors: errors }; function getFileNames() { @@ -3892,6 +3923,34 @@ var ts; } return fileNames; } + function getTypingOptions() { + var options = ts.getBaseFileName(configFileName) === "jsconfig.json" + ? { enableAutoDiscovery: true, include: [], exclude: [] } + : { enableAutoDiscovery: false, include: [], exclude: [] }; + var jsonTypingOptions = json["typingOptions"]; + if (jsonTypingOptions) { + for (var id in jsonTypingOptions) { + if (id === "enableAutoDiscovery") { + if (typeof jsonTypingOptions[id] === "boolean") { + options.enableAutoDiscovery = jsonTypingOptions[id]; + } + else { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_typing_option_0, id)); + } + } + else if (id === "include") { + options.include = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); + } + else if (id === "exclude") { + options.exclude = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); + } + else { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_typing_option_0, id)); + } + } + } + return options; + } } ts.parseJsonConfigFileContent = parseJsonConfigFileContent; function convertCompilerOptionsFromJson(jsonOptions, basePath, configFileName) { @@ -3940,6 +3999,30 @@ var ts; return { options: options, errors: errors }; } ts.convertCompilerOptionsFromJson = convertCompilerOptionsFromJson; + function convertJsonOptionToStringArray(optionName, optionJson, errors, func) { + var items = []; + var invalidOptionType = false; + if (!ts.isArray(optionJson)) { + invalidOptionType = true; + } + else { + for (var _i = 0, _a = optionJson; _i < _a.length; _i++) { + var element = _a[_i]; + if (typeof element === "string") { + var item = func ? func(element) : element; + items.push(item); + } + else { + invalidOptionType = true; + break; + } + } + } + if (invalidOptionType) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_should_have_array_of_strings_as_a_value, optionName)); + } + return items; + } })(ts || (ts = {})); var ts; (function (ts) { @@ -4856,6 +4939,9 @@ var ts; } ts.isRequireCall = isRequireCall; function getSpecialPropertyAssignmentKind(expression) { + if (!isInJavaScriptFile(expression)) { + return 0; + } if (expression.kind !== 184) { return 0; } @@ -6620,10 +6706,10 @@ var ts; } } ts.forEachChild = forEachChild; - function createSourceFile(fileName, sourceText, languageVersion, setParentNodes) { + function createSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind) { if (setParentNodes === void 0) { setParentNodes = false; } var start = new Date().getTime(); - var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, undefined, setParentNodes); + var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, undefined, setParentNodes, scriptKind); ts.parseTime += new Date().getTime() - start; return result; } @@ -6657,18 +6743,18 @@ var ts; var parsingContext; var contextFlags; var parseErrorBeforeNextFinishedNode = false; - function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes) { - var isJavaScriptFile = ts.hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0; - initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor); - var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes); + function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes, scriptKind) { + scriptKind = ts.ensureScriptKind(fileName, scriptKind); + initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind); + var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); clearState(); return result; } Parser.parseSourceFile = parseSourceFile; - function getLanguageVariant(fileName) { - return ts.fileExtensionIs(fileName, ".tsx") || ts.fileExtensionIs(fileName, ".jsx") || ts.fileExtensionIs(fileName, ".js") ? 1 : 0; + function getLanguageVariant(scriptKind) { + return scriptKind === 4 || scriptKind === 2 || scriptKind === 1 ? 1 : 0; } - function initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor) { + function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind) { NodeConstructor = ts.objectAllocator.getNodeConstructor(); SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); sourceText = _sourceText; @@ -6678,12 +6764,12 @@ var ts; identifiers = {}; identifierCount = 0; nodeCount = 0; - contextFlags = isJavaScriptFile ? 32 : 0; + contextFlags = scriptKind === 1 || scriptKind === 2 ? 32 : 0; parseErrorBeforeNextFinishedNode = false; scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(getLanguageVariant(fileName)); + scanner.setLanguageVariant(getLanguageVariant(scriptKind)); } function clearState() { scanner.setText(""); @@ -6694,8 +6780,8 @@ var ts; syntaxCursor = undefined; sourceText = undefined; } - function parseSourceFileWorker(fileName, languageVersion, setParentNodes) { - sourceFile = createSourceFile(fileName, languageVersion); + function parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind) { + sourceFile = createSourceFile(fileName, languageVersion, scriptKind); if (contextFlags & 32) { sourceFile.parserContextFlags = 32; } @@ -6744,7 +6830,7 @@ var ts; } } Parser.fixupParentReferences = fixupParentReferences; - function createSourceFile(fileName, languageVersion) { + function createSourceFile(fileName, languageVersion, scriptKind) { var sourceFile = new SourceFileConstructor(251, 0, sourceText.length); nodeCount++; sourceFile.text = sourceText; @@ -6752,7 +6838,8 @@ var ts; sourceFile.languageVersion = languageVersion; sourceFile.fileName = ts.normalizePath(fileName); sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 4096 : 0; - sourceFile.languageVariant = getLanguageVariant(sourceFile.fileName); + sourceFile.languageVariant = getLanguageVariant(scriptKind); + sourceFile.scriptKind = scriptKind; return sourceFile; } function setContextFlag(val, flag) { @@ -7288,7 +7375,7 @@ var ts; if (ts.containsParseError(node)) { return undefined; } - var nodeContextFlags = node.parserContextFlags & 31; + var nodeContextFlags = node.parserContextFlags & 63; if (nodeContextFlags !== contextFlags) { return undefined; } @@ -10165,7 +10252,7 @@ var ts; } JSDocParser.isJSDocType = isJSDocType; function parseJSDocTypeExpressionForTests(content, start, length) { - initializeState("file.js", content, 2, true, undefined); + initializeState("file.js", content, 2, undefined, 1); scanner.setText(content, start, length); token = scanner.scan(); var jsDocTypeExpression = parseJSDocTypeExpression(); @@ -10418,7 +10505,7 @@ var ts; } } function parseIsolatedJSDocComment(content, start, length) { - initializeState("file.js", content, 2, true, undefined); + initializeState("file.js", content, 2, undefined, 1); sourceFile = { languageVariant: 0, text: content }; var jsDocComment = parseJSDocCommentWorker(start, length); var diagnostics = parseDiagnostics; @@ -10671,7 +10758,7 @@ var ts; return sourceFile; } if (sourceFile.statements.length === 0) { - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, undefined, true); + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, undefined, true, sourceFile.scriptKind); } var incrementalSourceFile = sourceFile; ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); @@ -10685,7 +10772,7 @@ var ts; ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange))); var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length; updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); - var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, true); + var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, true, sourceFile.scriptKind); return result; } IncrementalParser.updateSourceFile = updateSourceFile; @@ -11440,6 +11527,7 @@ var ts; case 146: case 147: case 153: + case 264: case 154: case 176: case 177: @@ -11930,7 +12018,7 @@ var ts; } function bindModuleExportsAssignment(node) { setCommonJsModuleIndicator(node); - bindExportAssignment(node); + declareSymbol(file.symbol.exports, file.symbol, node, 4 | 7340032 | 512, 0); } function bindThisPropertyAssignment(node) { if (container.kind === 176 || container.kind === 216) { @@ -11952,7 +12040,7 @@ var ts; if (!funcSymbol.members) { funcSymbol.members = {}; } - declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4, 107455); + declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4, 107455 & ~4); } function bindCallExpression(node) { if (!file.commonJsModuleIndicator && ts.isRequireCall(node, false)) { @@ -12835,7 +12923,9 @@ var ts; function getTargetOfImportClause(node) { var moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier); if (moduleSymbol) { - var exportDefaultSymbol = resolveSymbol(moduleSymbol.exports["default"]); + var exportDefaultSymbol = moduleSymbol.exports["export="] ? + getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") : + resolveSymbol(moduleSymbol.exports["default"]); if (!exportDefaultSymbol && !allowSyntheticDefaultImports) { error(node.name, ts.Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); } @@ -12886,8 +12976,14 @@ var ts; if (targetSymbol) { var name_9 = specifier.propertyName || specifier.name; if (name_9.text) { + var symbolFromVariable = void 0; + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports["export="]) { + symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name_9.text); + } + else { + symbolFromVariable = getPropertyOfVariable(targetSymbol, name_9.text); + } var symbolFromModule = getExportOfModule(targetSymbol, name_9.text); - var symbolFromVariable = getPropertyOfVariable(targetSymbol, name_9.text); var symbol = symbolFromModule && symbolFromVariable ? combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) : symbolFromModule || symbolFromVariable; @@ -16348,7 +16444,7 @@ var ts; for (var i = 0; i < checkCount; i++) { var s = i < sourceMax ? getTypeOfSymbol(sourceParams[i]) : getRestTypeOfSignature(source); var t = i < targetMax ? getTypeOfSymbol(targetParams[i]) : getRestTypeOfSignature(target); - var related = compareTypes(t, s, false) || compareTypes(s, t, reportErrors); + var related = compareTypes(s, t, false) || compareTypes(t, s, reportErrors); if (!related) { if (reportErrors) { errorReporter(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, sourceParams[i < sourceMax ? i : sourceMax].name, targetParams[i < targetMax ? i : targetMax].name); @@ -17346,8 +17442,10 @@ var ts; function inferTypes(context, source, target) { var sourceStack; var targetStack; + var maxDepth = 5; var depth = 0; var inferiority = 0; + var visited = {}; inferFromTypes(source, target); function isInProcess(source, target) { for (var i = 0; i < depth; i++) { @@ -17443,9 +17541,17 @@ var ts; if (isInProcess(source, target)) { return; } + if (depth > maxDepth) { + return; + } if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { return; } + var key = source.id + "," + target.id; + if (ts.hasProperty(visited, key)) { + return; + } + visited[key] = true; if (depth === 0) { sourceStack = []; targetStack = []; @@ -33034,7 +33140,7 @@ var ts; ts.ioReadTime = 0; ts.ioWriteTime = 0; var emptyArray = []; - ts.version = "1.8.5"; + ts.version = "1.8.9"; function findConfigFile(searchPath, fileExists) { var fileName = "tsconfig.json"; while (true) { @@ -36696,6 +36802,168 @@ var ts; return name; } ts.stripQuotes = stripQuotes; + function scriptKindIs(fileName, host) { + var scriptKinds = []; + for (var _i = 2; _i < arguments.length; _i++) { + scriptKinds[_i - 2] = arguments[_i]; + } + var scriptKind = getScriptKind(fileName, host); + return ts.forEach(scriptKinds, function (k) { return k === scriptKind; }); + } + ts.scriptKindIs = scriptKindIs; + function getScriptKind(fileName, host) { + var scriptKind = ts.getScriptKindFromFileName(fileName); + if (scriptKind === 0 && host && host.getScriptKind) { + scriptKind = host.getScriptKind(fileName); + } + return ts.ensureScriptKind(fileName, scriptKind); + } + ts.getScriptKind = getScriptKind; +})(ts || (ts = {})); +var ts; +(function (ts) { + var JsTyping; + (function (JsTyping) { + ; + ; + var safeList; + function discoverTypings(host, fileNames, projectRootPath, safeListPath, packageNameToTypingLocation, typingOptions, compilerOptions) { + var inferredTypings = {}; + if (!typingOptions || !typingOptions.enableAutoDiscovery) { + return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; + } + fileNames = ts.filter(ts.map(fileNames, ts.normalizePath), function (f) { return ts.scriptKindIs(f, undefined, 1, 2); }); + if (!safeList) { + var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); }); + if (result.config) { + safeList = result.config; + } + else { + safeList = {}; + } + } + var filesToWatch = []; + var searchDirs = []; + var exclude = []; + mergeTypings(typingOptions.include); + exclude = typingOptions.exclude || []; + var possibleSearchDirs = ts.map(fileNames, ts.getDirectoryPath); + if (projectRootPath !== undefined) { + possibleSearchDirs.push(projectRootPath); + } + searchDirs = ts.deduplicate(possibleSearchDirs); + for (var _i = 0, searchDirs_1 = searchDirs; _i < searchDirs_1.length; _i++) { + var searchDir = searchDirs_1[_i]; + var packageJsonPath = ts.combinePaths(searchDir, "package.json"); + getTypingNamesFromJson(packageJsonPath, filesToWatch); + var bowerJsonPath = ts.combinePaths(searchDir, "bower.json"); + getTypingNamesFromJson(bowerJsonPath, filesToWatch); + var nodeModulesPath = ts.combinePaths(searchDir, "node_modules"); + getTypingNamesFromNodeModuleFolder(nodeModulesPath); + } + getTypingNamesFromSourceFileNames(fileNames); + for (var name_34 in packageNameToTypingLocation) { + if (ts.hasProperty(inferredTypings, name_34) && !inferredTypings[name_34]) { + inferredTypings[name_34] = packageNameToTypingLocation[name_34]; + } + } + for (var _a = 0, exclude_1 = exclude; _a < exclude_1.length; _a++) { + var excludeTypingName = exclude_1[_a]; + delete inferredTypings[excludeTypingName]; + } + var newTypingNames = []; + var cachedTypingPaths = []; + for (var typing in inferredTypings) { + if (inferredTypings[typing] !== undefined) { + cachedTypingPaths.push(inferredTypings[typing]); + } + else { + newTypingNames.push(typing); + } + } + return { cachedTypingPaths: cachedTypingPaths, newTypingNames: newTypingNames, filesToWatch: filesToWatch }; + function mergeTypings(typingNames) { + if (!typingNames) { + return; + } + for (var _i = 0, typingNames_1 = typingNames; _i < typingNames_1.length; _i++) { + var typing = typingNames_1[_i]; + if (!ts.hasProperty(inferredTypings, typing)) { + inferredTypings[typing] = undefined; + } + } + } + function getTypingNamesFromJson(jsonPath, filesToWatch) { + var result = ts.readConfigFile(jsonPath, function (path) { return host.readFile(path); }); + if (result.config) { + var jsonConfig = result.config; + filesToWatch.push(jsonPath); + if (jsonConfig.dependencies) { + mergeTypings(ts.getKeys(jsonConfig.dependencies)); + } + if (jsonConfig.devDependencies) { + mergeTypings(ts.getKeys(jsonConfig.devDependencies)); + } + if (jsonConfig.optionalDependencies) { + mergeTypings(ts.getKeys(jsonConfig.optionalDependencies)); + } + if (jsonConfig.peerDependencies) { + mergeTypings(ts.getKeys(jsonConfig.peerDependencies)); + } + } + } + function getTypingNamesFromSourceFileNames(fileNames) { + var jsFileNames = ts.filter(fileNames, ts.hasJavaScriptFileExtension); + var inferredTypingNames = ts.map(jsFileNames, function (f) { return ts.removeFileExtension(ts.getBaseFileName(f.toLowerCase())); }); + var cleanedTypingNames = ts.map(inferredTypingNames, function (f) { return f.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); }); + if (safeList === undefined) { + mergeTypings(cleanedTypingNames); + } + else { + mergeTypings(ts.filter(cleanedTypingNames, function (f) { return ts.hasProperty(safeList, f); })); + } + var hasJsxFile = ts.forEach(fileNames, function (f) { return ts.scriptKindIs(f, undefined, 2); }); + if (hasJsxFile) { + mergeTypings(["react"]); + } + } + function getTypingNamesFromNodeModuleFolder(nodeModulesPath) { + if (!host.directoryExists(nodeModulesPath)) { + return; + } + var typingNames = []; + var fileNames = host.readDirectory(nodeModulesPath, "*.json", undefined, 2); + for (var _i = 0, fileNames_1 = fileNames; _i < fileNames_1.length; _i++) { + var fileName = fileNames_1[_i]; + var normalizedFileName = ts.normalizePath(fileName); + if (ts.getBaseFileName(normalizedFileName) !== "package.json") { + continue; + } + var result = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); }); + if (!result.config) { + continue; + } + var packageJson = result.config; + if (packageJson._requiredBy && + ts.filter(packageJson._requiredBy, function (r) { return r[0] === "#" || r === "/"; }).length === 0) { + continue; + } + if (!packageJson.name) { + continue; + } + if (packageJson.typings) { + var absolutePath = ts.getNormalizedAbsolutePath(packageJson.typings, ts.getDirectoryPath(normalizedFileName)); + inferredTypings[packageJson.name] = absolutePath; + } + else { + typingNames.push(packageJson.name); + } + } + mergeTypings(typingNames); + } + } + JsTyping.discoverTypings = discoverTypings; + })(JsTyping = ts.JsTyping || (ts.JsTyping = {})); })(ts || (ts = {})); var ts; (function (ts) { @@ -37258,9 +37526,9 @@ var ts; } Rules.prototype.getRuleName = function (rule) { var o = this; - for (var name_34 in o) { - if (o[name_34] === rule) { - return name_34; + for (var name_35 in o) { + if (o[name_35] === rule) { + return name_35; } } throw new Error("Unknown rule"); @@ -37854,9 +38122,13 @@ var ts; if (line === 0) { return []; } + var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile); + while (ts.isWhiteSpace(sourceFile.text.charCodeAt(endOfFormatSpan)) && !ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { + endOfFormatSpan--; + } var span = { pos: ts.getStartPositionOfLine(line - 1, sourceFile), - end: ts.getEndLinePosition(line, sourceFile) + 1 + end: endOfFormatSpan + 1 }; return formatSpan(span, sourceFile, options, rulesProvider, 2); } @@ -38978,7 +39250,7 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { - ts.servicesVersion = "0.4"; + ts.servicesVersion = "0.5"; var ScriptSnapshot; (function (ScriptSnapshot) { var StringScriptSnapshot = (function () { @@ -39829,7 +40101,8 @@ var ts; entry = { hostFileName: fileName, version: this.host.getScriptVersion(fileName), - scriptSnapshot: scriptSnapshot + scriptSnapshot: scriptSnapshot, + scriptKind: ts.getScriptKind(fileName, this.host) }; } this.fileNameToEntry.set(path, entry); @@ -39876,10 +40149,11 @@ var ts; if (!scriptSnapshot) { throw new Error("Could not find file: '" + fileName + "'."); } + var scriptKind = ts.getScriptKind(fileName, this.host); var version = this.host.getScriptVersion(fileName); var sourceFile; if (this.currentFileName !== fileName) { - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2, version, true); + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2, version, true, scriptKind); } else if (this.currentFileVersion !== version) { var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); @@ -39954,9 +40228,9 @@ var ts; return output.outputText; } ts.transpile = transpile; - function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents) { + function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents, scriptKind) { var text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - var sourceFile = ts.createSourceFile(fileName, text, scriptTarget, setNodeParents); + var sourceFile = ts.createSourceFile(fileName, text, scriptTarget, setNodeParents, scriptKind); setSourceFileFields(sourceFile, scriptSnapshot, version); return sourceFile; } @@ -39997,7 +40271,7 @@ var ts; } } } - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, true); + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, true, sourceFile.scriptKind); } ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; function createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory) { @@ -40034,19 +40308,19 @@ var ts; }); return JSON.stringify(bucketInfoArray, undefined, 2); } - function acquireDocument(fileName, compilationSettings, scriptSnapshot, version) { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, true); + function acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, true, scriptKind); } - function updateDocument(fileName, compilationSettings, scriptSnapshot, version) { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, false); + function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, false, scriptKind); } - function acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, acquiring) { + function acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, acquiring, scriptKind) { var bucket = getBucketForCompilationSettings(compilationSettings, true); var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); var entry = bucket.get(path); if (!entry) { ts.Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); - var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, false); + var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, false, scriptKind); entry = { sourceFile: sourceFile, languageServiceRefCount: 0, @@ -40610,10 +40884,11 @@ var ts; if (!changesInCompilationSettingsAffectSyntax) { var oldSourceFile = program && program.getSourceFile(fileName); if (oldSourceFile) { - return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version); + ts.Debug.assert(hostFileInformation.scriptKind === oldSourceFile.scriptKind, "Registered script kind (" + oldSourceFile.scriptKind + ") should match new script kind (" + hostFileInformation.scriptKind + ") for file: " + fileName); + return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } } - return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version); + return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } function sourceFileUpToDate(sourceFile) { if (!sourceFile) { @@ -41214,8 +41489,8 @@ var ts; if (element.getStart() <= position && position <= element.getEnd()) { continue; } - var name_35 = element.propertyName || element.name; - exisingImportsOrExports[name_35.text] = true; + var name_36 = element.propertyName || element.name; + exisingImportsOrExports[name_36.text] = true; } if (ts.isEmpty(exisingImportsOrExports)) { return exportsOfModule; @@ -41307,13 +41582,13 @@ var ts; var entries = []; var target = program.getCompilerOptions().target; var nameTable = getNameTable(sourceFile); - for (var name_36 in nameTable) { - if (nameTable[name_36] === position) { + for (var name_37 in nameTable) { + if (nameTable[name_37] === position) { continue; } - if (!uniqueNames[name_36]) { - uniqueNames[name_36] = name_36; - var displayName = getCompletionEntryDisplayName(name_36, target, true); + if (!uniqueNames[name_37]) { + uniqueNames[name_37] = name_37; + var displayName = getCompletionEntryDisplayName(name_37, target, true); if (displayName) { var entry = { name: displayName, @@ -43025,17 +43300,17 @@ var ts; if (isNameOfPropertyAssignment(node)) { var objectLiteral = node.parent.parent; var contextualType = typeChecker.getContextualType(objectLiteral); - var name_37 = node.text; + var name_38 = node.text; if (contextualType) { if (contextualType.flags & 16384) { - var unionProperty = contextualType.getProperty(name_37); + var unionProperty = contextualType.getProperty(name_38); if (unionProperty) { return [unionProperty]; } else { var result_6 = []; ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name_37); + var symbol = t.getProperty(name_38); if (symbol) { result_6.push(symbol); } @@ -43044,7 +43319,7 @@ var ts; } } else { - var symbol_1 = contextualType.getProperty(name_37); + var symbol_1 = contextualType.getProperty(name_38); if (symbol_1) { return [symbol_1]; } @@ -45516,6 +45791,9 @@ var ts; LSHost.prototype.getScriptFileNames = function () { return this.roots.map(function (root) { return root.fileName; }); }; + LSHost.prototype.getScriptKind = function () { + return 0; + }; LSHost.prototype.getScriptVersion = function (filename) { return this.getScriptInfo(filename).svc.latestVersion().toString(); }; @@ -45921,8 +46199,8 @@ var ts; this.inferredProjects = copyListRemovingItem(project, this.inferredProjects); } var fileNames = project.getFileNames(); - for (var _b = 0, fileNames_1 = fileNames; _b < fileNames_1.length; _b++) { - var fileName = fileNames_1[_b]; + for (var _b = 0, fileNames_2 = fileNames; _b < fileNames_2.length; _b++) { + var fileName = fileNames_2[_b]; var info = this.getScriptInfo(fileName); if (info.defaultProject == project) { info.defaultProject = undefined; @@ -46392,6 +46670,7 @@ var ts; else { var defaultOpts = ts.getDefaultCompilerOptions(); defaultOpts.allowNonTsExtensions = true; + defaultOpts.allowJs = true; this.setCompilerOptions(defaultOpts); } this.languageService = ts.createLanguageService(this.host, this.documentRegistry); @@ -47513,6 +47792,14 @@ var ts; var scriptSnapshot = this.shimHost.getScriptSnapshot(fileName); return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot); }; + LanguageServiceShimHostAdapter.prototype.getScriptKind = function (fileName) { + if ("getScriptKind" in this.shimHost) { + return this.shimHost.getScriptKind(fileName); + } + else { + return 0; + } + }; LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) { return this.shimHost.getScriptVersion(fileName); }; @@ -47566,8 +47853,14 @@ var ts; this.directoryExists = function (directoryName) { return _this.shimHost.directoryExists(directoryName); }; } } - CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extension, exclude) { - var encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)); + CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extension, exclude, depth) { + var encoded; + try { + encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude), depth); + } + catch (e) { + encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)); + } return JSON.parse(encoded); }; CoreServicesShimHostAdapter.prototype.fileExists = function (fileName) { @@ -47912,6 +48205,7 @@ var ts; if (result.error) { return { options: {}, + typingOptions: {}, files: [], errors: [realizeDiagnostic(result.error, "\r\n")] }; @@ -47920,6 +48214,7 @@ var ts; var configFile = ts.parseJsonConfigFileContent(result.config, _this.host, ts.getDirectoryPath(normalizedFileName), {}, normalizedFileName); return { options: configFile.options, + typingOptions: configFile.typingOptions, files: configFile.fileNames, errors: realizeDiagnostics(configFile.errors, "\r\n") }; @@ -47928,6 +48223,14 @@ var ts; CoreServicesShimObject.prototype.getDefaultCompilationSettings = function () { return this.forwardJSONCall("getDefaultCompilationSettings()", function () { return ts.getDefaultCompilerOptions(); }); }; + CoreServicesShimObject.prototype.discoverTypings = function (discoverTypingsJson) { + var _this = this; + var getCanonicalFileName = ts.createGetCanonicalFileName(false); + return this.forwardJSONCall("discoverTypings()", function () { + var info = JSON.parse(discoverTypingsJson); + return ts.JsTyping.discoverTypings(_this.host, info.fileNames, ts.toPath(info.projectRootPath, info.projectRootPath, getCanonicalFileName), ts.toPath(info.safeListPath, info.safeListPath, getCanonicalFileName), info.packageNameToTypingLocation, info.typingOptions, info.compilerOptions); + }); + }; return CoreServicesShimObject; }(ShimBase)); var TypeScriptServicesFactory = (function () { diff --git a/lib/typescript.d.ts b/lib/typescript.d.ts index dd32085e5c1..2c1d5e609fb 100644 --- a/lib/typescript.d.ts +++ b/lib/typescript.d.ts @@ -1480,6 +1480,20 @@ declare namespace ts { noImplicitUseStrict?: boolean; [option: string]: string | number | boolean; } + interface TypingOptions { + enableAutoDiscovery?: boolean; + include?: string[]; + exclude?: string[]; + [option: string]: string[] | boolean; + } + interface DiscoverTypingsInfo { + fileNames: string[]; + projectRootPath: string; + safeListPath: string; + packageNameToTypingLocation: Map; + typingOptions: TypingOptions; + compilerOptions: CompilerOptions; + } enum ModuleKind { None = 0, CommonJS = 1, @@ -1502,6 +1516,13 @@ declare namespace ts { line: number; character: number; } + enum ScriptKind { + Unknown = 0, + JS = 1, + JSX = 2, + TS = 3, + TSX = 4, + } enum ScriptTarget { ES3 = 0, ES5 = 1, @@ -1515,6 +1536,7 @@ declare namespace ts { } interface ParsedCommandLine { options: CompilerOptions; + typingOptions?: TypingOptions; fileNames: string[]; errors: Diagnostic[]; } @@ -1663,7 +1685,7 @@ declare namespace ts { declare namespace ts { function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T; - function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean): SourceFile; + function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; } declare namespace ts { @@ -1798,6 +1820,7 @@ declare namespace ts { getNewLine?(): string; getProjectVersion?(): string; getScriptFileNames(): string[]; + getScriptKind?(fileName: string): ScriptKind; getScriptVersion(fileName: string): string; getScriptSnapshot(fileName: string): IScriptSnapshot; getLocalizedDiagnosticMessages?(): any; @@ -2166,7 +2189,7 @@ declare namespace ts { * @parm version Current version of the file. Only used if the file was not found * in the registry and a new one was created. */ - acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile; + acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; /** * Request an updated version of an already existing SourceFile with a given fileName * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile @@ -2179,7 +2202,7 @@ declare namespace ts { * @param scriptSnapshot Text of the file. * @param version Current version of the file. */ - updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile; + updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; /** * Informs the DocumentRegistry that a file is not needed any longer. * @@ -2303,7 +2326,7 @@ declare namespace ts { } function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput; function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; - function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile; + function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile; let disableIncrementalParsing: boolean; function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory?: string): DocumentRegistry; diff --git a/lib/typescript.js b/lib/typescript.js index 5923ee0e111..a952502f6ed 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -409,7 +409,7 @@ var ts; // its type can be specified usign a JSDoc comment. ParserContextFlags[ParserContextFlags["JavaScriptFile"] = 32] = "JavaScriptFile"; // Context flags set directly by the parser. - ParserContextFlags[ParserContextFlags["ParserGeneratedFlags"] = 31] = "ParserGeneratedFlags"; + ParserContextFlags[ParserContextFlags["ParserGeneratedFlags"] = 63] = "ParserGeneratedFlags"; // Exclude these flags when parsing a Type ParserContextFlags[ParserContextFlags["TypeExcludesFlags"] = 10] = "TypeExcludesFlags"; // Context flags computed by aggregating child flags upwards. @@ -716,6 +716,14 @@ var ts; NewLineKind[NewLineKind["LineFeed"] = 1] = "LineFeed"; })(ts.NewLineKind || (ts.NewLineKind = {})); var NewLineKind = ts.NewLineKind; + (function (ScriptKind) { + ScriptKind[ScriptKind["Unknown"] = 0] = "Unknown"; + ScriptKind[ScriptKind["JS"] = 1] = "JS"; + ScriptKind[ScriptKind["JSX"] = 2] = "JSX"; + ScriptKind[ScriptKind["TS"] = 3] = "TS"; + ScriptKind[ScriptKind["TSX"] = 4] = "TSX"; + })(ts.ScriptKind || (ts.ScriptKind = {})); + var ScriptKind = ts.ScriptKind; (function (ScriptTarget) { ScriptTarget[ScriptTarget["ES3"] = 0] = "ES3"; ScriptTarget[ScriptTarget["ES5"] = 1] = "ES5"; @@ -1137,6 +1145,14 @@ var ts; return hasOwnProperty.call(map, key); } ts.hasProperty = hasProperty; + function getKeys(map) { + var keys = []; + for (var key in map) { + keys.push(key); + } + return keys; + } + ts.getKeys = getKeys; function getProperty(map, key) { return hasOwnProperty.call(map, key) ? map[key] : undefined; } @@ -1594,6 +1610,32 @@ var ts; return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension; } ts.fileExtensionIs = fileExtensionIs; + function ensureScriptKind(fileName, scriptKind) { + // Using scriptKind as a condition handles both: + // - 'scriptKind' is unspecified and thus it is `undefined` + // - 'scriptKind' is set and it is `Unknown` (0) + // If the 'scriptKind' is 'undefined' or 'Unknown' then we attempt + // to get the ScriptKind from the file name. If it cannot be resolved + // from the file name then the default 'TS' script kind is returned. + return (scriptKind || getScriptKindFromFileName(fileName)) || 3 /* TS */; + } + ts.ensureScriptKind = ensureScriptKind; + function getScriptKindFromFileName(fileName) { + var ext = fileName.substr(fileName.lastIndexOf(".")); + switch (ext.toLowerCase()) { + case ".js": + return 1 /* JS */; + case ".jsx": + return 2 /* JSX */; + case ".ts": + return 3 /* TS */; + case ".tsx": + return 4 /* TSX */; + default: + return 0 /* Unknown */; + } + } + ts.getScriptKindFromFileName = getScriptKindFromFileName; /** * List of supported extensions in order of file resolution precedence. */ @@ -2819,6 +2861,7 @@ var ts; Only_amd_and_system_modules_are_supported_alongside_0: { code: 6082, category: ts.DiagnosticCategory.Error, key: "Only_amd_and_system_modules_are_supported_alongside_0_6082", message: "Only 'amd' and 'system' modules are supported alongside --{0}." }, Allow_javascript_files_to_be_compiled: { code: 6083, category: ts.DiagnosticCategory.Message, key: "Allow_javascript_files_to_be_compiled_6083", message: "Allow javascript files to be compiled." }, Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit: { code: 6084, category: ts.DiagnosticCategory.Message, key: "Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit_6084", message: "Specifies the object invoked for createElement and __spread when targeting 'react' JSX emit" }, + Option_0_should_have_array_of_strings_as_a_value: { code: 6103, category: ts.DiagnosticCategory.Error, key: "Option_0_should_have_array_of_strings_as_a_value_6103", message: "Option '{0}' should have array of strings as a value." }, Do_not_emit_use_strict_directives_in_module_output: { code: 6112, category: ts.DiagnosticCategory.Message, key: "Do_not_emit_use_strict_directives_in_module_output_6112", message: "Do not emit 'use strict' directives in module output." }, 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." }, @@ -2869,7 +2912,8 @@ var ts; An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses: { code: 17006, category: ts.DiagnosticCategory.Error, key: "An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_ex_17006", message: "An unary expression with the '{0}' operator is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses." }, A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses: { code: 17007, category: ts.DiagnosticCategory.Error, key: "A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Con_17007", message: "A type assertion expression is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses." }, JSX_element_0_has_no_corresponding_closing_tag: { code: 17008, category: ts.DiagnosticCategory.Error, key: "JSX_element_0_has_no_corresponding_closing_tag_17008", message: "JSX element '{0}' has no corresponding closing tag." }, - super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: ts.DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." } + super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: ts.DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." }, + Unknown_typing_option_0: { code: 17010, category: ts.DiagnosticCategory.Error, key: "Unknown_typing_option_0_17010", message: "Unknown typing option '{0}'." } }; })(ts || (ts = {})); /// @@ -5548,6 +5592,9 @@ var ts; /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property /// assignments we treat as special in the binder function getSpecialPropertyAssignmentKind(expression) { + if (!isInJavaScriptFile(expression)) { + return 0 /* None */; + } if (expression.kind !== 184 /* BinaryExpression */) { return 0 /* None */; } @@ -7557,10 +7604,10 @@ var ts; } } ts.forEachChild = forEachChild; - function createSourceFile(fileName, sourceText, languageVersion, setParentNodes) { + function createSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind) { if (setParentNodes === void 0) { setParentNodes = false; } var start = new Date().getTime(); - var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes); + var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); ts.parseTime += new Date().getTime() - start; return result; } @@ -7685,19 +7732,19 @@ var ts; // Note: any errors at the end of the file that do not precede a regular node, should get // attached to the EOF token. var parseErrorBeforeNextFinishedNode = false; - function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes) { - var isJavaScriptFile = ts.hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0; - initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor); - var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes); + function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes, scriptKind) { + scriptKind = ts.ensureScriptKind(fileName, scriptKind); + initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind); + var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); clearState(); return result; } Parser.parseSourceFile = parseSourceFile; - function getLanguageVariant(fileName) { + function getLanguageVariant(scriptKind) { // .tsx and .jsx files are treated as jsx language variant. - return ts.fileExtensionIs(fileName, ".tsx") || ts.fileExtensionIs(fileName, ".jsx") || ts.fileExtensionIs(fileName, ".js") ? 1 /* JSX */ : 0 /* Standard */; + return scriptKind === 4 /* TSX */ || scriptKind === 2 /* JSX */ || scriptKind === 1 /* JS */ ? 1 /* JSX */ : 0 /* Standard */; } - function initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor) { + function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind) { NodeConstructor = ts.objectAllocator.getNodeConstructor(); SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); sourceText = _sourceText; @@ -7707,13 +7754,13 @@ var ts; identifiers = {}; identifierCount = 0; nodeCount = 0; - contextFlags = isJavaScriptFile ? 32 /* JavaScriptFile */ : 0 /* None */; + contextFlags = scriptKind === 1 /* JS */ || scriptKind === 2 /* JSX */ ? 32 /* JavaScriptFile */ : 0 /* None */; parseErrorBeforeNextFinishedNode = false; // Initialize and prime the scanner before parsing the source elements. scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(getLanguageVariant(fileName)); + scanner.setLanguageVariant(getLanguageVariant(scriptKind)); } function clearState() { // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. @@ -7726,8 +7773,8 @@ var ts; syntaxCursor = undefined; sourceText = undefined; } - function parseSourceFileWorker(fileName, languageVersion, setParentNodes) { - sourceFile = createSourceFile(fileName, languageVersion); + function parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind) { + sourceFile = createSourceFile(fileName, languageVersion, scriptKind); if (contextFlags & 32 /* JavaScriptFile */) { sourceFile.parserContextFlags = 32 /* JavaScriptFile */; } @@ -7784,7 +7831,7 @@ var ts; } } Parser.fixupParentReferences = fixupParentReferences; - function createSourceFile(fileName, languageVersion) { + function createSourceFile(fileName, languageVersion, scriptKind) { // code from createNode is inlined here so createNode won't have to deal with special case of creating source files // this is quite rare comparing to other nodes and createNode should be as fast as possible var sourceFile = new SourceFileConstructor(251 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length); @@ -7794,7 +7841,8 @@ var ts; sourceFile.languageVersion = languageVersion; sourceFile.fileName = ts.normalizePath(fileName); sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 4096 /* DeclarationFile */ : 0; - sourceFile.languageVariant = getLanguageVariant(sourceFile.fileName); + sourceFile.languageVariant = getLanguageVariant(scriptKind); + sourceFile.scriptKind = scriptKind; return sourceFile; } function setContextFlag(val, flag) { @@ -8460,7 +8508,7 @@ var ts; // differently depending on what mode it is in. // // This also applies to all our other context flags as well. - var nodeContextFlags = node.parserContextFlags & 31 /* ParserGeneratedFlags */; + var nodeContextFlags = node.parserContextFlags & 63 /* ParserGeneratedFlags */; if (nodeContextFlags !== contextFlags) { return undefined; } @@ -12100,7 +12148,7 @@ var ts; } JSDocParser.isJSDocType = isJSDocType; function parseJSDocTypeExpressionForTests(content, start, length) { - initializeState("file.js", content, 2 /* Latest */, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined); + initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); scanner.setText(content, start, length); token = scanner.scan(); var jsDocTypeExpression = parseJSDocTypeExpression(); @@ -12367,7 +12415,7 @@ var ts; } } function parseIsolatedJSDocComment(content, start, length) { - initializeState("file.js", content, 2 /* Latest */, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined); + initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); sourceFile = { languageVariant: 0 /* Standard */, text: content }; var jsDocComment = parseJSDocCommentWorker(start, length); var diagnostics = parseDiagnostics; @@ -12637,7 +12685,7 @@ var ts; if (sourceFile.statements.length === 0) { // If we don't have any statements in the current source file, then there's no real // way to incrementally parse. So just do a full parse instead. - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true); + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind); } // Make sure we're not trying to incrementally update a source file more than once. Once // we do an update the original source file is considered unusbale from that point onwards. @@ -12693,7 +12741,7 @@ var ts; // inconsistent tree. Setting the parents on the new tree should be very fast. We // will immediately bail out of walking any subtrees when we can see that their parents // are already correct. - var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true); + var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind); return result; } IncrementalParser.updateSourceFile = updateSourceFile; @@ -13745,6 +13793,7 @@ var ts; case 146 /* GetAccessor */: case 147 /* SetAccessor */: case 153 /* FunctionType */: + case 264 /* JSDocFunctionType */: case 154 /* ConstructorType */: case 176 /* FunctionExpression */: case 177 /* ArrowFunction */: @@ -14350,7 +14399,7 @@ var ts; function bindModuleExportsAssignment(node) { // 'module.exports = expr' assignment setCommonJsModuleIndicator(node); - bindExportAssignment(node); + declareSymbol(file.symbol.exports, file.symbol, node, 4 /* Property */ | 7340032 /* Export */ | 512 /* ValueModule */, 0 /* None */); } function bindThisPropertyAssignment(node) { // Declare a 'member' in case it turns out the container was an ES5 class @@ -14380,7 +14429,8 @@ var ts; funcSymbol.members = {}; } // Declare the method/property - declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4 /* Property */, 107455 /* PropertyExcludes */); + // It's acceptable for multiple prototype property assignments of the same identifier to occur + declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4 /* Property */, 107455 /* PropertyExcludes */ & ~4 /* Property */); } function bindCallExpression(node) { // We're only inspecting call expressions to detect CommonJS modules, so we can skip @@ -15439,7 +15489,9 @@ var ts; function getTargetOfImportClause(node) { var moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier); if (moduleSymbol) { - var exportDefaultSymbol = resolveSymbol(moduleSymbol.exports["default"]); + var exportDefaultSymbol = moduleSymbol.exports["export="] ? + getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") : + resolveSymbol(moduleSymbol.exports["default"]); if (!exportDefaultSymbol && !allowSyntheticDefaultImports) { error(node.name, ts.Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); } @@ -15508,8 +15560,15 @@ var ts; if (targetSymbol) { var name_9 = specifier.propertyName || specifier.name; if (name_9.text) { + var symbolFromVariable = void 0; + // First check if module was specified with "export=". If so, get the member from the resolved type + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports["export="]) { + symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name_9.text); + } + else { + symbolFromVariable = getPropertyOfVariable(targetSymbol, name_9.text); + } var symbolFromModule = getExportOfModule(targetSymbol, name_9.text); - var symbolFromVariable = getPropertyOfVariable(targetSymbol, name_9.text); var symbol = symbolFromModule && symbolFromVariable ? combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) : symbolFromModule || symbolFromVariable; @@ -19403,7 +19462,7 @@ var ts; for (var i = 0; i < checkCount; i++) { var s = i < sourceMax ? getTypeOfSymbol(sourceParams[i]) : getRestTypeOfSignature(source); var t = i < targetMax ? getTypeOfSymbol(targetParams[i]) : getRestTypeOfSignature(target); - var related = compareTypes(t, s, /*reportErrors*/ false) || compareTypes(s, t, reportErrors); + var related = compareTypes(s, t, /*reportErrors*/ false) || compareTypes(t, s, reportErrors); if (!related) { if (reportErrors) { errorReporter(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, sourceParams[i < sourceMax ? i : sourceMax].name, targetParams[i < targetMax ? i : targetMax].name); @@ -20528,8 +20587,10 @@ var ts; function inferTypes(context, source, target) { var sourceStack; var targetStack; + var maxDepth = 5; var depth = 0; var inferiority = 0; + var visited = {}; inferFromTypes(source, target); function isInProcess(source, target) { for (var i = 0; i < depth; i++) { @@ -20655,9 +20716,19 @@ var ts; if (isInProcess(source, target)) { return; } + // we delibirately limit the depth we examine to infer types: this speeds up the overall inference process + // and user rarely expects inferences to be made from the deeply nested constituents. + if (depth > maxDepth) { + return; + } if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { return; } + var key = source.id + "," + target.id; + if (ts.hasProperty(visited, key)) { + return; + } + visited[key] = true; if (depth === 0) { sourceStack = []; targetStack = []; @@ -39261,7 +39332,7 @@ var ts; /* @internal */ ts.ioWriteTime = 0; /** The version of the TypeScript compiler release */ var emptyArray = []; - ts.version = "1.8.5"; + ts.version = "1.8.9"; function findConfigFile(searchPath, fileExists) { var fileName = "tsconfig.json"; while (true) { @@ -40972,6 +41043,7 @@ var ts; return { options: options, fileNames: getFileNames(), + typingOptions: getTypingOptions(), errors: errors }; function getFileNames() { @@ -41031,6 +41103,34 @@ var ts; } return fileNames; } + function getTypingOptions() { + var options = ts.getBaseFileName(configFileName) === "jsconfig.json" + ? { enableAutoDiscovery: true, include: [], exclude: [] } + : { enableAutoDiscovery: false, include: [], exclude: [] }; + var jsonTypingOptions = json["typingOptions"]; + if (jsonTypingOptions) { + for (var id in jsonTypingOptions) { + if (id === "enableAutoDiscovery") { + if (typeof jsonTypingOptions[id] === "boolean") { + options.enableAutoDiscovery = jsonTypingOptions[id]; + } + else { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_typing_option_0, id)); + } + } + else if (id === "include") { + options.include = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); + } + else if (id === "exclude") { + options.exclude = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); + } + else { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_typing_option_0, id)); + } + } + } + return options; + } } ts.parseJsonConfigFileContent = parseJsonConfigFileContent; function convertCompilerOptionsFromJson(jsonOptions, basePath, configFileName) { @@ -41079,6 +41179,30 @@ var ts; return { options: options, errors: errors }; } ts.convertCompilerOptionsFromJson = convertCompilerOptionsFromJson; + function convertJsonOptionToStringArray(optionName, optionJson, errors, func) { + var items = []; + var invalidOptionType = false; + if (!ts.isArray(optionJson)) { + invalidOptionType = true; + } + else { + for (var _i = 0, _a = optionJson; _i < _a.length; _i++) { + var element = _a[_i]; + if (typeof element === "string") { + var item = func ? func(element) : element; + items.push(item); + } + else { + invalidOptionType = true; + break; + } + } + } + if (invalidOptionType) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_should_have_array_of_strings_as_a_value, optionName)); + } + return items; + } })(ts || (ts = {})); /* @internal */ var ts; @@ -43742,6 +43866,212 @@ var ts; return name; } ts.stripQuotes = stripQuotes; + function scriptKindIs(fileName, host) { + var scriptKinds = []; + for (var _i = 2; _i < arguments.length; _i++) { + scriptKinds[_i - 2] = arguments[_i]; + } + var scriptKind = getScriptKind(fileName, host); + return ts.forEach(scriptKinds, function (k) { return k === scriptKind; }); + } + ts.scriptKindIs = scriptKindIs; + function getScriptKind(fileName, host) { + // First check to see if the script kind can be determined from the file name + var scriptKind = ts.getScriptKindFromFileName(fileName); + if (scriptKind === 0 /* Unknown */ && host && host.getScriptKind) { + // Next check to see if the host can resolve the script kind + scriptKind = host.getScriptKind(fileName); + } + return ts.ensureScriptKind(fileName, scriptKind); + } + ts.getScriptKind = getScriptKind; +})(ts || (ts = {})); +// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. +// See LICENSE.txt in the project root for complete license information. +/// +/* @internal */ +var ts; +(function (ts) { + var JsTyping; + (function (JsTyping) { + ; + ; + // A map of loose file names to library names + // that we are confident require typings + var safeList; + /** + * @param host is the object providing I/O related operations. + * @param fileNames are the file names that belong to the same project + * @param projectRootPath is the path to the project root directory + * @param safeListPath is the path used to retrieve the safe list + * @param packageNameToTypingLocation is the map of package names to their cached typing locations + * @param typingOptions are used to customize the typing inference process + * @param compilerOptions are used as a source for typing inference + */ + function discoverTypings(host, fileNames, projectRootPath, safeListPath, packageNameToTypingLocation, typingOptions, compilerOptions) { + // A typing name to typing file path mapping + var inferredTypings = {}; + if (!typingOptions || !typingOptions.enableAutoDiscovery) { + return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; + } + // Only infer typings for .js and .jsx files + fileNames = ts.filter(ts.map(fileNames, ts.normalizePath), function (f) { return ts.scriptKindIs(f, /*LanguageServiceHost*/ undefined, 1 /* JS */, 2 /* JSX */); }); + if (!safeList) { + var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); }); + if (result.config) { + safeList = result.config; + } + else { + safeList = {}; + } + } + var filesToWatch = []; + // Directories to search for package.json, bower.json and other typing information + var searchDirs = []; + var exclude = []; + mergeTypings(typingOptions.include); + exclude = typingOptions.exclude || []; + var possibleSearchDirs = ts.map(fileNames, ts.getDirectoryPath); + if (projectRootPath !== undefined) { + possibleSearchDirs.push(projectRootPath); + } + searchDirs = ts.deduplicate(possibleSearchDirs); + for (var _i = 0, searchDirs_1 = searchDirs; _i < searchDirs_1.length; _i++) { + var searchDir = searchDirs_1[_i]; + var packageJsonPath = ts.combinePaths(searchDir, "package.json"); + getTypingNamesFromJson(packageJsonPath, filesToWatch); + var bowerJsonPath = ts.combinePaths(searchDir, "bower.json"); + getTypingNamesFromJson(bowerJsonPath, filesToWatch); + var nodeModulesPath = ts.combinePaths(searchDir, "node_modules"); + getTypingNamesFromNodeModuleFolder(nodeModulesPath); + } + getTypingNamesFromSourceFileNames(fileNames); + // Add the cached typing locations for inferred typings that are already installed + for (var name_34 in packageNameToTypingLocation) { + if (ts.hasProperty(inferredTypings, name_34) && !inferredTypings[name_34]) { + inferredTypings[name_34] = packageNameToTypingLocation[name_34]; + } + } + // Remove typings that the user has added to the exclude list + for (var _a = 0, exclude_1 = exclude; _a < exclude_1.length; _a++) { + var excludeTypingName = exclude_1[_a]; + delete inferredTypings[excludeTypingName]; + } + var newTypingNames = []; + var cachedTypingPaths = []; + for (var typing in inferredTypings) { + if (inferredTypings[typing] !== undefined) { + cachedTypingPaths.push(inferredTypings[typing]); + } + else { + newTypingNames.push(typing); + } + } + return { cachedTypingPaths: cachedTypingPaths, newTypingNames: newTypingNames, filesToWatch: filesToWatch }; + /** + * Merge a given list of typingNames to the inferredTypings map + */ + function mergeTypings(typingNames) { + if (!typingNames) { + return; + } + for (var _i = 0, typingNames_1 = typingNames; _i < typingNames_1.length; _i++) { + var typing = typingNames_1[_i]; + if (!ts.hasProperty(inferredTypings, typing)) { + inferredTypings[typing] = undefined; + } + } + } + /** + * Get the typing info from common package manager json files like package.json or bower.json + */ + function getTypingNamesFromJson(jsonPath, filesToWatch) { + var result = ts.readConfigFile(jsonPath, function (path) { return host.readFile(path); }); + if (result.config) { + var jsonConfig = result.config; + filesToWatch.push(jsonPath); + if (jsonConfig.dependencies) { + mergeTypings(ts.getKeys(jsonConfig.dependencies)); + } + if (jsonConfig.devDependencies) { + mergeTypings(ts.getKeys(jsonConfig.devDependencies)); + } + if (jsonConfig.optionalDependencies) { + mergeTypings(ts.getKeys(jsonConfig.optionalDependencies)); + } + if (jsonConfig.peerDependencies) { + mergeTypings(ts.getKeys(jsonConfig.peerDependencies)); + } + } + } + /** + * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js" + * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred + * to the 'angular-route' typing name. + * @param fileNames are the names for source files in the project + */ + function getTypingNamesFromSourceFileNames(fileNames) { + var jsFileNames = ts.filter(fileNames, ts.hasJavaScriptFileExtension); + var inferredTypingNames = ts.map(jsFileNames, function (f) { return ts.removeFileExtension(ts.getBaseFileName(f.toLowerCase())); }); + var cleanedTypingNames = ts.map(inferredTypingNames, function (f) { return f.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); }); + if (safeList === undefined) { + mergeTypings(cleanedTypingNames); + } + else { + mergeTypings(ts.filter(cleanedTypingNames, function (f) { return ts.hasProperty(safeList, f); })); + } + var hasJsxFile = ts.forEach(fileNames, function (f) { return ts.scriptKindIs(f, /*LanguageServiceHost*/ undefined, 2 /* JSX */); }); + if (hasJsxFile) { + mergeTypings(["react"]); + } + } + /** + * Infer typing names from node_module folder + * @param nodeModulesPath is the path to the "node_modules" folder + */ + function getTypingNamesFromNodeModuleFolder(nodeModulesPath) { + // Todo: add support for ModuleResolutionHost too + if (!host.directoryExists(nodeModulesPath)) { + return; + } + var typingNames = []; + var fileNames = host.readDirectory(nodeModulesPath, "*.json", /*exclude*/ undefined, /*depth*/ 2); + for (var _i = 0, fileNames_1 = fileNames; _i < fileNames_1.length; _i++) { + var fileName = fileNames_1[_i]; + var normalizedFileName = ts.normalizePath(fileName); + if (ts.getBaseFileName(normalizedFileName) !== "package.json") { + continue; + } + var result = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); }); + if (!result.config) { + continue; + } + var packageJson = result.config; + // npm 3's package.json contains a "_requiredBy" field + // we should include all the top level module names for npm 2, and only module names whose + // "_requiredBy" field starts with "#" or equals "/" for npm 3. + if (packageJson._requiredBy && + ts.filter(packageJson._requiredBy, function (r) { return r[0] === "#" || r === "/"; }).length === 0) { + continue; + } + // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used + // to download d.ts files from DefinitelyTyped + if (!packageJson.name) { + continue; + } + if (packageJson.typings) { + var absolutePath = ts.getNormalizedAbsolutePath(packageJson.typings, ts.getDirectoryPath(normalizedFileName)); + inferredTypings[packageJson.name] = absolutePath; + } + else { + typingNames.push(packageJson.name); + } + } + mergeTypings(typingNames); + } + } + JsTyping.discoverTypings = discoverTypings; + })(JsTyping = ts.JsTyping || (ts.JsTyping = {})); })(ts || (ts = {})); /// /// @@ -44452,9 +44782,9 @@ var ts; } Rules.prototype.getRuleName = function (rule) { var o = this; - for (var name_34 in o) { - if (o[name_34] === rule) { - return name_34; + for (var name_35 in o) { + if (o[name_35] === rule) { + return name_35; } } throw new Error("Unknown rule"); @@ -45129,12 +45459,20 @@ var ts; if (line === 0) { return []; } - // get the span for the previous\current line + // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters. + // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as + // trailing whitespaces. So the end of the formatting span should be the later one between: + // 1. the end of the previous line + // 2. the last non-whitespace character in the current line + var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile); + while (ts.isWhiteSpace(sourceFile.text.charCodeAt(endOfFormatSpan)) && !ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { + endOfFormatSpan--; + } var span = { // get start position for the previous line pos: ts.getStartPositionOfLine(line - 1, sourceFile), - // get end position for the current line (end value is exclusive so add 1 to the result) - end: ts.getEndLinePosition(line, sourceFile) + 1 + // end value is exclusive so add 1 to the result + end: endOfFormatSpan + 1 }; return formatSpan(span, sourceFile, options, rulesProvider, 2 /* FormatOnEnter */); } @@ -46456,12 +46794,13 @@ var ts; /// /// /// +/// /// /// var ts; (function (ts) { /** The version of the language service API */ - ts.servicesVersion = "0.4"; + ts.servicesVersion = "0.5"; var ScriptSnapshot; (function (ScriptSnapshot) { var StringScriptSnapshot = (function () { @@ -47449,7 +47788,8 @@ var ts; entry = { hostFileName: fileName, version: this.host.getScriptVersion(fileName), - scriptSnapshot: scriptSnapshot + scriptSnapshot: scriptSnapshot, + scriptKind: ts.getScriptKind(fileName, this.host) }; } this.fileNameToEntry.set(path, entry); @@ -47497,11 +47837,12 @@ var ts; // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } + var scriptKind = ts.getScriptKind(fileName, this.host); var version = this.host.getScriptVersion(fileName); var sourceFile; if (this.currentFileName !== fileName) { // This is a new file, just parse it - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2 /* Latest */, version, /*setNodeParents*/ true); + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2 /* Latest */, version, /*setNodeParents*/ true, scriptKind); } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. @@ -47601,9 +47942,9 @@ var ts; return output.outputText; } ts.transpile = transpile; - function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents) { + function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents, scriptKind) { var text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - var sourceFile = ts.createSourceFile(fileName, text, scriptTarget, setNodeParents); + var sourceFile = ts.createSourceFile(fileName, text, scriptTarget, setNodeParents, scriptKind); setSourceFileFields(sourceFile, scriptSnapshot, version); return sourceFile; } @@ -47656,7 +47997,7 @@ var ts; } } // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true); + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind); } ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; function createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory) { @@ -47695,20 +48036,20 @@ var ts; }); return JSON.stringify(bucketInfoArray, undefined, 2); } - function acquireDocument(fileName, compilationSettings, scriptSnapshot, version) { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true); + function acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true, scriptKind); } - function updateDocument(fileName, compilationSettings, scriptSnapshot, version) { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false); + function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false, scriptKind); } - function acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, acquiring) { + function acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, acquiring, scriptKind) { var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); var entry = bucket.get(path); if (!entry) { ts.Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); // Have never seen this file with these settings. Create a new source file for it. - var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false); + var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind); entry = { sourceFile: sourceFile, languageServiceRefCount: 0, @@ -48396,11 +48737,15 @@ var ts; // it's source file any more, and instead defers to DocumentRegistry to get // either version 1, version 2 (or some other version) depending on what the // host says should be used. - return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version); + // We do not support the scenario where a host can modify a registered + // file's script kind, i.e. in one project some file is treated as ".ts" + // and in another as ".js" + ts.Debug.assert(hostFileInformation.scriptKind === oldSourceFile.scriptKind, "Registered script kind (" + oldSourceFile.scriptKind + ") should match new script kind (" + hostFileInformation.scriptKind + ") for file: " + fileName); + return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } } // Could not find this file in the old program, create a new SourceFile for it. - return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version); + return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } function sourceFileUpToDate(sourceFile) { if (!sourceFile) { @@ -49153,8 +49498,8 @@ var ts; if (element.getStart() <= position && position <= element.getEnd()) { continue; } - var name_35 = element.propertyName || element.name; - exisingImportsOrExports[name_35.text] = true; + var name_36 = element.propertyName || element.name; + exisingImportsOrExports[name_36.text] = true; } if (ts.isEmpty(exisingImportsOrExports)) { return exportsOfModule; @@ -49271,14 +49616,14 @@ var ts; var entries = []; var target = program.getCompilerOptions().target; var nameTable = getNameTable(sourceFile); - for (var name_36 in nameTable) { + for (var name_37 in nameTable) { // Skip identifiers produced only from the current location - if (nameTable[name_36] === position) { + if (nameTable[name_37] === position) { continue; } - if (!uniqueNames[name_36]) { - uniqueNames[name_36] = name_36; - var displayName = getCompletionEntryDisplayName(name_36, target, /*performCharacterChecks*/ true); + if (!uniqueNames[name_37]) { + uniqueNames[name_37] = name_37; + var displayName = getCompletionEntryDisplayName(name_37, target, /*performCharacterChecks*/ true); if (displayName) { var entry = { name: displayName, @@ -51230,19 +51575,19 @@ var ts; if (isNameOfPropertyAssignment(node)) { var objectLiteral = node.parent.parent; var contextualType = typeChecker.getContextualType(objectLiteral); - var name_37 = node.text; + var name_38 = node.text; if (contextualType) { if (contextualType.flags & 16384 /* Union */) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - var unionProperty = contextualType.getProperty(name_37); + var unionProperty = contextualType.getProperty(name_38); if (unionProperty) { return [unionProperty]; } else { var result_6 = []; ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name_37); + var symbol = t.getProperty(name_38); if (symbol) { result_6.push(symbol); } @@ -51251,7 +51596,7 @@ var ts; } } else { - var symbol_1 = contextualType.getProperty(name_37); + var symbol_1 = contextualType.getProperty(name_38); if (symbol_1) { return [symbol_1]; } @@ -53628,6 +53973,14 @@ var ts; var scriptSnapshot = this.shimHost.getScriptSnapshot(fileName); return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot); }; + LanguageServiceShimHostAdapter.prototype.getScriptKind = function (fileName) { + if ("getScriptKind" in this.shimHost) { + return this.shimHost.getScriptKind(fileName); + } + else { + return 0 /* Unknown */; + } + }; LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) { return this.shimHost.getScriptVersion(fileName); }; @@ -53686,8 +54039,16 @@ var ts; this.directoryExists = function (directoryName) { return _this.shimHost.directoryExists(directoryName); }; } } - CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extension, exclude) { - var encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)); + CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extension, exclude, depth) { + // Wrap the API changes for 2.0 release. This try/catch + // should be removed once TypeScript 2.0 has shipped. + var encoded; + try { + encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude), depth); + } + catch (e) { + encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)); + } return JSON.parse(encoded); }; CoreServicesShimHostAdapter.prototype.fileExists = function (fileName) { @@ -54090,6 +54451,7 @@ var ts; if (result.error) { return { options: {}, + typingOptions: {}, files: [], errors: [realizeDiagnostic(result.error, "\r\n")] }; @@ -54098,6 +54460,7 @@ var ts; var configFile = ts.parseJsonConfigFileContent(result.config, _this.host, ts.getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName); return { options: configFile.options, + typingOptions: configFile.typingOptions, files: configFile.fileNames, errors: realizeDiagnostics(configFile.errors, "\r\n") }; @@ -54106,6 +54469,14 @@ var ts; CoreServicesShimObject.prototype.getDefaultCompilationSettings = function () { return this.forwardJSONCall("getDefaultCompilationSettings()", function () { return ts.getDefaultCompilerOptions(); }); }; + CoreServicesShimObject.prototype.discoverTypings = function (discoverTypingsJson) { + var _this = this; + var getCanonicalFileName = ts.createGetCanonicalFileName(/*useCaseSensitivefileNames:*/ false); + return this.forwardJSONCall("discoverTypings()", function () { + var info = JSON.parse(discoverTypingsJson); + return ts.JsTyping.discoverTypings(_this.host, info.fileNames, ts.toPath(info.projectRootPath, info.projectRootPath, getCanonicalFileName), ts.toPath(info.safeListPath, info.safeListPath, getCanonicalFileName), info.packageNameToTypingLocation, info.typingOptions, info.compilerOptions); + }); + }; return CoreServicesShimObject; }(ShimBase)); var TypeScriptServicesFactory = (function () { diff --git a/lib/typescriptServices.d.ts b/lib/typescriptServices.d.ts index 3b098c5dc24..2a21625c2af 100644 --- a/lib/typescriptServices.d.ts +++ b/lib/typescriptServices.d.ts @@ -1480,6 +1480,20 @@ declare namespace ts { noImplicitUseStrict?: boolean; [option: string]: string | number | boolean; } + interface TypingOptions { + enableAutoDiscovery?: boolean; + include?: string[]; + exclude?: string[]; + [option: string]: string[] | boolean; + } + interface DiscoverTypingsInfo { + fileNames: string[]; + projectRootPath: string; + safeListPath: string; + packageNameToTypingLocation: Map; + typingOptions: TypingOptions; + compilerOptions: CompilerOptions; + } enum ModuleKind { None = 0, CommonJS = 1, @@ -1502,6 +1516,13 @@ declare namespace ts { line: number; character: number; } + enum ScriptKind { + Unknown = 0, + JS = 1, + JSX = 2, + TS = 3, + TSX = 4, + } enum ScriptTarget { ES3 = 0, ES5 = 1, @@ -1515,6 +1536,7 @@ declare namespace ts { } interface ParsedCommandLine { options: CompilerOptions; + typingOptions?: TypingOptions; fileNames: string[]; errors: Diagnostic[]; } @@ -1663,7 +1685,7 @@ declare namespace ts { declare namespace ts { function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T; - function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean): SourceFile; + function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; } declare namespace ts { @@ -1798,6 +1820,7 @@ declare namespace ts { getNewLine?(): string; getProjectVersion?(): string; getScriptFileNames(): string[]; + getScriptKind?(fileName: string): ScriptKind; getScriptVersion(fileName: string): string; getScriptSnapshot(fileName: string): IScriptSnapshot; getLocalizedDiagnosticMessages?(): any; @@ -2166,7 +2189,7 @@ declare namespace ts { * @parm version Current version of the file. Only used if the file was not found * in the registry and a new one was created. */ - acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile; + acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; /** * Request an updated version of an already existing SourceFile with a given fileName * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile @@ -2179,7 +2202,7 @@ declare namespace ts { * @param scriptSnapshot Text of the file. * @param version Current version of the file. */ - updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile; + updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; /** * Informs the DocumentRegistry that a file is not needed any longer. * @@ -2303,7 +2326,7 @@ declare namespace ts { } function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput; function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; - function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile; + function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile; let disableIncrementalParsing: boolean; function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory?: string): DocumentRegistry; diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 5923ee0e111..a952502f6ed 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -409,7 +409,7 @@ var ts; // its type can be specified usign a JSDoc comment. ParserContextFlags[ParserContextFlags["JavaScriptFile"] = 32] = "JavaScriptFile"; // Context flags set directly by the parser. - ParserContextFlags[ParserContextFlags["ParserGeneratedFlags"] = 31] = "ParserGeneratedFlags"; + ParserContextFlags[ParserContextFlags["ParserGeneratedFlags"] = 63] = "ParserGeneratedFlags"; // Exclude these flags when parsing a Type ParserContextFlags[ParserContextFlags["TypeExcludesFlags"] = 10] = "TypeExcludesFlags"; // Context flags computed by aggregating child flags upwards. @@ -716,6 +716,14 @@ var ts; NewLineKind[NewLineKind["LineFeed"] = 1] = "LineFeed"; })(ts.NewLineKind || (ts.NewLineKind = {})); var NewLineKind = ts.NewLineKind; + (function (ScriptKind) { + ScriptKind[ScriptKind["Unknown"] = 0] = "Unknown"; + ScriptKind[ScriptKind["JS"] = 1] = "JS"; + ScriptKind[ScriptKind["JSX"] = 2] = "JSX"; + ScriptKind[ScriptKind["TS"] = 3] = "TS"; + ScriptKind[ScriptKind["TSX"] = 4] = "TSX"; + })(ts.ScriptKind || (ts.ScriptKind = {})); + var ScriptKind = ts.ScriptKind; (function (ScriptTarget) { ScriptTarget[ScriptTarget["ES3"] = 0] = "ES3"; ScriptTarget[ScriptTarget["ES5"] = 1] = "ES5"; @@ -1137,6 +1145,14 @@ var ts; return hasOwnProperty.call(map, key); } ts.hasProperty = hasProperty; + function getKeys(map) { + var keys = []; + for (var key in map) { + keys.push(key); + } + return keys; + } + ts.getKeys = getKeys; function getProperty(map, key) { return hasOwnProperty.call(map, key) ? map[key] : undefined; } @@ -1594,6 +1610,32 @@ var ts; return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension; } ts.fileExtensionIs = fileExtensionIs; + function ensureScriptKind(fileName, scriptKind) { + // Using scriptKind as a condition handles both: + // - 'scriptKind' is unspecified and thus it is `undefined` + // - 'scriptKind' is set and it is `Unknown` (0) + // If the 'scriptKind' is 'undefined' or 'Unknown' then we attempt + // to get the ScriptKind from the file name. If it cannot be resolved + // from the file name then the default 'TS' script kind is returned. + return (scriptKind || getScriptKindFromFileName(fileName)) || 3 /* TS */; + } + ts.ensureScriptKind = ensureScriptKind; + function getScriptKindFromFileName(fileName) { + var ext = fileName.substr(fileName.lastIndexOf(".")); + switch (ext.toLowerCase()) { + case ".js": + return 1 /* JS */; + case ".jsx": + return 2 /* JSX */; + case ".ts": + return 3 /* TS */; + case ".tsx": + return 4 /* TSX */; + default: + return 0 /* Unknown */; + } + } + ts.getScriptKindFromFileName = getScriptKindFromFileName; /** * List of supported extensions in order of file resolution precedence. */ @@ -2819,6 +2861,7 @@ var ts; Only_amd_and_system_modules_are_supported_alongside_0: { code: 6082, category: ts.DiagnosticCategory.Error, key: "Only_amd_and_system_modules_are_supported_alongside_0_6082", message: "Only 'amd' and 'system' modules are supported alongside --{0}." }, Allow_javascript_files_to_be_compiled: { code: 6083, category: ts.DiagnosticCategory.Message, key: "Allow_javascript_files_to_be_compiled_6083", message: "Allow javascript files to be compiled." }, Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit: { code: 6084, category: ts.DiagnosticCategory.Message, key: "Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit_6084", message: "Specifies the object invoked for createElement and __spread when targeting 'react' JSX emit" }, + Option_0_should_have_array_of_strings_as_a_value: { code: 6103, category: ts.DiagnosticCategory.Error, key: "Option_0_should_have_array_of_strings_as_a_value_6103", message: "Option '{0}' should have array of strings as a value." }, Do_not_emit_use_strict_directives_in_module_output: { code: 6112, category: ts.DiagnosticCategory.Message, key: "Do_not_emit_use_strict_directives_in_module_output_6112", message: "Do not emit 'use strict' directives in module output." }, 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." }, @@ -2869,7 +2912,8 @@ var ts; An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses: { code: 17006, category: ts.DiagnosticCategory.Error, key: "An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_ex_17006", message: "An unary expression with the '{0}' operator is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses." }, A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses: { code: 17007, category: ts.DiagnosticCategory.Error, key: "A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Con_17007", message: "A type assertion expression is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses." }, JSX_element_0_has_no_corresponding_closing_tag: { code: 17008, category: ts.DiagnosticCategory.Error, key: "JSX_element_0_has_no_corresponding_closing_tag_17008", message: "JSX element '{0}' has no corresponding closing tag." }, - super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: ts.DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." } + super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: ts.DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." }, + Unknown_typing_option_0: { code: 17010, category: ts.DiagnosticCategory.Error, key: "Unknown_typing_option_0_17010", message: "Unknown typing option '{0}'." } }; })(ts || (ts = {})); /// @@ -5548,6 +5592,9 @@ var ts; /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property /// assignments we treat as special in the binder function getSpecialPropertyAssignmentKind(expression) { + if (!isInJavaScriptFile(expression)) { + return 0 /* None */; + } if (expression.kind !== 184 /* BinaryExpression */) { return 0 /* None */; } @@ -7557,10 +7604,10 @@ var ts; } } ts.forEachChild = forEachChild; - function createSourceFile(fileName, sourceText, languageVersion, setParentNodes) { + function createSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind) { if (setParentNodes === void 0) { setParentNodes = false; } var start = new Date().getTime(); - var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes); + var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); ts.parseTime += new Date().getTime() - start; return result; } @@ -7685,19 +7732,19 @@ var ts; // Note: any errors at the end of the file that do not precede a regular node, should get // attached to the EOF token. var parseErrorBeforeNextFinishedNode = false; - function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes) { - var isJavaScriptFile = ts.hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0; - initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor); - var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes); + function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes, scriptKind) { + scriptKind = ts.ensureScriptKind(fileName, scriptKind); + initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind); + var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); clearState(); return result; } Parser.parseSourceFile = parseSourceFile; - function getLanguageVariant(fileName) { + function getLanguageVariant(scriptKind) { // .tsx and .jsx files are treated as jsx language variant. - return ts.fileExtensionIs(fileName, ".tsx") || ts.fileExtensionIs(fileName, ".jsx") || ts.fileExtensionIs(fileName, ".js") ? 1 /* JSX */ : 0 /* Standard */; + return scriptKind === 4 /* TSX */ || scriptKind === 2 /* JSX */ || scriptKind === 1 /* JS */ ? 1 /* JSX */ : 0 /* Standard */; } - function initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor) { + function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind) { NodeConstructor = ts.objectAllocator.getNodeConstructor(); SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); sourceText = _sourceText; @@ -7707,13 +7754,13 @@ var ts; identifiers = {}; identifierCount = 0; nodeCount = 0; - contextFlags = isJavaScriptFile ? 32 /* JavaScriptFile */ : 0 /* None */; + contextFlags = scriptKind === 1 /* JS */ || scriptKind === 2 /* JSX */ ? 32 /* JavaScriptFile */ : 0 /* None */; parseErrorBeforeNextFinishedNode = false; // Initialize and prime the scanner before parsing the source elements. scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(getLanguageVariant(fileName)); + scanner.setLanguageVariant(getLanguageVariant(scriptKind)); } function clearState() { // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. @@ -7726,8 +7773,8 @@ var ts; syntaxCursor = undefined; sourceText = undefined; } - function parseSourceFileWorker(fileName, languageVersion, setParentNodes) { - sourceFile = createSourceFile(fileName, languageVersion); + function parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind) { + sourceFile = createSourceFile(fileName, languageVersion, scriptKind); if (contextFlags & 32 /* JavaScriptFile */) { sourceFile.parserContextFlags = 32 /* JavaScriptFile */; } @@ -7784,7 +7831,7 @@ var ts; } } Parser.fixupParentReferences = fixupParentReferences; - function createSourceFile(fileName, languageVersion) { + function createSourceFile(fileName, languageVersion, scriptKind) { // code from createNode is inlined here so createNode won't have to deal with special case of creating source files // this is quite rare comparing to other nodes and createNode should be as fast as possible var sourceFile = new SourceFileConstructor(251 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length); @@ -7794,7 +7841,8 @@ var ts; sourceFile.languageVersion = languageVersion; sourceFile.fileName = ts.normalizePath(fileName); sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 4096 /* DeclarationFile */ : 0; - sourceFile.languageVariant = getLanguageVariant(sourceFile.fileName); + sourceFile.languageVariant = getLanguageVariant(scriptKind); + sourceFile.scriptKind = scriptKind; return sourceFile; } function setContextFlag(val, flag) { @@ -8460,7 +8508,7 @@ var ts; // differently depending on what mode it is in. // // This also applies to all our other context flags as well. - var nodeContextFlags = node.parserContextFlags & 31 /* ParserGeneratedFlags */; + var nodeContextFlags = node.parserContextFlags & 63 /* ParserGeneratedFlags */; if (nodeContextFlags !== contextFlags) { return undefined; } @@ -12100,7 +12148,7 @@ var ts; } JSDocParser.isJSDocType = isJSDocType; function parseJSDocTypeExpressionForTests(content, start, length) { - initializeState("file.js", content, 2 /* Latest */, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined); + initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); scanner.setText(content, start, length); token = scanner.scan(); var jsDocTypeExpression = parseJSDocTypeExpression(); @@ -12367,7 +12415,7 @@ var ts; } } function parseIsolatedJSDocComment(content, start, length) { - initializeState("file.js", content, 2 /* Latest */, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined); + initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); sourceFile = { languageVariant: 0 /* Standard */, text: content }; var jsDocComment = parseJSDocCommentWorker(start, length); var diagnostics = parseDiagnostics; @@ -12637,7 +12685,7 @@ var ts; if (sourceFile.statements.length === 0) { // If we don't have any statements in the current source file, then there's no real // way to incrementally parse. So just do a full parse instead. - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true); + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind); } // Make sure we're not trying to incrementally update a source file more than once. Once // we do an update the original source file is considered unusbale from that point onwards. @@ -12693,7 +12741,7 @@ var ts; // inconsistent tree. Setting the parents on the new tree should be very fast. We // will immediately bail out of walking any subtrees when we can see that their parents // are already correct. - var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true); + var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind); return result; } IncrementalParser.updateSourceFile = updateSourceFile; @@ -13745,6 +13793,7 @@ var ts; case 146 /* GetAccessor */: case 147 /* SetAccessor */: case 153 /* FunctionType */: + case 264 /* JSDocFunctionType */: case 154 /* ConstructorType */: case 176 /* FunctionExpression */: case 177 /* ArrowFunction */: @@ -14350,7 +14399,7 @@ var ts; function bindModuleExportsAssignment(node) { // 'module.exports = expr' assignment setCommonJsModuleIndicator(node); - bindExportAssignment(node); + declareSymbol(file.symbol.exports, file.symbol, node, 4 /* Property */ | 7340032 /* Export */ | 512 /* ValueModule */, 0 /* None */); } function bindThisPropertyAssignment(node) { // Declare a 'member' in case it turns out the container was an ES5 class @@ -14380,7 +14429,8 @@ var ts; funcSymbol.members = {}; } // Declare the method/property - declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4 /* Property */, 107455 /* PropertyExcludes */); + // It's acceptable for multiple prototype property assignments of the same identifier to occur + declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4 /* Property */, 107455 /* PropertyExcludes */ & ~4 /* Property */); } function bindCallExpression(node) { // We're only inspecting call expressions to detect CommonJS modules, so we can skip @@ -15439,7 +15489,9 @@ var ts; function getTargetOfImportClause(node) { var moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier); if (moduleSymbol) { - var exportDefaultSymbol = resolveSymbol(moduleSymbol.exports["default"]); + var exportDefaultSymbol = moduleSymbol.exports["export="] ? + getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") : + resolveSymbol(moduleSymbol.exports["default"]); if (!exportDefaultSymbol && !allowSyntheticDefaultImports) { error(node.name, ts.Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); } @@ -15508,8 +15560,15 @@ var ts; if (targetSymbol) { var name_9 = specifier.propertyName || specifier.name; if (name_9.text) { + var symbolFromVariable = void 0; + // First check if module was specified with "export=". If so, get the member from the resolved type + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports["export="]) { + symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name_9.text); + } + else { + symbolFromVariable = getPropertyOfVariable(targetSymbol, name_9.text); + } var symbolFromModule = getExportOfModule(targetSymbol, name_9.text); - var symbolFromVariable = getPropertyOfVariable(targetSymbol, name_9.text); var symbol = symbolFromModule && symbolFromVariable ? combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) : symbolFromModule || symbolFromVariable; @@ -19403,7 +19462,7 @@ var ts; for (var i = 0; i < checkCount; i++) { var s = i < sourceMax ? getTypeOfSymbol(sourceParams[i]) : getRestTypeOfSignature(source); var t = i < targetMax ? getTypeOfSymbol(targetParams[i]) : getRestTypeOfSignature(target); - var related = compareTypes(t, s, /*reportErrors*/ false) || compareTypes(s, t, reportErrors); + var related = compareTypes(s, t, /*reportErrors*/ false) || compareTypes(t, s, reportErrors); if (!related) { if (reportErrors) { errorReporter(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, sourceParams[i < sourceMax ? i : sourceMax].name, targetParams[i < targetMax ? i : targetMax].name); @@ -20528,8 +20587,10 @@ var ts; function inferTypes(context, source, target) { var sourceStack; var targetStack; + var maxDepth = 5; var depth = 0; var inferiority = 0; + var visited = {}; inferFromTypes(source, target); function isInProcess(source, target) { for (var i = 0; i < depth; i++) { @@ -20655,9 +20716,19 @@ var ts; if (isInProcess(source, target)) { return; } + // we delibirately limit the depth we examine to infer types: this speeds up the overall inference process + // and user rarely expects inferences to be made from the deeply nested constituents. + if (depth > maxDepth) { + return; + } if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { return; } + var key = source.id + "," + target.id; + if (ts.hasProperty(visited, key)) { + return; + } + visited[key] = true; if (depth === 0) { sourceStack = []; targetStack = []; @@ -39261,7 +39332,7 @@ var ts; /* @internal */ ts.ioWriteTime = 0; /** The version of the TypeScript compiler release */ var emptyArray = []; - ts.version = "1.8.5"; + ts.version = "1.8.9"; function findConfigFile(searchPath, fileExists) { var fileName = "tsconfig.json"; while (true) { @@ -40972,6 +41043,7 @@ var ts; return { options: options, fileNames: getFileNames(), + typingOptions: getTypingOptions(), errors: errors }; function getFileNames() { @@ -41031,6 +41103,34 @@ var ts; } return fileNames; } + function getTypingOptions() { + var options = ts.getBaseFileName(configFileName) === "jsconfig.json" + ? { enableAutoDiscovery: true, include: [], exclude: [] } + : { enableAutoDiscovery: false, include: [], exclude: [] }; + var jsonTypingOptions = json["typingOptions"]; + if (jsonTypingOptions) { + for (var id in jsonTypingOptions) { + if (id === "enableAutoDiscovery") { + if (typeof jsonTypingOptions[id] === "boolean") { + options.enableAutoDiscovery = jsonTypingOptions[id]; + } + else { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_typing_option_0, id)); + } + } + else if (id === "include") { + options.include = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); + } + else if (id === "exclude") { + options.exclude = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); + } + else { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_typing_option_0, id)); + } + } + } + return options; + } } ts.parseJsonConfigFileContent = parseJsonConfigFileContent; function convertCompilerOptionsFromJson(jsonOptions, basePath, configFileName) { @@ -41079,6 +41179,30 @@ var ts; return { options: options, errors: errors }; } ts.convertCompilerOptionsFromJson = convertCompilerOptionsFromJson; + function convertJsonOptionToStringArray(optionName, optionJson, errors, func) { + var items = []; + var invalidOptionType = false; + if (!ts.isArray(optionJson)) { + invalidOptionType = true; + } + else { + for (var _i = 0, _a = optionJson; _i < _a.length; _i++) { + var element = _a[_i]; + if (typeof element === "string") { + var item = func ? func(element) : element; + items.push(item); + } + else { + invalidOptionType = true; + break; + } + } + } + if (invalidOptionType) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_should_have_array_of_strings_as_a_value, optionName)); + } + return items; + } })(ts || (ts = {})); /* @internal */ var ts; @@ -43742,6 +43866,212 @@ var ts; return name; } ts.stripQuotes = stripQuotes; + function scriptKindIs(fileName, host) { + var scriptKinds = []; + for (var _i = 2; _i < arguments.length; _i++) { + scriptKinds[_i - 2] = arguments[_i]; + } + var scriptKind = getScriptKind(fileName, host); + return ts.forEach(scriptKinds, function (k) { return k === scriptKind; }); + } + ts.scriptKindIs = scriptKindIs; + function getScriptKind(fileName, host) { + // First check to see if the script kind can be determined from the file name + var scriptKind = ts.getScriptKindFromFileName(fileName); + if (scriptKind === 0 /* Unknown */ && host && host.getScriptKind) { + // Next check to see if the host can resolve the script kind + scriptKind = host.getScriptKind(fileName); + } + return ts.ensureScriptKind(fileName, scriptKind); + } + ts.getScriptKind = getScriptKind; +})(ts || (ts = {})); +// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. +// See LICENSE.txt in the project root for complete license information. +/// +/* @internal */ +var ts; +(function (ts) { + var JsTyping; + (function (JsTyping) { + ; + ; + // A map of loose file names to library names + // that we are confident require typings + var safeList; + /** + * @param host is the object providing I/O related operations. + * @param fileNames are the file names that belong to the same project + * @param projectRootPath is the path to the project root directory + * @param safeListPath is the path used to retrieve the safe list + * @param packageNameToTypingLocation is the map of package names to their cached typing locations + * @param typingOptions are used to customize the typing inference process + * @param compilerOptions are used as a source for typing inference + */ + function discoverTypings(host, fileNames, projectRootPath, safeListPath, packageNameToTypingLocation, typingOptions, compilerOptions) { + // A typing name to typing file path mapping + var inferredTypings = {}; + if (!typingOptions || !typingOptions.enableAutoDiscovery) { + return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; + } + // Only infer typings for .js and .jsx files + fileNames = ts.filter(ts.map(fileNames, ts.normalizePath), function (f) { return ts.scriptKindIs(f, /*LanguageServiceHost*/ undefined, 1 /* JS */, 2 /* JSX */); }); + if (!safeList) { + var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); }); + if (result.config) { + safeList = result.config; + } + else { + safeList = {}; + } + } + var filesToWatch = []; + // Directories to search for package.json, bower.json and other typing information + var searchDirs = []; + var exclude = []; + mergeTypings(typingOptions.include); + exclude = typingOptions.exclude || []; + var possibleSearchDirs = ts.map(fileNames, ts.getDirectoryPath); + if (projectRootPath !== undefined) { + possibleSearchDirs.push(projectRootPath); + } + searchDirs = ts.deduplicate(possibleSearchDirs); + for (var _i = 0, searchDirs_1 = searchDirs; _i < searchDirs_1.length; _i++) { + var searchDir = searchDirs_1[_i]; + var packageJsonPath = ts.combinePaths(searchDir, "package.json"); + getTypingNamesFromJson(packageJsonPath, filesToWatch); + var bowerJsonPath = ts.combinePaths(searchDir, "bower.json"); + getTypingNamesFromJson(bowerJsonPath, filesToWatch); + var nodeModulesPath = ts.combinePaths(searchDir, "node_modules"); + getTypingNamesFromNodeModuleFolder(nodeModulesPath); + } + getTypingNamesFromSourceFileNames(fileNames); + // Add the cached typing locations for inferred typings that are already installed + for (var name_34 in packageNameToTypingLocation) { + if (ts.hasProperty(inferredTypings, name_34) && !inferredTypings[name_34]) { + inferredTypings[name_34] = packageNameToTypingLocation[name_34]; + } + } + // Remove typings that the user has added to the exclude list + for (var _a = 0, exclude_1 = exclude; _a < exclude_1.length; _a++) { + var excludeTypingName = exclude_1[_a]; + delete inferredTypings[excludeTypingName]; + } + var newTypingNames = []; + var cachedTypingPaths = []; + for (var typing in inferredTypings) { + if (inferredTypings[typing] !== undefined) { + cachedTypingPaths.push(inferredTypings[typing]); + } + else { + newTypingNames.push(typing); + } + } + return { cachedTypingPaths: cachedTypingPaths, newTypingNames: newTypingNames, filesToWatch: filesToWatch }; + /** + * Merge a given list of typingNames to the inferredTypings map + */ + function mergeTypings(typingNames) { + if (!typingNames) { + return; + } + for (var _i = 0, typingNames_1 = typingNames; _i < typingNames_1.length; _i++) { + var typing = typingNames_1[_i]; + if (!ts.hasProperty(inferredTypings, typing)) { + inferredTypings[typing] = undefined; + } + } + } + /** + * Get the typing info from common package manager json files like package.json or bower.json + */ + function getTypingNamesFromJson(jsonPath, filesToWatch) { + var result = ts.readConfigFile(jsonPath, function (path) { return host.readFile(path); }); + if (result.config) { + var jsonConfig = result.config; + filesToWatch.push(jsonPath); + if (jsonConfig.dependencies) { + mergeTypings(ts.getKeys(jsonConfig.dependencies)); + } + if (jsonConfig.devDependencies) { + mergeTypings(ts.getKeys(jsonConfig.devDependencies)); + } + if (jsonConfig.optionalDependencies) { + mergeTypings(ts.getKeys(jsonConfig.optionalDependencies)); + } + if (jsonConfig.peerDependencies) { + mergeTypings(ts.getKeys(jsonConfig.peerDependencies)); + } + } + } + /** + * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js" + * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred + * to the 'angular-route' typing name. + * @param fileNames are the names for source files in the project + */ + function getTypingNamesFromSourceFileNames(fileNames) { + var jsFileNames = ts.filter(fileNames, ts.hasJavaScriptFileExtension); + var inferredTypingNames = ts.map(jsFileNames, function (f) { return ts.removeFileExtension(ts.getBaseFileName(f.toLowerCase())); }); + var cleanedTypingNames = ts.map(inferredTypingNames, function (f) { return f.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); }); + if (safeList === undefined) { + mergeTypings(cleanedTypingNames); + } + else { + mergeTypings(ts.filter(cleanedTypingNames, function (f) { return ts.hasProperty(safeList, f); })); + } + var hasJsxFile = ts.forEach(fileNames, function (f) { return ts.scriptKindIs(f, /*LanguageServiceHost*/ undefined, 2 /* JSX */); }); + if (hasJsxFile) { + mergeTypings(["react"]); + } + } + /** + * Infer typing names from node_module folder + * @param nodeModulesPath is the path to the "node_modules" folder + */ + function getTypingNamesFromNodeModuleFolder(nodeModulesPath) { + // Todo: add support for ModuleResolutionHost too + if (!host.directoryExists(nodeModulesPath)) { + return; + } + var typingNames = []; + var fileNames = host.readDirectory(nodeModulesPath, "*.json", /*exclude*/ undefined, /*depth*/ 2); + for (var _i = 0, fileNames_1 = fileNames; _i < fileNames_1.length; _i++) { + var fileName = fileNames_1[_i]; + var normalizedFileName = ts.normalizePath(fileName); + if (ts.getBaseFileName(normalizedFileName) !== "package.json") { + continue; + } + var result = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); }); + if (!result.config) { + continue; + } + var packageJson = result.config; + // npm 3's package.json contains a "_requiredBy" field + // we should include all the top level module names for npm 2, and only module names whose + // "_requiredBy" field starts with "#" or equals "/" for npm 3. + if (packageJson._requiredBy && + ts.filter(packageJson._requiredBy, function (r) { return r[0] === "#" || r === "/"; }).length === 0) { + continue; + } + // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used + // to download d.ts files from DefinitelyTyped + if (!packageJson.name) { + continue; + } + if (packageJson.typings) { + var absolutePath = ts.getNormalizedAbsolutePath(packageJson.typings, ts.getDirectoryPath(normalizedFileName)); + inferredTypings[packageJson.name] = absolutePath; + } + else { + typingNames.push(packageJson.name); + } + } + mergeTypings(typingNames); + } + } + JsTyping.discoverTypings = discoverTypings; + })(JsTyping = ts.JsTyping || (ts.JsTyping = {})); })(ts || (ts = {})); /// /// @@ -44452,9 +44782,9 @@ var ts; } Rules.prototype.getRuleName = function (rule) { var o = this; - for (var name_34 in o) { - if (o[name_34] === rule) { - return name_34; + for (var name_35 in o) { + if (o[name_35] === rule) { + return name_35; } } throw new Error("Unknown rule"); @@ -45129,12 +45459,20 @@ var ts; if (line === 0) { return []; } - // get the span for the previous\current line + // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters. + // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as + // trailing whitespaces. So the end of the formatting span should be the later one between: + // 1. the end of the previous line + // 2. the last non-whitespace character in the current line + var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile); + while (ts.isWhiteSpace(sourceFile.text.charCodeAt(endOfFormatSpan)) && !ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { + endOfFormatSpan--; + } var span = { // get start position for the previous line pos: ts.getStartPositionOfLine(line - 1, sourceFile), - // get end position for the current line (end value is exclusive so add 1 to the result) - end: ts.getEndLinePosition(line, sourceFile) + 1 + // end value is exclusive so add 1 to the result + end: endOfFormatSpan + 1 }; return formatSpan(span, sourceFile, options, rulesProvider, 2 /* FormatOnEnter */); } @@ -46456,12 +46794,13 @@ var ts; /// /// /// +/// /// /// var ts; (function (ts) { /** The version of the language service API */ - ts.servicesVersion = "0.4"; + ts.servicesVersion = "0.5"; var ScriptSnapshot; (function (ScriptSnapshot) { var StringScriptSnapshot = (function () { @@ -47449,7 +47788,8 @@ var ts; entry = { hostFileName: fileName, version: this.host.getScriptVersion(fileName), - scriptSnapshot: scriptSnapshot + scriptSnapshot: scriptSnapshot, + scriptKind: ts.getScriptKind(fileName, this.host) }; } this.fileNameToEntry.set(path, entry); @@ -47497,11 +47837,12 @@ var ts; // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } + var scriptKind = ts.getScriptKind(fileName, this.host); var version = this.host.getScriptVersion(fileName); var sourceFile; if (this.currentFileName !== fileName) { // This is a new file, just parse it - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2 /* Latest */, version, /*setNodeParents*/ true); + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2 /* Latest */, version, /*setNodeParents*/ true, scriptKind); } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. @@ -47601,9 +47942,9 @@ var ts; return output.outputText; } ts.transpile = transpile; - function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents) { + function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents, scriptKind) { var text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - var sourceFile = ts.createSourceFile(fileName, text, scriptTarget, setNodeParents); + var sourceFile = ts.createSourceFile(fileName, text, scriptTarget, setNodeParents, scriptKind); setSourceFileFields(sourceFile, scriptSnapshot, version); return sourceFile; } @@ -47656,7 +47997,7 @@ var ts; } } // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true); + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind); } ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; function createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory) { @@ -47695,20 +48036,20 @@ var ts; }); return JSON.stringify(bucketInfoArray, undefined, 2); } - function acquireDocument(fileName, compilationSettings, scriptSnapshot, version) { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true); + function acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true, scriptKind); } - function updateDocument(fileName, compilationSettings, scriptSnapshot, version) { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false); + function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false, scriptKind); } - function acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, acquiring) { + function acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, acquiring, scriptKind) { var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); var entry = bucket.get(path); if (!entry) { ts.Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); // Have never seen this file with these settings. Create a new source file for it. - var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false); + var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind); entry = { sourceFile: sourceFile, languageServiceRefCount: 0, @@ -48396,11 +48737,15 @@ var ts; // it's source file any more, and instead defers to DocumentRegistry to get // either version 1, version 2 (or some other version) depending on what the // host says should be used. - return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version); + // We do not support the scenario where a host can modify a registered + // file's script kind, i.e. in one project some file is treated as ".ts" + // and in another as ".js" + ts.Debug.assert(hostFileInformation.scriptKind === oldSourceFile.scriptKind, "Registered script kind (" + oldSourceFile.scriptKind + ") should match new script kind (" + hostFileInformation.scriptKind + ") for file: " + fileName); + return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } } // Could not find this file in the old program, create a new SourceFile for it. - return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version); + return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } function sourceFileUpToDate(sourceFile) { if (!sourceFile) { @@ -49153,8 +49498,8 @@ var ts; if (element.getStart() <= position && position <= element.getEnd()) { continue; } - var name_35 = element.propertyName || element.name; - exisingImportsOrExports[name_35.text] = true; + var name_36 = element.propertyName || element.name; + exisingImportsOrExports[name_36.text] = true; } if (ts.isEmpty(exisingImportsOrExports)) { return exportsOfModule; @@ -49271,14 +49616,14 @@ var ts; var entries = []; var target = program.getCompilerOptions().target; var nameTable = getNameTable(sourceFile); - for (var name_36 in nameTable) { + for (var name_37 in nameTable) { // Skip identifiers produced only from the current location - if (nameTable[name_36] === position) { + if (nameTable[name_37] === position) { continue; } - if (!uniqueNames[name_36]) { - uniqueNames[name_36] = name_36; - var displayName = getCompletionEntryDisplayName(name_36, target, /*performCharacterChecks*/ true); + if (!uniqueNames[name_37]) { + uniqueNames[name_37] = name_37; + var displayName = getCompletionEntryDisplayName(name_37, target, /*performCharacterChecks*/ true); if (displayName) { var entry = { name: displayName, @@ -51230,19 +51575,19 @@ var ts; if (isNameOfPropertyAssignment(node)) { var objectLiteral = node.parent.parent; var contextualType = typeChecker.getContextualType(objectLiteral); - var name_37 = node.text; + var name_38 = node.text; if (contextualType) { if (contextualType.flags & 16384 /* Union */) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - var unionProperty = contextualType.getProperty(name_37); + var unionProperty = contextualType.getProperty(name_38); if (unionProperty) { return [unionProperty]; } else { var result_6 = []; ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name_37); + var symbol = t.getProperty(name_38); if (symbol) { result_6.push(symbol); } @@ -51251,7 +51596,7 @@ var ts; } } else { - var symbol_1 = contextualType.getProperty(name_37); + var symbol_1 = contextualType.getProperty(name_38); if (symbol_1) { return [symbol_1]; } @@ -53628,6 +53973,14 @@ var ts; var scriptSnapshot = this.shimHost.getScriptSnapshot(fileName); return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot); }; + LanguageServiceShimHostAdapter.prototype.getScriptKind = function (fileName) { + if ("getScriptKind" in this.shimHost) { + return this.shimHost.getScriptKind(fileName); + } + else { + return 0 /* Unknown */; + } + }; LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) { return this.shimHost.getScriptVersion(fileName); }; @@ -53686,8 +54039,16 @@ var ts; this.directoryExists = function (directoryName) { return _this.shimHost.directoryExists(directoryName); }; } } - CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extension, exclude) { - var encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)); + CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extension, exclude, depth) { + // Wrap the API changes for 2.0 release. This try/catch + // should be removed once TypeScript 2.0 has shipped. + var encoded; + try { + encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude), depth); + } + catch (e) { + encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)); + } return JSON.parse(encoded); }; CoreServicesShimHostAdapter.prototype.fileExists = function (fileName) { @@ -54090,6 +54451,7 @@ var ts; if (result.error) { return { options: {}, + typingOptions: {}, files: [], errors: [realizeDiagnostic(result.error, "\r\n")] }; @@ -54098,6 +54460,7 @@ var ts; var configFile = ts.parseJsonConfigFileContent(result.config, _this.host, ts.getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName); return { options: configFile.options, + typingOptions: configFile.typingOptions, files: configFile.fileNames, errors: realizeDiagnostics(configFile.errors, "\r\n") }; @@ -54106,6 +54469,14 @@ var ts; CoreServicesShimObject.prototype.getDefaultCompilationSettings = function () { return this.forwardJSONCall("getDefaultCompilationSettings()", function () { return ts.getDefaultCompilerOptions(); }); }; + CoreServicesShimObject.prototype.discoverTypings = function (discoverTypingsJson) { + var _this = this; + var getCanonicalFileName = ts.createGetCanonicalFileName(/*useCaseSensitivefileNames:*/ false); + return this.forwardJSONCall("discoverTypings()", function () { + var info = JSON.parse(discoverTypingsJson); + return ts.JsTyping.discoverTypings(_this.host, info.fileNames, ts.toPath(info.projectRootPath, info.projectRootPath, getCanonicalFileName), ts.toPath(info.safeListPath, info.safeListPath, getCanonicalFileName), info.packageNameToTypingLocation, info.typingOptions, info.compilerOptions); + }); + }; return CoreServicesShimObject; }(ShimBase)); var TypeScriptServicesFactory = (function () { diff --git a/package.json b/package.json index 3fc0bd67db8..331fcd812fe 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typescript", "author": "Microsoft Corp.", "homepage": "http://typescriptlang.org/", - "version": "1.8.5", + "version": "1.8.9", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index b8c134b44a8..98bc54e88c3 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -279,6 +279,7 @@ namespace ts { Debug.assert(!hasDynamicName(node)); const isDefaultExport = node.flags & NodeFlags.Default; + // The exported symbol for an export default function/class node is always named "default" const name = isDefaultExport && parent ? "default" : getDeclarationName(node); @@ -1429,7 +1430,7 @@ namespace ts { function bindModuleExportsAssignment(node: BinaryExpression) { // 'module.exports = expr' assignment setCommonJsModuleIndicator(node); - bindExportAssignment(node); + declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.Export | SymbolFlags.ValueModule, SymbolFlags.None); } function bindThisPropertyAssignment(node: BinaryExpression) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 44713b2c1db..baa57ddd014 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -888,8 +888,12 @@ namespace ts { function getTargetOfImportClause(node: ImportClause): Symbol { const moduleSymbol = resolveExternalModuleName(node, (node.parent).moduleSpecifier); + if (moduleSymbol) { - const exportDefaultSymbol = resolveSymbol(moduleSymbol.exports["default"]); + const exportDefaultSymbol = moduleSymbol.exports["export="] ? + getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") : + resolveSymbol(moduleSymbol.exports["default"]); + if (!exportDefaultSymbol && !allowSyntheticDefaultImports) { error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); } @@ -960,8 +964,15 @@ namespace ts { if (targetSymbol) { const name = specifier.propertyName || specifier.name; if (name.text) { + let symbolFromVariable: Symbol; + // First check if module was specified with "export=". If so, get the member from the resolved type + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports["export="]) { + symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.text); + } + else { + symbolFromVariable = getPropertyOfVariable(targetSymbol, name.text); + } const symbolFromModule = getExportOfModule(targetSymbol, name.text); - const symbolFromVariable = getPropertyOfVariable(targetSymbol, name.text); const symbol = symbolFromModule && symbolFromVariable ? combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) : symbolFromModule || symbolFromVariable; diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 55cc2be0b72..b3a081d6b05 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -511,6 +511,7 @@ namespace ts { return { options, fileNames: getFileNames(), + typingOptions: getTypingOptions(), errors }; @@ -575,6 +576,35 @@ namespace ts { } return fileNames; } + + function getTypingOptions(): TypingOptions { + const options: TypingOptions = getBaseFileName(configFileName) === "jsconfig.json" + ? { enableAutoDiscovery: true, include: [], exclude: [] } + : { enableAutoDiscovery: false, include: [], exclude: [] }; + const jsonTypingOptions = json["typingOptions"]; + if (jsonTypingOptions) { + for (const id in jsonTypingOptions) { + if (id === "enableAutoDiscovery") { + if (typeof jsonTypingOptions[id] === "boolean") { + options.enableAutoDiscovery = jsonTypingOptions[id]; + } + else { + errors.push(createCompilerDiagnostic(Diagnostics.Unknown_typing_option_0, id)); + } + } + else if (id === "include") { + options.include = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); + } + else if (id === "exclude") { + options.exclude = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); + } + else { + errors.push(createCompilerDiagnostic(Diagnostics.Unknown_typing_option_0, id)); + } + } + } + return options; + } } export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { @@ -610,9 +640,9 @@ namespace ts { } if (opt.isFilePath) { value = normalizePath(combinePaths(basePath, value)); - if (value === "") { - value = "."; - } + if (value === "") { + value = "."; + } } options[opt.name] = value; } @@ -627,4 +657,28 @@ namespace ts { return { options, errors }; } + + function convertJsonOptionToStringArray(optionName: string, optionJson: any, errors: Diagnostic[], func?: (element: string) => string): string[] { + const items: string[] = []; + let invalidOptionType = false; + if (!isArray(optionJson)) { + invalidOptionType = true; + } + else { + for (const element of optionJson) { + if (typeof element === "string") { + const item = func ? func(element) : element; + items.push(item); + } + else { + invalidOptionType = true; + break; + } + } + } + if (invalidOptionType) { + errors.push(createCompilerDiagnostic(Diagnostics.Option_0_should_have_array_of_strings_as_a_value, optionName)); + } + return items; + } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index cfdcb2b930c..b3c7657b872 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -280,6 +280,14 @@ namespace ts { return hasOwnProperty.call(map, key); } + export function getKeys(map: Map): string[] { + const keys: string[] = []; + for (const key in map) { + keys.push(key); + } + return keys; + } + export function getProperty(map: Map, key: string): T { return hasOwnProperty.call(map, key) ? map[key] : undefined; } @@ -769,6 +777,32 @@ namespace ts { return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension; } + export function ensureScriptKind(fileName: string, scriptKind?: ScriptKind): ScriptKind { + // Using scriptKind as a condition handles both: + // - 'scriptKind' is unspecified and thus it is `undefined` + // - 'scriptKind' is set and it is `Unknown` (0) + // If the 'scriptKind' is 'undefined' or 'Unknown' then we attempt + // to get the ScriptKind from the file name. If it cannot be resolved + // from the file name then the default 'TS' script kind is returned. + return (scriptKind || getScriptKindFromFileName(fileName)) || ScriptKind.TS; + } + + export function getScriptKindFromFileName(fileName: string): ScriptKind { + const ext = fileName.substr(fileName.lastIndexOf(".")); + switch (ext.toLowerCase()) { + case ".js": + return ScriptKind.JS; + case ".jsx": + return ScriptKind.JSX; + case ".ts": + return ScriptKind.TS; + case ".tsx": + return ScriptKind.TSX; + default: + return ScriptKind.Unknown; + } + } + /** * List of supported extensions in order of file resolution precedence. */ diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 19112e88437..ce9303a85c9 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2450,11 +2450,14 @@ "category": "Message", "code": 6084 }, + "Option '{0}' should have array of strings as a value.": { + "category": "Error", + "code": 6103 + }, "Do not emit 'use strict' directives in module output.": { "category": "Message", "code": 6112 }, - "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 @@ -2654,5 +2657,9 @@ "'super' must be called before accessing 'this' in the constructor of a derived class.": { "category": "Error", "code": 17009 + }, + "Unknown typing option '{0}'.": { + "category": "Error", + "code": 17010 } } \ No newline at end of file diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5def394578d..281adf9c90c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -399,9 +399,9 @@ namespace ts { } } - export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false): SourceFile { + export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile { const start = new Date().getTime(); - const result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes); + const result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); parseTime += new Date().getTime() - start; return result; @@ -533,23 +533,24 @@ namespace ts { // attached to the EOF token. let parseErrorBeforeNextFinishedNode = false; - export function parseSourceFile(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean): SourceFile { - const isJavaScriptFile = hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0; - initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor); + export function parseSourceFile(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile { + scriptKind = ensureScriptKind(fileName, scriptKind); - const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes); + initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind); + + const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); clearState(); return result; } - function getLanguageVariant(fileName: string) { + function getLanguageVariant(scriptKind: ScriptKind) { // .tsx and .jsx files are treated as jsx language variant. - return fileExtensionIs(fileName, ".tsx") || fileExtensionIs(fileName, ".jsx") || fileExtensionIs(fileName, ".js") ? LanguageVariant.JSX : LanguageVariant.Standard; + return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS ? LanguageVariant.JSX : LanguageVariant.Standard; } - function initializeState(fileName: string, _sourceText: string, languageVersion: ScriptTarget, isJavaScriptFile: boolean, _syntaxCursor: IncrementalParser.SyntaxCursor) { + function initializeState(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) { NodeConstructor = objectAllocator.getNodeConstructor(); SourceFileConstructor = objectAllocator.getSourceFileConstructor(); @@ -562,14 +563,14 @@ namespace ts { identifierCount = 0; nodeCount = 0; - contextFlags = isJavaScriptFile ? ParserContextFlags.JavaScriptFile : ParserContextFlags.None; + contextFlags = scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSX ? ParserContextFlags.JavaScriptFile : ParserContextFlags.None; parseErrorBeforeNextFinishedNode = false; // Initialize and prime the scanner before parsing the source elements. scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(getLanguageVariant(fileName)); + scanner.setLanguageVariant(getLanguageVariant(scriptKind)); } function clearState() { @@ -585,8 +586,8 @@ namespace ts { sourceText = undefined; } - function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean): SourceFile { - sourceFile = createSourceFile(fileName, languageVersion); + function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind): SourceFile { + sourceFile = createSourceFile(fileName, languageVersion, scriptKind); if (contextFlags & ParserContextFlags.JavaScriptFile) { sourceFile.parserContextFlags = ParserContextFlags.JavaScriptFile; @@ -656,7 +657,7 @@ namespace ts { } } - function createSourceFile(fileName: string, languageVersion: ScriptTarget): SourceFile { + function createSourceFile(fileName: string, languageVersion: ScriptTarget, scriptKind: ScriptKind): SourceFile { // code from createNode is inlined here so createNode won't have to deal with special case of creating source files // this is quite rare comparing to other nodes and createNode should be as fast as possible const sourceFile = new SourceFileConstructor(SyntaxKind.SourceFile, /*pos*/ 0, /* end */ sourceText.length); @@ -667,7 +668,8 @@ namespace ts { sourceFile.languageVersion = languageVersion; sourceFile.fileName = normalizePath(fileName); sourceFile.flags = fileExtensionIs(sourceFile.fileName, ".d.ts") ? NodeFlags.DeclarationFile : 0; - sourceFile.languageVariant = getLanguageVariant(sourceFile.fileName); + sourceFile.languageVariant = getLanguageVariant(scriptKind); + sourceFile.scriptKind = scriptKind; return sourceFile; } @@ -5604,7 +5606,7 @@ namespace ts { } export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number) { - initializeState("file.js", content, ScriptTarget.Latest, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined); + initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); scanner.setText(content, start, length); token = scanner.scan(); const jsDocTypeExpression = parseJSDocTypeExpression(); @@ -5923,7 +5925,7 @@ namespace ts { } export function parseIsolatedJSDocComment(content: string, start: number, length: number) { - initializeState("file.js", content, ScriptTarget.Latest, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined); + initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); sourceFile = { languageVariant: LanguageVariant.Standard, text: content }; const jsDocComment = parseJSDocCommentWorker(start, length); const diagnostics = parseDiagnostics; @@ -6249,7 +6251,7 @@ namespace ts { if (sourceFile.statements.length === 0) { // If we don't have any statements in the current source file, then there's no real // way to incrementally parse. So just do a full parse instead. - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true); + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind); } // Make sure we're not trying to incrementally update a source file more than once. Once @@ -6313,7 +6315,7 @@ namespace ts { // inconsistent tree. Setting the parents on the new tree should be very fast. We // will immediately bail out of walking any subtrees when we can see that their parents // are already correct. - const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true); + const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind); return result; } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index a76517ecbce..f93801e123a 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -12,7 +12,7 @@ namespace ts { const emptyArray: any[] = []; - export const version = "1.8.5"; + export const version = "1.8.9"; export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string { let fileName = "tsconfig.json"; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d605a684a76..d0cd0ae6080 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1,3 +1,4 @@ + namespace ts { export interface Map { [index: string]: T; @@ -1559,6 +1560,7 @@ namespace ts { hasNoDefaultLib: boolean; languageVersion: ScriptTarget; + /* @internal */ scriptKind: ScriptKind; // The first node that causes this file to be an external module /* @internal */ externalModuleIndicator: Node; @@ -2447,6 +2449,22 @@ namespace ts { [option: string]: string | number | boolean; } + export interface TypingOptions { + enableAutoDiscovery?: boolean; + include?: string[]; + exclude?: string[]; + [option: string]: string[] | boolean; + } + + export interface DiscoverTypingsInfo { + fileNames: string[]; // The file names that belong to the same project. + projectRootPath: string; // The path to the project root directory + safeListPath: string; // The path used to retrieve the safe list + packageNameToTypingLocation: Map; // The map of package names to their cached typing locations + typingOptions: TypingOptions; // Used to customize the typing inference process + compilerOptions: CompilerOptions; // Used as a source for typing inference + } + export const enum ModuleKind { None = 0, CommonJS = 1, @@ -2476,6 +2494,14 @@ namespace ts { character: number; } + export const enum ScriptKind { + Unknown = 0, + JS = 1, + JSX = 2, + TS = 3, + TSX = 4 + } + export const enum ScriptTarget { ES3 = 0, ES5 = 1, @@ -2497,6 +2523,7 @@ namespace ts { export interface ParsedCommandLine { options: CompilerOptions; + typingOptions?: TypingOptions; fileNames: string[]; errors: Diagnostic[]; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index fa9305ae722..42f439e0ded 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1107,6 +1107,9 @@ namespace ts { /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property /// assignments we treat as special in the binder export function getSpecialPropertyAssignmentKind(expression: Node): SpecialPropertyAssignmentKind { + if (!isInJavaScriptFile(expression)) { + return SpecialPropertyAssignmentKind.None; + } if (expression.kind !== SyntaxKind.BinaryExpression) { return SpecialPropertyAssignmentKind.None; } diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index a0cac439729..cb8f85eea31 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -183,6 +183,7 @@ namespace Harness.LanguageService { const script = this.getScriptInfo(fileName); return script ? new ScriptSnapshot(script) : undefined; } + getScriptKind(fileName: string): ts.ScriptKind { return ts.ScriptKind.Unknown; } getScriptVersion(fileName: string): string { const script = this.getScriptInfo(fileName); return script ? script.version.toString() : undefined; @@ -253,6 +254,7 @@ namespace Harness.LanguageService { const nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName); return nativeScriptSnapshot && new ScriptSnapshotProxy(nativeScriptSnapshot); } + getScriptKind(fileName: string): ts.ScriptKind { return this.nativeHost.getScriptKind(fileName); } getScriptVersion(fileName: string): string { return this.nativeHost.getScriptVersion(fileName); } getLocalizedDiagnosticMessages(): string { return JSON.stringify({}); } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index e2ec5cc159f..42a2bded6a5 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -192,6 +192,10 @@ namespace ts.server { return this.roots.map(root => root.fileName); } + getScriptKind() { + return ScriptKind.Unknown; + } + getScriptVersion(filename: string) { return this.getScriptInfo(filename).svc.latestVersion().toString(); } @@ -1313,6 +1317,7 @@ namespace ts.server { else { const defaultOpts = ts.getDefaultCompilerOptions(); defaultOpts.allowNonTsExtensions = true; + defaultOpts.allowJs = true; this.setCompilerOptions(defaultOpts); } this.languageService = ts.createLanguageService(this.host, this.documentRegistry); diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 53a8c2b4307..e94e6d6fb29 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -72,12 +72,20 @@ namespace ts.formatting { if (line === 0) { return []; } - // get the span for the previous\current line + // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters. + // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as + // trailing whitespaces. So the end of the formatting span should be the later one between: + // 1. the end of the previous line + // 2. the last non-whitespace character in the current line + let endOfFormatSpan = getEndLinePosition(line, sourceFile); + while (isWhiteSpace(sourceFile.text.charCodeAt(endOfFormatSpan)) && !isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { + endOfFormatSpan--; + } let span = { // get start position for the previous line pos: getStartPositionOfLine(line - 1, sourceFile), - // get end position for the current line (end value is exclusive so add 1 to the result) - end: getEndLinePosition(line, sourceFile) + 1 + // end value is exclusive so add 1 to the result + end: endOfFormatSpan + 1 } return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnEnter); } diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts new file mode 100644 index 00000000000..4d4903ab59d --- /dev/null +++ b/src/services/jsTyping.ts @@ -0,0 +1,227 @@ +// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. +// See LICENSE.txt in the project root for complete license information. + +/// + +/* @internal */ +namespace ts.JsTyping { + + export interface TypingResolutionHost { + directoryExists: (path: string) => boolean; + fileExists: (fileName: string) => boolean; + readFile: (path: string, encoding?: string) => string; + readDirectory: (path: string, extension?: string, exclude?: string[], depth?: number) => string[]; + }; + + interface PackageJson { + _requiredBy?: string[]; + dependencies?: Map; + devDependencies?: Map; + name?: string; + optionalDependencies?: Map; + peerDependencies?: Map; + typings?: string; + }; + + // A map of loose file names to library names + // that we are confident require typings + let safeList: Map; + + /** + * @param host is the object providing I/O related operations. + * @param fileNames are the file names that belong to the same project + * @param projectRootPath is the path to the project root directory + * @param safeListPath is the path used to retrieve the safe list + * @param packageNameToTypingLocation is the map of package names to their cached typing locations + * @param typingOptions are used to customize the typing inference process + * @param compilerOptions are used as a source for typing inference + */ + export function discoverTypings( + host: TypingResolutionHost, + fileNames: string[], + projectRootPath: Path, + safeListPath: Path, + packageNameToTypingLocation: Map, + typingOptions: TypingOptions, + compilerOptions: CompilerOptions): + { cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } { + + // A typing name to typing file path mapping + const inferredTypings: Map = {}; + + if (!typingOptions || !typingOptions.enableAutoDiscovery) { + return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; + } + + // Only infer typings for .js and .jsx files + fileNames = filter(map(fileNames, normalizePath), f => scriptKindIs(f, /*LanguageServiceHost*/ undefined, ScriptKind.JS, ScriptKind.JSX)); + + if (!safeList) { + const result = readConfigFile(safeListPath, (path: string) => host.readFile(path)); + if (result.config) { + safeList = result.config; + } + else { + safeList = {}; + } + } + + const filesToWatch: string[] = []; + // Directories to search for package.json, bower.json and other typing information + let searchDirs: string[] = []; + let exclude: string[] = []; + + mergeTypings(typingOptions.include); + exclude = typingOptions.exclude || []; + + const possibleSearchDirs = map(fileNames, getDirectoryPath); + if (projectRootPath !== undefined) { + possibleSearchDirs.push(projectRootPath); + } + searchDirs = deduplicate(possibleSearchDirs); + for (const searchDir of searchDirs) { + const packageJsonPath = combinePaths(searchDir, "package.json"); + getTypingNamesFromJson(packageJsonPath, filesToWatch); + + const bowerJsonPath = combinePaths(searchDir, "bower.json"); + getTypingNamesFromJson(bowerJsonPath, filesToWatch); + + const nodeModulesPath = combinePaths(searchDir, "node_modules"); + getTypingNamesFromNodeModuleFolder(nodeModulesPath); + } + getTypingNamesFromSourceFileNames(fileNames); + + // Add the cached typing locations for inferred typings that are already installed + for (const name in packageNameToTypingLocation) { + if (hasProperty(inferredTypings, name) && !inferredTypings[name]) { + inferredTypings[name] = packageNameToTypingLocation[name]; + } + } + + // Remove typings that the user has added to the exclude list + for (const excludeTypingName of exclude) { + delete inferredTypings[excludeTypingName]; + } + + const newTypingNames: string[] = []; + const cachedTypingPaths: string[] = []; + for (const typing in inferredTypings) { + if (inferredTypings[typing] !== undefined) { + cachedTypingPaths.push(inferredTypings[typing]); + } + else { + newTypingNames.push(typing); + } + } + return { cachedTypingPaths, newTypingNames, filesToWatch }; + + /** + * Merge a given list of typingNames to the inferredTypings map + */ + function mergeTypings(typingNames: string[]) { + if (!typingNames) { + return; + } + + for (const typing of typingNames) { + if (!hasProperty(inferredTypings, typing)) { + inferredTypings[typing] = undefined; + } + } + } + + /** + * Get the typing info from common package manager json files like package.json or bower.json + */ + function getTypingNamesFromJson(jsonPath: string, filesToWatch: string[]) { + const result = readConfigFile(jsonPath, (path: string) => host.readFile(path)); + if (result.config) { + const jsonConfig: PackageJson = result.config; + filesToWatch.push(jsonPath); + if (jsonConfig.dependencies) { + mergeTypings(getKeys(jsonConfig.dependencies)); + } + if (jsonConfig.devDependencies) { + mergeTypings(getKeys(jsonConfig.devDependencies)); + } + if (jsonConfig.optionalDependencies) { + mergeTypings(getKeys(jsonConfig.optionalDependencies)); + } + if (jsonConfig.peerDependencies) { + mergeTypings(getKeys(jsonConfig.peerDependencies)); + } + } + } + + /** + * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js" + * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred + * to the 'angular-route' typing name. + * @param fileNames are the names for source files in the project + */ + function getTypingNamesFromSourceFileNames(fileNames: string[]) { + const jsFileNames = filter(fileNames, hasJavaScriptFileExtension); + const inferredTypingNames = map(jsFileNames, f => removeFileExtension(getBaseFileName(f.toLowerCase()))); + const cleanedTypingNames = map(inferredTypingNames, f => f.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, "")); + if (safeList === undefined) { + mergeTypings(cleanedTypingNames); + } + else { + mergeTypings(filter(cleanedTypingNames, f => hasProperty(safeList, f))); + } + + const hasJsxFile = forEach(fileNames, f => scriptKindIs(f, /*LanguageServiceHost*/ undefined, ScriptKind.JSX)); + if (hasJsxFile) { + mergeTypings(["react"]); + } + } + + /** + * Infer typing names from node_module folder + * @param nodeModulesPath is the path to the "node_modules" folder + */ + function getTypingNamesFromNodeModuleFolder(nodeModulesPath: string) { + // Todo: add support for ModuleResolutionHost too + if (!host.directoryExists(nodeModulesPath)) { + return; + } + + const typingNames: string[] = []; + const fileNames = host.readDirectory(nodeModulesPath, "*.json", /*exclude*/ undefined, /*depth*/ 2); + for (const fileName of fileNames) { + const normalizedFileName = normalizePath(fileName); + if (getBaseFileName(normalizedFileName) !== "package.json") { + continue; + } + const result = readConfigFile(normalizedFileName, (path: string) => host.readFile(path)); + if (!result.config) { + continue; + } + const packageJson: PackageJson = result.config; + + // npm 3's package.json contains a "_requiredBy" field + // we should include all the top level module names for npm 2, and only module names whose + // "_requiredBy" field starts with "#" or equals "/" for npm 3. + if (packageJson._requiredBy && + filter(packageJson._requiredBy, (r: string) => r[0] === "#" || r === "/").length === 0) { + continue; + } + + // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used + // to download d.ts files from DefinitelyTyped + if (!packageJson.name) { + continue; + } + if (packageJson.typings) { + const absolutePath = getNormalizedAbsolutePath(packageJson.typings, getDirectoryPath(normalizedFileName)); + inferredTypings[packageJson.name] = absolutePath; + } + else { + typingNames.push(packageJson.name); + } + } + mergeTypings(typingNames); + } + + } +} diff --git a/src/services/services.ts b/src/services/services.ts index 0fb7f329dfe..bdd3db708be 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -7,12 +7,13 @@ /// /// /// +/// /// /// namespace ts { /** The version of the language service API */ - export const servicesVersion = "0.4"; + export const servicesVersion = "0.5"; export interface Node { getSourceFile(): SourceFile; @@ -805,6 +806,7 @@ namespace ts { public identifierCount: number; public symbolCount: number; public version: string; + public scriptKind: ScriptKind; public languageVersion: ScriptTarget; public languageVariant: LanguageVariant; public identifiers: Map; @@ -1018,6 +1020,7 @@ namespace ts { getNewLine?(): string; getProjectVersion?(): string; getScriptFileNames(): string[]; + getScriptKind?(fileName: string): ScriptKind; getScriptVersion(fileName: string): string; getScriptSnapshot(fileName: string): IScriptSnapshot; getLocalizedDiagnosticMessages?(): any; @@ -1467,7 +1470,8 @@ namespace ts { fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, - version: string): SourceFile; + version: string, + scriptKind?: ScriptKind): SourceFile; /** * Request an updated version of an already existing SourceFile with a given fileName @@ -1485,7 +1489,8 @@ namespace ts { fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, - version: string): SourceFile; + version: string, + scriptKind?: ScriptKind): SourceFile; /** * Informs the DocumentRegistry that a file is not needed any longer. @@ -1656,6 +1661,7 @@ namespace ts { hostFileName: string; version: string; scriptSnapshot: IScriptSnapshot; + scriptKind: ScriptKind; } interface DocumentRegistryEntry { @@ -1750,7 +1756,8 @@ namespace ts { entry = { hostFileName: fileName, version: this.host.getScriptVersion(fileName), - scriptSnapshot: scriptSnapshot + scriptSnapshot: scriptSnapshot, + scriptKind: getScriptKind(fileName, this.host) }; } @@ -1816,12 +1823,13 @@ namespace ts { throw new Error("Could not find file: '" + fileName + "'."); } + const scriptKind = getScriptKind(fileName, this.host); const version = this.host.getScriptVersion(fileName); let sourceFile: SourceFile; if (this.currentFileName !== fileName) { // This is a new file, just parse it - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents*/ true); + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents*/ true, scriptKind); } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. @@ -1952,9 +1960,9 @@ namespace ts { return output.outputText; } - export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile { + export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile { const text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - const sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); + const sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents, scriptKind); setSourceFileFields(sourceFile, scriptSnapshot, version); return sourceFile; } @@ -2016,7 +2024,7 @@ namespace ts { } // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true); + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind); } export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry { @@ -2058,12 +2066,12 @@ namespace ts { return JSON.stringify(bucketInfoArray, undefined, 2); } - function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true); + function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile { + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true, scriptKind); } - function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false); + function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile { + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false, scriptKind); } function acquireOrUpdateDocument( @@ -2071,7 +2079,8 @@ namespace ts { compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, - acquiring: boolean): SourceFile { + acquiring: boolean, + scriptKind?: ScriptKind): SourceFile { const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); const path = toPath(fileName, currentDirectory, getCanonicalFileName); @@ -2080,7 +2089,7 @@ namespace ts { Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); // Have never seen this file with these settings. Create a new source file for it. - const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false); + const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind); entry = { sourceFile: sourceFile, @@ -2844,14 +2853,20 @@ namespace ts { // it's source file any more, and instead defers to DocumentRegistry to get // either version 1, version 2 (or some other version) depending on what the // host says should be used. - return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version); + + // We do not support the scenario where a host can modify a registered + // file's script kind, i.e. in one project some file is treated as ".ts" + // and in another as ".js" + Debug.assert(hostFileInformation.scriptKind === oldSourceFile.scriptKind, "Registered script kind (" + oldSourceFile.scriptKind + ") should match new script kind (" + hostFileInformation.scriptKind + ") for file: " + fileName); + + return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } // We didn't already have the file. Fall through and acquire it from the registry. } // Could not find this file in the old program, create a new SourceFile for it. - return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version); + return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } function sourceFileUpToDate(sourceFile: SourceFile): boolean { diff --git a/src/services/shims.ts b/src/services/shims.ts index 9ca3f19244d..a9ef3054838 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -55,6 +55,7 @@ namespace ts { /** Returns a JSON-encoded value of the type: string[] */ getScriptFileNames(): string; + getScriptKind?(fileName: string): ScriptKind; getScriptVersion(fileName: string): string; getScriptSnapshot(fileName: string): ScriptSnapshotShim; getLocalizedDiagnosticMessages(): string; @@ -77,7 +78,7 @@ namespace ts { * @param exclude A JSON encoded string[] containing the paths to exclude * when enumerating the directory. */ - readDirectory(rootDir: string, extension: string, exclude?: string): string; + readDirectory(rootDir: string, extension: string, exclude?: string, depth?: number): string; } /// @@ -229,6 +230,7 @@ namespace ts { getPreProcessedFileInfo(fileName: string, sourceText: IScriptSnapshot): string; getTSConfigFileInfo(fileName: string, sourceText: IScriptSnapshot): string; getDefaultCompilationSettings(): string; + discoverTypings(discoverTypingsJson: string): string; } function logInternalError(logger: Logger, err: Error) { @@ -344,6 +346,15 @@ namespace ts { return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot); } + public getScriptKind(fileName: string): ScriptKind { + if ("getScriptKind" in this.shimHost) { + return this.shimHost.getScriptKind(fileName); + } + else { + return ScriptKind.Unknown; + } + } + public getScriptVersion(fileName: string): string { return this.shimHost.getScriptVersion(fileName); } @@ -410,8 +421,16 @@ namespace ts { } } - public readDirectory(rootDir: string, extension: string, exclude: string[]): string[] { - const encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)); + public readDirectory(rootDir: string, extension: string, exclude: string[], depth?: number): string[] { + // Wrap the API changes for 2.0 release. This try/catch + // should be removed once TypeScript 2.0 has shipped. + let encoded: string; + try { + encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude), depth); + } + catch (e) { + encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)); + } return JSON.parse(encoded); } @@ -941,6 +960,7 @@ namespace ts { if (result.error) { return { options: {}, + typingOptions: {}, files: [], errors: [realizeDiagnostic(result.error, "\r\n")] }; @@ -951,6 +971,7 @@ namespace ts { return { options: configFile.options, + typingOptions: configFile.typingOptions, files: configFile.fileNames, errors: realizeDiagnostics(configFile.errors, "\r\n") }; @@ -963,6 +984,21 @@ namespace ts { () => getDefaultCompilerOptions() ); } + + public discoverTypings(discoverTypingsJson: string): string { + const getCanonicalFileName = createGetCanonicalFileName(/*useCaseSensitivefileNames:*/ false); + return this.forwardJSONCall("discoverTypings()", () => { + const info = JSON.parse(discoverTypingsJson); + return ts.JsTyping.discoverTypings( + this.host, + info.fileNames, + toPath(info.projectRootPath, info.projectRootPath, getCanonicalFileName), + toPath(info.safeListPath, info.safeListPath, getCanonicalFileName), + info.packageNameToTypingLocation, + info.typingOptions, + info.compilerOptions); + }); + } } export class TypeScriptServicesFactory implements ShimFactory { diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index 5dcee789243..43c4477115b 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -30,6 +30,7 @@ "shims.ts", "signatureHelp.ts", "utilities.ts", + "jsTyping.ts", "formatting/formatting.ts", "formatting/formattingContext.ts", "formatting/formattingRequestKind.ts", diff --git a/src/services/utilities.ts b/src/services/utilities.ts index afdc85fffd8..e423d870ca4 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -837,4 +837,19 @@ namespace ts { }; return name; } + + export function scriptKindIs(fileName: string, host: LanguageServiceHost, ...scriptKinds: ScriptKind[]): boolean { + const scriptKind = getScriptKind(fileName, host); + return forEach(scriptKinds, k => k === scriptKind); + } + + export function getScriptKind(fileName: string, host?: LanguageServiceHost): ScriptKind { + // First check to see if the script kind can be determined from the file name + var scriptKind = getScriptKindFromFileName(fileName); + if (scriptKind === ScriptKind.Unknown && host && host.getScriptKind) { + // Next check to see if the host can resolve the script kind + scriptKind = host.getScriptKind(fileName); + } + return ensureScriptKind(fileName, scriptKind); + } } \ No newline at end of file diff --git a/tests/baselines/reference/exportEqualsDefaultProperty.js b/tests/baselines/reference/exportEqualsDefaultProperty.js new file mode 100644 index 00000000000..6d75ef5d95d --- /dev/null +++ b/tests/baselines/reference/exportEqualsDefaultProperty.js @@ -0,0 +1,27 @@ +//// [tests/cases/compiler/exportEqualsDefaultProperty.ts] //// + +//// [exp.ts] + +var x = { + "greeting": "hello, world", + "default": 42 +}; + +export = x + +//// [imp.ts] +import foo from "./exp"; +foo.toExponential(2); + + +//// [exp.js] +"use strict"; +var x = { + "greeting": "hello, world", + "default": 42 +}; +module.exports = x; +//// [imp.js] +"use strict"; +var exp_1 = require("./exp"); +exp_1["default"].toExponential(2); diff --git a/tests/baselines/reference/exportEqualsDefaultProperty.symbols b/tests/baselines/reference/exportEqualsDefaultProperty.symbols new file mode 100644 index 00000000000..54bbbde6956 --- /dev/null +++ b/tests/baselines/reference/exportEqualsDefaultProperty.symbols @@ -0,0 +1,21 @@ +=== tests/cases/compiler/exp.ts === + +var x = { +>x : Symbol(x, Decl(exp.ts, 1, 3)) + + "greeting": "hello, world", + "default": 42 +}; + +export = x +>x : Symbol(x, Decl(exp.ts, 1, 3)) + +=== tests/cases/compiler/imp.ts === +import foo from "./exp"; +>foo : Symbol(foo, Decl(imp.ts, 0, 6)) + +foo.toExponential(2); +>foo.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>foo : Symbol(foo, Decl(imp.ts, 0, 6)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/exportEqualsDefaultProperty.types b/tests/baselines/reference/exportEqualsDefaultProperty.types new file mode 100644 index 00000000000..31a6c8052f9 --- /dev/null +++ b/tests/baselines/reference/exportEqualsDefaultProperty.types @@ -0,0 +1,28 @@ +=== tests/cases/compiler/exp.ts === + +var x = { +>x : { "greeting": string; "default": number; } +>{ "greeting": "hello, world", "default": 42} : { "greeting": string; "default": number; } + + "greeting": "hello, world", +>"hello, world" : string + + "default": 42 +>42 : number + +}; + +export = x +>x : { "greeting": string; "default": number; } + +=== tests/cases/compiler/imp.ts === +import foo from "./exp"; +>foo : number + +foo.toExponential(2); +>foo.toExponential(2) : string +>foo.toExponential : (fractionDigits?: number) => string +>foo : number +>toExponential : (fractionDigits?: number) => string +>2 : number + diff --git a/tests/cases/compiler/exportEqualsDefaultProperty.ts b/tests/cases/compiler/exportEqualsDefaultProperty.ts new file mode 100644 index 00000000000..1adce3cabe1 --- /dev/null +++ b/tests/cases/compiler/exportEqualsDefaultProperty.ts @@ -0,0 +1,12 @@ + +// @Filename: exp.ts +var x = { + "greeting": "hello, world", + "default": 42 +}; + +export = x + +// @Filename: imp.ts +import foo from "./exp"; +foo.toExponential(2); diff --git a/tests/cases/fourslash/javascriptModules20.ts b/tests/cases/fourslash/javascriptModules20.ts new file mode 100644 index 00000000000..7ef5c73e1c3 --- /dev/null +++ b/tests/cases/fourslash/javascriptModules20.ts @@ -0,0 +1,13 @@ +/// +// @allowJs: true + +// @Filename: mod.js +//// function foo() { return {a: true}; } +//// module.exports = foo(); + +// @Filename: app.js +//// import * as mod from "./mod" +//// mod./**/ + +goTo.marker(); +verify.completionListContains('a'); diff --git a/tests/cases/fourslash/javascriptModules21.ts b/tests/cases/fourslash/javascriptModules21.ts new file mode 100644 index 00000000000..3a046515924 --- /dev/null +++ b/tests/cases/fourslash/javascriptModules21.ts @@ -0,0 +1,14 @@ +/// +// @allowJs: true +// @module: system + +// @Filename: mod.js +//// function foo() { return {a: true}; } +//// module.exports = foo(); + +// @Filename: app.js +//// import mod from "./mod" +//// mod./**/ + +goTo.marker(); +verify.completionListContains('a'); diff --git a/tests/cases/fourslash/javascriptModules22.ts b/tests/cases/fourslash/javascriptModules22.ts new file mode 100644 index 00000000000..89fa99b5ea2 --- /dev/null +++ b/tests/cases/fourslash/javascriptModules22.ts @@ -0,0 +1,32 @@ +/// +// @allowJs: true + +// @Filename: mod.js +//// function foo() { return {a: "hello, world"}; } +//// module.exports = foo(); + +// @Filename: mod2.js +//// var x = {name: 'test'}; +//// (function createExport(obj){ +//// module.exports = { +//// "default": x, +//// "sausages": {eggs: 2} +//// }; +//// })(); + +// @Filename: app.js +//// import {a} from "./mod" +//// import def, {sausages} from "./mod2" +//// a./**/ + +goTo.marker(); +verify.completionListContains('toString'); + +edit.backspace(2); +edit.insert("def."); +verify.completionListContains("name"); + +edit.insert("name;\nsausages."); +verify.completionListContains("eggs"); +edit.insert("eggs;"); +verify.numberOfErrorsInCurrentFile(0); diff --git a/tests/cases/fourslash/javascriptModules23.ts b/tests/cases/fourslash/javascriptModules23.ts new file mode 100644 index 00000000000..eafbea87baa --- /dev/null +++ b/tests/cases/fourslash/javascriptModules23.ts @@ -0,0 +1,12 @@ +/// + +// @Filename: mod.ts +//// var foo = {a: "test"}; +//// export = foo; + +// @Filename: app.ts +//// import {a} from "./mod" +//// a./**/ + +goTo.marker(); +verify.completionListContains('toString'); diff --git a/tests/cases/fourslash/javascriptModules24.ts b/tests/cases/fourslash/javascriptModules24.ts new file mode 100644 index 00000000000..5a0dd892db7 --- /dev/null +++ b/tests/cases/fourslash/javascriptModules24.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: mod.ts +//// function foo() { return 42; } +//// namespace foo { +//// export function bar (a: string) { return a; } +//// } +//// export = foo; + +// @Filename: app.ts +//// import * as foo from "./mod" +//// foo/*1*/(); +//// foo.bar(/*2*/"test"); + +goTo.marker('1'); + +/**** BUG: Should be an error to invoke a call signature on a namespace import ****/ +//verify.errorExistsBeforeMarker('1'); +verify.quickInfoIs("(alias) foo(): number\nimport foo"); +goTo.marker('2'); +verify.signatureHelpArgumentCountIs(1);