Skip to content

Commit 31c57e6

Browse files
committed
Workflow params
Signed-off-by: Ben Sherman <bentshermann@gmail.com>
1 parent a166c7c commit 31c57e6

File tree

8 files changed

+74
-48
lines changed

8 files changed

+74
-48
lines changed

src/main/java/nextflow/lsp/ast/ASTNodeStringUtils.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,16 @@ private static String workflowToLabel(WorkflowNode node) {
106106
fmt.incIndent();
107107
fmt.appendIndent();
108108
fmt.append("take:\n");
109-
var takes = asBlockStatements(node.takes);
110-
if( takes.isEmpty() ) {
109+
var takes = node.getParameters();
110+
if( takes.length == 0 ) {
111111
fmt.appendIndent();
112112
fmt.append("<none>\n");
113113
}
114-
takes.stream().forEach((take) -> {
114+
for( var take : takes ) {
115115
fmt.appendIndent();
116-
fmt.append(asVarX(take).getName());
116+
fmt.append(take.getName());
117117
fmt.appendNewLine();
118-
});
118+
}
119119
fmt.appendNewLine();
120120
fmt.appendIndent();
121121
fmt.append("emit:\n");
@@ -305,6 +305,9 @@ public static String getDocumentation(ASTNode node) {
305305
return result;
306306
}
307307

308+
if( node instanceof Parameter param )
309+
return groovydocToMarkdown(param.getGroovydoc());
310+
308311
return null;
309312
}
310313

src/main/java/nextflow/lsp/ast/ASTParentVisitor.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,20 +275,24 @@ public void visitClosureExpression(ClosureExpression node) {
275275
push(node);
276276
try {
277277
var parameters = node.getParameters();
278-
if( parameters != null ) {
279-
for( var parameter : parameters )
280-
visitParameter(parameter);
281-
}
278+
if( parameters != null )
279+
visitParameters(parameters);
282280
super.visitClosureExpression(node);
283281
}
284282
finally {
285283
pop();
286284
}
287285
}
288286

289-
public void visitParameter(Parameter node) {
287+
public void visitParameters(Parameter[] parameters) {
288+
for( var parameter : parameters )
289+
visitParameter(parameter);
290+
}
291+
292+
private void visitParameter(Parameter node) {
290293
push(node);
291294
try {
295+
super.visit(node.getInitialExpression());
292296
}
293297
finally {
294298
pop();

src/main/java/nextflow/lsp/services/SemanticTokensVisitor.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,11 @@ public void visitClosureExpression(ClosureExpression node) {
139139
}
140140

141141
public void visitParameters(Parameter[] parameters) {
142-
for( int i = 0; i < parameters.length; i++ ) {
143-
var param = parameters[i];
144-
append((TokenPosition) param.getNodeMetaData("_START_NAME"), param.getName(), SemanticTokenTypes.Parameter);
142+
for( var param : parameters ) {
143+
if( param.getNodeMetaData("_START_NAME") instanceof TokenPosition start )
144+
append(start, param.getName(), SemanticTokenTypes.Parameter);
145+
else
146+
append(param.getLineNumber() - 1, param.getColumnNumber() - 1, param.getName().length(), SemanticTokenTypes.Parameter);
145147
if( param.hasInitialExpression() )
146148
visit(param.getInitialExpression());
147149
}

src/main/java/nextflow/lsp/services/script/ParameterSchemaVisitor.java

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.util.stream.Stream;
2727

2828
import groovy.json.JsonSlurper;
29+
import nextflow.lsp.ast.ASTNodeStringUtils;
30+
import nextflow.script.ast.ParamBlockNode;
2931
import nextflow.script.ast.ScriptNode;
3032
import nextflow.script.ast.ScriptVisitorSupport;
3133
import nextflow.script.ast.WorkflowNode;
@@ -71,30 +73,55 @@ protected SourceUnit getSourceUnit() {
7173
public void visit() {
7274
var moduleNode = sourceUnit.getAST();
7375
if( moduleNode instanceof ScriptNode sn ) {
74-
if( sn.getEntry() != null )
75-
visitWorkflow(sn.getEntry());
76+
if( sn.getEntry() != null ) {
77+
paramsType = sn.getParams() != null
78+
? declareParamsFromScript(sn.getParams())
79+
: declareParamsFromSchema(sn.getEntry());
80+
if( paramsType != null )
81+
visitWorkflow(sn.getEntry());
82+
}
7683
}
7784
}
7885

79-
@Override
80-
public void visitWorkflow(WorkflowNode node) {
86+
private ClassNode declareParamsFromScript(ParamBlockNode node) {
87+
var cn = new ClassNode(ParamsMap.class);
88+
89+
for( var param : node.declarations ) {
90+
var name = param.getName();
91+
var type = param.getType();
92+
var fn = new FieldNode(name, Modifier.PUBLIC, type, cn, null);
93+
fn.setHasNoRealSourcePosition(true);
94+
fn.setDeclaringClass(cn);
95+
fn.setSynthetic(true);
96+
var description = ASTNodeStringUtils.getDocumentation(param);
97+
if( description != null ) {
98+
var an = new AnnotationNode(ClassHelper.makeCached(Description.class));
99+
an.addMember("value", new ConstantExpression(description));
100+
fn.addAnnotation(an);
101+
}
102+
cn.addField(fn);
103+
}
104+
105+
return cn;
106+
}
107+
108+
private ClassNode declareParamsFromSchema(WorkflowNode entry) {
81109
try {
82-
declareParameters();
110+
return declareParamsFromSchema0();
83111
}
84112
catch( Exception e ) {
85113
System.err.println("Failed to parse parameter schema (nextflow_schema.json): " + e.toString());
86-
addError("Failed to parse parameter schema -- check nextflow_schema.json for possible errors", node);
87-
return;
114+
addError("Failed to parse parameter schema -- check nextflow_schema.json for possible errors", entry);
115+
return null;
88116
}
89-
super.visitWorkflow(node);
90117
}
91118

92-
private void declareParameters() {
119+
private ClassNode declareParamsFromSchema0() {
93120
// load parameter schema
94121
var uri = sourceUnit.getSource().getURI();
95122
var schemaPath = Path.of(uri).getParent().resolve("nextflow_schema.json");
96123
if( !Files.exists(schemaPath) )
97-
return;
124+
return null;
98125
var schemaJson = getParameterSchema(schemaPath);
99126

100127
var schema = asMap(schemaJson).orElse(Collections.emptyMap());
@@ -124,7 +151,7 @@ private void declareParameters() {
124151
.toList();
125152

126153
if( entries.isEmpty() )
127-
return;
154+
return null;
128155

129156
// create synthetic params type
130157
var cn = new ClassNode(ParamsMap.class);
@@ -146,7 +173,7 @@ private void declareParameters() {
146173
cn.addField(fn);
147174
}
148175

149-
this.paramsType = cn;
176+
return cn;
150177
}
151178

152179
private Object getParameterSchema(Path schemaPath) {

src/main/java/nextflow/lsp/services/script/ScriptAstParentVisitor.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import nextflow.script.ast.IncludeEntryNode;
2424
import nextflow.script.ast.IncludeNode;
2525
import nextflow.script.ast.OutputNode;
26-
import nextflow.script.ast.ParamNode;
26+
import nextflow.script.ast.ParamBlockNode;
2727
import nextflow.script.ast.ProcessNode;
2828
import nextflow.script.ast.ScriptNode;
2929
import nextflow.script.ast.ScriptVisitorSupport;
@@ -96,10 +96,10 @@ protected void visitIncludeEntry(IncludeEntryNode node) {
9696
}
9797

9898
@Override
99-
public void visitParam(ParamNode node) {
99+
public void visitParams(ParamBlockNode node) {
100100
lookup.push(node);
101101
try {
102-
lookup.visit(node.value);
102+
lookup.visitParameters(node.declarations);
103103
}
104104
finally {
105105
lookup.pop();
@@ -110,7 +110,7 @@ public void visitParam(ParamNode node) {
110110
public void visitWorkflow(WorkflowNode node) {
111111
lookup.push(node);
112112
try {
113-
lookup.visit(node.takes);
113+
lookup.visitParameters(node.getParameters());
114114
lookup.visit(node.main);
115115
lookup.visit(node.emits);
116116
lookup.visit(node.publishers);
@@ -140,8 +140,7 @@ public void visitProcess(ProcessNode node) {
140140
public void visitFunction(FunctionNode node) {
141141
lookup.push(node);
142142
try {
143-
for( var parameter : node.getParameters() )
144-
lookup.visitParameter(parameter);
143+
lookup.visitParameters(node.getParameters());
145144
lookup.visit(node.getCode());
146145
}
147146
finally {

src/main/java/nextflow/lsp/services/script/ScriptSemanticTokensProvider.java

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import nextflow.script.ast.FunctionNode;
2727
import nextflow.script.ast.IncludeNode;
2828
import nextflow.script.ast.OutputNode;
29-
import nextflow.script.ast.ParamNode;
29+
import nextflow.script.ast.ParamBlockNode;
3030
import nextflow.script.ast.ProcessNode;
3131
import nextflow.script.ast.ScriptNode;
3232
import nextflow.script.ast.ScriptVisitorSupport;
@@ -115,15 +115,13 @@ public void visitInclude(IncludeNode node) {
115115
}
116116

117117
@Override
118-
public void visitParam(ParamNode node) {
119-
tok.visit(node.target);
120-
tok.visit(node.value);
118+
public void visitParams(ParamBlockNode node) {
119+
tok.visitParameters(node.declarations);
121120
}
122121

123122
@Override
124123
public void visitWorkflow(WorkflowNode node) {
125-
if( node.takes instanceof BlockStatement block )
126-
visitWorkflowTakes(block.getStatements());
124+
tok.visitParameters(node.getParameters());
127125

128126
tok.visit(node.main);
129127

@@ -133,13 +131,6 @@ public void visitWorkflow(WorkflowNode node) {
133131
tok.visit(node.publishers);
134132
}
135133

136-
protected void visitWorkflowTakes(List<Statement> takes) {
137-
for( var stmt : takes ) {
138-
var ve = (VariableExpression) asVarX(stmt);
139-
tok.append(ve, SemanticTokenTypes.Parameter);
140-
}
141-
}
142-
143134
protected void visitWorkflowEmits(List<Statement> emits) {
144135
for( var stmt : emits ) {
145136
var es = (ExpressionStatement)stmt;

src/main/java/nextflow/lsp/services/script/dag/DataflowVisitor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,9 @@ public void visitWorkflow(WorkflowNode node) {
120120
}
121121

122122
private void visitWorkflowTakes(WorkflowNode node, Map<String,Node> result) {
123-
for( var stmt : asBlockStatements(node.takes) ) {
124-
var name = asVarX(stmt).getName();
125-
var dn = addNode(name, Node.Type.NAME, stmt);
123+
for( var take : node.getParameters() ) {
124+
var name = take.getName();
125+
var dn = addNode(name, Node.Type.NAME, take);
126126
dn.verbose = false;
127127
vc.putSymbol(name, dn);
128128
result.put(name, dn);

src/test/groovy/nextflow/lsp/ast/ASTNodeStringUtilsTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class ASTNodeStringUtilsTest extends Specification {
8888
def node = Mock(WorkflowNode) {
8989
isEntry() >> false
9090
getName() >> 'FOO'
91-
takes >> EmptyStatement.INSTANCE
91+
getParameters() >> Parameter.EMPTY_ARRAY
9292
emits >> EmptyStatement.INSTANCE
9393
getGroovydoc() >> Mock(Groovydoc) {
9494
isPresent() >> true

0 commit comments

Comments
 (0)