2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 package com
.intellij
.psi
.impl
.compiled
;
22 import com
.intellij
.lexer
.JavaLexer
;
23 import com
.intellij
.openapi
.extensions
.Extensions
;
24 import com
.intellij
.openapi
.util
.Comparing
;
25 import com
.intellij
.openapi
.util
.text
.StringUtil
;
26 import com
.intellij
.openapi
.vfs
.VirtualFile
;
27 import com
.intellij
.pom
.java
.LanguageLevel
;
28 import com
.intellij
.psi
.JavaTokenType
;
29 import com
.intellij
.psi
.PsiNameHelper
;
30 import com
.intellij
.psi
.PsiReferenceList
;
31 import com
.intellij
.psi
.impl
.cache
.ModifierFlags
;
32 import com
.intellij
.psi
.impl
.cache
.TypeInfo
;
33 import com
.intellij
.psi
.impl
.java
.stubs
.*;
34 import com
.intellij
.psi
.impl
.java
.stubs
.impl
.*;
35 import com
.intellij
.psi
.stubs
.PsiFileStub
;
36 import com
.intellij
.psi
.stubs
.StubElement
;
37 import com
.intellij
.util
.ArrayUtil
;
38 import com
.intellij
.util
.cls
.ClsFormatException
;
39 import com
.intellij
.util
.io
.StringRef
;
40 import org
.jetbrains
.annotations
.NonNls
;
41 import org
.jetbrains
.annotations
.NotNull
;
42 import org
.jetbrains
.annotations
.Nullable
;
43 import org
.objectweb
.asm
.*;
44 import org
.objectweb
.asm
.commons
.EmptyVisitor
;
46 import java
.io
.IOException
;
47 import java
.text
.CharacterIterator
;
48 import java
.text
.StringCharacterIterator
;
49 import java
.util
.ArrayList
;
50 import java
.util
.Collections
;
51 import java
.util
.List
;
53 @SuppressWarnings({"HardCodedStringLiteral"})
54 public class ClsStubBuilder
{
55 private ClsStubBuilder() {
59 public static PsiFileStub
build(final VirtualFile vFile
, byte[] bytes
) throws ClsFormatException
{
60 final ClsStubBuilderFactory
[] factories
= Extensions
.getExtensions(ClsStubBuilderFactory
.EP_NAME
);
61 for (ClsStubBuilderFactory factory
: factories
) {
62 if (factory
.canBeProcessed(vFile
, bytes
)) {
63 return factory
.buildFileStub(vFile
, bytes
);
67 final PsiJavaFileStubImpl file
= new PsiJavaFileStubImpl("dont.know.yet", true);
69 final PsiClassStub result
= buildClass(vFile
, bytes
, file
, Opcodes
.ACC_STATIC
);
70 if (result
== null) return null;
72 file
.setPackageName(getPackageName(result
));
75 throw new ClsFormatException();
80 private static PsiClassStub
<?
> buildClass(final VirtualFile vFile
, final byte[] bytes
, final StubElement parent
, final int access
) {
81 ClassReader reader
= new ClassReader(bytes
);
83 final MyClassVisitor classVisitor
= new MyClassVisitor(vFile
, parent
, access
);
84 reader
.accept(classVisitor
, 0);
85 return classVisitor
.getResult();
88 private static String
getPackageName(final PsiClassStub result
) {
89 final String fqn
= result
.getQualifiedName();
90 final String shortName
= result
.getName();
91 if (fqn
== null || Comparing
.equal(shortName
, fqn
)) {
95 return fqn
.substring(0, fqn
.lastIndexOf('.'));
98 private static class MyClassVisitor
implements ClassVisitor
{
99 private final StubElement myParent
;
100 private final int myAccess
;
101 private final VirtualFile myVFile
;
102 private PsiModifierListStub myModlist
;
103 private PsiClassStub myResult
;
104 @NonNls private static final String SYNTHETIC_CLINIT_METHOD
= "<clinit>";
105 @NonNls private static final String SYNTHETIC_INIT_METHOD
= "<init>";
106 private JavaLexer myLexer
;
108 private MyClassVisitor(final VirtualFile vFile
, final StubElement parent
, final int access
) {
114 public PsiClassStub
<?
> getResult() {
118 public void visit(final int version
,
121 final String signature
,
122 final String superName
,
123 final String
[] interfaces
) {
124 String fqn
= getClassName(name
);
126 final String shortName
= PsiNameHelper
.getShortClassName(fqn
);
128 final int flags
= myAccess
| access
;
130 boolean isDeprecated
= (flags
& Opcodes
.ACC_DEPRECATED
) != 0;
131 boolean isInterface
= (flags
& Opcodes
.ACC_INTERFACE
) != 0;
132 boolean isEnum
= (flags
& Opcodes
.ACC_ENUM
) != 0;
133 boolean isAnnotationType
= (flags
& Opcodes
.ACC_ANNOTATION
) != 0;
135 final byte stubFlags
= PsiClassStubImpl
.packFlags(isDeprecated
, isInterface
, isEnum
, false, false, isAnnotationType
, false, false);
137 myResult
= new PsiClassStubImpl(JavaStubElementTypes
.CLASS
, myParent
, fqn
, shortName
, null, stubFlags
);
139 LanguageLevel languageLevel
= convertFromVersion(version
);
140 myLexer
= new JavaLexer(languageLevel
);
142 ((PsiClassStubImpl
)myResult
).setLanguageLevel(languageLevel
);
143 myModlist
= new PsiModifierListStubImpl(myResult
, packModlistFlags(flags
));
145 CharacterIterator signatureIterator
= signature
!= null ?
new StringCharacterIterator(signature
) : null;
146 if (signatureIterator
!= null) {
148 SignatureParsing
.parseTypeParametersDeclaration(signatureIterator
, myResult
);
150 catch (ClsFormatException e
) {
151 signatureIterator
= null;
154 new PsiTypeParameterListStubImpl(myResult
);
157 String convertedSuper
;
158 List
<String
> convertedInterfaces
= new ArrayList
<String
>();
159 if (signatureIterator
== null) {
160 convertedSuper
= parseClassDescription(superName
, interfaces
, convertedInterfaces
);
163 convertedSuper
= parseClassSignature(signatureIterator
, convertedInterfaces
);
165 catch (ClsFormatException e
) {
166 new PsiTypeParameterListStubImpl(myResult
);
167 convertedSuper
= parseClassDescription(superName
, interfaces
, convertedInterfaces
);
171 String
[] interfacesArray
= ArrayUtil
.toStringArray(convertedInterfaces
);
173 new PsiClassReferenceListStubImpl(JavaStubElementTypes
.EXTENDS_LIST
, myResult
, interfacesArray
, PsiReferenceList
.Role
.EXTENDS_LIST
);
174 new PsiClassReferenceListStubImpl(JavaStubElementTypes
.IMPLEMENTS_LIST
, myResult
, ArrayUtil
.EMPTY_STRING_ARRAY
,
175 PsiReferenceList
.Role
.IMPLEMENTS_LIST
);
177 if (convertedSuper
!= null && !"java.lang.Object".equals(convertedSuper
)) {
178 new PsiClassReferenceListStubImpl(JavaStubElementTypes
.EXTENDS_LIST
, myResult
, new String
[]{convertedSuper
},
179 PsiReferenceList
.Role
.EXTENDS_LIST
);
181 new PsiClassReferenceListStubImpl(JavaStubElementTypes
.EXTENDS_LIST
, myResult
, ArrayUtil
.EMPTY_STRING_ARRAY
, PsiReferenceList
.Role
.EXTENDS_LIST
);
183 new PsiClassReferenceListStubImpl(JavaStubElementTypes
.IMPLEMENTS_LIST
, myResult
, interfacesArray
,
184 PsiReferenceList
.Role
.IMPLEMENTS_LIST
);
189 private static String
parseClassDescription(final String superName
, final String
[] interfaces
, final List
<String
> convertedInterfaces
) {
190 final String convertedSuper
= superName
!= null ?
getClassName(superName
) : null;
191 for (String anInterface
: interfaces
) {
192 convertedInterfaces
.add(getClassName(anInterface
));
194 return convertedSuper
;
198 private static String
parseClassSignature(final CharacterIterator signatureIterator
, final List
<String
> convertedInterfaces
)
199 throws ClsFormatException
{
200 final String convertedSuper
= SignatureParsing
.parseToplevelClassRefSignature(signatureIterator
);
201 while (signatureIterator
.current() != CharacterIterator
.DONE
) {
202 final String ifs
= SignatureParsing
.parseToplevelClassRefSignature(signatureIterator
);
203 if (ifs
== null) throw new ClsFormatException();
205 convertedInterfaces
.add(ifs
);
207 return convertedSuper
;
210 private static LanguageLevel
convertFromVersion(final int version
) {
211 if (version
== Opcodes
.V1_1
|| version
== Opcodes
.V1_2
|| version
== Opcodes
.V1_3
) {
212 return LanguageLevel
.JDK_1_3
;
215 if (version
== Opcodes
.V1_4
) {
216 return LanguageLevel
.JDK_1_4
;
219 if (version
== Opcodes
.V1_5
|| version
== Opcodes
.V1_6
) {
220 return LanguageLevel
.JDK_1_5
;
223 return LanguageLevel
.HIGHEST
;
226 private static int packModlistFlags(final int access
) {
229 if ((access
& Opcodes
.ACC_PRIVATE
) != 0) {
230 flags
|= ModifierFlags
.PRIVATE_MASK
;
232 else if ((access
& Opcodes
.ACC_PROTECTED
) != 0) {
233 flags
|= ModifierFlags
.PROTECTED_MASK
;
235 else if ((access
& Opcodes
.ACC_PUBLIC
) != 0) {
236 flags
|= ModifierFlags
.PUBLIC_MASK
;
239 flags
|= ModifierFlags
.PACKAGE_LOCAL_MASK
;
242 if ((access
& Opcodes
.ACC_ABSTRACT
) != 0) {
243 flags
|= ModifierFlags
.ABSTRACT_MASK
;
245 if ((access
& Opcodes
.ACC_FINAL
) != 0) {
246 flags
|= ModifierFlags
.FINAL_MASK
;
248 if ((access
& Opcodes
.ACC_NATIVE
) != 0) {
249 flags
|= ModifierFlags
.NATIVE_MASK
;
251 if ((access
& Opcodes
.ACC_STATIC
) != 0) {
252 flags
|= ModifierFlags
.STATIC_MASK
;
254 if ((access
& Opcodes
.ACC_TRANSIENT
) != 0) {
255 flags
|= ModifierFlags
.TRANSIENT_MASK
;
257 if ((access
& Opcodes
.ACC_VOLATILE
) != 0) {
258 flags
|= ModifierFlags
.VOLATILE_MASK
;
260 if ((access
& Opcodes
.ACC_STRICT
) != 0) {
261 flags
|= ModifierFlags
.STRICTFP_MASK
;
267 public void visitSource(final String source
, final String debug
) {
268 ((PsiClassStubImpl
)myResult
).setSourceFileName(source
);
271 public void visitOuterClass(final String owner
, final String name
, final String desc
) {
274 public AnnotationVisitor
visitAnnotation(final String desc
, final boolean visible
) {
275 return new AnnotationTextCollector(desc
, new AnnotationResultCallback() {
276 public void callback(final String text
) {
277 new PsiAnnotationStubImpl(myModlist
, text
);
282 public void visitAttribute(final Attribute attr
) {
285 public void visitInnerClass(final String name
, final String outerName
, final String innerName
, final int access
) {
286 if ((access
& Opcodes
.ACC_SYNTHETIC
) != 0) return;
287 if (!isCorrectName(innerName
)) return;
289 if (innerName
!= null && outerName
!= null && getClassName(outerName
).equals(myResult
.getQualifiedName())) {
290 final String basename
= myVFile
.getNameWithoutExtension();
291 final VirtualFile dir
= myVFile
.getParent();
294 final VirtualFile innerFile
= dir
.findChild(basename
+ "$" + innerName
+ ".class");
295 if (innerFile
!= null) {
297 buildClass(innerFile
, innerFile
.contentsToByteArray(), myResult
, access
);
299 catch (IOException e
) {
300 // No inner class file found, ignore.
306 private boolean isCorrectName(String name
) {
307 if (name
== null) return false;
310 if (myLexer
.getTokenType() != JavaTokenType
.IDENTIFIER
) return false;
312 return myLexer
.getTokenType() == null;
315 public FieldVisitor
visitField(final int access
, final String name
, final String desc
, final String signature
, final Object value
) {
316 if ((access
& Opcodes
.ACC_SYNTHETIC
) != 0) return null;
317 if (!isCorrectName(name
)) return null;
319 final byte flags
= PsiFieldStubImpl
.packFlags((access
& Opcodes
.ACC_ENUM
) != 0, (access
& Opcodes
.ACC_DEPRECATED
) != 0, false);
320 PsiFieldStub stub
= new PsiFieldStubImpl(myResult
, name
, fieldType(desc
, signature
), constToString(value
), flags
);
321 final PsiModifierListStub modlist
= new PsiModifierListStubImpl(stub
, packModlistFlags(access
));
322 return new AnnotationCollectingVisitor(stub
, modlist
);
326 private static TypeInfo
fieldType(String desc
, String signature
) {
327 if (signature
!= null) {
329 return TypeInfo
.fromString(SignatureParsing
.parseTypeString(new StringCharacterIterator(signature
, 0)));
331 catch (ClsFormatException e
) {
332 return fieldTypeViaDescription(desc
);
335 return fieldTypeViaDescription(desc
);
340 private static TypeInfo
fieldTypeViaDescription(final String desc
) {
341 Type type
= Type
.getType(desc
);
342 final int dim
= type
.getSort() == Type
.ARRAY ? type
.getDimensions() : 0;
344 type
= type
.getElementType();
346 return new TypeInfo(StringRef
.fromString(getTypeText(type
)), (byte)dim
, false, Collections
.<PsiAnnotationStub
>emptyList()); //todo read annos from .class file
351 public MethodVisitor
visitMethod(final int access
,
354 final String signature
,
355 final String
[] exceptions
) {
356 if ((access
& Opcodes
.ACC_SYNTHETIC
) != 0) return null;
357 if ((access
& Opcodes
.ACC_BRIDGE
) != 0) return null;
358 if (SYNTHETIC_CLINIT_METHOD
.equals(name
)) return null;
360 boolean isDeprecated
= (access
& Opcodes
.ACC_DEPRECATED
) != 0;
361 boolean isConstructor
= SYNTHETIC_INIT_METHOD
.equals(name
);
362 boolean isVarargs
= (access
& Opcodes
.ACC_VARARGS
) != 0;
363 boolean isAnnotationMethod
= myResult
.isAnnotationType();
365 if (!isConstructor
&& !isCorrectName(name
)) return null;
367 final byte flags
= PsiMethodStubImpl
.packFlags(isConstructor
, isAnnotationMethod
, isVarargs
, isDeprecated
, false);
369 String canonicalMethodName
= isConstructor ? myResult
.getName() : name
;
370 final List
<String
> args
= new ArrayList
<String
>();
371 final List
<String
> throwables
= exceptions
!= null ?
new ArrayList
<String
>() : null;
373 PsiMethodStubImpl stub
= new PsiMethodStubImpl(myResult
, StringRef
.fromString(canonicalMethodName
), flags
, null);
375 final PsiModifierListStub modlist
= new PsiModifierListStubImpl(stub
, packMethodFlags(access
));
376 boolean parsedViaGenericSignature
= false;
378 if (signature
== null) {
379 returnType
= parseMethodViaDescription(desc
, stub
, args
);
383 returnType
= parseMethodViaGenericSignature(signature
, stub
, args
, throwables
);
384 parsedViaGenericSignature
= true;
386 catch (ClsFormatException e
) {
387 returnType
= parseMethodViaDescription(desc
, stub
, args
);
391 stub
.setReturnType(TypeInfo
.fromString(returnType
));
394 boolean nonStaticInnerClassConstructor
=
395 isConstructor
&& !parsedViaGenericSignature
&& !(myParent
instanceof PsiFileStub
) && (myModlist
.getModifiersMask() & Opcodes
.ACC_STATIC
) == 0;
397 final PsiParameterListStubImpl parameterList
= new PsiParameterListStubImpl(stub
);
398 final int paramCount
= args
.size();
399 final PsiParameterStubImpl
[] paramStubs
= new PsiParameterStubImpl
[paramCount
];
400 for (int i
= 0; i
< paramCount
; i
++) {
401 if (nonStaticInnerClassConstructor
&& i
== 0) continue;
403 String arg
= args
.get(i
);
404 boolean isEllipsisParam
= isVarargs
&& i
== paramCount
- 1;
405 final TypeInfo typeInfo
= TypeInfo
.fromString(arg
, isEllipsisParam
);
407 PsiParameterStubImpl parameterStub
= new PsiParameterStubImpl(parameterList
, "p" + (i
+ 1), typeInfo
, isEllipsisParam
);
408 paramStubs
[i
] = parameterStub
;
409 new PsiModifierListStubImpl(parameterStub
, 0);
412 String
[] thrownTypes
= buildThrowsList(exceptions
, throwables
, parsedViaGenericSignature
);
413 new PsiClassReferenceListStubImpl(JavaStubElementTypes
.THROWS_LIST
, stub
, thrownTypes
, PsiReferenceList
.Role
.THROWS_LIST
);
415 int ignoreCount
= (access
& Opcodes
.ACC_STATIC
) != 0 ?
0 : 1;
416 return new AnnotationParamCollectingVisitor(stub
, modlist
, ignoreCount
, paramCount
, paramStubs
);
419 private static String
[] buildThrowsList(String
[] exceptions
, List
<String
> throwables
, boolean parsedViaGenericSignature
) {
420 if (exceptions
== null) return ArrayUtil
.EMPTY_STRING_ARRAY
;
422 if (parsedViaGenericSignature
&& throwables
!= null && exceptions
.length
> throwables
.size()) {
423 // There seem to be an inconsistency (or bug) in class format. For instance, java.lang.Class.forName() method has
424 // signature equal to "(Ljava/lang/String;)Ljava/lang/Class<*>;" (i.e. no exceptions thrown) but exceptions actually not empty,
425 // method throws ClassNotFoundException
426 parsedViaGenericSignature
= false;
429 if (parsedViaGenericSignature
&& throwables
!= null) {
430 return ArrayUtil
.toStringArray(throwables
);
433 String
[] converted
= ArrayUtil
.newStringArray(exceptions
.length
);
434 for (int i
= 0; i
< converted
.length
; i
++) {
435 converted
[i
] = getClassName(exceptions
[i
]);
441 private static int packMethodFlags(final int access
) {
442 int commonFlags
= packModlistFlags(access
);
443 if ((access
& Opcodes
.ACC_SYNCHRONIZED
) != 0) {
444 commonFlags
|= ModifierFlags
.SYNCHRONIZED_MASK
;
450 private static String
parseMethodViaDescription(final String desc
, final PsiMethodStubImpl stub
, final List
<String
> args
) {
451 final String returnType
= getTypeText(Type
.getReturnType(desc
));
452 final Type
[] argTypes
= Type
.getArgumentTypes(desc
);
453 for (Type argType
: argTypes
) {
454 args
.add(getTypeText(argType
));
456 new PsiTypeParameterListStubImpl(stub
);
460 private static String
parseMethodViaGenericSignature(final String signature
,
461 final PsiMethodStubImpl stub
,
462 final List
<String
> args
,
463 final List
<String
> throwables
)
464 throws ClsFormatException
{
465 StringCharacterIterator iterator
= new StringCharacterIterator(signature
);
466 SignatureParsing
.parseTypeParametersDeclaration(iterator
, stub
);
468 if (iterator
.current() != '(') {
469 throw new ClsFormatException();
473 while (iterator
.current() != ')' && iterator
.current() != CharacterIterator
.DONE
) {
474 args
.add(SignatureParsing
.parseTypeString(iterator
));
477 if (iterator
.current() != ')') {
478 throw new ClsFormatException();
482 String returnType
= SignatureParsing
.parseTypeString(iterator
);
484 while (iterator
.current() == '^') {
486 throwables
.add(SignatureParsing
.parseTypeString(iterator
));
492 public void visitEnd() {
496 private static class AnnotationTextCollector
implements AnnotationVisitor
{
497 private final StringBuilder myBuilder
= new StringBuilder();
498 private final AnnotationResultCallback myCallback
;
499 private boolean hasParams
= false;
500 private final String myDesc
;
502 public AnnotationTextCollector(@Nullable String desc
, AnnotationResultCallback callback
) {
503 myCallback
= callback
;
507 myBuilder
.append('@').append(getTypeText(Type
.getType(desc
)));
511 public void visit(final String name
, final Object value
) {
512 valuePairPrefix(name
);
513 myBuilder
.append(constToString(value
));
516 public void visitEnum(final String name
, final String desc
, final String value
) {
517 valuePairPrefix(name
);
518 myBuilder
.append(getTypeText(Type
.getType(desc
))).append(".").append(value
);
521 private void valuePairPrefix(final String name
) {
524 if (myDesc
!= null) {
525 myBuilder
.append('(');
528 myBuilder
.append(',');
531 if (name
!= null && !"value".equals(name
)) {
532 myBuilder
.append(name
).append('=');
536 public AnnotationVisitor
visitAnnotation(final String name
, final String desc
) {
537 valuePairPrefix(name
);
538 return new AnnotationTextCollector(desc
, new AnnotationResultCallback() {
539 public void callback(final String text
) {
540 myBuilder
.append(text
);
545 public AnnotationVisitor
visitArray(final String name
) {
546 valuePairPrefix(name
);
547 myBuilder
.append("{");
548 return new AnnotationTextCollector(null, new AnnotationResultCallback() {
549 public void callback(final String text
) {
550 myBuilder
.append(text
).append('}');
555 public void visitEnd() {
556 if (hasParams
&& myDesc
!= null) {
557 myBuilder
.append(')');
559 myCallback
.callback(myBuilder
.toString());
563 private static class AnnotationCollectingVisitor
extends EmptyVisitor
{
564 private final StubElement myOwner
;
565 private final PsiModifierListStub myModList
;
567 private AnnotationCollectingVisitor(final StubElement owner
, final PsiModifierListStub modList
) {
572 public AnnotationVisitor
visitAnnotationDefault() {
573 return new AnnotationTextCollector(null, new AnnotationResultCallback() {
574 public void callback(final String text
) {
575 ((PsiMethodStubImpl
)myOwner
).setDefaultValueText(text
);
580 public AnnotationVisitor
visitAnnotation(final String desc
, final boolean visible
) {
581 return new AnnotationTextCollector(desc
, new AnnotationResultCallback() {
582 public void callback(final String text
) {
583 new PsiAnnotationStubImpl(myModList
, text
);
588 public AnnotationVisitor
visitParameterAnnotation(final int parameter
, final String desc
, final boolean visible
) {
589 return new AnnotationTextCollector(desc
, new AnnotationResultCallback() {
590 public void callback(final String text
) {
591 new PsiAnnotationStubImpl(((PsiMethodStub
)myOwner
).findParameter(parameter
).getModList(), text
);
597 private static class AnnotationParamCollectingVisitor
extends AnnotationCollectingVisitor
{
598 private final int myIgnoreCount
;
599 private final int myParamCount
;
600 private final PsiParameterStubImpl
[] myParamStubs
;
602 private AnnotationParamCollectingVisitor(final StubElement owner
, final PsiModifierListStub modList
, int ignoreCount
, int paramCount
,
603 PsiParameterStubImpl
[] paramStubs
) {
604 super(owner
, modList
);
605 myIgnoreCount
= ignoreCount
;
606 myParamCount
= paramCount
;
607 myParamStubs
= paramStubs
;
611 public void visitLocalVariable(String name
, String desc
, String signature
, Label start
, Label end
, int index
) {
612 if (index
>= myIgnoreCount
&& index
< myIgnoreCount
+ myParamCount
) {
613 PsiParameterStubImpl parameterStub
= myParamStubs
[index
- myIgnoreCount
];
614 if (parameterStub
!= null) {
615 parameterStub
.setName(name
);
621 @SuppressWarnings({"HardCodedStringLiteral"})
623 private static String
constToString(final Object value
) {
624 if (value
== null) return null;
626 if (value
instanceof String
) return "\"" + StringUtil
.escapeStringCharacters((String
)value
) + "\"";
627 if (value
instanceof Integer
|| value
instanceof Boolean
) return value
.toString();
628 if (value
instanceof Long
) return value
.toString() + "L";
630 if (value
instanceof Double
) {
631 final double d
= ((Double
)value
).doubleValue();
632 if (Double
.isInfinite(d
)) {
633 return d
> 0 ?
"1.0 / 0.0" : "-1.0 / 0.0";
635 else if (Double
.isNaN(d
)) {
638 return Double
.toString(d
);
641 if (value
instanceof Float
) {
642 final float v
= ((Float
)value
).floatValue();
644 if (Float
.isInfinite(v
)) {
645 return v
> 0 ?
"1.0f / 0.0" : "-1.0f / 0.0";
647 else if (Float
.isNaN(v
)) {
651 return Float
.toString(v
) + "f";
658 private interface AnnotationResultCallback
{
659 void callback(String text
);
662 private static String
getClassName(final String name
) {
663 return getTypeText(Type
.getObjectType(name
));
666 private static String
getTypeText(final Type type
) {
667 final String raw
= type
.getClassName();
668 return raw
.replace('$', '.');