Skip to content

Commit 02d2063

Browse files
committed
Fixed detecting public/protected class fields declared in constructor
Fixes #13
1 parent a631d6c commit 02d2063

File tree

4 files changed

+117
-12
lines changed

4 files changed

+117
-12
lines changed

src/transformer.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ import * as ts from 'typescript';
33
import { ExportsSymbolTree } from './exports-symbol-tree';
44
import {
55
getDeclarationsForSymbol,
6+
getNodeJSDocComment,
67
isClassMember,
78
isConstructorParameter,
9+
isNodeNamedDeclaration,
810
isPrivateClassMember,
11+
isSymbolClassMember,
912
splitTransientSymbol,
10-
getNodeJSDocComment,
11-
isNodeNamedDeclaration,
13+
getClassOfMemberSymbol,
1214
} from './typescript-helpers';
1315

1416
export interface RenameOptions {
@@ -373,11 +375,13 @@ function createTransformerFactory(program: ts.Program, options?: Partial<RenameO
373375
return VisibilityType.External;
374376
}
375377

376-
if (isClassMember(node.parent) && isTypePropertyExternal(typeChecker.getTypeAtLocation(node.parent.parent), node.getText())) {
378+
const nodeSymbol = getNodeSymbol(node);
379+
const classOfMember = nodeSymbol !== null ? getClassOfMemberSymbol(nodeSymbol) : null;
380+
if (classOfMember !== null && isTypePropertyExternal(typeChecker.getTypeAtLocation(classOfMember), node.getText())) {
377381
return VisibilityType.External;
378382
}
379383

380-
const symbol = ts.isBindingElement(node) ? getShorthandObjectBindingElementSymbol(node) : getNodeSymbol(node);
384+
const symbol = ts.isBindingElement(node) ? getShorthandObjectBindingElementSymbol(node) : nodeSymbol;
381385
if (symbol === null) {
382386
return VisibilityType.External;
383387
}
@@ -478,7 +482,7 @@ function createTransformerFactory(program: ts.Program, options?: Partial<RenameO
478482
return false;
479483
}
480484

481-
return isPrivateClassMember(typeChecker.getSymbolAtLocation(node));
485+
return isSymbolClassMember(typeChecker.getSymbolAtLocation(node));
482486
}
483487

484488
return (sourceFile: ts.SourceFile) => transformNodeAndChildren(sourceFile, context);

src/typescript-helpers.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const namedDeclarationKinds = [
99
ts.SyntaxKind.FunctionDeclaration,
1010
ts.SyntaxKind.VariableDeclaration,
1111
ts.SyntaxKind.PropertySignature,
12+
ts.SyntaxKind.Parameter,
1213
];
1314

1415
export function isNodeNamedDeclaration(node: ts.Node): node is ts.NamedDeclaration {
@@ -111,6 +112,21 @@ export function isClassMember(node: ts.Node): node is ClassMember {
111112
return ts.isMethodDeclaration(node) || ts.isPropertyDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node);
112113
}
113114

115+
export function getClassOfMemberSymbol(nodeSymbol: ts.Symbol): ts.ClassLikeDeclaration | ts.ObjectLiteralExpression | null {
116+
const classMembers = getClassMemberDeclarations(nodeSymbol);
117+
if (classMembers.length !== 0) {
118+
// we need any member to get class' declaration
119+
const classMember = classMembers[0];
120+
if (isConstructorParameter(classMember)) {
121+
return (classMember.parent as ts.ConstructorDeclaration).parent;
122+
}
123+
124+
return classMember.parent;
125+
}
126+
127+
return null;
128+
}
129+
114130
export function hasPrivateKeyword(node: ClassMember | ts.ParameterDeclaration): boolean {
115131
return hasModifier(node, ts.SyntaxKind.PrivateKeyword);
116132
}
@@ -129,17 +145,29 @@ export function isConstructorParameter(node: ts.Node): node is ts.ParameterDecla
129145
);
130146
}
131147

