Skip to content

Commit e760650

Browse files
committed
Allow mixin classes to have members added via .prototype calls.
For example: /** @type {string} */ MyMixin.prototype.foo; We already support this behavior for normal classes, but not for mixin classes.
1 parent 1e32fc3 commit e760650

6 files changed

Lines changed: 34 additions & 12 deletions

File tree

packages/analyzer/src/javascript/class-scanner.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,16 @@ export class ClassScanner implements JavaScriptScanner {
7676
document: JavaScriptDocument,
7777
visit: (visitor: Visitor) => Promise<void>) {
7878
const classFinder = new ClassFinder(document);
79-
const mixinFinder = new MixinVisitor(document);
8079
const elementDefinitionFinder =
8180
new CustomElementsDefineCallFinder(document);
8281
const prototypeMemberFinder = new PrototypeMemberFinder(document);
82+
await visit(prototypeMemberFinder);
83+
const mixinFinder = new MixinVisitor(document, prototypeMemberFinder);
8384
// Find all classes and all calls to customElements.define()
8485
await Promise.all([
8586
visit(classFinder),
8687
visit(elementDefinitionFinder),
8788
visit(mixinFinder),
88-
visit(prototypeMemberFinder),
8989
]);
9090
const mixins = mixinFinder.mixins;
9191

@@ -424,7 +424,7 @@ interface CustomElementDefinition {
424424
definition?: ElementDefineCall;
425425
}
426426

427-
class PrototypeMemberFinder implements Visitor {
427+
export class PrototypeMemberFinder implements Visitor {
428428
readonly members = new MapWithDefault<string, {
429429
methods: Map<string, ScannedMethod>,
430430
properties: Map<string, ScannedProperty>
@@ -505,16 +505,16 @@ class PrototypeMemberFinder implements Visitor {
505505
}
506506

507507
if (jsdoc.hasTag(jsdocAnn, 'function')) {
508-
const prop =
508+
const method =
509509
this._createMethodFromExpression(node.property.name, node, jsdocAnn);
510-
if (prop) {
511-
this._addMethodToClass(cls, prop);
510+
if (method) {
511+
this._addMethodToClass(cls, method);
512512
}
513513
} else {
514-
const method = this._createPropertyFromExpression(
514+
const prop = this._createPropertyFromExpression(
515515
node.property.name, node, jsdocAnn);
516-
if (method) {
517-
this._addPropertyToClass(cls, method);
516+
if (prop) {
517+
this._addPropertyToClass(cls, prop);
518518
}
519519
}
520520
}

packages/analyzer/src/polymer/polymer2-mixin-scanner.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {NodePath} from '@babel/traverse';
1616
import * as babel from '@babel/types';
1717

1818
import {getIdentifierName, getNamespacedIdentifier} from '../javascript/ast-value';
19-
import {extractPropertiesFromClass} from '../javascript/class-scanner';
19+
import {extractPropertiesFromClass, PrototypeMemberFinder} from '../javascript/class-scanner';
2020
import {Visitor} from '../javascript/estree-visitor';
2121
import * as esutil from '../javascript/esutil';
2222
import {getMethods, getOrInferPrivacy, getStaticMethods} from '../javascript/esutil';
@@ -34,10 +34,14 @@ export class MixinVisitor implements Visitor {
3434
private _currentMixin: ScannedPolymerElementMixin|null = null;
3535
private _currentMixinNode: babel.Node|null = null;
3636
private _currentMixinFunction: babel.Function|null = null;
37+
private _prototypeMemberFinder: PrototypeMemberFinder;
3738
readonly warnings: Warning[] = [];
3839

39-
constructor(document: JavaScriptDocument) {
40+
constructor(
41+
document: JavaScriptDocument,
42+
prototypeMemberFinder: PrototypeMemberFinder) {
4043
this._document = document;
44+
this._prototypeMemberFinder = prototypeMemberFinder;
4145
}
4246

4347
enterAssignmentExpression(
@@ -159,7 +163,21 @@ export class MixinVisitor implements Visitor {
159163
mixin.events = esutil.getEventComments(node);
160164
// mixin.sourceRange = this._document.sourceRangeForNode(node);
161165

162-
return mixin;
166+
// Also add members that were described like:
167+
// /** @type {string} */
168+
// MixinClass.prototype.foo;
169+
const name = getIdentifierName(node.id);
170+
if (name !== undefined) {
171+
const prototypeMembers = this._prototypeMemberFinder.members.get(name);
172+
if (prototypeMembers !== undefined) {
173+
for (const [, property] of prototypeMembers.properties) {
174+
mixin.addProperty(property);
175+
}
176+
for (const [, method] of prototypeMembers.methods) {
177+
mixin.addMethod(method);
178+
}
179+
}
180+
}
163181
}
164182
}
165183

packages/gen-typescript-declarations/src/test/goldens/polymer-2/lib/legacy/legacy-element-mixin.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ declare namespace Polymer {
4646
* `this.getRootNode().host`.
4747
*/
4848
readonly domHost: any;
49+
is: string;
4950

5051
/**
5152
* Overrides the default `Polymer.PropertyEffects` implementation to

packages/gen-typescript-declarations/src/test/goldens/polymer-3/lib/legacy/legacy-element-mixin.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ interface LegacyElementMixin extends ElementMixin, PropertyEffects, TemplateStam
7171
* `this.getRootNode().host`.
7272
*/
7373
readonly domHost: any;
74+
is: string;
7475

7576
/**
7677
* Overrides the default `Polymer.PropertyEffects` implementation to

packages/gen-typescript-declarations/src/test/goldens_goog/polymer-2/lib/legacy/legacy-element-mixin.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ declare namespace Polymer {
4646
* `this.getRootNode().host`.
4747
*/
4848
readonly domHost: any;
49+
is: string;
4950

5051
/**
5152
* Overrides the default `Polymer.PropertyEffects` implementation to

packages/gen-typescript-declarations/src/test/goldens_goog/polymer-3/lib/legacy/legacy-element-mixin.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ declare module 'goog:polymer.polymer.lib.legacy.legacyElementMixin' {
7373
* `this.getRootNode().host`.
7474
*/
7575
readonly domHost: any;
76+
is: string;
7677

7778
/**
7879
* Overrides the default `Polymer.PropertyEffects` implementation to

0 commit comments

Comments
 (0)