-
Notifications
You must be signed in to change notification settings - Fork 758
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
In progress for #1363 This is an early preview of the work for allowing lexical scoping (nesting) of child resources. This changeset doesn't totally match the current proposal. It will need to be updated based on decisions tracker there and the loops/scoping work that is happening right now.
- Loading branch information
Showing
37 changed files
with
1,116 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
using System.Linq; | ||
using Bicep.Core.Diagnostics; | ||
using Bicep.Core.Semantics; | ||
using Bicep.Core.TypeSystem; | ||
using Bicep.Core.UnitTests.Assertions; | ||
using Bicep.Core.UnitTests.Utils; | ||
using FluentAssertions; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
|
||
namespace Bicep.Core.IntegrationTests | ||
{ | ||
[TestClass] | ||
public class ResourceTests | ||
{ | ||
[TestMethod] | ||
public void NestedResources_symbols_are_bound() | ||
{ | ||
var program = @" | ||
resource parent 'My.RP/parentType@2020-01-01' = { | ||
name: 'parent' | ||
properties: { | ||
size: 'large' | ||
} | ||
resource child 'My.RP/parentType/childType@2020-01-01' = { | ||
name: 'child' | ||
properties: { | ||
style: 'very cool' | ||
} | ||
} | ||
resource sibling 'My.RP/parentType/childType@2020-01-01' = { | ||
name: 'sibling' | ||
properties: { | ||
style: child.properties.style | ||
size: parent.properties.size | ||
} | ||
} | ||
} | ||
"; | ||
|
||
var compilation = new Compilation(TestResourceTypeProvider.Create(), SyntaxTreeGroupingFactory.CreateFromText(program)); | ||
var model = compilation.GetEntrypointSemanticModel(); | ||
|
||
model.GetAllDiagnostics().Should().BeEmpty(); | ||
|
||
var expected = new [] | ||
{ | ||
new { name = "child", type = "My.RP/parentType/childType@2020-01-01", }, | ||
new { name = "parent", type = "My.RP/parentType@2020-01-01", }, | ||
new { name = "sibling", type = "My.RP/parentType/childType@2020-01-01", }, | ||
}; | ||
|
||
model.Root.GetAllResourceDeclarations() | ||
.Select(s => new { name = s.Name, type = (s.Type as ResourceType)?.TypeReference.FormatName(), }) | ||
.OrderBy(n => n.name) | ||
.Should().BeEquivalentTo(expected); | ||
} | ||
|
||
[TestMethod] | ||
public void NestedResources_child_cannot_be_referenced_outside_of_scope() | ||
{ | ||
var program = @" | ||
resource parent 'My.RP/parentType@2020-01-01' = { | ||
name: 'parent' | ||
properties: { | ||
} | ||
resource child 'My.RP/parentType/childType@2020-01-01' = { | ||
name: 'child' | ||
properties: { | ||
style: 'very cool' | ||
} | ||
} | ||
} | ||
resource other 'My.RP/parentType@2020-01-01' = { | ||
name: 'other' | ||
properties: { | ||
style: child.properties.style | ||
} | ||
} | ||
"; | ||
|
||
var compilation = new Compilation(TestResourceTypeProvider.Create(), SyntaxTreeGroupingFactory.CreateFromText(program)); | ||
var diagnostics = compilation.GetEntrypointSemanticModel().GetAllDiagnostics(); | ||
diagnostics.Should().HaveDiagnostics(new[] { | ||
("BCP057", DiagnosticLevel.Error, "The name \"child\" does not exist in the current context."), | ||
}); | ||
} | ||
|
||
[TestMethod] | ||
public void NestedResources_child_cycle_is_detected_correctly() | ||
{ | ||
var program = @" | ||
resource parent 'My.RP/parentType@2020-01-01' = { | ||
name: 'parent' | ||
properties: { | ||
style: child.properties.style | ||
} | ||
resource child 'My.RP/parentType/childType@2020-01-01' = { | ||
name: 'child' | ||
properties: { | ||
style: 'very cool' | ||
} | ||
} | ||
} | ||
"; | ||
|
||
var compilation = new Compilation(TestResourceTypeProvider.Create(), SyntaxTreeGroupingFactory.CreateFromText(program)); | ||
compilation.GetEntrypointSemanticModel().GetAllDiagnostics().Should().HaveDiagnostics(new[] { | ||
("BCP080", DiagnosticLevel.Error, "The expression is involved in a cycle (\"child\" -> \"parent\")."), | ||
}); | ||
} | ||
|
||
[TestMethod] // With more than one level of nesting the name just isn't visible. | ||
public void NestedResources_grandchild_cycle_results_in_binding_failure() | ||
{ | ||
var program = @" | ||
resource parent 'My.RP/parentType@2020-01-01' = { | ||
name: 'parent' | ||
properties: { | ||
style: grandchild.properties.style | ||
} | ||
resource child 'My.RP/parentType/childType@2020-01-01' = { | ||
name: 'child' | ||
properties: { | ||
} | ||
resource grandchild 'My.RP/parentType/childType/grandchildType@2020-01-01' = { | ||
name: 'grandchild' | ||
properties: { | ||
style: 'very cool' | ||
} | ||
} | ||
} | ||
} | ||
"; | ||
|
||
var compilation = new Compilation(TestResourceTypeProvider.Create(), SyntaxTreeGroupingFactory.CreateFromText(program)); | ||
compilation.GetEntrypointSemanticModel().GetAllDiagnostics().Should().HaveDiagnostics(new[] { | ||
("BCP057", DiagnosticLevel.Error, "The name \"grandchild\" does not exist in the current context."), | ||
}); | ||
} | ||
|
||
[TestMethod] | ||
public void NestedResources_ancestors_are_detected() | ||
{ | ||
var program = @" | ||
resource parent 'My.RP/parentType@2020-01-01' = { | ||
name: 'parent' | ||
properties: { | ||
} | ||
resource child 'My.RP/parentType/childType@2020-01-01' = { | ||
name: 'child' | ||
properties: { | ||
} | ||
resource grandchild 'My.RP/parentType/childType/grandchildType@2020-01-01' = { | ||
name: 'grandchild' | ||
properties: { | ||
} | ||
} | ||
} | ||
} | ||
"; | ||
|
||
var compilation = new Compilation(TestResourceTypeProvider.Create(), SyntaxTreeGroupingFactory.CreateFromText(program)); | ||
var model = compilation.GetEntrypointSemanticModel(); | ||
model.GetAllDiagnostics().Should().BeEmpty(); | ||
|
||
var parent = model.Root.GetAllResourceDeclarations().Single(r => r.Name == "parent"); | ||
model.ResourceAncestors.GetAncestors(parent).Should().BeEmpty(); | ||
|
||
var child = model.Root.GetAllResourceDeclarations().Single(r => r.Name == "child"); | ||
model.ResourceAncestors.GetAncestors(child).Should().Equal(new []{ parent, }); | ||
|
||
var grandchild = model.Root.GetAllResourceDeclarations().Single(r => r.Name == "grandchild"); | ||
model.ResourceAncestors.GetAncestors(grandchild).Should().Equal(new []{ parent, child, }); // order matters | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.