예제 #1
0
        private void AddImplementsStatement(ExtractInterfaceModel model, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName);

            var implementsStatement = $"Implements {model.InterfaceName}";

            var(insertionIndex, isImplementsStatement) = InsertionIndex(model);

            if (insertionIndex == -1)
            {
                rewriter.InsertBefore(0, $"{implementsStatement}{Environment.NewLine}{Environment.NewLine}");
            }
            else
            {
                rewriter.InsertAfter(insertionIndex, $"{Environment.NewLine}{(isImplementsStatement ? string.Empty : Environment.NewLine)}{implementsStatement}");
            }
        }
예제 #2
0
 private static void RemoveAttributes(IEnumerable <Declaration> declarationsForWhichToRemoveAttributes, IRewriteSession rewriteSession)
 {
     foreach (var declaration in declarationsForWhichToRemoveAttributes)
     {
         foreach (var attribute in declaration.Attributes)
         {
             //We cannot remove use the attributesUpdater here because it requires an attribute rewrite session,
             //which rewrites in a suspended state.
             var attributeContext = attribute.Context;
             var rewriter         = rewriteSession.CheckOutModuleRewriter(declaration.QualifiedModuleName);
             rewriter.Remove(attribute.Context);
             if (attributeContext.TryGetFollowingContext(out VBAParser.EndOfLineContext followingEndOfLine))
             {
                 rewriter.Remove(followingEndOfLine);
             }
         }
     }
 }
예제 #3
0
        private void RenameReferences(Declaration target, string newName, IRewriteSession rewriteSession)
        {
            var modules = target.References
                          .Where(reference =>
                                 reference.Context.GetText() != "Me" &&
                                 !reference.IsArrayAccess &&
                                 !reference.IsDefaultMemberAccess)
                          .GroupBy(r => r.QualifiedModuleName);

            foreach (var grouping in modules)
            {
                var rewriter = rewriteSession.CheckOutModuleRewriter(grouping.Key);
                foreach (var reference in grouping)
                {
                    rewriter.Replace(reference.Context, newName);
                }
            }
        }
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName);
            var finder   = _declarationFinderProvider.DeclarationFinder;

            var lExpressionContext = result.Context;
            var selection          = result.QualifiedSelection;

            InsertDefaultMember(lExpressionContext, selection, finder, rewriter);

            if (result.Inspection is SuspiciousLetAssignmentInspection)
            {
                IdentifierReference rhsReference = result.Properties.RhSReference;
                var rhsLExpressionContext        = rhsReference.Context;
                var rhsSelection = rhsReference.QualifiedSelection;
                InsertDefaultMember(rhsLExpressionContext, rhsSelection, finder, rewriter);
            }
        }
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            var module            = result.QualifiedSelection.QualifiedName;
            var moduleDeclaration = _state.DeclarationFinder.Members(module, DeclarationType.Module)
                                    .FirstOrDefault();

            if (moduleDeclaration == null)
            {
                return;
            }

            var existingIgnoreModuleAnnotation = moduleDeclaration.Annotations
                                                 .FirstOrDefault(pta => pta.Annotation is IgnoreModuleAnnotation);

            var annotationType = new IgnoreModuleAnnotation();

            if (existingIgnoreModuleAnnotation != null)
            {
                var annotationValues = existingIgnoreModuleAnnotation.AnnotationArguments.ToList();

                if (annotationValues.Contains(result.Inspection.AnnotationName))
                {
                    return;
                }

                annotationValues.Insert(0, result.Inspection.AnnotationName);
                _annotationUpdater.UpdateAnnotation(rewriteSession, existingIgnoreModuleAnnotation, annotationType, annotationValues);
            }
            else
            {
                var newModuleText    = rewriteSession.CheckOutModuleRewriter(module).GetText();
                var ignoreModuleText = $"'{ParseTreeAnnotation.ANNOTATION_MARKER}{annotationType.Name}";
                if (newModuleText.Contains(ignoreModuleText))
                {
                    //Most probably, we have added this already in another invocation on the same rewrite session.
                    return;
                }

                var annotationValues = new List <string> {
                    result.Inspection.AnnotationName
                };
                _annotationUpdater.AddAnnotation(rewriteSession, moduleDeclaration, annotationType, annotationValues);
            }
        }
        private void ModifyFields(EncapsulateFieldUseBackingUDTMemberModel encapsulateFieldModel, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(encapsulateFieldModel.QualifiedModuleName);

            if (encapsulateFieldModel.ObjectStateUDTField.IsExistingDeclaration)
            {
                var model = new ModifyUserDefinedTypeModel(encapsulateFieldModel.ObjectStateUDTField.AsTypeDeclaration);

                foreach (var candidate in encapsulateFieldModel.SelectedFieldCandidates)
                {
                    model.AddNewMemberPrototype(candidate.Declaration, candidate.BackingIdentifier);
                }

                _modifyUDTRefactoringAction.Refactor(model, rewriteSession);
            }

            rewriter.RemoveVariables(encapsulateFieldModel.SelectedFieldCandidates.Select(f => f.Declaration)
                                     .Cast <VariableDeclaration>());
        }
