All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.angular.rebind.AngularGenerator Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
package com.google.gwt.angular.rebind;

import com.google.common.base.Joiner;
import com.google.gwt.angular.client.*;
import com.google.gwt.angular.client.impl.JsModelBase;
import com.google.gwt.angular.client.impl.JsScopeBase;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.*;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import elemental.json.JsonObject;
import elemental.util.ArrayOf;
import elemental.util.ArrayOfString;

import java.io.PrintWriter;
import java.util.*;

public class AngularGenerator extends Generator {
  public static final String IMPL = "Impl";
  private static final String SCOPEIMPL = "Jso";
//  private static final String FACTORY = "Factory";
  private static final String MODELIMPL = "Jso";
  private static final String MODULEIMPL = "Impl";
  private JClassType scopeType;
  private JClassType elementType;
  private JClassType gwtElementType;
  private JClassType stringType;
  private JClassType controllerType;
  private JClassType modelType;
  private JClassType moduleType;
//  private JClassType factoryType;
  private JClassType arrayOfType;

  @Override
  public String generate(TreeLogger logger, GeneratorContext context, String typeName)
      throws UnableToCompleteException {
    TypeOracle typeOracle = context.getTypeOracle();
    scopeType = typeOracle.findType(Scope.class.getName());
    elementType = typeOracle.findType(elemental.dom.Element.class.getName());
    gwtElementType = typeOracle.findType(com.google.gwt.dom.client.Element.class.getName());
    stringType = typeOracle.findType(String.class.getName());
    controllerType = typeOracle.findType(AngularController.class.getName());
    modelType = typeOracle.findType(Model.class.getName());
    moduleType = typeOracle.findType(AngularModule.class.getName());
//    factoryType = typeOracle.findType(Factory.class.getName());
    arrayOfType = typeOracle.findType(ArrayOf.class.getName());
    logger.log(TreeLogger.Type.DEBUG, "Generating " + typeName);
    JClassType type = typeOracle.findType(typeName);
    if (type.isAssignableTo(controllerType)) {
      return generateController(logger, context, typeName, type);
    } else if (type.isAssignableTo(scopeType)) {
      return generateScope(logger, context, type);
//      return generateScopeFactory(logger, context, type);
    } else if (type.isAssignableTo(modelType)) {
      return generateScope(logger, context, type);
//      return generateModelFactory(logger, context, type);
    } else if (type.isAssignableTo(moduleType)) {
      return generateModule(logger, context, type);
    }
    logger.log(TreeLogger.Type.ERROR, "Don't know how to create " + typeName);
    throw new UnableToCompleteException();
  }

//  private String generateScopeFactory(TreeLogger logger, GeneratorContext context,
//                                      JClassType type) throws UnableToCompleteException {
//    ClassSourceFileComposerFactory fac =
//        new ClassSourceFileComposerFactory(type.getPackage().getName(),
//            type.getName() + FACTORY);
//    fac.addImplementedInterface(factoryType.getQualifiedSourceName());
//    fac.addImport(JsJsonObject.class.getName());
//    fac.addImport(Util.class.getName());
//    PrintWriter pw = context.tryCreate(logger, type.getPackage().getName(),
//        type.getName() + FACTORY);
//    SourceWriter sw = null;
//    String typeName = type.getQualifiedSourceName() + FACTORY;
//    if (pw != null) {
//      sw = fac.createSourceWriter(context, pw);
//    }
//    if (sw == null) {
//      return typeName;
//    }
//
//    sw.indent();
//    sw.println("public native " + generateScope(logger, context, type) + " create() /*-{");
//    sw.indent();
//
//
//    sw.println("return {};");
//    sw.outdent();
//    sw.println("}-*/;");
//    sw.outdent();
//    sw.commit(logger);
//    logger.log(TreeLogger.Type.DEBUG, "Generated " + typeName);
//    return typeName;
//  }

//  private String generateModelFactory(TreeLogger logger, GeneratorContext context,
//                                      JClassType type) throws UnableToCompleteException {
//    ClassSourceFileComposerFactory fac =
//        new ClassSourceFileComposerFactory(type.getPackage().getName(),
//            type.getName() + FACTORY);
//    fac.addImplementedInterface(factoryType.getQualifiedSourceName());
//    fac.addImport(JsJsonObject.class.getName());
//    fac.addImport(Util.class.getName());
//    PrintWriter pw = context.tryCreate(logger, type.getPackage().getName(),
//        type.getName() + FACTORY);
//    SourceWriter sw = null;
//    String typeName = type.getQualifiedSourceName() + FACTORY;
//    if (pw != null) {
//      sw = fac.createSourceWriter(context, pw);
//    }
//    if (sw == null) {
//      return typeName;
//    }
//
//    sw.indent();
//    sw.println("public native " + generateModelType(logger, context, type) + " create() /*-{");
//    sw.indent();
//
//
//    sw.println("return {};");
//    sw.outdent();
//    sw.println("}-*/;");
//    sw.outdent();
//    sw.commit(logger);
//    logger.log(TreeLogger.Type.DEBUG, "Generated " + typeName);
//    return typeName;
//  }

