Skip to content

Commit 7cb1309

Browse files
committed
Merge pull request #1380 from elastic/feature/variable-suffix
Feature/variable suffix
2 parents a8927ee + 5d03818 commit 7cb1309

File tree

4 files changed

+208
-41
lines changed

4 files changed

+208
-41
lines changed

src/Nest/Resolvers/PropertyNameResolver.cs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using System.Reflection;
99
using System.Runtime.CompilerServices;
1010
using System.Collections.Concurrent;
11+
using System.Collections.ObjectModel;
12+
using System.ComponentModel;
1113

1214
namespace Nest.Resolvers
1315
{
@@ -130,9 +132,12 @@ protected override Expression VisitMethodCall(MethodCallExpression m, Stack<stri
130132
{
131133
if (m.Method.Name == "Suffix" && m.Arguments.Any())
132134
{
133-
var constantExpression = m.Arguments.Last() as ConstantExpression;
134-
if (constantExpression != null)
135-
stack.Push(constantExpression.Value as string);
135+
VisitConstantOrVariable(m, stack);
136+
var callingMember = new ReadOnlyCollection<Expression>(
137+
new List<Expression> {{m.Arguments.First()}}
138+
);
139+
base.VisitExpressionList(callingMember, stack, properties);
140+
return m;
136141
}
137142
else if (m.Method.Name == "FullyQualified" && m.Arguments.Any())
138143
{
@@ -142,20 +147,21 @@ protected override Expression VisitMethodCall(MethodCallExpression m, Stack<stri
142147
}
143148
else if (m.Method.Name == "get_Item" && m.Arguments.Any())
144149
{
145-
if (!typeof(IDictionary).IsAssignableFrom(m.Object.Type))
150+
var t = m.Object.Type;
151+
var isDict =
152+
typeof(IDictionary).IsAssignableFrom(t)
153+
|| typeof(IDictionary<,>).IsAssignableFrom(t)
154+
|| (t.IsGenericType && t.GetGenericTypeDefinition() == typeof (IDictionary<,>));
155+
156+
if (!isDict)
146157
{
147158
return base.VisitMethodCall(m, stack, properties);
148159
}
149-
var lastArg = m.Arguments.Last();
150-
var constantExpression = lastArg as ConstantExpression;
151-
var value = constantExpression != null
152-
? constantExpression.Value.ToString()
153-
: Expression.Lambda(lastArg).Compile().DynamicInvoke().ToString();
154-
stack.Push(value);
160+
VisitConstantOrVariable(m, stack);
155161
Visit(m.Object, stack, properties);
156162
return m;
157163
}
158-
if (IsLinqOperator(m.Method))
164+
else if (IsLinqOperator(m.Method))
159165
{
160166
for (int i = 1; i < m.Arguments.Count; i++)
161167
{
@@ -166,6 +172,16 @@ protected override Expression VisitMethodCall(MethodCallExpression m, Stack<stri
166172
}
167173
return base.VisitMethodCall(m, stack, properties);
168174
}
175+
176+
private static void VisitConstantOrVariable(MethodCallExpression m, Stack<string> stack)
177+
{
178+
var lastArg = m.Arguments.Last();
179+
var constantExpression = lastArg as ConstantExpression;
180+
var value = constantExpression != null
181+
? constantExpression.Value.ToString()
182+
: Expression.Lambda(lastArg).Compile().DynamicInvoke().ToString();
183+
stack.Push(value);
184+
}
169185

170186
private static bool IsLinqOperator(MethodInfo method)
171187
{
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Linq.Expressions;
6+
using FluentAssertions;
7+
using Nest.Resolvers;
8+
using NUnit.Framework;
9+
using Nest.Tests.MockData.Domain;
10+
11+
namespace Nest.Tests.Unit.Internals.Inferno
12+
{
13+
[TestFixture]
14+
public class PropertyPathResolverTests
15+
{
16+
private class CustomDict : Dictionary<string, ElasticsearchProject> { }
17+
18+
private class DomainObject
19+
{
20+
public string Name { get; set; }
21+
public IDictionary<string, ElasticsearchProject> Dictionary { get; set; }
22+
public CustomDict CustomDict { get; set; }
23+
public IList<ElasticsearchProject> Collection { get; set; }
24+
25+
}
26+
27+
private readonly ElasticInferrer _infer;
28+
private readonly string _variable = "vari";
29+
30+
public PropertyPathResolverTests()
31+
{
32+
_infer = TestElasticClient.Client.Infer;
33+
}
34+
35+
private string P(Expression<Func<DomainObject, object>> path)
36+
{
37+
return this._infer.PropertyPath(Property.Path(path));
38+
}
39+
40+
[Test]
41+
public void SimpleProperty()
42+
{
43+
P(p => p.Name).Should().Be("name");
44+
}
45+
46+
[Test]
47+
public void SuffixOnPropery()
48+
{
49+
P(p => p.Name.Suffix("sort")).Should().Be("name.sort");
50+
}
51+
52+
[Test]
53+
public void IndexOnCollection()
54+
{
55+
P(p => p.Collection[0]).Should().Be("collection");
56+
}
57+
58+
[Test]
59+
public void IndexOnCollectionProperty()
60+
{
61+
P(p => p.Collection[0].Name).Should().Be("collection.name");
62+
}
63+
64+
[Test]
65+
public void FirstOnCollection()
66+
{
67+
P(p => p.Collection.First()).Should().Be("collection");
68+
}
69+
70+
[Test]
71+
public void FirstOnCollectionProperty()
72+
{
73+
P(p => p.Collection.First().Name).Should().Be("collection.name");
74+
}
75+
76+
[Test]
77+
public void Dictionary()
78+
{
79+
P(p => p.Dictionary["hardcoded"]).Should().Be("dictionary.hardcoded");
80+
}
81+
82+
[Test]
83+
public void DictionaryPropery()
84+
{
85+
P(p => p.Dictionary["hardcoded"].Name).Should().Be("dictionary.hardcoded.name");
86+
}
87+
88+
//Test variables
89+
[Test]
90+
public void DictionaryVariableKey()
91+
{
92+
P(p => p.Dictionary[_variable]).Should().Be("dictionary.vari");
93+
}
94+
95+
[Test]
96+
public void DictionaryVariableKeyProperty()
97+
{
98+
P(p => p.Dictionary[_variable].Name).Should().Be("dictionary.vari.name");
99+
}
100+
101+
[Test]
102+
public void CustomDictionary()
103+
{
104+
P(p => p.CustomDict["hardcoded"]).Should().Be("customDict.hardcoded");
105+
}
106+
107+
[Test]
108+
public void CustomDictionaryPropery()
109+
{
110+
P(p => p.CustomDict["hardcoded"].Name).Should().Be("customDict.hardcoded.name");
111+
}
112+
113+
//Test variables
114+
115+
[Test]
116+
public void CustomDictionaryVariableKey()
117+
{
118+
P(p => p.CustomDict[_variable]).Should().Be("customDict.vari");
119+
}
120+
121+
[Test]
122+
public void CustomDictionaryVariableKeyProperty()
123+
{
124+
P(p => p.CustomDict[_variable].Name).Should().Be("customDict.vari.name");
125+
}
126+
127+
//Test suffixes
128+
[Test]
129+
public void PropertySuffix()
130+
{
131+
P(p => p.Name.Suffix("suffix")).Should().Be("name.suffix");
132+
}
133+
134+
[Test]
135+
public void DictionarySuffix()
136+
{
137+
P(p => p.Dictionary["hardcoded"].Suffix("suffix")).Should().Be("dictionary.hardcoded.suffix");
138+
}
139+
140+
[Test]
141+
public void FirstOnCollectionSuffix()
142+
{
143+
P(p => p.Collection.First().Suffix("suffix")).Should().Be("collection.suffix");
144+
}
145+
146+
[Test]
147+
public void IndexOnCollectionSuffix()
148+
{
149+
P(p => p.Collection[0].Suffix("suffix")).Should().Be("collection.suffix");
150+
}
151+
152+
[Test]
153+
public void CollectionSuffix()
154+
{
155+
P(p => p.Collection.Suffix("suffix")).Should().Be("collection.suffix");
156+
}
157+
158+
[Test]
159+
public void PropertySuffixVariable()
160+
{
161+
P(p => p.Name.Suffix(_variable)).Should().Be("name.vari");
162+
}
163+
164+
[Test]
165+
public void PropertySuffixLocalVariable()
166+
{
167+
var prop = "propXY12";
168+
P(p => p.Name.Suffix(prop)).Should().Be("name." + prop);
169+
}
170+
171+
//Fully qualified tests
172+
//TODO remove in 2.0 as type.properties are gonna be removed in elasticsearch 2.0
173+
174+
[Test]
175+
public void PropertySuffixVariableFullyQualified()
176+
{
177+
P(p => p.FullyQualified().Name.Suffix(_variable)).Should().Be("domainobject.name.vari");
178+
}
179+
}
180+
}

src/Tests/Nest.Tests.Unit/Internals/Inferno/PropertyVisitorTests.cs

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/Tests/Nest.Tests.Unit/Nest.Tests.Unit.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@
501501
<Compile Include="Core\AttributeBasedMap\BaseAttributeMappingTests.cs" />
502502
<Compile Include="Core\AttributeBasedMap\DeepObjectMappingTests.cs" />
503503
<Compile Include="Properties\AssemblyInfo.cs" />
504-
<Compile Include="Internals\Inferno\PropertyVisitorTests.cs" />
504+
<Compile Include="Internals\Inferno\PropertyPathResolverTests.cs" />
505505
<Compile Include="Search\Highlight\HighlightTests.cs" />
506506
<Compile Include="Search\Query\ConditionLess\ConditionLessTests.cs" />
507507
<Compile Include="Search\Query\ConditionlessBool\ConditionLessBooleanTests.cs" />

0 commit comments

Comments
 (0)