// Try syntax found in iptables.rb. Not sure it's correct
// but it seems to be parsed
// OK by the puppet-tool
nodes = RubyParserUtils.findNodes(puppetModule.getBody(), new NodeType[] { NodeType.FCALLNODE });
for(Node node : nodes) {
FCallNode call = (FCallNode) node;
if("newtype".equals(call.getName())) {
newtypeNode = call;
break;
}
}
}
}
else {
// The call might be a CallNode at the top level
nodes = RubyParserUtils.findNodes((root).getBody(), new NodeType[] { NodeType.CALLNODE });
for(Node node : nodes) {
CallNode call = (CallNode) node;
if("newtype".equals(call.getName())) {
Node receiver = call.getReceiver();
if(receiver instanceof Colon2ConstNode) {
Colon2ConstNode c2cNode = (Colon2ConstNode) receiver;
if("Type".equals(c2cNode.getName()) && c2cNode.getLeftNode() instanceof ConstNode &&
"Puppet".equals(((ConstNode) c2cNode.getLeftNode()).getName())) {
newtypeNode = call;
break;
}
}
}
}
}
if(newtypeNode == null)
throw new IOException("Unable to find newtype call in " + typeFileStr);
// Find the parameter that is passed in the call to newtype. It must
// be one
// single parameter in the form of a Symbol. This Symbol denotes the
// name of
// the new type.
Node argsNode = ((IArgumentNode) newtypeNode).getArgs();
nodes = RubyParserUtils.findNodes(argsNode, new NodeType[] { NodeType.SYMBOLNODE });
if(nodes.size() != 1)
throw new IOException("The newtype call does not take exactly one symbol parameter in " + typeFileStr);
SymbolNode typeName = (SymbolNode) nodes.get(0);
type.setName(typeName.getName());
// Find the assignment of the @doc instance variable
Node iterNode = newtypeNode.getIter();
nodes = RubyParserUtils.findNodes(iterNode, new NodeType[] { NodeType.BLOCKNODE, NodeType.INSTASGNNODE });
if(nodes.isEmpty())
// No block when there's just one assignment
nodes = RubyParserUtils.findNodes(iterNode, new NodeType[] { NodeType.INSTASGNNODE });
for(Node node : nodes) {
InstAsgnNode asgnNode = (InstAsgnNode) node;
if(!"@doc".equals(asgnNode.getName()))
continue;
Node valueNode = asgnNode.getValue();
if(valueNode instanceof StrNode)
type.setDocumentation(((StrNode) valueNode).getValue());
break;
}
// Find the calls to newparam (receiver is the instance returned by
// newtype)
nodes = RubyParserUtils.findNodes(iterNode, new NodeType[] { NodeType.BLOCKNODE, NodeType.FCALLNODE });
if(nodes.isEmpty())
// No block when there's just one call
nodes = RubyParserUtils.findNodes(iterNode, new NodeType[] { NodeType.FCALLNODE });
ArrayList<NamedTypeItem> parameters = null;
ArrayList<NamedTypeItem> properties = null;
for(Node node : nodes) {
FCallNode callNode = (FCallNode) node;
boolean isParam = "newparam".equals(callNode.getName());
if(!isParam && !"newproperty".equals(callNode.getName()))
continue;
List<Node> pnodes = RubyParserUtils.findNodes(callNode.getArgs(), new NodeType[] { NodeType.SYMBOLNODE });
if(pnodes.size() != 1)
throw new IOException("A newparam or newproperty call does not take exactly one symbol parameter in " +
typeFileStr);
NamedTypeItem elem = new NamedTypeItem();
if(isParam) {
if(parameters == null)
parameters = new ArrayList<NamedTypeItem>();
parameters.add(elem);
}
else {
if(properties == null)
properties = new ArrayList<NamedTypeItem>();
properties.add(elem);
}
elem.setName(((SymbolNode) pnodes.get(0)).getName());
iterNode = callNode.getIter();
pnodes = RubyParserUtils.findNodes(iterNode, new NodeType[] { NodeType.BLOCKNODE, NodeType.FCALLNODE });
if(pnodes.isEmpty())
// No block when there's just one call
pnodes = RubyParserUtils.findNodes(iterNode, new NodeType[] { NodeType.FCALLNODE });
for(Node pnode : pnodes) {
FCallNode pcallNode = (FCallNode) pnode;
if("desc".equals(pcallNode.getName())) {
List<Node> args = pcallNode.getArgs().childNodes();
if(args.size() != 1)
throw new IOException(
"A newparam or newproperty desc call does not take exactly one parameter in " + typeFileStr);
elem.setDocumentation(RubyParserUtils.stringValue(args.get(0)));
break;