Example #1
0
        internal override CustomAttributesBag <CSharpAttributeData> GetAttributesBag()
        {
            if (lazyCustomAttributesBag == null || !lazyCustomAttributesBag.IsSealed)
            {
                bool lazyAttributesStored = false;

                var sourceMethod = this.ContainingSymbol as SourceMemberMethodSymbol;
                if ((object)sourceMethod == null || (object)sourceMethod.SourcePartialDefinition == null)
                {
                    lazyAttributesStored = LoadAndValidateAttributes(OneOrMany.Create(this.MergedAttributeDeclarationSyntaxLists), ref lazyCustomAttributesBag);
                }
                else
                {
                    var typeParameter = (SourceTypeParameterSymbolBase)sourceMethod.SourcePartialDefinition.TypeParameters[this.ordinal];
                    CustomAttributesBag <CSharpAttributeData> attributesBag = typeParameter.GetAttributesBag();

                    lazyAttributesStored = Interlocked.CompareExchange(ref lazyCustomAttributesBag, attributesBag, null) == null;
                }

                if (lazyAttributesStored)
                {
                    state.NotePartComplete(CompletionPart.Attributes);
                }
            }

            return(lazyCustomAttributesBag);
        }
Example #2
0
        /// <summary>
        /// Returns a bag of applied custom attributes and data decoded from well-known attributes. Returns null if there are no attributes applied on the symbol.
        /// </summary>
        /// <remarks>
        /// Forces binding and decoding of attributes.
        /// </remarks>
        internal virtual CustomAttributesBag <CSharpAttributeData> GetAttributesBag()
        {
            if (_lazyCustomAttributesBag == null || !_lazyCustomAttributesBag.IsSealed)
            {
                bool lazyAttributesStored = false;

                var sourceMethod = this.ContainingSymbol as SourceOrdinaryMethodSymbol;
                if ((object)sourceMethod == null || (object)sourceMethod.SourcePartialDefinition == null)
                {
                    lazyAttributesStored = LoadAndValidateAttributes(
                        OneOrMany.Create(this.MergedAttributeDeclarationSyntaxLists),
                        ref _lazyCustomAttributesBag,
                        binderOpt: (ContainingSymbol as LocalFunctionSymbol)?.SignatureBinder);
                }
                else
                {
                    var typeParameter = (SourceTypeParameterSymbolBase)sourceMethod.SourcePartialDefinition.TypeParameters[_ordinal];
                    CustomAttributesBag <CSharpAttributeData> attributesBag = typeParameter.GetAttributesBag();

                    lazyAttributesStored = Interlocked.CompareExchange(ref _lazyCustomAttributesBag, attributesBag, null) == null;
                }

                if (lazyAttributesStored)
                {
                    _state.NotePartComplete(CompletionPart.Attributes);
                }
            }

            return(_lazyCustomAttributesBag);
        }
Example #3
0
        internal override void ForceComplete(SourceLocation locationOpt, CancellationToken cancellationToken)
        {
            if (!_state.HasComplete(CompletionPart.Attributes))
            {
                _ = GetAttributes();

                // Consider the following items:
                //  1. It is possible for parallel calls to GetAttributes to exist
                //  2. GetAttributes will return when the attributes are available, not when the part is noted
                //     as complete.
                //  3. The thread which actually completes the attributes is the one which must set the CompletionParts.Attributes
                //     value.
                //  4. This call cannot correctly return until this part is set.
                //
                // That is why it is necessary to check this value again.
                //
                // Note: #2 above is common practice amongst all of the symbols.
                //
                // Note: #3 above is an invariant that has existed in the code for some time. It's not clear if this invariant
                // is 100% correct. After inspection though it seems likely to be correct as the code is asserting that
                // SymbolDeclaredEvent is raised before CompletionPart.Attributes is noted as completed. Also this is a common
                // pattern amongst the GetAttributes implementations.
                _state.SpinWaitComplete(CompletionPart.Attributes, cancellationToken);
            }

            _state.NotePartComplete(CompletionPart.All);
        }
