Package com.google.gwt.dev.jjs.impl

Source Code of com.google.gwt.dev.jjs.impl.JsniRefLookup$ErrorReporter

/*
* Copyright 2009 Google Inc.
*
* 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.
*/
package com.google.gwt.dev.jjs.impl;

import com.google.gwt.dev.jjs.ast.HasEnclosingType;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.util.JsniRef;

import java.util.LinkedList;
import java.util.Queue;
import java.util.TreeSet;

/**
* A utility class that can look up a {@link JsniRef} in a {@link JProgram}.
*/
public class JsniRefLookup {

  /**
   * A callback used to indicate the reason for a failed JSNI lookup.
   */
  public interface ErrorReporter {
    void reportError(String error);
  }

  /**
   * Look up a JSNI reference.
   *
   * @param ref The reference to look up
   * @param program The program to look up the reference in
   * @param errorReporter A callback used to indicate the reason for a failed
   *          JSNI lookup
   * @return The item referred to, or <code>null</code> if it could not be
   *         found. If the return value is <code>null</code>,
   *         <code>errorReporter</code> will have been invoked.
   */
  public static HasEnclosingType findJsniRefTarget(JsniRef ref,
      JProgram program, JsniRefLookup.ErrorReporter errorReporter) {
    String className = ref.className();
    JType type = null;
    if (!className.equals("null")) {
      type = program.getTypeFromJsniRef(className);
      if (type == null) {
        errorReporter.reportError("Unresolvable native reference to type '"
            + className + "'");
        return null;
      }
    }

    if (!ref.isMethod()) {
      // look for a field
      String fieldName = ref.memberName();
      if (type == null) {
        if (fieldName.equals("nullField")) {
          return program.getNullField();
        }

      } else if (fieldName.equals("class")) {
        JClassLiteral lit = program.getLiteralClass(type);
        return lit.getField();

      } else if (type instanceof JPrimitiveType) {
        errorReporter.reportError("May not refer to fields on primitive types");
        return null;

      } else if (type instanceof JArrayType) {
        errorReporter.reportError("May not refer to fields on array types");
        return null;

      } else {
        for (JField field : ((JDeclaredType) type).getFields()) {
          if (field.getName().equals(fieldName)) {
            return field;
          }
        }
      }

      errorReporter.reportError("Unresolvable native reference to field '"
          + fieldName + "' in type '" + className + "'");
      return null;

    } else if (type instanceof JPrimitiveType) {
      errorReporter.reportError("May not refer to methods on primitive types");
      return null;

    } else {
      // look for a method
      TreeSet<String> almostMatches = new TreeSet<String>();
      String methodName = ref.memberName();
      String jsniSig = ref.memberSignature();
      if (type == null) {
        if (jsniSig.equals("nullMethod()")) {
          return program.getNullMethod();
        }
      } else {
        Queue<JDeclaredType> workList = new LinkedList<JDeclaredType>();
        workList.add((JDeclaredType) type);
        while (!workList.isEmpty()) {
          JDeclaredType cur = workList.poll();
          for (JMethod method : cur.getMethods()) {
            if (method.getName().equals(methodName)) {
              String sig = JProgram.getJsniSig(method);
              if (sig.equals(jsniSig)) {
                return method;
              } else if (sig.startsWith(jsniSig) && jsniSig.endsWith(")")) {
                return method;
              } else {
                almostMatches.add(sig);
              }
            }
          }
          if (cur.getSuperClass() != null) {
            workList.add(cur.getSuperClass());
          }
          workList.addAll(cur.getImplements());
        }
      }

      if (almostMatches.isEmpty()) {
        errorReporter.reportError("Unresolvable native reference to method '"
            + methodName + "' in type '" + className + "'");
        return null;
      } else {
        StringBuilder suggestList = new StringBuilder();
        String comma = "";
        for (String almost : almostMatches) {
          suggestList.append(comma + "'" + almost + "'");
          comma = ", ";
        }
        errorReporter.reportError("Unresolvable native reference to method '"
            + methodName + "' in type '" + className + "' (did you mean "
            + suggestList.toString() + "?)");
        return null;
      }
    }
  }

}
TOP

Related Classes of com.google.gwt.dev.jjs.impl.JsniRefLookup$ErrorReporter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.