2016-06-12 5 views
0

私はOPALフレームワークを使ってJavaバイトコードの静的解析を開発しています。OPAL:コードをメソッドに外部化した後にSingleOriginReferenceが見つからないのはなぜですか?

現在、コードの構造を変更して機能を追加する必要があります。

:私は別のメソッドに最後の場合は、大きなブロックを外部化理由です

def singleCallUpperTypeBounds(
    caller: Method, 
    pc: Int, 
    calleeDescriptor: MethodDescriptor, 
    project: Project[URL], 
    callGraph: CallGraph, 
    propertyStore: PropertyStore): Iterable[(Int, Set[FieldType])] = { 
    val classFile = project.classFile(caller) 
    val callDescriptor = caller.body.get.instructions(pc) match { 
    case INVOKEVIRTUAL(_, _, d) ⇒ d 
    case INVOKESPECIAL(_, _, d) ⇒ d 
    case INVOKESTATIC(_, _, d) ⇒ d 
    case INVOKEINTERFACE(_, _, d) ⇒ d 
    } 
    val analysisResult = if (!notClientCallable(caller, propertyStore) || worklist.contains(caller)) 
    BaseAI.perform(classFile, caller, new DefaultDomain(project, classFile, caller))(None) 
    else { 
    val callerTypeMap = intermediateResult.getOrElse(caller, { 
     worklist = worklist.+:(caller) 
     val result = singleMethodUpperTypeBounds(caller, project, callGraph, propertyStore) 
     worklist = worklist.diff(Seq(caller)) 
     result 
    }) 
    //Create all combinations of the upper type bounds of the parameters. 
    //If a parameter is not in the TypeMap, 
    //e.g. because it is a primitive value, add it as a one element set. 
    val typeCombinations = allCombinations(caller.descriptor.parameterTypes.zipWithIndex.map { 
     case (t, index) => 
     callerTypeMap.getOrElse(index, 
      Set[FieldType](caller.descriptor.parameterTypes(index))) 
    }) 
    println(typeCombinations) 
    //TODO Use the type combinations 
    BaseAI.perform(classFile, caller, new DefaultDomain(project, classFile, caller))(None) 
    } 
    if (analysisResult.evaluatedInstructions.contains(pc)) 
    for { 
     parameterIndex ← callDescriptor.parameterTypes.zipWithIndex.collect { 
     //we are not interested in primitive array types 
     case (t: ReferenceType, index) if { 
      //may be the case for sinature polymorphic methods 
      if (index >= calleeDescriptor.parametersCount) { 
      true 
      } else { 
      val expectedType = calleeDescriptor.parameterType(index) 
      !(expectedType.isArrayType && expectedType.asArrayType.elementType.isBaseType) 
      } 
     } ⇒ index 
     } 
     compileTimeType = callDescriptor.parameterType(parameterIndex) 
     stackIndex = (callDescriptor.parametersCount - 1) - parameterIndex 
    } yield { 
     val operand = analysisResult.operandsArray(pc)(stackIndex) 
     val runTimeTypes: Set[FieldType] = operand match { 
     case v: analysisResult.domain.SingleOriginReferenceValue ⇒ 
      v.upperTypeBound.foldLeft(Set[FieldType]())((set, t) ⇒ set + t) 
     case analysisResult.domain.MultipleReferenceValues(singleOriginReferenceValues) ⇒ 
      singleOriginReferenceValues.foldLeft(Set[FieldType]())((set, sorv) ⇒ set ++ 
      sorv.upperTypeBound.foldLeft(Set[FieldType]())((s, t) ⇒ s + t)) 
     } 
     (parameterIndex, runTimeTypes) 
    } 
    //If the call was not evaluated, it is on a dead path. So ignore this call. 
    else { 
    Set[(Int, Set[FieldType])]() 
    } 
} 

これは私が別の方法に一部を外部化するために持っているのは大きな方法、発祥しました何らかの理由で

