/
JField.java
257 lines (213 loc) · 6.75 KB
/
JField.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
* Copyright 2008 Google Inc.
*
* 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.gwt.dev.jjs.ast;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.util.StringInterner;
import java.io.Serializable;
/**
* Java field definition.
*/
public class JField extends JVariable implements JMember {
/**
* Determines whether the variable is final, volatile, or neither.
*/
public static enum Disposition {
COMPILE_TIME_CONSTANT, FINAL, NONE, THIS_REF, VOLATILE;
public boolean isFinal() {
return this == COMPILE_TIME_CONSTANT || this == FINAL || this == THIS_REF;
}
public boolean isThisRef() {
return this == THIS_REF;
}
private boolean isCompileTimeConstant() {
return this == COMPILE_TIME_CONSTANT;
}
private boolean isVolatile() {
return this == VOLATILE;
}
}
private static class ExternalSerializedForm implements Serializable {
private final JDeclaredType enclosingType;
private final String signature;
public ExternalSerializedForm(JField field) {
enclosingType = field.getEnclosingType();
signature = field.getSignature();
}
private Object readResolve() {
String name = StringInterner.get().intern(signature.substring(0, signature.indexOf(':')));
JField result =
new JField(SourceOrigin.UNKNOWN, name, enclosingType, JReferenceType.NULL_TYPE, false,
Disposition.NONE);
result.signature = signature;
return result;
}
}
private static class ExternalSerializedNullField implements Serializable {
public static final ExternalSerializedNullField INSTANCE = new ExternalSerializedNullField();
private Object readResolve() {
return NULL_FIELD;
}
}
public static final JField NULL_FIELD = new JField(SourceOrigin.UNKNOWN, "nullField", null,
JReferenceType.NULL_TYPE, false, Disposition.FINAL);
private String jsName;
private String jsNamespace;
private boolean exported;
private final JDeclaredType enclosingType;
private final boolean isCompileTimeConstant;
private final boolean isStatic;
private final boolean isThisRef;
private boolean isVolatile;
private transient String signature;
/**
* The access modifier; stored as an int to reduce memory / serialization footprint.
*/
private final int access;
public JField(SourceInfo info, String name, JDeclaredType enclosingType, JType type,
boolean isStatic, Disposition disposition, AccessModifier access) {
super(info, name, type, disposition.isFinal());
this.enclosingType = enclosingType;
this.isStatic = isStatic;
this.isCompileTimeConstant = disposition.isCompileTimeConstant();
this.isVolatile = disposition.isVolatile();
this.isThisRef = disposition.isThisRef();
this.access = access.ordinal();
// Disposition is not cached because we can be set final later.
}
public JField(SourceInfo info, String name, JDeclaredType enclosingType, JType type,
boolean isStatic, Disposition disposition) {
this(info, name, enclosingType, type, isStatic, disposition, AccessModifier.DEFAULT);
}
@Override
public String getQualifiedName() {
return getEnclosingType().getName() + "." + getName();
}
@Override
public JDeclaredType getEnclosingType() {
return enclosingType;
}
public JValueLiteral getLiteralInitializer() {
JExpression initializer = getInitializer();
if (initializer instanceof JValueLiteral) {
return (JValueLiteral) initializer;
}
return null;
}
@Override
public void setJsMemberInfo(String namespace, String name, boolean exported) {
this.jsName = name;
this.jsNamespace = namespace;
this.exported = exported;
}
public boolean isJsInteropEntryPoint() {
return exported && isStatic();
}
public boolean canBeReferencedExternally() {
return exported;
}
@Override
public String getJsNamespace() {
return jsNamespace == null ? enclosingType.getQualifiedJsName() : jsNamespace;
}
@Override
public String getQualifiedJsName() {
String namespace = getJsNamespace();
return namespace.isEmpty() ? jsName : namespace + "." + jsName;
}
public boolean isJsProperty() {
return jsName != null;
}
public boolean isJsNative() {
return enclosingType.isJsNative();
}
@Override
public String getJsName() {
return jsName;
}
public String getSignature() {
if (signature == null) {
StringBuilder sb = new StringBuilder();
sb.append(getName());
sb.append(':');
sb.append(getType().getJsniSignatureName());
signature = sb.toString();
}
return signature;
}
public boolean isCompileTimeConstant() {
return isCompileTimeConstant;
}
public boolean isExternal() {
return getEnclosingType() != null && getEnclosingType().isExternal();
}
@Override
public boolean isPublic() {
return access == AccessModifier.PUBLIC.ordinal();
}
@Override
public boolean needsDynamicDispatch() {
return !isStatic;
}
@Override
public boolean isStatic() {
return isStatic;
}
@Override
public boolean isSynthetic() {
return false;
}
public boolean isThisRef() {
return isThisRef;
}
public boolean isVolatile() {
return isVolatile;
}
@Override
public void setFinal() {
if (isVolatile()) {
throw new IllegalStateException("Volatile fields cannot be set final");
}
super.setFinal();
}
@Override
public void setInitializer(JDeclarationStatement declStmt) {
this.declStmt = declStmt;
}
@Override
public void traverse(JVisitor visitor, Context ctx) {
if (visitor.visit(this, ctx)) {
// Do not visit declStmt, it gets visited within its own code block.
}
visitor.endVisit(this, ctx);
}
protected Object writeReplace() {
if (isExternal()) {
return new ExternalSerializedForm(this);
} else if (this == NULL_FIELD) {
return ExternalSerializedNullField.INSTANCE;
} else {
return this;
}
}
boolean replaces(JField originalField) {
if (this == originalField) {
return true;
}
return originalField.isExternal() && originalField.getSignature().equals(this.getSignature())
&& this.getEnclosingType().replaces(originalField.getEnclosingType());
}
}