IsModuleMoveReIndex
Add a method for checking if the From and To addresses in a move statement are only changing the indexes of modules relative to the statement module. This is needed because move statement nested within the module will be able to match against both the From and To addresses, causing cycles in the order of move operations.
This commit is contained in:
parent
cd7277128f
commit
346418e31f
|
@ -162,9 +162,9 @@ func TestModuleInstance_IsDeclaredByCall(t *testing.T) {
|
|||
}
|
||||
|
||||
func mustParseModuleInstanceStr(str string) ModuleInstance {
|
||||
mi, err := ParseModuleInstanceStr(str)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
mi, diags := ParseModuleInstanceStr(str)
|
||||
if diags.HasErrors() {
|
||||
panic(diags.ErrWithWarnings())
|
||||
}
|
||||
return mi
|
||||
}
|
||||
|
|
|
@ -373,7 +373,7 @@ func (e *MoveEndpointInModule) CanChainFrom(other *MoveEndpointInModule) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// NestedWithin returns true if the reciever describes an address that is
|
||||
// NestedWithin returns true if the receiver describes an address that is
|
||||
// contained within one of the objects that the given other address could
|
||||
// select.
|
||||
func (e *MoveEndpointInModule) NestedWithin(other *MoveEndpointInModule) bool {
|
||||
|
@ -704,3 +704,53 @@ func (r AbsResourceInstance) MoveDestination(fromMatch, toMatch *MoveEndpointInM
|
|||
panic("unexpected object kind")
|
||||
}
|
||||
}
|
||||
|
||||
// IsModuleMoveReIndex takes the from and to endpoints from a move statement,
|
||||
// and returns true if the only changes are to module indexes, and all
|
||||
// non-absolute paths remain the same.
|
||||
func IsModuleMoveReIndex(from, to *MoveEndpointInModule) bool {
|
||||
// The statements must originate from the same module.
|
||||
if !from.module.Equal(to.module) {
|
||||
panic("cannot compare move expressions from different modules")
|
||||
}
|
||||
|
||||
switch f := from.relSubject.(type) {
|
||||
case AbsModuleCall:
|
||||
switch t := to.relSubject.(type) {
|
||||
case ModuleInstance:
|
||||
if len(t) != 1 {
|
||||
// An AbsModuleCall only ever has one segment, so the
|
||||
// ModuleInstance length must match.
|
||||
return false
|
||||
}
|
||||
|
||||
return f.Call.Name == t[0].Name
|
||||
}
|
||||
|
||||
case ModuleInstance:
|
||||
switch t := to.relSubject.(type) {
|
||||
case AbsModuleCall:
|
||||
if len(f) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
return f[0].Name == t.Call.Name
|
||||
|
||||
case ModuleInstance:
|
||||
// We must have the same number of segments, and the names must all
|
||||
// match in order for this to solely be an index change operation.
|
||||
if len(f) != len(t) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range f {
|
||||
if f[i].Name != t[i].Name {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -1584,6 +1584,139 @@ func TestSelectsResource(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestIsModuleMoveReIndex(t *testing.T) {
|
||||
tests := []struct {
|
||||
from, to AbsMoveable
|
||||
expect bool
|
||||
}{
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar`),
|
||||
to: mustParseModuleInstanceStr(`module.bar`),
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar`),
|
||||
to: mustParseModuleInstanceStr(`module.bar[0]`),
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
from: AbsModuleCall{
|
||||
Call: ModuleCall{Name: "bar"},
|
||||
},
|
||||
to: mustParseModuleInstanceStr(`module.bar[0]`),
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar["a"]`),
|
||||
to: AbsModuleCall{
|
||||
Call: ModuleCall{Name: "bar"},
|
||||
},
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.foo`),
|
||||
to: mustParseModuleInstanceStr(`module.bar`),
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar`),
|
||||
to: mustParseModuleInstanceStr(`module.foo[0]`),
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
from: AbsModuleCall{
|
||||
Call: ModuleCall{Name: "bar"},
|
||||
},
|
||||
to: mustParseModuleInstanceStr(`module.foo[0]`),
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar["a"]`),
|
||||
to: AbsModuleCall{
|
||||
Call: ModuleCall{Name: "foo"},
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar.module.baz`),
|
||||
to: mustParseModuleInstanceStr(`module.bar.module.baz`),
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar.module.baz`),
|
||||
to: mustParseModuleInstanceStr(`module.bar.module.baz[0]`),
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar.module.baz`),
|
||||
to: mustParseModuleInstanceStr(`module.baz.module.baz`),
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar.module.baz`),
|
||||
to: mustParseModuleInstanceStr(`module.baz.module.baz[0]`),
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar.module.baz`),
|
||||
to: mustParseModuleInstanceStr(`module.bar[0].module.baz`),
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar[0].module.baz`),
|
||||
to: mustParseModuleInstanceStr(`module.bar.module.baz[0]`),
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar[0].module.baz`),
|
||||
to: mustParseModuleInstanceStr(`module.bar[1].module.baz[0]`),
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
from: AbsModuleCall{
|
||||
Call: ModuleCall{Name: "baz"},
|
||||
},
|
||||
to: mustParseModuleInstanceStr(`module.bar.module.baz[0]`),
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar.module.baz[0]`),
|
||||
to: AbsModuleCall{
|
||||
Call: ModuleCall{Name: "baz"},
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.baz`),
|
||||
to: mustParseModuleInstanceStr(`module.bar.module.baz[0]`),
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
from: mustParseModuleInstanceStr(`module.bar.module.baz[0]`),
|
||||
to: mustParseModuleInstanceStr(`module.baz`),
|
||||
expect: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(fmt.Sprintf("[%02d]IsModuleMoveReIndex(%s, %s)", i, test.from, test.to),
|
||||
func(t *testing.T) {
|
||||
from := &MoveEndpointInModule{
|
||||
relSubject: test.from,
|
||||
}
|
||||
|
||||
to := &MoveEndpointInModule{
|
||||
relSubject: test.to,
|
||||
}
|
||||
|
||||
if got := IsModuleMoveReIndex(from, to); got != test.expect {
|
||||
t.Errorf("expected %t, got %t", test.expect, got)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func mustParseAbsResourceInstanceStr(s string) AbsResourceInstance {
|
||||
r, diags := ParseAbsResourceInstanceStr(s)
|
||||
if diags.HasErrors() {
|
||||
|
|
Loading…
Reference in New Issue