예제 #7
0
        protected override void ModifyFields(IRewriteSession refactorRewriteSession)
        {
            var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN);

            rewriter.RemoveVariables(_fieldsToDeleteAndReplace.Select(f => f.Declaration).Cast <VariableDeclaration>());

            foreach (var field in SelectedFields.Except(_fieldsToDeleteAndReplace))
            {
                if (field.Declaration.HasPrivateAccessibility() && field.BackingIdentifier.Equals(field.Declaration.IdentifierName))
                {
                    rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration);
                    continue;
                }

                rewriter.Rename(field.Declaration, field.BackingIdentifier);
                rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString());
                rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration);
            }
        }
예제 #8
0
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            Debug.Assert(result.Target.Context.Parent is VBAParser.ArgListContext);
            Debug.Assert(null != ((ParserRuleContext)result.Target.Context.Parent.Parent).GetChild <VBAParser.EndOfStatementContext>());

            _quickFixTarget = result.Target;

            var localIdentifier = PromptForLocalVariableName(result.Target);

            if (string.IsNullOrEmpty(localIdentifier))
            {
                return;
            }

            var rewriter = rewriteSession.CheckOutModuleRewriter(result.Target.QualifiedModuleName);

            ReplaceAssignedByValParameterReferences(rewriter, result.Target, localIdentifier);
            InsertLocalVariableDeclarationAndAssignment(rewriter, result.Target, localIdentifier);
        }
        private void InsertNewDeclaration(Declaration target, IRewriteSession rewriteSession)
        {
            var subscripts = target.Context.GetDescendent <VBAParser.SubscriptsContext>()?.GetText() ?? string.Empty;
            var identifier = target.IsArray ? $"{target.IdentifierName}({subscripts})" : target.IdentifierName;

            var newVariable = target.AsTypeContext is null
                ? $"{Tokens.Dim} {identifier} {Tokens.As} {Tokens.Variant}"
                : $"{Tokens.Dim} {identifier} {Tokens.As} {(target.IsSelfAssigned ? Tokens.New + " " : string.Empty)}{target.AsTypeNameWithoutArrayDesignator}";

            var firstReference = target.References.OrderBy(r => r.Selection.StartLine).First();

            var enclosingBlockStatement = firstReference.Context.GetAncestor <VBAParser.BlockStmtContext>();
            var insertionIndex          = enclosingBlockStatement.Start.TokenIndex;
            var insertCode = PaddedDeclaration(newVariable, enclosingBlockStatement);

            var rewriter = rewriteSession.CheckOutModuleRewriter(firstReference.QualifiedModuleName);

            rewriter.InsertBefore(insertionIndex, insertCode);
        }
        public override void Refactor(ReplaceReferencesModel model, IRewriteSession rewriteSession)
        {
            var replacementPairByQualifiedModuleName = model.ReferenceReplacementPairs
                                                       .Where(pr =>
                                                              pr.IdentifierReference.Context.GetText() != Tokens.Me &&
                                                              !pr.IdentifierReference.IsArrayAccess &&
                                                              !pr.IdentifierReference.IsDefaultMemberAccess)
                                                       .GroupBy(r => r.IdentifierReference.QualifiedModuleName);

            foreach (var replacements in replacementPairByQualifiedModuleName)
            {
                var rewriter = rewriteSession.CheckOutModuleRewriter(replacements.Key);
                foreach ((IdentifierReference identifierReference, string newIdentifier) in replacements)
                {
                    (ParserRuleContext context, string replacementName) = BuildReferenceReplacementString(identifierReference, newIdentifier, model.ModuleQualifyExternalReferences);
                    rewriter.Replace(context, replacementName);
                }
            }
        }
