Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce local variable supporting target-type new syntax #76342

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeCleanup;
using Microsoft.CodeAnalysis.CSharp.CodeStyle.TypeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Simplification;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
Expand All @@ -28,6 +30,7 @@ internal sealed partial class CSharpIntroduceVariableService
{
protected override Document IntroduceLocal(
SemanticDocument document,
CodeCleanupOptions options,
ExpressionSyntax expression,
bool allOccurrences,
bool isConstant,
Expand All @@ -47,14 +50,25 @@ protected override Document IntroduceLocal(
? TokenList(ConstKeyword)
: default;

var updatedExpression = expression.WithoutTrivia();
var csOptions = (CSharpSimplifierOptions)options.SimplifierOptions;

// If the target-type new syntax is preferred and "var" is not preferred under any circumstance, then we use the target-type new syntax.
// The approach is not exhaustive. We aim to support codebases that rely strictly on the target-type new syntax (i.e., no "var").
if (csOptions.ImplicitObjectCreationWhenTypeIsApparent.Value && csOptions.GetUseVarPreference() == UseVarPreference.None
&& expression is ObjectCreationExpressionSyntax objectCreationExpression)
{
updatedExpression = ImplicitObjectCreationExpression(objectCreationExpression.ArgumentList, objectCreationExpression.Initializer);
}

var declarationStatement = LocalDeclarationStatement(
modifiers,
VariableDeclaration(
GetTypeSyntax(document, expression, cancellationToken),
[VariableDeclarator(
newLocalNameToken.WithAdditionalAnnotations(RenameAnnotation.Create()),
argumentList: null,
EqualsValueClause(expression.WithoutTrivia()))]));
EqualsValueClause(updatedExpression))]));

switch (containerToGenerateInto)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ class Program
{
static void Main()
{
G<int>.@class {|Rename:@class|} = new G<int>.@class();
G<int>.@class {|Rename:@class|} = new();
G<int>.Add(@class);
}
}
Expand Down Expand Up @@ -1018,7 +1018,7 @@ public static void Add(object @class)

static void Main()
{
G<int>.@class {|Rename:@class|} = new G<int>.@class();
G<int>.@class {|Rename:@class|} = new();
G<int>.Add(@class);
}
}
Expand Down Expand Up @@ -3001,7 +3001,7 @@ class Program
{
static void Main()
{
Nullable<int*> {|Rename:v|} = new Nullable<int*>();
Nullable<int*> {|Rename:v|} = new();
v.GetValueOrDefault();
}
}
Expand Down Expand Up @@ -4283,6 +4283,56 @@ public T this[int i]
await TestInRegularAndScriptAsync(code, expected, options: ImplicitTypingEverywhere());
}

[Fact]
public async Task TestIntroduceLocalWithTargetTypedNew()
{
var code =
"""
using System;
class SampleType
{
public SampleType()
{
int sum = Sum([|new Numbers()|]);
}

private int Sum(Numbers numbers)
{
return 42;
}

private class Numbers {}
}
""";

var expected =
"""
using System;
class SampleType
{
public SampleType()
{
Numbers {|Rename:numbers|} = new();
int sum = Sum(numbers);
}

private int Sum(Numbers numbers)
{
return 42;
}

private class Numbers {}
}
""";

OptionsCollection optionsCollection = new(GetLanguage())
{
{ CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, new CodeStyleOption2<bool>(true, NotificationOption2.Warning) },
MartyIX marked this conversation as resolved.
Show resolved Hide resolved
};

await TestInRegularAndScriptAsync(code, expected, options: optionsCollection);
}

[Fact]
public async Task TestIntroduceFieldInExpressionBodiedPropertyGetter()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private async Task<Document> GetChangedDocumentCoreAsync(CancellationToken cance
}
else if (_isLocal)
{
return _service.IntroduceLocal(_semanticDocument, _expression, _allOccurrences, _isConstant, cancellationToken);
return _service.IntroduceLocal(_semanticDocument, Options, _expression, _allOccurrences, _isConstant, cancellationToken);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeCleanup;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageService;
Expand Down Expand Up @@ -50,7 +51,7 @@ internal abstract partial class AbstractIntroduceVariableService<TService, TExpr
protected abstract bool IsExpressionInStaticLocalFunction(TExpressionSyntax expression);

protected abstract Document IntroduceQueryLocal(SemanticDocument document, TExpressionSyntax expression, bool allOccurrences, CancellationToken cancellationToken);
protected abstract Document IntroduceLocal(SemanticDocument document, TExpressionSyntax expression, bool allOccurrences, bool isConstant, CancellationToken cancellationToken);
protected abstract Document IntroduceLocal(SemanticDocument document, CodeCleanupOptions options, TExpressionSyntax expression, bool allOccurrences, bool isConstant, CancellationToken cancellationToken);
protected abstract Task<Document> IntroduceFieldAsync(SemanticDocument document, TExpressionSyntax expression, bool allOccurrences, bool isConstant, CancellationToken cancellationToken);

protected abstract int DetermineFieldInsertPosition(TTypeDeclarationSyntax oldDeclaration, TTypeDeclarationSyntax newDeclaration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeActions
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.CodeCleanup
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax

Namespace Microsoft.CodeAnalysis.VisualBasic.IntroduceVariable
Partial Friend Class VisualBasicIntroduceVariableService
Protected Overrides Function IntroduceLocal(
document As SemanticDocument,
options As CodeCleanupOptions,
expression As ExpressionSyntax,
allOccurrences As Boolean,
isConstant As Boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ internal sealed record class CSharpSimplifierOptions : SimplifierOptions, IEquat
[DataMember] public CodeStyleOption2<bool> AllowEmbeddedStatementsOnSameLine { get; init; } = CodeStyleOption2.TrueWithSilentEnforcement;
[DataMember] public CodeStyleOption2<PreferBracesPreference> PreferBraces { get; init; } = s_defaultPreferBraces;
[DataMember] public CodeStyleOption2<bool> PreferThrowExpression { get; init; } = CodeStyleOption2.TrueWithSuggestionEnforcement;
[DataMember] public CodeStyleOption2<bool> ImplicitObjectCreationWhenTypeIsApparent { get; init; } = CodeStyleOption2.FalseWithSilentEnforcement;

public CSharpSimplifierOptions()
{
Expand All @@ -43,6 +44,7 @@ public CSharpSimplifierOptions(IOptionsReader options)
AllowEmbeddedStatementsOnSameLine = options.GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine);
PreferBraces = options.GetOption(CSharpCodeStyleOptions.PreferBraces);
PreferThrowExpression = options.GetOption(CSharpCodeStyleOptions.PreferThrowExpression);
ImplicitObjectCreationWhenTypeIsApparent = options.GetOption(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent);
}

public UseVarPreference GetUseVarPreference()
Expand Down
Loading