  private String generateModule(TreeLogger logger, GeneratorContext context, JClassType type) {
    NgDepends deps = type.getAnnotation(NgDepends.class);
    String simpleName = type.getName() + MODULEIMPL;
    ClassSourceFileComposerFactory fac =
        new ClassSourceFileComposerFactory(type.getPackage().getName(),
            simpleName);
    fac.addImport(GWT.class.getName());
    fac.addImport(Util.class.getName());
    fac.addImplementedInterface(AngularModule.class.getName());
    PrintWriter pw = context.tryCreate(logger, type.getPackage().getName(),
        simpleName);
    SourceWriter sw = null;
    String typeName = type.getQualifiedSourceName() + MODULEIMPL;

    if (pw != null) {
      sw = fac.createSourceWriter(context, pw);
    }
    if (sw == null) {
      return typeName;
    }
    sw.indent();
    sw.println("public " + simpleName + "() {");
    sw.indent();
    // init(GWT.create(dep1), GWT.create(dep2))
    sw.print("init(");
    if (deps != null) {
      boolean first = true;
      for (Class clazz : deps.value()) {
        if (clazz.getAnnotation(NgInject.class) != null) {
          if (!first) {
            sw.print(",");
          } else {
            first = false;
          }
          sw.print("GWT.create(" + clazz.getName() + ".class)");
        }
      }
    }
    sw.println(");");

    sw.outdent();
    sw.println("}");
    sw.println();
    sw.println("public native void init(Object... args) /*-{");
    String modName = type.getSimpleSourceName();
    NgName ngName = type.getAnnotation(NgName.class);
    if (ngName != null) {
      modName = ngName.value();
    }

    StringBuilder outerDeps = new StringBuilder();
    NgNativeDepends nativeDeps = type.getAnnotation(NgNativeDepends.class);
    if (nativeDeps != null) {
      for (String dep : nativeDeps.value()) {
        outerDeps.append("'").append(dep).append("',");
      }
    }
    if (outerDeps.length() > 0) {
      outerDeps.setLength(outerDeps.length() - 1);//remove trailing comma
    }

    sw.println("var module = $wnd.angular.module('" + modName + "', [" + outerDeps + "]);");
    if (deps != null) {
      int i = 0;
      for (Class clazz : deps.value()) {
        NgInject ngInject = clazz.getAnnotation(NgInject.class);
        if (ngInject != null) {
          if (AngularController.class.isAssignableFrom(clazz)) {
            sw.println("args[" + i + "].@" + AngularController.class.getName() + "::register" +
                "(Lcom/google/gwt/core/client/JavaScriptObject;)(module);");
          } else {
            sw.println("module.factory('" + ngInject.name() + "', function() {");
            sw.indent();
            sw.println(" return args[" + i + "];");
            sw.outdent();
            sw.println("});");
          }
        } else if (Directive.class.isAssignableFrom(clazz)) {
          JClassType dType = context.getTypeOracle().findType(clazz.getName());

          for (JMethod method : dType.getMethods()) {
            NgDirective ngDirective = method.getAnnotation(NgDirective.class);
            if (ngDirective != null) {
              sw.print("module.directive('" + ngDirective.value() + "', " +
                  "function " + method.getName() + "(");
              JMethod initMethod = null;
              for (JMethod m : dType.getMethods()) {
                if (m == method) {
                  continue;
                }
                if (m.getName().equals("on" + Character.toUpperCase(method.getName()
                    .charAt(0)) + method.getName().substring(1))) {
                  initMethod = m;
                  break;
                }
              }
              ArrayList params = new ArrayList();
              if (initMethod != null) {
                for (JParameter param : initMethod.getParameters()) {
                  JClassType pType = param.getType().isClassOrInterface();
                  if (pType != null) {
                    NgInject pInject = pType.getAnnotation(NgInject
                        .class);

                    if (pInject != null) {
                      params.add(pInject.name());
                    }
                  }
                }
              }
              String paramString = Joiner.on(",").join(params);
              sw.println(paramString + ") {");
              sw.indent();
              sw.println("return function(scope, elem, attrs) {");
              sw.indent();
              sw.println("var directive = @" + dType.getQualifiedSourceName() + "::new()();");
              if (initMethod != null) {
                sw.println("directive." + initMethod.getJsniSignature() + "(" + paramString + ");");
              }
              sw.println("directive." + method.getJsniSignature() + "(scope, elem, attrs);");
              sw.println("};");
              sw.outdent();
              sw.outdent();
              sw.println("});");
            }
          }
        }
        i++;
      }
    }
    sw.println("}-*/;");
    sw.outdent();
    sw.commit(logger);
    return typeName;
  }

