Skip to content

Commit

Permalink
Allow mixin classes to have members added via .prototype calls.
Browse files Browse the repository at this point in the history
For example:

  /** @type {string} */
  MyMixin.prototype.foo;

We already support this behavior for normal classes, but not for mixin
classes.
  • Loading branch information
aomarks committed Dec 1, 2018
1 parent 1e32fc3 commit e760650
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 12 deletions.
18 changes: 9 additions & 9 deletions packages/analyzer/src/javascript/class-scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,16 @@ export class ClassScanner implements JavaScriptScanner {
document: JavaScriptDocument,
visit: (visitor: Visitor) => Promise<void>) {
const classFinder = new ClassFinder(document);
const mixinFinder = new MixinVisitor(document);
const elementDefinitionFinder =
new CustomElementsDefineCallFinder(document);
const prototypeMemberFinder = new PrototypeMemberFinder(document);
await visit(prototypeMemberFinder);
const mixinFinder = new MixinVisitor(document, prototypeMemberFinder);
// Find all classes and all calls to customElements.define()
await Promise.all([
visit(classFinder),
visit(elementDefinitionFinder),
visit(mixinFinder),
visit(prototypeMemberFinder),
]);
const mixins = mixinFinder.mixins;

Expand Down Expand Up @@ -424,7 +424,7 @@ interface CustomElementDefinition {
definition?: ElementDefineCall;
}

class PrototypeMemberFinder implements Visitor {
export class PrototypeMemberFinder implements Visitor {
readonly members = new MapWithDefault<string, {
methods: Map<string, ScannedMethod>,
properties: Map<string, ScannedProperty>
Expand Down Expand Up @@ -505,16 +505,16 @@ class PrototypeMemberFinder implements Visitor {
}

if (jsdoc.hasTag(jsdocAnn, 'function')) {
const prop =
const method =
this._createMethodFromExpression(node.property.name, node, jsdocAnn);
if (prop) {
this._addMethodToClass(cls, prop);
if (method) {
this._addMethodToClass(cls, method);
}
} else {
const method = this._createPropertyFromExpression(
const prop = this._createPropertyFromExpression(
node.property.name, node, jsdocAnn);
if (method) {
this._addPropertyToClass(cls, method);
if (prop) {
this._addPropertyToClass(cls, prop);
}
}
}
Expand Down
24 changes: 21 additions & 3 deletions packages/analyzer/src/polymer/polymer2-mixin-scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {NodePath} from '@babel/traverse';
import * as babel from '@babel/types';

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

constructor(document: JavaScriptDocument) {
constructor(
document: JavaScriptDocument,
prototypeMemberFinder: PrototypeMemberFinder) {
this._document = document;
this._prototypeMemberFinder = prototypeMemberFinder;
}

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

return mixin;
// Also add members that were described like:
// /** @type {string} */
// MixinClass.prototype.foo;
const name = getIdentifierName(node.id);
if (name !== undefined) {
const prototypeMembers = this._prototypeMemberFinder.members.get(name);
if (prototypeMembers !== undefined) {
for (const [, property] of prototypeMembers.properties) {
mixin.addProperty(property);
}
for (const [, method] of prototypeMembers.methods) {
mixin.addMethod(method);
}
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ declare namespace Polymer {
* `this.getRootNode().host`.
*/
readonly domHost: any;
is: string;

/**
* Overrides the default `Polymer.PropertyEffects` implementation to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ interface LegacyElementMixin extends ElementMixin, PropertyEffects, TemplateStam
* `this.getRootNode().host`.
*/
readonly domHost: any;
is: string;

/**
* Overrides the default `Polymer.PropertyEffects` implementation to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ declare namespace Polymer {
* `this.getRootNode().host`.
*/
readonly domHost: any;
is: string;

/**
* Overrides the default `Polymer.PropertyEffects` implementation to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ declare module 'goog:polymer.polymer.lib.legacy.legacyElementMixin' {
* `this.getRootNode().host`.
*/
readonly domHost: any;
is: string;

/**
* Overrides the default `Polymer.PropertyEffects` implementation to
Expand Down

0 comments on commit e760650

Please sign in to comment.