mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #22442 from Microsoft/mergeMaster3-9
Merge master into release-2.8
This commit is contained in:
@@ -65,6 +65,7 @@ workflows:
|
||||
base: &base
|
||||
environment:
|
||||
- workerCount: 4
|
||||
- timeout: 400000
|
||||
steps:
|
||||
- checkout
|
||||
- run: |
|
||||
|
||||
+125
-80
@@ -315,7 +315,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getDisplayName(node: Declaration): string {
|
||||
return (node as NamedDeclaration).name ? declarationNameToString((node as NamedDeclaration).name) : unescapeLeadingUnderscores(getDeclarationName(node));
|
||||
return isNamedDeclaration(node) ? declarationNameToString(node.name) : unescapeLeadingUnderscores(getDeclarationName(node));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,8 +383,8 @@ namespace ts {
|
||||
symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name));
|
||||
}
|
||||
else {
|
||||
if ((node as NamedDeclaration).name) {
|
||||
(node as NamedDeclaration).name.parent = node;
|
||||
if (isNamedDeclaration(node)) {
|
||||
node.name.parent = node;
|
||||
}
|
||||
|
||||
// Report errors every position with duplicate declaration
|
||||
@@ -1996,7 +1996,7 @@ namespace ts {
|
||||
|
||||
/// Should be called only on prologue directives (isPrologueDirective(node) should be true)
|
||||
function isUseStrictPrologueDirective(node: ExpressionStatement): boolean {
|
||||
const nodeText = getTextOfNodeFromSourceText(file.text, node.expression);
|
||||
const nodeText = getSourceTextOfNodeFromSourceFile(file, node.expression);
|
||||
|
||||
// Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the
|
||||
// string to contain unicode escapes (as per ES5).
|
||||
@@ -2036,19 +2036,22 @@ namespace ts {
|
||||
const specialKind = getSpecialPropertyAssignmentKind(node as BinaryExpression);
|
||||
switch (specialKind) {
|
||||
case SpecialPropertyAssignmentKind.ExportsProperty:
|
||||
bindExportsPropertyAssignment(<BinaryExpression>node);
|
||||
bindExportsPropertyAssignment(node as BinaryExpression);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.ModuleExports:
|
||||
bindModuleExportsAssignment(<BinaryExpression>node);
|
||||
bindModuleExportsAssignment(node as BinaryExpression);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.PrototypeProperty:
|
||||
bindPrototypePropertyAssignment(<BinaryExpression>node);
|
||||
bindPrototypePropertyAssignment((node as BinaryExpression).left as PropertyAccessEntityNameExpression, node);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.Prototype:
|
||||
bindPrototypeAssignment(node as BinaryExpression);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.ThisProperty:
|
||||
bindThisPropertyAssignment(<BinaryExpression>node);
|
||||
bindThisPropertyAssignment(node as BinaryExpression);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.Property:
|
||||
bindStaticPropertyAssignment(<BinaryExpression>node);
|
||||
bindSpecialPropertyAssignment(node as BinaryExpression);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.None:
|
||||
// Nothing to do
|
||||
@@ -2291,7 +2294,18 @@ namespace ts {
|
||||
// When we create a property via 'exports.foo = bar', the 'exports.foo' property access
|
||||
// expression is the declaration
|
||||
setCommonJsModuleIndicator(node);
|
||||
declareSymbol(file.symbol.exports, file.symbol, <PropertyAccessExpression>node.left, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None);
|
||||
const lhs = node.left as PropertyAccessEntityNameExpression;
|
||||
const symbol = forEachIdentifierInEntityName(lhs.expression, (id, original) => {
|
||||
if (!original) {
|
||||
return undefined;
|
||||
}
|
||||
const s = getJSInitializerSymbol(original);
|
||||
addDeclarationToSymbol(s, id, SymbolFlags.Module | SymbolFlags.JSContainer);
|
||||
return s;
|
||||
});
|
||||
if (symbol) {
|
||||
declareSymbol(symbol.exports, symbol, lhs, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None);
|
||||
}
|
||||
}
|
||||
|
||||
function bindModuleExportsAssignment(node: BinaryExpression) {
|
||||
@@ -2338,103 +2352,134 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindSpecialPropertyDeclaration(node: PropertyAccessExpression) {
|
||||
Debug.assert(isInJavaScriptFile(node));
|
||||
if (node.expression.kind === SyntaxKind.ThisKeyword) {
|
||||
bindThisPropertyAssignment(node);
|
||||
}
|
||||
else if ((node.expression.kind === SyntaxKind.Identifier || node.expression.kind === SyntaxKind.PropertyAccessExpression) &&
|
||||
node.parent.parent.kind === SyntaxKind.SourceFile) {
|
||||
bindStaticPropertyAssignment(node);
|
||||
else if (isEntityNameExpression(node) && node.parent.parent.kind === SyntaxKind.SourceFile) {
|
||||
if (isPropertyAccessExpression(node.expression) && node.expression.name.escapedText === "prototype") {
|
||||
bindPrototypePropertyAssignment(node as PropertyAccessEntityNameExpression, node.parent);
|
||||
}
|
||||
else {
|
||||
bindStaticPropertyAssignment(node as PropertyAccessEntityNameExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bindPrototypePropertyAssignment(node: BinaryExpression) {
|
||||
// We saw a node of the form 'x.prototype.y = z'. Declare a 'member' y on x if x is a function or class, or not declared.
|
||||
|
||||
// Look up the function in the local scope, since prototype assignments should
|
||||
// follow the function declaration
|
||||
const leftSideOfAssignment = node.left as PropertyAccessExpression;
|
||||
const classPrototype = leftSideOfAssignment.expression as PropertyAccessExpression;
|
||||
const constructorFunction = classPrototype.expression as Identifier;
|
||||
|
||||
// Fix up parent pointers since we're going to use these nodes before we bind into them
|
||||
leftSideOfAssignment.parent = node;
|
||||
constructorFunction.parent = classPrototype;
|
||||
classPrototype.parent = leftSideOfAssignment;
|
||||
|
||||
bindPropertyAssignment(constructorFunction.escapedText, leftSideOfAssignment, /*isPrototypeProperty*/ true);
|
||||
/** For `x.prototype = { p, ... }`, declare members p,... if `x` is function/class/{}, or not declared. */
|
||||
function bindPrototypeAssignment(node: BinaryExpression) {
|
||||
node.left.parent = node;
|
||||
node.right.parent = node;
|
||||
const lhs = node.left as PropertyAccessEntityNameExpression;
|
||||
bindPropertyAssignment(lhs, lhs, /*isPrototypeProperty*/ false);
|
||||
}
|
||||
|
||||
/**
|
||||
* For nodes like `x.y = z`, declare a member 'y' on 'x' if x is a function or class, or not declared.
|
||||
* Also works for expression statements preceded by JSDoc, like / ** @type number * / x.y;
|
||||
* For `x.prototype.y = z`, declare a member `y` on `x` if `x` is a function or class, or not declared.
|
||||
* Note that jsdoc preceding an ExpressionStatement like `x.prototype.y;` is also treated as a declaration.
|
||||
*/
|
||||
function bindStaticPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) {
|
||||
// Look up the function in the local scope, since static assignments should
|
||||
function bindPrototypePropertyAssignment(lhs: PropertyAccessEntityNameExpression, parent: Node) {
|
||||
// Look up the function in the local scope, since prototype assignments should
|
||||
// follow the function declaration
|
||||
const leftSideOfAssignment = node.kind === SyntaxKind.PropertyAccessExpression ? node : node.left as PropertyAccessExpression;
|
||||
const target = leftSideOfAssignment.expression;
|
||||
const classPrototype = lhs.expression as PropertyAccessEntityNameExpression;
|
||||
const constructorFunction = classPrototype.expression;
|
||||
|
||||
if (isIdentifier(target)) {
|
||||
// Fix up parent pointers since we're going to use these nodes before we bind into them
|
||||
target.parent = leftSideOfAssignment;
|
||||
if (node.kind === SyntaxKind.BinaryExpression) {
|
||||
leftSideOfAssignment.parent = node;
|
||||
}
|
||||
if (container === file && isNameOfExportsOrModuleExportsAliasDeclaration(file, target)) {
|
||||
// This can be an alias for the 'exports' or 'module.exports' names, e.g.
|
||||
// var util = module.exports;
|
||||
// util.property = function ...
|
||||
bindExportsPropertyAssignment(node as BinaryExpression);
|
||||
}
|
||||
else {
|
||||
bindPropertyAssignment(target.escapedText, leftSideOfAssignment, /*isPrototypeProperty*/ false);
|
||||
}
|
||||
}
|
||||
// Fix up parent pointers since we're going to use these nodes before we bind into them
|
||||
lhs.parent = parent;
|
||||
constructorFunction.parent = classPrototype;
|
||||
classPrototype.parent = lhs;
|
||||
|
||||
bindPropertyAssignment(constructorFunction, lhs, /*isPrototypeProperty*/ true);
|
||||
}
|
||||
|
||||
function lookupSymbolForName(name: __String) {
|
||||
return lookupSymbolForNameWorker(container, name);
|
||||
}
|
||||
|
||||
function bindPropertyAssignment(functionName: __String, propertyAccess: PropertyAccessExpression, isPrototypeProperty: boolean) {
|
||||
const symbol = lookupSymbolForName(functionName);
|
||||
let targetSymbol = symbol && isDeclarationOfFunctionOrClassExpression(symbol) ?
|
||||
(symbol.valueDeclaration as VariableDeclaration).initializer.symbol :
|
||||
symbol;
|
||||
Debug.assert(propertyAccess.parent.kind === SyntaxKind.BinaryExpression || propertyAccess.parent.kind === SyntaxKind.ExpressionStatement);
|
||||
let isLegalPosition: boolean;
|
||||
if (propertyAccess.parent.kind === SyntaxKind.BinaryExpression) {
|
||||
const initializerKind = (propertyAccess.parent as BinaryExpression).right.kind;
|
||||
isLegalPosition = (initializerKind === SyntaxKind.ClassExpression || initializerKind === SyntaxKind.FunctionExpression) &&
|
||||
propertyAccess.parent.parent.parent.kind === SyntaxKind.SourceFile;
|
||||
function bindSpecialPropertyAssignment(node: BinaryExpression) {
|
||||
const lhs = node.left as PropertyAccessEntityNameExpression;
|
||||
// Fix up parent pointers since we're going to use these nodes before we bind into them
|
||||
node.left.parent = node;
|
||||
node.right.parent = node;
|
||||
if (isIdentifier(lhs.expression) && container === file && isNameOfExportsOrModuleExportsAliasDeclaration(file, lhs.expression)) {
|
||||
// This can be an alias for the 'exports' or 'module.exports' names, e.g.
|
||||
// var util = module.exports;
|
||||
// util.property = function ...
|
||||
bindExportsPropertyAssignment(node);
|
||||
}
|
||||
else {
|
||||
isLegalPosition = propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
|
||||
bindStaticPropertyAssignment(lhs);
|
||||
}
|
||||
if (!isPrototypeProperty && (!targetSymbol || !(targetSymbol.flags & SymbolFlags.Namespace)) && isLegalPosition) {
|
||||
Debug.assert(isIdentifier(propertyAccess.expression));
|
||||
const identifier = propertyAccess.expression as Identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* For nodes like `x.y = z`, declare a member 'y' on 'x' if x is a function (or IIFE) or class or {}, or not declared.
|
||||
* Also works for expression statements preceded by JSDoc, like / ** @type number * / x.y;
|
||||
*/
|
||||
function bindStaticPropertyAssignment(node: PropertyAccessEntityNameExpression) {
|
||||
node.expression.parent = node;
|
||||
bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false);
|
||||
}
|
||||
|
||||
function bindPropertyAssignment(name: EntityNameExpression, propertyAccess: PropertyAccessEntityNameExpression, isPrototypeProperty: boolean) {
|
||||
let symbol = getJSInitializerSymbol(lookupSymbolForPropertyAccess(name));
|
||||
let isToplevelNamespaceableInitializer: boolean;
|
||||
if (isBinaryExpression(propertyAccess.parent)) {
|
||||
const isPrototypeAssignment = isPropertyAccessExpression(propertyAccess.parent.left) && propertyAccess.parent.left.name.escapedText === "prototype";
|
||||
isToplevelNamespaceableInitializer = propertyAccess.parent.parent.parent.kind === SyntaxKind.SourceFile &&
|
||||
!!getJavascriptInitializer(propertyAccess.parent.right, isPrototypeAssignment);
|
||||
}
|
||||
else {
|
||||
isToplevelNamespaceableInitializer = propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
|
||||
}
|
||||
if (!isPrototypeProperty && (!symbol || !(symbol.flags & SymbolFlags.Namespace)) && isToplevelNamespaceableInitializer) {
|
||||
// make symbols or add declarations for intermediate containers
|
||||
const flags = SymbolFlags.Module | SymbolFlags.JSContainer;
|
||||
const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.JSContainer;
|
||||
if (targetSymbol) {
|
||||
addDeclarationToSymbol(symbol, identifier, flags);
|
||||
}
|
||||
else {
|
||||
targetSymbol = declareSymbol(container.locals, /*parent*/ undefined, identifier, flags, excludeFlags);
|
||||
}
|
||||
forEachIdentifierInEntityName(propertyAccess.expression, (id, original) => {
|
||||
if (original) {
|
||||
// Note: add declaration to original symbol, not the special-syntax's symbol, so that namespaces work for type lookup
|
||||
addDeclarationToSymbol(original, id, flags);
|
||||
return original;
|
||||
}
|
||||
else {
|
||||
return symbol = declareSymbol(symbol ? symbol.exports : container.locals, symbol, id, flags, excludeFlags);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.NamespaceModule))) {
|
||||
if (!symbol || !(symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.NamespaceModule | SymbolFlags.ObjectLiteral))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up the members collection if it doesn't exist already
|
||||
const symbolTable = isPrototypeProperty ?
|
||||
(targetSymbol.members || (targetSymbol.members = createSymbolTable())) :
|
||||
(targetSymbol.exports || (targetSymbol.exports = createSymbolTable()));
|
||||
(symbol.members || (symbol.members = createSymbolTable())) :
|
||||
(symbol.exports || (symbol.exports = createSymbolTable()));
|
||||
|
||||
// Declare the method/property
|
||||
declareSymbol(symbolTable, targetSymbol, propertyAccess, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
const symbolFlags = SymbolFlags.Property | (isToplevelNamespaceableInitializer ? SymbolFlags.JSContainer : 0);
|
||||
const symbolExcludes = SymbolFlags.PropertyExcludes & ~(isToplevelNamespaceableInitializer ? SymbolFlags.JSContainer : 0);
|
||||
declareSymbol(symbolTable, symbol, propertyAccess, symbolFlags, symbolExcludes);
|
||||
}
|
||||
|
||||
function lookupSymbolForPropertyAccess(node: EntityNameExpression): Symbol | undefined {
|
||||
if (isIdentifier(node)) {
|
||||
return lookupSymbolForNameWorker(container, node.escapedText);
|
||||
}
|
||||
else {
|
||||
const symbol = getJSInitializerSymbol(lookupSymbolForPropertyAccess(node.expression));
|
||||
return symbol && symbol.exports && symbol.exports.get(node.name.escapedText);
|
||||
}
|
||||
}
|
||||
|
||||
function forEachIdentifierInEntityName(e: EntityNameExpression, action: (e: Identifier, symbol: Symbol) => Symbol): Symbol {
|
||||
if (isExportsOrModuleExportsOrAlias(file, e)) {
|
||||
return file.symbol;
|
||||
}
|
||||
else if (isIdentifier(e)) {
|
||||
return action(e, lookupSymbolForPropertyAccess(e));
|
||||
}
|
||||
else {
|
||||
const s = getJSInitializerSymbol(forEachIdentifierInEntityName(e.expression, action));
|
||||
Debug.assert(!!s && !!s.exports);
|
||||
return action(e.name, s.exports.get(e.name.escapedText));
|
||||
}
|
||||
}
|
||||
|
||||
function bindCallExpression(node: CallExpression) {
|
||||
@@ -2665,7 +2710,7 @@ namespace ts {
|
||||
|
||||
function isExportsOrModuleExportsOrAliasOrAssignment(sourceFile: SourceFile, node: Expression): boolean {
|
||||
return isExportsOrModuleExportsOrAlias(sourceFile, node) ||
|
||||
(isAssignmentExpression(node, /*excludeCompoundAssignements*/ true) && (
|
||||
(isAssignmentExpression(node, /*excludeCompoundAssignment*/ true) && (
|
||||
isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node.left) || isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node.right)));
|
||||
}
|
||||
|
||||
|
||||
+234
-137
@@ -870,7 +870,7 @@ namespace ts {
|
||||
|
||||
function mergeSymbol(target: Symbol, source: Symbol) {
|
||||
if (!(target.flags & getExcludedSymbolFlags(source.flags)) ||
|
||||
source.flags & SymbolFlags.JSContainer || target.flags & SymbolFlags.JSContainer) {
|
||||
(source.flags | target.flags) & SymbolFlags.JSContainer) {
|
||||
// Javascript static-property-assignment declarations always merge, even though they are also values
|
||||
if (source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) {
|
||||
// reset flag when merging instantiated module into value module that has only const enums
|
||||
@@ -892,6 +892,13 @@ namespace ts {
|
||||
if (!target.exports) target.exports = createSymbolTable();
|
||||
mergeSymbolTable(target.exports, source.exports);
|
||||
}
|
||||
if ((source.flags | target.flags) & SymbolFlags.JSContainer) {
|
||||
const sourceInitializer = getJSInitializerSymbol(source);
|
||||
const targetInitializer = getJSInitializerSymbol(target);
|
||||
if (sourceInitializer !== source || targetInitializer !== target) {
|
||||
mergeSymbol(targetInitializer, sourceInitializer);
|
||||
}
|
||||
}
|
||||
recordMergedSymbol(target, source);
|
||||
}
|
||||
else if (target.flags & SymbolFlags.NamespaceModule) {
|
||||
@@ -904,10 +911,12 @@ namespace ts {
|
||||
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
|
||||
: Diagnostics.Duplicate_identifier_0;
|
||||
forEach(source.declarations, node => {
|
||||
error(getNameOfDeclaration(node) || node, message, symbolToString(source));
|
||||
const errorNode = (getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? getOuterNameOfJsInitializer(node) : getNameOfDeclaration(node)) || node;
|
||||
error(errorNode, message, symbolToString(source));
|
||||
});
|
||||
forEach(target.declarations, node => {
|
||||
error(getNameOfDeclaration(node) || node, message, symbolToString(source));
|
||||
const errorNode = (getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? getOuterNameOfJsInitializer(node) : getNameOfDeclaration(node)) || node;
|
||||
error(errorNode, message, symbolToString(source));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1599,8 +1608,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
|
||||
if (meaning === SymbolFlags.Namespace) {
|
||||
const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Namespace, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
|
||||
const namespaceMeaning = SymbolFlags.Namespace | (isInJavaScriptFile(errorLocation) ? SymbolFlags.Value : 0);
|
||||
if (meaning === namespaceMeaning) {
|
||||
const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~namespaceMeaning, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
|
||||
const parent = errorLocation.parent;
|
||||
if (symbol) {
|
||||
if (isQualifiedName(parent)) {
|
||||
@@ -2014,9 +2024,10 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const namespaceMeaning = SymbolFlags.Namespace | (isInJavaScriptFile(name) ? meaning & SymbolFlags.Value : 0);
|
||||
let symbol: Symbol;
|
||||
if (name.kind === SyntaxKind.Identifier) {
|
||||
const message = meaning === SymbolFlags.Namespace ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0;
|
||||
const message = meaning === namespaceMeaning ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0;
|
||||
|
||||
symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors ? undefined : message, name, /*isUse*/ true);
|
||||
if (!symbol) {
|
||||
@@ -2024,31 +2035,32 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
let left: EntityNameOrEntityNameExpression;
|
||||
|
||||
if (name.kind === SyntaxKind.QualifiedName) {
|
||||
left = name.left;
|
||||
}
|
||||
else if (name.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
left = name.expression;
|
||||
}
|
||||
else {
|
||||
// If the expression in property-access expression is not entity-name or parenthsizedExpression (e.g. it is a call expression), it won't be able to successfully resolve the name.
|
||||
// This is the case when we are trying to do any language service operation in heritage clauses. By return undefined, the getSymbolOfEntityNameOrPropertyAccessExpression
|
||||
// will attempt to checkPropertyAccessExpression to resolve symbol.
|
||||
// i.e class C extends foo()./*do language service operation here*/B {}
|
||||
return undefined;
|
||||
}
|
||||
const left = name.kind === SyntaxKind.QualifiedName ? name.left : name.expression;
|
||||
const right = name.kind === SyntaxKind.QualifiedName ? name.right : name.name;
|
||||
let namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors, /*dontResolveAlias*/ false, location);
|
||||
let namespace = resolveEntityName(left, namespaceMeaning, ignoreErrors, /*dontResolveAlias*/ false, location);
|
||||
if (!namespace || nodeIsMissing(right)) {
|
||||
return undefined;
|
||||
}
|
||||
else if (namespace === unknownSymbol) {
|
||||
return namespace;
|
||||
}
|
||||
if (isInJavaScriptFile(name) && isDeclarationOfFunctionOrClassExpression(namespace)) {
|
||||
namespace = getSymbolOfNode((namespace.valueDeclaration as VariableDeclaration).initializer);
|
||||
if (isInJavaScriptFile(name)) {
|
||||
const initializer = getDeclaredJavascriptInitializer(namespace.valueDeclaration) || getAssignedJavascriptInitializer(namespace.valueDeclaration);
|
||||
if (initializer) {
|
||||
namespace = getSymbolOfNode(initializer);
|
||||
}
|
||||
if (namespace.valueDeclaration &&
|
||||
isVariableDeclaration(namespace.valueDeclaration) &&
|
||||
isCommonJsRequire(namespace.valueDeclaration.initializer)) {
|
||||
const moduleName = (namespace.valueDeclaration.initializer as CallExpression).arguments[0] as StringLiteral;
|
||||
const moduleSym = resolveExternalModuleName(moduleName, moduleName);
|
||||
if (moduleSym) {
|
||||
const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym);
|
||||
if (resolvedModuleSymbol) {
|
||||
namespace = resolvedModuleSymbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
symbol = getSymbol(getExportsOfSymbol(namespace), right.escapedText, meaning);
|
||||
if (!symbol) {
|
||||
@@ -4227,6 +4239,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getWidenedTypeFromJSSpecialPropertyDeclarations(symbol: Symbol) {
|
||||
// function/class/{} assignments are fresh declarations, not property assignments, so only add prototype assignments
|
||||
const specialDeclaration = getAssignedJavascriptInitializer(symbol.valueDeclaration);
|
||||
if (specialDeclaration) {
|
||||
return getWidenedLiteralType(checkExpressionCached(specialDeclaration));
|
||||
}
|
||||
const types: Type[] = [];
|
||||
let definedInConstructor = false;
|
||||
let definedInMethod = false;
|
||||
@@ -6959,7 +6976,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature {
|
||||
return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), /*eraseTypeParameters*/ true);
|
||||
return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true);
|
||||
}
|
||||
function createSignatureTypeMapper(signature: Signature, typeArguments: Type[]): TypeMapper {
|
||||
return createTypeMapper(signature.typeParameters, typeArguments);
|
||||
}
|
||||
|
||||
function getErasedSignature(signature: Signature): Signature {
|
||||
@@ -7303,12 +7323,11 @@ namespace ts {
|
||||
// A jsdoc TypeReference may have resolved to a value (as opposed to a type). If
|
||||
// the symbol is a constructor function, return the inferred class type; otherwise,
|
||||
// the type of this reference is just the type of the value we resolved to.
|
||||
const assignedType = getAssignedClassType(symbol);
|
||||
const valueType = getTypeOfSymbol(symbol);
|
||||
if (valueType.symbol && !isInferredClassType(valueType)) {
|
||||
const referenceType = getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments);
|
||||
if (referenceType) {
|
||||
return referenceType;
|
||||
}
|
||||
const referenceType = valueType.symbol && !isInferredClassType(valueType) && getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments);
|
||||
if (referenceType || assignedType) {
|
||||
return referenceType && assignedType ? getIntersectionType([assignedType, referenceType]) : referenceType || assignedType;
|
||||
}
|
||||
|
||||
// Resolve the type reference as a Type for the purpose of reporting errors.
|
||||
@@ -8005,10 +8024,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getLiteralTypeFromPropertyName(prop: Symbol) {
|
||||
const links = getSymbolLinks(prop);
|
||||
const links = getSymbolLinks(getLateBoundSymbol(prop));
|
||||
if (!links.nameType) {
|
||||
if (links.target) {
|
||||
Debug.assert(links.target.escapedName === prop.escapedName, "Target symbol and symbol do not have the same name");
|
||||
if (links.target && links.target !== unknownSymbol && links.target !== resolvingSymbol) {
|
||||
Debug.assert(links.target.escapedName === prop.escapedName || links.target.escapedName === InternalSymbolName.Computed, "Target symbol and symbol do not have the same name");
|
||||
links.nameType = getLiteralTypeFromPropertyName(links.target);
|
||||
}
|
||||
else {
|
||||
@@ -10555,6 +10574,11 @@ namespace ts {
|
||||
if (isIgnoredJsxProperty(source, prop, /*targetMemberType*/ undefined)) {
|
||||
continue;
|
||||
}
|
||||
// Skip over symbol-named members
|
||||
const nameType = getLiteralTypeFromPropertyName(prop);
|
||||
if (nameType !== undefined && !(isRelatedTo(nameType, stringType) || isRelatedTo(nameType, numberType))) {
|
||||
continue;
|
||||
}
|
||||
if (kind === IndexKind.String || isNumericLiteralName(prop.escapedName)) {
|
||||
const related = isRelatedTo(getTypeOfSymbol(prop), target, reportErrors);
|
||||
if (!related) {
|
||||
@@ -11419,8 +11443,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createInferenceContext(typeParameters: TypeParameter[], signature: Signature, flags: InferenceFlags, compareTypes?: TypeComparer, baseInferences?: InferenceInfo[]): InferenceContext {
|
||||
const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(typeParameters, createInferenceInfo);
|
||||
function createInferenceContext(typeParameters: TypeParameter[], signature: Signature | undefined, flags: InferenceFlags, compareTypes?: TypeComparer, baseInferences?: InferenceInfo[]): InferenceContext {
|
||||
const inferences = baseInferences ? baseInferences.map(cloneInferenceInfo) : typeParameters.map(createInferenceInfo);
|
||||
const context = mapper as InferenceContext;
|
||||
context.typeParameters = typeParameters;
|
||||
context.signature = signature;
|
||||
@@ -14086,7 +14110,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getContainingObjectLiteral(func: FunctionLike): ObjectLiteralExpression | undefined {
|
||||
function getContainingObjectLiteral(func: SignatureDeclaration): ObjectLiteralExpression | undefined {
|
||||
return (func.kind === SyntaxKind.MethodDeclaration ||
|
||||
func.kind === SyntaxKind.GetAccessor ||
|
||||
func.kind === SyntaxKind.SetAccessor) && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? func.parent :
|
||||
@@ -14104,7 +14128,7 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function getContextualThisParameterType(func: FunctionLike): Type {
|
||||
function getContextualThisParameterType(func: SignatureDeclaration): Type {
|
||||
if (func.kind === SyntaxKind.ArrowFunction) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -14301,7 +14325,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getContextualReturnType(functionDecl: FunctionLike): Type {
|
||||
function getContextualReturnType(functionDecl: SignatureDeclaration): Type {
|
||||
// If the containing function has a return type annotation, is a constructor, or is a get accessor whose
|
||||
// corresponding set accessor has a type annotation, return statements in the function are contextually typed
|
||||
if (functionDecl.kind === SyntaxKind.Constructor ||
|
||||
@@ -14350,9 +14374,11 @@ namespace ts {
|
||||
return node === right && isContextSensitiveAssignment(binaryExpression) ? getTypeOfExpression(left) : undefined;
|
||||
case SyntaxKind.BarBarToken:
|
||||
// When an || expression has a contextual type, the operands are contextually typed by that type. When an ||
|
||||
// expression has no contextual type, the right operand is contextually typed by the type of the left operand.
|
||||
// expression has no contextual type, the right operand is contextually typed by the type of the left operand,
|
||||
// except for the special case of Javascript declarations of the form `namespace.prop = namespace.prop || {}`
|
||||
const type = getContextualType(binaryExpression);
|
||||
return !type && node === right ? getTypeOfExpression(left, /*cache*/ true) : type;
|
||||
return !type && node === right && !getDeclaredJavascriptInitializer(binaryExpression.parent) && !getAssignedJavascriptInitializer(binaryExpression) ?
|
||||
getTypeOfExpression(left, /*cache*/ true) : type;
|
||||
case SyntaxKind.AmpersandAmpersandToken:
|
||||
case SyntaxKind.CommaToken:
|
||||
return node === right ? getContextualType(binaryExpression) : undefined;
|
||||
@@ -14375,6 +14401,7 @@ namespace ts {
|
||||
case SpecialPropertyAssignmentKind.ModuleExports:
|
||||
case SpecialPropertyAssignmentKind.PrototypeProperty:
|
||||
case SpecialPropertyAssignmentKind.ThisProperty:
|
||||
case SpecialPropertyAssignmentKind.Prototype:
|
||||
return false;
|
||||
default:
|
||||
Debug.assertNever(kind);
|
||||
@@ -14976,7 +15003,7 @@ namespace ts {
|
||||
// Grammar checking
|
||||
checkGrammarObjectLiteralExpression(node, inDestructuringPattern);
|
||||
|
||||
let propertiesTable = createSymbolTable();
|
||||
let propertiesTable: SymbolTable;
|
||||
let propertiesArray: Symbol[] = [];
|
||||
let spread: Type = emptyObjectType;
|
||||
let propagatedFlags: TypeFlags = TypeFlags.FreshLiteral;
|
||||
@@ -14984,12 +15011,22 @@ namespace ts {
|
||||
const contextualType = getApparentTypeOfContextualType(node);
|
||||
const contextualTypeHasPattern = contextualType && contextualType.pattern &&
|
||||
(contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression);
|
||||
const isJSObjectLiteral = !contextualType && isInJavaScriptFile(node);
|
||||
const isInJSFile = isInJavaScriptFile(node);
|
||||
const isJSObjectLiteral = !contextualType && isInJSFile;
|
||||
let typeFlags: TypeFlags = 0;
|
||||
let patternWithComputedProperties = false;
|
||||
let hasComputedStringProperty = false;
|
||||
let hasComputedNumberProperty = false;
|
||||
const isInJSFile = isInJavaScriptFile(node);
|
||||
if (isInJSFile && node.properties.length === 0) {
|
||||
// an empty JS object literal that nonetheless has members is a JS namespace
|
||||
const symbol = getSymbolOfNode(node);
|
||||
if (symbol.exports) {
|
||||
propertiesTable = symbol.exports;
|
||||
symbol.exports.forEach(symbol => propertiesArray.push(getMergedSymbol(symbol)));
|
||||
return createObjectLiteralType();
|
||||
}
|
||||
}
|
||||
propertiesTable = createSymbolTable();
|
||||
|
||||
let offset = 0;
|
||||
for (let i = 0; i < node.properties.length; i++) {
|
||||
@@ -16409,15 +16446,23 @@ namespace ts {
|
||||
return isValidPropertyAccessWithType(node, node.expression, property.escapedName, type)
|
||||
&& (!(property.flags & SymbolFlags.Method) || isValidMethodAccess(property, type));
|
||||
}
|
||||
function isValidMethodAccess(method: Symbol, type: Type) {
|
||||
function isValidMethodAccess(method: Symbol, actualThisType: Type): boolean {
|
||||
const propType = getTypeOfFuncClassEnumModule(method);
|
||||
const signatures = getSignaturesOfType(getNonNullableType(propType), SignatureKind.Call);
|
||||
Debug.assert(signatures.length !== 0);
|
||||
return signatures.some(sig => {
|
||||
const thisType = getThisTypeOfSignature(sig);
|
||||
return !thisType || isTypeAssignableTo(type, thisType);
|
||||
const signatureThisType = getThisTypeOfSignature(sig);
|
||||
return !signatureThisType || isTypeAssignableTo(actualThisType, getInstantiatedSignatureThisType(sig, signatureThisType, actualThisType));
|
||||
});
|
||||
}
|
||||
function getInstantiatedSignatureThisType(sig: Signature, signatureThisType: Type, actualThisType: Type): Type {
|
||||
if (!sig.typeParameters) {
|
||||
return signatureThisType;
|
||||
}
|
||||
const context = createInferenceContext(sig.typeParameters, sig, InferenceFlags.None);
|
||||
inferTypes(context.inferences, actualThisType, signatureThisType);
|
||||
return instantiateType(signatureThisType, createSignatureTypeMapper(sig, getInferredTypes(context)));
|
||||
}
|
||||
|
||||
function isValidPropertyAccessWithType(
|
||||
node: PropertyAccessExpression | QualifiedName,
|
||||
@@ -17993,20 +18038,54 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getJavaScriptClassType(symbol: Symbol): Type | undefined {
|
||||
if (isDeclarationOfFunctionOrClassExpression(symbol)) {
|
||||
symbol = getSymbolOfNode((<VariableDeclaration>symbol.valueDeclaration).initializer);
|
||||
const initializer = getDeclaredJavascriptInitializer(symbol.valueDeclaration);
|
||||
if (initializer) {
|
||||
symbol = getSymbolOfNode(initializer);
|
||||
}
|
||||
let inferred: Type | undefined;
|
||||
if (isJavaScriptConstructor(symbol.valueDeclaration)) {
|
||||
return getInferredClassType(symbol);
|
||||
inferred = getInferredClassType(symbol);
|
||||
}
|
||||
if (symbol.flags & SymbolFlags.Variable) {
|
||||
const valueType = getTypeOfSymbol(symbol);
|
||||
if (valueType.symbol && !isInferredClassType(valueType) && isJavaScriptConstructor(valueType.symbol.valueDeclaration)) {
|
||||
return getInferredClassType(valueType.symbol);
|
||||
const assigned = getAssignedClassType(symbol);
|
||||
const valueType = getTypeOfSymbol(symbol);
|
||||
if (valueType.symbol && !isInferredClassType(valueType) && isJavaScriptConstructor(valueType.symbol.valueDeclaration)) {
|
||||
inferred = getInferredClassType(valueType.symbol);
|
||||
}
|
||||
return assigned && inferred ?
|
||||
getIntersectionType([inferred, assigned]) :
|
||||
assigned || inferred;
|
||||
}
|
||||
|
||||
function getAssignedClassType(symbol: Symbol) {
|
||||
const decl = symbol.valueDeclaration;
|
||||
const assignmentSymbol = decl && decl.parent &&
|
||||
(isBinaryExpression(decl.parent) && getSymbolOfNode(decl.parent.left) ||
|
||||
isVariableDeclaration(decl.parent) && getSymbolOfNode(decl.parent));
|
||||
if (assignmentSymbol) {
|
||||
const prototype = forEach(assignmentSymbol.declarations, getAssignedJavascriptPrototype);
|
||||
if (prototype) {
|
||||
return checkExpression(prototype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getAssignedJavascriptPrototype(node: Node) {
|
||||
if (!node.parent) {
|
||||
return false;
|
||||
}
|
||||
let parent: Node = node.parent;
|
||||
while (parent && parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
parent = parent.parent;
|
||||
}
|
||||
return parent && isBinaryExpression(parent) &&
|
||||
isPropertyAccessExpression(parent.left) &&
|
||||
parent.left.name.escapedText === "prototype" &&
|
||||
parent.operatorToken.kind === SyntaxKind.EqualsToken &&
|
||||
isObjectLiteralExpression(parent.right) &&
|
||||
parent.right;
|
||||
}
|
||||
|
||||
|
||||
function getInferredClassType(symbol: Symbol) {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.inferredClassType) {
|
||||
@@ -18066,7 +18145,7 @@ namespace ts {
|
||||
|
||||
// In JavaScript files, calls to any identifier 'require' are treated as external module imports
|
||||
if (isInJavaScriptFile(node) && isCommonJsRequire(node)) {
|
||||
return resolveExternalModuleTypeByLiteral(<StringLiteral>node.arguments[0]);
|
||||
return resolveExternalModuleTypeByLiteral(node.arguments[0] as StringLiteral);
|
||||
}
|
||||
|
||||
const returnType = getReturnTypeOfSignature(signature);
|
||||
@@ -18444,27 +18523,23 @@ namespace ts {
|
||||
|
||||
function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, checkMode: CheckMode): Type[] {
|
||||
const aggregatedTypes: Type[] = [];
|
||||
const functionFlags = getFunctionFlags(func);
|
||||
const isAsync = (getFunctionFlags(func) & FunctionFlags.Async) !== 0;
|
||||
forEachYieldExpression(<Block>func.body, yieldExpression => {
|
||||
const expr = yieldExpression.expression;
|
||||
if (expr) {
|
||||
let type = checkExpressionCached(expr, checkMode);
|
||||
if (yieldExpression.asteriskToken) {
|
||||
// A yield* expression effectively yields everything that its operand yields
|
||||
type = checkIteratedTypeOrElementType(type, yieldExpression.expression, /*allowStringInput*/ false, (functionFlags & FunctionFlags.Async) !== 0);
|
||||
}
|
||||
if (functionFlags & FunctionFlags.Async) {
|
||||
type = checkAwaitedType(type, expr, yieldExpression.asteriskToken
|
||||
? Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member
|
||||
: Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
|
||||
}
|
||||
pushIfUnique(aggregatedTypes, type);
|
||||
}
|
||||
pushIfUnique(aggregatedTypes, getYieldedTypeOfYieldExpression(yieldExpression, isAsync, checkMode));
|
||||
});
|
||||
|
||||
return aggregatedTypes;
|
||||
}
|
||||
|
||||
function getYieldedTypeOfYieldExpression(node: YieldExpression, isAsync: boolean, checkMode?: CheckMode): Type {
|
||||
const errorNode = node.expression || node;
|
||||
const expressionType = node.expression ? checkExpressionCached(node.expression, checkMode) : undefinedWideningType;
|
||||
// A `yield*` expression effectively yields everything that its operand yields
|
||||
const yieldedType = node.asteriskToken ? checkIteratedTypeOrElementType(expressionType, errorNode, /*allowStringInput*/ false, isAsync) : expressionType;
|
||||
return !isAsync ? yieldedType : getAwaitedType(yieldedType, errorNode, node.asteriskToken
|
||||
? Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member
|
||||
: Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
|
||||
}
|
||||
|
||||
function isExhaustiveSwitchStatement(node: SwitchStatement): boolean {
|
||||
if (!node.possiblyExhaustive) {
|
||||
return false;
|
||||
@@ -19186,6 +19261,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkBinaryExpression(node: BinaryExpression, checkMode?: CheckMode) {
|
||||
if (isInJavaScriptFile(node) && getAssignedJavascriptInitializer(node)) {
|
||||
return checkExpression(node.right, checkMode);
|
||||
}
|
||||
return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, checkMode, node);
|
||||
}
|
||||
|
||||
@@ -19417,62 +19495,40 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (node.expression) {
|
||||
const func = getContainingFunction(node);
|
||||
// If the user's code is syntactically correct, the func should always have a star. After all,
|
||||
// we are in a yield context.
|
||||
const functionFlags = func && getFunctionFlags(func);
|
||||
if (node.asteriskToken) {
|
||||
// Async generator functions prior to ESNext require the __await, __asyncDelegator,
|
||||
// and __asyncValues helpers
|
||||
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.AsyncGenerator &&
|
||||
languageVersion < ScriptTarget.ESNext) {
|
||||
checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncDelegatorIncludes);
|
||||
}
|
||||
const func = getContainingFunction(node);
|
||||
const functionFlags = func ? getFunctionFlags(func) : FunctionFlags.Normal;
|
||||
|
||||
// Generator functions prior to ES2015 require the __values helper
|
||||
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Generator &&
|
||||
languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
|
||||
checkExternalEmitHelpers(node, ExternalEmitHelpers.Values);
|
||||
}
|
||||
if (!(functionFlags & FunctionFlags.Generator)) {
|
||||
// If the user's code is syntactically correct, the func should always have a star. After all, we are in a yield context.
|
||||
return anyType;
|
||||
}
|
||||
|
||||
if (node.asteriskToken) {
|
||||
// Async generator functions prior to ESNext require the __await, __asyncDelegator,
|
||||
// and __asyncValues helpers
|
||||
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.AsyncGenerator &&
|
||||
languageVersion < ScriptTarget.ESNext) {
|
||||
checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncDelegatorIncludes);
|
||||
}
|
||||
|
||||
if (functionFlags & FunctionFlags.Generator) {
|
||||
const expressionType = checkExpressionCached(node.expression);
|
||||
let expressionElementType: Type;
|
||||
const nodeIsYieldStar = !!node.asteriskToken;
|
||||
if (nodeIsYieldStar) {
|
||||
expressionElementType = checkIteratedTypeOrElementType(expressionType, node.expression, /*allowStringInput*/ false, (functionFlags & FunctionFlags.Async) !== 0);
|
||||
}
|
||||
|
||||
// There is no point in doing an assignability check if the function
|
||||
// has no explicit return type because the return type is directly computed
|
||||
// from the yield expressions.
|
||||
const returnType = getEffectiveReturnTypeNode(func);
|
||||
if (returnType) {
|
||||
const signatureElementType = getIteratedTypeOfGenerator(getTypeFromTypeNode(returnType), (functionFlags & FunctionFlags.Async) !== 0) || anyType;
|
||||
if (nodeIsYieldStar) {
|
||||
checkTypeAssignableTo(
|
||||
functionFlags & FunctionFlags.Async
|
||||
? getAwaitedType(expressionElementType, node.expression, Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)
|
||||
: expressionElementType,
|
||||
signatureElementType,
|
||||
node.expression,
|
||||
/*headMessage*/ undefined);
|
||||
}
|
||||
else {
|
||||
checkTypeAssignableTo(
|
||||
functionFlags & FunctionFlags.Async
|
||||
? getAwaitedType(expressionType, node.expression, Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)
|
||||
: expressionType,
|
||||
signatureElementType,
|
||||
node.expression,
|
||||
/*headMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
// Generator functions prior to ES2015 require the __values helper
|
||||
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Generator &&
|
||||
languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
|
||||
checkExternalEmitHelpers(node, ExternalEmitHelpers.Values);
|
||||
}
|
||||
}
|
||||
|
||||
const isAsync = (functionFlags & FunctionFlags.Async) !== 0;
|
||||
const yieldedType = getYieldedTypeOfYieldExpression(node, isAsync);
|
||||
// There is no point in doing an assignability check if the function
|
||||
// has no explicit return type because the return type is directly computed
|
||||
// from the yield expressions.
|
||||
const returnType = getEffectiveReturnTypeNode(func);
|
||||
if (returnType) {
|
||||
const signatureElementType = getIteratedTypeOfGenerator(getTypeFromTypeNode(returnType), isAsync) || anyType;
|
||||
checkTypeAssignableTo(yieldedType, signatureElementType, node.expression || node, /*headMessage*/ undefined);
|
||||
}
|
||||
|
||||
// Both yield and yield* expressions have type 'any'
|
||||
return anyType;
|
||||
}
|
||||
@@ -19541,10 +19597,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkDeclarationInitializer(declaration: HasExpressionInitializer) {
|
||||
const type = getTypeOfExpression(declaration.initializer, /*cache*/ true);
|
||||
const initializer = isInJavaScriptFile(declaration) && getDeclaredJavascriptInitializer(declaration) || declaration.initializer;
|
||||
const type = getTypeOfExpression(initializer, /*cache*/ true);
|
||||
return getCombinedNodeFlags(declaration) & NodeFlags.Const ||
|
||||
(getCombinedModifierFlags(declaration) & ModifierFlags.Readonly && !isParameterPropertyDeclaration(declaration)) ||
|
||||
isTypeAssertion(declaration.initializer) ? type : getWidenedLiteralType(type);
|
||||
isTypeAssertion(initializer) ? type : getWidenedLiteralType(type);
|
||||
}
|
||||
|
||||
function isLiteralOfContextualType(candidateType: Type, contextualType: Type): boolean {
|
||||
@@ -20623,12 +20680,12 @@ namespace ts {
|
||||
let hasOverloads = false;
|
||||
let bodyDeclaration: FunctionLikeDeclaration;
|
||||
let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration;
|
||||
let previousDeclaration: FunctionLike;
|
||||
let previousDeclaration: SignatureDeclaration;
|
||||
|
||||
const declarations = symbol.declarations;
|
||||
const isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0;
|
||||
|
||||
function reportImplementationExpectedError(node: FunctionLike): void {
|
||||
function reportImplementationExpectedError(node: SignatureDeclaration): void {
|
||||
if (node.name && nodeIsMissing(node.name)) {
|
||||
return;
|
||||
}
|
||||
@@ -20690,7 +20747,7 @@ namespace ts {
|
||||
let duplicateFunctionDeclaration = false;
|
||||
let multipleConstructorImplementation = false;
|
||||
for (const current of declarations) {
|
||||
const node = <FunctionLike>current;
|
||||
const node = <SignatureDeclaration>current;
|
||||
const inAmbientContext = node.flags & NodeFlags.Ambient;
|
||||
const inAmbientContextOrInterface = node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral || inAmbientContext;
|
||||
if (inAmbientContextOrInterface) {
|
||||
@@ -21603,7 +21660,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (!isRemovedPropertyFromObjectSpread(node.kind === SyntaxKind.Identifier ? node.parent : node)) {
|
||||
error(node, Diagnostics._0_is_declared_but_its_value_is_never_read, name);
|
||||
diagnostics.add(createDiagnosticForNodeSpan(getSourceFileOfNode(declaration), declaration, node, Diagnostics._0_is_declared_but_its_value_is_never_read, name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21612,7 +21669,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isIdentifierThatStartsWithUnderScore(node: Node) {
|
||||
return node.kind === SyntaxKind.Identifier && idText(<Identifier>node).charCodeAt(0) === CharacterCodes._;
|
||||
return isIdentifier(node) && idText(node).charCodeAt(0) === CharacterCodes._;
|
||||
}
|
||||
|
||||
function checkUnusedClassMembers(node: ClassDeclaration | ClassExpression): void {
|
||||
@@ -21671,18 +21728,58 @@ namespace ts {
|
||||
|
||||
function checkUnusedModuleMembers(node: ModuleDeclaration | SourceFile): void {
|
||||
if (compilerOptions.noUnusedLocals && !(node.flags & NodeFlags.Ambient)) {
|
||||
// Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value.
|
||||
const unusedImports = createMap<[ImportClause, ImportedDeclaration[]]>();
|
||||
node.locals.forEach(local => {
|
||||
if (!local.isReferenced && !local.exportSymbol) {
|
||||
for (const declaration of local.declarations) {
|
||||
if (!isAmbientModule(declaration)) {
|
||||
errorUnusedLocal(declaration, symbolName(local));
|
||||
if (local.isReferenced || local.exportSymbol) return;
|
||||
for (const declaration of local.declarations) {
|
||||
if (isAmbientModule(declaration)) continue;
|
||||
if (isImportedDeclaration(declaration)) {
|
||||
const importClause = importClauseFromImported(declaration);
|
||||
const key = String(getNodeId(importClause));
|
||||
const group = unusedImports.get(key);
|
||||
if (group) {
|
||||
group[1].push(declaration);
|
||||
}
|
||||
else {
|
||||
unusedImports.set(key, [importClause, [declaration]]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
errorUnusedLocal(declaration, symbolName(local));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
unusedImports.forEach(([importClause, unuseds]) => {
|
||||
const importDecl = importClause.parent;
|
||||
if (forEachImportedDeclaration(importClause, d => !contains(unuseds, d))) {
|
||||
for (const unused of unuseds) errorUnusedLocal(unused, idText(unused.name));
|
||||
}
|
||||
else if (unuseds.length === 1) {
|
||||
error(importDecl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(first(unuseds).name));
|
||||
}
|
||||
else {
|
||||
error(importDecl, Diagnostics.All_imports_in_import_declaration_are_unused, showModuleSpecifier(importDecl));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
type ImportedDeclaration = ImportClause | ImportSpecifier | NamespaceImport;
|
||||
function isImportedDeclaration(node: Node): node is ImportedDeclaration {
|
||||
return node.kind === SyntaxKind.ImportClause || node.kind === SyntaxKind.ImportSpecifier || node.kind === SyntaxKind.NamespaceImport;
|
||||
}
|
||||
function importClauseFromImported(decl: ImportedDeclaration): ImportClause {
|
||||
return decl.kind === SyntaxKind.ImportClause ? decl : decl.kind === SyntaxKind.NamespaceImport ? decl.parent : decl.parent.parent;
|
||||
}
|
||||
|
||||
function forEachImportedDeclaration<T>(importClause: ImportClause, cb: (im: ImportedDeclaration) => T | undefined): T | undefined {
|
||||
const { name: defaultName, namedBindings } = importClause;
|
||||
return (defaultName && cb(importClause)) ||
|
||||
namedBindings && (namedBindings.kind === SyntaxKind.NamespaceImport ? cb(namedBindings) : forEach(namedBindings.elements, cb));
|
||||
}
|
||||
|
||||
function checkBlock(node: Block) {
|
||||
// Grammar checking for SyntaxKind.Block
|
||||
if (node.kind === SyntaxKind.Block) {
|
||||
@@ -22076,7 +22173,8 @@ namespace ts {
|
||||
// Node is the primary declaration of the symbol, just validate the initializer
|
||||
// Don't validate for-in initializer as it is already an error
|
||||
if (node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) {
|
||||
checkTypeAssignableTo(checkExpressionCached(node.initializer), type, node, /*headMessage*/ undefined);
|
||||
const initializer = isInJavaScriptFile(node) && getDeclaredJavascriptInitializer(node) || node.initializer;
|
||||
checkTypeAssignableTo(checkExpressionCached(initializer), type, node, /*headMessage*/ undefined);
|
||||
checkParameterInitializer(node);
|
||||
}
|
||||
}
|
||||
@@ -22657,12 +22755,12 @@ namespace ts {
|
||||
// TODO: Check that target label is valid
|
||||
}
|
||||
|
||||
function isGetAccessorWithAnnotatedSetAccessor(node: FunctionLike) {
|
||||
function isGetAccessorWithAnnotatedSetAccessor(node: SignatureDeclaration) {
|
||||
return node.kind === SyntaxKind.GetAccessor
|
||||
&& getEffectiveSetAccessorTypeAnnotationNode(getDeclarationOfKind<SetAccessorDeclaration>(node.symbol, SyntaxKind.SetAccessor)) !== undefined;
|
||||
}
|
||||
|
||||
function isUnwrappedReturnTypeVoidOrAny(func: FunctionLike, returnType: Type): boolean {
|
||||
function isUnwrappedReturnTypeVoidOrAny(func: SignatureDeclaration, returnType: Type): boolean {
|
||||
const unwrappedReturnType = (getFunctionFlags(func) & FunctionFlags.AsyncGenerator) === FunctionFlags.Async
|
||||
? getPromisedTypeOfPromise(returnType) // Async function
|
||||
: returnType; // AsyncGenerator function, Generator function, or normal function
|
||||
@@ -22800,8 +22898,7 @@ namespace ts {
|
||||
return "quit";
|
||||
}
|
||||
if (current.kind === SyntaxKind.LabeledStatement && (<LabeledStatement>current).label.escapedText === node.label.escapedText) {
|
||||
const sourceFile = getSourceFileOfNode(node);
|
||||
grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getTextOfNodeFromSourceText(sourceFile.text, node.label));
|
||||
grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getTextOfNode(node.label));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@@ -25384,7 +25481,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isImplementationOfOverload(node: FunctionLike) {
|
||||
function isImplementationOfOverload(node: SignatureDeclaration) {
|
||||
if (nodeIsPresent((node as FunctionLikeDeclaration).body)) {
|
||||
const symbol = getSymbolOfNode(node);
|
||||
const signaturesOfSymbol = getSignaturesOfSymbol(symbol);
|
||||
|
||||
@@ -2029,7 +2029,7 @@ namespace ts {
|
||||
export function getFileNamesFromConfigSpecs(spec: ConfigFileSpecs, basePath: string, options: CompilerOptions, host: ParseConfigHost, extraFileExtensions: ReadonlyArray<JsFileExtensionInfo> = []): ExpandResult {
|
||||
basePath = normalizePath(basePath);
|
||||
|
||||
const keyMapper = host.useCaseSensitiveFileNames ? caseSensitiveKeyMapper : caseInsensitiveKeyMapper;
|
||||
const keyMapper = host.useCaseSensitiveFileNames ? identity : toLowerCase;
|
||||
|
||||
// Literal file names (provided via the "files" array in tsconfig.json) are stored in a
|
||||
// file map with a possibly case insensitive key. We use this map later when when including
|
||||
@@ -2233,24 +2233,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a case sensitive key.
|
||||
*
|
||||
* @param key The original key.
|
||||
*/
|
||||
function caseSensitiveKeyMapper(key: string) {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a case insensitive key.
|
||||
*
|
||||
* @param key The original key.
|
||||
*/
|
||||
function caseInsensitiveKeyMapper(key: string) {
|
||||
return key.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a cleaned version of compiler options with personally identifiying info (aka, paths) removed.
|
||||
* Also converts enum values back to strings.
|
||||
|
||||
+38
-3
@@ -25,6 +25,10 @@ namespace ts {
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export const emptyArray: never[] = [] as never[];
|
||||
export function closeFileWatcher(watcher: FileWatcher) {
|
||||
watcher.close();
|
||||
}
|
||||
|
||||
/** Create a MapLike with good performance. */
|
||||
function createDictionaryObject<T>(): MapLike<T> {
|
||||
const map = Object.create(/*prototype*/ null); // tslint:disable-line:no-null-keyword
|
||||
@@ -2539,7 +2543,6 @@ namespace ts {
|
||||
path = normalizePath(path);
|
||||
currentDirectory = normalizePath(currentDirectory);
|
||||
|
||||
const comparer = useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive;
|
||||
const patterns = getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory);
|
||||
|
||||
const regexFlag = useCaseSensitiveFileNames ? "" : "i";
|
||||
@@ -2560,7 +2563,7 @@ namespace ts {
|
||||
function visitDirectory(path: string, absolutePath: string, depth: number | undefined) {
|
||||
const { files, directories } = getFileSystemEntries(path);
|
||||
|
||||
for (const current of sort(files, comparer)) {
|
||||
for (const current of sort(files, compareStringsCaseSensitive)) {
|
||||
const name = combinePaths(path, current);
|
||||
const absoluteName = combinePaths(absolutePath, current);
|
||||
if (extensions && !fileExtensionIsOneOf(name, extensions)) continue;
|
||||
@@ -2583,7 +2586,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
for (const current of sort(directories, comparer)) {
|
||||
for (const current of sort(directories, compareStringsCaseSensitive)) {
|
||||
const name = combinePaths(path, current);
|
||||
const absoluteName = combinePaths(absolutePath, current);
|
||||
if ((!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) &&
|
||||
@@ -3143,4 +3146,36 @@ namespace ts {
|
||||
export function singleElementArray<T>(t: T | undefined): T[] | undefined {
|
||||
return t === undefined ? undefined : [t];
|
||||
}
|
||||
|
||||
export function enumerateInsertsAndDeletes<T, U>(newItems: ReadonlyArray<T>, oldItems: ReadonlyArray<U>, comparer: (a: T, b: U) => Comparison, inserted: (newItem: T) => void, deleted: (oldItem: U) => void, unchanged?: (oldItem: U, newItem: T) => void) {
|
||||
unchanged = unchanged || noop;
|
||||
let newIndex = 0;
|
||||
let oldIndex = 0;
|
||||
const newLen = newItems.length;
|
||||
const oldLen = oldItems.length;
|
||||
while (newIndex < newLen && oldIndex < oldLen) {
|
||||
const newItem = newItems[newIndex];
|
||||
const oldItem = oldItems[oldIndex];
|
||||
const compareResult = comparer(newItem, oldItem);
|
||||
if (compareResult === Comparison.LessThan) {
|
||||
inserted(newItem);
|
||||
newIndex++;
|
||||
}
|
||||
else if (compareResult === Comparison.GreaterThan) {
|
||||
deleted(oldItem);
|
||||
oldIndex++;
|
||||
}
|
||||
else {
|
||||
unchanged(oldItem, newItem);
|
||||
newIndex++;
|
||||
oldIndex++;
|
||||
}
|
||||
}
|
||||
while (newIndex < newLen) {
|
||||
inserted(newItems[newIndex++]);
|
||||
}
|
||||
while (oldIndex < oldLen) {
|
||||
deleted(oldItems[oldIndex++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3480,6 +3480,10 @@
|
||||
"category": "Message",
|
||||
"code": 6191
|
||||
},
|
||||
"All imports in import declaration are unused.": {
|
||||
"category": "Error",
|
||||
"code": 6192
|
||||
},
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
"code": 7005
|
||||
@@ -3851,6 +3855,10 @@
|
||||
"category": "Message",
|
||||
"code": 90004
|
||||
},
|
||||
"Remove import from '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 90005
|
||||
},
|
||||
"Implement interface '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 90006
|
||||
|
||||
@@ -4266,16 +4266,6 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function skipParentheses(node: Expression): Expression;
|
||||
export function skipParentheses(node: Node): Node;
|
||||
export function skipParentheses(node: Node): Node {
|
||||
while (node.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
node = (<ParenthesizedExpression>node).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function skipAssertions(node: Expression): Expression;
|
||||
export function skipAssertions(node: Node): Node;
|
||||
export function skipAssertions(node: Node): Node {
|
||||
|
||||
+728
-248
File diff suppressed because it is too large
Load Diff
@@ -1780,7 +1780,7 @@ namespace ts {
|
||||
return createArrayLiteral(expressions);
|
||||
}
|
||||
|
||||
function getParametersOfDecoratedDeclaration(node: FunctionLike, container: ClassLikeDeclaration) {
|
||||
function getParametersOfDecoratedDeclaration(node: SignatureDeclaration, container: ClassLikeDeclaration) {
|
||||
if (container && node.kind === SyntaxKind.GetAccessor) {
|
||||
const { setAccessor } = getAllAccessorDeclarations(container.members, <AccessorDeclaration>node);
|
||||
if (setAccessor) {
|
||||
|
||||
@@ -399,4 +399,8 @@ if (ts.Debug.isDebugging) {
|
||||
if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) {
|
||||
ts.sys.tryEnableSourceMapsForHost();
|
||||
}
|
||||
declare var process: any;
|
||||
if (process && process.stdout && process.stdout._handle && process.stdout._handle.setBlocking) {
|
||||
process.stdout._handle.setBlocking(true);
|
||||
}
|
||||
ts.executeCommandLine(ts.sys.args);
|
||||
|
||||
+12
-27
@@ -967,15 +967,8 @@ namespace ts {
|
||||
| SetAccessorDeclaration
|
||||
| FunctionExpression
|
||||
| ArrowFunction;
|
||||
export type FunctionLike =
|
||||
| FunctionLikeDeclaration
|
||||
| FunctionTypeNode
|
||||
| ConstructorTypeNode
|
||||
| IndexSignatureDeclaration
|
||||
| MethodSignature
|
||||
| ConstructSignatureDeclaration
|
||||
| CallSignatureDeclaration
|
||||
| JSDocFunctionType;
|
||||
/** @deprecated Use SignatureDeclaration */
|
||||
export type FunctionLike = SignatureDeclaration;
|
||||
|
||||
export interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement {
|
||||
kind: SyntaxKind.FunctionDeclaration;
|
||||
@@ -2793,6 +2786,7 @@ namespace ts {
|
||||
|
||||
/** Note that the resulting nodes cannot be checked. */
|
||||
typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode;
|
||||
/* @internal */ typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker): TypeNode; // tslint:disable-line unified-signatures
|
||||
/** Note that the resulting nodes cannot be checked. */
|
||||
signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): SignatureDeclaration & {typeArguments?: NodeArray<TypeNode>} | undefined;
|
||||
/** Note that the resulting nodes cannot be checked. */
|
||||
@@ -2855,7 +2849,7 @@ namespace ts {
|
||||
*/
|
||||
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature;
|
||||
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined;
|
||||
isImplementationOfOverload(node: FunctionLike): boolean | undefined;
|
||||
isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined;
|
||||
isUndefinedSymbol(symbol: Symbol): boolean;
|
||||
isArgumentsSymbol(symbol: Symbol): boolean;
|
||||
isUnknownSymbol(symbol: Symbol): boolean;
|
||||
@@ -3259,8 +3253,8 @@ namespace ts {
|
||||
|
||||
Enum = RegularEnum | ConstEnum,
|
||||
Variable = FunctionScopedVariable | BlockScopedVariable,
|
||||
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
|
||||
Type = Class | Interface | Enum | EnumMember | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias,
|
||||
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor | JSContainer,
|
||||
Type = Class | Interface | Enum | EnumMember | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias | JSContainer,
|
||||
Namespace = ValueModule | NamespaceModule | Enum,
|
||||
Module = ValueModule | NamespaceModule,
|
||||
Accessor = GetAccessor | SetAccessor,
|
||||
@@ -3999,7 +3993,9 @@ namespace ts {
|
||||
/// this.name = expr
|
||||
ThisProperty,
|
||||
// F.name = expr
|
||||
Property
|
||||
Property,
|
||||
// F.prototype = { ... }
|
||||
Prototype,
|
||||
}
|
||||
|
||||
export interface JsFileExtensionInfo {
|
||||
@@ -5003,12 +4999,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface EmitTextWriter extends SymbolTracker, SymbolWriter {
|
||||
export interface EmitTextWriter extends SymbolWriter {
|
||||
write(s: string): void;
|
||||
writeTextOfNode(text: string, node: Node): void;
|
||||
writeLine(): void;
|
||||
increaseIndent(): void;
|
||||
decreaseIndent(): void;
|
||||
getText(): string;
|
||||
rawWrite(s: string): void;
|
||||
writeLiteral(s: string): void;
|
||||
@@ -5017,18 +5010,10 @@ namespace ts {
|
||||
getColumn(): number;
|
||||
getIndent(): number;
|
||||
isAtStartOfLine(): boolean;
|
||||
clear(): void;
|
||||
|
||||
writeKeyword(text: string): void;
|
||||
writeOperator(text: string): void;
|
||||
writePunctuation(text: string): void;
|
||||
writeSpace(text: string): void;
|
||||
writeStringLiteral(text: string): void;
|
||||
writeParameter(text: string): void;
|
||||
writeProperty(text: string): void;
|
||||
writeSymbol(text: string, symbol: Symbol): void;
|
||||
}
|
||||
|
||||
/** @deprecated See comment on SymbolWriter */
|
||||
// Note: this has non-deprecated internal uses.
|
||||
export interface SymbolTracker {
|
||||
// Called when the symbol writer encounters a symbol to write. Currently only used by the
|
||||
// declaration emitter to help determine if it should patch up the final declaration file
|
||||
|
||||
+208
-87
@@ -314,20 +314,15 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node, includeTrivia = false): string {
|
||||
if (nodeIsMissing(node)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const text = sourceFile.text;
|
||||
return text.substring(includeTrivia ? node.pos : skipTrivia(text, node.pos), node.end);
|
||||
return getTextOfNodeFromSourceText(sourceFile.text, node, includeTrivia);
|
||||
}
|
||||
|
||||
export function getTextOfNodeFromSourceText(sourceText: string, node: Node): string {
|
||||
export function getTextOfNodeFromSourceText(sourceText: string, node: Node, includeTrivia = false): string {
|
||||
if (nodeIsMissing(node)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return sourceText.substring(skipTrivia(sourceText, node.pos), node.end);
|
||||
return sourceText.substring(includeTrivia ? node.pos : skipTrivia(sourceText, node.pos), node.end);
|
||||
}
|
||||
|
||||
export function getTextOfNode(node: Node, includeTrivia = false): string {
|
||||
@@ -607,6 +602,11 @@ namespace ts {
|
||||
return createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
export function createDiagnosticForNodeSpan(sourceFile: SourceFile, startNode: Node, endNode: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic {
|
||||
const start = skipTrivia(sourceFile.text, startNode.pos);
|
||||
return createFileDiagnostic(sourceFile, start, endNode.end - start, message, arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain): Diagnostic {
|
||||
const sourceFile = getSourceFileOfNode(node);
|
||||
const span = getErrorSpanForNode(sourceFile, node);
|
||||
@@ -1035,7 +1035,7 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
export function getContainingFunction(node: Node): FunctionLike {
|
||||
export function getContainingFunction(node: Node): SignatureDeclaration {
|
||||
return findAncestor(node.parent, isFunctionLike);
|
||||
}
|
||||
|
||||
@@ -1199,7 +1199,7 @@ namespace ts {
|
||||
&& (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.ThisKeyword;
|
||||
}
|
||||
|
||||
export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression {
|
||||
export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
return (<TypeReferenceNode>node).typeName;
|
||||
@@ -1472,13 +1472,115 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the node is a variable declaration whose initializer is a function or class expression.
|
||||
* This function does not test if the node is in a JavaScript file or not.
|
||||
* Given the symbol of a declaration, find the symbol of its Javascript container-like initializer,
|
||||
* if it has one. Otherwise just return the original symbol.
|
||||
*
|
||||
* Container-like initializer behave like namespaces, so the binder needs to add contained symbols
|
||||
* to their exports. An example is a function with assignments to `this` inside.
|
||||
*/
|
||||
export function isDeclarationOfFunctionOrClassExpression(s: Symbol) {
|
||||
if (s.valueDeclaration && s.valueDeclaration.kind === SyntaxKind.VariableDeclaration) {
|
||||
const declaration = s.valueDeclaration as VariableDeclaration;
|
||||
return declaration.initializer && (declaration.initializer.kind === SyntaxKind.FunctionExpression || declaration.initializer.kind === SyntaxKind.ClassExpression);
|
||||
export function getJSInitializerSymbol(symbol: Symbol) {
|
||||
if (!symbol || !symbol.valueDeclaration) {
|
||||
return symbol;
|
||||
}
|
||||
const declaration = symbol.valueDeclaration;
|
||||
const e = getDeclaredJavascriptInitializer(declaration) || getAssignedJavascriptInitializer(declaration);
|
||||
return e && e.symbol ? e.symbol : symbol;
|
||||
}
|
||||
|
||||
/** Get the declaration initializer, when the initializer is container-like (See getJavascriptInitializer) */
|
||||
export function getDeclaredJavascriptInitializer(node: Node) {
|
||||
if (node && isVariableDeclaration(node) && node.initializer) {
|
||||
return getJavascriptInitializer(node.initializer, /*isPrototypeAssignment*/ false) ||
|
||||
isIdentifier(node.name) && getDefaultedJavascriptInitializer(node.name, node.initializer, /*isPrototypeAssignment*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the assignment 'initializer' -- the righthand side-- when the initializer is container-like (See getJavascriptInitializer).
|
||||
* We treat the right hand side of assignments with container-like initalizers as declarations.
|
||||
*/
|
||||
export function getAssignedJavascriptInitializer(node: Node) {
|
||||
if (node && node.parent && isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.EqualsToken) {
|
||||
const isPrototypeAssignment = isPropertyAccessExpression(node.parent.left) && node.parent.left.name.escapedText === "prototype";
|
||||
return getJavascriptInitializer(node.parent.right, isPrototypeAssignment) ||
|
||||
getDefaultedJavascriptInitializer(node.parent.left as EntityNameExpression, node.parent.right, isPrototypeAssignment);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recognized Javascript container-like initializers are:
|
||||
* 1. (function() {})() -- IIFEs
|
||||
* 2. function() { } -- Function expressions
|
||||
* 3. class { } -- Class expressions
|
||||
* 4. {} -- Empty object literals
|
||||
* 5. { ... } -- Non-empty object literals, when used to initialize a prototype, like `C.prototype = { m() { } }`
|
||||
*
|
||||
* This function returns the provided initializer, or undefined if it is not valid.
|
||||
*/
|
||||
export function getJavascriptInitializer(initializer: Node, isPrototypeAssignment: boolean): Expression {
|
||||
if (isCallExpression(initializer)) {
|
||||
const e = skipParentheses(initializer.expression);
|
||||
return e.kind === SyntaxKind.FunctionExpression || e.kind === SyntaxKind.ArrowFunction ? initializer : undefined;
|
||||
}
|
||||
if (initializer.kind === SyntaxKind.FunctionExpression || initializer.kind === SyntaxKind.ClassExpression) {
|
||||
return initializer as Expression;
|
||||
}
|
||||
if (isObjectLiteralExpression(initializer) && (initializer.properties.length === 0 || isPrototypeAssignment)) {
|
||||
return initializer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A defaulted Javascript initializer matches the pattern
|
||||
* `Lhs = Lhs || JavascriptInitializer`
|
||||
* or `var Lhs = Lhs || JavascriptInitializer`
|
||||
*
|
||||
* The second Lhs is required to be the same as the first except that it may be prefixed with
|
||||
* 'window.', 'global.' or 'self.' The second Lhs is otherwise ignored by the binder and checker.
|
||||
*/
|
||||
function getDefaultedJavascriptInitializer(name: EntityNameExpression, initializer: Expression, isPrototypeAssignment: boolean) {
|
||||
const e = isBinaryExpression(initializer) && initializer.operatorToken.kind === SyntaxKind.BarBarToken && getJavascriptInitializer(initializer.right, isPrototypeAssignment);
|
||||
if (e && isSameEntityName(name, (initializer as BinaryExpression).left as EntityNameExpression)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
/** Given a Javascript initializer, return the outer name. That is, the lhs of the assignment or the declaration name. */
|
||||
export function getOuterNameOfJsInitializer(node: Declaration): DeclarationName | undefined {
|
||||
if (isBinaryExpression(node.parent)) {
|
||||
const parent = (node.parent.operatorToken.kind === SyntaxKind.BarBarToken && isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent;
|
||||
if (parent.operatorToken.kind === SyntaxKind.EqualsToken && isIdentifier(parent.left)) {
|
||||
return parent.left;
|
||||
}
|
||||
}
|
||||
else if (isVariableDeclaration(node.parent)) {
|
||||
return node.parent.name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the 'declared' name the same as the one in the initializer?
|
||||
* @return true for identical entity names, as well as ones where the initializer is prefixed with
|
||||
* 'window', 'self' or 'global'. For example:
|
||||
*
|
||||
* var my = my || {}
|
||||
* var min = window.min || {}
|
||||
* my.app = self.my.app || class { }
|
||||
*/
|
||||
function isSameEntityName(name: EntityNameExpression, initializer: EntityNameExpression): boolean {
|
||||
if (isIdentifier(name) && isIdentifier(initializer)) {
|
||||
return name.escapedText === initializer.escapedText;
|
||||
}
|
||||
if (isIdentifier(name) && isPropertyAccessExpression(initializer)) {
|
||||
return (initializer.expression.kind as SyntaxKind.ThisKeyword === SyntaxKind.ThisKeyword ||
|
||||
isIdentifier(initializer.expression) &&
|
||||
(initializer.expression.escapedText === "window" as __String ||
|
||||
initializer.expression.escapedText === "self" as __String ||
|
||||
initializer.expression.escapedText === "global" as __String)) &&
|
||||
isSameEntityName(name, initializer.name);
|
||||
}
|
||||
if (isPropertyAccessExpression(name) && isPropertyAccessExpression(initializer)) {
|
||||
return name.name.escapedText === initializer.name.escapedText && isSameEntityName(name.expression, initializer.expression);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1501,46 +1603,43 @@ namespace ts {
|
||||
/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
|
||||
/// assignments we treat as special in the binder
|
||||
export function getSpecialPropertyAssignmentKind(expr: BinaryExpression): SpecialPropertyAssignmentKind {
|
||||
if (!isInJavaScriptFile(expr)) {
|
||||
if (!isInJavaScriptFile(expr) ||
|
||||
expr.operatorToken.kind !== SyntaxKind.EqualsToken ||
|
||||
!isPropertyAccessExpression(expr.left)) {
|
||||
return SpecialPropertyAssignmentKind.None;
|
||||
}
|
||||
if (expr.operatorToken.kind !== SyntaxKind.EqualsToken || expr.left.kind !== SyntaxKind.PropertyAccessExpression) {
|
||||
return SpecialPropertyAssignmentKind.None;
|
||||
}
|
||||
const lhs = <PropertyAccessExpression>expr.left;
|
||||
if (lhs.expression.kind === SyntaxKind.Identifier) {
|
||||
const lhsId = <Identifier>lhs.expression;
|
||||
if (lhsId.escapedText === "exports") {
|
||||
// exports.name = expr
|
||||
return SpecialPropertyAssignmentKind.ExportsProperty;
|
||||
}
|
||||
else if (lhsId.escapedText === "module" && lhs.name.escapedText === "exports") {
|
||||
// module.exports = expr
|
||||
return SpecialPropertyAssignmentKind.ModuleExports;
|
||||
}
|
||||
else {
|
||||
// F.x = expr
|
||||
return SpecialPropertyAssignmentKind.Property;
|
||||
}
|
||||
}
|
||||
else if (lhs.expression.kind === SyntaxKind.ThisKeyword) {
|
||||
const lhs = expr.left;
|
||||
if (lhs.expression.kind === SyntaxKind.ThisKeyword) {
|
||||
return SpecialPropertyAssignmentKind.ThisProperty;
|
||||
}
|
||||
else if (lhs.expression.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
// chained dot, e.g. x.y.z = expr; this var is the 'x.y' part
|
||||
const innerPropertyAccess = <PropertyAccessExpression>lhs.expression;
|
||||
if (innerPropertyAccess.expression.kind === SyntaxKind.Identifier) {
|
||||
// module.exports.name = expr
|
||||
const innerPropertyAccessIdentifier = <Identifier>innerPropertyAccess.expression;
|
||||
if (innerPropertyAccessIdentifier.escapedText === "module" && innerPropertyAccess.name.escapedText === "exports") {
|
||||
return SpecialPropertyAssignmentKind.ExportsProperty;
|
||||
}
|
||||
if (innerPropertyAccess.name.escapedText === "prototype") {
|
||||
return SpecialPropertyAssignmentKind.PrototypeProperty;
|
||||
}
|
||||
}
|
||||
else if (isIdentifier(lhs.expression) && lhs.expression.escapedText === "module" && lhs.name.escapedText === "exports") {
|
||||
// module.exports = expr
|
||||
return SpecialPropertyAssignmentKind.ModuleExports;
|
||||
}
|
||||
else if (isEntityNameExpression(lhs.expression)) {
|
||||
if (lhs.name.escapedText === "prototype" && isObjectLiteralExpression(expr.right)) {
|
||||
// F.prototype = { ... }
|
||||
return SpecialPropertyAssignmentKind.Prototype;
|
||||
}
|
||||
else if (isPropertyAccessExpression(lhs.expression) && lhs.expression.name.escapedText === "prototype") {
|
||||
// F.G....prototype.x = expr
|
||||
return SpecialPropertyAssignmentKind.PrototypeProperty;
|
||||
}
|
||||
|
||||
let nextToLast = lhs;
|
||||
while (isPropertyAccessExpression(nextToLast.expression)) {
|
||||
nextToLast = nextToLast.expression;
|
||||
}
|
||||
Debug.assert(isIdentifier(nextToLast.expression));
|
||||
const id = nextToLast.expression as Identifier;
|
||||
if (id.escapedText === "exports" ||
|
||||
id.escapedText === "module" && nextToLast.name.escapedText === "exports") {
|
||||
// exports.name = expr OR module.exports.name = expr
|
||||
return SpecialPropertyAssignmentKind.ExportsProperty;
|
||||
}
|
||||
// F.G...x = expr
|
||||
return SpecialPropertyAssignmentKind.Property;
|
||||
}
|
||||
|
||||
return SpecialPropertyAssignmentKind.None;
|
||||
}
|
||||
@@ -1617,6 +1716,15 @@ namespace ts {
|
||||
node.expression.right;
|
||||
}
|
||||
|
||||
function getSourceOfDefaultedAssignment(node: Node): Node {
|
||||
return isExpressionStatement(node) &&
|
||||
isBinaryExpression(node.expression) &&
|
||||
getSpecialPropertyAssignmentKind(node.expression) !== SpecialPropertyAssignmentKind.None &&
|
||||
isBinaryExpression(node.expression.right) &&
|
||||
node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken &&
|
||||
node.expression.right.right;
|
||||
}
|
||||
|
||||
function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node: Node): Expression | undefined {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VariableStatement:
|
||||
@@ -1660,7 +1768,8 @@ namespace ts {
|
||||
(getSingleVariableOfVariableStatement(parent.parent) === node || getSourceOfAssignment(parent.parent))) {
|
||||
getJSDocCommentsAndTagsWorker(parent.parent);
|
||||
}
|
||||
if (parent && parent.parent && parent.parent.parent && getSingleInitializerOfVariableStatementOrPropertyDeclaration(parent.parent.parent) === node) {
|
||||
if (parent && parent.parent && parent.parent.parent &&
|
||||
(getSingleInitializerOfVariableStatementOrPropertyDeclaration(parent.parent.parent) === node || getSourceOfDefaultedAssignment(parent.parent.parent))) {
|
||||
getJSDocCommentsAndTagsWorker(parent.parent.parent);
|
||||
}
|
||||
if (isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) !== SpecialPropertyAssignmentKind.None ||
|
||||
@@ -1700,9 +1809,10 @@ namespace ts {
|
||||
return parameter && parameter.symbol;
|
||||
}
|
||||
|
||||
export function getHostSignatureFromJSDoc(node: JSDocParameterTag): FunctionLike | undefined {
|
||||
export function getHostSignatureFromJSDoc(node: JSDocParameterTag): SignatureDeclaration | undefined {
|
||||
const host = getJSDocHost(node);
|
||||
const decl = getSourceOfAssignment(host) ||
|
||||
const decl = getSourceOfDefaultedAssignment(host) ||
|
||||
getSourceOfAssignment(host) ||
|
||||
getSingleInitializerOfVariableStatementOrPropertyDeclaration(host) ||
|
||||
getSingleVariableOfVariableStatement(host) ||
|
||||
getNestedModuleDeclaration(host) ||
|
||||
@@ -1843,6 +1953,16 @@ namespace ts {
|
||||
return walkUp(node, SyntaxKind.ParenthesizedExpression);
|
||||
}
|
||||
|
||||
export function skipParentheses(node: Expression): Expression;
|
||||
export function skipParentheses(node: Node): Node;
|
||||
export function skipParentheses(node: Node): Node {
|
||||
while (node.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
node = (<ParenthesizedExpression>node).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// a node is delete target iff. it is PropertyAccessExpression/ElementAccessExpression with parentheses skipped
|
||||
export function isDeleteTarget(node: Node): boolean {
|
||||
if (node.kind !== SyntaxKind.PropertyAccessExpression && node.kind !== SyntaxKind.ElementAccessExpression) {
|
||||
@@ -2024,7 +2144,7 @@ namespace ts {
|
||||
AsyncGenerator = Async | Generator, // Function is an async generator function
|
||||
}
|
||||
|
||||
export function getFunctionFlags(node: FunctionLike | undefined) {
|
||||
export function getFunctionFlags(node: SignatureDeclaration | undefined) {
|
||||
if (!node) {
|
||||
return FunctionFlags.Invalid;
|
||||
}
|
||||
@@ -2466,7 +2586,6 @@ namespace ts {
|
||||
const singleQuoteEscapedCharsRegExp = /[\\\'\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
const backtickQuoteEscapedCharsRegExp = /[\\\`\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
const escapedCharsMap = createMapFromTemplate({
|
||||
"\0": "\\0",
|
||||
"\t": "\\t",
|
||||
"\v": "\\v",
|
||||
"\f": "\\f",
|
||||
@@ -2481,7 +2600,6 @@ namespace ts {
|
||||
"\u2029": "\\u2029", // paragraphSeparator
|
||||
"\u0085": "\\u0085" // nextLine
|
||||
});
|
||||
const escapedNullRegExp = /\\0[0-9]/g;
|
||||
|
||||
/**
|
||||
* Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2),
|
||||
@@ -2493,14 +2611,19 @@ namespace ts {
|
||||
quoteChar === CharacterCodes.backtick ? backtickQuoteEscapedCharsRegExp :
|
||||
quoteChar === CharacterCodes.singleQuote ? singleQuoteEscapedCharsRegExp :
|
||||
doubleQuoteEscapedCharsRegExp;
|
||||
return s.replace(escapedCharsRegExp, getReplacement).replace(escapedNullRegExp, nullReplacement);
|
||||
return s.replace(escapedCharsRegExp, getReplacement);
|
||||
}
|
||||
|
||||
function nullReplacement(c: string) {
|
||||
return "\\x00" + c.charAt(c.length - 1);
|
||||
}
|
||||
|
||||
function getReplacement(c: string) {
|
||||
function getReplacement(c: string, offset: number, input: string) {
|
||||
if (c.charCodeAt(0) === CharacterCodes.nullCharacter) {
|
||||
const lookAhead = input.charCodeAt(offset + c.length);
|
||||
if (lookAhead >= CharacterCodes._0 && lookAhead <= CharacterCodes._9) {
|
||||
// If the null character is followed by digits, print as a hex escape to prevent the result from parsing as an octal (which is forbidden in strict mode)
|
||||
return "\\x00";
|
||||
}
|
||||
// Otherwise, keep printing a literal \0 for the null character
|
||||
return "\\0";
|
||||
}
|
||||
return escapedCharsMap.get(c) || get16BitUnicodeEscapeSequence(c.charCodeAt(0));
|
||||
}
|
||||
|
||||
@@ -2834,49 +2957,38 @@ namespace ts {
|
||||
* Gets the effective type annotation of a variable, parameter, or property. If the node was
|
||||
* parsed in a JavaScript file, gets the type annotation from JSDoc.
|
||||
*/
|
||||
export function getEffectiveTypeAnnotationNode(node: Node, checkJSDoc?: boolean): TypeNode | undefined {
|
||||
if (hasType(node)) {
|
||||
return node.type;
|
||||
}
|
||||
if (checkJSDoc || isInJavaScriptFile(node)) {
|
||||
return getJSDocType(node);
|
||||
}
|
||||
export function getEffectiveTypeAnnotationNode(node: Node): TypeNode | undefined {
|
||||
return (node as HasType).type || (isInJavaScriptFile(node) ? getJSDocType(node) : undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the effective return type annotation of a signature. If the node was parsed in a
|
||||
* JavaScript file, gets the return type annotation from JSDoc.
|
||||
*/
|
||||
export function getEffectiveReturnTypeNode(node: SignatureDeclaration, checkJSDoc?: boolean): TypeNode | undefined {
|
||||
if (node.type) {
|
||||
return node.type;
|
||||
}
|
||||
if (checkJSDoc || isInJavaScriptFile(node)) {
|
||||
return getJSDocReturnType(node);
|
||||
}
|
||||
export function getEffectiveReturnTypeNode(node: SignatureDeclaration): TypeNode | undefined {
|
||||
return node.type || (isInJavaScriptFile(node) ? getJSDocReturnType(node) : undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the effective type parameters. If the node was parsed in a
|
||||
* JavaScript file, gets the type parameters from the `@template` tag from JSDoc.
|
||||
*/
|
||||
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters, checkJSDoc?: boolean): ReadonlyArray<TypeParameterDeclaration> {
|
||||
if (node.typeParameters) {
|
||||
return node.typeParameters;
|
||||
}
|
||||
if (checkJSDoc || isInJavaScriptFile(node)) {
|
||||
const templateTag = getJSDocTemplateTag(node);
|
||||
return templateTag && templateTag.typeParameters;
|
||||
}
|
||||
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): ReadonlyArray<TypeParameterDeclaration> | undefined {
|
||||
return node.typeParameters || (isInJavaScriptFile(node) ? getJSDocTypeParameterDeclarations(node) : undefined);
|
||||
}
|
||||
|
||||
export function getJSDocTypeParameterDeclarations(node: DeclarationWithTypeParameters): ReadonlyArray<TypeParameterDeclaration> {
|
||||
const templateTag = getJSDocTemplateTag(node);
|
||||
return templateTag && templateTag.typeParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the effective type annotation of the value parameter of a set accessor. If the node
|
||||
* was parsed in a JavaScript file, gets the type annotation from JSDoc.
|
||||
*/
|
||||
export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration, checkJSDoc?: boolean): TypeNode {
|
||||
export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration): TypeNode {
|
||||
const parameter = getSetAccessorValueParameter(node);
|
||||
return parameter && getEffectiveTypeAnnotationNode(parameter, checkJSDoc);
|
||||
return parameter && getEffectiveTypeAnnotationNode(parameter);
|
||||
}
|
||||
|
||||
export function emitNewLineBeforeLeadingComments(lineMap: ReadonlyArray<number>, writer: EmitTextWriter, node: TextRange, leadingComments: ReadonlyArray<CommentRange>) {
|
||||
@@ -3723,6 +3835,10 @@ namespace ts {
|
||||
export function isUMDExportSymbol(symbol: Symbol) {
|
||||
return symbol && symbol.declarations && symbol.declarations[0] && isNamespaceExportDeclaration(symbol.declarations[0]);
|
||||
}
|
||||
|
||||
export function showModuleSpecifier({ moduleSpecifier }: ImportDeclaration): string {
|
||||
return isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : getTextOfNode(moduleSpecifier);
|
||||
}
|
||||
}
|
||||
|
||||
namespace ts {
|
||||
@@ -4238,6 +4354,11 @@ namespace ts {
|
||||
return declaration.name || nameForNamelessJSDocTypedef(declaration);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isNamedDeclaration(node: Node): node is NamedDeclaration & { name: DeclarationName } {
|
||||
return !!(node as NamedDeclaration).name; // A 'name' property should always be a DeclarationName.
|
||||
}
|
||||
|
||||
export function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined {
|
||||
if (!declaration) {
|
||||
return undefined;
|
||||
@@ -5188,7 +5309,7 @@ namespace ts {
|
||||
|
||||
// Functions
|
||||
|
||||
export function isFunctionLike(node: Node): node is FunctionLike {
|
||||
export function isFunctionLike(node: Node): node is SignatureDeclaration {
|
||||
return node && isFunctionLikeKind(node.kind);
|
||||
}
|
||||
|
||||
|
||||
+11
-12
@@ -483,18 +483,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
const trace = host.trace && ((s: string) => { host.trace(s + newLine); });
|
||||
const loggingEnabled = trace && (compilerOptions.diagnostics || compilerOptions.extendedDiagnostics);
|
||||
const writeLog = loggingEnabled ? trace : noop;
|
||||
const watchFile = compilerOptions.extendedDiagnostics ? addFileWatcherWithLogging : loggingEnabled ? addFileWatcherWithOnlyTriggerLogging : addFileWatcher;
|
||||
const watchFilePath = compilerOptions.extendedDiagnostics ? addFilePathWatcherWithLogging : addFilePathWatcher;
|
||||
const watchDirectoryWorker = compilerOptions.extendedDiagnostics ? addDirectoryWatcherWithLogging : addDirectoryWatcher;
|
||||
const watchLogLevel = trace ? compilerOptions.extendedDiagnostics ? WatchLogLevel.Verbose :
|
||||
compilerOptions.diagnostis ? WatchLogLevel.TriggerOnly : WatchLogLevel.None : WatchLogLevel.None;
|
||||
const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? trace : noop;
|
||||
const { watchFile, watchFilePath, watchDirectory: watchDirectoryWorker } = getWatchFactory(watchLogLevel, writeLog);
|
||||
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
let newLine = updateNewLine();
|
||||
|
||||
writeLog(`Current directory: ${currentDirectory} CaseSensitiveFileNames: ${useCaseSensitiveFileNames}`);
|
||||
if (configFileName) {
|
||||
watchFile(host, configFileName, scheduleProgramReload, writeLog);
|
||||
watchFile(host, configFileName, scheduleProgramReload, PollingInterval.High);
|
||||
}
|
||||
|
||||
const compilerHost: CompilerHost & ResolutionCacheHost = {
|
||||
@@ -583,8 +582,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Compile the program
|
||||
if (loggingEnabled) {
|
||||
writeLog(`CreatingProgramWith::`);
|
||||
if (watchLogLevel !== WatchLogLevel.None) {
|
||||
writeLog("CreatingProgramWith::");
|
||||
writeLog(` roots: ${JSON.stringify(rootFileNames)}`);
|
||||
writeLog(` options: ${JSON.stringify(compilerOptions)}`);
|
||||
}
|
||||
@@ -677,7 +676,7 @@ namespace ts {
|
||||
(hostSourceFile as FilePresentOnHost).sourceFile = sourceFile;
|
||||
sourceFile.version = hostSourceFile.version.toString();
|
||||
if (!(hostSourceFile as FilePresentOnHost).fileWatcher) {
|
||||
(hostSourceFile as FilePresentOnHost).fileWatcher = watchFilePath(host, fileName, onSourceFileChange, path, writeLog);
|
||||
(hostSourceFile as FilePresentOnHost).fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -691,7 +690,7 @@ namespace ts {
|
||||
else {
|
||||
if (sourceFile) {
|
||||
sourceFile.version = initialVersion.toString();
|
||||
const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, path, writeLog);
|
||||
const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path);
|
||||
sourceFilesCache.set(path, { sourceFile, version: initialVersion, fileWatcher });
|
||||
}
|
||||
else {
|
||||
@@ -854,11 +853,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function watchDirectory(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags) {
|
||||
return watchDirectoryWorker(host, directory, cb, flags, writeLog);
|
||||
return watchDirectoryWorker(host, directory, cb, flags);
|
||||
}
|
||||
|
||||
function watchMissingFilePath(missingFilePath: Path) {
|
||||
return watchFilePath(host, missingFilePath, onMissingFileChange, missingFilePath, writeLog);
|
||||
return watchFilePath(host, missingFilePath, onMissingFileChange, PollingInterval.Medium, missingFilePath);
|
||||
}
|
||||
|
||||
function onMissingFileChange(fileName: string, eventKind: FileWatcherEventKind, missingFilePath: Path) {
|
||||
|
||||
@@ -331,85 +331,101 @@ namespace ts {
|
||||
return program.isEmittedFile(file);
|
||||
}
|
||||
|
||||
export enum WatchLogLevel {
|
||||
None,
|
||||
TriggerOnly,
|
||||
Verbose
|
||||
}
|
||||
|
||||
export interface WatchFileHost {
|
||||
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
|
||||
}
|
||||
|
||||
export function addFileWatcher(host: WatchFileHost, file: string, cb: FileWatcherCallback): FileWatcher {
|
||||
return host.watchFile(file, cb);
|
||||
}
|
||||
|
||||
export function addFileWatcherWithLogging(host: WatchFileHost, file: string, cb: FileWatcherCallback, log: (s: string) => void): FileWatcher {
|
||||
const watcherCaption = `FileWatcher:: `;
|
||||
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, file, cb);
|
||||
}
|
||||
|
||||
export function addFileWatcherWithOnlyTriggerLogging(host: WatchFileHost, file: string, cb: FileWatcherCallback, log: (s: string) => void): FileWatcher {
|
||||
const watcherCaption = `FileWatcher:: `;
|
||||
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, file, cb);
|
||||
}
|
||||
|
||||
export type FilePathWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind, filePath: Path) => void;
|
||||
export function addFilePathWatcher(host: WatchFileHost, file: string, cb: FilePathWatcherCallback, path: Path): FileWatcher {
|
||||
return host.watchFile(file, (fileName, eventKind) => cb(fileName, eventKind, path));
|
||||
}
|
||||
|
||||
export function addFilePathWatcherWithLogging(host: WatchFileHost, file: string, cb: FilePathWatcherCallback, path: Path, log: (s: string) => void): FileWatcher {
|
||||
const watcherCaption = `FileWatcher:: `;
|
||||
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, file, cb, path);
|
||||
}
|
||||
|
||||
export function addFilePathWatcherWithOnlyTriggerLogging(host: WatchFileHost, file: string, cb: FilePathWatcherCallback, path: Path, log: (s: string) => void): FileWatcher {
|
||||
const watcherCaption = `FileWatcher:: `;
|
||||
return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, file, cb, path);
|
||||
}
|
||||
|
||||
export interface WatchDirectoryHost {
|
||||
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
|
||||
}
|
||||
export type WatchFile<X, Y> = (host: WatchFileHost, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type FilePathWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind, filePath: Path) => void;
|
||||
export type WatchFilePath<X, Y> = (host: WatchFileHost, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
export type WatchDirectory<X, Y> = (host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
|
||||
|
||||
export function addDirectoryWatcher(host: WatchDirectoryHost, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher {
|
||||
const recursive = (flags & WatchDirectoryFlags.Recursive) !== 0;
|
||||
return host.watchDirectory(directory, cb, recursive);
|
||||
export interface WatchFactory<X, Y> {
|
||||
watchFile: WatchFile<X, Y>;
|
||||
watchFilePath: WatchFilePath<X, Y>;
|
||||
watchDirectory: WatchDirectory<X, Y>;
|
||||
}
|
||||
|
||||
export function addDirectoryWatcherWithLogging(host: WatchDirectoryHost, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, log: (s: string) => void): FileWatcher {
|
||||
const watcherCaption = `DirectoryWatcher ${(flags & WatchDirectoryFlags.Recursive) !== 0 ? "recursive" : ""}:: `;
|
||||
return createWatcherWithLogging(addDirectoryWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, directory, cb, flags);
|
||||
export function getWatchFactory<X = undefined, Y = undefined>(watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo?: GetDetailWatchInfo<X, Y>): WatchFactory<X, Y> {
|
||||
return getWatchFactoryWith(watchLogLevel, log, getDetailWatchInfo, watchFile, watchDirectory);
|
||||
}
|
||||
|
||||
export function addDirectoryWatcherWithOnlyTriggerLogging(host: WatchDirectoryHost, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, log: (s: string) => void): FileWatcher {
|
||||
const watcherCaption = `DirectoryWatcher ${(flags & WatchDirectoryFlags.Recursive) !== 0 ? "recursive" : ""}:: `;
|
||||
return createWatcherWithLogging(addDirectoryWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, directory, cb, flags);
|
||||
}
|
||||
function getWatchFactoryWith<X = undefined, Y = undefined>(watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined,
|
||||
watchFile: (host: WatchFileHost, file: string, callback: FileWatcherCallback, watchPriority: PollingInterval) => FileWatcher,
|
||||
watchDirectory: (host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags) => FileWatcher): WatchFactory<X, Y> {
|
||||
const createFileWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchFile);
|
||||
const createFilePathWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, Path, X, Y> = watchLogLevel === WatchLogLevel.None ? watchFilePath : createFileWatcher;
|
||||
const createDirectoryWatcher: CreateFileWatcher<WatchDirectoryHost, WatchDirectoryFlags, undefined, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchDirectory);
|
||||
return {
|
||||
watchFile: (host, file, callback, pollingInterval, detailInfo1, detailInfo2) =>
|
||||
createFileWatcher(host, file, callback, pollingInterval, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo),
|
||||
watchFilePath: (host, file, callback, pollingInterval, path, detailInfo1, detailInfo2) =>
|
||||
createFilePathWatcher(host, file, callback, pollingInterval, path, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo),
|
||||
watchDirectory: (host, directory, callback, flags, detailInfo1, detailInfo2) =>
|
||||
createDirectoryWatcher(host, directory, callback, flags, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchDirectory, log, "DirectoryWatcher", getDetailWatchInfo)
|
||||
};
|
||||
|
||||
type WatchCallback<T, U> = (fileName: string, cbOptional1?: T, optional?: U) => void;
|
||||
type AddWatch<H, T, U> = (host: H, file: string, cb: WatchCallback<T, U>, optional?: U) => FileWatcher;
|
||||
function createWatcherWithLogging<H, T, U>(addWatch: AddWatch<H, T, U>, watcherCaption: string, log: (s: string) => void, logOnlyTrigger: boolean, host: H, file: string, cb: WatchCallback<T, U>, optional?: U): FileWatcher {
|
||||
const info = `PathInfo: ${file}`;
|
||||
if (!logOnlyTrigger) {
|
||||
log(`${watcherCaption}Added: ${info}`);
|
||||
function watchFilePath(host: WatchFileHost, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path): FileWatcher {
|
||||
return watchFile(host, file, (fileName, eventKind) => callback(fileName, eventKind, path), pollingInterval);
|
||||
}
|
||||
const watcher = addWatch(host, file, (fileName, cbOptional1?) => {
|
||||
const optionalInfo = cbOptional1 !== undefined ? ` ${cbOptional1}` : "";
|
||||
log(`${watcherCaption}Trigger: ${fileName}${optionalInfo} ${info}`);
|
||||
const start = timestamp();
|
||||
cb(fileName, cbOptional1, optional);
|
||||
const elapsed = timestamp() - start;
|
||||
log(`${watcherCaption}Elapsed: ${elapsed}ms Trigger: ${fileName}${optionalInfo} ${info}`);
|
||||
}, optional);
|
||||
}
|
||||
|
||||
function watchFile(host: WatchFileHost, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval): FileWatcher {
|
||||
return host.watchFile(file, callback, pollingInterval);
|
||||
}
|
||||
|
||||
function watchDirectory(host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher {
|
||||
return host.watchDirectory(directory, callback, (flags & WatchDirectoryFlags.Recursive) !== 0);
|
||||
}
|
||||
|
||||
type WatchCallback<T, U> = (fileName: string, cbOptional?: T, passThrough?: U) => void;
|
||||
type AddWatch<H, T, U, V> = (host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough?: V, detailInfo1?: undefined, detailInfo2?: undefined) => FileWatcher;
|
||||
export type GetDetailWatchInfo<X, Y> = (detailInfo1: X, detailInfo2: Y) => string;
|
||||
|
||||
type CreateFileWatcher<H, T, U, V, X, Y> = (host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, V>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined) => FileWatcher;
|
||||
function getCreateFileWatcher<H, T, U, V, X, Y>(watchLogLevel: WatchLogLevel, addWatch: AddWatch<H, T, U, V>): CreateFileWatcher<H, T, U, V, X, Y> {
|
||||
switch (watchLogLevel) {
|
||||
case WatchLogLevel.None:
|
||||
return addWatch;
|
||||
case WatchLogLevel.TriggerOnly:
|
||||
return createFileWatcherWithTriggerLogging;
|
||||
case WatchLogLevel.Verbose:
|
||||
return createFileWatcherWithLogging;
|
||||
}
|
||||
}
|
||||
|
||||
function createFileWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
log(`${watchCaption}:: Added:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`);
|
||||
const watcher = createFileWatcherWithTriggerLogging(host, file, cb, flags, passThrough, detailInfo1, detailInfo2, addWatch, log, watchCaption, getDetailWatchInfo);
|
||||
return {
|
||||
close: () => {
|
||||
if (!logOnlyTrigger) {
|
||||
log(`${watcherCaption}Close: ${info}`);
|
||||
}
|
||||
log(`${watchCaption}:: Close:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`);
|
||||
watcher.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function closeFileWatcher(watcher: FileWatcher) {
|
||||
watcher.close();
|
||||
function createFileWatcherWithTriggerLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
return addWatch(host, file, (fileName, cbOptional) => {
|
||||
const triggerredInfo = `${watchCaption}:: Triggered with ${fileName}${cbOptional !== undefined ? cbOptional : ""}:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
|
||||
log(triggerredInfo);
|
||||
const start = timestamp();
|
||||
cb(fileName, cbOptional, passThrough);
|
||||
const elapsed = timestamp() - start;
|
||||
log(`Elapsed:: ${elapsed}ms ${triggerredInfo}`);
|
||||
}, flags);
|
||||
}
|
||||
|
||||
function getWatchInfo<T, X, Y>(file: string, flags: T, detailInfo1: X | undefined, detailInfo2: Y | undefined, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined) {
|
||||
return `WatchInfo: ${file} ${flags} ${getDetailWatchInfo ? getDetailWatchInfo(detailInfo1, detailInfo2) : ""}`;
|
||||
}
|
||||
|
||||
export function closeFileWatcherOf<T extends { watcher: FileWatcher; }>(objWithWatcher: T) {
|
||||
|
||||
@@ -848,7 +848,7 @@ namespace FourSlash {
|
||||
const actual = actualCompletions.entries;
|
||||
|
||||
if (actual.length !== expected.length) {
|
||||
this.raiseError(`Expected ${expected.length} completions, got ${actual.map(a => a.name)}.`);
|
||||
this.raiseError(`Expected ${expected.length} completions, got ${actual.length} (${actual.map(a => a.name)}).`);
|
||||
}
|
||||
|
||||
ts.zipWith(actual, expected, (completion, expectedCompletion, index) => {
|
||||
@@ -2923,6 +2923,10 @@ Actual: ${stringify(fullActual)}`);
|
||||
if (!codeFixes.length) {
|
||||
this.raiseError(`verifyCodeFixAvailable failed - expected code fixes but none found.`);
|
||||
}
|
||||
codeFixes.forEach(fix => fix.changes.forEach(change => {
|
||||
assert.isObject(change, `Invalid change in code fix: ${JSON.stringify(fix)}`);
|
||||
change.textChanges.forEach(textChange => assert.isObject(textChange, `Invalid textChange in codeFix: ${JSON.stringify(fix)}`));
|
||||
}));
|
||||
if (info) {
|
||||
assert.equal(info.length, codeFixes.length);
|
||||
ts.zipWith(codeFixes, info, (fix, info) => {
|
||||
|
||||
@@ -72,8 +72,7 @@ class TypeWriterWalker {
|
||||
private writeTypeOrSymbol(node: ts.Node, isSymbolWalk: boolean): TypeWriterResult {
|
||||
const actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos);
|
||||
const lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos);
|
||||
const sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node);
|
||||
|
||||
const sourceText = ts.getSourceTextOfNodeFromSourceFile(this.currentSourceFile, node);
|
||||
|
||||
if (!isSymbolWalk) {
|
||||
// Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions
|
||||
|
||||
@@ -91,6 +91,18 @@ namespace ts {
|
||||
"c:/dev/g.min.js/.g/g.ts"
|
||||
]);
|
||||
|
||||
const caseInsensitiveOrderingDiffersWithCaseHost = new Utils.MockParseConfigHost(caseInsensitiveBasePath, /*useCaseSensitiveFileNames*/ false, [
|
||||
"c:/dev/xylophone.ts",
|
||||
"c:/dev/Yosemite.ts",
|
||||
"c:/dev/zebra.ts",
|
||||
]);
|
||||
|
||||
const caseSensitiveOrderingDiffersWithCaseHost = new Utils.MockParseConfigHost(caseSensitiveBasePath, /*useCaseSensitiveFileNames*/ true, [
|
||||
"/dev/xylophone.ts",
|
||||
"/dev/Yosemite.ts",
|
||||
"/dev/zebra.ts",
|
||||
]);
|
||||
|
||||
function assertParsed(actual: ParsedCommandLine, expected: ParsedCommandLine): void {
|
||||
assert.deepEqual(actual.fileNames, expected.fileNames);
|
||||
assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
|
||||
@@ -1482,5 +1494,25 @@ namespace ts {
|
||||
validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
|
||||
});
|
||||
});
|
||||
|
||||
it("can include files in the same order on multiple platforms", () => {
|
||||
function getExpected(basePath: string): ParsedCommandLine {
|
||||
return {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
`${basePath}Yosemite.ts`, // capital always comes before lowercase letters
|
||||
`${basePath}xylophone.ts`,
|
||||
`${basePath}zebra.ts`
|
||||
],
|
||||
wildcardDirectories: {
|
||||
[basePath.slice(0, basePath.length - 1)]: WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
}
|
||||
const json = {};
|
||||
validateMatches(getExpected(caseSensitiveBasePath), json, caseSensitiveOrderingDiffersWithCaseHost, caseSensitiveBasePath);
|
||||
validateMatches(getExpected(caseInsensitiveBasePath), json, caseInsensitiveOrderingDiffersWithCaseHost, caseInsensitiveBasePath);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
/// <reference path="..\virtualFileSystemWithWatch.ts" />
|
||||
|
||||
namespace ts.tscWatch {
|
||||
|
||||
import WatchedSystem = TestFSWithWatch.TestServerHost;
|
||||
type FileOrFolder = TestFSWithWatch.FileOrFolder;
|
||||
import createWatchedSystem = TestFSWithWatch.createWatchedSystem;
|
||||
import checkFileNames = TestFSWithWatch.checkFileNames;
|
||||
import checkArray = TestFSWithWatch.checkArray;
|
||||
import libFile = TestFSWithWatch.libFile;
|
||||
import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles;
|
||||
import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories;
|
||||
@@ -15,11 +14,11 @@ namespace ts.tscWatch {
|
||||
import checkOutputDoesNotContain = TestFSWithWatch.checkOutputDoesNotContain;
|
||||
|
||||
export function checkProgramActualFiles(program: Program, expectedFiles: string[]) {
|
||||
checkFileNames(`Program actual files`, program.getSourceFiles().map(file => file.fileName), expectedFiles);
|
||||
checkArray(`Program actual files`, program.getSourceFiles().map(file => file.fileName), expectedFiles);
|
||||
}
|
||||
|
||||
export function checkProgramRootFiles(program: Program, expectedFiles: string[]) {
|
||||
checkFileNames(`Program rootFileNames`, program.getRootFileNames(), expectedFiles);
|
||||
checkArray(`Program rootFileNames`, program.getRootFileNames(), expectedFiles);
|
||||
}
|
||||
|
||||
function createWatchOfConfigFile(configFileName: string, host: WatchedSystem, maxNumberOfFilesToIterateForInvalidation?: number) {
|
||||
@@ -73,64 +72,60 @@ namespace ts.tscWatch {
|
||||
checkOutputDoesNotContain(host, expectedNonAffectedFiles);
|
||||
}
|
||||
|
||||
enum ExpectedOutputErrorsPosition {
|
||||
BeforeCompilationStarts,
|
||||
AfterCompilationStarting,
|
||||
AfterFileChangeDetected
|
||||
}
|
||||
|
||||
function checkOutputErrors(
|
||||
host: WatchedSystem,
|
||||
preErrorsWatchDiagnostic: DiagnosticMessage | undefined,
|
||||
errors: ReadonlyArray<Diagnostic>,
|
||||
errorsPosition: ExpectedOutputErrorsPosition,
|
||||
skipWaiting?: true
|
||||
...postErrorsWatchDiagnostics: DiagnosticMessage[]
|
||||
) {
|
||||
const outputs = host.getOutput();
|
||||
const expectedOutputCount = errors.length + (skipWaiting ? 0 : 1) + 1;
|
||||
assert.equal(outputs.length, expectedOutputCount, "Outputs = " + outputs.toString());
|
||||
let index: number;
|
||||
|
||||
switch (errorsPosition) {
|
||||
case ExpectedOutputErrorsPosition.AfterCompilationStarting:
|
||||
assertWatchDiagnosticAt(host, 0, Diagnostics.Starting_compilation_in_watch_mode);
|
||||
index = 1;
|
||||
break;
|
||||
case ExpectedOutputErrorsPosition.AfterFileChangeDetected:
|
||||
assertWatchDiagnosticAt(host, 0, Diagnostics.File_change_detected_Starting_incremental_compilation);
|
||||
index = 1;
|
||||
break;
|
||||
case ExpectedOutputErrorsPosition.BeforeCompilationStarts:
|
||||
assertWatchDiagnosticAt(host, errors.length, Diagnostics.Starting_compilation_in_watch_mode);
|
||||
index = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
forEach(errors, error => {
|
||||
assertDiagnosticAt(host, index, error);
|
||||
index++;
|
||||
});
|
||||
if (!skipWaiting) {
|
||||
if (errorsPosition === ExpectedOutputErrorsPosition.BeforeCompilationStarts) {
|
||||
assertWatchDiagnosticAt(host, index, Diagnostics.Starting_compilation_in_watch_mode);
|
||||
index += 1;
|
||||
}
|
||||
assertWatchDiagnosticAt(host, index, Diagnostics.Compilation_complete_Watching_for_file_changes);
|
||||
const expectedOutputCount = (preErrorsWatchDiagnostic ? 1 : 0) + errors.length + postErrorsWatchDiagnostics.length;
|
||||
assert.equal(outputs.length, expectedOutputCount);
|
||||
let index = 0;
|
||||
if (preErrorsWatchDiagnostic) {
|
||||
assertWatchDiagnostic(preErrorsWatchDiagnostic);
|
||||
}
|
||||
// Verify errors
|
||||
forEach(errors, assertDiagnostic);
|
||||
forEach(postErrorsWatchDiagnostics, assertWatchDiagnostic);
|
||||
host.clearOutput();
|
||||
|
||||
function assertDiagnostic(diagnostic: Diagnostic) {
|
||||
const expected = formatDiagnostic(diagnostic, host);
|
||||
assert.equal(outputs[index], expected, getOutputAtFailedMessage("Diagnostic", expected));
|
||||
index++;
|
||||
}
|
||||
|
||||
function assertWatchDiagnostic(diagnosticMessage: DiagnosticMessage) {
|
||||
const expected = getWatchDiagnosticWithoutDate(diagnosticMessage);
|
||||
assert.isTrue(endsWith(outputs[index], expected), getOutputAtFailedMessage("Watch diagnostic", expected));
|
||||
index++;
|
||||
}
|
||||
|
||||
function getOutputAtFailedMessage(caption: string, expectedOutput: string) {
|
||||
return `Expected ${caption}: ${expectedOutput} at ${index} in ${JSON.stringify(outputs)}`;
|
||||
}
|
||||
|
||||
function getWatchDiagnosticWithoutDate(diagnosticMessage: DiagnosticMessage) {
|
||||
return ` - ${flattenDiagnosticMessageText(getLocaleSpecificMessage(diagnosticMessage), host.newLine)}${host.newLine + host.newLine + host.newLine}`;
|
||||
}
|
||||
}
|
||||
|
||||
function assertDiagnosticAt(host: WatchedSystem, outputAt: number, diagnostic: Diagnostic) {
|
||||
const output = host.getOutput()[outputAt];
|
||||
assert.equal(output, formatDiagnostic(diagnostic, host), "outputs[" + outputAt + "] is " + output);
|
||||
function checkOutputErrorsInitial(host: WatchedSystem, errors: ReadonlyArray<Diagnostic>) {
|
||||
checkOutputErrors(host, Diagnostics.Starting_compilation_in_watch_mode, errors, Diagnostics.Compilation_complete_Watching_for_file_changes);
|
||||
}
|
||||
|
||||
function assertWatchDiagnosticAt(host: WatchedSystem, outputAt: number, diagnosticMessage: DiagnosticMessage) {
|
||||
const output = host.getOutput()[outputAt];
|
||||
assert.isTrue(endsWith(output, getWatchDiagnosticWithoutDate(host, diagnosticMessage)), "outputs[" + outputAt + "] is " + output);
|
||||
function checkOutputErrorsInitialWithConfigErrors(host: WatchedSystem, errors: ReadonlyArray<Diagnostic>) {
|
||||
checkOutputErrors(host, /*preErrorsWatchDiagnostic*/ undefined, errors, Diagnostics.Starting_compilation_in_watch_mode, Diagnostics.Compilation_complete_Watching_for_file_changes);
|
||||
}
|
||||
|
||||
function getWatchDiagnosticWithoutDate(host: WatchedSystem, diagnosticMessage: DiagnosticMessage) {
|
||||
return ` - ${flattenDiagnosticMessageText(getLocaleSpecificMessage(diagnosticMessage), host.newLine)}${host.newLine + host.newLine + host.newLine}`;
|
||||
function checkOutputErrorsIncremental(host: WatchedSystem, errors: ReadonlyArray<Diagnostic>) {
|
||||
checkOutputErrors(host, Diagnostics.File_change_detected_Starting_incremental_compilation, errors, Diagnostics.Compilation_complete_Watching_for_file_changes);
|
||||
}
|
||||
|
||||
function checkOutputErrorsIncrementalWithExit(host: WatchedSystem, errors: ReadonlyArray<Diagnostic>, expectedExitCode: ExitStatus) {
|
||||
checkOutputErrors(host, Diagnostics.File_change_detected_Starting_incremental_compilation, errors);
|
||||
assert.equal(host.exitCode, expectedExitCode);
|
||||
}
|
||||
|
||||
function getDiagnosticOfFileFrom(file: SourceFile, text: string, start: number, length: number, message: DiagnosticMessage): Diagnostic {
|
||||
@@ -346,16 +341,16 @@ namespace ts.tscWatch {
|
||||
|
||||
checkProgramRootFiles(watch(), [file1.path]);
|
||||
checkProgramActualFiles(watch(), [file1.path, libFile.path]);
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsInitial(host, [
|
||||
getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content.indexOf(commonFile2Name), commonFile2Name.length, Diagnostics.File_0_not_found, commonFile2.path),
|
||||
getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content.indexOf("y"), 1, Diagnostics.Cannot_find_name_0, "y")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
]);
|
||||
|
||||
host.reloadFS([file1, commonFile2, libFile]);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkProgramRootFiles(watch(), [file1.path]);
|
||||
checkProgramActualFiles(watch(), [file1.path, libFile.path, commonFile2.path]);
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
it("should reflect change in config file", () => {
|
||||
@@ -683,15 +678,14 @@ namespace ts.tscWatch {
|
||||
const watch = createWatchOfConfigFile(config.path, host);
|
||||
|
||||
checkProgramActualFiles(watch(), [file1.path, file2.path, libFile.path]);
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
host.reloadFS([file1, file2, libFile]);
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
|
||||
assert.equal(host.exitCode, ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsIncrementalWithExit(host, [
|
||||
getDiagnosticWithoutFile(Diagnostics.File_0_not_found, config.path)
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected, /*skipWaiting*/ true);
|
||||
], ExitStatus.DiagnosticsPresent_OutputsSkipped);
|
||||
});
|
||||
|
||||
it("Proper errors: document is not contained in project", () => {
|
||||
@@ -794,21 +788,21 @@ namespace ts.tscWatch {
|
||||
};
|
||||
const host = createWatchedSystem([moduleFile, file1, libFile]);
|
||||
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host);
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
const moduleFileOldPath = moduleFile.path;
|
||||
const moduleFileNewPath = "/a/b/moduleFile1.ts";
|
||||
moduleFile.path = moduleFileNewPath;
|
||||
host.reloadFS([moduleFile, file1, libFile]);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsIncremental(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
]);
|
||||
|
||||
moduleFile.path = moduleFileOldPath;
|
||||
host.reloadFS([moduleFile, file1, libFile]);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
it("rename a module file and rename back should restore the states for configured projects", () => {
|
||||
@@ -826,21 +820,21 @@ namespace ts.tscWatch {
|
||||
};
|
||||
const host = createWatchedSystem([moduleFile, file1, configFile, libFile]);
|
||||
const watch = createWatchOfConfigFile(configFile.path, host);
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
const moduleFileOldPath = moduleFile.path;
|
||||
const moduleFileNewPath = "/a/b/moduleFile1.ts";
|
||||
moduleFile.path = moduleFileNewPath;
|
||||
host.reloadFS([moduleFile, file1, configFile, libFile]);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsIncremental(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
]);
|
||||
|
||||
moduleFile.path = moduleFileOldPath;
|
||||
host.reloadFS([moduleFile, file1, configFile, libFile]);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
it("types should load from config file path if config exists", () => {
|
||||
@@ -877,13 +871,13 @@ namespace ts.tscWatch {
|
||||
const host = createWatchedSystem([file1, libFile]);
|
||||
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host);
|
||||
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsInitial(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
]);
|
||||
|
||||
host.reloadFS([file1, moduleFile, libFile]);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
it("Configure file diagnostics events are generated when the config file has errors", () => {
|
||||
@@ -903,10 +897,10 @@ namespace ts.tscWatch {
|
||||
|
||||
const host = createWatchedSystem([file, configFile, libFile]);
|
||||
const watch = createWatchOfConfigFile(configFile.path, host);
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsInitialWithConfigErrors(host, [
|
||||
getUnknownCompilerOption(watch(), configFile, "foo"),
|
||||
getUnknownCompilerOption(watch(), configFile, "allowJS")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.BeforeCompilationStarts);
|
||||
]);
|
||||
});
|
||||
|
||||
it("If config file doesnt have errors, they are not reported", () => {
|
||||
@@ -923,7 +917,7 @@ namespace ts.tscWatch {
|
||||
|
||||
const host = createWatchedSystem([file, configFile, libFile]);
|
||||
createWatchOfConfigFile(configFile.path, host);
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
});
|
||||
|
||||
it("Reports errors when the config file changes", () => {
|
||||
@@ -940,7 +934,7 @@ namespace ts.tscWatch {
|
||||
|
||||
const host = createWatchedSystem([file, configFile, libFile]);
|
||||
const watch = createWatchOfConfigFile(configFile.path, host);
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
configFile.content = `{
|
||||
"compilerOptions": {
|
||||
@@ -949,16 +943,16 @@ namespace ts.tscWatch {
|
||||
}`;
|
||||
host.reloadFS([file, configFile, libFile]);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsIncremental(host, [
|
||||
getUnknownCompilerOption(watch(), configFile, "haha")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
]);
|
||||
|
||||
configFile.content = `{
|
||||
"compilerOptions": {}
|
||||
}`;
|
||||
host.reloadFS([file, configFile, libFile]);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
it("non-existing directories listed in config file input array should be tolerated without crashing the server", () => {
|
||||
@@ -1046,13 +1040,13 @@ namespace ts.tscWatch {
|
||||
getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")
|
||||
];
|
||||
const intialErrors = errors();
|
||||
checkOutputErrors(host, intialErrors, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
checkOutputErrorsInitial(host, intialErrors);
|
||||
|
||||
configFile.content = configFileContentWithoutCommentLine;
|
||||
host.reloadFS(files);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
const nowErrors = errors();
|
||||
checkOutputErrors(host, nowErrors, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, nowErrors);
|
||||
assert.equal(nowErrors[0].start, intialErrors[0].start - configFileContentComment.length);
|
||||
assert.equal(nowErrors[1].start, intialErrors[1].start - configFileContentComment.length);
|
||||
});
|
||||
@@ -1105,13 +1099,13 @@ namespace ts.tscWatch {
|
||||
noUnusedLocals: true
|
||||
});
|
||||
checkProgramActualFiles(watch(), files.map(file => file.path));
|
||||
checkOutputErrors(host, [], ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
checkOutputErrorsInitial(host, []);
|
||||
|
||||
file.content = getFileContent(/*asModule*/ true);
|
||||
host.reloadFS(files);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkProgramActualFiles(watch(), files.map(file => file.path));
|
||||
checkOutputErrors(host, [], ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, []);
|
||||
});
|
||||
|
||||
it("watched files when file is deleted and new file is added as part of change", () => {
|
||||
@@ -1800,7 +1794,7 @@ namespace ts.tscWatch {
|
||||
const cannotFindFoo = getDiagnosticOfFileFromProgram(watch(), imported.path, imported.content.indexOf("foo"), "foo".length, Diagnostics.Cannot_find_name_0, "foo");
|
||||
|
||||
// ensure that imported file was found
|
||||
checkOutputErrors(host, [f1IsNotModule, cannotFindFoo], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
checkOutputErrorsInitial(host, [f1IsNotModule, cannotFindFoo]);
|
||||
|
||||
const originalFileExists = host.fileExists;
|
||||
{
|
||||
@@ -1816,11 +1810,11 @@ namespace ts.tscWatch {
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
// ensure file has correct number of errors after edit
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsIncremental(host, [
|
||||
f1IsNotModule,
|
||||
getDiagnosticOfFileFromProgram(watch(), root.path, newContent.indexOf("var x") + "var ".length, "x".length, Diagnostics.Type_0_is_not_assignable_to_type_1, 1, "string"),
|
||||
cannotFindFoo
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
]);
|
||||
}
|
||||
{
|
||||
let fileExistsIsCalled = false;
|
||||
@@ -1840,9 +1834,9 @@ namespace ts.tscWatch {
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
// ensure file has correct number of errors after edit
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsIncremental(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), root, "f2")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
]);
|
||||
|
||||
assert.isTrue(fileExistsIsCalled);
|
||||
}
|
||||
@@ -1863,7 +1857,7 @@ namespace ts.tscWatch {
|
||||
host.reloadFS(files);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
checkOutputErrors(host, [f1IsNotModule, cannotFindFoo], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, [f1IsNotModule, cannotFindFoo]);
|
||||
assert.isTrue(fileExistsCalled);
|
||||
}
|
||||
});
|
||||
@@ -1898,16 +1892,16 @@ namespace ts.tscWatch {
|
||||
const watch = createWatchOfFilesAndCompilerOptions([root.path], host, { module: ModuleKind.AMD });
|
||||
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsInitial(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), root, "bar")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
]);
|
||||
|
||||
fileExistsCalledForBar = false;
|
||||
root.content = `import {y} from "bar"`;
|
||||
host.reloadFS(files.concat(imported));
|
||||
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
|
||||
});
|
||||
|
||||
@@ -1940,20 +1934,20 @@ namespace ts.tscWatch {
|
||||
const watch = createWatchOfFilesAndCompilerOptions([root.path], host, { module: ModuleKind.AMD });
|
||||
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
fileExistsCalledForBar = false;
|
||||
host.reloadFS(files);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsIncremental(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), root, "bar")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
]);
|
||||
|
||||
fileExistsCalledForBar = false;
|
||||
host.reloadFS(filesWithImported);
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
|
||||
});
|
||||
|
||||
@@ -1988,13 +1982,13 @@ declare module "fs" {
|
||||
|
||||
const watch = createWatchOfFilesAndCompilerOptions([root.path], host, { });
|
||||
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsInitial(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), root, "fs")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
]);
|
||||
|
||||
host.reloadFS(filesWithNodeType);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
it("works when included file with ambient module changes", () => {
|
||||
@@ -2030,14 +2024,14 @@ declare module "fs" {
|
||||
|
||||
const watch = createWatchOfFilesAndCompilerOptions([root.path, file.path], host, {});
|
||||
|
||||
checkOutputErrors(host, [
|
||||
checkOutputErrorsInitial(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch(), root, "fs")
|
||||
], /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
]);
|
||||
|
||||
file.content += fileContentWithFS;
|
||||
host.reloadFS(files);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
it("works when reusing program with files from external library", () => {
|
||||
@@ -2072,7 +2066,7 @@ declare module "fs" {
|
||||
const host = createWatchedSystem(programFiles.concat(configFile), { currentDirectory: "/a/b/projects/myProject/" });
|
||||
const watch = createWatchOfConfigFile(configFile.path, host);
|
||||
checkProgramActualFiles(watch(), programFiles.map(f => f.path));
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterCompilationStarting);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
const expectedFiles: ExpectedFile[] = [
|
||||
createExpectedEmittedFile(file1),
|
||||
createExpectedEmittedFile(file2),
|
||||
@@ -2091,7 +2085,7 @@ declare module "fs" {
|
||||
host.reloadFS(programFiles.concat(configFile));
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkProgramActualFiles(watch(), programFiles.map(f => f.path));
|
||||
checkOutputErrors(host, emptyArray, /*errorsPosition*/ ExpectedOutputErrorsPosition.AfterFileChangeDetected);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
verifyExpectedFiles(expectedFiles);
|
||||
|
||||
|
||||
@@ -2212,4 +2206,136 @@ declare module "fs" {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("tsc-watch with different polling/non polling options", () => {
|
||||
it("watchFile using dynamic priority polling", () => {
|
||||
const projectFolder = "/a/username/project";
|
||||
const file1: FileOrFolder = {
|
||||
path: `${projectFolder}/typescript.ts`,
|
||||
content: "var z = 10;"
|
||||
};
|
||||
const files = [file1, libFile];
|
||||
const environmentVariables = createMap<string>();
|
||||
environmentVariables.set("TSC_WATCHFILE", "DynamicPriorityPolling");
|
||||
const host = createWatchedSystem(files, { environmentVariables });
|
||||
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host);
|
||||
|
||||
const initialProgram = watch();
|
||||
verifyProgram();
|
||||
|
||||
const mediumPollingIntervalThreshold = unchangedPollThresholds[PollingInterval.Medium];
|
||||
for (let index = 0; index < mediumPollingIntervalThreshold; index++) {
|
||||
// Transition libFile and file1 to low priority queue
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
assert.deepEqual(watch(), initialProgram);
|
||||
}
|
||||
|
||||
// Make a change to file
|
||||
file1.content = "var zz30 = 100;";
|
||||
host.reloadFS(files);
|
||||
|
||||
// This should detect change in the file
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
assert.deepEqual(watch(), initialProgram);
|
||||
|
||||
// Callbacks: medium priority + high priority queue and scheduled program update
|
||||
host.checkTimeoutQueueLengthAndRun(3);
|
||||
// During this timeout the file would be detected as unchanged
|
||||
let fileUnchangeDetected = 1;
|
||||
const newProgram = watch();
|
||||
assert.notStrictEqual(newProgram, initialProgram);
|
||||
|
||||
verifyProgram();
|
||||
const outputFile1 = changeExtension(file1.path, ".js");
|
||||
assert.isTrue(host.fileExists(outputFile1));
|
||||
assert.equal(host.readFile(outputFile1), file1.content + host.newLine);
|
||||
|
||||
const newThreshold = unchangedPollThresholds[PollingInterval.Low] + mediumPollingIntervalThreshold;
|
||||
for (; fileUnchangeDetected < newThreshold; fileUnchangeDetected++) {
|
||||
// For high + Medium/low polling interval
|
||||
host.checkTimeoutQueueLengthAndRun(2);
|
||||
assert.deepEqual(watch(), newProgram);
|
||||
}
|
||||
|
||||
// Everything goes in high polling interval queue
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
assert.deepEqual(watch(), newProgram);
|
||||
|
||||
function verifyProgram() {
|
||||
checkProgramActualFiles(watch(), files.map(f => f.path));
|
||||
checkWatchedFiles(host, []);
|
||||
checkWatchedDirectories(host, [], /*recursive*/ false);
|
||||
checkWatchedDirectories(host, [], /*recursive*/ true);
|
||||
}
|
||||
});
|
||||
|
||||
describe("tsc-watch when watchDirectories implementation", () => {
|
||||
function verifyRenamingFileInSubFolder(tscWatchDirectory: TestFSWithWatch.Tsc_WatchDirectory) {
|
||||
const projectFolder = "/a/username/project";
|
||||
const projectSrcFolder = `${projectFolder}/src`;
|
||||
const configFile: FileOrFolder = {
|
||||
path: `${projectFolder}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const file: FileOrFolder = {
|
||||
path: `${projectSrcFolder}/file1.ts`,
|
||||
content: ""
|
||||
};
|
||||
const programFiles = [file, libFile];
|
||||
const files = [file, configFile, libFile];
|
||||
const environmentVariables = createMap<string>();
|
||||
environmentVariables.set("TSC_WATCHDIRECTORY", tscWatchDirectory);
|
||||
const host = createWatchedSystem(files, { environmentVariables });
|
||||
const watch = createWatchOfConfigFile(configFile.path, host);
|
||||
const projectFolders = [projectFolder, projectSrcFolder, `${projectFolder}/node_modules/@types`];
|
||||
// Watching files config file, file, lib file
|
||||
const expectedWatchedFiles = files.map(f => f.path);
|
||||
const expectedWatchedDirectories = tscWatchDirectory === TestFSWithWatch.Tsc_WatchDirectory.NonRecursiveWatchDirectory ? projectFolders : emptyArray;
|
||||
if (tscWatchDirectory === TestFSWithWatch.Tsc_WatchDirectory.WatchFile) {
|
||||
expectedWatchedFiles.push(...projectFolders);
|
||||
}
|
||||
|
||||
verifyProgram(checkOutputErrorsInitial);
|
||||
|
||||
// Rename the file:
|
||||
file.path = file.path.replace("file1.ts", "file2.ts");
|
||||
expectedWatchedFiles[0] = file.path;
|
||||
host.reloadFS(files);
|
||||
if (tscWatchDirectory === TestFSWithWatch.Tsc_WatchDirectory.DynamicPolling) {
|
||||
// With dynamic polling the fs change would be detected only by running timeouts
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
}
|
||||
// Delayed update program
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
verifyProgram(checkOutputErrorsIncremental);
|
||||
|
||||
function verifyProgram(checkOutputErrors: (host: WatchedSystem, errors: ReadonlyArray<Diagnostic>) => void) {
|
||||
checkProgramActualFiles(watch(), programFiles.map(f => f.path));
|
||||
checkOutputErrors(host, emptyArray);
|
||||
|
||||
const outputFile = changeExtension(file.path, ".js");
|
||||
assert(host.fileExists(outputFile));
|
||||
assert.equal(host.readFile(outputFile), file.content);
|
||||
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
|
||||
|
||||
// Watching config file, file, lib file and directories
|
||||
TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedFiles", host.watchedFiles, expectedWatchedFiles, 1);
|
||||
TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedDirectories", host.watchedDirectories, expectedWatchedDirectories, 1);
|
||||
}
|
||||
}
|
||||
|
||||
it("uses watchFile when renaming file in subfolder", () => {
|
||||
verifyRenamingFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.WatchFile);
|
||||
});
|
||||
|
||||
it("uses non recursive watchDirectory when renaming file in subfolder", () => {
|
||||
verifyRenamingFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.NonRecursiveWatchDirectory);
|
||||
});
|
||||
|
||||
it("uses non recursive dynamic polling when renaming file in subfolder", () => {
|
||||
verifyRenamingFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.DynamicPolling);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace ts.projectSystem {
|
||||
export import TestServerHost = TestFSWithWatch.TestServerHost;
|
||||
export type FileOrFolder = TestFSWithWatch.FileOrFolder;
|
||||
export import createServerHost = TestFSWithWatch.createServerHost;
|
||||
export import checkFileNames = TestFSWithWatch.checkFileNames;
|
||||
export import checkArray = TestFSWithWatch.checkArray;
|
||||
export import libFile = TestFSWithWatch.libFile;
|
||||
export import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles;
|
||||
import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories;
|
||||
@@ -355,11 +355,11 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
export function checkProjectActualFiles(project: server.Project, expectedFiles: string[]) {
|
||||
checkFileNames(`${server.ProjectKind[project.projectKind]} project, actual files`, project.getFileNames(), expectedFiles);
|
||||
checkArray(`${server.ProjectKind[project.projectKind]} project, actual files`, project.getFileNames(), expectedFiles);
|
||||
}
|
||||
|
||||
function checkProjectRootFiles(project: server.Project, expectedFiles: string[]) {
|
||||
checkFileNames(`${server.ProjectKind[project.projectKind]} project, rootFileNames`, project.getRootFiles(), expectedFiles);
|
||||
checkArray(`${server.ProjectKind[project.projectKind]} project, rootFileNames`, project.getRootFiles(), expectedFiles);
|
||||
}
|
||||
|
||||
function mapCombinedPathsInAncestor(dir: string, path2: string, mapAncestor: (ancestor: string) => boolean) {
|
||||
@@ -392,7 +392,7 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
function checkOpenFiles(projectService: server.ProjectService, expectedFiles: FileOrFolder[]) {
|
||||
checkFileNames("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path).fileName), expectedFiles.map(file => file.path));
|
||||
checkArray("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path).fileName), expectedFiles.map(file => file.path));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -531,7 +531,7 @@ namespace ts.projectSystem {
|
||||
|
||||
const project = projectService.inferredProjects[0];
|
||||
|
||||
checkFileNames("inferred project", project.getFileNames(), [appFile.path, libFile.path, moduleFile.path]);
|
||||
checkArray("inferred project", project.getFileNames(), [appFile.path, libFile.path, moduleFile.path]);
|
||||
const configFileLocations = ["/a/b/c/", "/a/b/", "/a/", "/"];
|
||||
const configFiles = flatMap(configFileLocations, location => [location + "tsconfig.json", location + "jsconfig.json"]);
|
||||
checkWatchedFiles(host, configFiles.concat(libFile.path, moduleFile.path));
|
||||
@@ -5350,13 +5350,13 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
// send outlining spans request (normal priority)
|
||||
session.executeCommandSeq(<protocol.OutliningSpansRequest>{
|
||||
session.executeCommandSeq(<protocol.OutliningSpansRequestFull>{
|
||||
command: "outliningSpans",
|
||||
arguments: { file: f1.path }
|
||||
});
|
||||
|
||||
// ensure the outlining spans request can be canceled
|
||||
verifyExecuteCommandSeqIsCancellable(<protocol.OutliningSpansRequest>{
|
||||
verifyExecuteCommandSeqIsCancellable(<protocol.OutliningSpansRequestFull>{
|
||||
command: "outliningSpans",
|
||||
arguments: { file: f1.path }
|
||||
});
|
||||
@@ -5663,16 +5663,11 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
function verifyCalledOnEachEntry(callback: CalledMaps, expectedKeys: Map<number>) {
|
||||
const calledMap = calledMaps[callback];
|
||||
TestFSWithWatch.verifyMapSize(callback, calledMap, arrayFrom(expectedKeys.keys()));
|
||||
expectedKeys.forEach((called, name) => {
|
||||
assert.isTrue(calledMap.has(name), `${callback} is expected to contain ${name}, actual keys: ${arrayFrom(calledMap.keys())}`);
|
||||
assert.equal(calledMap.get(name).length, called, `${callback} is expected to be called ${called} times with ${name}. Actual entry: ${calledMap.get(name)}`);
|
||||
});
|
||||
TestFSWithWatch.checkMultiMapKeyCount(callback, calledMaps[callback], expectedKeys);
|
||||
}
|
||||
|
||||
function verifyCalledOnEachEntryNTimes(callback: CalledMaps, expectedKeys: string[], nTimes: number) {
|
||||
return verifyCalledOnEachEntry(callback, zipToMap(expectedKeys, expectedKeys.map(() => nTimes)));
|
||||
TestFSWithWatch.checkMultiMapEachKeyWithCount(callback, calledMaps[callback], expectedKeys, nTimes);
|
||||
}
|
||||
|
||||
function verifyNoHostCalls() {
|
||||
@@ -7009,7 +7004,6 @@ namespace ts.projectSystem {
|
||||
assert.isDefined(projectService.configuredProjects.get(aTsconfig.path));
|
||||
assert.isDefined(projectService.configuredProjects.get(bTsconfig.path));
|
||||
|
||||
debugger;
|
||||
verifyRenameResponse(session.executeCommandSeq<protocol.RenameRequest>({
|
||||
command: protocol.CommandTypes.Rename,
|
||||
arguments: {
|
||||
@@ -7438,4 +7432,88 @@ namespace ts.projectSystem {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("watchDirectories implementation", () => {
|
||||
function verifyCompletionListWithNewFileInSubFolder(tscWatchDirectory: TestFSWithWatch.Tsc_WatchDirectory) {
|
||||
const projectFolder = "/a/username/project";
|
||||
const projectSrcFolder = `${projectFolder}/src`;
|
||||
const configFile: FileOrFolder = {
|
||||
path: `${projectFolder}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const index: FileOrFolder = {
|
||||
path: `${projectSrcFolder}/index.ts`,
|
||||
content: `import {} from "./"`
|
||||
};
|
||||
const file1: FileOrFolder = {
|
||||
path: `${projectSrcFolder}/file1.ts`,
|
||||
content: ""
|
||||
};
|
||||
|
||||
const files = [index, file1, configFile, libFile];
|
||||
const fileNames = files.map(file => file.path);
|
||||
// All closed files(files other than index), project folder, project/src folder and project/node_modules/@types folder
|
||||
const expectedWatchedFiles = arrayToMap(fileNames.slice(1), s => s, () => 1);
|
||||
const expectedWatchedDirectories = createMap<number>();
|
||||
const mapOfDirectories = tscWatchDirectory === TestFSWithWatch.Tsc_WatchDirectory.NonRecursiveWatchDirectory ?
|
||||
expectedWatchedDirectories :
|
||||
tscWatchDirectory === TestFSWithWatch.Tsc_WatchDirectory.WatchFile ?
|
||||
expectedWatchedFiles :
|
||||
createMap();
|
||||
// For failed resolution lookup and tsconfig files
|
||||
mapOfDirectories.set(projectFolder, 2);
|
||||
// Through above recursive watches
|
||||
mapOfDirectories.set(projectSrcFolder, 2);
|
||||
// node_modules/@types folder
|
||||
mapOfDirectories.set(`${projectFolder}/${nodeModulesAtTypes}`, 1);
|
||||
const expectedCompletions = ["file1"];
|
||||
const completionPosition = index.content.lastIndexOf('"');
|
||||
const environmentVariables = createMap<string>();
|
||||
environmentVariables.set("TSC_WATCHDIRECTORY", tscWatchDirectory);
|
||||
const host = createServerHost(files, { environmentVariables });
|
||||
const projectService = createProjectService(host);
|
||||
projectService.openClientFile(index.path);
|
||||
|
||||
const project = projectService.configuredProjects.get(configFile.path);
|
||||
assert.isDefined(project);
|
||||
verifyProjectAndCompletions();
|
||||
|
||||
// Add file2
|
||||
const file2: FileOrFolder = {
|
||||
path: `${projectSrcFolder}/file2.ts`,
|
||||
content: ""
|
||||
};
|
||||
files.push(file2);
|
||||
fileNames.push(file2.path);
|
||||
expectedWatchedFiles.set(file2.path, 1);
|
||||
expectedCompletions.push("file2");
|
||||
host.reloadFS(files);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
assert.equal(projectService.configuredProjects.get(configFile.path), project);
|
||||
verifyProjectAndCompletions();
|
||||
|
||||
function verifyProjectAndCompletions() {
|
||||
const completions = project.getLanguageService().getCompletionsAtPosition(index.path, completionPosition, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
|
||||
checkArray("Completion Entries", completions.entries.map(e => e.name), expectedCompletions);
|
||||
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
|
||||
|
||||
TestFSWithWatch.checkMultiMapKeyCount("watchedFiles", host.watchedFiles, expectedWatchedFiles);
|
||||
TestFSWithWatch.checkMultiMapKeyCount("watchedDirectories", host.watchedDirectories, expectedWatchedDirectories);
|
||||
checkProjectActualFiles(project, fileNames);
|
||||
}
|
||||
}
|
||||
|
||||
it("uses watchFile when file is added to subfolder, completion list has new file", () => {
|
||||
verifyCompletionListWithNewFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.WatchFile);
|
||||
});
|
||||
|
||||
it("uses non recursive watchDirectory when file is added to subfolder, completion list has new file", () => {
|
||||
verifyCompletionListWithNewFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.NonRecursiveWatchDirectory);
|
||||
});
|
||||
|
||||
it("uses dynamic polling when file is added to subfolder, completion list has new file", () => {
|
||||
verifyCompletionListWithNewFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.DynamicPolling);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ interface Array<T> {}`
|
||||
currentDirectory?: string;
|
||||
newLine?: string;
|
||||
useWindowsStylePaths?: boolean;
|
||||
environmentVariables?: Map<string>;
|
||||
}
|
||||
|
||||
export function createWatchedSystem(fileOrFolderList: ReadonlyArray<FileOrFolder>, params?: TestServerHostCreationParameters): TestServerHost {
|
||||
@@ -48,7 +49,8 @@ interface Array<T> {}`
|
||||
params.currentDirectory || "/",
|
||||
fileOrFolderList,
|
||||
params.newLine,
|
||||
params.useWindowsStylePaths);
|
||||
params.useWindowsStylePaths,
|
||||
params.environmentVariables);
|
||||
return host;
|
||||
}
|
||||
|
||||
@@ -62,7 +64,8 @@ interface Array<T> {}`
|
||||
params.currentDirectory || "/",
|
||||
fileOrFolderList,
|
||||
params.newLine,
|
||||
params.useWindowsStylePaths);
|
||||
params.useWindowsStylePaths,
|
||||
params.environmentVariables);
|
||||
return host;
|
||||
}
|
||||
|
||||
@@ -76,6 +79,7 @@ interface Array<T> {}`
|
||||
interface FSEntry {
|
||||
path: Path;
|
||||
fullPath: string;
|
||||
modifiedTime: Date;
|
||||
}
|
||||
|
||||
interface File extends FSEntry {
|
||||
@@ -152,10 +156,22 @@ interface Array<T> {}`
|
||||
}
|
||||
}
|
||||
|
||||
export function checkFileNames(caption: string, actualFileNames: ReadonlyArray<string>, expectedFileNames: string[]) {
|
||||
assert.equal(actualFileNames.length, expectedFileNames.length, `${caption}: incorrect actual number of files, expected:\r\n${expectedFileNames.join("\r\n")}\r\ngot: ${actualFileNames.join("\r\n")}`);
|
||||
for (const f of expectedFileNames) {
|
||||
assert.equal(true, contains(actualFileNames, f), `${caption}: expected to find ${f} in ${actualFileNames}`);
|
||||
export function checkMultiMapKeyCount(caption: string, actual: MultiMap<any>, expectedKeys: Map<number>) {
|
||||
verifyMapSize(caption, actual, arrayFrom(expectedKeys.keys()));
|
||||
expectedKeys.forEach((count, name) => {
|
||||
assert.isTrue(actual.has(name), `${caption}: expected to contain ${name}, actual keys: ${arrayFrom(actual.keys())}`);
|
||||
assert.equal(actual.get(name).length, count, `${caption}: Expected to be have ${count} entries for ${name}. Actual entry: ${JSON.stringify(actual.get(name))}`);
|
||||
});
|
||||
}
|
||||
|
||||
export function checkMultiMapEachKeyWithCount(caption: string, actual: MultiMap<any>, expectedKeys: ReadonlyArray<string>, count: number) {
|
||||
return checkMultiMapKeyCount(caption, actual, arrayToMap(expectedKeys, s => s, () => count));
|
||||
}
|
||||
|
||||
export function checkArray(caption: string, actual: ReadonlyArray<string>, expected: ReadonlyArray<string>) {
|
||||
assert.equal(actual.length, expected.length, `${caption}: incorrect actual number of files, expected:\r\n${expected.join("\r\n")}\r\ngot: ${actual.join("\r\n")}`);
|
||||
for (const f of expected) {
|
||||
assert.equal(true, contains(actual, f), `${caption}: expected to find ${f} in ${actual}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,6 +270,12 @@ interface Array<T> {}`
|
||||
invokeFileDeleteCreateAsPartInsteadOfChange: boolean;
|
||||
}
|
||||
|
||||
export enum Tsc_WatchDirectory {
|
||||
WatchFile = "RecursiveDirectoryUsingFsWatchFile",
|
||||
NonRecursiveWatchDirectory = "RecursiveDirectoryUsingNonRecursiveWatchDirectory",
|
||||
DynamicPolling = "RecursiveDirectoryUsingDynamicPriorityPolling"
|
||||
}
|
||||
|
||||
export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, ModuleResolutionHost {
|
||||
args: string[] = [];
|
||||
|
||||
@@ -271,13 +293,47 @@ interface Array<T> {}`
|
||||
readonly watchedFiles = createMultiMap<TestFileWatcher>();
|
||||
private readonly executingFilePath: string;
|
||||
private readonly currentDirectory: string;
|
||||
private readonly dynamicPriorityWatchFile: HostWatchFile;
|
||||
private readonly customRecursiveWatchDirectory: HostWatchDirectory | undefined;
|
||||
|
||||
constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderList: ReadonlyArray<FileOrFolder>, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean) {
|
||||
constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderList: ReadonlyArray<FileOrFolder>, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean, private readonly environmentVariables?: Map<string>) {
|
||||
this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
this.toPath = s => toPath(s, currentDirectory, this.getCanonicalFileName);
|
||||
this.executingFilePath = this.getHostSpecificPath(executingFilePath);
|
||||
this.currentDirectory = this.getHostSpecificPath(currentDirectory);
|
||||
this.reloadFS(fileOrFolderList);
|
||||
this.dynamicPriorityWatchFile = this.environmentVariables && this.environmentVariables.get("TSC_WATCHFILE") === "DynamicPriorityPolling" ?
|
||||
createDynamicPriorityPollingWatchFile(this) :
|
||||
undefined;
|
||||
const tscWatchDirectory = this.environmentVariables && this.environmentVariables.get("TSC_WATCHDIRECTORY") as Tsc_WatchDirectory;
|
||||
if (tscWatchDirectory === Tsc_WatchDirectory.WatchFile) {
|
||||
const watchDirectory: HostWatchDirectory = (directory, cb) => this.watchFile(directory, () => cb(directory), PollingInterval.Medium);
|
||||
this.customRecursiveWatchDirectory = createRecursiveDirectoryWatcher({
|
||||
directoryExists: path => this.directoryExists(path),
|
||||
getAccessileSortedChildDirectories: path => this.getDirectories(path),
|
||||
filePathComparer: this.useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive,
|
||||
watchDirectory
|
||||
});
|
||||
}
|
||||
else if (tscWatchDirectory === Tsc_WatchDirectory.NonRecursiveWatchDirectory) {
|
||||
const watchDirectory: HostWatchDirectory = (directory, cb) => this.watchDirectory(directory, fileName => cb(fileName), /*recursive*/ false);
|
||||
this.customRecursiveWatchDirectory = createRecursiveDirectoryWatcher({
|
||||
directoryExists: path => this.directoryExists(path),
|
||||
getAccessileSortedChildDirectories: path => this.getDirectories(path),
|
||||
filePathComparer: this.useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive,
|
||||
watchDirectory
|
||||
});
|
||||
}
|
||||
else if (tscWatchDirectory === Tsc_WatchDirectory.DynamicPolling) {
|
||||
const watchFile = createDynamicPriorityPollingWatchFile(this);
|
||||
const watchDirectory: HostWatchDirectory = (directory, cb) => watchFile(directory, () => cb(directory), PollingInterval.Medium);
|
||||
this.customRecursiveWatchDirectory = createRecursiveDirectoryWatcher({
|
||||
directoryExists: path => this.directoryExists(path),
|
||||
getAccessileSortedChildDirectories: path => this.getDirectories(path),
|
||||
filePathComparer: this.useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive,
|
||||
watchDirectory
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getNewLine() {
|
||||
@@ -325,6 +381,8 @@ interface Array<T> {}`
|
||||
}
|
||||
else {
|
||||
currentEntry.content = fileOrDirectory.content;
|
||||
currentEntry.modifiedTime = new Date();
|
||||
this.fs.get(getDirectoryPath(currentEntry.path)).modifiedTime = new Date();
|
||||
if (options && options.invokeDirectoryWatcherInsteadOfFileChanged) {
|
||||
this.invokeDirectoryWatcher(getDirectoryPath(currentEntry.fullPath), currentEntry.fullPath);
|
||||
}
|
||||
@@ -348,6 +406,7 @@ interface Array<T> {}`
|
||||
}
|
||||
else {
|
||||
// Folder update: Nothing to do.
|
||||
currentEntry.modifiedTime = new Date();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -446,14 +505,13 @@ interface Array<T> {}`
|
||||
|
||||
private addFileOrFolderInFolder(folder: Folder, fileOrDirectory: File | Folder | SymLink, ignoreWatch?: boolean) {
|
||||
folder.entries.push(fileOrDirectory);
|
||||
folder.modifiedTime = new Date();
|
||||
this.fs.set(fileOrDirectory.path, fileOrDirectory);
|
||||
|
||||
if (ignoreWatch) {
|
||||
return;
|
||||
}
|
||||
if (isFile(fileOrDirectory) || isSymLink(fileOrDirectory)) {
|
||||
this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Created);
|
||||
}
|
||||
this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Created);
|
||||
this.invokeDirectoryWatcher(folder.fullPath, fileOrDirectory.fullPath);
|
||||
}
|
||||
|
||||
@@ -462,14 +520,13 @@ interface Array<T> {}`
|
||||
const baseFolder = this.fs.get(basePath) as Folder;
|
||||
if (basePath !== fileOrDirectory.path) {
|
||||
Debug.assert(!!baseFolder);
|
||||
baseFolder.modifiedTime = new Date();
|
||||
filterMutate(baseFolder.entries, entry => entry !== fileOrDirectory);
|
||||
}
|
||||
this.fs.delete(fileOrDirectory.path);
|
||||
|
||||
if (isFile(fileOrDirectory) || isSymLink(fileOrDirectory)) {
|
||||
this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Deleted);
|
||||
}
|
||||
else {
|
||||
this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Deleted);
|
||||
if (isFolder(fileOrDirectory)) {
|
||||
Debug.assert(fileOrDirectory.entries.length === 0 || isRenaming);
|
||||
const relativePath = this.getRelativePathToDirectory(fileOrDirectory.fullPath, fileOrDirectory.fullPath);
|
||||
// Invoke directory and recursive directory watcher for the folder
|
||||
@@ -503,6 +560,8 @@ interface Array<T> {}`
|
||||
*/
|
||||
private invokeDirectoryWatcher(folderFullPath: string, fileName: string) {
|
||||
const relativePath = this.getRelativePathToDirectory(folderFullPath, fileName);
|
||||
// Folder is changed when the directory watcher is invoked
|
||||
invokeWatcherCallbacks(this.watchedFiles.get(this.toPath(folderFullPath)), ({ cb, fileName }) => cb(fileName, FileWatcherEventKind.Changed));
|
||||
invokeWatcherCallbacks(this.watchedDirectories.get(this.toPath(folderFullPath)), cb => this.directoryCallback(cb, relativePath));
|
||||
this.invokeRecursiveDirectoryWatcher(folderFullPath, fileName);
|
||||
}
|
||||
@@ -523,34 +582,34 @@ interface Array<T> {}`
|
||||
}
|
||||
}
|
||||
|
||||
private toFile(fileOrDirectory: FileOrFolder): File {
|
||||
const fullPath = getNormalizedAbsolutePath(fileOrDirectory.path, this.currentDirectory);
|
||||
return {
|
||||
path: this.toPath(fullPath),
|
||||
content: fileOrDirectory.content,
|
||||
fullPath,
|
||||
fileSize: fileOrDirectory.fileSize
|
||||
};
|
||||
}
|
||||
|
||||
private toSymLink(fileOrDirectory: FileOrFolder): SymLink {
|
||||
const fullPath = getNormalizedAbsolutePath(fileOrDirectory.path, this.currentDirectory);
|
||||
return {
|
||||
path: this.toPath(fullPath),
|
||||
fullPath,
|
||||
symLink: getNormalizedAbsolutePath(fileOrDirectory.symLink, getDirectoryPath(fullPath))
|
||||
};
|
||||
}
|
||||
|
||||
private toFolder(path: string): Folder {
|
||||
private toFsEntry(path: string): FSEntry {
|
||||
const fullPath = getNormalizedAbsolutePath(path, this.currentDirectory);
|
||||
return {
|
||||
path: this.toPath(fullPath),
|
||||
entries: [],
|
||||
fullPath
|
||||
fullPath,
|
||||
modifiedTime: new Date()
|
||||
};
|
||||
}
|
||||
|
||||
private toFile(fileOrDirectory: FileOrFolder): File {
|
||||
const file = this.toFsEntry(fileOrDirectory.path) as File;
|
||||
file.content = fileOrDirectory.content;
|
||||
file.fileSize = fileOrDirectory.fileSize;
|
||||
return file;
|
||||
}
|
||||
|
||||
private toSymLink(fileOrDirectory: FileOrFolder): SymLink {
|
||||
const symLink = this.toFsEntry(fileOrDirectory.path) as SymLink;
|
||||
symLink.symLink = getNormalizedAbsolutePath(fileOrDirectory.symLink, getDirectoryPath(symLink.fullPath));
|
||||
return symLink;
|
||||
}
|
||||
|
||||
private toFolder(path: string): Folder {
|
||||
const folder = this.toFsEntry(path) as Folder;
|
||||
folder.entries = [];
|
||||
return folder;
|
||||
}
|
||||
|
||||
private getRealFsEntry<T extends FSEntry>(isFsEntry: (fsEntry: FSEntry) => fsEntry is T, path: Path, fsEntry = this.fs.get(path)): T | undefined {
|
||||
if (isFsEntry(fsEntry)) {
|
||||
return fsEntry;
|
||||
@@ -594,6 +653,12 @@ interface Array<T> {}`
|
||||
return !!this.getRealFile(path);
|
||||
}
|
||||
|
||||
getModifiedTime(s: string) {
|
||||
const path = this.toFullPath(s);
|
||||
const fsEntry = this.fs.get(path);
|
||||
return fsEntry && fsEntry.modifiedTime;
|
||||
}
|
||||
|
||||
readFile(s: string): string {
|
||||
const fsEntry = this.getRealFile(this.toFullPath(s));
|
||||
return fsEntry ? fsEntry.content : undefined;
|
||||
@@ -646,6 +711,9 @@ interface Array<T> {}`
|
||||
}
|
||||
|
||||
watchDirectory(directoryName: string, cb: DirectoryWatcherCallback, recursive: boolean): FileWatcher {
|
||||
if (recursive && this.customRecursiveWatchDirectory) {
|
||||
return this.customRecursiveWatchDirectory(directoryName, cb, /*recursive*/ true);
|
||||
}
|
||||
const path = this.toFullPath(directoryName);
|
||||
const map = recursive ? this.watchedDirectoriesRecursive : this.watchedDirectories;
|
||||
const callback: TestDirectoryWatcher = {
|
||||
@@ -662,7 +730,11 @@ interface Array<T> {}`
|
||||
return Harness.mockHash(s);
|
||||
}
|
||||
|
||||
watchFile(fileName: string, cb: FileWatcherCallback) {
|
||||
watchFile(fileName: string, cb: FileWatcherCallback, pollingInterval: number) {
|
||||
if (this.dynamicPriorityWatchFile) {
|
||||
return this.dynamicPriorityWatchFile(fileName, cb, pollingInterval);
|
||||
}
|
||||
|
||||
const path = this.toFullPath(fileName);
|
||||
const callback: TestFileWatcher = { fileName, cb };
|
||||
this.watchedFiles.add(path, callback);
|
||||
@@ -701,7 +773,7 @@ interface Array<T> {}`
|
||||
this.timeoutCallbacks.invoke(timeoutId);
|
||||
}
|
||||
catch (e) {
|
||||
if (e.message === this.existMessage) {
|
||||
if (e.message === this.exitMessage) {
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
@@ -779,15 +851,17 @@ interface Array<T> {}`
|
||||
return realFullPath;
|
||||
}
|
||||
|
||||
readonly existMessage = "System Exit";
|
||||
readonly exitMessage = "System Exit";
|
||||
exitCode: number;
|
||||
readonly resolvePath = (s: string) => s;
|
||||
readonly getExecutingFilePath = () => this.executingFilePath;
|
||||
readonly getCurrentDirectory = () => this.currentDirectory;
|
||||
exit(exitCode?: number) {
|
||||
this.exitCode = exitCode;
|
||||
throw new Error(this.existMessage);
|
||||
throw new Error(this.exitMessage);
|
||||
}
|
||||
getEnvironmentVariable(name: string) {
|
||||
return this.environmentVariables && this.environmentVariables.get(name);
|
||||
}
|
||||
readonly getEnvironmentVariable = notImplemented;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+15062
-14535
File diff suppressed because it is too large
Load Diff
Vendored
+1757
-1930
File diff suppressed because it is too large
Load Diff
+10
-2
@@ -522,8 +522,16 @@ namespace ts.server {
|
||||
}));
|
||||
}
|
||||
|
||||
getOutliningSpans(_fileName: string): OutliningSpan[] {
|
||||
return notImplemented();
|
||||
getOutliningSpans(file: string): OutliningSpan[] {
|
||||
const request = this.processRequest<protocol.OutliningSpansRequest>(CommandNames.GetOutliningSpans, { file });
|
||||
const response = this.processResponse<protocol.OutliningSpansResponse>(request);
|
||||
|
||||
return response.body.map<OutliningSpan>(item => ({
|
||||
textSpan: this.decodeSpan(item.textSpan, file),
|
||||
hintSpan: this.decodeSpan(item.hintSpan, file),
|
||||
bannerText: item.bannerText,
|
||||
autoCollapse: item.autoCollapse
|
||||
}));
|
||||
}
|
||||
|
||||
getTodoComments(_fileName: string, _descriptors: TodoCommentDescriptor[]): TodoComment[] {
|
||||
|
||||
@@ -311,9 +311,9 @@ namespace ts.server {
|
||||
typesMapLocation?: string;
|
||||
}
|
||||
|
||||
type WatchFile = (host: ServerHost, file: string, cb: FileWatcherCallback, watchType: WatchType, project?: Project) => FileWatcher;
|
||||
type WatchFilePath = (host: ServerHost, file: string, cb: FilePathWatcherCallback, path: Path, watchType: WatchType, project?: Project) => FileWatcher;
|
||||
type WatchDirectory = (host: ServerHost, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, watchType: WatchType, project?: Project) => FileWatcher;
|
||||
function getDetailWatchInfo(watchType: WatchType, project: Project | undefined) {
|
||||
return `Project: ${project ? project.getProjectName() : ""} WatchType: ${watchType}`;
|
||||
}
|
||||
|
||||
export class ProjectService {
|
||||
|
||||
@@ -401,11 +401,7 @@ namespace ts.server {
|
||||
private readonly seenProjects = createMap<true>();
|
||||
|
||||
/*@internal*/
|
||||
readonly watchFile: WatchFile;
|
||||
/*@internal*/
|
||||
readonly watchFilePath: WatchFilePath;
|
||||
/*@internal*/
|
||||
readonly watchDirectory: WatchDirectory;
|
||||
readonly watchFactory: WatchFactory<WatchType, Project>;
|
||||
|
||||
constructor(opts: ProjectServiceOptions) {
|
||||
this.host = opts.host;
|
||||
@@ -447,26 +443,10 @@ namespace ts.server {
|
||||
};
|
||||
|
||||
this.documentRegistry = createDocumentRegistry(this.host.useCaseSensitiveFileNames, this.currentDirectory);
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.watchFile = (host, file, cb, watchType, project) => addFileWatcherWithLogging(host, file, cb, this.createWatcherLog(watchType, project));
|
||||
this.watchFilePath = (host, file, cb, path, watchType, project) => addFilePathWatcherWithLogging(host, file, cb, path, this.createWatcherLog(watchType, project));
|
||||
this.watchDirectory = (host, dir, cb, flags, watchType, project) => addDirectoryWatcherWithLogging(host, dir, cb, flags, this.createWatcherLog(watchType, project));
|
||||
}
|
||||
else if (this.logger.loggingEnabled()) {
|
||||
this.watchFile = (host, file, cb, watchType, project) => addFileWatcherWithOnlyTriggerLogging(host, file, cb, this.createWatcherLog(watchType, project));
|
||||
this.watchFilePath = (host, file, cb, path, watchType, project) => addFilePathWatcherWithOnlyTriggerLogging(host, file, cb, path, this.createWatcherLog(watchType, project));
|
||||
this.watchDirectory = (host, dir, cb, flags, watchType, project) => addDirectoryWatcherWithOnlyTriggerLogging(host, dir, cb, flags, this.createWatcherLog(watchType, project));
|
||||
}
|
||||
else {
|
||||
this.watchFile = addFileWatcher;
|
||||
this.watchFilePath = addFilePathWatcher;
|
||||
this.watchDirectory = addDirectoryWatcher;
|
||||
}
|
||||
}
|
||||
|
||||
private createWatcherLog(watchType: WatchType, project: Project | undefined): (s: string) => void {
|
||||
const detailedInfo = ` Project: ${project ? project.getProjectName() : ""} WatchType: ${watchType}`;
|
||||
return s => this.logger.info(s + detailedInfo);
|
||||
const watchLogLevel = this.logger.hasLevel(LogLevel.verbose) ? WatchLogLevel.Verbose :
|
||||
this.logger.loggingEnabled() ? WatchLogLevel.TriggerOnly : WatchLogLevel.None;
|
||||
const log: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? (s => this.logger.info(s)) : noop;
|
||||
this.watchFactory = getWatchFactory(watchLogLevel, log, getDetailWatchInfo);
|
||||
}
|
||||
|
||||
toPath(fileName: string) {
|
||||
@@ -714,8 +694,8 @@ namespace ts.server {
|
||||
return formatCodeSettings || this.hostConfiguration.formatCodeOptions;
|
||||
}
|
||||
|
||||
private onSourceFileChanged(fileName: NormalizedPath, eventKind: FileWatcherEventKind) {
|
||||
const info = this.getScriptInfoForNormalizedPath(fileName);
|
||||
private onSourceFileChanged(fileName: string, eventKind: FileWatcherEventKind, path: Path) {
|
||||
const info = this.getScriptInfoForPath(path);
|
||||
if (!info) {
|
||||
this.logger.msg(`Error: got watch notification for unknown file: ${fileName}`);
|
||||
}
|
||||
@@ -759,7 +739,7 @@ namespace ts.server {
|
||||
*/
|
||||
/*@internal*/
|
||||
watchWildcardDirectory(directory: Path, flags: WatchDirectoryFlags, project: ConfiguredProject) {
|
||||
return this.watchDirectory(
|
||||
return this.watchFactory.watchDirectory(
|
||||
this.host,
|
||||
directory,
|
||||
fileOrDirectory => {
|
||||
@@ -1097,10 +1077,11 @@ namespace ts.server {
|
||||
canonicalConfigFilePath: string,
|
||||
configFileExistenceInfo: ConfigFileExistenceInfo
|
||||
) {
|
||||
configFileExistenceInfo.configFileWatcherForRootOfInferredProject = this.watchFile(
|
||||
configFileExistenceInfo.configFileWatcherForRootOfInferredProject = this.watchFactory.watchFile(
|
||||
this.host,
|
||||
configFileName,
|
||||
(_filename, eventKind) => this.onConfigFileChangeForOpenScriptInfo(configFileName, eventKind),
|
||||
PollingInterval.High,
|
||||
WatchType.ConfigFileForInferredRoot
|
||||
);
|
||||
this.logConfigFileWatchUpdate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.UpdatedCallback);
|
||||
@@ -1481,10 +1462,11 @@ namespace ts.server {
|
||||
|
||||
project.configFileSpecs = configFileSpecs;
|
||||
// TODO: We probably should also watch the configFiles that are extended
|
||||
project.configFileWatcher = this.watchFile(
|
||||
project.configFileWatcher = this.watchFactory.watchFile(
|
||||
this.host,
|
||||
configFileName,
|
||||
(_fileName, eventKind) => this.onConfigChangedForConfiguredProject(project, eventKind),
|
||||
PollingInterval.High,
|
||||
WatchType.ConfigFilePath,
|
||||
project
|
||||
);
|
||||
@@ -1745,10 +1727,12 @@ namespace ts.server {
|
||||
// do not watch files with mixed content - server doesn't know how to interpret it
|
||||
if (!info.isDynamicOrHasMixedContent()) {
|
||||
const { fileName } = info;
|
||||
info.fileWatcher = this.watchFile(
|
||||
info.fileWatcher = this.watchFactory.watchFilePath(
|
||||
this.host,
|
||||
fileName,
|
||||
(_fileName, eventKind) => this.onSourceFileChanged(fileName, eventKind),
|
||||
(fileName, eventKind, path) => this.onSourceFileChanged(fileName, eventKind, path),
|
||||
PollingInterval.Medium,
|
||||
info.path,
|
||||
WatchType.ClosedScriptInfo
|
||||
);
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ namespace ts.server {
|
||||
|
||||
/*@internal*/
|
||||
watchDirectoryOfFailedLookupLocation(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags) {
|
||||
return this.projectService.watchDirectory(
|
||||
return this.projectService.watchFactory.watchDirectory(
|
||||
this.projectService.host,
|
||||
directory,
|
||||
cb,
|
||||
@@ -415,7 +415,7 @@ namespace ts.server {
|
||||
|
||||
/*@internal*/
|
||||
watchTypeRootsDirectory(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags) {
|
||||
return this.projectService.watchDirectory(
|
||||
return this.projectService.watchFactory.watchDirectory(
|
||||
this.projectService.host,
|
||||
directory,
|
||||
cb,
|
||||
@@ -907,7 +907,7 @@ namespace ts.server {
|
||||
|
||||
const oldExternalFiles = this.externalFiles || emptyArray as SortedReadonlyArray<string>;
|
||||
this.externalFiles = this.getExternalFiles();
|
||||
enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles,
|
||||
enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles, compareStringsCaseSensitive,
|
||||
// Ensure a ScriptInfo is created for new external files. This is performed indirectly
|
||||
// by the LSHost for files in the program when the program is retrieved above but
|
||||
// the program doesn't contain external files so this must be done explicitly.
|
||||
@@ -915,8 +915,7 @@ namespace ts.server {
|
||||
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost);
|
||||
scriptInfo.attachToProject(this);
|
||||
},
|
||||
removed => this.detachScriptInfoFromProject(removed),
|
||||
compareStringsCaseSensitive
|
||||
removed => this.detachScriptInfoFromProject(removed)
|
||||
);
|
||||
const elapsed = timestamp() - start;
|
||||
this.writeLog(`Finishing updateGraphWorker: Project: ${this.getProjectName()} Version: ${this.getProjectVersion()} structureChanged: ${hasChanges} Elapsed: ${elapsed}ms`);
|
||||
@@ -932,7 +931,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private addMissingFileWatcher(missingFilePath: Path) {
|
||||
const fileWatcher = this.projectService.watchFile(
|
||||
const fileWatcher = this.projectService.watchFactory.watchFile(
|
||||
this.projectService.host,
|
||||
missingFilePath,
|
||||
(fileName, eventKind) => {
|
||||
@@ -948,6 +947,7 @@ namespace ts.server {
|
||||
this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this);
|
||||
}
|
||||
},
|
||||
PollingInterval.Medium,
|
||||
WatchType.MissingFilePath,
|
||||
this
|
||||
);
|
||||
|
||||
+37
-5
@@ -91,8 +91,9 @@ namespace ts.server.protocol {
|
||||
EncodedSemanticClassificationsFull = "encodedSemanticClassifications-full",
|
||||
/* @internal */
|
||||
Cleanup = "cleanup",
|
||||
GetOutliningSpans = "getOutliningSpans",
|
||||
/* @internal */
|
||||
OutliningSpans = "outliningSpans",
|
||||
GetOutliningSpansFull = "outliningSpans", // Full command name is different for backward compatibility purposes
|
||||
TodoComments = "todoComments",
|
||||
Indentation = "indentation",
|
||||
DocCommentTemplate = "docCommentTemplate",
|
||||
@@ -303,17 +304,48 @@ namespace ts.server.protocol {
|
||||
/**
|
||||
* Request to obtain outlining spans in file.
|
||||
*/
|
||||
/* @internal */
|
||||
export interface OutliningSpansRequest extends FileRequest {
|
||||
command: CommandTypes.OutliningSpans;
|
||||
command: CommandTypes.GetOutliningSpans;
|
||||
}
|
||||
|
||||
export interface OutliningSpan {
|
||||
/** The span of the document to actually collapse. */
|
||||
textSpan: TextSpan;
|
||||
|
||||
/** The span of the document to display when the user hovers over the collapsed span. */
|
||||
hintSpan: TextSpan;
|
||||
|
||||
/** The text to display in the editor for the collapsed region. */
|
||||
bannerText: string;
|
||||
|
||||
/**
|
||||
* Whether or not this region should be automatically collapsed when
|
||||
* the 'Collapse to Definitions' command is invoked.
|
||||
*/
|
||||
autoCollapse: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response to OutliningSpansRequest request.
|
||||
*/
|
||||
export interface OutliningSpansResponse extends Response {
|
||||
body?: OutliningSpan[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to obtain outlining spans in file.
|
||||
*/
|
||||
/* @internal */
|
||||
export interface OutliningSpansRequestFull extends FileRequest {
|
||||
command: CommandTypes.GetOutliningSpansFull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response to OutliningSpansRequest request.
|
||||
*/
|
||||
/* @internal */
|
||||
export interface OutliningSpansResponse extends Response {
|
||||
body?: OutliningSpan[];
|
||||
export interface OutliningSpansResponseFull extends Response {
|
||||
body?: ts.OutliningSpan[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-16
@@ -128,7 +128,7 @@ namespace ts.server {
|
||||
|
||||
const fs: {
|
||||
openSync(path: string, options: string): number;
|
||||
close(fd: number): void;
|
||||
close(fd: number, callback: (err: NodeJS.ErrnoException) => void): void;
|
||||
writeSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number): number;
|
||||
writeSync(fd: number, data: any, position?: number, enconding?: string): number;
|
||||
statSync(path: string): Stats;
|
||||
@@ -167,7 +167,7 @@ namespace ts.server {
|
||||
|
||||
close() {
|
||||
if (this.fd >= 0) {
|
||||
fs.close(this.fd);
|
||||
fs.close(this.fd, noop);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,11 +685,11 @@ namespace ts.server {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.stat(watchedFile.fileName, (err: any, stats: any) => {
|
||||
fs.stat(watchedFile.fileName, (err, stats) => {
|
||||
if (err) {
|
||||
if (err.code === "ENOENT") {
|
||||
if (watchedFile.mtime.getTime() !== 0) {
|
||||
watchedFile.mtime = new Date(0);
|
||||
watchedFile.mtime = missingFileModifiedTime;
|
||||
watchedFile.callback(watchedFile.fileName, FileWatcherEventKind.Deleted);
|
||||
}
|
||||
}
|
||||
@@ -698,17 +698,7 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
else {
|
||||
const oldTime = watchedFile.mtime.getTime();
|
||||
const newTime = stats.mtime.getTime();
|
||||
if (oldTime !== newTime) {
|
||||
watchedFile.mtime = stats.mtime;
|
||||
const eventKind = oldTime === 0
|
||||
? FileWatcherEventKind.Created
|
||||
: newTime === 0
|
||||
? FileWatcherEventKind.Deleted
|
||||
: FileWatcherEventKind.Changed;
|
||||
watchedFile.callback(watchedFile.fileName, eventKind);
|
||||
}
|
||||
onWatchedFileStat(watchedFile, stats.mtime);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -742,7 +732,7 @@ namespace ts.server {
|
||||
callback,
|
||||
mtime: sys.fileExists(fileName)
|
||||
? getModifiedTime(fileName)
|
||||
: new Date(0) // Any subsequent modification will occur after this time
|
||||
: missingFileModifiedTime // Any subsequent modification will occur after this time
|
||||
};
|
||||
|
||||
watchedFiles.push(file);
|
||||
@@ -991,6 +981,7 @@ namespace ts.server {
|
||||
ioSession.logError(err, "unknown");
|
||||
});
|
||||
// See https://github.com/Microsoft/TypeScript/issues/11348
|
||||
// tslint:disable-next-line no-unnecessary-type-assertion-2
|
||||
(process as any).noAsar = true;
|
||||
// Start listening
|
||||
ioSession.listen();
|
||||
|
||||
+19
-4
@@ -1087,9 +1087,21 @@ namespace ts.server {
|
||||
return { file, project };
|
||||
}
|
||||
|
||||
private getOutliningSpans(args: protocol.FileRequestArgs) {
|
||||
private getOutliningSpans(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.OutliningSpan[] | OutliningSpan[] {
|
||||
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
|
||||
return languageService.getOutliningSpans(file);
|
||||
const spans = languageService.getOutliningSpans(file);
|
||||
if (simplifiedResult) {
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
|
||||
return spans.map(s => ({
|
||||
textSpan: this.toLocationTextSpan(s.textSpan, scriptInfo),
|
||||
hintSpan: this.toLocationTextSpan(s.hintSpan, scriptInfo),
|
||||
bannerText: s.bannerText,
|
||||
autoCollapse: s.autoCollapse
|
||||
}));
|
||||
}
|
||||
else {
|
||||
return spans;
|
||||
}
|
||||
}
|
||||
|
||||
private getTodoComments(args: protocol.TodoCommentRequestArgs) {
|
||||
@@ -1893,8 +1905,11 @@ namespace ts.server {
|
||||
[CommandNames.QuickinfoFull]: (request: protocol.QuickInfoRequest) => {
|
||||
return this.requiredResponse(this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.OutliningSpans]: (request: protocol.FileRequest) => {
|
||||
return this.requiredResponse(this.getOutliningSpans(request.arguments));
|
||||
[CommandNames.GetOutliningSpans]: (request: protocol.FileRequest) => {
|
||||
return this.requiredResponse(this.getOutliningSpans(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.GetOutliningSpansFull]: (request: protocol.FileRequest) => {
|
||||
return this.requiredResponse(this.getOutliningSpans(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.TodoComments]: (request: protocol.TodoCommentRequest) => {
|
||||
return this.requiredResponse(this.getTodoComments(request.arguments));
|
||||
|
||||
@@ -264,36 +264,6 @@ namespace ts.server {
|
||||
return index === 0 || value !== array[index - 1];
|
||||
}
|
||||
|
||||
export function enumerateInsertsAndDeletes<T>(newItems: SortedReadonlyArray<T>, oldItems: SortedReadonlyArray<T>, inserted: (newItem: T) => void, deleted: (oldItem: T) => void, comparer: Comparer<T>) {
|
||||
let newIndex = 0;
|
||||
let oldIndex = 0;
|
||||
const newLen = newItems.length;
|
||||
const oldLen = oldItems.length;
|
||||
while (newIndex < newLen && oldIndex < oldLen) {
|
||||
const newItem = newItems[newIndex];
|
||||
const oldItem = oldItems[oldIndex];
|
||||
const compareResult = comparer(newItem, oldItem);
|
||||
if (compareResult === Comparison.LessThan) {
|
||||
inserted(newItem);
|
||||
newIndex++;
|
||||
}
|
||||
else if (compareResult === Comparison.GreaterThan) {
|
||||
deleted(oldItem);
|
||||
oldIndex++;
|
||||
}
|
||||
else {
|
||||
newIndex++;
|
||||
oldIndex++;
|
||||
}
|
||||
}
|
||||
while (newIndex < newLen) {
|
||||
inserted(newItems[newIndex++]);
|
||||
}
|
||||
while (oldIndex < oldLen) {
|
||||
deleted(oldItems[oldIndex++]);
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function indent(str: string): string {
|
||||
return "\n " + str;
|
||||
|
||||
@@ -88,13 +88,6 @@ namespace ts {
|
||||
return createCombinedCodeActions(changes, commands.length === 0 ? undefined : commands);
|
||||
}
|
||||
|
||||
export function codeFixAllWithTextChanges(context: CodeFixAllContext, errorCodes: number[], use: (changes: Push<TextChange>, error: Diagnostic) => void): CombinedCodeActions {
|
||||
const changes: TextChange[] = [];
|
||||
eachDiagnostic(context, errorCodes, diag => use(changes, diag));
|
||||
changes.sort((a, b) => b.span.start - a.span.start);
|
||||
return createCombinedCodeActions([createFileTextChanges(context.sourceFile.fileName, changes)]);
|
||||
}
|
||||
|
||||
function eachDiagnostic({ program, sourceFile }: CodeFixAllContext, errorCodes: number[], cb: (diag: Diagnostic) => void): void {
|
||||
for (const diag of program.getSemanticDiagnostics(sourceFile).concat(computeSuggestionDiagnostics(sourceFile, program))) {
|
||||
if (contains(errorCodes, diag.code)) {
|
||||
|
||||
@@ -42,19 +42,28 @@ namespace ts.codefix {
|
||||
|
||||
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, decl: DeclarationWithType): void {
|
||||
if (isFunctionLikeDeclaration(decl) && (getJSDocReturnType(decl) || decl.parameters.some(p => !!getJSDocType(p)))) {
|
||||
findAncestor(decl, isFunctionLike);
|
||||
const fn = findAncestor(decl, isFunctionLikeDeclaration);
|
||||
const functionWithType = addTypesToFunctionLike(fn);
|
||||
suppressLeadingAndTrailingTrivia(functionWithType);
|
||||
changes.replaceNode(sourceFile, fn, functionWithType, textChanges.useNonAdjustedPositions);
|
||||
return;
|
||||
if (!decl.typeParameters) {
|
||||
const typeParameters = getJSDocTypeParameterDeclarations(decl);
|
||||
if (typeParameters) changes.insertTypeParameters(sourceFile, decl, typeParameters);
|
||||
}
|
||||
const needParens = isArrowFunction(decl) && !findChildOfKind(decl, SyntaxKind.OpenParenToken, sourceFile);
|
||||
if (needParens) changes.insertNodeBefore(sourceFile, first(decl.parameters), createToken(SyntaxKind.OpenParenToken));
|
||||
for (const param of decl.parameters) {
|
||||
if (!param.type) {
|
||||
const paramType = getJSDocType(param);
|
||||
if (paramType) changes.insertTypeAnnotation(sourceFile, param, transformJSDocType(paramType));
|
||||
}
|
||||
}
|
||||
if (needParens) changes.insertNodeAfter(sourceFile, last(decl.parameters), createToken(SyntaxKind.CloseParenToken));
|
||||
if (!decl.type) {
|
||||
const returnType = getJSDocReturnType(decl);
|
||||
if (returnType) changes.insertTypeAnnotation(sourceFile, decl, transformJSDocType(returnType));
|
||||
}
|
||||
}
|
||||
else {
|
||||
const jsdocType = Debug.assertDefined(getJSDocType(decl)); // If not defined, shouldn't have been an error to fix
|
||||
Debug.assert(!decl.type); // If defined, shouldn't have been an error to fix.
|
||||
const declarationWithType = addType(decl, transformJSDocType(jsdocType) as TypeNode);
|
||||
suppressLeadingAndTrailingTrivia(declarationWithType);
|
||||
changes.replaceNode(sourceFile, decl, declarationWithType, textChanges.useNonAdjustedPositions);
|
||||
changes.insertTypeAnnotation(sourceFile, decl, transformJSDocType(jsdocType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,48 +74,7 @@ namespace ts.codefix {
|
||||
node.kind === SyntaxKind.PropertyDeclaration;
|
||||
}
|
||||
|
||||
function addTypesToFunctionLike(decl: FunctionLikeDeclaration) {
|
||||
const typeParameters = getEffectiveTypeParameterDeclarations(decl, /*checkJSDoc*/ true);
|
||||
const parameters = decl.parameters.map(
|
||||
p => createParameter(p.decorators, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, transformJSDocType(getEffectiveTypeAnnotationNode(p, /*checkJSDoc*/ true)) as TypeNode, p.initializer));
|
||||
const returnType = transformJSDocType(getEffectiveReturnTypeNode(decl, /*checkJSDoc*/ true)) as TypeNode;
|
||||
switch (decl.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return createFunctionDeclaration(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, typeParameters, parameters, returnType, decl.body);
|
||||
case SyntaxKind.Constructor:
|
||||
return createConstructor(decl.decorators, decl.modifiers, parameters, decl.body);
|
||||
case SyntaxKind.FunctionExpression:
|
||||
return createFunctionExpression(decl.modifiers, decl.asteriskToken, decl.name, typeParameters, parameters, returnType, decl.body);
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return createArrowFunction(decl.modifiers, typeParameters, parameters, returnType, decl.equalsGreaterThanToken, decl.body);
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return createMethod(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.questionToken, typeParameters, parameters, returnType, decl.body);
|
||||
case SyntaxKind.GetAccessor:
|
||||
return createGetAccessor(decl.decorators, decl.modifiers, decl.name, decl.parameters, returnType, decl.body);
|
||||
case SyntaxKind.SetAccessor:
|
||||
return createSetAccessor(decl.decorators, decl.modifiers, decl.name, parameters, decl.body);
|
||||
default:
|
||||
return Debug.assertNever(decl, `Unexpected SyntaxKind: ${(decl as any).kind}`);
|
||||
}
|
||||
}
|
||||
|
||||
function addType(decl: DeclarationWithType, jsdocType: TypeNode) {
|
||||
switch (decl.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return createVariableDeclaration(decl.name, jsdocType, decl.initializer);
|
||||
case SyntaxKind.PropertySignature:
|
||||
return createPropertySignature(decl.modifiers, decl.name, decl.questionToken, jsdocType, decl.initializer);
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return createProperty(decl.decorators, decl.modifiers, decl.name, decl.questionToken, jsdocType, decl.initializer);
|
||||
default:
|
||||
return Debug.fail(`Unexpected SyntaxKind: ${decl.kind}`);
|
||||
}
|
||||
}
|
||||
|
||||
function transformJSDocType(node: Node): Node | undefined {
|
||||
if (node === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
function transformJSDocType(node: TypeNode): TypeNode | undefined {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JSDocAllType:
|
||||
case SyntaxKind.JSDocUnknownType:
|
||||
@@ -121,12 +89,10 @@ namespace ts.codefix {
|
||||
return transformJSDocVariadicType(node as JSDocVariadicType);
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
return transformJSDocFunctionType(node as JSDocFunctionType);
|
||||
case SyntaxKind.Parameter:
|
||||
return transformJSDocParameter(node as ParameterDeclaration);
|
||||
case SyntaxKind.TypeReference:
|
||||
return transformJSDocTypeReference(node as TypeReferenceNode);
|
||||
default:
|
||||
const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined) as TypeNode;
|
||||
const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined);
|
||||
setEmitFlags(visited, EmitFlags.SingleLine);
|
||||
return visited;
|
||||
}
|
||||
@@ -145,8 +111,7 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function transformJSDocFunctionType(node: JSDocFunctionType) {
|
||||
const parameters = node.parameters && node.parameters.map(transformJSDocType);
|
||||
return createFunctionTypeNode(emptyArray, parameters as ParameterDeclaration[], node.type);
|
||||
return createFunctionTypeNode(emptyArray, node.parameters.map(transformJSDocParameter), node.type);
|
||||
}
|
||||
|
||||
function transformJSDocParameter(node: ParameterDeclaration) {
|
||||
|
||||
@@ -221,4 +221,4 @@ namespace ts.codefix {
|
||||
function getModifierKindFromSource(source: Node, kind: SyntaxKind): ReadonlyArray<Modifier> {
|
||||
return filter(source.modifiers, modifier => modifier.kind === kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,60 +9,69 @@ namespace ts.codefix {
|
||||
registerCodeFix({
|
||||
errorCodes,
|
||||
getCodeActions(context) {
|
||||
const { sourceFile, program, span } = context;
|
||||
const { sourceFile, program, span, host, formatContext } = context;
|
||||
|
||||
if (!isInJavaScriptFile(sourceFile) || !isCheckJsEnabledForFile(sourceFile, program.getCompilerOptions())) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const newLineCharacter = getNewLineOrDefaultFromHost(context.host, context.formatContext.options);
|
||||
const fixes: CodeFixAction[] = [
|
||||
{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Disable_checking_for_this_file),
|
||||
changes: [createFileTextChanges(sourceFile.fileName, [
|
||||
createTextChange(sourceFile.checkJsDirective
|
||||
? createTextSpanFromBounds(sourceFile.checkJsDirective.pos, sourceFile.checkJsDirective.end)
|
||||
: createTextSpan(0, 0), `// @ts-nocheck${getNewLineOrDefaultFromHost(host, formatContext.options)}`),
|
||||
])],
|
||||
// fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file.
|
||||
fixId: undefined,
|
||||
}];
|
||||
|
||||
return [{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Ignore_this_error_message),
|
||||
changes: [createFileTextChanges(sourceFile.fileName, [getIgnoreCommentLocationForLocation(sourceFile, span.start, newLineCharacter).change])],
|
||||
fixId,
|
||||
},
|
||||
{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Disable_checking_for_this_file),
|
||||
changes: [createFileTextChanges(sourceFile.fileName, [
|
||||
createTextChange(sourceFile.checkJsDirective ? createTextSpanFromBounds(sourceFile.checkJsDirective.pos, sourceFile.checkJsDirective.end) : createTextSpan(0, 0), `// @ts-nocheck${newLineCharacter}`),
|
||||
])],
|
||||
// fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file.
|
||||
fixId: undefined,
|
||||
}];
|
||||
if (isValidSuppressLocation(sourceFile, span.start)) {
|
||||
fixes.unshift({
|
||||
description: getLocaleSpecificMessage(Diagnostics.Ignore_this_error_message),
|
||||
changes: textChanges.ChangeTracker.with(context, t => makeChange(t, sourceFile, span.start)),
|
||||
fixId,
|
||||
});
|
||||
}
|
||||
|
||||
return fixes;
|
||||
},
|
||||
fixIds: [fixId],
|
||||
getAllCodeActions: context => {
|
||||
const seenLines = createMap<true>(); // Only need to add `// @ts-ignore` for a line once.
|
||||
return codeFixAllWithTextChanges(context, errorCodes, (changes, err) => {
|
||||
if (err.start !== undefined) {
|
||||
const { lineNumber, change } = getIgnoreCommentLocationForLocation(err.file!, err.start, getNewLineOrDefaultFromHost(context.host, context.formatContext.options));
|
||||
if (addToSeen(seenLines, lineNumber)) {
|
||||
changes.push(change);
|
||||
}
|
||||
const seenLines = createMap<true>();
|
||||
return codeFixAll(context, errorCodes, (changes, diag) => {
|
||||
if (isValidSuppressLocation(diag.file!, diag.start!)) {
|
||||
makeChange(changes, diag.file!, diag.start!, seenLines);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
function getIgnoreCommentLocationForLocation(sourceFile: SourceFile, position: number, newLineCharacter: string): { lineNumber: number, change: TextChange } {
|
||||
function isValidSuppressLocation(sourceFile: SourceFile, position: number) {
|
||||
return !isInComment(sourceFile, position) && !isInString(sourceFile, position) && !isInTemplateString(sourceFile, position);
|
||||
}
|
||||
|
||||
function makeChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, seenLines?: Map<true>) {
|
||||
const { line: lineNumber } = getLineAndCharacterOfPosition(sourceFile, position);
|
||||
|
||||
// Only need to add `// @ts-ignore` for a line once.
|
||||
if (seenLines && !addToSeen(seenLines, lineNumber)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lineStartPosition = getStartPositionOfLine(lineNumber, sourceFile);
|
||||
const startPosition = getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition);
|
||||
|
||||
// First try to see if we can put the '// @ts-ignore' on the previous line.
|
||||
// We need to make sure that we are not in the middle of a string literal or a comment.
|
||||
// We also want to check if the previous line holds a comment for a node on the next line
|
||||
// if so, we do not want to separate the node from its comment if we can.
|
||||
if (!isInComment(sourceFile, startPosition) && !isInString(sourceFile, startPosition) && !isInTemplateString(sourceFile, startPosition)) {
|
||||
const token = getTouchingToken(sourceFile, startPosition, /*includeJsDocComment*/ false);
|
||||
const tokenLeadingComments = getLeadingCommentRangesOfNode(token, sourceFile);
|
||||
if (!tokenLeadingComments || !tokenLeadingComments.length || tokenLeadingComments[0].pos >= startPosition) {
|
||||
return { lineNumber, change: createTextChangeFromStartLength(startPosition, 0, `// @ts-ignore${newLineCharacter}`) };
|
||||
}
|
||||
}
|
||||
// If so, we do not want to separate the node from its comment if we can.
|
||||
// Otherwise, add an extra new line immediately before the error span.
|
||||
const insertAtLineStart = isValidSuppressLocation(sourceFile, startPosition);
|
||||
|
||||
// If all fails, add an extra new line immediately before the error span.
|
||||
return { lineNumber, change: createTextChangeFromStartLength(position, 0, `${position === startPosition ? "" : newLineCharacter}// @ts-ignore${newLineCharacter}`) };
|
||||
const token = getTouchingToken(sourceFile, insertAtLineStart ? startPosition : position, /*includeJsDocComment*/ false);
|
||||
const clone = setStartsOnNewLine(getSynthesizedDeepClone(token), true);
|
||||
addSyntheticLeadingComment(clone, SyntaxKind.SingleLineCommentTrivia, " @ts-ignore");
|
||||
changes.replaceNode(sourceFile, token, clone, { preserveLeadingWhitespace: true, prefix: insertAtLineStart ? undefined : changes.newLineCharacter });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,42 +21,36 @@ namespace ts.codefix {
|
||||
return actions;
|
||||
|
||||
function fix(type: Type, fixId: string): CodeFixAction {
|
||||
const newText = typeString(type, checker);
|
||||
return {
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Change_0_to_1), [original, newText]),
|
||||
changes: [createFileTextChanges(sourceFile.fileName, [createChange(typeNode, sourceFile, newText)])],
|
||||
fixId,
|
||||
};
|
||||
const newText = checker.typeToString(type);
|
||||
const description = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Change_0_to_1), [original, newText]);
|
||||
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, typeNode, type, checker));
|
||||
return { description, changes, fixId };
|
||||
}
|
||||
},
|
||||
fixIds: [fixIdPlain, fixIdNullable],
|
||||
getAllCodeActions(context) {
|
||||
const { fixId, program, sourceFile } = context;
|
||||
const checker = program.getTypeChecker();
|
||||
return codeFixAllWithTextChanges(context, errorCodes, (changes, err) => {
|
||||
return codeFixAll(context, errorCodes, (changes, err) => {
|
||||
const info = getInfo(err.file, err.start!, checker);
|
||||
if (!info) return;
|
||||
const { typeNode, type } = info;
|
||||
const fixedType = typeNode.kind === SyntaxKind.JSDocNullableType && fixId === fixIdNullable ? checker.getNullableType(type, TypeFlags.Undefined) : type;
|
||||
changes.push(createChange(typeNode, sourceFile, typeString(fixedType, checker)));
|
||||
doChange(changes, sourceFile, typeNode, fixedType, checker);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, oldTypeNode: TypeNode, newType: Type, checker: TypeChecker): void {
|
||||
changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode));
|
||||
}
|
||||
|
||||
function getInfo(sourceFile: SourceFile, pos: number, checker: TypeChecker): { readonly typeNode: TypeNode, type: Type } {
|
||||
const decl = findAncestor(getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), isTypeContainer);
|
||||
const typeNode = decl && decl.type;
|
||||
return typeNode && { typeNode, type: checker.getTypeFromTypeNode(typeNode) };
|
||||
}
|
||||
|
||||
function createChange(declaration: TypeNode, sourceFile: SourceFile, newText: string): TextChange {
|
||||
return createTextChange(createTextSpanFromNode(declaration, sourceFile), newText);
|
||||
}
|
||||
|
||||
function typeString(type: Type, checker: TypeChecker): string {
|
||||
return checker.typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTruncation);
|
||||
}
|
||||
|
||||
// TODO: GH#19856 Node & { type: TypeNode }
|
||||
type TypeContainer =
|
||||
| AsExpression | CallSignatureDeclaration | ConstructSignatureDeclaration | FunctionDeclaration
|
||||
|
||||
@@ -5,12 +5,20 @@ namespace ts.codefix {
|
||||
const errorCodes = [
|
||||
Diagnostics._0_is_declared_but_its_value_is_never_read.code,
|
||||
Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code,
|
||||
Diagnostics.All_imports_in_import_declaration_are_unused.code,
|
||||
];
|
||||
registerCodeFix({
|
||||
errorCodes,
|
||||
getCodeActions(context) {
|
||||
const { sourceFile } = context;
|
||||
const token = getToken(sourceFile, context.span.start);
|
||||
const { errorCode, sourceFile } = context;
|
||||
const importDecl = tryGetFullImport(sourceFile, context.span.start);
|
||||
if (importDecl) {
|
||||
const description = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Remove_import_from_0), [showModuleSpecifier(importDecl)]);
|
||||
const changes = textChanges.ChangeTracker.with(context, t => t.deleteNode(sourceFile, importDecl));
|
||||
return [{ description, changes, fixId: fixIdDelete }];
|
||||
}
|
||||
|
||||
const token = getToken(sourceFile, textSpanEnd(context.span));
|
||||
const result: CodeFixAction[] = [];
|
||||
|
||||
const deletion = textChanges.ChangeTracker.with(context, t => tryDeleteDeclaration(t, sourceFile, token));
|
||||
@@ -19,7 +27,7 @@ namespace ts.codefix {
|
||||
result.push({ description, changes: deletion, fixId: fixIdDelete });
|
||||
}
|
||||
|
||||
const prefix = textChanges.ChangeTracker.with(context, t => tryPrefixDeclaration(t, context.errorCode, sourceFile, token));
|
||||
const prefix = textChanges.ChangeTracker.with(context, t => tryPrefixDeclaration(t, errorCode, sourceFile, token));
|
||||
if (prefix.length) {
|
||||
const description = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Prefix_0_with_an_underscore), [token.getText()]);
|
||||
result.push({ description, changes: prefix, fixId: fixIdPrefix });
|
||||
@@ -30,7 +38,7 @@ namespace ts.codefix {
|
||||
fixIds: [fixIdPrefix, fixIdDelete],
|
||||
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => {
|
||||
const { sourceFile } = context;
|
||||
const token = getToken(diag.file!, diag.start!);
|
||||
const token = findPrecedingToken(textSpanEnd(diag), diag.file!);
|
||||
switch (context.fixId) {
|
||||
case fixIdPrefix:
|
||||
if (isIdentifier(token) && canPrefix(token)) {
|
||||
@@ -38,7 +46,13 @@ namespace ts.codefix {
|
||||
}
|
||||
break;
|
||||
case fixIdDelete:
|
||||
tryDeleteDeclaration(changes, sourceFile, token);
|
||||
const importDecl = tryGetFullImport(diag.file!, diag.start!);
|
||||
if (importDecl) {
|
||||
changes.deleteNode(sourceFile, importDecl);
|
||||
}
|
||||
else {
|
||||
tryDeleteDeclaration(changes, sourceFile, token);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Debug.fail(JSON.stringify(context.fixId));
|
||||
@@ -46,10 +60,16 @@ namespace ts.codefix {
|
||||
}),
|
||||
});
|
||||
|
||||
// Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing.
|
||||
function tryGetFullImport(sourceFile: SourceFile, pos: number): ImportDeclaration | undefined {
|
||||
const startToken = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
|
||||
return startToken.kind === SyntaxKind.ImportKeyword ? tryCast(startToken.parent, isImportDeclaration) : undefined;
|
||||
}
|
||||
|
||||
function getToken(sourceFile: SourceFile, pos: number): Node {
|
||||
const token = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
|
||||
const token = findPrecedingToken(pos, sourceFile);
|
||||
// this handles var ["computed"] = 12;
|
||||
return token.kind === SyntaxKind.OpenBracketToken ? getTokenAtPosition(sourceFile, pos + 1, /*includeJsDocComment*/ false) : token;
|
||||
return token.kind === SyntaxKind.CloseBracketToken ? findPrecedingToken(pos - 1, sourceFile) : token;
|
||||
}
|
||||
|
||||
function tryPrefixDeclaration(changes: textChanges.ChangeTracker, errorCode: number, sourceFile: SourceFile, token: Node): void {
|
||||
|
||||
@@ -24,27 +24,26 @@ namespace ts.codefix {
|
||||
];
|
||||
registerCodeFix({
|
||||
errorCodes,
|
||||
getCodeActions({ sourceFile, program, span: { start }, errorCode, cancellationToken }) {
|
||||
getCodeActions(context) {
|
||||
const { sourceFile, program, span: { start }, errorCode, cancellationToken } = context;
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
return undefined; // TODO: GH#20113
|
||||
}
|
||||
|
||||
const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false);
|
||||
const fix = getFix(sourceFile, token, errorCode, program, cancellationToken);
|
||||
if (!fix) return undefined;
|
||||
|
||||
const { declaration, textChanges } = fix;
|
||||
const name = getNameOfDeclaration(declaration);
|
||||
const description = formatStringFromArgs(getLocaleSpecificMessage(getDiagnostic(errorCode, token)), [name.getText()]);
|
||||
return [{ description, changes: [{ fileName: sourceFile.fileName, textChanges }], fixId }];
|
||||
let declaration!: Declaration;
|
||||
const changes = textChanges.ChangeTracker.with(context, changes => { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken); });
|
||||
if (changes.length === 0) return undefined;
|
||||
const name = getNameOfDeclaration(declaration).getText();
|
||||
const description = formatStringFromArgs(getLocaleSpecificMessage(getDiagnostic(errorCode, token)), [name]);
|
||||
return [{ description, changes, fixId }];
|
||||
},
|
||||
fixIds: [fixId],
|
||||
getAllCodeActions(context) {
|
||||
const { sourceFile, program, cancellationToken } = context;
|
||||
const seenFunctions = createMap<true>();
|
||||
return codeFixAllWithTextChanges(context, errorCodes, (changes, err) => {
|
||||
const fix = getFix(sourceFile, getTokenAtPosition(err.file!, err.start!, /*includeJsDocComment*/ false), err.code, program, cancellationToken, seenFunctions);
|
||||
if (fix) changes.push(...fix.textChanges);
|
||||
return codeFixAll(context, errorCodes, (changes, err) => {
|
||||
doChange(changes, sourceFile, getTokenAtPosition(err.file!, err.start!, /*includeJsDocComment*/ false), err.code, program, cancellationToken, seenFunctions);
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -60,12 +59,7 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
interface Fix {
|
||||
readonly declaration: Declaration;
|
||||
readonly textChanges: TextChange[];
|
||||
}
|
||||
|
||||
function getFix(sourceFile: SourceFile, token: Node, errorCode: number, program: Program, cancellationToken: CancellationToken, seenFunctions?: Map<true>): Fix | undefined {
|
||||
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Node, errorCode: number, program: Program, cancellationToken: CancellationToken, seenFunctions?: Map<true>): Declaration | undefined {
|
||||
if (!isAllowedTokenKind(token.kind)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -74,11 +68,15 @@ namespace ts.codefix {
|
||||
// Variable and Property declarations
|
||||
case Diagnostics.Member_0_implicitly_has_an_1_type.code:
|
||||
case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code:
|
||||
return getCodeActionForVariableDeclaration(<PropertyDeclaration | PropertySignature | VariableDeclaration>token.parent, program, cancellationToken);
|
||||
annotateVariableDeclaration(changes, sourceFile, <PropertyDeclaration | PropertySignature | VariableDeclaration>token.parent, program, cancellationToken);
|
||||
return token.parent as Declaration;
|
||||
|
||||
case Diagnostics.Variable_0_implicitly_has_an_1_type.code: {
|
||||
const symbol = program.getTypeChecker().getSymbolAtLocation(token);
|
||||
return symbol && symbol.valueDeclaration && getCodeActionForVariableDeclaration(<VariableDeclaration>symbol.valueDeclaration, program, cancellationToken);
|
||||
if (symbol && symbol.valueDeclaration) {
|
||||
annotateVariableDeclaration(changes, sourceFile, <VariableDeclaration>symbol.valueDeclaration, program, cancellationToken);
|
||||
return symbol.valueDeclaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,22 +89,34 @@ namespace ts.codefix {
|
||||
// Parameter declarations
|
||||
case Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
|
||||
if (isSetAccessor(containingFunction)) {
|
||||
return getCodeActionForSetAccessor(containingFunction, program, cancellationToken);
|
||||
annotateSetAccessor(changes, sourceFile, containingFunction, program, cancellationToken);
|
||||
return containingFunction;
|
||||
}
|
||||
// falls through
|
||||
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
|
||||
return !seenFunctions || addToSeen(seenFunctions, getNodeId(containingFunction))
|
||||
? getCodeActionForParameters(cast(token.parent, isParameter), containingFunction, sourceFile, program, cancellationToken)
|
||||
: undefined;
|
||||
if (!seenFunctions || addToSeen(seenFunctions, getNodeId(containingFunction))) {
|
||||
const param = cast(token.parent, isParameter);
|
||||
annotateParameters(changes, param, containingFunction, sourceFile, program, cancellationToken);
|
||||
return param;
|
||||
}
|
||||
return undefined;
|
||||
|
||||
// Get Accessor declarations
|
||||
case Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code:
|
||||
case Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code:
|
||||
return isGetAccessor(containingFunction) ? getCodeActionForGetAccessor(containingFunction, sourceFile, program, cancellationToken) : undefined;
|
||||
if (isGetAccessor(containingFunction) && isIdentifier(containingFunction.name)) {
|
||||
annotate(changes, sourceFile, containingFunction, inferTypeForVariableFromUsage(containingFunction.name, program, cancellationToken), program);
|
||||
return containingFunction;
|
||||
}
|
||||
return undefined;
|
||||
|
||||
// Set Accessor declarations
|
||||
case Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code:
|
||||
return isSetAccessor(containingFunction) ? getCodeActionForSetAccessor(containingFunction, program, cancellationToken) : undefined;
|
||||
if (isSetAccessor(containingFunction)) {
|
||||
annotateSetAccessor(changes, sourceFile, containingFunction, program, cancellationToken);
|
||||
return containingFunction;
|
||||
}
|
||||
return undefined;
|
||||
|
||||
default:
|
||||
return Debug.fail(String(errorCode));
|
||||
@@ -127,10 +137,10 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function getCodeActionForVariableDeclaration(declaration: VariableDeclaration | PropertyDeclaration | PropertySignature, program: Program, cancellationToken: CancellationToken): Fix | undefined {
|
||||
if (!isIdentifier(declaration.name)) return undefined;
|
||||
const type = inferTypeForVariableFromUsage(declaration.name, program, cancellationToken);
|
||||
return makeFix(declaration, declaration.name.getEnd(), type, program);
|
||||
function annotateVariableDeclaration(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: VariableDeclaration | PropertyDeclaration | PropertySignature, program: Program, cancellationToken: CancellationToken): void {
|
||||
if (isIdentifier(declaration.name)) {
|
||||
annotate(changes, sourceFile, declaration, inferTypeForVariableFromUsage(declaration.name, program, cancellationToken), program);
|
||||
}
|
||||
}
|
||||
|
||||
function isApplicableFunctionForInference(declaration: FunctionLike): declaration is MethodDeclaration | FunctionDeclaration | ConstructorDeclaration {
|
||||
@@ -145,53 +155,51 @@ namespace ts.codefix {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getCodeActionForParameters(parameterDeclaration: ParameterDeclaration, containingFunction: FunctionLike, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): Fix | undefined {
|
||||
function annotateParameters(changes: textChanges.ChangeTracker, parameterDeclaration: ParameterDeclaration, containingFunction: FunctionLike, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): void {
|
||||
if (!isIdentifier(parameterDeclaration.name) || !isApplicableFunctionForInference(containingFunction)) {
|
||||
return undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
const types = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) ||
|
||||
containingFunction.parameters.map(p => isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : undefined);
|
||||
if (!types) return undefined;
|
||||
|
||||
// We didn't actually find a set of type inference positions matching each parameter position
|
||||
if (containingFunction.parameters.length !== types.length) {
|
||||
return undefined;
|
||||
if (!types || containingFunction.parameters.length !== types.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const textChanges = arrayFrom(mapDefinedIterator(zipToIterator(containingFunction.parameters, types), ([parameter, type]) =>
|
||||
type && !parameter.type && !parameter.initializer ? makeChange(containingFunction, parameter.end, type, program) : undefined));
|
||||
return textChanges.length ? { declaration: parameterDeclaration, textChanges } : undefined;
|
||||
zipWith(containingFunction.parameters, types, (parameter, type) => {
|
||||
if (!parameter.type && !parameter.initializer) {
|
||||
annotate(changes, sourceFile, parameter, type, program);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getCodeActionForSetAccessor(setAccessorDeclaration: SetAccessorDeclaration, program: Program, cancellationToken: CancellationToken): Fix | undefined {
|
||||
const setAccessorParameter = setAccessorDeclaration.parameters[0];
|
||||
if (!setAccessorParameter || !isIdentifier(setAccessorDeclaration.name) || !isIdentifier(setAccessorParameter.name)) {
|
||||
return undefined;
|
||||
function annotateSetAccessor(changes: textChanges.ChangeTracker, sourceFile: SourceFile, setAccessorDeclaration: SetAccessorDeclaration, program: Program, cancellationToken: CancellationToken): void {
|
||||
const param = firstOrUndefined(setAccessorDeclaration.parameters);
|
||||
if (param && isIdentifier(setAccessorDeclaration.name) && isIdentifier(param.name)) {
|
||||
const type = inferTypeForVariableFromUsage(setAccessorDeclaration.name, program, cancellationToken) ||
|
||||
inferTypeForVariableFromUsage(param.name, program, cancellationToken);
|
||||
annotate(changes, sourceFile, param, type, program);
|
||||
}
|
||||
|
||||
const type = inferTypeForVariableFromUsage(setAccessorDeclaration.name, program, cancellationToken) ||
|
||||
inferTypeForVariableFromUsage(setAccessorParameter.name, program, cancellationToken);
|
||||
return makeFix(setAccessorParameter, setAccessorParameter.name.getEnd(), type, program);
|
||||
}
|
||||
|
||||
function getCodeActionForGetAccessor(getAccessorDeclaration: GetAccessorDeclaration, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): Fix | undefined {
|
||||
if (!isIdentifier(getAccessorDeclaration.name)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const type = inferTypeForVariableFromUsage(getAccessorDeclaration.name, program, cancellationToken);
|
||||
const closeParenToken = findChildOfKind(getAccessorDeclaration, SyntaxKind.CloseParenToken, sourceFile);
|
||||
return makeFix(getAccessorDeclaration, closeParenToken.getEnd(), type, program);
|
||||
function annotate(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: textChanges.TypeAnnotatable, type: Type | undefined, program: Program): void {
|
||||
const typeNode = type && getTypeNodeIfAccessible(type, declaration, program.getTypeChecker());
|
||||
if (typeNode) changes.insertTypeAnnotation(sourceFile, declaration, typeNode);
|
||||
}
|
||||
|
||||
function makeFix(declaration: Declaration, start: number, type: Type | undefined, program: Program): Fix | undefined {
|
||||
return type && { declaration, textChanges: [makeChange(declaration, start, type, program)] };
|
||||
}
|
||||
|
||||
function makeChange(declaration: Declaration, start: number, type: Type | undefined, program: Program): TextChange | undefined {
|
||||
const typeString = type && typeToString(type, declaration, program.getTypeChecker());
|
||||
return typeString === undefined ? undefined : createTextChangeFromStartLength(start, 0, `: ${typeString}`);
|
||||
function getTypeNodeIfAccessible(type: Type, enclosingScope: Node, checker: TypeChecker): TypeNode | undefined {
|
||||
let typeIsAccessible = true;
|
||||
const notAccessible = () => { typeIsAccessible = false; };
|
||||
const res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, {
|
||||
trackSymbol: (symbol, declaration, meaning) => {
|
||||
typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible;
|
||||
},
|
||||
reportInaccessibleThisError: notAccessible,
|
||||
reportPrivateInBaseOfClassExpression: notAccessible,
|
||||
reportInaccessibleUniqueSymbolError: notAccessible,
|
||||
});
|
||||
return typeIsAccessible ? res : undefined;
|
||||
}
|
||||
|
||||
function getReferences(token: PropertyName | Token<SyntaxKind.ConstructorKeyword>, program: Program, cancellationToken: CancellationToken): ReadonlyArray<Identifier> {
|
||||
@@ -220,51 +228,6 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeAccessiblityWriter(checker: TypeChecker): EmitTextWriter {
|
||||
let str = "";
|
||||
let typeIsAccessible = true;
|
||||
|
||||
const writeText: (text: string) => void = text => str += text;
|
||||
return {
|
||||
getText: () => typeIsAccessible ? str : undefined,
|
||||
writeKeyword: writeText,
|
||||
writeOperator: writeText,
|
||||
writePunctuation: writeText,
|
||||
writeSpace: writeText,
|
||||
writeStringLiteral: writeText,
|
||||
writeParameter: writeText,
|
||||
writeProperty: writeText,
|
||||
writeSymbol: writeText,
|
||||
write: writeText,
|
||||
writeTextOfNode: writeText,
|
||||
rawWrite: writeText,
|
||||
writeLiteral: writeText,
|
||||
getTextPos: () => 0,
|
||||
getLine: () => 0,
|
||||
getColumn: () => 0,
|
||||
getIndent: () => 0,
|
||||
isAtStartOfLine: () => false,
|
||||
writeLine: () => writeText(" "),
|
||||
increaseIndent: noop,
|
||||
decreaseIndent: noop,
|
||||
clear: () => { str = ""; typeIsAccessible = true; },
|
||||
trackSymbol: (symbol, declaration, meaning) => {
|
||||
if (checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility !== SymbolAccessibility.Accessible) {
|
||||
typeIsAccessible = false;
|
||||
}
|
||||
},
|
||||
reportInaccessibleThisError: () => { typeIsAccessible = false; },
|
||||
reportPrivateInBaseOfClassExpression: () => { typeIsAccessible = false; },
|
||||
reportInaccessibleUniqueSymbolError: () => { typeIsAccessible = false; }
|
||||
};
|
||||
}
|
||||
|
||||
function typeToString(type: Type, enclosingDeclaration: Declaration, checker: TypeChecker): string {
|
||||
const writer = getTypeAccessiblityWriter(checker);
|
||||
checker.writeType(type, enclosingDeclaration, /*flags*/ undefined, writer);
|
||||
return writer.getText();
|
||||
}
|
||||
|
||||
namespace InferFromReference {
|
||||
interface CallContext {
|
||||
argumentTypes: Type[];
|
||||
|
||||
@@ -275,6 +275,7 @@ namespace ts.NavigationBar {
|
||||
case SpecialPropertyAssignmentKind.ExportsProperty:
|
||||
case SpecialPropertyAssignmentKind.ModuleExports:
|
||||
case SpecialPropertyAssignmentKind.PrototypeProperty:
|
||||
case SpecialPropertyAssignmentKind.Prototype:
|
||||
addNodeWithRecursiveChild(node, (node as BinaryExpression).right);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.ThisProperty:
|
||||
|
||||
@@ -94,6 +94,10 @@ namespace ts.textChanges {
|
||||
* Text of inserted node will be formatted with this delta, otherwise delta will be inferred from the new node kind
|
||||
*/
|
||||
delta?: number;
|
||||
/**
|
||||
* Do not trim leading white spaces in the edit range
|
||||
*/
|
||||
preserveLeadingWhitespace?: boolean;
|
||||
}
|
||||
|
||||
enum ChangeKind {
|
||||
@@ -136,7 +140,7 @@ namespace ts.textChanges {
|
||||
|
||||
export function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: ConfigurableStart, position: Position) {
|
||||
if (options.useNonAdjustedStartPosition) {
|
||||
return node.getStart();
|
||||
return node.getStart(sourceFile);
|
||||
}
|
||||
const fullStart = node.getFullStart();
|
||||
const start = node.getStart(sourceFile);
|
||||
@@ -195,6 +199,8 @@ namespace ts.textChanges {
|
||||
formatContext: formatting.FormatContext;
|
||||
}
|
||||
|
||||
export type TypeAnnotatable = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature;
|
||||
|
||||
export class ChangeTracker {
|
||||
private readonly changes: Change[] = [];
|
||||
private readonly deletedNodesInLists: true[] = []; // Stores ids of nodes in lists that we already deleted. Used to avoid deleting `, ` twice in `a, b`.
|
||||
@@ -212,7 +218,7 @@ namespace ts.textChanges {
|
||||
}
|
||||
|
||||
/** Public for tests only. Other callers should use `ChangeTracker.with`. */
|
||||
constructor(private readonly newLineCharacter: string, private readonly formatContext: formatting.FormatContext) {}
|
||||
constructor(public readonly newLineCharacter: string, private readonly formatContext: formatting.FormatContext) {}
|
||||
|
||||
public deleteRange(sourceFile: SourceFile, range: TextRange) {
|
||||
this.changes.push({ kind: ChangeKind.Remove, sourceFile, range });
|
||||
@@ -321,6 +327,10 @@ namespace ts.textChanges {
|
||||
return this;
|
||||
}
|
||||
|
||||
private insertNodesAt(sourceFile: SourceFile, pos: number, newNodes: ReadonlyArray<Node>, options: InsertNodeOptions = {}): void {
|
||||
this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile, options, nodes: newNodes, range: { pos, end: pos } });
|
||||
}
|
||||
|
||||
public insertNodeAtTopOfFile(sourceFile: SourceFile, newNode: Statement, blankLineBetween: boolean): void {
|
||||
const pos = getInsertionPositionAtSourceFileTop(sourceFile);
|
||||
this.insertNodeAt(sourceFile, pos, newNode, {
|
||||
@@ -339,6 +349,21 @@ namespace ts.textChanges {
|
||||
this.replaceRange(sourceFile, { pos, end: pos }, createToken(modifier), { suffix: " " });
|
||||
}
|
||||
|
||||
/** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */
|
||||
public insertTypeAnnotation(sourceFile: SourceFile, node: TypeAnnotatable, type: TypeNode): void {
|
||||
const end = (isFunctionLike(node)
|
||||
// If no `)`, is an arrow function `x => x`, so use the end of the first parameter
|
||||
? findChildOfKind(node, SyntaxKind.CloseParenToken, sourceFile) || first(node.parameters)
|
||||
: node.kind !== SyntaxKind.VariableDeclaration && node.questionToken ? node.questionToken : node.name).end;
|
||||
this.insertNodeAt(sourceFile, end, type, { prefix: ": " });
|
||||
}
|
||||
|
||||
public insertTypeParameters(sourceFile: SourceFile, node: SignatureDeclaration, typeParameters: ReadonlyArray<TypeParameterDeclaration>): void {
|
||||
// If no `(`, is an arrow function `x => x`, so use the pos of the first parameter
|
||||
const start = (findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile) || first(node.parameters)).getStart(sourceFile);
|
||||
this.insertNodesAt(sourceFile, start, typeParameters, { prefix: "<", suffix: ">" });
|
||||
}
|
||||
|
||||
private getOptionsForInsertNodeBefore(before: Node, doubleNewlines: boolean): ChangeNodeOptions {
|
||||
if (isStatement(before) || isClassElement(before)) {
|
||||
return { suffix: doubleNewlines ? this.newLineCharacter + this.newLineCharacter : this.newLineCharacter };
|
||||
@@ -346,6 +371,9 @@ namespace ts.textChanges {
|
||||
else if (isVariableDeclaration(before)) { // insert `x = 1, ` into `const x = 1, y = 2;
|
||||
return { suffix: ", " };
|
||||
}
|
||||
else if (isParameter(before)) {
|
||||
return {};
|
||||
}
|
||||
return Debug.failBadSyntaxKind(before); // We haven't handled this kind of node yet -- add it
|
||||
}
|
||||
|
||||
@@ -430,6 +458,9 @@ namespace ts.textChanges {
|
||||
else if (isVariableDeclaration(node)) {
|
||||
return { prefix: ", " };
|
||||
}
|
||||
else if (isParameter(node)) {
|
||||
return {};
|
||||
}
|
||||
return Debug.failBadSyntaxKind(node); // We haven't handled this kind of node yet -- add it
|
||||
}
|
||||
|
||||
@@ -628,7 +659,7 @@ namespace ts.textChanges {
|
||||
? change.nodes.map(n => removeSuffix(format(n), newLineCharacter)).join(newLineCharacter)
|
||||
: format(change.node);
|
||||
// strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line
|
||||
const noIndent = (options.indentation !== undefined || getLineStartPositionForPosition(pos, sourceFile) === pos) ? text : text.replace(/^\s+/, "");
|
||||
const noIndent = (options.preserveLeadingWhitespace || options.indentation !== undefined || getLineStartPositionForPosition(pos, sourceFile) === pos) ? text : text.replace(/^\s+/, "");
|
||||
return (options.prefix || "") + noIndent + (options.suffix || "");
|
||||
}
|
||||
|
||||
|
||||
+26
-31
@@ -359,6 +359,8 @@ namespace ts {
|
||||
case SpecialPropertyAssignmentKind.Property:
|
||||
// static method / property
|
||||
return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement;
|
||||
case SpecialPropertyAssignmentKind.Prototype:
|
||||
return ScriptElementKind.localClassElement;
|
||||
default: {
|
||||
assertTypeIsNever(kind);
|
||||
return ScriptElementKind.unknown;
|
||||
@@ -1386,37 +1388,30 @@ namespace ts {
|
||||
*/
|
||||
/* @internal */
|
||||
export function suppressLeadingAndTrailingTrivia(node: Node) {
|
||||
Debug.assert(node !== undefined);
|
||||
|
||||
suppressLeading(node);
|
||||
suppressTrailing(node);
|
||||
|
||||
function suppressLeading(node: Node) {
|
||||
addEmitFlags(node, EmitFlags.NoLeadingComments);
|
||||
|
||||
const firstChild = forEachChild(node, child => child);
|
||||
if (firstChild) {
|
||||
suppressLeading(firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
function suppressTrailing(node: Node) {
|
||||
addEmitFlags(node, EmitFlags.NoTrailingComments);
|
||||
|
||||
let lastChild: Node;
|
||||
forEachChild(
|
||||
node,
|
||||
child => (lastChild = child, undefined),
|
||||
children => {
|
||||
// As an optimization, jump straight to the end of the list.
|
||||
if (children.length) {
|
||||
lastChild = last(children);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
if (lastChild) {
|
||||
suppressTrailing(lastChild);
|
||||
}
|
||||
Debug.assertDefined(node);
|
||||
suppress(node, EmitFlags.NoLeadingComments, getFirstChild);
|
||||
suppress(node, EmitFlags.NoTrailingComments, getLastChild);
|
||||
function suppress(node: Node, flag: EmitFlags, getChild: (n: Node) => Node) {
|
||||
addEmitFlags(node, flag);
|
||||
const child = getChild(node);
|
||||
if (child) suppress(child, flag, getChild);
|
||||
}
|
||||
}
|
||||
|
||||
function getFirstChild(node: Node): Node | undefined {
|
||||
return node.forEachChild(child => child);
|
||||
}
|
||||
|
||||
function getLastChild(node: Node): Node | undefined {
|
||||
let lastChild: Node | undefined;
|
||||
node.forEachChild(
|
||||
child => { lastChild = child; },
|
||||
children => {
|
||||
// As an optimization, jump straight to the end of the list.
|
||||
if (children.length) {
|
||||
lastChild = last(children);
|
||||
}
|
||||
});
|
||||
return lastChild;
|
||||
}
|
||||
}
|
||||
|
||||
+50
-28
@@ -644,7 +644,8 @@ declare namespace ts {
|
||||
body?: Block | Expression;
|
||||
}
|
||||
type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionExpression | ArrowFunction;
|
||||
type FunctionLike = FunctionLikeDeclaration | FunctionTypeNode | ConstructorTypeNode | IndexSignatureDeclaration | MethodSignature | ConstructSignatureDeclaration | CallSignatureDeclaration | JSDocFunctionType;
|
||||
/** @deprecated Use SignatureDeclaration */
|
||||
type FunctionLike = SignatureDeclaration;
|
||||
interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement {
|
||||
kind: SyntaxKind.FunctionDeclaration;
|
||||
name?: Identifier;
|
||||
@@ -1801,7 +1802,7 @@ declare namespace ts {
|
||||
*/
|
||||
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature;
|
||||
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined;
|
||||
isImplementationOfOverload(node: FunctionLike): boolean | undefined;
|
||||
isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined;
|
||||
isUndefinedSymbol(symbol: Symbol): boolean;
|
||||
isArgumentsSymbol(symbol: Symbol): boolean;
|
||||
isUnknownSymbol(symbol: Symbol): boolean;
|
||||
@@ -1960,28 +1961,28 @@ declare namespace ts {
|
||||
JSContainer = 67108864,
|
||||
Enum = 384,
|
||||
Variable = 3,
|
||||
Value = 107455,
|
||||
Type = 793064,
|
||||
Value = 67216319,
|
||||
Type = 67901928,
|
||||
Namespace = 1920,
|
||||
Module = 1536,
|
||||
Accessor = 98304,
|
||||
FunctionScopedVariableExcludes = 107454,
|
||||
BlockScopedVariableExcludes = 107455,
|
||||
ParameterExcludes = 107455,
|
||||
FunctionScopedVariableExcludes = 67216318,
|
||||
BlockScopedVariableExcludes = 67216319,
|
||||
ParameterExcludes = 67216319,
|
||||
PropertyExcludes = 0,
|
||||
EnumMemberExcludes = 900095,
|
||||
FunctionExcludes = 106927,
|
||||
ClassExcludes = 899519,
|
||||
InterfaceExcludes = 792968,
|
||||
RegularEnumExcludes = 899327,
|
||||
ConstEnumExcludes = 899967,
|
||||
ValueModuleExcludes = 106639,
|
||||
EnumMemberExcludes = 68008959,
|
||||
FunctionExcludes = 67215791,
|
||||
ClassExcludes = 68008383,
|
||||
InterfaceExcludes = 67901832,
|
||||
RegularEnumExcludes = 68008191,
|
||||
ConstEnumExcludes = 68008831,
|
||||
ValueModuleExcludes = 67215503,
|
||||
NamespaceModuleExcludes = 0,
|
||||
MethodExcludes = 99263,
|
||||
GetAccessorExcludes = 41919,
|
||||
SetAccessorExcludes = 74687,
|
||||
TypeParameterExcludes = 530920,
|
||||
TypeAliasExcludes = 793064,
|
||||
MethodExcludes = 67208127,
|
||||
GetAccessorExcludes = 67150783,
|
||||
SetAccessorExcludes = 67183551,
|
||||
TypeParameterExcludes = 67639784,
|
||||
TypeAliasExcludes = 67901928,
|
||||
AliasExcludes = 2097152,
|
||||
ModuleMember = 2623475,
|
||||
ExportHasLocal = 944,
|
||||
@@ -2749,6 +2750,7 @@ declare namespace ts {
|
||||
newLine?: NewLineKind;
|
||||
omitTrailingSemicolon?: boolean;
|
||||
}
|
||||
/** @deprecated See comment on SymbolWriter */
|
||||
interface SymbolTracker {
|
||||
trackSymbol?(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
|
||||
reportInaccessibleThisError?(): void;
|
||||
@@ -2854,11 +2856,6 @@ declare namespace ts {
|
||||
}
|
||||
type FileWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind) => void;
|
||||
type DirectoryWatcherCallback = (fileName: string) => void;
|
||||
interface WatchedFile {
|
||||
fileName: string;
|
||||
callback: FileWatcherCallback;
|
||||
mtime?: Date;
|
||||
}
|
||||
interface System {
|
||||
args: string[];
|
||||
newLine: string;
|
||||
@@ -3215,7 +3212,7 @@ declare namespace ts {
|
||||
function isEntityName(node: Node): node is EntityName;
|
||||
function isPropertyName(node: Node): node is PropertyName;
|
||||
function isBindingName(node: Node): node is BindingName;
|
||||
function isFunctionLike(node: Node): node is FunctionLike;
|
||||
function isFunctionLike(node: Node): node is SignatureDeclaration;
|
||||
function isClassElement(node: Node): node is ClassElement;
|
||||
function isClassLike(node: Node): node is ClassLikeDeclaration;
|
||||
function isAccessor(node: Node): node is AccessorDeclaration;
|
||||
@@ -5066,6 +5063,7 @@ declare namespace ts.server.protocol {
|
||||
OpenExternalProject = "openExternalProject",
|
||||
OpenExternalProjects = "openExternalProjects",
|
||||
CloseExternalProject = "closeExternalProject",
|
||||
GetOutliningSpans = "getOutliningSpans",
|
||||
TodoComments = "todoComments",
|
||||
Indentation = "indentation",
|
||||
DocCommentTemplate = "docCommentTemplate",
|
||||
@@ -5224,6 +5222,31 @@ declare namespace ts.server.protocol {
|
||||
*/
|
||||
onlyMultiLine: boolean;
|
||||
}
|
||||
/**
|
||||
* Request to obtain outlining spans in file.
|
||||
*/
|
||||
interface OutliningSpansRequest extends FileRequest {
|
||||
command: CommandTypes.GetOutliningSpans;
|
||||
}
|
||||
interface OutliningSpan {
|
||||
/** The span of the document to actually collapse. */
|
||||
textSpan: TextSpan;
|
||||
/** The span of the document to display when the user hovers over the collapsed span. */
|
||||
hintSpan: TextSpan;
|
||||
/** The text to display in the editor for the collapsed region. */
|
||||
bannerText: string;
|
||||
/**
|
||||
* Whether or not this region should be automatically collapsed when
|
||||
* the 'Collapse to Definitions' command is invoked.
|
||||
*/
|
||||
autoCollapse: boolean;
|
||||
}
|
||||
/**
|
||||
* Response to OutliningSpansRequest request.
|
||||
*/
|
||||
interface OutliningSpansResponse extends Response {
|
||||
body?: OutliningSpan[];
|
||||
}
|
||||
/**
|
||||
* A request to get indentation for a location in file
|
||||
*/
|
||||
@@ -7275,7 +7298,7 @@ declare namespace ts.server {
|
||||
private getFileAndProject(args);
|
||||
private getFileAndLanguageServiceForSyntacticOperation(args);
|
||||
private getFileAndProjectWorker(uncheckedFileName, projectFileName);
|
||||
private getOutliningSpans(args);
|
||||
private getOutliningSpans(args, simplifiedResult);
|
||||
private getTodoComments(args);
|
||||
private getDocCommentTemplate(args);
|
||||
private getSpanOfEnclosingComment(args);
|
||||
@@ -7831,7 +7854,6 @@ declare namespace ts.server {
|
||||
/** Tracks projects that we have already sent telemetry for. */
|
||||
private readonly seenProjects;
|
||||
constructor(opts: ProjectServiceOptions);
|
||||
private createWatcherLog(watchType, project);
|
||||
toPath(fileName: string): Path;
|
||||
private loadTypesMap();
|
||||
updateTypingsForProject(response: SetTypings | InvalidateCachedTypings | PackageInstalledResponse): void;
|
||||
@@ -7853,7 +7875,7 @@ declare namespace ts.server {
|
||||
private ensureProjectStructuresUptoDate();
|
||||
private updateProjectIfDirty(project);
|
||||
getFormatCodeOptions(file?: NormalizedPath): FormatCodeSettings;
|
||||
private onSourceFileChanged(fileName, eventKind);
|
||||
private onSourceFileChanged(fileName, eventKind, path);
|
||||
private handleDeletedFile(info);
|
||||
private onConfigChangedForConfiguredProject(project, eventKind);
|
||||
/**
|
||||
|
||||
+22
-25
@@ -644,7 +644,8 @@ declare namespace ts {
|
||||
body?: Block | Expression;
|
||||
}
|
||||
type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionExpression | ArrowFunction;
|
||||
type FunctionLike = FunctionLikeDeclaration | FunctionTypeNode | ConstructorTypeNode | IndexSignatureDeclaration | MethodSignature | ConstructSignatureDeclaration | CallSignatureDeclaration | JSDocFunctionType;
|
||||
/** @deprecated Use SignatureDeclaration */
|
||||
type FunctionLike = SignatureDeclaration;
|
||||
interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement {
|
||||
kind: SyntaxKind.FunctionDeclaration;
|
||||
name?: Identifier;
|
||||
@@ -1801,7 +1802,7 @@ declare namespace ts {
|
||||
*/
|
||||
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature;
|
||||
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined;
|
||||
isImplementationOfOverload(node: FunctionLike): boolean | undefined;
|
||||
isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined;
|
||||
isUndefinedSymbol(symbol: Symbol): boolean;
|
||||
isArgumentsSymbol(symbol: Symbol): boolean;
|
||||
isUnknownSymbol(symbol: Symbol): boolean;
|
||||
@@ -1960,28 +1961,28 @@ declare namespace ts {
|
||||
JSContainer = 67108864,
|
||||
Enum = 384,
|
||||
Variable = 3,
|
||||
Value = 107455,
|
||||
Type = 793064,
|
||||
Value = 67216319,
|
||||
Type = 67901928,
|
||||
Namespace = 1920,
|
||||
Module = 1536,
|
||||
Accessor = 98304,
|
||||
FunctionScopedVariableExcludes = 107454,
|
||||
BlockScopedVariableExcludes = 107455,
|
||||
ParameterExcludes = 107455,
|
||||
FunctionScopedVariableExcludes = 67216318,
|
||||
BlockScopedVariableExcludes = 67216319,
|
||||
ParameterExcludes = 67216319,
|
||||
PropertyExcludes = 0,
|
||||
EnumMemberExcludes = 900095,
|
||||
FunctionExcludes = 106927,
|
||||
ClassExcludes = 899519,
|
||||
InterfaceExcludes = 792968,
|
||||
RegularEnumExcludes = 899327,
|
||||
ConstEnumExcludes = 899967,
|
||||
ValueModuleExcludes = 106639,
|
||||
EnumMemberExcludes = 68008959,
|
||||
FunctionExcludes = 67215791,
|
||||
ClassExcludes = 68008383,
|
||||
InterfaceExcludes = 67901832,
|
||||
RegularEnumExcludes = 68008191,
|
||||
ConstEnumExcludes = 68008831,
|
||||
ValueModuleExcludes = 67215503,
|
||||
NamespaceModuleExcludes = 0,
|
||||
MethodExcludes = 99263,
|
||||
GetAccessorExcludes = 41919,
|
||||
SetAccessorExcludes = 74687,
|
||||
TypeParameterExcludes = 530920,
|
||||
TypeAliasExcludes = 793064,
|
||||
MethodExcludes = 67208127,
|
||||
GetAccessorExcludes = 67150783,
|
||||
SetAccessorExcludes = 67183551,
|
||||
TypeParameterExcludes = 67639784,
|
||||
TypeAliasExcludes = 67901928,
|
||||
AliasExcludes = 2097152,
|
||||
ModuleMember = 2623475,
|
||||
ExportHasLocal = 944,
|
||||
@@ -2749,6 +2750,7 @@ declare namespace ts {
|
||||
newLine?: NewLineKind;
|
||||
omitTrailingSemicolon?: boolean;
|
||||
}
|
||||
/** @deprecated See comment on SymbolWriter */
|
||||
interface SymbolTracker {
|
||||
trackSymbol?(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
|
||||
reportInaccessibleThisError?(): void;
|
||||
@@ -2854,11 +2856,6 @@ declare namespace ts {
|
||||
}
|
||||
type FileWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind) => void;
|
||||
type DirectoryWatcherCallback = (fileName: string) => void;
|
||||
interface WatchedFile {
|
||||
fileName: string;
|
||||
callback: FileWatcherCallback;
|
||||
mtime?: Date;
|
||||
}
|
||||
interface System {
|
||||
args: string[];
|
||||
newLine: string;
|
||||
@@ -3270,7 +3267,7 @@ declare namespace ts {
|
||||
function isEntityName(node: Node): node is EntityName;
|
||||
function isPropertyName(node: Node): node is PropertyName;
|
||||
function isBindingName(node: Node): node is BindingName;
|
||||
function isFunctionLike(node: Node): node is FunctionLike;
|
||||
function isFunctionLike(node: Node): node is SignatureDeclaration;
|
||||
function isClassElement(node: Node): node is ClassElement;
|
||||
function isClassLike(node: Node): node is ClassLikeDeclaration;
|
||||
function isAccessor(node: Node): node is AccessorDeclaration;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
=== tests/cases/conformance/salsa/mod.js ===
|
||||
exports.n = {};
|
||||
>exports.n : Symbol(n, Decl(mod.js, 0, 0))
|
||||
>exports : Symbol(n, Decl(mod.js, 0, 0))
|
||||
>n : Symbol(n, Decl(mod.js, 0, 0))
|
||||
|
||||
exports.n.K = function () {
|
||||
>exports.n.K : Symbol(K, Decl(mod.js, 0, 15))
|
||||
>exports.n : Symbol(K, Decl(mod.js, 0, 15))
|
||||
>exports : Symbol("tests/cases/conformance/salsa/mod", Decl(mod.js, 0, 0))
|
||||
>n : Symbol(n, Decl(mod.js, 0, 0))
|
||||
>K : Symbol(K, Decl(mod.js, 0, 15))
|
||||
|
||||
this.x = 10;
|
||||
>this : Symbol(__object, Decl(mod.js, 0, 11), Decl(mod.js, 1, 8))
|
||||
>x : Symbol((Anonymous function).x, Decl(mod.js, 1, 27))
|
||||
}
|
||||
exports.Classic = class {
|
||||
>exports.Classic : Symbol(Classic, Decl(mod.js, 3, 1))
|
||||
>exports : Symbol(Classic, Decl(mod.js, 3, 1))
|
||||
>Classic : Symbol(Classic, Decl(mod.js, 3, 1))
|
||||
|
||||
constructor() {
|
||||
this.p = 1
|
||||
>this.p : Symbol((Anonymous class).p, Decl(mod.js, 5, 19))
|
||||
>this : Symbol((Anonymous class), Decl(mod.js, 4, 17))
|
||||
>p : Symbol((Anonymous class).p, Decl(mod.js, 5, 19))
|
||||
}
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/salsa/use.js ===
|
||||
import * as s from './mod'
|
||||
>s : Symbol(s, Decl(use.js, 0, 6))
|
||||
|
||||
var k = new s.n.K()
|
||||
>k : Symbol(k, Decl(use.js, 2, 3))
|
||||
>s.n.K : Symbol(K, Decl(mod.js, 0, 15))
|
||||
>s.n : Symbol(s.n, Decl(mod.js, 0, 0))
|
||||
>s : Symbol(s, Decl(use.js, 0, 6))
|
||||
>n : Symbol(s.n, Decl(mod.js, 0, 0))
|
||||
>K : Symbol(K, Decl(mod.js, 0, 15))
|
||||
|
||||
k.x
|
||||
>k.x : Symbol((Anonymous function).x, Decl(mod.js, 1, 27))
|
||||
>k : Symbol(k, Decl(use.js, 2, 3))
|
||||
>x : Symbol((Anonymous function).x, Decl(mod.js, 1, 27))
|
||||
|
||||
var classic = new s.Classic()
|
||||
>classic : Symbol(classic, Decl(use.js, 4, 3))
|
||||
>s.Classic : Symbol(s.Classic, Decl(mod.js, 3, 1))
|
||||
>s : Symbol(s, Decl(use.js, 0, 6))
|
||||
>Classic : Symbol(s.Classic, Decl(mod.js, 3, 1))
|
||||
|
||||
|
||||
/** @param {s.n.K} c
|
||||
@param {s.Classic} classic */
|
||||
function f(c, classic) {
|
||||
>f : Symbol(f, Decl(use.js, 4, 29))
|
||||
>c : Symbol(c, Decl(use.js, 9, 11))
|
||||
>classic : Symbol(classic, Decl(use.js, 9, 13))
|
||||
|
||||
c.x
|
||||
>c.x : Symbol((Anonymous function).x, Decl(mod.js, 1, 27))
|
||||
>c : Symbol(c, Decl(use.js, 9, 11))
|
||||
>x : Symbol((Anonymous function).x, Decl(mod.js, 1, 27))
|
||||
|
||||
classic.p
|
||||
>classic.p : Symbol((Anonymous class).p, Decl(mod.js, 5, 19))
|
||||
>classic : Symbol(classic, Decl(use.js, 9, 13))
|
||||
>p : Symbol((Anonymous class).p, Decl(mod.js, 5, 19))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
=== tests/cases/conformance/salsa/mod.js ===
|
||||
exports.n = {};
|
||||
>exports.n = {} : typeof __object
|
||||
>exports.n : typeof __object
|
||||
>exports : typeof "tests/cases/conformance/salsa/mod"
|
||||
>n : typeof __object
|
||||
>{} : typeof __object
|
||||
|
||||
exports.n.K = function () {
|
||||
>exports.n.K = function () { this.x = 10;} : () => void
|
||||
>exports.n.K : () => void
|
||||
>exports.n : typeof __object
|
||||
>exports : typeof "tests/cases/conformance/salsa/mod"
|
||||
>n : typeof __object
|
||||
>K : () => void
|
||||
>function () { this.x = 10;} : () => void
|
||||
|
||||
this.x = 10;
|
||||
>this.x = 10 : 10
|
||||
>this.x : any
|
||||
>this : typeof __object
|
||||
>x : any
|
||||
>10 : 10
|
||||
}
|
||||
exports.Classic = class {
|
||||
>exports.Classic = class { constructor() { this.p = 1 }} : typeof (Anonymous class)
|
||||
>exports.Classic : typeof (Anonymous class)
|
||||
>exports : typeof "tests/cases/conformance/salsa/mod"
|
||||
>Classic : typeof (Anonymous class)
|
||||
>class { constructor() { this.p = 1 }} : typeof (Anonymous class)
|
||||
|
||||
constructor() {
|
||||
this.p = 1
|
||||
>this.p = 1 : 1
|
||||
>this.p : number
|
||||
>this : this
|
||||
>p : number
|
||||
>1 : 1
|
||||
}
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/salsa/use.js ===
|
||||
import * as s from './mod'
|
||||
>s : typeof s
|
||||
|
||||
var k = new s.n.K()
|
||||
>k : { x: number; }
|
||||
>new s.n.K() : { x: number; }
|
||||
>s.n.K : () => void
|
||||
>s.n : typeof __object
|
||||
>s : typeof s
|
||||
>n : typeof __object
|
||||
>K : () => void
|
||||
|
||||
k.x
|
||||
>k.x : number
|
||||
>k : { x: number; }
|
||||
>x : number
|
||||
|
||||
var classic = new s.Classic()
|
||||
>classic : (Anonymous class)
|
||||
>new s.Classic() : (Anonymous class)
|
||||
>s.Classic : typeof (Anonymous class)
|
||||
>s : typeof s
|
||||
>Classic : typeof (Anonymous class)
|
||||
|
||||
|
||||
/** @param {s.n.K} c
|
||||
@param {s.Classic} classic */
|
||||
function f(c, classic) {
|
||||
>f : (c: { x: number; }, classic: (Anonymous class)) => void
|
||||
>c : { x: number; }
|
||||
>classic : (Anonymous class)
|
||||
|
||||
c.x
|
||||
>c.x : number
|
||||
>c : { x: number; }
|
||||
>x : number
|
||||
|
||||
classic.p
|
||||
>classic.p : number
|
||||
>classic : (Anonymous class)
|
||||
>p : number
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
tests/cases/conformance/salsa/first.js(1,1): error TS2539: Cannot assign to '"tests/cases/conformance/salsa/first"' because it is not a variable.
|
||||
tests/cases/conformance/salsa/first.js(1,11): error TS2304: Cannot find name 'require'.
|
||||
tests/cases/conformance/salsa/first.js(2,9): error TS2339: Property 'formatters' does not exist on type 'typeof "tests/cases/conformance/salsa/first"'.
|
||||
tests/cases/conformance/salsa/second.js(1,1): error TS2539: Cannot assign to '"tests/cases/conformance/salsa/second"' because it is not a variable.
|
||||
tests/cases/conformance/salsa/second.js(1,11): error TS2304: Cannot find name 'require'.
|
||||
tests/cases/conformance/salsa/second.js(2,9): error TS2339: Property 'formatters' does not exist on type 'typeof "tests/cases/conformance/salsa/second"'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/salsa/mod.js (0 errors) ====
|
||||
// Based on a pattern from adonis
|
||||
exports.formatters = {}
|
||||
==== tests/cases/conformance/salsa/first.js (3 errors) ====
|
||||
exports = require('./mod')
|
||||
~~~~~~~
|
||||
!!! error TS2539: Cannot assign to '"tests/cases/conformance/salsa/first"' because it is not a variable.
|
||||
~~~~~~~
|
||||
!!! error TS2304: Cannot find name 'require'.
|
||||
exports.formatters.j = function (v) {
|
||||
~~~~~~~~~~
|
||||
!!! error TS2339: Property 'formatters' does not exist on type 'typeof "tests/cases/conformance/salsa/first"'.
|
||||
return v
|
||||
}
|
||||
==== tests/cases/conformance/salsa/second.js (3 errors) ====
|
||||
exports = require('./mod')
|
||||
~~~~~~~
|
||||
!!! error TS2539: Cannot assign to '"tests/cases/conformance/salsa/second"' because it is not a variable.
|
||||
~~~~~~~
|
||||
!!! error TS2304: Cannot find name 'require'.
|
||||
exports.formatters.o = function (v) {
|
||||
~~~~~~~~~~
|
||||
!!! error TS2339: Property 'formatters' does not exist on type 'typeof "tests/cases/conformance/salsa/second"'.
|
||||
return v
|
||||
}
|
||||
|
||||
==== tests/cases/conformance/salsa/use.js (0 errors) ====
|
||||
import * as debug from './mod'
|
||||
|
||||
debug.formatters.j
|
||||
var one = debug.formatters.o(1)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
=== tests/cases/conformance/salsa/mod.js ===
|
||||
// Based on a pattern from adonis
|
||||
exports.formatters = {}
|
||||
>exports.formatters : Symbol(formatters, Decl(mod.js, 0, 0))
|
||||
>exports : Symbol(formatters, Decl(mod.js, 0, 0))
|
||||
>formatters : Symbol(formatters, Decl(mod.js, 0, 0))
|
||||
|
||||
=== tests/cases/conformance/salsa/first.js ===
|
||||
exports = require('./mod')
|
||||
>exports : Symbol("tests/cases/conformance/salsa/first", Decl(first.js, 0, 0))
|
||||
>'./mod' : Symbol("tests/cases/conformance/salsa/mod", Decl(mod.js, 0, 0))
|
||||
|
||||
exports.formatters.j = function (v) {
|
||||
>exports : Symbol("tests/cases/conformance/salsa/first", Decl(first.js, 0, 0))
|
||||
>v : Symbol(v, Decl(first.js, 1, 33))
|
||||
|
||||
return v
|
||||
>v : Symbol(v, Decl(first.js, 1, 33))
|
||||
}
|
||||
=== tests/cases/conformance/salsa/second.js ===
|
||||
exports = require('./mod')
|
||||
>exports : Symbol("tests/cases/conformance/salsa/second", Decl(second.js, 0, 0))
|
||||
>'./mod' : Symbol("tests/cases/conformance/salsa/mod", Decl(mod.js, 0, 0))
|
||||
|
||||
exports.formatters.o = function (v) {
|
||||
>exports : Symbol("tests/cases/conformance/salsa/second", Decl(second.js, 0, 0))
|
||||
>v : Symbol(v, Decl(second.js, 1, 33))
|
||||
|
||||
return v
|
||||
>v : Symbol(v, Decl(second.js, 1, 33))
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/salsa/use.js ===
|
||||
import * as debug from './mod'
|
||||
>debug : Symbol(debug, Decl(use.js, 0, 6))
|
||||
|
||||
debug.formatters.j
|
||||
>debug.formatters : Symbol(debug.formatters, Decl(mod.js, 0, 0))
|
||||
>debug : Symbol(debug, Decl(use.js, 0, 6))
|
||||
>formatters : Symbol(debug.formatters, Decl(mod.js, 0, 0))
|
||||
|
||||
var one = debug.formatters.o(1)
|
||||
>one : Symbol(one, Decl(use.js, 3, 3))
|
||||
>debug.formatters : Symbol(debug.formatters, Decl(mod.js, 0, 0))
|
||||
>debug : Symbol(debug, Decl(use.js, 0, 6))
|
||||
>formatters : Symbol(debug.formatters, Decl(mod.js, 0, 0))
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
=== tests/cases/conformance/salsa/mod.js ===
|
||||
// Based on a pattern from adonis
|
||||
exports.formatters = {}
|
||||
>exports.formatters = {} : { [x: string]: any; }
|
||||
>exports.formatters : { [x: string]: any; }
|
||||
>exports : typeof "tests/cases/conformance/salsa/mod"
|
||||
>formatters : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; }
|
||||
|
||||
=== tests/cases/conformance/salsa/first.js ===
|
||||
exports = require('./mod')
|
||||
>exports = require('./mod') : typeof "tests/cases/conformance/salsa/mod"
|
||||
>exports : any
|
||||
>require('./mod') : typeof "tests/cases/conformance/salsa/mod"
|
||||
>require : any
|
||||
>'./mod' : "./mod"
|
||||
|
||||
exports.formatters.j = function (v) {
|
||||
>exports.formatters.j = function (v) { return v} : (v: any) => any
|
||||
>exports.formatters.j : any
|
||||
>exports.formatters : any
|
||||
>exports : typeof "tests/cases/conformance/salsa/first"
|
||||
>formatters : any
|
||||
>j : any
|
||||
>function (v) { return v} : (v: any) => any
|
||||
>v : any
|
||||
|
||||
return v
|
||||
>v : any
|
||||
}
|
||||
=== tests/cases/conformance/salsa/second.js ===
|
||||
exports = require('./mod')
|
||||
>exports = require('./mod') : typeof "tests/cases/conformance/salsa/mod"
|
||||
>exports : any
|
||||
>require('./mod') : typeof "tests/cases/conformance/salsa/mod"
|
||||
>require : any
|
||||
>'./mod' : "./mod"
|
||||
|
||||
exports.formatters.o = function (v) {
|
||||
>exports.formatters.o = function (v) { return v} : (v: any) => any
|
||||
>exports.formatters.o : any
|
||||
>exports.formatters : any
|
||||
>exports : typeof "tests/cases/conformance/salsa/second"
|
||||
>formatters : any
|
||||
>o : any
|
||||
>function (v) { return v} : (v: any) => any
|
||||
>v : any
|
||||
|
||||
return v
|
||||
>v : any
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/salsa/use.js ===
|
||||
import * as debug from './mod'
|
||||
>debug : typeof debug
|
||||
|
||||
debug.formatters.j
|
||||
>debug.formatters.j : any
|
||||
>debug.formatters : { [x: string]: any; }
|
||||
>debug : typeof debug
|
||||
>formatters : { [x: string]: any; }
|
||||
>j : any
|
||||
|
||||
var one = debug.formatters.o(1)
|
||||
>one : any
|
||||
>debug.formatters.o(1) : any
|
||||
>debug.formatters.o : any
|
||||
>debug.formatters : { [x: string]: any; }
|
||||
>debug : typeof debug
|
||||
>formatters : { [x: string]: any; }
|
||||
>o : any
|
||||
>1 : 1
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/a.ts(2,8): error TS6133: 'Bar' is declared but its value is never read.
|
||||
/a.ts(2,1): error TS6133: 'Bar' is declared but its value is never read.
|
||||
|
||||
|
||||
==== /a.ts (1 errors) ====
|
||||
import Foo from "foo";
|
||||
import Bar from "bar"; // error: unused
|
||||
~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS6133: 'Bar' is declared but its value is never read.
|
||||
export class A extends Foo { }
|
||||
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck48.ts(1,9): error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck48.ts(1,11): error TS7010: 'g', which lacks return-type annotation, implicitly has an 'any' return type.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck48.ts(5,11): error TS7010: 'h', which lacks return-type annotation, implicitly has an 'any' return type.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck48.ts (1 errors) ====
|
||||
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck48.ts (2 errors) ====
|
||||
function* g() {
|
||||
~
|
||||
!!! error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.
|
||||
~
|
||||
!!! error TS7010: 'g', which lacks return-type annotation, implicitly has an 'any' return type.
|
||||
yield;
|
||||
}
|
||||
}
|
||||
|
||||
function* h() {
|
||||
~
|
||||
!!! error TS7010: 'h', which lacks return-type annotation, implicitly has an 'any' return type.
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
//// [generatorTypeCheck48.ts]
|
||||
function* g() {
|
||||
yield;
|
||||
}
|
||||
}
|
||||
|
||||
function* h() {
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
|
||||
//// [generatorTypeCheck48.js]
|
||||
function* g() {
|
||||
yield;
|
||||
}
|
||||
function* h() {
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
@@ -4,3 +4,11 @@ function* g() {
|
||||
|
||||
yield;
|
||||
}
|
||||
|
||||
function* h() {
|
||||
>h : Symbol(h, Decl(generatorTypeCheck48.ts, 2, 1))
|
||||
|
||||
yield undefined;
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,3 +5,12 @@ function* g() {
|
||||
yield;
|
||||
>yield : any
|
||||
}
|
||||
|
||||
function* h() {
|
||||
>h : () => IterableIterator<any>
|
||||
|
||||
yield undefined;
|
||||
>yield undefined : any
|
||||
>undefined : undefined
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
error TS5055: Cannot write file 'tests/cases/conformance/salsa/a.js' because it would overwrite input file.
|
||||
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
|
||||
tests/cases/conformance/salsa/a.js(1,10): error TS2300: Duplicate identifier 'x'.
|
||||
tests/cases/conformance/salsa/b.ts(1,5): error TS2300: Duplicate identifier 'x'.
|
||||
|
||||
|
||||
!!! error TS5055: Cannot write file 'tests/cases/conformance/salsa/a.js' because it would overwrite input file.
|
||||
!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
|
||||
==== tests/cases/conformance/salsa/a.js (1 errors) ====
|
||||
var /*1*/x = function foo() {
|
||||
~
|
||||
!!! error TS2300: Duplicate identifier 'x'.
|
||||
}
|
||||
x.a = function bar() {
|
||||
}
|
||||
==== tests/cases/conformance/salsa/b.ts (1 errors) ====
|
||||
var x = function () {
|
||||
~
|
||||
!!! error TS2300: Duplicate identifier 'x'.
|
||||
return 1;
|
||||
}();
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//// [tests/cases/conformance/salsa/jsContainerMergeTsDeclaration.ts] ////
|
||||
|
||||
//// [a.js]
|
||||
var /*1*/x = function foo() {
|
||||
}
|
||||
x.a = function bar() {
|
||||
}
|
||||
//// [b.ts]
|
||||
var x = function () {
|
||||
return 1;
|
||||
}();
|
||||
|
||||
|
||||
//// [b.js]
|
||||
var x = function () {
|
||||
return 1;
|
||||
}();
|
||||
@@ -0,0 +1,18 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var /*1*/x = function foo() {
|
||||
>x : Symbol(x, Decl(a.js, 0, 3), Decl(a.js, 1, 1), Decl(b.ts, 0, 3))
|
||||
>foo : Symbol(foo, Decl(a.js, 0, 12))
|
||||
}
|
||||
x.a = function bar() {
|
||||
>x.a : Symbol(foo.a, Decl(a.js, 1, 1))
|
||||
>x : Symbol(x, Decl(a.js, 0, 3), Decl(a.js, 1, 1), Decl(b.ts, 0, 3))
|
||||
>a : Symbol(foo.a, Decl(a.js, 1, 1))
|
||||
>bar : Symbol(bar, Decl(a.js, 2, 5))
|
||||
}
|
||||
=== tests/cases/conformance/salsa/b.ts ===
|
||||
var x = function () {
|
||||
>x : Symbol(x, Decl(a.js, 0, 3), Decl(a.js, 1, 1), Decl(b.ts, 0, 3))
|
||||
|
||||
return 1;
|
||||
}();
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var /*1*/x = function foo() {
|
||||
>x : { (): void; a: () => void; }
|
||||
>function foo() {} : { (): void; a: () => void; }
|
||||
>foo : { (): void; a: () => void; }
|
||||
}
|
||||
x.a = function bar() {
|
||||
>x.a = function bar() {} : () => void
|
||||
>x.a : () => void
|
||||
>x : { (): void; a: () => void; }
|
||||
>a : () => void
|
||||
>function bar() {} : () => void
|
||||
>bar : () => void
|
||||
}
|
||||
=== tests/cases/conformance/salsa/b.ts ===
|
||||
var x = function () {
|
||||
>x : { (): void; a: () => void; }
|
||||
>function () { return 1;}() : number
|
||||
>function () { return 1;} : () => number
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
|
||||
}();
|
||||
|
||||
@@ -3,7 +3,9 @@ var variable = {};
|
||||
>variable : Symbol(variable, Decl(a.js, 0, 3))
|
||||
|
||||
variable.a = 0;
|
||||
>variable.a : Symbol(a, Decl(a.js, 0, 18))
|
||||
>variable : Symbol(variable, Decl(a.js, 0, 3))
|
||||
>a : Symbol(a, Decl(a.js, 0, 18))
|
||||
|
||||
class C {
|
||||
>C : Symbol(C, Decl(a.js, 1, 15))
|
||||
@@ -49,7 +51,9 @@ function getObj() {
|
||||
|
||||
=== tests/cases/conformance/salsa/b.ts ===
|
||||
variable.a = 1;
|
||||
>variable.a : Symbol(a, Decl(a.js, 0, 18))
|
||||
>variable : Symbol(variable, Decl(a.js, 0, 3))
|
||||
>a : Symbol(a, Decl(a.js, 0, 18))
|
||||
|
||||
(new C()).member.a = 1;
|
||||
>(new C()).member : Symbol(C.member, Decl(a.js, 5, 19))
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var variable = {};
|
||||
>variable : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; }
|
||||
>variable : { [x: string]: any; a: number; }
|
||||
>{} : { [x: string]: any; a: number; }
|
||||
|
||||
variable.a = 0;
|
||||
>variable.a = 0 : 0
|
||||
>variable.a : any
|
||||
>variable : { [x: string]: any; }
|
||||
>a : any
|
||||
>variable.a : number
|
||||
>variable : { [x: string]: any; a: number; }
|
||||
>a : number
|
||||
>0 : 0
|
||||
|
||||
class C {
|
||||
@@ -71,9 +71,9 @@ function getObj() {
|
||||
=== tests/cases/conformance/salsa/b.ts ===
|
||||
variable.a = 1;
|
||||
>variable.a = 1 : 1
|
||||
>variable.a : any
|
||||
>variable : { [x: string]: any; }
|
||||
>a : any
|
||||
>variable.a : number
|
||||
>variable : { [x: string]: any; a: number; }
|
||||
>a : number
|
||||
>1 : 1
|
||||
|
||||
(new C()).member.a = 1;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/a.ts(1,20): error TS2307: Cannot find module 'something'.
|
||||
/b.ts(3,6): error TS2345: Argument of type '""' is not assignable to parameter of type '"x"'.
|
||||
|
||||
|
||||
==== /b.ts (1 errors) ====
|
||||
import a = require('./a');
|
||||
declare function f<T>(obj: T, key: keyof T): void;
|
||||
f(a, "");
|
||||
~~
|
||||
!!! error TS2345: Argument of type '""' is not assignable to parameter of type '"x"'.
|
||||
|
||||
==== /a.ts (1 errors) ====
|
||||
import x = require("something");
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2307: Cannot find module 'something'.
|
||||
export { x };
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
//// [tests/cases/compiler/literalTypeNameAssertionNotTriggered.ts] ////
|
||||
|
||||
//// [a.ts]
|
||||
import x = require("something");
|
||||
export { x };
|
||||
|
||||
//// [b.ts]
|
||||
import a = require('./a');
|
||||
declare function f<T>(obj: T, key: keyof T): void;
|
||||
f(a, "");
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var x = require("something");
|
||||
exports.x = x;
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var a = require("./a");
|
||||
f(a, "");
|
||||
@@ -0,0 +1,23 @@
|
||||
=== /b.ts ===
|
||||
import a = require('./a');
|
||||
>a : Symbol(a, Decl(b.ts, 0, 0))
|
||||
|
||||
declare function f<T>(obj: T, key: keyof T): void;
|
||||
>f : Symbol(f, Decl(b.ts, 0, 26))
|
||||
>T : Symbol(T, Decl(b.ts, 1, 19))
|
||||
>obj : Symbol(obj, Decl(b.ts, 1, 22))
|
||||
>T : Symbol(T, Decl(b.ts, 1, 19))
|
||||
>key : Symbol(key, Decl(b.ts, 1, 29))
|
||||
>T : Symbol(T, Decl(b.ts, 1, 19))
|
||||
|
||||
f(a, "");
|
||||
>f : Symbol(f, Decl(b.ts, 0, 26))
|
||||
>a : Symbol(a, Decl(b.ts, 0, 0))
|
||||
|
||||
=== /a.ts ===
|
||||
import x = require("something");
|
||||
>x : Symbol(x, Decl(a.ts, 0, 0))
|
||||
|
||||
export { x };
|
||||
>x : Symbol(x, Decl(a.ts, 1, 8))
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
=== /b.ts ===
|
||||
import a = require('./a');
|
||||
>a : typeof a
|
||||
|
||||
declare function f<T>(obj: T, key: keyof T): void;
|
||||
>f : <T>(obj: T, key: keyof T) => void
|
||||
>T : T
|
||||
>obj : T
|
||||
>T : T
|
||||
>key : keyof T
|
||||
>T : T
|
||||
|
||||
f(a, "");
|
||||
>f(a, "") : any
|
||||
>f : <T>(obj: T, key: keyof T) => void
|
||||
>a : typeof a
|
||||
>"" : ""
|
||||
|
||||
=== /a.ts ===
|
||||
import x = require("something");
|
||||
>x : any
|
||||
|
||||
export { x };
|
||||
>x : any
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@ for (const element of document.getElementsByTagName("a")) {
|
||||
>getElementsByTagName : Symbol(Document.getElementsByTagName, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
element.href;
|
||||
>element.href : Symbol(HTMLAnchorElement.href, Decl(lib.dom.d.ts, --, --))
|
||||
>element.href : Symbol(HTMLHyperlinkElementUtils.href, Decl(lib.dom.d.ts, --, --))
|
||||
>element : Symbol(element, Decl(modularizeLibrary_Dom.iterable.ts, 0, 10))
|
||||
>href : Symbol(HTMLAnchorElement.href, Decl(lib.dom.d.ts, --, --))
|
||||
>href : Symbol(HTMLHyperlinkElementUtils.href, Decl(lib.dom.d.ts, --, --))
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
for (const element of document.getElementsByTagName("a")) {
|
||||
>element : HTMLAnchorElement
|
||||
>document.getElementsByTagName("a") : NodeListOf<HTMLAnchorElement>
|
||||
>document.getElementsByTagName : { <K extends "object" | "a" | "abbr" | "acronym" | "address" | "applet" | "area" | "article" | "aside" | "audio" | "b" | "base" | "basefont" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "cite" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "del" | "dfn" | "dir" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "font" | "footer" | "form" | "frame" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "isindex" | "kbd" | "keygen" | "label" | "legend" | "li" | "link" | "listing" | "map" | "mark" | "marquee" | "menu" | "meta" | "meter" | "nav" | "nextid" | "nobr" | "noframes" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "plaintext" | "pre" | "progress" | "q" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "slot" | "small" | "source" | "span" | "strike" | "strong" | "style" | "sub" | "sup" | "table" | "tbody" | "td" | "template" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "tt" | "u" | "ul" | "var" | "video" | "wbr" | "x-ms-webview" | "xmp">(tagname: K): NodeListOf<HTMLElementTagNameMap[K]>; <K extends "symbol" | "circle" | "clippath" | "defs" | "desc" | "ellipse" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "filter" | "foreignobject" | "g" | "image" | "line" | "lineargradient" | "marker" | "mask" | "metadata" | "path" | "pattern" | "polygon" | "polyline" | "radialgradient" | "rect" | "stop" | "svg" | "switch" | "text" | "textpath" | "tspan" | "use" | "view">(tagname: K): NodeListOf<SVGElementTagNameMap[K]>; (tagname: string): NodeListOf<Element>; }
|
||||
>document.getElementsByTagName : { <K extends "object" | "a" | "abbr" | "acronym" | "address" | "applet" | "area" | "article" | "aside" | "audio" | "b" | "base" | "basefont" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "cite" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "del" | "dfn" | "dir" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "font" | "footer" | "form" | "frame" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "isindex" | "kbd" | "keygen" | "label" | "legend" | "li" | "link" | "listing" | "map" | "mark" | "marquee" | "menu" | "meta" | "meter" | "nav" | "nextid" | "nobr" | "noframes" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "plaintext" | "pre" | "progress" | "q" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "slot" | "small" | "source" | "span" | "strike" | "strong" | "style" | "sub" | "sup" | "table" | "tbody" | "td" | "template" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "tt" | "u" | "ul" | "var" | "video" | "wbr" | "xmp">(tagname: K): NodeListOf<HTMLElementTagNameMap[K]>; <K extends "symbol" | "circle" | "clippath" | "defs" | "desc" | "ellipse" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "filter" | "foreignobject" | "g" | "image" | "line" | "lineargradient" | "marker" | "mask" | "metadata" | "path" | "pattern" | "polygon" | "polyline" | "radialgradient" | "rect" | "stop" | "svg" | "switch" | "text" | "textpath" | "tspan" | "use" | "view">(tagname: K): NodeListOf<SVGElementTagNameMap[K]>; (tagname: string): NodeListOf<Element>; }
|
||||
>document : Document
|
||||
>getElementsByTagName : { <K extends "object" | "a" | "abbr" | "acronym" | "address" | "applet" | "area" | "article" | "aside" | "audio" | "b" | "base" | "basefont" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "cite" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "del" | "dfn" | "dir" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "font" | "footer" | "form" | "frame" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "isindex" | "kbd" | "keygen" | "label" | "legend" | "li" | "link" | "listing" | "map" | "mark" | "marquee" | "menu" | "meta" | "meter" | "nav" | "nextid" | "nobr" | "noframes" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "plaintext" | "pre" | "progress" | "q" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "slot" | "small" | "source" | "span" | "strike" | "strong" | "style" | "sub" | "sup" | "table" | "tbody" | "td" | "template" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "tt" | "u" | "ul" | "var" | "video" | "wbr" | "x-ms-webview" | "xmp">(tagname: K): NodeListOf<HTMLElementTagNameMap[K]>; <K extends "symbol" | "circle" | "clippath" | "defs" | "desc" | "ellipse" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "filter" | "foreignobject" | "g" | "image" | "line" | "lineargradient" | "marker" | "mask" | "metadata" | "path" | "pattern" | "polygon" | "polyline" | "radialgradient" | "rect" | "stop" | "svg" | "switch" | "text" | "textpath" | "tspan" | "use" | "view">(tagname: K): NodeListOf<SVGElementTagNameMap[K]>; (tagname: string): NodeListOf<Element>; }
|
||||
>getElementsByTagName : { <K extends "object" | "a" | "abbr" | "acronym" | "address" | "applet" | "area" | "article" | "aside" | "audio" | "b" | "base" | "basefont" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "cite" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "del" | "dfn" | "dir" | "div" | "dl" | "dt" | "em" | "embed" | "fieldset" | "figcaption" | "figure" | "font" | "footer" | "form" | "frame" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "img" | "input" | "ins" | "isindex" | "kbd" | "keygen" | "label" | "legend" | "li" | "link" | "listing" | "map" | "mark" | "marquee" | "menu" | "meta" | "meter" | "nav" | "nextid" | "nobr" | "noframes" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "picture" | "plaintext" | "pre" | "progress" | "q" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "slot" | "small" | "source" | "span" | "strike" | "strong" | "style" | "sub" | "sup" | "table" | "tbody" | "td" | "template" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "tt" | "u" | "ul" | "var" | "video" | "wbr" | "xmp">(tagname: K): NodeListOf<HTMLElementTagNameMap[K]>; <K extends "symbol" | "circle" | "clippath" | "defs" | "desc" | "ellipse" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "filter" | "foreignobject" | "g" | "image" | "line" | "lineargradient" | "marker" | "mask" | "metadata" | "path" | "pattern" | "polygon" | "polyline" | "radialgradient" | "rect" | "stop" | "svg" | "switch" | "text" | "textpath" | "tspan" | "use" | "view">(tagname: K): NodeListOf<SVGElementTagNameMap[K]>; (tagname: string): NodeListOf<Element>; }
|
||||
>"a" : "a"
|
||||
|
||||
element.href;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
tests/cases/conformance/salsa/mod.js(1,1): error TS2304: Cannot find name 'module'.
|
||||
tests/cases/conformance/salsa/mod.js(2,1): error TS2304: Cannot find name 'module'.
|
||||
tests/cases/conformance/salsa/mod.js(5,1): error TS2304: Cannot find name 'module'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/salsa/mod.js (3 errors) ====
|
||||
module.exports.n = {};
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'module'.
|
||||
module.exports.n.K = function C() {
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'module'.
|
||||
this.x = 10;
|
||||
}
|
||||
module.exports.Classic = class {
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'module'.
|
||||
constructor() {
|
||||
this.p = 1
|
||||
}
|
||||
}
|
||||
|
||||
==== tests/cases/conformance/salsa/use.js (0 errors) ====
|
||||
import * as s from './mod'
|
||||
|
||||
var k = new s.n.K()
|
||||
k.x
|
||||
var classic = new s.Classic()
|
||||
|
||||
|
||||
/** @param {s.n.K} c
|
||||
@param {s.Classic} classic */
|
||||
function f(c, classic) {
|
||||
c.x
|
||||
classic.p
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
=== tests/cases/conformance/salsa/mod.js ===
|
||||
module.exports.n = {};
|
||||
>module.exports : Symbol(n, Decl(mod.js, 0, 0))
|
||||
>n : Symbol(n, Decl(mod.js, 0, 0))
|
||||
|
||||
module.exports.n.K = function C() {
|
||||
>module.exports.n : Symbol(K, Decl(mod.js, 0, 22))
|
||||
>K : Symbol(K, Decl(mod.js, 0, 22))
|
||||
>C : Symbol(C, Decl(mod.js, 1, 20))
|
||||
|
||||
this.x = 10;
|
||||
>x : Symbol(C.x, Decl(mod.js, 1, 35))
|
||||
}
|
||||
module.exports.Classic = class {
|
||||
>module.exports : Symbol(Classic, Decl(mod.js, 3, 1))
|
||||
>Classic : Symbol(Classic, Decl(mod.js, 3, 1))
|
||||
|
||||
constructor() {
|
||||
this.p = 1
|
||||
>this.p : Symbol((Anonymous class).p, Decl(mod.js, 5, 19))
|
||||
>this : Symbol((Anonymous class), Decl(mod.js, 4, 24))
|
||||
>p : Symbol((Anonymous class).p, Decl(mod.js, 5, 19))
|
||||
}
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/salsa/use.js ===
|
||||
import * as s from './mod'
|
||||
>s : Symbol(s, Decl(use.js, 0, 6))
|
||||
|
||||
var k = new s.n.K()
|
||||
>k : Symbol(k, Decl(use.js, 2, 3))
|
||||
>s.n.K : Symbol(K, Decl(mod.js, 0, 22))
|
||||
>s.n : Symbol(s.n, Decl(mod.js, 0, 0))
|
||||
>s : Symbol(s, Decl(use.js, 0, 6))
|
||||
>n : Symbol(s.n, Decl(mod.js, 0, 0))
|
||||
>K : Symbol(K, Decl(mod.js, 0, 22))
|
||||
|
||||
k.x
|
||||
>k.x : Symbol(C.x, Decl(mod.js, 1, 35))
|
||||
>k : Symbol(k, Decl(use.js, 2, 3))
|
||||
>x : Symbol(C.x, Decl(mod.js, 1, 35))
|
||||
|
||||
var classic = new s.Classic()
|
||||
>classic : Symbol(classic, Decl(use.js, 4, 3))
|
||||
>s.Classic : Symbol(s.Classic, Decl(mod.js, 3, 1))
|
||||
>s : Symbol(s, Decl(use.js, 0, 6))
|
||||
>Classic : Symbol(s.Classic, Decl(mod.js, 3, 1))
|
||||
|
||||
|
||||
/** @param {s.n.K} c
|
||||
@param {s.Classic} classic */
|
||||
function f(c, classic) {
|
||||
>f : Symbol(f, Decl(use.js, 4, 29))
|
||||
>c : Symbol(c, Decl(use.js, 9, 11))
|
||||
>classic : Symbol(classic, Decl(use.js, 9, 13))
|
||||
|
||||
c.x
|
||||
>c.x : Symbol(C.x, Decl(mod.js, 1, 35))
|
||||
>c : Symbol(c, Decl(use.js, 9, 11))
|
||||
>x : Symbol(C.x, Decl(mod.js, 1, 35))
|
||||
|
||||
classic.p
|
||||
>classic.p : Symbol((Anonymous class).p, Decl(mod.js, 5, 19))
|
||||
>classic : Symbol(classic, Decl(use.js, 9, 13))
|
||||
>p : Symbol((Anonymous class).p, Decl(mod.js, 5, 19))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
=== tests/cases/conformance/salsa/mod.js ===
|
||||
module.exports.n = {};
|
||||
>module.exports.n = {} : typeof __object
|
||||
>module.exports.n : any
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>n : any
|
||||
>{} : typeof __object
|
||||
|
||||
module.exports.n.K = function C() {
|
||||
>module.exports.n.K = function C() { this.x = 10;} : () => void
|
||||
>module.exports.n.K : any
|
||||
>module.exports.n : any
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>n : any
|
||||
>K : any
|
||||
>function C() { this.x = 10;} : () => void
|
||||
>C : () => void
|
||||
|
||||
this.x = 10;
|
||||
>this.x = 10 : 10
|
||||
>this.x : any
|
||||
>this : any
|
||||
>x : any
|
||||
>10 : 10
|
||||
}
|
||||
module.exports.Classic = class {
|
||||
>module.exports.Classic = class { constructor() { this.p = 1 }} : typeof (Anonymous class)
|
||||
>module.exports.Classic : any
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>Classic : any
|
||||
>class { constructor() { this.p = 1 }} : typeof (Anonymous class)
|
||||
|
||||
constructor() {
|
||||
this.p = 1
|
||||
>this.p = 1 : 1
|
||||
>this.p : number
|
||||
>this : this
|
||||
>p : number
|
||||
>1 : 1
|
||||
}
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/salsa/use.js ===
|
||||
import * as s from './mod'
|
||||
>s : typeof s
|
||||
|
||||
var k = new s.n.K()
|
||||
>k : { x: number; }
|
||||
>new s.n.K() : { x: number; }
|
||||
>s.n.K : () => void
|
||||
>s.n : typeof __object
|
||||
>s : typeof s
|
||||
>n : typeof __object
|
||||
>K : () => void
|
||||
|
||||
k.x
|
||||
>k.x : number
|
||||
>k : { x: number; }
|
||||
>x : number
|
||||
|
||||
var classic = new s.Classic()
|
||||
>classic : (Anonymous class)
|
||||
>new s.Classic() : (Anonymous class)
|
||||
>s.Classic : typeof (Anonymous class)
|
||||
>s : typeof s
|
||||
>Classic : typeof (Anonymous class)
|
||||
|
||||
|
||||
/** @param {s.n.K} c
|
||||
@param {s.Classic} classic */
|
||||
function f(c, classic) {
|
||||
>f : (c: { x: number; }, classic: (Anonymous class)) => void
|
||||
>c : { x: number; }
|
||||
>classic : (Anonymous class)
|
||||
|
||||
c.x
|
||||
>c.x : number
|
||||
>c : { x: number; }
|
||||
>x : number
|
||||
|
||||
classic.p
|
||||
>classic.p : number
|
||||
>classic : (Anonymous class)
|
||||
>p : number
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(3,10): error TS6133: 'f' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(5,14): error TS6133: 'g' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(9,7): error TS6133: 'C' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(12,6): error TS6133: 'E' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(13,11): error TS6133: 'I' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(14,6): error TS6133: 'T' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(15,11): error TS6133: 'N' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(3,1): error TS6133: 'f' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(5,5): error TS6133: 'g' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(9,1): error TS6133: 'C' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(12,1): error TS6133: 'E' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(13,1): error TS6133: 'I' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(14,1): error TS6133: 'T' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(15,1): error TS6133: 'N' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference.ts(22,19): error TS6133: 'm' is declared but its value is never read.
|
||||
|
||||
|
||||
@@ -12,31 +12,31 @@ tests/cases/compiler/noUnusedLocals_selfReference.ts(22,19): error TS6133: 'm' i
|
||||
export {}; // Make this a module scope, so these are local variables.
|
||||
|
||||
function f() {
|
||||
~
|
||||
~~~~~~~~~~
|
||||
!!! error TS6133: 'f' is declared but its value is never read.
|
||||
f;
|
||||
function g() {
|
||||
~
|
||||
~~~~~~~~~~
|
||||
!!! error TS6133: 'g' is declared but its value is never read.
|
||||
g;
|
||||
}
|
||||
}
|
||||
class C {
|
||||
~
|
||||
~~~~~~~
|
||||
!!! error TS6133: 'C' is declared but its value is never read.
|
||||
m() { C; }
|
||||
}
|
||||
enum E { A = 0, B = E.A }
|
||||
~
|
||||
~~~~~~
|
||||
!!! error TS6133: 'E' is declared but its value is never read.
|
||||
interface I { x: I };
|
||||
~
|
||||
~~~~~~~~~~~
|
||||
!!! error TS6133: 'I' is declared but its value is never read.
|
||||
type T = { x: T };
|
||||
~
|
||||
~~~~~~
|
||||
!!! error TS6133: 'T' is declared but its value is never read.
|
||||
namespace N { N; }
|
||||
~
|
||||
~~~~~~~~~~~
|
||||
!!! error TS6133: 'N' is declared but its value is never read.
|
||||
|
||||
// Avoid a false positive.
|
||||
|
||||
+6
-6
@@ -1,12 +1,12 @@
|
||||
tests/cases/compiler/noUnusedLocals_selfReference_skipsBlockLocations.ts(2,14): error TS6133: 'f' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference_skipsBlockLocations.ts(8,22): error TS6133: 'g' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference_skipsBlockLocations.ts(12,22): error TS6133: 'h' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference_skipsBlockLocations.ts(2,5): error TS6133: 'f' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference_skipsBlockLocations.ts(8,13): error TS6133: 'g' is declared but its value is never read.
|
||||
tests/cases/compiler/noUnusedLocals_selfReference_skipsBlockLocations.ts(12,13): error TS6133: 'h' is declared but its value is never read.
|
||||
|
||||
|
||||
==== tests/cases/compiler/noUnusedLocals_selfReference_skipsBlockLocations.ts (3 errors) ====
|
||||
namespace n {
|
||||
function f() {
|
||||
~
|
||||
~~~~~~~~~~
|
||||
!!! error TS6133: 'f' is declared but its value is never read.
|
||||
f;
|
||||
}
|
||||
@@ -14,13 +14,13 @@ tests/cases/compiler/noUnusedLocals_selfReference_skipsBlockLocations.ts(12,22):
|
||||
switch (0) {
|
||||
case 0:
|
||||
function g() {
|
||||
~
|
||||
~~~~~~~~~~
|
||||
!!! error TS6133: 'g' is declared but its value is never read.
|
||||
g;
|
||||
}
|
||||
default:
|
||||
function h() {
|
||||
~
|
||||
~~~~~~~~~~
|
||||
!!! error TS6133: 'h' is declared but its value is never read.
|
||||
h;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
//// [nonstrictTemplateWithNotOctalPrintsAsIs.ts]
|
||||
// https://github.com/Microsoft/TypeScript/issues/21828
|
||||
const d2 = `\\0041`;
|
||||
|
||||
|
||||
//// [nonstrictTemplateWithNotOctalPrintsAsIs.js]
|
||||
// https://github.com/Microsoft/TypeScript/issues/21828
|
||||
var d2 = "\\0041";
|
||||
@@ -0,0 +1,5 @@
|
||||
=== tests/cases/compiler/nonstrictTemplateWithNotOctalPrintsAsIs.ts ===
|
||||
// https://github.com/Microsoft/TypeScript/issues/21828
|
||||
const d2 = `\\0041`;
|
||||
>d2 : Symbol(d2, Decl(nonstrictTemplateWithNotOctalPrintsAsIs.ts, 1, 5))
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
=== tests/cases/compiler/nonstrictTemplateWithNotOctalPrintsAsIs.ts ===
|
||||
// https://github.com/Microsoft/TypeScript/issues/21828
|
||||
const d2 = `\\0041`;
|
||||
>d2 : "\\0041"
|
||||
>`\\0041` : "\\0041"
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
=== tests/cases/conformance/salsa/module.js ===
|
||||
var Outer = Outer || {};
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
|
||||
Outer.app = Outer.app || {};
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
|
||||
=== tests/cases/conformance/salsa/someview.js ===
|
||||
Outer.app.SomeView = (function () {
|
||||
>Outer.app.SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0))
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0))
|
||||
|
||||
var SomeView = function() {
|
||||
>SomeView : Symbol(SomeView, Decl(someview.js, 1, 7))
|
||||
|
||||
var me = this;
|
||||
>me : Symbol(me, Decl(someview.js, 2, 11))
|
||||
}
|
||||
return SomeView;
|
||||
>SomeView : Symbol(SomeView, Decl(someview.js, 1, 7))
|
||||
|
||||
})();
|
||||
Outer.app.Inner = class {
|
||||
>Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5))
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5))
|
||||
|
||||
constructor() {
|
||||
/** @type {number} */
|
||||
this.y = 12;
|
||||
>this.y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19))
|
||||
>this : Symbol((Anonymous class), Decl(someview.js, 6, 17))
|
||||
>y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19))
|
||||
}
|
||||
}
|
||||
var example = new Outer.app.Inner();
|
||||
>example : Symbol(example, Decl(someview.js, 12, 3))
|
||||
>Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5))
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5))
|
||||
|
||||
example.y;
|
||||
>example.y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19))
|
||||
>example : Symbol(example, Decl(someview.js, 12, 3))
|
||||
>y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19))
|
||||
|
||||
/** @param {number} k */
|
||||
Outer.app.statische = function (k) {
|
||||
>Outer.app.statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10))
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10))
|
||||
>k : Symbol(k, Decl(someview.js, 15, 32))
|
||||
|
||||
return k ** k;
|
||||
>k : Symbol(k, Decl(someview.js, 15, 32))
|
||||
>k : Symbol(k, Decl(someview.js, 15, 32))
|
||||
}
|
||||
=== tests/cases/conformance/salsa/application.js ===
|
||||
Outer.app.Application = (function () {
|
||||
>Outer.app.Application : Symbol(app.Application, Decl(application.js, 0, 0))
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Application : Symbol(app.Application, Decl(application.js, 0, 0))
|
||||
|
||||
/**
|
||||
* Application main class.
|
||||
* Will be instantiated & initialized by HTML page
|
||||
*/
|
||||
var Application = function () {
|
||||
>Application : Symbol(Application, Decl(application.js, 6, 7))
|
||||
|
||||
var me = this;
|
||||
>me : Symbol(me, Decl(application.js, 7, 11))
|
||||
|
||||
me.view = new Outer.app.SomeView();
|
||||
>me : Symbol(me, Decl(application.js, 7, 11))
|
||||
>Outer.app.SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0))
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0))
|
||||
|
||||
};
|
||||
return Application;
|
||||
>Application : Symbol(Application, Decl(application.js, 6, 7))
|
||||
|
||||
})();
|
||||
=== tests/cases/conformance/salsa/main.js ===
|
||||
var app = new Outer.app.Application();
|
||||
>app : Symbol(app, Decl(main.js, 0, 3))
|
||||
>Outer.app.Application : Symbol(app.Application, Decl(application.js, 0, 0))
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Application : Symbol(app.Application, Decl(application.js, 0, 0))
|
||||
|
||||
var inner = new Outer.app.Inner();
|
||||
>inner : Symbol(inner, Decl(main.js, 1, 3))
|
||||
>Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5))
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5))
|
||||
|
||||
inner.y;
|
||||
>inner.y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19))
|
||||
>inner : Symbol(inner, Decl(main.js, 1, 3))
|
||||
>y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19))
|
||||
|
||||
/** @type {Outer.app.Inner} */
|
||||
var x;
|
||||
>x : Symbol(x, Decl(main.js, 4, 3))
|
||||
|
||||
x.y;
|
||||
>x.y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19))
|
||||
>x : Symbol(x, Decl(main.js, 4, 3))
|
||||
>y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19))
|
||||
|
||||
Outer.app.statische(101); // Infinity, duh
|
||||
>Outer.app.statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10))
|
||||
>Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0))
|
||||
>app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6))
|
||||
>statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10))
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
=== tests/cases/conformance/salsa/module.js ===
|
||||
var Outer = Outer || {};
|
||||
>Outer : typeof __object
|
||||
>Outer || {} : typeof __object
|
||||
>Outer : typeof __object
|
||||
>{} : typeof __object
|
||||
|
||||
Outer.app = Outer.app || {};
|
||||
>Outer.app = Outer.app || {} : typeof __object
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>Outer.app || {} : typeof __object
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>{} : typeof __object
|
||||
|
||||
=== tests/cases/conformance/salsa/someview.js ===
|
||||
Outer.app.SomeView = (function () {
|
||||
>Outer.app.SomeView = (function () { var SomeView = function() { var me = this; } return SomeView;})() : () => void
|
||||
>Outer.app.SomeView : () => void
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>SomeView : () => void
|
||||
>(function () { var SomeView = function() { var me = this; } return SomeView;})() : () => void
|
||||
>(function () { var SomeView = function() { var me = this; } return SomeView;}) : () => () => void
|
||||
>function () { var SomeView = function() { var me = this; } return SomeView;} : () => () => void
|
||||
|
||||
var SomeView = function() {
|
||||
>SomeView : () => void
|
||||
>function() { var me = this; } : () => void
|
||||
|
||||
var me = this;
|
||||
>me : any
|
||||
>this : any
|
||||
}
|
||||
return SomeView;
|
||||
>SomeView : () => void
|
||||
|
||||
})();
|
||||
Outer.app.Inner = class {
|
||||
>Outer.app.Inner = class { constructor() { /** @type {number} */ this.y = 12; }} : typeof (Anonymous class)
|
||||
>Outer.app.Inner : typeof (Anonymous class)
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>Inner : typeof (Anonymous class)
|
||||
>class { constructor() { /** @type {number} */ this.y = 12; }} : typeof (Anonymous class)
|
||||
|
||||
constructor() {
|
||||
/** @type {number} */
|
||||
this.y = 12;
|
||||
>this.y = 12 : 12
|
||||
>this.y : number
|
||||
>this : this
|
||||
>y : number
|
||||
>12 : 12
|
||||
}
|
||||
}
|
||||
var example = new Outer.app.Inner();
|
||||
>example : (Anonymous class)
|
||||
>new Outer.app.Inner() : (Anonymous class)
|
||||
>Outer.app.Inner : typeof (Anonymous class)
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>Inner : typeof (Anonymous class)
|
||||
|
||||
example.y;
|
||||
>example.y : number
|
||||
>example : (Anonymous class)
|
||||
>y : number
|
||||
|
||||
/** @param {number} k */
|
||||
Outer.app.statische = function (k) {
|
||||
>Outer.app.statische = function (k) { return k ** k;} : (k: number) => number
|
||||
>Outer.app.statische : (k: number) => number
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>statische : (k: number) => number
|
||||
>function (k) { return k ** k;} : (k: number) => number
|
||||
>k : number
|
||||
|
||||
return k ** k;
|
||||
>k ** k : number
|
||||
>k : number
|
||||
>k : number
|
||||
}
|
||||
=== tests/cases/conformance/salsa/application.js ===
|
||||
Outer.app.Application = (function () {
|
||||
>Outer.app.Application = (function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;})() : () => void
|
||||
>Outer.app.Application : () => void
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>Application : () => void
|
||||
>(function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;})() : () => void
|
||||
>(function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;}) : () => () => void
|
||||
>function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;} : () => () => void
|
||||
|
||||
/**
|
||||
* Application main class.
|
||||
* Will be instantiated & initialized by HTML page
|
||||
*/
|
||||
var Application = function () {
|
||||
>Application : () => void
|
||||
>function () { var me = this; me.view = new Outer.app.SomeView(); } : () => void
|
||||
|
||||
var me = this;
|
||||
>me : any
|
||||
>this : any
|
||||
|
||||
me.view = new Outer.app.SomeView();
|
||||
>me.view = new Outer.app.SomeView() : any
|
||||
>me.view : any
|
||||
>me : any
|
||||
>view : any
|
||||
>new Outer.app.SomeView() : any
|
||||
>Outer.app.SomeView : () => void
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>SomeView : () => void
|
||||
|
||||
};
|
||||
return Application;
|
||||
>Application : () => void
|
||||
|
||||
})();
|
||||
=== tests/cases/conformance/salsa/main.js ===
|
||||
var app = new Outer.app.Application();
|
||||
>app : any
|
||||
>new Outer.app.Application() : any
|
||||
>Outer.app.Application : () => void
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>Application : () => void
|
||||
|
||||
var inner = new Outer.app.Inner();
|
||||
>inner : (Anonymous class)
|
||||
>new Outer.app.Inner() : (Anonymous class)
|
||||
>Outer.app.Inner : typeof (Anonymous class)
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>Inner : typeof (Anonymous class)
|
||||
|
||||
inner.y;
|
||||
>inner.y : number
|
||||
>inner : (Anonymous class)
|
||||
>y : number
|
||||
|
||||
/** @type {Outer.app.Inner} */
|
||||
var x;
|
||||
>x : (Anonymous class)
|
||||
|
||||
x.y;
|
||||
>x.y : number
|
||||
>x : (Anonymous class)
|
||||
>y : number
|
||||
|
||||
Outer.app.statische(101); // Infinity, duh
|
||||
>Outer.app.statische(101) : number
|
||||
>Outer.app.statische : (k: number) => number
|
||||
>Outer.app : typeof __object
|
||||
>Outer : typeof __object
|
||||
>app : typeof __object
|
||||
>statische : (k: number) => number
|
||||
>101 : 101
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
=== tests/cases/conformance/salsa/module.js ===
|
||||
var Inner = function() {}
|
||||
>Inner : Symbol(Inner, Decl(module.js, 0, 3), Decl(module.js, 0, 25))
|
||||
|
||||
Inner.prototype = {
|
||||
>Inner.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>Inner : Symbol(Inner, Decl(module.js, 0, 3), Decl(module.js, 0, 25))
|
||||
>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
m() { },
|
||||
>m : Symbol(m, Decl(module.js, 1, 19))
|
||||
|
||||
i: 1
|
||||
>i : Symbol(i, Decl(module.js, 2, 12))
|
||||
}
|
||||
// incremental assignments still work
|
||||
Inner.prototype.j = 2
|
||||
>Inner.prototype : Symbol(Inner.j, Decl(module.js, 4, 1))
|
||||
>Inner : Symbol(Inner, Decl(module.js, 0, 3), Decl(module.js, 0, 25))
|
||||
>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>j : Symbol(Inner.j, Decl(module.js, 4, 1))
|
||||
|
||||
/** @type {string} */
|
||||
Inner.prototype.k;
|
||||
>Inner.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>Inner : Symbol(Inner, Decl(module.js, 0, 3), Decl(module.js, 0, 25))
|
||||
>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var inner = new Inner()
|
||||
>inner : Symbol(inner, Decl(module.js, 9, 3))
|
||||
>Inner : Symbol(Inner, Decl(module.js, 0, 3), Decl(module.js, 0, 25))
|
||||
|
||||
inner.m()
|
||||
>inner.m : Symbol(m, Decl(module.js, 1, 19))
|
||||
>inner : Symbol(inner, Decl(module.js, 9, 3))
|
||||
>m : Symbol(m, Decl(module.js, 1, 19))
|
||||
|
||||
inner.i
|
||||
>inner.i : Symbol(i, Decl(module.js, 2, 12))
|
||||
>inner : Symbol(inner, Decl(module.js, 9, 3))
|
||||
>i : Symbol(i, Decl(module.js, 2, 12))
|
||||
|
||||
inner.j
|
||||
>inner.j : Symbol(Inner.j, Decl(module.js, 4, 1))
|
||||
>inner : Symbol(inner, Decl(module.js, 9, 3))
|
||||
>j : Symbol(Inner.j, Decl(module.js, 4, 1))
|
||||
|
||||
inner.k
|
||||
>inner.k : Symbol(Inner.k, Decl(module.js, 6, 21))
|
||||
>inner : Symbol(inner, Decl(module.js, 9, 3))
|
||||
>k : Symbol(Inner.k, Decl(module.js, 6, 21))
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
=== tests/cases/conformance/salsa/module.js ===
|
||||
var Inner = function() {}
|
||||
>Inner : () => void
|
||||
>function() {} : () => void
|
||||
|
||||
Inner.prototype = {
|
||||
>Inner.prototype = { m() { }, i: 1} : { [x: string]: any; m(): void; i: number; }
|
||||
>Inner.prototype : any
|
||||
>Inner : () => void
|
||||
>prototype : any
|
||||
>{ m() { }, i: 1} : { [x: string]: any; m(): void; i: number; }
|
||||
|
||||
m() { },
|
||||
>m : () => void
|
||||
|
||||
i: 1
|
||||
>i : number
|
||||
>1 : 1
|
||||
}
|
||||
// incremental assignments still work
|
||||
Inner.prototype.j = 2
|
||||
>Inner.prototype.j = 2 : 2
|
||||
>Inner.prototype.j : any
|
||||
>Inner.prototype : any
|
||||
>Inner : () => void
|
||||
>prototype : any
|
||||
>j : any
|
||||
>2 : 2
|
||||
|
||||
/** @type {string} */
|
||||
Inner.prototype.k;
|
||||
>Inner.prototype.k : any
|
||||
>Inner.prototype : any
|
||||
>Inner : () => void
|
||||
>prototype : any
|
||||
>k : any
|
||||
|
||||
var inner = new Inner()
|
||||
>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>new Inner() : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>Inner : () => void
|
||||
|
||||
inner.m()
|
||||
>inner.m() : void
|
||||
>inner.m : () => void
|
||||
>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>m : () => void
|
||||
|
||||
inner.i
|
||||
>inner.i : number
|
||||
>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>i : number
|
||||
|
||||
inner.j
|
||||
>inner.j : number
|
||||
>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>j : number
|
||||
|
||||
inner.k
|
||||
>inner.k : string
|
||||
>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>k : string
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
=== tests/cases/conformance/salsa/module.js ===
|
||||
var Outer = function(element, config) {};
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(usage.js, 0, 0))
|
||||
>element : Symbol(element, Decl(module.js, 0, 21))
|
||||
>config : Symbol(config, Decl(module.js, 0, 29))
|
||||
|
||||
=== tests/cases/conformance/salsa/usage.js ===
|
||||
/** @constructor */
|
||||
Outer.Pos = function (line, ch) {};
|
||||
>Outer.Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(usage.js, 0, 0))
|
||||
>Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0))
|
||||
>line : Symbol(line, Decl(usage.js, 1, 22))
|
||||
>ch : Symbol(ch, Decl(usage.js, 1, 27))
|
||||
|
||||
/** @type {number} */
|
||||
Outer.Pos.prototype.line;
|
||||
>Outer.Pos.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>Outer.Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(usage.js, 0, 0))
|
||||
>Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0))
|
||||
>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var pos = new Outer.Pos(1, 'x');
|
||||
>pos : Symbol(pos, Decl(usage.js, 4, 3))
|
||||
>Outer.Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(usage.js, 0, 0))
|
||||
>Pos : Symbol(Outer.Pos, Decl(usage.js, 0, 0))
|
||||
|
||||
pos.line;
|
||||
>pos.line : Symbol((Anonymous function).line, Decl(usage.js, 1, 35))
|
||||
>pos : Symbol(pos, Decl(usage.js, 4, 3))
|
||||
>line : Symbol((Anonymous function).line, Decl(usage.js, 1, 35))
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
=== tests/cases/conformance/salsa/module.js ===
|
||||
var Outer = function(element, config) {};
|
||||
>Outer : typeof Outer
|
||||
>function(element, config) {} : typeof Outer
|
||||
>element : any
|
||||
>config : any
|
||||
|
||||
=== tests/cases/conformance/salsa/usage.js ===
|
||||
/** @constructor */
|
||||
Outer.Pos = function (line, ch) {};
|
||||
>Outer.Pos = function (line, ch) {} : (line: any, ch: any) => void
|
||||
>Outer.Pos : (line: any, ch: any) => void
|
||||
>Outer : typeof Outer
|
||||
>Pos : (line: any, ch: any) => void
|
||||
>function (line, ch) {} : (line: any, ch: any) => void
|
||||
>line : any
|
||||
>ch : any
|
||||
|
||||
/** @type {number} */
|
||||
Outer.Pos.prototype.line;
|
||||
>Outer.Pos.prototype.line : any
|
||||
>Outer.Pos.prototype : any
|
||||
>Outer.Pos : (line: any, ch: any) => void
|
||||
>Outer : typeof Outer
|
||||
>Pos : (line: any, ch: any) => void
|
||||
>prototype : any
|
||||
>line : any
|
||||
|
||||
var pos = new Outer.Pos(1, 'x');
|
||||
>pos : { line: number; }
|
||||
>new Outer.Pos(1, 'x') : { line: number; }
|
||||
>Outer.Pos : (line: any, ch: any) => void
|
||||
>Outer : typeof Outer
|
||||
>Pos : (line: any, ch: any) => void
|
||||
>1 : 1
|
||||
>'x' : "x"
|
||||
|
||||
pos.line;
|
||||
>pos.line : number
|
||||
>pos : { line: number; }
|
||||
>line : number
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
=== tests/cases/conformance/salsa/module.js ===
|
||||
var Outer = {}
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27))
|
||||
|
||||
Outer.Inner = function() {}
|
||||
>Outer.Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27))
|
||||
>Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6))
|
||||
|
||||
Outer.Inner.prototype = {
|
||||
>Outer.Inner.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>Outer.Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27))
|
||||
>Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6))
|
||||
>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
m() { },
|
||||
>m : Symbol(m, Decl(module.js, 2, 25))
|
||||
|
||||
i: 1
|
||||
>i : Symbol(i, Decl(module.js, 3, 12))
|
||||
}
|
||||
// incremental assignments still work
|
||||
Outer.Inner.prototype.j = 2
|
||||
>Outer.Inner.prototype : Symbol((Anonymous function).j, Decl(module.js, 5, 1))
|
||||
>Outer.Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27))
|
||||
>Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6))
|
||||
>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>j : Symbol((Anonymous function).j, Decl(module.js, 5, 1))
|
||||
|
||||
/** @type {string} */
|
||||
Outer.Inner.prototype.k;
|
||||
>Outer.Inner.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
>Outer.Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27))
|
||||
>Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6))
|
||||
>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
var inner = new Outer.Inner()
|
||||
>inner : Symbol(inner, Decl(module.js, 10, 3))
|
||||
>Outer.Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6))
|
||||
>Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(module.js, 0, 14), Decl(module.js, 1, 27))
|
||||
>Inner : Symbol(Inner, Decl(module.js, 0, 14), Decl(module.js, 2, 6))
|
||||
|
||||
inner.m()
|
||||
>inner.m : Symbol(m, Decl(module.js, 2, 25))
|
||||
>inner : Symbol(inner, Decl(module.js, 10, 3))
|
||||
>m : Symbol(m, Decl(module.js, 2, 25))
|
||||
|
||||
inner.i
|
||||
>inner.i : Symbol(i, Decl(module.js, 3, 12))
|
||||
>inner : Symbol(inner, Decl(module.js, 10, 3))
|
||||
>i : Symbol(i, Decl(module.js, 3, 12))
|
||||
|
||||
inner.j
|
||||
>inner.j : Symbol((Anonymous function).j, Decl(module.js, 5, 1))
|
||||
>inner : Symbol(inner, Decl(module.js, 10, 3))
|
||||
>j : Symbol((Anonymous function).j, Decl(module.js, 5, 1))
|
||||
|
||||
inner.k
|
||||
>inner.k : Symbol((Anonymous function).k, Decl(module.js, 7, 27))
|
||||
>inner : Symbol(inner, Decl(module.js, 10, 3))
|
||||
>k : Symbol((Anonymous function).k, Decl(module.js, 7, 27))
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
=== tests/cases/conformance/salsa/module.js ===
|
||||
var Outer = {}
|
||||
>Outer : { [x: string]: any; Inner: () => void; }
|
||||
>{} : { [x: string]: any; Inner: () => void; }
|
||||
|
||||
Outer.Inner = function() {}
|
||||
>Outer.Inner = function() {} : () => void
|
||||
>Outer.Inner : () => void
|
||||
>Outer : { [x: string]: any; Inner: () => void; }
|
||||
>Inner : () => void
|
||||
>function() {} : () => void
|
||||
|
||||
Outer.Inner.prototype = {
|
||||
>Outer.Inner.prototype = { m() { }, i: 1} : { [x: string]: any; m(): void; i: number; }
|
||||
>Outer.Inner.prototype : any
|
||||
>Outer.Inner : () => void
|
||||
>Outer : { [x: string]: any; Inner: () => void; }
|
||||
>Inner : () => void
|
||||
>prototype : any
|
||||
>{ m() { }, i: 1} : { [x: string]: any; m(): void; i: number; }
|
||||
|
||||
m() { },
|
||||
>m : () => void
|
||||
|
||||
i: 1
|
||||
>i : number
|
||||
>1 : 1
|
||||
}
|
||||
// incremental assignments still work
|
||||
Outer.Inner.prototype.j = 2
|
||||
>Outer.Inner.prototype.j = 2 : 2
|
||||
>Outer.Inner.prototype.j : any
|
||||
>Outer.Inner.prototype : any
|
||||
>Outer.Inner : () => void
|
||||
>Outer : { [x: string]: any; Inner: () => void; }
|
||||
>Inner : () => void
|
||||
>prototype : any
|
||||
>j : any
|
||||
>2 : 2
|
||||
|
||||
/** @type {string} */
|
||||
Outer.Inner.prototype.k;
|
||||
>Outer.Inner.prototype.k : any
|
||||
>Outer.Inner.prototype : any
|
||||
>Outer.Inner : () => void
|
||||
>Outer : { [x: string]: any; Inner: () => void; }
|
||||
>Inner : () => void
|
||||
>prototype : any
|
||||
>k : any
|
||||
|
||||
var inner = new Outer.Inner()
|
||||
>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>new Outer.Inner() : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>Outer.Inner : () => void
|
||||
>Outer : { [x: string]: any; Inner: () => void; }
|
||||
>Inner : () => void
|
||||
|
||||
inner.m()
|
||||
>inner.m() : void
|
||||
>inner.m : () => void
|
||||
>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>m : () => void
|
||||
|
||||
inner.i
|
||||
>inner.i : number
|
||||
>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>i : number
|
||||
|
||||
inner.j
|
||||
>inner.j : number
|
||||
>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>j : number
|
||||
|
||||
inner.k
|
||||
>inner.k : string
|
||||
>inner : { j: number; k: string; } & { [x: string]: any; m(): void; i: number; }
|
||||
>k : string
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
=== tests/cases/conformance/salsa/def.js ===
|
||||
var Outer = {};
|
||||
>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(work.js, 0, 0), Decl(work.js, 0, 28))
|
||||
|
||||
=== tests/cases/conformance/salsa/work.js ===
|
||||
Outer.Inner = function () {}
|
||||
>Outer.Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6))
|
||||
>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(work.js, 0, 0), Decl(work.js, 0, 28))
|
||||
>Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6))
|
||||
|
||||
Outer.Inner.prototype = {
|
||||
>Outer.Inner.prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --))
|
||||
>Outer.Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6))
|
||||
>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(work.js, 0, 0), Decl(work.js, 0, 28))
|
||||
>Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6))
|
||||
>prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --))
|
||||
|
||||
x: 1,
|
||||
>x : Symbol(x, Decl(work.js, 1, 25))
|
||||
|
||||
m() { }
|
||||
>m : Symbol(m, Decl(work.js, 2, 9))
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/salsa/use.js ===
|
||||
/** @type {Outer.Inner} */
|
||||
var inner
|
||||
>inner : Symbol(inner, Decl(use.js, 1, 3))
|
||||
|
||||
inner.x
|
||||
>inner.x : Symbol(x, Decl(work.js, 1, 25))
|
||||
>inner : Symbol(inner, Decl(use.js, 1, 3))
|
||||
>x : Symbol(x, Decl(work.js, 1, 25))
|
||||
|
||||
inner.m()
|
||||
>inner.m : Symbol(m, Decl(work.js, 2, 9))
|
||||
>inner : Symbol(inner, Decl(use.js, 1, 3))
|
||||
>m : Symbol(m, Decl(work.js, 2, 9))
|
||||
|
||||
var inno = new Outer.Inner()
|
||||
>inno : Symbol(inno, Decl(use.js, 4, 3))
|
||||
>Outer.Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6))
|
||||
>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(work.js, 0, 0), Decl(work.js, 0, 28))
|
||||
>Inner : Symbol(Outer.Inner, Decl(work.js, 0, 0), Decl(work.js, 1, 6))
|
||||
|
||||
inno.x
|
||||
>inno.x : Symbol(x, Decl(work.js, 1, 25))
|
||||
>inno : Symbol(inno, Decl(use.js, 4, 3))
|
||||
>x : Symbol(x, Decl(work.js, 1, 25))
|
||||
|
||||
inno.m()
|
||||
>inno.m : Symbol(m, Decl(work.js, 2, 9))
|
||||
>inno : Symbol(inno, Decl(use.js, 4, 3))
|
||||
>m : Symbol(m, Decl(work.js, 2, 9))
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
=== tests/cases/conformance/salsa/def.js ===
|
||||
var Outer = {};
|
||||
>Outer : typeof Outer
|
||||
>{} : typeof Outer
|
||||
|
||||
=== tests/cases/conformance/salsa/work.js ===
|
||||
Outer.Inner = function () {}
|
||||
>Outer.Inner = function () {} : () => void
|
||||
>Outer.Inner : () => void
|
||||
>Outer : typeof Outer
|
||||
>Inner : () => void
|
||||
>function () {} : () => void
|
||||
|
||||
Outer.Inner.prototype = {
|
||||
>Outer.Inner.prototype = { x: 1, m() { }} : { [x: string]: any; x: number; m(): void; }
|
||||
>Outer.Inner.prototype : any
|
||||
>Outer.Inner : () => void
|
||||
>Outer : typeof Outer
|
||||
>Inner : () => void
|
||||
>prototype : any
|
||||
>{ x: 1, m() { }} : { [x: string]: any; x: number; m(): void; }
|
||||
|
||||
x: 1,
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
m() { }
|
||||
>m : () => void
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/salsa/use.js ===
|
||||
/** @type {Outer.Inner} */
|
||||
var inner
|
||||
>inner : { [x: string]: any; x: number; m(): void; }
|
||||
|
||||
inner.x
|
||||
>inner.x : number
|
||||
>inner : { [x: string]: any; x: number; m(): void; }
|
||||
>x : number
|
||||
|
||||
inner.m()
|
||||
>inner.m() : void
|
||||
>inner.m : () => void
|
||||
>inner : { [x: string]: any; x: number; m(): void; }
|
||||
>m : () => void
|
||||
|
||||
var inno = new Outer.Inner()
|
||||
>inno : { [x: string]: any; x: number; m(): void; }
|
||||
>new Outer.Inner() : { [x: string]: any; x: number; m(): void; }
|
||||
>Outer.Inner : () => void
|
||||
>Outer : typeof Outer
|
||||
>Inner : () => void
|
||||
|
||||
inno.x
|
||||
>inno.x : number
|
||||
>inno : { [x: string]: any; x: number; m(): void; }
|
||||
>x : number
|
||||
|
||||
inno.m()
|
||||
>inno.m() : void
|
||||
>inno.m : () => void
|
||||
>inno : { [x: string]: any; x: number; m(): void; }
|
||||
>m : () => void
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var Outer = {};
|
||||
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15))
|
||||
|
||||
Outer.Inner = class {
|
||||
>Outer.Inner : Symbol(Inner, Decl(a.js, 0, 15))
|
||||
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15))
|
||||
>Inner : Symbol(Inner, Decl(a.js, 0, 15))
|
||||
|
||||
constructor() {
|
||||
this.x = 1
|
||||
>this.x : Symbol((Anonymous class).x, Decl(a.js, 3, 19))
|
||||
>this : Symbol((Anonymous class), Decl(a.js, 2, 13))
|
||||
>x : Symbol((Anonymous class).x, Decl(a.js, 3, 19))
|
||||
}
|
||||
m() { }
|
||||
>m : Symbol((Anonymous class).m, Decl(a.js, 5, 5))
|
||||
}
|
||||
|
||||
/** @type {Outer.Inner} */
|
||||
var inner
|
||||
>inner : Symbol(inner, Decl(a.js, 10, 3))
|
||||
|
||||
inner.x
|
||||
>inner.x : Symbol((Anonymous class).x, Decl(a.js, 3, 19))
|
||||
>inner : Symbol(inner, Decl(a.js, 10, 3))
|
||||
>x : Symbol((Anonymous class).x, Decl(a.js, 3, 19))
|
||||
|
||||
inner.m()
|
||||
>inner.m : Symbol((Anonymous class).m, Decl(a.js, 5, 5))
|
||||
>inner : Symbol(inner, Decl(a.js, 10, 3))
|
||||
>m : Symbol((Anonymous class).m, Decl(a.js, 5, 5))
|
||||
|
||||
var inno = new Outer.Inner()
|
||||
>inno : Symbol(inno, Decl(a.js, 13, 3))
|
||||
>Outer.Inner : Symbol(Inner, Decl(a.js, 0, 15))
|
||||
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15))
|
||||
>Inner : Symbol(Inner, Decl(a.js, 0, 15))
|
||||
|
||||
inno.x
|
||||
>inno.x : Symbol((Anonymous class).x, Decl(a.js, 3, 19))
|
||||
>inno : Symbol(inno, Decl(a.js, 13, 3))
|
||||
>x : Symbol((Anonymous class).x, Decl(a.js, 3, 19))
|
||||
|
||||
inno.m()
|
||||
>inno.m : Symbol((Anonymous class).m, Decl(a.js, 5, 5))
|
||||
>inno : Symbol(inno, Decl(a.js, 13, 3))
|
||||
>m : Symbol((Anonymous class).m, Decl(a.js, 5, 5))
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var Outer = {};
|
||||
>Outer : { [x: string]: any; Inner: typeof (Anonymous class); }
|
||||
>{} : { [x: string]: any; Inner: typeof (Anonymous class); }
|
||||
|
||||
Outer.Inner = class {
|
||||
>Outer.Inner = class { constructor() { this.x = 1 } m() { }} : typeof (Anonymous class)
|
||||
>Outer.Inner : typeof (Anonymous class)
|
||||
>Outer : { [x: string]: any; Inner: typeof (Anonymous class); }
|
||||
>Inner : typeof (Anonymous class)
|
||||
>class { constructor() { this.x = 1 } m() { }} : typeof (Anonymous class)
|
||||
|
||||
constructor() {
|
||||
this.x = 1
|
||||
>this.x = 1 : 1
|
||||
>this.x : number
|
||||
>this : this
|
||||
>x : number
|
||||
>1 : 1
|
||||
}
|
||||
m() { }
|
||||
>m : () => void
|
||||
}
|
||||
|
||||
/** @type {Outer.Inner} */
|
||||
var inner
|
||||
>inner : (Anonymous class)
|
||||
|
||||
inner.x
|
||||
>inner.x : number
|
||||
>inner : (Anonymous class)
|
||||
>x : number
|
||||
|
||||
inner.m()
|
||||
>inner.m() : void
|
||||
>inner.m : () => void
|
||||
>inner : (Anonymous class)
|
||||
>m : () => void
|
||||
|
||||
var inno = new Outer.Inner()
|
||||
>inno : (Anonymous class)
|
||||
>new Outer.Inner() : (Anonymous class)
|
||||
>Outer.Inner : typeof (Anonymous class)
|
||||
>Outer : { [x: string]: any; Inner: typeof (Anonymous class); }
|
||||
>Inner : typeof (Anonymous class)
|
||||
|
||||
inno.x
|
||||
>inno.x : number
|
||||
>inno : (Anonymous class)
|
||||
>x : number
|
||||
|
||||
inno.m()
|
||||
>inno.m() : void
|
||||
>inno.m : () => void
|
||||
>inno : (Anonymous class)
|
||||
>m : () => void
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var Outer = {};
|
||||
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15), Decl(a.js, 2, 28))
|
||||
|
||||
Outer.Inner = function () {}
|
||||
>Outer.Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6))
|
||||
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15), Decl(a.js, 2, 28))
|
||||
>Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6))
|
||||
|
||||
Outer.Inner.prototype = {
|
||||
>Outer.Inner.prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --))
|
||||
>Outer.Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6))
|
||||
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15), Decl(a.js, 2, 28))
|
||||
>Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6))
|
||||
>prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --))
|
||||
|
||||
x: 1,
|
||||
>x : Symbol(x, Decl(a.js, 3, 25))
|
||||
|
||||
m() { }
|
||||
>m : Symbol(m, Decl(a.js, 4, 9))
|
||||
}
|
||||
|
||||
/** @type {Outer.Inner} */
|
||||
var inner
|
||||
>inner : Symbol(inner, Decl(a.js, 9, 3))
|
||||
|
||||
inner.x
|
||||
>inner.x : Symbol(x, Decl(a.js, 3, 25))
|
||||
>inner : Symbol(inner, Decl(a.js, 9, 3))
|
||||
>x : Symbol(x, Decl(a.js, 3, 25))
|
||||
|
||||
inner.m()
|
||||
>inner.m : Symbol(m, Decl(a.js, 4, 9))
|
||||
>inner : Symbol(inner, Decl(a.js, 9, 3))
|
||||
>m : Symbol(m, Decl(a.js, 4, 9))
|
||||
|
||||
var inno = new Outer.Inner()
|
||||
>inno : Symbol(inno, Decl(a.js, 12, 3))
|
||||
>Outer.Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6))
|
||||
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 0, 15), Decl(a.js, 2, 28))
|
||||
>Inner : Symbol(Inner, Decl(a.js, 0, 15), Decl(a.js, 3, 6))
|
||||
|
||||
inno.x
|
||||
>inno.x : Symbol(x, Decl(a.js, 3, 25))
|
||||
>inno : Symbol(inno, Decl(a.js, 12, 3))
|
||||
>x : Symbol(x, Decl(a.js, 3, 25))
|
||||
|
||||
inno.m()
|
||||
>inno.m : Symbol(m, Decl(a.js, 4, 9))
|
||||
>inno : Symbol(inno, Decl(a.js, 12, 3))
|
||||
>m : Symbol(m, Decl(a.js, 4, 9))
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var Outer = {};
|
||||
>Outer : { [x: string]: any; Inner: () => void; }
|
||||
>{} : { [x: string]: any; Inner: () => void; }
|
||||
|
||||
Outer.Inner = function () {}
|
||||
>Outer.Inner = function () {} : () => void
|
||||
>Outer.Inner : () => void
|
||||
>Outer : { [x: string]: any; Inner: () => void; }
|
||||
>Inner : () => void
|
||||
>function () {} : () => void
|
||||
|
||||
Outer.Inner.prototype = {
|
||||
>Outer.Inner.prototype = { x: 1, m() { }} : { [x: string]: any; x: number; m(): void; }
|
||||
>Outer.Inner.prototype : any
|
||||
>Outer.Inner : () => void
|
||||
>Outer : { [x: string]: any; Inner: () => void; }
|
||||
>Inner : () => void
|
||||
>prototype : any
|
||||
>{ x: 1, m() { }} : { [x: string]: any; x: number; m(): void; }
|
||||
|
||||
x: 1,
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
m() { }
|
||||
>m : () => void
|
||||
}
|
||||
|
||||
/** @type {Outer.Inner} */
|
||||
var inner
|
||||
>inner : { [x: string]: any; x: number; m(): void; }
|
||||
|
||||
inner.x
|
||||
>inner.x : number
|
||||
>inner : { [x: string]: any; x: number; m(): void; }
|
||||
>x : number
|
||||
|
||||
inner.m()
|
||||
>inner.m() : void
|
||||
>inner.m : () => void
|
||||
>inner : { [x: string]: any; x: number; m(): void; }
|
||||
>m : () => void
|
||||
|
||||
var inno = new Outer.Inner()
|
||||
>inno : { [x: string]: any; x: number; m(): void; }
|
||||
>new Outer.Inner() : { [x: string]: any; x: number; m(): void; }
|
||||
>Outer.Inner : () => void
|
||||
>Outer : { [x: string]: any; Inner: () => void; }
|
||||
>Inner : () => void
|
||||
|
||||
inno.x
|
||||
>inno.x : number
|
||||
>inno : { [x: string]: any; x: number; m(): void; }
|
||||
>x : number
|
||||
|
||||
inno.m()
|
||||
>inno.m() : void
|
||||
>inno.m : () => void
|
||||
>inno : { [x: string]: any; x: number; m(): void; }
|
||||
>m : () => void
|
||||
|
||||
@@ -4,7 +4,9 @@ var Outer = {};
|
||||
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
Outer.Inner = class {
|
||||
>Outer.Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0))
|
||||
>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(a.js, 0, 0))
|
||||
>Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0))
|
||||
|
||||
constructor() {
|
||||
/** @type {number} */
|
||||
@@ -15,9 +17,29 @@ Outer.Inner = class {
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {Outer.Inner} */
|
||||
var local
|
||||
>local : Symbol(local, Decl(a.js, 8, 3))
|
||||
|
||||
local.y
|
||||
>local.y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))
|
||||
>local : Symbol(local, Decl(a.js, 8, 3))
|
||||
>y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))
|
||||
|
||||
var inner = new Outer.Inner()
|
||||
>inner : Symbol(inner, Decl(a.js, 10, 3))
|
||||
>Outer.Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0))
|
||||
>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(a.js, 0, 0))
|
||||
>Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0))
|
||||
|
||||
inner.y
|
||||
>inner.y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))
|
||||
>inner : Symbol(inner, Decl(a.js, 10, 3))
|
||||
>y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))
|
||||
|
||||
=== tests/cases/conformance/salsa/b.js ===
|
||||
/** @type {Outer.Inner} */
|
||||
var x;
|
||||
var x
|
||||
>x : Symbol(x, Decl(b.js, 1, 3))
|
||||
|
||||
x.y
|
||||
@@ -25,3 +47,14 @@ x.y
|
||||
>x : Symbol(x, Decl(b.js, 1, 3))
|
||||
>y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))
|
||||
|
||||
var z = new Outer.Inner()
|
||||
>z : Symbol(z, Decl(b.js, 3, 3))
|
||||
>Outer.Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0))
|
||||
>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(a.js, 0, 0))
|
||||
>Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0))
|
||||
|
||||
z.y
|
||||
>z.y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))
|
||||
>z : Symbol(z, Decl(b.js, 3, 3))
|
||||
>y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
=== tests/cases/conformance/salsa/def.js ===
|
||||
var Outer = {};
|
||||
>Outer : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; }
|
||||
>Outer : typeof Outer
|
||||
>{} : typeof Outer
|
||||
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
Outer.Inner = class {
|
||||
>Outer.Inner = class { constructor() { /** @type {number} */ this.y = 12 }} : typeof (Anonymous class)
|
||||
>Outer.Inner : any
|
||||
>Outer : { [x: string]: any; }
|
||||
>Inner : any
|
||||
>Outer.Inner : typeof (Anonymous class)
|
||||
>Outer : typeof Outer
|
||||
>Inner : typeof (Anonymous class)
|
||||
>class { constructor() { /** @type {number} */ this.y = 12 }} : typeof (Anonymous class)
|
||||
|
||||
constructor() {
|
||||
@@ -22,9 +22,30 @@ Outer.Inner = class {
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {Outer.Inner} */
|
||||
var local
|
||||
>local : (Anonymous class)
|
||||
|
||||
local.y
|
||||
>local.y : number
|
||||
>local : (Anonymous class)
|
||||
>y : number
|
||||
|
||||
var inner = new Outer.Inner()
|
||||
>inner : (Anonymous class)
|
||||
>new Outer.Inner() : (Anonymous class)
|
||||
>Outer.Inner : typeof (Anonymous class)
|
||||
>Outer : typeof Outer
|
||||
>Inner : typeof (Anonymous class)
|
||||
|
||||
inner.y
|
||||
>inner.y : number
|
||||
>inner : (Anonymous class)
|
||||
>y : number
|
||||
|
||||
=== tests/cases/conformance/salsa/b.js ===
|
||||
/** @type {Outer.Inner} */
|
||||
var x;
|
||||
var x
|
||||
>x : (Anonymous class)
|
||||
|
||||
x.y
|
||||
@@ -32,3 +53,15 @@ x.y
|
||||
>x : (Anonymous class)
|
||||
>y : number
|
||||
|
||||
var z = new Outer.Inner()
|
||||
>z : (Anonymous class)
|
||||
>new Outer.Inner() : (Anonymous class)
|
||||
>Outer.Inner : typeof (Anonymous class)
|
||||
>Outer : typeof Outer
|
||||
>Inner : typeof (Anonymous class)
|
||||
|
||||
z.y
|
||||
>z.y : number
|
||||
>z : (Anonymous class)
|
||||
>y : number
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var obj = {};
|
||||
>obj : Symbol(obj, Decl(a.js, 0, 3), Decl(a.js, 0, 13))
|
||||
|
||||
obj.method = function (hunch) {
|
||||
>obj.method : Symbol(method, Decl(a.js, 0, 13))
|
||||
>obj : Symbol(obj, Decl(a.js, 0, 3), Decl(a.js, 0, 13))
|
||||
>method : Symbol(method, Decl(a.js, 0, 13))
|
||||
>hunch : Symbol(hunch, Decl(a.js, 1, 23))
|
||||
|
||||
return true;
|
||||
}
|
||||
var b = obj.method();
|
||||
>b : Symbol(b, Decl(a.js, 4, 3))
|
||||
>obj.method : Symbol(method, Decl(a.js, 0, 13))
|
||||
>obj : Symbol(obj, Decl(a.js, 0, 3), Decl(a.js, 0, 13))
|
||||
>method : Symbol(method, Decl(a.js, 0, 13))
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var obj = {};
|
||||
>obj : { [x: string]: any; method: (hunch: any) => boolean; }
|
||||
>{} : { [x: string]: any; method: (hunch: any) => boolean; }
|
||||
|
||||
obj.method = function (hunch) {
|
||||
>obj.method = function (hunch) { return true;} : (hunch: any) => boolean
|
||||
>obj.method : (hunch: any) => boolean
|
||||
>obj : { [x: string]: any; method: (hunch: any) => boolean; }
|
||||
>method : (hunch: any) => boolean
|
||||
>function (hunch) { return true;} : (hunch: any) => boolean
|
||||
>hunch : any
|
||||
|
||||
return true;
|
||||
>true : true
|
||||
}
|
||||
var b = obj.method();
|
||||
>b : boolean
|
||||
>obj.method() : boolean
|
||||
>obj.method : (hunch: any) => boolean
|
||||
>obj : { [x: string]: any; method: (hunch: any) => boolean; }
|
||||
>method : (hunch: any) => boolean
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var my = my || {};
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 1, 22))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 1, 22))
|
||||
|
||||
my.app = my.app || {};
|
||||
>my.app : Symbol(app, Decl(a.js, 0, 18), Decl(a.js, 3, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 1, 22))
|
||||
>app : Symbol(app, Decl(a.js, 0, 18), Decl(a.js, 3, 3))
|
||||
>my.app : Symbol(app, Decl(a.js, 0, 18), Decl(a.js, 3, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 1, 22))
|
||||
>app : Symbol(app, Decl(a.js, 0, 18), Decl(a.js, 3, 3))
|
||||
|
||||
my.app.Application = (function () {
|
||||
>my.app.Application : Symbol(Application, Decl(a.js, 1, 22))
|
||||
>my.app : Symbol(app, Decl(a.js, 0, 18), Decl(a.js, 3, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 1, 22))
|
||||
>app : Symbol(app, Decl(a.js, 0, 18), Decl(a.js, 3, 3))
|
||||
>Application : Symbol(Application, Decl(a.js, 1, 22))
|
||||
|
||||
var Application = function () {
|
||||
>Application : Symbol(Application, Decl(a.js, 4, 3))
|
||||
|
||||
//...
|
||||
};
|
||||
return Application;
|
||||
>Application : Symbol(Application, Decl(a.js, 4, 3))
|
||||
|
||||
})();
|
||||
my.app.Application()
|
||||
>my.app.Application : Symbol(Application, Decl(a.js, 1, 22))
|
||||
>my.app : Symbol(app, Decl(a.js, 0, 18), Decl(a.js, 3, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 1, 22))
|
||||
>app : Symbol(app, Decl(a.js, 0, 18), Decl(a.js, 3, 3))
|
||||
>Application : Symbol(Application, Decl(a.js, 1, 22))
|
||||
|
||||
=== tests/cases/conformance/salsa/b.js ===
|
||||
var min = window.min || {};
|
||||
>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 1, 24))
|
||||
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
min.app = min.app || {};
|
||||
>min.app : Symbol(app, Decl(b.js, 0, 27), Decl(b.js, 3, 4))
|
||||
>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 1, 24))
|
||||
>app : Symbol(app, Decl(b.js, 0, 27), Decl(b.js, 3, 4))
|
||||
>min.app : Symbol(app, Decl(b.js, 0, 27), Decl(b.js, 3, 4))
|
||||
>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 1, 24))
|
||||
>app : Symbol(app, Decl(b.js, 0, 27), Decl(b.js, 3, 4))
|
||||
|
||||
min.app.Application = (function () {
|
||||
>min.app.Application : Symbol(Application, Decl(b.js, 1, 24))
|
||||
>min.app : Symbol(app, Decl(b.js, 0, 27), Decl(b.js, 3, 4))
|
||||
>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 1, 24))
|
||||
>app : Symbol(app, Decl(b.js, 0, 27), Decl(b.js, 3, 4))
|
||||
>Application : Symbol(Application, Decl(b.js, 1, 24))
|
||||
|
||||
var Application = function () {
|
||||
>Application : Symbol(Application, Decl(b.js, 4, 3))
|
||||
|
||||
//...
|
||||
};
|
||||
return Application;
|
||||
>Application : Symbol(Application, Decl(b.js, 4, 3))
|
||||
|
||||
})();
|
||||
min.app.Application()
|
||||
>min.app.Application : Symbol(Application, Decl(b.js, 1, 24))
|
||||
>min.app : Symbol(app, Decl(b.js, 0, 27), Decl(b.js, 3, 4))
|
||||
>min : Symbol(min, Decl(b.js, 0, 3), Decl(b.js, 1, 24))
|
||||
>app : Symbol(app, Decl(b.js, 0, 27), Decl(b.js, 3, 4))
|
||||
>Application : Symbol(Application, Decl(b.js, 1, 24))
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var my = my || {};
|
||||
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>my || {} : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>{} : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
|
||||
my.app = my.app || {};
|
||||
>my.app = my.app || {} : { [x: string]: any; Application: () => void; }
|
||||
>my.app : { [x: string]: any; Application: () => void; }
|
||||
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>app : { [x: string]: any; Application: () => void; }
|
||||
>my.app || {} : { [x: string]: any; Application: () => void; }
|
||||
>my.app : { [x: string]: any; Application: () => void; }
|
||||
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>app : { [x: string]: any; Application: () => void; }
|
||||
>{} : { [x: string]: any; Application: () => void; }
|
||||
|
||||
my.app.Application = (function () {
|
||||
>my.app.Application = (function () {var Application = function () { //...};return Application;})() : () => void
|
||||
>my.app.Application : () => void
|
||||
>my.app : { [x: string]: any; Application: () => void; }
|
||||
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>app : { [x: string]: any; Application: () => void; }
|
||||
>Application : () => void
|
||||
>(function () {var Application = function () { //...};return Application;})() : () => void
|
||||
>(function () {var Application = function () { //...};return Application;}) : () => () => void
|
||||
>function () {var Application = function () { //...};return Application;} : () => () => void
|
||||
|
||||
var Application = function () {
|
||||
>Application : () => void
|
||||
>function () { //...} : () => void
|
||||
|
||||
//...
|
||||
};
|
||||
return Application;
|
||||
>Application : () => void
|
||||
|
||||
})();
|
||||
my.app.Application()
|
||||
>my.app.Application() : void
|
||||
>my.app.Application : () => void
|
||||
>my.app : { [x: string]: any; Application: () => void; }
|
||||
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>app : { [x: string]: any; Application: () => void; }
|
||||
>Application : () => void
|
||||
|
||||
=== tests/cases/conformance/salsa/b.js ===
|
||||
var min = window.min || {};
|
||||
>min : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>window.min || {} : any
|
||||
>window.min : any
|
||||
>window : Window
|
||||
>min : any
|
||||
>{} : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
|
||||
min.app = min.app || {};
|
||||
>min.app = min.app || {} : { [x: string]: any; Application: () => void; }
|
||||
>min.app : { [x: string]: any; Application: () => void; }
|
||||
>min : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>app : { [x: string]: any; Application: () => void; }
|
||||
>min.app || {} : { [x: string]: any; Application: () => void; }
|
||||
>min.app : { [x: string]: any; Application: () => void; }
|
||||
>min : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>app : { [x: string]: any; Application: () => void; }
|
||||
>{} : { [x: string]: any; Application: () => void; }
|
||||
|
||||
min.app.Application = (function () {
|
||||
>min.app.Application = (function () {var Application = function () { //...};return Application;})() : () => void
|
||||
>min.app.Application : () => void
|
||||
>min.app : { [x: string]: any; Application: () => void; }
|
||||
>min : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>app : { [x: string]: any; Application: () => void; }
|
||||
>Application : () => void
|
||||
>(function () {var Application = function () { //...};return Application;})() : () => void
|
||||
>(function () {var Application = function () { //...};return Application;}) : () => () => void
|
||||
>function () {var Application = function () { //...};return Application;} : () => () => void
|
||||
|
||||
var Application = function () {
|
||||
>Application : () => void
|
||||
>function () { //...} : () => void
|
||||
|
||||
//...
|
||||
};
|
||||
return Application;
|
||||
>Application : () => void
|
||||
|
||||
})();
|
||||
min.app.Application()
|
||||
>min.app.Application() : void
|
||||
>min.app.Application : () => void
|
||||
>min.app : { [x: string]: any; Application: () => void; }
|
||||
>min : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
|
||||
>app : { [x: string]: any; Application: () => void; }
|
||||
>Application : () => void
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var my = my || {};
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
|
||||
/** @param {number} n */
|
||||
my.method = function(n) {
|
||||
>my.method : Symbol(method, Decl(a.js, 0, 18))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>method : Symbol(method, Decl(a.js, 0, 18))
|
||||
>n : Symbol(n, Decl(a.js, 2, 21))
|
||||
|
||||
return n + 1;
|
||||
>n : Symbol(n, Decl(a.js, 2, 21))
|
||||
}
|
||||
my.number = 1;
|
||||
>my.number : Symbol(number, Decl(a.js, 4, 1))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>number : Symbol(number, Decl(a.js, 4, 1))
|
||||
|
||||
my.object = {};
|
||||
>my.object : Symbol(object, Decl(a.js, 5, 14))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>object : Symbol(object, Decl(a.js, 5, 14))
|
||||
|
||||
my.predicate = my.predicate || {};
|
||||
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
|
||||
my.predicate.query = function () {
|
||||
>my.predicate.query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13))
|
||||
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13))
|
||||
|
||||
var me = this;
|
||||
>me : Symbol(me, Decl(a.js, 9, 7))
|
||||
>this : Symbol(__object, Decl(a.js, 7, 30))
|
||||
|
||||
me.property = false;
|
||||
>me : Symbol(me, Decl(a.js, 9, 7))
|
||||
|
||||
};
|
||||
var q = new my.predicate.query();
|
||||
>q : Symbol(q, Decl(a.js, 12, 3))
|
||||
>my.predicate.query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13))
|
||||
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13))
|
||||
|
||||
my.predicate.query.another = function () {
|
||||
>my.predicate.query.another : Symbol((Anonymous function).another, Decl(a.js, 12, 33))
|
||||
>my.predicate.query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13))
|
||||
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13))
|
||||
>another : Symbol((Anonymous function).another, Decl(a.js, 12, 33))
|
||||
|
||||
return 1;
|
||||
}
|
||||
my.predicate.query.result = 'none'
|
||||
>my.predicate.query.result : Symbol((Anonymous function).result, Decl(a.js, 15, 1))
|
||||
>my.predicate.query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13))
|
||||
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13))
|
||||
>result : Symbol((Anonymous function).result, Decl(a.js, 15, 1))
|
||||
|
||||
/** @param {number} first
|
||||
* @param {number} second
|
||||
*/
|
||||
my.predicate.sort = my.predicate.sort || function (first, second) {
|
||||
>my.predicate.sort : Symbol(sort, Decl(a.js, 16, 34))
|
||||
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>sort : Symbol(sort, Decl(a.js, 16, 34))
|
||||
>my.predicate.sort : Symbol(sort, Decl(a.js, 16, 34))
|
||||
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>sort : Symbol(sort, Decl(a.js, 16, 34))
|
||||
>first : Symbol(first, Decl(a.js, 20, 51))
|
||||
>second : Symbol(second, Decl(a.js, 20, 57))
|
||||
|
||||
return first > second ? first : second;
|
||||
>first : Symbol(first, Decl(a.js, 20, 51))
|
||||
>second : Symbol(second, Decl(a.js, 20, 57))
|
||||
>first : Symbol(first, Decl(a.js, 20, 51))
|
||||
>second : Symbol(second, Decl(a.js, 20, 57))
|
||||
}
|
||||
my.predicate.type = class {
|
||||
>my.predicate.type : Symbol(type, Decl(a.js, 22, 1))
|
||||
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more)
|
||||
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3))
|
||||
>type : Symbol(type, Decl(a.js, 22, 1))
|
||||
|
||||
m() { return 101; }
|
||||
>m : Symbol((Anonymous class).m, Decl(a.js, 23, 27))
|
||||
}
|
||||
|
||||
|
||||
// global-ish prefixes
|
||||
var min = window.min || {};
|
||||
>min : Symbol(min, Decl(a.js, 29, 3))
|
||||
|
||||
min.nest = this.min.nest || function () { };
|
||||
>min.nest : Symbol(nest, Decl(a.js, 29, 27))
|
||||
>min : Symbol(min, Decl(a.js, 29, 3))
|
||||
>nest : Symbol(nest, Decl(a.js, 29, 27))
|
||||
|
||||
min.nest.other = self.min.nest.other || class { };
|
||||
>min.nest.other : Symbol((Anonymous function).other, Decl(a.js, 30, 44))
|
||||
>min.nest : Symbol(nest, Decl(a.js, 29, 27))
|
||||
>min : Symbol(min, Decl(a.js, 29, 3))
|
||||
>nest : Symbol(nest, Decl(a.js, 29, 27))
|
||||
>other : Symbol((Anonymous function).other, Decl(a.js, 30, 44))
|
||||
|
||||
min.property = global.min.property || {};
|
||||
>min.property : Symbol(property, Decl(a.js, 31, 50))
|
||||
>min : Symbol(min, Decl(a.js, 29, 3))
|
||||
>property : Symbol(property, Decl(a.js, 31, 50))
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
=== tests/cases/conformance/salsa/a.js ===
|
||||
var my = my || {};
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>my || {} : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>{} : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
|
||||
/** @param {number} n */
|
||||
my.method = function(n) {
|
||||
>my.method = function(n) { return n + 1;} : (n: number) => number
|
||||
>my.method : (n: number) => number
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>method : (n: number) => number
|
||||
>function(n) { return n + 1;} : (n: number) => number
|
||||
>n : number
|
||||
|
||||
return n + 1;
|
||||
>n + 1 : number
|
||||
>n : number
|
||||
>1 : 1
|
||||
}
|
||||
my.number = 1;
|
||||
>my.number = 1 : 1
|
||||
>my.number : number
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>number : number
|
||||
>1 : 1
|
||||
|
||||
my.object = {};
|
||||
>my.object = {} : { [x: string]: any; }
|
||||
>my.object : { [x: string]: any; }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>object : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; }
|
||||
|
||||
my.predicate = my.predicate || {};
|
||||
>my.predicate = my.predicate || {} : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my.predicate || {} : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>{} : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
|
||||
my.predicate.query = function () {
|
||||
>my.predicate.query = function () { var me = this; me.property = false;} : { (): void; another: () => number; result: string; }
|
||||
>my.predicate.query : { (): void; another: () => number; result: string; }
|
||||
>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>query : { (): void; another: () => number; result: string; }
|
||||
>function () { var me = this; me.property = false;} : { (): void; another: () => number; result: string; }
|
||||
|
||||
var me = this;
|
||||
>me : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>this : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
|
||||
me.property = false;
|
||||
>me.property = false : false
|
||||
>me.property : any
|
||||
>me : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>property : any
|
||||
>false : false
|
||||
|
||||
};
|
||||
var q = new my.predicate.query();
|
||||
>q : any
|
||||
>new my.predicate.query() : any
|
||||
>my.predicate.query : { (): void; another: () => number; result: string; }
|
||||
>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>query : { (): void; another: () => number; result: string; }
|
||||
|
||||
my.predicate.query.another = function () {
|
||||
>my.predicate.query.another = function () { return 1;} : () => number
|
||||
>my.predicate.query.another : () => number
|
||||
>my.predicate.query : { (): void; another: () => number; result: string; }
|
||||
>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>query : { (): void; another: () => number; result: string; }
|
||||
>another : () => number
|
||||
>function () { return 1;} : () => number
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
}
|
||||
my.predicate.query.result = 'none'
|
||||
>my.predicate.query.result = 'none' : "none"
|
||||
>my.predicate.query.result : string
|
||||
>my.predicate.query : { (): void; another: () => number; result: string; }
|
||||
>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>query : { (): void; another: () => number; result: string; }
|
||||
>result : string
|
||||
>'none' : "none"
|
||||
|
||||
/** @param {number} first
|
||||
* @param {number} second
|
||||
*/
|
||||
my.predicate.sort = my.predicate.sort || function (first, second) {
|
||||
>my.predicate.sort = my.predicate.sort || function (first, second) { return first > second ? first : second;} : (first: number, second: number) => number
|
||||
>my.predicate.sort : (first: number, second: number) => number
|
||||
>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>sort : (first: number, second: number) => number
|
||||
>my.predicate.sort || function (first, second) { return first > second ? first : second;} : (first: number, second: number) => number
|
||||
>my.predicate.sort : (first: number, second: number) => number
|
||||
>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>sort : (first: number, second: number) => number
|
||||
>function (first, second) { return first > second ? first : second;} : (first: number, second: number) => number
|
||||
>first : number
|
||||
>second : number
|
||||
|
||||
return first > second ? first : second;
|
||||
>first > second ? first : second : number
|
||||
>first > second : boolean
|
||||
>first : number
|
||||
>second : number
|
||||
>first : number
|
||||
>second : number
|
||||
}
|
||||
my.predicate.type = class {
|
||||
>my.predicate.type = class { m() { return 101; }} : typeof (Anonymous class)
|
||||
>my.predicate.type : typeof (Anonymous class)
|
||||
>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; }
|
||||
>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }
|
||||
>type : typeof (Anonymous class)
|
||||
>class { m() { return 101; }} : typeof (Anonymous class)
|
||||
|
||||
m() { return 101; }
|
||||
>m : () => number
|
||||
>101 : 101
|
||||
}
|
||||
|
||||
|
||||
// global-ish prefixes
|
||||
var min = window.min || {};
|
||||
>min : { [x: string]: any; nest: { (): void; other: typeof (Anonymous class); }; property: { [x: string]: any; }; }
|
||||
>window.min || {} : any
|
||||
>window.min : any
|
||||
>window : any
|
||||
>min : any
|
||||
>{} : { [x: string]: any; nest: { (): void; other: typeof (Anonymous class); }; property: { [x: string]: any; }; }
|
||||
|
||||
min.nest = this.min.nest || function () { };
|
||||
>min.nest = this.min.nest || function () { } : { (): void; other: typeof (Anonymous class); }
|
||||
>min.nest : { (): void; other: typeof (Anonymous class); }
|
||||
>min : { [x: string]: any; nest: { (): void; other: typeof (Anonymous class); }; property: { [x: string]: any; }; }
|
||||
>nest : { (): void; other: typeof (Anonymous class); }
|
||||
>this.min.nest || function () { } : { (): void; other: typeof (Anonymous class); }
|
||||
>this.min.nest : any
|
||||
>this.min : any
|
||||
>this : any
|
||||
>min : any
|
||||
>nest : any
|
||||
>function () { } : { (): void; other: typeof (Anonymous class); }
|
||||
|
||||
min.nest.other = self.min.nest.other || class { };
|
||||
>min.nest.other = self.min.nest.other || class { } : typeof (Anonymous class)
|
||||
>min.nest.other : typeof (Anonymous class)
|
||||
>min.nest : { (): void; other: typeof (Anonymous class); }
|
||||
>min : { [x: string]: any; nest: { (): void; other: typeof (Anonymous class); }; property: { [x: string]: any; }; }
|
||||
>nest : { (): void; other: typeof (Anonymous class); }
|
||||
>other : typeof (Anonymous class)
|
||||
>self.min.nest.other || class { } : typeof (Anonymous class)
|
||||
>self.min.nest.other : any
|
||||
>self.min.nest : any
|
||||
>self.min : any
|
||||
>self : any
|
||||
>min : any
|
||||
>nest : any
|
||||
>other : any
|
||||
>class { } : typeof (Anonymous class)
|
||||
|
||||
min.property = global.min.property || {};
|
||||
>min.property = global.min.property || {} : { [x: string]: any; }
|
||||
>min.property : { [x: string]: any; }
|
||||
>min : { [x: string]: any; nest: { (): void; other: typeof (Anonymous class); }; property: { [x: string]: any; }; }
|
||||
>property : { [x: string]: any; }
|
||||
>global.min.property || {} : { [x: string]: any; }
|
||||
>global.min.property : any
|
||||
>global.min : any
|
||||
>global : any
|
||||
>min : any
|
||||
>property : any
|
||||
>{} : { [x: string]: any; }
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
=== tests/cases/conformance/salsa/index.js ===
|
||||
Common.Item = class I {}
|
||||
>Common.Item : Symbol(Common.Item, Decl(index.js, 0, 0))
|
||||
>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3))
|
||||
>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3), Decl(roots.js, 0, 12))
|
||||
>Item : Symbol(Common.Item, Decl(index.js, 0, 0))
|
||||
>I : Symbol(I, Decl(index.js, 0, 13))
|
||||
|
||||
Common.Object = class extends Common.Item {}
|
||||
>Common.Object : Symbol(Common.Object, Decl(index.js, 0, 24))
|
||||
>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3))
|
||||
>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3), Decl(roots.js, 0, 12))
|
||||
>Object : Symbol(Common.Object, Decl(index.js, 0, 24))
|
||||
>Common.Item : Symbol(Common.Item, Decl(index.js, 0, 0))
|
||||
>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3))
|
||||
>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3), Decl(roots.js, 0, 12))
|
||||
>Item : Symbol(Common.Item, Decl(index.js, 0, 0))
|
||||
|
||||
Workspace.Object = class extends Common.Object {}
|
||||
>Workspace.Object : Symbol(Workspace.Object, Decl(index.js, 1, 44))
|
||||
>Workspace : Symbol(Workspace, Decl(index.js, 1, 44), Decl(roots.js, 1, 3))
|
||||
>Workspace : Symbol(Workspace, Decl(index.js, 1, 44), Decl(roots.js, 1, 3), Decl(roots.js, 1, 15))
|
||||
>Object : Symbol(Workspace.Object, Decl(index.js, 1, 44))
|
||||
>Common.Object : Symbol(Common.Object, Decl(index.js, 0, 24))
|
||||
>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3))
|
||||
>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3), Decl(roots.js, 0, 12))
|
||||
>Object : Symbol(Common.Object, Decl(index.js, 0, 24))
|
||||
|
||||
/** @type {Workspace.Object} */
|
||||
@@ -27,8 +27,8 @@ var am;
|
||||
|
||||
=== tests/cases/conformance/salsa/roots.js ===
|
||||
var Common = {};
|
||||
>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3))
|
||||
>Common : Symbol(Common, Decl(index.js, 0, 0), Decl(roots.js, 0, 3), Decl(roots.js, 0, 12))
|
||||
|
||||
var Workspace = {};
|
||||
>Workspace : Symbol(Workspace, Decl(index.js, 1, 44), Decl(roots.js, 1, 3))
|
||||
>Workspace : Symbol(Workspace, Decl(index.js, 1, 44), Decl(roots.js, 1, 3), Decl(roots.js, 1, 15))
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ var am;
|
||||
=== tests/cases/conformance/salsa/roots.js ===
|
||||
var Common = {};
|
||||
>Common : typeof Common
|
||||
>{} : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; Item: typeof I; Object: typeof (Anonymous class); }
|
||||
|
||||
var Workspace = {};
|
||||
>Workspace : typeof Workspace
|
||||
>{} : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; Object: typeof (Anonymous class); }
|
||||
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
// this is a javascript file...
|
||||
|
||||
export const Adapter = {};
|
||||
>Adapter : Symbol(Adapter, Decl(a.js, 2, 12), Decl(a.js, 4, 18))
|
||||
>Adapter : Symbol(Adapter, Decl(a.js, 2, 12), Decl(a.js, 2, 26), Decl(a.js, 4, 18))
|
||||
|
||||
Adapter.prop = {};
|
||||
>Adapter : Symbol(Adapter, Decl(a.js, 2, 12), Decl(a.js, 4, 18))
|
||||
>Adapter.prop : Symbol(prop, Decl(a.js, 2, 26))
|
||||
>Adapter : Symbol(Adapter, Decl(a.js, 2, 12), Decl(a.js, 2, 26), Decl(a.js, 4, 18))
|
||||
>prop : Symbol(prop, Decl(a.js, 2, 26))
|
||||
|
||||
// comment this out, and it works
|
||||
Adapter.asyncMethod = function() {}
|
||||
>Adapter : Symbol(Adapter, Decl(a.js, 2, 12), Decl(a.js, 4, 18))
|
||||
>Adapter.asyncMethod : Symbol(asyncMethod, Decl(a.js, 4, 18))
|
||||
>Adapter : Symbol(Adapter, Decl(a.js, 2, 12), Decl(a.js, 2, 26), Decl(a.js, 4, 18))
|
||||
>asyncMethod : Symbol(asyncMethod, Decl(a.js, 4, 18))
|
||||
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
// this is a javascript file...
|
||||
|
||||
export const Adapter = {};
|
||||
>Adapter : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; }
|
||||
>Adapter : { [x: string]: any; prop: { [x: string]: any; }; asyncMethod: () => void; }
|
||||
>{} : { [x: string]: any; prop: { [x: string]: any; }; asyncMethod: () => void; }
|
||||
|
||||
Adapter.prop = {};
|
||||
>Adapter.prop = {} : {}
|
||||
>Adapter.prop : any
|
||||
>Adapter : { [x: string]: any; }
|
||||
>prop : any
|
||||
>{} : {}
|
||||
>Adapter.prop = {} : { [x: string]: any; }
|
||||
>Adapter.prop : { [x: string]: any; }
|
||||
>Adapter : { [x: string]: any; prop: { [x: string]: any; }; asyncMethod: () => void; }
|
||||
>prop : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; }
|
||||
|
||||
// comment this out, and it works
|
||||
Adapter.asyncMethod = function() {}
|
||||
>Adapter.asyncMethod = function() {} : () => void
|
||||
>Adapter.asyncMethod : any
|
||||
>Adapter : { [x: string]: any; }
|
||||
>asyncMethod : any
|
||||
>Adapter.asyncMethod : () => void
|
||||
>Adapter : { [x: string]: any; prop: { [x: string]: any; }; asyncMethod: () => void; }
|
||||
>asyncMethod : () => void
|
||||
>function() {} : () => void
|
||||
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
tests/cases/compiler/uniqueSymbolAllowsIndexInObjectWithIndexSignature.ts(10,5): error TS2322: Type '{ [SYM]: "str"; }' is not assignable to type 'I'.
|
||||
Types of property '[SYM]' are incompatible.
|
||||
Type '"str"' is not assignable to type '"sym"'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/uniqueSymbolAllowsIndexInObjectWithIndexSignature.ts (1 errors) ====
|
||||
// https://github.com/Microsoft/TypeScript/issues/21962
|
||||
export const SYM = Symbol('a unique symbol');
|
||||
|
||||
export interface I {
|
||||
[SYM]: 'sym';
|
||||
[x: string]: 'str';
|
||||
}
|
||||
|
||||
let a: I = {[SYM]: 'sym'}; // Expect ok
|
||||
let b: I = {[SYM]: 'str'}; // Expect error
|
||||
~
|
||||
!!! error TS2322: Type '{ [SYM]: "str"; }' is not assignable to type 'I'.
|
||||
!!! error TS2322: Types of property '[SYM]' are incompatible.
|
||||
!!! error TS2322: Type '"str"' is not assignable to type '"sym"'.
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
//// [uniqueSymbolAllowsIndexInObjectWithIndexSignature.ts]
|
||||
// https://github.com/Microsoft/TypeScript/issues/21962
|
||||
export const SYM = Symbol('a unique symbol');
|
||||
|
||||
export interface I {
|
||||
[SYM]: 'sym';
|
||||
[x: string]: 'str';
|
||||
}
|
||||
|
||||
let a: I = {[SYM]: 'sym'}; // Expect ok
|
||||
let b: I = {[SYM]: 'str'}; // Expect error
|
||||
|
||||
|
||||
//// [uniqueSymbolAllowsIndexInObjectWithIndexSignature.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
// https://github.com/Microsoft/TypeScript/issues/21962
|
||||
exports.SYM = Symbol('a unique symbol');
|
||||
var a = (_a = {}, _a[exports.SYM] = 'sym', _a); // Expect ok
|
||||
var b = (_b = {}, _b[exports.SYM] = 'str', _b); // Expect error
|
||||
var _a, _b;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user