From e072f63da5b7c2151ec2fa062bd144838589a951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Miku=C5=A1?= Date: Tue, 24 Oct 2023 17:26:21 +0200 Subject: [PATCH] Generic function call tokens fixed --- .../Parser/Binding/Parser/BindingParser.cs | 4 +- .../Binding/Parser/BindingParserNode.cs | 18 +++-- ...ypeOrFunctionReferenceBindingParserNode.cs | 5 +- .../Parser/Binding/BindingParserTests.cs | 65 ++++++++++++++++++- 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/Framework/Framework/Compilation/Parser/Binding/Parser/BindingParser.cs b/src/Framework/Framework/Compilation/Parser/Binding/Parser/BindingParser.cs index d0063a6d68..b31ec48144 100644 --- a/src/Framework/Framework/Compilation/Parser/Binding/Parser/BindingParser.cs +++ b/src/Framework/Framework/Compilation/Parser/Binding/Parser/BindingParser.cs @@ -638,7 +638,7 @@ private BindingParserNode ReadIdentifierExpression(bool onlyTypeName) Read(); var member = ReadIdentifierNameExpression(); if (expression is TypeOrFunctionReferenceBindingParserNode typeOrFunction) - expression = typeOrFunction.ToTypeReference(); + expression = CreateNode(typeOrFunction.ToTypeReference(), startIndex); expression = CreateNode(new MemberAccessBindingParserNode(expression, member), startIndex); } @@ -653,7 +653,7 @@ private BindingParserNode ReadIdentifierExpression(bool onlyTypeName) else if (!onlyTypeName && next.Type == BindingTokenType.OpenParenthesis) { if (expression is TypeOrFunctionReferenceBindingParserNode typeOrFunction) - expression = typeOrFunction.ToFunctionReference(); + expression = CreateNode(typeOrFunction.ToFunctionReference(), startIndex); expression = ReadFunctionCall(startIndex, expression); } diff --git a/src/Framework/Framework/Compilation/Parser/Binding/Parser/BindingParserNode.cs b/src/Framework/Framework/Compilation/Parser/Binding/Parser/BindingParserNode.cs index 08edd72480..34a9d487b2 100644 --- a/src/Framework/Framework/Compilation/Parser/Binding/Parser/BindingParserNode.cs +++ b/src/Framework/Framework/Compilation/Parser/Binding/Parser/BindingParserNode.cs @@ -47,14 +47,24 @@ public virtual IEnumerable EnumerateNodes() public abstract string ToDisplayString(); - internal void TransferTokens(BindingParserNode sourceNode) + internal void TransferTokens(BindingParserNode sourceNode, int? startPosition = null) { - Length = sourceNode.Length; - StartPosition = sourceNode.StartPosition; + + StartPosition = startPosition ?? sourceNode.StartPosition; + Length = 0; + Tokens.Clear(); Tokens.Capacity = sourceNode.Tokens.Capacity; + for (int i = 0; i < sourceNode.Tokens.Count; i++) - Tokens.Add(sourceNode.Tokens[i]); + { + var token = sourceNode.Tokens[i]; + if ((startPosition ?? 0) <= token.StartPosition) + { + Length += token.Length; + Tokens.Add(token); + } + } } } } diff --git a/src/Framework/Framework/Compilation/Parser/Binding/Parser/TypeOrFunctionReferenceBindingParserNode.cs b/src/Framework/Framework/Compilation/Parser/Binding/Parser/TypeOrFunctionReferenceBindingParserNode.cs index 07a2478b44..abd790dc99 100644 --- a/src/Framework/Framework/Compilation/Parser/Binding/Parser/TypeOrFunctionReferenceBindingParserNode.cs +++ b/src/Framework/Framework/Compilation/Parser/Binding/Parser/TypeOrFunctionReferenceBindingParserNode.cs @@ -54,7 +54,10 @@ public BindingParserNode ToFunctionReference() if (TypeArguments.Count == 0) return memberAccess; - var genericName = new GenericNameBindingParserNode(memberAccess.MemberNameExpression.NameToken, TypeArguments); + var name = memberAccess.MemberNameExpression.NameToken; + var genericName = new GenericNameBindingParserNode(name, TypeArguments); + genericName.TransferTokens(this, name.StartPosition); + memberAccess.MemberNameExpression = genericName; return memberAccess; } diff --git a/src/Tests/Parser/Binding/BindingParserTests.cs b/src/Tests/Parser/Binding/BindingParserTests.cs index d6ccf42000..3103964df3 100644 --- a/src/Tests/Parser/Binding/BindingParserTests.cs +++ b/src/Tests/Parser/Binding/BindingParserTests.cs @@ -937,9 +937,10 @@ public void BindingParser_Lambda_WithTypeInfo_SingleParameter(string expr, strin var parameters = lambda.ParameterExpressions; Assert.AreEqual(1, parameters.Count); - Assert.AreEqual(type, parameters[0].Type.ToDisplayString()); - Assert.AreEqual("arg", parameters[0].Name.ToDisplayString()); - Assert.AreEqual("Method(arg)", body.ToDisplayString()); + + AssertNode(parameters[0].Type, type, 1, type.Length+1); + AssertNode(parameters[0].Name, "arg", type.Length + 2, 3); + AssertNode(body, "Method(arg)", type.Length + 10, 11); } [TestMethod] @@ -1346,6 +1347,64 @@ public void BindingParser_GenericTypePropertyDeclaration() AssertNode(arg2, "System.String", 17, 13); } + [TestMethod] + public void BindingParser_GenericMethodCall_SimpleName() + { + var source = "GetType(StringProp)"; + var parser = bindingParserNodeFactory.SetupParser(source); + var root = parser.ReadExpression().As(); + + var generic = root.TargetExpression.As(); + var typeArgument = generic.TypeArguments[0].As(); + + AssertNode(root, source, 0, source.Length); + AssertNode(generic, "GetType", 0, source.Length-12); + AssertNode(typeArgument, "string", 8, 6); + } + + [TestMethod] + public void BindingParser_GenericMethodCall_MemberAccessName() + { + var source = "service.GetType(StringProp)"; + + var parser = bindingParserNodeFactory.SetupParser(source); + var root = parser.ReadExpression().As(); + + var memberAccess = root.TargetExpression.As(); + var generic = memberAccess.MemberNameExpression.As(); + var typeArgument = generic.TypeArguments[0].As(); + + AssertNode(root, source, 0, source.Length); + AssertNode(memberAccess, "service.GetType", 0, source.Length-12); + AssertNode(generic, "GetType", 8, source.Length - 20); + + AssertNode(typeArgument, "string?", 16, 7); + + } + + [TestMethod] + public void BindingParser_GenericMethodCall_MultipleGenericArguments() + { + var source = "_this.Modal.GetType(StringProp)"; + + var parser = bindingParserNodeFactory.SetupParser(source); + var root = parser.ReadExpression().As(); + + var memberAccess1 = root.TargetExpression.As(); + var memberAccess2 = memberAccess1.TargetExpression.As(); + var generic = memberAccess1.MemberNameExpression.As(); + var typeArgument1 = generic.TypeArguments[0].As(); + var typeArgument2 = generic.TypeArguments[1].As(); + + AssertNode(root, source, 0, source.Length); + AssertNode(memberAccess1, "_this.Modal.GetType", 0, source.Length - 12); + AssertNode(memberAccess2, "_this.Modal", 0, 11); + AssertNode(generic, "GetType", 12, 31); + + AssertNode(typeArgument1, "string?", 20, 7); + AssertNode(typeArgument2, "System.String", 29, 13); + } + private static void AssertNode(BindingParserNode elementType, string expectedDisplayString, int start, int length) { Assert.AreEqual(expectedDisplayString, elementType.ToDisplayString(), $"Node {elementType.GetType().Name}: display string incorrect.");