Skip to content

Commit

Permalink
Merge pull request rubberduck-vba#4401 from MDoerner/MakeModuleAnnota…
Browse files Browse the repository at this point in the history
…tionRecognitionIndependentOfTheVBE

Fix module annotation recognition
  • Loading branch information
retailcoder authored Oct 2, 2018
2 parents ac318dd + e75127a commit 496dcf9
Show file tree
Hide file tree
Showing 5 changed files with 323 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ public override void Fix(IInspectionResult result)
var annotationList = (VBAParser.AnnotationListContext)annotation.Context.Parent;

RemoveAnnotationMarker(annotationList, annotation, rewriter);
RemoveWhiteSpaceAfterAnnotation(annotationList, annotation, rewriter);

rewriter.Remove(annotation.Context);

Expand Down Expand Up @@ -71,18 +70,6 @@ private static void RemoveAnnotationMarker(VBAParser.AnnotationListContext annot
rewriter.Remove(annotationList.AT(index));
}

private static void RemoveWhiteSpaceAfterAnnotation(VBAParser.AnnotationListContext annotationList,
IAnnotation annotation, IModuleRewriter rewriter)
{
var whitespace = annotationList.whiteSpace().FirstOrDefault(ws =>
ws.Start.StartIndex == annotation.Context.Stop.StopIndex + 1);

if (whitespace != null)
{
rewriter.Remove(whitespace);
}
}

private static bool OnlyQuoteRemainedFromAnnotationList(KeyValuePair<VBAParser.AnnotationListContext, int> pair)
{
return pair.Key.annotation().Length == pair.Value && pair.Key.commentBody() == null;
Expand Down
4 changes: 2 additions & 2 deletions Rubberduck.Parsing/Grammar/VBAParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -926,8 +926,8 @@ commentOrAnnotation :
remComment : REM whiteSpace? commentBody;
comment : SINGLEQUOTE commentBody;
commentBody : (~NEWLINE)*;
annotationList : SINGLEQUOTE (AT annotation whiteSpace?)+ (COLON commentBody)?;
annotation : annotationName annotationArgList?;
annotationList : SINGLEQUOTE (AT annotation)+ (COLON commentBody)?;
annotation : annotationName annotationArgList? whiteSpace?;
annotationName : unrestrictedIdentifier;
annotationArgList :
whiteSpace annotationArg
Expand Down
86 changes: 67 additions & 19 deletions Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class DeclarationSymbolsListener : VBAParserBaseListener
private Declaration _currentScopeDeclaration;
private Declaration _parentDeclaration;

private readonly IEnumerable<IAnnotation> _annotations;
private readonly ICollection<IAnnotation> _annotations;
private readonly IDictionary<(string scopeIdentifier, DeclarationType scopeType), Attributes> _attributes;
private readonly IDictionary<(string scopeIdentifier, DeclarationType scopeType), ParserRuleContext> _membersAllowingAttributes;

Expand All @@ -40,7 +40,7 @@ public DeclarationSymbolsListener(
{
_state = state;
_qualifiedModuleName = qualifiedModuleName;
_annotations = annotations;
_annotations = annotations.ToList();
_attributes = attributes;
_membersAllowingAttributes = membersAllowingAttributes;

Expand All @@ -61,7 +61,7 @@ public DeclarationSymbolsListener(
projectDeclaration,
_qualifiedModuleName.ComponentName,
true,
FindAnnotations(),
FindModuleAnnotations(),
moduleAttributes);
}
else
Expand All @@ -73,7 +73,7 @@ public DeclarationSymbolsListener(
projectDeclaration,
_qualifiedModuleName.ComponentName,
true,
FindAnnotations(),
FindModuleAnnotations(),
moduleAttributes,
hasDefaultInstanceVariable: hasDefaultInstanceVariable);
}
Expand All @@ -88,26 +88,73 @@ public DeclarationSymbolsListener(
}
}

