1 | /******************************************************************************* |
---|---|
2 | * Copyright (c) 2000, 2020 IBM Corporation and others. |
3 | * |
4 | * This program and the accompanying materials |
5 | * are made available under the terms of the Eclipse Public License 2.0 |
6 | * which accompanies this distribution, and is available at |
7 | * https://www.eclipse.org/legal/epl-2.0/ |
8 | * |
9 | * SPDX-License-Identifier: EPL-2.0 |
10 | * |
11 | * Contributors: |
12 | * IBM Corporation - initial API and implementation |
13 | *******************************************************************************/ |
14 | package org.eclipse.jdt.astview.views; |
15 | |
16 | import java.util.ArrayList; |
17 | import java.util.Objects; |
18 | import java.util.function.Function; |
19 | |
20 | import org.eclipse.jdt.astview.ASTViewPlugin; |
21 | |
22 | import org.eclipse.swt.graphics.Image; |
23 | |
24 | import org.eclipse.jdt.core.IJavaElement; |
25 | import org.eclipse.jdt.core.dom.AST; |
26 | import org.eclipse.jdt.core.dom.CharacterLiteral; |
27 | import org.eclipse.jdt.core.dom.IAnnotationBinding; |
28 | import org.eclipse.jdt.core.dom.IBinding; |
29 | import org.eclipse.jdt.core.dom.IMemberValuePairBinding; |
30 | import org.eclipse.jdt.core.dom.IMethodBinding; |
31 | import org.eclipse.jdt.core.dom.IModuleBinding; |
32 | import org.eclipse.jdt.core.dom.IPackageBinding; |
33 | import org.eclipse.jdt.core.dom.ITypeBinding; |
34 | import org.eclipse.jdt.core.dom.IVariableBinding; |
35 | import org.eclipse.jdt.core.dom.Modifier; |
36 | import org.eclipse.jdt.core.dom.PrimitiveType; |
37 | import org.eclipse.jdt.core.dom.StringLiteral; |
38 | |
39 | /** |
40 | * |
41 | */ |
42 | public class Binding extends ASTAttribute { |
43 | |
44 | private final IBinding fBinding; |
45 | private final String fLabel; |
46 | private final Object fParent; |
47 | private final boolean fIsRelevant; |
48 | |
49 | public Binding(Object parent, String label, IBinding binding, boolean isRelevant) { |
50 | fParent= parent; |
51 | fBinding= binding; |
52 | fLabel= label; |
53 | fIsRelevant= isRelevant; |
54 | } |
55 | |
56 | @Override |
57 | public Object getParent() { |
58 | return fParent; |
59 | } |
60 | |
61 | public IBinding getBinding() { |
62 | return fBinding; |
63 | } |
64 | |
65 | |
66 | public boolean hasBindingProperties() { |
67 | return fBinding != null; |
68 | } |
69 | |
70 | public boolean isRelevant() { |
71 | return fIsRelevant; |
72 | } |
73 | |
74 | |
75 | private static boolean isType(int typeKinds, int kind) { |
76 | return (typeKinds & kind) != 0; |
77 | } |
78 | |
79 | @Override |
80 | public Object[] getChildren() { |
81 | try { |
82 | if (fBinding != null) { |
83 | fBinding.getKey(); |
84 | } |
85 | } catch (RuntimeException e) { |
86 | ASTViewPlugin.log("Exception thrown in IBinding#getKey() for \"" + fBinding + "\"", e); |
87 | return new Object[] { new Error(this, "BrokenBinding: " + fBinding, null) }; |
88 | } |
89 | if (fBinding != null) { |
90 | ArrayList<ASTAttribute> res= new ArrayList<>(); |
91 | res.add(new BindingProperty(this, "NAME", fBinding.getName(), true)); //$NON-NLS-1$ |
92 | res.add(new BindingProperty(this, "KEY", fBinding.getKey(), true)); //$NON-NLS-1$ |
93 | res.add(new BindingProperty(this, "IS RECOVERED", fBinding.isRecovered(), true)); //$NON-NLS-1$ |
94 | switch (fBinding.getKind()) { |
95 | case IBinding.VARIABLE: |
96 | IVariableBinding variableBinding= (IVariableBinding) fBinding; |
97 | res.add(new BindingProperty(this, "IS FIELD", variableBinding.isField(), true)); //$NON-NLS-1$ |
98 | res.add(new BindingProperty(this, "IS ENUM CONSTANT", variableBinding.isEnumConstant(), true)); //$NON-NLS-1$ |
99 | res.add(new BindingProperty(this, "IS PARAMETER", variableBinding.isParameter(), true)); //$NON-NLS-1$ |
100 | res.add(new BindingProperty(this, "IS RECORD COMPONENT", variableBinding.isRecordComponent(), true)); //$NON-NLS-1$ |
101 | res.add(new BindingProperty(this, "VARIABLE ID", variableBinding.getVariableId(), true)); //$NON-NLS-1$ |
102 | res.add(new BindingProperty(this, "MODIFIERS", getModifiersString(fBinding.getModifiers(), false), true)); //$NON-NLS-1$ |
103 | res.add(new Binding(this, "TYPE", variableBinding.getType(), true)); //$NON-NLS-1$ |
104 | res.add(new Binding(this, "DECLARING CLASS", variableBinding.getDeclaringClass(), true)); //$NON-NLS-1$ |
105 | res.add(new Binding(this, "DECLARING METHOD", variableBinding.getDeclaringMethod(), true)); //$NON-NLS-1$ |
106 | res.add(new Binding(this, "VARIABLE DECLARATION", variableBinding.getVariableDeclaration(), true)); //$NON-NLS-1$ |
107 | res.add(new BindingProperty(this, "IS SYNTHETIC", fBinding.isSynthetic(), true)); //$NON-NLS-1$ |
108 | res.add(new BindingProperty(this, "IS DEPRECATED", fBinding.isDeprecated(), true)); //$NON-NLS-1$ |
109 | res.add(new BindingProperty(this, "CONSTANT VALUE", variableBinding.getConstantValue(), true)); //$NON-NLS-1$ |
110 | res.add(new BindingProperty(this, "IS EFFECTIVELY FINAL", variableBinding.isEffectivelyFinal(), true)); //$NON-NLS-1$ |
111 | break; |
112 | |
113 | case IBinding.PACKAGE: |
114 | IPackageBinding packageBinding= (IPackageBinding) fBinding; |
115 | res.add(new BindingProperty(this, "IS UNNAMED", packageBinding.isUnnamed(), true)); //$NON-NLS-1$ |
116 | res.add(new BindingProperty(this, "IS SYNTHETIC", fBinding.isSynthetic(), true)); //$NON-NLS-1$ |
117 | res.add(new BindingProperty(this, "IS DEPRECATED", fBinding.isDeprecated(), true)); //$NON-NLS-1$ |
118 | break; |
119 | |
120 | case IBinding.TYPE: |
121 | ITypeBinding typeBinding= (ITypeBinding) fBinding; |
122 | res.add(new BindingProperty(this, "QUALIFIED NAME", typeBinding.getQualifiedName(), true)); //$NON-NLS-1$ |
123 | |
124 | int typeKind= getTypeKind(typeBinding); |
125 | boolean isRefType= isType(typeKind, REF_TYPE); |
126 | final boolean isNonPrimitive= ! isType(typeKind, PRIMITIVE_TYPE); |
127 | |
128 | StringBuilder kinds= new StringBuilder("KIND:"); //$NON-NLS-1$ |
129 | if (typeBinding.isArray()) kinds.append(" isArray"); //$NON-NLS-1$ |
130 | if (typeBinding.isCapture()) kinds.append(" isCapture"); //$NON-NLS-1$ |
131 | if (typeBinding.isNullType()) kinds.append(" isNullType"); //$NON-NLS-1$ |
132 | if (typeBinding.isPrimitive()) kinds.append(" isPrimitive"); //$NON-NLS-1$ |
133 | if (typeBinding.isTypeVariable()) kinds.append(" isTypeVariable"); //$NON-NLS-1$ |
134 | if (typeBinding.isWildcardType()) kinds.append(" isWildcardType"); //$NON-NLS-1$ |
135 | // ref types |
136 | if (typeBinding.isAnnotation()) kinds.append(" isAnnotation"); //$NON-NLS-1$ |
137 | if (typeBinding.isClass()) kinds.append(" isClass"); //$NON-NLS-1$ |
138 | if (typeBinding.isInterface()) kinds.append(" isInterface"); //$NON-NLS-1$ |
139 | if (typeBinding.isEnum()) kinds.append(" isEnum"); //$NON-NLS-1$ |
140 | res.add(new BindingProperty(this, kinds, true)); |
141 | |
142 | StringBuilder generics= new StringBuilder("GENERICS:"); //$NON-NLS-1$ |
143 | if (typeBinding.isRawType()) generics.append(" isRawType"); //$NON-NLS-1$ |
144 | if (typeBinding.isGenericType()) generics.append(" isGenericType"); //$NON-NLS-1$ |
145 | if (typeBinding.isParameterizedType()) generics.append(" isParameterizedType"); //$NON-NLS-1$ |
146 | if (!isType(typeKind, GENERIC | PARAMETRIZED)) { |
147 | generics.append(" (non-generic, non-parameterized)"); |
148 | } |
149 | res.add(new BindingProperty(this, generics, isRefType)); |
150 | |
151 | res.add(new Binding(this, "ELEMENT TYPE", typeBinding.getElementType(), isType(typeKind, ARRAY_TYPE))); //$NON-NLS-1$ |
152 | res.add(new Binding(this, "COMPONENT TYPE", typeBinding.getComponentType(), isType(typeKind, ARRAY_TYPE))); //$NON-NLS-1$ |
153 | res.add(new BindingProperty(this, "DIMENSIONS", typeBinding.getDimensions(), isType(typeKind, ARRAY_TYPE))); //$NON-NLS-1$ |
154 | final String createArrayTypeLabel= "CREATE ARRAY TYPE (+1)"; |
155 | try { |
156 | ITypeBinding arrayType= typeBinding.createArrayType(1); |
157 | res.add(new Binding(this, createArrayTypeLabel, arrayType, true)); |
158 | } catch (RuntimeException e) { |
159 | String msg= e.getClass().getName() + ": " + e.getLocalizedMessage(); |
160 | boolean isRelevant= ! typeBinding.getName().equals(PrimitiveType.VOID.toString()) && ! typeBinding.isRecovered(); |
161 | if (isRelevant) { |
162 | res.add(new Error(this, createArrayTypeLabel + ": " + msg, e)); |
163 | } else { |
164 | res.add(new BindingProperty(this, createArrayTypeLabel, msg, false)); |
165 | } |
166 | } |
167 | |
168 | StringBuilder origin= new StringBuilder("ORIGIN:"); //$NON-NLS-1$ |
169 | if (typeBinding.isTopLevel()) origin.append(" isTopLevel"); //$NON-NLS-1$ |
170 | if (typeBinding.isNested()) origin.append(" isNested"); //$NON-NLS-1$ |
171 | if (typeBinding.isLocal()) origin.append(" isLocal"); //$NON-NLS-1$ |
172 | if (typeBinding.isMember()) origin.append(" isMember"); //$NON-NLS-1$ |
173 | if (typeBinding.isAnonymous()) origin.append(" isAnonymous"); //$NON-NLS-1$ |
174 | res.add(new BindingProperty(this, origin, isRefType)); |
175 | |
176 | res.add(new BindingProperty(this, "IS FROM SOURCE", typeBinding.isFromSource(), isType(typeKind, REF_TYPE | VARIABLE_TYPE | CAPTURE_TYPE))); //$NON-NLS-1$ |
177 | |
178 | res.add(new Binding(this, "PACKAGE", typeBinding.getPackage(), isRefType)); //$NON-NLS-1$ |
179 | res.add(new Binding(this, "DECLARING CLASS", typeBinding.getDeclaringClass(), isType(typeKind, REF_TYPE | VARIABLE_TYPE | CAPTURE_TYPE))); //$NON-NLS-1$ |
180 | res.add(new Binding(this, "DECLARING METHOD", typeBinding.getDeclaringMethod(), isType(typeKind, REF_TYPE | VARIABLE_TYPE | CAPTURE_TYPE))); //$NON-NLS-1$ |
181 | res.add(new Binding(this, "DECLARING MEMBER", typeBinding.getDeclaringMember(), typeBinding.isLocal())); //$NON-NLS-1$ |
182 | res.add(new BindingProperty(this, "MODIFIERS", getModifiersString(fBinding.getModifiers(), false), isRefType)); //$NON-NLS-1$ |
183 | res.add(new BindingProperty(this, "BINARY NAME", typeBinding.getBinaryName(), true)); //$NON-NLS-1$ |
184 | |
185 | String isTypeDeclaration= typeBinding == typeBinding.getTypeDeclaration() ? " ( == this)" : " ( != this)"; |
186 | res.add(new Binding(this, "TYPE DECLARATION" + isTypeDeclaration, typeBinding.getTypeDeclaration(), true)); //$NON-NLS-1$ |
187 | String isErasure= typeBinding == typeBinding.getErasure() ? " ( == this)" : " ( != this)"; |
188 | res.add(new Binding(this, "ERASURE" + isErasure, typeBinding.getErasure(), isNonPrimitive)); //$NON-NLS-1$ |
189 | res.add(new BindingProperty(this, "TYPE PARAMETERS", typeBinding.getTypeParameters(), isType(typeKind, GENERIC))); //$NON-NLS-1$ |
190 | res.add(new BindingProperty(this, "TYPE ARGUMENTS", typeBinding.getTypeArguments(), isType(typeKind, PARAMETRIZED))); //$NON-NLS-1$ |
191 | res.add(new BindingProperty(this, "TYPE BOUNDS", typeBinding.getTypeBounds(), isType(typeKind, VARIABLE_TYPE | WILDCARD_TYPE | CAPTURE_TYPE))); //$NON-NLS-1$ |
192 | res.add(new Binding(this, "BOUND", typeBinding.getBound(), isType(typeKind, WILDCARD_TYPE))); //$NON-NLS-1$ |
193 | res.add(new BindingProperty(this, "IS UPPERBOUND", typeBinding.isUpperbound(), isType(typeKind, WILDCARD_TYPE))); //$NON-NLS-1$ |
194 | res.add(new Binding(this, "GENERIC TYPE OF WILDCARD TYPE", typeBinding.getGenericTypeOfWildcardType(), isType(typeKind, WILDCARD_TYPE))); //$NON-NLS-1$ |
195 | res.add(new BindingProperty(this, "RANK", typeBinding.getRank(), isType(typeKind, WILDCARD_TYPE))); //$NON-NLS-1$ |
196 | res.add(new Binding(this, "WILDCARD", typeBinding.getWildcard(), isType(typeKind, CAPTURE_TYPE))); //$NON-NLS-1$ |
197 | |
198 | res.add(new Binding(this, "SUPERCLASS", typeBinding.getSuperclass(), isRefType)); //$NON-NLS-1$ |
199 | res.add(new BindingProperty(this, "INTERFACES", typeBinding.getInterfaces(), isRefType)); //$NON-NLS-1$ |
200 | res.add(new BindingProperty(this, "DECLARED TYPES", typeBinding.getDeclaredTypes(), isRefType)); //$NON-NLS-1$ |
201 | res.add(new BindingProperty(this, "DECLARED FIELDS", typeBinding.getDeclaredFields(), isRefType)); //$NON-NLS-1$ |
202 | res.add(new BindingProperty(this, "DECLARED METHODS", typeBinding.getDeclaredMethods(), isRefType)); //$NON-NLS-1$ |
203 | res.add(new Binding(this, "FUNCTIONAL INTERFACE METHOD", typeBinding.getFunctionalInterfaceMethod(), typeBinding.isInterface())); //$NON-NLS-1$ |
204 | res.add(new BindingProperty(this, "IS SYNTHETIC", fBinding.isSynthetic(), isNonPrimitive)); //$NON-NLS-1$ |
205 | res.add(new BindingProperty(this, "IS DEPRECATED", fBinding.isDeprecated(), isRefType)); //$NON-NLS-1$ |
206 | res.add(new BindingProperty(this, "TYPE ANNOTATIONS", typeBinding.getTypeAnnotations(), true)); //$NON-NLS-1$ |
207 | break; |
208 | |
209 | case IBinding.METHOD: |
210 | IMethodBinding methodBinding= (IMethodBinding) fBinding; |
211 | res.add(new BindingProperty(this, "IS CONSTRUCTOR", methodBinding.isConstructor(), true)); //$NON-NLS-1$ |
212 | res.add(new BindingProperty(this, "IS DEFAULT CONSTRUCTOR", methodBinding.isDefaultConstructor(), true)); //$NON-NLS-1$ |
213 | res.add(new Binding(this, "DECLARING CLASS", methodBinding.getDeclaringClass(), true)); //$NON-NLS-1$ |
214 | res.add(new Binding(this, "DECLARING MEMBER", methodBinding.getDeclaringMember(), methodBinding.getDeclaringMember() != null)); //$NON-NLS-1$ |
215 | res.add(new Binding(this, "RETURN TYPE", methodBinding.getReturnType(), true)); //$NON-NLS-1$ |
216 | res.add(new BindingProperty(this, "MODIFIERS", getModifiersString(fBinding.getModifiers(), true), true)); //$NON-NLS-1$ |
217 | res.add(new BindingProperty(this, "PARAMETER TYPES", methodBinding.getParameterTypes(), true)); //$NON-NLS-1$ |
218 | res.add(new BindingProperty(this, "IS VARARGS", methodBinding.isVarargs(), true)); //$NON-NLS-1$ |
219 | res.add(new BindingProperty(this, "EXCEPTION TYPES", methodBinding.getExceptionTypes(), true)); //$NON-NLS-1$ |
220 | |
221 | StringBuilder genericsM= new StringBuilder("GENERICS:"); //$NON-NLS-1$ |
222 | if (methodBinding.isRawMethod()) genericsM.append(" isRawMethod"); //$NON-NLS-1$ |
223 | if (methodBinding.isGenericMethod()) genericsM.append(" isGenericMethod"); //$NON-NLS-1$ |
224 | if (methodBinding.isParameterizedMethod()) genericsM.append(" isParameterizedMethod"); //$NON-NLS-1$ |
225 | res.add(new BindingProperty(this, genericsM, true)); |
226 | |
227 | String isMethodDeclaration= methodBinding == methodBinding.getMethodDeclaration() ? " ( == this)" : " ( != this)"; |
228 | res.add(new Binding(this, "METHOD DECLARATION" + isMethodDeclaration, methodBinding.getMethodDeclaration(), true)); //$NON-NLS-1$ |
229 | res.add(new BindingProperty(this, "TYPE PARAMETERS", methodBinding.getTypeParameters(), true)); //$NON-NLS-1$ |
230 | res.add(new BindingProperty(this, "TYPE ARGUMENTS", methodBinding.getTypeArguments(), true)); //$NON-NLS-1$ |
231 | res.add(new BindingProperty(this, "IS SYNTHETIC", fBinding.isSynthetic(), true)); //$NON-NLS-1$ |
232 | res.add(new BindingProperty(this, "IS DEPRECATED", fBinding.isDeprecated(), true)); //$NON-NLS-1$ |
233 | |
234 | res.add(new BindingProperty(this, "IS ANNOTATION MEMBER", methodBinding.isAnnotationMember(), true)); //$NON-NLS-1$ |
235 | res.add(Binding.createValueAttribute(this, "DEFAULT VALUE", methodBinding.getDefaultValue())); |
236 | |
237 | int parameterCount= methodBinding.getParameterTypes().length; |
238 | BindingProperty[] parametersAnnotations= new BindingProperty[parameterCount]; |
239 | for (int i= 0; i < parameterCount; i++) { |
240 | parametersAnnotations[i]= new BindingProperty(this, "Parameter " + String.valueOf(i), methodBinding.getParameterAnnotations(i), true); |
241 | } |
242 | res.add(new BindingProperty(this, "PARAMETER ANNOTATIONS", parametersAnnotations, true)); |
243 | break; |
244 | |
245 | case IBinding.ANNOTATION: |
246 | IAnnotationBinding annotationBinding= (IAnnotationBinding) fBinding; |
247 | res.add(new Binding(this, "ANNOTATION TYPE", annotationBinding.getAnnotationType(), true)); |
248 | res.add(new BindingProperty(this, "DECLARED MEMBER VALUE PAIRS", annotationBinding.getDeclaredMemberValuePairs(), true)); |
249 | res.add(new BindingProperty(this, "ALL MEMBER VALUE PAIRS", annotationBinding.getAllMemberValuePairs(), true)); |
250 | break; |
251 | |
252 | case IBinding.MEMBER_VALUE_PAIR: |
253 | IMemberValuePairBinding memberValuePairBinding= (IMemberValuePairBinding) fBinding; |
254 | res.add(new Binding(this, "METHOD BINDING", memberValuePairBinding.getMethodBinding(), true)); |
255 | res.add(new BindingProperty(this, "IS DEFAULT", memberValuePairBinding.isDefault(), true)); |
256 | res.add(Binding.createValueAttribute(this, "VALUE", memberValuePairBinding.getValue())); |
257 | break; |
258 | |
259 | case IBinding.MODULE: |
260 | IModuleBinding moduleBinding= (IModuleBinding) fBinding; |
261 | res.add(new BindingProperty(this, "REQUIRED MODULES", moduleBinding.getRequiredModules(), true)); |
262 | res.add(createPropertiesWithSecondary(moduleBinding.getExportedPackages(), "EXPORTED PACKAGES", "PACKAGE", "TO", |
263 | moduleBinding::getExportedTo)); |
264 | res.add(createPropertiesWithSecondary(moduleBinding.getOpenedPackages(), "OPENED PACKAGES", "PACKAGE", "TO", |
265 | moduleBinding::getOpenedTo)); |
266 | res.add(new BindingProperty(this, "USES", moduleBinding.getUses(), true)); |
267 | res.add(createPropertiesWithSecondary(moduleBinding.getServices(), "SERVICES", "PROVIDES", "WITH", |
268 | moduleBinding::getImplementations)); |
269 | break; |
270 | |
271 | default: |
272 | break; |
273 | } |
274 | try { |
275 | IAnnotationBinding[] annotations= fBinding.getAnnotations(); |
276 | res.add(new BindingProperty(this, "ANNOTATIONS", annotations, true)); //$NON-NLS-1$ |
277 | } catch (RuntimeException e) { |
278 | String label= "Error in IBinding#getAnnotations() for \"" + fBinding.getKey() + "\""; |
279 | res.add(new Error(this, label, e)); |
280 | ASTViewPlugin.log("Exception thrown in IBinding#getAnnotations() for \"" + fBinding.getKey() + "\"", e); |
281 | } |
282 | try { |
283 | IJavaElement javaElement= fBinding.getJavaElement(); |
284 | res.add(new JavaElement(this, javaElement)); |
285 | } catch (RuntimeException e) { |
286 | String label= ">java element: " + e.getClass().getName() + " for \"" + fBinding.getKey() + "\""; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ |
287 | res.add(new Error(this, label, e)); |
288 | ASTViewPlugin.log("Exception thrown in IBinding#getJavaElement() for \"" + fBinding.getKey() + "\"", e); |
289 | } |
290 | return res.toArray(); |
291 | } |
292 | return EMPTY; |
293 | } |
294 | |
295 | private <T extends IBinding> BindingProperty createPropertiesWithSecondary(T[] bindings, String propertiesName, String propertyName, String secondaryName, |
296 | Function<T, Object[]> secondaryAccessor) { |
297 | int count= bindings.length; |
298 | ASTAttribute[] attributes= new ASTAttribute[count * 2]; |
299 | BindingProperty property= new BindingProperty(this, propertiesName, attributes, true) { |
300 | @Override |
301 | public String getLabel() { |
302 | return propertiesName + " (" + count + ")"; |
303 | } |
304 | }; |
305 | for (int i= 0; i < count; i++) { |
306 | attributes[i * 2]= new Binding(this, propertyName, bindings[i], true); |
307 | Object[] secondaryPropertyValues= secondaryAccessor.apply(bindings[i]); |
308 | if (secondaryPropertyValues instanceof IBinding[]) { |
309 | attributes[i * 2 + 1]= new BindingProperty(this, secondaryName, (IBinding[]) secondaryPropertyValues, true); |
310 | } else { |
311 | GeneralAttribute[] secondaryProperties= new GeneralAttribute[secondaryPropertyValues.length]; |
312 | for (int j= 0; j < secondaryProperties.length; j++) { |
313 | secondaryProperties[j]= new GeneralAttribute(property, String.valueOf(j), String.valueOf(secondaryPropertyValues[j])); |
314 | } |
315 | attributes[i * 2 + 1]= new BindingProperty(this, secondaryName, secondaryProperties, true); |
316 | } |
317 | } |
318 | return property; |
319 | } |
320 | |
321 | private final static int ARRAY_TYPE= 1 << 0; |
322 | private final static int NULL_TYPE= 1 << 1; |
323 | private final static int VARIABLE_TYPE= 1 << 2; |
324 | private final static int WILDCARD_TYPE= 1 << 3; |
325 | private final static int CAPTURE_TYPE= 1 << 4; |
326 | private final static int PRIMITIVE_TYPE= 1 << 5; |
327 | |
328 | private final static int REF_TYPE= 1 << 6; |
329 | |
330 | private final static int GENERIC= 1 << 8; |
331 | private final static int PARAMETRIZED= 1 << 9; |
332 | |
333 | private int getTypeKind(ITypeBinding typeBinding) { |
334 | if (typeBinding.isArray()) return ARRAY_TYPE; |
335 | if (typeBinding.isCapture()) return CAPTURE_TYPE; |
336 | if (typeBinding.isNullType()) return NULL_TYPE; |
337 | if (typeBinding.isPrimitive()) return PRIMITIVE_TYPE; |
338 | if (typeBinding.isTypeVariable()) return VARIABLE_TYPE; |
339 | if (typeBinding.isWildcardType()) return WILDCARD_TYPE; |
340 | |
341 | if (typeBinding.isGenericType()) return REF_TYPE | GENERIC; |
342 | if (typeBinding.isParameterizedType() || typeBinding.isRawType()) return REF_TYPE | PARAMETRIZED; |
343 | |
344 | return REF_TYPE; |
345 | } |
346 | |
347 | @Override |
348 | public String getLabel() { |
349 | StringBuffer buf= new StringBuffer(fLabel); |
350 | buf.append(": "); //$NON-NLS-1$ |
351 | if (fBinding != null) { |
352 | switch (fBinding.getKind()) { |
353 | case IBinding.VARIABLE: |
354 | IVariableBinding variableBinding= (IVariableBinding) fBinding; |
355 | if (!variableBinding.isField()) { |
356 | buf.append(variableBinding.getName()); |
357 | } else { |
358 | if (variableBinding.getDeclaringClass() == null) { |
359 | buf.append("<some array type>"); //$NON-NLS-1$ |
360 | } else { |
361 | buf.append(variableBinding.getDeclaringClass().getName()); |
362 | } |
363 | buf.append('.'); |
364 | buf.append(variableBinding.getName()); |
365 | } |
366 | break; |
367 | case IBinding.PACKAGE: |
368 | IPackageBinding packageBinding= (IPackageBinding) fBinding; |
369 | buf.append(packageBinding.getName()); |
370 | break; |
371 | case IBinding.TYPE: |
372 | ITypeBinding typeBinding= (ITypeBinding) fBinding; |
373 | appendAnnotatedQualifiedName(buf, typeBinding); |
374 | break; |
375 | case IBinding.METHOD: |
376 | IMethodBinding methodBinding= (IMethodBinding) fBinding; |
377 | buf.append(methodBinding.getDeclaringClass().getName()); |
378 | buf.append('.'); |
379 | buf.append(methodBinding.getName()); |
380 | buf.append('('); |
381 | ITypeBinding[] parameters= methodBinding.getParameterTypes(); |
382 | for (int i= 0; i < parameters.length; i++) { |
383 | if (i > 0) { |
384 | buf.append(", "); //$NON-NLS-1$ |
385 | } |
386 | ITypeBinding parameter= parameters[i]; |
387 | buf.append(parameter.getName()); |
388 | } |
389 | buf.append(')'); |
390 | break; |
391 | case IBinding.ANNOTATION: |
392 | case IBinding.MEMBER_VALUE_PAIR: |
393 | buf.append(fBinding.toString()); |
394 | break; |
395 | case IBinding.MODULE: |
396 | buf.append(fBinding.getName()); |
397 | } |
398 | |
399 | } else { |
400 | buf.append("null"); //$NON-NLS-1$ |
401 | } |
402 | return buf.toString(); |
403 | |
404 | } |
405 | |
406 | public static void appendAnnotatedQualifiedName(StringBuffer buf, ITypeBinding typeBinding) { |
407 | String debugString= typeBinding.toString(); // XXX: hack, but that's OK for a debugging tool... |
408 | if (debugString.indexOf('\n') == -1 || typeBinding.getTypeAnnotations().length != 0) { |
409 | // one-liner || outermost type has type annotations |
410 | buf.append(debugString); |
411 | } else { |
412 | buf.append(typeBinding.getQualifiedName()); |
413 | } |
414 | } |
415 | |
416 | @Override |
417 | public Image getImage() { |
418 | return null; |
419 | } |
420 | |
421 | @Override |
422 | public String toString() { |
423 | return getLabel(); |
424 | } |
425 | |
426 | /* |
427 | * @see java.lang.Object#equals(java.lang.Object) |
428 | */ |
429 | @Override |
430 | public boolean equals(Object obj) { |
431 | if (this == obj) |
432 | return true; |
433 | if (obj == null || !obj.getClass().equals(getClass())) { |
434 | return false; |
435 | } |
436 | |
437 | Binding other= (Binding) obj; |
438 | if (!Objects.equals(fParent, other.fParent)) { |
439 | return false; |
440 | } |
441 | |
442 | if (!Objects.equals(fBinding, other.fBinding)) { |
443 | return false; |
444 | } |
445 | |
446 | if (!Objects.equals(fLabel, other.fLabel)) { |
447 | return false; |
448 | } |
449 | |
450 | return true; |
451 | } |
452 | |
453 | /* |
454 | * @see java.lang.Object#hashCode() |
455 | */ |
456 | @Override |
457 | public int hashCode() { |
458 | int result= fParent != null ? fParent.hashCode() : 0; |
459 | result+= (fBinding != null && fBinding.getKey() != null) ? fBinding.getKey().hashCode() : 0; |
460 | result+= fLabel != null ? fLabel.hashCode() : 0; |
461 | return result; |
462 | } |
463 | |
464 | public static String getBindingLabel(IBinding binding) { |
465 | String label; |
466 | if (binding == null) { |
467 | label= ">binding"; //$NON-NLS-1$ |
468 | } else { |
469 | switch (binding.getKind()) { |
470 | case IBinding.VARIABLE: |
471 | label= "> variable binding"; //$NON-NLS-1$ |
472 | break; |
473 | case IBinding.TYPE: |
474 | label= "> type binding"; //$NON-NLS-1$ |
475 | break; |
476 | case IBinding.METHOD: |
477 | label= "> method binding"; //$NON-NLS-1$ |
478 | break; |
479 | case IBinding.PACKAGE: |
480 | label= "> package binding"; //$NON-NLS-1$ |
481 | break; |
482 | case IBinding.ANNOTATION: |
483 | label= "> annotation binding"; //$NON-NLS-1$ |
484 | break; |
485 | case IBinding.MEMBER_VALUE_PAIR: |
486 | label= "> member value pair binding"; //$NON-NLS-1$ |
487 | break; |
488 | case IBinding.MODULE: |
489 | label= "> module binding"; //$NON-NLS-1$ |
490 | break; |
491 | default: |
492 | label= "> unknown binding"; //$NON-NLS-1$ |
493 | } |
494 | } |
495 | return label; |
496 | } |
497 | |
498 | /** |
499 | * Creates an {@link ASTAttribute} for a value from |
500 | * {@link IMemberValuePairBinding#getValue()} or from |
501 | * {@link IMethodBinding#getDefaultValue()}. |
502 | * |
503 | * @param parent the parent node |
504 | * @param name the attribute name |
505 | * @param value the attribute value |
506 | * @return an ASTAttribute |
507 | */ |
508 | public static ASTAttribute createValueAttribute(ASTAttribute parent, String name, Object value) { |
509 | ASTAttribute res; |
510 | if (value instanceof IBinding) { |
511 | IBinding binding= (IBinding) value; |
512 | res= new Binding(parent, name + ": " + getBindingLabel(binding), binding, true); |
513 | |
514 | } else if (value instanceof String) { |
515 | res= new GeneralAttribute(parent, name, getEscapedStringLiteral((String) value)); |
516 | |
517 | } else if (value instanceof Object[]) { |
518 | res= new GeneralAttribute(parent, name, (Object[]) value); |
519 | |
520 | } else if (value instanceof ASTAttribute) { |
521 | res= (ASTAttribute) value; |
522 | |
523 | } else { |
524 | res= new GeneralAttribute(parent, name, value); |
525 | } |
526 | return res; |
527 | } |
528 | |
529 | public static String getEscapedStringLiteral(String stringValue) { |
530 | StringLiteral stringLiteral= AST.newAST(ASTView.JLS_LATEST, false).newStringLiteral(); |
531 | stringLiteral.setLiteralValue(stringValue); |
532 | return stringLiteral.getEscapedValue(); |
533 | } |
534 | |
535 | public static String getEscapedCharLiteral(char charValue) { |
536 | CharacterLiteral charLiteral= AST.newAST(ASTView.JLS_LATEST, false).newCharacterLiteral(); |
537 | charLiteral.setCharValue(charValue); |
538 | return charLiteral.getEscapedValue(); |
539 | } |
540 | |
541 | private static StringBuffer getModifiersString(int flags, boolean isMethod) { |
542 | StringBuffer sb = new StringBuffer().append("0x").append(Integer.toHexString(flags)).append(" ("); |
543 | int prologLen= sb.length(); |
544 | int rest= flags; |
545 | |
546 | rest&= ~ appendFlag(sb, flags, Modifier.PUBLIC, "public "); |
547 | rest&= ~ appendFlag(sb, flags, Modifier.PRIVATE, "private "); |
548 | rest&= ~ appendFlag(sb, flags, Modifier.PROTECTED, "protected "); |
549 | rest&= ~ appendFlag(sb, flags, Modifier.STATIC, "static "); |
550 | rest&= ~ appendFlag(sb, flags, Modifier.FINAL, "final "); |
551 | if (isMethod) { |
552 | rest&= ~ appendFlag(sb, flags, Modifier.SYNCHRONIZED, "synchronized "); |
553 | rest&= ~ appendFlag(sb, flags, Modifier.DEFAULT, "default "); |
554 | } else { |
555 | rest&= ~ appendFlag(sb, flags, Modifier.VOLATILE, "volatile "); |
556 | rest&= ~ appendFlag(sb, flags, Modifier.TRANSIENT, "transient "); |
557 | } |
558 | rest&= ~ appendFlag(sb, flags, Modifier.NATIVE, "native "); |
559 | rest&= ~ appendFlag(sb, flags, Modifier.ABSTRACT, "abstract "); |
560 | rest&= ~ appendFlag(sb, flags, Modifier.STRICTFP, "strictfp "); |
561 | |
562 | if (rest != 0) |
563 | sb.append("unknown:0x").append(Integer.toHexString(rest)).append(" "); |
564 | int len = sb.length(); |
565 | if (len != prologLen) |
566 | sb.setLength(len - 1); |
567 | sb.append(")"); |
568 | return sb; |
569 | } |
570 | |
571 | private static int appendFlag(StringBuffer sb, int flags, int flag, String name) { |
572 | if ((flags & flag) != 0) { |
573 | sb.append(name); |
574 | return flag; |
575 | } else { |
576 | return 0; |
577 | } |
578 | } |
579 | } |
580 |
Members