Package com.google.gwt.dev.shell.mac

Source Code of com.google.gwt.dev.shell.mac.StaticWebKitDispatchAdapter

/*******************************************************************************
* Copyright 2011 Google Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* 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.shell.mac;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import com.google.gwt.dev.javac.CompilationUnit;
import com.google.gwt.dev.javac.JsniMethod;
import com.google.gwt.dev.shell.CompilingClassLoader;
import com.google.gwt.dev.shell.Jsni;
import com.google.gwt.dev.util.JsniRef;

/**
* The implementation of {@link WebKitDispatchAdapter} which able to provide the references to static fields
* in jsni code.
*
* @author mitin_aa
*/
final class StaticWebKitDispatchAdapter extends WebKitDispatchAdapter {
  private static final String[] EMPTY_STRING_ARRAY = new String[0];
  private final Stack<String> m_executionStack = new Stack<String>();
  private final Map<Integer, String[]> m_fieldsMap = new HashMap<Integer, String[]>();
  ////////////////////////////////////////////////////////////////////////////
  //
  // Constructor
  //
  ////////////////////////////////////////////////////////////////////////////
  StaticWebKitDispatchAdapter(CompilingClassLoader cl) {
    super(cl);
  }
  ////////////////////////////////////////////////////////////////////////////
  //
  // Fields list support
  //
  ////////////////////////////////////////////////////////////////////////////
  @Override
  public String[] getFields() {
    try {
      if (m_executionStack.empty()) {
        return EMPTY_STRING_ARRAY;
      }
      String currentMethod = m_executionStack.peek();
      int dispId = classLoader.getDispId(currentMethod);
      if (dispId == -1) {
        return EMPTY_STRING_ARRAY;
      }
      String[] fieldReferences = m_fieldsMap.get(dispId);
      if (fieldReferences == null) {
        String[] fieldReferencesGot = getJsniFieldReferences(currentMethod);
        fieldReferences = new String[fieldReferencesGot.length];
        int index = 0;
        for (int i = 0; i < fieldReferencesGot.length; i++) {
          int fieldDispId = classLoader.getDispId(fieldReferencesGot[i]);
          if (fieldDispId > 0) {
            fieldReferences[index++] = Jsni.WBP_MEMBER + String.valueOf(fieldDispId);
          }
        }
        System.arraycopy(fieldReferences, 0, fieldReferences = new String[index], 0, index);
        m_fieldsMap.put(dispId, fieldReferences);
      }
      return fieldReferences;
    } catch (Throwable e) {
      // capture all exceptions to prevent them to go into native code
      e.printStackTrace();
      return EMPTY_STRING_ARRAY;
    }
  }
  /**
   * Searches for method body for any references to static fields and return the array of references found.
   *
   * @param methodSignature
   *            the method jsni signature which body will be searched for field references.
   */
  private String[] getJsniFieldReferences(String methodSignature) {
    JsniRef parsed = JsniRef.parse(methodSignature);
    if (parsed != null) {
      String lookupClassName = parsed.className().replace('.', '/');
      CompilationUnit compilationUnit = classLoader.getUnitForClassName(lookupClassName);
      if (compilationUnit != null) {
        for (JsniMethod jsniMethod : compilationUnit.getJsniMethods()) {
          if (jsniMethod.name().equals(methodSignature)) {
            String source = jsniMethod.function().toSource();
            return parseJsniFieldReferences(source);
          }
        }
      }
    }
    return EMPTY_STRING_ARRAY;
  }
  /**
   * Parses the method body and looks up for static field references.
   *
   * @return the field references as the array of {@link String}.
   */
  private String[] parseJsniFieldReferences(String code) {
    Set<String> fieldRefs = new HashSet<String>();
    if (code != null && code.indexOf('@') != -1) {
      while (true) {
        int atIndex = code.indexOf('@');
        if (atIndex == -1) {
          break;
        }
        //
        int closeIndex;
        String memberSignature;
        {
          closeIndex = atIndex;
          for (;; closeIndex++) {
            char c = code.charAt(closeIndex);
            if (c == '(') {
              closeIndex = code.indexOf(')', closeIndex) + 1;
              break;
            }
            if (c != '@'
              && c != '.'
              && c != ':'
              && !Character.isLetter(c)
              && !Character.isDigit(c)) {
              break;
            }
          }
          memberSignature = code.substring(atIndex, closeIndex);
        }
        // check for 'name.@XXX' and skip it
        if (code.charAt(atIndex - 1) != '.') {
          // do additional check using Jsni.parse() method
          JsniRef parsedSignature = JsniRef.parse(memberSignature);
          if (parsedSignature != null && parsedSignature.isField()) {
            String fieldName = parsedSignature.memberName();
            int referenceIndex = fieldName.indexOf('.');
            if (referenceIndex != -1) {
              fieldName = fieldName.substring(0, referenceIndex);
            }
            fieldRefs.add("@" + parsedSignature.className() + "::" + fieldName);
          }
        }
        code = code.substring(closeIndex, code.length());
      }
    }
    return fieldRefs.toArray(new String[fieldRefs.size()]);
  }
  public void push(String method) {
    m_executionStack.push(method);
  }
  public String pop() {
    return m_executionStack.pop();
  }
}
TOP

Related Classes of com.google.gwt.dev.shell.mac.StaticWebKitDispatchAdapter

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.