  private String generateModelType(TreeLogger logger, GeneratorContext context,
                                   JClassType modelType) throws UnableToCompleteException {
    String simpleName = modelType.getName() + MODELIMPL;
    ClassSourceFileComposerFactory fac =
        new ClassSourceFileComposerFactory(modelType.getPackage().getName(),
            simpleName);
    fac.setSuperclass(JsModelBase.class.getName() + "<" + modelType.getName() + ">");
    fac.addImport(JsonObject.class.getName());
    fac.addImport(ArrayOfString.class.getName());
    fac.addImport(JsModelBase.class.getName());
    fac.addImport(Util.class.getName());
    fac.addImplementedInterface(modelType.getQualifiedSourceName());
    PrintWriter pw = context.tryCreate(logger, modelType.getPackage().getName(),
        simpleName);
    SourceWriter sw = null;
    String typeName = modelType.getQualifiedSourceName() + MODELIMPL;

    if (pw != null) {
      sw = fac.createSourceWriter(context, pw);
    }
    if (sw == null) {
      return typeName;
    }
    generateBeanImpl(logger, context, modelType, simpleName, sw);

    sw.commit(logger);
    return typeName;
  }

  private String generateController(TreeLogger logger, GeneratorContext context, String typeName,
                                    JClassType type) throws UnableToCompleteException {
    ClassSourceFileComposerFactory fac =
        new ClassSourceFileComposerFactory(type.getPackage().getName(),
            type.getName() + IMPL);
    fac.setSuperclass(typeName);
    fac.addImport(JavaScriptObject.class.getName());
    PrintWriter pw = context.tryCreate(logger, type.getPackage().getName(), type.getName() + IMPL);
    SourceWriter sw = null;
    if (pw != null) {
      sw = fac.createSourceWriter(context, pw);
    }
    if (sw == null) {
      return typeName + IMPL;
    }
    String controllerName = type.getSimpleSourceName();
    NgInject ngInject = type.getAnnotation(NgInject.class);
    if (ngInject != null) {
      controllerName = ngInject.name();
    }
        /*
         * Generates code that looks similar to this:
         *  var self=this;
         * $wnd.TodoController = $entry(function ($scope, $element) {
         * var wrapScope = @com.google.gwt.todomvc.BodyScopeAdapter::new(Lelemental/json/JsonObject;)($scope);
         * [email protected]::setScope(Lcom/google/gwt/angular/client/Scope;)(wrapScope);
         * [email protected]::onInit(Lcom/google/gwt/angular/client/TodoScope;Lcom/google/gwt/dom/client/Element;)(wrapScope, $element);
         * $scope.doSomething = $entry(function() {
         *   return [email protected]::doSomething()();
         * });
         * });
         * $wnd.TodoController.$inject = ['$scope', '$element'];
         */
    JMethod onInitMethod = findInitMethod(type, logger);
    JClassType scopeClass = findScopeClass(onInitMethod);

    String scopeAdapter = null;
    if (scopeClass != null) {
      scopeAdapter = generateScope(logger, context, scopeClass);
    }
    // this override teaches the compiler that TodoScope has been instantiated so it is not pruned
    sw.indent();
    sw.println("protected void setScope(" + scopeAdapter + " jsoScope) { super.setScope" +
        "(jsoScope); " +
        "}");
    sw.outdent();

    sw.indent();
    sw.println("protected native void register(JavaScriptObject module) /*-{");
    sw.indent();
    sw.println("var self = this;");
    sw.print("var ctrlFunc =  $entry(function(");
    List params = declareControllerParams(onInitMethod.getParameters());
    sw.print(Joiner.on(", ").join(params));
    sw.println(") {");
    sw.indent();
    sw.println(
        "self.@" + typeName + IMPL + "::setScope" +
            "(*)($scope);");
    sw.print("self." + onInitMethod.getJsniSignature() + "(");
    String controllerParams = Joiner.on(", ").join(params);
    sw.print(controllerParams);
    sw.println(");");

    for (JMethod action : publicActionMethods(type, onInitMethod)) {
      String argString = declareArgs(action);
      sw.println("$scope." + action.getName() + " = $entry(function("
          + argString + ") {");
      sw.indent();
      sw.print(isVoidMethod(action) ? "" : "return ");
      sw.print("self." + action.getJsniSignature());
      sw.println("(" + argString + ");");
      sw.outdent();
      sw.println("});");
    }

    for (JMethod action : watchMethods(type)) {
      NgWatch watchParams = action.getAnnotation(NgWatch.class);
      String argString = declareArgs(action);
      sw.println("$scope.$watch('" + watchParams.value() + "', $entry(function("
          + argString + ") {");
      sw.indent();
      sw.print(isVoidMethod(action) ? "" : "return ");
      sw.print("self." + action.getJsniSignature());
      sw.println("(" + argString + ");");
      sw.outdent();
      sw.println("}), " + watchParams.objEq() + ");");
    }

    sw.outdent();
    sw.println("});");
    // assign controller injections
    sw.println(
        "ctrlFunc.$inject = [\"" + Joiner.on("\", " +
            "\"").join(params) + "\"];");
    sw.println("module.controller('" + controllerName + "', ctrlFunc);");
    sw.outdent();
    sw.println("}-*/;");

    sw.commit(logger);
    return typeName + IMPL;
  }

