-
Notifications
You must be signed in to change notification settings - Fork 727
/
ApiDiff.java
121 lines (106 loc) · 4.73 KB
/
ApiDiff.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
* Copyright 2018 The Error Prone 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.errorprone.bugpatterns.apidiff;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
import com.google.errorprone.bugpatterns.apidiff.ApiDiffProto.Diff;
import java.util.Set;
/** The difference between two APIs. */
@AutoValue
public abstract class ApiDiff {
/** A per class unique identifier for a field or method. */
@AutoValue
public abstract static class ClassMemberKey {
/** The simple name of the member. */
public abstract String identifier();
/** The JVMS 4.3 member descriptor. */
public abstract String descriptor();
public static ClassMemberKey create(String identifier, String descriptor) {
return new AutoValue_ApiDiff_ClassMemberKey(identifier, descriptor);
}
@Override
public final String toString() {
return String.format("%s:%s", identifier(), descriptor());
}
}
/** Binary names of classes only present in the new API. */
public abstract ImmutableSet<String> unsupportedClasses();
/** Members only present in the new API, grouped by binary name of their declaring class. */
public abstract ImmutableSetMultimap<String, ClassMemberKey> unsupportedMembersByClass();
/** Returns true if the class with the given binary name is unsupported. */
boolean isClassUnsupported(String className) {
return unsupportedClasses().contains(className);
}
/** Returns true if the member with the given declaring class is unsupported. */
boolean isMemberUnsupported(String className, ClassMemberKey memberKey) {
return unsupportedMembersByClass().containsEntry(className, memberKey)
|| unsupportedMembersByClass()
.containsEntry(className, ClassMemberKey.create(memberKey.identifier(), ""));
}
public static ApiDiff fromMembers(
Set<String> unsupportedClasses, Multimap<String, ClassMemberKey> unsupportedMembersByClass) {
return new AutoValue_ApiDiff(
ImmutableSet.copyOf(unsupportedClasses),
ImmutableSetMultimap.copyOf(unsupportedMembersByClass));
}
/** Converts a {@link Diff} to a {@link ApiDiff}. */
public static ApiDiff fromProto(Diff diff) {
ImmutableSet.Builder<String> unsupportedClasses = ImmutableSet.builder();
ImmutableSetMultimap.Builder<String, ClassMemberKey> unsupportedMembersByClass =
ImmutableSetMultimap.builder();
for (ApiDiffProto.ClassDiff c : diff.getClassDiffList()) {
switch (c.getDiffCase()) {
case EVERYTHING_DIFF:
unsupportedClasses.add(c.getEverythingDiff().getClassName());
break;
case MEMBER_DIFF:
ApiDiffProto.MemberDiff memberDiff = c.getMemberDiff();
for (ApiDiffProto.ClassMember member : memberDiff.getMemberList()) {
unsupportedMembersByClass.put(
memberDiff.getClassName(),
ClassMemberKey.create(member.getIdentifier(), member.getMemberDescriptor()));
}
break;
default:
throw new AssertionError(c.getDiffCase());
}
}
return new AutoValue_ApiDiff(unsupportedClasses.build(), unsupportedMembersByClass.build());
}
/** Converts a {@link ApiDiff} to a {@link ApiDiffProto.Diff}. */
public Diff toProto() {
ApiDiffProto.Diff.Builder builder = ApiDiffProto.Diff.newBuilder();
for (String className : unsupportedClasses()) {
builder.addClassDiff(
ApiDiffProto.ClassDiff.newBuilder()
.setEverythingDiff(ApiDiffProto.EverythingDiff.newBuilder().setClassName(className)));
}
for (String className : unsupportedMembersByClass().keySet()) {
ApiDiffProto.MemberDiff.Builder memberDiff =
ApiDiffProto.MemberDiff.newBuilder().setClassName(className);
for (ClassMemberKey member : unsupportedMembersByClass().get(className)) {
memberDiff.addMember(
ApiDiffProto.ClassMember.newBuilder()
.setIdentifier(member.identifier())
.setMemberDescriptor(member.descriptor()));
}
builder.addClassDiff(ApiDiffProto.ClassDiff.newBuilder().setMemberDiff(memberDiff));
}
return builder.build();
}
}