blob: b92a6e92bbaf96a707e353669c5a32b281b7f5f9 [file] [log] [blame]
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {LegacyLifecycleMethodsArray, LegacyPolymerComponent} from './polymerComponentParser';
import {LifecycleMethodsBuilder} from './lifecycleMethodsBuilder';
import {ClassBasedPolymerElement, PolymerElementBuilder} from './polymerElementBuilder';
import * as codeUtils from '../utils/codeUtils';
import * as ts from 'typescript';
export class PolymerFuncToClassBasedConverter {
public static convert(component: LegacyPolymerComponent): ClassBasedPolymerElement {
const legacySettings = component.componentSettings;
const reservedDeclarations = legacySettings.reservedDeclarations;
if(!reservedDeclarations.is) {
throw new Error("Legacy component doesn't have 'is' property");
}
const className = this.generateClassNameFromTagName(reservedDeclarations.is.data);
const updater = new PolymerElementBuilder(component, className);
updater.addIsAccessor(reservedDeclarations.is.data);
if(reservedDeclarations.properties) {
updater.addPolymerPropertiesAccessor(reservedDeclarations.properties);
}
updater.addMixin("Polymer.Element");
updater.addMixin("Polymer.LegacyElementMixin");
updater.addMixin("Polymer.GestureEventListeners");
if(reservedDeclarations._legacyUndefinedCheck) {
updater.addMixin("Polymer.LegacyDataMixin");
}
if(reservedDeclarations.behaviors) {
updater.addMixin("Polymer.mixinBehaviors", [reservedDeclarations.behaviors.data]);
const mixinNames = this.getMixinNamesFromBehaviors(reservedDeclarations.behaviors.data);
const jsDocLines = mixinNames.map(mixinName => {
return `@appliesMixin ${mixinName}`;
});
updater.addClassJSDocComments(jsDocLines);
}
if(reservedDeclarations.observers) {
updater.addPolymerPropertiesObservers(reservedDeclarations.observers.data);
}
if(reservedDeclarations.keyBindings) {
updater.addKeyBindings(reservedDeclarations.keyBindings.data);
}
const lifecycleBuilder = new LifecycleMethodsBuilder();
if (reservedDeclarations.listeners) {
lifecycleBuilder.addListeners(reservedDeclarations.listeners.data, legacySettings.ordinaryMethods);
}
if (reservedDeclarations.hostAttributes) {
lifecycleBuilder.addHostAttributes(reservedDeclarations.hostAttributes.data);
}
for(const name of LegacyLifecycleMethodsArray) {
const existingMethod = legacySettings.lifecycleMethods.get(name);
if(existingMethod) {
lifecycleBuilder.addLegacyLifecycleMethod(name, existingMethod)
}
}
const newLifecycleMethods = lifecycleBuilder.buildNewMethods();
updater.addLifecycleMethods(newLifecycleMethods);
updater.addOrdinaryMethods(legacySettings.ordinaryMethods);
updater.addOrdinaryGetAccessors(legacySettings.ordinaryGetAccessors);
updater.addOrdinaryShorthandProperties(legacySettings.ordinaryShorthandProperties);
updater.addOrdinaryPropertyAssignments(legacySettings.ordinaryPropertyAssignments);
return updater.build();
}
private static generateClassNameFromTagName(tagName: string) {
let result = "";
let nextUppercase = true;
for(const ch of tagName) {
if (ch === '-') {
nextUppercase = true;
continue;
}
result += nextUppercase ? ch.toUpperCase() : ch;
nextUppercase = false;
}
return result;
}
private static getMixinNamesFromBehaviors(behaviors: ts.ArrayLiteralExpression): string[] {
return behaviors.elements.map((expression) => {
const propertyAccessExpression = codeUtils.assertNodeKind(expression, ts.SyntaxKind.PropertyAccessExpression) as ts.PropertyAccessExpression;
const namespaceName = codeUtils.assertNodeKind(propertyAccessExpression.expression, ts.SyntaxKind.Identifier) as ts.Identifier;
const behaviorName = propertyAccessExpression.name;
if(namespaceName.text === 'Gerrit') {
let behaviorNameText = behaviorName.text;
const suffix = 'Behavior';
if(behaviorNameText.endsWith(suffix)) {
behaviorNameText =
behaviorNameText.substr(0, behaviorNameText.length - suffix.length);
}
const mixinName = behaviorNameText + 'Mixin';
return `${namespaceName.text}.${mixinName}`
} else if(namespaceName.text === 'Polymer') {
let behaviorNameText = behaviorName.text;
if(behaviorNameText === "IronFitBehavior") {
return "Polymer.IronFitMixin";
} else if(behaviorNameText === "IronOverlayBehavior") {
return "";
}
throw new Error(`Unsupported behavior: ${propertyAccessExpression.getText()}`);
}
throw new Error(`Unsupported behavior name ${expression.getFullText()}`)
}).filter(name => name.length > 0);
}
}