예제 #11
0
        public void RemoveAnnotations(IRewriteSession rewriteSession, IEnumerable <IParseTreeAnnotation> annotations)
        {
            if (annotations == null)
            {
                return;
            }

            if (rewriteSession.TargetCodeKind != CodeKind.CodePaneCode && rewriteSession.TargetCodeKind != CodeKind.AttributesCode)
            {
                _logger.Warn($"Tried to remove multiple annotations with a rewriter not suitable for annotations. (target code kind = {rewriteSession.TargetCodeKind})");
                return;
            }

            var annotationsByAnnotationList = annotations.Distinct()
                                              .GroupBy(annotation => new QualifiedContext(annotation.QualifiedSelection.QualifiedName, (ParserRuleContext)annotation.Context.Parent))
                                              .ToDictionary(grouping => grouping.Key, grouping => grouping.ToList());

            if (!annotationsByAnnotationList.Keys.Any())
            {
                return;
            }

            foreach (var qualifiedAnnotationList in annotationsByAnnotationList.Keys)
            {
                var annotationList = (VBAParser.AnnotationListContext)qualifiedAnnotationList.Context;
                if (annotationList.commentBody() == null && annotationList.annotation().Length == annotationsByAnnotationList[qualifiedAnnotationList].Count)
                {
                    //We want to remove all annotations in the list. So, we remove the entire line.
                    //This does not really work if there are multiple consecutive lines at the end of the file that need to be removed,
                    //but I think we can live with leaving an empty line in this edge-case.
                    var rewriter = rewriteSession.CheckOutModuleRewriter(qualifiedAnnotationList.ModuleName);
                    RemoveEntireLine(rewriter, annotationList);
                }
                else
                {
                    foreach (var annotation in annotationsByAnnotationList[qualifiedAnnotationList])
                    {
                        RemoveAnnotation(rewriteSession, annotation);
                    }
                }
            }
        }
        private static void AdjustReferences(
            ReorderParametersModel model,
            QualifiedModuleName module,
            Dictionary <Selection, List <ArgumentReference> > argumentReferences,
            IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(module);

            foreach (var(argumentListSelection, sameArgumentListReferences) in argumentReferences)
            {
                //This happens for (with) dictionary access expressions only,
                //which cannot be reordered anyway.
                if (argumentListSelection.Equals(Selection.Empty))
                {
                    continue;
                }

                AdjustReferences(model, sameArgumentListReferences, rewriter);
            }
        }
예제 #13
0
        private void ModifyFields(EncapsulateFieldUseBackingFieldModel model, List <IEncapsulateFieldCandidate> publicFieldsToRemove, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(model.QualifiedModuleName);

            rewriter.RemoveVariables(publicFieldsToRemove.Select(f => f.Declaration)
                                     .Cast <VariableDeclaration>());

            var retainedFieldDeclarations = model.SelectedFieldCandidates
                                            .Except(publicFieldsToRemove)
                                            .ToList();

            if (retainedFieldDeclarations.Any())
            {
                MakeImplicitDeclarationTypeExplicit(retainedFieldDeclarations, rewriter);

                SetPrivateVariableVisiblity(retainedFieldDeclarations, rewriter);

                Rename(retainedFieldDeclarations, rewriteSession);
            }
        }
