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

com.google.javascript.jscomp.serialization.ColorSerializer 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 2021 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.serialization;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.javascript.jscomp.colors.Color;
import com.google.javascript.jscomp.colors.ColorId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.function.Predicate;
import org.jspecify.nullness.Nullable;

/**
 * Serializes `Color`s and information about them into a `TypePool`.
 *
 * 

Client code should call `addColor()` for each of the colors it wants to have included in the * `TypePool`, then call `generateTypePool()` to get the result. */ class ColorSerializer { private final SerializationOptions serializationMode; /** * Used to find the index at which a `String` will appear in the `StringPoolProto` that will * eventually be serialized with the `TypePool` generated by this `ColorSerializer`. */ private final Function getStringPoolIndexFn; /** Only property names that pass this predicate will be serialized. */ private final Predicate propertyFilter; /** * Stores the `Integer` values assigned to `Color`s as they are added for serialization, so they * can be looked up and used for references between the output `TypeProto`s. */ private final HashMap colorIdToTypePointer = new HashMap<>(); /** * Stores the `Color`s to be serialized in the order they will be serialized. * *

This is used as a worklist when the `TypePool` is generated. */ private final ArrayList colorsInSerializedOrder = new ArrayList<>(); /** * Create a ColorSerializer. * * @param serializationMode determines what parts of the `TypePool` proto to fill in. * @param stringPoolIndexFn Used to request an integer index to encode in place of string value. * The `TypePool` generated by this object will use these indices, so a `StringPoolProto` that * contains the actual `String` values needs to be serialized along with it. * @param propertyFilter Property names for which this returns `false` will not be included in the * generated `TypeProto`s. */ ColorSerializer( SerializationOptions serializationMode, Function stringPoolIndexFn, Predicate propertyFilter) { this.serializationMode = serializationMode; this.getStringPoolIndexFn = stringPoolIndexFn; this.propertyFilter = propertyFilter; // We must pre-populate the type pointers with the few axiomatic colors that won't actually // be serialized. These types are required to get the first few offsets in the order they // are specified by `TypePointers.OFFSET_TO_AXIOMATIC_COLOR`. for (Color color : TypePointers.OFFSET_TO_AXIOMATIC_COLOR) { addColor(color); } } /** * Add a collection of `Color`s to the list of those that must be serialized. * * @param colors to be serialized * @return list of `Integer`s that will refer to the input `Color`s in the TypePool` that this * object will create. The order will match the order of the input `Color`s. */ ImmutableList addColors(Collection colors) { final ImmutableList.Builder builder = ImmutableList.builder(); for (Color color : colors) { builder.add(addColor(color)); } return builder.build(); } /** * Add `color` to the list of those that must be serialized (if it wasn't already there) and * return the `Integer` value that will refer to it in the `TypePool` that this object will * create. */ int addColor(Color color) { return colorIdToTypePointer.computeIfAbsent( color.getId(), (unusedKey) -> { final int index = colorsInSerializedOrder.size(); colorsInSerializedOrder.add(color); return index; }); } /** * Generate a `TypePool` proto built from the previously added `Color`s and the arguments supplied * to this method. * * @param getDisambiguationSupertypesFn Given a `Color` return a set of `Color`s it inherits from. * @param getMismatchSourceRefsFn May be `null` if this `serializationMode` is `SKIP_DEBUG_INFO`. * Otherwise, this function must provide a set of all the source reference strings indicating * code locations where the given `Color` encountered a type mismatch. * @return a new `TypePool` proto */ TypePool generateTypePool( Function> getDisambiguationSupertypesFn, @Nullable Function> getMismatchSourceRefsFn) { final TypePool.Builder typePoolBuilder = TypePool.newBuilder(); // We use an indexed loop here for 2 reasons. // 1. We must skip serialization of the axiomatic colors that start our list of serialized // colors. // 2. The logic in the loop may end up adding more colors to the list. It's often hard to tell // what effect changing an iterable will have on an iteration that is in progress. for (int i = TypePointers.untrimOffset(0); i < colorsInSerializedOrder.size(); i++) { final Color color = colorsInSerializedOrder.get(i); final Integer typePointer = colorIdToTypePointer.get(color.getId()); typePoolBuilder.addType(generateTypeProto(color)); for (Color supertype : getDisambiguationSupertypesFn.apply(color)) { typePoolBuilder .addDisambiguationEdgesBuilder() .setSubtype(typePointer) .setSupertype(addColor(supertype)); } } if (serializationMode != SerializationOptions.SKIP_DEBUG_INFO) { checkNotNull(getMismatchSourceRefsFn); final TypePool.DebugInfo.Builder debugInfoBuilder = typePoolBuilder.getDebugInfoBuilder(); // Construct a map from source reference string to type pointers, // because that's the way the Mismatch protos work. // Construct entries only for those colors that we have actually serialized in order to save // space. final LinkedHashMap> srcRefToTypePointerList = new LinkedHashMap<>(); for (Color color : colorsInSerializedOrder) { final Integer typePointer = colorIdToTypePointer.get(color.getId()); for (String srcRef : getMismatchSourceRefsFn.apply(color)) { final ArrayList typePointerList = srcRefToTypePointerList.computeIfAbsent(srcRef, (key) -> new ArrayList<>()); typePointerList.add(typePointer); } } // Now use the map to build the Mismatch protos and put them into the debug info. for (Entry> entry : srcRefToTypePointerList.entrySet()) { debugInfoBuilder .addMismatchBuilder() .setSourceRef(entry.getKey()) .addAllInvolvedColor(entry.getValue()); } } return typePoolBuilder.build(); } private TypeProto generateTypeProto(Color color) { final TypeProto.Builder typeProtoBuilder = TypeProto.newBuilder(); if (color.isUnion()) { typeProtoBuilder.getUnionBuilder().addAllUnionMember(addColors(color.getUnionElements())); } else { final ObjectTypeProto.Builder objectTypeProtoBuilder = typeProtoBuilder.getObjectBuilder(); objectTypeProtoBuilder .setIsInvalidating(color.isInvalidating()) .setUuid(color.getId().asByteString()) .setPropertiesKeepOriginalName(color.getPropertiesKeepOriginalName()) .addAllInstanceType(addColors(color.getInstanceColors())) .addAllPrototype(addColors(color.getPrototypes())) .setMarkedConstructor(color.isConstructor()) .addAllOwnProperty(getOwnPropertyStringPoolOffsets(color)) .setClosureAssert(color.isClosureAssert()); } return typeProtoBuilder.build(); } private ImmutableList getOwnPropertyStringPoolOffsets(Color color) { final ImmutableList.Builder builder = ImmutableList.builder(); for (String ownProperty : color.getOwnProperties()) { // The client code may know that some properties are unused in the AST, so there's no need // to serialize them. if (propertyFilter.test(ownProperty)) { builder.add(getStringPoolIndexFn.apply(ownProperty)); } } return builder.build(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy