如何用PMD的XPath查找Java中的二元运算符重复表达式
用PMD检测Java中的二元运算符重复公共子表达式
需求说明
我需要用PMD查找Java代码中如下形式的公共子表达式:
z = a +b; q = a +b;
我知道CPD可以处理这类场景,但它会返回文件中匹配的复制函数等内容,我只想定位与二元运算符关联的重复表达式。
AST结构分析
分析示例代码z = a + b时,对应的BlockStatement结构如下:
└─ BlockStatement └─ Statement └─ StatementExpression ├─ PrimaryExpression │ └─ PrimaryPrefix // z │ └─ Name ├─ AssignmentOperator └─ Expression └─ AdditiveExpression // + ├─ PrimaryExpression │ └─ PrimaryPrefix // a │ └─ Name └─ PrimaryExpression └─ PrimaryPrefix // b └─ Name
问题与尝试
我知道需要检查某个AdditiveExpression在方法中是否出现多次,但无法实现。目前有个疑惑:判定重复时,是需要比较表达式的全部三个部分,还是只需比较内部的AdditiveExpression节点即可?
我尝试过的错误XPath写法:
//AdditiveExpression[count(.) > 0] //AdditiveExpression[.=../../../../BlockStatement/Statement/StatementExpression/Expression]/AdditiveExpression]
补充示例
Java代码示例
public class Example{ public static void main(final String[] args){ int i = 5; int k = 10; int z,h; z = i + k; h = i + k; } }
对应的AST XML
<?xml version='1.0' encoding='UTF-8' ?> <CompilationUnit Image='' PackageName='' declarationsAreInDefaultPackage='true'> <TypeDeclaration Image=''> <ClassOrInterfaceDeclaration Abstract='false' BinaryName='Example' Default='false' Final='false' Image='Example' Interface='false' Local='false' Modifiers='1' Native='false' Nested='false' NonSealed='false' PackagePrivate='false' Private='false' Protected='false' Public='true' Sealed='false' SimpleName='Example' Static='false' Strictfp='false' Synchronized='false' Transient='false' TypeKind='CLASS' Volatile='false'> <ClassOrInterfaceBody AnonymousInnerClass='false' EnumChild='false' Image=''> <ClassOrInterfaceBodyDeclaration AnonymousInnerClass='false' EnumChild='false' Image='' Kind='METHOD'> <MethodDeclaration Abstract='false' Arity='1' Default='false' Final='false' Image='' InterfaceMember='false' Kind='METHOD' MethodName='main' Modifiers='17' Name='main' Native='false' PackagePrivate='false' Private='false' Protected='false' Public='true' Static='true' Strictfp='false' Synchronized='false' SyntacticallyAbstract='false' SyntacticallyPublic='true' Transient='false' Void='true' Volatile='false'> <ResultType Image='' Void='true' returnsArray='false' /> <MethodDeclarator Image='main' ParameterCount='1'> <FormalParameters Image='' ParameterCount='1' Size='1'> <FormalParameter Abstract='false' Array='true' ArrayDepth='1' Default='false' ExplicitReceiverParameter='false' Final='true' Image='' Modifiers='32' Native='false' PackagePrivate='true' Private='false' Protected='false' Public='false' Static='false' Strictfp='false' Synchronized='false' Transient='false' TypeInferred='false' Varargs='false' Volatile='false'> <Type Array='true' ArrayDepth='1' ArrayType='true' Image='' TypeImage='String'> <ReferenceType Array='true' ArrayDepth='1' Image=''> <ClassOrInterfaceType AnonymousClass='false' Array='true' ArrayDepth='1' Image='String' ReferenceToClassSameCompilationUnit='false' /> </ReferenceType> </Type> <VariableDeclaratorId Array='false' ArrayDepth='0' ArrayType='true' ExceptionBlockParameter='false' ExplicitReceiverParameter='false' Field='false' Final='true' ForeachVariable='false' FormalParameter='true' Image='args' LambdaParameter='false' LocalVariable='false' Name='args' PatternBinding='false' ResourceDeclaration='false' TypeInferred='false' VariableName='args' /> </FormalParameter> </FormalParameters> </MethodDeclarator> <Block Image='' containsComment='false'> <BlockStatement Allocation='false' Image=''> <LocalVariableDeclaration Abstract='false' Array='false' ArrayDepth='0' Default='false' Final='false' Image='' Modifiers='0' Native='false' PackagePrivate='true' Private='false' Protected='false' Public='false' Static='false' Strictfp='false' Synchronized='false' Transient='false' TypeInferred='false' VariableName='i' Volatile='false'> <Type Array='false' ArrayDepth='0' ArrayType='false' Image='' TypeImage='int'> <PrimitiveType Array='false' ArrayDepth='0' Boolean='false' Image='int' /> </Type> <VariableDeclarator Image='' Initializer='true' Name='i'> <VariableDeclaratorId Array='false' ArrayDepth='0' ArrayType='false' ExceptionBlockParameter='false' ExplicitReceiverParameter='false' Field='false' Final='false' ForeachVariable='false' FormalParameter='false' Image='i' LambdaParameter='false' LocalVariable='true' Name='i' PatternBinding='false' ResourceDeclaration='false' TypeInferred='false' VariableName='i' /> <VariableInitializer Image=''> <Expression Image='' StandAlonePrimitive='true'> <PrimaryExpression Image=''> <PrimaryPrefix Image='' SuperModifier='false' ThisModifier='false'> <Literal CharLiteral='false' DoubleLiteral='false' EscapedStringLiteral='5' FloatLiteral='false' Image='5' IntLiteral='true' LongLiteral='false' SingleCharacterStringLiteral='false' StringLiteral='false' TextBlock='false' TextBlockContent='5' ValueAsDouble='NaN' ValueAsFloat='NaN' ValueAsInt='5' ValueAsLong='5' /> </PrimaryPrefix> </PrimaryExpression> </Expression> </VariableInitializer> </VariableDeclarator> </LocalVariableDeclaration> </BlockStatement> <BlockStatement Allocation='false' Image=''> <LocalVariableDeclaration Abstract='false' Array='false' ArrayDepth='0' Default='false' Final='false' Image='' Modifiers='0' Native='false' PackagePrivate='true' Private='false' Protected='false' Public='false' Static='false' Strictfp='false' Synchronized='false' Transient='false' TypeInferred='false' VariableName='k' Volatile='false'> <Type Array='false' ArrayDepth='0' ArrayType='false' Image='' TypeImage='int'> <PrimitiveType Array='false' ArrayDepth='0' Boolean='false' Image='int' /> </Type> <VariableDeclarator Image='' Initializer='true' Name='k'> <VariableDeclaratorId Array='false' ArrayDepth='0' ArrayType='false' ExceptionBlockParameter='false' ExplicitReceiverParameter='false' Field='false' Final='false' ForeachVariable='false' FormalParameter='false' Image='k' LambdaParameter='false' LocalVariable='true' Name='k' PatternBinding='false' ResourceDeclaration='false' TypeInferred='false' VariableName='k' /> <VariableInitializer Image=''> <Expression Image='' StandAlonePrimitive='true'> <PrimaryExpression Image=''> <PrimaryPrefix Image='' SuperModifier='false' ThisModifier='false'> <Literal CharLiteral='false' DoubleLiteral='false' EscapedStringLiteral='10' FloatLiteral='false' Image='10' IntLiteral='true' LongLiteral='false' SingleCharacterStringLiteral='false' StringLiteral='false' TextBlock='false' TextBlockContent='10' ValueAsDouble='NaN' ValueAsFloat='NaN' ValueAsInt='10' ValueAsLong='10' /> </PrimaryPrefix> </PrimaryExpression> </Expression> </VariableInitializer> </VariableDeclarator> </LocalVariableDeclaration> </BlockStatement> <BlockStatement Allocation='false' Image=''> <LocalVariableDeclaration Abstract='false' Array='false' ArrayDepth='0' Default='false' Final='false' Image='' Modifiers='0' Native='false' PackagePrivate='true' Private='false' Protected='false' Public='false' Static='false' Strictfp='false' Synchronized='false' Transient='false' TypeInferred='false' VariableName='z' Volatile='false'> <Type Array='false' ArrayDepth='0' ArrayType='false' Image='' TypeImage='int'> <PrimitiveType Array='false' ArrayDepth='0' Boolean='false' Image='int' /> </Type> <VariableDeclarator Image='' Initializer='false' Name='z'> <VariableDeclaratorId Array='false' ArrayDepth='0' ArrayType='false' ExceptionBlockParameter='false' ExplicitReceiverParameter='false' Field='false' Final='false' ForeachVariable='false' FormalParameter='false' Image='z' LambdaParameter='false' LocalVariable='true' Name='z' PatternBinding='false' ResourceDeclaration='false' TypeInferred='false' VariableName='z' /> </VariableDeclarator> <VariableDeclarator Image='' Initializer='false' Name='h'> <VariableDeclaratorId Array='false' ArrayDepth='0' ArrayType='false' ExceptionBlockParameter='false' ExplicitReceiverParameter='false' Field='false' Final='false' ForeachVariable='false' FormalParameter='false' Image='h' LambdaParameter='false' LocalVariable='true' Name='h' PatternBinding='false' ResourceDeclaration='false' TypeInferred='false' VariableName='h' /> </VariableDeclarator> </LocalVariableDeclaration> </BlockStatement> <BlockStatement Allocation='false' Image=''> <Statement Image=''> <StatementExpression Image=''> <PrimaryExpression Image=''> <PrimaryPrefix Image='' SuperModifier='false' ThisModifier='false'> <Name Image='z' /> </PrimaryPrefix> </PrimaryExpression> <AssignmentOperator Compound='false' Image='=' /> <Expression Image='' StandAlonePrimitive='false'> <AdditiveExpression Image='+' Operator='+'> <PrimaryExpression Image=''> <PrimaryPrefix Image='' SuperModifier='false' ThisModifier='false'> <Name Image='i' /> </PrimaryPrefix> </PrimaryExpression> <PrimaryExpression Image=''> <PrimaryPrefix Image='' SuperModifier='false' ThisModifier='false'> <Name Image='k' /> </PrimaryPrefix> </PrimaryExpression> </AdditiveExpression> </Expression> </StatementExpression> </Statement> </BlockStatement> <BlockStatement Allocation='false' Image=''> <Statement Image=''> <StatementExpression Image=''> <PrimaryExpression Image=''> <PrimaryPrefix Image='' SuperModifier='false' ThisModifier='false'> <Name Image='h' /> </PrimaryPrefix> </PrimaryExpression> <AssignmentOperator Compound='false' Image='=' /> <Expression Image='' StandAlonePrimitive='false'> <AdditiveExpression Image='+' Operator='+'> <PrimaryExpression Image=''> <PrimaryPrefix Image='' SuperModifier='false' ThisModifier='false'> <Name Image='i' /> </PrimaryPrefix> </PrimaryExpression> <PrimaryExpression Image=''> <PrimaryPrefix Image='' SuperModifier='false' ThisModifier='false'> <Name Image='k' /> </PrimaryPrefix> </PrimaryExpression> </AdditiveExpression> </Expression> </StatementExpression> </Statement> </BlockStatement> </Block> </MethodDeclaration> </ClassOrInterfaceBodyDeclaration> </ClassOrInterfaceBody> </ClassOrInterfaceDeclaration> </TypeDeclaration> </CompilationUnit>
内容的提问来源于stack exchange,提问作者Laschoking
相关产品推荐
相关产品推荐

