Skip to content

Commit

Permalink
Added support for "unless" attribute and special node for use instead…
Browse files Browse the repository at this point in the history
… of negating if statements
  • Loading branch information
RobertTheGrey committed Jun 1, 2012
1 parent 7984faa commit f24f155
Show file tree
Hide file tree
Showing 24 changed files with 275 additions and 8 deletions.
1 change: 1 addition & 0 deletions src/Spark.JsTests/CodeConstructsTests.html
Expand Up @@ -20,6 +20,7 @@
assertContains("ok1", contents);
assertContains("ok2", contents);
assertContains("ok3", contents);
assertContains("ok4", contents);
}

function testIteration()
Expand Down
8 changes: 8 additions & 0 deletions src/Spark.JsTests/Views/CodeConstructs/_Conditionals.spark
Expand Up @@ -16,5 +16,13 @@
<s:else/>
ok3
</s:test>

<p s:unless="true">
unless fail
</p>

<p s:unless="false">
ok4
</p>

</div>
18 changes: 18 additions & 0 deletions src/Spark.Python.Tests/PythonViewCompilerTests.cs
Expand Up @@ -361,6 +361,24 @@ public void ElseBlockFollowsIf()
Assert.AreEqual("aok1ok2b", contents);
}

[Test]
public void ConditionalChunkUnlessNegates()
{
var condition1 = new ConditionalChunk { Condition = "x != 12", Type = ConditionalType.Unless };
condition1.Body.Add(new SendLiteralChunk { Text = "ok1" });
var condition2 = new ConditionalChunk { Condition = "x == 12", Type = ConditionalType.Unless };
condition2.Body.Add(new SendLiteralChunk { Text = "fail" });
var chunks = Chunks(
new LocalVariableChunk { Name = "x", Value = "12" },
new SendLiteralChunk { Text = "a" },
condition1,
condition2,
new SendLiteralChunk { Text = "b" });
_compiler.CompileView(chunks, chunks);
var contents = ExecuteView();
Assert.AreEqual("aok1b", contents);
}

[Test]
public void ChainingElseIfNestsProperly()
{
Expand Down
Expand Up @@ -196,6 +196,9 @@ protected override void Visit(ConditionalChunk chunk)
case ConditionalType.Once:
_source.Write("if Once(").Write(chunk.Condition).WriteLine("):");
break;
case ConditionalType.Unless:
_source.Write("if not ").Write(chunk.Condition).WriteLine(":");
break;
default:
throw new CompilerException(string.Format("Unknown ConditionalChunk type {0}", chunk.Type));
}
Expand Down
18 changes: 18 additions & 0 deletions src/Spark.Ruby.Tests/RubyViewCompilerTests.cs
Expand Up @@ -359,6 +359,24 @@ public void ElseBlockFollowsIf()
Assert.AreEqual("aok1ok2b", contents);
}

[Test]
public void ConditionalChunkUnlessNegates()
{
var condition1 = new ConditionalChunk { Condition = "x != 12", Type = ConditionalType.Unless };
condition1.Body.Add(new SendLiteralChunk { Text = "ok1" });
var condition2 = new ConditionalChunk { Condition = "x == 12", Type = ConditionalType.Unless };
condition2.Body.Add(new SendLiteralChunk { Text = "fail" });
var chunks = Chunks(
new LocalVariableChunk { Name = "x", Value = "12" },
new SendLiteralChunk { Text = "a" },
condition1,
condition2,
new SendLiteralChunk { Text = "b" });
_compiler.CompileView(chunks, chunks);
var contents = ExecuteView();
Assert.AreEqual("aok1b", contents);
}

[Test]
public void ChainingElseIfNestsProperly()
{
Expand Down
3 changes: 3 additions & 0 deletions src/Spark.Ruby/Compiler/ChunkVisitors/GeneratedCodeVisitor.cs
Expand Up @@ -199,6 +199,9 @@ protected override void Visit(ConditionalChunk chunk)
case ConditionalType.Once:
_source.Write("if once(").Write(chunk.Condition).WriteLine(")");
break;
case ConditionalType.Unless:
_source.Write("unless ").WriteLine(chunk.Condition);
break;
default:
throw new CompilerException(string.Format("Unknown ConditionalChunk type {0}", chunk.Type));
}
Expand Down
38 changes: 38 additions & 0 deletions src/Spark.Tests/Compiler/CSharpViewCompilerTester.cs
Expand Up @@ -219,6 +219,44 @@ public void IfElseFalseCondition()
Assert.AreEqual("<p>wasfalse</p>", contents);
}

[Test]
public void UnlessTrueCondition()
{
var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };

var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };

