Exemplo n.º 1
0
        private ImmutableArray <TypeParameterSymbol> MakeTypeParameters(MethodDeclarationSyntax syntax, DiagnosticBag diagnostics)
        {
            Debug.Assert(syntax.TypeParameterList != null);

            OverriddenMethodTypeParameterMapBase typeMap = null;

            if (this.IsOverride)
            {
                typeMap = new OverriddenMethodTypeParameterMap(this);
            }
            else if (this.IsExplicitInterfaceImplementation)
            {
                typeMap = new ExplicitInterfaceMethodTypeParameterMap(this);
            }

            var typeParameters = syntax.TypeParameterList.Parameters;
            var result         = ArrayBuilder <TypeParameterSymbol> .GetInstance();

            for (int ordinal = 0; ordinal < typeParameters.Count; ordinal++)
            {
                var parameter  = typeParameters[ordinal];
                var identifier = parameter.Identifier;
                var location   = identifier.GetLocation();
                var name       = identifier.ValueText;

                // Note: It is not an error to have a type parameter named the same as its enclosing method: void M<M>() {}

                for (int i = 0; i < result.Count; i++)
                {
                    if (name == result[i].Name)
                    {
                        diagnostics.Add(ErrorCode.ERR_DuplicateTypeParameter, location, name);
                        break;
                    }
                }

                var tpEnclosing = ContainingType.FindEnclosingTypeParameter(name);
                if ((object)tpEnclosing != null)
                {
                    // Type parameter '{0}' has the same name as the type parameter from outer type '{1}'
                    diagnostics.Add(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, location, name, tpEnclosing.ContainingType);
                }

                var syntaxRefs    = ImmutableArray.Create(parameter.GetReference());
                var locations     = ImmutableArray.Create(location);
                var typeParameter = (typeMap != null) ?
                                    (TypeParameterSymbol) new SourceOverridingMethodTypeParameterSymbol(
                    typeMap,
                    name,
                    ordinal,
                    locations,
                    syntaxRefs) :
                                    new SourceMethodTypeParameterSymbol(
                    this,
                    name,
                    ordinal,
                    locations,
                    syntaxRefs);

                result.Add(typeParameter);
            }

            return(result.ToImmutableAndFree());
        }
Exemplo n.º 2
0
        private ImmutableArray <TypeParameterSymbol> MakeTypeParameters(DiagnosticBag diagnostics)
        {
            if (declaration.Arity == 0)
            {
                return(ImmutableArray <TypeParameterSymbol> .Empty);
            }

            var typeParameterMismatchReported = false;
            var typeParameterNames            = new string[declaration.Arity];
            var typeParameterVarianceKeywords = new string[declaration.Arity];
            var parameterBuilders1            = new List <List <TypeParameterBuilder> >();

            foreach (var syntaxRef in this.SyntaxReferences)
            {
                var typeDecl   = (CSharpSyntaxNode)syntaxRef.GetSyntax();
                var syntaxTree = syntaxRef.SyntaxTree;

                TypeParameterListSyntax tpl;
                switch (typeDecl.Kind())
                {
                case SyntaxKind.ClassDeclaration:
                case SyntaxKind.StructDeclaration:
                case SyntaxKind.InterfaceDeclaration:
                    tpl = ((TypeDeclarationSyntax)typeDecl).TypeParameterList;
                    break;

                case SyntaxKind.DelegateDeclaration:
                    tpl = ((DelegateDeclarationSyntax)typeDecl).TypeParameterList;
                    break;

                case SyntaxKind.EnumDeclaration:
                default:
                    // there is no such thing as a generic enum, so code should never reach here.
                    throw ExceptionUtilities.UnexpectedValue(typeDecl.Kind());
                }

                var parameterBuilder = new List <TypeParameterBuilder>();
                parameterBuilders1.Add(parameterBuilder);
                int i = 0;
                foreach (var tp in tpl.Parameters)
                {
                    var name         = typeParameterNames[i];
                    var location     = new SourceLocation(tp.Identifier);
                    var varianceKind = typeParameterVarianceKeywords[i];
                    if (name == null)
                    {
                        name         = typeParameterNames[i] = tp.Identifier.ValueText;
                        varianceKind = typeParameterVarianceKeywords[i] = tp.VarianceKeyword.ValueText;
                        for (int j = 0; j < i; j++)
                        {
                            if (name == typeParameterNames[j])
                            {
                                typeParameterMismatchReported = true;
                                diagnostics.Add(ErrorCode.ERR_DuplicateTypeParameter, location, name);
                                goto next;
                            }
                        }

                        if (!ReferenceEquals(ContainingType, null))
                        {
                            var tpEnclosing = ContainingType.FindEnclosingTypeParameter(name);
                            if ((object)tpEnclosing != null)
                            {
                                // Type parameter '{0}' has the same name as the type parameter from outer type '{1}'
                                diagnostics.Add(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, location, name, tpEnclosing.ContainingType);
                            }
                        }
                        next :;
                    }
                    else if (!typeParameterMismatchReported)
                    {
                        // Note: the "this", below, refers to the name of the current class, which includes its type
                        // parameter names.  But the type parameter names have not been computed yet.  Therefore, we
                        // take advantage of the fact that "this" won't undergo "ToString()" until later, when the
                        // diagnostic is printed, by which time the type parameters field will have been filled in.
                        if (varianceKind != tp.VarianceKeyword.ValueText)
                        {
                            // Dev10 reports CS1067, even if names also don't match
                            typeParameterMismatchReported = true;
                            diagnostics.Add(
                                ErrorCode.ERR_PartialWrongTypeParamsVariance,
                                declaration.NameLocations.First(),
                                this); // see comment above
                        }
                        else if (name != tp.Identifier.ValueText)
                        {
                            typeParameterMismatchReported = true;
                            diagnostics.Add(
                                ErrorCode.ERR_PartialWrongTypeParams,
                                declaration.NameLocations.First(),
                                this); // see comment above
                        }
                    }
                    parameterBuilder.Add(new TypeParameterBuilder(syntaxTree.GetReference(tp), this, location));
                    i++;
                }
            }

            var parameterBuilders2 = parameterBuilders1.Transpose(); // type arguments are positional
            var parameters         = parameterBuilders2.Select((builders, i) => builders[0].MakeSymbol(i, builders, diagnostics));

            return(parameters.AsImmutable());
        }