ac6cb178f958308b892555cc466ab50c4773643d
[idea/community.git] / jps / jps-builders / src / org / jetbrains / jps / backwardRefs / LightUsage.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
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 package org.jetbrains.jps.backwardRefs;
17
18 import com.intellij.util.io.DataInputOutputUtil;
19 import com.intellij.util.io.KeyDescriptor;
20 import com.sun.tools.javac.code.Symbol;
21 import org.jetbrains.annotations.NotNull;
22 import org.jetbrains.jps.builders.java.dependencyView.RW;
23 import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
24
25 import javax.lang.model.element.ElementKind;
26 import java.io.DataInput;
27 import java.io.DataOutput;
28 import java.io.IOException;
29
30 public abstract class LightUsage implements RW.Savable {
31   private final static byte CLASS_MARKER = 0x0;
32   private final static byte METHOD_MARKER = 0x1;
33   private final static byte FIELD_MARKER = 0x2;
34
35   public final int myOwner;
36
37   protected LightUsage(int owner) {
38     myOwner = owner;
39   }
40
41   public int getOwner() {
42     return myOwner;
43   }
44
45   @NotNull
46   public abstract LightUsage override(int ownerOverrider);
47
48   public static class LightMethodUsage extends LightUsage {
49     private final int myName;
50     private final int myParameterCount;
51
52     LightMethodUsage(int owner, int name, int parameterCount) {
53       super(owner);
54       myName = name;
55       myParameterCount = parameterCount;
56     }
57
58     public int getName() {
59       return myName;
60     }
61
62     public int getParameterCount() {
63       return myParameterCount;
64     }
65
66     @Override
67     public void save(DataOutput out) {
68       try {
69         out.writeByte(METHOD_MARKER);
70         DataInputOutputUtil.writeINT(out, getOwner());
71         DataInputOutputUtil.writeINT(out, getName());
72         DataInputOutputUtil.writeINT(out, getParameterCount());
73       }
74       catch (IOException e) {
75         throw new BuildDataCorruptedException(e);
76       }
77     }
78
79     @Override
80     public boolean equals(Object o) {
81       if (this == o) return true;
82       if (o == null || getClass() != o.getClass()) return false;
83
84       LightMethodUsage usage = (LightMethodUsage)o;
85
86       if (myOwner != usage.myOwner) return false;
87       if (myName != usage.myName) return false;
88       if (myParameterCount != usage.myParameterCount) return false;
89
90       return true;
91     }
92
93     @Override
94     public int hashCode() {
95       int result = myName;
96       result = 31 * result + myParameterCount;
97       result = 31 * result + myOwner;
98       return result;
99     }
100
101     @NotNull
102     @Override
103     public LightMethodUsage override(int ownerOverrider) {
104       return new LightMethodUsage(ownerOverrider, getName(), getParameterCount());
105     }
106   }
107
108   public static class LightFieldUsage extends LightUsage {
109     private final int myName;
110
111     LightFieldUsage(int owner, int name) {
112       super(owner);
113       myName = name;
114     }
115
116     public int getName() {
117       return myName;
118     }
119
120     @Override
121     public void save(DataOutput out) {
122       try {
123         out.writeByte(FIELD_MARKER);
124         DataInputOutputUtil.writeINT(out, getOwner());
125         DataInputOutputUtil.writeINT(out, getName());
126       }
127       catch (IOException e) {
128         throw new BuildDataCorruptedException(e);
129       }
130     }
131
132     @Override
133     public boolean equals(Object o) {
134       if (this == o) return true;
135       if (o == null || getClass() != o.getClass()) return false;
136
137       LightFieldUsage usage = (LightFieldUsage)o;
138
139       if (myOwner != usage.myOwner) return false;
140       if (myName != usage.myName) return false;
141
142       return true;
143     }
144
145     @Override
146     public int hashCode() {
147       return myName + 31 * myOwner;
148     }
149
150     @NotNull
151     @Override
152     public LightFieldUsage override(int ownerOverrider) {
153       return new LightFieldUsage(ownerOverrider, getName());
154     }
155
156   }
157
158   public static class LightClassUsage extends LightUsage {
159     LightClassUsage(int owner) {
160       super(owner);
161     }
162
163     @NotNull
164     @Override
165     public LightClassUsage override(int ownerOverrider) {
166       return new LightClassUsage(ownerOverrider);
167     }
168
169     @Override
170     public void save(DataOutput out) {
171       try {
172         out.writeByte(CLASS_MARKER);
173         DataInputOutputUtil.writeINT(out, getOwner());
174       }
175       catch (IOException e) {
176         throw new BuildDataCorruptedException(e);
177       }
178     }
179
180     @Override
181     public boolean equals(Object o) {
182       if (this == o) return true;
183       if (o == null || getClass() != o.getClass()) return false;
184
185       LightClassUsage usage = (LightClassUsage)o;
186
187       if (myOwner != usage.myOwner) return false;
188
189       return true;
190     }
191
192     @Override
193     public int hashCode() {
194       return myOwner;
195     }
196   }
197
198   static KeyDescriptor<LightUsage> createDescriptor() {
199     return new KeyDescriptor<LightUsage>() {
200       @Override
201       public int getHashCode(LightUsage value) {
202         return value.hashCode();
203       }
204
205       @Override
206       public boolean isEqual(LightUsage val1, LightUsage val2) {
207         return val1.equals(val2);
208       }
209
210       @Override
211       public void save(@NotNull DataOutput out, LightUsage value) throws IOException {
212         value.save(out);
213       }
214
215       @Override
216       public LightUsage read(@NotNull DataInput in) throws IOException {
217         final byte type = in.readByte();
218         switch (type) {
219           case CLASS_MARKER:
220             return new LightClassUsage(DataInputOutputUtil.readINT(in));
221           case METHOD_MARKER:
222             return new LightMethodUsage(DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in));
223           case FIELD_MARKER:
224             return new LightFieldUsage(DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in));
225         }
226         throw new AssertionError();
227       }
228     };
229   }
230
231   static byte[] bytes(Symbol symbol) {
232     return symbol.flatName().toUtf();
233   }
234
235   static LightUsage fromSymbol(Symbol symbol, ByteArrayEnumerator byteArrayEnumerator) {
236     final ElementKind kind = symbol.getKind();
237     if (symbol instanceof Symbol.ClassSymbol) {
238       return new LightClassUsage(id(symbol, byteArrayEnumerator));
239     }
240     else if (symbol instanceof Symbol.VarSymbol) {
241       return new LightFieldUsage(id(symbol.owner, byteArrayEnumerator), id(symbol, byteArrayEnumerator));
242     }
243     else if (symbol instanceof Symbol.MethodSymbol) {
244       int paramCount = ((Symbol.MethodSymbol)symbol).type.getParameterTypes().size();
245       return new LightMethodUsage(id(symbol.owner, byteArrayEnumerator), id(symbol, byteArrayEnumerator), paramCount);
246     }
247     else {
248       throw new AssertionError("unexpected symbol: " + symbol + " class: " + symbol.getClass() + " kind: " + kind);
249     }
250   }
251
252   private static int id(Symbol symbol, ByteArrayEnumerator byteArrayEnumerator) {
253     return byteArrayEnumerator.enumerate(bytes(symbol));
254   }
255 }