예제 #14
0
        public void UpdateAttribute(IRewriteSession rewriteSession, Declaration declaration, string attribute, IReadOnlyList <string> newValues, IReadOnlyList <string> oldValues = null)
        {
            if (string.IsNullOrEmpty(attribute))
            {
                return;
            }

            //Attributes must have at least one value.
            if (newValues == null || !newValues.Any())
            {
                return;
            }

            if (declaration == null)
            {
                _logger.Warn("Tried to updtae an attribute on a declaration that is null.");
                _logger.Trace($"Tried to update values for attribute {attribute} {(oldValues != null ? $"with values {AttributeValuesText(oldValues)} " : string.Empty)}on a declaration that is null.");
                return;
            }

            if (rewriteSession.TargetCodeKind != CodeKind.AttributesCode)
            {
                _logger.Warn($"Tried to update an attribute with a rewriter not suitable for attributes. (target code kind = {rewriteSession.TargetCodeKind})");
                _logger.Trace($"Tried to update values for attribute {attribute} {(oldValues != null ? $"with values {AttributeValuesText(oldValues)} " : string.Empty)}on {declaration.QualifiedModuleName} to {AttributeValuesText(oldValues)} using a rewriter not suitable for attributes.");
                return;
            }

            var attributeNodes = ApplicableAttributeNodes(declaration, attribute, oldValues);

            if (!attributeNodes.Any())
            {
                return;
            }

            var rewriter = rewriteSession.CheckOutModuleRewriter(declaration.QualifiedModuleName);

            var nodeToUpdate = attributeNodes[0];

            UpdateAttributeValues(rewriter, nodeToUpdate, newValues);
            RemoveNodes(rewriter, attributeNodes.Skip(1));
        }
예제 #15
0
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            if (!(result.Properties is ParameterDeclaration parameter))
            {
                Logger.Trace(
                    $"Properties for IsMissingOnInappropriateArgumentQuickFix was {(result.Properties == null ? "null" : "not a ParameterDeclaration")}.");
                return;
            }

            var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName);

            if (!result.Context.TryGetAncestor <VBAParser.LExprContext>(out var context))
            {
                Logger.Trace("IsMissingOnInappropriateArgumentQuickFix could not locate containing LExprContext for replacement.");
                return;
            }

            if (parameter.IsParamArray || parameter.IsArray)
            {
                rewriter.Replace(context, $"{Tokens.LBound}({parameter.IdentifierName}) > {Tokens.UBound}({parameter.IdentifierName})");
                return;
            }

            if (!string.IsNullOrEmpty(parameter.DefaultValue))
            {
                if (parameter.DefaultValue.Equals("\"\""))
                {
                    rewriter.Replace(context, $"{parameter.IdentifierName} = {Tokens.vbNullString}");
                }
                else if (parameter.DefaultValue.Equals(Tokens.Nothing, StringComparison.InvariantCultureIgnoreCase))
                {
                    rewriter.Replace(context, $"{parameter.IdentifierName} Is {Tokens.Nothing}");
                }
                else
                {
                    rewriter.Replace(context, $"{parameter.IdentifierName} = {parameter.DefaultValue}");
                }
                return;
            }
            rewriter.Replace(context, UninitializedComparisonForParameter(parameter));
        }
        private void AddProperty(IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(_model.TargetDeclaration.QualifiedModuleName);

            UpdateReferences(rewriteSession);
            SetFieldToPrivate(rewriter);

            var members = _model.State.DeclarationFinder
                          .Members(_model.TargetDeclaration.QualifiedName.QualifiedModuleName)
                          .OrderBy(declaration => declaration.QualifiedSelection);

            var fields = members.Where(d => d.DeclarationType == DeclarationType.Variable && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)).ToList();

            var property = Environment.NewLine + Environment.NewLine + GetPropertyText();

            if (members.Any(m => m.DeclarationType.HasFlag(DeclarationType.Member)))
            {
                property += Environment.NewLine;
            }

            if (_model.TargetDeclaration.Accessibility != Accessibility.Private)
            {
                var newField = $"Private {_model.TargetDeclaration.IdentifierName} As {_model.TargetDeclaration.AsTypeName}";
                if (fields.Count > 1)
                {
                    newField = Environment.NewLine + newField;
                }

                property = newField + property;
            }

            if (_model.TargetDeclaration.Accessibility == Accessibility.Private || fields.Count > 1)
            {
                rewriter.InsertAfter(fields.Last().Context.Stop.TokenIndex, property);
            }
            else
            {
                rewriter.InsertBefore(0, property);
            }
        }
