protected override ImmutableArray <LocalFunctionSymbol> BuildLocalFunctions() { ArrayBuilder <LocalFunctionSymbol> locals = null; BuildLocalFunctions(_statement, ref locals); return(locals?.ToImmutableAndFree() ?? ImmutableArray <LocalFunctionSymbol> .Empty); }
public SourceAssemblySymbol( PhpCompilation compilation, string assemblySimpleName, string moduleName) { Debug.Assert(compilation != null); Debug.Assert(!String.IsNullOrWhiteSpace(assemblySimpleName)); Debug.Assert(!String.IsNullOrWhiteSpace(moduleName)); _compilation = compilation; _simpleName = assemblySimpleName; var moduleBuilder = new ArrayBuilder<ModuleSymbol>(1); moduleBuilder.Add(new SourceModuleSymbol(this, compilation.SourceSymbolTables, moduleName)); //var importOptions = (compilation.Options.MetadataImportOptions == MetadataImportOptions.All) ? // MetadataImportOptions.All : MetadataImportOptions.Internal; //foreach (PEModule netModule in netModules) //{ // moduleBuilder.Add(new PEModuleSymbol(this, netModule, importOptions, moduleBuilder.Count)); // // SetReferences will be called later by the ReferenceManager (in CreateSourceAssemblyFullBind for // // a fresh manager, in CreateSourceAssemblyReuseData for a reused one). //} _modules = moduleBuilder.ToImmutableAndFree(); }
protected override ImmutableArray <LabelSymbol> BuildLabels() { ArrayBuilder <LabelSymbol> labels = null; var containingMethod = (MethodSymbol)this.ContainingMemberOrLambda; BuildLabels(containingMethod, _statement, ref labels); return(labels?.ToImmutableAndFree() ?? ImmutableArray <LabelSymbol> .Empty); }
protected ImmutableArray <LocalFunctionSymbol> BuildLocalFunctions(SyntaxList <StatementSyntax> statements) { ArrayBuilder <LocalFunctionSymbol> locals = null; foreach (var statement in statements) { BuildLocalFunctions(statement, ref locals); } return(locals?.ToImmutableAndFree() ?? ImmutableArray <LocalFunctionSymbol> .Empty); }
protected ImmutableArray <LocalSymbol> BuildLocals(SyntaxList <StatementSyntax> statements) { ArrayBuilder <LocalSymbol> locals = null; foreach (var statement in statements) { var innerStatement = statement; // drill into any LabeledStatements -- atomic LabelStatements have been bound into // wrapped LabeledStatements by this point while (innerStatement.Kind() == SyntaxKind.LabeledStatement) { innerStatement = ((LabeledStatementSyntax)innerStatement).Statement; } switch (innerStatement.Kind()) { case SyntaxKind.LocalDeclarationStatement: { var decl = (LocalDeclarationStatementSyntax)innerStatement; if (locals == null) { locals = ArrayBuilder <LocalSymbol> .GetInstance(); } if (!decl.Declaration.IsDeconstructionDeclaration) { RefKind refKind = decl.RefKeyword.Kind().GetRefKind(); LocalDeclarationKind kind = decl.IsConst ? LocalDeclarationKind.Constant : LocalDeclarationKind.RegularVariable; foreach (var vdecl in decl.Declaration.Variables) { var localSymbol = MakeLocal(refKind, decl.Declaration, vdecl, kind); locals.Add(localSymbol); } } else { CollectLocalsFromDeconstruction(decl.Declaration, decl.Declaration.Type, LocalDeclarationKind.RegularVariable, locals); } } break; default: // no other statement introduces local variables into the enclosing scope break; } } return(locals?.ToImmutableAndFree() ?? ImmutableArray <LocalSymbol> .Empty); }
protected override ImmutableArray <LabelSymbol> BuildLabels() { ArrayBuilder <LabelSymbol>?labels = null; foreach (var statement in _entryPoint.CompilationUnit.Members) { if (statement is GlobalStatementSyntax topLevelStatement) { BuildLabels(_entryPoint, topLevelStatement.Statement, ref labels); } } return(labels?.ToImmutableAndFree() ?? ImmutableArray <LabelSymbol> .Empty); }
private ImmutableArray <BoundExpression> EvaluateSideEffectingArgumentsToTemps( ImmutableArray <BoundExpression> args, ArrayBuilder <BoundExpression> sideeffects, ref ArrayBuilder <LocalSymbol> temps) { ArrayBuilder <BoundExpression> newArgs = null; for (int i = 0; i < args.Length; i++) { var arg = args[i]; if (CanChangeValueBetweenReads(arg)) { if (newArgs == null) { newArgs = ArrayBuilder <BoundExpression> .GetInstance(args.Length); newArgs.AddRange(args, i); } BoundAssignmentOperator store; var temp = _factory.StoreToTemp(arg, out store); newArgs.Add(temp); if (temps == null) { temps = ArrayBuilder <LocalSymbol> .GetInstance(); } temps.Add(temp.LocalSymbol); sideeffects.Add(store); } else if (newArgs != null) { newArgs.Add(arg); } } return(newArgs? .ToImmutableAndFree() ?? args); }
internal static ImmutableArray <BoundStatement> ConstructNullCheckedStatementList( ImmutableArray <ParameterSymbol> parameters, SyntheticBoundNodeFactory factory) { ArrayBuilder <BoundStatement>?statementList = null; MethodSymbol?throwIfNullMethod = null; foreach (ParameterSymbol param in parameters) { if (param.IsNullChecked) { var isNullCheckableValueType = param.Type.IsNullableTypeOrTypeParameter() || param.Type.IsPointerOrFunctionPointer(); Debug.Assert(!param.Type.IsValueType || isNullCheckableValueType); statementList ??= ArrayBuilder <BoundStatement> .GetInstance(); var constructedIf = isNullCheckableValueType ? ConstructDirectNullCheck(param, factory) : ConstructNullCheckHelperCall(param, ref throwIfNullMethod, factory); statementList.Add(constructedIf); } } return(statementList?.ToImmutableAndFree() ?? ImmutableArray <BoundStatement> .Empty); }
public override BoundNode VisitFromEndIndexExpression(BoundFromEndIndexExpression node) { Debug.Assert(node.MethodOpt != null); NamedTypeSymbol booleanType = _compilation.GetSpecialType(SpecialType.System_Boolean); BoundExpression fromEnd = MakeLiteral(node.Syntax, ConstantValue.Create(true), booleanType); BoundExpression operand = VisitExpression(node.Operand); if (NullableNeverHasValue(operand)) { operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType()); } operand = NullableAlwaysHasValue(operand) ?? operand; if (!node.Type.IsNullableType()) { return(new BoundObjectCreationExpression(node.Syntax, node.MethodOpt, binderOpt: null, operand, fromEnd)); } ArrayBuilder <BoundExpression> sideeffects = ArrayBuilder <BoundExpression> .GetInstance(); ArrayBuilder <LocalSymbol> locals = ArrayBuilder <LocalSymbol> .GetInstance(); // operand.HasValue operand = CaptureExpressionInTempIfNeeded(operand, sideeffects, locals); BoundExpression condition = MakeOptimizedHasValue(operand.Syntax, operand); // new Index(operand, fromEnd: true) BoundExpression boundOperandGetValueOrDefault = MakeOptimizedGetValueOrDefault(operand.Syntax, operand); BoundExpression indexCreation = new BoundObjectCreationExpression(node.Syntax, node.MethodOpt, binderOpt: null, boundOperandGetValueOrDefault, fromEnd); if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor)) { return(BadExpression(node.Syntax, node.Type, operand)); } // new Nullable(new Index(operand, fromEnd: true)) BoundExpression consequence = new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, indexCreation); // default BoundExpression alternative = new BoundDefaultExpression(node.Syntax, node.Type); // operand.HasValue ? new Nullable(new Index(operand, fromEnd: true)) : default BoundExpression conditionalExpression = RewriteConditionalOperator( syntax: node.Syntax, rewrittenCondition: condition, rewrittenConsequence: consequence, rewrittenAlternative: alternative, constantValueOpt: null, rewrittenType: node.Type, isRef: false); return(new BoundSequence( syntax: node.Syntax, locals: locals.ToImmutableAndFree(), sideEffects: sideeffects.ToImmutableAndFree(), value: conditionalExpression, type: node.Type)); }
private BoundNode RewriteWithRefOperand( bool isPrefix, bool isChecked, ArrayBuilder<LocalSymbol> tempSymbols, ArrayBuilder<BoundExpression> tempInitializers, CSharpSyntaxNode syntax, BoundExpression operand, TypeSymbol operandType, BoundExpression boundTemp, BoundExpression newValue) { var tempValue = isPrefix ? newValue : MakeRValue(operand); var tempAssignment = MakeAssignmentOperator(syntax, boundTemp, tempValue, operandType, used: false, isChecked: isChecked, isCompoundAssignment: false); var operandValue = isPrefix ? boundTemp : newValue; var tempAssignedAndOperandValue = new BoundSequence( syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray.Create<BoundExpression>(tempAssignment), operandValue, tempValue.Type); // prefix: operand = Seq{temp = (T)(operand + 1); temp;} // postfix: operand = Seq{temp = operand; ; (T)(temp + 1);} BoundExpression operandAssignment = MakeAssignmentOperator(syntax, operand, tempAssignedAndOperandValue, operandType, used: false, isChecked: isChecked, isCompoundAssignment: false); // prefix: Seq{operand initializers; operand = Seq{temp = (T)(operand + 1); temp;} result: temp} // postfix: Seq{operand initializers; operand = Seq{temp = operand; ; (T)(temp + 1);} result: temp} tempInitializers.Add(operandAssignment); return new BoundSequence( syntax: syntax, locals: tempSymbols.ToImmutableAndFree(), sideEffects: tempInitializers.ToImmutableAndFree(), value: boundTemp, type: operandType); }
public sealed override ImmutableArray <CSharpAttributeData> GetAttributes() { if (_attributes.IsDefault) { Debug.Assert(base.GetAttributes().Length == 0); ArrayBuilder <CSharpAttributeData> builder = null; // Inherit some attributes from the container of the kickoff method var kickoffType = KickoffMethod.ContainingType; foreach (var attribute in kickoffType.GetAttributes()) { if (attribute.IsTargetAttribute(kickoffType, AttributeDescription.DebuggerNonUserCodeAttribute) || attribute.IsTargetAttribute(kickoffType, AttributeDescription.DebuggerStepThroughAttribute)) { if (builder == null) { builder = ArrayBuilder <CSharpAttributeData> .GetInstance(2); // only 2 different attributes are inherited at the moment } builder.Add(attribute); } } ImmutableInterlocked.InterlockedCompareExchange(ref _attributes, builder == null ? ImmutableArray <CSharpAttributeData> .Empty : builder.ToImmutableAndFree(), default(ImmutableArray <CSharpAttributeData>)); } return(_attributes); }
private static void AppendAllLoadedSyntaxTrees( ArrayBuilder <SyntaxTree> treesBuilder, SyntaxTree tree, string scriptClassName, SourceReferenceResolver resolver, CommonMessageProvider messageProvider, bool isSubmission, IDictionary <SyntaxTree, int> ordinalMapBuilder, IDictionary <SyntaxTree, ImmutableArray <LoadDirective> > loadDirectiveMapBuilder, IDictionary <string, SyntaxTree> loadedSyntaxTreeMapBuilder, IDictionary <SyntaxTree, Lazy <RootSingleNamespaceDeclaration> > declMapBuilder, ref DeclarationTable declTable) { ArrayBuilder <LoadDirective> loadDirectives = null; foreach (var directive in tree.GetCompilationUnitRoot().GetLoadDirectives()) { var fileToken = directive.File; var path = (string)fileToken.Value; if (path == null) { // If there is no path, the parser should have some Diagnostics to report (if we're in an active region). Debug.Assert(!directive.IsActive || tree.GetDiagnostics().Any(d => d.Severity == DiagnosticSeverity.Error)); continue; } var diagnostics = DiagnosticBag.GetInstance(); string resolvedFilePath = null; if (resolver == null) { diagnostics.Add( messageProvider.CreateDiagnostic( (int)ErrorCode.ERR_SourceFileReferencesNotSupported, directive.Location)); } else { resolvedFilePath = resolver.ResolveReference(path, baseFilePath: tree.FilePath); if (resolvedFilePath == null) { diagnostics.Add( messageProvider.CreateDiagnostic( (int)ErrorCode.ERR_NoSourceFile, fileToken.GetLocation(), path, CSharpResources.CouldNotFindFile)); } else if (!loadedSyntaxTreeMapBuilder.ContainsKey(resolvedFilePath)) { try { var code = resolver.ReadText(resolvedFilePath); var loadedTree = SyntaxFactory.ParseSyntaxTree( code, tree.Options, // Use ParseOptions propagated from "external" tree. resolvedFilePath); // All #load'ed trees should have unique path information. loadedSyntaxTreeMapBuilder.Add(loadedTree.FilePath, loadedTree); AppendAllSyntaxTrees( treesBuilder, loadedTree, scriptClassName, resolver, messageProvider, isSubmission, ordinalMapBuilder, loadDirectiveMapBuilder, loadedSyntaxTreeMapBuilder, declMapBuilder, ref declTable); } catch (Exception e) { diagnostics.Add( CommonCompiler.ToFileReadDiagnostics(messageProvider, e, resolvedFilePath), fileToken.GetLocation()); } } else { // The path resolved, but we've seen this file before, // so don't attempt to load it again. Debug.Assert(diagnostics.IsEmptyWithoutResolution); } } if (loadDirectives == null) { loadDirectives = ArrayBuilder <LoadDirective> .GetInstance(); } loadDirectives.Add(new LoadDirective(resolvedFilePath, diagnostics.ToReadOnlyAndFree())); } if (loadDirectives != null) { loadDirectiveMapBuilder.Add(tree, loadDirectives.ToImmutableAndFree()); } }
private (TypeParameterConstraintClause, ArrayBuilder <TypeConstraintSyntax>?) BindTypeParameterConstraints(TypeParameterSyntax typeParameterSyntax, TypeParameterConstraintClauseSyntax constraintClauseSyntax, bool isForOverride, DiagnosticBag diagnostics) { var constraints = TypeParameterConstraintKind.None; ArrayBuilder <TypeWithAnnotations>? constraintTypes = null; ArrayBuilder <TypeConstraintSyntax>?syntaxBuilder = null; SeparatedSyntaxList <TypeParameterConstraintSyntax> constraintsSyntax = constraintClauseSyntax.Constraints; Debug.Assert(!InExecutableBinder); // Cannot eagerly report diagnostics handled by LazyMissingNonNullTypesContextDiagnosticInfo bool hasTypeLikeConstraint = false; bool reportedOverrideWithConstraints = false; for (int i = 0, n = constraintsSyntax.Count; i < n; i++) { var syntax = constraintsSyntax[i]; switch (syntax.Kind()) { case SyntaxKind.ClassConstraint: hasTypeLikeConstraint = true; if (i != 0) { diagnostics.Add(ErrorCode.ERR_RefValBoundMustBeFirst, syntax.GetFirstToken().GetLocation()); if (isForOverride && (constraints & (TypeParameterConstraintKind.ValueType | TypeParameterConstraintKind.ReferenceType)) != 0) { continue; } } var constraintSyntax = (ClassOrStructConstraintSyntax)syntax; SyntaxToken questionToken = constraintSyntax.QuestionToken; if (questionToken.IsKind(SyntaxKind.QuestionToken)) { constraints |= TypeParameterConstraintKind.NullableReferenceType; if (isForOverride) { reportOverrideWithConstraints(ref reportedOverrideWithConstraints, syntax, diagnostics); } else { LazyMissingNonNullTypesContextDiagnosticInfo.ReportNullableReferenceTypesIfNeeded(AreNullableAnnotationsEnabled(questionToken), questionToken.GetLocation(), diagnostics); } } else if (isForOverride || AreNullableAnnotationsEnabled(constraintSyntax.ClassOrStructKeyword)) { constraints |= TypeParameterConstraintKind.NotNullableReferenceType; } else { constraints |= TypeParameterConstraintKind.ReferenceType; } continue; case SyntaxKind.StructConstraint: hasTypeLikeConstraint = true; if (i != 0) { diagnostics.Add(ErrorCode.ERR_RefValBoundMustBeFirst, syntax.GetFirstToken().GetLocation()); if (isForOverride && (constraints & (TypeParameterConstraintKind.ValueType | TypeParameterConstraintKind.ReferenceType)) != 0) { continue; } } constraints |= TypeParameterConstraintKind.ValueType; continue; case SyntaxKind.ConstructorConstraint: if (isForOverride) { reportOverrideWithConstraints(ref reportedOverrideWithConstraints, syntax, diagnostics); continue; } if ((constraints & TypeParameterConstraintKind.ValueType) != 0) { diagnostics.Add(ErrorCode.ERR_NewBoundWithVal, syntax.GetFirstToken().GetLocation()); } if ((constraints & TypeParameterConstraintKind.Unmanaged) != 0) { diagnostics.Add(ErrorCode.ERR_NewBoundWithUnmanaged, syntax.GetFirstToken().GetLocation()); } if (i != n - 1) { diagnostics.Add(ErrorCode.ERR_NewBoundMustBeLast, syntax.GetFirstToken().GetLocation()); } constraints |= TypeParameterConstraintKind.Constructor; continue; case SyntaxKind.TypeConstraint: if (isForOverride) { reportOverrideWithConstraints(ref reportedOverrideWithConstraints, syntax, diagnostics); } else { hasTypeLikeConstraint = true; if (constraintTypes == null) { constraintTypes = ArrayBuilder <TypeWithAnnotations> .GetInstance(); syntaxBuilder = ArrayBuilder <TypeConstraintSyntax> .GetInstance(); } var typeConstraintSyntax = (TypeConstraintSyntax)syntax; var typeSyntax = typeConstraintSyntax.Type; var type = BindTypeOrConstraintKeyword(typeSyntax, diagnostics, out ConstraintContextualKeyword keyword); switch (keyword) { case ConstraintContextualKeyword.Unmanaged: if (i != 0) { diagnostics.Add(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, typeSyntax.GetLocation()); continue; } // This should produce diagnostics if the types are missing GetWellKnownType(WellKnownType.System_Runtime_InteropServices_UnmanagedType, diagnostics, typeSyntax); GetSpecialType(SpecialType.System_ValueType, diagnostics, typeSyntax); constraints |= TypeParameterConstraintKind.Unmanaged; continue; case ConstraintContextualKeyword.NotNull: if (i != 0) { diagnostics.Add(ErrorCode.ERR_NotNullConstraintMustBeFirst, typeSyntax.GetLocation()); } constraints |= TypeParameterConstraintKind.NotNull; continue; case ConstraintContextualKeyword.None: break; default: throw ExceptionUtilities.UnexpectedValue(keyword); } constraintTypes.Add(type); syntaxBuilder !.Add(typeConstraintSyntax); } continue; default: throw ExceptionUtilities.UnexpectedValue(syntax.Kind()); } } if (!isForOverride && !hasTypeLikeConstraint && !AreNullableAnnotationsEnabled(typeParameterSyntax.Identifier)) { constraints |= TypeParameterConstraintKind.ObliviousNullabilityIfReferenceType; } Debug.Assert(!isForOverride || (constraints & (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType)) != (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType)); return(TypeParameterConstraintClause.Create(constraints, constraintTypes?.ToImmutableAndFree() ?? ImmutableArray <TypeWithAnnotations> .Empty), syntaxBuilder);
private BoundExpression LiftRangeExpression(BoundRangeExpression node, ImmutableArray <BoundExpression> operands) { Debug.Assert(node.Type.IsNullableType()); Debug.Assert(operands.Any(operand => operand.Type.IsNullableType())); Debug.Assert(operands.Length == 1 || operands.Length == 2); ArrayBuilder <BoundExpression> sideeffects = ArrayBuilder <BoundExpression> .GetInstance(); ArrayBuilder <LocalSymbol> locals = ArrayBuilder <LocalSymbol> .GetInstance(); ArrayBuilder <BoundExpression> arguments = ArrayBuilder <BoundExpression> .GetInstance(); // left.HasValue && right.HasValue BoundExpression condition = null; foreach (var operand in operands) { BoundExpression tempOperand = CaptureExpressionInTempIfNeeded(operand, sideeffects, locals); if (tempOperand.Type.IsNullableType()) { BoundExpression operandHasValue = MakeOptimizedHasValue(tempOperand.Syntax, tempOperand); if (condition is null) { condition = operandHasValue; } else { TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean); condition = MakeBinaryOperator(node.Syntax, BinaryOperatorKind.BoolAnd, condition, operandHasValue, boolType, method: null); } arguments.Add(MakeOptimizedGetValueOrDefault(tempOperand.Syntax, tempOperand)); } else { arguments.Add(tempOperand); } } Debug.Assert(condition != null); // method(left.GetValueOrDefault(), right.GetValueOrDefault()) BoundExpression rangeCall = MakeCall( node.Syntax, rewrittenReceiver: null, node.MethodOpt, arguments.ToImmutableArray(), node.MethodOpt.ReturnType.TypeSymbol); if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor)) { return(BadExpression(node.Syntax, node.Type, node)); } // new Nullable(method(left.GetValueOrDefault(), right.GetValueOrDefault())) BoundExpression consequence = new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCall); // default BoundExpression alternative = new BoundDefaultExpression(node.Syntax, constantValueOpt: null, node.Type); // left.HasValue && right.HasValue ? new Nullable(method(left.GetValueOrDefault(), right.GetValueOrDefault())) : default BoundExpression conditionalExpression = RewriteConditionalOperator( syntax: node.Syntax, rewrittenCondition: condition, rewrittenConsequence: consequence, rewrittenAlternative: alternative, constantValueOpt: null, rewrittenType: node.Type, isRef: false); return(new BoundSequence( syntax: node.Syntax, locals: locals.ToImmutableAndFree(), sideEffects: sideeffects.ToImmutableAndFree(), value: conditionalExpression, type: node.Type)); }
public bool Equals(Symbol member1, Symbol member2) { if (ReferenceEquals(member1, member2)) { return(true); } if ((object)member1 == null || (object)member2 == null || member1.Kind != member2.Kind) { return(false); } bool sawInterfaceInName1 = false; bool sawInterfaceInName2 = false; if (_considerName) { string name1 = ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member1.Name); string name2 = ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member2.Name); sawInterfaceInName1 = name1 != member1.Name; sawInterfaceInName2 = name2 != member2.Name; if (name1 != name2) { return(false); } } // NB: up to, and including, this check, we have not actually forced the (type) parameters // to be expanded - we're only using the counts. int arity = member1.GetMemberArity(); if ((arity != member2.GetMemberArity()) || (member1.GetParameterCount() != member2.GetParameterCount())) { return(false); } TypeMap typeMap1; TypeMap typeMap2; if (arity > 0 && _useSpecialHandlingForNullableTypes) { // We need this special handling in order to avoid forcing resolution of nullable types // in signature of an overriding member while we are looking for a matching overridden member. // Doing the resolution in the original signature can send us into an infinite cycle because // constraints must be inherited from the member we are looking for. // It is important to ensure that the fact whether an indexed type parameter we are about to use // is a reference type is inherited from the corresponding type parameter of the possibly overridden // member (which is member2 when _useSpecialHandlingForNullableTypes is true). This will ensure // proper resolution for nullable types in substituted signature of member1, ensuring proper // comparison of types across both members. ArrayBuilder <TypeParameterSymbol> builder = ArrayBuilder <TypeParameterSymbol> .GetInstance(arity); var typeParameters2 = member2.GetMemberTypeParameters(); for (int i = arity - 1; i >= 0; i--) { builder.Add(IndexedTypeParameterSymbolForOverriding.GetTypeParameter(i, typeParameters2[i].IsValueType)); } var indexed = builder.ToImmutableAndFree(); typeMap1 = new TypeMap(member1.GetMemberTypeParameters(), indexed, true); typeMap2 = new TypeMap(typeParameters2, indexed, true); } else { typeMap1 = GetTypeMap(member1); typeMap2 = GetTypeMap(member2); } if ((_considerReturnRefKindDifferences || _considerReturnType) && !HaveSameReturnTypes(member1, typeMap1, member2, typeMap2, _typeComparison)) { return(false); } if (member1.GetParameterCount() > 0 && !HaveSameParameterTypes(member1.GetParameters(), typeMap1, member2.GetParameters(), typeMap2, _considerRefKindDifferences, _typeComparison)) { return(false); } if (_considerCallingConvention) { if (GetCallingConvention(member1) != GetCallingConvention(member2)) { return(false); } } else { if (IsVarargMethod(member1) != IsVarargMethod(member2)) { return(false); } } if (_considerExplicitlyImplementedInterfaces) { if (sawInterfaceInName1 != sawInterfaceInName2) { return(false); } // The purpose of this check is to determine whether the interface parts of the member names agree, // but to do so using robust symbolic checks, rather than syntactic ones. Therefore, if neither member // name contains an interface name, this check is not relevant. // Phrased differently, the explicitly implemented interface is not part of the signature unless it's // part of the name. if (sawInterfaceInName1) { Debug.Assert(sawInterfaceInName2); // May avoid realizing interface members. if (member1.IsExplicitInterfaceImplementation() != member2.IsExplicitInterfaceImplementation()) { return(false); } // By comparing symbols, rather than syntax, we gain the flexibility of ignoring whitespace // and gracefully accepting multiple names for the same (or equivalent) types (e.g. "I<int>.M" // vs "I<System.Int32>.M"), but we lose the connection with the name. For example, in metadata, // a method name "I.M" could have nothing to do with "I" but explicitly implement interface "I2". // We will behave as if the method was really named "I2.M". Furthermore, in metadata, a method // can explicitly implement more than one interface method, in which case it doesn't really // make sense to pretend that all of them are part of the signature. var explicitInterfaceImplementations1 = member1.GetExplicitInterfaceImplementations(); var explicitInterfaceImplementations2 = member2.GetExplicitInterfaceImplementations(); if (!explicitInterfaceImplementations1.SetEquals(explicitInterfaceImplementations2, EqualityComparer <Symbol> .Default)) { return(false); } } } return(!_considerTypeConstraints || HaveSameConstraints(member1, typeMap1, member2, typeMap2)); }
private BoundExpression MakeDecimalLiteral(SyntaxNode syntax, ConstantValue constantValue) { Debug.Assert(constantValue != null); Debug.Assert(constantValue.IsDecimal); var value = constantValue.DecimalValue; bool isNegative; byte scale; uint low, mid, high; value.GetBits(out isNegative, out scale, out low, out mid, out high); var arguments = new ArrayBuilder <BoundExpression>(); SpecialMember member; // check if we can call a simpler constructor, or use a predefined constant if (scale == 0 && int.MinValue <= value && value <= int.MaxValue) { // If we are building static constructor of System.Decimal, accessing static fields // would be bad. var curMethod = _factory.CurrentFunction; if ((curMethod.MethodKind != MethodKind.SharedConstructor || curMethod.ContainingType.SpecialType != SpecialType.System_Decimal) && !_inExpressionLambda) { Symbol useField = null; if (value == decimal.Zero) { useField = _compilation.GetSpecialTypeMember(SpecialMember.System_Decimal__Zero); } else if (value == decimal.One) { useField = _compilation.GetSpecialTypeMember(SpecialMember.System_Decimal__One); } else if (value == decimal.MinusOne) { useField = _compilation.GetSpecialTypeMember(SpecialMember.System_Decimal__MinusOne); } if ((object)useField != null && !useField.HasUseSiteError && !useField.ContainingType.HasUseSiteError) { var fieldSymbol = (FieldSymbol)useField; return(new BoundFieldAccess(syntax, null, fieldSymbol, constantValue)); } } //new decimal(int); member = SpecialMember.System_Decimal__CtorInt32; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((int)value), _compilation.GetSpecialType(SpecialType.System_Int32))); } else if (scale == 0 && uint.MinValue <= value && value <= uint.MaxValue) { //new decimal(uint); member = SpecialMember.System_Decimal__CtorUInt32; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((uint)value), _compilation.GetSpecialType(SpecialType.System_UInt32))); } else if (scale == 0 && long.MinValue <= value && value <= long.MaxValue) { //new decimal(long); member = SpecialMember.System_Decimal__CtorInt64; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((long)value), _compilation.GetSpecialType(SpecialType.System_Int64))); } else if (scale == 0 && ulong.MinValue <= value && value <= ulong.MaxValue) { //new decimal(ulong); member = SpecialMember.System_Decimal__CtorUInt64; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((ulong)value), _compilation.GetSpecialType(SpecialType.System_UInt64))); } else { //new decimal(int low, int mid, int high, bool isNegative, byte scale); member = SpecialMember.System_Decimal__CtorInt32Int32Int32BooleanByte; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(low), _compilation.GetSpecialType(SpecialType.System_Int32))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(mid), _compilation.GetSpecialType(SpecialType.System_Int32))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(high), _compilation.GetSpecialType(SpecialType.System_Int32))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(isNegative), _compilation.GetSpecialType(SpecialType.System_Boolean))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(scale), _compilation.GetSpecialType(SpecialType.System_Byte))); } var ctor = (MethodSymbol)_compilation.Assembly.GetSpecialTypeMember(member); Debug.Assert((object)ctor != null); Debug.Assert(ctor.ContainingType.SpecialType == SpecialType.System_Decimal); return(new BoundObjectCreationExpression( syntax, ctor, arguments.ToImmutableAndFree(), default(ImmutableArray <string>), default(ImmutableArray <RefKind>), false, default(ImmutableArray <int>), constantValue, null, null, ctor.ContainingType)); }
public override SourceText ToSourceText() { Flush(); return(new LargeText(_chunks.ToImmutableAndFree(), Encoding, default, _checksumAlgorithm, default));
public override SourceText ToSourceText() { this.Flush(); return(new LargeText(_chunks.ToImmutableAndFree(), _encoding, default(ImmutableArray <byte>), _checksumAlgorithm)); }
internal static SourceText ToSourceTextAndFree(ArrayBuilder<SourceText> segments, SourceText original, bool adjustSegments) { if (adjustSegments) { TrimInaccessibleText(segments); ReduceSegmentCountIfNecessary(segments); } if (segments.Count == 0) { segments.Free(); return SourceText.From(string.Empty, original.Encoding, original.ChecksumAlgorithm); } else if (segments.Count == 1) { SourceText result = segments[0]; segments.Free(); return result; } else { return new CompositeText(segments.ToImmutableAndFree(), original.Encoding, original.ChecksumAlgorithm); } }
/// <summary> /// Visits a node that is possibly a <see cref="BoundUsingLocalDeclarations"/> /// </summary> /// <param name="node">The node to visit</param> /// <param name="statements">All statements in the block containing this node</param> /// <param name="statementIndex">The current statement being visited in <paramref name="statements"/></param> /// <param name="replacedLocalDeclarations">Set to true if this visited a <see cref="BoundUsingLocalDeclarations"/> node</param> /// <returns>A <see cref="BoundStatement"/></returns> /// <remarks> /// The node being visited is not necessarily equal to statements[startIndex]. /// When traversing down a set of labels, we set node to the label.body and recurse, but statements[startIndex] still refers to the original parent label /// as we haven't actually moved down the original statement list /// </remarks> public BoundStatement?VisitPossibleUsingDeclaration(BoundStatement node, ImmutableArray <BoundStatement> statements, int statementIndex, out bool replacedLocalDeclarations) { switch (node.Kind) { case BoundKind.LabeledStatement: var labelStatement = (BoundLabeledStatement)node; return(MakeLabeledStatement(labelStatement, VisitPossibleUsingDeclaration(labelStatement.Body, statements, statementIndex, out replacedLocalDeclarations))); case BoundKind.UsingLocalDeclarations: // visit everything after this node ArrayBuilder <BoundStatement> builder = ArrayBuilder <BoundStatement> .GetInstance(); VisitStatementSubList(builder, statements, statementIndex + 1); // make a using declaration with the visited statements as its body replacedLocalDeclarations = true; return(MakeLocalUsingDeclarationStatement((BoundUsingLocalDeclarations)node, builder.ToImmutableAndFree())); default: replacedLocalDeclarations = false; return(VisitStatement(node)); } }
internal static ImmutableArray <ParameterSymbol> CopyParameterCustomModifiers( ImmutableArray <ParameterSymbol> sourceParameters, ImmutableArray <ParameterSymbol> destinationParameters, bool alsoCopyParamsModifier ) { Debug.Assert(!destinationParameters.IsDefault); Debug.Assert(destinationParameters.All(p => p is SourceParameterSymbolBase)); Debug.Assert(sourceParameters.Length == destinationParameters.Length); // Nearly all of the time, there will be no custom modifiers to copy, so don't // allocate the builder until we know that we need it. ArrayBuilder <ParameterSymbol> builder = null; int numParams = destinationParameters.Length; for (int i = 0; i < numParams; i++) { SourceParameterSymbolBase destinationParameter = (SourceParameterSymbolBase)destinationParameters[i]; ParameterSymbol sourceParameter = sourceParameters[i]; if ( sourceParameter.TypeWithAnnotations.CustomModifiers.Any() || sourceParameter.RefCustomModifiers.Any() || sourceParameter.Type.HasCustomModifiers( flagNonDefaultArraySizesOrLowerBounds: true ) || destinationParameter.TypeWithAnnotations.CustomModifiers.Any() || destinationParameter.RefCustomModifiers.Any() || destinationParameter.Type.HasCustomModifiers( flagNonDefaultArraySizesOrLowerBounds: true ) || // Could happen if the associated property has custom modifiers. ( alsoCopyParamsModifier && (sourceParameter.IsParams != destinationParameter.IsParams) ) ) { if (builder == null) { builder = ArrayBuilder <ParameterSymbol> .GetInstance(); builder.AddRange(destinationParameters, i); //add up to, but not including, the current parameter } bool newParams = alsoCopyParamsModifier ? sourceParameter.IsParams : destinationParameter.IsParams; builder.Add( destinationParameter.WithCustomModifiersAndParams( sourceParameter.Type, sourceParameter.TypeWithAnnotations.CustomModifiers, destinationParameter.RefKind != RefKind.None ? sourceParameter.RefCustomModifiers : ImmutableArray <CustomModifier> .Empty, newParams ) ); } else if (builder != null) { builder.Add(destinationParameter); } } return(builder == null ? destinationParameters : builder.ToImmutableAndFree()); }
private ImmutableArray<IMethodSymbol> GetMatchingMethods(ImmutableArray<ISymbol> candidateMembers, int? arity, ParameterInfo[] parameters, TypeInfo? returnType) { var builder = new ArrayBuilder<IMethodSymbol>(); foreach (var symbol in candidateMembers) { var methodSymbol = symbol as IMethodSymbol; if (methodSymbol == null || (arity != null && methodSymbol.Arity != arity)) { continue; } if (!AllParametersMatch(methodSymbol.Parameters, parameters)) { continue; } if (returnType == null) { // If no return type specified, then any matches builder.Add(methodSymbol); } else { // If return type is specified, then it must match var boundReturnType = BindParameterOrReturnType(methodSymbol, returnType.Value); if (boundReturnType != null && methodSymbol.ReturnType.Equals(boundReturnType)) { builder.Add(methodSymbol); } } } return builder.ToImmutableAndFree(); }
private BoundExpression BindAnonymousObjectCreation(AnonymousObjectCreationExpressionSyntax node, DiagnosticBag diagnostics) { // prepare var initializers = node.Initializers; int fieldCount = initializers.Count; bool hasError = false; // bind field initializers BoundExpression[] boundExpressions = new BoundExpression[fieldCount]; AnonymousTypeField[] fields = new AnonymousTypeField[fieldCount]; CSharpSyntaxNode[] fieldSyntaxNodes = new CSharpSyntaxNode[fieldCount]; // WARNING: Note that SemanticModel.GetDeclaredSymbol for field initializer node relies on // the fact that the order of properties in anonymous type template corresponds // 1-to-1 to the appropriate filed initializer syntax nodes; This means such // correspondence must be preserved all the time including erroneos scenarios // set of names already used HashSet <string> uniqueFieldNames = new HashSet <string>(); for (int i = 0; i < fieldCount; i++) { AnonymousObjectMemberDeclaratorSyntax fieldInitializer = initializers[i]; NameEqualsSyntax nameEquals = fieldInitializer.NameEquals; ExpressionSyntax expression = fieldInitializer.Expression; SyntaxToken nameToken = default(SyntaxToken); if (nameEquals != null) { nameToken = nameEquals.Name.Identifier; } else { nameToken = expression.ExtractAnonymousTypeMemberName(); } hasError = hasError || expression.HasErrors; boundExpressions[i] = this.BindValue(expression, diagnostics, BindValueKind.RValue); // check the name to be unique string fieldName = null; if (nameToken.Kind() == SyntaxKind.IdentifierToken) { fieldName = nameToken.ValueText; if (uniqueFieldNames.Contains(fieldName)) { // name duplication Error(diagnostics, ErrorCode.ERR_AnonymousTypeDuplicatePropertyName, fieldInitializer); hasError = true; fieldName = null; } else { uniqueFieldNames.Add(fieldName); } } else { // there is something wrong with field's name hasError = true; } // calculate the expression's type and report errors if needed TypeSymbol fieldType = GetAnonymousTypeFieldType(boundExpressions[i], fieldInitializer, diagnostics, ref hasError); // build anonymous type field descriptor fieldSyntaxNodes[i] = (nameToken.Kind() == SyntaxKind.IdentifierToken) ? (CSharpSyntaxNode)nameToken.Parent : fieldInitializer; fields[i] = new AnonymousTypeField(fieldName == null ? "$" + i.ToString() : fieldName, fieldSyntaxNodes[i].Location, fieldType); // NOTE: ERR_InvalidAnonymousTypeMemberDeclarator (CS0746) would be generated by parser if needed } // Create anonymous type AnonymousTypeManager manager = this.Compilation.AnonymousTypeManager; AnonymousTypeDescriptor descriptor = new AnonymousTypeDescriptor(fields.AsImmutableOrNull(), node.NewKeyword.GetLocation()); NamedTypeSymbol anonymousType = manager.ConstructAnonymousTypeSymbol(descriptor); // declarators - bound nodes created for providing semantic info // on anonymous type fields having explicitly specified name ArrayBuilder <BoundAnonymousPropertyDeclaration> declarators = ArrayBuilder <BoundAnonymousPropertyDeclaration> .GetInstance(); for (int i = 0; i < fieldCount; i++) { NameEqualsSyntax explicitName = initializers[i].NameEquals; if (explicitName != null) { AnonymousTypeField field = fields[i]; if (field.Name != null) { // get property symbol and create a bound property declaration node foreach (var symbol in anonymousType.GetMembers(field.Name)) { if (symbol.Kind == SymbolKind.Property) { declarators.Add(new BoundAnonymousPropertyDeclaration(fieldSyntaxNodes[i], (PropertySymbol)symbol, field.Type)); break; } } } } } // check if anonymous object creation is allowed in this context if (!this.IsAnonymousTypesAllowed()) { Error(diagnostics, ErrorCode.ERR_AnonymousTypeNotAvailable, node.NewKeyword); hasError = true; } // Finally create a bound node return(new BoundAnonymousObjectCreationExpression( node, anonymousType.InstanceConstructors[0], boundExpressions.AsImmutableOrNull(), declarators.ToImmutableAndFree(), anonymousType, hasError)); }
/// <summary> /// If we have a WinRT type event, we need to encapsulate the adder call /// (which returns an EventRegistrationToken) with a call to /// WindowsRuntimeMarshal.AddEventHandler or RemoveEventHandler, but these /// require us to create a new Func representing the adder and another /// Action representing the Remover. /// /// The rewritten call looks something like: /// /// WindowsRuntimeMarshal.AddEventHandler<EventHandler> /// (new Func<EventHandler, EventRegistrationToken>(@object.add), /// new Action<EventRegistrationToken>(@object.remove), handler); /// /// Where @object is a compiler-generated local temp if needed. /// </summary> /// <remarks> /// TODO: use or delete isDynamic. /// </remarks> private BoundExpression RewriteWindowsRuntimeEventAssignmentOperator(SyntaxNode syntax, EventSymbol eventSymbol, EventAssignmentKind kind, bool isDynamic, BoundExpression rewrittenReceiverOpt, BoundExpression rewrittenArgument) { BoundAssignmentOperator tempAssignment = null; BoundLocal boundTemp = null; if (!eventSymbol.IsStatic && CanChangeValueBetweenReads(rewrittenReceiverOpt)) { boundTemp = _factory.StoreToTemp(rewrittenReceiverOpt, out tempAssignment); } NamedTypeSymbol tokenType = _factory.WellKnownType(WellKnownType.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationToken); NamedTypeSymbol marshalType = _factory.WellKnownType(WellKnownType.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal); NamedTypeSymbol actionType = _factory.WellKnownType(WellKnownType.System_Action_T).Construct(tokenType); TypeSymbol eventType = eventSymbol.Type; BoundExpression delegateCreationArgument = boundTemp ?? rewrittenReceiverOpt ?? _factory.Type(eventType); BoundDelegateCreationExpression removeDelegate = new BoundDelegateCreationExpression( syntax: syntax, argument: delegateCreationArgument, methodOpt: eventSymbol.RemoveMethod, isExtensionMethod: false, type: actionType); BoundExpression clearCall = null; if (kind == EventAssignmentKind.Assignment) { MethodSymbol clearMethod; if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal__RemoveAllEventHandlers, out clearMethod)) { clearCall = MakeCall( syntax: syntax, rewrittenReceiver: null, method: clearMethod, rewrittenArguments: ImmutableArray.Create <BoundExpression>(removeDelegate), type: clearMethod.ReturnType); } else { clearCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundNode>(removeDelegate), ErrorTypeSymbol.UnknownResultType); } } ImmutableArray <BoundExpression> marshalArguments; WellKnownMember helper; if (kind == EventAssignmentKind.Subtraction) { helper = WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal__RemoveEventHandler_T; marshalArguments = ImmutableArray.Create <BoundExpression>(removeDelegate, rewrittenArgument); } else { NamedTypeSymbol func2Type = _factory.WellKnownType(WellKnownType.System_Func_T2).Construct(eventType, tokenType); BoundDelegateCreationExpression addDelegate = new BoundDelegateCreationExpression( syntax: syntax, argument: delegateCreationArgument, methodOpt: eventSymbol.AddMethod, isExtensionMethod: false, type: func2Type); helper = WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_WindowsRuntimeMarshal__AddEventHandler_T; marshalArguments = ImmutableArray.Create <BoundExpression>(addDelegate, removeDelegate, rewrittenArgument); } BoundExpression marshalCall; MethodSymbol marshalMethod; if (TryGetWellKnownTypeMember(syntax, helper, out marshalMethod)) { marshalMethod = marshalMethod.Construct(eventType); marshalCall = MakeCall( syntax: syntax, rewrittenReceiver: null, method: marshalMethod, rewrittenArguments: marshalArguments, type: marshalMethod.ReturnType); } else { marshalCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, StaticCast <BoundNode> .From(marshalArguments), ErrorTypeSymbol.UnknownResultType); } // In this case, we don't need a sequence. if (boundTemp == null && clearCall == null) { return(marshalCall); } ImmutableArray <LocalSymbol> tempSymbols = boundTemp == null ? ImmutableArray <LocalSymbol> .Empty : ImmutableArray.Create <LocalSymbol>(boundTemp.LocalSymbol); ArrayBuilder <BoundExpression> sideEffects = ArrayBuilder <BoundExpression> .GetInstance(2); //max size if (clearCall != null) { sideEffects.Add(clearCall); } if (tempAssignment != null) { sideEffects.Add(tempAssignment); } Debug.Assert(sideEffects.Any(), "Otherwise, we shouldn't be building a sequence"); return(new BoundSequence(syntax, tempSymbols, sideEffects.ToImmutableAndFree(), marshalCall, marshalCall.Type)); }
protected ImmutableArray <LocalSymbol> BuildLocals(SyntaxList <StatementSyntax> statements, Binder enclosingBinder) { #if DEBUG Binder currentBinder = enclosingBinder; while (true) { if (this == currentBinder) { break; } currentBinder = currentBinder.Next; } #endif ArrayBuilder <LocalSymbol> locals = ArrayBuilder <LocalSymbol> .GetInstance(); foreach (var statement in statements) { var innerStatement = statement; // drill into any LabeledStatements -- atomic LabelStatements have been bound into // wrapped LabeledStatements by this point while (innerStatement.Kind() == SyntaxKind.LabeledStatement) { innerStatement = ((LabeledStatementSyntax)innerStatement).Statement; } switch (innerStatement.Kind()) { case SyntaxKind.LocalDeclarationStatement: { Binder localDeclarationBinder = enclosingBinder.GetBinder(innerStatement) ?? enclosingBinder; var decl = (LocalDeclarationStatementSyntax)innerStatement; LocalDeclarationKind kind; if (decl.IsConst) { kind = LocalDeclarationKind.Constant; } else if (decl.UsingKeyword != default(SyntaxToken)) { kind = LocalDeclarationKind.UsingVariable; } else { kind = LocalDeclarationKind.RegularVariable; } foreach (var vdecl in decl.Declaration.Variables) { var localSymbol = MakeLocal(decl.Declaration, vdecl, kind, localDeclarationBinder); locals.Add(localSymbol); // also gather expression-declared variables from the bracketed argument lists and the initializers ExpressionVariableFinder.FindExpressionVariables(this, locals, vdecl, localDeclarationBinder); } } break; case SyntaxKind.ExpressionStatement: case SyntaxKind.IfStatement: case SyntaxKind.YieldReturnStatement: case SyntaxKind.ReturnStatement: case SyntaxKind.ThrowStatement: ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, enclosingBinder.GetBinder(innerStatement) ?? enclosingBinder); break; case SyntaxKind.SwitchStatement: var switchStatement = (SwitchStatementSyntax)innerStatement; ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, enclosingBinder.GetBinder(switchStatement.Expression) ?? enclosingBinder); break; case SyntaxKind.LockStatement: Binder statementBinder = enclosingBinder.GetBinder(innerStatement); Debug.Assert(statementBinder != null); // Lock always has a binder. ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, statementBinder); break; default: // no other statement introduces local variables into the enclosing scope break; } } return(locals.ToImmutableAndFree()); }
/// <summary> /// Get all the sequence points, possibly mapping them using #line/ExternalSource directives, and mapping /// file names to debug documents with the given mapping function. /// </summary> /// <param name="documentProvider">Function that maps file paths to CCI debug documents</param> public ImmutableArray <Cci.SequencePoint> GetSequencePoints(DebugDocumentProvider documentProvider) { bool lastPathIsMapped = false; string lastPath = null; Cci.DebugSourceDocument lastDebugDocument = null; // First, count the number of sequence points. int count = 0; SequencePointList current = this; while (current != null) { count += current._points.Length; current = current._next; } ArrayBuilder <Cci.SequencePoint> result = ArrayBuilder <Cci.SequencePoint> .GetInstance(count); current = this; while (current != null) { SyntaxTree currentTree = current._tree; foreach (var offsetAndSpan in current._points) { TextSpan span = offsetAndSpan.Span; // if it's a hidden sequence point, or a sequence point with syntax that points to a position that is inside // of a hidden region (can be defined with #line hidden (C#) or implicitly by #ExternalSource (VB), make it // a hidden sequence point. bool isHidden = span == RawSequencePoint.HiddenSequencePointSpan; FileLinePositionSpan fileLinePositionSpan = default(FileLinePositionSpan); if (!isHidden) { fileLinePositionSpan = currentTree.GetMappedLineSpanAndVisibility(span, out isHidden); } if (isHidden) { if (lastPath == null) { lastPath = currentTree.FilePath; lastDebugDocument = documentProvider(lastPath, basePath: null); } if (lastDebugDocument != null) { result.Add(new Cci.SequencePoint( lastDebugDocument, offset: offsetAndSpan.Offset, startLine: HiddenSequencePointLine, startColumn: 0, endLine: HiddenSequencePointLine, endColumn: 0)); } } else { if (lastPath != fileLinePositionSpan.Path || lastPathIsMapped != fileLinePositionSpan.HasMappedPath) { lastPath = fileLinePositionSpan.Path; lastPathIsMapped = fileLinePositionSpan.HasMappedPath; lastDebugDocument = documentProvider(lastPath, basePath: lastPathIsMapped ? currentTree.FilePath : null); } if (lastDebugDocument != null) { result.Add(new Cci.SequencePoint( lastDebugDocument, offset: offsetAndSpan.Offset, startLine: (fileLinePositionSpan.StartLinePosition.Line == -1) ? 0 : fileLinePositionSpan.StartLinePosition.Line + 1, startColumn: fileLinePositionSpan.StartLinePosition.Character + 1, endLine: (fileLinePositionSpan.EndLinePosition.Line == -1) ? 0 : fileLinePositionSpan.EndLinePosition.Line + 1, endColumn: fileLinePositionSpan.EndLinePosition.Character + 1 )); } } } current = current._next; } return(result.ToImmutableAndFree()); }
protected ImmutableArray <LocalSymbol> BuildLocals(SyntaxList <StatementSyntax> statements, Binder enclosingBinder) { #if DEBUG Binder currentBinder = enclosingBinder; while (true) { if (this == currentBinder) { break; } currentBinder = currentBinder.Next; } #endif ArrayBuilder <LocalSymbol> locals = ArrayBuilder <LocalSymbol> .GetInstance(); foreach (var statement in statements) { var innerStatement = statement; // drill into any LabeledStatements -- atomic LabelStatements have been bound into // wrapped LabeledStatements by this point while (innerStatement.Kind() == SyntaxKind.LabeledStatement) { innerStatement = ((LabeledStatementSyntax)innerStatement).Statement; } switch (innerStatement.Kind()) { case SyntaxKind.DeconstructionDeclarationStatement: { var decl = (DeconstructionDeclarationStatementSyntax)innerStatement; Binder deconstructionDeclarationBinder = enclosingBinder.GetBinder(innerStatement) ?? enclosingBinder; CollectLocalsFromDeconstruction( decl.Assignment.VariableComponent, LocalDeclarationKind.RegularVariable, locals, innerStatement, deconstructionDeclarationBinder); ExpressionVariableFinder.FindExpressionVariables(this, locals, decl.Assignment.Value, deconstructionDeclarationBinder); break; } case SyntaxKind.LocalDeclarationStatement: { Binder localDeclarationBinder = enclosingBinder.GetBinder(innerStatement) ?? enclosingBinder; var decl = (LocalDeclarationStatementSyntax)innerStatement; LocalDeclarationKind kind = decl.IsConst ? LocalDeclarationKind.Constant : LocalDeclarationKind.RegularVariable; foreach (var vdecl in decl.Declaration.Variables) { var localSymbol = MakeLocal(decl.Declaration, vdecl, kind, localDeclarationBinder); locals.Add(localSymbol); ExpressionVariableFinder.FindExpressionVariables(this, locals, vdecl.Initializer?.Value, localDeclarationBinder); } } break; case SyntaxKind.ExpressionStatement: case SyntaxKind.IfStatement: case SyntaxKind.YieldReturnStatement: case SyntaxKind.ReturnStatement: case SyntaxKind.ThrowStatement: ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, enclosingBinder.GetBinder(innerStatement) ?? enclosingBinder); break; case SyntaxKind.SwitchStatement: var switchStatement = (SwitchStatementSyntax)innerStatement; ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, enclosingBinder.GetBinder(switchStatement.Expression) ?? enclosingBinder); break; case SyntaxKind.WhileStatement: case SyntaxKind.DoStatement: case SyntaxKind.LockStatement: Binder statementBinder = enclosingBinder.GetBinder(innerStatement); Debug.Assert(statementBinder != null); // Lock, Do and while loops always have binders. ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, statementBinder); break; default: // no other statement introduces local variables into the enclosing scope break; } } return(locals.ToImmutableAndFree()); }
/// <summary> /// Given a base field declaration syntax, get the corresponding symbols. /// </summary> /// <param name="declarationSyntax">The syntax node that declares one or more fields or events.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The field symbols that were declared.</returns> internal override ImmutableArray<ISymbol> GetDeclaredSymbols(BaseFieldDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken)) { CheckSyntaxNode(declarationSyntax); var builder = new ArrayBuilder<ISymbol>(); foreach (var declarator in declarationSyntax.Declaration.Variables) { var field = this.GetDeclaredSymbol(declarator, cancellationToken) as ISymbol; if (field != null) { builder.Add(field); } } return builder.ToImmutableAndFree(); }
private BoundExpression MakeDecimalLiteral(CSharpSyntaxNode syntax, ConstantValue constantValue) { Debug.Assert(constantValue != null); Debug.Assert(constantValue.IsDecimal); var value = constantValue.DecimalValue; bool isNegative; byte scale; uint low, mid, high; value.GetBits(out isNegative, out scale, out low, out mid, out high); var arguments = new ArrayBuilder<BoundExpression>(); SpecialMember member; // check if we can call a simpler constructor, or use a predefined constant if (scale == 0 && int.MinValue <= value && value <= int.MaxValue) { // If we are building static constructor of System.Decimal, accessing static fields // would be bad. var curMethod = _factory.CurrentMethod; if ((curMethod.MethodKind != MethodKind.SharedConstructor || curMethod.ContainingType.SpecialType != SpecialType.System_Decimal) && !_inExpressionLambda) { Symbol useField = null; if (value == decimal.Zero) { useField = _compilation.GetSpecialTypeMember(SpecialMember.System_Decimal__Zero); } else if (value == decimal.One) { useField = _compilation.GetSpecialTypeMember(SpecialMember.System_Decimal__One); } else if (value == decimal.MinusOne) { useField = _compilation.GetSpecialTypeMember(SpecialMember.System_Decimal__MinusOne); } if ((object)useField != null && !useField.HasUseSiteError && !useField.ContainingType.HasUseSiteError) { var fieldSymbol = (FieldSymbol)useField; return new BoundFieldAccess(syntax, null, fieldSymbol, constantValue); } } //new decimal(int); member = SpecialMember.System_Decimal__CtorInt32; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((int)value), _compilation.GetSpecialType(SpecialType.System_Int32))); } else if (scale == 0 && uint.MinValue <= value && value <= uint.MaxValue) { //new decimal(uint); member = SpecialMember.System_Decimal__CtorUInt32; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((uint)value), _compilation.GetSpecialType(SpecialType.System_UInt32))); } else if (scale == 0 && long.MinValue <= value && value <= long.MaxValue) { //new decimal(long); member = SpecialMember.System_Decimal__CtorInt64; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((long)value), _compilation.GetSpecialType(SpecialType.System_Int64))); } else if (scale == 0 && ulong.MinValue <= value && value <= ulong.MaxValue) { //new decimal(ulong); member = SpecialMember.System_Decimal__CtorUInt64; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((ulong)value), _compilation.GetSpecialType(SpecialType.System_UInt64))); } else { //new decimal(int low, int mid, int high, bool isNegative, byte scale); member = SpecialMember.System_Decimal__CtorInt32Int32Int32BooleanByte; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(low), _compilation.GetSpecialType(SpecialType.System_Int32))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(mid), _compilation.GetSpecialType(SpecialType.System_Int32))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(high), _compilation.GetSpecialType(SpecialType.System_Int32))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(isNegative), _compilation.GetSpecialType(SpecialType.System_Boolean))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(scale), _compilation.GetSpecialType(SpecialType.System_Byte))); } var ctor = (MethodSymbol)_compilation.Assembly.GetSpecialTypeMember(member); Debug.Assert((object)ctor != null); Debug.Assert(ctor.ContainingType.SpecialType == SpecialType.System_Decimal); return new BoundObjectCreationExpression( syntax, ctor, arguments.ToImmutableAndFree(), default(ImmutableArray<string>), default(ImmutableArray<RefKind>), false, default(ImmutableArray<int>), constantValue, null, ctor.ContainingType); }
private static void ReadCSharpNativeImportsInfo( ISymUnmanagedReader3 reader, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, int methodToken, int methodVersion, out ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups, out ImmutableArray <ExternAliasRecord> externAliasRecords) { ImmutableArray <string> externAliasStrings; var importStringGroups = CustomDebugInfoReader.GetCSharpGroupedImportStrings( methodToken, KeyValuePair.Create(reader, methodVersion), getMethodCustomDebugInfo: (token, arg) => GetCustomDebugInfoBytes(arg.Key, token, arg.Value), getMethodImportStrings: (token, arg) => GetImportStrings(arg.Key, token, arg.Value), externAliasStrings: out externAliasStrings); Debug.Assert(importStringGroups.IsDefault == externAliasStrings.IsDefault); ArrayBuilder <ImmutableArray <ImportRecord> > importRecordGroupBuilder = null; ArrayBuilder <ExternAliasRecord> externAliasRecordBuilder = null; if (!importStringGroups.IsDefault) { importRecordGroupBuilder = ArrayBuilder <ImmutableArray <ImportRecord> > .GetInstance(importStringGroups.Length); foreach (var importStringGroup in importStringGroups) { var groupBuilder = ArrayBuilder <ImportRecord> .GetInstance(importStringGroup.Length); foreach (var importString in importStringGroup) { ImportRecord record; if (TryCreateImportRecordFromCSharpImportString(symbolProvider, importString, out record)) { groupBuilder.Add(record); } else { Debug.WriteLine($"Failed to parse import string {importString}"); } } importRecordGroupBuilder.Add(groupBuilder.ToImmutableAndFree()); } if (!externAliasStrings.IsDefault) { externAliasRecordBuilder = ArrayBuilder <ExternAliasRecord> .GetInstance(externAliasStrings.Length); foreach (string externAliasString in externAliasStrings) { string alias; string externAlias; string target; ImportTargetKind kind; if (!CustomDebugInfoReader.TryParseCSharpImportString(externAliasString, out alias, out externAlias, out target, out kind)) { Debug.WriteLine($"Unable to parse extern alias '{externAliasString}'"); continue; } Debug.Assert(kind == ImportTargetKind.Assembly, "Programmer error: How did a non-assembly get in the extern alias list?"); Debug.Assert(alias != null); // Name of the extern alias. Debug.Assert(externAlias == null); // Not used. Debug.Assert(target != null); // Name of the target assembly. AssemblyIdentity targetIdentity; if (!AssemblyIdentity.TryParseDisplayName(target, out targetIdentity)) { Debug.WriteLine($"Unable to parse target of extern alias '{externAliasString}'"); continue; } externAliasRecordBuilder.Add(new ExternAliasRecord(alias, targetIdentity)); } } } importRecordGroups = importRecordGroupBuilder?.ToImmutableAndFree() ?? ImmutableArray <ImmutableArray <ImportRecord> > .Empty; externAliasRecords = externAliasRecordBuilder?.ToImmutableAndFree() ?? ImmutableArray <ExternAliasRecord> .Empty; }
protected ImmutableArray <BoundStatement> LowerDecisionDagCore(BoundDecisionDag decisionDag) { _loweredDecisionDag = ArrayBuilder <BoundStatement> .GetInstance(); ComputeLabelSet(decisionDag); ImmutableArray <BoundDecisionDagNode> sortedNodes = decisionDag.TopologicallySortedNodes; var firstNode = sortedNodes[0]; switch (firstNode) { case BoundWhenDecisionDagNode _: case BoundLeafDecisionDagNode _: // If the first node is a leaf or when clause rather than the code for the // lowered decision dag, jump there to start. _loweredDecisionDag.Add(_factory.Goto(GetDagNodeLabel(firstNode))); break; } // Code for each when clause goes in the separate code section for its switch section. foreach (BoundDecisionDagNode node in sortedNodes) { if (node is BoundWhenDecisionDagNode w) { LowerWhenClause(w); } } ImmutableArray <BoundDecisionDagNode> nodesToLower = sortedNodes.WhereAsArray(n => n.Kind != BoundKind.WhenDecisionDagNode && n.Kind != BoundKind.LeafDecisionDagNode); var loweredNodes = PooledHashSet <BoundDecisionDagNode> .GetInstance(); for (int i = 0, length = nodesToLower.Length; i < length; i++) { BoundDecisionDagNode node = nodesToLower[i]; if (loweredNodes.Contains(node)) { Debug.Assert(!_dagNodeLabels.TryGetValue(node, out _)); continue; } if (_dagNodeLabels.TryGetValue(node, out LabelSymbol label)) { _loweredDecisionDag.Add(_factory.Label(label)); } // If we can generate an IL switch instruction, do so if (GenerateSwitchDispatch(node, loweredNodes)) { continue; } // If we can generate a type test and cast more efficiently as an `is` followed by a null check, do so if (GenerateTypeTestAndCast(node, loweredNodes, nodesToLower, i)) { continue; } // We pass the node that will follow so we can permit a test to fall through if appropriate BoundDecisionDagNode nextNode = ((i + 1) < length) ? nodesToLower[i + 1] : null; if (nextNode != null && loweredNodes.Contains(nextNode)) { nextNode = null; } LowerDecisionDagNode(node, nextNode); } loweredNodes.Free(); var result = _loweredDecisionDag.ToImmutableAndFree(); _loweredDecisionDag = null; return(result); }
private BoundExpression MakeDateTimeLiteral(CSharpSyntaxNode syntax, ConstantValue constantValue) { Debug.Assert(constantValue != null); Debug.Assert(constantValue.IsDateTime); var arguments = new ArrayBuilder<BoundExpression>(); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(constantValue.DateTimeValue.Ticks), _compilation.GetSpecialType(SpecialType.System_Int64))); var ctor = (MethodSymbol)_compilation.Assembly.GetSpecialTypeMember(SpecialMember.System_DateTime__CtorInt64); Debug.Assert((object)ctor != null); Debug.Assert(ctor.ContainingType.SpecialType == SpecialType.System_DateTime); // This is not a constant from C#'s perspective, so do not mark it as one. return new BoundObjectCreationExpression( syntax, ctor, arguments.ToImmutableAndFree(), default(ImmutableArray<string>), default(ImmutableArray<RefKind>), false, default(ImmutableArray<int>), ConstantValue.NotAvailable, null, ctor.ContainingType); }
private BoundNode RewriteWithNotRefOperand( bool isPrefix, bool isChecked, ArrayBuilder<LocalSymbol> tempSymbols, ArrayBuilder<BoundExpression> tempInitializers, CSharpSyntaxNode syntax, BoundExpression transformedLHS, TypeSymbol operandType, BoundExpression boundTemp, BoundExpression newValue) { // prefix: temp = (X)(T.Increment((T)operand))); operand = temp; // postfix: temp = operand; operand = (X)(T.Increment((T)temp))); ImmutableArray<BoundExpression> assignments = ImmutableArray.Create<BoundExpression>( MakeAssignmentOperator(syntax, boundTemp, isPrefix ? newValue : MakeRValue(transformedLHS), operandType, used: false, isChecked: isChecked, isCompoundAssignment: false), MakeAssignmentOperator(syntax, transformedLHS, isPrefix ? boundTemp : newValue, operandType, used: false, isChecked: isChecked, isCompoundAssignment: false)); // prefix: Seq( operand initializers; temp = (T)(operand + 1); operand = temp; result: temp) // postfix: Seq( operand initializers; temp = operand; operand = (T)(temp + 1); result: temp) return new BoundSequence( syntax: syntax, locals: tempSymbols.ToImmutableAndFree(), sideEffects: tempInitializers.ToImmutableAndFree().Concat(assignments), value: boundTemp, type: operandType); }
public override BoundNode VisitTypeOrInstanceInitializers(BoundTypeOrInstanceInitializers node) { ImmutableArray <BoundStatement> originalStatements = node.Statements; ArrayBuilder <BoundStatement> statements = ArrayBuilder <BoundStatement> .GetInstance(node.Statements.Length); foreach (var initializer in originalStatements) { if (IsFieldOrPropertyInitializer(initializer)) { statements.Add(RewriteExpressionStatement((BoundExpressionStatement)initializer, suppressInstrumentation: true)); } else { statements.Add(VisitStatement(initializer)); } } int optimizedInitializers = 0; bool optimize = _compilation.Options.OptimizationLevel == OptimizationLevel.Release; for (int i = 0; i < statements.Count; i++) { if (statements[i] == null || (optimize && IsFieldOrPropertyInitializer(originalStatements[i]) && ShouldOptimizeOutInitializer(statements[i]))) { optimizedInitializers++; if (!_factory.CurrentMethod.IsStatic) { // NOTE: Dev11 removes static initializers if ONLY all of them are optimized out statements[i] = null; } } } ImmutableArray <BoundStatement> rewrittenStatements; if (optimizedInitializers == statements.Count) { // all are optimized away rewrittenStatements = ImmutableArray <BoundStatement> .Empty; statements.Free(); } else { // instrument remaining statements int remaining = 0; for (int i = 0; i < statements.Count; i++) { BoundStatement rewritten = statements[i]; if (rewritten != null) { if (IsFieldOrPropertyInitializer(originalStatements[i])) { var original = (BoundExpressionStatement)originalStatements[i]; if (Instrument && !original.WasCompilerGenerated) { rewritten = _instrumenter.InstrumentFieldOrPropertyInitializer(original, rewritten); } } statements[remaining] = rewritten; remaining++; } } statements.Count = remaining; rewrittenStatements = statements.ToImmutableAndFree(); } return(new BoundStatementList(node.Syntax, rewrittenStatements, node.HasErrors)); }
private ImmutableArray<string> DecodeSuppressMessageAttributes(ISymbol symbol) { var builder = new ArrayBuilder<string>(); foreach (var attribute in symbol.GetAttributes().Where(a => a.AttributeClass == this.SuppressMessageAttribute)) { SuppressMessageInfo info; if (!TryDecodeSuppressMessageAttributeData(attribute, out info)) { continue; } builder.Add(info.Id); } return builder.ToImmutableAndFree(); }
public override BoundStatement CreateBlockPrologue(BoundBlock original, out LocalSymbol synthesizedLocal) { BoundStatement previousPrologue = base.CreateBlockPrologue(original, out synthesizedLocal); if (_methodBody == original) { _dynamicAnalysisSpans = _spansBuilder.ToImmutableAndFree(); // In the future there will be multiple analysis kinds. const int analysisKind = 0; ArrayTypeSymbol modulePayloadType = ArrayTypeSymbol.CreateCSharpArray(_methodBodyFactory.Compilation.Assembly, TypeSymbolWithAnnotations.Create(_payloadType)); // Synthesize the initialization of the instrumentation payload array, using concurrency-safe code: // // var payload = PID.PayloadRootField[methodIndex]; // if (payload == null) // payload = Instrumentation.CreatePayload(mvid, methodIndex, fileIndexOrIndices, ref PID.PayloadRootField[methodIndex], payloadLength); BoundStatement payloadInitialization = _methodBodyFactory.Assignment( _methodBodyFactory.Local(_methodPayload), _methodBodyFactory.ArrayAccess( _methodBodyFactory.InstrumentationPayloadRoot(analysisKind, modulePayloadType), ImmutableArray.Create(_methodBodyFactory.MethodDefIndex(_method)))); BoundExpression mvid = _methodBodyFactory.ModuleVersionId(); BoundExpression methodToken = _methodBodyFactory.MethodDefIndex(_method); BoundExpression payloadSlot = _methodBodyFactory.ArrayAccess( _methodBodyFactory.InstrumentationPayloadRoot(analysisKind, modulePayloadType), ImmutableArray.Create(_methodBodyFactory.MethodDefIndex(_method))); BoundStatement createPayloadCall = GetCreatePayloadStatement( _dynamicAnalysisSpans, _methodBody.Syntax, _methodPayload, _createPayloadForMethodsSpanningSingleFile, _createPayloadForMethodsSpanningMultipleFiles, mvid, methodToken, payloadSlot, _methodBodyFactory, _debugDocumentProvider); BoundExpression payloadNullTest = _methodBodyFactory.Binary( BinaryOperatorKind.ObjectEqual, _methodBodyFactory.SpecialType(SpecialType.System_Boolean), _methodBodyFactory.Local(_methodPayload), _methodBodyFactory.Null(_payloadType)); BoundStatement payloadIf = _methodBodyFactory.If(payloadNullTest, createPayloadCall); Debug.Assert(synthesizedLocal == null); synthesizedLocal = _methodPayload; ArrayBuilder <BoundStatement> prologueStatements = ArrayBuilder <BoundStatement> .GetInstance(previousPrologue == null? 3 : 4); prologueStatements.Add(payloadInitialization); prologueStatements.Add(payloadIf); if (_methodEntryInstrumentation != null) { prologueStatements.Add(_methodEntryInstrumentation); } if (previousPrologue != null) { prologueStatements.Add(previousPrologue); } return(_methodBodyFactory.StatementList(prologueStatements.ToImmutableAndFree())); } return(previousPrologue); }
private void SerializeMethodDebugInfo(IMethodBody bodyOpt, int methodRid, StandaloneSignatureHandle localSignatureHandleOpt, ref LocalVariableHandle lastLocalVariableHandle, ref LocalConstantHandle lastLocalConstantHandle) { if (bodyOpt == null) { _debugMetadataOpt.AddMethodDebugInformation(default(DocumentHandle), default(BlobHandle)); return; } bool isIterator = bodyOpt.StateMachineTypeName != null; bool emitDebugInfo = isIterator || bodyOpt.HasAnySequencePoints; if (!emitDebugInfo) { _debugMetadataOpt.AddMethodDebugInformation(default(DocumentHandle), default(BlobHandle)); return; } var methodHandle = MetadataTokens.MethodDefinitionHandle(methodRid); var bodyImportScope = bodyOpt.ImportScope; var importScopeHandle = (bodyImportScope != null) ? GetImportScopeIndex(bodyImportScope, _scopeIndex) : default(ImportScopeHandle); // documents & sequence points: DocumentHandle singleDocumentHandle; ArrayBuilder <Cci.SequencePoint> sequencePoints = ArrayBuilder <Cci.SequencePoint> .GetInstance(); bodyOpt.GetSequencePoints(sequencePoints); BlobHandle sequencePointsBlob = SerializeSequencePoints(localSignatureHandleOpt, sequencePoints.ToImmutableAndFree(), _documentIndex, out singleDocumentHandle); _debugMetadataOpt.AddMethodDebugInformation(document: singleDocumentHandle, sequencePoints: sequencePointsBlob); // Unlike native PDB we don't emit an empty root scope. // scopes are already ordered by StartOffset ascending then by EndOffset descending (the longest scope first). if (bodyOpt.LocalScopes.Length == 0) { // TODO: the compiler should produce a scope for each debuggable method _debugMetadataOpt.AddLocalScope( method: methodHandle, importScope: importScopeHandle, variableList: NextHandle(lastLocalVariableHandle), constantList: NextHandle(lastLocalConstantHandle), startOffset: 0, length: bodyOpt.IL.Length); } else { foreach (LocalScope scope in bodyOpt.LocalScopes) { _debugMetadataOpt.AddLocalScope( method: methodHandle, importScope: importScopeHandle, variableList: NextHandle(lastLocalVariableHandle), constantList: NextHandle(lastLocalConstantHandle), startOffset: scope.StartOffset, length: scope.Length); foreach (ILocalDefinition local in scope.Variables) { Debug.Assert(local.SlotIndex >= 0); lastLocalVariableHandle = _debugMetadataOpt.AddLocalVariable( attributes: local.PdbAttributes, index: local.SlotIndex, name: _debugMetadataOpt.GetOrAddString(local.Name)); SerializeLocalInfo(local, lastLocalVariableHandle); } foreach (ILocalDefinition constant in scope.Constants) { var mdConstant = constant.CompileTimeValue; Debug.Assert(mdConstant != null); lastLocalConstantHandle = _debugMetadataOpt.AddLocalConstant( name: _debugMetadataOpt.GetOrAddString(constant.Name), signature: SerializeLocalConstantSignature(constant)); SerializeLocalInfo(constant, lastLocalConstantHandle); } } } var asyncDebugInfo = bodyOpt.AsyncDebugInfo; if (asyncDebugInfo != null) { _debugMetadataOpt.AddStateMachineMethod( moveNextMethod: methodHandle, kickoffMethod: GetMethodDefinitionHandle(asyncDebugInfo.KickoffMethod)); SerializeAsyncMethodSteppingInfo(asyncDebugInfo, methodHandle); } SerializeStateMachineLocalScopes(bodyOpt, methodHandle); // delta doesn't need this information - we use information recorded by previous generation emit if (Context.Module.CommonCompilation.Options.EnableEditAndContinue && IsFullMetadata) { SerializeEncMethodDebugInformation(bodyOpt, methodHandle); } }
public static ImmutableArray <T> ToImmutableOrEmptyAndFree <T>(this ArrayBuilder <T> builderOpt) { return(builderOpt?.ToImmutableAndFree() ?? ImmutableArray <T> .Empty); }
/// <summary> /// Apply post processing steps to any <see cref="ApplyChangesOperation"/>'s. /// </summary> /// <param name="operations">A list of operations.</param> /// <param name="cancellationToken">A cancellation token.</param> /// <returns>A new list of operations with post processing steps applied to any <see cref="ApplyChangesOperation"/>'s.</returns> protected async Task<ImmutableArray<CodeActionOperation>> PostProcessAsync(IEnumerable<CodeActionOperation> operations, CancellationToken cancellationToken) { var arrayBuilder = new ArrayBuilder<CodeActionOperation>(); foreach (var op in operations) { var ac = op as ApplyChangesOperation; if (ac != null) { arrayBuilder.Add(new ApplyChangesOperation(await this.PostProcessChangesAsync(ac.ChangedSolution, cancellationToken).ConfigureAwait(false))); } else { arrayBuilder.Add(op); } } return arrayBuilder.ToImmutableAndFree(); }
// This can only be called after Consolidate internal ImmutableArray <BoundExpression> ToImmutableAndFree() { return(init.ToImmutableAndFree()); }