提交 bf2cd3bb 编写于 作者: T TomasMatousek

Implements misc CR feedback: naming, comments, moving code around, etc. (changeset 1393287)

上级 03e6a00e
......@@ -556,11 +556,11 @@
</Node>
<!--
BoundIteratorScope represents a scope within a translated iterator method.
BoundStateMachineScope represents a scope within a translated iterator/async method.
It is used to emit debugging information that allows the EE to map
fields to locals.
-->
<Node Name="BoundIteratorScope" Base="BoundStatement">
<Node Name="BoundStateMachineScope" Base="BoundStatement">
<Field Name="Fields" Type="ImmutableArray&lt;StateMachineFieldSymbol&gt;"/>
<Field Name="Statement" Type="BoundStatement" Null="disallow"/>
</Node>
......
......@@ -69,8 +69,8 @@ private void EmitStatement(BoundStatement statement)
EmitSwitchStatement((BoundSwitchStatement)statement);
break;
case BoundKind.IteratorScope:
EmitIteratorScope((BoundIteratorScope)statement);
case BoundKind.StateMachineScope:
EmitStateMachineScope((BoundStateMachineScope)statement);
break;
case BoundKind.NoOpStatement:
......@@ -598,16 +598,16 @@ private void EmitBlock(BoundBlock block)
}
}
private void EmitIteratorScope(BoundIteratorScope scope)
private void EmitStateMachineScope(BoundStateMachineScope scope)
{
builder.OpenIteratorScope();
builder.OpenStateMachineScope();
foreach (var field in scope.Fields)
{
builder.DefineUserDefinedStateMachineHoistedLocal(field.SlotIndex);
}
EmitStatement(scope.Statement);
builder.CloseIteratorScope();
builder.CloseStateMachineScope();
}
// There are two ways a value can be returned from a function:
......
......@@ -82,7 +82,7 @@ protected override void GenerateControlFields()
{
// the fields are initialized from async method, so they need to be public:
this.stateField = F.StateMachineField(F.SpecialType(SpecialType.System_Int32), GeneratedNames.MakeStateMachineStateName(), isPublic: true);
this.stateField = F.StateMachineField(F.SpecialType(SpecialType.System_Int32), GeneratedNames.MakeStateMachineStateFieldName(), isPublic: true);
this.builderField = F.StateMachineField(asyncMethodBuilderMemberCollection.BuilderType, GeneratedNames.AsyncBuilderFieldName(), isPublic: true);
}
......
......@@ -19,7 +19,7 @@ internal IteratorConstructor(IteratorStateMachine container)
{
var intType = container.DeclaringCompilation.GetSpecialType(SpecialType.System_Int32);
parameters = ImmutableArray.Create<ParameterSymbol>(
new SynthesizedParameterSymbol(this, intType, 0, RefKind.None, GeneratedNames.MakeStateMachineStateName()));
new SynthesizedParameterSymbol(this, intType, 0, RefKind.None, GeneratedNames.MakeStateMachineStateFieldName()));
}
internal override void AddSynthesizedAttributes(ModuleCompilationState compilationState, ref ArrayBuilder<SynthesizedAttributeData> attributes)
......
......@@ -84,7 +84,7 @@ protected override bool PreserveInitialParameterValues
protected override void GenerateControlFields()
{
this.stateField = F.StateMachineField(F.SpecialType(SpecialType.System_Int32), GeneratedNames.MakeStateMachineStateName());
this.stateField = F.StateMachineField(F.SpecialType(SpecialType.System_Int32), GeneratedNames.MakeStateMachineStateFieldName());
// Add a field: T current
currentField = F.StateMachineField(elementType, GeneratedNames.MakeIteratorCurrentBackingFieldName());
......@@ -97,7 +97,7 @@ protected override void GenerateControlFields()
(object)F.WellKnownMember(WellKnownMember.System_Environment__CurrentManagedThreadId, isOptional: true) != null);
initialThreadIdField = addInitialThreadId
? F.StateMachineField(F.SpecialType(SpecialType.System_Int32), GeneratedNames.MakeIteratorCurrentThreadIdName())
? F.StateMachineField(F.SpecialType(SpecialType.System_Int32), GeneratedNames.MakeIteratorCurrentThreadIdFieldName())
: null;
}
......
......@@ -49,7 +49,7 @@ private static string GetCapturedVariableFieldName(Symbol variable, ref int uniq
{
if (IsThis(variable))
{
return GeneratedNames.ThisProxyName();
return GeneratedNames.ThisProxyFieldName();
}
var local = variable as LocalSymbol;
......
......@@ -31,7 +31,7 @@ internal LambdaFrame(VariableSlotAllocator slotAllocatorOpt, TypeCompilationStat
if (isStatic)
{
this.staticConstructor = new SynthesizedStaticConstructor(this);
var cacheVariableName = GeneratedNames.MakeCachedFrameInstanceName();
var cacheVariableName = GeneratedNames.MakeCachedFrameInstanceFieldName();
singletonCache = new SynthesizedLambdaCacheFieldSymbol(this, this, cacheVariableName, topLevelMethod, isReadOnly: true, isStatic: true);
this.ScopeSyntaxOpt = null;
}
......
......@@ -94,20 +94,6 @@ public static OrderedSet<Symbol> Analyze(CSharpCompilation compilation, MethodSy
return variablesToHoist;
}
private static int GetVariableSourcePosition(Symbol symbol)
{
if (symbol.Locations.IsEmpty)
{
// All user-defined locals and long-lived synthesized variables have to have a position.
Debug.Assert(symbol is SynthesizedParameterSymbol || !((LocalSymbol)symbol).SynthesizedKind.IsLongLived());
// Short-lived locals don't get hoisted to fields, so their order doesn't matter.
return -1;
}
return symbol.Locations[0].SourceSpan.Start;
}
private static bool HoistInDebugBuild(Symbol symbol)
{
// in Debug build hoist all parameters that can be hoisted:
......@@ -177,11 +163,7 @@ public override BoundNode VisitYieldReturnStatement(BoundYieldReturnStatement no
protected override ImmutableArray<PendingBranch> Scan(ref bool badRegion)
{
variablesToHoist.Clear();
if (lazyDisallowedCaptures != null)
{
lazyDisallowedCaptures.Clear();
}
lazyDisallowedCaptures?.Clear();
return base.Scan(ref badRegion);
}
......
......@@ -322,7 +322,7 @@ private BoundStatement PossibleIteratorScope(ImmutableArray<LocalSymbol> locals,
// wrap the node in an iterator scope for debugging
if (hoistedLocalsWithDebugScopes.Count != 0)
{
translatedStatement = F.Block(new BoundIteratorScope(F.Syntax, hoistedLocalsWithDebugScopes.ToImmutable(), translatedStatement));
translatedStatement = F.Block(new BoundStateMachineScope(F.Syntax, hoistedLocalsWithDebugScopes.ToImmutable(), translatedStatement));
}
hoistedLocalsWithDebugScopes.Free();
......
......@@ -201,7 +201,7 @@ protected BoundStatement Rewrite()
if (parameter.IsThis)
{
var containingType = method.ContainingType;
var proxyField = F.StateMachineField(containingType, GeneratedNames.ThisProxyName(), isPublic: true);
var proxyField = F.StateMachineField(containingType, GeneratedNames.ThisProxyFieldName(), isPublic: true);
proxiesBuilder.Add(parameter, new CapturedToStateMachineFieldReplacement(proxyField, isReusable: false));
if (PreserveInitialParameterValues)
......@@ -221,7 +221,7 @@ protected BoundStatement Rewrite()
if (PreserveInitialParameterValues)
{
var field = F.StateMachineField(typeMap.SubstituteType(parameter.Type), GeneratedNames.StateMachineParameterProxyName(parameter.Name), isPublic: true);
var field = F.StateMachineField(typeMap.SubstituteType(parameter.Type), GeneratedNames.StateMachineParameterProxyFieldName(parameter.Name), isPublic: true);
initialParameters.Add(parameter, new CapturedToStateMachineFieldReplacement(field, isReusable: false));
}
}
......
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
internal enum GeneratedNameKind
......@@ -11,11 +7,11 @@ internal enum GeneratedNameKind
None = 0,
// Used by EE:
ThisProxy = '4',
ThisProxyField = '4',
HoistedLocalField = '5',
DisplayClassLocalOrField = '8',
LambdaMethod = 'b',
LambdaDisplayClassType = 'c',
LambdaDisplayClass = 'c',
StateMachineType = 'd',
// Used by EnC:
......@@ -23,60 +19,35 @@ internal enum GeneratedNameKind
HoistedSynthesizedLocalField = 's',
// Currently not parsed:
DynamicCallSiteContainer = 'o',
StateMachineStateField = '1',
IteratorCurrentBackingField = '2',
StateMachineParameterProxyField = '3',
ReusableHoistedLocalField = '7',
LambdaCacheField = '9',
FixedBufferField = 'e',
AutoPropertyBackingField = 'k',
IteratorCurrentThreadIdField = 'l',
IteratorFinallyMethod = 'm',
BaseMethodWrapper = 'n',
AsyncBuilderField = 't',
DynamicCallSiteContainerType = 'o',
DynamicCallSiteField = 'p',
}
internal static partial class GeneratedNames
internal static class GeneratedNameKindExtensions
{
// The type of generated name. See TryParseGeneratedName.
internal static GeneratedNameKind GetKind(string name)
internal static bool IsTypeName(this GeneratedNameKind kind)
{
GeneratedNameKind kind;
int openBracketOffset;
int closeBracketOffset;
return TryParseGeneratedName(name, out kind, out openBracketOffset, out closeBracketOffset) ? kind : GeneratedNameKind.None;
}
// Parse the generated name. Returns true for names of the form
// [CS$]<[middle]>c[__[suffix]] where [CS$] is included for certain
// generated names, where [middle] and [__[suffix]] are optional,
// and where c is a single character in [1-9a-z]
// (csharp\LanguageAnalysis\LIB\SpecialName.cpp).
internal static bool TryParseGeneratedName(
string name,
out GeneratedNameKind kind,
out int openBracketOffset,
out int closeBracketOffset)
switch (kind)
{
openBracketOffset = -1;
if (name.StartsWith("CS$<", StringComparison.Ordinal))
{
openBracketOffset = 3;
}
else if (name.StartsWith("<", StringComparison.Ordinal))
{
openBracketOffset = 0;
}
if (openBracketOffset >= 0)
{
closeBracketOffset = name.IndexOfBalancedParenthesis(openBracketOffset, '>');
if (closeBracketOffset >= 0 && closeBracketOffset + 1 < name.Length)
{
int c = name[closeBracketOffset + 1];
if ((c >= '1' && c <= '9') || (c >= 'a' && c <= 'z')) // Note '0' is not special.
{
kind = (GeneratedNameKind)c;
case GeneratedNameKind.LambdaDisplayClass:
case GeneratedNameKind.StateMachineType:
case GeneratedNameKind.DynamicCallSiteContainerType:
return true;
}
}
}
kind = GeneratedNameKind.None;
openBracketOffset = -1;
closeBracketOffset = -1;
default:
return false;
}
}
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
......@@ -20,14 +17,6 @@ internal static partial class GeneratedNames
private const char IdSeparator = '_';
private const char GenerationSeparator = '#';
private static readonly ImmutableArray<string> numericStrings = ImmutableArray.Create("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
private static string GetString(int number)
{
Debug.Assert(number >= 0);
return (number < numericStrings.Length) ? numericStrings[number] : number.ToString();
}
internal static bool IsGeneratedMemberName(string memberName)
{
return memberName.Length > 0 && memberName[0] == '<';
......@@ -35,6 +24,7 @@ internal static bool IsGeneratedMemberName(string memberName)
internal static string MakeBackingFieldName(string propertyName)
{
Debug.Assert((char)GeneratedNameKind.AutoPropertyBackingField == 'k');
return "<" + propertyName + ">k__BackingField";
}
......@@ -46,12 +36,13 @@ internal static string MakeIteratorFinallyMethodName(int iteratorState)
// <>m__Finally3
// . . .
// that will roughly match native naming scheme and may also be easier when need to debug.
return "<>m__Finally" + GetString(Math.Abs(iteratorState + 2));
Debug.Assert((char)GeneratedNameKind.IteratorFinallyMethod == 'm');
return "<>m__Finally" + StringExtensions.GetNumeral(Math.Abs(iteratorState + 2));
}
internal static string MakeStaticLambdaDisplayClassName(int methodOrdinal, int generation)
{
return MakeMethodScopedSynthesizedName(GeneratedNameKind.LambdaDisplayClassType, methodOrdinal, generation);
return MakeMethodScopedSynthesizedName(GeneratedNameKind.LambdaDisplayClass, methodOrdinal, generation);
}
internal static string MakeLambdaDisplayClassName(int methodOrdinal, int generation, int scopeOrdinal)
......@@ -60,15 +51,15 @@ internal static string MakeLambdaDisplayClassName(int methodOrdinal, int generat
Debug.Assert(scopeOrdinal >= -1);
Debug.Assert(methodOrdinal >= 0);
return MakeMethodScopedSynthesizedName(GeneratedNameKind.LambdaDisplayClassType, methodOrdinal, generation, suffix: "DisplayClass", uniqueId: scopeOrdinal, isTypeName: true);
return MakeMethodScopedSynthesizedName(GeneratedNameKind.LambdaDisplayClass, methodOrdinal, generation, suffix: "DisplayClass", uniqueId: scopeOrdinal, isTypeName: true);
}
internal static string MakeAnonymousTypeTemplateName(int index, int submissionSlotIndex, string moduleId)
{
var name = "<" + moduleId + ">f__AnonymousType" + GetString(index);
var name = "<" + moduleId + ">f__AnonymousType" + StringExtensions.GetNumeral(index);
if (submissionSlotIndex >= 0)
{
name += "#" + GetString(submissionSlotIndex);
name += "#" + StringExtensions.GetNumeral(submissionSlotIndex);
}
return name;
......@@ -125,7 +116,8 @@ internal static string MakeStateMachineTypeName(string methodName, int methodOrd
internal static string MakeBaseMethodWrapperName(int uniqueId)
{
return "<>n__" + GetString(uniqueId);
Debug.Assert((char)GeneratedNameKind.BaseMethodWrapper == 'n');
return "<>n__" + StringExtensions.GetNumeral(uniqueId);
}
internal static string MakeLambdaMethodName(string methodName, int methodOrdinal, int generation, int lambdaOrdinal)
......@@ -168,7 +160,7 @@ private static string MakeMethodScopedSynthesizedName(GeneratedNameKind kind, in
// consumer cannot figure where namespace ends and actual type name starts.
// Therefore it is a good practice to avoid type names with dots.
// As a replacement use a character not allowed in C# identifier to avoid conflicts.
if (isTypeName)
if (kind.IsTypeName())
{
builder.Replace('.', DotReplacementInTypeNames);
}
......@@ -241,7 +233,7 @@ internal static string MakeHoistedLocalFieldName(SynthesizedLocalKind kind, int
}
else
{
builder.Append('s');
builder.Append((char)GeneratedNameKind.HoistedSynthesizedLocalField);
}
builder.Append("__");
......@@ -250,9 +242,87 @@ internal static string MakeHoistedLocalFieldName(SynthesizedLocalKind kind, int
return result.ToStringAndFree();
}
// The type of generated name. See TryParseGeneratedName.
internal static GeneratedNameKind GetKind(string name)
{
GeneratedNameKind kind;
int openBracketOffset;
int closeBracketOffset;
return TryParseGeneratedName(name, out kind, out openBracketOffset, out closeBracketOffset) ? kind : GeneratedNameKind.None;
}
// Parse the generated name. Returns true for names of the form
// [CS$]<[middle]>c[__[suffix]] where [CS$] is included for certain
// generated names, where [middle] and [__[suffix]] are optional,
// and where c is a single character in [1-9a-z]
// (csharp\LanguageAnalysis\LIB\SpecialName.cpp).
internal static bool TryParseGeneratedName(
string name,
out GeneratedNameKind kind,
out int openBracketOffset,
out int closeBracketOffset)
{
openBracketOffset = -1;
if (name.StartsWith("CS$<", StringComparison.Ordinal))
{
openBracketOffset = 3;
}
else if (name.StartsWith("<", StringComparison.Ordinal))
{
openBracketOffset = 0;
}
if (openBracketOffset >= 0)
{
closeBracketOffset = name.IndexOfBalancedParenthesis(openBracketOffset, '>');
if (closeBracketOffset >= 0 && closeBracketOffset + 1 < name.Length)
{
int c = name[closeBracketOffset + 1];
if ((c >= '1' && c <= '9') || (c >= 'a' && c <= 'z')) // Note '0' is not special.
{
kind = (GeneratedNameKind)c;
return true;
}
}
}
kind = GeneratedNameKind.None;
openBracketOffset = -1;
closeBracketOffset = -1;
return false;
}
internal static bool TryParseSourceMethodNameFromGeneratedName(string generatedName, GeneratedNameKind requiredKind, out string methodName)
{
int openBracketOffset;
int closeBracketOffset;
GeneratedNameKind kind;
if (!TryParseGeneratedName(generatedName, out kind, out openBracketOffset, out closeBracketOffset))
{
methodName = null;
return false;
}
if (requiredKind != 0 && kind != requiredKind)
{
methodName = null;
return false;
}
methodName = generatedName.Substring(openBracketOffset + 1, closeBracketOffset - openBracketOffset - 1);
if (kind.IsTypeName())
{
methodName = methodName.Replace(DotReplacementInTypeNames, '.');
}
return true;
}
internal static string AsyncAwaiterFieldName(int slotIndex)
{
return "<>u__" + GetString(slotIndex + 1);
Debug.Assert((char)GeneratedNameKind.AwaiterField == 'u');
return "<>u__" + StringExtensions.GetNumeral(slotIndex + 1);
}
// Extracts the slot index from a name of a field that stores hoisted variables or awaiters.
......@@ -277,8 +347,9 @@ internal static bool TryParseSlotIndex(string fieldName, out int slotIndex)
return false;
}
internal static string MakeCachedFrameInstanceName()
internal static string MakeCachedFrameInstanceFieldName()
{
Debug.Assert((char)GeneratedNameKind.LambdaCacheField == '9');
return "<>9";
}
......@@ -298,7 +369,7 @@ internal static string MakeSynthesizedLocalName(SynthesizedLocalKind kind, ref i
internal static string MakeLambdaDisplayLocalName(int uniqueId)
{
Debug.Assert((char)GeneratedNameKind.DisplayClassLocalOrField == '8');
return SynthesizedLocalNamePrefix + "<>8__locals" + GetString(uniqueId);
return SynthesizedLocalNamePrefix + "<>8__locals" + StringExtensions.GetNumeral(uniqueId);
}
internal static bool IsSynthesizedLocalName(string name)
......@@ -309,94 +380,68 @@ internal static bool IsSynthesizedLocalName(string name)
internal static string MakeFixedFieldImplementationName(string fieldName)
{
// the native compiler adds numeric digits at the end. Roslyn does not.
Debug.Assert((char)GeneratedNameKind.FixedBufferField == 'e');
return "<" + fieldName + ">e__FixedBuffer";
}
internal static string MakeStateMachineStateName()
internal static string MakeStateMachineStateFieldName()
{
// Microsoft.VisualStudio.VIL.VisualStudioHost.AsyncReturnStackFrame depends on this name.
Debug.Assert((char)GeneratedNameKind.StateMachineStateField == '1');
return "<>1__state";
}
internal static bool TryParseIteratorName(string mangledTypeName, out string iteratorName)
{
GeneratedNameKind kind;
int openBracketOffset;
int closeBracketOffset;
if (TryParseGeneratedName(mangledTypeName, out kind, out openBracketOffset, out closeBracketOffset) &&
(kind == GeneratedNameKind.StateMachineType) &&
(openBracketOffset == 0))
{
iteratorName = mangledTypeName.Substring(openBracketOffset + 1, closeBracketOffset - openBracketOffset - 1);
return true;
}
iteratorName = null;
return false;
}
internal static bool TryParseLambdaMethodName(string mangledTypeName, out string containingMethodName)
{
GeneratedNameKind kind;
int openBracketOffset;
int closeBracketOffset;
if (TryParseGeneratedName(mangledTypeName, out kind, out openBracketOffset, out closeBracketOffset) &&
(kind == GeneratedNameKind.LambdaMethod) &&
(openBracketOffset == 0))
{
containingMethodName = mangledTypeName.Substring(openBracketOffset + 1, closeBracketOffset - openBracketOffset - 1);
return true;
}
containingMethodName = null;
return false;
}
internal static string MakeIteratorCurrentBackingFieldName()
{
Debug.Assert((char)GeneratedNameKind.IteratorCurrentBackingField == '2');
return "<>2__current";
}
internal static string MakeIteratorCurrentThreadIdName()
internal static string MakeIteratorCurrentThreadIdFieldName()
{
Debug.Assert((char)GeneratedNameKind.IteratorCurrentThreadIdField == 'l');
return "<>l__initialThreadId";
}
internal static string ThisProxyName()
internal static string ThisProxyFieldName()
{
Debug.Assert((char)GeneratedNameKind.ThisProxy == '4');
Debug.Assert((char)GeneratedNameKind.ThisProxyField == '4');
return "<>4__this";
}
internal static string StateMachineThisParameterProxyName()
{
return StateMachineParameterProxyName(ThisProxyName());
return StateMachineParameterProxyFieldName(ThisProxyFieldName());
}
internal static string StateMachineParameterProxyName(string parameterName)
internal static string StateMachineParameterProxyFieldName(string parameterName)
{
Debug.Assert((char)GeneratedNameKind.StateMachineParameterProxyField == '3');
return "<>3__" + parameterName;
}
internal static string MakeDynamicCallSiteContainerName(int methodOrdinal, int generation)
{
return MakeMethodScopedSynthesizedName(GeneratedNameKind.DynamicCallSiteContainer, methodOrdinal, generation, isTypeName: true);
return MakeMethodScopedSynthesizedName(GeneratedNameKind.DynamicCallSiteContainerType, methodOrdinal, generation, isTypeName: true);
}
internal static string MakeDynamicCallSiteFieldName(int uniqueId)
{
return "<>p__" + GetString(uniqueId);
Debug.Assert((char)GeneratedNameKind.DynamicCallSiteField == 'p');
return "<>p__" + StringExtensions.GetNumeral(uniqueId);
}
internal static string AsyncBuilderFieldName()
{
// Microsoft.VisualStudio.VIL.VisualStudioHost.AsyncReturnStackFrame depends on this name.
Debug.Assert((char)GeneratedNameKind.AsyncBuilderField == 't');
return "<>t__builder";
}
internal static string ReusableHoistedLocalFieldName(int number)
{
return "<>7__wrap" + GetString(number);
Debug.Assert((char)GeneratedNameKind.ReusableHoistedLocalField == '7');
return "<>7__wrap" + StringExtensions.GetNumeral(number);
}
}
}
......@@ -26,6 +26,7 @@
<Compile Include="Diagnostics\DiagnosticLocalizationTests.cs" />
<Compile Include="Emit\EmitOptionsTests.cs" />
<Compile Include="Emit\CustomDebugInfoReaderTests.cs" />
<Compile Include="InternalUtilities\StringExtensionsTests.cs" />
<Compile Include="PEWriter\BinaryWriterTests.cs" />
<Compile Include="XmlDocumentationCommentTextReaderTests.cs" />
</ItemGroup>
......
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace Roslyn.Utilities.UnitTests.InternalUtilities
......
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Xunit;
namespace Roslyn.Utilities.UnitTests.InternalUtilities
{
public class StringExtensionsTests
{
[Fact]
public void GetNumeral1()
{
Assert.Equal("0", StringExtensions.GetNumeral(0));
Assert.Equal("5", StringExtensions.GetNumeral(5));
Assert.Equal("10", StringExtensions.GetNumeral(10));
Assert.Equal("10000000", StringExtensions.GetNumeral(10000000));
}
}
}
......@@ -1133,7 +1133,7 @@ internal void OpenLocalScope(ScopeType scopeType = ScopeType.Variable, Microsoft
break;
case ScopeType.Variable:
case ScopeType.TryCatchFinally:
case ScopeType.IteratorVariable:
case ScopeType.StateMachineVariable:
break;
default:
throw ExceptionUtilities.UnexpectedValue(scopeType);
......@@ -1166,9 +1166,9 @@ internal void CloseLocalScope()
scopeManager.CloseScope(this);
}
internal void OpenIteratorScope()
internal void OpenStateMachineScope()
{
OpenLocalScope(ScopeType.IteratorVariable);
OpenLocalScope(ScopeType.StateMachineVariable);
}
internal void DefineUserDefinedStateMachineHoistedLocal(int slotIndex)
......@@ -1178,7 +1178,7 @@ internal void DefineUserDefinedStateMachineHoistedLocal(int slotIndex)
scopeManager.AddUserHoistedLocal(slotIndex);
}
internal void CloseIteratorScope()
internal void CloseStateMachineScope()
{
scopeManager.ClosingScope(this);
EndBlock(); // blocks should not cross scope boundaries.
......
......@@ -224,7 +224,7 @@ internal abstract class ScopeInfo
}
else
{
Debug.Assert(scopeType == ScopeType.Variable || scopeType == ScopeType.IteratorVariable);
Debug.Assert(scopeType == ScopeType.Variable || scopeType == ScopeType.StateMachineVariable);
return new LocalScopeInfo();
}
}
......
......@@ -11,6 +11,10 @@ internal enum ScopeType
Filter,
Finally,
Fault,
IteratorVariable,
/// <summary>
/// Scope of user-defined variable hoisted to state machine.
/// </summary>
StateMachineVariable,
}
}
......@@ -2,13 +2,28 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
namespace Roslyn.Utilities
{
internal static class StringExtensions
{
private static ImmutableArray<string> lazyNumerals;
internal static string GetNumeral(int number)
{
var numerals = lazyNumerals;
if (numerals.IsDefault)
{
numerals = ImmutableArray.Create("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
ImmutableInterlocked.InterlockedInitialize(ref lazyNumerals, numerals);
}
Debug.Assert(number >= 0);
return (number < numerals.Length) ? numerals[number] : number.ToString();
}
public static string Join(this IEnumerable<string> source, string separator)
{
if (source == null)
......
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Threading;
namespace Roslyn.Utilities
......
......@@ -252,7 +252,13 @@ internal unsafe void WriteUlong(ulong value)
}
}
public void WriteReference(uint reference, int size)
/// <summary>
/// Writes a reference to a heap (heap index) or a table (row id).
/// </summary>
/// <remarks>
/// References may be small (2B) or large (4B).
/// </remarks>
internal void WriteReference(uint reference, int size)
{
Debug.Assert(size == 2 || size == 4);
......

// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
......
......@@ -81,6 +81,9 @@ internal sealed class MetadataSizes
int resourceDataSize,
bool isMinimalDelta)
{
Debug.Assert(rowCounts.Length == MetadataTokens.TableCount);
Debug.Assert(heapSizes.Length == MetadataTokens.HeapCount);
const byte large = 4;
const byte small = 2;
......
......@@ -35,13 +35,7 @@ internal struct SequencePoint
Document = document;
}
public bool IsHidden
{
get
{
return StartLine == 0xfeefee;
}
}
public bool IsHidden => StartLine == 0xfeefee;
public override int GetHashCode()
{
......
......@@ -1055,7 +1055,7 @@ private void WriteUserStrings()
}
// TODO: the heap is aligned, don't display the trailing empty strings
writer.WriteLine(string.Format("#US (size = {0}):", size));
writer.WriteLine($"#US (size = {size}):");
var handle = MetadataTokens.UserStringHandle(0);
do
{
......@@ -1076,7 +1076,7 @@ private void WriteStrings()
return;
}
writer.WriteLine(string.Format("#String (size = {0}):", size));
writer.WriteLine($"#String (size = {size}):");
var handle = MetadataTokens.StringHandle(0);
do
{
......@@ -1099,7 +1099,7 @@ private void WriteBlobs()
int[] sizePerKind = new int[(int)BlobKind.Count];
writer.WriteLine(string.Format("#Blob (size = {0}):", size));
writer.WriteLine($"#Blob (size = {size}):");
var handle = MetadataTokens.BlobHandle(0);
do
{
......
......@@ -11,10 +11,6 @@ namespace Microsoft.CodeAnalysis.Differencing
/// </summary>
internal abstract class LongestCommonImmutableArraySubsequence<TElement> : LongestCommonSubsequence<ImmutableArray<TElement>>
{
protected LongestCommonImmutableArraySubsequence()
{
}
protected abstract bool Equals(TElement oldElement, TElement newElement);
protected sealed override bool ItemsEqual(ImmutableArray<TElement> oldSequence, int oldIndex, ImmutableArray<TElement> newSequence, int newIndex)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册