예제 #17
0
        private void AddModuleAnnotation(IRewriteSession rewriteSession, Declaration declaration, AnnotationType annotationType, IReadOnlyList <string> annotationValues)
        {
            if (!annotationType.HasFlag(AnnotationType.ModuleAnnotation))
            {
                _logger.Warn("Tried to add an annotation without the module annotation flag to a module.");
                _logger.Trace($"Tried to add the annotation {annotationType} with values {AnnotationValuesText(annotationValues)} to the module {declaration.QualifiedModuleName}.");
                return;
            }

            if (rewriteSession.TargetCodeKind != CodeKind.CodePaneCode)
            {
                _logger.Warn($"Tried to add an annotation to a module with a rewriter not suitable for annotationss. (target code kind = {rewriteSession.TargetCodeKind})");
                _logger.Trace($"Tried to add annotation {annotationType} with values {AnnotationValuesText(annotationValues)} to the module {declaration.QualifiedModuleName} using a rewriter not suitable for annotations.");
                return;
            }

            var codeToAdd = $"{AnnotationText(annotationType, annotationValues)}{Environment.NewLine}";

            var rewriter = rewriteSession.CheckOutModuleRewriter(declaration.QualifiedModuleName);

            rewriter.InsertBefore(0, codeToAdd);
        }
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName);

            switch (result.Context)
            {
            case VBAParser.IfStmtContext ifContext:
                UpdateContext(ifContext, rewriter);
                break;

            case VBAParser.IfWithEmptyThenContext ifWithEmtyThenContext:
                UpdateContext(ifWithEmtyThenContext, rewriter);
                break;

            case VBAParser.ElseIfBlockContext elseIfBlockContext:
                UpdateContext(elseIfBlockContext, rewriter);
                break;

            default:
                throw new NotSupportedException(result.Context.GetType().ToString());
            }
        }
        private void AddParameter(Declaration targetMethod, Declaration targetVariable, VBAParser.ArgListContext paramList, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(targetMethod.QualifiedModuleName);

            var argList      = paramList.arg();
            var newParameter = $"{Tokens.ByVal} {targetVariable.IdentifierName} {Tokens.As} {targetVariable.AsTypeName}";

            if (!argList.Any())
            {
                rewriter.InsertBefore(paramList.RPAREN().Symbol.TokenIndex, newParameter);
            }
            else if (targetMethod.DeclarationType != DeclarationType.PropertyLet &&
                     targetMethod.DeclarationType != DeclarationType.PropertySet)
            {
                rewriter.InsertBefore(paramList.RPAREN().Symbol.TokenIndex, $", {newParameter}");
            }
            else
            {
                var lastParam = argList.Last();
                rewriter.InsertBefore(lastParam.Start.TokenIndex, $"{newParameter}, ");
            }
        }
        private void AddProperty(EncapsulateFieldModel model, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName);

            UpdateReferences(model, rewriteSession);

            var members = _declarationFinderProvider.DeclarationFinder
                          .Members(model.TargetDeclaration.QualifiedName.QualifiedModuleName)
                          .OrderBy(declaration => declaration.QualifiedSelection);

            var fields = members.Where(d => d.DeclarationType == DeclarationType.Variable && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)).ToList();

            var property = Environment.NewLine + Environment.NewLine + GetPropertyText(model);

            if (model.TargetDeclaration.Accessibility != Accessibility.Private)
            {
                var newField = $"Private {model.TargetDeclaration.IdentifierName} As {model.TargetDeclaration.AsTypeName}";
                if (fields.Count > 1)
                {
                    newField = Environment.NewLine + newField;
                }

                property = newField + property;
            }

            if (model.TargetDeclaration.Accessibility == Accessibility.Private || fields.Count > 1)
            {
                if (model.TargetDeclaration.Accessibility != Accessibility.Private)
                {
                    rewriter.Remove(model.TargetDeclaration);
                }
                rewriter.InsertAfter(fields.Last().Context.Stop.TokenIndex, property);
            }
            else
            {
                rewriter.Replace(model.TargetDeclaration.Context.GetAncestor <VBAParser.ModuleDeclarationsElementContext>(), property);
            }
        }
        private static void AdjustReferences(
            QualifiedModuleName module,
            Dictionary <Selection, List <ArgumentReference> > argumentReferences,
            IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(module);

            foreach (var(argumentListSelection, sameArgumentListReferences) in argumentReferences)
            {
                //This happens for (with) dictionary access expressions only.
                if (argumentListSelection.Equals(Selection.Empty))
                {
                    foreach (var dictionaryAccessArgument in sameArgumentListReferences)
                    {
                        ReplaceDictionaryAccess(dictionaryAccessArgument, rewriter);
                    }

                    continue;
                }

                AdjustReferences(sameArgumentListReferences, rewriter);
            }
        }
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName);

            rewriter.Remove(result.Context);
        }
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(result.Target.QualifiedModuleName);

            rewriter.Replace(((ParserRuleContext)result.Context.Parent.Parent).GetDescendent <VBAParser.VisibilityContext>(), Tokens.Public);
        }
