Repository: aws-cloudformation/cfn-lint

Issue:
Is this valid Cloudformation and a cfn-lint bug?
**cfn-lint Version **

0.87.3

Syntax:

// add a pseudo element to array (/null) so we can rely on intrinsic length to pop last element we want
 `Id: !Select [ !Length !Split ["/", !Sub "${AWS::StackName}-v1"], !Split [ "/", !Sub "${AWS::StackName}-v1/null" ] ]`

Response:

E0000 did not find expected ',' or ']'


Discussion:
Also tried:

```
        Id: 
            Fn::Select:
              [ Fn::Length: 
                !Split ["/", !Sub "${AWS::StackId}-v1/null"] , !Split ["/", !Sub "${AWS::StackId}-v1/null"]
              ]
 ```
 
 Response:
 
E1017 Select index should be an Integer or a function Ref, Fn::FindInMap, or Fn::Select for Resources/EventRule/Properties/Targets/0/Id/Fn::Select/0             

Its how you are using the short function syntax `
```
duplication of a tag property (6:32)

 3 |     Type: AWS::SSM::Parameter
 4 |     Properties:
 5 |       Type: String
 6 |       Value: !Select [ !Length !Split ["/", !Sub "${AWS::StackN ...
------------------------------------^
```

`Id: !Select [ !Length {"Fn::Split": ["/", !Sub "${AWS::StackName}-v1"]}, !Split [ "/", !Sub "${AWS::StackName}-v1/null" ] ]`

Looking into the integer issue
In relation to the [docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html) the question is `Fn::Length` supported 
Your right, the issue is that !Select index only supports  Ref and Fn::FindInMap functions.
@ispyinternet going to reopen this as the Fn::Length does work when you have the language extension transform added.   I was able to make it work.

This template works.
```yaml
Transform: AWS::LanguageExtensions
Resources:
  Parameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Value: !Select [ {"Fn::Length": {"Fn::Split": ["/", !Sub "${AWS::StackName}-v1"]}}, !Split [ "/", !Sub "${AWS::StackName}-v1/null" ] ]
```
ok cool, yh, I was using this too



Patch:
diff --git a/src/cfnlint/rules/functions/Select.py b/src/cfnlint/rules/functions/Select.py
index f5456d7560..12e47007f4 100644
--- a/src/cfnlint/rules/functions/Select.py
+++ b/src/cfnlint/rules/functions/Select.py
@@ -25,7 +25,7 @@ def __init__(self) -> None:
         self.fn_select = self.validate
 
     def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
-        return {
+        schema = {
             "type": "array",
             "maxItems": 2,
             "minItems": 2,
@@ -63,3 +63,8 @@ def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
                 },
             ],
         }
+
+        if validator.context.transforms.has_language_extensions_transform():
+            schema["fn_items"][0]["functions"].append("Fn::Length")  # type: ignore
+
+        return schema


Test patch:
diff --git a/test/unit/rules/functions/test_select.py b/test/unit/rules/functions/test_select.py
index 88b0d06628..c700149696 100644
--- a/test/unit/rules/functions/test_select.py
+++ b/test/unit/rules/functions/test_select.py
@@ -55,12 +55,12 @@ def template():
             ],
         ),
         (
-            "Invalid Fn::Select using an invalid function for index",
-            {"Fn::Select": [{"Fn::GetAtt": "MyResource"}, ["bar"]]},
+            "Invalid Fn::Length using an invalid function for index",
+            {"Fn::Select": [{"Fn::Length": [1, 2]}, ["bar"]]},
             {"type": "string"},
             [
                 ValidationError(
-                    "{'Fn::GetAtt': 'MyResource'} is not of type 'integer'",
+                    "{'Fn::Length': [1, 2]} is not of type 'integer'",
                     path=deque(["Fn::Select", 0]),
                     schema_path=deque(["fn_items", "type"]),
                     validator="fn_select",
diff --git a/test/unit/rules/functions/test_select_language_extension.py b/test/unit/rules/functions/test_select_language_extension.py
new file mode 100644
index 0000000000..d71fd67888
--- /dev/null
+++ b/test/unit/rules/functions/test_select_language_extension.py
@@ -0,0 +1,53 @@
+"""
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+SPDX-License-Identifier: MIT-0
+"""
+
+from collections import deque
+
+import pytest
+
+from cfnlint.jsonschema import ValidationError
+from cfnlint.rules.functions.Select import Select
+from cfnlint.rules.functions.SelectResolved import SelectResolved
+
+
+@pytest.fixture(scope="module")
+def rule():
+    rule = Select()
+    rule.child_rules["W1035"] = SelectResolved()
+    yield rule
+
+
+@pytest.fixture
+def template():
+    return {"Transform": "AWS::LanguageExtensions"}
+
+
+@pytest.mark.parametrize(
+    "name,instance,schema,expected",
+    [
+        (
+            "Invalid Fn::Select using an invalid function for index",
+            {"Fn::Select": [{"Fn::GetAtt": "MyResource"}, ["bar"]]},
+            {"type": "string"},
+            [
+                ValidationError(
+                    "{'Fn::GetAtt': 'MyResource'} is not of type 'integer'",
+                    path=deque(["Fn::Select", 0]),
+                    schema_path=deque(["fn_items", "type"]),
+                    validator="fn_select",
+                ),
+            ],
+        ),
+        (
+            "Valid Fn::Length with language extension",
+            {"Fn::Select": [{"Fn::Length": [1, 2]}, ["A", "B", "C"]]},
+            {"type": "string"},
+            [],
+        ),
+    ],
+)
+def test_validate(name, instance, schema, expected, rule, validator):
+    errs = list(rule.fn_select(validator, schema, instance, {}))
+    assert errs == expected, f"Test {name!r} got {errs!r}"