在我的實驗中,看起來當跨多個XExpression塊存在一系列依賴關係時,XText無法解析變量類型。類型推斷中的XText鏈式依賴關係
一個簡單的例子,說明。我有一個語法:
grammar eg.types.inference.TypeInferenceExample with org.eclipse.xtext.xbase.Xbase
generate typeInferenceExample "example.org/types/inference/TypeInferenceExample"
Model:
blocks += Block*
;
Block:
'{'
'name' ':' name=QualifiedName
'from' ':' ('none' | from=[Block|QualifiedName])
'block' ':' expression=XBlockExpression
'}'
;
接口:
package eg.lib;
public interface IModelBlock {
public void push(org.eclipse.xtext.xbase.lib.Pair<String, ?> toPush);
}
並有JvmModelInferrer:
package eg.types.inference.jvmmodel
import com.google.inject.Inject
import eg.lib.IModelBlock
import eg.types.inference.typeInferenceExample.Block
import eg.types.inference.typeInferenceExample.Model
import org.eclipse.xtext.xbase.XBinaryOperation
import org.eclipse.xtext.xbase.XExpression
import org.eclipse.xtext.xbase.XFeatureCall
import org.eclipse.xtext.xbase.XStringLiteral
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
class TypeInferenceExampleJvmModelInferrer extends AbstractModelInferrer {
@Inject extension JvmTypesBuilder
def dispatch void infer(Model model, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
model.blocks.forEach [block |
acceptor.accept(block.toClass(block.name)).initializeLater [
superTypes += block.newTypeRef(typeof(IModelBlock))
members += block.toMethod("invoke", newTypeRef(Void::TYPE)) [
if (block.from != null) {
block.from.pushType.forEach [p |
parameters += block.toParameter(p.key, p.value)
]
}
body = block.expression
]
]
]
}
def private pushType(Block block) {
return block.eAllContents.filter[ // List of push calls in this Block
it instanceof XFeatureCall && (it as XFeatureCall).concreteSyntaxFeatureName.equals("push")
].map [
val call = it as XFeatureCall
// Add entry for push call as an OutputDeclaration
return call.featureCallArguments.map[
if (!(it instanceof XBinaryOperation)) {
throw new RuntimeException("Must push using -> operator")
}
val key = (it as XBinaryOperation).leftOperand
val value = (it as XBinaryOperation).rightOperand
return key.name -> value.inferredType
]
].head
}
def private String name(XExpression literal) {
if (!(literal instanceof XStringLiteral)) {
throw new UnsupportedOperationException("Literal was not a string literal")
}
return (literal as XStringLiteral).value
}
}
當我創建一個簡單的例子,這種DSL,如:
{
name : BlockOne
from : none
block : {
val i = 42 * 3.6
push("index" -> i)
}
}
{
name : BlockTwo
from : BlockOne
block : {
val res = "Another Value from " + index
push("result" -> res)
}
}
代碼生成得很好(type inferenc e成功地生成了輸出Java中的index
和res
的類型)。我正在使用調用中的對來推斷調用方法中的接口BlockTwo
。這push
方法來自上面的IModelBlock
接口。如果我的第三塊添加到本實施例中,因此:
{
name : BlockThree
from : BlockTwo
block : {
val out = "This one came from: " + result
push("out" -> out)
}
}
推理失敗,與UnsupportedOperationException: TODO: import a functional handle on the type resolution that delegates to the best available (current, but evolving) result
(從OnChangeEvictingCache.execWithoutCacheClear
,CachingBatchTypeResolver.resolveTypes
)。
是否有一些其他技術我應該用來派生變量類型的鏈接依賴像這樣在XText中?
感謝您的幫助!
我剛剛嘗試使用XText 2.5.0(根據文檔R201312110906),它拋出了相同的異常。我是否缺少更新網站? – 2013-12-27 15:50:17