예제 #24
0
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(result.Target.QualifiedModuleName);

            rewriter.InsertBefore(result.Context.Start.TokenIndex, "Public ");
        }
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName);

            UpdateContext((VBAParser.ElseBlockContext)result.Context, rewriter);
        }
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName);

            rewriter.InsertBefore(result.Context.Start.TokenIndex, "WorksheetFunction.");
        }
예제 #27
0
        private void RemoveOldDeclaration(IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(_target.QualifiedModuleName);

            rewriter.Remove(_target);
        }
예제 #28
0
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            var annotationText = $"'@Ignore {result.Inspection.AnnotationName}";

            int annotationLine;
            //TODO: Make this use the parse tree instead of the code module.
            var component = _state.ProjectsProvider.Component(result.QualifiedSelection.QualifiedName);

            using (var module = component.CodeModule)
            {
                annotationLine = result.QualifiedSelection.Selection.StartLine;
                while (annotationLine != 1 && module.GetLines(annotationLine - 1, 1).EndsWith(" _"))
                {
                    annotationLine--;
                }
            }

            RuleContext treeRoot = result.Context;

            while (treeRoot.Parent != null)
            {
                treeRoot = treeRoot.Parent;
            }

            var listener = new CommentOrAnnotationListener();

            ParseTreeWalker.Default.Walk(listener, treeRoot);
            var commentContext = listener.Contexts.LastOrDefault(i => i.Stop.TokenIndex <= result.Context.Start.TokenIndex);
            var commented      = commentContext?.Stop.Line + 1 == annotationLine;

            var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName);

            if (commented)
            {
                var annotation = commentContext.annotationList()?.annotation(0);
                if (annotation != null && annotation.GetText().StartsWith("Ignore"))
                {
                    rewriter.InsertAfter(annotation.annotationName().Stop.TokenIndex, $" {result.Inspection.AnnotationName},");
                }
                else
                {
                    var indent = new string(Enumerable.Repeat(' ', commentContext.Start.Column).ToArray());
                    rewriter.InsertAfter(commentContext.Stop.TokenIndex, $"{indent}{annotationText}{Environment.NewLine}");
                }
            }
            else
            {
                int insertIndex;

                // this value is used when the annotation should be on line 1--we need to insert before token index 0
                if (annotationLine == 1)
                {
                    insertIndex     = 0;
                    annotationText += Environment.NewLine;
                }
                else
                {
                    var eol = new EndOfLineListener();
                    ParseTreeWalker.Default.Walk(eol, treeRoot);

                    // we subtract 2 here to get the insertion index to A) account for VBE's one-based indexing
                    // and B) to get the newline token that introduces that line
                    var eolContext = eol.Contexts.OrderBy(o => o.Start.TokenIndex).ElementAt(annotationLine - 2);
                    insertIndex = eolContext.Start.TokenIndex;

                    annotationText = Environment.NewLine + annotationText;
                }

                rewriter.InsertBefore(insertIndex, annotationText);
            }
        }
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            if (!(result is IWithInspectionResultProperties <IReadOnlyList <VBAParser.OnErrorStmtContext> > resultProperties))
            {
                return;
            }

            var exitStatement = "Exit ";

            VBAParser.BlockContext block;
            var bodyElementContext = result.Context.GetAncestor <VBAParser.ModuleBodyElementContext>();

            if (bodyElementContext.propertyGetStmt() != null)
            {
                exitStatement += "Property";
                block          = bodyElementContext.propertyGetStmt().block();
            }
            else if (bodyElementContext.propertyLetStmt() != null)
            {
                exitStatement += "Property";
                block          = bodyElementContext.propertyLetStmt().block();
            }
            else if (bodyElementContext.propertySetStmt() != null)
            {
                exitStatement += "Property";
                block          = bodyElementContext.propertySetStmt().block();
            }
            else if (bodyElementContext.functionStmt() != null)
            {
                exitStatement += "Function";
                block          = bodyElementContext.functionStmt().block();
            }
            else
            {
                exitStatement += "Sub";
                block          = bodyElementContext.subStmt().block();
            }

            var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName);
            var context  = (VBAParser.OnErrorStmtContext)result.Context;
            var labels   = bodyElementContext.GetDescendents <VBAParser.IdentifierStatementLabelContext>()
                           .OrderBy(labelContext => labelContext.GetSelection())
                           .ToArray();
            var maximumExistingLabelIndex = GetMaximumExistingLabelIndex(labels);
            var unhandledContexts         = resultProperties.Properties;
            var offset     = unhandledContexts.IndexOf(result.Context);
            var labelIndex = maximumExistingLabelIndex + offset;

            var labelSuffix = labelIndex == 0
                ? labels.Select(GetLabelText).Any(text => text == LabelPrefix)
                    ? "1"
                    : ""
                : maximumExistingLabelIndex == 0
                    ? labelIndex.ToString()
                    : (labelIndex + 1).ToString();

            rewriter.Replace(context.RESUME(), Tokens.GoTo);
            rewriter.Replace(context.NEXT(), $"{LabelPrefix}{labelSuffix}");

            var errorHandlerSubroutine = $@"
    {exitStatement}
{LabelPrefix}{labelSuffix}:
    If Err.Number > 0 Then 'TODO: handle specific error
        Err.Clear
        Resume Next
    End If
";

            rewriter.InsertAfter(block.Stop.TokenIndex, errorHandlerSubroutine);
        }
예제 #30
0
        public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
        {
            var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName);

            rewriter.InsertBefore(0, Tokens.Option + ' ' + Tokens.Explicit + Environment.NewLine + Environment.NewLine);
        }