提交 887e6938 编写于 作者: C Cyrus Najmabadi

Revert json features. They will be added in the jsonFeatures branch

上级 a0751db8
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.RegularExpressions;
using Microsoft.CodeAnalysis.VirtualChars;
namespace Microsoft.CodeAnalysis.ValidateRegexString
{
internal abstract class AbstractValidateRegexStringDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer
{
private readonly int _stringLiteralKind;
private readonly ISyntaxFactsService _syntaxFacts;
private readonly ISemanticFactsService _semanticFacts;
private readonly IVirtualCharService _virtualCharService;
protected AbstractValidateRegexStringDiagnosticAnalyzer(
int stringLiteralKind,
ISyntaxFactsService syntaxFacts,
ISemanticFactsService semanticFacts,
IVirtualCharService virtualCharService)
: base(IDEDiagnosticIds.RegexPatternDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Regex_issue_0), FeaturesResources.ResourceManager, typeof(FeaturesResources)))
{
_stringLiteralKind = stringLiteralKind;
_syntaxFacts = syntaxFacts;
_semanticFacts = semanticFacts;
_virtualCharService = virtualCharService;
}
public override DiagnosticAnalyzerCategory GetAnalyzerCategory()
=> DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
public override bool OpenFileOnly(Workspace workspace)
=> false;
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSemanticModelAction(AnalyzeSemanticModel);
private void AnalyzeSemanticModel(SemanticModelAnalysisContext context)
{
var semanticModel = context.SemanticModel;
var syntaxTree = semanticModel.SyntaxTree;
var cancellationToken = context.CancellationToken;
var options = context.Options;
var optionSet = options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult();
if (optionSet == null)
{
return;
}
var option = optionSet.GetOption(RegularExpressionsOptions.ReportInvalidRegexPatterns, syntaxTree.Options.Language);
if (!option)
{
return;
}
var detector = RegexPatternDetector.TryGetOrCreate(semanticModel, _syntaxFacts, _semanticFacts);
if (detector == null)
{
return;
}
var root = syntaxTree.GetRoot(cancellationToken);
Analyze(context, detector, _virtualCharService, root, cancellationToken);
}
private void Analyze(
SemanticModelAnalysisContext context, RegexPatternDetector detector,
IVirtualCharService virtualCharService, SyntaxNode node, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
foreach (var child in node.ChildNodesAndTokens())
{
if (child.IsNode)
{
Analyze(context, detector, virtualCharService, child.AsNode(), cancellationToken);
}
else
{
var token = child.AsToken();
if (token.RawKind == _stringLiteralKind)
{
var tree = detector.TryParseRegexPattern(token, virtualCharService, cancellationToken);
if (tree != null)
{
foreach (var diag in tree.Diagnostics)
{
context.ReportDiagnostic(Diagnostic.Create(
this.GetDescriptorWithSeverity(DiagnosticSeverity.Warning),
Location.Create(context.SemanticModel.SyntaxTree, diag.Span),
diag.Message));
}
}
}
}
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.CSharp.VirtualChars;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.CSharp.Classification.Classifiers
{
internal class RegexPatternTokenClassifier : AbstractSyntaxClassifier
{
public override ImmutableArray<int> SyntaxTokenKinds { get; } = ImmutableArray.Create((int)SyntaxKind.StringLiteralToken);
public override void AddClassifications(Workspace workspace, SyntaxToken token, SemanticModel semanticModel, ArrayBuilder<ClassifiedSpan> result, CancellationToken cancellationToken)
{
Debug.Assert(token.Kind() == SyntaxKind.StringLiteralToken);
CommonRegexPatternTokenClassifier.AddClassifications(
workspace, token, semanticModel, result,
CSharpSyntaxFactsService.Instance,
CSharpSemanticFactsService.Instance,
CSharpVirtualCharService.Instance,
cancellationToken);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using Microsoft.CodeAnalysis.Json;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.VirtualChars;
namespace Microsoft.CodeAnalysis.Classification
{
internal static class CommonJsonPatternTokenClassifier
{
private static ObjectPool<Visitor> _visitorPool = new ObjectPool<Visitor>(() => new Visitor());
public static void AddClassifications(
Workspace workspace, SyntaxToken token, SemanticModel semanticModel, ArrayBuilder<ClassifiedSpan> result,
ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, IVirtualCharService virtualCharService,
CancellationToken cancellationToken)
{
if (!workspace.Options.GetOption(JsonOptions.ColorizeJsonPatterns, LanguageNames.CSharp))
{
return;
}
// Do some quick syntactic checks before doing any complex work.
if (JsonPatternDetector.IsDefinitelyNotJson(token, syntaxFacts))
{
return;
}
var detector = JsonPatternDetector.GetOrCreate(semanticModel, syntaxFacts, semanticFacts, virtualCharService);
if (!detector.IsDefinitelyJson(token, cancellationToken))
{
return;
}
var tree = detector?.TryParseJson(token, cancellationToken);
if (tree == null)
{
return;
}
var visitor = _visitorPool.Allocate();
try
{
visitor.Result = result;
AddClassifications(tree.Root, visitor, result);
}
finally
{
visitor.Result = null;
_visitorPool.Free(visitor);
}
}
private static void AddClassifications(JsonNode node, Visitor visitor, ArrayBuilder<ClassifiedSpan> result)
{
node.Accept(visitor);
foreach (var child in node)
{
if (child.IsNode)
{
AddClassifications(child.Node, visitor, result);
}
else
{
AddTriviaClassifications(child.Token, result);
}
}
}
private static void AddTriviaClassifications(JsonToken token, ArrayBuilder<ClassifiedSpan> result)
{
foreach (var trivia in token.LeadingTrivia)
{
AddTriviaClassifications(trivia, result);
}
foreach (var trivia in token.TrailingTrivia)
{
AddTriviaClassifications(trivia, result);
}
}
private static void AddTriviaClassifications(JsonTrivia trivia, ArrayBuilder<ClassifiedSpan> result)
{
if ((trivia.Kind == JsonKind.MultiLineCommentTrivia || trivia.Kind == JsonKind.SingleLineCommentTrivia) &&
trivia.VirtualChars.Length > 0)
{
result.Add(new ClassifiedSpan(
ClassificationTypeNames.JsonComment, JsonHelpers.GetSpan(trivia.VirtualChars)));
}
}
private class Visitor : IJsonNodeVisitor
{
public ArrayBuilder<ClassifiedSpan> Result;
private void AddClassification(JsonToken token, string typeName)
{
if (!token.IsMissing)
{
Result.Add(new ClassifiedSpan(typeName, JsonHelpers.GetSpan(token)));
}
}
private void ClassifyWholeNode(JsonNode node, string typeName)
{
foreach (var child in node)
{
if (child.IsNode)
{
ClassifyWholeNode(child.Node, typeName);
}
else
{
AddClassification(child.Token, typeName);
}
}
}
public void Visit(JsonCompilationUnit node)
{
// nothing to do.
}
public void Visit(JsonSequenceNode node)
{
// nothing to do.
}
public void Visit(JsonArrayNode node)
{
AddClassification(node.OpenBracketToken, ClassificationTypeNames.JsonArray);
AddClassification(node.CloseBracketToken, ClassificationTypeNames.JsonArray);
}
public void Visit(JsonObjectNode node)
{
AddClassification(node.OpenBraceToken, ClassificationTypeNames.JsonObject);
AddClassification(node.CloseBraceToken, ClassificationTypeNames.JsonObject);
}
public void Visit(JsonPropertyNode node)
{
AddClassification(node.NameToken, ClassificationTypeNames.JsonPropertyName);
AddClassification(node.ColonToken, ClassificationTypeNames.JsonPunctuation);
}
public void Visit(JsonConstructorNode node)
{
AddClassification(node.NewKeyword, ClassificationTypeNames.JsonKeyword);
AddClassification(node.NameToken, ClassificationTypeNames.JsonConstructorName);
AddClassification(node.OpenParenToken, ClassificationTypeNames.JsonPunctuation);
AddClassification(node.CloseParenToken, ClassificationTypeNames.JsonPunctuation);
}
public void Visit(JsonLiteralNode node)
{
VisitLiteral(node.LiteralToken);
}
private void VisitLiteral(JsonToken literalToken)
{
switch (literalToken.Kind)
{
case JsonKind.NumberToken:
AddClassification(literalToken, ClassificationTypeNames.JsonNumber);
return;
case JsonKind.StringToken:
AddClassification(literalToken, ClassificationTypeNames.JsonString);
return;
case JsonKind.TrueLiteralToken:
case JsonKind.FalseLiteralToken:
case JsonKind.NullLiteralToken:
case JsonKind.UndefinedLiteralToken:
case JsonKind.NaNLiteralToken:
case JsonKind.InfinityLiteralToken:
AddClassification(literalToken, ClassificationTypeNames.JsonKeyword);
return;
default:
AddClassification(literalToken, ClassificationTypeNames.JsonText);
return;
}
}
public void Visit(JsonNegativeLiteralNode node)
{
AddClassification(node.MinusToken, ClassificationTypeNames.JsonOperator);
VisitLiteral(node.LiteralToken);
}
public void Visit(JsonTextNode node)
{
VisitLiteral(node.TextToken);
}
public void Visit(JsonEmptyValueNode node)
{
AddClassification(node.CommaToken, ClassificationTypeNames.JsonPunctuation);
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.RegularExpressions;
using Microsoft.CodeAnalysis.VirtualChars;
namespace Microsoft.CodeAnalysis.Classification
{
internal static class CommonRegexPatternTokenClassifier
{
private static ObjectPool<Visitor> _visitorPool = new ObjectPool<Visitor>(() => new Visitor());
public static void AddClassifications(
Workspace workspace, SyntaxToken token, SemanticModel semanticModel, ArrayBuilder<ClassifiedSpan> result,
ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, IVirtualCharService virtualCharService,
CancellationToken cancellationToken)
{
if (!workspace.Options.GetOption(RegularExpressionsOptions.ColorizeRegexPatterns, LanguageNames.CSharp))
{
return;
}
// Do some quick syntactic checks before doing any complex work.
if (RegexPatternDetector.IsDefinitelyNotPattern(token, syntaxFacts))
{
return;
}
var detector = RegexPatternDetector.TryGetOrCreate(semanticModel, syntaxFacts, semanticFacts);
var tree = detector?.TryParseRegexPattern(token, virtualCharService, cancellationToken);
if (tree == null)
{
return;
}
var visitor = _visitorPool.Allocate();
try
{
visitor.Result = result;
AddClassifications(tree.Root, visitor, result);
}
finally
{
visitor.Result = null;
_visitorPool.Free(visitor);
}
}
private static void AddClassifications(RegexNode node, Visitor visitor, ArrayBuilder<ClassifiedSpan> result)
{
node.Accept(visitor);
foreach (var child in node)
{
if (child.IsNode)
{
AddClassifications(child.Node, visitor, result);
}
else
{
AddTriviaClassifications(child.Token, result);
}
}
}
private static void AddTriviaClassifications(RegexToken token, ArrayBuilder<ClassifiedSpan> result)
{
foreach (var trivia in token.LeadingTrivia)
{
AddTriviaClassifications(trivia, result);
}
}
private static void AddTriviaClassifications(RegexTrivia trivia, ArrayBuilder<ClassifiedSpan> result)
{
if (trivia.Kind == RegexKind.CommentTrivia &&
trivia.VirtualChars.Length > 0)
{
result.Add(new ClassifiedSpan(
ClassificationTypeNames.RegexComment, RegexHelpers.GetSpan(trivia.VirtualChars)));
}
}
private class Visitor : IRegexNodeVisitor
{
public ArrayBuilder<ClassifiedSpan> Result;
private void AddClassification(RegexToken token, string typeName)
{
if (!token.IsMissing)
{
Result.Add(new ClassifiedSpan(typeName, RegexHelpers.GetSpan(token)));
}
}
private void ClassifyWholeNode(RegexNode node, string typeName)
{
foreach (var child in node)
{
if (child.IsNode)
{
ClassifyWholeNode(child.Node, typeName);
}
else
{
AddClassification(child.Token, typeName);
}
}
}
public void Visit(RegexCompilationUnit node)
{
// Nothing to highlight.
}
public void Visit(RegexSequenceNode node)
{
// Nothing to highlight.
}
#region Character classes
public void Visit(RegexWildcardNode node)
=> AddClassification(node.DotToken, ClassificationTypeNames.RegexCharacterClass);
public void Visit(RegexCharacterClassNode node)
{
AddClassification(node.OpenBracketToken, ClassificationTypeNames.RegexCharacterClass);
AddClassification(node.CloseBracketToken, ClassificationTypeNames.RegexCharacterClass);
}
public void Visit(RegexNegatedCharacterClassNode node)
{
AddClassification(node.OpenBracketToken, ClassificationTypeNames.RegexCharacterClass);
AddClassification(node.CaretToken, ClassificationTypeNames.RegexCharacterClass);
AddClassification(node.CloseBracketToken, ClassificationTypeNames.RegexCharacterClass);
}
public void Visit(RegexCharacterClassRangeNode node)
=> AddClassification(node.MinusToken, ClassificationTypeNames.RegexCharacterClass);
public void Visit(RegexCharacterClassSubtractionNode node)
=> AddClassification(node.MinusToken, ClassificationTypeNames.RegexCharacterClass);
public void Visit(RegexCharacterClassEscapeNode node)
=> ClassifyWholeNode(node, ClassificationTypeNames.RegexCharacterClass);
public void Visit(RegexCategoryEscapeNode node)
=> ClassifyWholeNode(node, ClassificationTypeNames.RegexCharacterClass);
#endregion
#region Quantifiers
public void Visit(RegexZeroOrMoreQuantifierNode node)
=> AddClassification(node.AsteriskToken, ClassificationTypeNames.RegexQuantifier);
public void Visit(RegexOneOrMoreQuantifierNode node)
=> AddClassification(node.PlusToken, ClassificationTypeNames.RegexQuantifier);
public void Visit(RegexZeroOrOneQuantifierNode node)
=> AddClassification(node.QuestionToken, ClassificationTypeNames.RegexQuantifier);
public void Visit(RegexLazyQuantifierNode node)
=> AddClassification(node.QuestionToken, ClassificationTypeNames.RegexQuantifier);
public void Visit(RegexExactNumericQuantifierNode node)
{
AddClassification(node.OpenBraceToken, ClassificationTypeNames.RegexQuantifier);
AddClassification(node.FirstNumberToken, ClassificationTypeNames.RegexQuantifier);
AddClassification(node.CloseBraceToken, ClassificationTypeNames.RegexQuantifier);
}
public void Visit(RegexOpenNumericRangeQuantifierNode node)
{
AddClassification(node.OpenBraceToken, ClassificationTypeNames.RegexQuantifier);
AddClassification(node.FirstNumberToken, ClassificationTypeNames.RegexQuantifier);
AddClassification(node.CommaToken, ClassificationTypeNames.RegexQuantifier);
AddClassification(node.CloseBraceToken, ClassificationTypeNames.RegexQuantifier);
}
public void Visit(RegexClosedNumericRangeQuantifierNode node)
{
AddClassification(node.OpenBraceToken, ClassificationTypeNames.RegexQuantifier);
AddClassification(node.FirstNumberToken, ClassificationTypeNames.RegexQuantifier);
AddClassification(node.CommaToken, ClassificationTypeNames.RegexQuantifier);
AddClassification(node.SecondNumberToken, ClassificationTypeNames.RegexQuantifier);
AddClassification(node.CloseBraceToken, ClassificationTypeNames.RegexQuantifier);
}
#endregion
#region Groupings
public void Visit(RegexSimpleGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexSimpleOptionsGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexNestedOptionsGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexNonCapturingGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexPositiveLookaheadGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexNegativeLookaheadGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexPositiveLookbehindGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexNegativeLookbehindGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexNonBacktrackingGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexCaptureGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexBalancingGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexConditionalCaptureGroupingNode node)
=> ClassifyGrouping(node);
public void Visit(RegexConditionalExpressionGroupingNode node)
=> ClassifyGrouping(node);
// Captures and backreferences refer to groups. So we classify them the same way as groups.
public void Visit(RegexCaptureEscapeNode node)
=> ClassifyWholeNode(node, ClassificationTypeNames.RegexGrouping);
public void Visit(RegexKCaptureEscapeNode node)
=> ClassifyWholeNode(node, ClassificationTypeNames.RegexGrouping);
public void Visit(RegexBackreferenceEscapeNode node)
=> ClassifyWholeNode(node, ClassificationTypeNames.RegexGrouping);
private void ClassifyGrouping(RegexGroupingNode node)
{
foreach (var child in node)
{
if (!child.IsNode)
{
AddClassification(child.Token, ClassificationTypeNames.RegexGrouping);
}
}
}
#endregion
#region Escapes
public void Visit(RegexControlEscapeNode node)
=> ClassifyEscape(node);
public void Visit(RegexHexEscapeNode node)
=> ClassifyEscape(node);
public void Visit(RegexUnicodeEscapeNode node)
=> ClassifyEscape(node);
public void Visit(RegexOctalEscapeNode node)
=> ClassifyEscape(node);
public void Visit(RegexSimpleEscapeNode node)
=> ClassifyEscape(node);
public void ClassifyEscape(RegexNode node)
=> ClassifyWholeNode(node, ClassificationTypeNames.RegexEscape);
#endregion
#region Anchors
public void Visit(RegexAnchorNode node)
=> AddClassification(node.AnchorToken, ClassificationTypeNames.RegexAnchor);
public void Visit(RegexAnchorEscapeNode node)
=> ClassifyWholeNode(node, ClassificationTypeNames.RegexAnchor);
#endregion
public void Visit(RegexTextNode node)
=> AddClassification(node.TextToken, ClassificationTypeNames.RegexText);
public void Visit(RegexPosixPropertyNode node)
{
// The .net parser just interprets the [ of the node, and skips the rest. So
// classify the end part as a comment.
Result.Add(new ClassifiedSpan(node.TextToken.VirtualChars[0].Span, ClassificationTypeNames.RegexText));
Result.Add(new ClassifiedSpan(
RegexHelpers.GetSpan(node.TextToken.VirtualChars[1], node.TextToken.VirtualChars.Last()),
ClassificationTypeNames.RegexComment));
}
public void Visit(RegexAlternationNode node)
=> AddClassification(node.BarToken, ClassificationTypeNames.RegexAlternation);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册