  private String declareArgs(JMethod action) {
    StringBuilder args = new StringBuilder();
    for (int i = 0; i < action.getParameters().length; i++) {
      if (i > 0) {
        args.append(", ");
      }
      args.append("arg").append(i);
    }
    return args.toString();
  }

  private boolean isVoidMethod(JMethod method) {
    return method.getReturnType() == JPrimitiveType.VOID;
  }

  private boolean typeEquals(JType type1, JType type2) {
    if (type1 == null || type2 == null) {
      return type1 == type2;
    }
    return type1.getErasedType() == type2.getErasedType();
  }

  private Collection publicActionMethods(JClassType type, JMethod onInitMethod) {
    Collection methods = new ArrayList();
    Set methodNames = new HashSet();

    while(!typeEquals(type, controllerType)) {
      for (JMethod method : type.getMethods()) {
        if (method == onInitMethod) {
          continue;
        }
        if (method.isAnnotationPresent(NgWatch.class) ||
                method.isAnnotationPresent(NgExclude.class)) {
          continue;
        }
        String name = method.getName();
        if (methodNames.contains(name)) {
          continue;
        }

        if (method.isPublic() && !method.isAbstract() && !method.isStatic()) {
          methods.add(method);
          methodNames.add(name);
        }
      }
      type = type.getSuperclass();
    }
    return methods;
  }

  private Collection watchMethods(JClassType type) {
    Collection methods = new ArrayList();
    for (JMethod method : type.getMethods()) {

      if (method.getAnnotation(NgWatch.class) == null) {
        continue;
      }

      methods.add(method);

    }
    return methods;
  }

  private boolean isSetter(JMethod method) {
    String name = method.getName();
    // traditional setFooField(type) JavaBean setter
    if (name.startsWith("set") && Character.isUpperCase(name.charAt(3))) {
      return method.getParameters().length == 1 &&
          (method.getReturnType() == JPrimitiveType.VOID || method.getReturnType() == method
              .getEnclosingType());
      // non-traditional fluent-only EnclosingType fooField(type) setter
    } else if (method.getReturnType() == method.getEnclosingType() &&
        method.getParameters().length == 1) {
      return true;
    }
    return false;
  }

  private boolean isGetter(JMethod method) {
    String name = method.getName();
    // traditional boolean isFooField() JavaBean getter
    if (name.startsWith("is") && Character.isUpperCase(name.charAt(2))) {
      return method.getReturnType().isPrimitive() == JPrimitiveType.BOOLEAN && method.getParameters().length == 0;
    // traditional Type getFooField() JavaBean getter
    } else if (name.startsWith("get") && Character.isUpperCase(name.charAt(3))) {
      return method.getParameters().length == 0;
      // non traditional Type foo() getter, needs to have paired setter to be detected correctly
    } else if (method.getParameters().length == 0) {
      // TODO: should enforce that a setter exists  to disambiguate this style of getter
      return true;
    }
    return false;
  }

