2016-06-12 1 views
0

Я разрабатываю статический анализ Java-байт-кода с использованием рамки OPAL.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-блок в отдельный метод, эти сообщения об ошибках сделали n ot происходят. Изменения этих линий к

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

Смежные вопросы