예제 #1
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.TypeParameterConstraints:
                    var constraintTypes = this.ConstraintTypesNoUseSiteDiagnostics;

                    // Nested type parameter references might not be valid in error scenarios.
                    //Debug.Assert(this.ContainingSymbol.IsContainingSymbolOfAllTypeParameters(this.ConstraintTypes));
                    //Debug.Assert(this.ContainingSymbol.IsContainingSymbolOfAllTypeParameters(ImmutableArray<TypeSymbol>.CreateFrom(this.Interfaces)));
                    Debug.Assert(this.ContainingSymbol.IsContainingSymbolOfAllTypeParameters(this.EffectiveBaseClassNoUseSiteDiagnostics));
                    Debug.Assert(this.ContainingSymbol.IsContainingSymbolOfAllTypeParameters(this.DeducedBaseTypeNoUseSiteDiagnostics));
                    break;

                case CompletionPart.None:
                    return;

                default:
                    // any other values are completion parts intended for other kinds of symbols
                    _state.NotePartComplete(CompletionPart.All & ~CompletionPart.TypeParameterSymbolAll);
                    break;
                }

                _state.SpinWaitComplete(incompletePart, cancellationToken);
            }
        }
예제 #2
0
        // basesBeingResolved is only used to break circular references.
        internal NamespaceOrTypeSymbol GetAliasTarget(ConsList <TypeSymbol>?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(_binder, _aliasTargetName, newDiagnostics, basesBeingResolved);

                if ((object?)Interlocked.CompareExchange(ref _aliasTarget, symbol, null) == null)
                {
                    // Note: It's important that we don't call newDiagnosticsToReadOnlyAndFree here. That call
                    // can force the prompt evaluation of lazy initialized diagnostics.  That in turn can
                    // call back into GetAliasTarget on the same thread resulting in a dead lock scenario.
                    bool won = Interlocked.Exchange(ref _aliasTargetDiagnostics, newDiagnostics) == null;
                    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 !);
        }
예제 #3
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(_binder, _aliasTargetName, newDiagnostics, basesBeingResolved);

                if ((object)Interlocked.CompareExchange(ref _aliasTarget, symbol, null) == null)
                {
                    bool won = ImmutableInterlocked.InterlockedInitialize(ref _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);
        }
예제 #4
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);
        }
예제 #5
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);
            }
        }