未验证 提交 c5cd0f66 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #46318 from CyrusNajmabadi/updateTests

Update GenerateHashCode tests to use new analyzer test framework.
......@@ -30,7 +30,7 @@
<RoslynDiagnosticsNugetPackageVersion>3.3.0-beta1.20352.4</RoslynDiagnosticsNugetPackageVersion>
<MicrosoftCodeAnalysisNetAnalyzersVersion>3.3.0-beta1.20352.4</MicrosoftCodeAnalysisNetAnalyzersVersion>
<CodeStyleLayerCodeAnalysisVersion>3.6.0-2.final</CodeStyleLayerCodeAnalysisVersion>
<MicrosoftCodeAnalysisTestingVersion>1.0.1-beta1.20374.2</MicrosoftCodeAnalysisTestingVersion>
<MicrosoftCodeAnalysisTestingVersion>1.0.1-beta1.20378.2</MicrosoftCodeAnalysisTestingVersion>
<CodeStyleAnalyzerVersion>3.7.0-3.20271.4</CodeStyleAnalyzerVersion>
<VisualStudioEditorPackagesVersion>16.4.248</VisualStudioEditorPackagesVersion>
<ILToolsPackageVersion>5.0.0-alpha1.19409.1</ILToolsPackageVersion>
......
......@@ -2,25 +2,64 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.GenerateComparisonOperators;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Testing;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.GenerateComparisonOperators
{
public class GenerateComparisonOperatorsTests : AbstractCSharpCodeActionTest
{
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
=> new GenerateComparisonOperatorsCodeRefactoringProvider();
using static Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.AbstractCodeActionOrUserDiagnosticTest;
using VerifyCS = CSharpCodeRefactoringVerifier<GenerateComparisonOperatorsCodeRefactoringProvider>;
[UseExportProvider]
public class GenerateComparisonOperatorsTests
{
private static Task TestInRegularAndScript1Async(
string initialMarkup,
string expectedMarkup,
int index = 0,
TestParameters? parameters = null,
List<DiagnosticResult> fixedExpectedDiagnostics = null)
{
return TestInRegularAndScript1Async(
new[] { initialMarkup }, new[] { expectedMarkup }, index, parameters, fixedExpectedDiagnostics);
}
private static async Task TestInRegularAndScript1Async(
string[] initialMarkup,
string[] expectedMarkup,
int index = 0,
TestParameters? parameters = null,
List<DiagnosticResult> fixedExpectedDiagnostics = null)
{
var test = new VerifyCS.Test
{
CodeActionIndex = index,
};
foreach (var source in initialMarkup)
test.TestState.Sources.Add(source);
foreach (var source in expectedMarkup)
test.FixedState.Sources.Add(source);
protected override ImmutableArray<CodeAction> MassageActions(ImmutableArray<CodeAction> actions)
=> FlattenActions(actions);
if (parameters?.parseOptions != null)
test.LanguageVersion = ((CSharpParseOptions)parameters.Value.parseOptions).LanguageVersion;
if (parameters?.options != null)
test.EditorConfig = CodeFixVerifierHelper.GetEditorConfigText(parameters.Value.options);
foreach (var diagnostic in fixedExpectedDiagnostics ?? new List<DiagnosticResult>())
test.FixedState.ExpectedDiagnostics.Add(diagnostic);
await test.RunAsync();
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateComparisonOperators)]
public async Task TestClass()
......@@ -65,7 +104,9 @@ class C : IComparable<C>
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateComparisonOperators)]
public async Task TestPreferExpressionBodies()
{
await TestInRegularAndScriptAsync(
await new VerifyCS.Test
{
TestCode =
@"
using System;
......@@ -73,6 +114,7 @@ public async Task TestPreferExpressionBodies()
{
public int CompareTo(C c) => 0;
}",
FixedCode =
@"
using System;
......@@ -84,7 +126,13 @@ class C : IComparable<C>
public static bool operator >(C left, C right) => left.CompareTo(right) > 0;
public static bool operator <=(C left, C right) => left.CompareTo(right) <= 0;
public static bool operator >=(C left, C right) => left.CompareTo(right) >= 0;
}", options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement));
}",
EditorConfig = CodeFixVerifierHelper.GetEditorConfigText(
new OptionsCollection(LanguageNames.CSharp)
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement },
}),
}.RunAsync();
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateComparisonOperators)]
......@@ -252,35 +300,45 @@ class C : IComparable<C>
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateComparisonOperators)]
public async Task TestMissingWithoutCompareMethod()
{
await TestMissingAsync(
@"
var code = @"
using System;
class C : IComparable<C>
class C : {|CS0535:IComparable<C>|}
{
[||]
}");
}";
await new VerifyCS.Test
{
TestCode = code,
FixedCode = code,
}.RunAsync();
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateComparisonOperators)]
public async Task TestMissingWithUnknownType()
{
await TestMissingAsync(
@"
var code = @"
using System;
class C : IComparable<Goo>
class C : IComparable<{|CS0246:Goo|}>
{
public int CompareTo(Goo g) => 0;
public int CompareTo({|CS0246:Goo|} g) => 0;
[||]
}");
}";
await new VerifyCS.Test
{
TestCode = code,
FixedCode = code,
}.RunAsync();
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateComparisonOperators)]
public async Task TestMissingWithAllExistingOperators()
{
await TestMissingAsync(
var code =
@"
using System;
......@@ -309,7 +367,13 @@ class C : IComparable<C>
}
[||]
}");
}";
await new VerifyCS.Test
{
TestCode = code,
FixedCode = code,
}.RunAsync();
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateComparisonOperators)]
......@@ -323,7 +387,7 @@ class C : IComparable<C>
{
public int CompareTo(C c) => 0;
public static bool operator <(C left, C right)
public static bool operator {|CS0216:<|}(C left, C right)
{
return left.CompareTo(right) < 0;
}
......@@ -412,7 +476,7 @@ public async Task TestInInterfaceWithDefaultImpl()
interface C : IComparable<C>
{
int IComparable<C>.CompareTo(C c) => 0;
int IComparable<C>.{|CS8701:CompareTo|}(C c) => 0;
[||]
}",
......@@ -421,24 +485,24 @@ interface C : IComparable<C>
interface C : IComparable<C>
{
int IComparable<C>.CompareTo(C c) => 0;
int IComparable<C>.{|CS8701:CompareTo|}(C c) => 0;
public static bool operator <(C left, C right)
public static bool operator {|CS8701:<|}(C left, C right)
{
return left.CompareTo(right) < 0;
}
public static bool operator >(C left, C right)
public static bool operator {|CS8701:>|}(C left, C right)
{
return left.CompareTo(right) > 0;
}
public static bool operator <=(C left, C right)
public static bool operator {|CS8701:<=|}(C left, C right)
{
return left.CompareTo(right) <= 0;
}
public static bool operator >=(C left, C right)
public static bool operator {|CS8701:>=|}(C left, C right)
{
return left.CompareTo(right) >= 0;
}
......
......@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Diagnostics;
using System.Linq;
using System.Threading;
......@@ -14,6 +15,7 @@
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Editor.Implementation.Preview;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.PickMembers;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Utilities;
......@@ -114,32 +116,6 @@ protected override Task<ImmutableArray<Diagnostic>> GetDiagnosticsWorkerAsync(Te
protected static Document GetDocument(TestWorkspace workspace)
=> workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id);
private class TestPickMembersService : IPickMembersService
{
private readonly ImmutableArray<string> _memberNames;
private readonly Action<ImmutableArray<PickMembersOption>> _optionsCallback;
public TestPickMembersService(
ImmutableArray<string> memberNames,
Action<ImmutableArray<PickMembersOption>> optionsCallback)
{
_memberNames = memberNames;
_optionsCallback = optionsCallback;
}
public PickMembersResult PickMembers(
string title, ImmutableArray<ISymbol> members,
ImmutableArray<PickMembersOption> options)
{
_optionsCallback?.Invoke(options);
return new PickMembersResult(
_memberNames.IsDefault
? members
: _memberNames.SelectAsArray(n => members.Single(m => m.Name == n)),
options);
}
}
internal static void EnableOptions(
ImmutableArray<PickMembersOption> options,
params string[] ids)
......@@ -174,4 +150,39 @@ internal static void EnableOption(ImmutableArray<PickMembersOption> options, str
parameters.WithFixProviderData(pickMembersService));
}
}
[ExportWorkspaceService(typeof(IPickMembersService), ServiceLayer.Host), Shared, PartNotDiscoverable]
internal class TestPickMembersService : IPickMembersService
{
public ImmutableArray<string> MemberNames;
public Action<ImmutableArray<PickMembersOption>> OptionsCallback;
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TestPickMembersService()
{
}
#pragma warning disable RS0034 // Exported parts should be marked with 'ImportingConstructorAttribute'
public TestPickMembersService(
ImmutableArray<string> memberNames,
Action<ImmutableArray<PickMembersOption>> optionsCallback)
{
MemberNames = memberNames;
OptionsCallback = optionsCallback;
}
#pragma warning restore RS0034 // Exported parts should be marked with 'ImportingConstructorAttribute'
public PickMembersResult PickMembers(
string title, ImmutableArray<ISymbol> members,
ImmutableArray<PickMembersOption> options)
{
OptionsCallback?.Invoke(options);
return new PickMembersResult(
MemberNames.IsDefault
? members
: MemberNames.SelectAsArray(n => members.Single(m => m.Name == n)),
options);
}
}
}
......@@ -420,6 +420,9 @@ public partial class CodeGenerationTests
getAccessor,
setAccessor,
isIndexer);
codeGenerationOptions ??= new CodeGenerationOptions();
codeGenerationOptions = codeGenerationOptions.With(options: codeGenerationOptions.Options ?? workspace.Options);
context.Result = await context.Service.AddPropertyAsync(context.Solution, (INamedTypeSymbol)context.GetDestination(), property, codeGenerationOptions);
}
......@@ -546,6 +549,10 @@ public partial class CodeGenerationTests
.GetDocument(documentId)
.GetSemanticModelAsync();
var docOptions = await context.Document.GetOptionsAsync();
codeGenerationOptions ??= new CodeGenerationOptions();
codeGenerationOptions = codeGenerationOptions.With(options: codeGenerationOptions.Options ?? docOptions);
var symbol = TestContext.GetSelectedSymbol<INamespaceOrTypeSymbol>(destSpan, semanticModel);
var destination = context.GetDestination();
if (destination.IsType)
......
......@@ -120,7 +120,9 @@ private async Task<Document> DetermineNewDocumentAsync(Document document, Comple
}
// CodeGenerationOptions containing before and after
var options = new CodeGenerationOptions(contextLocation: semanticModel.SyntaxTree.GetLocation(TextSpan.FromBounds(line.Start, line.Start)));
var options = new CodeGenerationOptions(
contextLocation: semanticModel.SyntaxTree.GetLocation(TextSpan.FromBounds(line.Start, line.Start)),
options: await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false));
var generatedMember = await GenerateMemberAsync(overriddenMember, containingType, document, completionItem, cancellationToken).ConfigureAwait(false);
generatedMember = _annotation.AddAnnotationToSymbol(generatedMember);
......
......@@ -95,6 +95,7 @@ private async Task<Document> ConvertToClassAsync(Document document, TextSpan spa
Debug.Assert(anonymousType != null);
var position = span.Start;
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
......@@ -139,14 +140,15 @@ private async Task<Document> ConvertToClassAsync(Document document, TextSpan spa
editor.ReplaceNode(container, (currentContainer, _) =>
{
var codeGenService = document.GetLanguageService<ICodeGenerationService>();
var options = new CodeGenerationOptions(
var codeGenOptions = new CodeGenerationOptions(
generateMembers: true,
sortMembers: false,
autoInsertionLocation: false,
options: options,
parseOptions: root.SyntaxTree.Options);
return codeGenService.AddNamedType(
currentContainer, namedTypeSymbol, options, cancellationToken);
currentContainer, namedTypeSymbol, codeGenOptions, cancellationToken);
});
var updatedDocument = document.WithSyntaxRoot(editor.GetChangedRoot());
......
......@@ -316,11 +316,12 @@ protected static async Task<Solution> AddPropertyAsync(Document document, Soluti
var fieldDeclaration = field.DeclaringSyntaxReferences.First();
var options = new CodeGenerationOptions(
contextLocation: fieldDeclaration.SyntaxTree.GetLocation(fieldDeclaration.Span),
parseOptions: fieldDeclaration.SyntaxTree.Options);
parseOptions: fieldDeclaration.SyntaxTree.Options,
options: await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false));
var destination = field.ContainingType;
var updatedDocument = await codeGenerationService.AddPropertyAsync(destinationSolution, destination, property, options, cancellationToken)
.ConfigureAwait(false);
var updatedDocument = await codeGenerationService.AddPropertyAsync(
destinationSolution, destination, property, options, cancellationToken).ConfigureAwait(false);
updatedDocument = await Formatter.FormatAsync(updatedDocument, Formatter.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false);
updatedDocument = await Simplifier.ReduceAsync(updatedDocument, cancellationToken: cancellationToken).ConfigureAwait(false);
......
......@@ -352,7 +352,10 @@ public async Task<ExtractInterfaceResult> ExtractInterfaceFromAnalyzedTypeAsync(
interfaceDocument.Project.Solution,
interfaceDocumentSemanticModel.GetEnclosingNamespace(0, cancellationToken),
extractedInterfaceSymbol.GenerateRootNamespaceOrType(namespaceParts.ToArray()),
options: new CodeGenerationOptions(contextLocation: interfaceDocumentSemanticModel.SyntaxTree.GetLocation(new TextSpan()), generateMethodBodies: false),
options: new CodeGenerationOptions(
contextLocation: interfaceDocumentSemanticModel.SyntaxTree.GetLocation(new TextSpan()),
generateMethodBodies: false,
options: await interfaceDocument.GetOptionsAsync(cancellationToken).ConfigureAwait(false)),
cancellationToken: cancellationToken).ConfigureAwait(false);
var syntaxRoot = await unformattedInterfaceDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
......
......@@ -80,8 +80,10 @@ protected override async Task<Document> GetChangedDocumentAsync(CancellationToke
await AddOperatorsAsync(methods, cancellationToken).ConfigureAwait(false);
}
var options = await _document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var newTypeDeclaration = CodeGenerator.AddMemberDeclarations(
_typeDeclaration, methods, _document.Project.Solution.Workspace);
_typeDeclaration, methods, _document.Project.Solution.Workspace,
new CodeGenerationOptions(options: options));
if (constructedTypeToImplement is object)
{
......
......@@ -556,7 +556,9 @@ private IEnumerable<string> GetUnavailableMemberNames()
document.Project.Solution,
TypeToGenerateIn,
members.Concat(constructor),
new CodeGenerationOptions(Token.GetLocation()),
new CodeGenerationOptions(
Token.GetLocation(),
options: await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false)),
cancellationToken).ConfigureAwait(false);
}
......@@ -605,7 +607,9 @@ private IEnumerable<string> GetUnavailableMemberNames()
addNullChecks: false,
preferThrowExpression: false,
generateProperties: withProperties),
new CodeGenerationOptions(Token.GetLocation()),
new CodeGenerationOptions(
Token.GetLocation(),
options: await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false)),
cancellationToken).ConfigureAwait(false);
}
}
......
......@@ -44,16 +44,17 @@ private partial class GenerateVariableCodeAction : CodeAction
_equivalenceKey = Title;
}
protected override Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
protected override async Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
{
var solution = _semanticDocument.Project.Solution;
var generateUnsafe = _state.TypeMemberType.RequiresUnsafeModifier() &&
!_state.IsContainedInUnsafeType;
var otions = new CodeGenerationOptions(
var options = new CodeGenerationOptions(
afterThisLocation: _state.AfterThisLocation,
beforeThisLocation: _state.BeforeThisLocation,
contextLocation: _state.IdentifierToken.GetLocation());
contextLocation: _state.IdentifierToken.GetLocation(),
options: await _semanticDocument.Document.GetOptionsAsync(cancellationToken).ConfigureAwait(false));
if (_generateProperty)
{
......@@ -75,8 +76,8 @@ protected override Task<Document> GetChangedDocumentAsync(CancellationToken canc
getMethod: getAccessor,
setMethod: setAccessor);
return CodeGenerator.AddPropertyDeclarationAsync(
solution, _state.TypeToGenerateIn, propertySymbol, otions, cancellationToken);
return await CodeGenerator.AddPropertyDeclarationAsync(
solution, _state.TypeToGenerateIn, propertySymbol, options, cancellationToken).ConfigureAwait(false);
}
else
{
......@@ -89,8 +90,8 @@ protected override Task<Document> GetChangedDocumentAsync(CancellationToken canc
type: _state.TypeMemberType,
name: _state.IdentifierToken.ValueText);
return CodeGenerator.AddFieldDeclarationAsync(
solution, _state.TypeToGenerateIn, fieldSymbol, otions, cancellationToken);
return await CodeGenerator.AddFieldDeclarationAsync(
solution, _state.TypeToGenerateIn, fieldSymbol, options, cancellationToken).ConfigureAwait(false);
}
}
......
......@@ -77,7 +77,8 @@ protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperation
members,
new CodeGenerationOptions(
afterThisLocation: afterThisLocation,
contextLocation: syntaxTree.GetLocation(_textSpan)),
contextLocation: syntaxTree.GetLocation(_textSpan),
options: await _document.GetOptionsAsync(cancellationToken).ConfigureAwait(false)),
cancellationToken).ConfigureAwait(false);
return SpecializedCollections.SingletonEnumerable(
......
......@@ -382,9 +382,10 @@ private async Task<IEnumerable<CodeActionOperation>> GetGenerateIntoContainingNa
solution,
enclosingNamespace,
namedType,
new CodeGenerationOptions(afterThisLocation: _semanticDocument.SyntaxTree.GetLocation(_state.SimpleName.Span)),
_cancellationToken)
.ConfigureAwait(false);
new CodeGenerationOptions(
afterThisLocation: _semanticDocument.SyntaxTree.GetLocation(_state.SimpleName.Span),
options: await _semanticDocument.Document.GetOptionsAsync(_cancellationToken).ConfigureAwait(false)),
_cancellationToken).ConfigureAwait(false);
return new CodeActionOperation[] { new ApplyChangesOperation(codeGenResult.Project.Solution) };
}
......
......@@ -117,7 +117,8 @@ internal class ImplementAbstractClassData
new CodeGenerationOptions(
contextLocation: classNodeToAddMembersTo.GetLocation(),
autoInsertionLocation: groupMembers,
sortMembers: groupMembers));
sortMembers: groupMembers,
options: options));
var root = await _document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var newRoot = root.ReplaceNode(_classNode, updatedClassNode);
......
......@@ -206,7 +206,8 @@ public Task<Document> GetUpdatedDocumentAsync(CancellationToken cancellationToke
new CodeGenerationOptions(
contextLocation: classOrStructDecl.GetLocation(),
autoInsertionLocation: groupMembers,
sortMembers: groupMembers),
sortMembers: groupMembers,
options: await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false)),
cancellationToken).ConfigureAwait(false);
}
......
......@@ -423,6 +423,7 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, workspace);
var generator = editor.Generator;
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
if (fieldOrProperty.ContainingType == null)
{
......@@ -448,13 +449,13 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
{
return CodeGenerator.AddPropertyDeclaration(
currentTypeDecl, property, workspace,
GetAddOptions<IPropertySymbol>(parameter, blockStatementOpt, typeDeclaration, cancellationToken));
GetAddOptions<IPropertySymbol>(parameter, blockStatementOpt, typeDeclaration, options, cancellationToken));
}
else if (fieldOrProperty is IFieldSymbol field)
{
return CodeGenerator.AddFieldDeclaration(
currentTypeDecl, field, workspace,
GetAddOptions<IFieldSymbol>(parameter, blockStatementOpt, typeDeclaration, cancellationToken));
GetAddOptions<IFieldSymbol>(parameter, blockStatementOpt, typeDeclaration, options, cancellationToken));
}
else
{
......@@ -482,9 +483,9 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
return document.WithSyntaxRoot(editor.GetChangedRoot());
}
private static CodeGenerationOptions? GetAddOptions<TSymbol>(
private static CodeGenerationOptions GetAddOptions<TSymbol>(
IParameterSymbol parameter, IBlockOperation? blockStatementOpt,
SyntaxNode typeDeclaration, CancellationToken cancellationToken)
SyntaxNode typeDeclaration, OptionSet options, CancellationToken cancellationToken)
where TSymbol : ISymbol
{
foreach (var (sibling, before) in GetSiblingParameters(parameter))
......@@ -502,19 +503,19 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
{
// Found an existing field/property that corresponds to a preceding parameter.
// Place ourselves directly after it.
return new CodeGenerationOptions(afterThisLocation: symbolSyntax.GetLocation());
return new CodeGenerationOptions(afterThisLocation: symbolSyntax.GetLocation(), options: options);
}
else
{
// Found an existing field/property that corresponds to a following parameter.
// Place ourselves directly before it.
return new CodeGenerationOptions(beforeThisLocation: symbolSyntax.GetLocation());
return new CodeGenerationOptions(beforeThisLocation: symbolSyntax.GetLocation(), options: options);
}
}
}
}
return null;
return new CodeGenerationOptions(options: options);
}
private static ImmutableArray<(IParameterSymbol parameter, bool before)> GetSiblingParameters(IParameterSymbol parameter)
......
......@@ -12,6 +12,7 @@
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Formatting.Rules;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Text;
......@@ -31,12 +32,14 @@ public async Task<Document> AddSourceToAsync(Document document, Compilation symb
var newSemanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var rootNamespace = newSemanticModel.GetEnclosingNamespace(0, cancellationToken);
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
// Add the interface of the symbol to the top of the root namespace
document = await CodeGenerator.AddNamespaceOrTypeDeclarationAsync(
document.Project.Solution,
rootNamespace,
CreateCodeGenerationSymbol(document, symbol),
CreateCodeGenerationOptions(newSemanticModel.SyntaxTree.GetLocation(new TextSpan())),
CreateCodeGenerationOptions(newSemanticModel.SyntaxTree.GetLocation(new TextSpan()), options),
cancellationToken).ConfigureAwait(false);
document = await AddNullableRegionsAsync(document, cancellationToken).ConfigureAwait(false);
......@@ -97,14 +100,15 @@ private static INamespaceOrTypeSymbol CreateCodeGenerationSymbol(Document docume
new[] { wrappedType });
}
private static CodeGenerationOptions CreateCodeGenerationOptions(Location contextLocation)
private static CodeGenerationOptions CreateCodeGenerationOptions(Location contextLocation, OptionSet options)
{
return new CodeGenerationOptions(
contextLocation: contextLocation,
generateMethodBodies: false,
generateDocumentationComments: true,
mergeAttributes: false,
autoInsertionLocation: false);
autoInsertionLocation: false,
options: options);
}
}
}
......@@ -96,7 +96,10 @@ private static IMethodSymbol MakePublicAccessor(IMethodSymbol getterOrSetter)
SelectAsArray(analysisResult => GetSymbolsToPullUp(analysisResult));
// Add members to interface
var codeGenerationOptions = new CodeGenerationOptions(generateMethodBodies: false, generateMembers: false);
var codeGenerationOptions = new CodeGenerationOptions(
generateMethodBodies: false,
generateMembers: false,
options: await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false));
var destinationWithMembersAdded = codeGenerationService.AddMembers(destinationSyntaxNode, symbolsToPullUp, options: codeGenerationOptions, cancellationToken: cancellationToken);
var destinationEditor = await solutionEditor.GetDocumentEditorAsync(
solution.GetDocumentId(destinationSyntaxNode.SyntaxTree),
......@@ -252,7 +255,10 @@ private static ISymbol GetSymbolsToPullUp(MemberAnalysisResult analysisResult)
return memberResult.Member;
}
});
var options = new CodeGenerationOptions(reuseSyntax: true, generateMethodBodies: false);
var options = new CodeGenerationOptions(
reuseSyntax: true,
generateMethodBodies: false,
options: await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false));
var newDestination = codeGenerationService.AddMembers(destinationSyntaxNode, pullUpMembersSymbols, options: options, cancellationToken: cancellationToken);
// Remove some original members since we are pulling members into class.
......
......@@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel
{
......@@ -17,12 +18,13 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel
public partial class AbstractCodeModelObject
{
private static CodeGenerationOptions GetCodeGenerationOptions(
EnvDTE.vsCMAccess access, ParseOptions parseOptions)
EnvDTE.vsCMAccess access, ParseOptions parseOptions, OptionSet options)
{
var generateDefaultAccessibility = (access & EnvDTE.vsCMAccess.vsCMAccessDefault) == 0;
return new CodeGenerationOptions(
generateDefaultAccessibility: generateDefaultAccessibility,
parseOptions: parseOptions);
parseOptions: parseOptions,
options: options);
}
protected SyntaxNode CreateConstructorDeclaration(SyntaxNode containerNode, string typeName, EnvDTE.vsCMAccess access)
......@@ -38,7 +40,8 @@ protected SyntaxNode CreateConstructorDeclaration(SyntaxNode containerNode, stri
return CodeGenerationService.CreateMethodDeclaration(
newMethodSymbol, destination,
options: GetCodeGenerationOptions(access, containerNode.SyntaxTree.Options));
options: GetCodeGenerationOptions(
access, containerNode.SyntaxTree.Options, options: null));
}
protected SyntaxNode CreateDestructorDeclaration(SyntaxNode containerNode, string typeName)
......@@ -67,7 +70,8 @@ protected SyntaxNode CreateDelegateTypeDeclaration(SyntaxNode containerNode, str
return CodeGenerationService.CreateNamedTypeDeclaration(
newTypeSymbol, destination,
options: GetCodeGenerationOptions(access, containerNode.SyntaxTree.Options));
options: GetCodeGenerationOptions(
access, containerNode.SyntaxTree.Options, options: null));
}
protected SyntaxNode CreateEventDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol type, bool createPropertyStyleEvent)
......@@ -114,7 +118,8 @@ protected SyntaxNode CreateEventDeclaration(SyntaxNode containerNode, string nam
return CodeGenerationService.CreateEventDeclaration(
newEventSymbol, destination,
options: GetCodeGenerationOptions(access, containerNode.SyntaxTree.Options));
options: GetCodeGenerationOptions(
access, containerNode.SyntaxTree.Options, options: null));
}
protected SyntaxNode CreateFieldDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol type)
......@@ -130,7 +135,8 @@ protected SyntaxNode CreateFieldDeclaration(SyntaxNode containerNode, string nam
return CodeGenerationService.CreateFieldDeclaration(
newFieldSymbol, destination,
options: GetCodeGenerationOptions(access, containerNode.SyntaxTree.Options));
options: GetCodeGenerationOptions(
access, containerNode.SyntaxTree.Options, options: null));
}
protected SyntaxNode CreateMethodDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol returnType)
......@@ -148,7 +154,8 @@ protected SyntaxNode CreateMethodDeclaration(SyntaxNode containerNode, string na
typeParameters: default,
parameters: default);
var codeGenerationOptions = GetCodeGenerationOptions(access, containerNode.SyntaxTree.Options);
var codeGenerationOptions = GetCodeGenerationOptions(
access, containerNode.SyntaxTree.Options, options: null);
if (destination == CodeGenerationDestination.InterfaceType)
{
// Generating method with body is allowed when targeting an interface,
......@@ -161,7 +168,14 @@ protected SyntaxNode CreateMethodDeclaration(SyntaxNode containerNode, string na
options: codeGenerationOptions);
}
protected SyntaxNode CreatePropertyDeclaration(SyntaxNode containerNode, string name, bool generateGetter, bool generateSetter, EnvDTE.vsCMAccess access, ITypeSymbol type)
protected SyntaxNode CreatePropertyDeclaration(
SyntaxNode containerNode,
string name,
bool generateGetter,
bool generateSetter,
EnvDTE.vsCMAccess access,
ITypeSymbol type,
OptionSet options)
{
var destination = CodeModelService.GetDestination(containerNode);
......@@ -210,7 +224,8 @@ protected SyntaxNode CreatePropertyDeclaration(SyntaxNode containerNode, string
return CodeGenerationService.CreatePropertyDeclaration(
newPropertySymbol, destination,
options: GetCodeGenerationOptions(access, containerNode.SyntaxTree.Options));
options: GetCodeGenerationOptions(
access, containerNode.SyntaxTree.Options, options));
}
protected SyntaxNode CreateNamespaceDeclaration(SyntaxNode containerNode, string name)
......@@ -249,7 +264,8 @@ protected SyntaxNode CreateNamespaceDeclaration(SyntaxNode containerNode, string
return CodeGenerationService.CreateNamedTypeDeclaration(
newTypeSymbol, destination,
options: GetCodeGenerationOptions(access, containerNode.SyntaxTree.Options));
options: GetCodeGenerationOptions(
access, containerNode.SyntaxTree.Options, options: null));
}
}
}
......@@ -375,12 +375,16 @@ internal EnvDTE.CodeProperty AddProperty(SyntaxNode containerNode, string getter
var containerNodePosition = containerNode.SpanStart;
var semanticModel = GetSemanticModel();
var options = GetDocument().GetOptionsAsync(CancellationToken.None).WaitAndGetResult_CodeModel(CancellationToken.None);
var propertyType = CodeModelService.GetTypeSymbol(type, semanticModel, containerNodePosition);
var newProperty = CreatePropertyDeclaration(containerNode,
CodeModelService.GetUnescapedName(isGetterPresent ? getterName : putterName),
isGetterPresent,
isPutterPresent,
access, propertyType);
var newProperty = CreatePropertyDeclaration(
containerNode,
CodeModelService.GetUnescapedName(isGetterPresent ? getterName : putterName),
isGetterPresent,
isPutterPresent,
access,
propertyType,
options);
var insertionIndex = CodeModelService.PositionVariantToMemberInsertionIndex(position, containerNode, fileCodeModel: this);
newProperty = InsertMember(containerNode, newProperty, insertionIndex);
......
......@@ -53,8 +53,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
Private Protected Overloads Async Function TestElementUpdate(
code As XElement, expectedCode As XElement, updater As Action(Of TCodeElement),
Optional options As IDictionary(Of OptionKey2, Object) = Nothing) As Task
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code))
Optional options As IDictionary(Of OptionKey2, Object) = Nothing,
Optional editorConfig As String = "") As Task
Using state = CreateCodeModelTestState(GetWorkspaceDefinition(code, editorConfig))
Dim workspace = state.Workspace
If options IsNot Nothing Then
For Each kvp In options
......@@ -775,14 +776,16 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
Private Protected Overrides Async Function TestAddProperty(
code As XElement, expectedCode As XElement, data As PropertyData,
Optional options As IDictionary(Of OptionKey2, Object) = Nothing) As Task
Optional options As IDictionary(Of OptionKey2, Object) = Nothing,
Optional editorConfig As String = "") As Task
Await TestElementUpdate(code, expectedCode,
Sub(codeElement)
Dim prop = AddProperty(codeElement, data)
Assert.NotNull(prop)
Assert.True(data.GetterName = prop.Name OrElse data.PutterName = prop.Name)
End Sub,
options)
options,
editorConfig)
End Function
Protected Overrides Async Function TestAddVariable(code As XElement, expectedCode As XElement, data As VariableData) As Task
......
......@@ -12,10 +12,13 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
Protected MustOverride ReadOnly Property LanguageName As String
Protected Function GetWorkspaceDefinition(code As XElement) As XElement
Protected Function GetWorkspaceDefinition(code As XElement, Optional editorConfig As String = "") As XElement
Return <Workspace>
<Project Language=<%= LanguageName %> CommonReferences="true">
<Document><%= code.Value.Trim() %></Document>
<AnalyzerConfigDocument FilePath="z:\\.editorconfig">
<%= editorConfig %>
</AnalyzerConfigDocument>
</Project>
</Workspace>
End Function
......@@ -64,8 +67,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel
Throw New NotImplementedException
End Function
Private Protected Overridable Function TestAddProperty(code As XElement, expectedCode As XElement, data As PropertyData,
Optional options As IDictionary(Of OptionKey2, Object) = Nothing) As Task
Private Protected Overridable Function TestAddProperty(
code As XElement, expectedCode As XElement, data As PropertyData,
Optional options As IDictionary(Of OptionKey2, Object) = Nothing,
Optional editorConfig As String = "") As Task
Throw New NotImplementedException
End Function
......
......@@ -2187,11 +2187,7 @@ class C
{
string Name
{
get
{
return default;
}
get =&gt; default;
set
{
}
......@@ -2202,10 +2198,11 @@ class C
Await TestAddProperty(
code, expected,
New PropertyData With {.GetterName = "Name", .PutterName = "Name", .Type = EnvDTE.vsCMTypeRef.vsCMTypeRefString},
New Dictionary(Of OptionKey2, Object) From {
{CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSilentEnforcement},
{CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithSilentEnforcement}
})
editorConfig:="
[*]
csharp_style_expression_bodied_accessors=false:silent
csharp_style_expression_bodied_properties=false:silent
")
End Function
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
......@@ -2241,22 +2238,17 @@ class C$$
<Code>
class C
{
string Name
{
get
{
return default;
}
}
string Name =&gt; default;
}
</Code>
Await TestAddProperty(
code, expected, New PropertyData With {.GetterName = "Name", .PutterName = Nothing, .Type = EnvDTE.vsCMTypeRef.vsCMTypeRefString},
New Dictionary(Of OptionKey2, Object) From {
{CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSilentEnforcement},
{CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithSilentEnforcement}
})
editorConfig:="
[*]
csharp_style_expression_bodied_accessors=false:silent
csharp_style_expression_bodied_properties=false:silent
")
End Function
<ConditionalWpfFact(GetType(x86)), Trait(Traits.Feature, Traits.Features.CodeModel)>
......
......@@ -139,7 +139,7 @@ protected override TDeclarationNode AddMethod<TDeclarationNode>(TDeclarationNode
if (method.IsConstructor())
{
return Cast<TDeclarationNode>(ConstructorGenerator.AddConstructorTo(
typeDeclaration, method, Workspace, options, availableIndices));
typeDeclaration, method, options, availableIndices));
}
if (method.IsDestructor())
......@@ -150,13 +150,13 @@ protected override TDeclarationNode AddMethod<TDeclarationNode>(TDeclarationNode
if (method.MethodKind == MethodKind.Conversion)
{
return Cast<TDeclarationNode>(ConversionGenerator.AddConversionTo(
typeDeclaration, method, Workspace, options, availableIndices));
typeDeclaration, method, options, availableIndices));
}
if (method.MethodKind == MethodKind.UserDefinedOperator)
{
return Cast<TDeclarationNode>(OperatorGenerator.AddOperatorTo(
typeDeclaration, method, Workspace, options, availableIndices));
typeDeclaration, method, options, availableIndices));
}
return Cast<TDeclarationNode>(MethodGenerator.AddMethodTo(
......@@ -229,12 +229,12 @@ protected override TDeclarationNode AddProperty<TDeclarationNode>(TDeclarationNo
if (destination is TypeDeclarationSyntax)
{
return Cast<TDeclarationNode>(PropertyGenerator.AddPropertyTo(
Cast<TypeDeclarationSyntax>(destination), property, Workspace, options, availableIndices));
Cast<TypeDeclarationSyntax>(destination), property, options, availableIndices));
}
else
{
return Cast<TDeclarationNode>(PropertyGenerator.AddPropertyTo(
Cast<CompilationUnitSyntax>(destination), property, Workspace, options, availableIndices));
Cast<CompilationUnitSyntax>(destination), property, options, availableIndices));
}
}
......@@ -587,17 +587,17 @@ public override SyntaxNode CreateFieldDeclaration(IFieldSymbol field, CodeGenera
if (method.IsConstructor())
{
return ConstructorGenerator.GenerateConstructorDeclaration(
method, Workspace, options, options.ParseOptions);
method, options, options.ParseOptions);
}
else if (method.IsUserDefinedOperator())
{
return OperatorGenerator.GenerateOperatorDeclaration(
method, Workspace, options, options.ParseOptions);
method, options, options.ParseOptions);
}
else if (method.IsConversion())
{
return ConversionGenerator.GenerateConversionDeclaration(
method, Workspace, options, options.ParseOptions);
method, options, options.ParseOptions);
}
else if (method.IsLocalFunction())
{
......@@ -615,7 +615,7 @@ public override SyntaxNode CreateFieldDeclaration(IFieldSymbol field, CodeGenera
IPropertySymbol property, CodeGenerationDestination destination, CodeGenerationOptions options)
{
return PropertyGenerator.GeneratePropertyOrIndexer(
property, destination, Workspace, options, options.ParseOptions);
property, destination, options, options.ParseOptions);
}
public override SyntaxNode CreateNamedTypeDeclaration(
......
......@@ -24,13 +24,11 @@ private static MemberDeclarationSyntax LastConstructorOrField(SyntaxList<MemberD
internal static TypeDeclarationSyntax AddConstructorTo(
TypeDeclarationSyntax destination,
IMethodSymbol constructor,
Workspace workspace,
CodeGenerationOptions options,
IList<bool> availableIndices)
{
var constructorDeclaration = GenerateConstructorDeclaration(
constructor, workspace, options,
destination?.SyntaxTree.Options ?? options.ParseOptions);
constructor, options, destination?.SyntaxTree.Options ?? options.ParseOptions);
// Generate after the last constructor, or after the last field, or at the start of the
// type.
......@@ -42,7 +40,6 @@ private static MemberDeclarationSyntax LastConstructorOrField(SyntaxList<MemberD
internal static ConstructorDeclarationSyntax GenerateConstructorDeclaration(
IMethodSymbol constructor,
Workspace workspace,
CodeGenerationOptions options,
ParseOptions parseOptions)
{
......@@ -65,20 +62,20 @@ private static MemberDeclarationSyntax LastConstructorOrField(SyntaxList<MemberD
body: hasNoBody ? null : GenerateBlock(constructor),
semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : default);
declaration = UseExpressionBodyIfDesired(workspace, declaration, parseOptions);
declaration = UseExpressionBodyIfDesired(options, declaration, parseOptions);
return AddFormatterAndCodeGeneratorAnnotationsTo(
ConditionallyAddDocumentationCommentTo(declaration, constructor, options));
}
private static ConstructorDeclarationSyntax UseExpressionBodyIfDesired(
Workspace workspace, ConstructorDeclarationSyntax declaration, ParseOptions options)
CodeGenerationOptions options, ConstructorDeclarationSyntax declaration, ParseOptions parseOptions)
{
if (declaration.ExpressionBody == null)
{
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors).Value;
var expressionBodyPreference = options.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors).Value;
if (declaration.Body.TryConvertToArrowExpressionBody(
declaration.Kind(), options, expressionBodyPreference,
declaration.Kind(), parseOptions, expressionBodyPreference,
out var expressionBody, out var semicolonToken))
{
return declaration.WithBody(null)
......
......@@ -18,13 +18,11 @@ internal static class ConversionGenerator
internal static TypeDeclarationSyntax AddConversionTo(
TypeDeclarationSyntax destination,
IMethodSymbol method,
Workspace workspace,
CodeGenerationOptions options,
IList<bool> availableIndices)
{
var methodDeclaration = GenerateConversionDeclaration(
method, workspace, options,
destination?.SyntaxTree.Options ?? options.ParseOptions);
method, options, destination?.SyntaxTree.Options ?? options.ParseOptions);
var members = Insert(destination.Members, methodDeclaration, options, availableIndices, after: LastOperator);
......@@ -33,18 +31,16 @@ internal static class ConversionGenerator
internal static ConversionOperatorDeclarationSyntax GenerateConversionDeclaration(
IMethodSymbol method,
Workspace workspace,
CodeGenerationOptions options,
ParseOptions parseOptions)
{
var declaration = GenerateConversionDeclarationWorker(method, workspace, options, parseOptions);
var declaration = GenerateConversionDeclarationWorker(method, options, parseOptions);
return AddFormatterAndCodeGeneratorAnnotationsTo(AddAnnotationsTo(method,
ConditionallyAddDocumentationCommentTo(declaration, method, options)));
}
private static ConversionOperatorDeclarationSyntax GenerateConversionDeclarationWorker(
IMethodSymbol method,
Workspace workspace,
CodeGenerationOptions options,
ParseOptions parseOptions)
{
......@@ -70,20 +66,20 @@ internal static class ConversionGenerator
body: hasNoBody ? null : StatementGenerator.GenerateBlock(method),
semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : new SyntaxToken());
declaration = UseExpressionBodyIfDesired(workspace, declaration, parseOptions);
declaration = UseExpressionBodyIfDesired(options, declaration, parseOptions);
return declaration;
}
private static ConversionOperatorDeclarationSyntax UseExpressionBodyIfDesired(
Workspace workspace, ConversionOperatorDeclarationSyntax declaration, ParseOptions options)
CodeGenerationOptions options, ConversionOperatorDeclarationSyntax declaration, ParseOptions parseOptions)
{
if (declaration.ExpressionBody == null)
{
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value;
var expressionBodyPreference = options.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value;
if (declaration.Body.TryConvertToArrowExpressionBody(
declaration.Kind(), options, expressionBodyPreference,
declaration.Kind(), parseOptions, expressionBodyPreference,
out var expressionBody, out var semicolonToken))
{
return declaration.WithBody(null)
......
......@@ -19,13 +19,11 @@ internal static class OperatorGenerator
internal static TypeDeclarationSyntax AddOperatorTo(
TypeDeclarationSyntax destination,
IMethodSymbol method,
Workspace workspace,
CodeGenerationOptions options,
IList<bool> availableIndices)
{
var methodDeclaration = GenerateOperatorDeclaration(
method, workspace, options,
destination?.SyntaxTree.Options ?? options.ParseOptions);
method, options, destination?.SyntaxTree.Options ?? options.ParseOptions);
var members = Insert(destination.Members, methodDeclaration, options, availableIndices, after: LastOperator);
......@@ -34,7 +32,6 @@ internal static class OperatorGenerator
internal static OperatorDeclarationSyntax GenerateOperatorDeclaration(
IMethodSymbol method,
Workspace workspace,
CodeGenerationOptions options,
ParseOptions parseOptions)
{
......@@ -45,20 +42,20 @@ internal static class OperatorGenerator
}
var declaration = GenerateOperatorDeclarationWorker(method, options, parseOptions);
declaration = UseExpressionBodyIfDesired(workspace, declaration, parseOptions);
declaration = UseExpressionBodyIfDesired(options, declaration, parseOptions);
return AddAnnotationsTo(method,
ConditionallyAddDocumentationCommentTo(declaration, method, options));
}
private static OperatorDeclarationSyntax UseExpressionBodyIfDesired(
Workspace workspace, OperatorDeclarationSyntax declaration, ParseOptions options)
CodeGenerationOptions options, OperatorDeclarationSyntax declaration, ParseOptions parseOptions)
{
if (declaration.ExpressionBody == null)
{
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value;
var expressionBodyPreference = options.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value;
if (declaration.Body.TryConvertToArrowExpressionBody(
declaration.Kind(), options, expressionBodyPreference,
declaration.Kind(), parseOptions, expressionBodyPreference,
out var expressionBody, out var semicolonToken))
{
return declaration.WithBody(null)
......@@ -99,25 +96,6 @@ internal static class OperatorGenerator
return operatorDecl;
}
private static OperatorDeclarationSyntax UseExpressionBodyIfDesired(
CodeGenerationOptions options, OperatorDeclarationSyntax operatorDeclaration, ParseOptions parseOptions)
{
if (operatorDeclaration.ExpressionBody == null)
{
var expressionBodyPreference = options.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value;
if (operatorDeclaration.Body.TryConvertToArrowExpressionBody(
operatorDeclaration.Kind(), parseOptions, expressionBodyPreference,
out var expressionBody, out var semicolonToken))
{
return operatorDeclaration.WithBody(null)
.WithExpressionBody(expressionBody)
.WithSemicolonToken(semicolonToken);
}
}
return operatorDeclaration;
}
private static SyntaxTokenList GenerateModifiers()
{
return SyntaxFactory.TokenList(
......
......@@ -33,12 +33,11 @@ public static bool CanBeGenerated(IPropertySymbol property)
internal static CompilationUnitSyntax AddPropertyTo(
CompilationUnitSyntax destination,
IPropertySymbol property,
Workspace workspace,
CodeGenerationOptions options,
IList<bool> availableIndices)
{
var declaration = GeneratePropertyOrIndexer(
property, CodeGenerationDestination.CompilationUnit, workspace, options,
property, CodeGenerationDestination.CompilationUnit, options,
destination?.SyntaxTree.Options ?? options.ParseOptions);
var members = Insert(destination.Members, declaration, options,
......@@ -49,11 +48,10 @@ public static bool CanBeGenerated(IPropertySymbol property)
internal static TypeDeclarationSyntax AddPropertyTo(
TypeDeclarationSyntax destination,
IPropertySymbol property,
Workspace workspace,
CodeGenerationOptions options,
IList<bool> availableIndices)
{
var declaration = GeneratePropertyOrIndexer(property, GetDestination(destination), workspace,
var declaration = GeneratePropertyOrIndexer(property, GetDestination(destination),
options, destination?.SyntaxTree.Options ?? options.ParseOptions);
// Create a clone of the original type with the new method inserted.
......@@ -68,7 +66,6 @@ public static bool CanBeGenerated(IPropertySymbol property)
public static MemberDeclarationSyntax GeneratePropertyOrIndexer(
IPropertySymbol property,
CodeGenerationDestination destination,
Workspace workspace,
CodeGenerationOptions options,
ParseOptions parseOptions)
{
......@@ -79,8 +76,8 @@ public static bool CanBeGenerated(IPropertySymbol property)
}
var declaration = property.IsIndexer
? GenerateIndexerDeclaration(property, destination, workspace, options, parseOptions)
: GeneratePropertyDeclaration(property, destination, workspace, options, parseOptions);
? GenerateIndexerDeclaration(property, destination, options, parseOptions)
: GeneratePropertyDeclaration(property, destination, options, parseOptions);
return ConditionallyAddDocumentationCommentTo(declaration, property, options);
}
......@@ -88,7 +85,6 @@ public static bool CanBeGenerated(IPropertySymbol property)
private static MemberDeclarationSyntax GenerateIndexerDeclaration(
IPropertySymbol property,
CodeGenerationDestination destination,
Workspace workspace,
CodeGenerationOptions options,
ParseOptions parseOptions)
{
......@@ -100,8 +96,8 @@ public static bool CanBeGenerated(IPropertySymbol property)
type: GenerateTypeSyntax(property),
explicitInterfaceSpecifier: explicitInterfaceSpecifier,
parameterList: ParameterGenerator.GenerateBracketedParameterList(property.Parameters, explicitInterfaceSpecifier != null, options),
accessorList: GenerateAccessorList(property, destination, workspace, options, parseOptions));
declaration = UseExpressionBodyIfDesired(workspace, declaration, parseOptions);
accessorList: GenerateAccessorList(property, destination, options, parseOptions));
declaration = UseExpressionBodyIfDesired(options, declaration, parseOptions);
return AddFormatterAndCodeGeneratorAnnotationsTo(
AddAnnotationsTo(property, declaration));
......@@ -109,7 +105,7 @@ public static bool CanBeGenerated(IPropertySymbol property)
private static MemberDeclarationSyntax GeneratePropertyDeclaration(
IPropertySymbol property, CodeGenerationDestination destination,
Workspace workspace, CodeGenerationOptions options, ParseOptions parseOptions)
CodeGenerationOptions options, ParseOptions parseOptions)
{
var initializer = CodeGenerationPropertyInfo.GetInitializer(property) is ExpressionSyntax initializerNode
? SyntaxFactory.EqualsValueClause(initializerNode)
......@@ -117,7 +113,7 @@ public static bool CanBeGenerated(IPropertySymbol property)
var explicitInterfaceSpecifier = GenerateExplicitInterfaceSpecifier(property.ExplicitInterfaceImplementations);
var accessorList = GenerateAccessorList(property, destination, workspace, options, parseOptions);
var accessorList = GenerateAccessorList(property, destination, options, parseOptions);
var propertyDeclaration = SyntaxFactory.PropertyDeclaration(
attributeLists: AttributeGenerator.GenerateAttributeLists(property.GetAttributes(), options),
......@@ -129,8 +125,7 @@ public static bool CanBeGenerated(IPropertySymbol property)
expressionBody: null,
initializer: initializer);
propertyDeclaration = UseExpressionBodyIfDesired(
workspace, propertyDeclaration, parseOptions);
propertyDeclaration = UseExpressionBodyIfDesired(options, propertyDeclaration, parseOptions);
return AddFormatterAndCodeGeneratorAnnotationsTo(
AddAnnotationsTo(property, propertyDeclaration));
......@@ -177,15 +172,15 @@ private static TypeSyntax GenerateTypeSyntax(IPropertySymbol property)
}
private static PropertyDeclarationSyntax UseExpressionBodyIfDesired(
Workspace workspace, PropertyDeclarationSyntax declaration, ParseOptions options)
CodeGenerationOptions options, PropertyDeclarationSyntax declaration, ParseOptions parseOptions)
{
if (declaration.ExpressionBody == null)
{
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties).Value;
var expressionBodyPreference = options.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties).Value;
if (declaration.Initializer == null)
{
if (TryGetExpressionBody(
declaration, options, expressionBodyPreference,
declaration, parseOptions, expressionBodyPreference,
out var expressionBody, out var semicolonToken))
{
declaration = declaration.WithAccessorList(null)
......@@ -199,13 +194,13 @@ private static TypeSyntax GenerateTypeSyntax(IPropertySymbol property)
}
private static IndexerDeclarationSyntax UseExpressionBodyIfDesired(
Workspace workspace, IndexerDeclarationSyntax declaration, ParseOptions options)
CodeGenerationOptions options, IndexerDeclarationSyntax declaration, ParseOptions parseOptions)
{
if (declaration.ExpressionBody == null)
{
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers).Value;
var expressionBodyPreference = options.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers).Value;
if (TryGetExpressionBody(
declaration, options, expressionBodyPreference,
declaration, parseOptions, expressionBodyPreference,
out var expressionBody, out var semicolonToken))
{
declaration = declaration.WithAccessorList(null)
......@@ -218,13 +213,13 @@ private static TypeSyntax GenerateTypeSyntax(IPropertySymbol property)
}
private static AccessorDeclarationSyntax UseExpressionBodyIfDesired(
Workspace workspace, AccessorDeclarationSyntax declaration, ParseOptions options)
CodeGenerationOptions options, AccessorDeclarationSyntax declaration, ParseOptions parseOptions)
{
if (declaration.ExpressionBody == null)
{
var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
var expressionBodyPreference = options.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
if (declaration.Body.TryConvertToArrowExpressionBody(
declaration.Kind(), options, expressionBodyPreference,
declaration.Kind(), parseOptions, expressionBodyPreference,
out var expressionBody, out var semicolonToken))
{
declaration = declaration.WithBody(null)
......@@ -255,13 +250,13 @@ private static TypeSyntax GenerateTypeSyntax(IPropertySymbol property)
private static AccessorListSyntax GenerateAccessorList(
IPropertySymbol property, CodeGenerationDestination destination,
Workspace workspace, CodeGenerationOptions options, ParseOptions parseOptions)
CodeGenerationOptions options, ParseOptions parseOptions)
{
var setAccessorKind = property.SetMethod?.IsInitOnly == true ? SyntaxKind.InitAccessorDeclaration : SyntaxKind.SetAccessorDeclaration;
var accessors = new List<AccessorDeclarationSyntax>
{
GenerateAccessorDeclaration(property, property.GetMethod, SyntaxKind.GetAccessorDeclaration, destination, workspace, options, parseOptions),
GenerateAccessorDeclaration(property, property.SetMethod, setAccessorKind, destination, workspace, options, parseOptions),
GenerateAccessorDeclaration(property, property.GetMethod, SyntaxKind.GetAccessorDeclaration, destination, options, parseOptions),
GenerateAccessorDeclaration(property, property.SetMethod, setAccessorKind, destination, options, parseOptions),
};
return accessors[0] == null && accessors[1] == null
......@@ -274,14 +269,13 @@ private static TypeSyntax GenerateTypeSyntax(IPropertySymbol property)
IMethodSymbol accessor,
SyntaxKind kind,
CodeGenerationDestination destination,
Workspace workspace,
CodeGenerationOptions options,
ParseOptions parseOptions)
{
var hasBody = options.GenerateMethodBodies && HasAccessorBodies(property, destination, accessor);
return accessor == null
? null
: GenerateAccessorDeclaration(property, accessor, kind, hasBody, workspace, options, parseOptions);
: GenerateAccessorDeclaration(property, accessor, kind, hasBody, options, parseOptions);
}
private static AccessorDeclarationSyntax GenerateAccessorDeclaration(
......@@ -289,7 +283,6 @@ private static TypeSyntax GenerateTypeSyntax(IPropertySymbol property)
IMethodSymbol accessor,
SyntaxKind kind,
bool hasBody,
Workspace workspace,
CodeGenerationOptions options,
ParseOptions parseOptions)
{
......@@ -298,7 +291,7 @@ private static TypeSyntax GenerateTypeSyntax(IPropertySymbol property)
.WithBody(hasBody ? GenerateBlock(accessor) : null)
.WithSemicolonToken(hasBody ? default : SyntaxFactory.Token(SyntaxKind.SemicolonToken));
declaration = UseExpressionBodyIfDesired(workspace, declaration, parseOptions);
declaration = UseExpressionBodyIfDesired(options, declaration, parseOptions);
return AddAnnotationsTo(accessor, declaration);
}
......
......@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Editing;
using Roslyn.Utilities;
......@@ -58,10 +59,11 @@ private static SyntaxNode CreateNotImplementedException(SyntaxGenerator codeDefi
ITypeSymbol type)
{
var equalityComparerType = compilation.EqualityComparerOfTType();
var constructedType = equalityComparerType.Construct(type);
return factory.MemberAccessExpression(
factory.TypeExpression(constructedType),
factory.IdentifierName(DefaultName));
var typeExpression = equalityComparerType == null
? factory.GenericName(nameof(EqualityComparer<int>), type)
: factory.TypeExpression(equalityComparerType.Construct(type));
return factory.MemberAccessExpression(typeExpression, factory.IdentifierName(DefaultName));
}
private static ITypeSymbol GetType(Compilation compilation, ISymbol symbol)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册