List of usage examples for org.eclipse.jdt.internal.compiler.lookup LocalTypeBinding anonymousOriginalSuperType
public ReferenceBinding anonymousOriginalSuperType()
From source file:org.eclipselabs.nullness.NullnessAssertionInserter.java
License:Open Source License
@Override public MethodVisitor visitMethod(final int access, final String name, String desc, String signature, String[] exceptions) {/*w w w . j a v a 2 s . c o m*/ MethodVisitor methodVisitor = cv.visitMethod(access, name, desc, signature, exceptions); if ((access & ACC_SYNTHETIC) != 0) { return methodVisitor; } IMethodBinding methodBinding = findMethod(name, desc); if (methodBinding != null && isEffectivelySynthetic(methodBinding)) { return methodVisitor; } final Type[] args = Type.getArgumentTypes(desc); // null == undefined, false == nullable, true == non-null final Boolean[] nonNullParameters = methodBinding != null ? new Boolean[methodBinding.getParameterTypes().length] : new Boolean[0]; final Boolean[] returnTypeNonNull = new Boolean[1]; if (methodBinding != null) { for (int i = 0; i < nonNullParameters.length; i++) { nonNullParameters[i] = annotationFinder.getEffectiveNonNullState(methodBinding, methodBinding.getParameterAnnotations(i), defaultNonNullState); } returnTypeNonNull[0] = annotationFinder.getEffectiveNonNullState(methodBinding, defaultNonNullState); } final boolean hasNonNullParameter = hasNonNullParameter(nonNullParameters); final String[] parameterNames = hasNonNullParameter ? getParameterNames(methodBinding) : null; return new MethodAdapter(methodVisitor) { private Label startGeneratedCodeLabel; @Override public void visitCode() { if (hasNonNullParameter) { startGeneratedCodeLabel = new Label(); mv.visitLabel(startGeneratedCodeLabel); for (int param = 0; param < nonNullParameters.length; param++) { if (Boolean.TRUE.equals(nonNullParameters[param])) { int var = ((access & ACC_STATIC) == 0) ? 1 : 0; // adjust for things like enums constructors and // non-static inner class constructors int offset = args.length - nonNullParameters.length; for (int i = 0; i < param + offset; ++i) { var += args[i].getSize(); } mv.visitVarInsn(ALOAD, var); Label end = new Label(); mv.visitJumpInsn(IFNONNULL, end); throwStatement(ILLEGAL_ARGUMENT_EXCEPTION, String.format( "Argument for non-null parameter %s at index %d of %s#%s must not be null", parameterNames[param], param, getTypeName(), name), end); } } } } protected String getTypeName() { String result = typeBinding.getName(); if (result != null && result.length() > 0) { return result; } if (typeBinding.isLocal()) { LocalTypeBinding localType = Bindings.getInternalBinding(typeBinding); return "anonymous " + String.valueOf(localType.anonymousOriginalSuperType().shortReadableName()); } return result; } @Override public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { boolean isStatic = (access & ACC_STATIC) != 0; boolean isParameter = isStatic ? index < args.length : index <= args.length; mv.visitLocalVariable(name, desc, signature, (isParameter && startGeneratedCodeLabel != null) ? startGeneratedCodeLabel : start, end, index); } @Override public void visitInsn(int opcode) { if (opcode == ARETURN) { if (Boolean.TRUE.equals(returnTypeNonNull[0])) { mv.visitInsn(DUP); Label skipLabel = new Label(); mv.visitJumpInsn(IFNONNULL, skipLabel); throwStatement(ILLEGAL_STATE_EXCEPTION, String.format("Non-null method %s#%s must not return null", getTypeName(), name), skipLabel); } } mv.visitInsn(opcode); } @Override public void visitVarInsn(final int opcode, final int var) { if (opcode == ASTORE) { if (hasNonNullParameter) { int parameterIdx = toParameterIndex(var); if (parameterIdx >= 0 && Boolean.TRUE.equals(nonNullParameters[parameterIdx])) { mv.visitInsn(DUP); Label end = new Label(); mv.visitJumpInsn(IFNONNULL, end); // not quite sure about the concrete exception type // but ISE should do for now. throwStatement(ILLEGAL_STATE_EXCEPTION, String.format( "Value for non-null parameter %s at index %d of %s#%s must not be reassigned to null", parameterNames[parameterIdx], parameterIdx, getTypeName(), name), end); } } } super.visitVarInsn(opcode, var); } protected int toParameterIndex(int var) { boolean isStatic = ((access & ACC_STATIC) != 0); if (!isStatic && var == 0) { return -1; } int parameterIdx = 0; for (int i = 0; i < args.length; ++i) { parameterIdx += args[i].getSize(); if (parameterIdx == var) { parameterIdx = i - (args.length - nonNullParameters.length); return parameterIdx; } } return -1; } @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { if (opcode == PUTFIELD || opcode == PUTSTATIC) { Boolean nullState = fieldCache.getEffectiveNonNullState(owner, name); if (Boolean.TRUE.equals(nullState)) { mv.visitInsn(DUP); Label skipLabel = new Label(); mv.visitJumpInsn(IFNONNULL, skipLabel); Label label = new Label(); mv.visitLabel(label); throwStatement(ILLEGAL_STATE_EXCEPTION, String.format("Non-null field %s#%s must not be set to null", owner, name), skipLabel); } } mv.visitFieldInsn(opcode, owner, name, desc); } private void throwStatement(String exceptionType, String message, Label label) { Type stringType = Type.getType(String.class); String descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { stringType }); mv.visitTypeInsn(NEW, exceptionType); mv.visitInsn(DUP); mv.visitLdcInsn(message); mv.visitMethodInsn(INVOKESPECIAL, exceptionType, CONSTRUCTOR, descriptor); mv.visitInsn(ATHROW); mv.visitLabel(label); checkInserted = true; } }; }