/// <inheritdoc /> public void AugmentCompletionSession(ICompletionSession session, IList <CompletionSet> completionSets) { // The IntelliSense calculation within comments is rather simple. To detect when the completion is // currently located within an XML documentation comment, the following "tricks" are used. // // 1. The filtering algorithm in use never removes "!--" (indicating an XML comment) from the // completion set, so it is always listed when completion is invoked. In addition, the sorting // algorithm always places this item first in the completion set. // 2. Since this particular tag is not valid elsewhere in C#, it is easily used to determine when the // caret is inside an XML documentation comment. if (completionSets.Count == 0 || completionSets[0].Completions.Count == 0 || completionSets[0].Completions[0].DisplayText != "!--") { // Not inside a documentation comment, so leave things alone return; } // Next, we need to determine if the user pressed "<" or simply pressed Ctrl+Space to invoke code // completion. Since the C# IntelliSense provider doesn't include any existing "<" character in the // reported ApplicableTo tracking span, we must insert this character when it's not already present. // XML itself makes this easy - the "<" character will either appear immediately before the // ApplicableTo span or it will not be present. ITextSnapshot snapshot = _textBuffer.CurrentSnapshot; SnapshotPoint startPoint = completionSets[0].ApplicableTo.GetStartPoint(snapshot); string prefix = String.Empty; if (startPoint > 0 && snapshot.GetText(startPoint.Position - 1, 1) != "<") { prefix = "<"; } // Use the GlyphKeyword glyph for "normal" XML tags, to match the glyphs used by C# // for the standard IntelliSense tags. Use the GlyphGroupMacro glyph for other completion // items that expand to something other that what the user wrote (e.g. "true" expands to // <see langword="true"/> as opposed to <true/>). // // The descriptions for custom tags is copied from the Sandcastle XML Comments Guide. Obsolete // custom tags are not included. var iconSource = _provider.GlyphService.GetGlyph(StandardGlyphGroup.GlyphKeyword, StandardGlyphItem.GlyphItemPublic); var macroIconSource = _provider.GlyphService.GetGlyph(StandardGlyphGroup.GlyphGroupMacro, StandardGlyphItem.GlyphItemPublic); // The elements are context sensitive so only show them if applicable based on the elements // determined to be valid by the C# IntelliSense provider. var allTags = completionSets.SelectMany(c => c.CompletionBuilders).Select(b => b.DisplayText).Concat( completionSets.SelectMany(c => c.Completions).Select(c => c.DisplayText)).ToList(); // Elements allowed anywhere var completions = new List <Completion> { new CustomCompletion(session, "conceptualLink", prefix + "conceptualLink target=\"\xFF\"/>", "This element is used to create a link to a MAML topic within the See Also section of a " + "topic or an inline link to a MAML topic within one of the other XML comments elements.", iconSource, ""), new Completion("inheritdoc", prefix + "inheritdoc/>", "This element can help minimize the " + "effort required to document complex APIs by allowing common documentation to be " + "inherited from base types/members.", iconSource, ""), new CustomCompletion(session, "inheritdoc cref", prefix + "inheritdoc cref=\"\xFF\"/>", "Inherit documentation from a specific member.", iconSource, ""), new CustomCompletion(session, "inheritdoc cref/select", prefix + "inheritdoc cref=\"\xFF\" " + "select=\"summary|remarks\"/>", "Inherit documentation from a specific member and comments.", iconSource, ""), new Completion("token", prefix + "token", "This element represents a replaceable tag within " + "a topic.", iconSource, "") }; // General top-level elements if (allTags.Contains("exception")) { completions.AddRange(new[] { new Completion("AttachedEventComments", prefix + "AttachedEventComments", "This element " + "is used to define the content that should appear on the auto-generated attached " + "event member topic for a given WPF routed event member.", iconSource, ""), new Completion("AttachedPropertyComments", prefix + "AttachedPropertyComments", "This element is used to define the content that should appear on the auto-generated " + "attached property member topic for a given WPF dependency property member.", iconSource, ""), new CustomCompletion(session, "event", prefix + "event cref=\"\xFF\"", "This element is used to list events that can be raised by a type's member.", iconSource, ""), new Completion("overloads", prefix + "overloads", "This element is used to define the " + "content that should appear on the auto-generated overloads topic for a given set of " + "member overloads.", iconSource, ""), new Completion("preliminary", prefix + "preliminary/>", "This element is used to indicate that a particular type or member is preliminary and " + "is subject to change.", iconSource, ""), new Completion("threadsafety", prefix + "threadsafety static=\"true\" instance=\"false\"/>", "This element is used to indicate whether or not a class or structure's static and " + "instance members are safe for use in multi-threaded scenarios.", iconSource, "") }); } // General inline elements if (allTags.Contains("list")) { completions.AddRange(new[] { new Completion("note", prefix + "note type=\"note\"", "This element is used to create a " + "note-like section within a topic to draw attention to some important information.", iconSource, "") }); // Language-specific keyword extensions. The C# provider allows these at any level but // Sandcastle only uses them if they are inline. completions.AddRange(new[] { new Completion("null", prefix + "see langword=\"null\"/>", "Inserts the language-specific " + "keyword 'null'.", macroIconSource, ""), new Completion("static", prefix + "see langword=\"static\"/>", "Inserts the " + "language-specific keyword 'static'.", macroIconSource, ""), new Completion("virtual", prefix + "see langword=\"virtual\"/>", "Inserts the " + "language-specific keyword 'virtual'.", macroIconSource, ""), new Completion("true", prefix + "see langword=\"true\"/>", "Inserts the language-specific " + "keyword 'true'.", macroIconSource, ""), new Completion("false", prefix + "see langword=\"false\"/>", "Inserts the " + "language-specific keyword 'false'.", macroIconSource, ""), new Completion("abstract", prefix + "see langword=\"abstract\"/>", "Inserts the " + "language-specific keyword 'abstract'.", macroIconSource, ""), new Completion("async", prefix + "see langword=\"async\"/>", "Inserts the " + "language-specific keyword 'async'.", macroIconSource, ""), new Completion("await", prefix + "see langword=\"await\"/>", "Inserts the " + "language-specific keyword 'await'.", macroIconSource, ""), new Completion("async/await", prefix + "see langword=\"async/await\"/>", "Inserts the " + "language-specific keyword 'async/await'.", macroIconSource, "") }); } // Code element extensions if (allTags.Contains("code")) { completions.AddRange(new[] { new CustomCompletion(session, "code import", prefix + "code language=\"\xFF\" title=\" \" " + "source=\"..\\Path\\SourceFile.cs\" region=\"Region Name\"/>", "This element is used " + "to indicate that a multi-line section of text should be imported from the named " + "region of the named file and formatted as a code block.", iconSource, ""), new CustomCompletion(session, "code language", prefix + "code language=\"\xFF\" " + "title=\" \"></code>", "This element is used to indicate that a multi-line section of " + "text should be formatted as a code block.", iconSource, ""), }); } // The augmented completion set is created from the previously existing one (created by the C# // language service), and a CompletionSet created for the custom XML tags. The moniker and display // name for the additional set are not used, since the augmented set always returns the values // reported by the original completion set. CompletionSet additionalCompletionSet = new CompletionSet("", "", completionSets[0].ApplicableTo, completions, Enumerable.Empty <Completion>()); completionSets[0] = new AugmentedCompletionSet(session, completionSets[0], additionalCompletionSet); }
/// <inheritdoc /> public void AugmentCompletionSession(ICompletionSession session, IList<CompletionSet> completionSets) { // The IntelliSense calculation within comments is rather simple. To detect when the completion is // currently located within an XML documentation comment, the following "tricks" are used. // // 1. The filtering algorithm in use never removes "!--" (indicating an XML comment) from the // completion set, so it is always listed when completion is invoked. In addition, the sorting // algorithm always places this item first in the completion set. // 2. Since this particular tag is not valid elsewhere in C#, it is easily used to determine when the // caret is inside an XML documentation comment. if(completionSets.Count == 0 || completionSets[0].Completions.Count == 0 || completionSets[0].Completions[0].DisplayText != "!--") { // Not inside a documentation comment, so leave things alone return; } // Next, we need to determine if the user pressed "<" or simply pressed Ctrl+Space to invoke code // completion. Since the C# IntelliSense provider doesn't include any existing "<" character in the // reported ApplicableTo tracking span, we must insert this character when it's not already present. // XML itself makes this easy - the "<" character will either appear immediately before the // ApplicableTo span or it will not be present. ITextSnapshot snapshot = _textBuffer.CurrentSnapshot; SnapshotPoint startPoint = completionSets[0].ApplicableTo.GetStartPoint(snapshot); string prefix = String.Empty; if(startPoint > 0 && snapshot.GetText(startPoint.Position - 1, 1) != "<") prefix = "<"; // Use the GlyphKeyword glyph for "normal" XML tags, to match the glyphs used by C# // for the standard IntelliSense tags. Use the GlyphGroupMacro glyph for other completion // items that expand to something other that what the user wrote (e.g. "true" expands to // <see langword="true"/> as opposed to <true/>). // // The descriptions for custom tags is copied from the Sandcastle XML Comments Guide. Obsolete // custom tags are not included. var iconSource = _provider.GlyphService.GetGlyph(StandardGlyphGroup.GlyphKeyword, StandardGlyphItem.GlyphItemPublic); var macroIconSource = _provider.GlyphService.GetGlyph(StandardGlyphGroup.GlyphGroupMacro, StandardGlyphItem.GlyphItemPublic); // The elements are context sensitive so only show them if applicable based on the elements // determined to be valid by the C# IntelliSense provider. var allTags = completionSets.SelectMany(c => c.CompletionBuilders).Select(b => b.DisplayText).Concat( completionSets.SelectMany(c => c.Completions).Select(c => c.DisplayText)).ToList(); // Elements allowed anywhere var completions = new List<Completion> { new CustomCompletion(session, "conceptualLink", prefix + "conceptualLink target=\"\xFF\"/>", "This element is used to create a link to a MAML topic within the See Also section of a " + "topic or an inline link to a MAML topic within one of the other XML comments elements.", iconSource, ""), new Completion("inheritdoc", prefix + "inheritdoc/>", "This element can help minimize the " + "effort required to document complex APIs by allowing common documentation to be " + "inherited from base types/members.", iconSource, ""), new CustomCompletion(session, "inheritdoc cref", prefix + "inheritdoc cref=\"\xFF\"/>", "Inherit documentation from a specific member.", iconSource, ""), new CustomCompletion(session, "inheritdoc cref/select", prefix + "inheritdoc cref=\"\xFF\" " + "select=\"summary|remarks\"/>", "Inherit documentation from a specific member and comments.", iconSource, ""), new Completion("token", prefix + "token", "This element represents a replaceable tag within " + "a topic.", iconSource, "") }; // General top-level elements if(allTags.Contains("exception")) completions.AddRange(new[] { new Completion("AttachedEventComments", prefix + "AttachedEventComments", "This element " + "is used to define the content that should appear on the auto-generated attached " + "event member topic for a given WPF routed event member.", iconSource, ""), new Completion("AttachedPropertyComments", prefix + "AttachedPropertyComments", "This element is used to define the content that should appear on the auto-generated " + "attached property member topic for a given WPF dependency property member.", iconSource, ""), new CustomCompletion(session, "event", prefix + "event cref=\"\xFF\"", "This element is used to list events that can be raised by a type's member.", iconSource, ""), new Completion("overloads", prefix + "overloads", "This element is used to define the " + "content that should appear on the auto-generated overloads topic for a given set of " + "member overloads.", iconSource, ""), new Completion("preliminary", prefix + "preliminary/>", "This element is used to indicate that a particular type or member is preliminary and " + "is subject to change.", iconSource, ""), new Completion("threadsafety", prefix + "threadsafety static=\"true\" instance=\"false\"/>", "This element is used to indicate whether or not a class or structure's static and " + "instance members are safe for use in multi-threaded scenarios.", iconSource, "") }); // General inline elements if(allTags.Contains("list")) { completions.AddRange(new[] { new Completion("note", prefix + "note type=\"note\"", "This element is used to create a " + "note-like section within a topic to draw attention to some important information.", iconSource, "") }); // Language-specific keyword extensions. The C# provider allows these at any level but // Sandcastle only uses them if they are inline. completions.AddRange(new[] { new Completion("null", prefix + "see langword=\"null\"/>", "Inserts the language-specific " + "keyword 'null'.", macroIconSource, ""), new Completion("static", prefix + "see langword=\"static\"/>", "Inserts the " + "language-specific keyword 'static'.", macroIconSource, ""), new Completion("virtual", prefix + "see langword=\"virtual\"/>", "Inserts the " + "language-specific keyword 'virtual'.", macroIconSource, ""), new Completion("true", prefix + "see langword=\"true\"/>", "Inserts the language-specific " + "keyword 'true'.", macroIconSource, ""), new Completion("false", prefix + "see langword=\"false\"/>", "Inserts the " + "language-specific keyword 'false'.", macroIconSource, ""), new Completion("abstract", prefix + "see langword=\"abstract\"/>", "Inserts the " + "language-specific keyword 'abstract'.", macroIconSource, ""), new Completion("async", prefix + "see langword=\"async\"/>", "Inserts the " + "language-specific keyword 'async'.", macroIconSource, ""), new Completion("await", prefix + "see langword=\"await\"/>", "Inserts the " + "language-specific keyword 'await'.", macroIconSource, ""), new Completion("async/await", prefix + "see langword=\"async/await\"/>", "Inserts the " + "language-specific keyword 'async/await'.", macroIconSource, "") }); } // Code element extensions if(allTags.Contains("code")) completions.AddRange(new[] { new CustomCompletion(session, "code import", prefix + "code language=\"\xFF\" title=\" \" " + "source=\"..\\Path\\SourceFile.cs\" region=\"Region Name\"/>", "This element is used " + "to indicate that a multi-line section of text should be imported from the named " + "region of the named file and formatted as a code block.", iconSource, ""), new CustomCompletion(session, "code language", prefix + "code language=\"\xFF\" " + "title=\" \"></code>", "This element is used to indicate that a multi-line section of " + "text should be formatted as a code block.", iconSource, ""), }); // The augmented completion set is created from the previously existing one (created by the C# // language service), and a CompletionSet created for the custom XML tags. The moniker and display // name for the additional set are not used, since the augmented set always returns the values // reported by the original completion set. CompletionSet additionalCompletionSet = new CompletionSet("", "", completionSets[0].ApplicableTo, completions, Enumerable.Empty<Completion>()); completionSets[0] = new AugmentedCompletionSet(session, completionSets[0], additionalCompletionSet); }