Package com.google.gwt.dev.js

Source Code of com.google.gwt.dev.js.JsPrettyNamer

/*
* Copyright 2007 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.js;

import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsScope;

import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
* A namer that uses short, readable idents to maximize reability.
*/
public class JsPrettyNamer {

  public static void exec(JsProgram program) {
    new JsPrettyNamer(program).execImpl();
  }

  /**
   * Communicates to a parent scope all the idents used by all child scopes.
   */
  private Set<String> childIdents = null;

  private final JsProgram program;
 
  /**
   * A map containing the next integer to try as an identifier suffix for
   * a given JsScope.
   */
  private IdentityHashMap<JsScope,HashMap<String,Integer>> startIdentForScope =
    new IdentityHashMap<JsScope, HashMap<String,Integer>>();

  public JsPrettyNamer(JsProgram program) {
    this.program = program;
  }

  private void execImpl() {
    visit(program.getRootScope());
  }

  private boolean isLegal(JsScope scope, Set<String> childIdents, String newIdent) {
    if (JsKeywords.isKeyword(newIdent)) {
      return false;
    }
    if (childIdents.contains(newIdent)) {
      // one of my children already claimed this ident
      return false;
    }
    /*
     * Never obfuscate a name into an identifier that conflicts with an existing
     * unobfuscatable name! It's okay if it conflicts with an existing
     * obfuscatable name; that name will get obfuscated out of the way.
     */
    return (scope.findExistingUnobfuscatableName(newIdent) == null);
  }

  private void visit(JsScope scope) {
    HashMap<String,Integer> startIdent = startIdentForScope.get(scope);
    if (startIdent == null) {
      startIdent = new HashMap<String,Integer>();
      startIdentForScope.put(scope, startIdent);
    }
   
    // Save off the childIdents which is currently being computed for my parent.
    Set<String> myChildIdents = childIdents;

    /*
     * Visit my children first. Reset childIdents so that my children will get a
     * clean slate: I do not communicate to my children.
     */
    childIdents = new HashSet<String>();
    List<JsScope> children = scope.getChildren();
    for (Iterator<JsScope> it = children.iterator(); it.hasNext();) {
      visit(it.next());
    }

    JsRootScope rootScope = program.getRootScope();
    if (scope == rootScope) {
      return;
    }

    // Visit all my idents.
    for (Iterator<JsName> it = scope.getAllNames(); it.hasNext();) {
      JsName name = it.next();
      if (!name.isObfuscatable()) {
        // Unobfuscatable names become themselves.
        name.setShortIdent(name.getIdent());
        continue;
      }

      String newIdent = name.getShortIdent();
      if (!isLegal(scope, childIdents, newIdent)) {
        String checkIdent;
       
        // Start searching using a suffix hint stored in the scope.
        // We still do a search in case there is a collision with
        // a user-provided identifier
        Integer s = startIdent.get(newIdent);
        int suffix = (s == null) ? 0 : s.intValue();
        do {
          checkIdent = newIdent + "_" + suffix++;
        } while (!isLegal(scope, childIdents, checkIdent));
        startIdent.put(newIdent, suffix);
        name.setShortIdent(checkIdent);
      } else {
        // nothing to do; the short name is already good
      }
      childIdents.add(name.getShortIdent());
    }
    myChildIdents.addAll(childIdents);
    childIdents = myChildIdents;
  }
}
TOP

Related Classes of com.google.gwt.dev.js.JsPrettyNamer

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.