Repository: terraform-docs/terraform-docs
Pull request #401 (2021-02-22 15:34:35)

Fixed lexicographic sorting of resources
<!--
Thank you for helping to improve terraform-docs!

Please read through https://git.io/JtEzg if this is your first time opening a
terraform-docs pull request. Find us in https://slack.terraform-docs.io/messages/dev if
you need any help contributing.
-->

### Description of your changes

<!--
Briefly describe what this pull request does. Be sure to direct your reviewers'
attention to anything that needs special consideration.

We love pull requests that resolve an open terraform-docs issue. If yours does, you
can uncomment the below line to indicate which issue your PR fixes, for example
"Fixes #500":
-->

The big fix in #392 broke sort order for resources that have common prefix.
For example, after upgrading to 0.11.1, we see a flood of the following diffs in our modules:

```diff
 | Name |
 |------|
 | [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/3.10/docs/data-sources/iam_policy_document) |
-| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/3.10/docs/resources/iam_role) |
-| [aws_iam_role_policy](https://registry.terraform.io/providers/hashicorp/aws/3.10/docs/resources/iam_role_policy) |
 | [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/3.10/docs/resources/iam_role_policy_attachment) |
+| [aws_iam_role_policy](https://registry.terraform.io/providers/hashicorp/aws/3.10/docs/resources/iam_role_policy) |
+| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/3.10/docs/resources/iam_role) |
 | [aws_iam_service_linked_role](https://registry.terraform.io/providers/hashicorp/aws/3.10/docs/resources/iam_service_linked_role) |
```

As it can be seen, some resources are now sorted in a reverse order, because of the way the new comparison function works.
This PR attempts to enforce a stricter lexicographic sorting order.

<!-- Fixes # -->
Related to: #392 

I have:

- [x] Read and followed terraform-docs' [contribution process].
- [x] All tests pass when I run `make test`.

### How has this code been tested

<!--
Before reviewers can be confident in the correctness of this pull request, it
needs to tested and shown to be correct. Briefly describe the testing that has
already been done or which is planned for this change.
-->

The unit test has been updated to test additional corner cases.

```
$ go test ./internal/terraform
ok  	github.com/terraform-docs/terraform-docs/internal/terraform	0.015s
```

[contribution process]: https://git.io/JtEzg



Patch:
diff --git a/internal/terraform/resource.go b/internal/terraform/resource.go
index 6f0c8df..b34f892 100644
--- a/internal/terraform/resource.go
+++ b/internal/terraform/resource.go
@@ -70,5 +70,5 @@ type resourcesSortedByType []*Resource
 func (a resourcesSortedByType) Len() int      { return len(a) }
 func (a resourcesSortedByType) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
 func (a resourcesSortedByType) Less(i, j int) bool {
-	return a[i].FullType()+a[i].Mode < a[j].FullType()+a[j].Mode || (a[i].FullType()+a[i].Mode == a[j].FullType()+a[j].Mode)
+	return a[i].FullType() < a[j].FullType() || (a[i].FullType() == a[j].FullType() && a[i].FullType()+a[i].Mode <= a[j].FullType()+a[j].Mode)
 }


Test patch:
diff --git a/internal/terraform/resource_test.go b/internal/terraform/resource_test.go
index f5467ae..40fb2cb 100644
--- a/internal/terraform/resource_test.go
+++ b/internal/terraform/resource_test.go
@@ -76,7 +76,7 @@ func TestResourcesSortedByType(t *testing.T) {
 
 	sort.Sort(resourcesSortedByType(resources))
 
-	expected := []string{"a_a", "a_f", "b_b", "b_d", "c_c", "c_e", "z_z", "z_z", "z_z"}
+	expected := []string{"a_a", "a_f", "b_b", "b_d", "c_c", "c_e", "c_e_x", "z_z", "z_z", "z_z"}
 	actual := make([]string, len(resources))
 
 	for k, i := range resources {
@@ -92,7 +92,7 @@ func TestResourcesSortedByTypeAndMode(t *testing.T) {
 
 	sort.Sort(resourcesSortedByType(resources))
 
-	expected := []string{"a_a_m", "a_f_m", "b_b_m", "b_d_m", "c_c_m", "c_e_m", "z_z", "z_z_d", "z_z_m"}
+	expected := []string{"a_a_m", "a_f_m", "b_b_m", "b_d_m", "c_c_m", "c_e_m", "c_e_x_m", "z_z", "z_z_d", "z_z_m"}
 	actual := make([]string, len(resources))
 
 	for k, i := range resources {
@@ -118,6 +118,13 @@ func sampleResources() []*Resource {
 			Mode:           "managed",
 			Version:        "1.5.0",
 		},
+		{
+			Type:           "e_x",
+			ProviderName:   "c",
+			ProviderSource: "hashicorp/e",
+			Mode:           "managed",
+			Version:        "1.5.0",
+		},
 		{
 			Type:           "a",
 			ProviderName:   "a",