Example #4
0
 private AliasSymbol(InContainerBinder binder, NamespaceOrTypeSymbol target, SyntaxToken aliasName, ImmutableArray <Location> locations)
 {
     _aliasName   = aliasName;
     _locations   = locations;
     _aliasTarget = target;
     _binder      = binder;
     _state.NotePartComplete(CompletionPart.AliasTarget);
 }
        protected void LazyMethodChecks()
        {
            if (!state.HasComplete(CompletionPart.FinishMethodChecks))
            {
                // TODO: if this lock ever encloses a potential call to Debugger.NotifyOfCrossThreadDependency,
                // then we should call DebuggerUtilities.CallBeforeAcquiringLock() (see method comment for more
                // details).

                object lockObject = MethodChecksLockObject;
                Debug.Assert(lockObject != null);
                lock (lockObject)
                {
                    if (state.NotePartComplete(CompletionPart.StartMethodChecks))
                    {
                        // By setting StartMethodChecks, we've committed to doing the checks and setting
                        // FinishMethodChecks.  So there is no cancellation supported between one and the other.
                        var diagnostics = BindingDiagnosticBag.GetInstance();
                        try
                        {
                            MethodChecks(diagnostics);
                            AddDeclarationDiagnostics(diagnostics);
                        }
                        finally
                        {
                            state.NotePartComplete(CompletionPart.FinishMethodChecks);
                            diagnostics.Free();
                        }
                    }
                    else
                    {
                        // Either (1) this thread is in the process of completing the method,
                        // or (2) some other thread has beat us to the punch and completed the method.
                        // We can distinguish the two cases here by checking for the FinishMethodChecks
                        // part to be complete, which would only occur if another thread completed this
                        // method.
                        //
                        // The other case, in which this thread is in the process of completing the method,
                        // requires that we return here even though the checks are not complete.  That's because
                        // methods are processed by first populating the return type and parameters by binding
                        // the syntax from source.  Those values are visible to the same thread for the purpose
                        // of computing which methods are implemented and overridden.  But then those values
                        // may be rewritten (by the same thread) to copy down custom modifiers.  In order to
                        // allow the same thread to see the return type and parameters from the syntax (though
                        // they do not yet take on their final values), we return here.

                        // Due to the fact that LazyMethodChecks is potentially reentrant, we must use a
                        // reentrant lock to avoid deadlock and cannot assert that at this point method checks
                        // have completed (state.HasComplete(CompletionPart.FinishMethodChecks)).
                    }
                }
            }
        }
Example #6
0
        // basesBeingResolved is only used to break circular references.
        internal NamespaceOrTypeSymbol GetAliasTarget(ConsList <Symbol> basesBeingResolved)
        {
            if (!state.HasComplete(CompletionPart.AliasTarget))
            {
                // the target is not yet bound. If it is an ordinary alias, bind the target
                // symbol. If it is an extern alias then find the target in the list of metadata references.
                var newDiagnostics = DiagnosticBag.GetInstance();

                NamespaceOrTypeSymbol symbol = this.IsExtern ?
                                               ResolveExternAliasTarget(newDiagnostics) :
                                               ResolveAliasTarget(this.binder, this.aliasTargetName, newDiagnostics, basesBeingResolved);

                if ((object)Interlocked.CompareExchange(ref this.aliasTarget, symbol, null) == null)
                {
                    bool won = ImmutableInterlocked.InterlockedInitialize(ref this.aliasTargetDiagnostics, newDiagnostics.ToReadOnlyAndFree());
                    Debug.Assert(won, "Only one thread can win the alias target CompareExchange");

                    state.NotePartComplete(CompletionPart.AliasTarget);
                    // we do not clear this.aliasTargetName, as another thread might be about to use it for ResolveAliasTarget(...)
                }
                else
                {
                    newDiagnostics.Free();
                    // Wait for diagnostics to have been reported if another thread resolves the alias
                    state.SpinWaitComplete(CompletionPart.AliasTarget, default(CancellationToken));
                }
            }

            return(aliasTarget);
        }
        /// <summary>
        /// Returns a bag of applied custom attributes and data decoded from well-known attributes. Returns null if there are no attributes applied on the symbol.
        /// </summary>
        /// <remarks>
        /// Forces binding and decoding of attributes.
        /// </remarks>
        private CustomAttributesBag <CSharpAttributeData> GetAttributesBag()
        {
            if ((_lazyCustomAttributesBag == null || !_lazyCustomAttributesBag.IsSealed) &&
                LoadAndValidateAttributes(OneOrMany.Create(this.AttributeDeclarationSyntaxList), ref _lazyCustomAttributesBag))
            {
                DeclaringCompilation.SymbolDeclaredEvent(this);
                var wasCompletedThisThread = state.NotePartComplete(CompletionPart.Attributes);
                Debug.Assert(wasCompletedThisThread);
            }

            return(_lazyCustomAttributesBag);
        }
        private TypeParameterBounds GetBounds(ConsList <TypeParameterSymbol> inProgress)
        {
            Debug.Assert(!inProgress.ContainsReference(this));
            Debug.Assert(!inProgress.Any() || ReferenceEquals(inProgress.Head.ContainingSymbol, ContainingSymbol));

            if (ReferenceEquals(_lazyBounds, TypeParameterBounds.Unset))
            {
                var diagnostics = DiagnosticBag.GetInstance();
                var bounds      = ResolveBounds(inProgress, diagnostics);

                if (ReferenceEquals(Interlocked.CompareExchange(ref _lazyBounds, bounds, TypeParameterBounds.Unset), TypeParameterBounds.Unset))
                {
                    //@t-mawind TODO: does this belong elsewhere?
                    CheckAllConstraintTypesNameConcepts(diagnostics);

                    CheckConstraintTypeConstraints(diagnostics);
                    AddDeclarationDiagnostics(diagnostics);
                    _state.NotePartComplete(CompletionPart.TypeParameterConstraints);
                }

                diagnostics.Free();
            }
            return(_lazyBounds);
        }