  private JClassType findScopeClass(JMethod onInitMethod) {
    for (JParameter param : onInitMethod.getParameters()) {
      JClassType cType = param.getType().isClassOrInterface();
      if (isScope(cType)) {
        return cType;
      }
    }
    return null;
  }

  private String generateScope(TreeLogger logger, GeneratorContext context,
                               JClassType scopeClass)
      throws UnableToCompleteException {
    String simpleName = scopeClass.getName() + SCOPEIMPL;
    ClassSourceFileComposerFactory fac =
        new ClassSourceFileComposerFactory(scopeClass.getPackage().getName(),
            simpleName);
    fac.setSuperclass(JsScopeBase.class.getName() + "<" + scopeClass.getName() + ">");
    fac.addImport(JsonObject.class.getName());
    fac.addImport(ArrayOfString.class.getName());
    fac.addImport(JsScopeBase.class.getName());
    fac.addImport(Util.class.getName());
    fac.addImplementedInterface(scopeClass.getQualifiedSourceName());
    PrintWriter pw = context.tryCreate(logger, scopeClass.getPackage().getName(),
        simpleName);
    SourceWriter sw = null;
    String typeName = scopeClass.getQualifiedSourceName() + SCOPEIMPL;

    if (pw != null) {
      sw = fac.createSourceWriter(context, pw);
    }
    if (sw == null) {
      return typeName;
    }
    generateBeanImpl(logger, context, scopeClass, simpleName, sw);

    sw.commit(logger);
    return typeName;
  }

  private void generateBeanImpl(TreeLogger logger, GeneratorContext context, JClassType scopeClass,
                                String simpleName, SourceWriter sw)
      throws UnableToCompleteException {
    // constructor
    sw.println("protected " + simpleName + "() {}");

    /*Set types = new HashSet();
    Queue queue = new LinkedList();
    queue.add(scopeClass);
    while(!queue.isEmpty()) {
      JClassType type = queue.poll();
      types.add(type);
      for (JClassType interfaceType : type.getImplementedInterfaces()) {
        if (!types.contains(interfaceType) &&
            !typeEquals(interfaceType, modelType) && !typeEquals(interfaceType, scopeType)) {
          queue.add(interfaceType);
        }
      }
    }
    for (JClassType type : types) { }
    */

    // getters and setters
    for (JMethod method : scopeClass.getMethods()) {
      if (isGetter(method)) {
        JPrimitiveType pType = method.getReturnType().isPrimitive();
        if (pType != null) {
          if (pType != JPrimitiveType.BOOLEAN) {
            sw.println("final public " + pType.getSimpleSourceName() + " " + method.getName() + "() {");
            sw.indent();
            sw.println("return (" + pType.getSimpleSourceName() + ") json().getNumber(" +
                quotedFieldName(method) + ");");
            sw.outdent();
            sw.println("}");
          } else if (pType == JPrimitiveType.BOOLEAN) {
            sw.println("final public boolean " + method.getName() + "() {");
            sw.indent();
            sw.println("return json().getBoolean(" + quotedFieldName(method) + ");");
            sw.outdent();
            sw.println("}");
          } else {
            // shouldn't reach here (only void left)
            throw new UnableToCompleteException();
          }
        } else {
          JClassType cType = method.getReturnType().isClassOrInterface();
          if (cType.isAssignableTo(stringType)) {
            sw.println("final public String " + method.getName() + "() {");
            sw.indent();
            sw.println("return json().getString(" + quotedFieldName(method) + ");");
            sw.outdent();
            sw.println("}");
          } else {
            sw.println(
                "final public " + method.getReturnType().getParameterizedQualifiedSourceName() +
                    " " + method.getName() + "() {");
            sw.indent();
            generateDependentType(logger, context, method.getReturnType().isClassOrInterface());
            sw.println("return Util.reinterpret_cast(json().get(" + quotedFieldName(method) + "));");
            sw.outdent();
            sw.println("}");
            // handle arrays
            // handle nested models
          }
        }
      } else if (isSetter(method)) {
        JPrimitiveType pType = method.getParameters()[0].getType().isPrimitive();
        if (pType != null) {
          if (pType != JPrimitiveType.BOOLEAN) {
            sw.println(
                "final public " + fluentOrVoid(method) + " " + method.getName() + "(" + pType
                    .getSimpleSourceName() + " arg) {");
            sw.indent();
            sw.println("json().put(" + quotedFieldName(method) + ", arg);");
            maybeFluentReturn(sw, method);
            sw.outdent();
            sw.println("}");
          } else if (pType == JPrimitiveType.BOOLEAN) {
            sw.println("final public " + fluentOrVoid(method) + " " + method.getName() + "" +
                "(boolean arg) {");
            sw.indent();
            sw.println("json().put(" + quotedFieldName(method) + ", arg);");
            maybeFluentReturn(sw, method);
            sw.outdent();
            sw.println("}");
          } else {
            // shouldn't reach here (only void left)
            throw new UnableToCompleteException();
          }
        } else {
          JClassType cType = method.getParameters()[0].getType().isClassOrInterface();
          if (cType.isAssignableTo(stringType)) {
            sw.println(
                "final public " + fluentOrVoid(method) + " " + method.getName() + "(String arg) {");
            sw.indent();
            sw.println("json().put(" + quotedFieldName(method) + ", arg);");
            maybeFluentReturn(sw, method);
            sw.outdent();
            sw.println("}");
          } else {
            String paramType =
                method.getParameters()[0].getType().getParameterizedQualifiedSourceName();
            sw.println("final public " + fluentOrVoid(method) + " " + method.getName() + "(" +
                paramType + " arg) {");
            sw.indent();
            generateDependentType(logger, context, method.getReturnType().isClassOrInterface());

            String arg = "Util.reinterpret_cast(arg)";
            sw.println("json().put(" + quotedFieldName(method) + ", " + arg + ");");
            maybeFluentReturn(sw, method);
            sw.outdent();
            sw.println("}");
            // handle arrays
            // handle nested models
          }
        }
      }
    }
  }

