提交 bedf32ad 编写于 作者: J Jared Parsons

Disable extract method on pattern matching features

This addresses #9104 in the following ways:

- Fixes the gaps in data flow analysis that were causing the original assert in the bug.
- Disables extract method on pattern matching for now.  Filed #9244 to design scenarios here.

In order to fill in the data flow gaps I used commit 9d36a64a as a guide.  This change removed declaration expressions from the code base and hence gave a good outline of where data flow would be affected by pattern declaration expressions.

closes #9104
上级 014b868a
......@@ -104,6 +104,11 @@ private Symbol GetNodeSymbol(BoundNode node)
{
switch (node.Kind)
{
case BoundKind.DeclarationPattern:
{
return ((BoundDeclarationPattern)node).LocalSymbol;
}
case BoundKind.FieldAccess:
{
var fieldAccess = (BoundFieldAccess)node;
......
......@@ -53,6 +53,16 @@ protected override void Free()
_variablesDeclared = null;
}
public override BoundNode VisitDeclarationPattern(BoundDeclarationPattern node)
{
if (IsInside)
{
_variablesDeclared.Add(node.LocalSymbol);
}
return base.VisitDeclarationPattern(node);
}
public override BoundNode VisitLocalDeclaration(BoundLocalDeclaration node)
{
if (IsInside)
......
// 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;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
......@@ -15,9 +16,16 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ExtractMethod
{
public class ExtractMethodBase
{
protected async Task ExpectExtractMethodToFailAsync(string codeWithMarker, bool allowMovingDeclaration = true, bool dontPutOutOrRefOnStruct = true)
protected async Task ExpectExtractMethodToFailAsync(string codeWithMarker, bool allowMovingDeclaration = true, bool dontPutOutOrRefOnStruct = true, string[] features = null)
{
using (var workspace = await TestWorkspace.CreateCSharpAsync(codeWithMarker))
ParseOptions parseOptions = null;
if (features != null)
{
var featuresMapped = features.Select(x => new KeyValuePair<string, string>(x, string.Empty));
parseOptions = new CSharpParseOptions().WithFeatures(featuresMapped);
}
using (var workspace = await TestWorkspace.CreateCSharpAsync(codeWithMarker, parseOptions: parseOptions))
{
var testDocument = workspace.Documents.First();
var textSpan = testDocument.SelectedSpans.Single();
......
......@@ -816,6 +816,34 @@ private static int NewMethod()
#endregion
#region Patterns
[WorkItem(9244, "https://github.com/dotnet/roslyn/issues/9244")]
[Fact]
public async Task PatternIsDisabled()
{
var code = @"
using System;
class Program
{
static void Main()
{
object o = null;
if (o is Program [|p|])
{
}
}
}
";
var patterns = MessageID.IDS_FeaturePatternMatching.RequiredFeature();
await ExpectExtractMethodToFailAsync(code, features: new[] { patterns });
}
#endregion
[WorkItem(11155, "DevDiv_Projects/Roslyn")]
[Fact, Trait(Traits.Feature, Traits.Features.ExtractMethod)]
public async Task AnonymousTypeMember1()
......
......@@ -30,6 +30,7 @@ public partial class TestWorkspace
private const string ReportDiagnosticAttributeName = "ReportDiagnostic";
private const string ParseOptionsElementName = "ParseOptions";
private const string LanguageVersionAttributeName = "LanguageVersion";
private const string FeaturesAttributeName = "Features";
private const string DocumentationModeAttributeName = "DocumentationMode";
private const string DocumentElementName = "Document";
private const string AnalyzerElementName = "Analyzer";
......
......@@ -344,6 +344,12 @@ private static ParseOptions GetParseOptionsWorker(XElement projectElement, strin
parseOptions = GetParseOptionsWithLanguageVersion(language, parseOptions, languageVersionAttribute);
}
var featuresAttribute = projectElement.Attribute(FeaturesAttributeName);
if (featuresAttribute != null)
{
parseOptions = GetParseOptionsWithFeatures(parseOptions, featuresAttribute);
}
var documentationMode = GetDocumentationMode(projectElement);
if (documentationMode != null)
{
......@@ -370,6 +376,18 @@ private static ParseOptions GetPreProcessorParseOptions(string language, XAttrib
}
}
private static ParseOptions GetParseOptionsWithFeatures(ParseOptions parseOptions, XAttribute featuresAttribute)
{
var entries = featuresAttribute.Value.Split(';');
var features = entries.Select(x =>
{
var split = x.Split('=');
return new KeyValuePair<string, string>(split[0], split[1]);
});
return parseOptions.WithFeatures(features);
}
private static ParseOptions GetParseOptionsWithLanguageVersion(string language, ParseOptions parseOptions, XAttribute languageVersionAttribute)
{
if (language == LanguageNames.CSharp)
......
......@@ -28,6 +28,7 @@ public partial class TestWorkspace
commonReferences ? new XAttribute(CommonReferencesAttributeName, true) : null,
parseOptions == null ? null : CreateLanguageVersionAttribute(parseOptions),
parseOptions == null ? null : CreateDocumentationModeAttribute(parseOptions),
parseOptions == null ? null : CreateFeaturesAttribute(parseOptions),
compilationOptions == null ? null : CreateCompilationOptionsElement(compilationOptions),
elements);
}
......@@ -50,6 +51,17 @@ private static XAttribute CreateLanguageVersionAttribute(ParseOptions parseOptio
}
}
private static XAttribute CreateFeaturesAttribute(ParseOptions parseOptions)
{
if (parseOptions.Features == null || parseOptions.Features.Count == 0)
{
return null;
}
var value = string.Join(";", parseOptions.Features.Select(p => $"{p.Key}={p.Value}"));
return new XAttribute(FeaturesAttributeName, value);
}
private static XAttribute CreateDocumentationModeAttribute(ParseOptions parseOptions)
{
if (parseOptions == null)
......
......@@ -754,6 +754,15 @@ internal class CSharpFeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Selection can not contain a pattern expression..
/// </summary>
internal static string SelectionCanNotContainPattern {
get {
return ResourceManager.GetString("SelectionCanNotContainPattern", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Selection can not contain throw statement..
/// </summary>
......
......@@ -219,6 +219,9 @@
<data name="SelectionCanNotBePartOfConstInitializerExpr" xml:space="preserve">
<value>Selection can not be part of constant initializer expression.</value>
</data>
<data name="SelectionCanNotContainPattern" xml:space="preserve">
<value>Selection can not contain a pattern expression.</value>
</data>
<data name="TheSelectedCodeIsInsideAnUnsafeContext" xml:space="preserve">
<value>The selected code is inside an unsafe context.</value>
</data>
......
......@@ -274,6 +274,14 @@ private SelectionInfo CheckErrorCasesAndAppendDescriptions(SelectionInfo selecti
selectionInfo = selectionInfo.WithStatus(s => s.With(s.Flag, CSharpFeaturesResources.TheSelectedCodeIsInsideAnUnsafeContext));
}
// For now patterns are being blanket disabled for extract method. This issue covers designing extractions for them
// and re-enabling this.
// https://github.com/dotnet/roslyn/issues/9244
if (commonNode.Kind() == SyntaxKind.IsPatternExpression)
{
selectionInfo = selectionInfo.WithStatus(s => s.With(OperationStatusFlag.None, CSharpFeaturesResources.SelectionCanNotContainPattern));
}
var selectionChanged = selectionInfo.FirstTokenInOriginalSpan != selectionInfo.FirstTokenInFinalSpan || selectionInfo.LastTokenInOriginalSpan != selectionInfo.LastTokenInFinalSpan;
if (selectionChanged)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册