提交 87182136 编写于 作者: V VSadov 提交者: GitHub

Merge pull request #14715 from VSadov/merge-dev15-rc-into-master20161020-150037

Merge dev15 rc into master
......@@ -121,7 +121,7 @@ private void ComputeBinderMap()
}
}
public ImmutableArray<MethodSymbol> MethodSymbolsWithYield
private ImmutableArray<MethodSymbol> MethodSymbolsWithYield
{
get
{
......@@ -133,5 +133,35 @@ public ImmutableArray<MethodSymbol> MethodSymbolsWithYield
return _methodSymbolsWithYield;
}
}
public void ValidateIteratorMethods(DiagnosticBag diagnostics)
{
foreach (var iterator in MethodSymbolsWithYield)
{
foreach (var parameter in iterator.Parameters)
{
if (parameter.RefKind != RefKind.None)
{
diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, parameter.Locations[0]);
}
else if (parameter.Type.IsUnsafe())
{
diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, parameter.Locations[0]);
}
}
if (iterator.IsVararg)
{
// error CS1636: __arglist is not allowed in the parameter list of iterators
diagnostics.Add(ErrorCode.ERR_VarargsIterator, iterator.Locations[0]);
}
if (((iterator as SourceMethodSymbol)?.IsUnsafe == true || (iterator as LocalFunctionSymbol)?.IsUnsafe == true)
&& Compilation.Options.AllowUnsafe) // Don't cascade
{
diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, iterator.Locations[0]);
}
}
}
}
}
......@@ -555,7 +555,6 @@ private DecisionTree Add(DecisionTree.ByType byType, DecisionMaker makeDecision)
case ConversionKind.ExplicitEnumeration:// a value of enum type does not match a pattern of integral type
case ConversionKind.ExplicitNumeric: // a value of type long does not match a pattern of type int
case ConversionKind.ImplicitNumeric: // a value of type short does not match a pattern of type int
case ConversionKind.ImplicitTuple: // distinct tuple types don't match
case ConversionKind.NoConversion:
return false;
......@@ -564,9 +563,8 @@ private DecisionTree Add(DecisionTree.ByType byType, DecisionMaker makeDecision)
case ConversionKind.Unboxing: // a value of type object might match a pattern of type int
return null;
default:
// other conversions don't apply (e.g. conversions from expression, user-defined) and should not arise
throw ExceptionUtilities.UnexpectedValue(conversion.Kind);
default: // other conversions do not apply (e.g. conversions from expression, user-defined, pointer conversions, tuple)
return false;
}
}
}
......
......@@ -451,6 +451,8 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
returnType);
lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));
block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics);
((ExecutableCodeBinder)lambdaBodyBinder).ValidateIteratorMethods(diagnostics);
ValidateUnsafeParameters(diagnostics, parameters);
haveLambdaBodyAndBinders:
......
......@@ -1492,52 +1492,20 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
var compilation = method.DeclaringCompilation;
var factory = compilation.GetBinderFactory(sourceMethod.SyntaxTree);
var blockSyntax = sourceMethod.BodySyntax as BlockSyntax;
var bodySyntax = sourceMethod.BodySyntax;
if (blockSyntax != null)
if (bodySyntax != null)
{
var inMethodBinder = factory.GetBinder(blockSyntax);
var binder = new ExecutableCodeBinder(blockSyntax, sourceMethod, inMethodBinder);
body = (BoundBlock)binder.BindEmbeddedBlock(blockSyntax, diagnostics);
var inMethodBinder = factory.GetBinder(bodySyntax);
var binder = new ExecutableCodeBinder(bodySyntax, sourceMethod, inMethodBinder);
importChain = binder.ImportChain;
foreach (var iterator in binder.MethodSymbolsWithYield)
{
foreach (var parameter in iterator.Parameters)
{
if (parameter.RefKind != RefKind.None)
{
diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, parameter.Locations[0]);
}
else if (parameter.Type.IsUnsafe())
{
diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, parameter.Locations[0]);
}
}
if (iterator.IsVararg)
{
// error CS1636: __arglist is not allowed in the parameter list of iterators
diagnostics.Add(ErrorCode.ERR_VarargsIterator, iterator.Locations[0]);
}
binder.ValidateIteratorMethods(diagnostics);
if (((iterator as SourceMethodSymbol)?.IsUnsafe == true || (iterator as LocalFunctionSymbol)?.IsUnsafe == true) && compilation.Options.AllowUnsafe) // Don't cascade
{
diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, iterator.Locations[0]);
}
}
}
else if (sourceMethod.IsExpressionBodied)
{
var methodSyntax = sourceMethod.SyntaxNode;
var arrowExpression = methodSyntax.GetExpressionBodySyntax();
Binder binder = factory.GetBinder(arrowExpression);
binder = new ExecutableCodeBinder(arrowExpression, sourceMethod, binder);
importChain = binder.ImportChain;
// Add locals
body = binder.BindExpressionBodyAsBlock(arrowExpression, diagnostics);
body = bodySyntax.Kind() == SyntaxKind.Block
? binder.BindEmbeddedBlock((BlockSyntax)bodySyntax, diagnostics)
: binder.BindExpressionBodyAsBlock(
(ArrowExpressionClauseSyntax)bodySyntax, diagnostics);
}
else
{
......
......@@ -29,7 +29,7 @@ internal sealed class SourceCustomEventAccessorSymbol : SourceEventAccessorSymbo
DiagnosticBag diagnostics)
: base(@event,
syntax.GetReference(),
syntax.Body?.GetReference(),
((SyntaxNode)syntax.Body ?? syntax.ExpressionBody)?.GetReference(),
ImmutableArray.Create(syntax.Keyword.GetLocation()))
{
Debug.Assert(syntax != null);
......
......@@ -193,8 +193,11 @@ internal override bool IsExpressionBodied
AccessorDeclarationSyntax syntax,
MethodKind methodKind,
bool isAutoPropertyAccessor,
DiagnosticBag diagnostics) :
base(containingType, syntax.GetReference(), syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), location)
DiagnosticBag diagnostics)
: base(containingType,
syntax.GetReference(),
((SyntaxNode)syntax.Body ?? syntax.ExpressionBody)?.GetReference(),
location)
{
_property = property;
_explicitInterfaceImplementations = explicitInterfaceImplementations;
......
......@@ -29,6 +29,147 @@ internal void VerifyDiagnostics(string source, CSharpCompilationOptions options,
[CompilerTrait(CompilerFeature.LocalFunctions)]
public class LocalFunctionTests : LocalFunctionsTestBase
{
[Fact]
public void RefArgsInIteratorLocalFuncs()
{
var src = @"
using System;
using System.Collections.Generic;
class C
{
public void M1()
{
IEnumerable<int> Local(ref int a) { yield break; }
int x = 0;
Local(ref x);
}
public void M2()
{
Action a = () =>
{
IEnumerable<int> Local(ref int x) { yield break; }
int y = 0;
Local(ref y);
return;
};
a();
}
public Func<int> M3() => (() =>
{
IEnumerable<int> Local(ref int a) { yield break; }
int x = 0;
Local(ref x);
return 0;
});
public IEnumerable<int> M4(ref int a)
{
yield return new Func<int>(() =>
{
IEnumerable<int> Local(ref int b) { yield break; }
int x = 0;
Local(ref x);
return 0;
})();
}
}";
VerifyDiagnostics(src,
// (8,40): error CS1623: Iterators cannot have ref or out parameters
// IEnumerable<int> Local(ref int a) { yield break; }
Diagnostic(ErrorCode.ERR_BadIteratorArgType, "a").WithLocation(8, 40),
// (17,44): error CS1623: Iterators cannot have ref or out parameters
// IEnumerable<int> Local(ref int x) { yield break; }
Diagnostic(ErrorCode.ERR_BadIteratorArgType, "x").WithLocation(17, 44),
// (27,40): error CS1623: Iterators cannot have ref or out parameters
// IEnumerable<int> Local(ref int a) { yield break; }
Diagnostic(ErrorCode.ERR_BadIteratorArgType, "a").WithLocation(27, 40),
// (33,40): error CS1623: Iterators cannot have ref or out parameters
// public IEnumerable<int> M4(ref int a)
Diagnostic(ErrorCode.ERR_BadIteratorArgType, "a").WithLocation(33, 40),
// (37,48): error CS1623: Iterators cannot have ref or out parameters
// IEnumerable<int> Local(ref int b) { yield break; }
Diagnostic(ErrorCode.ERR_BadIteratorArgType, "b").WithLocation(37, 48));
}
[Fact]
public void UnsafeArgsInIteratorLocalFuncs()
{
var src = @"
using System;
using System.Collections.Generic;
class C
{
public unsafe void M1()
{
IEnumerable<int> Local(int* a) { yield break; }
int x = 0;
Local(&x);
}
public unsafe void M2()
{
Action a = () =>
{
IEnumerable<int> Local(int* x) { yield break; }
int y = 0;
Local(&y);
return;
};
a();
}
public unsafe Func<int> M3() => (() =>
{
IEnumerable<int> Local(int* a) { yield break; }
int x = 0;
Local(&x);
return 0;
});
public unsafe IEnumerable<int> M4(int* a)
{
yield return new Func<int>(() =>
{
IEnumerable<int> Local(int* b) { yield break; }
int x = 0;
Local(&x);
return 0;
})();
}
}";
CreateCompilationWithMscorlib(src, options: TestOptions.UnsafeDebugDll)
.VerifyDiagnostics(
// (8,37): error CS1637: Iterators cannot have unsafe parameters or yield types
// IEnumerable<int> Local(int* a) { yield break; }
Diagnostic(ErrorCode.ERR_UnsafeIteratorArgType, "a").WithLocation(8, 37),
// (17,41): error CS1637: Iterators cannot have unsafe parameters or yield types
// IEnumerable<int> Local(int* x) { yield break; }
Diagnostic(ErrorCode.ERR_UnsafeIteratorArgType, "x").WithLocation(17, 41),
// (27,37): error CS1637: Iterators cannot have unsafe parameters or yield types
// IEnumerable<int> Local(int* a) { yield break; }
Diagnostic(ErrorCode.ERR_UnsafeIteratorArgType, "a").WithLocation(27, 37),
// (33,44): error CS1637: Iterators cannot have unsafe parameters or yield types
// public unsafe IEnumerable<int> M4(int* a)
Diagnostic(ErrorCode.ERR_UnsafeIteratorArgType, "a").WithLocation(33, 44),
// (33,36): error CS1629: Unsafe code may not appear in iterators
// public unsafe IEnumerable<int> M4(int* a)
Diagnostic(ErrorCode.ERR_IllegalInnerUnsafe, "M4").WithLocation(33, 36),
// (37,45): error CS1637: Iterators cannot have unsafe parameters or yield types
// IEnumerable<int> Local(int* b) { yield break; }
Diagnostic(ErrorCode.ERR_UnsafeIteratorArgType, "b").WithLocation(37, 45),
// (37,40): error CS1629: Unsafe code may not appear in iterators
// IEnumerable<int> Local(int* b) { yield break; }
Diagnostic(ErrorCode.ERR_IllegalInnerUnsafe, "int*").WithLocation(37, 40),
// (39,23): error CS1629: Unsafe code may not appear in iterators
// Local(&x);
Diagnostic(ErrorCode.ERR_IllegalInnerUnsafe, "&x").WithLocation(39, 23),
// (39,17): error CS1629: Unsafe code may not appear in iterators
// Local(&x);
Diagnostic(ErrorCode.ERR_IllegalInnerUnsafe, "Local(&x)").WithLocation(39, 17));
}
[Fact]
[WorkItem(13193, "https://github.com/dotnet/roslyn/issues/13193")]
public void LocalFunctionConflictingName()
......
......@@ -194,7 +194,7 @@ private async Task<TriggerIdentifierKind> DetermineIfRenamableSymbolsAsync(IEnum
// Get the source symbol if possible
var sourceSymbol = await SymbolFinder.FindSourceDefinitionAsync(symbol, document.Project.Solution, _cancellationToken).ConfigureAwait(false) ?? symbol;
if (!sourceSymbol.Locations.All(loc => loc.IsInSource))
if (!sourceSymbol.IsFromSource())
{
return TriggerIdentifierKind.NotRenamable;
}
......@@ -217,7 +217,7 @@ private async Task<TriggerIdentifierKind> DetermineIfRenamableSymbolAsync(ISymbo
return TriggerIdentifierKind.NotRenamable;
}
if (!sourceSymbol.Locations.All(loc => loc.IsInSource))
if (!sourceSymbol.IsFromSource())
{
return TriggerIdentifierKind.NotRenamable;
}
......
......@@ -1478,5 +1478,72 @@ End Sub
await state.AssertNoTag();
}
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.RenameTracking)]
[WorkItem(14159, "https://github.com/dotnet/roslyn/issues/14159")]
public async Task RenameTrackingNotOnWellKnownValueTupleType()
{
var workspaceXml = @"
<Workspace>
<Project Language=""C#"" CommonReferences=""true"" LanguageVersion=""7"">
<Document>
using System;
class C
{
void M()
{
var x = new ValueTuple$$&lt;int&gt;();
}
}
namespace System
{
public struct ValueTuple&lt;T1&gt;
{
public T1 Item1;
}
}
</Document>
</Project>
</Workspace>";
using (var state = await RenameTrackingTestState.CreateFromWorkspaceXmlAsync(workspaceXml, LanguageNames.CSharp))
{
state.EditorOperations.InsertText("2");
await state.AssertNoTag();
}
}
[WpfFact]
[Trait(Traits.Feature, Traits.Features.RenameTracking)]
[WorkItem(14159, "https://github.com/dotnet/roslyn/issues/14159")]
public async Task RenameTrackingOnThingsCalledValueTupleThatAreNotTheWellKnownType()
{
var workspaceXml = @"
<Workspace>
<Project Language=""C#"" CommonReferences=""true"" LanguageVersion=""7"">
<Document>
class C
{
void M()
{
var x = new ValueTuple$$&lt;int&gt;();
}
}
public struct ValueTuple&lt;T1&gt;
{
public T1 Item1;
}
</Document>
</Project>
</Workspace>";
using (var state = await RenameTrackingTestState.CreateFromWorkspaceXmlAsync(workspaceXml, LanguageNames.CSharp))
{
state.EditorOperations.InsertText("2");
await state.AssertTag("ValueTuple", "ValueTuple2");
}
}
}
}
......@@ -60,6 +60,19 @@ internal sealed class RenameTrackingTestState : IDisposable
return new RenameTrackingTestState(workspace, languageName, onBeforeGlobalSymbolRenamedReturnValue, onAfterGlobalSymbolRenamedReturnValue);
}
public static async Task<RenameTrackingTestState> CreateFromWorkspaceXmlAsync(
string workspaceXml,
string languageName,
bool onBeforeGlobalSymbolRenamedReturnValue = true,
bool onAfterGlobalSymbolRenamedReturnValue = true)
{
var workspace = await TestWorkspace.CreateAsync(
workspaceXml,
exportProvider: TestExportProvider.CreateExportProviderWithCSharpAndVisualBasic());
return new RenameTrackingTestState(workspace, languageName, onBeforeGlobalSymbolRenamedReturnValue, onAfterGlobalSymbolRenamedReturnValue);
}
public RenameTrackingTestState(
TestWorkspace workspace,
string languageName,
......
......@@ -88,9 +88,9 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
}
private IEnumerable<CodeAction> CreateActions(
CodeFixContext context, Document document, Diagnostic diagnostic,
SyntaxNode node, SemanticModel semanticModel,
IEnumerable<INamespaceOrTypeSymbol> proposedContainers,
CodeFixContext context, Document document, Diagnostic diagnostic,
SyntaxNode node, SemanticModel semanticModel,
IEnumerable<INamespaceOrTypeSymbol> proposedContainers,
ISymbolDisplayService displayService)
{
foreach (var container in proposedContainers)
......@@ -239,7 +239,7 @@ private bool BindsWithoutErrors(INamespaceSymbol ns, string rightName, bool isAt
{
return false;
}
return BindsWithoutErrors(ns, rightName + "Attribute", isAttributeName: false);
}
......@@ -291,4 +291,4 @@ public GroupingCodeAction(string title, ImmutableArray<CodeAction> nestedActions
}
}
}
}
}
\ No newline at end of file
......@@ -5,5 +5,6 @@ namespace Microsoft.CodeAnalysis.Editor.Xaml.Diagnostics
internal static class XamlDiagnosticIds
{
public const string UnnecessaryNamespacesId = "XAML1103";
public const string MissingNamespaceId = "XAML0002";
}
}
......@@ -122,6 +122,11 @@ private static bool ShouldRenameOnlyAffectDeclaringProject(ISymbol symbol)
var symbolInfo = semanticModel.GetSymbolInfo(token, cancellationToken);
if (symbolInfo.Symbol != null)
{
if (symbolInfo.Symbol.IsTupleType())
{
return TokenRenameInfo.NoSymbolsTokenInfo;
}
return TokenRenameInfo.CreateSingleSymbolTokenInfo(symbolInfo.Symbol);
}
......
......@@ -168,6 +168,11 @@ public static bool IsArrayType(this ISymbol symbol)
return symbol?.Kind == SymbolKind.ArrayType;
}
public static bool IsTupleType(this ISymbol symbol)
{
return (symbol as ITypeSymbol)?.IsTupleType ?? false;
}
public static bool IsAnonymousFunction(this ISymbol symbol)
{
return (symbol as IMethodSymbol)?.MethodKind == MethodKind.AnonymousFunction;
......@@ -819,6 +824,11 @@ public static bool IsEventAccessor(this ISymbol symbol)
method.MethodKind == MethodKind.EventRemove);
}
public static bool IsFromSource(this ISymbol symbol)
{
return symbol.Locations.Any() && symbol.Locations.All(location => location.IsInSource);
}
public static DeclarationModifiers GetSymbolModifiers(this ISymbol symbol)
{
return new DeclarationModifiers(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册