DoCompileView(compiler, new Chunk[]
{
new SendLiteralChunk {Text = "<p>"},
new LocalVariableChunk{Name="arg", Value="5"},
new ConditionalChunk{Type=ConditionalType.Unless, Condition="arg==5", Body=trueChunks},
new SendLiteralChunk {Text = "</p>"}
});
var instance = compiler.CreateInstance();
var contents = instance.RenderView();
Assert.AreEqual("<p></p>", contents);
}

[Test]
public void UnlessFalseCondition()
{
var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };

var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };

DoCompileView(compiler, new Chunk[]
{
new SendLiteralChunk {Text = "<p>"},
new LocalVariableChunk{Name="arg", Value="5"},
new ConditionalChunk{Type=ConditionalType.Unless, Condition="arg==6", Body=trueChunks},
new SendLiteralChunk {Text = "</p>"}
});
var instance = compiler.CreateInstance();
var contents = instance.RenderView();
Assert.AreEqual("<p>wastrue</p>", contents);
}

[Test]
public void LenientSilentNullDoesNotCauseWarningCS0168()
{
Expand Down
38 changes: 38 additions & 0 deletions src/Spark.Tests/Compiler/VisualBasicViewCompilerTester.cs
Expand Up @@ -309,6 +309,44 @@ public void IfElseFalseCondition()
Assert.AreEqual("<p>wasfalse</p>", contents);
}

[Test]
public void UnlessTrueCondition()
{
var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };

var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };

DoCompileView(compiler, new Chunk[]
{
new SendLiteralChunk {Text = "<p>"},
new LocalVariableChunk{Name="arg", Value="5"},
new ConditionalChunk{Type=ConditionalType.Unless, Condition="arg=5", Body=trueChunks},
new SendLiteralChunk {Text = "</p>"}
});
var instance = compiler.CreateInstance();
var contents = instance.RenderView();
Assert.AreEqual("<p></p>", contents);
}

[Test]
public void UnlessFalseCondition()
{
var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };

var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };

DoCompileView(compiler, new Chunk[]
{
new SendLiteralChunk {Text = "<p>"},
new LocalVariableChunk{Name="arg", Value="5"},
new ConditionalChunk{Type=ConditionalType.Unless, Condition="arg=6", Body=trueChunks},
new SendLiteralChunk {Text = "</p>"}
});
var instance = compiler.CreateInstance();
var contents = instance.RenderView();
Assert.AreEqual("<p>wastrue</p>", contents);
}

[Test]
public void StrictNullUsesException()
{
Expand Down
4 changes: 3 additions & 1 deletion src/Spark.Tests/PrefixSupportTester.cs
Expand Up @@ -108,12 +108,14 @@ public void ConditionalAttributes()
ContainsInOrder(output.ToString(),
"ok1",
"ok2",
"ok3");
"ok3",
"ok4");

Assert.IsFalse(output.ToString().Contains("fail"));
Assert.IsFalse(output.ToString().Contains("if"));
Assert.IsFalse(output.ToString().Contains("else"));
Assert.IsFalse(output.ToString().Contains("condition"));
Assert.IsFalse(output.ToString().Contains("unless fail"));
}

[Test]
Expand Down
@@ -0,0 +1,5 @@
<content name="Hello" each="var name in new[]{'alpha', 'beta', 'gamma'}" unless="name == 'beta'">
<p>name-${nameIndex}-${name}</p>
</content>
<use content="Hello"/>
<SimpleValue each="var foo in new[] {'one','two','three'}" unless="foo == 'two'"/>
8 changes: 8 additions & 0 deletions src/Spark.Tests/Spark.Tests.Views/Home/unlessattribute.spark
@@ -0,0 +1,8 @@
<div>
<var arg="5"/>

<p unless="arg==5">argis5</p>

<p unless="arg==6">argisnot6</p>

</div>
12 changes: 12 additions & 0 deletions src/Spark.Tests/Spark.Tests.Views/Home/unlesselement.spark
@@ -0,0 +1,12 @@
<div>
<var arg="5"/>

<unless condition="arg==5">
<p>argis5</p>
</unless>

<unless condition="arg==6">
<p>argisnot6</p>
</unless>

</div>
Expand Up @@ -16,5 +16,13 @@
<s:else/>
ok3
</s:test>

<p s:unless="true">
unless fail
</p>

<p s:unless="false">
ok4
</p>

