/// <summary> /// Called when the StyleCopCore.ViolationEncountered event is raised. Converts /// <see cref="ViolationEventArgs"/>into ReSharper Violation. /// </summary> /// <param name="sender"> /// Object that raised the event. /// </param> /// <param name="e"> /// Data Structure containing information about the Violation encountered. /// </param> private void OnViolationEncountered(object sender, ViolationEventArgs e) { string path = e.SourceCode.Path; int lineNumber = e.LineNumber; // if violations fire in the related files we ignore them as we only want to highlight in the current file if (path == this.file.Location.FullPath) { JB::JetBrains.Util.dataStructures.TypedIntrinsics.Int32 <DocLine> line = (JB::JetBrains.Util.dataStructures.TypedIntrinsics.Int32 <DocLine>)lineNumber; JB::JetBrains.Util.TextRange textRange = Utils.GetTextRange(this.file, line.Minus1()); // The TextRange could be a completely blank line. If it is just return the line and don't trim it. DocumentRange documentRange = new DocumentRange(this.file, textRange); if (!textRange.IsEmpty) { // Once we have a TextRange for the entire line reduce it to not include whitespace at the left or whitespace at the right // if it wasn't empty documentRange = Utils.TrimWhitespaceFromDocumentRange(documentRange); } string fileName = this.file.Location.Name; if (e.Violation.Element != null) { fileName = e.Violation.Element.Document.SourceCode.Name; } IHighlighting violation = StyleCopViolationFactory.GetHighlight(e, documentRange, fileName, lineNumber); this.CreateViolation(documentRange, violation); } }
/// <summary> /// Formats the current line using the settings as defined in ReSharper > Option > Languages > Common > Code Style Sharing. /// </summary> /// <param name="solution"> /// Current Solution. /// </param> /// <param name="textControl"> /// Current Text Control. /// </param> public override void ExecuteTransactionInner(ISolution solution, ITextControl textControl) { JB::JetBrains.Util.dataStructures.TypedIntrinsics.Int32 <DocLine> line = Utils.GetLineNumberForTextControl(textControl); ITreeNode element = Utils.GetElementAtCaret(solution, textControl); IUsingDirective containingElement = element.GetContainingNode <IUsingDirective>(true); Utils.FormatLines(solution, textControl.Document, line.Minus1(), line.Plus1()); if (containingElement != null) { new SpacingRules().EqualsMustBeSpacedCorrectly(containingElement); } }
/// <summary> /// Initializes the QuickFix with all the available BulbItems that can fix the current /// StyleCop Violation. /// </summary> protected override void InitialiseBulbItems() { JB::JetBrains.Util.dataStructures.TypedIntrinsics.Int32 <DocLine> line = (JB::JetBrains.Util.dataStructures.TypedIntrinsics.Int32 <DocLine>) this.Violation.LineNumber; string target = this.Violation.DocumentRange.Document.GetLineText(line.Minus1()); target = target.Contains("++") ? "++" : "--"; this.BulbItems = new List <IBulbItem> { new FormatLineBulbItem { DocumentRange = this.Violation.DocumentRange, Description = "Fix Spacing : " + this.Violation.ToolTip, LineNumber = this.Violation.LineNumber, Target = target } }; }
/// <summary> /// Closing curly bracket must be followed by blank line. /// </summary> /// <param name="node"> /// The node to use. /// </param> public static void ClosingCurlyBracketMustBeFollowedByBlankLine(ITreeNode node) { // Closing curly brackets must be followed by a newline unless they are closing an object initializer or // followed by one of the endtokens defined here. // catch // finally // else // rbrace // dowhile // preprocessor directives List <TokenNodeType> tokensThatFollowClosingCurlyBracketWithoutNewLine = new List <TokenNodeType> { CSharpTokenType.RBRACE, CSharpTokenType.DO_KEYWORD, CSharpTokenType.ELSE_KEYWORD, CSharpTokenType.CATCH_KEYWORD, CSharpTokenType.FINALLY_KEYWORD }; List <TokenNodeType> objectInitializerFollowers = new List <TokenNodeType> { CSharpTokenType.AS_KEYWORD, CSharpTokenType.IS_KEYWORD, CSharpTokenType.COMMA, CSharpTokenType.SEMICOLON, CSharpTokenType.DOT, CSharpTokenType.QUEST, CSharpTokenType.COLON, CSharpTokenType.RPARENTH, CSharpTokenType.EQEQ, CSharpTokenType.GE, CSharpTokenType.GT, CSharpTokenType.LE, CSharpTokenType.LT, CSharpTokenType.NE, CSharpTokenType.MINUS, CSharpTokenType.PLUS, CSharpTokenType.DIV, CSharpTokenType.ASTERISK, CSharpTokenType.PERC, CSharpTokenType.MINUSMINUS, CSharpTokenType.PLUSPLUS }; for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling) { if (currentNode is ITokenNode) { ITokenNode tokenNode = currentNode as ITokenNode; if (tokenNode.GetTokenType() == CSharpTokenType.RBRACE) { IBlock blockNode = tokenNode.Parent as IBlock; if (blockNode != null) { JB::JetBrains.Util.dataStructures.TypedIntrinsics.Int32 <DocLine> lineNumberForLBrace = Utils.GetLineNumberForElement(blockNode.LBrace); JB::JetBrains.Util.dataStructures.TypedIntrinsics.Int32 <DocLine> lineNumberForRBrace = Utils.GetLineNumberForElement(blockNode.RBrace); if (lineNumberForLBrace != lineNumberForRBrace) { ITokenNode currentToken = tokenNode.GetNextToken(); int newLineCount = 0; while (currentToken != null) { if (currentToken.IsWhitespace()) { if (currentToken.IsNewLine()) { newLineCount++; if (newLineCount == 2) { // if we get 2 new lines we've already got a blank line after the closing curly bracket so jog on. break; } } } else { if ((!tokensThatFollowClosingCurlyBracketWithoutNewLine.Contains(currentToken.GetTokenType()) && !objectInitializerFollowers.Contains(currentToken.GetTokenType())) || (objectInitializerFollowers.Contains(currentToken.GetTokenType()) && newLineCount == 1)) { tokenNode.GetNextToken().InsertNewLineBefore(); } break; } currentToken = currentToken.GetNextToken(); } } } } } if (currentNode.FirstChild != null) { ClosingCurlyBracketMustBeFollowedByBlankLine(currentNode.FirstChild); } } }