@Override @Nullable public MethodVisitor visitMethod( final int access, final String name, final String desc, final String signature, final String[] exceptions) { // JLS 13.1 says: Any constructs introduced by the compiler that do not have a corresponding // construct in the source code // must be marked as synthetic, except for default constructors and the class initialization // method. // However Scala compiler erroneously generates ACC_BRIDGE instead of ACC_SYNTHETIC flag for // in-trait implementation delegation. // See IDEA-78649 if ((access & Opcodes.ACC_SYNTHETIC) != 0) return null; if (SYNTHETIC_CLASS_INIT_METHOD.equals(name)) return null; boolean isDeprecated = (access & Opcodes.ACC_DEPRECATED) != 0; boolean isConstructor = SYNTHETIC_INIT_METHOD.equals(name); boolean isVarargs = (access & Opcodes.ACC_VARARGS) != 0; boolean isAnnotationMethod = myResult.isAnnotationType(); if (!isConstructor && !isCorrectName(name)) return null; final byte flags = PsiMethodStubImpl.packFlags( isConstructor, isAnnotationMethod, isVarargs, isDeprecated, false); final String canonicalMethodName = isConstructor ? myResult.getName() : name; final List<String> args = new ArrayList<String>(); final List<String> throwables = exceptions != null ? new ArrayList<String>() : null; final PsiMethodStubImpl stub = new PsiMethodStubImpl(myResult, StringRef.fromString(canonicalMethodName), flags, null); final PsiModifierListStub modList = new PsiModifierListStubImpl(stub, packMethodFlags(access, myResult.isInterface())); boolean parsedViaGenericSignature = false; String returnType; if (signature == null) { returnType = parseMethodViaDescription(desc, stub, args); } else { try { returnType = parseMethodViaGenericSignature(signature, stub, args, throwables); parsedViaGenericSignature = true; } catch (ClsFormatException e) { returnType = parseMethodViaDescription(desc, stub, args); } } stub.setReturnType(TypeInfo.fromString(returnType)); final boolean isNonStaticInnerClassConstructor = isConstructor && !(myParent instanceof PsiFileStub) && (myModList.getModifiersMask() & Opcodes.ACC_STATIC) == 0; final boolean shouldSkipFirstParamForNonStaticInnerClassConstructor = !parsedViaGenericSignature && isNonStaticInnerClassConstructor; final PsiParameterListStubImpl parameterList = new PsiParameterListStubImpl(stub); final int paramCount = args.size(); final PsiParameterStubImpl[] paramStubs = new PsiParameterStubImpl[paramCount]; for (int i = 0; i < paramCount; i++) { if (shouldSkipFirstParamForNonStaticInnerClassConstructor && i == 0) continue; String arg = args.get(i); boolean isEllipsisParam = isVarargs && i == paramCount - 1; final TypeInfo typeInfo = TypeInfo.fromString(arg, isEllipsisParam); String paramName = i < parameterNames.length ? parameterNames[i] : "p" + (i + 1); PsiParameterStubImpl parameterStub = new PsiParameterStubImpl(parameterList, paramName, typeInfo, isEllipsisParam); paramStubs[i] = parameterStub; new PsiModifierListStubImpl(parameterStub, 0); } String[] thrownTypes = buildThrowsList(exceptions, throwables, parsedViaGenericSignature); newReferenceList(JavaStubElementTypes.THROWS_LIST, stub, thrownTypes); final int localVarIgnoreCount = (access & Opcodes.ACC_STATIC) != 0 ? 0 : isConstructor && myResult.isEnum() ? 3 : 1; final int paramIgnoreCount = isConstructor && myResult.isEnum() ? 2 : isNonStaticInnerClassConstructor ? 1 : 0; return new AnnotationParamCollectingVisitor( stub, modList, localVarIgnoreCount, paramIgnoreCount, paramCount, paramStubs); }
@Override public void visit( int version, int access, String name, String signature, String superName, String[] interfaces) { String fqn = getClassName(name); String shortName = myShortName != null ? myShortName : PsiNameHelper.getShortClassName(fqn); int flags = myAccess == 0 ? access : myAccess; boolean isDeprecated = (flags & Opcodes.ACC_DEPRECATED) != 0; boolean isInterface = (flags & Opcodes.ACC_INTERFACE) != 0; boolean isEnum = (flags & Opcodes.ACC_ENUM) != 0; boolean isAnnotationType = (flags & Opcodes.ACC_ANNOTATION) != 0; byte stubFlags = PsiClassStubImpl.packFlags( isDeprecated, isInterface, isEnum, false, false, isAnnotationType, false, false); myResult = new PsiClassStubImpl(JavaStubElementTypes.CLASS, myParent, fqn, shortName, null, stubFlags); LanguageLevel languageLevel = convertFromVersion(version); ((PsiClassStubImpl) myResult).setLanguageLevel(languageLevel); myModList = new PsiModifierListStubImpl(myResult, packClassFlags(flags)); CharacterIterator signatureIterator = signature != null ? new StringCharacterIterator(signature) : null; if (signatureIterator != null) { try { SignatureParsing.parseTypeParametersDeclaration(signatureIterator, myResult); } catch (ClsFormatException e) { signatureIterator = null; } } else { new PsiTypeParameterListStubImpl(myResult); } String convertedSuper; List<String> convertedInterfaces = new ArrayList<String>(); if (signatureIterator == null) { convertedSuper = parseClassDescription(superName, interfaces, convertedInterfaces); } else { try { convertedSuper = parseClassSignature(signatureIterator, convertedInterfaces); } catch (ClsFormatException e) { new PsiTypeParameterListStubImpl(myResult); convertedSuper = parseClassDescription(superName, interfaces, convertedInterfaces); } } if (isInterface) { if (isAnnotationType) { convertedInterfaces.remove(JAVA_LANG_ANNOTATION_ANNOTATION); } newReferenceList( JavaStubElementTypes.EXTENDS_LIST, myResult, ArrayUtil.toStringArray(convertedInterfaces)); newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult); } else { if (convertedSuper == null || JAVA_LANG_OBJECT.equals(convertedSuper) || isEnum && (JAVA_LANG_ENUM.equals(convertedSuper) || (JAVA_LANG_ENUM + "<" + fqn + ">").equals(convertedSuper))) { newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult); } else { newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, convertedSuper); } newReferenceList( JavaStubElementTypes.IMPLEMENTS_LIST, myResult, ArrayUtil.toStringArray(convertedInterfaces)); } }
@Override @Nullable public MethodVisitor visitMethod( final int access, final String name, final String desc, final String signature, final String[] exceptions) { // JLS 13.1 says: Any constructs introduced by the compiler that do not have a corresponding // construct in the source code // must be marked as synthetic, except for default constructors and the class initialization // method. // However Scala compiler erroneously generates ACC_BRIDGE instead of ACC_SYNTHETIC flag for // in-trait implementation delegation. // See IDEA-78649 if ((access & Opcodes.ACC_SYNTHETIC) != 0) return null; if (SYNTHETIC_CLASS_INIT_METHOD.equals(name)) return null; // skip semi-synthetic enum methods boolean isEnum = myResult.isEnum(); if (isEnum) { if ("values".equals(name) && desc.startsWith("()")) return null; if ("valueOf".equals(name) && desc.startsWith("(Ljava/lang/String;)")) return null; } boolean isDeprecated = (access & Opcodes.ACC_DEPRECATED) != 0; boolean isConstructor = SYNTHETIC_INIT_METHOD.equals(name); boolean isVarargs = (access & Opcodes.ACC_VARARGS) != 0; boolean isAnnotationMethod = myResult.isAnnotationType(); if (!isConstructor && !isCorrectName(name)) return null; final byte flags = PsiMethodStubImpl.packFlags( isConstructor, isAnnotationMethod, isVarargs, isDeprecated, false); String canonicalMethodName = isConstructor ? myResult.getName() : name; List<String> args = new ArrayList<String>(); List<String> throwables = exceptions != null ? new ArrayList<String>() : null; StringRef stringRef = StringRef.fromString(canonicalMethodName); int modifiersMask = packMethodFlags(access, myResult.isInterface()); PsiMethodStubImpl stub = new PsiMethodStubImpl( myResult, stringRef, flags, signature, args, throwables, desc, modifiersMask); PsiModifierListStub modList = (PsiModifierListStub) stub.findChildStubByType(JavaStubElementTypes.MODIFIER_LIST); assert modList != null : stub; if (isEnum && isConstructor && signature == null && args.size() >= 2 && JAVA_LANG_STRING.equals(args.get(0)) && "int".equals(args.get(1))) { // exclude synthetic enum constructor parameters args = args.subList(2, args.size()); } final boolean isNonStaticInnerClassConstructor = isConstructor && !(myParent instanceof PsiFileStub) && (myModList.getModifiersMask() & Opcodes.ACC_STATIC) == 0; boolean parsedViaGenericSignature = stub.isParsedViaGenericSignature(); final boolean shouldSkipFirstParamForNonStaticInnerClassConstructor = !parsedViaGenericSignature && isNonStaticInnerClassConstructor; final PsiParameterListStubImpl parameterList = new PsiParameterListStubImpl(stub); final int paramCount = args.size(); final PsiParameterStubImpl[] paramStubs = new PsiParameterStubImpl[paramCount]; for (int i = 0; i < paramCount; i++) { if (shouldSkipFirstParamForNonStaticInnerClassConstructor && i == 0) continue; String arg = args.get(i); boolean isEllipsisParam = isVarargs && i == paramCount - 1; final TypeInfo typeInfo = TypeInfo.fromString(arg, isEllipsisParam); String paramName = i < parameterNames.length ? parameterNames[i] : "p" + (i + 1); PsiParameterStubImpl parameterStub = new PsiParameterStubImpl(parameterList, paramName, typeInfo, isEllipsisParam); paramStubs[i] = parameterStub; new PsiModifierListStubImpl(parameterStub, 0); } String[] thrownTypes = buildThrowsList(exceptions, throwables, parsedViaGenericSignature); newReferenceList(JavaStubElementTypes.THROWS_LIST, stub, thrownTypes); int localVarIgnoreCount = (access & Opcodes.ACC_STATIC) != 0 ? 0 : isConstructor && isEnum ? 3 : 1; int paramIgnoreCount = isConstructor && isEnum ? 2 : isNonStaticInnerClassConstructor ? 1 : 0; return new AnnotationParamCollectingVisitor( stub, modList, localVarIgnoreCount, paramIgnoreCount, paramCount, paramStubs); }