diff --git a/src/Nest/Resolvers/PropertyNameResolver.cs b/src/Nest/Resolvers/PropertyNameResolver.cs index a650668ae64..b87f37c4dd3 100644 --- a/src/Nest/Resolvers/PropertyNameResolver.cs +++ b/src/Nest/Resolvers/PropertyNameResolver.cs @@ -8,6 +8,8 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Collections.Concurrent; +using System.Collections.ObjectModel; +using System.ComponentModel; namespace Nest.Resolvers { @@ -130,9 +132,12 @@ protected override Expression VisitMethodCall(MethodCallExpression m, Stack( + new List {{m.Arguments.First()}} + ); + base.VisitExpressionList(callingMember, stack, properties); + return m; } else if (m.Method.Name == "FullyQualified" && m.Arguments.Any()) { @@ -142,20 +147,21 @@ protected override Expression VisitMethodCall(MethodCallExpression m, Stack).IsAssignableFrom(t) + || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof (IDictionary<,>)); + + if (!isDict) { return base.VisitMethodCall(m, stack, properties); } - var lastArg = m.Arguments.Last(); - var constantExpression = lastArg as ConstantExpression; - var value = constantExpression != null - ? constantExpression.Value.ToString() - : Expression.Lambda(lastArg).Compile().DynamicInvoke().ToString(); - stack.Push(value); + VisitConstantOrVariable(m, stack); Visit(m.Object, stack, properties); return m; } - if (IsLinqOperator(m.Method)) + else if (IsLinqOperator(m.Method)) { for (int i = 1; i < m.Arguments.Count; i++) { @@ -166,6 +172,16 @@ protected override Expression VisitMethodCall(MethodCallExpression m, Stack stack) + { + var lastArg = m.Arguments.Last(); + var constantExpression = lastArg as ConstantExpression; + var value = constantExpression != null + ? constantExpression.Value.ToString() + : Expression.Lambda(lastArg).Compile().DynamicInvoke().ToString(); + stack.Push(value); + } private static bool IsLinqOperator(MethodInfo method) { diff --git a/src/Tests/Nest.Tests.Unit/Internals/Inferno/PropertyPathResolverTests.cs b/src/Tests/Nest.Tests.Unit/Internals/Inferno/PropertyPathResolverTests.cs new file mode 100644 index 00000000000..7a316ec15a5 --- /dev/null +++ b/src/Tests/Nest.Tests.Unit/Internals/Inferno/PropertyPathResolverTests.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using FluentAssertions; +using Nest.Resolvers; +using NUnit.Framework; +using Nest.Tests.MockData.Domain; + +namespace Nest.Tests.Unit.Internals.Inferno +{ + [TestFixture] + public class PropertyPathResolverTests + { + private class CustomDict : Dictionary { } + + private class DomainObject + { + public string Name { get; set; } + public IDictionary Dictionary { get; set; } + public CustomDict CustomDict { get; set; } + public IList Collection { get; set; } + + } + + private readonly ElasticInferrer _infer; + private readonly string _variable = "vari"; + + public PropertyPathResolverTests() + { + _infer = TestElasticClient.Client.Infer; + } + + private string P(Expression> path) + { + return this._infer.PropertyPath(Property.Path(path)); + } + + [Test] + public void SimpleProperty() + { + P(p => p.Name).Should().Be("name"); + } + + [Test] + public void SuffixOnPropery() + { + P(p => p.Name.Suffix("sort")).Should().Be("name.sort"); + } + + [Test] + public void IndexOnCollection() + { + P(p => p.Collection[0]).Should().Be("collection"); + } + + [Test] + public void IndexOnCollectionProperty() + { + P(p => p.Collection[0].Name).Should().Be("collection.name"); + } + + [Test] + public void FirstOnCollection() + { + P(p => p.Collection.First()).Should().Be("collection"); + } + + [Test] + public void FirstOnCollectionProperty() + { + P(p => p.Collection.First().Name).Should().Be("collection.name"); + } + + [Test] + public void Dictionary() + { + P(p => p.Dictionary["hardcoded"]).Should().Be("dictionary.hardcoded"); + } + + [Test] + public void DictionaryPropery() + { + P(p => p.Dictionary["hardcoded"].Name).Should().Be("dictionary.hardcoded.name"); + } + + //Test variables + [Test] + public void DictionaryVariableKey() + { + P(p => p.Dictionary[_variable]).Should().Be("dictionary.vari"); + } + + [Test] + public void DictionaryVariableKeyProperty() + { + P(p => p.Dictionary[_variable].Name).Should().Be("dictionary.vari.name"); + } + + [Test] + public void CustomDictionary() + { + P(p => p.CustomDict["hardcoded"]).Should().Be("customDict.hardcoded"); + } + + [Test] + public void CustomDictionaryPropery() + { + P(p => p.CustomDict["hardcoded"].Name).Should().Be("customDict.hardcoded.name"); + } + + //Test variables + + [Test] + public void CustomDictionaryVariableKey() + { + P(p => p.CustomDict[_variable]).Should().Be("customDict.vari"); + } + + [Test] + public void CustomDictionaryVariableKeyProperty() + { + P(p => p.CustomDict[_variable].Name).Should().Be("customDict.vari.name"); + } + + //Test suffixes + [Test] + public void PropertySuffix() + { + P(p => p.Name.Suffix("suffix")).Should().Be("name.suffix"); + } + + [Test] + public void DictionarySuffix() + { + P(p => p.Dictionary["hardcoded"].Suffix("suffix")).Should().Be("dictionary.hardcoded.suffix"); + } + + [Test] + public void FirstOnCollectionSuffix() + { + P(p => p.Collection.First().Suffix("suffix")).Should().Be("collection.suffix"); + } + + [Test] + public void IndexOnCollectionSuffix() + { + P(p => p.Collection[0].Suffix("suffix")).Should().Be("collection.suffix"); + } + + [Test] + public void CollectionSuffix() + { + P(p => p.Collection.Suffix("suffix")).Should().Be("collection.suffix"); + } + + [Test] + public void PropertySuffixVariable() + { + P(p => p.Name.Suffix(_variable)).Should().Be("name.vari"); + } + + [Test] + public void PropertySuffixLocalVariable() + { + var prop = "propXY12"; + P(p => p.Name.Suffix(prop)).Should().Be("name." + prop); + } + + //Fully qualified tests + //TODO remove in 2.0 as type.properties are gonna be removed in elasticsearch 2.0 + + [Test] + public void PropertySuffixVariableFullyQualified() + { + P(p => p.FullyQualified().Name.Suffix(_variable)).Should().Be("domainobject.name.vari"); + } + } +} diff --git a/src/Tests/Nest.Tests.Unit/Internals/Inferno/PropertyVisitorTests.cs b/src/Tests/Nest.Tests.Unit/Internals/Inferno/PropertyVisitorTests.cs deleted file mode 100644 index 3143659d849..00000000000 --- a/src/Tests/Nest.Tests.Unit/Internals/Inferno/PropertyVisitorTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NUnit.Framework; -using Nest.Tests.MockData.Domain; - -namespace Nest.Tests.Unit.Internals.Inferno -{ - [TestFixture] - public class PropertyVisitorTests - { - [Test] - public void SuffixMakesItIntoPropertyName() - { - var s = new SearchDescriptor() - .From(0) - .Size(10) - .Query(q => q.Term(f => f.Name.Suffix("sort"), "value")); - var json = TestElasticClient.Serialize(s); - var expected = @"{ from: 0, size: 10, - query: { - term: { - ""name.sort"": { - value: ""value"" - } - } - } - }"; - Assert.True(json.JsonEquals(expected), json); - } - } -} diff --git a/src/Tests/Nest.Tests.Unit/Nest.Tests.Unit.csproj b/src/Tests/Nest.Tests.Unit/Nest.Tests.Unit.csproj index 6a55438fe52..f131b75c189 100644 --- a/src/Tests/Nest.Tests.Unit/Nest.Tests.Unit.csproj +++ b/src/Tests/Nest.Tests.Unit/Nest.Tests.Unit.csproj @@ -501,7 +501,7 @@ - +