Example #9
0
        /// <summary>
        /// Returns a bag of applied custom attributes and data decoded from well-known attributes. Returns null if there are no attributes applied on the symbol.
        /// </summary>
        /// <remarks>
        /// Forces binding and decoding of attributes.
        /// </remarks>
        private CustomAttributesBag <CSharpAttributeData> GetAttributesBag()
        {
            var bag = this.lazyCustomAttributesBag;

            if (bag != null && bag.IsSealed)
            {
                return(bag);
            }

            if (LoadAndValidateAttributes(OneOrMany.Create(this.AttributeDeclarationSyntaxList), ref lazyCustomAttributesBag))
            {
                var completed = state.NotePartComplete(CompletionPart.Attributes);
                Debug.Assert(completed);
            }

            Debug.Assert(lazyCustomAttributesBag.IsSealed);
            return(this.lazyCustomAttributesBag);
        }
Example #10
0
        internal override void ForceComplete(SourceLocation locationOpt, CancellationToken cancellationToken)
        {
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var incompletePart = _state.NextIncompletePart;
                switch (incompletePart)
                {
                case CompletionPart.Attributes:
                    GetAttributes();
                    break;

                case CompletionPart.StartValidatingReferencedAssemblies:
                {
                    BindingDiagnosticBag diagnostics = null;

                    if (AnyReferencedAssembliesAreLinked)
                    {
                        diagnostics = BindingDiagnosticBag.GetInstance();
                        ValidateLinkedAssemblies(diagnostics, cancellationToken);
                    }

                    if (_state.NotePartComplete(CompletionPart.StartValidatingReferencedAssemblies))
                    {
                        if (diagnostics != null)
                        {
                            _assemblySymbol.AddDeclarationDiagnostics(diagnostics);
                        }

                        _state.NotePartComplete(CompletionPart.FinishValidatingReferencedAssemblies);
                    }

                    if (diagnostics != null)
                    {
                        diagnostics.Free();
                    }
                }
                break;

                case CompletionPart.FinishValidatingReferencedAssemblies:
                    // some other thread has started validating references (otherwise we would be in the case above) so
                    // we just wait for it to both finish and report the diagnostics.
                    Debug.Assert(_state.HasComplete(CompletionPart.StartValidatingReferencedAssemblies));
                    _state.SpinWaitComplete(CompletionPart.FinishValidatingReferencedAssemblies, cancellationToken);
                    break;

                case CompletionPart.MembersCompleted:
                    this.GlobalNamespace.ForceComplete(locationOpt, cancellationToken);

                    if (this.GlobalNamespace.HasComplete(CompletionPart.MembersCompleted))
                    {
                        _state.NotePartComplete(CompletionPart.MembersCompleted);
                    }
                    else
                    {
                        Debug.Assert(locationOpt != null, "If no location was specified, then the namespace members should be completed");
                        return;
                    }

                    break;

                case CompletionPart.None:
                    return;

                default:
                    // any other values are completion parts intended for other kinds of symbols
                    _state.NotePartComplete(incompletePart);
                    break;
                }

                _state.SpinWaitComplete(incompletePart, cancellationToken);
            }
        }
        public void TestNextCompletionPart()
        {
            SymbolCompletionState state = new SymbolCompletionState();

            Action reader = () =>
            {
                while (state.IncompleteParts != 0)
                {
                    Assert.True(SymbolCompletionState.HasAtMostOneBitSet((int)state.NextIncompletePart));
                }
            };

            Action writers = () =>
            {
                Parallel.For(0, Math.Max(1, Environment.ProcessorCount - 1), t =>
                {
                    Random r = new Random(t);
                    while (state.IncompleteParts != 0)
                    {
                        CompletionPart part = (CompletionPart)(1 << r.Next(8 * sizeof(CompletionPart)));
                        state.NotePartComplete(part);
                    }
                });
            };

            for (int i = 0; i < 1000; i++)
            {
                Parallel.Invoke(reader, writers);
            }
        }