public void NameIsSetCorrectly() { var collectionFunctionCallNode = new CollectionFunctionCallNode("stuff", HardCodedTestModel.GetHasDogOverloads(), null, collectionTypeReference, null); collectionFunctionCallNode.Name.Should().Be("stuff"); }
public void ArgumentsSetCorrectly() { var collectionFunctionCallNode = new CollectionFunctionCallNode("stuff", new List<IEdmFunction>() { HardCodedTestModel.GetFunctionForHasJob() }, new QueryNode[] { new ConstantNode(1) }, collectionTypeReference, null); collectionFunctionCallNode.Parameters.Should().HaveCount(1); collectionFunctionCallNode.Parameters.ElementAt(0).ShouldBeConstantQueryNode(1); }
private bool TryBindIdentifier(string identifier, IEnumerable<FunctionParameterToken> arguments, QueryNode parent, BindingState state, out QueryNode boundFunction) { boundFunction = null; IEdmType bindingType = null; var singleValueParent = parent as SingleValueNode; if (singleValueParent != null) { if (singleValueParent.TypeReference != null) { bindingType = singleValueParent.TypeReference.Definition; } } else { var collectionValueParent = parent as CollectionNode; if (collectionValueParent != null) { bindingType = collectionValueParent.CollectionType.Definition; } } if (!UriEdmHelpers.IsBindingTypeValid(bindingType)) { return false; } // All functions should be fully qualified, if they aren't they they aren't functions. // When using extension, there may be function call with unqualified name. So loose the restriction here. if (identifier.IndexOf(".", StringComparison.Ordinal) == -1 && this.Resolver.GetType() == typeof(ODataUriResolver)) { return false; } IEdmOperation operation; List<FunctionParameterToken> syntacticArguments = arguments == null ? new List<FunctionParameterToken>() : arguments.ToList(); if (!FunctionOverloadResolver.ResolveOperationFromList(identifier, syntacticArguments.Select(ar => ar.ParameterName).ToList(), bindingType, state.Model, out operation, this.Resolver)) { // TODO: FunctionOverloadResolver.ResolveOperationFromList() looks up the function by parameter names, but it shouldn't ignore parameter types. (test case ParseFilter_AliasInFunction_PropertyAsValue_TypeMismatch should fail) return false; } if (singleValueParent != null && singleValueParent.TypeReference == null) { // if the parent exists, but has no type information, then we're in open type land, and we // shouldn't go any farther. throw new ODataException(ODataErrorStrings.FunctionCallBinder_CallingFunctionOnOpenProperty(identifier)); } if (operation.IsAction()) { return false; } IEdmFunction function = (IEdmFunction)operation; // TODO: $filter $orderby parameter expression which contains complex or collection should NOT be supported in this way // but should be parsed into token tree, and binded to node tree: parsedParameters.Select(p => this.bindMethod(p)); ICollection<FunctionParameterToken> parsedParameters = HandleComplexOrCollectionParameterValueIfExists(state.Configuration.Model, function, syntacticArguments, state.Configuration.Resolver.EnableCaseInsensitive); IEnumerable<QueryNode> boundArguments = parsedParameters.Select(p => this.bindMethod(p)); boundArguments = boundArguments.ToList(); // force enumerable to run : will immediately evaluate all this.bindMethod(p). IEdmTypeReference returnType = function.ReturnType; IEdmEntitySetBase returnSet = null; var singleEntityNode = parent as SingleEntityNode; if (singleEntityNode != null) { returnSet = function.GetTargetEntitySet(singleEntityNode.NavigationSource, state.Model); } string functionName = function.FullName(); if (returnType.IsEntity()) { boundFunction = new SingleEntityFunctionCallNode(functionName, new[] { function }, boundArguments, (IEdmEntityTypeReference)returnType.Definition.ToTypeReference(), returnSet, parent); } else if (returnType.IsEntityCollection()) { IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType; boundFunction = new EntityCollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, returnSet, parent); } else if (returnType.IsCollection()) { IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType; boundFunction = new CollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, parent); } else { boundFunction = new SingleValueFunctionCallNode(functionName, new[] { function }, boundArguments, returnType, parent); } return true; }
public void FunctionImportsAreSetCorrectly() { var collectionFunctionCallNode = new CollectionFunctionCallNode("stuff", HardCodedTestModel.GetHasDogOverloads(), null, collectionTypeReference, null); collectionFunctionCallNode.Functions.Should().ContainExactly(HardCodedTestModel.GetHasDogOverloads()); }
public void NameIsSetCorrectly() { var collectionFunctionCallNode = new CollectionFunctionCallNode("stuff", HardCodedTestModel.GetHasDogOverloads(), null, collectionTypeReference, null); Assert.Equal("stuff", collectionFunctionCallNode.Name); }
/// <summary> /// Visit a CollectionFunctionCallNode /// </summary> /// <param name="nodeIn">the node to visit</param> /// <returns>Defined by the implementer</returns> public virtual T Visit(CollectionFunctionCallNode nodeIn) { throw new NotImplementedException(); }
public override T Visit(CollectionFunctionCallNode nodeIn) => DebuggerBreakVisited(nodeIn);
public static CollectionFunctionCallNode ShouldHaveConstantParameter <TValue>(this CollectionFunctionCallNode functionCallNode, string name, TValue value) { Assert.NotNull(functionCallNode); functionCallNode.Parameters.ContainItemsAssignableTo <NamedFunctionParameterNode>(); var argument = functionCallNode.Parameters.OfType <NamedFunctionParameterNode>().SingleOrDefault(p => p.Name == name); Assert.NotNull(argument); argument.Value.ShouldBeConstantQueryNode(value); return(functionCallNode); }
private bool TryBindIdentifier(string identifier, IEnumerable <FunctionParameterToken> arguments, QueryNode parent, BindingState state, out QueryNode boundFunction) { boundFunction = null; IEdmType bindingType = null; var singleValueParent = parent as SingleValueNode; if (singleValueParent != null) { if (singleValueParent.TypeReference != null) { bindingType = singleValueParent.TypeReference.Definition; } } else { var collectionValueParent = parent as CollectionNode; if (collectionValueParent != null) { bindingType = collectionValueParent.CollectionType.Definition; } } if (!UriEdmHelpers.IsBindingTypeValid(bindingType)) { return(false); } // All functions should be fully qualified, if they aren't they they aren't functions. // When using extension, there may be function call with unqualified name. So loose the restriction here. if (identifier.IndexOf(".", StringComparison.Ordinal) == -1 && this.Resolver.GetType() == typeof(ODataUriResolver)) { return(false); } IEdmOperation operation; List <FunctionParameterToken> syntacticArguments = arguments == null ? new List <FunctionParameterToken>() : arguments.ToList(); if (!FunctionOverloadResolver.ResolveOperationFromList(identifier, syntacticArguments.Select(ar => ar.ParameterName).ToList(), bindingType, state.Model, out operation, this.Resolver)) { // TODO: FunctionOverloadResolver.ResolveOperationFromList() looks up the function by parameter names, but it shouldn't ignore parameter types. (test case ParseFilter_AliasInFunction_PropertyAsValue_TypeMismatch should fail) return(false); } if (singleValueParent != null && singleValueParent.TypeReference == null) { // if the parent exists, but has no type information, then we're in open type land, and we // shouldn't go any farther. throw new ODataException(ODataErrorStrings.FunctionCallBinder_CallingFunctionOnOpenProperty(identifier)); } if (operation.IsAction()) { return(false); } IEdmFunction function = (IEdmFunction)operation; // TODO: $filter $orderby parameter expression which contains complex or collection should NOT be supported in this way // but should be parsed into token tree, and binded to node tree: parsedParameters.Select(p => this.bindMethod(p)); ICollection <FunctionParameterToken> parsedParameters = HandleComplexOrCollectionParameterValueIfExists(state.Configuration.Model, function, syntacticArguments, state.Configuration.Resolver.EnableCaseInsensitive); IEnumerable <QueryNode> boundArguments = parsedParameters.Select(p => this.bindMethod(p)); boundArguments = boundArguments.ToList(); // force enumerable to run : will immediately evaluate all this.bindMethod(p). IEdmTypeReference returnType = function.ReturnType; IEdmEntitySetBase returnSet = null; var singleEntityNode = parent as SingleEntityNode; if (singleEntityNode != null) { returnSet = function.GetTargetEntitySet(singleEntityNode.NavigationSource, state.Model); } string functionName = function.FullName(); if (returnType.IsEntity()) { boundFunction = new SingleEntityFunctionCallNode(functionName, new[] { function }, boundArguments, (IEdmEntityTypeReference)returnType.Definition.ToTypeReference(), returnSet, parent); } else if (returnType.IsEntityCollection()) { IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType; boundFunction = new EntityCollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, returnSet, parent); } else if (returnType.IsCollection()) { IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType; boundFunction = new CollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, parent); } else { boundFunction = new SingleValueFunctionCallNode(functionName, new[] { function }, boundArguments, returnType, parent); } return(true); }
/// <summary> /// Visit a CollectionFunctionCallNode /// </summary> /// <param name="nodeIn">The node to visit</param> /// <returns>The translated expression</returns> public override Expression Visit(CollectionFunctionCallNode nodeIn) { throw new NotImplementedException(); }
public override IEnumerable <string> Visit(CollectionFunctionCallNode nodeIn) { return(nodeIn.Source.Accept(this)); }
public override object Visit(CollectionFunctionCallNode nodeIn) { return(null); }
public static AndConstraint <CollectionFunctionCallNode> ShouldHaveConstantParameter <TValue>(this CollectionFunctionCallNode functionCallNode, string name, TValue value) { functionCallNode.Should().NotBeNull(); functionCallNode.Parameters.Should().ContainItemsAssignableTo <NamedFunctionParameterNode>(); var argument = functionCallNode.Parameters.Cast <NamedFunctionParameterNode>().SingleOrDefault(p => p.Name == name); argument.Should().NotBeNull(); argument.Value.ShouldBeConstantQueryNode(value); return(new AndConstraint <CollectionFunctionCallNode>(functionCallNode)); }
public void ItemTypeSetCorrectly() { var collectionFunctionCallNode = new CollectionFunctionCallNode("stuff", new List<IEdmFunction>() { HardCodedTestModel.GetFunctionForHasJob() }, new QueryNode[] { new ConstantNode(1) }, collectionTypeReference, null); collectionFunctionCallNode.ItemType.Should().BeSameAs(this.itemTypeReference); }
public void FunctionImportsAreSetCorrectly() { var collectionFunctionCallNode = new CollectionFunctionCallNode("stuff", HardCodedTestModel.GetHasDogOverloads(), null, collectionTypeReference, null); collectionFunctionCallNode.Functions.ContainExactly(HardCodedTestModel.GetHasDogOverloads()); }
public void KindIsSetCorrectly() { var collectionFunctionCallNode = new CollectionFunctionCallNode("stuff", new List<IEdmFunction>() { HardCodedTestModel.GetFunctionForHasJob() }, new QueryNode[] { new ConstantNode(1) }, collectionTypeReference, null); collectionFunctionCallNode.Kind.Should().Be(QueryNodeKind.CollectionFunctionCall); }
private bool TryBindIdentifier(string identifier, IEnumerable <FunctionParameterToken> arguments, QueryNode parent, BindingState state, out QueryNode boundFunction) { boundFunction = null; IEdmType bindingType = null; var singleValueParent = parent as SingleValueNode; if (singleValueParent != null) { if (singleValueParent.TypeReference != null) { bindingType = singleValueParent.TypeReference.Definition; } } else { var collectionValueParent = parent as CollectionNode; if (collectionValueParent != null) { bindingType = collectionValueParent.CollectionType.Definition; } } if (!UriEdmHelpers.IsBindingTypeValid(bindingType)) { return(false); } IEdmFunctionImport functionImport; List <FunctionParameterToken> syntacticArguments = arguments == null ? new List <FunctionParameterToken>() : arguments.ToList(); if (!FunctionOverloadResolver.ResolveFunctionsFromList(identifier, syntacticArguments.Select(ar => ar.ParameterName).ToList(), bindingType, state.Model, out functionImport)) { return(false); } if (singleValueParent != null && singleValueParent.TypeReference == null) { // if the parent exists, but has no type information, then we're in open type land, and we // shouldn't go any farther. throw new ODataException(ODataErrorStrings.FunctionCallBinder_CallingFunctionOnOpenProperty(identifier)); } if (functionImport.IsSideEffecting) { return(false); } ICollection <FunctionParameterToken> parsedParameters; if (!FunctionParameterParser.TryParseFunctionParameters(syntacticArguments, state.Configuration, functionImport, out parsedParameters)) { return(false); } IEnumerable <QueryNode> boundArguments = parsedParameters.Select(p => this.bindMethod(p)); IEdmTypeReference returnType = functionImport.ReturnType; IEdmEntitySet returnSet = null; var singleEntityNode = parent as SingleEntityNode; if (singleEntityNode != null) { returnSet = functionImport.GetTargetEntitySet(singleEntityNode.EntitySet, state.Model); } if (returnType.IsEntity()) { boundFunction = new SingleEntityFunctionCallNode(identifier, new[] { functionImport }, boundArguments, (IEdmEntityTypeReference)returnType.Definition.ToTypeReference(), returnSet, parent); } else if (returnType.IsEntityCollection()) { IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType; boundFunction = new EntityCollectionFunctionCallNode(identifier, new[] { functionImport }, boundArguments, collectionTypeReference, returnSet, parent); } else if (returnType.IsCollection()) { IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType; boundFunction = new CollectionFunctionCallNode(identifier, new[] { functionImport }, boundArguments, collectionTypeReference, parent); } else { boundFunction = new SingleValueFunctionCallNode(identifier, new[] { functionImport }, boundArguments, returnType, parent); } return(true); }