diff --git a/pom.xml b/pom.xml index 259f3ad..6f16977 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ org.broadinstitute.compositetask Wdl jar - 0.0.2 + 0.0.3 Wdl http://github.com/broadinstitute/wdl diff --git a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java index c1abb17..53e9bbd 100644 --- a/src/main/java/org/broadinstitute/compositetask/CompositeTask.java +++ b/src/main/java/org/broadinstitute/compositetask/CompositeTask.java @@ -9,6 +9,8 @@ import java.util.LinkedHashSet; import java.util.HashMap; import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.broadinstitute.parser.Ast; import org.broadinstitute.parser.AstNode; @@ -75,6 +77,20 @@ public Ast verify(AstNode wdl_ast) throws SyntaxError { set_parents(CompositeTask.this); + Pattern expressionPattern = Pattern.compile("\\$\\{([^}]+)\\}"); + for ( Map.Entry output_file : this.output_files.entrySet() ) { + Matcher matcher = expressionPattern.matcher(output_file.getValue().getSourceString()); + while ( matcher.find() ) { + String filename_var = matcher.group(1); + for ( Map.Entry step_output : this.output_variables.entrySet() ) { + String output_var = step_output.getKey().getName(); + if ( output_var.equals(filename_var) ) { + throw new SyntaxError(this.syntaxErrorFormatter.variable_used_as_filename_and_step_output(output_file.getValue(), matcher.start(), step_output.getValue())); + } + } + } + } + return composite_task; } diff --git a/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java b/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java index fdb53f8..d3e2bd4 100644 --- a/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java +++ b/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java @@ -99,4 +99,14 @@ public String step_doesnt_use_loop_iterator(Terminal loop_iterator, Terminal ste this.code.getLine(loop_iterator.getLine()) + "\n" + Utility.getIndentString(loop_iterator.getColumn()-1) + "^\n"; } + public String variable_used_as_filename_and_step_output(Terminal filename_var, int filename_var_offset, Terminal output_var) { + return String.format("Variable %s used to construct an output filename and also as an output variable. One of these variable names must change.\n\n", output_var.getSourceString()) + + String.format("Line %d, Column %d:\n", filename_var.getLine(), filename_var.getColumn()) + + this.code.getLine(filename_var.getLine()) + "\n" + + Utility.getIndentString(filename_var.getColumn() + filename_var_offset - 1) + "^\n" + + String.format("Line %d, Column %d:\n", output_var.getLine(), output_var.getColumn()) + + this.code.getLine(output_var.getLine()) + "\n" + + Utility.getIndentString(output_var.getColumn()-1) + "^\n"; + } + } diff --git a/test-files/syntax-error/6/errors b/test-files/syntax-error/6/errors new file mode 100644 index 0000000..0344cc3 --- /dev/null +++ b/test-files/syntax-error/6/errors @@ -0,0 +1,8 @@ +org.broadinstitute.parser.SyntaxError: Variable filtered_bam_name used to construct an output filename and also as an output variable. One of these variable names must change. + +Line 3, Column 18: + output: File("${filtered_bam_name}.bam") as filtered_bam_name; + ^ +Line 3, Column 49: + output: File("${filtered_bam_name}.bam") as filtered_bam_name; + ^ diff --git a/test-files/syntax-error/6/source.wdl b/test-files/syntax-error/6/source.wdl new file mode 100644 index 0000000..ae70096 --- /dev/null +++ b/test-files/syntax-error/6/source.wdl @@ -0,0 +1,8 @@ +composite_task CufflinksPipeline { + step FilterBamForAlignedReads[version=8] { + output: File("${filtered_bam_name}.bam") as filtered_bam_name; + } + step Cufflinks[version=29] { + input: input.bam=filtered_bam_name; + } +} diff --git a/test-files/syntax-error/7/errors b/test-files/syntax-error/7/errors new file mode 100644 index 0000000..3d3e775 --- /dev/null +++ b/test-files/syntax-error/7/errors @@ -0,0 +1,8 @@ +org.broadinstitute.parser.SyntaxError: Variable filtered_bam_name used to construct an output filename and also as an output variable. One of these variable names must change. + +Line 3, Column 18: + output: File("${abc}.${filtered_bam_name}.bam") as filtered_bam_name; + ^ +Line 3, Column 56: + output: File("${abc}.${filtered_bam_name}.bam") as filtered_bam_name; + ^ diff --git a/test-files/syntax-error/7/source.wdl b/test-files/syntax-error/7/source.wdl new file mode 100644 index 0000000..99d5bb0 --- /dev/null +++ b/test-files/syntax-error/7/source.wdl @@ -0,0 +1,8 @@ +composite_task CufflinksPipeline { + step FilterBamForAlignedReads[version=8] { + output: File("${abc}.${filtered_bam_name}.bam") as filtered_bam_name; + } + step Cufflinks[version=29] { + input: input.bam=filtered_bam_name; + } +} diff --git a/test-files/syntax-error/8/errors b/test-files/syntax-error/8/errors new file mode 100644 index 0000000..db7e74c --- /dev/null +++ b/test-files/syntax-error/8/errors @@ -0,0 +1,8 @@ +org.broadinstitute.parser.SyntaxError: Variable xyz used to construct an output filename and also as an output variable. One of these variable names must change. + +Line 3, Column 18: + output: File("${abc}.${xyz}.bam") as filtered_bam_name, + ^ +Line 4, Column 35: + File("${abc}.bam") as xyz; + ^ diff --git a/test-files/syntax-error/8/source.wdl b/test-files/syntax-error/8/source.wdl new file mode 100644 index 0000000..a9953bd --- /dev/null +++ b/test-files/syntax-error/8/source.wdl @@ -0,0 +1,9 @@ +composite_task CufflinksPipeline { + step FilterBamForAlignedReads[version=8] { + output: File("${abc}.${xyz}.bam") as filtered_bam_name, + File("${abc}.bam") as xyz; + } + step Cufflinks[version=29] { + input: input.bam=xyz; + } +}