Merge pull request #20198 from Microsoft/jsdoc-values-as-namespaces

Jsdoc values as namespaces
This commit is contained in:
Nathan Shively-Sanders 2017-11-30 12:56:11 -08:00 committed by GitHub
commit 2ec2238c1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 7031 additions and 29942 deletions

View file

@ -2006,6 +2006,9 @@ namespace ts {
if (currentFlow && isNarrowableReference(<Expression>node)) {
node.flowNode = currentFlow;
}
if (isSpecialPropertyDeclaration(node as PropertyAccessExpression)) {
bindSpecialPropertyDeclaration(node as PropertyAccessExpression);
}
break;
case SyntaxKind.BinaryExpression:
const specialKind = getSpecialPropertyAssignmentKind(node as BinaryExpression);
@ -2314,7 +2317,7 @@ namespace ts {
declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule, SymbolFlags.None);
}
function bindThisPropertyAssignment(node: BinaryExpression) {
function bindThisPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) {
Debug.assert(isInJavaScriptFile(node));
const container = getThisContainer(node, /*includeArrowFunctions*/ false);
switch (container.kind) {
@ -2340,8 +2343,19 @@ 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);
}
}
function bindPrototypePropertyAssignment(node: BinaryExpression) {
// We saw a node of the form 'x.prototype.y = z'. Declare a 'member' y on x if x was a function.
// 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
@ -2357,24 +2371,27 @@ namespace ts {
bindPropertyAssignment(constructorFunction.escapedText, leftSideOfAssignment, /*isPrototypeProperty*/ true);
}
function bindStaticPropertyAssignment(node: BinaryExpression) {
// We saw a node of the form 'x.y = z'. Declare a 'member' y on x if x was a function.
// Look up the function in the local scope, since prototype assignments should
/**
* 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;
*/
function bindStaticPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) {
// Look up the function in the local scope, since static assignments should
// follow the function declaration
const leftSideOfAssignment = node.left as PropertyAccessExpression;
const leftSideOfAssignment = node.kind === SyntaxKind.PropertyAccessExpression ? node : node.left as PropertyAccessExpression;
const target = leftSideOfAssignment.expression;
if (isIdentifier(target)) {
// Fix up parent pointers since we're going to use these nodes before we bind into them
leftSideOfAssignment.parent = node;
target.parent = leftSideOfAssignment;
if (node.kind === SyntaxKind.BinaryExpression) {
leftSideOfAssignment.parent = node;
}
if (isNameOfExportsOrModuleExportsAliasDeclaration(target)) {
// This can be an alias for the 'exports' or 'module.exports' names, e.g.
// var util = module.exports;
// util.property = function ...
bindExportsPropertyAssignment(node);
bindExportsPropertyAssignment(node as BinaryExpression);
}
else {
bindPropertyAssignment(target.escapedText, leftSideOfAssignment, /*isPrototypeProperty*/ false);
@ -2383,17 +2400,41 @@ namespace ts {
}
function lookupSymbolForName(name: __String) {
return (container.symbol && container.symbol.exports && container.symbol.exports.get(name)) || (container.locals && container.locals.get(name));
const local = container.locals && container.locals.get(name);
if (local) {
return local.exportSymbol || local;
}
return container.symbol && container.symbol.exports && container.symbol.exports.get(name);
}
function bindPropertyAssignment(functionName: __String, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) {
let targetSymbol = lookupSymbolForName(functionName);
if (targetSymbol && isDeclarationOfFunctionOrClassExpression(targetSymbol)) {
targetSymbol = (targetSymbol.valueDeclaration as VariableDeclaration).initializer.symbol;
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;
}
if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class))) {
else {
isLegalPosition = propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
}
if (!isPrototypeProperty && (!targetSymbol || !(targetSymbol.flags & SymbolFlags.Namespace)) && isLegalPosition) {
Debug.assert(isIdentifier(propertyAccess.expression));
const identifier = propertyAccess.expression as Identifier;
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);
}
}
if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.NamespaceModule))) {
return;
}
@ -2403,7 +2444,7 @@ namespace ts {
(targetSymbol.exports || (targetSymbol.exports = createSymbolTable()));
// Declare the method/property
declareSymbol(symbolTable, targetSymbol, propertyAccessExpression, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
declareSymbol(symbolTable, targetSymbol, propertyAccess, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
}
function bindCallExpression(node: CallExpression) {

View file

@ -632,7 +632,9 @@ namespace ts {
}
function mergeSymbol(target: Symbol, source: Symbol) {
if (!(target.flags & getExcludedSymbolFlags(source.flags))) {
if (!(target.flags & getExcludedSymbolFlags(source.flags)) ||
source.flags & SymbolFlags.JSContainer || 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
target.constEnumOnlyModule = false;
@ -1735,13 +1737,16 @@ namespace ts {
return undefined;
}
const right = name.kind === SyntaxKind.QualifiedName ? name.right : name.name;
const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors, /*dontResolveAlias*/ false, location);
let namespace = resolveEntityName(left, SymbolFlags.Namespace, 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);
}
symbol = getSymbol(getExportsOfSymbol(namespace), right.escapedText, meaning);
if (!symbol) {
if (!ignoreErrors) {
@ -4478,7 +4483,9 @@ namespace ts {
if (!jsDocType) {
jsDocType = declarationType;
}
else if (jsDocType !== unknownType && declarationType !== unknownType && !isTypeIdenticalTo(jsDocType, declarationType)) {
else if (jsDocType !== unknownType && declarationType !== unknownType &&
!isTypeIdenticalTo(jsDocType, declarationType) &&
!(symbol.flags & SymbolFlags.JSContainer)) {
errorNextVariableOrPropertyDeclarationMustHaveSameType(jsDocType, declaration, declarationType);
}
}
@ -21443,7 +21450,10 @@ namespace ts {
// Node is a secondary declaration, check that type is identical to primary declaration and check that
// initializer is consistent with type associated with the node
const declarationType = convertAutoToAny(getWidenedTypeForVariableLikeDeclaration(node));
if (type !== unknownType && declarationType !== unknownType && !isTypeIdenticalTo(type, declarationType)) {
if (type !== unknownType && declarationType !== unknownType &&
!isTypeIdenticalTo(type, declarationType) &&
!(symbol.flags & SymbolFlags.JSContainer)) {
errorNextVariableOrPropertyDeclarationMustHaveSameType(type, node, declarationType);
}
if (node.initializer) {

View file

@ -633,7 +633,7 @@ namespace ts {
Node, // Unique name based on the node in the 'original' property.
}
export interface Identifier extends PrimaryExpression {
export interface Identifier extends PrimaryExpression, Declaration {
kind: SyntaxKind.Identifier;
/**
* Prefer to use `id.unescapedText`. (Note: This is available only in services, not internally to the TypeScript compiler.)
@ -3062,6 +3062,7 @@ namespace ts {
ExportStar = 1 << 23, // Export * declaration
Optional = 1 << 24, // Optional property
Transient = 1 << 25, // Transient symbol (created during type check)
JSContainer = 1 << 26, // Contains Javascript special declarations
/* @internal */
All = FunctionScopedVariable | BlockScopedVariable | Property | EnumMember | Function | Class | Interface | ConstEnum | RegularEnum | ValueModule | NamespaceModule | TypeLiteral

View file

@ -1446,7 +1446,7 @@ namespace ts {
}
/**
* Returns true if the node is a variable declaration whose initializer is a function expression.
* 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.
*/
export function isDeclarationOfFunctionOrClassExpression(s: Symbol) {
@ -1519,6 +1519,12 @@ namespace ts {
return SpecialPropertyAssignmentKind.None;
}
export function isSpecialPropertyDeclaration(expr: ts.PropertyAccessExpression): boolean {
return isInJavaScriptFile(expr) &&
expr.parent && expr.parent.kind === SyntaxKind.ExpressionStatement &&
!!getJSDocTypeTag(expr.parent);
}
export function getExternalModuleName(node: Node): Expression {
if (node.kind === SyntaxKind.ImportDeclaration) {
return (<ImportDeclaration>node).moduleSpecifier;
@ -1636,7 +1642,8 @@ namespace ts {
if (parent && parent.parent && parent.parent.parent && getSingleInitializerOfVariableStatement(parent.parent.parent, node)) {
getJSDocCommentsAndTagsWorker(parent.parent.parent);
}
if (isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) !== SpecialPropertyAssignmentKind.None) {
if (isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) !== SpecialPropertyAssignmentKind.None ||
node.kind === SyntaxKind.PropertyAccessExpression && node.parent && node.parent.kind === SyntaxKind.ExpressionStatement) {
getJSDocCommentsAndTagsWorker(parent);
}
@ -4203,6 +4210,8 @@ namespace ts {
return undefined;
}
switch (declaration.kind) {
case SyntaxKind.Identifier:
return declaration as Identifier;
case SyntaxKind.JSDocPropertyTag:
case SyntaxKind.JSDocParameterTag: {
const { name } = declaration as JSDocPropertyLikeTag;

View file

@ -416,6 +416,7 @@ namespace ts {
_updateExpressionBrand: any;
_unaryExpressionBrand: any;
_expressionBrand: any;
_declarationBrand: any;
/*@internal*/typeArguments: NodeArray<TypeNode>;
constructor(_kind: SyntaxKind.Identifier, pos: number, end: number) {
super(pos, end);

View file

@ -472,7 +472,7 @@ declare namespace ts {
type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
type Modifier = Token<SyntaxKind.AbstractKeyword> | Token<SyntaxKind.AsyncKeyword> | Token<SyntaxKind.ConstKeyword> | Token<SyntaxKind.DeclareKeyword> | Token<SyntaxKind.DefaultKeyword> | Token<SyntaxKind.ExportKeyword> | Token<SyntaxKind.PublicKeyword> | Token<SyntaxKind.PrivateKeyword> | Token<SyntaxKind.ProtectedKeyword> | Token<SyntaxKind.ReadonlyKeyword> | Token<SyntaxKind.StaticKeyword>;
type ModifiersArray = NodeArray<Modifier>;
interface Identifier extends PrimaryExpression {
interface Identifier extends PrimaryExpression, Declaration {
kind: SyntaxKind.Identifier;
/**
* Prefer to use `id.unescapedText`. (Note: This is available only in services, not internally to the TypeScript compiler.)
@ -1903,6 +1903,7 @@ declare namespace ts {
ExportStar = 8388608,
Optional = 16777216,
Transient = 33554432,
JSContainer = 67108864,
Enum = 384,
Variable = 3,
Value = 107455,

View file

@ -472,7 +472,7 @@ declare namespace ts {
type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
type Modifier = Token<SyntaxKind.AbstractKeyword> | Token<SyntaxKind.AsyncKeyword> | Token<SyntaxKind.ConstKeyword> | Token<SyntaxKind.DeclareKeyword> | Token<SyntaxKind.DefaultKeyword> | Token<SyntaxKind.ExportKeyword> | Token<SyntaxKind.PublicKeyword> | Token<SyntaxKind.PrivateKeyword> | Token<SyntaxKind.ProtectedKeyword> | Token<SyntaxKind.ReadonlyKeyword> | Token<SyntaxKind.StaticKeyword>;
type ModifiersArray = NodeArray<Modifier>;
interface Identifier extends PrimaryExpression {
interface Identifier extends PrimaryExpression, Declaration {
kind: SyntaxKind.Identifier;
/**
* Prefer to use `id.unescapedText`. (Note: This is available only in services, not internally to the TypeScript compiler.)
@ -1903,6 +1903,7 @@ declare namespace ts {
ExportStar = 8388608,
Optional = 16777216,
Transient = 33554432,
JSContainer = 67108864,
Enum = 384,
Variable = 3,
Value = 107455,

View file

@ -0,0 +1,41 @@
=== tests/cases/conformance/salsa/a.js ===
var Outer = class O {
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 2, 1))
>O : Symbol(O, Decl(a.js, 0, 11))
m(x, y) { }
>m : Symbol(O.m, Decl(a.js, 0, 21))
>x : Symbol(x, Decl(a.js, 1, 6))
>y : Symbol(y, Decl(a.js, 1, 8))
}
Outer.Inner = class I {
>Outer.Inner : Symbol(O.Inner, Decl(a.js, 2, 1))
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 2, 1))
>Inner : Symbol(O.Inner, Decl(a.js, 2, 1))
>I : Symbol(I, Decl(a.js, 3, 13))
n(a, b) { }
>n : Symbol(I.n, Decl(a.js, 3, 23))
>a : Symbol(a, Decl(a.js, 4, 6))
>b : Symbol(b, Decl(a.js, 4, 8))
}
/** @type {Outer} */
var si
>si : Symbol(si, Decl(a.js, 8, 3))
si.m
>si.m : Symbol(O.m, Decl(a.js, 0, 21))
>si : Symbol(si, Decl(a.js, 8, 3))
>m : Symbol(O.m, Decl(a.js, 0, 21))
/** @type {Outer.Inner} */
var oi
>oi : Symbol(oi, Decl(a.js, 11, 3))
oi.n
>oi.n : Symbol(I.n, Decl(a.js, 3, 23))
>oi : Symbol(oi, Decl(a.js, 11, 3))
>n : Symbol(I.n, Decl(a.js, 3, 23))

View file

@ -0,0 +1,44 @@
=== tests/cases/conformance/salsa/a.js ===
var Outer = class O {
>Outer : typeof O
>class O { m(x, y) { }} : typeof O
>O : typeof O
m(x, y) { }
>m : (x: any, y: any) => void
>x : any
>y : any
}
Outer.Inner = class I {
>Outer.Inner = class I { n(a, b) { }} : typeof I
>Outer.Inner : typeof I
>Outer : typeof O
>Inner : typeof I
>class I { n(a, b) { }} : typeof I
>I : typeof I
n(a, b) { }
>n : (a: any, b: any) => void
>a : any
>b : any
}
/** @type {Outer} */
var si
>si : O
si.m
>si.m : (x: any, y: any) => void
>si : O
>m : (x: any, y: any) => void
/** @type {Outer.Inner} */
var oi
>oi : I
oi.n
>oi.n : (a: any, b: any) => void
>oi : I
>n : (a: any, b: any) => void

View file

@ -0,0 +1,38 @@
=== tests/cases/conformance/salsa/a.js ===
function Outer() {
>Outer : Symbol(Outer, Decl(a.js, 0, 0), Decl(a.js, 2, 1))
this.y = 2
>y : Symbol(Outer.y, Decl(a.js, 0, 18))
}
Outer.Inner = class I {
>Outer.Inner : Symbol(Outer.Inner, Decl(a.js, 2, 1))
>Outer : Symbol(Outer, Decl(a.js, 0, 0), Decl(a.js, 2, 1))
>Inner : Symbol(Outer.Inner, Decl(a.js, 2, 1))
>I : Symbol(I, Decl(a.js, 3, 13))
constructor() {
this.x = 1
>this.x : Symbol(I.x, Decl(a.js, 4, 19))
>this : Symbol(I, Decl(a.js, 3, 13))
>x : Symbol(I.x, Decl(a.js, 4, 19))
}
}
/** @type {Outer} */
var ok
>ok : Symbol(ok, Decl(a.js, 9, 3))
ok.y
>ok.y : Symbol(Outer.y, Decl(a.js, 0, 18))
>ok : Symbol(ok, Decl(a.js, 9, 3))
>y : Symbol(Outer.y, Decl(a.js, 0, 18))
/** @type {Outer.Inner} */
var oc
>oc : Symbol(oc, Decl(a.js, 12, 3))
oc.x
>oc.x : Symbol(I.x, Decl(a.js, 4, 19))
>oc : Symbol(oc, Decl(a.js, 12, 3))
>x : Symbol(I.x, Decl(a.js, 4, 19))

View file

@ -0,0 +1,46 @@
=== tests/cases/conformance/salsa/a.js ===
function Outer() {
>Outer : typeof Outer
this.y = 2
>this.y = 2 : 2
>this.y : any
>this : any
>y : any
>2 : 2
}
Outer.Inner = class I {
>Outer.Inner = class I { constructor() { this.x = 1 }} : typeof I
>Outer.Inner : typeof I
>Outer : typeof Outer
>Inner : typeof I
>class I { constructor() { this.x = 1 }} : typeof I
>I : typeof I
constructor() {
this.x = 1
>this.x = 1 : 1
>this.x : number
>this : this
>x : number
>1 : 1
}
}
/** @type {Outer} */
var ok
>ok : typeof Outer
ok.y
>ok.y : number
>ok : typeof Outer
>y : number
/** @type {Outer.Inner} */
var oc
>oc : I
oc.x
>oc.x : number
>oc : I
>x : number

View file

@ -0,0 +1,39 @@
=== tests/cases/conformance/salsa/a.js ===
var Outer = function O() {
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 2, 1))
>O : Symbol(O, Decl(a.js, 0, 11))
this.y = 2
>y : Symbol(O.y, Decl(a.js, 0, 26))
}
Outer.Inner = class I {
>Outer.Inner : Symbol(O.Inner, Decl(a.js, 2, 1))
>Outer : Symbol(Outer, Decl(a.js, 0, 3), Decl(a.js, 2, 1))
>Inner : Symbol(O.Inner, Decl(a.js, 2, 1))
>I : Symbol(I, Decl(a.js, 3, 13))
constructor() {
this.x = 1
>this.x : Symbol(I.x, Decl(a.js, 4, 19))
>this : Symbol(I, Decl(a.js, 3, 13))
>x : Symbol(I.x, Decl(a.js, 4, 19))
}
}
/** @type {Outer} */
var ja
>ja : Symbol(ja, Decl(a.js, 9, 3))
ja.y
>ja.y : Symbol(O.y, Decl(a.js, 0, 26))
>ja : Symbol(ja, Decl(a.js, 9, 3))
>y : Symbol(O.y, Decl(a.js, 0, 26))
/** @type {Outer.Inner} */
var da
>da : Symbol(da, Decl(a.js, 12, 3))
da.x
>da.x : Symbol(I.x, Decl(a.js, 4, 19))
>da : Symbol(da, Decl(a.js, 12, 3))
>x : Symbol(I.x, Decl(a.js, 4, 19))

View file

@ -0,0 +1,48 @@
=== tests/cases/conformance/salsa/a.js ===
var Outer = function O() {
>Outer : { (): void; Inner: typeof I; }
>function O() { this.y = 2} : { (): void; Inner: typeof I; }
>O : { (): void; Inner: typeof I; }
this.y = 2
>this.y = 2 : 2
>this.y : any
>this : any
>y : any
>2 : 2
}
Outer.Inner = class I {
>Outer.Inner = class I { constructor() { this.x = 1 }} : typeof I
>Outer.Inner : typeof I
>Outer : { (): void; Inner: typeof I; }
>Inner : typeof I
>class I { constructor() { this.x = 1 }} : typeof I
>I : typeof I
constructor() {
this.x = 1
>this.x = 1 : 1
>this.x : number
>this : this
>x : number
>1 : 1
}
}
/** @type {Outer} */
var ja
>ja : { y: number; }
ja.y
>ja.y : number
>ja : { y: number; }
>y : number
/** @type {Outer.Inner} */
var da
>da : I
da.x
>da.x : number
>da : I
>x : number

View file

@ -0,0 +1,27 @@
=== tests/cases/conformance/salsa/def.js ===
var Outer = {};
>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(a.js, 0, 0))
=== tests/cases/conformance/salsa/a.js ===
Outer.Inner = class {
>Outer : Symbol(Outer, Decl(def.js, 0, 3), Decl(a.js, 0, 0))
constructor() {
/** @type {number} */
this.y = 12
>this.y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))
>this : Symbol((Anonymous class), Decl(a.js, 0, 13))
>y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))
}
}
=== tests/cases/conformance/salsa/b.js ===
/** @type {Outer.Inner} */
var x;
>x : Symbol(x, Decl(b.js, 1, 3))
x.y
>x.y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))
>x : Symbol(x, Decl(b.js, 1, 3))
>y : Symbol((Anonymous class).y, Decl(a.js, 1, 19))

View file

@ -0,0 +1,34 @@
=== tests/cases/conformance/salsa/def.js ===
var Outer = {};
>Outer : { [x: string]: any; }
>{} : { [x: string]: any; }
=== 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
>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
}
}
=== tests/cases/conformance/salsa/b.js ===
/** @type {Outer.Inner} */
var x;
>x : (Anonymous class)
x.y
>x.y : number
>x : (Anonymous class)
>y : number

View file

@ -0,0 +1,28 @@
=== tests/cases/conformance/salsa/a.js ===
export default function MyClass() {
>MyClass : Symbol(MyClass, Decl(a.js, 0, 0), Decl(a.js, 1, 1))
}
MyClass.bar = class C {
>MyClass.bar : Symbol(MyClass.bar, Decl(a.js, 1, 1))
>MyClass : Symbol(MyClass, Decl(a.js, 0, 0), Decl(a.js, 1, 1))
>bar : Symbol(MyClass.bar, Decl(a.js, 1, 1))
>C : Symbol(C, Decl(a.js, 2, 13))
}
MyClass.bar
>MyClass.bar : Symbol(MyClass.bar, Decl(a.js, 1, 1))
>MyClass : Symbol(MyClass, Decl(a.js, 0, 0), Decl(a.js, 1, 1))
>bar : Symbol(MyClass.bar, Decl(a.js, 1, 1))
=== tests/cases/conformance/salsa/b.js ===
import MC from './a'
>MC : Symbol(MC, Decl(b.js, 0, 6))
MC.bar
>MC.bar : Symbol(MC.bar, Decl(a.js, 1, 1))
>MC : Symbol(MC, Decl(b.js, 0, 6))
>bar : Symbol(MC.bar, Decl(a.js, 1, 1))
/** @type {MC.bar} */
var x
>x : Symbol(x, Decl(b.js, 3, 3))

View file

@ -0,0 +1,30 @@
=== tests/cases/conformance/salsa/a.js ===
export default function MyClass() {
>MyClass : typeof MyClass
}
MyClass.bar = class C {
>MyClass.bar = class C {} : typeof C
>MyClass.bar : typeof C
>MyClass : typeof MyClass
>bar : typeof C
>class C {} : typeof C
>C : typeof C
}
MyClass.bar
>MyClass.bar : typeof C
>MyClass : typeof MyClass
>bar : typeof C
=== tests/cases/conformance/salsa/b.js ===
import MC from './a'
>MC : typeof MC
MC.bar
>MC.bar : typeof C
>MC : typeof MC
>bar : typeof C
/** @type {MC.bar} */
var x
>x : C

View file

@ -0,0 +1,35 @@
=== tests/cases/conformance/salsa/def.js ===
class Outer {}
>Outer : Symbol(Outer, Decl(def.js, 0, 0), Decl(a.js, 0, 0))
=== tests/cases/conformance/salsa/a.js ===
Outer.Inner = class I {
>Outer.Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0))
>Outer : Symbol(Outer, Decl(def.js, 0, 0), Decl(a.js, 0, 0))
>Inner : Symbol(Outer.Inner, Decl(a.js, 0, 0))
>I : Symbol(I, Decl(a.js, 0, 13))
messages() { return [] }
>messages : Symbol(I.messages, Decl(a.js, 0, 23))
}
/** @type {!Outer.Inner} */
Outer.i
>Outer.i : Symbol(Outer.i, Decl(a.js, 2, 1))
>Outer : Symbol(Outer, Decl(def.js, 0, 0), Decl(a.js, 0, 0))
>i : Symbol(Outer.i, Decl(a.js, 2, 1))
=== tests/cases/conformance/salsa/b.js ===
var msgs = Outer.i.messages()
>msgs : Symbol(msgs, Decl(b.js, 0, 3))
>Outer.i.messages : Symbol(I.messages, Decl(a.js, 0, 23))
>Outer.i : Symbol(Outer.i, Decl(a.js, 2, 1))
>Outer : Symbol(Outer, Decl(def.js, 0, 0), Decl(a.js, 0, 0))
>i : Symbol(Outer.i, Decl(a.js, 2, 1))
>messages : Symbol(I.messages, Decl(a.js, 0, 23))
/** @param {Outer.Inner} inner */
function x(inner) {
>x : Symbol(x, Decl(b.js, 0, 29))
>inner : Symbol(inner, Decl(b.js, 3, 11))
}

View file

@ -0,0 +1,39 @@
=== tests/cases/conformance/salsa/def.js ===
class Outer {}
>Outer : Outer
=== tests/cases/conformance/salsa/a.js ===
Outer.Inner = class I {
>Outer.Inner = class I { messages() { return [] }} : typeof I
>Outer.Inner : typeof I
>Outer : typeof Outer
>Inner : typeof I
>class I { messages() { return [] }} : typeof I
>I : typeof I
messages() { return [] }
>messages : () => any[]
>[] : undefined[]
}
/** @type {!Outer.Inner} */
Outer.i
>Outer.i : I
>Outer : typeof Outer
>i : I
=== tests/cases/conformance/salsa/b.js ===
var msgs = Outer.i.messages()
>msgs : any[]
>Outer.i.messages() : any[]
>Outer.i.messages : () => any[]
>Outer.i : I
>Outer : typeof Outer
>i : I
>messages : () => any[]
/** @param {Outer.Inner} inner */
function x(inner) {
>x : (inner: I) => void
>inner : I
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @Filename: a.js
var Outer = class O {
m(x, y) { }
}
Outer.Inner = class I {
n(a, b) { }
}
/** @type {Outer} */
var si
si.m
/** @type {Outer.Inner} */
var oi
oi.n

View file

@ -0,0 +1,18 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @Filename: a.js
function Outer() {
this.y = 2
}
Outer.Inner = class I {
constructor() {
this.x = 1
}
}
/** @type {Outer} */
var ok
ok.y
/** @type {Outer.Inner} */
var oc
oc.x

View file

@ -0,0 +1,18 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @Filename: a.js
var Outer = function O() {
this.y = 2
}
Outer.Inner = class I {
constructor() {
this.x = 1
}
}
/** @type {Outer} */
var ja
ja.y
/** @type {Outer.Inner} */
var da
da.x

View file

@ -0,0 +1,19 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @Filename: def.js
var Outer = {};
// @Filename: a.js
Outer.Inner = class {
constructor() {
/** @type {number} */
this.y = 12
}
}
// @Filename: b.js
/** @type {Outer.Inner} */
var x;
x.y

View file

@ -0,0 +1,16 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @Filename: a.js
// @target: es6
export default function MyClass() {
}
MyClass.bar = class C {
}
MyClass.bar
// @Filename: b.js
import MC from './a'
MC.bar
/** @type {MC.bar} */
var x

View file

@ -0,0 +1,20 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @target: es6
// @Filename: def.js
class Outer {}
// @Filename: a.js
Outer.Inner = class I {
messages() { return [] }
}
/** @type {!Outer.Inner} */
Outer.i
// @Filename: b.js
var msgs = Outer.i.messages()
/** @param {Outer.Inner} inner */
function x(inner) {
}

View file

@ -0,0 +1,78 @@
var Accessibility = {};
var AccessibilityTestRunner = {};
var Animation = {};
var ApplicationTestRunner = {};
var Audits = {};
var Audits2 = {};
var AuditsTestRunner = {};
var Bindings = {};
var BindingsTestRunner = {};
var CPUProfilerTestRunner = {};
var Changes = {};
var CmModes = {};
var ColorPicker = {};
var Common = {};
var Components = {};
var ConsoleCounters = {};
var ConsoleModel = {};
var ConsoleTestRunner = {};
var CookieTable = {};
var Coverage = {};
var CoverageTestRunner = {};
var DataGrid = {};
var DataGridTestRunner = {};
var DeviceModeTestRunner = {};
var Devices = {};
var Diff = {};
var Elements = {};
var ElementsTestRunner = {};
var Emulation = {};
var EventListeners = {}
var Extensions = {};
var ExtensionsTestRunner = {};
var Formatter = {};
var FormatterWorker = {};
var HARImporter = {};
var HeapProfilerTestRunner = {};
var HeapSnapshotModel = {};
var HeapSnapshotWorker = {};
var Help = {};
var Host = {};
var InlineEditor = {};
var LayerViewer = {};
var Layers = {};
var LayersTestRunner = {};
var Main = {};
var MobileThrottling = {};
var Network = {};
var NetworkLog = {};
var NetworkPriorities = {};
var NetworkTestRunner = {};
var ObjectUI = {};
var PerfUI = {};
var PerformanceTestRunner = {};
var Persistence = {};
var ProductRegistry = {};
var ProductRegistryImpl = {};
var Profiler = {};
var Protocol = {};
var QuickOpen = {};
var Resources = {};
var SDK = {};
var SDKTestRunner = {};
var Screencast = {};
var Security = {};
var Services = {};
var Settings = {};
var Snippets = {};
var SourceFrame = {};
var Sources = {};
var SourcesTestRunner = {};
var TestRunner = {};
var TextEditor = {};
var TextUtils = {};
var Timeline = {};
var TimelineModel = {};
var UI = {};
var Workspace = {};
var WorkspaceDiff = {};

View file

@ -7,6 +7,7 @@
"types": []
},
"include": [
"./node_modules/chrome-devtools-frontend/front_end/**/*.js"
"./node_modules/chrome-devtools-frontend/front_end/**/*.js",
"definitions.js"
]
}
}