@Override public void visitInnerClass( final String name, final String outerName, final String innerName, final int access) { if ((access & Opcodes.ACC_SYNTHETIC) != 0) return; if (!isCorrectName(innerName) || outerName == null) return; if ((getClassName(outerName) + "." + innerName).equals(myResult.getQualifiedName())) { // our result is inner class if (myParent instanceof PsiFileStub) { throw new OutOfOrderInnerClassException(); } } if (!getClassName(outerName).equals(myResult.getQualifiedName())) return; final T innerSource = myInnersStrategy.findInnerClass(innerName, mySource); if (innerSource == null) return; final ClassReader reader = myInnersStrategy.readerForInnerClass(innerSource); if (reader == null) return; final StubBuildingVisitor<T> classVisitor = new StubBuildingVisitor<T>(innerSource, myInnersStrategy, myResult, access, innerName); reader.accept(classVisitor, ClassReader.SKIP_FRAMES); }
private static String getPackageName(@NotNull PsiClassStub<?> result) { String fqn = result.getQualifiedName(); String shortName = result.getName(); return fqn == null || Comparing.equal(shortName, fqn) ? "" : fqn.substring(0, fqn.lastIndexOf('.')); }
@Override public void visitInnerClass( final String name, final String outerName, final String innerName, final int access) { if ((access & Opcodes.ACC_SYNTHETIC) != 0) return; if (!isCorrectName(innerName) || outerName == null) return; if ((getClassName(outerName) + "." + innerName).equals(myResult.getQualifiedName())) { // our result is inner class if (myParent instanceof PsiFileStub) { throw new OutOfOrderInnerClassException(); } } if (!namesEqual(outerName, myResult.getQualifiedName())) { return; } T innerClass = myInnersStrategy.findInnerClass(innerName, mySource); if (innerClass != null) { StubBuildingVisitor<T> visitor = new StubBuildingVisitor<T>(innerClass, myInnersStrategy, myResult, access, innerName); myInnersStrategy.accept(innerClass, visitor); } }
@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 @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); }