我想使用 PMD 来查找形式的 Common Subexpression
z = a +b;
q = a +b;
Java代码。
我知道 CPD 工具存在用于此类事情,但我也会收到复制的函数等,这些文件在文件中有匹配项。我只想找到与二元运算符相关的重复表达式。
在分析一个小代码示例时
z = a + b
每个BlockStatement出现以下结构:
└─ BlockStatement
└─ Statement
└─ StatementExpression
├─ PrimaryExpression
│ └─ PrimaryPrefix // z
│ └─ Name
├─ AssignmentOperator
└─ Expression
└─ AdditiveExpression // +
├─ PrimaryExpression
│ └─ PrimaryPrefix // a
│ └─ Name
└─ PrimaryExpression
└─ PrimaryPrefix // b
└─ Name
我知道我必须以某种方式检查 AdditiveExpression 的计数是否在我的方法中出现不止一次,因为我无法让它工作。 我缺乏理解的一个方面是,我是否需要比较表达式的所有 3 个部分,或者我是否可以比较内部节点 AdditiveExpression 因为从那里开始重复的表达式是相同的。
错误的做法:
//AdditiveExpression[count(.) > 0]
//AdditiveExpression[.=../../../../BlockStatement/Statement/StatementExpression/Expression]/AdditiveExpression]
编辑 1:为以下 java 示例添加 XML 文件:
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;
}
}
<?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>
在 XPath 2 中,您没有版本 3 中可用的方便的
deep-equal
函数,该函数允许您在单个函数调用中比较两个 AdditiveExpression
元素及其所有后代。这种缺乏意味着你必须写一些更冗长的东西,但你可能会逃避这样的事情:
for $e1 in //AdditiveExpression return
$e1[
some $e2 in (//AdditiveExpression except $e1) satisfies
$e1/@Image = $e2/@Image and
$e1/PrimaryExpression[1]/PrimaryPrefix/Name/@Image =
$e2/PrimaryExpression[1]/PrimaryPrefix/Name/@Image and
$e1/PrimaryExpression[2]/PrimaryPrefix/Name/@Image =
$e2/PrimaryExpression[2]/PrimaryPrefix/Name/@Image
]
这个 XPath 2 表达式构造了一系列被认为具有重复项的元素,如下所示:
对于
$e1
元素集合中的每个表达式('AdditiiveExpression
'),如果谓词中的标准($e1
... [
)的计算结果为]
,则返回true
,即,还有一些其他表达式 ('$e2
'),它也是 AdditiveExpression
元素之一但不是 $e1
,并且具有与 Image
表达式相同的 $e1
属性,并且其子元素有 Image
属性匹配 $e1
. 的相应子元素
我不确定将您的两个表达式视为重复项的重要标准是什么;我没有从字面上比较每个属性等,但这应该给你一个想法。