private IEnumerable<IAnnotation> FindAnnotations()
private IEnumerable<IAnnotation> FindModuleAnnotations()
{
if (_annotations == null)
{
return null;
}

int lastDeclarationsSectionLine;
var component = _state.ProjectsProvider.Component(_qualifiedModuleName);
using (var codeModule = component.CodeModule)
var lastDeclarationsSectionLine = LastDeclarationsSectionLine();

//There is no module body.
if (lastDeclarationsSectionLine == null)
{
lastDeclarationsSectionLine = codeModule.CountOfDeclarationLines;
return _annotations;
}

var annotations = _annotations.Where(annotation => annotation.QualifiedSelection.QualifiedName.Equals(_qualifiedModuleName)
&& annotation.QualifiedSelection.Selection.EndLine <= lastDeclarationsSectionLine);
var lastPossibleModuleAnnotationLine = lastDeclarationsSectionLine.Value;
var annotations = _annotations.Where(annotation => annotation.QualifiedSelection.Selection.EndLine <= lastPossibleModuleAnnotationLine);
return annotations.ToList();
}

private IEnumerable<IAnnotation> FindAnnotations(int line)
private int? LastDeclarationsSectionLine()
{
var firstModuleBodyElementLine = FirstModuleBodyElementLine();

if (firstModuleBodyElementLine == null)
{
return null;
}

//The VBE uses 1-based lines.
for (var currentLine = firstModuleBodyElementLine.Value - 1; currentLine >= 1; currentLine--)
{
if (_annotations.Any(annotation => annotation.QualifiedSelection.Selection.StartLine <= currentLine
&& annotation.QualifiedSelection.Selection.EndLine >=
currentLine))
{
continue;
}

return currentLine;
}

//There is no declaration section.
return 0;
}

private int? FirstModuleBodyElementLine()
{
var moduleTrees = _state.ParseTrees.Where(kvp => kvp.Key.Equals(_qualifiedModuleName)).ToList();
if (!moduleTrees.Any())
{
return null;
}

var startContext = (ParserRuleContext) moduleTrees.First().Value;
var moduleBody = startContext.GetDescendent<VBAParser.ModuleBodyContext>();

var moduleBodyElements = moduleBody.moduleBodyElement();
if (!moduleBodyElements.Any())
{
return null;
}

return moduleBodyElements.Select(context => context.start.Line).Min();
}

private IEnumerable<IAnnotation> FindMemberAnnotations(int firstMemberLine)
{
if (_annotations == null)
{
Expand All @@ -117,16 +164,17 @@ private IEnumerable<IAnnotation> FindAnnotations(int line)
var annotations = new List<IAnnotation>();

// VBE 1-based indexing
for (var i = line - 1; i >= 1; i--)
for (var currentLine = firstMemberLine - 1; currentLine >= 1; currentLine--)
{
var lineAnnotations = _annotations.Where(a => a.QualifiedSelection.Selection.StartLine == i);

if (!lineAnnotations.Any())
if (!_annotations.Any(annotation => annotation.QualifiedSelection.Selection.StartLine <= currentLine
&& annotation.QualifiedSelection.Selection.EndLine >= currentLine))
{
break;
}

annotations.AddRange(lineAnnotations);
var annotationsStartingOnCurrentLine = _annotations.Where(a => a.QualifiedSelection.Selection.StartLine == currentLine);

annotations.AddRange(annotationsStartingOnCurrentLine);
}

return annotations;
Expand Down Expand Up @@ -225,7 +273,7 @@ private Declaration CreateDeclaration(
_attributes.TryGetValue(key, out var attributes);
_membersAllowingAttributes.TryGetValue(key, out var attributesPassContext);

var annotations = FindAnnotations(selection.StartLine);
var annotations = FindMemberAnnotations(selection.StartLine);
switch (declarationType)
{
case DeclarationType.Procedure:
Expand Down Expand Up @@ -821,7 +869,7 @@ public override void EnterConstSubStmt(VBAParser.ConstSubStmtContext context)
asTypeName,
asTypeClause,
typeHint,
FindAnnotations(constStmt.Start.Line),
FindMemberAnnotations(constStmt.Start.Line),
accessibility,
DeclarationType.Constant,
value,
Expand Down
Loading

0 comments on commit 496dcf9

Please sign in to comment.