提交 de42520f 编写于 作者: C CyrusNajmabadi

Merge remote-tracking branch 'upstream/master' into featureOptions

## Bootstrap Files
This directory contains the set of files necessary to run the bootstrap compiler. These are not produced as a part of normal build because they are not correct for standard insertions. This directory should be copied in its entirety whenever a bootstrap compiler is deployed.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<gcServer enabled="true" />
<gcConcurrent enabled="false"/>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.VisualBasic" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Thread" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.FileVersionInfo" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Principal.Windows" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Pipes" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<clear/>
<add name="exitingTraceListener" type="Microsoft.CodeAnalysis.CommandLine.ExitingTraceListener,VBCSCompiler" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
echo off
%~dp0\csc.exe /shared %*
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<gcServer enabled="true" />
<gcConcurrent enabled="false"/>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.VisualBasic" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Thread" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.FileVersionInfo" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Principal.Windows" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Pipes" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<clear/>
<add name="exitingTraceListener" type="Microsoft.CodeAnalysis.CommandLine.ExitingTraceListener,csc" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
echo off
%~dp0\vbc.exe /shared %*
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<gcServer enabled="true" />
<gcConcurrent enabled="false"/>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.VisualBasic" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Thread" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.FileVersionInfo" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Principal.Windows" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Pipes" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<clear/>
<add name="exitingTraceListener" type="Microsoft.CodeAnalysis.CommandLine.ExitingTraceListener,vbc" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
......@@ -70,7 +70,6 @@ powershell -noprofile -executionPolicy RemoteSigned -file "%RoslynRoot%\build\sc
if not exist "%bindir%\Bootstrap" mkdir "%bindir%\Bootstrap" || goto :BuildFailed
move "Binaries\%BuildConfiguration%\Exes\Toolset\*" "%bindir%\Bootstrap" || goto :BuildFailed
copy "build\bootstrap\*" "%bindir%\Bootstrap" || goto :BuildFailed
REM Clean the previous build
msbuild %MSBuildAdditionalCommandLineArgs% /t:Clean build/Toolset/Toolset.csproj /p:Configuration=%BuildConfiguration% /fileloggerparameters:LogFile="%bindir%\BootstrapClean.log" || goto :BuildFailed
......
......@@ -1240,7 +1240,13 @@ private static bool FallBackOnDiscard(IdentifierNameSyntax node, DiagnosticBag d
}
CSharpSyntaxNode containingDeconstruction = node.GetContainingDeconstruction();
return containingDeconstruction != null || IsOutVarDiscardIdentifier(node);
bool isDiscard = containingDeconstruction != null || IsOutVarDiscardIdentifier(node);
if (isDiscard)
{
CheckFeatureAvailability(node.Location, MessageID.IDS_FeatureTuples, diagnostics);
}
return isDiscard;
}
private static bool IsOutVarDiscardIdentifier(SimpleNameSyntax node)
......
......@@ -109,12 +109,12 @@ internal sealed override AssemblySymbol CorLibrary
public sealed override IEnumerable<string> LinkedAssembliesDebugInfo => SpecializedCollections.EmptyEnumerable<string>();
// C# currently doesn't emit compilation level imports (TODO: scripting).
public override ImmutableArray<Cci.UsedNamespaceOrType> GetImports() => ImmutableArray<Cci.UsedNamespaceOrType>.Empty;
public sealed override ImmutableArray<Cci.UsedNamespaceOrType> GetImports() => ImmutableArray<Cci.UsedNamespaceOrType>.Empty;
// C# doesn't allow to define default namespace for compilation.
public override string DefaultNamespace => null;
public sealed override string DefaultNamespace => null;
protected override IEnumerable<Cci.IAssemblyReference> GetAssemblyReferencesFromAddedModules(DiagnosticBag diagnostics)
protected sealed override IEnumerable<Cci.IAssemblyReference> GetAssemblyReferencesFromAddedModules(DiagnosticBag diagnostics)
{
ImmutableArray<ModuleSymbol> modules = SourceModule.ContainingAssembly.Modules;
......@@ -178,7 +178,7 @@ internal sealed override IEnumerable<Cci.INestedTypeDefinition> GetSynthesizedNe
return null;
}
public override MultiDictionary<Cci.DebugSourceDocument, Cci.DefinitionWithLocation> GetSymbolToLocationMap()
public sealed override MultiDictionary<Cci.DebugSourceDocument, Cci.DefinitionWithLocation> GetSymbolToLocationMap()
{
var result = new MultiDictionary<Cci.DebugSourceDocument, Cci.DefinitionWithLocation>();
......@@ -355,7 +355,7 @@ internal virtual bool TryGetAnonymousTypeName(NamedTypeSymbol template, out stri
return false;
}
internal override ImmutableArray<Cci.INamespaceTypeDefinition> GetAnonymousTypes()
internal sealed override ImmutableArray<Cci.INamespaceTypeDefinition> GetAnonymousTypes()
{
if (EmitOptions.EmitMetadataOnly)
{
......@@ -436,7 +436,7 @@ private static void GetExportedTypes(NamespaceOrTypeSymbol symbol, int parentInd
}
}
public override ImmutableArray<Cci.ExportedType> GetExportedTypes(DiagnosticBag diagnostics)
public sealed override ImmutableArray<Cci.ExportedType> GetExportedTypes(DiagnosticBag diagnostics)
{
Debug.Assert(HaveDeterminedTopLevelTypes);
......@@ -1073,7 +1073,7 @@ public static Cci.TypeMemberVisibility MemberVisibility(Symbol symbol)
}
}
internal override Cci.IMethodReference Translate(MethodSymbol symbol, DiagnosticBag diagnostics, bool needDeclaration)
internal sealed override Cci.IMethodReference Translate(MethodSymbol symbol, DiagnosticBag diagnostics, bool needDeclaration)
{
return Translate(symbol, null, diagnostics, null, needDeclaration);
}
......
......@@ -659,7 +659,14 @@ private BoundNode IntroduceFrame(BoundNode node, LambdaFrame frame, Func<ArrayBu
if ((object)_innermostFramePointer != null)
{
proxies.TryGetValue(_innermostFramePointer, out oldInnermostFrameProxy);
if (_analysis.NeedsParentFrame.Contains(node))
if (_analysis.NeedsParentFrame.Contains(node) &&
// If the frame pointer is a struct type that means the frame is a struct
// passed by-ref to a local function. Capturing parent frames for local
// functions is performed in RemapLambdaOrLocalFunction, rather than here
// (since struct frame pointers should never be captured, but instead be
// passed in a list to the needed local functions).
!(_innermostFramePointer.Kind == SymbolKind.Local &&
((LocalSymbol)_innermostFramePointer).Type.IsValueType))
{
var capturedFrame = LambdaCapturedVariable.Create(frame, _innermostFramePointer, ref _synthesizedFieldNameIdDispenser);
FieldSymbol frameParent = capturedFrame.AsMember(frameType);
......
......@@ -74,6 +74,7 @@
<Compile Include="Attributes\AttributeTests_Synthesized.cs" />
<Compile Include="Attributes\AttributeTests_Tuples.cs" />
<Compile Include="Attributes\AttributeTests_WellKnownAttributes.cs" />
<Compile Include="CodeGen\CodeGenCapturing.cs" />
<Compile Include="Emit\DesktopStrongNameProviderTests.cs" />
<Compile Include="Attributes\InternalsVisibleToAndStrongNameTests.cs" />
<Compile Include="Attributes\WellKnownAttributesTestBase.cs" />
......@@ -193,4 +194,4 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="..\..\..\..\..\build\Targets\Imports.targets" />
</Project>
</Project>
\ No newline at end of file

using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Roslyn.Test.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using System.Collections;
using System.Collections.Immutable;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
public class CodeGenCapturing : CSharpTestBase
{
private class CaptureContext
{
// Stores a mapping from scope index (0-based count of scopes
// from `this` to most nested scope)
public readonly List<IList<string>> VariablesByScope = new List<IList<string>>();
private CaptureContext() { }
public CaptureContext(int MaxVariables)
{
// Fields are shared among methods, so we also share them in the
// capture context when cloning
var fieldsBuilder = ImmutableArray.CreateBuilder<string>(MaxVariables);
for (int i = 0; i < MaxVariables; i++)
{
fieldsBuilder.Add($"field_{i}");
}
VariablesByScope.Add(fieldsBuilder.MoveToImmutable());
}
public void Add(int depth, string varName)
{
if (VariablesByScope.Count <= depth ||
VariablesByScope[depth] == null)
{
VariablesByScope.Insert(depth, new List<string>() { varName });
}
else
{
VariablesByScope[depth].Add(varName);
}
}
public CaptureContext Clone()
{
var fields = VariablesByScope[0];
var newCtx = new CaptureContext();
newCtx.VariablesByScope.Add(fields);
newCtx.VariablesByScope.AddRange(
this.VariablesByScope
.Skip(1)
.Select(list => list == null ? null : new List<string>(list)));
newCtx.CaptureNameIndex = this.CaptureNameIndex;
return newCtx;
}
public int CaptureNameIndex = 0;
}
private static string MakeLocalFunc(int nameIndex, string captureExpression)
=> $@"int Local_{nameIndex}() => {captureExpression};";
private static string MakeCaptureExpression(IList<int> varsToCapture, CaptureContext ctx)
{
var varNames = new List<string>();
for (int varDepth = 0; varDepth < varsToCapture.Count; varDepth++)
{
var variablesByScope = ctx.VariablesByScope;
// Do we have any variables in this scope depth?
// If not, initialize an empty list
if (variablesByScope.Count <= varDepth)
{
variablesByScope.Add(new List<string>());
}
var varsAtCurrentDepth = variablesByScope[varDepth];
int numToCapture = varsToCapture[varDepth];
int numVarsAvailable = variablesByScope[varDepth].Count;
// If we have enough variables to capture in the context
// just add them
if (numVarsAvailable >= numToCapture)
{
// Capture the last variables added since if there are more
// vars in the context than the max vars to capture we'll never
// have code coverage of the newest vars added to the context.
varNames.AddRange(varsAtCurrentDepth
.Skip(numVarsAvailable - numToCapture)
.Take(numToCapture));
}
else
{
// Not enough variables in the context -- add more
for (int i = 0; i < numToCapture - numVarsAvailable; i++)
{
varsAtCurrentDepth.Add($"captureVar_{ctx.CaptureNameIndex++}");
}
varNames.AddRange(varsAtCurrentDepth);
}
}
return varNames.Count == 0 ? "0" : string.Join(" + ", varNames);
}
/// <summary>
/// Generates all combinations of distributing a sum to a list of subsets.
/// This is equivalent to the "stars and bars" combinatorics construction.
/// </summary>
private static IEnumerable<IList<int>> GenerateAllSetCombinations(int sum, int numSubsets)
{
Assert.True(numSubsets > 0);
return GenerateAll(sum, 0, ImmutableList<int>.Empty);
IEnumerable<ImmutableList<int>> GenerateAll(
int remainingSum,
int setIndex, // 0-based index of subset we're generating
ImmutableList<int> setsSoFar)
{
for (int i = 0; i <= remainingSum; i++)
{
var newSets = setsSoFar.Add(i);
if (setIndex == numSubsets - 1)
{
yield return newSets;
}
else
{
foreach (var captures in GenerateAll(remainingSum - i,
setIndex + 1,
newSets))
{
yield return captures;
}
}
}
}
}
[Fact]
public void GenerateAllTest()
{
Assert.Equal(new[]
{
ImmutableList<int>.Empty.Add(0),
ImmutableList<int>.Empty.Add(1),
ImmutableList<int>.Empty.Add(2),
ImmutableList<int>.Empty.Add(3)
}, GenerateAllSetCombinations(3, 1));
Assert.Equal(new[]
{
ImmutableList<int>.Empty.Add(0).Add(0),
ImmutableList<int>.Empty.Add(0).Add(1),
ImmutableList<int>.Empty.Add(0).Add(2),
ImmutableList<int>.Empty.Add(0).Add(3),
ImmutableList<int>.Empty.Add(1).Add(0),
ImmutableList<int>.Empty.Add(1).Add(1),
ImmutableList<int>.Empty.Add(1).Add(2),
ImmutableList<int>.Empty.Add(2).Add(0),
ImmutableList<int>.Empty.Add(2).Add(1),
ImmutableList<int>.Empty.Add(3).Add(0)
}, GenerateAllSetCombinations(3, 2));
}
[Fact]
public void ExpressionGeneratorTest01()
{
var ctx = new CaptureContext(1);
int[] captures = { 1 }; // Capture 1 var at the 0 depth
var expr = MakeCaptureExpression(captures, ctx);
Assert.Equal("field_0", expr);
VerifyContext(new[]
{
new[] { "field_0"}
}, ctx.VariablesByScope);
ctx = new CaptureContext(3);
captures = new[] { 3 }; // Capture 3 vars at 0 depth
expr = MakeCaptureExpression(captures, ctx);
Assert.Equal("field_0 + field_1 + field_2", expr);
VerifyContext(new[]
{
new[] { "field_0", "field_1", "field_2" }
}, ctx.VariablesByScope);
ctx = new CaptureContext(3);
captures = new[] { 1, 1, 1 }; // Capture 1 var at each of 3 depths
expr = MakeCaptureExpression(captures, ctx);
Assert.Equal("field_2 + captureVar_0 + captureVar_1", expr);
VerifyContext(new[]
{
new[] { "field_0", "field_1", "field_2"},
new[] { "captureVar_0"},
new[] { "captureVar_1"}
}, ctx.VariablesByScope);
void VerifyContext(IList<IEnumerable<string>> expectedCtx, List<IList<string>> actualCtx)
{
Assert.Equal(expectedCtx.Count, ctx.VariablesByScope.Count);
for (int depth = 0; depth < expectedCtx.Count; depth++)
{
AssertEx.Equal(expectedCtx[depth], ctx.VariablesByScope[depth]);
}
}
}
private struct LayoutEnumerator : IEnumerator<(int depth, int localFuncIndex)>
{
private readonly IList<int> _layout;
private (int depth, int localFuncIndex) _current;
public LayoutEnumerator(IList<int> layout)
{
_layout = layout;
_current = (-1, -1);
}
public (int depth, int localFuncIndex) Current => _current;
object IEnumerator.Current => throw new NotImplementedException();
public void Dispose() => throw new NotImplementedException();
public bool MoveNext()
{
if (_current.depth < 0)
{
return FindNonEmptyDepth(0, _layout, out _current);
}
else
{
int newIndex = _current.localFuncIndex + 1;
if (newIndex == _layout[_current.depth])
{
return FindNonEmptyDepth(_current.depth + 1, _layout, out _current);
}
_current = (_current.depth, newIndex);
return true;
}
bool FindNonEmptyDepth(int startingDepth, IList<int> layout, out (int depth, int localFuncIndex) newCurrent)
{
for (int depth = startingDepth; depth < layout.Count; depth++)
{
if (layout[depth] > 0)
{
newCurrent = (depth, 0);
return true;
}
}
newCurrent = (layout.Count, 0);
return false;
}
}
public void Reset() => throw new NotImplementedException();
}
private class MethodInfo
{
public MethodInfo(int MaxCaptures)
{
LocalFuncs = new List<IList<string>>();
CaptureContext = new CaptureContext(MaxCaptures);
}
private MethodInfo() { }
public List<IList<string>> LocalFuncs { get; private set; }
public CaptureContext CaptureContext { get; private set; }
public int TotalLocalFuncs { get; set; }
public MethodInfo Clone()
{
return new MethodInfo
{
LocalFuncs = this.LocalFuncs
.Select(x => x == null
? null
: (IList<string>)new List<string>(x)).ToList(),
CaptureContext = this.CaptureContext.Clone()
};
}
}
private static IEnumerable<MethodInfo> MakeMethodsWithLayout(IList<int> localFuncLayout)
{
const int MaxCaptures = 3;
var enumerator = new LayoutEnumerator(localFuncLayout);
if (!enumerator.MoveNext())
{
return Array.Empty<MethodInfo>();
}
var methods = new List<MethodInfo>();
DfsLayout(enumerator, new MethodInfo(MaxCaptures), 0);
return methods;
// Note that the enumerator is a struct, so every new var
// is a copy
void DfsLayout(LayoutEnumerator e, MethodInfo methodSoFar, int localFuncNameIndex)
{
var (depth, localFuncIndex) = e.Current;
bool isLastFunc = !e.MoveNext();
foreach (var captureCombo in GenerateAllSetCombinations(MaxCaptures, depth + 2))
{
var copy = methodSoFar.Clone();
var expr = MakeCaptureExpression(captureCombo, copy.CaptureContext);
if (depth >= copy.LocalFuncs.Count)
{
copy.LocalFuncs.AddRange(Enumerable.Repeat<List<string>>(null, depth - copy.LocalFuncs.Count));
copy.LocalFuncs.Insert(depth, new List<string>());
}
string localFuncName = $"Local_{localFuncNameIndex}";
copy.LocalFuncs[depth].Add($"int {localFuncName}() => {expr};");
copy.CaptureContext.Add(depth + 1, $"{localFuncName}()");
if (!isLastFunc)
{
DfsLayout(e, copy, localFuncNameIndex + 1);
}
else
{
copy.TotalLocalFuncs = localFuncNameIndex + 1;
methods.Add(copy);
}
}
}
}
private static IEnumerable<MethodInfo> MakeAllMethods()
{
const int MaxDepth = 3;
const int MaxLocalFuncs = 3;
// Set combinations indicate what depth we will place local functions
// at. For instance, { 0, 1 } indicates 0 local functions at method
// depth and 1 local function at one nested scope below method level.
foreach (var localFuncLayout in GenerateAllSetCombinations(MaxLocalFuncs, MaxDepth))
{
// Given a local function map, we need to generate capture
// expressions for each local func at each depth
foreach (var method in MakeMethodsWithLayout(localFuncLayout))
yield return method;
}
}
private void SerializeMethod(MethodInfo methodInfo, StringBuilder builder, int methodIndex)
{
int totalLocalFuncs = methodInfo.TotalLocalFuncs;
var methodText = new StringBuilder();
var localFuncs = methodInfo.LocalFuncs;
for (int depth = 0; depth < localFuncs.Count; depth++)
{
if (depth > 0)
{
methodText.Append(' ', 4 * (depth + 1));
methodText.AppendLine("{");
}
var captureVars = methodInfo.CaptureContext.VariablesByScope;
if (captureVars.Count > (depth + 1) &&
captureVars[depth + 1] != null)
{
foreach (var captureVar in captureVars[depth + 1])
{
if (captureVar.EndsWith("()"))
{
continue;
}
methodText.Append(' ', 4 * (depth + 2));
methodText.AppendLine($"int {captureVar} = 0;");
}
}
if (localFuncs[depth] != null)
{
foreach (var localFunc in localFuncs[depth])
{
methodText.Append(' ', 4 * (depth + 2));
methodText.AppendLine(localFunc);
}
}
}
var localFuncCalls = string.Join(" + ",
Enumerable.Range(0, totalLocalFuncs).Select(f => $"Local_{f}()"));
methodText.AppendLine($"Console.WriteLine({localFuncCalls});");
for (int depth = localFuncs.Count - 1; depth > 0; depth--)
{
methodText.Append(' ', 4 * (depth + 1));
methodText.AppendLine("}");
}
builder.Append($@"
public void M_{methodIndex}()
{{
{methodText.ToString()}
}}");
}
/// <summary>
/// This test exercises the C# local function capturing analysis by generating
/// all possible combinations of capturing within a certain complexity. The
/// generating functions use a maximum number of variables captured per local function,
/// a maximum number of local functions, and a maximum scope depth to decide the
/// limits of the combinations.
/// </summary>
[Fact]
public void AllCaptureTests()
{
var methods = MakeAllMethods().ToList();
var fields = methods.First().CaptureContext.VariablesByScope[0];
const int PartitionSize = 500;
const string ClassFmt = @"
using System;
public class C
{{
{0}";
StringBuilder GetClassStart()
=> new StringBuilder(string.Format(ClassFmt,
string.Join("\r\n", fields.Select(f => $"public int {f} = 0;"))));
Parallel.ForEach(Partitioner.Create(0, methods.Count, PartitionSize), (range, state) =>
{
var methodsText = GetClassStart();
for (int methodIndex = range.Item1; methodIndex < range.Item2; methodIndex++)
{
var methodInfo = methods[methodIndex];
if (methodInfo.TotalLocalFuncs == 0)
{
continue;
}
SerializeMethod(methodInfo, methodsText, methodIndex);
}
methodsText.AppendLine("\r\n}");
CreateCompilationWithMscorlib(methodsText.ToString()).VerifyEmitDiagnostics();
});
}
}
}
......@@ -5125,6 +5125,106 @@ static void Main()
Assert.Equal("System.Int32", model.GetTypeInfo(discard1).Type.ToTestDisplayString());
}
[Fact]
public void SingleDiscardInAssignmentInCSharp6()
{
var source =
@"
class C
{
static void Error()
{
_ = 1;
}
static void Ok()
{
int _;
_ = 1;
System.Console.Write(_);
}
}
";
var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular6);
comp.VerifyDiagnostics(
// (6,9): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7 or greater.
// _ = M();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "_").WithArguments("tuples", "7").WithLocation(6, 9)
);
}
[Fact]
public void VariousDiscardsInCSharp6()
{
var source =
@"
class C
{
static void M(out int x)
{
(_, var _, int _) = (1, 2, 3);
var (_, _) = (1, 2);
bool b = 3 is int _;
switch (3)
{
case _: // not a discard
break;
}
switch (3)
{
case int _:
break;
}
M(out var _);
M(out int _);
M(out _);
x = 2;
}
}
";
var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular6, references: s_valueTupleRefs);
comp.VerifyDiagnostics(
// (6,9): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7 or greater.
// (_, var _, int _) = (1, 2, 3);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "(_, var _, int _)").WithArguments("tuples", "7").WithLocation(6, 9),
// (6,29): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7 or greater.
// (_, var _, int _) = (1, 2, 3);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "(1, 2, 3)").WithArguments("tuples", "7").WithLocation(6, 29),
// (7,13): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7 or greater.
// var (_, _) = (1, 2);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "(_, _)").WithArguments("tuples", "7").WithLocation(7, 13),
// (7,22): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7 or greater.
// var (_, _) = (1, 2);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "(1, 2)").WithArguments("tuples", "7").WithLocation(7, 22),
// (8,18): error CS8059: Feature 'pattern matching' is not available in C# 6. Please use language version 7 or greater.
// bool b = 3 is int _;
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "3 is int _").WithArguments("pattern matching", "7").WithLocation(8, 18),
// (16,13): error CS8059: Feature 'pattern matching' is not available in C# 6. Please use language version 7 or greater.
// case int _:
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "case int _:").WithArguments("pattern matching", "7").WithLocation(16, 13),
// (19,19): error CS8059: Feature 'out variable declaration' is not available in C# 6. Please use language version 7 or greater.
// M(out var _);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "_").WithArguments("out variable declaration", "7").WithLocation(19, 19),
// (20,19): error CS8059: Feature 'out variable declaration' is not available in C# 6. Please use language version 7 or greater.
// M(out int _);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "_").WithArguments("out variable declaration", "7").WithLocation(20, 19),
// (6,10): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7 or greater.
// (_, var _, int _) = (1, 2, 3);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "_").WithArguments("tuples", "7").WithLocation(6, 10),
// (11,18): error CS0103: The name '_' does not exist in the current context
// case _: // not a discard
Diagnostic(ErrorCode.ERR_NameNotInContext, "_").WithArguments("_").WithLocation(11, 18),
// (21,15): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7 or greater.
// M(out _);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "_").WithArguments("tuples", "7").WithLocation(21, 15),
// (12,17): warning CS0162: Unreachable code detected
// break;
Diagnostic(ErrorCode.WRN_UnreachableCode, "break").WithLocation(12, 17),
// (17,17): warning CS0162: Unreachable code detected
// break;
Diagnostic(ErrorCode.WRN_UnreachableCode, "break").WithLocation(17, 17)
);
}
[Fact]
public void SingleDiscardInAsyncAssignment()
{
......
......@@ -3126,6 +3126,53 @@ public void UseBeforeDeclaration()
VerifyOutputInMain(src, "5");
}
[Fact]
[WorkItem(15599, "https://github.com/dotnet/roslyn/issues/15599")]
public void NestedLocalFuncCapture()
{
var src = @"
using System;
public class C {
int instance = 11;
public void M() {
int M() => instance;
{
int local = 11;
bool M2() => local == M();
Console.WriteLine(M2());
}
}
public static void Main() => new C().M();
}";
VerifyOutput(src, "True");
}
[Fact]
[WorkItem(15599, "https://github.com/dotnet/roslyn/issues/15599")]
public void NestedLocalFuncCapture2()
{
var src = @"
using System;
public class C {
int instance = 0b1;
public void M() {
int var1 = 0b10;
int M() => var1 + instance;
{
int local = 0b100;
int M2() => local + M();
Console.WriteLine(M2());
}
}
public static void Main() => new C().M();
}";
VerifyOutput(src, "7");
}
internal CompilationVerifier VerifyOutput(string source, string output, CSharpCompilationOptions options)
{
var comp = CreateCompilationWithMscorlib45AndCSruntime(source, options: options);
......
......@@ -668,5 +668,74 @@ static void Main()
CompileAndVerify(comp, expectedOutput: "2");
}
[WorkItem(294553, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=294553")]
[Fact]
public void VoidPointerWithCustomModifiers()
{
var ilSource =
@".class public A
{
// F1(void* p)
.method public static void F1(void* p) { ret }
// F2(const void* p)
.method public static void F2(void modopt([mscorlib]System.Runtime.CompilerServices.IsConst)* p) { ret }
// F3(void* const p)
.method public static void F3(void* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) p) { ret }
// F4(const void* const p)
.method public static void F4(void modopt([mscorlib]System.Runtime.CompilerServices.IsConst)* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) p) { ret }
}";
var source =
@"class B
{
static void Main()
{
unsafe
{
A.F1(null);
A.F2(null);
A.F3(null);
A.F4(null);
}
}
}";
var compilation = CreateCompilationWithCustomILSource(source, ilSource, options: TestOptions.UnsafeReleaseExe);
compilation.VerifyDiagnostics();
CompileAndVerify(compilation);
}
[Fact]
public void IntPointerWithCustomModifiers()
{
var ilSource =
@".class public A
{
// F1(int* p)
.method public static void F1(int32* p) { ret }
// F2(const int* p)
.method public static void F2(int32 modopt([mscorlib]System.Runtime.CompilerServices.IsConst)* p) { ret }
// F3(int* const p)
.method public static void F3(int32* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) p) { ret }
// F4(const int* const p)
.method public static void F4(int32 modopt([mscorlib]System.Runtime.CompilerServices.IsConst)* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) p) { ret }
}";
var source =
@"class B
{
static void Main()
{
unsafe
{
A.F1(null);
A.F2(null);
A.F3(null);
A.F4(null);
}
}
}";
var compilation = CreateCompilationWithCustomILSource(source, ilSource, options: TestOptions.UnsafeReleaseExe);
compilation.VerifyDiagnostics();
CompileAndVerify(compilation);
}
}
}
......@@ -28,7 +28,15 @@ public static void Install()
internal static Assembly ResolveAssembly(string assemblyDisplayName, Assembly requestingAssemblyOpt)
{
var name = new AssemblyName(assemblyDisplayName);
return TryRedirect(name) ? Assembly.Load(name) : null;
try
{
return TryRedirect(name) ? Assembly.Load(name) : null;
}
catch
{
ValidateBootstrapUtil.AddFailedLoad(name);
throw;
}
}
private static readonly byte[] s_b03f5f7f11d50a3a = new byte[] { 0xb0, 0x3f, 0x5f, 0x7f, 0x11, 0xd5, 0x0a, 0x3a };
......@@ -44,6 +52,7 @@ private static bool TryRedirect(AssemblyName name)
case "System.Console":
case "System.Diagnostics.FileVersionInfo":
case "System.IO.Pipes":
case "System.Security.AccessControl":
case "System.Security.Cryptography.Primitives":
case "System.Security.Principal.Windows":
case "System.Threading.Thread":
......@@ -53,16 +62,12 @@ private static bool TryRedirect(AssemblyName name)
case "System.IO.FileSystem.Primitives":
return TryRedirect(name, s_b03f5f7f11d50a3a, 4, 0, 2, 0);
case "System.Diagnostics.Process":
case "System.Diagnostics.StackTrace":
case "System.Security.AccessControl":
return TryRedirect(name, s_b03f5f7f11d50a3a, 4, 0, 3, 0);
}
#if DEBUG || BOOTSTRAP
ValidateBootstrap.AddFailedLoad(name);
#endif
return false;
}
......
......@@ -540,6 +540,11 @@ private string LibDirectoryToUse()
/// </summary>
private int HandleResponse(BuildResponse response, string pathToTool, string responseFileCommands, string commandLineCommands)
{
if (response.Type != BuildResponse.ResponseType.Completed)
{
ValidateBootstrapUtil.AddFailedServerConnection();
}
switch (response.Type)
{
case BuildResponse.ResponseType.Completed:
......
......@@ -6,18 +6,20 @@
using System.Linq;
using System.Reflection;
using System;
using System.Threading;
namespace Microsoft.CodeAnalysis.BuildTasks
{
#if DEBUG || BOOTSTRAP
/// <summary>
/// This task exists to help us validate our bootstrap building phase is executing correctly. It
/// is very easy for us, or MSBuild, to accidentally load DLLs from locations that we are
/// not expecting. This task takes steps to validate the bootstrap phase is executing as expected.
/// This task exists to help us validate our bootstrap building phase is executing correctly. The bootstrap
/// phase of CI is the best way to validate the integration of our components is functioning correctly. Items
/// which are difficult to validate in a unit test scenario.
/// </summary>
public sealed class ValidateBootstrap : Task
public sealed partial class ValidateBootstrap : Task
{
private static readonly ConcurrentDictionary<AssemblyName, byte> s_failedLoadSet = new ConcurrentDictionary<AssemblyName, byte>();
private static int s_failedServerConnectionCount = 0;
private string _bootstrapPath;
......@@ -69,6 +71,19 @@ public override bool Execute()
}
}
// The number chosen is arbitrary here. The goal of this check is to catch cases where a coding error has
// broken our ability to use the compiler server in the bootstrap phase.
//
// It's possible on completely correct code for the server connection to fail. There could be simply
// named pipe errors, CPU load causing timeouts, etc ... Hence flagging a single failure would produce
// a lot of false positives. The current value was chosen as a reasonable number for warranting an
// investigation.
if (s_failedServerConnectionCount > 20)
{
Log.LogError($"Too many compiler server connection failures detected: {s_failedServerConnectionCount}");
allGood = false;
}
return allGood;
}
......@@ -104,6 +119,28 @@ internal static void AddFailedLoad(AssemblyName name)
break;
}
}
internal static void AddFailedServerConnection()
{
Interlocked.Increment(ref s_failedServerConnectionCount);
}
}
#endif
internal static class ValidateBootstrapUtil
{
internal static void AddFailedLoad(AssemblyName name)
{
#if DEBUG || BOOTSTRAP
ValidateBootstrap.AddFailedLoad(name);
#endif
}
internal static void AddFailedServerConnection()
{
#if DEBUG || BOOTSTRAP
ValidateBootstrap.AddFailedServerConnection();
#endif
}
}
}
......@@ -882,7 +882,7 @@ internal override bool SupportsPrivateImplClass
#endregion
public override Cci.ITypeReference GetPlatformType(Cci.PlatformType platformType, EmitContext context)
public sealed override Cci.ITypeReference GetPlatformType(Cci.PlatformType platformType, EmitContext context)
{
Debug.Assert((object)this == context.Module);
......
......@@ -3655,16 +3655,8 @@ private void SerializeTypeReference(SignatureTypeEncoder encoder, ITypeReference
if (pointerTypeReference != null)
{
typeReference = pointerTypeReference.GetTargetType(Context);
if (module.IsPlatformType(typeReference, PlatformType.SystemVoid))
{
encoder.VoidPointer();
return;
}
else
{
encoder = encoder.Pointer();
continue;
}
encoder = encoder.Pointer();
continue;
}
IGenericTypeParameterReference genericTypeParameterReference = typeReference.AsGenericTypeParameterReference;
......@@ -3803,6 +3795,13 @@ private static void SerializePrimitiveType(SignatureTypeEncoder encoder, Primiti
encoder.String();
break;
case PrimitiveTypeCode.Void:
// "void" is handled specifically for "void*" with custom modifiers.
// If SignatureTypeEncoder supports such cases directly, this can
// be removed. See https://github.com/dotnet/corefx/issues/14571.
encoder.Builder.WriteByte((byte)System.Reflection.Metadata.PrimitiveTypeCode.Void);
break;
default:
throw ExceptionUtilities.UnexpectedValue(primitiveType);
}
......
......@@ -78,7 +78,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
End Get
End Property
Public Overrides ReadOnly Property GenerateVisualBasicStylePdb As Boolean
Public NotOverridable Overrides ReadOnly Property GenerateVisualBasicStylePdb As Boolean
Get
Return True
End Get
......@@ -122,7 +122,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
End Get
End Property
Protected Overrides Iterator Function GetAssemblyReferencesFromAddedModules(diagnostics As DiagnosticBag) As IEnumerable(Of Cci.IAssemblyReference)
Protected NotOverridable Overrides Iterator Function GetAssemblyReferencesFromAddedModules(diagnostics As DiagnosticBag) As IEnumerable(Of Cci.IAssemblyReference)
Dim modules As ImmutableArray(Of ModuleSymbol) = SourceModule.ContainingAssembly.Modules
For i As Integer = 1 To modules.Length - 1
......@@ -188,7 +188,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Return SourceModule.GetCustomAttributesToEmit(Me.CompilationState)
End Function
Public Overrides Function GetSymbolToLocationMap() As MultiDictionary(Of Cci.DebugSourceDocument, Cci.DefinitionWithLocation)
Public NotOverridable Overrides Function GetSymbolToLocationMap() As MultiDictionary(Of Cci.DebugSourceDocument, Cci.DefinitionWithLocation)
Dim result As New MultiDictionary(Of Cci.DebugSourceDocument, Cci.DefinitionWithLocation)()
Dim namespacesAndTypesToProcess As New Stack(Of NamespaceOrTypeSymbol)()
......@@ -330,7 +330,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Return False
End Function
Friend Overrides Function GetAnonymousTypes() As ImmutableArray(Of Cci.INamespaceTypeDefinition)
Friend NotOverridable Overrides Function GetAnonymousTypes() As ImmutableArray(Of Cci.INamespaceTypeDefinition)
If EmitOptions.EmitMetadataOnly Then
Return ImmutableArray(Of Cci.INamespaceTypeDefinition).Empty
End If
......@@ -379,7 +379,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Return ImmutableArray(Of NamedTypeSymbol).Empty
End Function
Public Overrides Function GetExportedTypes(diagnostics As DiagnosticBag) As ImmutableArray(Of Cci.ExportedType)
Public NotOverridable Overrides Function GetExportedTypes(diagnostics As DiagnosticBag) As ImmutableArray(Of Cci.ExportedType)
Debug.Assert(HaveDeterminedTopLevelTypes)
If _lazyExportedTypes.IsDefault Then
......@@ -598,11 +598,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Return typeSymbol
End Function
Public Overrides Function GetInitArrayHelper() As Cci.IMethodReference
Public NotOverridable Overrides Function GetInitArrayHelper() As Cci.IMethodReference
Return DirectCast(Compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__InitializeArrayArrayRuntimeFieldHandle), MethodSymbol)
End Function
Public Overrides Function IsPlatformType(typeRef As Cci.ITypeReference, platformType As Cci.PlatformType) As Boolean
Public NotOverridable Overrides Function IsPlatformType(typeRef As Cci.ITypeReference, platformType As Cci.PlatformType) As Boolean
Dim namedType = TryCast(typeRef, NamedTypeSymbol)
If namedType IsNot Nothing Then
......@@ -616,7 +616,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Return False
End Function
Protected Overrides Function GetCorLibraryReferenceToEmit(context As EmitContext) As Cci.IAssemblyReference
Protected NotOverridable Overrides Function GetCorLibraryReferenceToEmit(context As EmitContext) As Cci.IAssemblyReference
Dim corLib = CorLibrary
If Not corLib.IsMissing AndAlso
......@@ -643,7 +643,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Return _disableJITOptimization.ContainsKey(methodSymbol)
End Function
Protected Overrides Function CreatePrivateImplementationDetailsStaticConstructor(details As PrivateImplementationDetails, syntaxOpt As SyntaxNode, diagnostics As DiagnosticBag) As Cci.IMethodDefinition
Protected NotOverridable Overrides Function CreatePrivateImplementationDetailsStaticConstructor(details As PrivateImplementationDetails, syntaxOpt As SyntaxNode, diagnostics As DiagnosticBag) As Cci.IMethodDefinition
Return New SynthesizedPrivateImplementationDetailsSharedConstructor(SourceModule, details, GetUntranslatedSpecialType(SpecialType.System_Void, syntaxOpt, diagnostics))
End Function
End Class
......
......@@ -10,5 +10,7 @@ internal static class ContentTypeNames
public const string VisualBasicContentType = "Basic";
public const string VisualBasicSignatureHelpContentType = "Basic Signature Help";
public const string XamlContentType = "XAML";
public const string JavaScriptContentTypeName = "JavaScript";
public const string TypeScriptContentTypeName = "TypeScript";
}
}
......@@ -36,7 +36,10 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions
[Export(typeof(ISuggestedActionsSourceProvider))]
[Export(typeof(SuggestedActionsSourceProvider))]
[VisualStudio.Utilities.ContentType(ContentTypeNames.RoslynContentType)]
[VisualStudio.Utilities.ContentType(ContentTypeNames.CSharpContentType)]
[VisualStudio.Utilities.ContentType(ContentTypeNames.VisualBasicContentType)]
[VisualStudio.Utilities.ContentType(ContentTypeNames.JavaScriptContentTypeName)]
[VisualStudio.Utilities.ContentType(ContentTypeNames.TypeScriptContentTypeName)]
[VisualStudio.Utilities.ContentType(ContentTypeNames.XamlContentType)]
[VisualStudio.Utilities.Name("Roslyn Code Fix")]
[VisualStudio.Utilities.Order]
......
......@@ -66,7 +66,7 @@ public abstract partial class CommonTestBase : TestBase
}
internal CompilationVerifier CompileAndVerify(
string[] sources,
IEnumerable<string> sources,
IEnumerable<MetadataReference> additionalRefs = null,
IEnumerable<ModuleData> dependencies = null,
Action<IModuleSymbol> sourceSymbolValidator = null,
......
......@@ -193,6 +193,14 @@ public override AdjustSpacesOperation GetAdjustSpacesOperation(SyntaxToken previ
return CreateAdjustSpacesOperation(0, AdjustSpacesOption.ForceSpacesIfOnSingleLine);
}
// extension method on tuple type
// M(this (
if (currentToken.Kind() == SyntaxKind.OpenParenToken &&
previousToken.Kind() == SyntaxKind.ThisKeyword)
{
return CreateAdjustSpacesOperation(1, AdjustSpacesOption.ForceSpacesIfOnSingleLine);
}
// some * "(" cases
if (currentToken.Kind() == SyntaxKind.OpenParenToken)
{
......
......@@ -4463,6 +4463,22 @@ void bar()
await AssertFormatAsync(expectedCode, code);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.Formatting)]
public async Task SpacingInTupleExtension()
{
var code = @"static class Class5
{
static void Extension(this(int, string) self) { }
}";
var expectedCode = @"static class Class5
{
static void Extension(this (int, string) self) { }
}";
await AssertFormatAsync(expectedCode, code);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.Formatting)]
public async Task SpacingInNestedDeconstruction()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册