Example usage for org.eclipse.jdt.internal.compiler.lookup LocalTypeBinding anonymousOriginalSuperType

List of usage examples for org.eclipse.jdt.internal.compiler.lookup LocalTypeBinding anonymousOriginalSuperType

Introduction

In this page you can find the example usage for org.eclipse.jdt.internal.compiler.lookup LocalTypeBinding anonymousOriginalSuperType.

Prototype

public ReferenceBinding anonymousOriginalSuperType() 

Source Link

Usage

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;
        }
    };
}