Skip to content

Commit 7507d26

Browse files
lauraharkercopybara-github
authored andcommitted
Add simple optimization type ("color") system
This is not full-featured and can be expanded later on. PiperOrigin-RevId: 321186327
1 parent 68d62fe commit 7507d26

File tree

7 files changed

+342
-0
lines changed

7 files changed

+342
-0
lines changed

BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ j2cl_library(
4141
"src/com/google/debugging/**/*.js",
4242
"src/com/google/javascript/rhino/**/*.java",
4343
"src/com/google/javascript/jscomp/*.java",
44+
"src/com/google/javascript/jscomp/colors/**/*.java",
4445
"src/com/google/javascript/jscomp/deps/**/*.java",
4546
"src/com/google/javascript/jscomp/lint/**/*.java",
4647
"src/com/google/javascript/jscomp/ijs/**/*.java",
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2020 The Closure Compiler Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.javascript.jscomp.colors;
18+
19+
import com.google.common.collect.ImmutableCollection;
20+
21+
/** A simplified version of a Closure or TS type for use by optimizations */
22+
public interface Color {
23+
24+
boolean isPrimitive();
25+
26+
boolean isUnion();
27+
28+
ImmutableCollection<Color> getAlternates();
29+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2020 The Closure Compiler Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.javascript.jscomp.colors;
18+
19+
import com.google.common.collect.ImmutableCollection;
20+
21+
/** Value types that are a) not user-defined and b) do not need individual classes */
22+
public enum PrimitiveColor implements Color {
23+
// JS primitive types
24+
NUMBER,
25+
STRING,
26+
SYMBOL,
27+
NULL_OR_VOID,
28+
BIGINT,
29+
// Equivalent to Closure '*'/'?' and TS unknown/any
30+
UNKNOWN;
31+
32+
@Override
33+
public boolean isPrimitive() {
34+
return true;
35+
}
36+
37+
@Override
38+
public boolean isUnion() {
39+
return false;
40+
}
41+
42+
@Override
43+
public ImmutableCollection<Color> getAlternates() {
44+
// In theory we could consider a primitive a union of a single value. It's not clear whether
45+
// that would be simpler or not.
46+
throw new UnsupportedOperationException("Can only call getAlternates() on unions");
47+
}
48+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2020 The Closure Compiler Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.javascript.jscomp.colors;
18+
19+
import static com.google.common.base.Preconditions.checkArgument;
20+
21+
import com.google.auto.value.AutoValue;
22+
import com.google.common.collect.ImmutableCollection;
23+
import com.google.common.collect.ImmutableSet;
24+
25+
/** A set of multiple {@link Color}s. */
26+
@AutoValue
27+
public abstract class UnionColor implements Color {
28+
29+
static UnionColor create(ImmutableSet<Color> alternates) {
30+
checkArgument(
31+
alternates.size() > 1,
32+
"UnionColor alternates should have more than one element, found %s",
33+
alternates);
34+
// Flatten other UnionColors
35+
ImmutableSet.Builder<Color> flatAlternates = ImmutableSet.builder();
36+
for (Color alternate : alternates) {
37+
if (alternate.isUnion()) {
38+
flatAlternates.addAll(alternate.getAlternates());
39+
} else {
40+
flatAlternates.add(alternate);
41+
}
42+
}
43+
return new AutoValue_UnionColor(flatAlternates.build());
44+
}
45+
46+
@Override
47+
public boolean isPrimitive() {
48+
return false;
49+
}
50+
51+
@Override
52+
public boolean isUnion() {
53+
return true;
54+
}
55+
56+
@Override
57+
public abstract ImmutableCollection<Color> getAlternates();
58+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2020 The Closure Compiler Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.javascript.jscomp.testing;
18+
19+
import static com.google.common.truth.Truth.assertAbout;
20+
21+
import com.google.common.truth.FailureMetadata;
22+
import com.google.common.truth.Subject;
23+
import com.google.javascript.jscomp.colors.Color;
24+
import javax.annotation.Nullable;
25+
26+
/** Subject for {@link Color} */
27+
public final class ColorSubject extends Subject {
28+
29+
@Nullable private final Color actual;
30+
31+
private ColorSubject(FailureMetadata metadata, @Nullable Color actual) {
32+
super(metadata, actual);
33+
this.actual = actual;
34+
}
35+
36+
public static Factory<ColorSubject, Color> colors() {
37+
return ColorSubject::new;
38+
}
39+
40+
public static ColorSubject assertThat(@Nullable Color actual) {
41+
return assertAbout(colors()).that(actual);
42+
}
43+
44+
private Color actualNonNull() {
45+
isNotNull();
46+
return actual;
47+
}
48+
49+
// Custom assertions
50+
51+
public void isPrimitive() {
52+
check("isPrimitive").that(actualNonNull().isPrimitive()).isTrue();
53+
}
54+
55+
public void isUnion() {
56+
check("isUnion").that(actualNonNull().isUnion()).isTrue();
57+
}
58+
59+
public void hasAlternates(Color... alternates) {
60+
isUnion();
61+
check("getAlternates().containsExactly()")
62+
.that(actualNonNull().getAlternates())
63+
// cast to Object[] to suppress warning about varargs vs. non-varargs call confusion
64+
.containsExactly((Object[]) alternates);
65+
}
66+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2020 The Closure Compiler Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.javascript.jscomp.colors;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
import static com.google.javascript.jscomp.testing.ColorSubject.assertThat;
21+
import static com.google.javascript.rhino.testing.Asserts.assertThrows;
22+
23+
import org.junit.Test;
24+
import org.junit.runner.RunWith;
25+
import org.junit.runners.JUnit4;
26+
27+
@RunWith(JUnit4.class)
28+
public class PrimitiveColorTest {
29+
@Test
30+
public void isPrimitiveReturnsTrue() {
31+
assertThat((Color) PrimitiveColor.NUMBER).isPrimitive();
32+
assertThat((Color) PrimitiveColor.UNKNOWN).isPrimitive();
33+
}
34+
35+
@Test
36+
public void isUnionReturnsFalse() {
37+
assertThat(PrimitiveColor.NUMBER.isUnion()).isFalse();
38+
assertThat(PrimitiveColor.NULL_OR_VOID.isUnion()).isFalse();
39+
assertThat(PrimitiveColor.UNKNOWN.isUnion()).isFalse();
40+
}
41+
42+
@Test
43+
public void getAlternatesIsNotAllowed() {
44+
assertThrows(Exception.class, PrimitiveColor.NUMBER::getAlternates);
45+
}
46+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2020 The Closure Compiler Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.javascript.jscomp.colors;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
import static com.google.javascript.jscomp.testing.ColorSubject.assertThat;
21+
import static com.google.javascript.rhino.testing.Asserts.assertThrows;
22+
23+
import com.google.common.collect.ImmutableSet;
24+
import org.junit.Test;
25+
import org.junit.runner.RunWith;
26+
import org.junit.runners.JUnit4;
27+
28+
@RunWith(JUnit4.class)
29+
public class UnionColorTest {
30+
@Test
31+
public void isPrimitiveReturnsFalse() {
32+
UnionColor numberOrString =
33+
UnionColor.create(ImmutableSet.of(PrimitiveColor.STRING, PrimitiveColor.NUMBER));
34+
35+
assertThat(numberOrString.isPrimitive()).isFalse();
36+
}
37+
38+
@Test
39+
public void isUnionHandlesReturnsTrue() {
40+
UnionColor union =
41+
UnionColor.create(ImmutableSet.of(PrimitiveColor.NUMBER, PrimitiveColor.STRING));
42+
43+
assertThat(union).isUnion();
44+
}
45+
46+
@Test
47+
public void getAlternatesReturnsAlternatesList() {
48+
UnionColor union =
49+
UnionColor.create(ImmutableSet.of(PrimitiveColor.NUMBER, PrimitiveColor.STRING));
50+
51+
assertThat(union).hasAlternates(PrimitiveColor.NUMBER, PrimitiveColor.STRING);
52+
}
53+
54+
@Test
55+
public void alternatesMayContainOtherUnion() {
56+
UnionColor union =
57+
UnionColor.create(ImmutableSet.of(PrimitiveColor.NUMBER, PrimitiveColor.STRING));
58+
UnionColor newUnion = UnionColor.create(ImmutableSet.of(union, PrimitiveColor.BIGINT));
59+
60+
assertThat(newUnion)
61+
.hasAlternates(PrimitiveColor.STRING, PrimitiveColor.BIGINT, PrimitiveColor.NUMBER);
62+
}
63+
64+
@Test
65+
public void alternatesAreDeduplicatedFromOtherUnion() {
66+
UnionColor union =
67+
UnionColor.create(
68+
ImmutableSet.of(
69+
PrimitiveColor.NUMBER,
70+
UnionColor.create(ImmutableSet.of(PrimitiveColor.NUMBER, PrimitiveColor.STRING))));
71+
72+
assertThat(union).hasAlternates(PrimitiveColor.NUMBER, PrimitiveColor.STRING);
73+
}
74+
75+
@Test
76+
public void createMethodRequiresTwoOrMoreAlternates() {
77+
assertThrows(IllegalArgumentException.class, () -> UnionColor.create(ImmutableSet.of()));
78+
assertThrows(
79+
IllegalArgumentException.class,
80+
() -> UnionColor.create(ImmutableSet.of(PrimitiveColor.NUMBER)));
81+
}
82+
83+
@Test
84+
public void unknownTypeIsNotSpecialCased() {
85+
// In some "check" type systems, the top type + another type is equivalent to just the
86+
// top type. Colors don't replicate those semantics. Whatever serialized type structure the
87+
// colors are created from has already dealt with this.
88+
UnionColor union =
89+
UnionColor.create(ImmutableSet.of(PrimitiveColor.UNKNOWN, PrimitiveColor.STRING));
90+
91+
assertThat(union).isUnion();
92+
assertThat(union.getAlternates()).hasSize(2);
93+
}
94+
}

0 commit comments

Comments
 (0)