📄 findunrelatedtypesingenericcontainer.java
字号:
// This basic block is probably dead continue; } Type operandType = frame.getTopValue(); if (operandType.equals(TopType.instance())) { // unreachable continue; } // Only consider generic... Type objectType = frame.getInstance(inv, cpg); if (!(objectType instanceof GenericObjectType)) continue; GenericObjectType operand = (GenericObjectType) objectType; // ... containers if (!operand.hasParameters()) continue; int numArguments = frame.getNumArguments(inv, cpg); if (numArguments <= 0 || argumentParameterIndex.length != numArguments) continue; // compare containers type parameters to corresponding arguments boolean match = true; IncompatibleTypes [] matches = new IncompatibleTypes [numArguments]; for (int i=0; i<numArguments; i++) matches[i] = IncompatibleTypes.SEEMS_OK; SignatureParser sigParser = new SignatureParser(inv.getSignature(cpg)); for (int ii=0; ii < numArguments; ii++) { if (argumentParameterIndex[ii] < 0) continue; // not relevant argument if (argumentParameterIndex[ii] >= operand.getNumParameters()) continue; // should never happen Type parmType = operand.getParameterAt(argumentParameterIndex[ii]); Type argType = frame.getArgument(inv, cpg, ii, sigParser); matches[ii] = compareTypes(parmType, argType); if (matches[ii] != IncompatibleTypes.SEEMS_OK) match = false; } if (match) continue; // no bug // Prepare bug report SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation .fromVisitedInstruction(classContext, methodGen, sourceFile, handle); // Report a bug that mentions each of the failed arguments in matches for (int i=0; i<numArguments; i++) { if (matches[i] == IncompatibleTypes.SEEMS_OK) continue; Type parmType = operand.getParameterAt(argumentParameterIndex[i]); if (parmType instanceof GenericObjectType) parmType = ((GenericObjectType)parmType).getUpperBound(); Type argType = frame.getArgument(inv, cpg, i, sigParser); accumulator.accumulateBug(new BugInstance(this, "GC_UNRELATED_TYPES", matches[i].getPriority()) .addClassAndMethod(methodGen, sourceFile) //.addString(GenericUtilities.getString(parmType)) //.addString(GenericUtilities.getString(argType)) .addFoundAndExpectedType(argType.getSignature(), parmType.getSignature()) .addCalledMethod(methodGen, (InvokeInstruction) ins) ,sourceLineAnnotation); } } accumulator.reportAccumulatedBugs(); } /** * Get a String triplet representing the information in this instruction: * the className, methodName, and methodSignature */ private String [] getInstructionTriplet(InvokeInstruction inv, ConstantPoolGen cpg) { // get the class name ConstantCP ref = (ConstantCP) cpg.getConstant( inv.getIndex() ); String className = ref.getClass(cpg.getConstantPool()); // get the method name ConstantNameAndType refNT = (ConstantNameAndType) cpg.getConstant( ref.getNameAndTypeIndex() ); String methodName = refNT.getName(cpg.getConstantPool()); // get the method signature String methodSignature = refNT.getSignature(cpg.getConstantPool()); return new String[] { className, methodName, methodSignature }; } /** * Given a triplet representing the className, methodName, and methodSignature * of an instruction, check to see if it is in our collectionsMap. <p> * [Not Implemented] If not, search harder to see if one of the super classes * of className is in our collectionMap */ private @CheckForNull String [] getRelevantTriplet(String [] instructionTriplet) { if (collectionsMap.containsKey( getCollectionsMapKey(instructionTriplet) )) return instructionTriplet; // HARDCODES // Map "get" and "remove" if (Arrays.asList(mapMembers).contains(instructionTriplet[0])) { if ( "get" .equals(instructionTriplet[1]) || "remove".equals(instructionTriplet[1]) ) { addToCollectionsMap(instructionTriplet[0], instructionTriplet[1], instructionTriplet[2], 0); return instructionTriplet; } } // XXX The rest not implemented // Not found return null; } /** * Compare to see if the argument <code>argType</code> passed to the method * matches the type of the corresponding parameter. The simplest case is when * both are equal. <p> * This is a conservative comparison - returns true if it cannot decide. * If the parameter type is a type variable (e.g. <code>T</code>) then we don't * know enough (yet) to decide if they do not match so return true. */ private IncompatibleTypes compareTypes(Type parmType, Type argType) { // XXX equality not implemented for GenericObjectType // if (parmType.equals(argType)) return true; // Compare type signatures instead String parmString = GenericUtilities.getString(parmType); String argString = GenericUtilities.getString(argType); if (parmString.equals(argString)) return IncompatibleTypes.SEEMS_OK; // if either type is java.lang.Object, then automatically true! // again compare strings... String objString = GenericUtilities.getString(Type.OBJECT); if ( parmString.equals(objString) || argString.equals(objString) ) { return IncompatibleTypes.SEEMS_OK; } // get a category for each type TypeCategory parmCat = GenericUtilities.getTypeCategory(parmType); TypeCategory argCat = GenericUtilities.getTypeCategory(argType); // -~- plain objects are easy if ( parmCat == TypeCategory.PLAIN_OBJECT_TYPE && argCat == TypeCategory.PLAIN_OBJECT_TYPE ) return IncompatibleTypes.getPriorityForAssumingCompatible(parmType, argType); // -~- parmType is: "? extends Another Type" OR "? super Another Type" if ( parmCat == TypeCategory.WILDCARD_EXTENDS || parmCat == TypeCategory.WILDCARD_SUPER ) return compareTypes( ((GenericObjectType)parmType).getExtension(), argType); // -~- Not handling type variables if ( parmCat == TypeCategory.TYPE_VARIABLE || argCat == TypeCategory.TYPE_VARIABLE ) return IncompatibleTypes.SEEMS_OK; // -~- Array Types: compare dimensions, then base type if ( parmCat == TypeCategory.ARRAY_TYPE && argCat == TypeCategory.ARRAY_TYPE ) { ArrayType parmArray = (ArrayType) parmType; ArrayType argArray = (ArrayType) argType; if (parmArray.getDimensions() != argArray.getDimensions()) return IncompatibleTypes.ARRAY_AND_NON_ARRAY; return compareTypes(parmArray.getBasicType(), argArray.getBasicType()); } // If one is an Array Type and the other is not, then they // are incompatible. (We already know neither is java.lang.Object) if ( parmCat == TypeCategory.ARRAY_TYPE ^ argCat == TypeCategory.ARRAY_TYPE ) { return IncompatibleTypes.ARRAY_AND_NON_ARRAY; } // -~- Parameter Types: compare base type then parameters if ( parmCat == TypeCategory.PARAMETERS && argCat == TypeCategory.PARAMETERS ) { GenericObjectType parmGeneric = (GenericObjectType) parmType; GenericObjectType argGeneric = (GenericObjectType) argType; // base types should be related return compareTypes( parmGeneric.getObjectType(), argGeneric.getObjectType()); // XXX More to come } // If one is a Parameter Type and the other is not, then they // are incompatible. (We already know neither is java.lang.Object) if (false) { // not true. Consider class Foo extends ArrayList<String> if ( parmCat == TypeCategory.PARAMETERS ^ argCat == TypeCategory.PARAMETERS ) { return IncompatibleTypes.SEEMS_OK; // fix this when we know what we are doing here } } // -~- Wildcard e.g. List<*>.contains(...) if (parmCat == TypeCategory.WILDCARD) // No Way to know return IncompatibleTypes.SEEMS_OK; // -~- Non Reference types // if ( parmCat == TypeCategory.NON_REFERENCE_TYPE || // argCat == TypeCategory.NON_REFERENCE_TYPE ) if (parmType instanceof BasicType || argType instanceof BasicType) { // this should not be possible, compiler will complain (pre 1.5) // or autobox primitive types (1.5 +) throw new IllegalArgumentException("checking for compatibility of " + parmType + " with " + argType); } return IncompatibleTypes.SEEMS_OK; } // old version of compare types private boolean compareTypesOld(Type parmType, Type argType) { // XXX equality not implemented for GenericObjectType // if (parmType.equals(argType)) return true; // Compare type signatures instead if (GenericUtilities.getString(parmType) .equals(GenericUtilities.getString(argType))) return true; if (parmType instanceof GenericObjectType) { GenericObjectType o = (GenericObjectType) parmType; if (o.getTypeCategory() == GenericUtilities.TypeCategory.WILDCARD_EXTENDS) { return compareTypesOld(o.getExtension(), argType); } } // ignore type variables for now if (parmType instanceof GenericObjectType && !((GenericObjectType) parmType).hasParameters()) return true; if (argType instanceof GenericObjectType && !((GenericObjectType) argType).hasParameters()) return true; // Case: Both are generic containers if (parmType instanceof GenericObjectType && argType instanceof GenericObjectType) { return true; } else { // Don't consider non reference types (should not be possible) if (!(parmType instanceof ReferenceType && argType instanceof ReferenceType)) return true; // Don't consider non object types (for now) if (!(parmType instanceof ObjectType && argType instanceof ObjectType)) return true; // Otherwise, compare base types ignoring generic information try { return Repository.instanceOf( ((ObjectType)argType).getClassName(), ((ObjectType)parmType).getClassName()); } catch (ClassNotFoundException e) {} } return true; } /** * Empty * @see edu.umd.cs.findbugs.Detector#report() */ public void report() { }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -