Allow variable statements used as declaration sites to be marked visible (#22798)

* Allow variable statements used as declaration sites to be marked visible and included in declaration emit by alias marking

* Dont forget to transform statements

* Accept baselines

* Accept updated baselines for new test

* Emit scope fix markers

* Add partial private variable declaration emit test
This commit is contained in:
Wesley Wigham 2018-04-09 14:30:40 -07:00 committed by GitHub
parent 71b39014eb
commit 83ab341531
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 491 additions and 174 deletions

View file

@ -2755,7 +2755,7 @@ namespace ts {
}
function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult {
let aliasesToMakeVisible: AnyImportSyntax[];
let aliasesToMakeVisible: LateVisibilityPaintedStatement[];
if (forEach(symbol.declarations, declaration => !getIsDeclarationVisible(declaration))) {
return undefined;
}
@ -2769,15 +2769,13 @@ namespace ts {
const anyImportSyntax = getAnyImportSyntax(declaration);
if (anyImportSyntax &&
!hasModifier(anyImportSyntax, ModifierFlags.Export) && // import clause without export
isDeclarationVisible(<Declaration>anyImportSyntax.parent)) {
// In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types,
// we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time
// since we will do the emitting later in trackSymbol.
if (shouldComputeAliasToMakeVisible) {
getNodeLinks(declaration).isVisible = true;
aliasesToMakeVisible = appendIfUnique(aliasesToMakeVisible, anyImportSyntax);
}
return true;
isDeclarationVisible(anyImportSyntax.parent)) {
return addVisibleAlias(declaration, anyImportSyntax);
}
else if (isVariableDeclaration(declaration) && isVariableStatement(declaration.parent.parent) &&
!hasModifier(declaration.parent.parent, ModifierFlags.Export) && // unexported variable statement
isDeclarationVisible(declaration.parent.parent.parent)) {
return addVisibleAlias(declaration, declaration.parent.parent);
}
// Declaration is not visible
@ -2786,6 +2784,17 @@ namespace ts {
return true;
}
function addVisibleAlias(declaration: Declaration, aliasingStatement: LateVisibilityPaintedStatement) {
// In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types,
// we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time
// since we will do the emitting later in trackSymbol.
if (shouldComputeAliasToMakeVisible) {
getNodeLinks(declaration).isVisible = true;
aliasesToMakeVisible = appendIfUnique(aliasesToMakeVisible, aliasingStatement);
}
return true;
}
}
function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult {
@ -3850,7 +3859,7 @@ namespace ts {
return symbolName(symbol);
}
function isDeclarationVisible(node: Declaration | AnyImportSyntax): boolean {
function isDeclarationVisible(node: Node): boolean {
if (node) {
const links = getNodeLinks(node);
if (links.isVisible === undefined) {
@ -3864,7 +3873,7 @@ namespace ts {
function determineIfDeclarationIsVisible() {
switch (node.kind) {
case SyntaxKind.BindingElement:
return isDeclarationVisible(<Declaration>node.parent.parent);
return isDeclarationVisible(node.parent.parent);
case SyntaxKind.VariableDeclaration:
if (isBindingPattern((node as VariableDeclaration).name) &&
!((node as VariableDeclaration).name as BindingPattern).elements.length) {
@ -3890,7 +3899,7 @@ namespace ts {
return isGlobalSourceFile(parent);
}
// Exported members/ambient module elements (exception import declaration) are visible if parent is visible
return isDeclarationVisible(<Declaration>parent);
return isDeclarationVisible(parent);
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
@ -3920,7 +3929,7 @@ namespace ts {
case SyntaxKind.UnionType:
case SyntaxKind.IntersectionType:
case SyntaxKind.ParenthesizedType:
return isDeclarationVisible(<Declaration>node.parent);
return isDeclarationVisible(node.parent);
// Default binding, import specifier and namespace import is visible
// only on demand so by default it is not visible

View file

@ -27,10 +27,12 @@ namespace ts {
let needsDeclare = true;
let isBundledEmit = false;
let resultHasExternalModuleIndicator = false;
let needsScopeFixMarker = false;
let resultHasScopeMarker = false;
let enclosingDeclaration: Node;
let necessaryTypeRefernces: Map<true>;
let possibleImports: AnyImportSyntax[];
let importDeclarationMap: Map<AnyImportSyntax | undefined>;
let lateMarkedStatements: LateVisibilityPaintedStatement[];
let lateStatementReplacementMap: Map<LateVisibilityPaintedStatement | undefined>;
let suppressNewDiagnosticContexts: boolean;
const symbolTracker: SymbolTracker = {
@ -63,12 +65,12 @@ namespace ts {
if (symbolAccessibilityResult.accessibility === SymbolAccessibility.Accessible) {
// Add aliases back onto the possible imports list if they're not there so we can try them again with updated visibility info
if (symbolAccessibilityResult && symbolAccessibilityResult.aliasesToMakeVisible) {
if (!possibleImports) {
possibleImports = symbolAccessibilityResult.aliasesToMakeVisible;
if (!lateMarkedStatements) {
lateMarkedStatements = symbolAccessibilityResult.aliasesToMakeVisible;
}
else {
for (const ref of symbolAccessibilityResult.aliasesToMakeVisible) {
pushIfUnique(possibleImports, ref);
pushIfUnique(lateMarkedStatements, ref);
}
}
}
@ -142,10 +144,12 @@ namespace ts {
hasNoDefaultLib = hasNoDefaultLib || sourceFile.hasNoDefaultLib;
currentSourceFile = sourceFile;
enclosingDeclaration = sourceFile;
possibleImports = undefined;
lateMarkedStatements = undefined;
suppressNewDiagnosticContexts = false;
importDeclarationMap = createMap();
lateStatementReplacementMap = createMap();
getSymbolAccessibilityDiagnostic = throwDiagnostic;
needsScopeFixMarker = false;
resultHasScopeMarker = false;
collectReferences(sourceFile, refs);
if (isExternalModule(sourceFile)) {
resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules)
@ -161,7 +165,7 @@ namespace ts {
}
needsDeclare = true;
const updated = visitNodes(sourceFile.statements, visitDeclarationStatements);
return updateSourceFileNode(sourceFile, updated, /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false);
return updateSourceFileNode(sourceFile, filterCandidateImports(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false);
}
));
bundle.syntheticFileReferences = [];
@ -175,14 +179,16 @@ namespace ts {
// Single source file
needsDeclare = true;
needsScopeFixMarker = false;
resultHasScopeMarker = false;
enclosingDeclaration = node;
currentSourceFile = node;
getSymbolAccessibilityDiagnostic = throwDiagnostic;
isBundledEmit = false;
resultHasExternalModuleIndicator = false;
suppressNewDiagnosticContexts = false;
possibleImports = undefined;
importDeclarationMap = createMap();
lateMarkedStatements = undefined;
lateStatementReplacementMap = createMap();
necessaryTypeRefernces = undefined;
const refs = collectReferences(currentSourceFile, createMap());
const references: FileReference[] = [];
@ -192,7 +198,7 @@ namespace ts {
const statements = visitNodes(node.statements, visitDeclarationStatements);
let combinedStatements = setTextRange(createNodeArray(filterCandidateImports(statements)), node.statements);
const emittedImports = filter(combinedStatements, isAnyImportSyntax);
if (isExternalModule(node) && !resultHasExternalModuleIndicator) {
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined)]), combinedStatements);
}
const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib);
@ -532,7 +538,7 @@ namespace ts {
// Nothing visible
}
function filterCandidateImports(statements: ReadonlyArray<Statement>): ReadonlyArray<Statement> {
function filterCandidateImports(statements: NodeArray<Statement>): NodeArray<Statement> {
// This is a `while` loop because `handleSymbolAccessibilityError` can see additional import aliases marked as visible during
// error handling which must now be included in the output and themselves checked for errors.
// For example:
@ -547,45 +553,63 @@ namespace ts {
// In such a scenario, only Q and D are initially visible, but we don't consider imports as private names - instead we say they if they are referenced they must
// be recorded. So while checking D's visibility we mark C as visible, then we must check C which in turn marks B, completing the chain of
// dependent imports and allowing a valid declaration file output. Today, this dependent alias marking only happens for internal import aliases.
const unconsideredImports: AnyImportSyntax[] = [];
while (length(possibleImports)) {
const i = possibleImports.shift();
const unconsideredStatements: LateVisibilityPaintedStatement[] = [];
while (length(lateMarkedStatements)) {
const i = lateMarkedStatements.shift();
if ((isSourceFile(i.parent) ? i.parent : i.parent.parent) !== enclosingDeclaration) { // Filter to only declarations in the current scope
unconsideredImports.push(i);
unconsideredStatements.push(i);
continue;
}
// Eagerly transform import equals - if they're not visible, we'll get nothing, if they are, we'll immediately add them since it's complete
if (i.kind === SyntaxKind.ImportEqualsDeclaration) {
const result = transformImportEqualsDeclaration(i);
importDeclarationMap.set("" + getNodeId(i), result);
continue;
if (!isLateVisibilityPaintedStatement(i)) {
return Debug.fail(`Late replaced statement was foudn which is not handled by the declaration transformer!: ${(ts as any).SyntaxKind ? (ts as any).SyntaxKind[(i as any).kind] : (i as any).kind}`);
}
switch (i.kind) {
case SyntaxKind.ImportEqualsDeclaration: {
const result = transformImportEqualsDeclaration(i);
lateStatementReplacementMap.set("" + getNodeId(i), result);
break;
}
case SyntaxKind.ImportDeclaration: {
const result = transformImportDeclaration(i);
lateStatementReplacementMap.set("" + getNodeId(i), result);
break;
}
case SyntaxKind.VariableStatement: {
const result = transformVariableStatement(i, /*privateDeclaration*/ true); // Transform the statement (potentially again, possibly revealing more sub-nodes)
lateStatementReplacementMap.set("" + getNodeId(i), result);
break;
}
default: Debug.assertNever(i, "Unhandled late painted statement!");
}
// Import declarations, on the other hand, can be partially painted by multiple aliases; so we can see many indeterminate states
// until we've marked all possible visibility
const result = transformImportDeclaration(i);
importDeclarationMap.set("" + getNodeId(i), result);
}
// Filtering available imports is the last thing done within a scope, so the possible set becomes those which could not
// be considered in the child scope
possibleImports = unconsideredImports;
lateMarkedStatements = unconsideredStatements;
// And lastly, we need to get the final form of all those indetermine import declarations from before and add them to the output list
// (and remove them from the set to examine for outter declarations)
return mapDefined(statements, statement => {
if (isImportDeclaration(statement) || isImportEqualsDeclaration(statement)) {
const key = "" + getNodeId(statement);
if (importDeclarationMap.has(key)) {
const result = importDeclarationMap.get(key);
importDeclarationMap.delete(key);
return result;
}
else {
return undefined;
return visitNodes(statements, visitLateVisibilityMarkedStatements);
}
function visitLateVisibilityMarkedStatements(statement: Statement) {
if (isLateVisibilityPaintedStatement(statement)) {
const key = "" + getNodeId(statement);
if (lateStatementReplacementMap.has(key)) {
const result = lateStatementReplacementMap.get(key);
lateStatementReplacementMap.delete(key);
if (result && isSourceFile(statement.parent) && !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasModifier(result, ModifierFlags.Export)) {
// Top-level declarations in .d.ts files are always considered exported even without a modifier unless there's an export assignment or specifier
needsScopeFixMarker = true;
}
return result;
}
else {
return statement;
return getParseTreeNode(statement) ? undefined : statement;
}
});
}
else {
return statement;
}
}
function visitDeclarationSubtree(input: Node): VisitResult<Node> {
@ -816,6 +840,7 @@ namespace ts {
case SyntaxKind.ExportDeclaration: {
if (isSourceFile(input.parent)) {
resultHasExternalModuleIndicator = true;
resultHasScopeMarker = true;
}
// Always visible if the parent node isn't dropped for being not visible
// Rewrite external module names if necessary
@ -825,6 +850,7 @@ namespace ts {
// Always visible if the parent node isn't dropped for being not visible
if (isSourceFile(input.parent)) {
resultHasExternalModuleIndicator = true;
resultHasScopeMarker = true;
}
if (input.expression.kind === SyntaxKind.Identifier) {
return input;
@ -844,8 +870,8 @@ namespace ts {
case SyntaxKind.ImportDeclaration: {
// Different parts of the import may be marked visible at different times (via visibility checking), so we defer our first look until later
// to reduce the likelihood we need to rewrite it
possibleImports = possibleImports || [];
pushIfUnique(possibleImports, input);
lateMarkedStatements = lateMarkedStatements || [];
pushIfUnique(lateMarkedStatements, input);
return input;
}
}
@ -866,7 +892,7 @@ namespace ts {
if (canProdiceDiagnostic) {
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing);
}
let oldPossibleImports: typeof possibleImports;
let oldPossibleImports: typeof lateMarkedStatements;
switch (input.kind) {
case SyntaxKind.TypeAliasDeclaration: // Type aliases get `declare`d if need be (for legacy support), but that's all
@ -906,8 +932,8 @@ namespace ts {
case SyntaxKind.ModuleDeclaration: {
previousNeedsDeclare = needsDeclare;
needsDeclare = false;
oldPossibleImports = possibleImports;
possibleImports = undefined;
oldPossibleImports = lateMarkedStatements;
lateMarkedStatements = undefined;
const inner = input.body;
if (inner && inner.kind === SyntaxKind.ModuleBlock) {
const statements = visitNodes(inner.statements, visitDeclarationStatements);
@ -1029,10 +1055,9 @@ namespace ts {
}
}
case SyntaxKind.VariableStatement: {
if (!forEach(input.declarationList.declarations, getBindingNameVisible)) return;
const nodes = visitNodes(input.declarationList.declarations, visitDeclarationSubtree);
if (!length(nodes)) return;
return cleanup(updateVariableStatement(input, createNodeArray(ensureModifiers(input)), updateVariableDeclarationList(input.declarationList, nodes)));
const result = transformVariableStatement(input);
lateStatementReplacementMap.set("" + getNodeId(input), result); // Don't actually elide yet; just leave as original node - will be elided/swapped by late pass
return cleanup(input);
}
case SyntaxKind.EnumDeclaration: {
return cleanup(updateEnumDeclaration(input, /*decorators*/ undefined, createNodeArray(ensureModifiers(input)), input.name, createNodeArray(mapDefined(input.members, m => {
@ -1053,12 +1078,12 @@ namespace ts {
}
if (input.kind === SyntaxKind.ModuleDeclaration) {
needsDeclare = previousNeedsDeclare;
possibleImports = concatenate(oldPossibleImports, possibleImports);
lateMarkedStatements = concatenate(oldPossibleImports, lateMarkedStatements);
}
if (canProdiceDiagnostic) {
getSymbolAccessibilityDiagnostic = oldDiag;
}
if (returnValue) {
if (returnValue && (!isLateVisibilityPaintedStatement(input) || lateStatementReplacementMap.get("" + getNodeId(input)))) {
if (!resultHasExternalModuleIndicator && hasModifier(input, ModifierFlags.Export) && isSourceFile(input.parent)) {
// Exported top-level member indicates moduleness
resultHasExternalModuleIndicator = true;
@ -1071,6 +1096,13 @@ namespace ts {
}
}
function transformVariableStatement(input: VariableStatement, privateDeclaration?: boolean) {
if (!forEach(input.declarationList.declarations, getBindingNameVisible)) return;
const nodes = visitNodes(input.declarationList.declarations, visitDeclarationSubtree);
if (!length(nodes)) return;
return updateVariableStatement(input, createNodeArray(ensureModifiers(input, privateDeclaration)), updateVariableDeclarationList(input.declarationList, nodes));
}
function recreateBindingPattern(d: BindingPattern): VariableDeclaration[] {
return flatten<VariableDeclaration>(mapDefined(d.elements, e => recreateBindingElement(e)));
}
@ -1122,21 +1154,21 @@ namespace ts {
return false;
}
function ensureModifiers(node: Node): ReadonlyArray<Modifier> {
function ensureModifiers(node: Node, privateDeclaration?: boolean): ReadonlyArray<Modifier> {
const currentFlags = getModifierFlags(node);
const newFlags = ensureModifierFlags(node);
const newFlags = ensureModifierFlags(node, privateDeclaration);
if (currentFlags === newFlags) {
return node.modifiers;
}
return createModifiersFromModifierFlags(newFlags);
}
function ensureModifierFlags(node: Node): ModifierFlags {
function ensureModifierFlags(node: Node, privateDeclaration?: boolean): ModifierFlags {
let mask = ModifierFlags.All ^ (ModifierFlags.Public | ModifierFlags.Async); // No async modifiers in declaration files
let additions = (needsDeclare && !isAlwaysType(node)) ? ModifierFlags.Ambient : ModifierFlags.None;
const parentIsFile = node.parent.kind === SyntaxKind.SourceFile;
if (!parentIsFile || (isBundledEmit && parentIsFile && isExternalModule(node.parent as SourceFile))) {
mask ^= ((isBundledEmit && parentIsFile ? 0 : ModifierFlags.Export) | ModifierFlags.Default | ModifierFlags.Ambient);
mask ^= ((privateDeclaration || (isBundledEmit && parentIsFile) ? 0 : ModifierFlags.Export) | ModifierFlags.Default | ModifierFlags.Ambient);
additions = ModifierFlags.None;
}
return maskModifierFlags(node, mask, additions);

View file

@ -3197,10 +3197,13 @@ namespace ts {
/* @internal */
export type RequireOrImportCall = CallExpression & { arguments: [StringLiteralLike] };
/* @internal */
export type LateVisibilityPaintedStatement = AnyImportSyntax | VariableStatement;
/* @internal */
export interface SymbolVisibilityResult {
accessibility: SymbolAccessibility;
aliasesToMakeVisible?: AnyImportSyntax[]; // aliases that need to have this symbol visible
aliasesToMakeVisible?: LateVisibilityPaintedStatement[]; // aliases that need to have this symbol visible
errorSymbolName?: string; // Optional symbol name that results in error
errorNode?: Node; // optional node that results in error
}

View file

@ -546,6 +546,17 @@ namespace ts {
}
}
export function isLateVisibilityPaintedStatement(node: Node): node is LateVisibilityPaintedStatement {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.VariableStatement:
return true;
default:
return false;
}
}
export function isAnyImportOrReExport(node: Node): node is AnyImportOrReExport {
return isAnyImportSyntax(node) || isExportDeclaration(node);
}

View file

@ -1,14 +0,0 @@
tests/cases/compiler/file.ts(4,17): error TS4060: Return type of exported function has or is using private name 'IGNORE_EXTRA_VARIABLES'.
==== tests/cases/compiler/file.ts (1 errors) ====
const IGNORE_EXTRA_VARIABLES = Symbol(); //Notice how this is unexported
//This is exported
export function ignoreExtraVariables<CtorT extends {new(...args:any[]):{}}> (ctor : CtorT) {
~~~~~~~~~~~~~~~~~~~~
!!! error TS4060: Return type of exported function has or is using private name 'IGNORE_EXTRA_VARIABLES'.
return class extends ctor {
[IGNORE_EXTRA_VARIABLES] = true; //An unexported constant is used
};
}

View file

@ -38,3 +38,15 @@ function ignoreExtraVariables(ctor) {
var _b, _a;
}
exports.ignoreExtraVariables = ignoreExtraVariables;
//// [file.d.ts]
declare const IGNORE_EXTRA_VARIABLES: unique symbol;
export declare function ignoreExtraVariables<CtorT extends {
new (...args: any[]): {};
}>(ctor: CtorT): {
new (...args: any[]): {
[IGNORE_EXTRA_VARIABLES]: boolean;
};
} & CtorT;
export {};

View file

@ -0,0 +1,25 @@
tests/cases/compiler/c.ts(4,14): error TS2415: Class 'D' incorrectly extends base class 'C'.
Types have separate declarations of a private property '[x]'.
==== tests/cases/compiler/a.ts (0 errors) ====
export const x = Symbol();
==== tests/cases/compiler/b.ts (0 errors) ====
import { x } from "./a";
export class C {
private [x]: number = 1;
}
==== tests/cases/compiler/c.ts (1 errors) ====
import { x } from "./a";
import { C } from "./b";
export class D extends C {
~
!!! error TS2415: Class 'D' incorrectly extends base class 'C'.
!!! error TS2415: Types have separate declarations of a private property '[x]'.
private [x]: 12 = 12;
}

View file

@ -0,0 +1,80 @@
//// [tests/cases/compiler/declarationEmitPrivateSymbolCausesVarDeclarationEmit2.ts] ////
//// [a.ts]
export const x = Symbol();
//// [b.ts]
import { x } from "./a";
export class C {
private [x]: number = 1;
}
//// [c.ts]
import { x } from "./a";
import { C } from "./b";
export class D extends C {
private [x]: 12 = 12;
}
//// [a.js]
"use strict";
exports.__esModule = true;
exports.x = Symbol();
//// [b.js]
"use strict";
exports.__esModule = true;
var a_1 = require("./a");
var C = /** @class */ (function () {
function C() {
this[_a] = 1;
}
return C;
}());
_a = a_1.x;
exports.C = C;
var _a;
//// [c.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var a_1 = require("./a");
var b_1 = require("./b");
var D = /** @class */ (function (_super) {
__extends(D, _super);
function D() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this[_a] = 12;
return _this;
}
return D;
}(b_1.C));
_a = a_1.x;
exports.D = D;
var _a;
//// [a.d.ts]
export declare const x: unique symbol;
//// [b.d.ts]
import { x } from "./a";
export declare class C {
private [x];
}
//// [c.d.ts]
import { x } from "./a";
import { C } from "./b";
export declare class D extends C {
private [x];
}

View file

@ -0,0 +1,33 @@
=== tests/cases/compiler/a.ts ===
export const x = Symbol();
>x : Symbol(x, Decl(a.ts, 0, 12))
>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --))
=== tests/cases/compiler/b.ts ===
import { x } from "./a";
>x : Symbol(x, Decl(b.ts, 0, 8))
export class C {
>C : Symbol(C, Decl(b.ts, 0, 24))
private [x]: number = 1;
>[x] : Symbol(C[x], Decl(b.ts, 2, 16))
>x : Symbol(x, Decl(b.ts, 0, 8))
}
=== tests/cases/compiler/c.ts ===
import { x } from "./a";
>x : Symbol(x, Decl(c.ts, 0, 8))
import { C } from "./b";
>C : Symbol(C, Decl(c.ts, 1, 8))
export class D extends C {
>D : Symbol(D, Decl(c.ts, 1, 24))
>C : Symbol(C, Decl(c.ts, 1, 8))
private [x]: 12 = 12;
>[x] : Symbol(D[x], Decl(c.ts, 3, 26))
>x : Symbol(x, Decl(c.ts, 0, 8))
}

View file

@ -0,0 +1,36 @@
=== tests/cases/compiler/a.ts ===
export const x = Symbol();
>x : unique symbol
>Symbol() : unique symbol
>Symbol : SymbolConstructor
=== tests/cases/compiler/b.ts ===
import { x } from "./a";
>x : unique symbol
export class C {
>C : C
private [x]: number = 1;
>[x] : number
>x : unique symbol
>1 : 1
}
=== tests/cases/compiler/c.ts ===
import { x } from "./a";
>x : unique symbol
import { C } from "./b";
>C : typeof C
export class D extends C {
>D : D
>C : C
private [x]: 12 = 12;
>[x] : 12
>x : unique symbol
>12 : 12
}

View file

@ -0,0 +1,27 @@
//// [declarationEmitPrivateSymbolCausesVarDeclarationToBeEmitted.ts]
const _data = Symbol('data');
export class User {
private [_data] : any;
};
//// [declarationEmitPrivateSymbolCausesVarDeclarationToBeEmitted.js]
"use strict";
exports.__esModule = true;
var _data = Symbol('data');
var User = /** @class */ (function () {
function User() {
}
return User;
}());
exports.User = User;
;
//// [declarationEmitPrivateSymbolCausesVarDeclarationToBeEmitted.d.ts]
declare const _data: unique symbol;
export declare class User {
private [_data];
}
export {};

View file

@ -0,0 +1,14 @@
=== tests/cases/compiler/declarationEmitPrivateSymbolCausesVarDeclarationToBeEmitted.ts ===
const _data = Symbol('data');
>_data : Symbol(_data, Decl(declarationEmitPrivateSymbolCausesVarDeclarationToBeEmitted.ts, 0, 5))
>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --))
export class User {
>User : Symbol(User, Decl(declarationEmitPrivateSymbolCausesVarDeclarationToBeEmitted.ts, 0, 29))
private [_data] : any;
>[_data] : Symbol(User[_data], Decl(declarationEmitPrivateSymbolCausesVarDeclarationToBeEmitted.ts, 2, 19))
>_data : Symbol(_data, Decl(declarationEmitPrivateSymbolCausesVarDeclarationToBeEmitted.ts, 0, 5))
};

View file

@ -0,0 +1,16 @@
=== tests/cases/compiler/declarationEmitPrivateSymbolCausesVarDeclarationToBeEmitted.ts ===
const _data = Symbol('data');
>_data : unique symbol
>Symbol('data') : unique symbol
>Symbol : SymbolConstructor
>'data' : "data"
export class User {
>User : User
private [_data] : any;
>[_data] : any
>_data : unique symbol
};

View file

@ -7,25 +7,9 @@ tests/cases/compiler/dynamicNamesErrors.ts(24,1): error TS2322: Type 'T2' is not
tests/cases/compiler/dynamicNamesErrors.ts(25,1): error TS2322: Type 'T1' is not assignable to type 'T2'.
Types of property '[c0]' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/compiler/dynamicNamesErrors.ts(33,6): error TS4033: Property '[x]' of exported interface has or is using private name 'x'.
tests/cases/compiler/dynamicNamesErrors.ts(34,6): error TS4102: Method '[y]' of exported interface has or is using private name 'y'.
tests/cases/compiler/dynamicNamesErrors.ts(38,13): error TS4028: Public static property '[x]' of exported class has or is using private name 'x'.
tests/cases/compiler/dynamicNamesErrors.ts(39,13): error TS4097: Public static method '[y]' of exported class has or is using private name 'y'.
tests/cases/compiler/dynamicNamesErrors.ts(40,17): error TS4028: Public static property '[z]' of exported class has or is using private name 'z'.
tests/cases/compiler/dynamicNamesErrors.ts(41,17): error TS4028: Public static property '[w]' of exported class has or is using private name 'w'.
tests/cases/compiler/dynamicNamesErrors.ts(43,6): error TS4031: Public property '[x]' of exported class has or is using private name 'x'.
tests/cases/compiler/dynamicNamesErrors.ts(44,6): error TS4100: Public method '[y]' of exported class has or is using private name 'y'.
tests/cases/compiler/dynamicNamesErrors.ts(45,10): error TS4031: Public property '[z]' of exported class has or is using private name 'z'.
tests/cases/compiler/dynamicNamesErrors.ts(46,10): error TS4031: Public property '[w]' of exported class has or is using private name 'w'.
tests/cases/compiler/dynamicNamesErrors.ts(50,6): error TS4033: Property '[x]' of exported interface has or is using private name 'x'.
tests/cases/compiler/dynamicNamesErrors.ts(51,6): error TS4102: Method '[y]' of exported interface has or is using private name 'y'.
tests/cases/compiler/dynamicNamesErrors.ts(54,14): error TS4025: Exported variable 'ObjectLiteralVisibility' has or is using private name 'w'.
tests/cases/compiler/dynamicNamesErrors.ts(54,14): error TS4025: Exported variable 'ObjectLiteralVisibility' has or is using private name 'x'.
tests/cases/compiler/dynamicNamesErrors.ts(54,14): error TS4025: Exported variable 'ObjectLiteralVisibility' has or is using private name 'y'.
tests/cases/compiler/dynamicNamesErrors.ts(54,14): error TS4025: Exported variable 'ObjectLiteralVisibility' has or is using private name 'z'.
==== tests/cases/compiler/dynamicNamesErrors.ts (21 errors) ====
==== tests/cases/compiler/dynamicNamesErrors.ts (5 errors) ====
const c0 = "1";
const c1 = 1;
@ -73,59 +57,27 @@ tests/cases/compiler/dynamicNamesErrors.ts(54,14): error TS4025: Exported variab
export interface InterfaceMemberVisibility {
[x]: number;
~
!!! error TS4033: Property '[x]' of exported interface has or is using private name 'x'.
[y](): number;
~
!!! error TS4102: Method '[y]' of exported interface has or is using private name 'y'.
}
export class ClassMemberVisibility {
static [x]: number;
~
!!! error TS4028: Public static property '[x]' of exported class has or is using private name 'x'.
static [y](): number { return 0; }
~
!!! error TS4097: Public static method '[y]' of exported class has or is using private name 'y'.
static get [z](): number { return 0; }
~
!!! error TS4028: Public static property '[z]' of exported class has or is using private name 'z'.
static set [w](value: number) { }
~
!!! error TS4028: Public static property '[w]' of exported class has or is using private name 'w'.
[x]: number;
~
!!! error TS4031: Public property '[x]' of exported class has or is using private name 'x'.
[y](): number { return 0; }
~
!!! error TS4100: Public method '[y]' of exported class has or is using private name 'y'.
get [z](): number { return 0; }
~
!!! error TS4031: Public property '[z]' of exported class has or is using private name 'z'.
set [w](value: number) { }
~
!!! error TS4031: Public property '[w]' of exported class has or is using private name 'w'.
}
export type ObjectTypeVisibility = {
[x]: number;
~
!!! error TS4033: Property '[x]' of exported interface has or is using private name 'x'.
[y](): number;
~
!!! error TS4102: Method '[y]' of exported interface has or is using private name 'y'.
};
export const ObjectLiteralVisibility = {
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS4025: Exported variable 'ObjectLiteralVisibility' has or is using private name 'w'.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS4025: Exported variable 'ObjectLiteralVisibility' has or is using private name 'x'.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS4025: Exported variable 'ObjectLiteralVisibility' has or is using private name 'y'.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS4025: Exported variable 'ObjectLiteralVisibility' has or is using private name 'z'.
[x]: 0,
[y](): number { return 0; },
get [z](): number { return 0; },

View file

@ -87,3 +87,35 @@ exports.ObjectLiteralVisibility = {
get [z]() { return 0; },
set [w](value) { },
};
//// [dynamicNamesErrors.d.ts]
declare const x: unique symbol;
declare const y: unique symbol;
declare const z: unique symbol;
declare const w: unique symbol;
export interface InterfaceMemberVisibility {
[x]: number;
[y](): number;
}
export declare class ClassMemberVisibility {
static [x]: number;
static [y](): number;
static readonly [z]: number;
static [w]: number;
[x]: number;
[y](): number;
readonly [z]: number;
[w]: number;
}
export declare type ObjectTypeVisibility = {
[x]: number;
[y](): number;
};
export declare const ObjectLiteralVisibility: {
[x]: number;
[y](): number;
readonly [z]: number;
[w]: number;
};
export {};

View file

@ -1,22 +1,8 @@
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(6,14): error TS2527: The inferred type of 'obj' references an inaccessible 'unique symbol' type. A type annotation is necessary.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(15,14): error TS2527: The inferred type of 'classExpression' references an inaccessible 'unique symbol' type. A type annotation is necessary.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(24,17): error TS2527: The inferred type of 'funcInferredReturnType' references an inaccessible 'unique symbol' type. A type annotation is necessary.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(24,64): error TS4078: Parameter 'obj' of exported function has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(29,6): error TS4033: Property '[s]' of exported interface has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(33,6): error TS4102: Method '[s]' of exported interface has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(37,6): error TS4033: Property '[s]' of exported interface has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(41,6): error TS4102: Method '[s]' of exported interface has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(45,6): error TS4031: Public property '[s]' of exported class has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(46,13): error TS4028: Public static property '[s]' of exported class has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(50,6): error TS4100: Public method '[s]' of exported class has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(51,13): error TS4097: Public static method '[s]' of exported class has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(55,10): error TS4031: Public property '[s]' of exported class has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(56,10): error TS4031: Public property '[s]' of exported class has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(57,17): error TS4028: Public static property '[s]' of exported class has or is using private name 's'.
tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(58,17): error TS4028: Public static property '[s]' of exported class has or is using private name 's'.
==== tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts (16 errors) ====
==== tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts (2 errors) ====
declare const s: unique symbol;
interface I { readonly readonlyType: unique symbol; }
@ -45,66 +31,38 @@ tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarationsErrors.ts(58
};
export function funcInferredReturnType(obj: { method(p: typeof s): void }) {
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2527: The inferred type of 'funcInferredReturnType' references an inaccessible 'unique symbol' type. A type annotation is necessary.
~
!!! error TS4078: Parameter 'obj' of exported function has or is using private name 's'.
return obj;
}
export interface InterfaceWithPrivateNamedProperties {
[s]: any;
~
!!! error TS4033: Property '[s]' of exported interface has or is using private name 's'.
}
export interface InterfaceWithPrivateNamedMethods {
[s](): any;
~
!!! error TS4102: Method '[s]' of exported interface has or is using private name 's'.
}
export type TypeLiteralWithPrivateNamedProperties = {
[s]: any;
~
!!! error TS4033: Property '[s]' of exported interface has or is using private name 's'.
}
export type TypeLiteralWithPrivateNamedMethods = {
[s](): any;
~
!!! error TS4102: Method '[s]' of exported interface has or is using private name 's'.
}
export class ClassWithPrivateNamedProperties {
[s]: any;
~
!!! error TS4031: Public property '[s]' of exported class has or is using private name 's'.
static [s]: any;
~
!!! error TS4028: Public static property '[s]' of exported class has or is using private name 's'.
}
export class ClassWithPrivateNamedMethods {
[s]() {}
~
!!! error TS4100: Public method '[s]' of exported class has or is using private name 's'.
static [s]() {}
~
!!! error TS4097: Public static method '[s]' of exported class has or is using private name 's'.
}
export class ClassWithPrivateNamedAccessors {
get [s](): any { return undefined; }
~
!!! error TS4031: Public property '[s]' of exported class has or is using private name 's'.
set [s](v: any) { }
~
!!! error TS4031: Public property '[s]' of exported class has or is using private name 's'.
static get [s](): any { return undefined; }
~
!!! error TS4028: Public static property '[s]' of exported class has or is using private name 's'.
static set [s](v: any) { }
~
!!! error TS4028: Public static property '[s]' of exported class has or is using private name 's'.
}

View file

@ -0,0 +1,28 @@
//// [variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.ts]
const key = Symbol(), value = 12;
export class Foo {
[key] = value;
}
//// [variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.js]
"use strict";
exports.__esModule = true;
var key = Symbol(), value = 12;
var Foo = /** @class */ (function () {
function Foo() {
this[_a] = value;
}
return Foo;
}());
_a = key;
exports.Foo = Foo;
var _a;
//// [variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.d.ts]
declare const key: unique symbol;
export declare class Foo {
[key]: number;
}
export {};

View file

@ -0,0 +1,14 @@
=== tests/cases/compiler/variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.ts ===
const key = Symbol(), value = 12;
>key : Symbol(key, Decl(variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.ts, 0, 5))
>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --))
>value : Symbol(value, Decl(variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.ts, 0, 21))
export class Foo {
>Foo : Symbol(Foo, Decl(variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.ts, 0, 33))
[key] = value;
>[key] : Symbol(Foo[key], Decl(variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.ts, 2, 18))
>key : Symbol(key, Decl(variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.ts, 0, 5))
>value : Symbol(value, Decl(variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.ts, 0, 21))
}

View file

@ -0,0 +1,16 @@
=== tests/cases/compiler/variableDeclarationDeclarationEmitUniqueSymbolPartialStatement.ts ===
const key = Symbol(), value = 12;
>key : unique symbol
>Symbol() : unique symbol
>Symbol : SymbolConstructor
>value : 12
>12 : 12
export class Foo {
>Foo : Foo
[key] = value;
>[key] : number
>key : unique symbol
>value : 12
}

View file

@ -0,0 +1,19 @@
// @declaration: true
// @lib: es6
// @filename: a.ts
export const x = Symbol();
// @filename: b.ts
import { x } from "./a";
export class C {
private [x]: number = 1;
}
// @filename: c.ts
import { x } from "./a";
import { C } from "./b";
export class D extends C {
private [x]: 12 = 12;
}

View file

@ -0,0 +1,7 @@
// @declaration: true
// @lib: es6
const _data = Symbol('data');
export class User {
private [_data] : any;
};

View file

@ -0,0 +1,7 @@
// @declaration: true
// @lib: es6
const key = Symbol(), value = 12;
export class Foo {
[key] = value;
}