  private void generateDependentType(TreeLogger logger, GeneratorContext context,
                                     JClassType classOrInterface) throws UnableToCompleteException {
    if (classOrInterface != null) {
      if (classOrInterface.isAssignableTo(scopeType)) {
        generateScope(logger, context, classOrInterface);
      } else if (classOrInterface.isAssignableTo(modelType)) {
        generateModelType(logger, context, classOrInterface);
      } else if (classOrInterface.isAssignableTo(arrayOfType) &&
          classOrInterface.isParameterized() != null) {
        generateDependentType(logger, context, classOrInterface.isParameterized().getTypeArgs()[0]);
      }
    }
  }

  private void maybeFluentReturn(SourceWriter sw, JMethod method) {
    if (method.getReturnType() != JPrimitiveType.VOID) {
      sw.println("return this;");
    }
  }

  private String fluentOrVoid(JMethod method) {
    return method.getReturnType() != JPrimitiveType.VOID ? method.getEnclosingType()
        .getSimpleSourceName() : "void";
  }

  private String quotedFieldName(JMethod method) {
    return "\"" + getPropertyName(method) + "\"";
  }

  private String getPropertyName(JMethod method) {
    String name = method.getName();
    name = isBeanStyle(method) ? name.substring(name.startsWith("is") ? 2 : 3) : name;
    return Character.toLowerCase(name.charAt(0)) + name.substring(1);
  }

  private boolean isBeanStyle(JMethod method) {
    return isGetter(method) || isSetter(method);
  }

  private JMethod findInitMethod(JClassType type, TreeLogger logger)
      throws UnableToCompleteException {
    JMethod onInit = null;
    for (JMethod method : type.getMethods()) {
      if (method.getName().equals("onInit")) {
        if (onInit == null) {
          onInit = method;
        } else {
          logger.log(TreeLogger.Type.ERROR, type.getName() + " has two onInit methods.");
          throw new UnableToCompleteException();
        }
      }
    }
    return onInit;
  }

  private List declareControllerParams(JParameter[] parameters) {
    List params = new ArrayList();
    for (JParameter param : parameters) {
      JClassType type = param.getType().isClassOrInterface();
      if (isScope(type)) {
        params.add("$scope");
      } else if (isElement(type)) {
        params.add("$element");
      } else {
        NgInject ngInject = type.getAnnotation(NgInject.class);
        if (ngInject != null) {
          params.add(ngInject.name());
        }
      }
    }
    return params;
  }

  private boolean isElement(JClassType ctype) {
    return ctype != null && (ctype.isAssignableTo(elementType)
        || ctype.isAssignableTo(gwtElementType));
  }

  private boolean isScope(JClassType ctype) {
    return ctype != null && ctype.isAssignableTo(scopeType);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy