Skip to content

Commit 6c18761

Browse files
committed
Merge pull request #1202 from retailcoder/next
More resolver tests, and fix for #1193
2 parents b2e94ae + 896016f commit 6c18761

File tree

2 files changed

+238
-4
lines changed

2 files changed

+238
-4
lines changed

Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,30 @@ private bool IsStaticClass(Declaration declaration)
11071107
&& (declaration.ParentDeclaration.HasPredeclaredId || declaration.IsBuiltIn);
11081108
}
11091109

1110+
private readonly IReadOnlyList<string> SpecialCasedTokens = new[]{
1111+
Tokens.Error,
1112+
Tokens.Hex,
1113+
Tokens.Oct,
1114+
Tokens.Str,
1115+
Tokens.CurDir,
1116+
Tokens.Command,
1117+
Tokens.Environ,
1118+
Tokens.Chr,
1119+
Tokens.ChrW,
1120+
Tokens.Format,
1121+
Tokens.LCase,
1122+
Tokens.Left,
1123+
Tokens.LeftB,
1124+
Tokens.LTrim,
1125+
Tokens.Mid,
1126+
Tokens.MidB,
1127+
Tokens.Trim,
1128+
Tokens.Right,
1129+
Tokens.RightB,
1130+
Tokens.RTrim,
1131+
Tokens.UCase
1132+
};
1133+
11101134
private Declaration FindProjectScopeDeclaration(string identifierName, Declaration localScope = null, ContextAccessorType accessorType = ContextAccessorType.GetValueOrReference, bool hasStringQualifier = false)
11111135
{
11121136
var matches = _declarationFinder.MatchName(identifierName).Where(item =>
@@ -1115,7 +1139,7 @@ private Declaration FindProjectScopeDeclaration(string identifierName, Declarati
11151139
|| IsStaticClass(item)
11161140
|| item.ParentScopeDeclaration.Equals(localScope)).ToList();
11171141

1118-
if (matches.Count == 1)
1142+
if (matches.Count == 1 && !SpecialCasedTokens.Contains(matches.Single().IdentifierName))
11191143
{
11201144
return matches.Single();
11211145
}
@@ -1132,7 +1156,7 @@ private Declaration FindProjectScopeDeclaration(string identifierName, Declarati
11321156
}
11331157

11341158
result = matches.Where(item => IsBuiltInDeclarationInScope(item, localScope)).ToList();
1135-
if (result.Count == 1)
1159+
if (result.Count == 1 && !SpecialCasedTokens.Contains(matches.Single().IdentifierName))
11361160
{
11371161
return result.SingleOrDefault();
11381162
}

RubberduckTests/Grammar/ResolverTests.cs

Lines changed: 212 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using Microsoft.VisualStudio.TestTools.UnitTesting;
55
using Rubberduck.Parsing.Symbols;
66
using Rubberduck.Parsing.VBA;
7-
using RubberduckTests.Inspections;
87
using RubberduckTests.Mocks;
98

109
namespace RubberduckTests.Grammar
@@ -31,7 +30,7 @@ private RubberduckParserState Resolve(string code, vbext_ComponentType moduleTyp
3130
private RubberduckParserState Resolve(params string[] classes)
3231
{
3332
var builder = new MockVbeBuilder();
34-
var projectBuilder = builder.ProjectBuilder("TestProject", vbext_ProjectProtection.vbext_pp_none);
33+
var projectBuilder = builder.ProjectBuilder("TestProject1", vbext_ProjectProtection.vbext_pp_none);
3534
for (var i = 0; i < classes.Length; i++)
3635
{
3736
projectBuilder.AddComponent("Class" + (i + 1), vbext_ComponentType.vbext_ct_ClassModule, classes[i]);
@@ -971,6 +970,217 @@ End Sub
971970
Assert.AreEqual(string.Empty, usage.Annotations);
972971
}
973972

973+
[TestMethod]
974+
public void GivenUDT_NamedAfterProject_LocalResolvesToUDT()
975+
{
976+
var code = @"
977+
Private Type TestProject1
978+
Foo As Integer
979+
Bar As String
980+
End Type
981+
982+
Public Sub DoSomething()
983+
Dim Foo As TestProject1
984+
Foo.Bar = ""DoSomething""
985+
Foo.Foo = 42
986+
End Sub
987+
";
988+
var state = Resolve(code);
989+
990+
var declaration = state.AllUserDeclarations.Single(item =>
991+
item.DeclarationType == DeclarationType.UserDefinedType);
992+
993+
if (declaration.ProjectName != declaration.IdentifierName)
994+
{
995+
Assert.Inconclusive("UDT should be named after project.");
996+
}
997+
998+
var usage = declaration.References.SingleOrDefault();
999+
1000+
Assert.IsNotNull(usage);
1001+
}
1002+
1003+
[TestMethod]
1004+
public void GivenUDT_NamedAfterProject_FieldResolvesToUDT_EvenIfHiddenByLocal()
1005+
{
1006+
var code = @"
1007+
Private Type TestProject1
1008+
Foo As Integer
1009+
Bar As String
1010+
End Type
1011+
1012+
Private Foo As TestProject1
1013+
1014+
Public Sub DoSomething()
1015+
Dim Foo As TestProject1
1016+
Foo.Bar = ""DoSomething""
1017+
Foo.Foo = 42
1018+
End Sub
1019+
";
1020+
var state = Resolve(code);
1021+
1022+
var declaration = state.AllUserDeclarations.Single(item =>
1023+
item.DeclarationType == DeclarationType.UserDefinedType);
9741024

1025+
if (declaration.ProjectName != declaration.IdentifierName)
1026+
{
1027+
Assert.Inconclusive("UDT should be named after project.");
1028+
}
1029+
1030+
var usages = declaration.References;
1031+
1032+
Assert.AreEqual(2, usages.Count());
1033+
}
1034+
1035+
[TestMethod]
1036+
public void GivenLocalVariable_NamedAfterUDTMember_ResolvesToLocalVariable()
1037+
{
1038+
var code = @"
1039+
Private Type TestProject1
1040+
Foo As Integer
1041+
Bar As String
1042+
End Type
1043+
1044+
Public Sub DoSomething()
1045+
Dim Foo As TestProject1
1046+
Foo.Bar = ""DoSomething""
1047+
Foo.Foo = 42
1048+
End Sub
1049+
";
1050+
var state = Resolve(code);
1051+
1052+
var declaration = state.AllUserDeclarations.Single(item =>
1053+
item.DeclarationType == DeclarationType.Variable);
1054+
1055+
if (declaration.ProjectName != declaration.AsTypeName)
1056+
{
1057+
Assert.Inconclusive("variable should be named after project.");
1058+
}
1059+
var usages = declaration.References;
1060+
1061+
Assert.AreEqual(2, usages.Count());
1062+
}
1063+
1064+
[TestMethod]
1065+
public void GivenLocalVariable_NamedAfterUDTMember_MemberCallResolvesToUDTMember()
1066+
{
1067+
var code = @"
1068+
Private Type TestProject1
1069+
Foo As Integer
1070+
Bar As String
1071+
End Type
1072+
1073+
Public Sub DoSomething()
1074+
Dim Foo As TestProject1
1075+
Foo.Bar = ""DoSomething""
1076+
Foo.Foo = 42
1077+
End Sub
1078+
";
1079+
var state = Resolve(code);
1080+
1081+
var declaration = state.AllUserDeclarations.Single(item =>
1082+
item.DeclarationType == DeclarationType.UserDefinedTypeMember
1083+
&& item.IdentifierName == "Foo");
1084+
1085+
var usages = declaration.References.Where(item =>
1086+
item.ParentScoping.IdentifierName == "DoSomething");
1087+
1088+
Assert.AreEqual(1, usages.Count());
1089+
}
1090+
1091+
[TestMethod]
1092+
public void GivenUDTMember_OfUDTType_ResolvesToDeclaredUDT()
1093+
{
1094+
var code = @"
1095+
Private Type TestProject1
1096+
Foo As Integer
1097+
Bar As String
1098+
End Type
1099+
1100+
Private Type Foo
1101+
Foo As TestProject1
1102+
End Type
1103+
1104+
Public Sub DoSomething()
1105+
Dim Foo As Foo
1106+
Foo.Foo.Bar = ""DoSomething""
1107+
Foo.Foo.Foo = 42
1108+
End Sub
1109+
";
1110+
var state = Resolve(code);
1111+
1112+
var declaration = state.AllUserDeclarations.Single(item =>
1113+
item.DeclarationType == DeclarationType.UserDefinedTypeMember
1114+
&& item.IdentifierName == "Foo"
1115+
&& item.AsTypeName == item.ProjectName
1116+
&& item.IdentifierName == item.ParentDeclaration.IdentifierName);
1117+
1118+
var usages = declaration.References.Where(item =>
1119+
item.ParentScoping.IdentifierName == "DoSomething");
1120+
1121+
Assert.AreEqual(2, usages.Count());
1122+
}
1123+
1124+
[TestMethod]
1125+
public void GivenUDT_NamedAfterModule_LocalAsTypeResolvesToUDT()
1126+
{
1127+
var code = @"
1128+
Private Type TestProject1
1129+
Foo As Integer
1130+
Bar As String
1131+
End Type
1132+
1133+
Private Type TestModule1
1134+
Foo As TestProject1
1135+
End Type
1136+
1137+
Public Sub DoSomething()
1138+
Dim Foo As TestModule1
1139+
Foo.Foo.Bar = ""DoSomething""
1140+
Foo.Foo.Foo = 42
1141+
End Sub
1142+
";
1143+
var state = Resolve(code);
1144+
1145+
var declaration = state.AllUserDeclarations.Single(item =>
1146+
item.DeclarationType == DeclarationType.UserDefinedType
1147+
&& item.IdentifierName == item.ComponentName);
1148+
1149+
var usages = declaration.References.Where(item =>
1150+
item.ParentScoping.IdentifierName == "DoSomething");
1151+
1152+
Assert.AreEqual(1, usages.Count());
1153+
}
1154+
1155+
[TestMethod]
1156+
public void GivenUDTMember_NamedAfterUDTType_NamedAfterModule_LocalAsTypeResolvesToUDT()
1157+
{
1158+
var code = @"
1159+
Private Type TestProject1
1160+
Foo As Integer
1161+
Bar As String
1162+
End Type
1163+
1164+
Private Type TestModule1
1165+
TestModule1 As TestProject1
1166+
End Type
1167+
1168+
Public Sub DoSomething()
1169+
Dim TestModule1 As TestModule1
1170+
TestModule1.TestModule1.Bar = ""DoSomething""
1171+
TestModule1.TestModule1.Foo = 42
1172+
End Sub
1173+
";
1174+
var state = Resolve(code);
1175+
1176+
var declaration = state.AllUserDeclarations.Single(item =>
1177+
item.DeclarationType == DeclarationType.UserDefinedType
1178+
&& item.IdentifierName == item.ComponentName);
1179+
1180+
var usages = declaration.References.Where(item =>
1181+
item.ParentScoping.IdentifierName == "DoSomething");
1182+
1183+
Assert.AreEqual(1, usages.Count());
1184+
}
9751185
}
9761186
}

0 commit comments

Comments
 (0)