Skip to content

Commit

Permalink
Create an unsafe method from a local function when necessary (#49389)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidwengier authored Nov 18, 2020
1 parent 4418173 commit 823039e
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,102 @@ C LocalFunction(C c)
return null;
}
}
}");
}

[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertLocalFunctionToMethod)]
[WorkItem(32976, "https://github.com/dotnet/roslyn/issues/32976")]
public async Task TestUnsafeLocalFunction()
{
await TestInRegularAndScriptAsync(
@"class C
{
public unsafe void UnsafeFunction()
{
byte b = 1;
[|unsafe byte* GetPtr(byte* bytePt)
{
return bytePt;
}|]
var aReference = GetPtr(&b);
}
}",
@"class C
{
public unsafe void UnsafeFunction()
{
byte b = 1;
var aReference = GetPtr(&b);
}
private static unsafe byte* GetPtr(byte* bytePt)
{
return bytePt;
}
}");
}

[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertLocalFunctionToMethod)]
[WorkItem(32976, "https://github.com/dotnet/roslyn/issues/32976")]
public async Task TestUnsafeLocalFunctionInUnsafeMethod()
{
await TestInRegularAndScriptAsync(
@"class C
{
public unsafe void UnsafeFunction()
{
byte b = 1;
[|byte* GetPtr(byte* bytePt)
{
return bytePt;
}|]
var aReference = GetPtr(&b);
}
}",
@"class C
{
public unsafe void UnsafeFunction()
{
byte b = 1;
var aReference = GetPtr(&b);
}
private static unsafe byte* GetPtr(byte* bytePt)
{
return bytePt;
}
}");
}

[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertLocalFunctionToMethod)]
[WorkItem(32976, "https://github.com/dotnet/roslyn/issues/32976")]
public async Task TestLocalFunctionInUnsafeMethod()
{
await TestInRegularAndScriptAsync(
@"class C
{
public unsafe void UnsafeFunction()
{
byte b = 1;
[|byte GetPtr(byte bytePt)
{
return bytePt;
}|]
var aReference = GetPtr(b);
}
}",
@"class C
{
public unsafe void UnsafeFunction()
{
byte b = 1;
var aReference = GetPtr(b);
}
private static byte GetPtr(byte bytePt)
{
return bytePt;
}
}");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,18 @@ private static async Task<Document> UpdateDocumentAsync(
var containerSymbol = semanticModel.GetDeclaredSymbol(container, cancellationToken);
var isStatic = containerSymbol.IsStatic || captures.All(capture => !capture.IsThisParameter());

// GetSymbolModifiers actually checks if the local function needs to be unsafe, not whether
// it is declared as such, so this check we don't need to worry about whether the containing method
// is unsafe, this will just work regardless.
var needsUnsafe = declaredSymbol.GetSymbolModifiers().IsUnsafe;

var methodName = GenerateUniqueMethodName(declaredSymbol);
var parameters = declaredSymbol.Parameters;
var methodSymbol = CodeGenerationSymbolFactory.CreateMethodSymbol(
containingType: declaredSymbol.ContainingType,
attributes: default,
accessibility: Accessibility.Private,
modifiers: new DeclarationModifiers(isStatic, isAsync: declaredSymbol.IsAsync),
modifiers: new DeclarationModifiers(isStatic, isAsync: declaredSymbol.IsAsync, isUnsafe: needsUnsafe),
returnType: declaredSymbol.ReturnType,
refKind: default,
explicitInterfaceImplementations: default,
Expand Down

0 comments on commit 823039e

Please sign in to comment.