Merge branch 'master' into map4

This commit is contained in:
Andy Hanson
2016-10-26 11:05:51 -07:00
127 changed files with 3976 additions and 617 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ matrix:
branches:
only:
- master
- release-2.0
- release-2.1
install:
- npm uninstall typescript
Executable
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Set up NVM
export NVM_DIR="/home/dotnet-bot/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install $1
npm uninstall typescript
npm uninstall tslint
npm install
npm update
npm test
+22
View File
@@ -0,0 +1,22 @@
// Import the utility functionality.
import jobs.generation.Utilities;
// Defines a the new of the repo, used elsewhere in the file
def project = GithubProject
def branch = GithubBranchName
def nodeVersions = ['stable', '4']
nodeVersions.each { nodeVer ->
def newJobName = "typescript_node.${nodeVer}"
def newJob = job(Utilities.getFullJobName(project, newJobName, true)) {
steps {
shell("./jenkins.sh ${nodeVer}")
}
}
Utilities.standardJobSetup(newJob, project, true, "*/${branch}")
Utilities.setMachineAffinity(newJob, 'Ubuntu', '20161020')
Utilities.addGithubPRTriggerForBranch(newJob, branch, "TypeScript Test Run ${newJobName}")
}
+40 -2
View File
@@ -54,6 +54,11 @@ namespace ts {
const body = (<ModuleDeclaration>node).body;
return body ? getModuleInstanceState(body) : ModuleInstanceState.Instantiated;
}
// Only jsdoc typedef definition can exist in jsdoc namespace, and it should
// be considered the same as type alias
else if (node.kind === SyntaxKind.Identifier && (<Identifier>node).isInJSDocNamespace) {
return ModuleInstanceState.NonInstantiated;
}
else {
return ModuleInstanceState.Instantiated;
}
@@ -429,7 +434,11 @@ namespace ts {
// during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation
// and this case is specially handled. Module augmentations should only be merged with original module definition
// and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed.
if (!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) {
const isJSDocTypedefInJSDocNamespace = node.kind === SyntaxKind.JSDocTypedefTag &&
node.name &&
node.name.kind === SyntaxKind.Identifier &&
(<Identifier>node.name).isInJSDocNamespace;
if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypedefInJSDocNamespace) {
const exportKind =
(symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) |
(symbolFlags & SymbolFlags.Type ? SymbolFlags.ExportType : 0) |
@@ -1007,7 +1016,7 @@ namespace ts {
currentFlow = finishFlowLabel(preFinallyLabel);
bind(node.finallyBlock);
// if flow after finally is unreachable - keep it
// otherwise check if flows after try and after catch are unreachable
// otherwise check if flows after try and after catch are unreachable
// if yes - convert current flow to unreachable
// i.e.
// try { return "1" } finally { console.log(1); }
@@ -1827,6 +1836,17 @@ namespace ts {
switch (node.kind) {
/* Strict mode checks */
case SyntaxKind.Identifier:
// for typedef type names with namespaces, bind the new jsdoc type symbol here
// because it requires all containing namespaces to be in effect, namely the
// current "blockScopeContainer" needs to be set to its immediate namespace parent.
if ((<Identifier>node).isInJSDocNamespace) {
let parentNode = node.parent;
while (parentNode && parentNode.kind !== SyntaxKind.JSDocTypedefTag) {
parentNode = parentNode.parent;
}
bindBlockScopedDeclaration(<Declaration>parentNode, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
break;
}
case SyntaxKind.ThisKeyword:
if (currentFlow && (isExpression(node) || parent.kind === SyntaxKind.ShorthandPropertyAssignment)) {
node.flowNode = currentFlow;
@@ -1950,6 +1970,10 @@ namespace ts {
case SyntaxKind.InterfaceDeclaration:
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes);
case SyntaxKind.JSDocTypedefTag:
if (!(<JSDocTypedefTag>node).fullName || (<JSDocTypedefTag>node).fullName.kind === SyntaxKind.Identifier) {
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
}
break;
case SyntaxKind.TypeAliasDeclaration:
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
case SyntaxKind.EnumDeclaration:
@@ -2421,6 +2445,9 @@ namespace ts {
case SyntaxKind.HeritageClause:
return computeHeritageClause(<HeritageClause>node, subtreeFlags);
case SyntaxKind.CatchClause:
return computeCatchClause(<CatchClause>node, subtreeFlags);
case SyntaxKind.ExpressionWithTypeArguments:
return computeExpressionWithTypeArguments(<ExpressionWithTypeArguments>node, subtreeFlags);
@@ -2650,6 +2677,17 @@ namespace ts {
return transformFlags & ~TransformFlags.NodeExcludes;
}
function computeCatchClause(node: CatchClause, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
if (node.variableDeclaration && isBindingPattern(node.variableDeclaration.name)) {
transformFlags |= TransformFlags.AssertES2015;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.NodeExcludes;
}
function computeExpressionWithTypeArguments(node: ExpressionWithTypeArguments, subtreeFlags: TransformFlags) {
// An ExpressionWithTypeArguments is ES6 syntax, as it is used in the
// extends clause of a class.
+282 -218
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -583,7 +583,7 @@ namespace ts {
return true;
}
export function extend<T1, T2>(first: T1 , second: T2): T1 & T2 {
export function extend<T1, T2>(first: T1, second: T2): T1 & T2 {
const result: T1 & T2 = <any>{};
for (const id in second) if (hasOwnProperty.call(second, id)) {
(result as any)[id] = (second as any)[id];
+22 -2
View File
@@ -599,7 +599,13 @@ namespace ts {
i++;
break;
case "boolean":
options[opt.name] = true;
// boolean flag has optional value true, false, others
let optValue = args[i];
options[opt.name] = optValue !== "false";
// consume next argument as boolean flag value
if (optValue === "false" || optValue === "true") {
i++;
}
break;
case "string":
options[opt.name] = args[i] || "";
@@ -905,6 +911,9 @@ namespace ts {
if (hasProperty(json, "files")) {
if (isArray(json["files"])) {
fileNames = <string[]>json["files"];
if (fileNames.length === 0) {
errors.push(createCompilerDiagnostic(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"));
}
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "files", "Array"));
@@ -947,7 +956,18 @@ namespace ts {
includeSpecs = ["**/*"];
}
return matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors);
const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors);
if (result.fileNames.length === 0 && !hasProperty(json, "files") && resolutionStack.length === 0) {
errors.push(
createCompilerDiagnostic(
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
configFileName || "tsconfig.json",
JSON.stringify(includeSpecs || []),
JSON.stringify(excludeSpecs || [])));
}
return result;
}
}
+56 -4
View File
@@ -431,6 +431,44 @@ namespace ts {
return result;
}
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T>, array2: ReadonlyArray<T>, equaler?: (a: T, b: T) => boolean): boolean {
if (!array1 || !array2) {
return array1 === array2;
}
if (array1.length !== array2.length) {
return false;
}
for (let i = 0; i < array1.length; i++) {
const equals = equaler ? equaler(array1[i], array2[i]) : array1[i] === array2[i];
if (!equals) {
return false;
}
}
return true;
}
export function changesAffectModuleResolution(oldOptions: CompilerOptions, newOptions: CompilerOptions): boolean {
return !oldOptions ||
(oldOptions.module !== newOptions.module) ||
(oldOptions.moduleResolution !== newOptions.moduleResolution) ||
(oldOptions.noResolve !== newOptions.noResolve) ||
(oldOptions.target !== newOptions.target) ||
(oldOptions.noLib !== newOptions.noLib) ||
(oldOptions.jsx !== newOptions.jsx) ||
(oldOptions.allowJs !== newOptions.allowJs) ||
(oldOptions.rootDir !== newOptions.rootDir) ||
(oldOptions.configFilePath !== newOptions.configFilePath) ||
(oldOptions.baseUrl !== newOptions.baseUrl) ||
(oldOptions.maxNodeModuleJsDepth !== newOptions.maxNodeModuleJsDepth) ||
!arrayIsEqualTo(oldOptions.lib, newOptions.lib) ||
!arrayIsEqualTo(oldOptions.typeRoots, newOptions.typeRoots) ||
!arrayIsEqualTo(oldOptions.rootDirs, newOptions.rootDirs) ||
!equalOwnProperties(oldOptions.paths, newOptions.paths);
}
/**
* Compacts an array, removing any falsey elements.
*/
@@ -507,6 +545,12 @@ namespace ts {
: undefined;
}
export function replaceElement<T>(array: T[], index: number, value: T): T[] {
const result = array.slice(0);
result[index] = value;
return result;
}
/**
* Performs a binary search, finding the index at which 'value' occurs in 'array'.
* If no such index is found, returns the 2's-complement of first index at which
@@ -602,6 +646,14 @@ namespace ts {
return Array.isArray ? Array.isArray(value) : value instanceof Array;
}
/** Does nothing. */
export function noop(): void {}
/** Throws an error because a function is not implemented. */
export function notImplemented(): never {
throw new Error("Not implemented");
}
export function memoize<T>(callback: () => T): () => T {
let value: T;
return () => {
@@ -699,8 +751,8 @@ namespace ts {
Debug.assert(length >= 0, "length must be non-negative, is " + length);
if (file) {
Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`);
Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`);
Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${start} > ${file.text.length}`);
Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${end} > ${file.text.length}`);
}
let text = getLocaleSpecificMessage(message);
@@ -1250,7 +1302,7 @@ namespace ts {
return undefined;
}
const replaceWildcardCharacter = usage === "files" ? replaceWildCardCharacterFiles : replaceWildCardCharacterOther;
const replaceWildcardCharacter = usage === "files" ? replaceWildCardCharacterFiles : replaceWildCardCharacterOther;
const singleAsteriskRegexFragment = usage === "files" ? singleAsteriskRegexFragmentFiles : singleAsteriskRegexFragmentOther;
/**
@@ -1492,7 +1544,7 @@ namespace ts {
/** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */
export const supportedTypescriptExtensionsForExtractExtension = [".d.ts", ".ts", ".tsx"];
export const supportedJavascriptExtensions = [".js", ".jsx"];
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
export function getSupportedExtensions(options?: CompilerOptions): string[] {
return options && options.allowJs ? allSupportedExtensions : supportedTypeScriptExtensions;
+1 -1
View File
@@ -63,7 +63,7 @@ namespace ts {
let isCurrentFileExternalModule: boolean;
let reportedDeclarationError = false;
let errorNameNode: DeclarationName;
const emitJsDocComments = compilerOptions.removeComments ? () => {} : writeJsDocComments;
const emitJsDocComments = compilerOptions.removeComments ? noop : writeJsDocComments;
const emit = compilerOptions.stripInternal ? stripInternal : emitNode;
let noDeclare: boolean;
+10 -4
View File
@@ -603,10 +603,6 @@
"category": "Error",
"code": 1194
},
"Catch clause variable name must be an identifier.": {
"category": "Error",
"code": 1195
},
"Catch clause variable cannot have a type annotation.": {
"category": "Error",
"code": 1196
@@ -3077,6 +3073,7 @@
"category": "Error",
"code": 17010
},
"Circularity detected while resolving configuration: {0}": {
"category": "Error",
"code": 18000
@@ -3085,6 +3082,15 @@
"category": "Error",
"code": 18001
},
"The 'files' list in config file '{0}' is empty.": {
"category": "Error",
"code": 18002
},
"No inputs were found in config file '{0}'. Specified 'include' paths were '{1}' and 'exclude' paths were '{2}'.": {
"category": "Error",
"code": 18003
},
"Add missing 'super()' call.": {
"category": "Message",
"code": 90001
+3 -1
View File
@@ -1625,7 +1625,9 @@ namespace ts {
// flag and setting a parent node.
const react = createIdentifier(reactNamespace || "React");
react.flags &= ~NodeFlags.Synthesized;
react.parent = parent;
// Set the parent that is in parse tree
// this makes sure that parent chain is intact for checker to traverse complete scope tree
react.parent = getParseTreeNode(parent);
return react;
}
+38 -7
View File
@@ -411,6 +411,7 @@ namespace ts {
return visitNodes(cbNodes, (<JSDocTemplateTag>node).typeParameters);
case SyntaxKind.JSDocTypedefTag:
return visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression) ||
visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
visitNode(cbNode, (<JSDocTypedefTag>node).name) ||
visitNode(cbNode, (<JSDocTypedefTag>node).jsDocTypeLiteral);
case SyntaxKind.JSDocTypeLiteral:
@@ -5472,7 +5473,7 @@ namespace ts {
exportDeclaration.name = parseIdentifier();
parseExpected(SyntaxKind.SemicolonToken);
parseSemicolon();
return finishNode(exportDeclaration);
}
@@ -6552,7 +6553,14 @@ namespace ts {
const typedefTag = <JSDocTypedefTag>createNode(SyntaxKind.JSDocTypedefTag, atToken.pos);
typedefTag.atToken = atToken;
typedefTag.tagName = tagName;
typedefTag.name = parseJSDocIdentifierName();
typedefTag.fullName = parseJSDocTypeNameWithNamespace(/*flags*/ 0);
if (typedefTag.fullName) {
let rightNode = typedefTag.fullName;
while (rightNode.kind !== SyntaxKind.Identifier) {
rightNode = rightNode.body;
}
typedefTag.name = rightNode;
}
typedefTag.typeExpression = typeExpression;
skipWhitespace();
@@ -6615,8 +6623,27 @@ namespace ts {
scanner.setTextPos(resumePos);
return finishNode(jsDocTypeLiteral);
}
function parseJSDocTypeNameWithNamespace(flags: NodeFlags) {
const pos = scanner.getTokenPos();
const typeNameOrNamespaceName = parseJSDocIdentifierName();
if (typeNameOrNamespaceName && parseOptional(SyntaxKind.DotToken)) {
const jsDocNamespaceNode = <JSDocNamespaceDeclaration>createNode(SyntaxKind.ModuleDeclaration, pos);
jsDocNamespaceNode.flags |= flags;
jsDocNamespaceNode.name = typeNameOrNamespaceName;
jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(NodeFlags.NestedNamespace);
return jsDocNamespaceNode;
}
if (typeNameOrNamespaceName && flags & NodeFlags.NestedNamespace) {
typeNameOrNamespaceName.isInJSDocNamespace = true;
}
return typeNameOrNamespaceName;
}
}
function tryParseChildTag(parentTag: JSDocTypeLiteral): boolean {
Debug.assert(token() === SyntaxKind.AtToken);
const atToken = <AtToken>createNode(SyntaxKind.AtToken, scanner.getStartPos());
@@ -6639,12 +6666,16 @@ namespace ts {
return true;
case "prop":
case "property":
if (!parentTag.jsDocPropertyTags) {
parentTag.jsDocPropertyTags = <NodeArray<JSDocPropertyTag>>[];
}
const propertyTag = parsePropertyTag(atToken, tagName);
parentTag.jsDocPropertyTags.push(propertyTag);
return true;
if (propertyTag) {
if (!parentTag.jsDocPropertyTags) {
parentTag.jsDocPropertyTags = <NodeArray<JSDocPropertyTag>>[];
}
parentTag.jsDocPropertyTags.push(propertyTag);
return true;
}
// Error parsing property tag
return false;
}
return false;
}
+2 -17
View File
@@ -458,21 +458,7 @@ namespace ts {
// check properties that can affect structure of the program or module resolution strategy
// if any of these properties has changed - structure cannot be reused
const oldOptions = oldProgram.getCompilerOptions();
if ((oldOptions.module !== options.module) ||
(oldOptions.moduleResolution !== options.moduleResolution) ||
(oldOptions.noResolve !== options.noResolve) ||
(oldOptions.target !== options.target) ||
(oldOptions.noLib !== options.noLib) ||
(oldOptions.jsx !== options.jsx) ||
(oldOptions.allowJs !== options.allowJs) ||
(oldOptions.rootDir !== options.rootDir) ||
(oldOptions.configFilePath !== options.configFilePath) ||
(oldOptions.baseUrl !== options.baseUrl) ||
(oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) ||
!arrayIsEqualTo(oldOptions.lib, options.lib) ||
!arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) ||
!arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) ||
!equalOwnProperties(oldOptions.paths, options.paths)) {
if (changesAffectModuleResolution(oldOptions, options)) {
return false;
}
@@ -946,8 +932,7 @@ namespace ts {
return runWithCancellationToken(() => {
const resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken);
// Don't actually write any files since we're just getting diagnostics.
const writeFile: WriteFileCallback = () => { };
return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile);
return ts.getDeclarationDiagnostics(getEmitHost(noop), resolver, sourceFile);
});
}
+3
View File
@@ -1800,6 +1800,9 @@ namespace ts {
case CharacterCodes.comma:
pos++;
return token = SyntaxKind.CommaToken;
case CharacterCodes.dot:
pos++;
return token = SyntaxKind.DotToken;
}
if (isIdentifierStart(ch, ScriptTarget.Latest)) {
+5 -1
View File
@@ -34,6 +34,8 @@ namespace ts {
realpath?(path: string): string;
/*@internal*/ getEnvironmentVariable(name: string): string;
/*@internal*/ tryEnableSourceMapsForHost?(): void;
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
clearTimeout?(timeoutId: any): void;
}
export interface FileWatcher {
@@ -563,7 +565,9 @@ namespace ts {
catch (e) {
// Could not enable source maps.
}
}
},
setTimeout,
clearTimeout
};
return nodeSystem;
}
+21
View File
@@ -362,6 +362,9 @@ namespace ts {
case SyntaxKind.ObjectLiteralExpression:
return visitObjectLiteralExpression(<ObjectLiteralExpression>node);
case SyntaxKind.CatchClause:
return visitCatchClause(<CatchClause>node);
case SyntaxKind.ShorthandPropertyAssignment:
return visitShorthandPropertyAssignment(<ShorthandPropertyAssignment>node);
@@ -2621,6 +2624,24 @@ namespace ts {
return expression;
}
function visitCatchClause(node: CatchClause): CatchClause {
Debug.assert(isBindingPattern(node.variableDeclaration.name));
const temp = createTempVariable(undefined);
const newVariableDeclaration = createVariableDeclaration(temp, undefined, undefined, node.variableDeclaration);
const vars = flattenVariableDestructuring(node.variableDeclaration, temp, visitor);
const list = createVariableDeclarationList(vars, /*location*/node.variableDeclaration, /*flags*/node.variableDeclaration.flags);
const destructure = createVariableStatement(undefined, list);
return updateCatchClause(node, newVariableDeclaration, addStatementToStartOfBlock(node.block, destructure));
}
function addStatementToStartOfBlock(block: Block, statement: Statement): Block {
const transformedStatements = visitNodes(block.statements, visitor, isStatement);
return updateBlock(block, [statement].concat(transformedStatements));
}
/**
* Visits a MethodDeclaration of an ObjectLiteralExpression and transforms it into a
* PropertyAssignment.
+16 -8
View File
@@ -250,8 +250,8 @@ namespace ts {
let compilerOptions: CompilerOptions; // Compiler options for compilation
let compilerHost: CompilerHost; // Compiler host
let hostGetSourceFile: typeof compilerHost.getSourceFile; // getSourceFile method from default host
let timerHandleForRecompilation: number; // Handle for 0.25s wait timer to trigger recompilation
let timerHandleForDirectoryChanges: number; // Handle for 0.25s wait timer to trigger directory change handler
let timerHandleForRecompilation: any; // Handle for 0.25s wait timer to trigger recompilation
let timerHandleForDirectoryChanges: any; // Handle for 0.25s wait timer to trigger directory change handler
// This map stores and reuses results of fileExists check that happen inside 'createProgram'
// This allows to save time in module resolution heavy scenarios when existence of the same file might be checked multiple times.
@@ -501,10 +501,14 @@ namespace ts {
}
function startTimerForHandlingDirectoryChanges() {
if (timerHandleForDirectoryChanges) {
clearTimeout(timerHandleForDirectoryChanges);
if (!sys.setTimeout || !sys.clearTimeout) {
return;
}
timerHandleForDirectoryChanges = setTimeout(directoryChangeHandler, 250);
if (timerHandleForDirectoryChanges) {
sys.clearTimeout(timerHandleForDirectoryChanges);
}
timerHandleForDirectoryChanges = sys.setTimeout(directoryChangeHandler, 250);
}
function directoryChangeHandler() {
@@ -523,10 +527,14 @@ namespace ts {
// operations (such as saving all modified files in an editor) a chance to complete before we kick
// off a new compilation.
function startTimerForRecompilation() {
if (timerHandleForRecompilation) {
clearTimeout(timerHandleForRecompilation);
if (!sys.setTimeout || !sys.clearTimeout) {
return;
}
timerHandleForRecompilation = setTimeout(recompile, 250);
if (timerHandleForRecompilation) {
sys.clearTimeout(timerHandleForRecompilation);
}
timerHandleForRecompilation = sys.setTimeout(recompile, 250);
}
function recompile() {
+40 -22
View File
@@ -456,7 +456,7 @@ namespace ts {
ThisNodeHasError = 1 << 19, // If the parser encountered an error when parsing the code that created this node
JavaScriptFile = 1 << 20, // If node was parsed in a JavaScript
ThisNodeOrAnySubNodesHasError = 1 << 21, // If this node or any of its children had an error
HasAggregatedChildData = 1 << 22, // If we've computed data from children and cached it in this node
HasAggregatedChildData = 1 << 22, // If we've computed data from children and cached it in this node
BlockScoped = Let | Const,
@@ -580,6 +580,7 @@ namespace ts {
originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later
/*@internal*/ autoGenerateKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier.
/*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name.
isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace
}
// Transient identifier node (marked by id === -1)
@@ -1669,7 +1670,7 @@ namespace ts {
export interface ModuleDeclaration extends DeclarationStatement {
kind: SyntaxKind.ModuleDeclaration;
name: Identifier | LiteralExpression;
body?: ModuleBlock | NamespaceDeclaration;
body?: ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | Identifier;
}
export interface NamespaceDeclaration extends ModuleDeclaration {
@@ -1677,6 +1678,11 @@ namespace ts {
body: ModuleBlock | NamespaceDeclaration;
}
export interface JSDocNamespaceDeclaration extends ModuleDeclaration {
name: Identifier;
body: JSDocNamespaceDeclaration | Identifier;
}
export interface ModuleBlock extends Node, Statement {
kind: SyntaxKind.ModuleBlock;
statements: NodeArray<Statement>;
@@ -1906,6 +1912,7 @@ namespace ts {
export interface JSDocTypedefTag extends JSDocTag, Declaration {
kind: SyntaxKind.JSDocTypedefTag;
fullName?: JSDocNamespaceDeclaration | Identifier;
name?: Identifier;
typeExpression?: JSDocTypeExpression;
jsDocTypeLiteral?: JSDocTypeLiteral;
@@ -2647,24 +2654,17 @@ namespace ts {
Null = 1 << 12,
Never = 1 << 13, // Never type
TypeParameter = 1 << 14, // Type parameter
Class = 1 << 15, // Class
Interface = 1 << 16, // Interface
Reference = 1 << 17, // Generic type reference
Tuple = 1 << 18, // Synthesized generic tuple type
Union = 1 << 19, // Union (T | U)
Intersection = 1 << 20, // Intersection (T & U)
Anonymous = 1 << 21, // Anonymous
Instantiated = 1 << 22, // Instantiated anonymous type
Object = 1 << 15, // Object type
Union = 1 << 16, // Union (T | U)
Intersection = 1 << 17, // Intersection (T & U)
/* @internal */
ObjectLiteral = 1 << 23, // Originates in an object literal
FreshLiteral = 1 << 18, // Fresh literal type
/* @internal */
FreshLiteral = 1 << 24, // Fresh literal type
ContainsWideningType = 1 << 19, // Type is or contains undefined or null widening type
/* @internal */
ContainsWideningType = 1 << 25, // Type is or contains undefined or null widening type
ContainsObjectLiteral = 1 << 20, // Type is or contains object literal type
/* @internal */
ContainsObjectLiteral = 1 << 26, // Type is or contains object literal type
/* @internal */
ContainsAnyFunctionType = 1 << 27, // Type is or contains object literal type
ContainsAnyFunctionType = 1 << 21, // Type is or contains object literal type
/* @internal */
Nullable = Undefined | Null,
@@ -2681,15 +2681,14 @@ namespace ts {
NumberLike = Number | NumberLiteral | Enum | EnumLiteral,
BooleanLike = Boolean | BooleanLiteral,
EnumLike = Enum | EnumLiteral,
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
UnionOrIntersection = Union | Intersection,
StructuredType = ObjectType | Union | Intersection,
StructuredType = Object | Union | Intersection,
StructuredOrTypeParameter = StructuredType | TypeParameter,
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
Narrowable = Any | StructuredType | TypeParameter | StringLike | NumberLike | BooleanLike | ESSymbol,
NotUnionOrUnit = Any | ESSymbol | ObjectType,
NotUnionOrUnit = Any | ESSymbol | Object,
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
/* @internal */
@@ -2732,9 +2731,22 @@ namespace ts {
baseType: EnumType & UnionType; // Base enum type
}
export const enum ObjectFlags {
Class = 1 << 0, // Class
Interface = 1 << 1, // Interface
Reference = 1 << 2, // Generic type reference
Tuple = 1 << 3, // Synthesized generic tuple type
Anonymous = 1 << 4, // Anonymous
Instantiated = 1 << 5, // Instantiated anonymous type
ObjectLiteral = 1 << 6, // Originates in an object literal
EvolvingArray = 1 << 7, // Evolving array type
ObjectLiteralPatternWithComputedProperties = 1 << 8, // Object literal pattern with computed properties
ClassOrInterface = Class | Interface
}
// Object types (TypeFlags.ObjectType)
export interface ObjectType extends Type {
isObjectLiteralPatternWithComputedProperties?: boolean;
objectFlags: ObjectFlags;
}
// Class and interface types (TypeFlags.Class and TypeFlags.Interface)
@@ -2788,13 +2800,18 @@ namespace ts {
export interface IntersectionType extends UnionOrIntersectionType { }
export type StructuredType = ObjectType | UnionType | IntersectionType;
/* @internal */
// An instantiated anonymous type has a target and a mapper
export interface AnonymousType extends ObjectType {
target?: AnonymousType; // Instantiation target
mapper?: TypeMapper; // Instantiation mapper
elementType?: Type; // Element expressions of evolving array type
finalArrayType?: Type; // Final array type of evolving array type
}
export interface EvolvingArrayType extends ObjectType {
elementType: Type; // Element expressions of evolving array type
finalArrayType?: Type; // Final array type of evolving array type
}
/* @internal */
@@ -3059,6 +3076,7 @@ namespace ts {
packageNameToTypingLocation: MapLike<string>; // 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
unresolvedImports: ReadonlyArray<string>; // List of unresolved module ids from imports
}
export enum ModuleKind {
+11 -32
View File
@@ -63,11 +63,11 @@ namespace ts {
// Completely ignore indentation for string writers. And map newlines to
// a single space.
writeLine: () => str += " ",
increaseIndent: () => { },
decreaseIndent: () => { },
increaseIndent: noop,
decreaseIndent: noop,
clear: () => str = "",
trackSymbol: () => { },
reportInaccessibleThisError: () => { }
trackSymbol: noop,
reportInaccessibleThisError: noop
};
}
@@ -83,25 +83,6 @@ namespace ts {
return node.end - node.pos;
}
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T>, array2: ReadonlyArray<T>, equaler?: (a: T, b: T) => boolean): boolean {
if (!array1 || !array2) {
return array1 === array2;
}
if (array1.length !== array2.length) {
return false;
}
for (let i = 0; i < array1.length; i++) {
const equals = equaler ? equaler(array1[i], array2[i]) : array1[i] === array2[i];
if (!equals) {
return false;
}
}
return true;
}
export function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean {
return !!(sourceFile && sourceFile.resolvedModules && sourceFile.resolvedModules.get(moduleNameText));
}
@@ -406,7 +387,12 @@ namespace ts {
export function isBlockOrCatchScoped(declaration: Declaration) {
return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 ||
isCatchClauseVariableDeclaration(declaration);
isCatchClauseVariableDeclarationOrBindingElement(declaration);
}
export function isCatchClauseVariableDeclarationOrBindingElement(declaration: Declaration) {
const node = getRootDeclaration(declaration);
return node.kind === SyntaxKind.VariableDeclaration && node.parent.kind === SyntaxKind.CatchClause;
}
export function isAmbientModule(node: Node): boolean {
@@ -489,13 +475,6 @@ namespace ts {
}
}
export function isCatchClauseVariableDeclaration(declaration: Declaration) {
return declaration &&
declaration.kind === SyntaxKind.VariableDeclaration &&
declaration.parent &&
declaration.parent.kind === SyntaxKind.CatchClause;
}
// Return display name of an identifier
// Computed property names will just be emitted as "[<expr>]", where <expr> is the source
// text of the expression in the computed property.
@@ -3037,7 +3016,7 @@ namespace ts {
}
}
if (node.flags & NodeFlags.NestedNamespace) {
if (node.flags & NodeFlags.NestedNamespace || (node.kind === SyntaxKind.Identifier && (<Identifier>node).isInJSDocNamespace)) {
flags |= ModifierFlags.Export;
}
+3 -3
View File
@@ -1331,18 +1331,18 @@ namespace ts {
export namespace Debug {
export const failNotOptional = shouldAssert(AssertionLevel.Normal)
? (message?: string) => assert(false, message || "Node not optional.")
: () => {};
: noop;
export const failBadSyntaxKind = shouldAssert(AssertionLevel.Normal)
? (node: Node, message?: string) => assert(false, message || "Unexpected node.", () => `Node ${formatSyntaxKind(node.kind)} was unexpected.`)
: () => {};
: noop;
export const assertNode = shouldAssert(AssertionLevel.Normal)
? (node: Node, test: (node: Node) => boolean, message?: string) => assert(
test === undefined || test(node),
message || "Unexpected node.",
() => `Node ${formatSyntaxKind(node.kind)} did not pass test '${getFunctionName(test)}'.`)
: () => {};
: noop;
function getFunctionName(func: Function) {
if (typeof func !== "function") {
+2 -2
View File
@@ -690,7 +690,7 @@ namespace Harness {
export const getCurrentDirectory = () => "";
export const args = () => <string[]>[];
export const getExecutingFilePath = () => "";
export const exit = () => { };
export const exit = ts.noop;
export const getDirectories = () => <string[]>[];
export let log = (s: string) => console.log(s);
@@ -1668,7 +1668,7 @@ namespace Harness {
// This does not need to exist strictly speaking, but many tests will need to be updated if it's removed
export function compileString(_code: string, _unitName: string, _callback: (result: CompilerResult) => void) {
// NEWTODO: Re-implement 'compileString'
throw new Error("compileString NYI");
return ts.notImplemented();
}
export interface GeneratedFile {
+8 -12
View File
@@ -313,14 +313,10 @@ namespace Harness.LanguageService {
getLocalizedDiagnosticMessages(): string { return JSON.stringify({}); }
readDirectory(_rootDir: string, _extension: string): string {
throw new Error("NYI");
}
readDirectoryNames(_path: string): string {
throw new Error("Not implemented.");
}
readFileNames(_path: string): string {
throw new Error("Not implemented.");
return ts.notImplemented();
}
readDirectoryNames = ts.notImplemented;
readFileNames = ts.notImplemented;
fileExists(fileName: string) { return this.getScriptInfo(fileName) !== undefined; }
readFile(fileName: string) {
const snapshot = this.nativeHost.getScriptSnapshot(fileName);
@@ -339,7 +335,7 @@ namespace Harness.LanguageService {
constructor(private shim: ts.ClassifierShim) {
}
getEncodedLexicalClassifications(_text: string, _lexState: ts.EndOfLineState, _classifyKeywordsInGenerics?: boolean): ts.Classifications {
throw new Error("NYI");
return ts.notImplemented();
}
getClassificationsForLine(text: string, lexState: ts.EndOfLineState, classifyKeywordsInGenerics?: boolean): ts.ClassificationResult {
const result = this.shim.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics).split("\n");
@@ -648,7 +644,7 @@ namespace Harness.LanguageService {
}
createDirectory(_directoryName: string): void {
throw new Error("Not Implemented Yet.");
return ts.notImplemented();
}
getCurrentDirectory(): string {
@@ -664,15 +660,15 @@ namespace Harness.LanguageService {
}
readDirectory(_path: string, _extension?: string[], _exclude?: string[], _include?: string[]): string[] {
throw new Error("Not implemented Yet.");
return ts.notImplemented();
}
watchFile(): ts.FileWatcher {
return { close() { } };
return { close: ts.noop };
}
watchDirectory(): ts.FileWatcher {
return { close() { } };
return { close: ts.noop };
}
close(): void {
+1 -1
View File
@@ -222,5 +222,5 @@ else {
}
if (!runUnitTests) {
// patch `describe` to skip unit tests
describe = <any>(function () { });
describe = ts.noop as any;
}
+15 -18
View File
@@ -21,16 +21,16 @@ namespace ts {
args: <string[]>[],
newLine: "\r\n",
useCaseSensitiveFileNames: false,
write: () => { },
write: noop,
readFile: (path: string): string => {
const file = fileMap.get(path);
return file !== undefined ? file.content : undefined;
},
writeFile: (_path: string, _data: string, _writeByteOrderMark?: boolean) => {
throw new Error("NYI");
return ts.notImplemented();
},
resolvePath: (_path: string): string => {
throw new Error("NYI");
return ts.notImplemented();
},
fileExists: (path: string): boolean => {
return fileMap.has(path);
@@ -38,7 +38,7 @@ namespace ts {
directoryExists: (path: string): boolean => {
return existingDirectories.has(path);
},
createDirectory: () => { },
createDirectory: noop,
getExecutingFilePath: (): string => {
return "";
},
@@ -48,14 +48,14 @@ namespace ts {
getDirectories: () => [],
getEnvironmentVariable: () => "",
readDirectory: (_path: string, _extension?: string[], _exclude?: string[], _include?: string[]): string[] => {
throw new Error("NYI");
return ts.notImplemented();
},
exit: () => { },
exit: noop,
watchFile: () => ({
close: () => { }
close: noop
}),
watchDirectory: () => ({
close: () => { }
close: noop
}),
setTimeout,
clearTimeout,
@@ -66,14 +66,14 @@ namespace ts {
function createProject(rootFile: string, serverHost: server.ServerHost): { project: server.Project, rootScriptInfo: server.ScriptInfo } {
const logger: server.Logger = {
close() { },
close: noop,
hasLevel: () => false,
loggingEnabled: () => false,
perftrc: () => { },
info: () => { },
startGroup: () => { },
endGroup: () => { },
msg: () => { },
perftrc: noop,
info: noop,
startGroup: noop,
endGroup: noop,
msg: noop,
getLogFileName: (): string => undefined
};
@@ -110,10 +110,7 @@ namespace ts {
const originalFileExists = serverHost.fileExists;
{
// patch fileExists to make sure that disk is not touched
serverHost.fileExists = (): boolean => {
assert.isTrue(false, "fileExists should not be called");
return false;
};
serverHost.fileExists = notImplemented;
const newContent = `import {x} from "f1"
var x: string = 1;`;
+34 -1
View File
@@ -1,4 +1,4 @@
/// <reference path="..\harness.ts" />
/// <reference path="..\harness.ts" />
/// <reference path="..\..\compiler\commandLineParser.ts" />
namespace ts {
@@ -338,5 +338,38 @@ namespace ts {
}
});
});
it("Parse explicit boolean flag value", () => {
assertParseResult(["--strictNullChecks", "false", "0.ts"],
{
errors: [],
fileNames: ["0.ts"],
options: {
strictNullChecks: false,
}
});
});
it("Parse non boolean argument after boolean flag", () => {
assertParseResult(["--noImplicitAny", "t", "0.ts"],
{
errors: [],
fileNames: ["t", "0.ts"],
options: {
noImplicitAny: true,
}
});
});
it("Parse implicit boolean flag value", () => {
assertParseResult(["--strictNullChecks"],
{
errors: [],
fileNames: [],
options: {
strictNullChecks: true,
}
});
});
});
}
+56 -24
View File
@@ -3,6 +3,7 @@
namespace ts {
const caseInsensitiveBasePath = "c:/dev/";
const caseInsensitiveTsconfigPath = "c:/dev/tsconfig.json";
const caseInsensitiveHost = new Utils.MockParseConfigHost(caseInsensitiveBasePath, /*useCaseSensitiveFileNames*/ false, [
"c:/dev/a.ts",
"c:/dev/a.d.ts",
@@ -88,6 +89,8 @@ namespace ts {
"c:/dev/g.min.js/.g/g.ts"
]);
const defaultExcludes = ["node_modules", "bower_components", "jspm_packages"];
describe("matchFiles", () => {
describe("with literal file list", () => {
it("without exclusions", () => {
@@ -189,11 +192,14 @@ namespace ts {
};
const expected: ts.ParsedCommandLine = {
options: {},
errors: [],
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
],
fileNames: [],
wildcardDirectories: {},
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
@@ -207,11 +213,14 @@ namespace ts {
};
const expected: ts.ParsedCommandLine = {
options: {},
errors: [],
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
],
fileNames: [],
wildcardDirectories: {},
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
@@ -551,13 +560,16 @@ namespace ts {
};
const expected: ts.ParsedCommandLine = {
options: {},
errors: [],
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
],
fileNames: [],
wildcardDirectories: {
"c:/dev": ts.WatchDirectoryFlags.Recursive
},
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
@@ -619,7 +631,7 @@ namespace ts {
it("with common package folders and no exclusions", () => {
const json = {
include: [
"**/a.ts"
"**/a.ts"
]
};
const expected: ts.ParsedCommandLine = {
@@ -701,13 +713,16 @@ namespace ts {
options: {
allowJs: false
},
errors: [],
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
],
fileNames: [],
wildcardDirectories: {
"c:/dev/js": ts.WatchDirectoryFlags.None
}
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
@@ -828,11 +843,14 @@ namespace ts {
};
const expected: ts.ParsedCommandLine = {
options: {},
errors: [],
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))]
,
fileNames: [],
wildcardDirectories: {}
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
@@ -1030,12 +1048,14 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**")
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
],
fileNames: [],
wildcardDirectories: {}
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
@@ -1051,11 +1071,14 @@ namespace ts {
};
const expected: ts.ParsedCommandLine = {
options: {},
errors: [],
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))
],
fileNames: [],
wildcardDirectories: {}
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
@@ -1071,12 +1094,14 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, "**/x/**/*")
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_multiple_recursive_directory_wildcards_Asterisk_Asterisk_Colon_0, "**/x/**/*"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
],
fileNames: [],
wildcardDirectories: {}
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
@@ -1122,12 +1147,14 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*")
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
],
fileNames: [],
wildcardDirectories: {}
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
@@ -1142,12 +1169,14 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*")
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*"),
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(defaultExcludes))
],
fileNames: [],
wildcardDirectories: {}
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
@@ -1195,7 +1224,7 @@ namespace ts {
const expected: ts.ParsedCommandLine = {
options: {},
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..")
ts.createCompilerDiagnostic(ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..")
],
fileNames: [
"c:/dev/a.ts",
@@ -1320,11 +1349,14 @@ namespace ts {
};
const expected: ts.ParsedCommandLine = {
options: {},
errors: [],
errors: [
ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))
],
fileNames: [],
wildcardDirectories: {}
};
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
assert.deepEqual(actual.fileNames, expected.fileNames);
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
assert.deepEqual(actual.errors, expected.errors);
+7 -13
View File
@@ -290,7 +290,7 @@ namespace ts {
return file !== undefined ? createSourceFile(fileName, file, languageVersion) : undefined;
},
getDefaultLibFileName: () => "lib.d.ts",
writeFile: (): void => { throw new Error("NotImplemented"); },
writeFile: notImplemented,
getCurrentDirectory: () => currentDirectory,
getDirectories: () => [],
getCanonicalFileName: fileName => fileName.toLowerCase(),
@@ -300,7 +300,7 @@ namespace ts {
const path = normalizePath(combinePaths(currentDirectory, fileName));
return files.has(path);
},
readFile: (): string => { throw new Error("NotImplemented"); }
readFile: notImplemented
};
const program = createProgram(rootFiles, options, host);
@@ -371,7 +371,7 @@ export = C;
return file !== undefined ? createSourceFile(fileName, file, languageVersion) : undefined;
},
getDefaultLibFileName: () => "lib.d.ts",
writeFile: (): void => { throw new Error("NotImplemented"); },
writeFile: notImplemented,
getCurrentDirectory: () => currentDirectory,
getDirectories: () => [],
getCanonicalFileName,
@@ -381,7 +381,7 @@ export = C;
const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
return files.has(path);
},
readFile: (): string => { throw new Error("NotImplemented"); }
readFile: notImplemented
};
const program = createProgram(rootFiles, options, host);
const diagnostics = sortAndDeduplicateDiagnostics(program.getSemanticDiagnostics().concat(program.getOptionsDiagnostics()));
@@ -912,15 +912,11 @@ import b = require("./moduleB");
});
});
function notImplemented(name: string): () => any {
return () => assert(`${name} is not implemented and should not be called`);
}
describe("ModuleResolutionHost.directoryExists", () => {
it("No 'fileExists' calls if containing directory is missing", () => {
const host: ModuleResolutionHost = {
readFile: notImplemented("readFile"),
fileExists: notImplemented("fileExists"),
readFile: notImplemented,
fileExists: notImplemented,
directoryExists: _ => false
};
@@ -1023,9 +1019,7 @@ import b = require("./moduleB");
fileExists : fileName => sourceFiles.has(fileName),
getSourceFile: fileName => sourceFiles.get(fileName),
getDefaultLibFileName: () => "lib.d.ts",
writeFile(_file, _text) {
throw new Error("NYI");
},
writeFile: notImplemented,
getCurrentDirectory: () => "/",
getDirectories: () => [],
getCanonicalFileName: f => f.toLowerCase(),
@@ -111,9 +111,7 @@ namespace ts {
getDefaultLibFileName(): string {
return "lib.d.ts";
},
writeFile() {
throw new Error("NYI");
},
writeFile: notImplemented,
getCurrentDirectory(): string {
return "";
},
@@ -245,13 +243,13 @@ namespace ts {
it("fails if change affects type references", () => {
const program_1 = newProgram(files, ["a.ts"], { types: ["a"] });
updateProgram(program_1, ["a.ts"], { types: ["b"] }, () => { });
updateProgram(program_1, ["a.ts"], { types: ["b"] }, noop);
assert.isTrue(!program_1.structureIsReused);
});
it("succeeds if change doesn't affect type references", () => {
const program_1 = newProgram(files, ["a.ts"], { types: ["a"] });
updateProgram(program_1, ["a.ts"], { types: ["a"] }, () => { });
updateProgram(program_1, ["a.ts"], { types: ["a"] }, noop);
assert.isTrue(program_1.structureIsReused);
});
@@ -277,19 +275,19 @@ namespace ts {
it("fails if module kind changes", () => {
const program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS });
updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.AMD }, () => { });
updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.AMD }, noop);
assert.isTrue(!program_1.structureIsReused);
});
it("fails if rootdir changes", () => {
const program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/b" });
updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/c" }, () => { });
updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/c" }, noop);
assert.isTrue(!program_1.structureIsReused);
});
it("fails if config path changes", () => {
const program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/b/tsconfig.json" });
updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/c/tsconfig.json" }, () => { });
updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/c/tsconfig.json" }, noop);
assert.isTrue(!program_1.structureIsReused);
});
+11 -11
View File
@@ -10,32 +10,32 @@ namespace ts.server {
useCaseSensitiveFileNames: true,
write(s): void { lastWrittenToHost = s; },
readFile(): string { return void 0; },
writeFile(): void {},
writeFile: noop,
resolvePath(): string { return void 0; },
fileExists: () => false,
directoryExists: () => false,
getDirectories: () => [],
createDirectory(): void {},
createDirectory: noop,
getExecutingFilePath(): string { return void 0; },
getCurrentDirectory(): string { return void 0; },
getEnvironmentVariable(): string { return ""; },
readDirectory(): string[] { return []; },
exit(): void { },
exit: noop,
setTimeout() { return 0; },
clearTimeout() { },
clearTimeout: noop,
setImmediate: () => 0,
clearImmediate() {}
clearImmediate: noop
};
const nullCancellationToken: HostCancellationToken = { isCancellationRequested: () => false };
const mockLogger: Logger = {
close(): void {},
close: noop,
hasLevel(): boolean { return false; },
loggingEnabled(): boolean { return false; },
perftrc(): void {},
info(): void {},
startGroup(): void {},
endGroup(): void {},
msg(): void {},
perftrc: noop,
info: noop,
startGroup: noop,
endGroup: noop,
msg: noop,
getLogFileName: (): string => undefined
};
+67
View File
@@ -28,6 +28,14 @@ namespace ts {
assert.isTrue(arrayIsEqualTo(parsed.fileNames.sort(), expectedFileList.sort()));
}
function assertParseFileDiagnostics(jsonText: string, configFileName: string, basePath: string, allFileList: string[], expectedDiagnosticCode: number) {
const json = JSON.parse(jsonText);
const host: ParseConfigHost = new Utils.MockParseConfigHost(basePath, true, allFileList);
const parsed = ts.parseJsonConfigFileContent(json, host, basePath, /*existingOptions*/ undefined, configFileName);
assert.isTrue(parsed.errors.length >= 0);
assert.isTrue(parsed.errors.filter(e => e.code === expectedDiagnosticCode).length > 0, `Expected error code ${expectedDiagnosticCode} to be in ${JSON.stringify(parsed.errors)}`);
}
it("returns empty config for file with only whitespaces", () => {
assertParseResult("", { config : {} });
assertParseResult(" ", { config : {} });
@@ -202,5 +210,64 @@ namespace ts {
assert.isTrue(diagnostics.length === 2);
assert.equal(JSON.stringify(configJsonObject), JSON.stringify(expectedResult));
});
it("generates errors for empty files list", () => {
const content = `{
"files": []
}`;
assertParseFileDiagnostics(content,
"/apath/tsconfig.json",
"tests/cases/unittests",
["/apath/a.ts"],
Diagnostics.The_files_list_in_config_file_0_is_empty.code);
});
it("generates errors for directory with no .ts files", () => {
const content = `{
}`;
assertParseFileDiagnostics(content,
"/apath/tsconfig.json",
"tests/cases/unittests",
["/apath/a.js"],
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
});
it("generates errors for empty directory", () => {
const content = `{
"compilerOptions": {
"allowJs": true
}
}`;
assertParseFileDiagnostics(content,
"/apath/tsconfig.json",
"tests/cases/unittests",
[],
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
});
it("generates errors for empty include", () => {
const content = `{
"include": []
}`;
assertParseFileDiagnostics(content,
"/apath/tsconfig.json",
"tests/cases/unittests",
["/apath/a.ts"],
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
});
it("generates errors for includes with outDir", () => {
const content = `{
"compilerOptions": {
"outDir": "./"
},
"include": ["**/*"]
}`;
assertParseFileDiagnostics(content,
"/apath/tsconfig.json",
"tests/cases/unittests",
["/apath/a.ts"],
Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code);
});
});
}
@@ -23,10 +23,6 @@ namespace ts.projectSystem {
readonly callback: TI.RequestCompletedAction;
}
export function notImplemented(): any {
throw new Error("Not yet implemented");
}
export const nullLogger: server.Logger = {
close: () => void 0,
hasLevel: () => void 0,
@@ -98,8 +94,8 @@ namespace ts.projectSystem {
this.projectService.updateTypingsForProject(response);
}
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions) {
const request = server.createInstallTypingsRequest(project, typingOptions, this.globalTypingsCacheLocation);
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions, unresolvedImports: server.SortedReadonlyArray<string>) {
const request = server.createInstallTypingsRequest(project, typingOptions, unresolvedImports, this.globalTypingsCacheLocation);
this.install(request);
}
+218 -17
View File
@@ -217,9 +217,9 @@ namespace ts.projectSystem {
constructor() {
super(host);
}
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions) {
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions, unresolvedImports: server.SortedReadonlyArray<string>) {
enqueueIsCalled = true;
super.enqueueInstallTypingsRequest(project, typingOptions);
super.enqueueInstallTypingsRequest(project, typingOptions, unresolvedImports);
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
const installedTypings = ["@types/jquery"];
@@ -319,9 +319,9 @@ namespace ts.projectSystem {
constructor() {
super(host);
}
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions) {
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions, unresolvedImports: server.SortedReadonlyArray<string>) {
enqueueIsCalled = true;
super.enqueueInstallTypingsRequest(project, typingOptions);
super.enqueueInstallTypingsRequest(project, typingOptions, unresolvedImports);
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
const installedTypings: string[] = [];
@@ -569,7 +569,7 @@ namespace ts.projectSystem {
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
if (requestKind === TI.NpmInstallRequest) {
let typingFiles: (FileOrFolder & { typings: string}) [] = [];
let typingFiles: (FileOrFolder & { typings: string })[] = [];
if (args.indexOf("@types/commander") >= 0) {
typingFiles = [commander, jquery, lodash, cordova];
}
@@ -591,7 +591,7 @@ namespace ts.projectSystem {
projectFileName: projectFileName1,
options: { allowJS: true, moduleResolution: ModuleResolutionKind.NodeJs },
rootFiles: [toExternalFile(lodashJs.path), toExternalFile(commanderJs.path), toExternalFile(file3.path)],
typingOptions: { include: ["jquery", "cordova" ] }
typingOptions: { include: ["jquery", "cordova"] }
});
installer.checkPendingCommands([TI.NpmViewRequest, TI.NpmViewRequest, TI.NpmViewRequest]);
@@ -626,7 +626,7 @@ namespace ts.projectSystem {
installer.executePendingCommands();
checkProjectActualFiles(p1, [lodashJs.path, commanderJs.path, file3.path, commander.path, jquery.path, lodash.path, cordova.path]);
checkProjectActualFiles(p2, [file3.path, grunt.path, gulp.path ]);
checkProjectActualFiles(p2, [file3.path, grunt.path, gulp.path]);
});
it("configured projects discover from node_modules", () => {
@@ -687,10 +687,10 @@ namespace ts.projectSystem {
const bowerJson = {
path: "/bower.json",
content: JSON.stringify({
"dependencies": {
"jquery": "^3.1.0"
}
})
"dependencies": {
"jquery": "^3.1.0"
}
})
};
const jqueryDTS = {
path: "/tmp/node_modules/@types/jquery/index.d.ts",
@@ -720,26 +720,196 @@ namespace ts.projectSystem {
checkNumberOfProjects(projectService, { configuredProjects: 1 });
checkProjectActualFiles(p, [app.path, jqueryDTS.path]);
});
it("Malformed package.json should be watched", () => {
const f = {
path: "/a/b/app.js",
content: "var x = 1"
};
const brokenPackageJson = {
path: "/a/b/package.json",
content: `{ "dependencies": { "co } }`
};
const fixedPackageJson = {
path: brokenPackageJson.path,
content: `{ "dependencies": { "commander": "0.0.2" } }`
};
const cachePath = "/a/cache/";
const commander = {
path: cachePath + "node_modules/@types/commander/index.d.ts",
content: "export let x: number"
};
const host = createServerHost([f, brokenPackageJson]);
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: cachePath });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
const installedTypings = ["@types/commander"];
const typingFiles = [commander];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
}
})();
const service = createProjectService(host, { typingsInstaller: installer });
service.openClientFile(f.path);
installer.checkPendingCommands([]);
host.reloadFS([f, fixedPackageJson]);
host.triggerFileWatcherCallback(fixedPackageJson.path, /*removed*/ false);
// expected one view and one install request
installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]);
service.checkNumberOfProjects({ inferredProjects: 1 });
checkProjectActualFiles(service.inferredProjects[0], [f.path, commander.path]);
});
it("should install typings for unresolved imports", () => {
const file = {
path: "/a/b/app.js",
content: `
import * as fs from "fs";
import * as commander from "commander";`
};
const cachePath = "/a/cache";
const node = {
path: cachePath + "/node_modules/@types/node/index.d.ts",
content: "export let x: number"
};
const commander = {
path: cachePath + "/node_modules/@types/commander/index.d.ts",
content: "export let y: string"
};
const host = createServerHost([file]);
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: cachePath });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, _args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
const installedTypings = ["@types/node", "@types/commander"];
const typingFiles = [node, commander];
executeCommand(this, host, installedTypings, typingFiles, requestKind, cb);
}
})();
const service = createProjectService(host, { typingsInstaller: installer });
service.openClientFile(file.path);
service.checkNumberOfProjects({ inferredProjects: 1 });
checkProjectActualFiles(service.inferredProjects[0], [file.path]);
installer.installAll([TI.NpmViewRequest, TI.NpmViewRequest], [TI.NpmInstallRequest]);
assert.isTrue(host.fileExists(node.path), "typings for 'node' should be created");
assert.isTrue(host.fileExists(commander.path), "typings for 'commander' should be created");
checkProjectActualFiles(service.inferredProjects[0], [file.path, node.path, commander.path]);
});
it("should pick typing names from non-relative unresolved imports", () => {
const f1 = {
path: "/a/b/app.js",
content: `
import * as a from "foo/a/a";
import * as b from "foo/a/b";
import * as c from "foo/a/c";
import * as d from "@bar/router/";
import * as e from "@bar/common/shared";
import * as e from "@bar/common/apps";
import * as f from "./lib"
`
};
const host = createServerHost([f1]);
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: "/tmp" });
}
executeRequest(requestKind: TI.RequestKind, _requestId: number, args: string[], _cwd: string, cb: server.typingsInstaller.RequestCompletedAction) {
if (requestKind === TI.NpmViewRequest) {
// args should have only non-scoped packages - scoped packages are not yet supported
assert.deepEqual(args, ["foo"]);
}
executeCommand(this, host, ["foo"], [], requestKind, cb);
}
})();
const projectService = createProjectService(host, { typingsInstaller: installer });
projectService.openClientFile(f1.path);
projectService.checkNumberOfProjects({ inferredProjects: 1 });
const proj = projectService.inferredProjects[0];
proj.updateGraph();
assert.deepEqual(
proj.getCachedUnresolvedImportsPerFile_TestOnly().get(<Path>f1.path),
["foo", "foo", "foo", "@bar/router", "@bar/common", "@bar/common"]
);
installer.installAll([TI.NpmViewRequest], [TI.NpmInstallRequest]);
});
it("cached unresolved typings are not recomputed if program structure did not change", () => {
const host = createServerHost([]);
const session = createSession(host);
const f = {
path: "/a/app.js",
content: `
import * as fs from "fs";
import * as cmd from "commander
`
};
session.executeCommand(<server.protocol.OpenRequest>{
seq: 1,
type: "request",
command: "open",
arguments: {
file: f.path,
fileContent: f.content
}
});
const projectService = session.getProjectService();
checkNumberOfProjects(projectService, { inferredProjects: 1 });
const proj = projectService.inferredProjects[0];
const version1 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion();
// make a change that should not affect the structure of the program
session.executeCommand(<server.protocol.ChangeRequest>{
seq: 2,
type: "request",
command: "change",
arguments: {
file: f.path,
insertString: "\nlet x = 1;",
line: 2,
offset: 0,
endLine: 2,
endOffset: 0
}
});
host.checkTimeoutQueueLength(1);
host.runQueuedTimeoutCallbacks();
const version2 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion();
assert.equal(version1, version2, "set of unresolved imports should not change");
});
});
describe("Validate package name:", () => {
it ("name cannot be too long", () => {
it("name cannot be too long", () => {
let packageName = "a";
for (let i = 0; i < 8; i++) {
packageName += packageName;
}
assert.equal(TI.validatePackageName(packageName), TI.PackageNameValidationResult.NameTooLong);
});
it ("name cannot start with dot", () => {
it("name cannot start with dot", () => {
assert.equal(TI.validatePackageName(".foo"), TI.PackageNameValidationResult.NameStartsWithDot);
});
it ("name cannot start with underscore", () => {
it("name cannot start with underscore", () => {
assert.equal(TI.validatePackageName("_foo"), TI.PackageNameValidationResult.NameStartsWithUnderscore);
});
it ("scoped packages not supported", () => {
it("scoped packages not supported", () => {
assert.equal(TI.validatePackageName("@scope/bar"), TI.PackageNameValidationResult.ScopedPackagesNotSupported);
});
it ("non URI safe characters are not supported", () => {
it("non URI safe characters are not supported", () => {
assert.equal(TI.validatePackageName(" scope "), TI.PackageNameValidationResult.NameContainsNonURISafeCharacters);
assert.equal(TI.validatePackageName("; say Hello from TypeScript! #"), TI.PackageNameValidationResult.NameContainsNonURISafeCharacters);
assert.equal(TI.validatePackageName("a/b/c"), TI.PackageNameValidationResult.NameContainsNonURISafeCharacters);
@@ -747,7 +917,7 @@ namespace ts.projectSystem {
});
describe("Invalid package names", () => {
it ("should not be installed", () => {
it("should not be installed", () => {
const f1 = {
path: "/a/b/app.js",
content: "let x = 1"
@@ -777,4 +947,35 @@ namespace ts.projectSystem {
assert.isTrue(messages.indexOf("Package name '; say Hello from TypeScript! #' contains non URI safe characters") > 0, "should find package with invalid name");
});
});
describe("discover typings", () => {
it("should return node for core modules", () => {
const f = {
path: "/a/b/app.js",
content: ""
};
const host = createServerHost([f]);
const cache = new StringMap<string>();
for (const name of JsTyping.nodeCoreModuleList) {
const result = JsTyping.discoverTypings(host, [f.path], getDirectoryPath(<Path>f.path), /*safeListPath*/ undefined, cache, { enableAutoDiscovery: true }, [name, "somename"]);
assert.deepEqual(result.newTypingNames.sort(), ["node", "somename"]);
}
});
it("should use cached locaitons", () => {
const f = {
path: "/a/b/app.js",
content: ""
};
const node = {
path: "/a/b/node.d.ts",
content: ""
};
const host = createServerHost([f, node]);
const cache = mapOfMapLike({ "node": node.path });
const result = JsTyping.discoverTypings(host, [f.path], getDirectoryPath(<Path>f.path), /*safeListPath*/ undefined, cache, { enableAutoDiscovery: true }, ["fs", "bar"]);
assert.deepEqual(result.cachedTypingPaths, [node.path]);
assert.deepEqual(result.newTypingNames, ["bar"]);
});
});
}
+4 -4
View File
@@ -205,13 +205,13 @@ interface NumberConstructor {
* number. Only finite values of the type number, result in true.
* @param number A numeric value.
*/
isFinite(number: number): boolean;
isFinite(value: any): value is number;
/**
* Returns true if the value passed is an integer, false otherwise.
* @param number A numeric value.
*/
isInteger(number: number): boolean;
isInteger(value: any): value is number;
/**
* Returns a Boolean value that indicates whether a value is the reserved value NaN (not a
@@ -219,13 +219,13 @@ interface NumberConstructor {
* to a number. Only values of the type number, that are also NaN, result in true.
* @param number A numeric value.
*/
isNaN(number: number): boolean;
isNaN(value: any): value is number;
/**
* Returns true if the value passed is a safe integer.
* @param number A numeric value.
*/
isSafeInteger(number: number): boolean;
isSafeInteger(value: any): value is number;
/**
* The value of the largest integer n such that n and n + 1 are both exactly representable as
+14 -14
View File
@@ -242,7 +242,7 @@ namespace ts.server {
}
getCompletionEntrySymbol(_fileName: string, _position: number, _entryName: string): Symbol {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getNavigateToItems(searchValue: string): NavigateToItem[] {
@@ -415,7 +415,7 @@ namespace ts.server {
}
getEmitOutput(_fileName: string): EmitOutput {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getSyntacticDiagnostics(fileName: string): Diagnostic[] {
@@ -457,7 +457,7 @@ namespace ts.server {
}
getCompilerOptionsDiagnostics(): Diagnostic[] {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getRenameInfo(fileName: string, position: number, findInStrings?: boolean, findInComments?: boolean): RenameInfo {
@@ -562,11 +562,11 @@ namespace ts.server {
}
getNameOrDottedNameSpan(_fileName: string, _startPos: number, _endPos: number): TextSpan {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getBreakpointStatementAtPosition(_fileName: string, _position: number): TextSpan {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems {
@@ -656,19 +656,19 @@ namespace ts.server {
}
getOutliningSpans(_fileName: string): OutliningSpan[] {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getTodoComments(_fileName: string, _descriptors: TodoCommentDescriptor[]): TodoComment[] {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getDocCommentTemplateAtPosition(_fileName: string, _position: number): TextInsertion {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
isValidBraceCompletionAtPosition(_fileName: string, _position: number, _openingBrace: number): boolean {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[]): CodeAction[] {
@@ -735,23 +735,23 @@ namespace ts.server {
}
getIndentationAtPosition(_fileName: string, _position: number, _options: EditorOptions): number {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getSyntacticClassifications(_fileName: string, _span: TextSpan): ClassifiedSpan[] {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getSemanticClassifications(_fileName: string, _span: TextSpan): ClassifiedSpan[] {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getEncodedSyntacticClassifications(_fileName: string, _span: TextSpan): Classifications {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getEncodedSemanticClassifications(_fileName: string, _span: TextSpan): Classifications {
throw new Error("Not Implemented Yet.");
return notImplemented();
}
getProgram(): Program {
+3 -3
View File
@@ -288,13 +288,13 @@ namespace ts.server {
}
switch (response.kind) {
case "set":
this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.typings);
project.updateGraph();
this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.unresolvedImports, response.typings);
break;
case "invalidate":
this.typingsCache.invalidateCachedTypingsForProject(project);
this.typingsCache.deleteTypingsForProject(response.projectName);
break;
}
project.updateGraph();
}
setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions): void {
+43 -6
View File
@@ -9,6 +9,8 @@ namespace ts.server {
private readonly resolvedTypeReferenceDirectives: ts.FileMap<Map<string, ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>;
private readonly getCanonicalFileName: (fileName: string) => string;
private filesWithChangedSetOfUnresolvedImports: Path[];
private readonly resolveModuleName: typeof resolveModuleName;
readonly trace: (s: string) => void;
@@ -52,12 +54,23 @@ namespace ts.server {
};
}
public startRecordingFilesWithChangedResolutions() {
this.filesWithChangedSetOfUnresolvedImports = [];
}
public finishRecordingFilesWithChangedResolutions() {
const collected = this.filesWithChangedSetOfUnresolvedImports;
this.filesWithChangedSetOfUnresolvedImports = undefined;
return collected;
}
private resolveNamesWithLocalCache<T extends { failedLookupLocations: string[] }, R extends { resolvedFileName?: string }>(
names: string[],
containingFile: string,
cache: ts.FileMap<Map<string, T>>,
loader: (name: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost) => T,
getResult: (s: T) => R): R[] {
getResult: (s: T) => R,
logChanges: boolean): R[] {
const path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName);
const currentResolutionsInFile = cache.get(path);
@@ -79,6 +92,11 @@ namespace ts.server {
else {
newResolutions.set(name, resolution = loader(name, containingFile, compilerOptions, this));
}
if (logChanges && this.filesWithChangedSetOfUnresolvedImports && !resolutionIsEqualTo(existingResolution, resolution)) {
this.filesWithChangedSetOfUnresolvedImports.push(path);
// reset log changes to avoid recording the same file multiple times
logChanges = false;
}
}
ts.Debug.assert(resolution !== undefined);
@@ -90,6 +108,24 @@ namespace ts.server {
cache.set(path, newResolutions);
return resolvedModules;
function resolutionIsEqualTo(oldResolution: T, newResolution: T): boolean {
if (oldResolution === newResolution) {
return true;
}
if (!oldResolution || !newResolution) {
return false;
}
const oldResult = getResult(oldResolution);
const newResult = getResult(newResolution);
if (oldResult === newResult) {
return true;
}
if (!oldResult || !newResult) {
return false;
}
return oldResult.resolvedFileName === newResult.resolvedFileName;
}
function moduleResolutionIsValid(resolution: T): boolean {
if (!resolution) {
return false;
@@ -126,11 +162,11 @@ namespace ts.server {
}
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[] {
return this.resolveNamesWithLocalCache(typeDirectiveNames, containingFile, this.resolvedTypeReferenceDirectives, resolveTypeReferenceDirective, m => m.resolvedTypeReferenceDirective);
return this.resolveNamesWithLocalCache(typeDirectiveNames, containingFile, this.resolvedTypeReferenceDirectives, resolveTypeReferenceDirective, m => m.resolvedTypeReferenceDirective, /*logChanges*/ false);
}
resolveModuleNames(moduleNames: string[], containingFile: string): ResolvedModule[] {
return this.resolveNamesWithLocalCache(moduleNames, containingFile, this.resolvedModuleNames, this.resolveModuleName, m => m.resolvedModule);
return this.resolveNamesWithLocalCache(moduleNames, containingFile, this.resolvedModuleNames, this.resolveModuleName, m => m.resolvedModule, /*logChanges*/ true);
}
getDefaultLibFileName() {
@@ -197,10 +233,11 @@ namespace ts.server {
}
setCompilationSettings(opt: ts.CompilerOptions) {
if (changesAffectModuleResolution(this.compilationSettings, opt)) {
this.resolvedModuleNames.clear();
this.resolvedTypeReferenceDirectives.clear();
}
this.compilationSettings = opt;
// conservatively assume that changing compiler options might affect module resolution strategy
this.resolvedModuleNames.clear();
this.resolvedTypeReferenceDirectives.clear();
}
}
}
+103 -3
View File
@@ -62,12 +62,43 @@ namespace ts.server {
projectErrors: Diagnostic[];
}
export class UnresolvedImportsMap {
readonly perFileMap = createFileMap<ReadonlyArray<string>>();
private version = 0;
public clear() {
this.perFileMap.clear();
this.version = 0;
}
public getVersion() {
return this.version;
}
public remove(path: Path) {
this.perFileMap.remove(path);
this.version++;
}
public get(path: Path) {
return this.perFileMap.get(path);
}
public set(path: Path, value: ReadonlyArray<string>) {
this.perFileMap.set(path, value);
this.version++;
}
}
export abstract class Project {
private rootFiles: ScriptInfo[] = [];
private rootFilesMap: FileMap<ScriptInfo> = createFileMap<ScriptInfo>();
private lsHost: ServerLanguageServiceHost;
private program: ts.Program;
private cachedUnresolvedImportsPerFile = new UnresolvedImportsMap();
private lastCachedUnresolvedImportsList: SortedReadonlyArray<string>;
private languageService: LanguageService;
builder: Builder;
/**
@@ -91,7 +122,7 @@ namespace ts.server {
*/
private projectStateVersion = 0;
private typingFiles: TypingsArray;
private typingFiles: SortedReadonlyArray<string>;
protected projectErrors: Diagnostic[];
@@ -107,6 +138,10 @@ namespace ts.server {
return hasOneOrMoreJsAndNoTsFiles(this);
}
public getCachedUnresolvedImportsPerFile_TestOnly() {
return this.cachedUnresolvedImportsPerFile;
}
constructor(
readonly projectKind: ProjectKind,
readonly projectService: ProjectService,
@@ -326,6 +361,7 @@ namespace ts.server {
removeFile(info: ScriptInfo, detachFromProject = true) {
this.removeRootFileIfNecessary(info);
this.lsHost.notifyFileRemoved(info);
this.cachedUnresolvedImportsPerFile.remove(info.path);
if (detachFromProject) {
info.detachFromProject(this);
@@ -338,6 +374,38 @@ namespace ts.server {
this.projectStateVersion++;
}
private extractUnresolvedImportsFromSourceFile(file: SourceFile, result: string[]) {
const cached = this.cachedUnresolvedImportsPerFile.get(file.path);
if (cached) {
// found cached result - use it and return
for (const f of cached) {
result.push(f);
}
return;
}
let unresolvedImports: string[];
if (file.resolvedModules) {
file.resolvedModules.forEach((resolvedModule, name) => {
// pick unresolved non-relative names
if (!resolvedModule && !isExternalModuleNameRelative(name)) {
// for non-scoped names extract part up-to the first slash
// for scoped names - extract up to the second slash
let trimmed = name.trim();
let i = trimmed.indexOf("/");
if (i !== -1 && trimmed.charCodeAt(0) === CharacterCodes.at) {
i = trimmed.indexOf("/", i + 1);
}
if (i !== -1) {
trimmed = trimmed.substr(0, i);
}
(unresolvedImports || (unresolvedImports = [])).push(trimmed);
result.push(trimmed);
}
});
}
this.cachedUnresolvedImportsPerFile.set(file.path, unresolvedImports || emptyArray);
}
/**
* Updates set of files that contribute to this project
* @returns: true if set of files in the project stays the same and false - otherwise.
@@ -346,8 +414,35 @@ namespace ts.server {
if (!this.languageServiceEnabled) {
return true;
}
this.lsHost.startRecordingFilesWithChangedResolutions();
let hasChanges = this.updateGraphWorker();
const cachedTypings = this.projectService.typingsCache.getTypingsForProject(this, hasChanges);
const changedFiles: ReadonlyArray<Path> = this.lsHost.finishRecordingFilesWithChangedResolutions() || emptyArray;
for (const file of changedFiles) {
// delete cached information for changed files
this.cachedUnresolvedImportsPerFile.remove(file);
}
// 1. no changes in structure, no changes in unresolved imports - do nothing
// 2. no changes in structure, unresolved imports were changed - collect unresolved imports for all files
// (can reuse cached imports for files that were not changed)
// 3. new files were added/removed, but compilation settings stays the same - collect unresolved imports for all new/modified files
// (can reuse cached imports for files that were not changed)
// 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch
let unresolvedImports: SortedReadonlyArray<string>;
if (hasChanges || changedFiles.length) {
const result: string[] = [];
for (const sourceFile of this.program.getSourceFiles()) {
this.extractUnresolvedImportsFromSourceFile(sourceFile, result);
}
this.lastCachedUnresolvedImportsList = toSortedReadonlyArray(result);
}
unresolvedImports = this.lastCachedUnresolvedImportsList;
const cachedTypings = this.projectService.typingsCache.getTypingsForProject(this, unresolvedImports, hasChanges);
if (this.setTypings(cachedTypings)) {
hasChanges = this.updateGraphWorker() || hasChanges;
}
@@ -357,7 +452,7 @@ namespace ts.server {
return !hasChanges;
}
private setTypings(typings: TypingsArray): boolean {
private setTypings(typings: SortedReadonlyArray<string>): boolean {
if (arrayIsEqualTo(this.typingFiles, typings)) {
return false;
}
@@ -430,6 +525,11 @@ namespace ts.server {
compilerOptions.allowJs = true;
}
compilerOptions.allowNonTsExtensions = true;
if (changesAffectModuleResolution(this.compilerOptions, compilerOptions)) {
// reset cached unresolved imports if changes in compiler options affected module resolution
this.cachedUnresolvedImportsPerFile.clear();
this.lastCachedUnresolvedImportsList = undefined;
}
this.compilerOptions = compilerOptions;
this.lsHost.setCompilationSettings(compilerOptions);
+52 -11
View File
@@ -14,21 +14,33 @@ namespace ts.server {
} = require("child_process");
const os: {
homedir(): string
homedir?(): string;
tmpdir(): string;
} = require("os");
function getGlobalTypingsCacheLocation() {
let basePath: string;
switch (process.platform) {
case "win32":
basePath = process.env.LOCALAPPDATA || process.env.APPDATA || os.homedir();
basePath = process.env.LOCALAPPDATA ||
process.env.APPDATA ||
(os.homedir && os.homedir()) ||
process.env.USERPROFILE ||
(process.env.HOMEDRIVE && process.env.HOMEPATH && normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) ||
os.tmpdir();
break;
case "linux":
basePath = os.homedir();
basePath = (os.homedir && os.homedir()) ||
process.env.HOME ||
((process.env.LOGNAME || process.env.USER) && `/home/${process.env.LOGNAME || process.env.USER}`) ||
os.tmpdir();
break;
case "darwin":
basePath = combinePaths(os.homedir(), "Library/Application Support/");
const homeDir = (os.homedir && os.homedir()) ||
process.env.HOME ||
((process.env.LOGNAME || process.env.USER) && `/Users/${process.env.LOGNAME || process.env.USER}`) ||
os.tmpdir();
basePath = combinePaths(homeDir, "Library/Application Support/");
break;
}
@@ -40,6 +52,7 @@ namespace ts.server {
send(message: any, sendHandle?: any): void;
on(message: "message", f: (m: any) => void): void;
kill(): void;
pid: number;
}
interface NodeSocket {
@@ -179,21 +192,40 @@ namespace ts.server {
class NodeTypingsInstaller implements ITypingsInstaller {
private installer: NodeChildProcess;
private installerPidReported = false;
private socket: NodeSocket;
private projectService: ProjectService;
private throttledOperations: ThrottledOperations;
constructor(
private readonly logger: server.Logger,
host: ServerHost,
eventPort: number,
readonly globalTypingsCacheLocation: string,
private newLine: string) {
this.throttledOperations = new ThrottledOperations(host);
if (eventPort) {
const s = net.connect({ port: eventPort }, () => {
this.socket = s;
this.reportInstallerProcessId();
});
}
}
private reportInstallerProcessId() {
if (this.installerPidReported) {
return;
}
if (this.socket && this.installer) {
this.sendEvent(0, "typingsInstallerPid", { pid: this.installer.pid });
this.installerPidReported = true;
}
}
private sendEvent(seq: number, event: string, body: any): void {
this.socket.write(formatMessage({ seq, type: "event", event, body }, this.logger, Buffer.byteLength, this.newLine), "utf8");
}
attach(projectService: ProjectService) {
this.projectService = projectService;
if (this.logger.hasLevel(LogLevel.requestTime)) {
@@ -222,6 +254,8 @@ namespace ts.server {
this.installer = childProcess.fork(combinePaths(__dirname, "typingsInstaller.js"), args, { execArgv });
this.installer.on("message", m => this.handleMessage(m));
this.reportInstallerProcessId();
process.on("exit", () => {
this.installer.kill();
});
@@ -231,12 +265,19 @@ namespace ts.server {
this.installer.send({ projectName: p.getProjectName(), kind: "closeProject" });
}
enqueueInstallTypingsRequest(project: Project, typingOptions: TypingOptions): void {
const request = createInstallTypingsRequest(project, typingOptions);
enqueueInstallTypingsRequest(project: Project, typingOptions: TypingOptions, unresolvedImports: SortedReadonlyArray<string>): void {
const request = createInstallTypingsRequest(project, typingOptions, unresolvedImports);
if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Sending request: ${JSON.stringify(request)}`);
if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Scheduling throttled operation: ${JSON.stringify(request)}`);
}
}
this.installer.send(request);
this.throttledOperations.schedule(project.getProjectName(), /*ms*/ 250, () => {
if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Sending request: ${JSON.stringify(request)}`);
}
this.installer.send(request);
});
}
private handleMessage(response: SetTypings | InvalidateCachedTypings) {
@@ -245,7 +286,7 @@ namespace ts.server {
}
this.projectService.updateTypingsForProject(response);
if (response.kind == "set" && this.socket) {
this.socket.write(formatMessage({ seq: 0, type: "event", message: response }, this.logger, Buffer.byteLength, this.newLine), "utf8");
this.sendEvent(0, "setTypings", response);
}
}
}
@@ -266,7 +307,7 @@ namespace ts.server {
useSingleInferredProject,
disableAutomaticTypingAcquisition
? nullTypingsInstaller
: new NodeTypingsInstaller(logger, installerEventPort, globalTypingsCacheLocation, host.newLine),
: new NodeTypingsInstaller(logger, host, installerEventPort, globalTypingsCacheLocation, host.newLine),
Buffer.byteLength,
process.hrtime,
logger,
+12 -4
View File
@@ -18,6 +18,10 @@ declare namespace ts.server {
trace?(s: string): void;
}
export interface SortedReadonlyArray<T> extends ReadonlyArray<T> {
" __sortedReadonlyArrayBrand": any;
}
export interface TypingInstallerRequest {
readonly projectName: string;
readonly kind: "discover" | "closeProject";
@@ -26,8 +30,9 @@ declare namespace ts.server {
export interface DiscoverTypings extends TypingInstallerRequest {
readonly fileNames: string[];
readonly projectRootPath: ts.Path;
readonly typingOptions: ts.TypingOptions;
readonly compilerOptions: ts.CompilerOptions;
readonly typingOptions: ts.TypingOptions;
readonly unresolvedImports: SortedReadonlyArray<string>;
readonly cachePath?: string;
readonly kind: "discover";
}
@@ -36,20 +41,23 @@ declare namespace ts.server {
readonly kind: "closeProject";
}
export type SetRequest = "set";
export type InvalidateRequest = "invalidate";
export interface TypingInstallerResponse {
readonly projectName: string;
readonly kind: "set" | "invalidate";
readonly kind: SetRequest | InvalidateRequest;
}
export interface SetTypings extends TypingInstallerResponse {
readonly typingOptions: ts.TypingOptions;
readonly compilerOptions: ts.CompilerOptions;
readonly typings: string[];
readonly kind: "set";
readonly unresolvedImports: SortedReadonlyArray<string>;
readonly kind: SetRequest;
}
export interface InvalidateCachedTypings extends TypingInstallerResponse {
readonly kind: "invalidate";
readonly kind: InvalidateRequest;
}
export interface InstallTypingHost extends JsTyping.TypingResolutionHost {
+28 -26
View File
@@ -2,23 +2,25 @@
namespace ts.server {
export interface ITypingsInstaller {
enqueueInstallTypingsRequest(p: Project, typingOptions: TypingOptions): void;
enqueueInstallTypingsRequest(p: Project, typingOptions: TypingOptions, unresolvedImports: SortedReadonlyArray<string>): void;
attach(projectService: ProjectService): void;
onProjectClosed(p: Project): void;
readonly globalTypingsCacheLocation: string;
}
export const nullTypingsInstaller: ITypingsInstaller = {
enqueueInstallTypingsRequest: () => {},
attach: () => {},
onProjectClosed: () => {},
enqueueInstallTypingsRequest: noop,
attach: noop,
onProjectClosed: noop,
globalTypingsCacheLocation: undefined
};
class TypingsCacheEntry {
readonly typingOptions: TypingOptions;
readonly compilerOptions: CompilerOptions;
readonly typings: TypingsArray;
readonly typings: SortedReadonlyArray<string>;
readonly unresolvedImports: SortedReadonlyArray<string>;
/* mainly useful for debugging */
poisoned: boolean;
}
@@ -62,13 +64,11 @@ namespace ts.server {
return opt1.allowJs != opt2.allowJs;
}
export interface TypingsArray extends ReadonlyArray<string> {
" __typingsArrayBrand": any;
}
function toTypingsArray(arr: string[]): TypingsArray {
arr.sort();
return <any>arr;
function unresolvedImportsChanged(imports1: SortedReadonlyArray<string>, imports2: SortedReadonlyArray<string>): boolean {
if (imports1 === imports2) {
return false;
}
return !arrayIsEqualTo(imports1, imports2);
}
export class TypingsCache {
@@ -77,7 +77,7 @@ namespace ts.server {
constructor(private readonly installer: ITypingsInstaller) {
}
getTypingsForProject(project: Project, forceRefresh: boolean): TypingsArray {
getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray<string>, forceRefresh: boolean): SortedReadonlyArray<string> {
const typingOptions = project.getTypingOptions();
if (!typingOptions || !typingOptions.enableAutoDiscovery) {
@@ -85,39 +85,41 @@ namespace ts.server {
}
const entry = this.perProjectCache.get(project.getProjectName());
const result: TypingsArray = entry ? entry.typings : <any>emptyArray;
if (forceRefresh || !entry || typingOptionsChanged(typingOptions, entry.typingOptions) || compilerOptionsChanged(project.getCompilerOptions(), entry.compilerOptions)) {
const result: SortedReadonlyArray<string> = entry ? entry.typings : <any>emptyArray;
if (forceRefresh ||
!entry ||
typingOptionsChanged(typingOptions, entry.typingOptions) ||
compilerOptionsChanged(project.getCompilerOptions(), entry.compilerOptions) ||
unresolvedImportsChanged(unresolvedImports, entry.unresolvedImports)) {
// Note: entry is now poisoned since it does not really contain typings for a given combination of compiler options\typings options.
// instead it acts as a placeholder to prevent issuing multiple requests
this.perProjectCache.set(project.getProjectName(), {
compilerOptions: project.getCompilerOptions(),
typingOptions,
typings: result,
unresolvedImports,
poisoned: true
});
// something has been changed, issue a request to update typings
this.installer.enqueueInstallTypingsRequest(project, typingOptions);
this.installer.enqueueInstallTypingsRequest(project, typingOptions, unresolvedImports);
}
return result;
}
invalidateCachedTypingsForProject(project: Project) {
const typingOptions = project.getTypingOptions();
if (!typingOptions.enableAutoDiscovery) {
return;
}
this.installer.enqueueInstallTypingsRequest(project, typingOptions);
}
updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typingOptions: TypingOptions, newTypings: string[]) {
updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typingOptions: TypingOptions, unresolvedImports: SortedReadonlyArray<string>, newTypings: string[]) {
this.perProjectCache.set(projectName, {
compilerOptions,
typingOptions,
typings: toTypingsArray(newTypings),
typings: toSortedReadonlyArray(newTypings),
unresolvedImports,
poisoned: false
});
}
deleteTypingsForProject(projectName: string) {
this.perProjectCache.delete(projectName);
}
onProjectClosed(project: Project) {
this.perProjectCache.delete(project.getProjectName());
this.installer.onProjectClosed(project);
@@ -15,7 +15,7 @@ namespace ts.server.typingsInstaller {
const nullLog: Log = {
isEnabled: () => false,
writeLine: () => {}
writeLine: noop
};
function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost): string {
@@ -26,6 +26,7 @@ namespace ts.server.typingsInstaller {
export enum PackageNameValidationResult {
Ok,
ScopedPackagesNotSupported,
EmptyName,
NameTooLong,
NameStartsWithDot,
NameStartsWithUnderscore,
@@ -38,7 +39,9 @@ namespace ts.server.typingsInstaller {
* Validates package name using rules defined at https://docs.npmjs.com/files/package.json
*/
export function validatePackageName(packageName: string): PackageNameValidationResult {
Debug.assert(!!packageName, "Package name is not specified");
if (!packageName) {
return PackageNameValidationResult.EmptyName;
}
if (packageName.length > MaxPackageNameLength) {
return PackageNameValidationResult.NameTooLong;
}
@@ -145,7 +148,8 @@ namespace ts.server.typingsInstaller {
req.projectRootPath,
this.safeListPath,
this.packageNameToTypingLocation,
req.typingOptions);
req.typingOptions,
req.unresolvedImports);
if (this.log.isEnabled()) {
this.log.writeLine(`Finished typings discovery: ${JSON.stringify(discoverTypingsResult)}`);
@@ -238,6 +242,9 @@ namespace ts.server.typingsInstaller {
this.missingTypingsSet.add(typing);
if (this.log.isEnabled()) {
switch (validationResult) {
case PackageNameValidationResult.EmptyName:
this.log.writeLine(`Package name '${typing}' cannot be empty`);
break;
case PackageNameValidationResult.NameTooLong:
this.log.writeLine(`Package name '${typing}' should be less than ${MaxPackageNameLength} characters`);
break;
@@ -381,8 +388,10 @@ namespace ts.server.typingsInstaller {
if (this.log.isEnabled()) {
this.log.writeLine(`Got FS notification for ${f}, handler is already invoked '${isInvoked}'`);
}
this.sendResponse({ projectName: projectName, kind: "invalidate" });
isInvoked = true;
if (!isInvoked) {
this.sendResponse({ projectName: projectName, kind: "invalidate" });
isInvoked = true;
}
});
watchers.push(w);
}
@@ -395,6 +404,7 @@ namespace ts.server.typingsInstaller {
typingOptions: request.typingOptions,
compilerOptions: request.compilerOptions,
typings,
unresolvedImports: request.unresolvedImports,
kind: "set"
};
}
+12 -2
View File
@@ -45,12 +45,13 @@ namespace ts.server {
}
}
export function createInstallTypingsRequest(project: Project, typingOptions: TypingOptions, cachePath?: string): DiscoverTypings {
export function createInstallTypingsRequest(project: Project, typingOptions: TypingOptions, unresolvedImports: SortedReadonlyArray<string>, cachePath?: string): DiscoverTypings {
return {
projectName: project.getProjectName(),
fileNames: project.getFileNames(),
compilerOptions: project.getCompilerOptions(),
typingOptions,
unresolvedImports,
projectRootPath: getProjectRootPath(project),
cachePath,
kind: "discover"
@@ -183,11 +184,15 @@ namespace ts.server {
export interface ServerLanguageServiceHost {
setCompilationSettings(options: CompilerOptions): void;
notifyFileRemoved(info: ScriptInfo): void;
startRecordingFilesWithChangedResolutions(): void;
finishRecordingFilesWithChangedResolutions(): Path[];
}
export const nullLanguageServiceHost: ServerLanguageServiceHost = {
setCompilationSettings: () => undefined,
notifyFileRemoved: () => undefined
notifyFileRemoved: () => undefined,
startRecordingFilesWithChangedResolutions: () => undefined,
finishRecordingFilesWithChangedResolutions: () => undefined
};
export interface ProjectOptions {
@@ -214,6 +219,11 @@ namespace ts.server {
return `/dev/null/inferredProject${counter}*`;
}
export function toSortedReadonlyArray(arr: string[]): SortedReadonlyArray<string> {
arr.sort();
return <any>arr;
}
export class ThrottledOperations {
private pendingTimeouts = new StringMap<any>();
constructor(private readonly host: ServerHost) {
+3 -1
View File
@@ -1589,7 +1589,9 @@ namespace ts.Completions {
if (m.kind !== SyntaxKind.PropertyAssignment &&
m.kind !== SyntaxKind.ShorthandPropertyAssignment &&
m.kind !== SyntaxKind.BindingElement &&
m.kind !== SyntaxKind.MethodDeclaration) {
m.kind !== SyntaxKind.MethodDeclaration &&
m.kind !== SyntaxKind.GetAccessor &&
m.kind !== SyntaxKind.SetAccessor) {
continue;
}
+25 -2
View File
@@ -31,6 +31,17 @@ namespace ts.JsTyping {
const EmptySafeList = new StringMap<string>();
/* @internal */
export const nodeCoreModuleList: ReadonlyArray<string> = [
"buffer", "querystring", "events", "http", "cluster",
"zlib", "os", "https", "punycode", "repl", "readline",
"vm", "child_process", "url", "dns", "net",
"dgram", "fs", "path", "string_decoder", "tls",
"crypto", "stream", "util", "assert", "tty", "domain",
"constants", "process", "v8", "timers", "console"];
const nodeCoreModules = arrayToMap(<string[]>nodeCoreModuleList, x => x);
/**
* @param host is the object providing I/O related operations.
* @param fileNames are the file names that belong to the same project
@@ -46,7 +57,8 @@ namespace ts.JsTyping {
projectRootPath: Path,
safeListPath: Path,
packageNameToTypingLocation: Map<string, string>,
typingOptions: TypingOptions):
typingOptions: TypingOptions,
unresolvedImports: ReadonlyArray<string>):
{ cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } {
// A typing name to typing file path mapping
@@ -92,6 +104,15 @@ namespace ts.JsTyping {
}
getTypingNamesFromSourceFileNames(fileNames);
// add typings for unresolved imports
if (unresolvedImports) {
for (const moduleId of unresolvedImports) {
const typingName = nodeCoreModules.has(moduleId) ? "node" : moduleId;
if (!inferredTypings.has(typingName)) {
inferredTypings.set(typingName, undefined);
}
}
}
// Add the cached typing locations for inferred typings that are already installed
packageNameToTypingLocation.forEach((typingLocation, name) => {
if (inferredTypings.has(name) && inferredTypings.get(name) === undefined) {
@@ -136,10 +157,12 @@ namespace ts.JsTyping {
* Get the typing info from common package manager json files like package.json or bower.json
*/
function getTypingNamesFromJson(jsonPath: string, filesToWatch: string[]) {
if (host.fileExists(jsonPath)) {
filesToWatch.push(jsonPath);
}
const result = readConfigFile(jsonPath, (path: string) => host.readFile(path));
if (result.config) {
const jsonConfig: PackageJson = result.config;
filesToWatch.push(jsonPath);
if (jsonConfig.dependencies) {
mergeTypings(getOwnKeys(jsonConfig.dependencies));
}
+19 -1
View File
@@ -403,6 +403,9 @@ namespace ts.NavigationBar {
if (getModifierFlags(node) & ModifierFlags.Default) {
return "default";
}
// We may get a string with newlines or other whitespace in the case of an object dereference
// (eg: "app\n.onactivated"), so we should remove the whitespace for readabiltiy in the
// navigation bar.
return getFunctionOrClassName(<ArrowFunction | FunctionExpression | ClassExpression>node);
case SyntaxKind.Constructor:
return "constructor";
@@ -602,7 +605,7 @@ namespace ts.NavigationBar {
// See if it is of the form "<expr> = function(){...}". If so, use the text from the left-hand side.
else if (node.parent.kind === SyntaxKind.BinaryExpression &&
(node.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
return nodeText((node.parent as BinaryExpression).left);
return nodeText((node.parent as BinaryExpression).left).replace(whiteSpaceRegex, "");
}
// See if it is a property assignment, and if so use the property name
else if (node.parent.kind === SyntaxKind.PropertyAssignment && (node.parent as PropertyAssignment).name) {
@@ -620,4 +623,19 @@ namespace ts.NavigationBar {
function isFunctionOrClassExpression(node: Node): boolean {
return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction || node.kind === SyntaxKind.ClassExpression;
}
/**
* Matches all whitespace characters in a string. Eg:
*
* "app.
*
* onactivated"
*
* matches because of the newline, whereas
*
* "app.onactivated"
*
* does not match.
*/
const whiteSpaceRegex = /\s+/g;
}
+3 -2
View File
@@ -347,6 +347,7 @@ namespace ts {
class TypeObject implements Type {
checker: TypeChecker;
flags: TypeFlags;
objectFlags?: ObjectFlags;
id: number;
symbol: Symbol;
constructor(checker: TypeChecker, flags: TypeFlags) {
@@ -381,7 +382,7 @@ namespace ts {
return this.checker.getIndexTypeOfType(this, IndexKind.Number);
}
getBaseTypes(): ObjectType[] {
return this.flags & (TypeFlags.Class | TypeFlags.Interface)
return this.flags & TypeFlags.Object && this.objectFlags & (ObjectFlags.Class | ObjectFlags.Interface)
? this.checker.getBaseTypes(<InterfaceType><Type>this)
: undefined;
}
@@ -1051,7 +1052,7 @@ namespace ts {
useCaseSensitiveFileNames: () => useCaseSensitivefileNames,
getNewLine: () => getNewLineOrDefaultFromHost(host),
getDefaultLibFileName: (options) => host.getDefaultLibFileName(options),
writeFile: () => { },
writeFile: noop,
getCurrentDirectory: () => currentDirectory,
fileExists: (fileName): boolean => {
// stub missing host functionality
+2 -1
View File
@@ -1168,7 +1168,8 @@ namespace ts {
toPath(info.projectRootPath, info.projectRootPath, getCanonicalFileName),
toPath(info.safeListPath, info.safeListPath, getCanonicalFileName),
mapOfMapLike(info.packageNameToTypingLocation),
info.typingOptions);
info.typingOptions,
info.unresolvedImports);
});
}
}
+1 -1
View File
@@ -173,7 +173,7 @@ namespace ts.SymbolDisplay {
displayParts.push(keywordPart(SyntaxKind.NewKeyword));
displayParts.push(spacePart());
}
if (!(type.flags & TypeFlags.Anonymous) && type.symbol) {
if (!(type.flags & TypeFlags.Object && (<ObjectType>type).objectFlags & ObjectFlags.Anonymous) && type.symbol) {
addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments));
}
addSignatureDisplayParts(signature, allSignatures, TypeFormatFlags.WriteArrowStyleSignature);
+2 -2
View File
@@ -1142,8 +1142,8 @@ namespace ts {
increaseIndent: () => { indent++; },
decreaseIndent: () => { indent--; },
clear: resetWriter,
trackSymbol: () => { },
reportInaccessibleThisError: () => { }
trackSymbol: noop,
reportInaccessibleThisError: noop
};
function writeIndent() {
@@ -18,6 +18,12 @@
"end": 16,
"text": "typedef"
},
"fullName": {
"kind": "Identifier",
"pos": 17,
"end": 23,
"text": "People"
},
"name": {
"kind": "Identifier",
"pos": 17,
@@ -0,0 +1,21 @@
//// [tests/cases/compiler/ambientRequireFunction.ts] ////
//// [node.d.ts]
declare function require(moduleName: string): any;
declare module "fs" {
export function readFileSync(s: string): string;
}
//// [app.js]
/// <reference path="node.d.ts"/>
const fs = require("fs");
const text = fs.readFileSync("/a/b/c");
//// [app.js]
/// <reference path="node.d.ts"/>
var fs = require("fs");
var text = fs.readFileSync("/a/b/c");
@@ -0,0 +1,27 @@
=== tests/cases/compiler/app.js ===
/// <reference path="node.d.ts"/>
const fs = require("fs");
>fs : Symbol(fs, Decl(app.js, 2, 5))
>require : Symbol(require, Decl(node.d.ts, 0, 0))
>"fs" : Symbol("fs", Decl(node.d.ts, 2, 50))
const text = fs.readFileSync("/a/b/c");
>text : Symbol(text, Decl(app.js, 3, 5))
>fs.readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
>fs : Symbol(fs, Decl(app.js, 2, 5))
>readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
=== tests/cases/compiler/node.d.ts ===
declare function require(moduleName: string): any;
>require : Symbol(require, Decl(node.d.ts, 0, 0))
>moduleName : Symbol(moduleName, Decl(node.d.ts, 2, 25))
declare module "fs" {
export function readFileSync(s: string): string;
>readFileSync : Symbol(readFileSync, Decl(node.d.ts, 4, 21))
>s : Symbol(s, Decl(node.d.ts, 5, 33))
}
@@ -0,0 +1,30 @@
=== tests/cases/compiler/app.js ===
/// <reference path="node.d.ts"/>
const fs = require("fs");
>fs : typeof "fs"
>require("fs") : typeof "fs"
>require : (moduleName: string) => any
>"fs" : "fs"
const text = fs.readFileSync("/a/b/c");
>text : string
>fs.readFileSync("/a/b/c") : string
>fs.readFileSync : (s: string) => string
>fs : typeof "fs"
>readFileSync : (s: string) => string
>"/a/b/c" : "/a/b/c"
=== tests/cases/compiler/node.d.ts ===
declare function require(moduleName: string): any;
>require : (moduleName: string) => any
>moduleName : string
declare module "fs" {
export function readFileSync(s: string): string;
>readFileSync : (s: string) => string
>s : string
}
@@ -1,10 +0,0 @@
tests/cases/compiler/catchClauseWithBindingPattern1.ts(3,8): error TS1195: Catch clause variable name must be an identifier.
==== tests/cases/compiler/catchClauseWithBindingPattern1.ts (1 errors) ====
try {
}
catch ({a}) {
~
!!! error TS1195: Catch clause variable name must be an identifier.
}
@@ -1,11 +0,0 @@
//// [catchClauseWithBindingPattern1.ts]
try {
}
catch ({a}) {
}
//// [catchClauseWithBindingPattern1.js]
try {
}
catch (a = (void 0).a) {
}
@@ -0,0 +1,58 @@
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNumericLiteral.ts(5,1): error TS2365: Operator '>' cannot be applied to types 'BrandedNum' and '0'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNumericLiteral.ts(10,1): error TS2365: Operator '<' cannot be applied to types 'BrandedNum' and '0'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNumericLiteral.ts(15,1): error TS2365: Operator '>=' cannot be applied to types 'BrandedNum' and '0'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNumericLiteral.ts(20,1): error TS2365: Operator '<=' cannot be applied to types 'BrandedNum' and '0'.
==== tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNumericLiteral.ts (4 errors) ====
type BrandedNum = number & { __numberBrand: any };
var x : BrandedNum;
// operator >
x > 0;
~~~~~
!!! error TS2365: Operator '>' cannot be applied to types 'BrandedNum' and '0'.
x > <number>0;
x > <BrandedNum>0;
// operator <
x < 0;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'BrandedNum' and '0'.
x < <number>0;
x < <BrandedNum>0;
// operator >=
x >= 0;
~~~~~~
!!! error TS2365: Operator '>=' cannot be applied to types 'BrandedNum' and '0'.
x >= <number>0;
x >= <BrandedNum>0;
// operator <=
x <= 0;
~~~~~~
!!! error TS2365: Operator '<=' cannot be applied to types 'BrandedNum' and '0'.
x <= <number>0;
x <= <BrandedNum>0;
// operator ==
x == 0;
x == <number>0;
x == <BrandedNum>0;
// operator !=
x != 0;
x != <number>0;
x != <BrandedNum>0;
// operator ===
x === 0;
x === <number>0;
x === <BrandedNum>0;
// operator !==
x !== 0;
x !== <number>0;
x !== <BrandedNum>0;
@@ -0,0 +1,79 @@
//// [comparisonOperatorWithNumericLiteral.ts]
type BrandedNum = number & { __numberBrand: any };
var x : BrandedNum;
// operator >
x > 0;
x > <number>0;
x > <BrandedNum>0;
// operator <
x < 0;
x < <number>0;
x < <BrandedNum>0;
// operator >=
x >= 0;
x >= <number>0;
x >= <BrandedNum>0;
// operator <=
x <= 0;
x <= <number>0;
x <= <BrandedNum>0;
// operator ==
x == 0;
x == <number>0;
x == <BrandedNum>0;
// operator !=
x != 0;
x != <number>0;
x != <BrandedNum>0;
// operator ===
x === 0;
x === <number>0;
x === <BrandedNum>0;
// operator !==
x !== 0;
x !== <number>0;
x !== <BrandedNum>0;
//// [comparisonOperatorWithNumericLiteral.js]
var x;
// operator >
x > 0;
x > 0;
x > 0;
// operator <
x < 0;
x < 0;
x < 0;
// operator >=
x >= 0;
x >= 0;
x >= 0;
// operator <=
x <= 0;
x <= 0;
x <= 0;
// operator ==
x == 0;
x == 0;
x == 0;
// operator !=
x != 0;
x != 0;
x != 0;
// operator ===
x === 0;
x === 0;
x === 0;
// operator !==
x !== 0;
x !== 0;
x !== 0;
@@ -0,0 +1,59 @@
//// [destructuringCatch.ts]
try {
throw [0, 1];
}
catch ([a, b]) {
a + b;
}
try {
throw { a: 0, b: 1 };
}
catch ({a, b}) {
a + b;
}
try {
throw [{ x: [0], z: 1 }];
}
catch ([{x: [y], z}]) {
y + z;
}
// Test of comment ranges. A fix to GH#11755 should update this.
try {
}
catch (/*Test comment ranges*/[/*a*/a]) {
}
//// [destructuringCatch.js]
try {
throw [0, 1];
}
catch (_a) {
var a = _a[0], b = _a[1];
a + b;
}
try {
throw { a: 0, b: 1 };
}
catch (_b) {
var a = _b.a, b = _b.b;
a + b;
}
try {
throw [{ x: [0], z: 1 }];
}
catch (_c) {
var _d = _c[0], y = _d.x[0], z = _d.z;
y + z;
}
// Test of comment ranges. A fix to GH#11755 should update this.
try {
}
catch (_e) {
var /*a*/ a = _e[0];
}
@@ -0,0 +1,51 @@
=== tests/cases/conformance/es6/destructuring/destructuringCatch.ts ===
try {
throw [0, 1];
}
catch ([a, b]) {
>a : Symbol(a, Decl(destructuringCatch.ts, 4, 8))
>b : Symbol(b, Decl(destructuringCatch.ts, 4, 10))
a + b;
>a : Symbol(a, Decl(destructuringCatch.ts, 4, 8))
>b : Symbol(b, Decl(destructuringCatch.ts, 4, 10))
}
try {
throw { a: 0, b: 1 };
>a : Symbol(a, Decl(destructuringCatch.ts, 9, 11))
>b : Symbol(b, Decl(destructuringCatch.ts, 9, 17))
}
catch ({a, b}) {
>a : Symbol(a, Decl(destructuringCatch.ts, 11, 8))
>b : Symbol(b, Decl(destructuringCatch.ts, 11, 10))
a + b;
>a : Symbol(a, Decl(destructuringCatch.ts, 11, 8))
>b : Symbol(b, Decl(destructuringCatch.ts, 11, 10))
}
try {
throw [{ x: [0], z: 1 }];
>x : Symbol(x, Decl(destructuringCatch.ts, 16, 12))
>z : Symbol(z, Decl(destructuringCatch.ts, 16, 20))
}
catch ([{x: [y], z}]) {
>x : Symbol(x)
>y : Symbol(y, Decl(destructuringCatch.ts, 18, 13))
>z : Symbol(z, Decl(destructuringCatch.ts, 18, 16))
y + z;
>y : Symbol(y, Decl(destructuringCatch.ts, 18, 13))
>z : Symbol(z, Decl(destructuringCatch.ts, 18, 16))
}
// Test of comment ranges. A fix to GH#11755 should update this.
try {
}
catch (/*Test comment ranges*/[/*a*/a]) {
>a : Symbol(a, Decl(destructuringCatch.ts, 25, 31))
}
@@ -0,0 +1,65 @@
=== tests/cases/conformance/es6/destructuring/destructuringCatch.ts ===
try {
throw [0, 1];
>[0, 1] : number[]
>0 : 0
>1 : 1
}
catch ([a, b]) {
>a : any
>b : any
a + b;
>a + b : any
>a : any
>b : any
}
try {
throw { a: 0, b: 1 };
>{ a: 0, b: 1 } : { a: number; b: number; }
>a : number
>0 : 0
>b : number
>1 : 1
}
catch ({a, b}) {
>a : any
>b : any
a + b;
>a + b : any
>a : any
>b : any
}
try {
throw [{ x: [0], z: 1 }];
>[{ x: [0], z: 1 }] : { x: number[]; z: number; }[]
>{ x: [0], z: 1 } : { x: number[]; z: number; }
>x : number[]
>[0] : number[]
>0 : 0
>z : number
>1 : 1
}
catch ([{x: [y], z}]) {
>x : any
>y : any
>z : any
y + z;
>y + z : any
>y : any
>z : any
}
// Test of comment ranges. A fix to GH#11755 should update this.
try {
}
catch (/*Test comment ranges*/[/*a*/a]) {
>a : any
}
@@ -1,7 +1,8 @@
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(17,5): error TS2322: Type 'A & B' is not assignable to type 'number'.
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(18,5): error TS2322: Type 'A & B' is not assignable to type 'boolean'.
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(19,5): error TS2322: Type 'A & B' is not assignable to type 'string'.
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(21,5): error TS2322: Type 'number & boolean' is not assignable to type 'string'.
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(21,5): error TS2322: Type '(number & true) | (number & false)' is not assignable to type 'string'.
Type 'number & true' is not assignable to type 'string'.
==== tests/cases/compiler/errorMessagesIntersectionTypes04.ts (4 errors) ====
@@ -33,5 +34,6 @@ tests/cases/compiler/errorMessagesIntersectionTypes04.ts(21,5): error TS2322: Ty
str = num_and_bool;
~~~
!!! error TS2322: Type 'number & boolean' is not assignable to type 'string'.
!!! error TS2322: Type '(number & true) | (number & false)' is not assignable to type 'string'.
!!! error TS2322: Type 'number & true' is not assignable to type 'string'.
}
@@ -0,0 +1,9 @@
=== tests/cases/compiler/exportAsNamespace.d.ts ===
// issue: https://github.com/Microsoft/TypeScript/issues/11545
export var X;
>X : Symbol(X, Decl(exportAsNamespace.d.ts, 2, 10))
export as namespace N
>N : Symbol(N, Decl(exportAsNamespace.d.ts, 2, 13))
@@ -0,0 +1,9 @@
=== tests/cases/compiler/exportAsNamespace.d.ts ===
// issue: https://github.com/Microsoft/TypeScript/issues/11545
export var X;
>X : any
export as namespace N
>N : typeof N
@@ -0,0 +1,15 @@
tests/cases/compiler/extendPrivateConstructorClass.ts(7,17): error TS2675: Cannot extend a class 'abc.XYZ'. Class constructor is marked as private.
==== tests/cases/compiler/extendPrivateConstructorClass.ts (1 errors) ====
declare namespace abc {
class XYZ {
private constructor();
}
}
class C extends abc.XYZ {
~~~~~~~
!!! error TS2675: Cannot extend a class 'abc.XYZ'. Class constructor is marked as private.
}
@@ -0,0 +1,24 @@
//// [extendPrivateConstructorClass.ts]
declare namespace abc {
class XYZ {
private constructor();
}
}
class C extends abc.XYZ {
}
//// [extendPrivateConstructorClass.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var C = (function (_super) {
__extends(C, _super);
function C() {
return _super.apply(this, arguments) || this;
}
return C;
}(abc.XYZ));
@@ -30,28 +30,29 @@ tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(29,1): e
Type 'A & B' is not assignable to type 'C | D'.
Type 'A & B' is not assignable to type 'D'.
Property 'd' is missing in type 'A & B'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(31,1): error TS2322: Type 'A & B' is not assignable to type '(A | B) & (C | D)'.
Type 'A & B' is not assignable to type 'C | D'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(31,1): error TS2322: Type 'A & B' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
Type 'A & B' is not assignable to type 'B & D'.
Type 'A & B' is not assignable to type 'D'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(32,1): error TS2322: Type 'A | B' is not assignable to type '(A | B) & (C | D)'.
Type 'A' is not assignable to type '(A | B) & (C | D)'.
Type 'A' is not assignable to type 'C | D'.
Type 'A' is not assignable to type 'D'.
Property 'd' is missing in type 'A'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(33,1): error TS2322: Type 'C & D' is not assignable to type '(A | B) & (C | D)'.
Type 'C & D' is not assignable to type 'A | B'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(32,1): error TS2322: Type 'A | B' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
Type 'A' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
Type 'A' is not assignable to type 'B & D'.
Type 'A' is not assignable to type 'B'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(33,1): error TS2322: Type 'C & D' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
Type 'C & D' is not assignable to type 'B & D'.
Type 'C & D' is not assignable to type 'B'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(34,1): error TS2322: Type 'C | D' is not assignable to type '(A | B) & (C | D)'.
Type 'C' is not assignable to type '(A | B) & (C | D)'.
Type 'C' is not assignable to type 'A | B'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(34,1): error TS2322: Type 'C | D' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
Type 'C' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
Type 'C' is not assignable to type 'B & D'.
Type 'C' is not assignable to type 'B'.
Property 'b' is missing in type 'C'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(35,1): error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A & B'.
Type '(A | B) & (C | D)' is not assignable to type 'A'.
Property 'a' is missing in type '(A | B) & (C | D)'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(37,1): error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'C & D'.
Type '(A | B) & (C | D)' is not assignable to type 'C'.
Property 'c' is missing in type '(A | B) & (C | D)'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(35,1): error TS2322: Type '(A & C) | (A & D) | (B & C) | (B & D)' is not assignable to type 'A & B'.
Type 'A & C' is not assignable to type 'A & B'.
Type 'A & C' is not assignable to type 'B'.
Property 'b' is missing in type 'A & C'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(37,1): error TS2322: Type '(A & C) | (A & D) | (B & C) | (B & D)' is not assignable to type 'C & D'.
Type 'A & C' is not assignable to type 'C & D'.
Type 'A & C' is not assignable to type 'D'.
Property 'd' is missing in type 'A & C'.
==== tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts (14 errors) ====
@@ -127,38 +128,39 @@ tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(37,1): e
y = anb;
~
!!! error TS2322: Type 'A & B' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'A & B' is not assignable to type 'C | D'.
!!! error TS2322: Type 'A & B' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
!!! error TS2322: Type 'A & B' is not assignable to type 'B & D'.
!!! error TS2322: Type 'A & B' is not assignable to type 'D'.
y = aob;
~
!!! error TS2322: Type 'A | B' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'A' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'A' is not assignable to type 'C | D'.
!!! error TS2322: Type 'A' is not assignable to type 'D'.
!!! error TS2322: Property 'd' is missing in type 'A'.
!!! error TS2322: Type 'A | B' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
!!! error TS2322: Type 'A' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
!!! error TS2322: Type 'A' is not assignable to type 'B & D'.
!!! error TS2322: Type 'A' is not assignable to type 'B'.
y = cnd;
~
!!! error TS2322: Type 'C & D' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'C & D' is not assignable to type 'A | B'.
!!! error TS2322: Type 'C & D' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
!!! error TS2322: Type 'C & D' is not assignable to type 'B & D'.
!!! error TS2322: Type 'C & D' is not assignable to type 'B'.
y = cod;
~
!!! error TS2322: Type 'C | D' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'C' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'C' is not assignable to type 'A | B'.
!!! error TS2322: Type 'C | D' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
!!! error TS2322: Type 'C' is not assignable to type '(A & C) | (A & D) | (B & C) | (B & D)'.
!!! error TS2322: Type 'C' is not assignable to type 'B & D'.
!!! error TS2322: Type 'C' is not assignable to type 'B'.
!!! error TS2322: Property 'b' is missing in type 'C'.
anb = y;
~~~
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A & B'.
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A'.
!!! error TS2322: Property 'a' is missing in type '(A | B) & (C | D)'.
!!! error TS2322: Type '(A & C) | (A & D) | (B & C) | (B & D)' is not assignable to type 'A & B'.
!!! error TS2322: Type 'A & C' is not assignable to type 'A & B'.
!!! error TS2322: Type 'A & C' is not assignable to type 'B'.
!!! error TS2322: Property 'b' is missing in type 'A & C'.
aob = y; // Ok
cnd = y;
~~~
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'C & D'.
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'C'.
!!! error TS2322: Property 'c' is missing in type '(A | B) & (C | D)'.
!!! error TS2322: Type '(A & C) | (A & D) | (B & C) | (B & D)' is not assignable to type 'C & D'.
!!! error TS2322: Type 'A & C' is not assignable to type 'C & D'.
!!! error TS2322: Type 'A & C' is not assignable to type 'D'.
!!! error TS2322: Property 'd' is missing in type 'A & C'.
cod = y; // Ok
@@ -0,0 +1,79 @@
//// [intersectionTypeNormalization.ts]
interface A { a: string }
interface B { b: string }
interface C { c: string }
interface D { d: string }
// Identical ways of writing the same type
type X1 = (A | B) & (C | D);
type X2 = A & (C | D) | B & (C | D)
type X3 = A & C | A & D | B & C | B & D;
var x: X1;
var x: X2;
var x: X3;
interface X { x: string }
interface Y { y: string }
// Identical ways of writing the same type
type Y1 = (A | X & Y) & (C | D);
type Y2 = A & (C | D) | X & Y & (C | D)
type Y3 = A & C | A & D | X & Y & C | X & Y & D;
var y: Y1;
var y: Y2;
var y: Y3;
interface M { m: string }
interface N { n: string }
// Identical ways of writing the same type
type Z1 = (A | X & (M | N)) & (C | D);
type Z2 = A & (C | D) | X & (M | N) & (C | D)
type Z3 = A & C | A & D | X & (M | N) & C | X & (M | N) & D;
type Z4 = A & C | A & D | X & M & C | X & N & C | X & M & D | X & N & D;
var z: Z1;
var z: Z2;
var z: Z3;
var z: Z4;
// Repro from #9919
type ToString = {
toString(): string;
}
type BoxedValue = { kind: 'int', num: number }
| { kind: 'string', str: string }
type IntersectionFail = BoxedValue & ToString
type IntersectionInline = { kind: 'int', num: number } & ToString
| { kind: 'string', str: string } & ToString
function getValueAsString(value: IntersectionFail): string {
if (value.kind === 'int') {
return '' + value.num;
}
return value.str;
}
//// [intersectionTypeNormalization.js]
var x;
var x;
var x;
var y;
var y;
var y;
var z;
var z;
var z;
var z;
function getValueAsString(value) {
if (value.kind === 'int') {
return '' + value.num;
}
return value.str;
}
@@ -0,0 +1,242 @@
=== tests/cases/compiler/intersectionTypeNormalization.ts ===
interface A { a: string }
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>a : Symbol(A.a, Decl(intersectionTypeNormalization.ts, 0, 13))
interface B { b: string }
>B : Symbol(B, Decl(intersectionTypeNormalization.ts, 0, 25))
>b : Symbol(B.b, Decl(intersectionTypeNormalization.ts, 1, 13))
interface C { c: string }
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>c : Symbol(C.c, Decl(intersectionTypeNormalization.ts, 2, 13))
interface D { d: string }
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
>d : Symbol(D.d, Decl(intersectionTypeNormalization.ts, 3, 13))
// Identical ways of writing the same type
type X1 = (A | B) & (C | D);
>X1 : Symbol(X1, Decl(intersectionTypeNormalization.ts, 3, 25))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>B : Symbol(B, Decl(intersectionTypeNormalization.ts, 0, 25))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
type X2 = A & (C | D) | B & (C | D)
>X2 : Symbol(X2, Decl(intersectionTypeNormalization.ts, 6, 28))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
>B : Symbol(B, Decl(intersectionTypeNormalization.ts, 0, 25))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
type X3 = A & C | A & D | B & C | B & D;
>X3 : Symbol(X3, Decl(intersectionTypeNormalization.ts, 7, 35))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
>B : Symbol(B, Decl(intersectionTypeNormalization.ts, 0, 25))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>B : Symbol(B, Decl(intersectionTypeNormalization.ts, 0, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
var x: X1;
>x : Symbol(x, Decl(intersectionTypeNormalization.ts, 10, 3), Decl(intersectionTypeNormalization.ts, 11, 3), Decl(intersectionTypeNormalization.ts, 12, 3))
>X1 : Symbol(X1, Decl(intersectionTypeNormalization.ts, 3, 25))
var x: X2;
>x : Symbol(x, Decl(intersectionTypeNormalization.ts, 10, 3), Decl(intersectionTypeNormalization.ts, 11, 3), Decl(intersectionTypeNormalization.ts, 12, 3))
>X2 : Symbol(X2, Decl(intersectionTypeNormalization.ts, 6, 28))
var x: X3;
>x : Symbol(x, Decl(intersectionTypeNormalization.ts, 10, 3), Decl(intersectionTypeNormalization.ts, 11, 3), Decl(intersectionTypeNormalization.ts, 12, 3))
>X3 : Symbol(X3, Decl(intersectionTypeNormalization.ts, 7, 35))
interface X { x: string }
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>x : Symbol(X.x, Decl(intersectionTypeNormalization.ts, 14, 13))
interface Y { y: string }
>Y : Symbol(Y, Decl(intersectionTypeNormalization.ts, 14, 25))
>y : Symbol(Y.y, Decl(intersectionTypeNormalization.ts, 15, 13))
// Identical ways of writing the same type
type Y1 = (A | X & Y) & (C | D);
>Y1 : Symbol(Y1, Decl(intersectionTypeNormalization.ts, 15, 25))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>Y : Symbol(Y, Decl(intersectionTypeNormalization.ts, 14, 25))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
type Y2 = A & (C | D) | X & Y & (C | D)
>Y2 : Symbol(Y2, Decl(intersectionTypeNormalization.ts, 18, 32))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>Y : Symbol(Y, Decl(intersectionTypeNormalization.ts, 14, 25))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
type Y3 = A & C | A & D | X & Y & C | X & Y & D;
>Y3 : Symbol(Y3, Decl(intersectionTypeNormalization.ts, 19, 39))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>Y : Symbol(Y, Decl(intersectionTypeNormalization.ts, 14, 25))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>Y : Symbol(Y, Decl(intersectionTypeNormalization.ts, 14, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
var y: Y1;
>y : Symbol(y, Decl(intersectionTypeNormalization.ts, 22, 3), Decl(intersectionTypeNormalization.ts, 23, 3), Decl(intersectionTypeNormalization.ts, 24, 3))
>Y1 : Symbol(Y1, Decl(intersectionTypeNormalization.ts, 15, 25))
var y: Y2;
>y : Symbol(y, Decl(intersectionTypeNormalization.ts, 22, 3), Decl(intersectionTypeNormalization.ts, 23, 3), Decl(intersectionTypeNormalization.ts, 24, 3))
>Y2 : Symbol(Y2, Decl(intersectionTypeNormalization.ts, 18, 32))
var y: Y3;
>y : Symbol(y, Decl(intersectionTypeNormalization.ts, 22, 3), Decl(intersectionTypeNormalization.ts, 23, 3), Decl(intersectionTypeNormalization.ts, 24, 3))
>Y3 : Symbol(Y3, Decl(intersectionTypeNormalization.ts, 19, 39))
interface M { m: string }
>M : Symbol(M, Decl(intersectionTypeNormalization.ts, 24, 10))
>m : Symbol(M.m, Decl(intersectionTypeNormalization.ts, 26, 13))
interface N { n: string }
>N : Symbol(N, Decl(intersectionTypeNormalization.ts, 26, 25))
>n : Symbol(N.n, Decl(intersectionTypeNormalization.ts, 27, 13))
// Identical ways of writing the same type
type Z1 = (A | X & (M | N)) & (C | D);
>Z1 : Symbol(Z1, Decl(intersectionTypeNormalization.ts, 27, 25))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>M : Symbol(M, Decl(intersectionTypeNormalization.ts, 24, 10))
>N : Symbol(N, Decl(intersectionTypeNormalization.ts, 26, 25))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
type Z2 = A & (C | D) | X & (M | N) & (C | D)
>Z2 : Symbol(Z2, Decl(intersectionTypeNormalization.ts, 30, 38))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>M : Symbol(M, Decl(intersectionTypeNormalization.ts, 24, 10))
>N : Symbol(N, Decl(intersectionTypeNormalization.ts, 26, 25))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
type Z3 = A & C | A & D | X & (M | N) & C | X & (M | N) & D;
>Z3 : Symbol(Z3, Decl(intersectionTypeNormalization.ts, 31, 45))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>M : Symbol(M, Decl(intersectionTypeNormalization.ts, 24, 10))
>N : Symbol(N, Decl(intersectionTypeNormalization.ts, 26, 25))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>M : Symbol(M, Decl(intersectionTypeNormalization.ts, 24, 10))
>N : Symbol(N, Decl(intersectionTypeNormalization.ts, 26, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
type Z4 = A & C | A & D | X & M & C | X & N & C | X & M & D | X & N & D;
>Z4 : Symbol(Z4, Decl(intersectionTypeNormalization.ts, 32, 60))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>A : Symbol(A, Decl(intersectionTypeNormalization.ts, 0, 0))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>M : Symbol(M, Decl(intersectionTypeNormalization.ts, 24, 10))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>N : Symbol(N, Decl(intersectionTypeNormalization.ts, 26, 25))
>C : Symbol(C, Decl(intersectionTypeNormalization.ts, 1, 25))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>M : Symbol(M, Decl(intersectionTypeNormalization.ts, 24, 10))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
>X : Symbol(X, Decl(intersectionTypeNormalization.ts, 12, 10))
>N : Symbol(N, Decl(intersectionTypeNormalization.ts, 26, 25))
>D : Symbol(D, Decl(intersectionTypeNormalization.ts, 2, 25))
var z: Z1;
>z : Symbol(z, Decl(intersectionTypeNormalization.ts, 35, 3), Decl(intersectionTypeNormalization.ts, 36, 3), Decl(intersectionTypeNormalization.ts, 37, 3), Decl(intersectionTypeNormalization.ts, 38, 3))
>Z1 : Symbol(Z1, Decl(intersectionTypeNormalization.ts, 27, 25))
var z: Z2;
>z : Symbol(z, Decl(intersectionTypeNormalization.ts, 35, 3), Decl(intersectionTypeNormalization.ts, 36, 3), Decl(intersectionTypeNormalization.ts, 37, 3), Decl(intersectionTypeNormalization.ts, 38, 3))
>Z2 : Symbol(Z2, Decl(intersectionTypeNormalization.ts, 30, 38))
var z: Z3;
>z : Symbol(z, Decl(intersectionTypeNormalization.ts, 35, 3), Decl(intersectionTypeNormalization.ts, 36, 3), Decl(intersectionTypeNormalization.ts, 37, 3), Decl(intersectionTypeNormalization.ts, 38, 3))
>Z3 : Symbol(Z3, Decl(intersectionTypeNormalization.ts, 31, 45))
var z: Z4;
>z : Symbol(z, Decl(intersectionTypeNormalization.ts, 35, 3), Decl(intersectionTypeNormalization.ts, 36, 3), Decl(intersectionTypeNormalization.ts, 37, 3), Decl(intersectionTypeNormalization.ts, 38, 3))
>Z4 : Symbol(Z4, Decl(intersectionTypeNormalization.ts, 32, 60))
// Repro from #9919
type ToString = {
>ToString : Symbol(ToString, Decl(intersectionTypeNormalization.ts, 38, 10))
toString(): string;
>toString : Symbol(toString, Decl(intersectionTypeNormalization.ts, 42, 17))
}
type BoxedValue = { kind: 'int', num: number }
>BoxedValue : Symbol(BoxedValue, Decl(intersectionTypeNormalization.ts, 44, 1))
>kind : Symbol(kind, Decl(intersectionTypeNormalization.ts, 46, 19))
>num : Symbol(num, Decl(intersectionTypeNormalization.ts, 46, 32))
| { kind: 'string', str: string }
>kind : Symbol(kind, Decl(intersectionTypeNormalization.ts, 47, 19))
>str : Symbol(str, Decl(intersectionTypeNormalization.ts, 47, 35))
type IntersectionFail = BoxedValue & ToString
>IntersectionFail : Symbol(IntersectionFail, Decl(intersectionTypeNormalization.ts, 47, 49))
>BoxedValue : Symbol(BoxedValue, Decl(intersectionTypeNormalization.ts, 44, 1))
>ToString : Symbol(ToString, Decl(intersectionTypeNormalization.ts, 38, 10))
type IntersectionInline = { kind: 'int', num: number } & ToString
>IntersectionInline : Symbol(IntersectionInline, Decl(intersectionTypeNormalization.ts, 49, 45))
>kind : Symbol(kind, Decl(intersectionTypeNormalization.ts, 51, 27))
>num : Symbol(num, Decl(intersectionTypeNormalization.ts, 51, 40))
>ToString : Symbol(ToString, Decl(intersectionTypeNormalization.ts, 38, 10))
| { kind: 'string', str: string } & ToString
>kind : Symbol(kind, Decl(intersectionTypeNormalization.ts, 52, 27))
>str : Symbol(str, Decl(intersectionTypeNormalization.ts, 52, 43))
>ToString : Symbol(ToString, Decl(intersectionTypeNormalization.ts, 38, 10))
function getValueAsString(value: IntersectionFail): string {
>getValueAsString : Symbol(getValueAsString, Decl(intersectionTypeNormalization.ts, 52, 68))
>value : Symbol(value, Decl(intersectionTypeNormalization.ts, 54, 26))
>IntersectionFail : Symbol(IntersectionFail, Decl(intersectionTypeNormalization.ts, 47, 49))
if (value.kind === 'int') {
>value.kind : Symbol(kind, Decl(intersectionTypeNormalization.ts, 46, 19), Decl(intersectionTypeNormalization.ts, 47, 19))
>value : Symbol(value, Decl(intersectionTypeNormalization.ts, 54, 26))
>kind : Symbol(kind, Decl(intersectionTypeNormalization.ts, 46, 19), Decl(intersectionTypeNormalization.ts, 47, 19))
return '' + value.num;
>value.num : Symbol(num, Decl(intersectionTypeNormalization.ts, 46, 32))
>value : Symbol(value, Decl(intersectionTypeNormalization.ts, 54, 26))
>num : Symbol(num, Decl(intersectionTypeNormalization.ts, 46, 32))
}
return value.str;
>value.str : Symbol(str, Decl(intersectionTypeNormalization.ts, 47, 35))
>value : Symbol(value, Decl(intersectionTypeNormalization.ts, 54, 26))
>str : Symbol(str, Decl(intersectionTypeNormalization.ts, 47, 35))
}
@@ -0,0 +1,246 @@
=== tests/cases/compiler/intersectionTypeNormalization.ts ===
interface A { a: string }
>A : A
>a : string
interface B { b: string }
>B : B
>b : string
interface C { c: string }
>C : C
>c : string
interface D { d: string }
>D : D
>d : string
// Identical ways of writing the same type
type X1 = (A | B) & (C | D);
>X1 : X1
>A : A
>B : B
>C : C
>D : D
type X2 = A & (C | D) | B & (C | D)
>X2 : X1
>A : A
>C : C
>D : D
>B : B
>C : C
>D : D
type X3 = A & C | A & D | B & C | B & D;
>X3 : X1
>A : A
>C : C
>A : A
>D : D
>B : B
>C : C
>B : B
>D : D
var x: X1;
>x : X1
>X1 : X1
var x: X2;
>x : X1
>X2 : X1
var x: X3;
>x : X1
>X3 : X1
interface X { x: string }
>X : X
>x : string
interface Y { y: string }
>Y : Y
>y : string
// Identical ways of writing the same type
type Y1 = (A | X & Y) & (C | D);
>Y1 : Y1
>A : A
>X : X
>Y : Y
>C : C
>D : D
type Y2 = A & (C | D) | X & Y & (C | D)
>Y2 : Y1
>A : A
>C : C
>D : D
>X : X
>Y : Y
>C : C
>D : D
type Y3 = A & C | A & D | X & Y & C | X & Y & D;
>Y3 : Y1
>A : A
>C : C
>A : A
>D : D
>X : X
>Y : Y
>C : C
>X : X
>Y : Y
>D : D
var y: Y1;
>y : Y1
>Y1 : Y1
var y: Y2;
>y : Y1
>Y2 : Y1
var y: Y3;
>y : Y1
>Y3 : Y1
interface M { m: string }
>M : M
>m : string
interface N { n: string }
>N : N
>n : string
// Identical ways of writing the same type
type Z1 = (A | X & (M | N)) & (C | D);
>Z1 : Z1
>A : A
>X : X
>M : M
>N : N
>C : C
>D : D
type Z2 = A & (C | D) | X & (M | N) & (C | D)
>Z2 : Z1
>A : A
>C : C
>D : D
>X : X
>M : M
>N : N
>C : C
>D : D
type Z3 = A & C | A & D | X & (M | N) & C | X & (M | N) & D;
>Z3 : Z1
>A : A
>C : C
>A : A
>D : D
>X : X
>M : M
>N : N
>C : C
>X : X
>M : M
>N : N
>D : D
type Z4 = A & C | A & D | X & M & C | X & N & C | X & M & D | X & N & D;
>Z4 : Z1
>A : A
>C : C
>A : A
>D : D
>X : X
>M : M
>C : C
>X : X
>N : N
>C : C
>X : X
>M : M
>D : D
>X : X
>N : N
>D : D
var z: Z1;
>z : Z1
>Z1 : Z1
var z: Z2;
>z : Z1
>Z2 : Z1
var z: Z3;
>z : Z1
>Z3 : Z1
var z: Z4;
>z : Z1
>Z4 : Z1
// Repro from #9919
type ToString = {
>ToString : { toString(): string; }
toString(): string;
>toString : () => string
}
type BoxedValue = { kind: 'int', num: number }
>BoxedValue : BoxedValue
>kind : "int"
>num : number
| { kind: 'string', str: string }
>kind : "string"
>str : string
type IntersectionFail = BoxedValue & ToString
>IntersectionFail : IntersectionFail
>BoxedValue : BoxedValue
>ToString : { toString(): string; }
type IntersectionInline = { kind: 'int', num: number } & ToString
>IntersectionInline : IntersectionInline
>kind : "int"
>num : number
>ToString : { toString(): string; }
| { kind: 'string', str: string } & ToString
>kind : "string"
>str : string
>ToString : { toString(): string; }
function getValueAsString(value: IntersectionFail): string {
>getValueAsString : (value: IntersectionFail) => string
>value : IntersectionFail
>IntersectionFail : IntersectionFail
if (value.kind === 'int') {
>value.kind === 'int' : boolean
>value.kind : "int" | "string"
>value : IntersectionFail
>kind : "int" | "string"
>'int' : "int"
return '' + value.num;
>'' + value.num : string
>'' : ""
>value.num : number
>value : { kind: "int"; num: number; } & { toString(): string; }
>num : number
}
return value.str;
>value.str : string
>value : { kind: "string"; str: string; } & { toString(): string; }
>str : string
}
@@ -0,0 +1,81 @@
//// [tests/cases/compiler/jsxEmitWithAttributes.ts] ////
//// [Element.ts]
declare namespace JSX {
interface Element {
name: string;
isIntrinsic: boolean;
isCustomElement: boolean;
toString(renderId?: number): string;
bindDOM(renderId?: number): number;
resetComponent(): void;
instantiateComponents(renderId?: number): number;
props: any;
}
}
export namespace Element {
export function isElement(el: any): el is JSX.Element {
return el.markAsChildOfRootElement !== undefined;
}
export function createElement(args: any[]) {
return {
}
}
}
export let createElement = Element.createElement;
function toCamelCase(text: string): string {
return text[0].toLowerCase() + text.substring(1);
}
//// [test.tsx]
import { Element} from './Element';
let c: {
a?: {
b: string
}
};
class A {
view() {
return [
<meta content="helloworld"></meta>,
<meta content={c.a!.b}></meta>
];
}
}
//// [Element.js]
"use strict";
var Element;
(function (Element) {
function isElement(el) {
return el.markAsChildOfRootElement !== undefined;
}
Element.isElement = isElement;
function createElement(args) {
return {};
}
Element.createElement = createElement;
})(Element = exports.Element || (exports.Element = {}));
exports.createElement = Element.createElement;
function toCamelCase(text) {
return text[0].toLowerCase() + text.substring(1);
}
//// [test.js]
"use strict";
const Element_1 = require("./Element");
let c;
class A {
view() {
return [
Element_1.Element.createElement("meta", { content: "helloworld" }),
Element_1.Element.createElement("meta", { content: c.a.b })
];
}
}
@@ -0,0 +1,119 @@
=== tests/cases/compiler/Element.ts ===
declare namespace JSX {
>JSX : Symbol(JSX, Decl(Element.ts, 0, 0))
interface Element {
>Element : Symbol(Element, Decl(Element.ts, 1, 23))
name: string;
>name : Symbol(Element.name, Decl(Element.ts, 2, 23))
isIntrinsic: boolean;
>isIntrinsic : Symbol(Element.isIntrinsic, Decl(Element.ts, 3, 21))
isCustomElement: boolean;
>isCustomElement : Symbol(Element.isCustomElement, Decl(Element.ts, 4, 29))
toString(renderId?: number): string;
>toString : Symbol(Element.toString, Decl(Element.ts, 5, 33))
>renderId : Symbol(renderId, Decl(Element.ts, 6, 17))
bindDOM(renderId?: number): number;
>bindDOM : Symbol(Element.bindDOM, Decl(Element.ts, 6, 44))
>renderId : Symbol(renderId, Decl(Element.ts, 7, 16))
resetComponent(): void;
>resetComponent : Symbol(Element.resetComponent, Decl(Element.ts, 7, 43))
instantiateComponents(renderId?: number): number;
>instantiateComponents : Symbol(Element.instantiateComponents, Decl(Element.ts, 8, 31))
>renderId : Symbol(renderId, Decl(Element.ts, 9, 30))
props: any;
>props : Symbol(Element.props, Decl(Element.ts, 9, 57))
}
}
export namespace Element {
>Element : Symbol(Element, Decl(Element.ts, 12, 1))
export function isElement(el: any): el is JSX.Element {
>isElement : Symbol(isElement, Decl(Element.ts, 13, 26))
>el : Symbol(el, Decl(Element.ts, 14, 30))
>el : Symbol(el, Decl(Element.ts, 14, 30))
>JSX : Symbol(JSX, Decl(Element.ts, 0, 0))
>Element : Symbol(JSX.Element, Decl(Element.ts, 1, 23))
return el.markAsChildOfRootElement !== undefined;
>el : Symbol(el, Decl(Element.ts, 14, 30))
>undefined : Symbol(undefined)
}
export function createElement(args: any[]) {
>createElement : Symbol(createElement, Decl(Element.ts, 16, 5))
>args : Symbol(args, Decl(Element.ts, 18, 34))
return {
}
}
}
export let createElement = Element.createElement;
>createElement : Symbol(createElement, Decl(Element.ts, 25, 10))
>Element.createElement : Symbol(Element.createElement, Decl(Element.ts, 16, 5))
>Element : Symbol(Element, Decl(Element.ts, 12, 1))
>createElement : Symbol(Element.createElement, Decl(Element.ts, 16, 5))
function toCamelCase(text: string): string {
>toCamelCase : Symbol(toCamelCase, Decl(Element.ts, 25, 49))
>text : Symbol(text, Decl(Element.ts, 27, 21))
return text[0].toLowerCase() + text.substring(1);
>text[0].toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
>text : Symbol(text, Decl(Element.ts, 27, 21))
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
>text.substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --))
>text : Symbol(text, Decl(Element.ts, 27, 21))
>substring : Symbol(String.substring, Decl(lib.es5.d.ts, --, --))
}
=== tests/cases/compiler/test.tsx ===
import { Element} from './Element';
>Element : Symbol(Element, Decl(test.tsx, 0, 8))
let c: {
>c : Symbol(c, Decl(test.tsx, 2, 3))
a?: {
>a : Symbol(a, Decl(test.tsx, 2, 8))
b: string
>b : Symbol(b, Decl(test.tsx, 3, 6))
}
};
class A {
>A : Symbol(A, Decl(test.tsx, 6, 2))
view() {
>view : Symbol(A.view, Decl(test.tsx, 8, 9))
return [
<meta content="helloworld"></meta>,
>meta : Symbol(unknown)
>content : Symbol(unknown)
>meta : Symbol(unknown)
<meta content={c.a!.b}></meta>
>meta : Symbol(unknown)
>content : Symbol(unknown)
>c.a!.b : Symbol(b, Decl(test.tsx, 3, 6))
>c.a : Symbol(a, Decl(test.tsx, 2, 8))
>c : Symbol(c, Decl(test.tsx, 2, 3))
>a : Symbol(a, Decl(test.tsx, 2, 8))
>b : Symbol(b, Decl(test.tsx, 3, 6))
>meta : Symbol(unknown)
];
}
}
@@ -0,0 +1,134 @@
=== tests/cases/compiler/Element.ts ===
declare namespace JSX {
>JSX : any
interface Element {
>Element : Element
name: string;
>name : string
isIntrinsic: boolean;
>isIntrinsic : boolean
isCustomElement: boolean;
>isCustomElement : boolean
toString(renderId?: number): string;
>toString : (renderId?: number) => string
>renderId : number
bindDOM(renderId?: number): number;
>bindDOM : (renderId?: number) => number
>renderId : number
resetComponent(): void;
>resetComponent : () => void
instantiateComponents(renderId?: number): number;
>instantiateComponents : (renderId?: number) => number
>renderId : number
props: any;
>props : any
}
}
export namespace Element {
>Element : typeof Element
export function isElement(el: any): el is JSX.Element {
>isElement : (el: any) => el is JSX.Element
>el : any
>el : any
>JSX : any
>Element : JSX.Element
return el.markAsChildOfRootElement !== undefined;
>el.markAsChildOfRootElement !== undefined : boolean
>el.markAsChildOfRootElement : any
>el : any
>markAsChildOfRootElement : any
>undefined : undefined
}
export function createElement(args: any[]) {
>createElement : (args: any[]) => {}
>args : any[]
return {
>{ } : {}
}
}
}
export let createElement = Element.createElement;
>createElement : (args: any[]) => {}
>Element.createElement : (args: any[]) => {}
>Element : typeof Element
>createElement : (args: any[]) => {}
function toCamelCase(text: string): string {
>toCamelCase : (text: string) => string
>text : string
return text[0].toLowerCase() + text.substring(1);
>text[0].toLowerCase() + text.substring(1) : string
>text[0].toLowerCase() : string
>text[0].toLowerCase : () => string
>text[0] : string
>text : string
>0 : 0
>toLowerCase : () => string
>text.substring(1) : string
>text.substring : (start: number, end?: number) => string
>text : string
>substring : (start: number, end?: number) => string
>1 : 1
}
=== tests/cases/compiler/test.tsx ===
import { Element} from './Element';
>Element : typeof Element
let c: {
>c : { a?: { b: string; }; }
a?: {
>a : { b: string; }
b: string
>b : string
}
};
class A {
>A : A
view() {
>view : () => any[]
return [
>[ <meta content="helloworld"></meta>, <meta content={c.a!.b}></meta> ] : any[]
<meta content="helloworld"></meta>,
><meta content="helloworld"></meta> : any
>meta : any
>content : any
>meta : any
<meta content={c.a!.b}></meta>
><meta content={c.a!.b}></meta> : any
>meta : any
>content : any
>c.a!.b : string
>c.a! : { b: string; }
>c.a : { b: string; }
>c : { a?: { b: string; }; }
>a : { b: string; }
>b : string
>meta : any
];
}
}
@@ -0,0 +1,15 @@
//// [app.js]
function require(a) {
return a;
}
const fs = require("fs");
const text = fs.readFileSync("/a/b/c");
//// [app.js]
function require(a) {
return a;
}
var fs = require("fs");
var text = fs.readFileSync("/a/b/c");
@@ -0,0 +1,18 @@
=== tests/cases/compiler/app.js ===
function require(a) {
>require : Symbol(require, Decl(app.js, 0, 0))
>a : Symbol(a, Decl(app.js, 1, 17))
return a;
>a : Symbol(a, Decl(app.js, 1, 17))
}
const fs = require("fs");
>fs : Symbol(fs, Decl(app.js, 5, 5))
>require : Symbol(require, Decl(app.js, 0, 0))
const text = fs.readFileSync("/a/b/c");
>text : Symbol(text, Decl(app.js, 6, 5))
>fs : Symbol(fs, Decl(app.js, 5, 5))
@@ -0,0 +1,24 @@
=== tests/cases/compiler/app.js ===
function require(a) {
>require : (a: any) => any
>a : any
return a;
>a : any
}
const fs = require("fs");
>fs : any
>require("fs") : any
>require : (a: any) => any
>"fs" : "fs"
const text = fs.readFileSync("/a/b/c");
>text : any
>fs.readFileSync("/a/b/c") : any
>fs.readFileSync : any
>fs : any
>readFileSync : any
>"/a/b/c" : "/a/b/c"
@@ -0,0 +1,14 @@
//// [tests/cases/compiler/nounusedTypeParameterConstraint.ts] ////
//// [bar.ts]
export interface IEventSourcedEntity { }
//// [test.ts]
import { IEventSourcedEntity } from "./bar";
export type DomainEntityConstructor<TEntity extends IEventSourcedEntity> = { new(): TEntity; };
//// [bar.js]
"use strict";
//// [test.js]
"use strict";
@@ -0,0 +1,15 @@
=== tests/cases/compiler/bar.ts ===
export interface IEventSourcedEntity { }
>IEventSourcedEntity : Symbol(IEventSourcedEntity, Decl(bar.ts, 0, 0))
=== tests/cases/compiler/test.ts ===
import { IEventSourcedEntity } from "./bar";
>IEventSourcedEntity : Symbol(IEventSourcedEntity, Decl(test.ts, 0, 8))
export type DomainEntityConstructor<TEntity extends IEventSourcedEntity> = { new(): TEntity; };
>DomainEntityConstructor : Symbol(DomainEntityConstructor, Decl(test.ts, 0, 44))
>TEntity : Symbol(TEntity, Decl(test.ts, 1, 36))
>IEventSourcedEntity : Symbol(IEventSourcedEntity, Decl(test.ts, 0, 8))
>TEntity : Symbol(TEntity, Decl(test.ts, 1, 36))
@@ -0,0 +1,15 @@
=== tests/cases/compiler/bar.ts ===
export interface IEventSourcedEntity { }
>IEventSourcedEntity : IEventSourcedEntity
=== tests/cases/compiler/test.ts ===
import { IEventSourcedEntity } from "./bar";
>IEventSourcedEntity : any
export type DomainEntityConstructor<TEntity extends IEventSourcedEntity> = { new(): TEntity; };
>DomainEntityConstructor : new () => TEntity
>TEntity : TEntity
>IEventSourcedEntity : IEventSourcedEntity
>TEntity : TEntity
@@ -1,8 +1,11 @@
tests/cases/compiler/redeclareParameterInCatchBlock.ts(5,11): error TS2492: Cannot redeclare identifier 'e' in catch clause
tests/cases/compiler/redeclareParameterInCatchBlock.ts(11,9): error TS2492: Cannot redeclare identifier 'e' in catch clause
tests/cases/compiler/redeclareParameterInCatchBlock.ts(17,15): error TS2492: Cannot redeclare identifier 'b' in catch clause
tests/cases/compiler/redeclareParameterInCatchBlock.ts(22,15): error TS2451: Cannot redeclare block-scoped variable 'x'.
tests/cases/compiler/redeclareParameterInCatchBlock.ts(22,21): error TS2451: Cannot redeclare block-scoped variable 'x'.
==== tests/cases/compiler/redeclareParameterInCatchBlock.ts (2 errors) ====
==== tests/cases/compiler/redeclareParameterInCatchBlock.ts (5 errors) ====
try {
@@ -22,10 +25,27 @@ tests/cases/compiler/redeclareParameterInCatchBlock.ts(11,9): error TS2492: Cann
try {
} catch ([a, b]) {
const [c, b] = [0, 1];
~
!!! error TS2492: Cannot redeclare identifier 'b' in catch clause
}
try {
} catch ({ a: x, b: x }) {
~
!!! error TS2451: Cannot redeclare block-scoped variable 'x'.
~
!!! error TS2451: Cannot redeclare block-scoped variable 'x'.
}
try {
} catch(e) {
function test() {
let e;
}
}
@@ -14,12 +14,23 @@ try {
try {
} catch ([a, b]) {
const [c, b] = [0, 1];
}
try {
} catch ({ a: x, b: x }) {
}
try {
} catch(e) {
function test() {
let e;
}
}
//// [redeclareParameterInCatchBlock.js]
@@ -35,6 +46,15 @@ catch (e) {
}
try {
}
catch ([a, b]) {
const [c, b] = [0, 1];
}
try {
}
catch ({ a: x, b: x }) {
}
try {
}
catch (e) {
function test() {
let e;
@@ -1,5 +1,6 @@
tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(19,10): error TS2678: Type 'number & boolean' is not comparable to type 'string & number'.
Type 'number & boolean' is not comparable to type 'string'.
tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(19,10): error TS2678: Type '(number & true) | (number & false)' is not comparable to type 'string & number'.
Type 'number & false' is not comparable to type 'string & number'.
Type 'number & false' is not comparable to type 'string'.
tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(23,10): error TS2678: Type 'boolean' is not comparable to type 'string & number'.
@@ -24,8 +25,9 @@ tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithInterse
// Overlap in constituents
case numAndBool:
~~~~~~~~~~
!!! error TS2678: Type 'number & boolean' is not comparable to type 'string & number'.
!!! error TS2678: Type 'number & boolean' is not comparable to type 'string'.
!!! error TS2678: Type '(number & true) | (number & false)' is not comparable to type 'string & number'.
!!! error TS2678: Type 'number & false' is not comparable to type 'string & number'.
!!! error TS2678: Type 'number & false' is not comparable to type 'string'.
break;
// No relation
@@ -0,0 +1,10 @@
tests/cases/compiler/typeAliasDeclarationEmit.ts(4,37): error TS2314: Generic type 'callback' requires 1 type argument(s).
==== tests/cases/compiler/typeAliasDeclarationEmit.ts (1 errors) ====
export type callback<T> = () => T;
export type CallbackArray<T extends callback> = () => T;
~~~~~~~~
!!! error TS2314: Generic type 'callback' requires 1 type argument(s).
@@ -25,7 +25,7 @@ if (!(result instanceof RegExp)) {
} else if (!result.global) {
>!result.global : boolean
>result.global : string & boolean
>result.global : (string & true) | (string & false)
>result : I & RegExp
>global : string & boolean
>global : (string & true) | (string & false)
}
@@ -0,0 +1,15 @@
tests/cases/compiler/unusedDestructuringParameters.ts(1,13): error TS6133: 'a' is declared but never used.
tests/cases/compiler/unusedDestructuringParameters.ts(3,14): error TS6133: 'a' is declared but never used.
==== tests/cases/compiler/unusedDestructuringParameters.ts (2 errors) ====
const f = ([a]) => { };
~
!!! error TS6133: 'a' is declared but never used.
f([1]);
const f2 = ({a}) => { };
~
!!! error TS6133: 'a' is declared but never used.
f2({ a: 10 });
const f3 = ([_]) => { };
f3([10]);
@@ -0,0 +1,21 @@
//// [unusedDestructuringParameters.ts]
const f = ([a]) => { };
f([1]);
const f2 = ({a}) => { };
f2({ a: 10 });
const f3 = ([_]) => { };
f3([10]);
//// [unusedDestructuringParameters.js]
var f = function (_a) {
var a = _a[0];
};
f([1]);
var f2 = function (_a) {
var a = _a.a;
};
f2({ a: 10 });
var f3 = function (_a) {
var _ = _a[0];
};
f3([10]);
@@ -0,0 +1,27 @@
//// [tests/cases/compiler/unusedImports13.ts] ////
//// [foo.tsx]
import React = require("react");
export const FooComponent = <div></div>
//// [index.d.ts]
export = React;
export as namespace React;
declare namespace React {
function createClass<P, S>(spec);
}
declare global {
namespace JSX {
}
}
//// [foo.jsx]
"use strict";
var React = require("react");
exports.FooComponent = <div></div>;
@@ -0,0 +1,36 @@
=== tests/cases/compiler/foo.tsx ===
import React = require("react");
>React : Symbol(React, Decl(foo.tsx, 0, 0))
export const FooComponent = <div></div>
>FooComponent : Symbol(FooComponent, Decl(foo.tsx, 3, 12))
>div : Symbol(unknown)
>div : Symbol(unknown)
=== tests/cases/compiler/node_modules/@types/react/index.d.ts ===
export = React;
>React : Symbol(React, Decl(index.d.ts, 1, 26))
export as namespace React;
>React : Symbol(React, Decl(index.d.ts, 0, 15))
declare namespace React {
>React : Symbol(React, Decl(index.d.ts, 1, 26))
function createClass<P, S>(spec);
>createClass : Symbol(createClass, Decl(index.d.ts, 3, 25))
>P : Symbol(P, Decl(index.d.ts, 4, 25))
>S : Symbol(S, Decl(index.d.ts, 4, 27))
>spec : Symbol(spec, Decl(index.d.ts, 4, 31))
}
declare global {
>global : Symbol(global, Decl(index.d.ts, 5, 1))
namespace JSX {
>JSX : Symbol(JSX, Decl(index.d.ts, 6, 16))
}
}
@@ -0,0 +1,37 @@
=== tests/cases/compiler/foo.tsx ===
import React = require("react");
>React : typeof React
export const FooComponent = <div></div>
>FooComponent : any
><div></div> : any
>div : any
>div : any
=== tests/cases/compiler/node_modules/@types/react/index.d.ts ===
export = React;
>React : typeof React
export as namespace React;
>React : typeof React
declare namespace React {
>React : typeof React
function createClass<P, S>(spec);
>createClass : <P, S>(spec: any) => any
>P : P
>S : S
>spec : any
}
declare global {
>global : any
namespace JSX {
>JSX : any
}
}
@@ -0,0 +1,27 @@
//// [tests/cases/compiler/unusedImports14.ts] ////
//// [foo.tsx]
import React = require("react");
export const FooComponent = <div></div>
//// [index.d.ts]
export = React;
export as namespace React;
declare namespace React {
function createClass<P, S>(spec);
}
declare global {
namespace JSX {
}
}
//// [foo.js]
"use strict";
var React = require("react");
exports.FooComponent = React.createElement("div", null);
@@ -0,0 +1,36 @@
=== tests/cases/compiler/foo.tsx ===
import React = require("react");
>React : Symbol(React, Decl(foo.tsx, 0, 0))
export const FooComponent = <div></div>
>FooComponent : Symbol(FooComponent, Decl(foo.tsx, 3, 12))
>div : Symbol(unknown)
>div : Symbol(unknown)
=== tests/cases/compiler/node_modules/@types/react/index.d.ts ===
export = React;
>React : Symbol(React, Decl(index.d.ts, 1, 26))
export as namespace React;
>React : Symbol(React, Decl(index.d.ts, 0, 15))
declare namespace React {
>React : Symbol(React, Decl(index.d.ts, 1, 26))
function createClass<P, S>(spec);
>createClass : Symbol(createClass, Decl(index.d.ts, 3, 25))
>P : Symbol(P, Decl(index.d.ts, 4, 25))
>S : Symbol(S, Decl(index.d.ts, 4, 27))
>spec : Symbol(spec, Decl(index.d.ts, 4, 31))
}
declare global {
>global : Symbol(global, Decl(index.d.ts, 5, 1))
namespace JSX {
>JSX : Symbol(JSX, Decl(index.d.ts, 6, 16))
}
}
@@ -0,0 +1,37 @@
=== tests/cases/compiler/foo.tsx ===
import React = require("react");
>React : typeof React
export const FooComponent = <div></div>
>FooComponent : any
><div></div> : any
>div : any
>div : any
=== tests/cases/compiler/node_modules/@types/react/index.d.ts ===
export = React;
>React : typeof React
export as namespace React;
>React : typeof React
declare namespace React {
>React : typeof React
function createClass<P, S>(spec);
>createClass : <P, S>(spec: any) => any
>P : P
>S : S
>spec : any
}
declare global {
>global : any
namespace JSX {
>JSX : any
}
}
@@ -0,0 +1,27 @@
//// [tests/cases/compiler/unusedImports15.ts] ////
//// [foo.tsx]
import Element = require("react");
export const FooComponent = <div></div>
//// [index.d.ts]
export = React;
export as namespace React;
declare namespace React {
function createClass<P, S>(spec);
}
declare global {
namespace JSX {
}
}
//// [foo.jsx]
"use strict";
var Element = require("react");
exports.FooComponent = <div></div>;
@@ -0,0 +1,36 @@
=== tests/cases/compiler/foo.tsx ===
import Element = require("react");
>Element : Symbol(Element, Decl(foo.tsx, 0, 0))
export const FooComponent = <div></div>
>FooComponent : Symbol(FooComponent, Decl(foo.tsx, 3, 12))
>div : Symbol(unknown)
>div : Symbol(unknown)
=== tests/cases/compiler/node_modules/@types/react/index.d.ts ===
export = React;
>React : Symbol(React, Decl(index.d.ts, 1, 26))
export as namespace React;
>React : Symbol(React, Decl(index.d.ts, 0, 15))
declare namespace React {
>React : Symbol(React, Decl(index.d.ts, 1, 26))
function createClass<P, S>(spec);
>createClass : Symbol(createClass, Decl(index.d.ts, 3, 25))
>P : Symbol(P, Decl(index.d.ts, 4, 25))
>S : Symbol(S, Decl(index.d.ts, 4, 27))
>spec : Symbol(spec, Decl(index.d.ts, 4, 31))
}
declare global {
>global : Symbol(global, Decl(index.d.ts, 5, 1))
namespace JSX {
>JSX : Symbol(JSX, Decl(index.d.ts, 6, 16))
}
}
@@ -0,0 +1,37 @@
=== tests/cases/compiler/foo.tsx ===
import Element = require("react");
>Element : typeof Element
export const FooComponent = <div></div>
>FooComponent : any
><div></div> : any
>div : any
>div : any
=== tests/cases/compiler/node_modules/@types/react/index.d.ts ===
export = React;
>React : typeof React
export as namespace React;
>React : typeof React
declare namespace React {
>React : typeof React
function createClass<P, S>(spec);
>createClass : <P, S>(spec: any) => any
>P : P
>S : S
>spec : any
}
declare global {
>global : any
namespace JSX {
>JSX : any
}
}
@@ -0,0 +1,27 @@
//// [tests/cases/compiler/unusedImports16.ts] ////
//// [foo.tsx]
import Element = require("react");
export const FooComponent = <div></div>
//// [index.d.ts]
export = React;
export as namespace React;
declare namespace React {
function createClass<P, S>(spec);
}
declare global {
namespace JSX {
}
}
//// [foo.js]
"use strict";
var Element = require("react");
exports.FooComponent = Element.createElement("div", null);
@@ -0,0 +1,36 @@
=== tests/cases/compiler/foo.tsx ===
import Element = require("react");
>Element : Symbol(Element, Decl(foo.tsx, 0, 0))
export const FooComponent = <div></div>
>FooComponent : Symbol(FooComponent, Decl(foo.tsx, 3, 12))
>div : Symbol(unknown)
>div : Symbol(unknown)
=== tests/cases/compiler/node_modules/@types/react/index.d.ts ===
export = React;
>React : Symbol(React, Decl(index.d.ts, 1, 26))
export as namespace React;
>React : Symbol(React, Decl(index.d.ts, 0, 15))
declare namespace React {
>React : Symbol(React, Decl(index.d.ts, 1, 26))
function createClass<P, S>(spec);
>createClass : Symbol(createClass, Decl(index.d.ts, 3, 25))
>P : Symbol(P, Decl(index.d.ts, 4, 25))
>S : Symbol(S, Decl(index.d.ts, 4, 27))
>spec : Symbol(spec, Decl(index.d.ts, 4, 31))
}
declare global {
>global : Symbol(global, Decl(index.d.ts, 5, 1))
namespace JSX {
>JSX : Symbol(JSX, Decl(index.d.ts, 6, 16))
}
}
@@ -0,0 +1,37 @@
=== tests/cases/compiler/foo.tsx ===
import Element = require("react");
>Element : typeof Element
export const FooComponent = <div></div>
>FooComponent : any
><div></div> : any
>div : any
>div : any
=== tests/cases/compiler/node_modules/@types/react/index.d.ts ===
export = React;
>React : typeof React
export as namespace React;
>React : typeof React
declare namespace React {
>React : typeof React
function createClass<P, S>(spec);
>createClass : <P, S>(spec: any) => any
>P : P
>S : S
>spec : any
}
declare global {
>global : any
namespace JSX {
>JSX : any
}
}
@@ -0,0 +1,18 @@
tests/cases/compiler/unusedLocalsStartingWithUnderscore.ts(7,9): error TS6133: '_' is declared but never used.
==== tests/cases/compiler/unusedLocalsStartingWithUnderscore.ts (1 errors) ====
for (const _ of []) { }
for (const _ in []) { }
namespace M {
let _;
~
!!! error TS6133: '_' is declared but never used.
for (const _ of []) { }
for (const _ in []) { }
}
@@ -0,0 +1,27 @@
//// [unusedLocalsStartingWithUnderscore.ts]
for (const _ of []) { }
for (const _ in []) { }
namespace M {
let _;
for (const _ of []) { }
for (const _ in []) { }
}
//// [unusedLocalsStartingWithUnderscore.js]
for (var _i = 0, _a = []; _i < _a.length; _i++) {
var _ = _a[_i];
}
for (var _ in []) { }
var M;
(function (M) {
var _;
for (var _i = 0, _a = []; _i < _a.length; _i++) {
var _1 = _a[_i];
}
for (var _2 in []) { }
})(M || (M = {}));
@@ -2,15 +2,11 @@ tests/cases/compiler/unusedParametersWithUnderscore.ts(2,12): error TS6133: 'a'
tests/cases/compiler/unusedParametersWithUnderscore.ts(2,19): error TS6133: 'c' is declared but never used.
tests/cases/compiler/unusedParametersWithUnderscore.ts(2,27): error TS6133: 'd' is declared but never used.
tests/cases/compiler/unusedParametersWithUnderscore.ts(2,29): error TS6133: 'e___' is declared but never used.
tests/cases/compiler/unusedParametersWithUnderscore.ts(6,14): error TS6133: '_a' is declared but never used.
tests/cases/compiler/unusedParametersWithUnderscore.ts(6,18): error TS6133: '___b' is declared but never used.
tests/cases/compiler/unusedParametersWithUnderscore.ts(9,14): error TS6133: '_a' is declared but never used.
tests/cases/compiler/unusedParametersWithUnderscore.ts(9,19): error TS6133: '___b' is declared but never used.
tests/cases/compiler/unusedParametersWithUnderscore.ts(12,16): error TS6133: 'arg' is declared but never used.
tests/cases/compiler/unusedParametersWithUnderscore.ts(18,13): error TS6133: 'arg' is declared but never used.
==== tests/cases/compiler/unusedParametersWithUnderscore.ts (10 errors) ====
==== tests/cases/compiler/unusedParametersWithUnderscore.ts (6 errors) ====
function f(a, _b, c, ___, d,e___, _f) {
~
@@ -25,17 +21,9 @@ tests/cases/compiler/unusedParametersWithUnderscore.ts(18,13): error TS6133: 'ar
function f2({_a, __b}) {
~~
!!! error TS6133: '_a' is declared but never used.
~~~
!!! error TS6133: '___b' is declared but never used.
}
function f3([_a, ,__b]) {
~~
!!! error TS6133: '_a' is declared but never used.
~~~
!!! error TS6133: '___b' is declared but never used.
}
function f4(...arg) {

Some files were not shown because too many files have changed in this diff Show More