-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Changes made: - Fixed loading of code analysis dictionaries with .NET Core/Standard SDK format project files. Fixes #228. - Update HtmlAgilityPack NuGet package and fixed up parser file offsets.
- Loading branch information
1 parent
fbe2bef
commit f29be90
Showing
15 changed files
with
211 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<topic id="e1588046-393b-4864-a3c1-6771b73bf124" revisionNumber="1"> | ||
<developerConceptualDocument xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
<introduction> | ||
<para>Changes in this release:</para> | ||
</introduction> | ||
|
||
<section> | ||
<content> | ||
<list class="bullet"> | ||
<listItem> | ||
<para>Fixed loading of code analysis dictionaries with .NET Core/Standard SDK format project files.</para> | ||
</listItem> | ||
|
||
<listItem> | ||
<para>Merged changes from Walter Goodwin to add a spell checker toolbar.</para> | ||
</listItem> | ||
|
||
</list> | ||
|
||
</content> | ||
</section> | ||
|
||
<relatedTopics> | ||
<link xlink:href="548dc6d7-6d08-4006-82b3-d5830be96f04" /> | ||
</relatedTopics> | ||
|
||
</developerConceptualDocument> | ||
</topic> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,8 @@ | |
// System : Visual Studio Spell Checker Package | ||
// File : CodeClassifier.cs | ||
// Author : Eric Woodruff ([email protected]) | ||
// Updated : 09/02/2018 | ||
// Note : Copyright 2015-2018, Eric Woodruff, All rights reserved | ||
// Compiler: Microsoft Visual C# | ||
// Updated : 02/28/2021 | ||
// Note : Copyright 2015-2021, Eric Woodruff, All rights reserved | ||
// | ||
// This file contains a class used to classify source code file content using a set of regular expressions | ||
// | ||
|
@@ -199,41 +198,73 @@ private void ParseNode(HtmlNode node, List<SpellCheckSpan> spans) | |
var commentNode = (HtmlCommentNode)node; | ||
|
||
if(commentNode.OuterHtml.StartsWith("<!--", StringComparison.Ordinal)) | ||
{ | ||
#if DEBUG | ||
// The parser offsets changed in an update to the HtmlAgilityPack. Catch any further | ||
// changes as we'll need to fix our computed offsets again. | ||
if(!this.Text.Substring(this.GetOffset(commentNode.Line, commentNode.LinePosition + 1), | ||
commentNode.OuterHtml.Length).Equals(commentNode.OuterHtml, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
System.Diagnostics.Debugger.Break(); | ||
} | ||
#endif | ||
spans.Add(new SpellCheckSpan | ||
{ | ||
Span = new Span(this.AdjustedOffset(this.GetOffset(commentNode.Line, | ||
commentNode.LinePosition) - 1, commentNode.OuterHtml), | ||
commentNode.LinePosition + 1), commentNode.OuterHtml), | ||
commentNode.OuterHtml.Length), | ||
Text = commentNode.OuterHtml, | ||
Classification = RangeClassification.XmlFileComment | ||
}); | ||
} | ||
break; | ||
|
||
case HtmlNodeType.Text: | ||
var textNode = (HtmlTextNode)node; | ||
|
||
if(!HtmlNode.IsOverlappedClosingElement(textNode.Text) && textNode.Text.Trim().Length != 0) | ||
{ | ||
#if DEBUG | ||
// See above | ||
if(!this.Text.Substring(this.GetOffset(textNode.Line, textNode.LinePosition + 1), | ||
textNode.Text.Length).Equals(textNode.Text, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
System.Diagnostics.Debugger.Break(); | ||
} | ||
#endif | ||
spans.Add(new SpellCheckSpan | ||
{ | ||
Span = new Span(this.GetOffset(textNode.Line, textNode.LinePosition), | ||
Span = new Span(this.GetOffset(textNode.Line, textNode.LinePosition + 1), | ||
textNode.Text.Length), | ||
Text = textNode.Text, | ||
Classification = RangeClassification.XmlCommentsInnerText | ||
}); | ||
} | ||
break; | ||
|
||
case HtmlNodeType.Element: | ||
foreach(var attribute in node.Attributes) | ||
if(this.SpellCheckConfiguration.SpellCheckedXmlAttributes.Contains(attribute.Name) && | ||
!String.IsNullOrWhiteSpace(attribute.Value)) | ||
{ | ||
#if DEBUG | ||
// See above | ||
if(!this.Text.Substring(this.GetOffset(attribute.Line, attribute.LinePosition + | ||
attribute.Name.Length + 3), attribute.Value.Length).Equals(attribute.Value, | ||
StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
System.Diagnostics.Debugger.Break(); | ||
} | ||
#endif | ||
spans.Add(new SpellCheckSpan | ||
{ | ||
Span = new Span(this.AdjustedOffset(this.GetOffset(attribute.Line, | ||
attribute.LinePosition + attribute.Name.Length + 1), attribute.Value), | ||
attribute.LinePosition + attribute.Name.Length + 3), attribute.Value), | ||
attribute.Value.Length), | ||
Text = attribute.Value, | ||
Classification = RangeClassification.AttributeValue | ||
}); | ||
} | ||
|
||
if(!this.SpellCheckConfiguration.IgnoredXmlElements.Contains(node.Name) && node.HasChildNodes) | ||
foreach(HtmlNode subnode in node.ChildNodes) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,8 @@ | |
// System : Visual Studio Spell Checker Package | ||
// File : HtmlClassifier.cs | ||
// Author : Eric Woodruff ([email protected]) | ||
// Updated : 09/17/2018 | ||
// Note : Copyright 2015-2018, Eric Woodruff, All rights reserved | ||
// Compiler: Microsoft Visual C# | ||
// Updated : 02/28/2021 | ||
// Note : Copyright 2015-2021, Eric Woodruff, All rights reserved | ||
// | ||
// This file contains a class used to classify HTML file content | ||
// | ||
|
@@ -132,11 +131,19 @@ private void ParseNode(HtmlNode node, List<SpellCheckSpan> spans) | |
// by the node parser but we don't want to include them. | ||
if(commentNode.OuterHtml.StartsWith("<!--", StringComparison.Ordinal)) | ||
{ | ||
#if DEBUG | ||
// The parser offsets changed in an update to the HtmlAgilityPack. Catch any further | ||
// changes as we'll need to fix our computed offsets again. | ||
if(!this.Text.Substring(this.GetOffset(commentNode.Line, commentNode.LinePosition + 1), | ||
commentNode.OuterHtml.Length).Equals(commentNode.OuterHtml, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
System.Diagnostics.Debugger.Break(); | ||
} | ||
#endif | ||
spans.Add(new SpellCheckSpan | ||
{ | ||
Span = new Span(this.AdjustedOffset(this.GetOffset(commentNode.Line, | ||
commentNode.LinePosition) - 1, commentNode.OuterHtml), | ||
commentNode.OuterHtml.Length), | ||
commentNode.LinePosition + 1), commentNode.OuterHtml), commentNode.OuterHtml.Length), | ||
Text = commentNode.OuterHtml, | ||
Classification = RangeClassification.XmlFileComment | ||
}); | ||
|
@@ -148,8 +155,20 @@ private void ParseNode(HtmlNode node, List<SpellCheckSpan> spans) | |
|
||
if(!HtmlNode.IsOverlappedClosingElement(textNode.Text) && textNode.Text.Trim().Length != 0) | ||
{ | ||
if(!this.DeterminePageLanguage(textNode.Text, this.GetOffset(textNode.Line, textNode.LinePosition), spans)) | ||
this.ParseScriptBlocks(textNode.Text, this.GetOffset(textNode.Line, textNode.LinePosition), spans); | ||
if(!this.DeterminePageLanguage(textNode.Text, this.GetOffset(textNode.Line, | ||
textNode.LinePosition + 1), spans)) | ||
{ | ||
#if DEBUG | ||
// See above | ||
if(!this.Text.Substring(this.GetOffset(textNode.Line, textNode.LinePosition + 1), | ||
textNode.Text.Length).Equals(textNode.Text, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
System.Diagnostics.Debugger.Break(); | ||
} | ||
#endif | ||
this.ParseScriptBlocks(textNode.Text, this.GetOffset(textNode.Line, | ||
textNode.LinePosition + 1), spans); | ||
} | ||
} | ||
break; | ||
|
||
|
@@ -158,10 +177,19 @@ private void ParseNode(HtmlNode node, List<SpellCheckSpan> spans) | |
if(this.SpellCheckConfiguration.SpellCheckedXmlAttributes.Contains(attribute.Name) && | ||
!String.IsNullOrWhiteSpace(attribute.Value)) | ||
{ | ||
#if DEBUG | ||
// See above | ||
if(!this.Text.Substring(this.GetOffset(attribute.Line, attribute.LinePosition + | ||
attribute.Name.Length + 3), attribute.Value.Length).Equals(attribute.Value, | ||
StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
System.Diagnostics.Debugger.Break(); | ||
} | ||
#endif | ||
spans.Add(new SpellCheckSpan | ||
{ | ||
Span = new Span(this.AdjustedOffset(this.GetOffset(attribute.Line, | ||
attribute.LinePosition + attribute.Name.Length + 1), attribute.Value), | ||
attribute.LinePosition + attribute.Name.Length + 3), attribute.Value), | ||
attribute.Value.Length), | ||
Text = attribute.Value, | ||
Classification = RangeClassification.AttributeValue | ||
|
@@ -171,7 +199,18 @@ private void ParseNode(HtmlNode node, List<SpellCheckSpan> spans) | |
if(!this.SpellCheckConfiguration.IgnoredXmlElements.Contains(node.Name) && node.HasChildNodes) | ||
{ | ||
if(node.Name == "script") | ||
this.ParseScriptElement(node.OuterHtml, this.GetOffset(node.Line, node.LinePosition), spans); | ||
{ | ||
#if DEBUG | ||
// See above | ||
if(!this.Text.Substring(this.GetOffset(node.Line, node.LinePosition + 1), | ||
node.OuterHtml.Length).Equals(node.OuterHtml, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
System.Diagnostics.Debugger.Break(); | ||
} | ||
#endif | ||
this.ParseScriptElement(node.OuterHtml, this.GetOffset(node.Line, | ||
node.LinePosition + 1), spans); | ||
} | ||
else | ||
foreach(HtmlNode subnode in node.ChildNodes) | ||
this.ParseNode(subnode, spans); | ||
|
@@ -248,10 +287,15 @@ private void ParseScriptBlocks(string text, int offset, List<SpellCheckSpan> spa | |
{ | ||
// Adjust the span to set the position relative to the start of the block within this file | ||
s.Span = new Span(s.Span.Start + offset, s.Span.Length); | ||
|
||
System.Diagnostics.Debug.Assert(this.Text.Substring(s.Span.Start, s.Span.Length) == | ||
s.Text.Replace('<', '\xFE').Replace('>', '\xFF')); | ||
|
||
#if DEBUG | ||
// The parser offsets changed in an update to the HtmlAgilityPack. Catch any further | ||
// changes as we'll need to fix our computed offsets again. | ||
if(!this.Text.Substring(s.Span.Start, s.Span.Length).Equals( | ||
s.Text.Replace('<', '\xFE').Replace('>', '\xFF'), StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
System.Diagnostics.Debugger.Break(); | ||
} | ||
#endif | ||
spans.Add(s); | ||
} | ||
} | ||
|
@@ -295,9 +339,14 @@ private void ParseScriptElement(string script, int offset, List<SpellCheckSpan> | |
{ | ||
// Adjust the span to set the position relative to the start of the block within this file | ||
s.Span = new Span(s.Span.Start + offset + scriptElement.Index + scriptElement.Length, s.Span.Length); | ||
|
||
System.Diagnostics.Debug.Assert(this.Text.Substring(s.Span.Start, s.Span.Length) == s.Text); | ||
|
||
#if DEBUG | ||
// The parser offsets changed in an update to the HtmlAgilityPack. Catch any further | ||
// changes as we'll need to fix our computed offsets again. | ||
if(!this.Text.Substring(s.Span.Start, s.Span.Length).Equals(s.Text, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
System.Diagnostics.Debugger.Break(); | ||
} | ||
#endif | ||
spans.Add(s); | ||
} | ||
} | ||
|
@@ -336,6 +385,6 @@ private TextClassifier GetClassifier(string language) | |
|
||
return c; | ||
} | ||
#endregion | ||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,8 @@ | |
// System : Visual Studio Spell Checker Package | ||
// File : SpellCheckFileInfo.cs | ||
// Author : Eric Woodruff ([email protected]) | ||
// Updated : 03/17/2020 | ||
// Note : Copyright 2015-2020, Eric Woodruff, All rights reserved | ||
// Compiler: Microsoft Visual C# | ||
// Updated : 02/28/2021 | ||
// Note : Copyright 2015-2021, Eric Woodruff, All rights reserved | ||
// | ||
// This file contains a class used to hold information about a file that will be spell checked | ||
// | ||
|
@@ -89,6 +88,11 @@ internal class SpellCheckFileInfo | |
/// </summary> | ||
public string DependencyConfigurationFile { get; private set; } | ||
|
||
/// <summary> | ||
/// This read-only property returns true if this item represents a code analysis dictionary, false if not | ||
/// </summary> | ||
public bool IsCodeAnalysisDictionary { get; private set; } | ||
|
||
/// <summary> | ||
/// This returns a description of the item with the solution and relative path to the file | ||
/// </summary> | ||
|
@@ -145,6 +149,18 @@ public static SpellCheckFileInfo ForOpenDocument(string filename) | |
}; | ||
} | ||
|
||
/// <summary> | ||
/// This is used to get the code analysis dictionaries from the named project | ||
/// </summary> | ||
/// <param name="projectName">The project from which to get code analysis dictionaries</param> | ||
/// <returns>An enumerable list of the code analysis dictionary files if any</returns> | ||
public static IEnumerable<SpellCheckFileInfo> ProjectCodeAnalysisDictionaries(string projectName) | ||
{ | ||
Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread(); | ||
|
||
return AllProjectFiles(projectName).Where(f => f.IsCodeAnalysisDictionary); | ||
} | ||
|
||
/// <summary> | ||
/// This is used to get information for all files in the solution or a specific project | ||
/// </summary> | ||
|
@@ -507,9 +523,9 @@ private static void ProcessHierarchyNodeRecursively(IVsHierarchy hierarchy, uint | |
result = hierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_FirstVisibleChild, | ||
out object value); | ||
|
||
while(result == VSConstants.S_OK && value != null && value is int) | ||
while(result == VSConstants.S_OK && value != null && value is int nodeId) | ||
{ | ||
uint visibleChildNode = (uint)(int)value; | ||
uint visibleChildNode = (uint)nodeId; | ||
|
||
if(visibleChildNode == VSConstants.VSITEMID_NIL) | ||
break; | ||
|
@@ -564,11 +580,17 @@ private static SpellCheckFileInfo DetermineProjectFileInformation(IVsHierarchy h | |
Path.IsPathRooted(canonicalName) && !canonicalName.EndsWith("\\", StringComparison.Ordinal) && | ||
!canonicalName.Equals(projectName, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
result = hierarchy.GetProperty(itemId, (int)__VSHPROPID4.VSHPROPID_BuildAction, out value); | ||
|
||
bool isCodeAnalysisDictionary = (result == VSConstants.S_OK && value != null && | ||
((string)value).Equals("CodeAnalysisDictionary", StringComparison.OrdinalIgnoreCase)); | ||
|
||
return new SpellCheckFileInfo | ||
{ | ||
ProjectFile = projectName, | ||
Filename = name, | ||
CanonicalName = canonicalName | ||
CanonicalName = canonicalName, | ||
IsCodeAnalysisDictionary = isCodeAnalysisDictionary | ||
}; | ||
} | ||
} | ||
|
Oops, something went wrong.