Skip to content

Commit 769a4bb

Browse files
author
Andrin Meier
committed
fix implements should allow class-type-name instead of identifier
1 parent b62455a commit 769a4bb

35 files changed

+12578
-2332
lines changed

RetailCoder.VBE/Inspections/OptionBaseInspection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public override IEnumerable<InspectionResultBase> GetInspectionResults()
2929
return new List<InspectionResultBase>();
3030
}
3131

32-
var issues = options.Where(option => ((VBAParser.OptionBaseStmtContext)option.Context).SHORTLITERAL().GetText() == "1")
32+
var issues = options.Where(option => ((VBAParser.OptionBaseStmtContext)option.Context).numberLiteral().GetText() == "1")
3333
.Select(issue => new OptionBaseInspectionResult(this, issue.QualifiedName.QualifiedModuleName));
3434

3535
return issues;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Antlr4.Runtime;
2+
using Rubberduck.Parsing.Grammar;
3+
using Rubberduck.Parsing.Symbols;
4+
5+
namespace Rubberduck.Parsing.Binding
6+
{
7+
public sealed class BindingService
8+
{
9+
private readonly IBindingContext _typedBindingContext;
10+
11+
public BindingService(IBindingContext typedBindingContext)
12+
{
13+
_typedBindingContext = typedBindingContext;
14+
}
15+
16+
public IBoundExpression Resolve(Declaration module, Declaration parent, string expression)
17+
{
18+
var expr = Parse(expression);
19+
return _typedBindingContext.Resolve(module, parent, expr);
20+
}
21+
22+
private VBAExpressionParser.ExpressionContext Parse(string expression)
23+
{
24+
var stream = new AntlrInputStream(expression);
25+
var lexer = new VBALexer(stream);
26+
var tokens = new CommonTokenStream(lexer);
27+
var parser = new VBAExpressionParser(tokens);
28+
parser.AddErrorListener(new ExceptionErrorListener());
29+
var tree = parser.startRule();
30+
return tree.expression();
31+
}
32+
}
33+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Antlr4.Runtime;
2+
using Rubberduck.Parsing.Symbols;
3+
4+
namespace Rubberduck.Parsing.Binding
5+
{
6+
public abstract class BoundExpression : IBoundExpression
7+
{
8+
private readonly Declaration _referencedDeclaration;
9+
private readonly ExpressionClassification _classification;
10+
private readonly ParserRuleContext _context;
11+
12+
public BoundExpression(Declaration referencedDeclaration, ExpressionClassification classification, ParserRuleContext context)
13+
{
14+
_referencedDeclaration = referencedDeclaration;
15+
_classification = classification;
16+
_context = context;
17+
}
18+
19+
public ExpressionClassification Classification
20+
{
21+
get
22+
{
23+
return _classification;
24+
}
25+
}
26+
27+
public Declaration ReferencedDeclaration
28+
{
29+
get
30+
{
31+
return _referencedDeclaration;
32+
}
33+
}
34+
35+
public ParserRuleContext Context
36+
{
37+
get
38+
{
39+
return _context;
40+
}
41+
}
42+
}
43+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace Rubberduck.Parsing.Binding
2+
{
3+
public enum ExpressionClassification
4+
{
5+
Value,
6+
Variable,
7+
Property,
8+
Function,
9+
Subroutine,
10+
Unbound,
11+
Project,
12+
ProceduralModule,
13+
Type
14+
}
15+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using Rubberduck.Parsing.Grammar;
2+
3+
namespace Rubberduck.Parsing.Binding
4+
{
5+
public static class ExpressionName
6+
{
7+
public static string GetName(VBAExpressionParser.NameContext context)
8+
{
9+
string name;
10+
if (context.untypedName() != null)
11+
{
12+
name = context.untypedName().GetText();
13+
}
14+
else
15+
{
16+
name = context.typedName().typedNameValue().GetText();
17+
}
18+
return name;
19+
}
20+
21+
public static string GetName(VBAExpressionParser.ReservedIdentifierNameContext context)
22+
{
23+
string name;
24+
if (context.reservedUntypedName() != null)
25+
{
26+
name = context.reservedUntypedName().GetText();
27+
}
28+
else
29+
{
30+
name = context.reservedTypedName().reservedIdentifier().GetText();
31+
}
32+
return name;
33+
}
34+
35+
public static string GetName(VBAExpressionParser.UnrestrictedNameContext context)
36+
{
37+
if (context.name() != null)
38+
{
39+
return GetName(context.name());
40+
}
41+
else
42+
{
43+
return GetName(context.reservedIdentifierName());
44+
}
45+
}
46+
}
47+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Antlr4.Runtime;
2+
using Rubberduck.Parsing.Symbols;
3+
4+
namespace Rubberduck.Parsing.Binding
5+
{
6+
public interface IBindingContext
7+
{
8+
IBoundExpression Resolve(Declaration module, Declaration parent, ParserRuleContext expression);
9+
}
10+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Antlr4.Runtime;
2+
using Rubberduck.Parsing.Symbols;
3+
4+
namespace Rubberduck.Parsing.Binding
5+
{
6+
public interface IBoundExpression
7+
{
8+
Declaration ReferencedDeclaration { get; }
9+
ExpressionClassification Classification { get; }
10+
ParserRuleContext Context { get; }
11+
}
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Rubberduck.Parsing.Binding
2+
{
3+
public interface IExpressionBinding
4+
{
5+
IBoundExpression Resolve();
6+
}
7+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Antlr4.Runtime;
2+
using Rubberduck.Parsing.Symbols;
3+
4+
namespace Rubberduck.Parsing.Binding
5+
{
6+
public sealed class SimpleNameExpression : BoundExpression
7+
{
8+
public SimpleNameExpression(Declaration referencedDeclaration, ExpressionClassification classification, ParserRuleContext context)
9+
: base(referencedDeclaration, classification, context)
10+
{
11+
}
12+
}
13+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
using Rubberduck.Parsing.Symbols;
2+
3+
namespace Rubberduck.Parsing.Binding
4+
{
5+
public sealed class SimpleNameTypeBinding : IExpressionBinding
6+
{
7+
private readonly DeclarationFinder _declarationFinder;
8+
private readonly Declaration _module;
9+
private readonly VBAExpressionParser.SimpleNameExpressionContext _expression;
10+
11+
public SimpleNameTypeBinding(DeclarationFinder declarationFinder, Declaration module, VBAExpressionParser.SimpleNameExpressionContext expression)
12+
{
13+
_declarationFinder = declarationFinder;
14+
_module = module;
15+
_expression = expression;
16+
}
17+
18+
public IBoundExpression Resolve()
19+
{
20+
IBoundExpression boundExpression = null;
21+
string name = ExpressionName.GetName(_expression.name());
22+
boundExpression = ResolveEnclodingModule(name);
23+
if (boundExpression != null)
24+
{
25+
return boundExpression;
26+
}
27+
boundExpression = ResolveEnclosingProject(name);
28+
if (boundExpression != null)
29+
{
30+
return boundExpression;
31+
}
32+
boundExpression = ResolveOtherModuleInEnclosingProject(name);
33+
if (boundExpression != null)
34+
{
35+
return boundExpression;
36+
}
37+
boundExpression = ResolveReferencedProject(name);
38+
if (boundExpression != null)
39+
{
40+
return boundExpression;
41+
}
42+
return ResolveModuleInReferencedProject(name);
43+
}
44+
45+
private IBoundExpression ResolveEnclodingModule(string name)
46+
{
47+
/* Namespace tier 1:
48+
Enclosing Module namespace: A UDT or Enum type defined at the module-level in the
49+
enclosing module.
50+
*/
51+
var udt = _declarationFinder.Find(_module, name, DeclarationType.UserDefinedType);
52+
if (udt != null)
53+
{
54+
return new SimpleNameExpression(udt, ExpressionClassification.Type, _expression);
55+
}
56+
var enumType = _declarationFinder.Find(_module, name, DeclarationType.UserDefinedType);
57+
if (enumType != null)
58+
{
59+
return new SimpleNameExpression(enumType, ExpressionClassification.Type, _expression);
60+
}
61+
return null;
62+
}
63+
64+
private IBoundExpression ResolveEnclosingProject(string name)
65+
{
66+
/* Namespace tier 2:
67+
Enclosing Project namespace: The enclosing project itself, a referenced project, or a
68+
procedural module or class module contained in the enclosing project.
69+
*/
70+
var enclosingProjectDeclaration = _module.ParentDeclaration;
71+
if (enclosingProjectDeclaration.Project.Name == name)
72+
{
73+
return new SimpleNameExpression(enclosingProjectDeclaration, ExpressionClassification.Project, _expression);
74+
}
75+
var referencedProject = _declarationFinder.FindReferencedProject(enclosingProjectDeclaration, name);
76+
if (referencedProject != null)
77+
{
78+
return new SimpleNameExpression(referencedProject, ExpressionClassification.Type, _expression);
79+
}
80+
var proceduralModuleEnclosingProject = _declarationFinder.Find(enclosingProjectDeclaration, name, DeclarationType.Module);
81+
if (proceduralModuleEnclosingProject != null)
82+
{
83+
return new SimpleNameExpression(proceduralModuleEnclosingProject, ExpressionClassification.ProceduralModule, _expression);
84+
}
85+
var classEnclosingProject = _declarationFinder.Find(enclosingProjectDeclaration, name, DeclarationType.Class);
86+
if (classEnclosingProject != null)
87+
{
88+
return new SimpleNameExpression(classEnclosingProject, ExpressionClassification.Type, _expression);
89+
}
90+
return null;
91+
}
92+
93+
private IBoundExpression ResolveOtherModuleInEnclosingProject(string name)
94+
{
95+
/* Namespace tier 3:
96+
Other Module in Enclosing Project namespace: An accessible UDT or Enum type defined in a
97+
procedural module or class module within the enclosing project other than the enclosing module.
98+
*/
99+
Declaration enclosingProjectDeclaration = _module.ParentDeclaration;
100+
var accessibleUdt = _declarationFinder.FindAccessible(enclosingProjectDeclaration, _module, name, DeclarationType.UserDefinedType);
101+
if (accessibleUdt != null)
102+
{
103+
return new SimpleNameExpression(accessibleUdt, ExpressionClassification.Type, _expression);
104+
}
105+
var accessibleType = _declarationFinder.FindAccessible(enclosingProjectDeclaration, _module, name, DeclarationType.Enumeration);
106+
if (accessibleType != null)
107+
{
108+
return new SimpleNameExpression(accessibleType, ExpressionClassification.Type, _expression);
109+
}
110+
return null;
111+
}
112+
113+
private IBoundExpression ResolveReferencedProject(string name)
114+
{
115+
/* Namespace tier 4:
116+
Referenced Project namespace: An accessible procedural module or class module contained in
117+
a referenced project.
118+
*/
119+
var enclosingProjectDeclaration = _module.ParentDeclaration;
120+
var accessibleModule = _declarationFinder.FindInReferencedProjectModule(enclosingProjectDeclaration, name);
121+
if (accessibleModule != null)
122+
{
123+
return new SimpleNameExpression(accessibleModule, ExpressionClassification.ProceduralModule, _expression);
124+
}
125+
var accessibleClass = _declarationFinder.FindInReferencedProjectClass(enclosingProjectDeclaration, name);
126+
if (accessibleClass != null)
127+
{
128+
return new SimpleNameExpression(accessibleClass, ExpressionClassification.Type, _expression);
129+
}
130+
return null;
131+
}
132+
133+
private IBoundExpression ResolveModuleInReferencedProject(string name)
134+
{
135+
/* Namespace tier 5:
136+
Module in Referenced Project namespace: An accessible UDT or Enum type defined in a
137+
procedural module or class module within a referenced project.
138+
*/
139+
var enclosingProjectDeclaration = _module.ParentDeclaration;
140+
var referencedProjectUdt = _declarationFinder.FindInReferencedProject(enclosingProjectDeclaration, name, DeclarationType.UserDefinedType, DeclarationType.Module | DeclarationType.Class);
141+
if (referencedProjectUdt != null)
142+
{
143+
return new SimpleNameExpression(referencedProjectUdt, ExpressionClassification.Type, _expression);
144+
}
145+
var referencedProjectEnumType = _declarationFinder.FindInReferencedProject(enclosingProjectDeclaration, name, DeclarationType.Enumeration, DeclarationType.Module | DeclarationType.Class);
146+
if (referencedProjectEnumType != null)
147+
{
148+
return new SimpleNameExpression(referencedProjectEnumType, ExpressionClassification.Type, _expression);
149+
}
150+
return null;
151+
}
152+
}
153+
}

0 commit comments

Comments
 (0)