def evaluateAIResult(
    analysisResult: AIResult, 
    pc: Int, 
    calleeDescriptor: MethodDescriptor, 
    callDescriptor: MethodDescriptor): Iterable[(Int, Set[FieldType])] = { 
    if (analysisResult.evaluatedInstructions.contains(pc)) 
    for { 
     parameterIndex ← callDescriptor.parameterTypes.zipWithIndex.collect { 
     //we are not interested in primitive array types 
     case (t: ReferenceType, index) if { 
      //may be the case for sinature polymorphic methods 
      if (index >= calleeDescriptor.parametersCount) { 
      true 
      } else { 
      val expectedType = calleeDescriptor.parameterType(index) 
      !(expectedType.isArrayType && expectedType.asArrayType.elementType.isBaseType) 
      } 
     } ⇒ index 
     } 
     compileTimeType = callDescriptor.parameterType(parameterIndex) 
     stackIndex = (callDescriptor.parametersCount - 1) - parameterIndex 
    } yield { 
     val operand = analysisResult.operandsArray(pc)(stackIndex) 
     val runTimeTypes: Set[FieldType] = operand match { 
     case v: analysisResult.domain.SingleOriginReferenceValue ⇒ 
      v.upperTypeBound.foldLeft(Set[FieldType]())((set, t) ⇒ set + t) 
     case analysisResult.domain.MultipleReferenceValues(singleOriginReferenceValues) ⇒ 
      singleOriginReferenceValues.foldLeft(Set[FieldType]())((set, sorv) ⇒ set ++ 
      sorv.upperTypeBound.foldLeft(Set[FieldType]())((s, t) ⇒ s + t)) 
     } 
     (parameterIndex, runTimeTypes) 
    } 
    //If the call was not evaluated, it is on a dead path. So ignore this call. 
    else { 
    Set[(Int, Set[FieldType])]() 
    } 
} 

、私は今のScala IDEでこれらの行のため若干の誤差が出る:

case v: analysisResult.domain.SingleOriginReferenceValue ⇒ 
      v.upperTypeBound.foldLeft(Set[FieldType]())((set, t) ⇒ set + t) 
case analysisResult.domain.MultipleReferenceValues(singleOriginReferenceValues) ⇒ 
      singleOriginReferenceValues.foldLeft(Set[FieldType]())((set, sorv) ⇒ set ++ 
      sorv.upperTypeBound.foldLeft(Set[FieldType]())((s, t) ⇒ s + t)) 

のエラーメッセージは以下の通りである:

型SingleOriginReferenceValueがorg.opalj.ai.Domain

の部材と

値MultipleReferenceValuesない組織のメンバーではありません。 opalj.ai.Domain

このif-blockを個別のメソッドに外部化する前に、これらのエラーメッセージはn起こる。

case v: SingleOriginReferenceValue ⇒ 
      v.upperTypeBound.foldLeft(Set[FieldType]())((set, t) ⇒ set + t) 
case MultipleReferenceValues(singleOriginReferenceValues) ⇒ 
      singleOriginReferenceValues.foldLeft(Set[FieldType]())((set, sorv) ⇒ set ++ 
      sorv.upperTypeBound.foldLeft(Set[FieldType]())((s, t) ⇒ s + t)) 

にこれらの行を変更し、輸入に 輸入org.opalj.ai.domain.l1.ReferenceValues.SingleOriginReferenceValue 輸入org.opalj.ai.domain.l1.ReferenceValues.MultipleReferenceValues をやって もありません助けて。

誰も私に教えてください、ここで何がうまくいかないのですか?

答えて

2

この場合、特定のタイプのドメインを持つAIResultを(ヘルパーのために)指定する必要があります。 (OPAL-AIは、いわゆるパス依存型の多用する。)

ヘルパーメソッドのシグネチャの以下の変更が助けるべきである:

def evaluateAIResult(
    analysisResult: AIResult { val domain: l1.DefaultDomain /*or whatever your domain requirements are*/}, 
    pc: Int, 
    calleeDescriptor: MethodDescriptor, 
    callDescriptor: MethodDescriptor): Iterable[(Int, Set[FieldType])] = {... 
+0

が、これは私のために働いた、ありがとうございます。しかし、私はDefaultDomainをDefaultDomain [URL]に変更しなければなりませんでした。 – mariotrageser

関連する問題