</div>
10 changes: 10 additions & 0 deletions src/Spark.Tests/Spark.Tests.csproj
Expand Up @@ -177,6 +177,15 @@
<None Include="Spark.Tests.Views\Home\addviewdatadifferenttypes.spark">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Spark.Tests.Views\Home\unlessattribute.spark">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Spark.Tests.Views\Home\unlesselement.spark">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Spark.Tests.Views\Home\UnlessAttributeWorksOnSpecialNodes.spark">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Spark.Tests.Views\Home\ShadeElementsMayStackOnOneLine.shade">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down Expand Up @@ -351,6 +360,7 @@
</None>
<None Include="Spark.Tests.Views\Home\ConditionalAttributeDelimitedBySpaces.spark">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<SubType>Designer</SubType>
</None>
<None Include="Spark.Tests.Views\Home\eachattribute-whitespace.spark">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
Expand Down
49 changes: 48 additions & 1 deletion src/Spark.Tests/SparkViewFactoryTester.cs
Expand Up @@ -244,6 +244,35 @@ public void IfElseAttributes()
Assert.That(content.Contains("<p>argisstillnot6</p>"));
}

[Test]
public void UnlessElements()
{
mocks.ReplayAll();
var viewContext = MakeViewContext("unlesselement", null);
factory.RenderView(viewContext);
mocks.VerifyAll();

string content = sb.ToString();
Assert.That(!content.Contains("<unless"));

Assert.That(content.Contains("<p>argisnot6</p>"));
Assert.That(!content.Contains("<p>argis5</p>"));
}

[Test]
public void UnlessAttributes()
{
mocks.ReplayAll();
var viewContext = MakeViewContext("unlessattribute", null);
factory.RenderView(viewContext);
mocks.VerifyAll();

string content = sb.ToString();
Assert.That(!content.Contains("<unless"));

Assert.That(content.Contains("<p>argisnot6</p>"));
Assert.That(!content.Contains("<p>argis5</p>"));
}

[Test]
public void ChainingElseIfElement()
Expand Down Expand Up @@ -1021,6 +1050,25 @@ public void IfAttributeWorksOnSpecialNodes()
Assert.IsFalse(content.Contains("two"));
}

[Test]
public void UnlessAttributeWorksOnSpecialNodes()
{
mocks.ReplayAll();
var viewContext = MakeViewContext("UnlessAttributeWorksOnSpecialNodes", null);
factory.RenderView(viewContext);
mocks.VerifyAll();
string content = sb.ToString();

Assert.That(content, Contains.InOrder(
"<p>name-0-alpha</p>",
"<p>name-2-gamma</p>",
"<span>one</span>",
"<span>three</span>"));

Assert.IsFalse(content.Contains("beta"));
Assert.IsFalse(content.Contains("two"));
}

[Test]
public void OnceAttributeWorksOnSpecialNodes()
{
Expand Down Expand Up @@ -1093,7 +1141,6 @@ public void RecursivePartialsThrowCompilerException()
Throws.TypeOf<CompilerException>());
}


[Test]
public void NestedPartialsCanBackRenderUpAndReRenderDown()
{
Expand Down
17 changes: 17 additions & 0 deletions src/Spark.Tests/Visitors/ConditionalAttributeVisitorTester.cs
Expand Up @@ -39,6 +39,23 @@ public void DetectIfAttribute()
Assert.AreEqual("if", ifNode.Element.Name);
}

[Test]
public void DetectUnlessAttribute()
{
var grammar = new MarkupGrammar();
string input = "<div unless=\"true\">hello</div>";
var nodes = grammar.Nodes(new Position(new SourceContext(input))).Value;
var visitor = new ConditionalAttributeVisitor(new VisitorContext());
visitor.Accept(nodes);

Assert.AreEqual(1, visitor.Nodes.Count);
Assert.IsAssignableFrom(typeof(SpecialNode), visitor.Nodes[0]);

var unlessNode = visitor.Nodes[0] as SpecialNode;
Assert.IsNotNull(unlessNode);
Assert.AreEqual("unless", unlessNode.Element.Name);
}

[Test]
public void ChainConditionalAttribute()
{
Expand Down
12 changes: 10 additions & 2 deletions src/Spark/Compiler/CSharp/ChunkVisitors/GeneratedCodeVisitor.cs
Expand Up @@ -439,6 +439,14 @@ protected override void Visit(ConditionalChunk chunk)
.WriteLine("))");
}
break;
case ConditionalType.Unless:
{
CodeIndent(chunk)
.Write("if (!(")
.WriteCode(chunk.Condition)
.WriteLine("))");
}
break;
default:
throw new CompilerException("Unexpected conditional type " + chunk.Type);
}
Expand All @@ -464,7 +472,7 @@ protected override void Visit(CacheChunk chunk)

_source
.WriteLine("try");

AppendOpenBrace();
Accept(chunk.Body);
AppendCloseBrace();
Expand All @@ -487,7 +495,7 @@ protected override void Visit(MarkdownChunk chunk)
AppendCloseBrace();
}


}

}

0 comments on commit f24f155

Please sign in to comment.