132-
export function isPrivateClassMember(symbol: ts.Symbol | undefined): boolean {
133-
// for some reason ts.Symbol.declarations can be undefined (for example in order to accessing to proto member)
134-
if (symbol === undefined || symbol.declarations === undefined) { // tslint:disable-line:strict-type-predicates
135-
return false;
148+
function getClassMemberDeclarations(symbol: ts.Symbol | undefined): (ClassMember | ts.ParameterDeclaration)[] {
149+
if (symbol === undefined) {
150+
return [];
136151
}
137152

138-
return symbol.declarations.some((x: ts.Declaration) => {
139-
return (isClassMember(x) || isConstructorParameter(x)) && hasPrivateKeyword(x);
153+
const declarations = symbol.getDeclarations();
154+
if (declarations === undefined) {
155+
return [];
156+
}
157+
158+
return declarations.filter((x: ts.Declaration): x is (ClassMember | ts.ParameterDeclaration) => {
159+
return isClassMember(x) || isConstructorParameter(x);
140160
});
141161
}
142162

163+
export function isSymbolClassMember(symbol: ts.Symbol | undefined): boolean {
164+
return getClassMemberDeclarations(symbol).length !== 0;
165+
}
166+
167+
export function isPrivateClassMember(symbol: ts.Symbol | undefined): boolean {
168+
return getClassMemberDeclarations(symbol).some(hasPrivateKeyword);
169+
}
170+
143171
export function getNodeJSDocComment(node: ts.Node): string {
144172
const start = node.getStart();
145173
const jsDocStart = node.getStart(undefined, true);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,42 @@
1+
interface Foo {
2+
bar: number;
3+
baz: number;
4+
}
5+
6+
class Measure {
7+
height: number;
8+
9+
constructor(public width: number, public ascent: number, public descent: number) {
10+
this.height = ascent + descent;
11+
}
12+
}
13+
14+
class Test {
15+
constructor(public pub: number, protected prot: number, private priv: number) {
16+
console.log(pub, prot, priv, this.pub, this.prot, this.priv);
17+
}
18+
}
19+
20+
export class ExportedClass {
21+
constructor(public pub: number, protected prot: number, private priv: number) {
22+
console.log(pub, prot, priv, this.pub, this.prot, this.priv);
23+
}
24+
}
25+
26+
class FooImpl implements Foo {
27+
baz: number = 15;
28+
29+
constructor(public bar: number) {}
30+
}
31+
132
export class Class {
233
public constructor(
334
private privateField: number
435
) {
536
console.log(privateField);
637
}
38+
39+
public getFoo(): Foo {
40+
return new FooImpl(42);
41+
}
742
}
Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,49 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3-
exports.Class = void 0;
3+
exports.Class = exports.ExportedClass = void 0;
4+
var Measure = /** @class */ (function () {
5+
function Measure(_internal_width, _internal_ascent, _internal_descent) {
6+
this._internal_width = _internal_width;
7+
this._internal_ascent = _internal_ascent;
8+
this._internal_descent = _internal_descent;
9+
this._internal_height = _internal_ascent + _internal_descent;
10+
}
11+
return Measure;
12+
}());
13+
var Test = /** @class */ (function () {
14+
function Test(_internal_pub, _internal_prot, _private_priv) {
15+
this._internal_pub = _internal_pub;
16+
this._internal_prot = _internal_prot;
17+
this._private_priv = _private_priv;
18+
console.log(_internal_pub, _internal_prot, _private_priv, this._internal_pub, this._internal_prot, this._private_priv);
19+
}
20+
return Test;
21+
}());
22+
var ExportedClass = /** @class */ (function () {
23+
function ExportedClass(pub, prot, _private_priv) {
24+
this.pub = pub;
25+
this.prot = prot;
26+
this._private_priv = _private_priv;
27+
console.log(pub, prot, _private_priv, this.pub, this.prot, this._private_priv);
28+
}
29+
return ExportedClass;
30+
}());
31+
exports.ExportedClass = ExportedClass;
32+
var FooImpl = /** @class */ (function () {
33+
function FooImpl(bar) {
34+
this.bar = bar;
35+
this.baz = 15;
36+
}
37+
return FooImpl;
38+
}());
439
var Class = /** @class */ (function () {
540
function Class(_private_privateField) {
641
this._private_privateField = _private_privateField;
742
console.log(_private_privateField);
843
}
44+
Class.prototype.getFoo = function () {
45+
return new FooImpl(42);
46+
};
947
return Class;
1048
}());
1149
exports.Class = Class;

0 commit comments

Comments
 (0)