简体   繁体   English

在Xtend循环中使用唯一的变量名(代码生成)

[英]Using unique variable names in Xtend loop (Code Generation)

I've created a custom DSL with Xtext which is useful to describe hierarchies (fixed height of 2 in this example). 我用Xtext创建了一个自定义DSL,它对于描述层次结构很有用(在此示例中,高度固定为2)。 Want I want to do now is to generate a simple Java Swing App that can display such an hierarchy using a JTree. 我现在想做的就是生成一个简单的Java Swing应用程序,该应用程序可以使用JTree显示这样的层次结构。 I did this by extending the code generation example from Xtext, using Xtend. 我通过使用Xtend扩展了Xtext的代码生成示例来做到这一点。 Everything works fine, but could be done better. 一切正常,但可以做得更好。

The part of my template which is quite ugly so far: 到目前为止,我模板的这一部分还很难看:

def compile(Level a) '''
    DefaultMutableTreeNode «a.name» = new DefaultMutableTreeNode("«a.name»");
    «FOR b:a.sublevels»
      DefaultMutableTreeNode «b.name» = new DefaultMutableTreeNode("«b.name»");
      «a.name».add(«b.name»);
    «ENDFOR»
'''

As you can see, I use the names of the entities defined by users of the DSL as variable names for the code generation, which is bad. 如您所见,我将DSL用户定义的实体名称用作代码生成的变量名称,这很不好。 If a user chooses a name that is not a valid variable name in Java, the application won't compile later on. 如果用户选择的名称不是Java中有效的变量名,则该应用程序以后将无法编译。

The reason I did this is because when creating the JTree and its Nodes, I need unique variable names. 我这样做的原因是因为在创建JTree及其节点时,我需要唯一的变量名。 The generated code looks something like this: 生成的代码如下所示:

DefaultMutableTreeNode a = new DefaultMutableTreeNode("a");
DefaultMutableTreeNode a1 = new DefaultMutableTreeNode("a1");
a.add(a1);
DefaultMutableTreeNode a2 = new DefaultMutableTreeNode("a2");
a.add(a2);
DefaultMutableTreeNode a3 = new DefaultMutableTreeNode("a2");
a.add(a3);
...

Since everything is in the same scope, the variable names need to be different - a, a1, a2 and a3 this case. 由于所有内容都在同一范围内,因此变量名称必须不同-这种情况下的a,a1,a2和a3。 But how could I create valid unique variable names instead of using the input from users (which could be invalid)? 但是,如何创建有效的唯一变量名称而不是使用用户的输入(可能无效)? Any help is appreciated, thanks. 任何帮助表示赞赏,谢谢。

You need artificial variable names for the nodes and a counter variable. 您需要节点的人工变量名称和计数器变量。 The easiest way is to add that as a field to your generator and reset it before calling the compile method. 最简单的方法是将其作为字段添加到生成器中,并在调用compile方法之前将其重置。

int count

def compile(Level a) {
    count = 0
    return compile(a, -1)
}   

def compile(Level a, int parentCount) {
  var aCount = count++
  return '''
    DefaultMutableTreeNode node«aCount» = new DefaultMutableTreeNode("«a.name»");
    «IF parentCount > -1»
      node«parentCount».add(node«aCount»);
    «ENDIF»
    «FOR b:a.sublevels»
      «compile(b, aCount)»
    «ENDFOR»
  '''
}

If you can spare the variable names, I'd prefer generating code using Java's lesser known non-static initializers as they reflect the structure of the tree in the Java code, eg 如果您可以保留变量名,那么我更喜欢使用Java鲜为人知的非静态初始化器生成代码,因为它们在Java代码中反映了树的结构,例如

new DefaultMutableTreeNode("a") {{
  add(new DefaultMutableTreeNode("a1") {{
    add(new DefaultMutableTreeNode("b1"))
  }})
  add(new DefaultMutableTreeNode("a2"))
  add(new DefaultMutableTreeNode("a2"))
}}

by the very simple generator 由非常简单的发电机

def CharSequence compile(Level a) '''
  new DefaultMutableTreeNode("«a.name»")«IF !a.sublevels.empty» {{
    «FOR b:a.sublevels»
      add(«compile(b)»);
    «ENDFOR»
  }}«ENDIF»'''

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM