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  *        Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
14  *                          Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
15  *       Jesper Steen Moeller - Contributions for:
16  *                          Bug 406973 - [compiler] Parse MethodParameters attribute
17  *******************************************************************************/
18 package org.eclipse.jdt.internal.core.util;
19 
20 import org.eclipse.jdt.core.JavaCore;
21 import org.eclipse.jdt.core.Signature;
22 import org.eclipse.jdt.core.compiler.CharOperation;
23 import org.eclipse.jdt.core.util.*;
24 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
25 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
26 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
27 
28 /**
29  * Disassembler of .class files. It generates an output in the Writer that looks close to
30  * the javap output.
31  */
32 public class Disassembler extends ClassFileBytesDisassembler {
33 
34 	private static final char[] ANY_EXCEPTION = Messages.classfileformat_anyexceptionhandler.toCharArray();
35 	private static final String VERSION_UNKNOWN = Messages.classfileformat_versionUnknown;
36 
appendModifier(StringBuffer buffer, int accessFlags, int modifierConstant, String modifier, boolean firstModifier)37 	private boolean appendModifier(StringBuffer buffer, int accessFlags, int modifierConstant, String modifier, boolean firstModifier) {
38 		if ((accessFlags & modifierConstant) != 0) {
39 			if (!firstModifier) {
40 				buffer.append(Messages.disassembler_space);
41 			}
42 			if (firstModifier) {
43 				firstModifier = false;
44 			}
45 			buffer.append(modifier);
46 		}
47 		return firstModifier;
48 	}
49 
decodeModifiers(StringBuffer buffer, int accessFlags, int[] checkBits)50 	private void decodeModifiers(StringBuffer buffer, int accessFlags, int[] checkBits) {
51 		decodeModifiers(buffer, accessFlags, false, false, checkBits);
52 	}
53 
decodeModifiers(StringBuffer buffer, int accessFlags, boolean printDefault, boolean asBridge, int[] checkBits)54 	private void decodeModifiers(StringBuffer buffer, int accessFlags, boolean printDefault, boolean asBridge, int[] checkBits) {
55 		if (checkBits == null) return;
56 		boolean firstModifier = true;
57 		for (int i = 0, max = checkBits.length; i < max; i++) {
58 			switch(checkBits[i]) {
59 				case IModifierConstants.ACC_PUBLIC :
60 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PUBLIC, "public", firstModifier); //$NON-NLS-1$
61 					break;
62 				case IModifierConstants.ACC_PROTECTED :
63 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PROTECTED, "protected", firstModifier); //$NON-NLS-1$
64 					break;
65 				case IModifierConstants.ACC_PRIVATE :
66 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PRIVATE, "private", firstModifier); //$NON-NLS-1$
67 					break;
68 				case IModifierConstants.ACC_ABSTRACT :
69 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ABSTRACT, "abstract", firstModifier); //$NON-NLS-1$
70 					break;
71 				case IModifierConstants.ACC_STATIC :
72 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC, "static", firstModifier); //$NON-NLS-1$
73 					break;
74 				case IModifierConstants.ACC_FINAL :
75 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_FINAL, "final", firstModifier); //$NON-NLS-1$
76 					break;
77 				case IModifierConstants.ACC_SYNCHRONIZED :
78 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_SYNCHRONIZED, "synchronized", firstModifier); //$NON-NLS-1$
79 					break;
80 				case IModifierConstants.ACC_NATIVE :
81 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_NATIVE, "native", firstModifier); //$NON-NLS-1$
82 					break;
83 				case IModifierConstants.ACC_STRICT :
84 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STRICT, "strictfp", firstModifier); //$NON-NLS-1$
85 					break;
86 				case IModifierConstants.ACC_TRANSIENT :
87 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_TRANSIENT, "transient", firstModifier); //$NON-NLS-1$
88 					break;
89 				case IModifierConstants.ACC_VOLATILE :
90 				// case IModifierConstants.ACC_BRIDGE :
91 					if (asBridge) {
92 						firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_BRIDGE, "bridge", firstModifier); //$NON-NLS-1$
93 					} else {
94 						firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_VOLATILE, "volatile", firstModifier); //$NON-NLS-1$
95 					}
96 					break;
97 				case IModifierConstants.ACC_ENUM :
98 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ENUM, "enum", firstModifier); //$NON-NLS-1$
99 					break;
100 				case IModifierConstants.ACC_SYNTHETIC :
101 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_SYNTHETIC, "synthetic", firstModifier); //$NON-NLS-1$
102 					break;
103 				case IModifierConstants.ACC_MANDATED :
104 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_MANDATED, "mandated", firstModifier); //$NON-NLS-1$
105 					break;
106 			}
107 		}
108 		if (!firstModifier) {
109 			if (!printDefault) buffer.append(Messages.disassembler_space);
110 		} else if (printDefault) {
111 			// no modifier: package default visibility
112 			buffer.append("default"); //$NON-NLS-1$
113 		}
114 	}
115 
decodeModifiersForField(StringBuffer buffer, int accessFlags)116 	private void decodeModifiersForField(StringBuffer buffer, int accessFlags) {
117 		decodeModifiers(buffer, accessFlags, new int[] {
118 				IModifierConstants.ACC_PUBLIC,
119 				IModifierConstants.ACC_PROTECTED,
120 				IModifierConstants.ACC_PRIVATE,
121 				IModifierConstants.ACC_STATIC,
122 				IModifierConstants.ACC_FINAL,
123 				IModifierConstants.ACC_TRANSIENT,
124 				IModifierConstants.ACC_VOLATILE,
125 				IModifierConstants.ACC_ENUM
126 		});
127 	}
128 
decodeModifiersForFieldForWorkingCopy(StringBuffer buffer, int accessFlags)129 	private void decodeModifiersForFieldForWorkingCopy(StringBuffer buffer, int accessFlags) {
130 		decodeModifiers(buffer, accessFlags, new int[] {
131 				IModifierConstants.ACC_PUBLIC,
132 				IModifierConstants.ACC_PROTECTED,
133 				IModifierConstants.ACC_PRIVATE,
134 				IModifierConstants.ACC_STATIC,
135 				IModifierConstants.ACC_FINAL,
136 				IModifierConstants.ACC_TRANSIENT,
137 				IModifierConstants.ACC_VOLATILE,
138 		});
139 	}
140 
decodeModifiersForInnerClasses(StringBuffer buffer, int accessFlags, boolean printDefault)141 	private final void decodeModifiersForInnerClasses(StringBuffer buffer, int accessFlags, boolean printDefault) {
142 		decodeModifiers(buffer, accessFlags, printDefault, false, new int[] {
143 				IModifierConstants.ACC_PUBLIC,
144 				IModifierConstants.ACC_PROTECTED,
145 				IModifierConstants.ACC_PRIVATE,
146 				IModifierConstants.ACC_ABSTRACT,
147 				IModifierConstants.ACC_STATIC,
148 				IModifierConstants.ACC_FINAL,
149 		});
150 	}
151 
decodeModifiersForMethod(StringBuffer buffer, int accessFlags)152 	private final void decodeModifiersForMethod(StringBuffer buffer, int accessFlags) {
153 		decodeModifiers(buffer, accessFlags, false, true, new int[] {
154 				IModifierConstants.ACC_PUBLIC,
155 				IModifierConstants.ACC_PROTECTED,
156 				IModifierConstants.ACC_PRIVATE,
157 				IModifierConstants.ACC_ABSTRACT,
158 				IModifierConstants.ACC_STATIC,
159 				IModifierConstants.ACC_FINAL,
160 				IModifierConstants.ACC_SYNCHRONIZED,
161 				IModifierConstants.ACC_NATIVE,
162 				IModifierConstants.ACC_STRICT,
163 				IModifierConstants.ACC_BRIDGE,
164 		});
165 	}
166 
decodeModifiersForMethodParameters(StringBuffer buffer, int accessFlags)167 	private final void decodeModifiersForMethodParameters(StringBuffer buffer, int accessFlags) {
168 		decodeModifiers(buffer, accessFlags, false, true, new int[] {
169 				IModifierConstants.ACC_FINAL,
170 				IModifierConstants.ACC_MANDATED,
171 				IModifierConstants.ACC_SYNTHETIC,
172 		});
173 	}
174 
decodeModifiersForType(StringBuffer buffer, int accessFlags)175 	private final void decodeModifiersForType(StringBuffer buffer, int accessFlags) {
176 		decodeModifiers(buffer, accessFlags, new int[] {
177 				IModifierConstants.ACC_PUBLIC,
178 				IModifierConstants.ACC_ABSTRACT,
179 				IModifierConstants.ACC_FINAL,
180 		});
181 	}
decodeModifiersForModuleRequires(StringBuffer buffer, int accessFlags)182 	private final void decodeModifiersForModuleRequires(StringBuffer buffer, int accessFlags) {
183 		int[] checkBits = new int[] {
184 				IModifierConstants.ACC_TRANSITIVE,
185 				IModifierConstants.ACC_STATIC_PHASE,
186 		};
187 		boolean firstModifier = true;
188 		for (int i = 0, max = checkBits.length; i < max; i++) {
189 			switch(checkBits[i]) {
190 				case IModifierConstants.ACC_TRANSITIVE :
191 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_TRANSITIVE, "transitive", firstModifier); //$NON-NLS-1$
192 					break;
193 				case IModifierConstants.ACC_STATIC_PHASE :
194 					firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC_PHASE, "protected", firstModifier); //$NON-NLS-1$
195 					break;
196 			}
197 		}
198 		if (!firstModifier) {
199 			buffer.append(Messages.disassembler_space);
200 		}
201 	}
decodeModifiersForModule(StringBuffer buffer, int accessFlags)202 	private final void decodeModifiersForModule(StringBuffer buffer, int accessFlags) {
203 		appendModifier(buffer, accessFlags, IModifierConstants.ACC_OPEN, "open", true); //$NON-NLS-1$
204 		buffer.append(Messages.disassembler_space);
205 	}
escapeString(String s)206 	public static String escapeString(String s) {
207 		return decodeStringValue(s);
208 	}
209 
decodeStringValue(char[] chars)210 	static String decodeStringValue(char[] chars) {
211 		StringBuffer buffer = new StringBuffer();
212 		for (int i = 0, max = chars.length; i < max; i++) {
213 			char c = chars[i];
214 			org.eclipse.jdt.internal.compiler.util.Util.appendEscapedChar(buffer, c, true);
215 		}
216 		return buffer.toString();
217 	}
218 
escapeChar(StringBuffer buffer, char c)219 	private static void escapeChar(StringBuffer buffer, char c) {
220 		org.eclipse.jdt.internal.compiler.util.Util.appendEscapedChar(buffer, c, false);
221 	}
222 
decodeStringValue(String s)223 	static String decodeStringValue(String s) {
224 		return decodeStringValue(s.toCharArray());
225 	}
226 
227 	/**
228 	 * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#disassemble(byte[], java.lang.String)
229 	 */
230 	@Override
disassemble(byte[] classFileBytes, String lineSeparator)231 	public String disassemble(byte[] classFileBytes, String lineSeparator) throws ClassFormatException {
232 		try {
233 			return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, ClassFileBytesDisassembler.DEFAULT);
234 		} catch (ArrayIndexOutOfBoundsException e) {
235 			throw new ClassFormatException(e.getMessage(), e);
236 		}
237 	}
238 
239 	/**
240 	 * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#disassemble(byte[], java.lang.String, int)
241 	 */
242 	@Override
disassemble(byte[] classFileBytes, String lineSeparator, int mode)243 	public String disassemble(byte[] classFileBytes, String lineSeparator, int mode) throws ClassFormatException {
244 		try {
245 			return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, mode);
246 		} catch (ArrayIndexOutOfBoundsException e) {
247 			throw new ClassFormatException(e.getMessage(), e);
248 		}
249 	}
250 
disassemble(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)251 	private void disassemble(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
252 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
253 		final int typeIndex = annotation.getTypeIndex();
254 		final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
255 		buffer.append(
256 			Messages.bind(Messages.disassembler_annotationentrystart, new String[] {
257 				Integer.toString(typeIndex),
258 				new String(returnClassName(Signature.toCharArray(typeName), '.', mode))
259 			}));
260 		final IAnnotationComponent[] components = annotation.getComponents();
261 		for (int i = 0, max = components.length; i < max; i++) {
262 			disassemble(components[i], buffer, lineSeparator, tabNumber + 1, mode);
263 		}
264 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
265 		buffer.append(Messages.disassembler_annotationentryend);
266 	}
267 
disassemble(IExtendedAnnotation extendedAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)268 	private void disassemble(IExtendedAnnotation extendedAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
269 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
270 		final int typeIndex = extendedAnnotation.getTypeIndex();
271 		final char[] typeName = CharOperation.replaceOnCopy(extendedAnnotation.getTypeName(), '/', '.');
272 		buffer.append(
273 			Messages.bind(Messages.disassembler_extendedannotationentrystart, new String[] {
274 				Integer.toString(typeIndex),
275 				new String(returnClassName(Signature.toCharArray(typeName), '.', mode))
276 			}));
277 		final IAnnotationComponent[] components = extendedAnnotation.getComponents();
278 		for (int i = 0, max = components.length; i < max; i++) {
279 			disassemble(components[i], buffer, lineSeparator, tabNumber + 1, mode);
280 		}
281 		writeNewLine(buffer, lineSeparator, tabNumber + 2);
282 		int targetType = extendedAnnotation.getTargetType();
283 		buffer.append(
284 				Messages.bind(Messages.disassembler_extendedannotation_targetType, new String[] {
285 					Integer.toHexString(targetType),
286 					getTargetType(targetType),
287 				}));
288 		switch(targetType) {
289 			case IExtendedAnnotationConstants.METHOD_RECEIVER :
290 			case IExtendedAnnotationConstants.METHOD_RETURN:
291 			case IExtendedAnnotationConstants.FIELD :
292 				break;
293 			default:
294 				writeNewLine(buffer, lineSeparator, tabNumber + 2);
295 				disassembleTargetTypeContents(false, targetType, extendedAnnotation, buffer, lineSeparator, tabNumber, mode);
296 		}
297 		disassembleTypePathContents(targetType, extendedAnnotation, buffer, lineSeparator, tabNumber, mode);
298 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
299 		buffer.append(Messages.disassembler_extendedannotationentryend);
300 	}
301 
disassembleTypePathContents(int targetType, IExtendedAnnotation extendedAnnotation,StringBuffer buffer, String lineSeparator, int tabNumber, int mode)302 	private void disassembleTypePathContents(int targetType, IExtendedAnnotation extendedAnnotation,StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
303 		int[][] typepath = extendedAnnotation.getTypePath();
304 		if (typepath.length != 0) {
305 			writeNewLine(buffer, lineSeparator, tabNumber + 2);
306 			buffer.append(
307 				Messages.bind(Messages.disassembler_extendedannotation_typepath, new String[] {
308 						toTypePathString(typepath),
309 				}));
310 		}
311 	}
disassembleTargetTypeContents(boolean insideWildcard, int targetType, IExtendedAnnotation extendedAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)312 	private void disassembleTargetTypeContents(boolean insideWildcard, int targetType, IExtendedAnnotation extendedAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
313 		switch(targetType) {
314 			case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER :
315 			case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER :
316 				buffer.append(
317 						Messages.bind(Messages.disassembler_extendedannotation_type_parameter, new String[] {
318 							Integer.toString(extendedAnnotation.getTypeParameterIndex()),
319 						}));
320 				break;
321 			case IExtendedAnnotationConstants.CLASS_EXTENDS :
322 				buffer.append(
323 					Messages.bind(Messages.disassembler_extendedannotation_classextendsimplements, new String[] {
324 						Integer.toString(extendedAnnotation.getAnnotationTypeIndex()),
325 					}));
326 				break;
327 
328 			case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_BOUND :
329 			case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND :
330 				buffer.append(
331 						Messages.bind(Messages.disassembler_extendedannotation_type_parameter_with_bound, new String[] {
332 							Integer.toString(extendedAnnotation.getTypeParameterIndex()),
333 							Integer.toString(extendedAnnotation.getTypeParameterBoundIndex()),
334 						}));
335 				break;
336 			case IExtendedAnnotationConstants.FIELD :
337 			case IExtendedAnnotationConstants.METHOD_RETURN :
338 			case IExtendedAnnotationConstants.METHOD_RECEIVER :
339 				break;
340 			case IExtendedAnnotationConstants.METHOD_FORMAL_PARAMETER :
341 				buffer.append(
342 						Messages.bind(Messages.disassembler_extendedannotation_method_parameter, new String[] {
343 							Integer.toString(extendedAnnotation.getParameterIndex()),
344 						}));
345 				break;
346 			case IExtendedAnnotationConstants.THROWS :
347 				buffer.append(
348 						Messages.bind(Messages.disassembler_extendedannotation_throws, new String[] {
349 							Integer.toString(extendedAnnotation.getAnnotationTypeIndex()),
350 						}));
351 				break;
352 
353 			case IExtendedAnnotationConstants.LOCAL_VARIABLE :
354 			case IExtendedAnnotationConstants.RESOURCE_VARIABLE :
355 				buffer.append(Messages.disassembler_localvariabletargetheader);
356 				writeNewLine(buffer, lineSeparator, tabNumber + 3);
357 				int localVariableTableSize = extendedAnnotation.getLocalVariableRefenceInfoLength();
358 				ILocalVariableReferenceInfo[] localVariableTable = extendedAnnotation.getLocalVariableTable();
359 				for (int i = 0; i < localVariableTableSize; i++) {
360 					if (i != 0) {
361 						writeNewLine(buffer, lineSeparator, tabNumber + 3);
362 					}
363 					ILocalVariableReferenceInfo info = localVariableTable[i];
364 					int index= info.getIndex();
365 					int startPC = info.getStartPC();
366 					int length  = info.getLength();
367 					buffer.append(Messages.bind(Messages.classfileformat_localvariablereferenceinfoentry,
368 						new String[] {
369 							Integer.toString(startPC),
370 							Integer.toString(startPC + length),
371 							Integer.toString(index),
372 						}));
373 				}
374 				break;
375 			case IExtendedAnnotationConstants.EXCEPTION_PARAMETER :
376 				buffer.append(
377 						Messages.bind(Messages.disassembler_extendedannotation_exception_table_index, new String[] {
378 							Integer.toString(extendedAnnotation.getExceptionTableIndex()),
379 						}));
380 				break;
381 
382 			case IExtendedAnnotationConstants.INSTANCEOF :
383 			case IExtendedAnnotationConstants.NEW :
384 			case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE :
385 			case IExtendedAnnotationConstants.METHOD_REFERENCE :
386 				buffer.append(
387 						Messages.bind(Messages.disassembler_extendedannotation_offset, new String[] {
388 							Integer.toString(extendedAnnotation.getOffset()),
389 						}));
390 				break;
391 			case IExtendedAnnotationConstants.CAST :
392 			case IExtendedAnnotationConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT :
393 			case IExtendedAnnotationConstants.METHOD_INVOCATION_TYPE_ARGUMENT :
394 			case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT :
395 			case IExtendedAnnotationConstants.METHOD_REFERENCE_TYPE_ARGUMENT :
396 				buffer.append(
397 						Messages.bind(Messages.disassembler_extendedannotation_offset, new String[] {
398 							Integer.toString(extendedAnnotation.getOffset()),
399 						}));
400 				writeNewLine(buffer, lineSeparator, tabNumber + 2);
401 				buffer.append(
402 						Messages.bind(Messages.disassembler_extendedannotation_type_argument, new String[] {
403 							Integer.toString(extendedAnnotation.getAnnotationTypeIndex()),
404 						}));
405 				break;
406 		}
407 	}
getTargetType(int targetType)408 	private String getTargetType(int targetType) {
409 		switch(targetType) {
410 			case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER :
411 				return "CLASS_TYPE_PARAMETER"; //$NON-NLS-1$
412 			case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER :
413 				return "METHOD_TYPE_PARAMETER"; //$NON-NLS-1$
414 
415 			case IExtendedAnnotationConstants.CLASS_EXTENDS :
416 				return "CLASS_EXTENDS"; //$NON-NLS-1$
417 			case IExtendedAnnotationConstants.CLASS_TYPE_PARAMETER_BOUND :
418 				return "CLASS_TYPE_PARAMETER_BOUND"; //$NON-NLS-1$
419 			case IExtendedAnnotationConstants.METHOD_TYPE_PARAMETER_BOUND :
420 				return "METHOD_TYPE_PARAMETER_BOUND"; //$NON-NLS-1$
421 			case IExtendedAnnotationConstants.FIELD :
422 				return "FIELD"; //$NON-NLS-1$
423 			case IExtendedAnnotationConstants.METHOD_RETURN :
424 				return "METHOD_RETURN"; //$NON-NLS-1$
425 			case IExtendedAnnotationConstants.METHOD_RECEIVER :
426 				return "METHOD_RECEIVER"; //$NON-NLS-1$
427 			case IExtendedAnnotationConstants.METHOD_FORMAL_PARAMETER :
428 				return "METHOD_FORMAL_PARAMETER"; //$NON-NLS-1$
429 			case IExtendedAnnotationConstants.THROWS :
430 				return "THROWS"; //$NON-NLS-1$
431 
432 			case IExtendedAnnotationConstants.LOCAL_VARIABLE :
433 				return "LOCAL_VARIABLE"; //$NON-NLS-1$
434 			case IExtendedAnnotationConstants.RESOURCE_VARIABLE :
435 				return "RESOURCE_VARIABLE"; //$NON-NLS-1$
436 			case IExtendedAnnotationConstants.EXCEPTION_PARAMETER :
437 				return "EXCEPTION_PARAMETER"; //$NON-NLS-1$
438 			case IExtendedAnnotationConstants.INSTANCEOF :
439 				return "INSTANCEOF"; //$NON-NLS-1$
440 			case IExtendedAnnotationConstants.NEW :
441 				return "NEW"; //$NON-NLS-1$
442 			case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE :
443 				return "CONSTRUCTOR_REFERENCE"; //$NON-NLS-1$
444 			case IExtendedAnnotationConstants.METHOD_REFERENCE :
445 				return "METHOD_REFERENCE"; //$NON-NLS-1$
446 			case IExtendedAnnotationConstants.CAST :
447 				return "CAST"; //$NON-NLS-1$
448 			case IExtendedAnnotationConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT :
449 				return "CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT"; //$NON-NLS-1$
450 			case IExtendedAnnotationConstants.METHOD_INVOCATION_TYPE_ARGUMENT :
451 				return "METHOD_INVOCATION_TYPE_ARGUMENT"; //$NON-NLS-1$
452 			case IExtendedAnnotationConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT :
453 				return "CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT"; //$NON-NLS-1$
454 			case IExtendedAnnotationConstants.METHOD_REFERENCE_TYPE_ARGUMENT :
455 				return "METHOD_REFERENCE_TYPE_ARGUMENT"; //$NON-NLS-1$
456 			default:
457 				return "UNKNOWN"; //$NON-NLS-1$
458 		}
459 	}
460 
461 
disassemble(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)462 	private void disassemble(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
463 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
464 		buffer.append(
465 			Messages.bind(Messages.disassembler_annotationcomponent,
466 				new String[] {
467 					Integer.toString(annotationComponent.getComponentNameIndex()),
468 					new String(annotationComponent.getComponentName())
469 				}));
470 		disassemble(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1, mode);
471 	}
472 
disassemble(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)473 	private void disassemble(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
474 		switch(annotationComponentValue.getTag()) {
475 			case IAnnotationComponentValue.BYTE_TAG:
476 			case IAnnotationComponentValue.CHAR_TAG:
477 			case IAnnotationComponentValue.DOUBLE_TAG:
478 			case IAnnotationComponentValue.FLOAT_TAG:
479 			case IAnnotationComponentValue.INTEGER_TAG:
480 			case IAnnotationComponentValue.LONG_TAG:
481 			case IAnnotationComponentValue.SHORT_TAG:
482 			case IAnnotationComponentValue.BOOLEAN_TAG:
483 			case IAnnotationComponentValue.STRING_TAG:
484 				IConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue();
485 				String value = null;
486 				switch(constantPoolEntry.getKind()) {
487 					case IConstantPoolConstant.CONSTANT_Long :
488 						value = constantPoolEntry.getLongValue() + "L"; //$NON-NLS-1$
489 						break;
490 					case IConstantPoolConstant.CONSTANT_Float :
491 						value = constantPoolEntry.getFloatValue() + "f"; //$NON-NLS-1$
492 						break;
493 					case IConstantPoolConstant.CONSTANT_Double :
494 						value = Double.toString(constantPoolEntry.getDoubleValue());
495 						break;
496 					case IConstantPoolConstant.CONSTANT_Integer:
497 						StringBuffer temp = new StringBuffer();
498 						switch(annotationComponentValue.getTag()) {
499 							case IAnnotationComponentValue.CHAR_TAG :
500 								temp.append('\'');
501 								escapeChar(temp, (char) constantPoolEntry.getIntegerValue());
502 								temp.append('\'');
503 								break;
504 							case IAnnotationComponentValue.BOOLEAN_TAG :
505 								temp.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$
506 								break;
507 							case IAnnotationComponentValue.BYTE_TAG :
508 								temp.append("(byte) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$
509 								break;
510 							case IAnnotationComponentValue.SHORT_TAG :
511 								temp.append("(short) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$
512 								break;
513 							case IAnnotationComponentValue.INTEGER_TAG :
514 								temp.append("(int) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$
515 						}
516 						value = String.valueOf(temp);
517 						break;
518 					case IConstantPoolConstant.CONSTANT_Utf8:
519 						value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$
520 				}
521 				buffer.append(Messages.bind(Messages.disassembler_annotationdefaultvalue, value));
522 				break;
523 			case IAnnotationComponentValue.ENUM_TAG:
524 				final int enumConstantTypeNameIndex = annotationComponentValue.getEnumConstantTypeNameIndex();
525 				final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.');
526 				final int enumConstantNameIndex = annotationComponentValue.getEnumConstantNameIndex();
527 				final char[] constantName = annotationComponentValue.getEnumConstantName();
528 				buffer.append(Messages.bind(Messages.disassembler_annotationenumvalue,
529 					new String[] {
530 						Integer.toString(enumConstantTypeNameIndex),
531 						Integer.toString(enumConstantNameIndex),
532 						new String(returnClassName(Signature.toCharArray(typeName), '.', mode)),
533 						new String(constantName)
534 					}));
535 				break;
536 			case IAnnotationComponentValue.CLASS_TAG:
537 				final int classIndex = annotationComponentValue.getClassInfoIndex();
538 				constantPoolEntry = annotationComponentValue.getClassInfo();
539 				final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.');
540 				buffer.append(Messages.bind(Messages.disassembler_annotationclassvalue,
541 					new String[] {
542 						Integer.toString(classIndex),
543 						new String(returnClassName(Signature.toCharArray(className), '.', mode))
544 					}));
545 				break;
546 			case IAnnotationComponentValue.ANNOTATION_TAG:
547 				buffer.append(Messages.disassembler_annotationannotationvalue);
548 				IAnnotation annotation = annotationComponentValue.getAnnotationValue();
549 				disassemble(annotation, buffer, lineSeparator, tabNumber + 1, mode);
550 				break;
551 			case IAnnotationComponentValue.ARRAY_TAG:
552 				buffer.append(Messages.disassembler_annotationarrayvaluestart);
553 				final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues();
554 				for (int i = 0, max = annotationComponentValues.length; i < max; i++) {
555 					writeNewLine(buffer, lineSeparator, tabNumber + 1);
556 					disassemble(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1, mode);
557 				}
558 				writeNewLine(buffer, lineSeparator, tabNumber + 1);
559 				buffer.append(Messages.disassembler_annotationarrayvalueend);
560 		}
561 	}
562 
disassemble(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)563 	private void disassemble(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
564 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
565 		buffer.append(Messages.disassembler_annotationdefaultheader);
566 		IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue();
567 		writeNewLine(buffer, lineSeparator, tabNumber + 2);
568 		disassemble(componentValue, buffer, lineSeparator, tabNumber + 1, mode);
569 	}
570 
disassemble(IClassFileAttribute classFileAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)571 	private void disassemble(IClassFileAttribute classFileAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
572 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
573 		buffer.append(Messages.bind(Messages.disassembler_genericattributeheader,
574 			new String[] {
575 				new String(classFileAttribute.getAttributeName()),
576 				Long.toString(classFileAttribute.getAttributeLength())
577 			}));
578 	}
579 
disassemble(IMethodParametersAttribute methodParametersAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)580 	private void disassemble(IMethodParametersAttribute methodParametersAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
581 		tabNumber += 2;
582 		writeNewLine(buffer, lineSeparator, tabNumber);
583 		buffer.append(Messages.disassembler_methodparametersheader);
584 		for (int i = 0, length = methodParametersAttribute.getMethodParameterLength(); i < length; ++i) {
585 			writeNewLine(buffer, lineSeparator, tabNumber + 1);
586 			short accessFlags = methodParametersAttribute.getAccessFlags(i);
587 			decodeModifiersForMethodParameters(buffer, accessFlags);
588 			char [] parameterName = methodParametersAttribute.getParameterName(i);
589 			if (parameterName == null)
590 				parameterName = Messages.disassembler_anonymousparametername.toCharArray();
591 			buffer.append(parameterName);
592 		}
593 	}
594 
disassembleEnumConstructor(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)595 	private void disassembleEnumConstructor(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
596 		writeNewLine(buffer, lineSeparator, tabNumber);
597 		final ICodeAttribute codeAttribute = methodInfo.getCodeAttribute();
598 		IMethodParametersAttribute methodParametersAttribute = (IMethodParametersAttribute) Util.getAttribute(methodInfo, IAttributeNamesConstants.METHOD_PARAMETERS);
599 		char[] methodDescriptor = methodInfo.getDescriptor();
600 		final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
601 		final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
602 		// disassemble compact version of annotations
603 		if (runtimeInvisibleAnnotationsAttribute != null) {
604 			disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
605 			writeNewLine(buffer, lineSeparator, tabNumber);
606 		}
607 		if (runtimeVisibleAnnotationsAttribute != null) {
608 			disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
609 			writeNewLine(buffer, lineSeparator, tabNumber);
610 		}
611 		final int accessFlags = methodInfo.getAccessFlags();
612 		decodeModifiersForMethod(buffer, accessFlags & IModifierConstants.ACC_PRIVATE);
613 		CharOperation.replace(methodDescriptor, '/', '.');
614 		final boolean isVarArgs = (accessFlags & IModifierConstants.ACC_VARARGS) != 0;
615 		final char[] signature = Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, methodParametersAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs);
616 		int index = CharOperation.indexOf(',', signature);
617 		index = CharOperation.indexOf(',', signature, index + 1);
618 		buffer.append(signature, 0, CharOperation.indexOf('(', signature) + 1);
619 		buffer.append(signature, index + 2, signature.length - index - 2);
620 		IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute();
621 		if (exceptionAttribute != null) {
622 			buffer.append(" throws "); //$NON-NLS-1$
623 			char[][] exceptionNames = exceptionAttribute.getExceptionNames();
624 			int length = exceptionNames.length;
625 			for (int i = 0; i < length; i++) {
626 				if (i != 0) {
627 					buffer
628     					.append(Messages.disassembler_comma)
629     					.append(Messages.disassembler_space);
630 				}
631 				char[] exceptionName = exceptionNames[i];
632 				CharOperation.replace(exceptionName, '/', '.');
633 				buffer.append(returnClassName(exceptionName, '.', mode));
634 			}
635 		}
636 		if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0)
637 				&& ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) {
638 			buffer.append(" {"); //$NON-NLS-1$
639 			final char[] returnType = Signature.getReturnType(methodDescriptor);
640 			if (returnType.length == 1) {
641 				switch(returnType[0]) {
642 					case 'V' :
643 						writeNewLine(buffer, lineSeparator, tabNumber);
644 						break;
645 					case 'I' :
646 					case 'B' :
647 					case 'J' :
648 					case 'D' :
649 					case 'F' :
650 					case 'S' :
651 					case 'C' :
652 						writeNewLine(buffer, lineSeparator, tabNumber + 1);
653 						buffer.append("return 0;"); //$NON-NLS-1$
654 						writeNewLine(buffer, lineSeparator, tabNumber);
655 						break;
656 					default :
657 						// boolean
658 						writeNewLine(buffer, lineSeparator, tabNumber + 1);
659 						buffer.append("return false;"); //$NON-NLS-1$
660 						writeNewLine(buffer, lineSeparator, tabNumber);
661 				}
662 			} else {
663 				// object
664 				writeNewLine(buffer, lineSeparator, tabNumber + 1);
665 				buffer.append("return null;"); //$NON-NLS-1$
666 				writeNewLine(buffer, lineSeparator, tabNumber);
667 			}
668 			buffer.append('}');
669 		} else {
670 			buffer.append(';');
671 		}
672 	}
673 
674 	/**
675 	 * Disassemble a method info header
676 	 */
disassemble(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)677 	private void disassemble(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
678 		writeNewLine(buffer, lineSeparator, tabNumber);
679 		final ICodeAttribute codeAttribute = methodInfo.getCodeAttribute();
680 		final char[] methodDescriptor = methodInfo.getDescriptor();
681 		final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(methodInfo, IAttributeNamesConstants.SIGNATURE);
682 		final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
683 		final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
684 		final IClassFileAttribute runtimeVisibleTypeAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
685 		final IClassFileAttribute runtimeInvisibleTypeAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
686 		final IClassFileAttribute runtimeVisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS);
687 		final IClassFileAttribute runtimeInvisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS);
688 		final IClassFileAttribute methodParametersAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.METHOD_PARAMETERS);
689 		final IClassFileAttribute annotationDefaultAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.ANNOTATION_DEFAULT);
690 		if (checkMode(mode, SYSTEM | DETAILED)) {
691 			buffer.append(Messages.bind(Messages.classfileformat_methoddescriptor,
692 				new String[] {
693 					Integer.toString(methodInfo.getDescriptorIndex()),
694 					new String(methodDescriptor)
695 				}));
696 			if (methodInfo.isDeprecated()) {
697 				buffer.append(Messages.disassembler_deprecated);
698 			}
699 			writeNewLine(buffer, lineSeparator, tabNumber);
700 			if (signatureAttribute != null) {
701 				buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature())));
702 				writeNewLine(buffer, lineSeparator, tabNumber);
703 			}
704 			if (codeAttribute != null) {
705 				buffer.append(Messages.bind(Messages.classfileformat_stacksAndLocals,
706 					new String[] {
707 						Integer.toString(codeAttribute.getMaxStack()),
708 						Integer.toString(codeAttribute.getMaxLocals())
709 					}));
710 				writeNewLine(buffer, lineSeparator, tabNumber);
711 			}
712 		}
713 		if (checkMode(mode, DETAILED)) {
714 			// disassemble compact version of annotations
715 			if (runtimeInvisibleAnnotationsAttribute != null) {
716 				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
717 				writeNewLine(buffer, lineSeparator, tabNumber);
718 			}
719 			if (runtimeVisibleAnnotationsAttribute != null) {
720 				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
721 				writeNewLine(buffer, lineSeparator, tabNumber);
722 			}
723 		}
724 		final int accessFlags = methodInfo.getAccessFlags();
725 		decodeModifiersForMethod(buffer, accessFlags);
726 		if (methodInfo.isSynthetic() && !checkMode(mode, WORKING_COPY)) {
727 			buffer.append("synthetic"); //$NON-NLS-1$
728 			buffer.append(Messages.disassembler_space);
729 		}
730 		CharOperation.replace(methodDescriptor, '/', '.');
731 		final boolean isVarArgs = isVarArgs(methodInfo);
732 		char[] methodHeader = null;
733 		char[][] parameterNames = null;
734 		if (!methodInfo.isClinit()) {
735 			parameterNames = getParameterNames(methodDescriptor, codeAttribute, (IMethodParametersAttribute)methodParametersAttribute, accessFlags);
736 		}
737 		if (methodInfo.isConstructor()) {
738 			if (checkMode(mode, WORKING_COPY) && signatureAttribute != null) {
739 				final char[] signature = signatureAttribute.getSignature();
740 				CharOperation.replace(signature, '/', '.');
741 				disassembleGenericSignature(mode, buffer, signature);
742 				buffer.append(' ');
743 				methodHeader = Signature.toCharArray(signature, returnClassName(className, '.', COMPACT), parameterNames, !checkMode(mode, COMPACT), false, isVarArgs);
744 			} else {
745 				methodHeader = Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), parameterNames, !checkMode(mode, COMPACT), false, isVarArgs);
746 			}
747 		} else if (methodInfo.isClinit()) {
748 			methodHeader = Messages.bind(Messages.classfileformat_clinitname).toCharArray();
749 		} else {
750 			if (checkMode(mode, WORKING_COPY) && signatureAttribute != null) {
751 				final char[] signature = signatureAttribute.getSignature();
752 				CharOperation.replace(signature, '/', '.');
753 				disassembleGenericSignature(mode, buffer, signature);
754 				buffer.append(' ');
755 				methodHeader = Signature.toCharArray(signature, methodInfo.getName(), parameterNames, !checkMode(mode, COMPACT), true, isVarArgs);
756 			} else {
757 				methodHeader = Signature.toCharArray(methodDescriptor, methodInfo.getName(), parameterNames, !checkMode(mode, COMPACT), true, isVarArgs);
758 			}
759 		}
760 		if (checkMode(mode, DETAILED) && (runtimeInvisibleParameterAnnotationsAttribute != null || runtimeVisibleParameterAnnotationsAttribute != null)) {
761 			IParameterAnnotation[] invisibleParameterAnnotations = null;
762 			IParameterAnnotation[] visibleParameterAnnotations = null;
763 			int length = -1;
764 			if (runtimeInvisibleParameterAnnotationsAttribute != null) {
765 				IRuntimeInvisibleParameterAnnotationsAttribute attribute = (IRuntimeInvisibleParameterAnnotationsAttribute) runtimeInvisibleParameterAnnotationsAttribute;
766 				invisibleParameterAnnotations = attribute.getParameterAnnotations();
767 				length = invisibleParameterAnnotations.length;
768 				if (length > 0) {
769 					int parameterNamesLength = parameterNames.length;
770 					if (length < parameterNamesLength) {
771 						System.arraycopy(invisibleParameterAnnotations, 0, (invisibleParameterAnnotations = new IParameterAnnotation[parameterNamesLength]), 1, length);
772 						length = parameterNamesLength;
773 					}
774 				}
775 			}
776 			if (runtimeVisibleParameterAnnotationsAttribute != null) {
777 				IRuntimeVisibleParameterAnnotationsAttribute attribute = (IRuntimeVisibleParameterAnnotationsAttribute) runtimeVisibleParameterAnnotationsAttribute;
778 				visibleParameterAnnotations = attribute.getParameterAnnotations();
779 				length = visibleParameterAnnotations.length;
780 				if (length > 0) {
781 					int parameterNamesLength = parameterNames.length;
782 					if (length < parameterNamesLength) {
783 						System.arraycopy(visibleParameterAnnotations, 0, (visibleParameterAnnotations = new IParameterAnnotation[parameterNamesLength]), 1, length);
784 						length = parameterNamesLength;
785 					}
786 				}
787 			}
788 			int insertionPosition = CharOperation.indexOf('(', methodHeader) + 1;
789 			int start = 0;
790 			StringBuffer stringBuffer = new StringBuffer();
791 			stringBuffer.append(methodHeader, 0, insertionPosition);
792 			for (int i = 0; i < length; i++) {
793 				if (i > 0) {
794 					stringBuffer.append(' ');
795 				}
796 				int stringBufferSize = stringBuffer.length();
797 				if (visibleParameterAnnotations != null) {
798 					disassembleAsModifier(visibleParameterAnnotations, stringBuffer, i, lineSeparator, tabNumber, mode);
799 				}
800 				if (invisibleParameterAnnotations != null) {
801 					if (stringBuffer.length() != stringBufferSize) {
802 						stringBuffer.append(' ');
803 						stringBufferSize = stringBuffer.length();
804 					}
805 					disassembleAsModifier(invisibleParameterAnnotations, stringBuffer, i, lineSeparator, tabNumber, mode);
806 				}
807 				if (i == 0 && stringBuffer.length() != stringBufferSize) {
808 					stringBuffer.append(' ');
809 				}
810 				start = insertionPosition;
811 				insertionPosition = CharOperation.indexOf(',', methodHeader, start + 1) + 1;
812 				if (insertionPosition == 0) {
813 					stringBuffer.append(methodHeader, start, methodHeader.length - start);
814 				} else {
815 					stringBuffer.append(methodHeader, start, insertionPosition - start);
816 				}
817 			}
818 			buffer.append(stringBuffer);
819 		} else {
820 			buffer.append(methodHeader);
821 		}
822 		IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute();
823 		if (exceptionAttribute != null) {
824 			buffer.append(" throws "); //$NON-NLS-1$
825 			char[][] exceptionNames = exceptionAttribute.getExceptionNames();
826 			int length = exceptionNames.length;
827 			for (int i = 0; i < length; i++) {
828 				if (i != 0) {
829 					buffer
830 						.append(Messages.disassembler_comma)
831 						.append(Messages.disassembler_space);
832 				}
833 				char[] exceptionName = exceptionNames[i];
834 				CharOperation.replace(exceptionName, '/', '.');
835 				buffer.append(returnClassName(exceptionName, '.', mode));
836 			}
837 		}
838 		if (checkMode(mode, DETAILED)) {
839 			if (annotationDefaultAttribute != null) {
840 				buffer.append(" default "); //$NON-NLS-1$
841 				disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
842 			}
843 		}
844 		if (checkMode(mode, WORKING_COPY)) {
845 			// put the annotation default attribute if needed
846 			if (annotationDefaultAttribute != null) {
847 				buffer.append(" default "); //$NON-NLS-1$
848 				disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
849 			}
850 			if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0)
851 					&& ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) {
852 				buffer.append(" {"); //$NON-NLS-1$
853 				final char[] returnType = Signature.getReturnType(methodDescriptor);
854 				if (returnType.length == 1) {
855 					switch(returnType[0]) {
856 						case 'V' :
857 							writeNewLine(buffer, lineSeparator, tabNumber);
858 							break;
859 						case 'I' :
860 						case 'B' :
861 						case 'J' :
862 						case 'D' :
863 						case 'F' :
864 						case 'S' :
865 						case 'C' :
866 							writeNewLine(buffer, lineSeparator, tabNumber + 1);
867 							buffer.append("return 0;"); //$NON-NLS-1$
868 							writeNewLine(buffer, lineSeparator, tabNumber);
869 							break;
870 						default :
871 							// boolean
872 							writeNewLine(buffer, lineSeparator, tabNumber + 1);
873 							buffer.append("return false;"); //$NON-NLS-1$
874 							writeNewLine(buffer, lineSeparator, tabNumber);
875 					}
876 				} else {
877 					// object
878 					writeNewLine(buffer, lineSeparator, tabNumber + 1);
879 					buffer.append("return null;"); //$NON-NLS-1$
880 					writeNewLine(buffer, lineSeparator, tabNumber);
881 				}
882 				buffer.append('}');
883 			} else {
884 				buffer.append(';');
885 			}
886 		} else {
887 			buffer.append(Messages.disassembler_endofmethodheader);
888 		}
889 
890 		if (checkMode(mode, SYSTEM | DETAILED)) {
891 			if (codeAttribute != null) {
892 				disassemble(codeAttribute, parameterNames, methodDescriptor, (accessFlags & IModifierConstants.ACC_STATIC) != 0, buffer, lineSeparator, tabNumber, mode);
893 			}
894 		}
895 		if (checkMode(mode, SYSTEM | DETAILED)) {
896 			if (methodParametersAttribute != null) {
897 				disassemble((IMethodParametersAttribute)methodParametersAttribute, buffer, lineSeparator, tabNumber, mode);
898 			}
899 		}
900 		if (checkMode(mode, SYSTEM)) {
901 			IClassFileAttribute[] attributes = methodInfo.getAttributes();
902 			int length = attributes.length;
903 			if (length != 0) {
904 				for (int i = 0; i < length; i++) {
905 					IClassFileAttribute attribute = attributes[i];
906 					if (attribute != codeAttribute
907 							&& attribute != exceptionAttribute
908 							&& attribute != signatureAttribute
909 							&& attribute != annotationDefaultAttribute
910 							&& attribute != runtimeInvisibleAnnotationsAttribute
911 							&& attribute != runtimeVisibleAnnotationsAttribute
912 							&& attribute != runtimeInvisibleTypeAnnotationsAttribute
913 							&& attribute != runtimeVisibleTypeAnnotationsAttribute
914 							&& attribute != runtimeInvisibleParameterAnnotationsAttribute
915 							&& attribute != runtimeVisibleParameterAnnotationsAttribute
916 							&& attribute != methodParametersAttribute
917 							&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
918 							&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
919 						disassemble(attribute, buffer, lineSeparator, tabNumber, mode);
920 						writeNewLine(buffer, lineSeparator, tabNumber);
921 					}
922 				}
923 			}
924 			if (annotationDefaultAttribute != null) {
925 				disassemble((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
926 			}
927 			if (runtimeVisibleAnnotationsAttribute != null) {
928 				disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
929 			}
930 			if (runtimeInvisibleAnnotationsAttribute != null) {
931 				disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
932 			}
933 			if (runtimeVisibleParameterAnnotationsAttribute != null) {
934 				disassemble((IRuntimeVisibleParameterAnnotationsAttribute) runtimeVisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
935 			}
936 			if (runtimeInvisibleParameterAnnotationsAttribute != null) {
937 				disassemble((IRuntimeInvisibleParameterAnnotationsAttribute) runtimeInvisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
938 			}
939 			if (runtimeVisibleTypeAnnotationsAttribute != null) {
940 				disassemble((IRuntimeVisibleTypeAnnotationsAttribute) runtimeVisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
941 			}
942 			if (runtimeInvisibleTypeAnnotationsAttribute != null) {
943 				disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
944  			}
945 		}
946 	}
947 
948 	/**
949 	 * @see #disassemble(org.eclipse.jdt.core.util.IClassFileReader, java.lang.String, int)
950 	 */
disassemble(IClassFileReader classFileReader, String lineSeparator)951 	public String disassemble(IClassFileReader classFileReader, String lineSeparator) {
952 		return disassemble(classFileReader, lineSeparator, ClassFileBytesDisassembler.DEFAULT);
953 	}
954 
955 	/**
956 	 * Answers back the disassembled string of the IClassFileReader according to the
957 	 * mode.
958 	 * This is an output quite similar to the javap tool.
959 	 *
960 	 * @param classFileReader The classFileReader to be disassembled
961 	 * @param lineSeparator the line separator to use.
962 	 * @param mode the mode used to disassemble the IClassFileReader
963 	 *
964 	 * @return the disassembled string of the IClassFileReader according to the mode
965 	 */
disassemble(IClassFileReader classFileReader, String lineSeparator, int mode)966 	public String disassemble(IClassFileReader classFileReader, String lineSeparator, int mode) {
967 		if (classFileReader == null) return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
968 		char[] className = classFileReader.getClassName();
969 		if (className == null) {
970 			// incomplete initialization. We cannot go further.
971 			return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
972 		}
973 		className= CharOperation.replaceOnCopy(className, '/', '.');
974 		final int classNameLength = className.length;
975 		final int accessFlags = classFileReader.getAccessFlags();
976 		final boolean isEnum = (accessFlags & IModifierConstants.ACC_ENUM) != 0;
977 
978 		StringBuffer buffer = new StringBuffer();
979 		ISourceAttribute sourceAttribute = classFileReader.getSourceFileAttribute();
980 		IClassFileAttribute classFileAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.SIGNATURE);
981 		ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute;
982 		if (checkMode(mode, SYSTEM | DETAILED)) {
983 			int minorVersion = classFileReader.getMinorVersion();
984 			int majorVersion = classFileReader.getMajorVersion();
985 			buffer.append(Messages.disassembler_begincommentline);
986 			if (sourceAttribute != null) {
987 				buffer.append(Messages.disassembler_sourceattributeheader);
988 				buffer.append(sourceAttribute.getSourceFileName());
989 			}
990 			String versionNumber = VERSION_UNKNOWN;
991 			if (minorVersion == 3 && majorVersion == 45) {
992 				versionNumber = JavaCore.VERSION_1_1;
993 			} else {
994 				versionNumber = CompilerOptions.versionFromJdkLevel((majorVersion << 16) + minorVersion);
995 				if (versionNumber.length() == 0)
996 					versionNumber = VERSION_UNKNOWN;
997 			}
998 			buffer.append(
999 				Messages.bind(Messages.classfileformat_versiondetails,
1000 				new String[] {
1001 					versionNumber,
1002 					Integer.toString(majorVersion),
1003 					Integer.toString(minorVersion),
1004 					((accessFlags & IModifierConstants.ACC_SUPER) != 0
1005 							? Messages.classfileformat_superflagisset
1006 							: Messages.classfileformat_superflagisnotset)
1007 					+ (isDeprecated(classFileReader) ? ", deprecated" : org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING)//$NON-NLS-1$
1008 				}));
1009 			writeNewLine(buffer, lineSeparator, 0);
1010 			if (signatureAttribute != null) {
1011 				buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature())));
1012 				writeNewLine(buffer, lineSeparator, 0);
1013 			}
1014 		}
1015 		final int lastDotIndexInClassName = CharOperation.lastIndexOf('.', className);
1016 
1017 		if (checkMode(mode, WORKING_COPY) && lastDotIndexInClassName != -1) {
1018 			// we print a package declaration
1019 			buffer.append("package ");//$NON-NLS-1$
1020 			buffer.append(className, 0, lastDotIndexInClassName);
1021 			buffer.append(';');
1022 			writeNewLine(buffer, lineSeparator, 0);
1023 		}
1024 
1025 		INestMembersAttribute nestMembersAttribute = classFileReader.getNestMembersAttribute();
1026 		IInnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute();
1027 		IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
1028 		IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
1029 		IClassFileAttribute runtimeVisibleTypeAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
1030 		IClassFileAttribute runtimeInvisibleTypeAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
1031 
1032 		IClassFileAttribute bootstrapMethods = Util.getAttribute(classFileReader, IAttributeNamesConstants.BOOTSTRAP_METHODS);
1033 		IModuleAttribute moduleAttribute = (IModuleAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.MODULE);
1034 		IRecordAttribute recordAttribute = classFileReader.getRecordAttribute();
1035 
1036 		if (checkMode(mode, DETAILED)) {
1037 			// disassemble compact version of annotations
1038 			if (runtimeInvisibleAnnotationsAttribute != null) {
1039 				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode);
1040 				writeNewLine(buffer, lineSeparator, 0);
1041 			}
1042 			if (runtimeVisibleAnnotationsAttribute != null) {
1043 				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode);
1044 				writeNewLine(buffer, lineSeparator, 0);
1045 			}
1046 		}
1047 		boolean decoded = false;
1048 		if (isEnum && checkMode(mode, WORKING_COPY)) {
1049 			decodeModifiersForType(buffer, accessFlags & IModifierConstants.ACC_PUBLIC);
1050 		} else {
1051 			if (innerClassesAttribute != null) {
1052 				// search the right entry
1053 				IInnerClassesAttributeEntry[] entries = innerClassesAttribute.getInnerClassAttributesEntries();
1054 				for (int i = 0, max = entries.length; i < max ; i++) {
1055 					IInnerClassesAttributeEntry entry = entries[i];
1056 					char[] innerClassName = entry.getInnerClassName();
1057 					if (innerClassName != null) {
1058 						if (CharOperation.equals(classFileReader.getClassName(), innerClassName)) {
1059 							decodeModifiersForInnerClasses(buffer, entry.getAccessFlags(), false);
1060 							decoded = true;
1061 						}
1062 					}
1063 				}
1064 			}
1065 			if (!decoded) {
1066 				decodeModifiersForType(buffer, accessFlags);
1067 				if (isSynthetic(classFileReader)) {
1068 					buffer.append("synthetic"); //$NON-NLS-1$
1069 					buffer.append(Messages.disassembler_space);
1070 				}
1071 			}
1072 		}
1073 
1074 		final boolean isAnnotation = (accessFlags & IModifierConstants.ACC_ANNOTATION) != 0;
1075 		final boolean isModule = (accessFlags & IModifierConstants.ACC_MODULE) != 0;
1076 		boolean isInterface = false;
1077 		if (isEnum) {
1078 			buffer.append("enum "); //$NON-NLS-1$
1079 		} else if (isModule) {
1080 			// skip - process under module attribute
1081 		} else if (classFileReader.isClass()) {
1082 			if (CharOperation.equals(classFileReader.getSuperclassName(), TypeConstants.CharArray_JAVA_LANG_RECORD_SLASH)) {
1083 				buffer.append("record "); //$NON-NLS-1$
1084 			}
1085 			else {
1086 				buffer.append("class "); //$NON-NLS-1$
1087 			}
1088 		} else {
1089 			if (isAnnotation) {
1090 				buffer.append("@"); //$NON-NLS-1$
1091 			}
1092 			buffer.append("interface "); //$NON-NLS-1$
1093 			isInterface = true;
1094 		}
1095 
1096 		if (checkMode(mode, WORKING_COPY)) {
1097 			// we print the simple class name
1098 			final int start = lastDotIndexInClassName + 1;
1099 			buffer.append(className, start, classNameLength - start);
1100 			className = CharOperation.subarray(className, start, classNameLength);
1101 			if (signatureAttribute != null) {
1102 				disassembleGenericSignature(mode, buffer, signatureAttribute.getSignature());
1103 			}
1104 		} else if (!isModule) {
1105 			buffer.append(className);
1106 		}
1107 
1108 		char[] superclassName = classFileReader.getSuperclassName();
1109 		if (superclassName != null) {
1110 			CharOperation.replace(superclassName, '/', '.');
1111 			if (!isJavaLangObject(superclassName) && !isEnum) {
1112 				buffer.append(" extends "); //$NON-NLS-1$
1113 				buffer.append(returnClassName(superclassName, '.', mode));
1114 			}
1115 		}
1116 		if (!isAnnotation || !checkMode(mode, WORKING_COPY)) {
1117 			char[][] superclassInterfaces = classFileReader.getInterfaceNames();
1118 			int length = superclassInterfaces.length;
1119 			if (length != 0) {
1120 				if (isInterface) {
1121 					buffer.append(" extends "); //$NON-NLS-1$
1122 				} else {
1123 					buffer.append(" implements "); //$NON-NLS-1$
1124 				}
1125 				for (int i = 0; i < length; i++) {
1126 					if (i != 0) {
1127 						buffer
1128 							.append(Messages.disassembler_comma)
1129 							.append(Messages.disassembler_space);
1130 					}
1131 					char[] superinterface = superclassInterfaces[i];
1132 					CharOperation.replace(superinterface, '/', '.');
1133 					buffer
1134 						.append(returnClassName(superinterface, '.', mode));
1135 				}
1136 			}
1137 		}
1138 		if (!isModule)
1139 			buffer.append(Messages.bind(Messages.disassembler_opentypedeclaration));
1140 		if (checkMode(mode, SYSTEM)) {
1141 			disassemble(classFileReader.getConstantPool(), buffer, lineSeparator, 1);
1142 		}
1143 		if (isModule && moduleAttribute != null) { // print attributes - module package and main class only if the mandatory module attribute non-null
1144 			decodeModifiersForModule(buffer, accessFlags);
1145 			buffer.append("module"); //$NON-NLS-1$
1146 			buffer.append(Messages.disassembler_space);
1147 			buffer.append(moduleAttribute.getModuleName());
1148 			buffer.append(Messages.disassembler_space);
1149 			buffer.append(Messages.bind(Messages.disassembler_opentypedeclaration));
1150 			disassembleModule(moduleAttribute, buffer, lineSeparator, 1);
1151 			IModulePackagesAttribute modulePackagesAttribute = (IModulePackagesAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.MODULE_PACKAGES);
1152 			disassembleModule(modulePackagesAttribute, buffer, lineSeparator, 1);
1153 			IModuleMainClassAttribute mainClassAttribute = (IModuleMainClassAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.MODULE_MAIN_CLASS);
1154 			disassembleModule(mainClassAttribute, buffer, lineSeparator, 1);
1155 		}
1156 		disassembleTypeMembers(classFileReader, className, buffer, lineSeparator, 1, mode, isEnum);
1157 		if (checkMode(mode, SYSTEM | DETAILED)) {
1158 			IClassFileAttribute[] attributes = classFileReader.getAttributes();
1159 			int length = attributes.length;
1160 			IEnclosingMethodAttribute enclosingMethodAttribute = (IEnclosingMethodAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.ENCLOSING_METHOD);
1161 			INestHostAttribute nestHostAttribute = (INestHostAttribute) Util.getAttribute(classFileReader, IAttributeNamesConstants.NEST_HOST);
1162 			int remainingAttributesLength = length;
1163 			if (innerClassesAttribute != null) {
1164 				remainingAttributesLength--;
1165 			}
1166 			if (enclosingMethodAttribute != null) {
1167 				remainingAttributesLength--;
1168 			}
1169 			if (sourceAttribute != null) {
1170 				remainingAttributesLength--;
1171 			}
1172 			if (signatureAttribute != null) {
1173 				remainingAttributesLength--;
1174 			}
1175 			if (bootstrapMethods != null) {
1176 				remainingAttributesLength--;
1177 			}
1178 			if (moduleAttribute != null) {
1179 				remainingAttributesLength--;
1180 			}
1181 			if (nestHostAttribute != null) {
1182 				remainingAttributesLength--;
1183 			}
1184 			if (nestMembersAttribute != null) {
1185 				remainingAttributesLength--;
1186 			}
1187 			if (innerClassesAttribute != null
1188 					|| enclosingMethodAttribute != null
1189 					|| nestHostAttribute != null
1190 					|| nestMembersAttribute != null
1191 					|| bootstrapMethods != null
1192 					|| moduleAttribute != null
1193 					|| recordAttribute != null
1194 					|| remainingAttributesLength != 0) {
1195 				// this test is to ensure we don't insert more than one line separator
1196 				if (buffer.lastIndexOf(lineSeparator) != buffer.length() - lineSeparator.length()) {
1197 					writeNewLine(buffer, lineSeparator, 0);
1198 				}
1199 			}
1200 			if (innerClassesAttribute != null) {
1201 				disassemble(innerClassesAttribute, buffer, lineSeparator, 1);
1202 			}
1203 			if (enclosingMethodAttribute != null) {
1204 				disassemble(enclosingMethodAttribute, buffer, lineSeparator, 0);
1205 			}
1206 			if (nestHostAttribute != null) {
1207 				disassemble(nestHostAttribute, buffer, lineSeparator, 0);
1208 			}
1209 			if (nestMembersAttribute != null) {
1210 				disassemble(nestMembersAttribute, buffer, lineSeparator, 0);
1211 			}
1212 			if (recordAttribute != null) {
1213 				disassemble(recordAttribute, buffer, lineSeparator, 0, mode);
1214 			}
1215 			if (bootstrapMethods != null) {
1216 				disassemble((IBootstrapMethodsAttribute) bootstrapMethods, buffer, lineSeparator, 0, classFileReader.getConstantPool());
1217 			}
1218 			if (checkMode(mode, SYSTEM)) {
1219 				if (runtimeVisibleAnnotationsAttribute != null) {
1220 					disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode);
1221 				}
1222 				if (runtimeInvisibleAnnotationsAttribute != null) {
1223 					disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 0, mode);
1224 				}
1225 				if (runtimeVisibleTypeAnnotationsAttribute != null) {
1226 					disassemble((IRuntimeVisibleTypeAnnotationsAttribute) runtimeVisibleTypeAnnotationsAttribute, buffer, lineSeparator, 0, mode);
1227 				}
1228 				if (runtimeInvisibleTypeAnnotationsAttribute != null) {
1229 					disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, 0, mode);
1230 	 			}
1231 				if (length != 0) {
1232 					for (int i = 0; i < length; i++) {
1233 						IClassFileAttribute attribute = attributes[i];
1234 						if (attribute != innerClassesAttribute
1235 								&& attribute != nestHostAttribute
1236 								&& attribute != nestMembersAttribute
1237 								&& attribute != recordAttribute
1238 								&& attribute != sourceAttribute
1239 								&& attribute != signatureAttribute
1240 								&& attribute != enclosingMethodAttribute
1241 								&& attribute != runtimeInvisibleAnnotationsAttribute
1242 								&& attribute != runtimeVisibleAnnotationsAttribute
1243 								&& attribute != runtimeInvisibleTypeAnnotationsAttribute
1244 								&& attribute != runtimeVisibleTypeAnnotationsAttribute
1245 								&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
1246 								&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)
1247 								&& attribute != bootstrapMethods
1248 								&& attribute != moduleAttribute
1249 								) {
1250 							disassemble(attribute, buffer, lineSeparator, 0, mode);
1251 						}
1252 					}
1253 				}
1254 			}
1255 		}
1256 		writeNewLine(buffer, lineSeparator, 0);
1257 		buffer.append(Messages.disassembler_closetypedeclaration);
1258 		return buffer.toString();
1259 	}
1260 
disassembleModule(IModuleAttribute moduleAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)1261 	private void disassembleModule(IModuleAttribute moduleAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
1262 		writeNewLine(buffer, lineSeparator, tabNumber);
1263 		char[] moduleVersion = moduleAttribute.getModuleVersionValue();
1264 		if (moduleVersion == null) {
1265 			moduleVersion = Messages.disassembler_module_version_none.toCharArray();
1266 		}
1267 		buffer.append(Messages.bind(Messages.disassembler_module_version, new String(moduleVersion)));
1268 		IRequiresInfo[] requiresInfo = moduleAttribute.getRequiresInfo();
1269 		if (requiresInfo.length > 0) {
1270 			writeNewLine(buffer, lineSeparator, 0);
1271 			for (int i = 0, max = requiresInfo.length; i < max; i++) {
1272 				writeNewLine(buffer, lineSeparator, tabNumber);
1273 				disassemble(requiresInfo[i], buffer, lineSeparator, tabNumber);
1274 			}
1275 		}
1276 		IPackageVisibilityInfo[] exportInfos = moduleAttribute.getExportsInfo();
1277 		if (exportInfos.length > 0) {
1278 			writeNewLine(buffer, lineSeparator, 0);
1279 			for (int i = 0, max = exportInfos.length; i < max; i++) {
1280 				writeNewLine(buffer, lineSeparator, tabNumber);
1281 				disassemble(exportInfos[i], buffer, lineSeparator, tabNumber, true);
1282 			}
1283 		}
1284 		IPackageVisibilityInfo[] opensInfos = moduleAttribute.getOpensInfo();
1285 		if (opensInfos.length > 0) {
1286 			writeNewLine(buffer, lineSeparator, 0);
1287 			for (int i = 0, max = opensInfos.length; i < max; i++) {
1288 				writeNewLine(buffer, lineSeparator, tabNumber);
1289 				disassemble(opensInfos[i], buffer, lineSeparator, tabNumber, false);
1290 			}
1291 		}
1292 		char[][] usesNames = moduleAttribute.getUsesClassNames();
1293 		if (usesNames.length > 0) {
1294 			writeNewLine(buffer, lineSeparator, 0);
1295 			for (int i = 0, max = usesNames.length; i < max; i++) {
1296 				writeNewLine(buffer, lineSeparator, tabNumber);
1297 				buffer.append("uses " + CharOperation.charToString(CharOperation.replaceOnCopy(usesNames[i], '/','.'))); //$NON-NLS-1$
1298 			}
1299 		}
1300 		IProvidesInfo[] providesInfos = moduleAttribute.getProvidesInfo();
1301 		if (providesInfos.length > 0) {
1302 			writeNewLine(buffer, lineSeparator, 0);
1303 			for (int i = 0, max = providesInfos.length; i < max; i++) {
1304 				writeNewLine(buffer, lineSeparator, tabNumber);
1305 				disassemble(providesInfos[i], buffer, lineSeparator, tabNumber);
1306 			}
1307 		}
1308 	}
convertModuleNames(StringBuffer buffer, char[] name)1309 	private void convertModuleNames(StringBuffer buffer, char[] name) {
1310 		buffer.append(CharOperation.replaceOnCopy(CharOperation.replaceOnCopy(name, '$','.'), '/','.'));
1311 	}
1312 
disassembleModule(IModulePackagesAttribute modulePackagesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)1313 	private void disassembleModule(IModulePackagesAttribute modulePackagesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
1314 		if (modulePackagesAttribute == null) return;
1315 		writeNewLine(buffer, lineSeparator, tabNumber);
1316 		writeNewLine(buffer, lineSeparator, tabNumber);
1317 		buffer.append(Messages.disassembler_modulepackagesattributeheader);
1318 		char[][] names = modulePackagesAttribute.getPackageNames();
1319 		for (int i = 0, l = modulePackagesAttribute.getPackagesCount(); i < l; ++i) {
1320 			writeNewLine(buffer, lineSeparator, tabNumber + 1);
1321 			convertModuleNames(buffer, names[i]);
1322 		}
1323 		writeNewLine(buffer, lineSeparator, 0);
1324 	}
1325 
disassembleModule(IModuleMainClassAttribute moduleMainClassAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)1326 	private void disassembleModule(IModuleMainClassAttribute moduleMainClassAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
1327 		if (moduleMainClassAttribute == null) return;
1328 		writeNewLine(buffer, lineSeparator, tabNumber);
1329 		buffer.append(Messages.disassembler_modulemainclassattributeheader);
1330 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
1331 		convertModuleNames(buffer, moduleMainClassAttribute.getMainClassName());
1332 		writeNewLine(buffer, lineSeparator, 0);
1333 	}
1334 
disassemble(IProvidesInfo iProvidesInfo, StringBuffer buffer, String lineSeparator, int tabNumber)1335 	private void disassemble(IProvidesInfo iProvidesInfo, StringBuffer buffer, String lineSeparator, int tabNumber) {
1336 		buffer.append("provides"); //$NON-NLS-1$
1337 		buffer.append(Messages.disassembler_space);
1338 		convertModuleNames(buffer, iProvidesInfo.getServiceName());
1339 		buffer.append(Messages.disassembler_space);
1340 		char[][] implementations = iProvidesInfo.getImplementationNames();
1341 		if (implementations.length > 0) {
1342 			buffer.append( "with"); //$NON-NLS-1$
1343 			buffer.append(Messages.disassembler_space);
1344 			for (int i = 0, l = implementations.length; i < l; ++i) {
1345 				if (i != 0) {
1346 					buffer
1347 						.append(Messages.disassembler_comma)
1348 						.append(Messages.disassembler_space);
1349 				}
1350 				convertModuleNames(buffer, implementations[i]);
1351 			}
1352 		}
1353 		buffer.append(';');
1354 	}
1355 
disassemble(INestHostAttribute nestHostAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)1356 	private void disassemble(INestHostAttribute nestHostAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
1357 		writeNewLine(buffer, lineSeparator, tabNumber);
1358 		writeNewLine(buffer, lineSeparator, tabNumber); // additional line
1359 		buffer.append(Messages.disassembler_nesthost);
1360 		buffer
1361 			.append(Messages.disassembler_constantpoolindex)
1362 			.append(nestHostAttribute.getNestHostIndex())
1363 			.append(" ")//$NON-NLS-1$
1364 			.append(nestHostAttribute.getNestHostName());
1365 	}
disassemble(IRecordAttribute recordAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)1366 	private void disassemble(IRecordAttribute recordAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
1367 		writeNewLine(buffer, lineSeparator, tabNumber);
1368 		writeNewLine(buffer, lineSeparator, tabNumber); // additional line
1369 		buffer.append(Messages.disassembler_record);
1370 		buffer
1371 			.append(Messages.disassembler_constantpoolindex)
1372 			.append(recordAttribute.getAttributeName());
1373 		writeNewLine(buffer, lineSeparator, tabNumber);
1374 		buffer.append(Messages.disassembler_components);
1375 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
1376 		IComponentInfo[] entries = recordAttribute.getComponentInfos();
1377 		for (IComponentInfo e : entries) {
1378 			disassemble(e, buffer, lineSeparator, tabNumber, mode);
1379 		}
1380 	}
disassemble(IComponentInfo componentInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)1381 	private void disassemble(IComponentInfo componentInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
1382 		writeNewLine(buffer, lineSeparator, tabNumber);
1383 		final char[] descriptor = componentInfo.getDescriptor();
1384 		final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(componentInfo, IAttributeNamesConstants.SIGNATURE);
1385 		if (checkMode(mode, SYSTEM | DETAILED)) {
1386 			buffer.append(Messages.bind(Messages.classfileformat_componentdescriptor,
1387 				new String[] {
1388 					Integer.toString(componentInfo.getDescriptorIndex()),
1389 					new String(descriptor)
1390 				}));
1391 			writeNewLine(buffer, lineSeparator, tabNumber);
1392 			if (signatureAttribute != null) {
1393 				buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature())));
1394 				writeNewLine(buffer, lineSeparator, tabNumber);
1395 			}
1396 		}
1397 		final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(componentInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
1398 		final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(componentInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
1399 		final IClassFileAttribute runtimeVisibleTypeAnnotationsAttribute = Util.getAttribute(componentInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
1400 		final IClassFileAttribute runtimeInvisibleTypeAnnotationsAttribute = Util.getAttribute(componentInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
1401 		if (checkMode(mode, DETAILED)) {
1402 			// disassemble compact version of annotations
1403 			if (runtimeInvisibleAnnotationsAttribute != null) {
1404 				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
1405 				writeNewLine(buffer, lineSeparator, tabNumber);
1406 			}
1407 			if (runtimeVisibleAnnotationsAttribute != null) {
1408 				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
1409 				writeNewLine(buffer, lineSeparator, tabNumber);
1410 			}
1411 		}
1412 		if (checkMode(mode, WORKING_COPY)) {
1413 			if (signatureAttribute != null) {
1414 				buffer.append(returnClassName(getSignatureForComponent(signatureAttribute.getSignature()), '.', mode));
1415 			} else {
1416 				buffer.append(returnClassName(getSignatureForComponent(descriptor), '.', mode));
1417 			}
1418 		} else {
1419 			buffer.append(returnClassName(getSignatureForComponent(descriptor), '.', mode));
1420 		}
1421 		buffer.append(' ');
1422 		buffer.append(new String(componentInfo.getName()));
1423 
1424 		buffer.append(Messages.disassembler_endofcomponent);
1425 		if (checkMode(mode, SYSTEM)) {
1426 			IClassFileAttribute[] attributes = componentInfo.getAttributes();
1427 			int length = attributes.length;
1428 			if (length != 0) {
1429 				for (int i = 0; i < length; i++) {
1430 					IClassFileAttribute attribute = attributes[i];
1431 					if (attribute != signatureAttribute
1432 						&& attribute != runtimeInvisibleAnnotationsAttribute
1433 						&& attribute != runtimeVisibleAnnotationsAttribute
1434 						&& attribute != runtimeInvisibleTypeAnnotationsAttribute
1435 						&& attribute != runtimeVisibleTypeAnnotationsAttribute) {
1436 						disassemble(attribute, buffer, lineSeparator, tabNumber, mode);
1437 					}
1438 				}
1439 			}
1440 			if (runtimeVisibleAnnotationsAttribute != null) {
1441 				disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
1442 			}
1443 			if (runtimeInvisibleAnnotationsAttribute != null) {
1444 				disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
1445 			}
1446 			if (runtimeVisibleTypeAnnotationsAttribute != null) {
1447 				disassemble((IRuntimeVisibleTypeAnnotationsAttribute) runtimeVisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
1448 			}
1449 			if (runtimeInvisibleTypeAnnotationsAttribute != null) {
1450 				disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
1451  			}
1452 		}
1453 	}
1454 
disassemble(INestMembersAttribute nestMembersAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)1455 	private void disassemble(INestMembersAttribute nestMembersAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
1456 		writeNewLine(buffer, lineSeparator, tabNumber);
1457 		writeNewLine(buffer, lineSeparator, tabNumber); // additional line
1458 		buffer.append(Messages.disassembler_nestmembers);
1459 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
1460 		INestMemberAttributeEntry[] entries = nestMembersAttribute.getNestMemberAttributesEntries();
1461 		int length = entries.length;
1462 		int nestMemberIndex;
1463 		INestMemberAttributeEntry entry;
1464 		for (int i = 0; i < length; i++) {
1465 			if (i != 0) {
1466 				buffer.append(Messages.disassembler_comma);
1467 				writeNewLine(buffer, lineSeparator, tabNumber + 1);
1468 			}
1469 			entry = entries[i];
1470 			nestMemberIndex = entry.getNestMemberIndex();
1471 			buffer
1472 				.append(Messages.disassembler_constantpoolindex)
1473 				.append(nestMemberIndex);
1474 			if (nestMemberIndex != 0) {
1475 				buffer
1476 					.append(Messages.disassembler_space)
1477 					.append(entry.getNestMemberName());
1478 			}
1479 		}
1480 	}
disassemble(IPackageVisibilityInfo iPackageVisibilityInfo, StringBuffer buffer, String lineSeparator, int tabNumber, boolean isExports)1481 	private void disassemble(IPackageVisibilityInfo iPackageVisibilityInfo, StringBuffer buffer, String lineSeparator,
1482 			int tabNumber, boolean isExports) {
1483 		buffer.append(isExports ? "exports" : "opens"); //$NON-NLS-1$ //$NON-NLS-2$
1484 		buffer.append(Messages.disassembler_space);
1485 		convertModuleNames(buffer, iPackageVisibilityInfo.getPackageName());
1486 		char[][] targets = iPackageVisibilityInfo.getTargetModuleNames();
1487 		if (targets.length > 0) {
1488 			buffer.append(Messages.disassembler_space);
1489 			buffer.append( "to"); //$NON-NLS-1$
1490 			buffer.append(Messages.disassembler_space);
1491 			for (int i = 0, l = targets.length; i < l; ++i) {
1492 				if (i != 0) {
1493 					buffer
1494 						.append(Messages.disassembler_comma)
1495 						.append(Messages.disassembler_space);
1496 				}
1497 				buffer.append(targets[i]);
1498 			}
1499 		}
1500 		buffer.append(';');
1501 	}
1502 
disassemble(IRequiresInfo iRequiresInfo, StringBuffer buffer, String lineSeparator, int tabNumber)1503 	private void disassemble(IRequiresInfo iRequiresInfo, StringBuffer buffer, String lineSeparator, int tabNumber) {
1504 		buffer.append("requires "); //$NON-NLS-1$
1505 		decodeModifiersForModuleRequires(buffer, iRequiresInfo.getRequiresFlags());
1506 		buffer.append(iRequiresInfo.getRequiresModuleName());
1507 		buffer.append(';');
1508 	}
1509 
disassembleGenericSignature(int mode, StringBuffer buffer, final char[] signature)1510 	private void disassembleGenericSignature(int mode, StringBuffer buffer, final char[] signature) {
1511 		CharOperation.replace(signature, '/', '.');
1512 		final char[][] typeParameters = Signature.getTypeParameters(signature);
1513 		final int typeParametersLength = typeParameters.length;
1514 		if (typeParametersLength != 0) {
1515 			buffer.append('<');
1516 			for (int i = 0; i < typeParametersLength; i++) {
1517 				if (i != 0) {
1518 					buffer.append(Messages.disassembler_comma);
1519 				}
1520 				// extract the name
1521 				buffer.append(typeParameters[i], 0, CharOperation.indexOf(':', typeParameters[i]));
1522 				final char[][] bounds = Signature.getTypeParameterBounds(typeParameters[i]);
1523 				final int boundsLength = bounds.length;
1524 				if (boundsLength != 0) {
1525 					if (boundsLength == 1) {
1526 						final char[] bound = bounds[0];
1527 						// check if this is java.lang.Object
1528 						if (!isJavaLangObject(Signature.toCharArray(bound))) {
1529 							buffer.append(" extends "); //$NON-NLS-1$
1530 							buffer.append(returnClassName(Signature.toCharArray(bound), '.', mode));
1531 						}
1532 					} else {
1533 						buffer.append(" extends "); //$NON-NLS-1$
1534 						for (int j= 0; j < boundsLength; j++) {
1535 							if (j != 0) {
1536 								buffer.append(" & "); //$NON-NLS-1$
1537 							}
1538 							buffer.append(returnClassName(Signature.toCharArray(bounds[j]), '.', mode));
1539 						}
1540 					}
1541 				}
1542 			}
1543 			buffer.append('>');
1544 		}
1545 	}
1546 
isJavaLangObject(final char[] className)1547 	private boolean isJavaLangObject(final char[] className) {
1548 		return CharOperation.equals(TypeConstants.JAVA_LANG_OBJECT, CharOperation.splitOn('.', className));
1549 	}
1550 
1551 
isVarArgs(IMethodInfo methodInfo)1552 	private boolean isVarArgs(IMethodInfo methodInfo) {
1553 		int accessFlags = methodInfo.getAccessFlags();
1554 		if ((accessFlags & IModifierConstants.ACC_VARARGS) != 0) return true;
1555 		// check the presence of the unspecified Varargs attribute
1556 		return Util.getAttribute(methodInfo, AttributeNamesConstants.VarargsName) != null;
1557 	}
disassemble(ICodeAttribute codeAttribute, char[][] parameterNames, char[] methodDescriptor, boolean isStatic, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)1558 	private void disassemble(ICodeAttribute codeAttribute, char[][] parameterNames, char[] methodDescriptor, boolean isStatic, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
1559 		writeNewLine(buffer, lineSeparator, tabNumber - 1);
1560 		DefaultBytecodeVisitor visitor = new DefaultBytecodeVisitor(codeAttribute, parameterNames, methodDescriptor, isStatic, buffer, lineSeparator, tabNumber, mode);
1561 		try {
1562 			codeAttribute.traverse(visitor);
1563 		} catch(ClassFormatException e) {
1564 			dumpTab(tabNumber + 3, buffer);
1565 			buffer.append(Messages.classformat_classformatexception);
1566 			writeNewLine(buffer, lineSeparator, tabNumber - 1);
1567 		}
1568 		final int exceptionTableLength = codeAttribute.getExceptionTableLength();
1569 		boolean isFirstAttribute = true;
1570 		if (exceptionTableLength != 0) {
1571 			final int tabNumberForExceptionAttribute = tabNumber + 2;
1572 			isFirstAttribute = false;
1573 			dumpTab(tabNumberForExceptionAttribute, buffer);
1574 			final IExceptionTableEntry[] exceptionTableEntries = codeAttribute.getExceptionTable();
1575 			buffer.append(Messages.disassembler_exceptiontableheader);
1576 			writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1);
1577 			for (int i = 0; i < exceptionTableLength; i++) {
1578 				if (i != 0) {
1579 					writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1);
1580 				}
1581 				IExceptionTableEntry exceptionTableEntry = exceptionTableEntries[i];
1582 				char[] catchType;
1583 				if (exceptionTableEntry.getCatchTypeIndex() != 0) {
1584 					catchType = exceptionTableEntry.getCatchType();
1585 					CharOperation.replace(catchType, '/', '.');
1586 					catchType = returnClassName(catchType, '.', mode);
1587 				} else {
1588 					catchType = ANY_EXCEPTION;
1589 				}
1590 				buffer.append(Messages.bind(Messages.classfileformat_exceptiontableentry,
1591 					new String[] {
1592 						Integer.toString(exceptionTableEntry.getStartPC()),
1593 						Integer.toString(exceptionTableEntry.getEndPC()),
1594 						Integer.toString(exceptionTableEntry.getHandlerPC()),
1595 						new String(catchType),
1596 					}));
1597 			}
1598 		}
1599 		final ILineNumberAttribute lineNumberAttribute = codeAttribute.getLineNumberAttribute();
1600 		final int lineAttributeLength = lineNumberAttribute == null ? 0 : lineNumberAttribute.getLineNumberTableLength();
1601 		if (lineAttributeLength != 0) {
1602 			int tabNumberForLineAttribute = tabNumber + 2;
1603 			if (!isFirstAttribute) {
1604 				writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute);
1605 			} else {
1606 				dumpTab(tabNumberForLineAttribute, buffer);
1607 				isFirstAttribute = false;
1608 			}
1609 			buffer.append(Messages.disassembler_linenumberattributeheader);
1610 			writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1);
1611 			int[][] lineattributesEntries = lineNumberAttribute.getLineNumberTable();
1612 			for (int i = 0; i < lineAttributeLength; i++) {
1613 				if (i != 0) {
1614 					writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1);
1615 				}
1616 				buffer.append(Messages.bind(Messages.classfileformat_linenumbertableentry,
1617 					new String[] {
1618 						Integer.toString(lineattributesEntries[i][0]),
1619 						Integer.toString(lineattributesEntries[i][1])
1620 					}));
1621 			}
1622 		}
1623 		final ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute();
1624 		final int localVariableAttributeLength = localVariableAttribute == null ? 0 : localVariableAttribute.getLocalVariableTableLength();
1625 		if (localVariableAttributeLength != 0) {
1626 			int tabNumberForLocalVariableAttribute = tabNumber + 2;
1627 			if (!isFirstAttribute) {
1628 				writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
1629 			} else {
1630 				isFirstAttribute = false;
1631 				dumpTab(tabNumberForLocalVariableAttribute, buffer);
1632 			}
1633 			buffer.append(Messages.disassembler_localvariabletableattributeheader);
1634 			writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
1635 			ILocalVariableTableEntry[] localVariableTableEntries = localVariableAttribute.getLocalVariableTable();
1636 			for (int i = 0; i < localVariableAttributeLength; i++) {
1637 				if (i != 0) {
1638 					writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
1639 				}
1640 				ILocalVariableTableEntry localVariableTableEntry = localVariableTableEntries[i];
1641 				int index= localVariableTableEntry.getIndex();
1642 				int startPC = localVariableTableEntry.getStartPC();
1643 				int length  = localVariableTableEntry.getLength();
1644 				final char[] typeName = Signature.toCharArray(localVariableTableEntry.getDescriptor());
1645 				CharOperation.replace(typeName, '/', '.');
1646 				buffer.append(Messages.bind(Messages.classfileformat_localvariabletableentry,
1647 					new String[] {
1648 						Integer.toString(startPC),
1649 						Integer.toString(startPC + length),
1650 						new String(localVariableTableEntry.getName()),
1651 						Integer.toString(index),
1652 						new String(returnClassName(typeName, '.', mode))
1653 					}));
1654 			}
1655 		}
1656 		final ILocalVariableTypeTableAttribute localVariableTypeAttribute= (ILocalVariableTypeTableAttribute) Util.getAttribute(codeAttribute, IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE);
1657 		final int localVariableTypeTableLength = localVariableTypeAttribute == null ? 0 : localVariableTypeAttribute.getLocalVariableTypeTableLength();
1658 		if (localVariableTypeTableLength != 0) {
1659 			int tabNumberForLocalVariableAttribute = tabNumber + 2;
1660 			if (!isFirstAttribute) {
1661 				writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
1662 			} else {
1663 				isFirstAttribute = false;
1664 				dumpTab(tabNumberForLocalVariableAttribute, buffer);
1665 			}
1666 			buffer.append(Messages.disassembler_localvariabletypetableattributeheader);
1667 			writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
1668 			ILocalVariableTypeTableEntry[] localVariableTypeTableEntries = localVariableTypeAttribute.getLocalVariableTypeTable();
1669 			for (int i = 0; i < localVariableTypeTableLength; i++) {
1670 				if (i != 0) {
1671 					writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
1672 				}
1673 				ILocalVariableTypeTableEntry localVariableTypeTableEntry = localVariableTypeTableEntries[i];
1674 				int index= localVariableTypeTableEntry.getIndex();
1675 				int startPC = localVariableTypeTableEntry.getStartPC();
1676 				int length  = localVariableTypeTableEntry.getLength();
1677 				final char[] typeName = Signature.toCharArray(localVariableTypeTableEntry.getSignature());
1678 				CharOperation.replace(typeName, '/', '.');
1679 				buffer.append(Messages.bind(Messages.classfileformat_localvariabletableentry,
1680 					new String[] {
1681 						Integer.toString(startPC),
1682 						Integer.toString(startPC + length),
1683 						new String(localVariableTypeTableEntry.getName()),
1684 						Integer.toString(index),
1685 						new String(returnClassName(typeName, '.', mode))
1686 					}));
1687 			}
1688 		}
1689 		final int length = codeAttribute.getAttributesCount();
1690 		if (length != 0) {
1691 			IClassFileAttribute[] attributes = codeAttribute.getAttributes();
1692 			for (int i = 0; i < length; i++) {
1693 				IClassFileAttribute attribute = attributes[i];
1694 				if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP_TABLE)) {
1695 					IStackMapTableAttribute stackMapTableAttribute = (IStackMapTableAttribute) attribute;
1696 					if (!isFirstAttribute) {
1697 						writeNewLine(buffer, lineSeparator, tabNumber + 2);
1698 					} else {
1699 						isFirstAttribute = false;
1700 						dumpTab(tabNumber + 1, buffer);
1701 					}
1702 					int numberOfEntries = stackMapTableAttribute.getNumberOfEntries();
1703 					buffer.append(Messages.bind(Messages.disassembler_stackmaptableattributeheader, Integer.toString(numberOfEntries)));
1704 					if (numberOfEntries != 0) {
1705 						disassemble(stackMapTableAttribute, buffer, lineSeparator, tabNumber, mode);
1706 					}
1707 				} else if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP)) {
1708 					IStackMapAttribute stackMapAttribute = (IStackMapAttribute) attribute;
1709 					if (!isFirstAttribute) {
1710 						writeNewLine(buffer, lineSeparator, tabNumber + 2);
1711 					} else {
1712 						isFirstAttribute = false;
1713 						dumpTab(tabNumber + 1, buffer);
1714 					}
1715 					int numberOfEntries = stackMapAttribute.getNumberOfEntries();
1716 					buffer.append(Messages.bind(Messages.disassembler_stackmapattributeheader, Integer.toString(numberOfEntries)));
1717 					if (numberOfEntries != 0) {
1718 						disassemble(stackMapAttribute, buffer, lineSeparator, tabNumber, mode);
1719 					}
1720 				} else if (CharOperation.equals(attribute.getAttributeName(),IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS)) {
1721 					disassemble((IRuntimeVisibleTypeAnnotationsAttribute) attribute, buffer, lineSeparator, tabNumber, mode);
1722 				} else if (CharOperation.equals(attribute.getAttributeName(),IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS)) {
1723 					disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) attribute, buffer, lineSeparator, tabNumber, mode);
1724 				} else if (attribute != lineNumberAttribute
1725 						&& attribute != localVariableAttribute
1726 						&& attribute != localVariableTypeAttribute) {
1727 					if (!isFirstAttribute) {
1728 						writeNewLine(buffer, lineSeparator, tabNumber + 2);
1729 					} else {
1730 						isFirstAttribute = false;
1731 						dumpTab(tabNumber + 1, buffer);
1732 					}
1733 					buffer.append(Messages.bind(Messages.disassembler_genericattributeheader,
1734 						new String[] {
1735 							new String(attribute.getAttributeName()),
1736 							Long.toString(attribute.getAttributeLength())
1737 						}));
1738 				}
1739 			}
1740 		}
1741 	}
1742 
disassemble(IStackMapTableAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)1743 	private void disassemble(IStackMapTableAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
1744 		writeNewLine(buffer, lineSeparator, tabNumber + 3);
1745 		int numberOfEntries = attribute.getNumberOfEntries();
1746 		final IStackMapFrame[] stackMapFrames = attribute.getStackMapFrame();
1747 		int absolutePC = -1;
1748 		for (int j = 0; j < numberOfEntries; j++) {
1749 			if (j > 0) {
1750 				writeNewLine(buffer, lineSeparator, tabNumber + 3);
1751 			}
1752 			final IStackMapFrame frame = stackMapFrames[j];
1753 			// disassemble each frame
1754 			int type = frame.getFrameType();
1755 			int offsetDelta = frame.getOffsetDelta();
1756 			if (absolutePC == -1) {
1757 				absolutePC = offsetDelta;
1758 			} else {
1759 				absolutePC += (offsetDelta + 1);
1760 			}
1761 			switch(type) {
1762 				case 247 : // SAME_LOCALS_1_STACK_ITEM_EXTENDED
1763 					buffer.append(
1764 						Messages.bind(
1765 							Messages.disassembler_frame_same_locals_1_stack_item_extended,
1766 							Integer.toString(absolutePC),
1767 							disassemble(frame.getStackItems(), mode)));
1768 					break;
1769 				case 248 :
1770 				case 249 :
1771 				case 250:
1772 					// CHOP
1773 					buffer.append(
1774 							Messages.bind(
1775 								Messages.disassembler_frame_chop,
1776 								Integer.toString(absolutePC),
1777 								Integer.toString(251 - type)));
1778 					break;
1779 				case 251 :
1780 					// SAME_FRAME_EXTENDED
1781 					buffer.append(
1782 							Messages.bind(
1783 								Messages.disassembler_frame_same_frame_extended,
1784 								Integer.toString(absolutePC)));
1785 					break;
1786 				case 252 :
1787 				case 253 :
1788 				case 254 :
1789 					// APPEND
1790 					buffer.append(
1791 							Messages.bind(
1792 								Messages.disassembler_frame_append,
1793 								Integer.toString(absolutePC),
1794 								disassemble(frame.getLocals(), mode)));
1795 					break;
1796 				case 255 :
1797 					// FULL_FRAME
1798 					buffer.append(
1799 							Messages.bind(
1800 								Messages.disassembler_frame_full_frame,
1801 								new String[] {
1802 									Integer.toString(absolutePC),
1803 									Integer.toString(frame.getNumberOfLocals()),
1804 									disassemble(frame.getLocals(), mode),
1805 									Integer.toString(frame.getNumberOfStackItems()),
1806 									disassemble(frame.getStackItems(), mode),
1807 									dumpNewLineWithTabs(lineSeparator, tabNumber + 5)
1808 								}));
1809 					break;
1810 				default:
1811 					if (type <= 63) {
1812 						// SAME_FRAME
1813 						offsetDelta = type;
1814 						buffer.append(
1815 								Messages.bind(
1816 									Messages.disassembler_frame_same_frame,
1817 									Integer.toString(absolutePC)));
1818 					} else if (type <= 127) {
1819 						// SAME_LOCALS_1_STACK_ITEM
1820 						offsetDelta = type - 64;
1821 						buffer.append(
1822 								Messages.bind(
1823 									Messages.disassembler_frame_same_locals_1_stack_item,
1824 									Integer.toString(absolutePC),
1825 									disassemble(frame.getStackItems(), mode)));
1826 					}
1827 			}
1828 		}
1829 	}
1830 
disassemble(IStackMapAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)1831 	private void disassemble(IStackMapAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
1832 		writeNewLine(buffer, lineSeparator, tabNumber + 3);
1833 		int numberOfEntries = attribute.getNumberOfEntries();
1834 		final IStackMapFrame[] stackMapFrames = attribute.getStackMapFrame();
1835 		for (int j = 0; j < numberOfEntries; j++) {
1836 			if (j > 0) {
1837 				writeNewLine(buffer, lineSeparator, tabNumber + 3);
1838 			}
1839 			final IStackMapFrame frame = stackMapFrames[j];
1840 			// disassemble each frame
1841 			buffer.append(
1842 					Messages.bind(
1843 						Messages.disassembler_frame_full_frame,
1844 						new String[] {
1845 							Integer.toString(frame.getOffsetDelta()),
1846 							Integer.toString(frame.getNumberOfLocals()),
1847 							disassemble(frame.getLocals(), mode),
1848 							Integer.toString(frame.getNumberOfStackItems()),
1849 							disassemble(frame.getStackItems(), mode),
1850 							dumpNewLineWithTabs(lineSeparator, tabNumber + 5)
1851 						}));
1852 		}
1853 	}
1854 
bootstrapMethodDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool)1855 	private String bootstrapMethodDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool) {
1856 		// http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
1857 		// The BootstrapMethods attribute records bootstrap method specifiers referenced by invokedynamic instructions.
1858 		// The value of the bootstrap_method_ref item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_MethodHandle_info structure (§4.4.8).
1859 		// http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.8
1860 		// constantpoolentry.getKind() = IConstantPoolConstant.CONSTANT_MethodHandle
1861 
1862 		ConstantPoolEntry2 constantPoolEntry2 =  (ConstantPoolEntry2) constantPool.decodeEntry(entry.getBootstrapMethodReference());
1863 
1864 		// The reference_kind item of the CONSTANT_MethodHandle_info structure should have the value 6 (REF_invokeStatic) or 8 (REF_newInvokeSpecial)
1865 		// (§5.4.3.5) or else invocation of the bootstrap method handle during call site specifier resolution for an invokedynamic instruction will complete abruptly.
1866 		// If the value of the reference_kind item is 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial),
1867 		// or 9 (REF_invokeInterface), the name of the method represented by a CONSTANT_Methodref_info structure must not be <init> or <clinit>.
1868 
1869 		if (constantPoolEntry2.getReferenceKind() != 6)
1870 			return null;
1871 		ConstantPoolEntry constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(constantPoolEntry2.getReferenceIndex());
1872 		StringBuilder builder = new StringBuilder();
1873 		//String[] methodMsg = methodDescription(constantPoolEntry);
1874 		builder.append(Messages.bind("invokestatic {0}.{1}:{2}", methodDescription(constantPoolEntry))); //$NON-NLS-1$
1875 		return builder.toString();
1876 	}
1877 
bootstrapArgumentsDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool)1878 	private String[] bootstrapArgumentsDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool) {
1879 		// http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.21
1880 		// bootstrap_arguments
1881 		// 	    Each entry in the bootstrap_arguments array must be a valid index into the constant_pool table.
1882 		//      The constant_pool entry at that index must be a CONSTANT_String_info, CONSTANT_Class_info, CONSTANT_Integer_info
1883 		//      CONSTANT_Long_info, CONSTANT_Float_info, CONSTANT_Double_info, CONSTANT_MethodHandle_info, or
1884 		//      CONSTANT_MethodType_info structure (§4.4.3, §4.4.1, §4.4.4, §4.4.5), §4.4.8, §4.4.9).
1885 		if (entry.getBootstrapArguments().length == 0)
1886 			return null;
1887 		int[] bootstrapArguments = entry.getBootstrapArguments();
1888 		String[] arguments = new String[bootstrapArguments.length];
1889 		for (int i = 0, length = bootstrapArguments.length; i < length; i++) {
1890 			ConstantPoolEntry constantPoolEntry =  (ConstantPoolEntry) constantPool.decodeEntry(bootstrapArguments[i]);
1891 			switch(constantPoolEntry.getKind()) {
1892 				case IConstantPoolConstant.CONSTANT_Integer:
1893 					arguments[i] = ((Integer) constantPoolEntry.getIntegerValue()).toString();
1894 					break;
1895 				case IConstantPoolConstant.CONSTANT_MethodHandle:
1896 					// http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.8
1897 					// If the value of the reference_kind item is 5 (REF_invokeVirtual), 6 (REF_invokeStatic),
1898 					// 7 (REF_invokeSpecial), or 8 (REF_newInvokeSpecial), then the constant_pool entry at that
1899 					// index must be a CONSTANT_Methodref_info structure (§4.4.2) representing a class's method or
1900 					// constructor (§2.9) for which a method handle is to be created.
1901 					ConstantPoolEntry2 constantPoolEntry2 = (ConstantPoolEntry2) constantPoolEntry;
1902 					StringBuilder builder = new StringBuilder(10);
1903 					switch(constantPoolEntry2.getReferenceKind()) {
1904 						case IConstantPoolConstant.METHOD_TYPE_REF_GetField:
1905 							builder.append("REF_getField "); //$NON-NLS-1$
1906 							constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(constantPoolEntry2.getReferenceIndex());
1907 							builder.append(Messages.bind("{0}:{1}", fieldDescription(constantPoolEntry))); //$NON-NLS-1$
1908 							arguments[i] =  builder.toString();
1909 							break;
1910 						case IConstantPoolConstant.METHOD_TYPE_REF_InvokeStatic:
1911 							builder.append("invokestatic "); //$NON-NLS-1$
1912 							//$FALL-THROUGH$
1913 						case IConstantPoolConstant.METHOD_TYPE_REF_InvokeVirtual:
1914 						case IConstantPoolConstant.METHOD_TYPE_REF_NewInvokeSpecial:
1915 							constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(constantPoolEntry2.getReferenceIndex());
1916 							builder.append(Messages.bind("{0}.{1}:{2}", methodDescription(constantPoolEntry))); //$NON-NLS-1$
1917 							arguments[i] =  builder.toString();
1918 							break;
1919 					}
1920 					break;
1921 				case IConstantPoolConstant.CONSTANT_MethodType:
1922 					arguments[i] = new String(((ConstantPoolEntry2) constantPoolEntry).getMethodDescriptor());
1923 					break;
1924 				case IConstantPoolConstant.CONSTANT_Class:
1925 					arguments[i] = new String(constantPoolEntry.getClassInfoName());
1926 					break;
1927 				case IConstantPoolConstant.CONSTANT_String:
1928 					arguments[i] = constantPoolEntry.getStringValue();
1929 					break;
1930 			}
1931 		}
1932 		return arguments;
1933 	}
1934 
fieldDescription(IConstantPoolEntry constantPoolEntry)1935 	private String[] fieldDescription(IConstantPoolEntry constantPoolEntry) {
1936 		return new String[] { new String(constantPoolEntry.getFieldName()),
1937 				new String(constantPoolEntry.getFieldDescriptor())};
1938 	}
1939 
methodDescription(IConstantPoolEntry constantPoolEntry)1940 	private String[] methodDescription(IConstantPoolEntry constantPoolEntry) {
1941 		return new String[] { new String(constantPoolEntry.getClassName()),
1942 				new String(constantPoolEntry.getMethodName()),
1943 				new String(constantPoolEntry.getMethodDescriptor())};
1944 	}
1945 
disassemble(IConstantPool constantPool, StringBuffer buffer, String lineSeparator, int tabNumber)1946 	private void disassemble(IConstantPool constantPool, StringBuffer buffer, String lineSeparator, int tabNumber) {
1947 		writeNewLine(buffer, lineSeparator, tabNumber);
1948 		int length = constantPool.getConstantPoolCount();
1949 		buffer.append(Messages.disassembler_constantpoolheader);
1950 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
1951 		for (int i = 1; i < length; i++) {
1952 			if (i != 1) {
1953 				writeNewLine(buffer, lineSeparator, tabNumber + 1);
1954 			}
1955 			IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(i);
1956 			String[] methodDescription;
1957 			int kind = constantPool.getEntryKind(i);
1958 			switch (kind) {
1959 				case IConstantPoolConstant.CONSTANT_Class :
1960 					buffer.append(
1961 						Messages.bind(Messages.disassembler_constantpool_class,
1962 							new String[] {
1963 								Integer.toString(i),
1964 								Integer.toString(constantPoolEntry.getClassInfoNameIndex()),
1965 								new String(constantPoolEntry.getClassInfoName())}));
1966 					break;
1967 				case IConstantPoolConstant.CONSTANT_Double :
1968 					buffer.append(
1969 						Messages.bind(Messages.disassembler_constantpool_double,
1970 							new String[] {
1971 								Integer.toString(i),
1972 								Double.toString(constantPoolEntry.getDoubleValue())}));
1973 					break;
1974 				case IConstantPoolConstant.CONSTANT_Fieldref :
1975 					buffer.append(
1976 						Messages.bind(Messages.disassembler_constantpool_fieldref,
1977 							new String[] {
1978 								Integer.toString(i),
1979 								Integer.toString(constantPoolEntry.getClassIndex()),
1980 								Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
1981 								new String(constantPoolEntry.getClassName()),
1982 								new String(constantPoolEntry.getFieldName()),
1983 								new String(constantPoolEntry.getFieldDescriptor())
1984 							}));
1985 					break;
1986 				case IConstantPoolConstant.CONSTANT_Float :
1987 					buffer.append(
1988 						Messages.bind(Messages.disassembler_constantpool_float,
1989 						new String[] {
1990 							Integer.toString(i),
1991 							Float.toString(constantPoolEntry.getFloatValue())}));
1992 					break;
1993 				case IConstantPoolConstant.CONSTANT_Integer :
1994 					buffer.append(
1995 						Messages.bind(Messages.disassembler_constantpool_integer,
1996 							new String[] {
1997 								Integer.toString(i),
1998 								Integer.toString(constantPoolEntry.getIntegerValue())}));
1999 					break;
2000 				case IConstantPoolConstant.CONSTANT_InterfaceMethodref :
2001 					methodDescription = methodDescription(constantPoolEntry);
2002 					buffer.append(
2003 							Messages.bind(Messages.disassembler_constantpool_interfacemethodref,
2004 								new String[] {
2005 									Integer.toString(i),
2006 									Integer.toString(constantPoolEntry.getClassIndex()),
2007 									Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
2008 									methodDescription[0], methodDescription[1], methodDescription[2]}));
2009 					break;
2010 				case IConstantPoolConstant.CONSTANT_Long :
2011 					buffer.append(
2012 						Messages.bind(Messages.disassembler_constantpool_long,
2013 							new String[] {
2014 								Integer.toString(i),
2015 								Long.toString(constantPoolEntry.getLongValue())}));
2016 					break;
2017 				case IConstantPoolConstant.CONSTANT_Methodref :
2018 					methodDescription = methodDescription(constantPoolEntry);
2019 					buffer.append(
2020 							Messages.bind(Messages.disassembler_constantpool_methodref,
2021 								new String[] {
2022 									Integer.toString(i),
2023 									Integer.toString(constantPoolEntry.getClassIndex()),
2024 									Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
2025 									methodDescription[0], methodDescription[1], methodDescription[2]}));
2026 					break;
2027 				case IConstantPoolConstant.CONSTANT_NameAndType :
2028 					int nameIndex = constantPoolEntry.getNameAndTypeInfoNameIndex();
2029 					int typeIndex = constantPoolEntry.getNameAndTypeInfoDescriptorIndex();
2030 					IConstantPoolEntry entry = constantPool.decodeEntry(nameIndex);
2031 					char[] nameValue = entry.getUtf8Value();
2032 					entry = constantPool.decodeEntry(typeIndex);
2033 					char[] typeValue = entry.getUtf8Value();
2034 					buffer.append(
2035 						Messages.bind(Messages.disassembler_constantpool_name_and_type,
2036 							new String[] {
2037 								Integer.toString(i),
2038 								Integer.toString(nameIndex),
2039 								Integer.toString(typeIndex),
2040 								String.valueOf(nameValue),
2041 								String.valueOf(typeValue)}));
2042 					break;
2043 				case IConstantPoolConstant.CONSTANT_String :
2044 					buffer.append(
2045 						Messages.bind(Messages.disassembler_constantpool_string,
2046 							new String[] {
2047 								Integer.toString(i),
2048 								Integer.toString(constantPoolEntry.getStringIndex()),
2049 								decodeStringValue(constantPoolEntry.getStringValue())}));
2050 					break;
2051 				case IConstantPoolConstant.CONSTANT_Utf8 :
2052 					buffer.append(
2053 						Messages.bind(Messages.disassembler_constantpool_utf8,
2054 							new String[] {
2055 								Integer.toString(i),
2056 								decodeStringValue(new String(constantPoolEntry.getUtf8Value()))}));
2057 					break;
2058 				case IConstantPoolConstant.CONSTANT_MethodHandle :
2059 					IConstantPoolEntry2 entry2 = (IConstantPoolEntry2) constantPoolEntry;
2060 					buffer.append(
2061 							Messages.bind(Messages.disassembler_constantpool_methodhandle,
2062 								new String[] {
2063 									Integer.toString(i),
2064 									getReferenceKind(entry2.getReferenceKind()),
2065 									Integer.toString(entry2.getReferenceIndex()),
2066 								}));
2067 					break;
2068 				case IConstantPoolConstant.CONSTANT_MethodType :
2069 					entry2 = (IConstantPoolEntry2) constantPoolEntry;
2070 					buffer.append(
2071 							Messages.bind(Messages.disassembler_constantpool_methodtype,
2072 								new String[] {
2073 									Integer.toString(i),
2074 									Integer.toString(entry2.getDescriptorIndex()),
2075 									String.valueOf(entry2.getMethodDescriptor()),
2076 								}));
2077 					break;
2078 				case IConstantPoolConstant.CONSTANT_InvokeDynamic :
2079 					entry2 = (IConstantPoolEntry2) constantPoolEntry;
2080 					buffer.append(
2081 						Messages.bind(Messages.disassembler_constantpool_invokedynamic,
2082 							new String[] {
2083 								Integer.toString(i),
2084 								Integer.toString(entry2.getBootstrapMethodAttributeIndex()),
2085 								Integer.toString(entry2.getNameAndTypeIndex()),
2086 								new String(constantPoolEntry.getMethodName()),
2087 								new String(constantPoolEntry.getMethodDescriptor())
2088 							}));
2089 					break;
2090 				case IConstantPoolConstant.CONSTANT_Dynamic :
2091 					entry2 = (IConstantPoolEntry2) constantPoolEntry;
2092 					buffer.append(
2093 						Messages.bind(Messages.disassembler_constantpool_dynamic,
2094 							new String[] {
2095 								Integer.toString(i),
2096 								Integer.toString(entry2.getBootstrapMethodAttributeIndex()),
2097 								Integer.toString(entry2.getNameAndTypeIndex()),
2098 								new String(constantPoolEntry.getFieldName()),
2099 								new String(constantPoolEntry.getFieldDescriptor())
2100 							}));
2101 					break;
2102 			}
2103 		}
2104 	}
2105 
getReferenceKind(int referenceKind)2106 	private String getReferenceKind(int referenceKind) {
2107 		String message = null;
2108 		switch(referenceKind) {
2109 			case IConstantPoolConstant.METHOD_TYPE_REF_GetField :
2110 				message = Messages.disassembler_method_type_ref_getfield;
2111 				break;
2112 			case IConstantPoolConstant.METHOD_TYPE_REF_GetStatic :
2113 				message = Messages.disassembler_method_type_ref_getstatic;
2114 				break;
2115 			case IConstantPoolConstant.METHOD_TYPE_REF_PutField :
2116 				message = Messages.disassembler_method_type_ref_putfield;
2117 				break;
2118 			case IConstantPoolConstant.METHOD_TYPE_REF_PutStatic :
2119 				message = Messages.disassembler_method_type_ref_putstatic;
2120 				break;
2121 			case IConstantPoolConstant.METHOD_TYPE_REF_InvokeInterface :
2122 				message = Messages.disassembler_method_type_ref_invokeinterface;
2123 				break;
2124 			case IConstantPoolConstant.METHOD_TYPE_REF_InvokeSpecial :
2125 				message = Messages.disassembler_method_type_ref_invokespecial;
2126 				break;
2127 			case IConstantPoolConstant.METHOD_TYPE_REF_InvokeStatic :
2128 				message = Messages.disassembler_method_type_ref_invokestatic;
2129 				break;
2130 			case IConstantPoolConstant.METHOD_TYPE_REF_InvokeVirtual :
2131 				message = Messages.disassembler_method_type_ref_invokevirtual;
2132 				break;
2133 			default :
2134 				message = Messages.disassembler_method_type_ref_newinvokespecial;
2135 		}
2136 		return Messages.bind(message, new String[] { Integer.toString(referenceKind) });
2137 	}
2138 
disassemble(IEnclosingMethodAttribute enclosingMethodAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)2139 	private void disassemble(IEnclosingMethodAttribute enclosingMethodAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
2140 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
2141 		buffer.append(Messages.disassembler_enclosingmethodheader);
2142 		buffer
2143 			.append(Messages.disassembler_constantpoolindex)
2144 			.append(enclosingMethodAttribute.getEnclosingClassIndex())
2145 			.append(" ")//$NON-NLS-1$
2146 			.append(Messages.disassembler_constantpoolindex)
2147 			.append(enclosingMethodAttribute.getMethodNameAndTypeIndex())
2148 			.append(" ")//$NON-NLS-1$
2149 			.append(enclosingMethodAttribute.getEnclosingClass());
2150 		if (enclosingMethodAttribute.getMethodNameAndTypeIndex() != 0) {
2151 			buffer
2152 				.append(".")//$NON-NLS-1$
2153 				.append(enclosingMethodAttribute.getMethodName())
2154 				.append(enclosingMethodAttribute.getMethodDescriptor());
2155 		}
2156 	}
2157 
disassembleEnumConstants(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, char[][] argumentTypes, int mode)2158 	private void disassembleEnumConstants(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, char[][] argumentTypes, int mode) {
2159 		writeNewLine(buffer, lineSeparator, tabNumber);
2160 		final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
2161 		final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
2162 		// disassemble compact version of annotations
2163 		if (runtimeInvisibleAnnotationsAttribute != null) {
2164 			disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
2165 			writeNewLine(buffer, lineSeparator, tabNumber);
2166 		}
2167 		if (runtimeVisibleAnnotationsAttribute != null) {
2168 			disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
2169 			writeNewLine(buffer, lineSeparator, tabNumber);
2170 		}
2171 		buffer.append(new String(fieldInfo.getName()));
2172 		buffer.append('(');
2173 		final int length = argumentTypes.length;
2174 		if (length != 0) {
2175 			// insert default value for corresponding argument types
2176 			for (int i = 0; i < length; i++) {
2177 				if (i != 0) {
2178 					buffer.append(Messages.disassembler_comma);
2179 				}
2180 				final char[] type = argumentTypes[i];
2181 				switch(type.length) {
2182 					case 1 :
2183 						switch(type[0]) {
2184 							case 'B' :
2185 							case 'I' :
2186 							case 'J' :
2187 							case 'D' :
2188 							case 'F' :
2189 							case 'S' :
2190 								buffer.append('0');
2191 								break;
2192 							case 'Z' :
2193 								buffer.append("false"); //$NON-NLS-1$
2194 								break;
2195 							case 'C' :
2196 								buffer.append("\' \'"); //$NON-NLS-1$
2197 								break;
2198 						}
2199 						break;
2200 					default :
2201 						buffer.append("null"); //$NON-NLS-1$
2202 				}
2203 			}
2204 		}
2205 		buffer.append(')').append(Messages.disassembler_comma);
2206 	}
2207 
2208 	/**
2209 	 * Disassemble a field info
2210 	 */
disassemble(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2211 	private void disassemble(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2212 		writeNewLine(buffer, lineSeparator, tabNumber);
2213 		final char[] fieldDescriptor = fieldInfo.getDescriptor();
2214 		final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(fieldInfo, IAttributeNamesConstants.SIGNATURE);
2215 		if (checkMode(mode, SYSTEM | DETAILED)) {
2216 			buffer.append(Messages.bind(Messages.classfileformat_fieldddescriptor,
2217 				new String[] {
2218 					Integer.toString(fieldInfo.getDescriptorIndex()),
2219 					new String(fieldDescriptor)
2220 				}));
2221 			if (fieldInfo.isDeprecated()) {
2222 				buffer.append(Messages.disassembler_deprecated);
2223 			}
2224 			writeNewLine(buffer, lineSeparator, tabNumber);
2225 			if (signatureAttribute != null) {
2226 				buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String(signatureAttribute.getSignature())));
2227 				writeNewLine(buffer, lineSeparator, tabNumber);
2228 			}
2229 		}
2230 		final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
2231 		final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
2232 		final IClassFileAttribute runtimeVisibleTypeAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
2233 		final IClassFileAttribute runtimeInvisibleTypeAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
2234 		if (checkMode(mode, DETAILED)) {
2235 			// disassemble compact version of annotations
2236 			if (runtimeInvisibleAnnotationsAttribute != null) {
2237 				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
2238 				writeNewLine(buffer, lineSeparator, tabNumber);
2239 			}
2240 			if (runtimeVisibleAnnotationsAttribute != null) {
2241 				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
2242 				writeNewLine(buffer, lineSeparator, tabNumber);
2243 			}
2244 		}
2245 		if (checkMode(mode, WORKING_COPY)) {
2246 			decodeModifiersForFieldForWorkingCopy(buffer, fieldInfo.getAccessFlags());
2247 			if (signatureAttribute != null) {
2248 				buffer.append(returnClassName(getSignatureForField(signatureAttribute.getSignature()), '.', mode));
2249 			} else {
2250 				buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode));
2251 			}
2252 		} else {
2253 			decodeModifiersForField(buffer, fieldInfo.getAccessFlags());
2254 			if (fieldInfo.isSynthetic()) {
2255 				buffer.append("synthetic"); //$NON-NLS-1$
2256 				buffer.append(Messages.disassembler_space);
2257 			}
2258 			buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode));
2259 		}
2260 		buffer.append(' ');
2261 		buffer.append(new String(fieldInfo.getName()));
2262 		IConstantValueAttribute constantValueAttribute = fieldInfo.getConstantValueAttribute();
2263 		if (constantValueAttribute != null) {
2264 			buffer.append(Messages.disassembler_fieldhasconstant);
2265 			IConstantPoolEntry constantPoolEntry = constantValueAttribute.getConstantValue();
2266 			switch(constantPoolEntry.getKind()) {
2267 				case IConstantPoolConstant.CONSTANT_Long :
2268 					buffer.append(constantPoolEntry.getLongValue() + "L"); //$NON-NLS-1$
2269 					break;
2270 				case IConstantPoolConstant.CONSTANT_Float :
2271 					buffer.append(constantPoolEntry.getFloatValue() + "f"); //$NON-NLS-1$
2272 					break;
2273 				case IConstantPoolConstant.CONSTANT_Double :
2274 					final double doubleValue = constantPoolEntry.getDoubleValue();
2275 					if (checkMode(mode, ClassFileBytesDisassembler.WORKING_COPY)) {
2276 						if (doubleValue == Double.POSITIVE_INFINITY) {
2277 							buffer.append("1.0 / 0.0"); //$NON-NLS-1$
2278 						} else if (doubleValue == Double.NEGATIVE_INFINITY) {
2279 							buffer.append("-1.0 / 0.0"); //$NON-NLS-1$
2280 						} else {
2281 							buffer.append(constantPoolEntry.getDoubleValue());
2282 						}
2283 					} else {
2284 						buffer.append(constantPoolEntry.getDoubleValue());
2285 					}
2286 					break;
2287 				case IConstantPoolConstant.CONSTANT_Integer:
2288 					switch(fieldDescriptor[0]) {
2289 						case 'C' :
2290 							buffer.append("'" + (char) constantPoolEntry.getIntegerValue() + "'"); //$NON-NLS-1$//$NON-NLS-2$
2291 							break;
2292 						case 'Z' :
2293 							buffer.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$
2294 							break;
2295 						case 'B' :
2296 							buffer.append(constantPoolEntry.getIntegerValue());
2297 							break;
2298 						case 'S' :
2299 							buffer.append(constantPoolEntry.getIntegerValue());
2300 							break;
2301 						case 'I' :
2302 							buffer.append(constantPoolEntry.getIntegerValue());
2303 					}
2304 					break;
2305 				case IConstantPoolConstant.CONSTANT_String:
2306 					buffer.append("\"" + decodeStringValue(constantPoolEntry.getStringValue()) + "\"" );//$NON-NLS-1$//$NON-NLS-2$
2307 			}
2308 		}
2309 		buffer.append(Messages.disassembler_endoffieldheader);
2310 		if (checkMode(mode, SYSTEM)) {
2311 			IClassFileAttribute[] attributes = fieldInfo.getAttributes();
2312 			int length = attributes.length;
2313 			if (length != 0) {
2314 				for (int i = 0; i < length; i++) {
2315 					IClassFileAttribute attribute = attributes[i];
2316 					if (attribute != constantValueAttribute
2317 						&& attribute != signatureAttribute
2318 						&& attribute != runtimeInvisibleAnnotationsAttribute
2319 						&& attribute != runtimeVisibleAnnotationsAttribute
2320 						&& attribute != runtimeInvisibleTypeAnnotationsAttribute
2321 						&& attribute != runtimeVisibleTypeAnnotationsAttribute
2322 						&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED)
2323 						&& !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
2324 						disassemble(attribute, buffer, lineSeparator, tabNumber, mode);
2325 					}
2326 				}
2327 			}
2328 			if (runtimeVisibleAnnotationsAttribute != null) {
2329 				disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
2330 			}
2331 			if (runtimeInvisibleAnnotationsAttribute != null) {
2332 				disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
2333 			}
2334 			if (runtimeVisibleTypeAnnotationsAttribute != null) {
2335 				disassemble((IRuntimeVisibleTypeAnnotationsAttribute) runtimeVisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
2336 			}
2337 			if (runtimeInvisibleTypeAnnotationsAttribute != null) {
2338 				disassemble((IRuntimeInvisibleTypeAnnotationsAttribute) runtimeInvisibleTypeAnnotationsAttribute, buffer, lineSeparator, tabNumber, mode);
2339  			}
2340 		}
2341 	}
2342 
disassemble(IInnerClassesAttribute innerClassesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber)2343 	private void disassemble(IInnerClassesAttribute innerClassesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
2344 		writeNewLine(buffer, lineSeparator, tabNumber);
2345 		buffer.append(Messages.disassembler_innerattributesheader);
2346 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
2347 		IInnerClassesAttributeEntry[] innerClassesAttributeEntries = innerClassesAttribute.getInnerClassAttributesEntries();
2348 		int length = innerClassesAttributeEntries.length;
2349 		int innerClassNameIndex, outerClassNameIndex, innerNameIndex, accessFlags;
2350 		IInnerClassesAttributeEntry innerClassesAttributeEntry;
2351 		for (int i = 0; i < length; i++) {
2352 			if (i != 0) {
2353 				buffer.append(Messages.disassembler_comma);
2354 				writeNewLine(buffer, lineSeparator, tabNumber + 1);
2355 			}
2356 			innerClassesAttributeEntry = innerClassesAttributeEntries[i];
2357 			innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex();
2358 			outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex();
2359 			innerNameIndex = innerClassesAttributeEntry.getInnerNameIndex();
2360 			accessFlags = innerClassesAttributeEntry.getAccessFlags();
2361 			buffer
2362 				.append(Messages.disassembler_openinnerclassentry)
2363 				.append(Messages.disassembler_inner_class_info_name)
2364 				.append(Messages.disassembler_constantpoolindex)
2365 				.append(innerClassNameIndex);
2366 			if (innerClassNameIndex != 0) {
2367 				buffer
2368 					.append(Messages.disassembler_space)
2369 					.append(innerClassesAttributeEntry.getInnerClassName());
2370 			}
2371 			buffer
2372 				.append(Messages.disassembler_comma)
2373 				.append(Messages.disassembler_space)
2374 				.append(Messages.disassembler_outer_class_info_name)
2375 				.append(Messages.disassembler_constantpoolindex)
2376 				.append(outerClassNameIndex);
2377 			if (outerClassNameIndex != 0) {
2378 				buffer
2379 					.append(Messages.disassembler_space)
2380 					.append(innerClassesAttributeEntry.getOuterClassName());
2381 			}
2382 			writeNewLine(buffer, lineSeparator, tabNumber);
2383 			dumpTab(tabNumber, buffer);
2384 			buffer.append(Messages.disassembler_space);
2385 			buffer
2386 				.append(Messages.disassembler_inner_name)
2387 				.append(Messages.disassembler_constantpoolindex)
2388 				.append(innerNameIndex);
2389 			if (innerNameIndex != 0) {
2390 				buffer
2391 					.append(Messages.disassembler_space)
2392 					.append(innerClassesAttributeEntry.getInnerName());
2393 			}
2394 			buffer
2395 				.append(Messages.disassembler_comma)
2396 				.append(Messages.disassembler_space)
2397 				.append(Messages.disassembler_inner_accessflags)
2398 				.append(accessFlags)
2399 				.append(Messages.disassembler_space);
2400 			decodeModifiersForInnerClasses(buffer, accessFlags, true);
2401 			buffer
2402 				.append(Messages.disassembler_closeinnerclassentry);
2403 		}
2404 	}
2405 
disassemble(IBootstrapMethodsAttribute bootstrapMethodsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, IConstantPool constantPool)2406 	private void disassemble(IBootstrapMethodsAttribute bootstrapMethodsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, IConstantPool constantPool) {
2407 		writeNewLine(buffer, lineSeparator, tabNumber);
2408 		buffer.append(Messages.disassembler_bootstrapmethodattributesheader);
2409 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
2410 		IBootstrapMethodsEntry[] entries = bootstrapMethodsAttribute.getBootstrapMethods();
2411 		int length = entries.length;
2412 		for (int i = 0; i < length; i++) {
2413 			if (i != 0) {
2414 				buffer.append(Messages.disassembler_comma);
2415 				writeNewLine(buffer, lineSeparator, tabNumber + 1);
2416 			}
2417 			IBootstrapMethodsEntry entry = entries[i];
2418 			String[] argumentsName = bootstrapArgumentsDescription(entry, constantPool);
2419 
2420 			buffer.append(
2421 				Messages.bind(
2422 					Messages.disassembler_bootstrapmethodentry,
2423 					new String[] {
2424 						Integer.toString(i),
2425 						Integer.toString(entry.getBootstrapMethodReference()),
2426 						bootstrapMethodDescription(entry, constantPool),
2427 						getArguments(entry.getBootstrapArguments(), argumentsName)
2428 					}));
2429 		}
2430 	}
2431 
getArguments(int[] arguments, String[] argumentsName)2432 	private String getArguments(int[] arguments, String[] argumentsName) {
2433 		StringBuffer buffer = new StringBuffer();
2434 		for (int i = 0, max = arguments.length; i < max; i++) {
2435 			buffer.append(
2436 				Messages.bind(
2437 					Messages.disassembler_bootstrapmethodentry_argument,
2438 					new String[] {
2439 						Integer.toString(arguments[i]),
2440 						argumentsName[i]
2441 					}));
2442 			if (i != arguments.length - 1)
2443 				buffer.append("\n\t\t"); //$NON-NLS-1$
2444 		}
2445 		return String.valueOf(buffer);
2446 	}
disassemble(int index, IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2447 	private void disassemble(int index, IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2448 		IAnnotation[] annotations = parameterAnnotation.getAnnotations();
2449 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
2450 		buffer.append(
2451 			Messages.bind(Messages.disassembler_parameterannotationentrystart, new String[] {Integer.toString(index), Integer.toString(annotations.length)}));
2452 		for (int i = 0, max = annotations.length; i < max; i++) {
2453 			disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
2454 		}
2455 	}
2456 
disassemble(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2457 	private void disassemble(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2458 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
2459 		buffer.append(Messages.disassembler_runtimeinvisibleannotationsattributeheader);
2460 		IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations();
2461 		for (int i = 0, max = annotations.length; i < max; i++) {
2462 			disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
2463 		}
2464 	}
2465 
disassemble(IRuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2466 	private void disassemble(IRuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2467 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
2468 		buffer.append(Messages.disassembler_runtimeinvisibleparameterannotationsattributeheader);
2469 		IParameterAnnotation[] parameterAnnotations = runtimeInvisibleParameterAnnotationsAttribute.getParameterAnnotations();
2470 		for (int i = 0, max = parameterAnnotations.length; i < max; i++) {
2471 			disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode);
2472 		}
2473 	}
2474 
disassemble(IRuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2475 	private void disassemble(IRuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2476 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
2477 		buffer.append(Messages.disassembler_runtimeinvisibletypeannotationsattributeheader);
2478 		IExtendedAnnotation[] extendedAnnotations = runtimeInvisibleTypeAnnotationsAttribute.getExtendedAnnotations();
2479 		for (int i = 0, max = extendedAnnotations.length; i < max; i++) {
2480 			disassemble(extendedAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode);
2481 		}
2482 	}
2483 
disassemble(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2484 	private void disassemble(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2485 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
2486 		buffer.append(Messages.disassembler_runtimevisibleannotationsattributeheader);
2487 		IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations();
2488 		for (int i = 0, max = annotations.length; i < max; i++) {
2489 			disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
2490 		}
2491 	}
2492 
disassemble(IRuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2493 	private void disassemble(IRuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2494 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
2495 		buffer.append(Messages.disassembler_runtimevisibleparameterannotationsattributeheader);
2496 		IParameterAnnotation[] parameterAnnotations = runtimeVisibleParameterAnnotationsAttribute.getParameterAnnotations();
2497 		for (int i = 0, max = parameterAnnotations.length; i < max; i++) {
2498 			disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode);
2499 		}
2500 	}
2501 
disassemble(IRuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2502 	private void disassemble(IRuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2503 		writeNewLine(buffer, lineSeparator, tabNumber + 1);
2504 		buffer.append(Messages.disassembler_runtimevisibletypeannotationsattributeheader);
2505 		IExtendedAnnotation[] extendedAnnotations = runtimeVisibleTypeAnnotationsAttribute.getExtendedAnnotations();
2506 		for (int i = 0, max = extendedAnnotations.length; i < max; i++) {
2507 			disassemble(extendedAnnotations[i], buffer, lineSeparator, tabNumber + 1, mode);
2508  		}
2509  	}
2510 
disassemble(IVerificationTypeInfo[] infos, int mode)2511 	private String disassemble(IVerificationTypeInfo[] infos, int mode) {
2512 		StringBuffer buffer = new StringBuffer();
2513 		buffer.append('{');
2514 		for (int i = 0, max = infos.length; i < max; i++) {
2515 			if(i != 0) {
2516 				buffer
2517 						.append(Messages.disassembler_comma)
2518 						.append(Messages.disassembler_space);
2519 			}
2520 			switch(infos[i].getTag()) {
2521 				case IVerificationTypeInfo.ITEM_DOUBLE :
2522 					buffer.append("double"); //$NON-NLS-1$
2523 					break;
2524 				case IVerificationTypeInfo.ITEM_FLOAT :
2525 					buffer.append("float"); //$NON-NLS-1$
2526 					break;
2527 				case IVerificationTypeInfo.ITEM_INTEGER :
2528 					buffer.append("int"); //$NON-NLS-1$
2529 					break;
2530 				case IVerificationTypeInfo.ITEM_LONG :
2531 					buffer.append("long"); //$NON-NLS-1$
2532 					break;
2533 				case IVerificationTypeInfo.ITEM_NULL :
2534 					buffer.append("null"); //$NON-NLS-1$
2535 					break;
2536 				case IVerificationTypeInfo.ITEM_OBJECT :
2537 					char[] classTypeName = infos[i].getClassTypeName();
2538 					CharOperation.replace(classTypeName, '/', '.');
2539 					if (classTypeName.length > 0 && classTypeName[0] == '[') { // length check for resilience
2540 						classTypeName = Signature.toCharArray(classTypeName);
2541 					}
2542 					buffer.append(returnClassName(classTypeName, '.', mode));
2543 					break;
2544 				case IVerificationTypeInfo.ITEM_TOP :
2545 					buffer.append("_"); //$NON-NLS-1$
2546 					break;
2547 				case IVerificationTypeInfo.ITEM_UNINITIALIZED :
2548 					buffer.append("uninitialized("); //$NON-NLS-1$
2549 					buffer.append(infos[i].getOffset());
2550 					buffer.append(')');
2551 					break;
2552 				case IVerificationTypeInfo.ITEM_UNINITIALIZED_THIS :
2553 					buffer.append("uninitialized_this"); //$NON-NLS-1$
2554 			}
2555 		}
2556 		buffer.append('}');
2557 		return String.valueOf(buffer);
2558 	}
2559 
disassembleAsModifier(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2560 	private void disassembleAsModifier(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2561 		final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
2562 		buffer.append('@').append(returnClassName(Signature.toCharArray(typeName), '.', mode));
2563 		final IAnnotationComponent[] components = annotation.getComponents();
2564 		final int length = components.length;
2565 		if (length != 0) {
2566 			buffer.append('(');
2567 			for (int i = 0; i < length; i++) {
2568 				if (i > 0) {
2569 					buffer.append(',');
2570 					writeNewLine(buffer, lineSeparator, tabNumber);
2571 				}
2572 				disassembleAsModifier(components[i], buffer, lineSeparator, tabNumber + 1, mode);
2573 			}
2574 			buffer.append(')');
2575 		}
2576 	}
2577 
disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2578 	private void disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2579 		buffer.append(annotationComponent.getComponentName()).append('=');
2580 		disassembleAsModifier(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1, mode);
2581 	}
2582 
disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2583 	private void disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2584 		switch(annotationComponentValue.getTag()) {
2585 			case IAnnotationComponentValue.BYTE_TAG:
2586 			case IAnnotationComponentValue.CHAR_TAG:
2587 			case IAnnotationComponentValue.DOUBLE_TAG:
2588 			case IAnnotationComponentValue.FLOAT_TAG:
2589 			case IAnnotationComponentValue.INTEGER_TAG:
2590 			case IAnnotationComponentValue.LONG_TAG:
2591 			case IAnnotationComponentValue.SHORT_TAG:
2592 			case IAnnotationComponentValue.BOOLEAN_TAG:
2593 			case IAnnotationComponentValue.STRING_TAG:
2594 				IConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue();
2595 				String value = null;
2596 				switch(constantPoolEntry.getKind()) {
2597 					case IConstantPoolConstant.CONSTANT_Long :
2598 						value = constantPoolEntry.getLongValue() + "L"; //$NON-NLS-1$
2599 						break;
2600 					case IConstantPoolConstant.CONSTANT_Float :
2601 						value = constantPoolEntry.getFloatValue() + "f"; //$NON-NLS-1$
2602 						break;
2603 					case IConstantPoolConstant.CONSTANT_Double :
2604 						value = Double.toString(constantPoolEntry.getDoubleValue());
2605 						break;
2606 					case IConstantPoolConstant.CONSTANT_Integer:
2607 						StringBuffer temp = new StringBuffer();
2608 						switch(annotationComponentValue.getTag()) {
2609 							case IAnnotationComponentValue.CHAR_TAG :
2610 								temp.append('\'');
2611 								escapeChar(temp, (char) constantPoolEntry.getIntegerValue());
2612 								temp.append('\'');
2613 								break;
2614 							case IAnnotationComponentValue.BOOLEAN_TAG :
2615 								temp.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$
2616 								break;
2617 							case IAnnotationComponentValue.BYTE_TAG :
2618 								temp.append("(byte) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$
2619 								break;
2620 							case IAnnotationComponentValue.SHORT_TAG :
2621 								temp.append("(short) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$
2622 								break;
2623 							case IAnnotationComponentValue.INTEGER_TAG :
2624 								temp.append("(int) ").append(constantPoolEntry.getIntegerValue()); //$NON-NLS-1$
2625 						}
2626 						value = String.valueOf(temp);
2627 						break;
2628 					case IConstantPoolConstant.CONSTANT_Utf8:
2629 						value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$
2630 				}
2631 				buffer.append(value);
2632 				break;
2633 			case IAnnotationComponentValue.ENUM_TAG:
2634 				final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.');
2635 				final char[] constantName = annotationComponentValue.getEnumConstantName();
2636 				buffer.append(returnClassName(Signature.toCharArray(typeName), '.', mode)).append('.').append(constantName);
2637 				break;
2638 			case IAnnotationComponentValue.CLASS_TAG:
2639 				constantPoolEntry = annotationComponentValue.getClassInfo();
2640 				final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.');
2641 				buffer.append(returnClassName(Signature.toCharArray(className), '.', mode));
2642 				break;
2643 			case IAnnotationComponentValue.ANNOTATION_TAG:
2644 				IAnnotation annotation = annotationComponentValue.getAnnotationValue();
2645 				disassembleAsModifier(annotation, buffer, lineSeparator, tabNumber + 1, mode);
2646 				break;
2647 			case IAnnotationComponentValue.ARRAY_TAG:
2648 				final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues();
2649 				buffer.append('{');
2650 				for (int i = 0, max = annotationComponentValues.length; i < max; i++) {
2651 					if (i > 0) {
2652 						buffer.append(',');
2653 					}
2654 					disassembleAsModifier(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1, mode);
2655 				}
2656 				buffer.append('}');
2657 		}
2658 	}
2659 
disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2660 	private void disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2661 		IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue();
2662 		disassembleAsModifier(componentValue, buffer, lineSeparator, tabNumber + 1, mode);
2663 	}
2664 
disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2665 	private void disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2666 		IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations();
2667 		for (int i = 0, max = annotations.length; i < max; i++) {
2668 			disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
2669 		}
2670 	}
2671 
disassembleAsModifier(IParameterAnnotation[] parameterAnnotations, StringBuffer buffer, int index, String lineSeparator, int tabNumber, int mode)2672 	private void disassembleAsModifier(IParameterAnnotation[] parameterAnnotations, StringBuffer buffer, int index, String lineSeparator, int tabNumber, int mode) {
2673 		if (parameterAnnotations.length > index) {
2674 			disassembleAsModifier(parameterAnnotations[index], buffer, lineSeparator, tabNumber + 1, mode);
2675 		}
2676 	}
2677 
disassembleAsModifier(IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2678 	private void disassembleAsModifier(IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2679 		if (parameterAnnotation == null) return;
2680 		IAnnotation[] annotations = parameterAnnotation.getAnnotations();
2681 		for (int i = 0, max = annotations.length; i < max; i++) {
2682 			if (i > 0) {
2683 				buffer.append(' ');
2684 			}
2685 			disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
2686 		}
2687 	}
2688 
disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode)2689 	private void disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
2690 		IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations();
2691 		for (int i = 0, max = annotations.length; i < max; i++) {
2692 			if (i > 0) {
2693 				writeNewLine(buffer, lineSeparator, tabNumber);
2694 			}
2695 			disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
2696 		}
2697 	}
2698 
disassembleTypeMembers(IClassFileReader classFileReader, char[] className, StringBuffer buffer, String lineSeparator, int tabNumber, int mode, boolean isEnum)2699 	private void disassembleTypeMembers(IClassFileReader classFileReader, char[] className, StringBuffer buffer, String lineSeparator, int tabNumber, int mode, boolean isEnum) {
2700 		IFieldInfo[] fields = classFileReader.getFieldInfos();
2701 		if (isEnum && checkMode(mode, WORKING_COPY)) {
2702 			int index = 0;
2703 			final int fieldsLength = fields.length;
2704 			IMethodInfo[] methods = classFileReader.getMethodInfos();
2705 			char[][] constructorArguments = getConstructorArgumentsForEnum(methods);
2706 			enumConstantLoop: for (; index < fieldsLength; index++) {
2707 				final IFieldInfo fieldInfo = fields[index];
2708 				final int accessFlags = fieldInfo.getAccessFlags();
2709 				if ((accessFlags & IModifierConstants.ACC_ENUM) != 0) {
2710 					writeNewLine(buffer, lineSeparator, tabNumber);
2711 					disassembleEnumConstants(fields[index], buffer, lineSeparator, tabNumber, constructorArguments, mode);
2712 				} else {
2713 					break enumConstantLoop;
2714 				}
2715 			}
2716 			buffer.append(';');
2717 			boolean foundSyntheticField = false;
2718 			fieldLoop: for (; index < fieldsLength; index++) {
2719 				if (!foundSyntheticField && CharOperation.equals(TypeConstants.SYNTHETIC_ENUM_VALUES, fields[index].getName())) {
2720 					foundSyntheticField = true;
2721 					continue fieldLoop;
2722 				}
2723 				writeNewLine(buffer, lineSeparator, tabNumber);
2724 				disassemble(fields[index], buffer, lineSeparator, tabNumber, mode);
2725 			}
2726 			methodLoop: for (int i = 0, max = methods.length; i < max; i++) {
2727 				final IMethodInfo methodInfo = methods[i];
2728 				if (CharOperation.equals(methodInfo.getName(), TypeConstants.VALUES)) {
2729 					final char[] descriptor = methodInfo.getDescriptor();
2730 					CharOperation.replace(descriptor, '/', '.');
2731 					if (Signature.getParameterCount(descriptor) == 0) {
2732 						if (CharOperation.equals(returnClassName(Signature.getReturnType(descriptor), '.', mode),
2733 								CharOperation.concat(new char[] {'[', 'L'}, className, new char[] {';'}))) {
2734 							continue methodLoop;
2735 						}
2736 					}
2737 				} else if (CharOperation.equals(methodInfo.getName(), TypeConstants.VALUEOF)) {
2738 					final char[] descriptor = methodInfo.getDescriptor();
2739 					CharOperation.replace(descriptor, '/', '.');
2740 					final char[][] parameterTypes = Signature.getParameterTypes(descriptor);
2741 					if (parameterTypes.length == 1
2742 							&& CharOperation.equals(parameterTypes[0], "Ljava.lang.String;".toCharArray())) { //$NON-NLS-1$
2743 						if (CharOperation.equals(returnClassName(Signature.getReturnType(descriptor), '.', mode),
2744 								CharOperation.concat('L', className, ';'))) {
2745 							continue methodLoop;
2746 						}
2747 					}
2748 				} else if (methodInfo.isClinit() || methodInfo.isSynthetic()) {
2749 					continue methodLoop;
2750 				} else if (methodInfo.isConstructor()) {
2751 					writeNewLine(buffer, lineSeparator, tabNumber);
2752 					disassembleEnumConstructor(classFileReader, className, methodInfo, buffer, lineSeparator, tabNumber, mode);
2753 				} else {
2754 					writeNewLine(buffer, lineSeparator, tabNumber);
2755 					disassemble(classFileReader, className, methodInfo, buffer, lineSeparator, tabNumber, mode);
2756 				}
2757 			}
2758 		} else {
2759 			for (int i = 0, max = fields.length; i < max; i++) {
2760 				writeNewLine(buffer, lineSeparator, tabNumber);
2761 				disassemble(fields[i], buffer, lineSeparator, tabNumber, mode);
2762 			}
2763 			IMethodInfo[] methods = classFileReader.getMethodInfos();
2764 			for (int i = 0, max = methods.length; i < max; i++) {
2765 				writeNewLine(buffer, lineSeparator, tabNumber);
2766 				disassemble(classFileReader, className, methods[i], buffer, lineSeparator, tabNumber, mode);
2767 			}
2768 		}
2769 	}
2770 
getConstructorArgumentsForEnum(final IMethodInfo[] methods)2771 	private char[][] getConstructorArgumentsForEnum(final IMethodInfo[] methods) {
2772 		loop: for (int i = 0, max = methods.length; i < max; i++) {
2773 			IMethodInfo methodInfo = methods[i];
2774 			if (methodInfo.isConstructor()) {
2775 				char[][] parameterTypes = Signature.getParameterTypes(methodInfo.getDescriptor());
2776 				final int length = parameterTypes.length;
2777 				if (length >= 2) {
2778 					return CharOperation.subarray(parameterTypes, 2, length);
2779 				}
2780 			} else {
2781 				continue loop;
2782 			}
2783 		}
2784 		return null;
2785 	}
2786 
dumpTab(int tabNumber, StringBuffer buffer)2787 	private final void dumpTab(int tabNumber, StringBuffer buffer) {
2788 		for (int i = 0; i < tabNumber; i++) {
2789 			buffer.append(Messages.disassembler_indentation);
2790 		}
2791 	}
2792 
dumpNewLineWithTabs(String lineSeparator, int tabNumber)2793 	private final String dumpNewLineWithTabs(String lineSeparator, int tabNumber) {
2794 		StringBuffer buffer = new StringBuffer();
2795 		writeNewLine(buffer, lineSeparator, tabNumber);
2796 		return String.valueOf(buffer);
2797 	}
2798 
2799 	/**
2800 	 * @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#getDescription()
2801 	 */
2802 	@Override
getDescription()2803 	public String getDescription() {
2804 		return Messages.disassembler_description;
2805 	}
2806 
getParameterNames(char[] methodDescriptor, ICodeAttribute codeAttribute, IMethodParametersAttribute parametersAttribute, int accessFlags)2807 	private char[][] getParameterNames(char[] methodDescriptor, ICodeAttribute codeAttribute, IMethodParametersAttribute parametersAttribute, int accessFlags) {
2808 		int paramCount = Signature.getParameterCount(methodDescriptor);
2809 		char[][] parameterNames = new char[paramCount][];
2810 		// check if the code attribute has debug info for this method
2811 		if (parametersAttribute != null) {
2812 			int parameterCount = parametersAttribute.getMethodParameterLength();
2813 			for (int i = 0; i < paramCount; i++) {
2814 				if (i < parameterCount && parametersAttribute.getParameterName(i) != null) {
2815 					parameterNames[i] = parametersAttribute.getParameterName(i);
2816 				} else {
2817 					parameterNames[i] = Messages.disassembler_anonymousparametername.toCharArray();
2818 				}
2819 			}
2820 		} else if (codeAttribute != null) {
2821 				ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute();
2822 				if (localVariableAttribute != null) {
2823 					ILocalVariableTableEntry[] entries = localVariableAttribute.getLocalVariableTable();
2824 					final int startingIndex = (accessFlags & IModifierConstants.ACC_STATIC) != 0 ? 0 : 1;
2825 					for (int i = 0; i < paramCount; i++) {
2826 						ILocalVariableTableEntry searchedEntry = getEntryFor(getLocalIndex(startingIndex, i, methodDescriptor), entries);
2827 						if (searchedEntry != null) {
2828 							parameterNames[i] = searchedEntry.getName();
2829 						} else {
2830 							parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray());
2831 						}
2832 					}
2833 				} else {
2834 					for (int i = 0; i < paramCount; i++) {
2835 						parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray());
2836 					}
2837 				}
2838 		} else {
2839 			for (int i = 0; i < paramCount; i++) {
2840 				parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray());
2841 			}
2842 		}
2843 		return parameterNames;
2844 	}
2845 
getLocalIndex(final int startingSlot, final int index, final char[] methodDescriptor)2846 	private int getLocalIndex(final int startingSlot, final int index, final char[] methodDescriptor) {
2847 		int slot = startingSlot;
2848 		final char[][] types = Signature.getParameterTypes(methodDescriptor);
2849 		for (int i = 0; i < index; i++) {
2850 			final char[] type = types[i];
2851 			switch(type.length) {
2852 				case 1 :
2853 					switch(type[0]) {
2854 						case 'D' :
2855 						case 'J' :
2856 							slot += 2;
2857 							break;
2858 						default :
2859 							slot++;
2860 					}
2861 					break;
2862 				default :
2863 					slot++;
2864 			}
2865 		}
2866 		return slot;
2867 	}
2868 
getEntryFor(final int index, final ILocalVariableTableEntry[] entries)2869 	private ILocalVariableTableEntry getEntryFor(final int index, final ILocalVariableTableEntry[] entries) {
2870 		for (int i = 0, max = entries.length; i < max; i++) {
2871 			ILocalVariableTableEntry entry = entries[i];
2872 			if (index == entry.getIndex()) {
2873 				return entry;
2874 			}
2875 		}
2876 		return null;
2877 	}
2878 
getSignatureForField(char[] fieldDescriptor)2879 	private char[] getSignatureForField(char[] fieldDescriptor) {
2880 		char[] newFieldDescriptor = CharOperation.replaceOnCopy(fieldDescriptor, '/', '.');
2881 		newFieldDescriptor = CharOperation.replaceOnCopy(newFieldDescriptor, '$', '%');
2882 		char[] fieldDescriptorSignature = Signature.toCharArray(newFieldDescriptor);
2883 		CharOperation.replace(fieldDescriptorSignature, '%', '$');
2884 		return fieldDescriptorSignature;
2885 	}
getSignatureForComponent(char[] componentDescriptor)2886 	private char[] getSignatureForComponent(char[] componentDescriptor) {
2887 		char[] newComponentDescriptor = CharOperation.replaceOnCopy(componentDescriptor, '/', '.');
2888 		newComponentDescriptor = CharOperation.replaceOnCopy(newComponentDescriptor, '$', '%');
2889 		char[] componentDescriptorSignature = Signature.toCharArray(newComponentDescriptor);
2890 		CharOperation.replace(componentDescriptorSignature, '%', '$');
2891 		return componentDescriptorSignature;
2892 	}
2893 
isDeprecated(IClassFileReader classFileReader)2894 	private boolean isDeprecated(IClassFileReader classFileReader) {
2895 		IClassFileAttribute[] attributes = classFileReader.getAttributes();
2896 		for (int i = 0, max = attributes.length; i < max; i++) {
2897 			if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.DEPRECATED)) {
2898 				return true;
2899 			}
2900 		}
2901 		return false;
2902 	}
2903 
isSynthetic(IClassFileReader classFileReader)2904 	private boolean isSynthetic(IClassFileReader classFileReader) {
2905 		int flags = classFileReader.getAccessFlags();
2906 		if ((flags & IModifierConstants.ACC_SYNTHETIC) != 0) {
2907 			return true;
2908 		}
2909 		IClassFileAttribute[] attributes = classFileReader.getAttributes();
2910 		for (int i = 0, max = attributes.length; i < max; i++) {
2911 			if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) {
2912 				return true;
2913 			}
2914 		}
2915 		return false;
2916 	}
2917 
checkMode(int mode, int flag)2918 	private boolean checkMode(int mode, int flag) {
2919 		return (mode & flag) != 0;
2920 	}
2921 
isCompact(int mode)2922 	private boolean isCompact(int mode) {
2923 		return (mode & ClassFileBytesDisassembler.COMPACT) != 0;
2924 	}
2925 
returnClassName(char[] classInfoName, char separator, int mode)2926 	private char[] returnClassName(char[] classInfoName, char separator, int mode) {
2927 		if (classInfoName.length == 0) {
2928 			return CharOperation.NO_CHAR;
2929 		} else if (isCompact(mode)) {
2930 			int lastIndexOfSlash = CharOperation.lastIndexOf(separator, classInfoName);
2931 			if (lastIndexOfSlash != -1) {
2932 				return CharOperation.subarray(classInfoName, lastIndexOfSlash + 1, classInfoName.length);
2933 			}
2934 		}
2935 		return classInfoName;
2936 	}
2937 
writeNewLine(StringBuffer buffer, String lineSeparator, int tabNumber)2938 	private void writeNewLine(StringBuffer buffer, String lineSeparator, int tabNumber) {
2939 		buffer.append(lineSeparator);
2940 		dumpTab(tabNumber, buffer);
2941 	}
2942 
toTypePathString(int[][] typepath)2943 	private String toTypePathString(int[][] typepath) {
2944 		StringBuffer buffer = new StringBuffer();
2945 		buffer.append('[');
2946 		for (int i = 0, max = typepath.length; i < max; i++) {
2947 			int[] typepathElement = typepath[i];
2948 			if (i > 0) {
2949 				buffer.append(',').append(' ');
2950 			}
2951 			switch (typepathElement[0]) {
2952 				case IExtendedAnnotationConstants.TYPE_PATH_DEEPER_IN_ARRAY:
2953 					buffer.append(Messages.disassembler_extendedannotation_typepath_array);
2954 					break;
2955 				case IExtendedAnnotationConstants.TYPE_PATH_DEEPER_IN_INNER_TYPE:
2956 					buffer.append(Messages.disassembler_extendedannotation_typepath_innertype);
2957 					break;
2958 				case IExtendedAnnotationConstants.TYPE_PATH_ANNOTATION_ON_WILDCARD_BOUND:
2959 					buffer.append(Messages.disassembler_extendedannotation_typepath_wildcard);
2960 					break;
2961 				case IExtendedAnnotationConstants.TYPE_PATH_TYPE_ARGUMENT_INDEX:
2962 					buffer.append(
2963 							Messages.bind(Messages.disassembler_extendedannotation_typepath_typeargument,
2964 								new String[] {
2965 									Integer.toString(typepathElement[1])
2966 								}));
2967 					break;
2968 				default:
2969 					throw new IllegalStateException("Unrecognized type_path_kind: "+typepathElement[0]); //$NON-NLS-1$
2970 			}
2971 		}
2972 		buffer.append(']');
2973 		return String.valueOf(buffer);
2974 	}
2975 
2976 }
2977