/// <summary> /// Our internal implementation of the bulb item which assumes it is running within a transaction /// </summary> /// <param name="solution">The currently open solution</param> /// <param name="textControl">The text control that is currently open</param> public void ExecuteEx(ISolution solution, ITextControl textControl) { // Get the comment block owner (ie the part of the declaration which will own the comment). IDocCommentBlockOwner docCommentBlockOwnerNode = XmlDocTemplateUtil.FindDocCommentOwner(_declaration as ITypeMemberDeclaration); // If we didn't get an owner then give up if (docCommentBlockOwnerNode == null) { return; } // We got one // Ask resharper to create the xml for us. int myCursorOffset; string text = XmlDocTemplateUtil.GetDocTemplate(docCommentBlockOwnerNode, out myCursorOffset); // Get a factory which can create elements in the C# docs CSharpElementFactory factory = CSharpElementFactory.GetInstance(docCommentBlockOwnerNode.GetPsiModule()); // Create the comment block IDocCommentBlock comment = factory.CreateDocCommentBlock(text); // And set the comment on the declaration. docCommentBlockOwnerNode.SetDocCommentBlock(comment); }
/// <summary> /// Creates a new DeclarationHeader for the declaration and assigns it to the declaration. /// </summary> /// <param name="declaration"> /// The declaration to create the header for. /// </param> /// <param name="docConfig"> /// Provides the configuration for the current ProjectFile. /// </param> /// <returns> /// A DeclarationHeader for the declaration passed in. /// </returns> public static DeclarationHeader CreateNewHeader(IDeclaration declaration, DocumentationRulesConfiguration docConfig) { IFile file = declaration.GetContainingFile(); using (WriteLockCookie.Create(file.IsPhysical())) { IDeclaration declarationTreeNode = declaration; IContextBoundSettingsStore settingsStore = PsiSourceFileExtensions.GetSettingsStore(null, declaration.GetSolution()); bool useSingleLineDeclarationComments = settingsStore.GetValue((StyleCopOptionsSettingsKey key) => key.UseSingleLineDeclarationComments); string middleText = useSingleLineDeclarationComments ? string.Empty : Environment.NewLine; string emptyDocHeader = string.Format("<summary>{0}</summary>", middleText); if (!(declarationTreeNode is IMultipleDeclarationMember)) { emptyDocHeader = CreateDocumentationForElement((IDocCommentBlockOwner)declaration, docConfig); emptyDocHeader = emptyDocHeader.Substring(0, emptyDocHeader.Length - Environment.NewLine.Length); } string header = LayoutDocumentationHeader(emptyDocHeader, declaration); IDocCommentBlock newDocCommentNode = Utils.CreateDocCommentBlockNode(file, header); IDocCommentBlockOwner docCommentBlockOwnerNode = Utils.GetDocCommentBlockOwnerNodeForDeclaration(declaration); if (docCommentBlockOwnerNode != null) { docCommentBlockOwnerNode.SetDocCommentBlock(newDocCommentNode); } return(new DeclarationHeader(declaration)); } }
public void Process(IDocCommentBlock docCommentBlockNode) { if (IsValid() == false) { return; } AnalyzeUnit.DocumentationBlock = new DocCommentBlockModel(AnalyzeUnit, docCommentBlockNode); }
/// <summary> /// Reflow the given comment block to fit within the given maximum line length /// </summary> /// <param name="blockNode">The comment block to reflow</param> /// <param name="maxLineLength">The maximum line length</param> /// <returns>The text for the new reflown comment.</returns> public string ReflowAndRetag(IDocCommentBlock blockNode, int maxLineLength) { ITreeNode parent = blockNode.Parent; ICSharpTypeMemberDeclaration parentDeclaration = parent as IClassMemberDeclaration; if (parentDeclaration == null) { IMultipleFieldDeclaration multipleFieldDeclaration = parent as IMultipleFieldDeclaration; if (multipleFieldDeclaration != null) { foreach (IFieldDeclaration field in multipleFieldDeclaration.Children <IFieldDeclaration>()) { parentDeclaration = field; break; } } IEnumMemberDeclaration enumMemberDeclaration = parent as IEnumMemberDeclaration; if (enumMemberDeclaration != null) { parentDeclaration = enumMemberDeclaration; } } // get the xml from the comment XmlNode node = blockNode.GetXML(null); // Walk the xml tree and process elements as we go. Use a recursive algo for now - comments shouldn't be that complex. XmlCommentOptions options = new XmlCommentOptions(); options.Declaration = parentDeclaration; options.IdentifierLookupScope = IdentifierLookupScopes.ProjectAndUsings; options.Solution = blockNode.GetSolution(); List <Regex> ignoreList = new List <Regex>(_settings.CompiledWordsToIgnoreForMetatagging); ignoreList.Add(new Regex("^[Aa]$")); ignoreList.Add(new Regex("^[iI]f$")); ignoreList.Add(new Regex("^[tT]his$")); ignoreList.Add(new Regex("^[eE]lse$")); ignoreList.Add(new Regex("^[lL]ong$")); ignoreList.Add(new Regex("^[wW]hile$")); ignoreList.Add(new Regex("^[lL]ock$")); ignoreList.Add(new Regex("^[fF]ixed$")); ignoreList.Add(new Regex("^[bB]ase$")); ignoreList.Add(new Regex("^[oO]bject$")); options.IdentifiersToIgnoreForMetaTagging = ignoreList; options.Settings = _reflowSettings; XmlComments.XmlComment comment = new XmlComments.XmlComment(options); comment.FromXml(node); comment.InsertMissingTags(); return(comment.ToXml(0, maxLineLength, 0)); }
private IEnumerable <Range> GetWordsFromXmlComment(IDocCommentBlock docBlock) { if (docBlock != null) { XmlDocLexer lexer = new XmlDocLexer(docBlock); lexer.Start(); int inCode = 0; while (lexer.TokenType != null) { if (lexer.TokenType == lexer.XmlTokenType.TAG_START) { lexer.Advance(); if (lexer.TokenType == lexer.XmlTokenType.IDENTIFIER && (lexer.TokenText == "code" || lexer.TokenText == "c")) { inCode++; } while (lexer.TokenType != lexer.XmlTokenType.TAG_END && lexer.TokenType != lexer.XmlTokenType.TAG_END1 && lexer.TokenType != null) { lexer.Advance(); } if (lexer.TokenType == lexer.XmlTokenType.TAG_END1) { inCode--; } } if (lexer.TokenType == lexer.XmlTokenType.TAG_START1) { lexer.Advance(); if (lexer.TokenType == lexer.XmlTokenType.IDENTIFIER && (lexer.TokenText == "code" || lexer.TokenText == "c")) { inCode--; } } if (lexer.TokenType == lexer.XmlTokenType.TEXT && inCode == 0) { ILexer wordLexer = new WordLexer(lexer.TokenText); wordLexer.Start(); while (wordLexer.TokenType != null) { int start = lexer.CurrentNode.GetTreeStartOffset().Offset + lexer.TokenStart + wordLexer.TokenStart; int end = start + wordLexer.GetCurrTokenText().Length; yield return(new Range(wordLexer.GetCurrTokenText(), new TreeTextRange(new TreeOffset(start), new TreeOffset(end)))); wordLexer.Advance(); } } lexer.Advance(); } } }
private static bool ShallEscape(IDocCommentNode node, int offset) { IDocCommentBlock docBlock = node.GetContainingNode <IDocCommentBlock>(true); if (docBlock == null) { return(false); } XmlDocLexer lexer = new XmlDocLexer(docBlock); lexer.Start(); bool inCData = false; bool insideTag = false; while (lexer.TokenType != null) { if (lexer.TokenType == lexer.XmlTokenType.TAG_START) { insideTag = true; } else if (lexer.TokenType == lexer.XmlTokenType.TAG_END) { insideTag = false; } else if (lexer.TokenType == lexer.XmlTokenType.TAG_START1) { insideTag = true; } else if (lexer.TokenType == lexer.XmlTokenType.TAG_END1) { insideTag = false; } else if (lexer.TokenType == lexer.XmlTokenType.CDATA_START) { inCData = true; } else if (lexer.TokenType == lexer.XmlTokenType.CDATA_END) { inCData = false; } else if (offset >= lexer.TokenLocalRange.StartOffset && offset <= lexer.TokenLocalRange.EndOffset) { return(!inCData && !insideTag); } else if (offset < lexer.TokenLocalRange.StartOffset) { return(false); } lexer.Advance(); } return(false); }
public IEnumerable <Paragraph> Parse(IDocCommentBlock blockNode) { // Create a lexer which can read the comment XmlCommentReflowableBlockLexer lexer = new XmlCommentReflowableBlockLexer(blockNode); // Create a parser which can turn the comment into paragraphs and lines XmlCommentParagraphParser paragraphParser = new XmlCommentParagraphParser(lexer); // Firstly walk through the paragraphs and: // - collapse each one to the minimum number of required lines (tags always take a whole line at this stage). // - remove extra whitespace. There's no point in having it, it wont show in generated doco return(paragraphParser.Parse()); }
public static void ReFlowCommentNode(ISolution solution, IProgressIndicator progress, [NotNull] IDocCommentNode docCommentNode) { // Get the comment block owner (ie the part of the declaration which will own the comment). IDocCommentBlock blockNode = docCommentNode.GetContainingNode <IDocCommentBlock>(); if (blockNode == null) { return; } ReFlowCommentBlockNode(solution, progress, blockNode); }
/// <summary> /// The execute transaction inner. /// </summary> /// <param name="solution"> /// The solution. /// </param> /// <param name="textControl"> /// The text control. /// </param> public override void ExecuteTransactionInner(ISolution solution, ITextControl textControl) { ITreeNode element = Utils.GetElementAtCaret(solution, textControl); ITreeNode currentNode = element; IDocCommentNode docCommentNode = currentNode as IDocCommentNode; IDocCommentBlock containingElement = docCommentNode.GetContainingNode <IDocCommentBlock>(true); ITreeNode rightNode = containingElement.FindFormattingRangeToRight(); Utils.RemoveNewLineBefore(rightNode); }
public static void ReflowAndRetagCommentBlockNode(ISolution solution, IProgressIndicator progress, IDocCommentBlock docCommentBlockNode) { if (docCommentBlockNode == null) { return; } // Get the settings. IContextBoundSettingsStore settingsStore = Shell.Instance.GetComponent <ISettingsStore>().BindToContextTransient(ContextRange.ApplicationWide); XmlDocumentationSettings settings = settingsStore.GetKey <XmlDocumentationSettings>(SettingsOptimization.OptimizeDefault); ReflowAndRetagSettings reflowSettings = settingsStore.GetKey <ReflowAndRetagSettings>(SettingsOptimization.OptimizeDefault); int maxLength = settings.MaxCharactersPerLine; // Get the comment block owner (ie the part of the declaration which will own the comment). IDocCommentBlockOwner ownerNode = docCommentBlockNode.GetContainingNode <IDocCommentBlockOwner>(); // If we didn't get an owner then give up if (ownerNode == null) { return; } // Get a factory which can create elements in the C# docs //CSharpElementFactory factory = CSharpElementFactory.GetInstance(ownerNode.GetPsiModule()); // Calculate line offset where /// starts and add 4 for the slashes and space int startPos = CalcLineOffset(ownerNode) + 4; // Create a new comment block with the adjusted text IDocCommentBlock comment = docCommentBlockNode; //factory.CreateDocCommentBlock(text); string reflownText = new XmlCommentReflower(settings, reflowSettings).ReflowAndRetag(comment, maxLength - startPos); // If the xml was malformed then the comment will now be empty - detect this and do nothing if (string.IsNullOrEmpty(reflownText)) { return; } /*comment = factory.CreateDocCommentBlock(reflownText); * * // And set the comment on the declaration. * ownerNode.SetDocCommentBlockNode(comment);*/ SetDocComment(ownerNode, reflownText, solution); }
public static void ReflowAndRetagCommentNode(ISolution solution, IProgressIndicator progress, IDocCommentNode docCommentNode) { if (docCommentNode == null) { return; } IDocCommentBlock blockNode = docCommentNode.GetContainingNode <IDocCommentBlock>(); if (blockNode == null) { return; } ReflowAndRetagCommentBlockNode(solution, progress, blockNode); }
public static void ReFlowCommentBlockNode(ISolution solution, IProgressIndicator progress, IDocCommentBlock docCommentBlockNode) { if (docCommentBlockNode == null) { return; } // Get the settings. IContextBoundSettingsStore settingsStore = Shell.Instance.GetComponent <ISettingsStore>().BindToContextTransient(ContextRange.ApplicationWide); XmlDocumentationSettings settings = settingsStore.GetKey <XmlDocumentationSettings>(SettingsOptimization.OptimizeDefault); ReflowAndRetagSettings reflowSettings = settingsStore.GetKey <ReflowAndRetagSettings>(SettingsOptimization.OptimizeDefault); int maxLength = settings.MaxCharactersPerLine; IDocCommentBlockOwner ownerNode = docCommentBlockNode.GetContainingNode <IDocCommentBlockOwner>(); // If we didn't get an owner then give up if (ownerNode == null) { return; } // Get a factory which can create elements in the C# docs //CSharpElementFactory factory = CSharpElementFactory.GetInstance(ownerNode.GetPsiModule()); // Calculate line offset where /// starts and add 3 for each // slash. int startPos = CalcLineOffset(ownerNode) + 3; // Create a new comment block with the adjusted text IDocCommentBlock comment = docCommentBlockNode; //factory.CreateDocCommentBlock(text); // Work out if we have a space between the /// and <summary> string reflownText = new XmlCommentReflower(settings, reflowSettings).Reflow(comment, maxLength - startPos); //comment = factory.CreateDocCommentBlock(reflownText); SetDocComment(ownerNode, reflownText, solution); // And set the comment on the declaration. //ownerNode.SetDocCommentBlockNode(comment); }
/// <summary> /// Updates the elements header with the current xml. /// </summary> public void Update() { if (this.DocCommentBlockNode != null) { IFile file = this.Declaration.GetContainingFile(); using (this.DocCommentBlockNode.CreateWriteLock()) { string header = LayoutDocumentationHeader(this.XmlNode, this.Declaration); IDocCommentBlock newDocCommentNode = Utils.CreateDocCommentBlockNode(file, header); if (newDocCommentNode == null) { ModificationUtil.DeleteChild(this.DocCommentBlockNode); } else { ModificationUtil.ReplaceChild(this.DocCommentBlockNode, newDocCommentNode); } } } }
public void CheckCommentSpelling(IClassMemberDeclaration decl, [CanBeNull] IDocCommentBlock docNode, DefaultHighlightingConsumer consumer, bool spellCheck) { if (docNode == null) { return; } IFile file = decl.GetContainingFile(); if (file == null) { return; } foreach (Range wordRange in this.GetWordsFromXmlComment(docNode)) { DocumentRange range = file.GetDocumentRange(wordRange.TreeTextRange); string word = wordRange.Word; if (decl.DeclaredName != word) { if ((IdentifierResolver.IsIdentifier(decl, _solution, word, _identifierSettings.IdentifierLookupScope) || IdentifierResolver.IsKeyword(decl, _solution, word)) && IdentifierResolver.AnalyzeForMetaTagging(word, _xmlDocumentationSettings.CompiledWordsToIgnoreForMetatagging)) { consumer.AddHighlighting( new CanBeSurroundedWithMetatagsHighlight(word, range, decl, _solution), range); } else if (spellCheck) { this.CheckWordSpelling(decl, wordRange, consumer, range); } } } }
public XmlDocLexer(IDocCommentBlock docCommentBlock) { _myDocCommentBlock = docCommentBlock; Start(); }
public XmlCommentReflowableBlockLexer(IDocCommentBlock docCommentBlock) { _docLexer = new XmlDocLexer(docCommentBlock); _docLexer.Start(); }
/// <summary> /// /// </summary> /// <param name="blockNode"></param> /// <param name="maxLineLength"></param> /// <returns></returns> public string Reflow(IDocCommentBlock blockNode, int maxLineLength) { return(ReflowToLineLength(Parse(blockNode), maxLineLength)); }
public void Process(IDocCommentBlock docCommentBlockNode) { }
public void SetDocCommentBlock(IDocCommentBlock block) { _classDeclaration.SetDocCommentBlock(block); }