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

com.google.javascript.jscomp.FieldCleanupPass Maven / Gradle / Ivy

Go to download

Closure Compiler is a JavaScript optimizing compiler. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls. It is used in many of Google's JavaScript apps, including Gmail, Google Web Search, Google Maps, and Google Docs.

There is a newer version: v20240317
Show newest version
/*
 * Copyright 2011 The Closure Compiler Authors.
 *
 * 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.javascript.jscomp;

import com.google.javascript.jscomp.NodeTraversal.AbstractShallowCallback;
import com.google.javascript.jscomp.NodeTraversal.Callback;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.jstype.JSType;
import com.google.javascript.rhino.jstype.JSTypeRegistry;
import com.google.javascript.rhino.jstype.ObjectType;

/**
 * A CleanupPass implementation that will remove all field declarations on
 * JSTypes contributed by the original file.
 * 

* This pass is expected to clear out declarations contributed to any JSType, * even if the constructor declaration is not provided in the file being * updated. */ public final class FieldCleanupPass implements HotSwapCompilerPass { private final AbstractCompiler compiler; public FieldCleanupPass(AbstractCompiler compiler) { this.compiler = compiler; } @Override public void hotSwapScript(Node scriptRoot, Node originalRoot) { String srcName = originalRoot.getSourceFileName(); Callback cb = new QualifiedNameSearchTraversal(compiler.getTypeRegistry(), srcName); NodeTraversal.traverse(compiler, originalRoot, cb); } @Override public void process(Node externs, Node root) { // FieldCleanupPass should not do work during process. } /** * Search for fields to cleanup by looking for nodes in the tree which are * root nodes of qualified names and getting the final token of the qualified * name as a candidate field. *

* Once a candidate field is found, ask the {@code JSTypeRegistry} for all * JSTypes that have a field with the same name, and check if the field on * that type is defined in the file the compiler is cleaning up. If so, remove * the field, and update the {@code JSTypeRegistry} to no longer associate the * type with the field. *

* This algorithm was chosen for simplicity and is less than optimally * efficient in two ways: *

* 1) All types with a matching field name are iterated over (when only types * that extend or implement the JSType indicated by the containing object in * the found Qualified Name need to be checked). *

* 2) All Qualified Names are checked, even those which are not L-Values or * single declarations of an Type Expression. In general field should only be * declared as part of an assignment ('ns.Type.a = 3;') or stand alone name * declaration ('ns.Type.a;'). */ static class QualifiedNameSearchTraversal extends AbstractShallowCallback { private final JSTypeRegistry typeRegistry; private final String srcName; public QualifiedNameSearchTraversal( JSTypeRegistry typeRegistry, String srcName) { this.typeRegistry = typeRegistry; this.srcName = srcName; } @Override public void visit(NodeTraversal t, Node n, Node p) { // We are a root GetProp if (n.isGetProp() && !p.isGetProp()) { String propName = getFieldName(n); JSType type = n.getFirstChild().getJSType(); if (type == null || type.toObjectType() == null) { // Note cases like .field return; } removeProperty(type.toObjectType(), propName); } } /** * Removes a given property from a type and updates type-registry. * * @param type the object type to be updated, should not be null * @param propName the property to remove */ private void removeProperty(ObjectType type, String propName) { Node pNode = type.getPropertyNode(propName); if (pNode != null && srcName.equals(pNode.getSourceFileName())) { typeRegistry.unregisterPropertyOnType(propName, type); type.removeProperty(propName); } } private static String getFieldName(Node n) { return n.getLastChild().getString(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy