Пример #1
0
        internal CSDiagnosticInfo Add(ErrorCode code, Location location, params object[] args)
        {
            var info = new CSDiagnosticInfo(code, args);

            Add(info, location);
            return(info);
        }
Пример #2
0
        internal CSDiagnosticInfo Add(ErrorCode code, Location location)
        {
            var info = new CSDiagnosticInfo(code);

            Add(info, location);
            return(info);
        }
Пример #3
0
        internal override void LookupSymbolsInSingleBinder(
            LookupResult result, string name, int arity, ConsList <TypeSymbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo)
        {
            Debug.Assert(result.IsClear);

            // first lookup members of the namespace
            if ((options & LookupOptions.NamespaceAliasesOnly) == 0)
            {
                this.LookupMembersInternal(result, _container, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteInfo);

                if (result.IsMultiViable)
                {
                    if (arity == 0)
                    {
                        // symbols cannot conflict with using alias names
                        if (Next is WithExternAndUsingAliasesBinder withUsingAliases && withUsingAliases.IsUsingAlias(name, originalBinder.IsSemanticModelBinder, basesBeingResolved))
                        {
                            CSDiagnosticInfo diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_ConflictAliasAndMember, name, _container);
                            var error = new ExtendedErrorTypeSymbol((NamespaceOrTypeSymbol)null, name, arity, diagInfo, unreported: true);
                            result.SetFrom(LookupResult.Good(error)); // force lookup to be done w/ error symbol as result
                        }
                    }

                    return;
                }
            }
        }
Пример #4
0
        internal CSDiagnosticInfo Add(ErrorCode code, Location location, ImmutableArray <Symbol> symbols, params object[] args)
        {
            var info = new CSDiagnosticInfo(code, args, symbols, ImmutableArray <Location> .Empty);

            Add(info, location);
            return(info);
        }
Пример #5
0
 internal static CSDiagnosticInfo Add(this DiagnosticBag diagnostics, ErrorCode code, Location location, ImmutableArray<Symbol> symbols, params object[] args)
 {
     var info = new CSDiagnosticInfo(code, args, symbols, ImmutableArray<Location>.Empty);
     var diag = new CSDiagnostic(info, location);
     diagnostics.Add(diag);
     return info;
 }
            private BoundExpression SelectField(SimpleNameSyntax node, BoundExpression receiver, string name, DiagnosticBag diagnostics)
            {
                var receiverType = receiver.Type as NamedTypeSymbol;

                if ((object)receiverType == null || !receiverType.IsAnonymousType)
                {
                    // We only construct transparent query variables using anonymous types, so if we're trying to navigate through
                    // some other type, we must have some hinky query API where the types don't match up as expected.
                    // We should report this as an error of some sort.
                    // TODO: DevDiv #737822 - reword error message and add test.
                    var info = new CSDiagnosticInfo(ErrorCode.ERR_UnsupportedTransparentIdentifierAccess, name, receiver.ExpressionSymbol ?? receiverType);
                    Error(diagnostics, info, node);
                    return(new BoundBadExpression(
                               node,
                               LookupResultKind.Empty,
                               ImmutableArray.Create <Symbol>(receiver.ExpressionSymbol),
                               ImmutableArray.Create <BoundNode>(receiver),
                               new ExtendedErrorTypeSymbol(this.Compilation, "", 0, info)));
                }

                LookupResult             lookupResult       = LookupResult.GetInstance();
                LookupOptions            options            = LookupOptions.MustBeInstance;
                HashSet <DiagnosticInfo> useSiteDiagnostics = null;

                LookupMembersWithFallback(lookupResult, receiver.Type, name, 0, ref useSiteDiagnostics, basesBeingResolved: null, options: options);
                diagnostics.Add(node, useSiteDiagnostics);

                var result = BindMemberOfType(node, node, name, 0, receiver, default(SeparatedSyntaxList <TypeSyntax>), default(ImmutableArray <TypeSymbol>), lookupResult, BoundMethodGroupFlags.None, diagnostics);

                result.WasCompilerGenerated = true;
                lookupResult.Free();
                return(result);
            }
Пример #7
0
 /// <summary>
 /// Add a diagnostic to the bag.
 /// </summary>
 /// <param name="diagnostics"></param>
 /// <param name="code"></param>
 /// <param name="location"></param>
 /// <param name="args"></param>
 /// <returns></returns>
 internal static CSDiagnosticInfo Add(this DiagnosticBag diagnostics, ErrorCode code, Location location, params object[] args)
 {
     var info = new CSDiagnosticInfo(code, args);
     var diag = new CSDiagnostic(info, location);
     diagnostics.Add(diag);
     return info;
 }
            private BoundExpression SelectField(SimpleNameSyntax node, BoundExpression receiver, string name, BindingDiagnosticBag diagnostics)
            {
                var receiverType = receiver.Type as NamedTypeSymbol;

                if ((object)receiverType == null || !receiverType.IsAnonymousType)
                {
                    // We only construct transparent query variables using anonymous types, so if we're trying to navigate through
                    // some other type, we must have some query API where the types don't match up as expected.
                    var info = new CSDiagnosticInfo(ErrorCode.ERR_UnsupportedTransparentIdentifierAccess, name, receiver.ExpressionSymbol ?? receiverType);
                    if (receiver.Type?.IsErrorType() != true)
                    {
                        Error(diagnostics, info, node);
                    }

                    return(new BoundBadExpression(
                               node,
                               LookupResultKind.Empty,
                               ImmutableArray.Create <Symbol>(receiver.ExpressionSymbol),
                               ImmutableArray.Create(BindToTypeForErrorRecovery(receiver)),
                               new ExtendedErrorTypeSymbol(this.Compilation, "", 0, info)));
                }

                LookupResult  lookupResult = LookupResult.GetInstance();
                LookupOptions options      = LookupOptions.MustBeInstance;
                CompoundUseSiteInfo <AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);

                LookupMembersWithFallback(lookupResult, receiver.Type, name, 0, ref useSiteInfo, basesBeingResolved: null, options: options);
                diagnostics.Add(node, useSiteInfo);

                var result = BindMemberOfType(node, node, name, 0, indexed: false, receiver, default(SeparatedSyntaxList <TypeSyntax>), default(ImmutableArray <TypeWithAnnotations>), lookupResult, BoundMethodGroupFlags.None, diagnostics);

                lookupResult.Free();
                return(result);
            }
Пример #9
0
        internal override void LookupSymbolsInSingleBinder(
            LookupResult result, string name, int arity, ConsList <Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(result.IsClear);

            if (IsSubmissionClass)
            {
                this.LookupMembersInternal(result, _container, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);
                return;
            }

            var imports = GetImports(basesBeingResolved);

            // first lookup members of the namespace
            if ((options & LookupOptions.NamespaceAliasesOnly) == 0 && _container != null)
            {
                this.LookupMembersInternal(result, _container, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);

                if (result.IsMultiViable)
                {
                    // symbols cannot conflict with using alias names
                    if (arity == 0 && imports.IsUsingAlias(name, originalBinder.IsSemanticModelBinder))
                    {
                        CSDiagnosticInfo diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_ConflictAliasAndMember, name, _container);
                        var error = new ExtendedErrorTypeSymbol((NamespaceOrTypeSymbol)null, name, arity, diagInfo, unreported: true);
                        result.SetFrom(LookupResult.Good(error)); // force lookup to be done w/ error symbol as result
                    }

                    return;
                }
            }

            // next try using aliases or symbols in imported namespaces
            imports.LookupSymbol(originalBinder, result, name, arity, basesBeingResolved, options, diagnose, ref useSiteDiagnostics);
        }
            private BoundExpression SelectField(SimpleNameSyntax node, BoundExpression receiver, string name, DiagnosticBag diagnostics)
            {
                var receiverType = receiver.Type as NamedTypeSymbol;
                if ((object)receiverType == null || !receiverType.IsAnonymousType)
                {
                    // We only construct transparent query variables using anonymous types, so if we're trying to navigate through
                    // some other type, we must have some hinky query API where the types don't match up as expected.
                    // We should report this as an error of some sort.
                    // TODO: DevDiv #737822 - reword error message and add test.
                    var info = new CSDiagnosticInfo(ErrorCode.ERR_UnsupportedTransparentIdentifierAccess, name, receiver.ExpressionSymbol ?? receiverType);
                    Error(diagnostics, info, node);
                    return new BoundBadExpression(
                        node,
                        LookupResultKind.Empty,
                        ImmutableArray.Create<Symbol>(receiver.ExpressionSymbol),
                        ImmutableArray.Create<BoundNode>(receiver),
                        new ExtendedErrorTypeSymbol(this.Compilation, "", 0, info));
                }

                LookupResult lookupResult = LookupResult.GetInstance();
                LookupOptions options = LookupOptions.MustBeInstance;
                HashSet<DiagnosticInfo> useSiteDiagnostics = null;
                LookupMembersWithFallback(lookupResult, receiver.Type, name, 0, ref useSiteDiagnostics, basesBeingResolved: null, options: options);
                diagnostics.Add(node, useSiteDiagnostics);

                var result = BindMemberOfType(node, node, name, 0, receiver, default(SeparatedSyntaxList<TypeSyntax>), default(ImmutableArray<TypeSymbol>), lookupResult, BoundMethodGroupFlags.None, diagnostics);
                result.WasCompilerGenerated = true;
                lookupResult.Free();
                return result;
            }
Пример #11
0
        internal Symbol XSharpResolveEqualSymbols(Symbol first, Symbol second, ImmutableArray <Symbol> originalSymbols, CSharpSyntaxNode where, DiagnosticBag diagnostics)
        {
            CSDiagnosticInfo info;

            if (first.IsFromCompilation(Compilation) && !second.IsFromCompilation(Compilation))
            {
                info = new CSDiagnosticInfo(ErrorCode.WRN_VulcanAmbiguous, originalSymbols,
                                            new object[] {
                    where,
                    first.Kind.ToString(),
                    new FormattedSymbol(first, SymbolDisplayFormat.CSharpErrorMessageFormat),
                    second.Kind.ToString(),
                    new FormattedSymbol(second, SymbolDisplayFormat.CSharpErrorMessageFormat)
                });
                diagnostics.Add(info, where.Location);
                return(first);
            }
            else if (second.IsFromCompilation(Compilation) && !first.IsFromCompilation(Compilation))
            {
                info = new CSDiagnosticInfo(ErrorCode.WRN_VulcanAmbiguous, originalSymbols,
                                            new object[] {
                    where,
                    first.Kind.ToString(),
                    new FormattedSymbol(second, SymbolDisplayFormat.CSharpErrorMessageFormat),
                    second.Kind.ToString(),
                    new FormattedSymbol(first, SymbolDisplayFormat.CSharpErrorMessageFormat)
                });
                diagnostics.Add(info, where.Location);
                return(second);
            }
            else if (first.Kind == second.Kind &&
                     !string.Equals(first.Name, second.Name) &&
                     string.Equals(first.Name, second.Name, StringComparison.OrdinalIgnoreCase))
            {
                // they only differ in case
                info = new CSDiagnosticInfo(ErrorCode.WRN_VulcanAmbiguous, originalSymbols,
                                            new object[] {
                    where,
                    first.Kind.ToString(),
                    new FormattedSymbol(first, SymbolDisplayFormat.CSharpErrorMessageFormat),
                    second.Kind.ToString(),
                    new FormattedSymbol(second, SymbolDisplayFormat.CSharpErrorMessageFormat)
                });
                diagnostics.Add(info, where.Location);
                return(first);
            }
            else
            {
                info = new CSDiagnosticInfo(ErrorCode.WRN_VulcanAmbiguous, originalSymbols,
                                            new object[] {
                    where,
                    first.Kind.ToString(),
                    new FormattedSymbol(first, SymbolDisplayFormat.CSharpErrorMessageFormat),
                    second.Kind.ToString(),
                    new FormattedSymbol(second, SymbolDisplayFormat.CSharpErrorMessageFormat)
                });
                diagnostics.Add(info, where.Location);
                return(first);
            }
        }
        /// <summary>
        /// Add a diagnostic to the bag.
        /// </summary>
        /// <param name="diagnostics"></param>
        /// <param name="code"></param>
        /// <param name="location"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        internal static CSDiagnosticInfo Add(this DiagnosticBag diagnostics, ErrorCode code, Location location, params object[] args)
        {
            var info = new CSDiagnosticInfo(code, args);
            var diag = new CSDiagnostic(info, location);

            diagnostics.Add(diag);
            return(info);
        }
        internal static CSDiagnosticInfo Add(this DiagnosticBag diagnostics, ErrorCode code, Location location, ImmutableArray <Symbol> symbols, params object[] args)
        {
            var info = new CSDiagnosticInfo(code, args, symbols, ImmutableArray <Location> .Empty);
            var diag = new CSDiagnostic(info, location);

            diagnostics.Add(diag);
            return(info);
        }
Пример #14
0
        /// <summary>
        /// Reports an error if the await expression did not occur in an async context.
        /// </summary>
        /// <returns>True if the expression contains errors.</returns>
        private bool ReportBadAwaitWithoutAsync(SyntaxNode node, DiagnosticBag diagnostics)
        {
            DiagnosticInfo info = null;
            var            containingMemberOrLambda = this.ContainingMemberOrLambda;

            if ((object)containingMemberOrLambda != null)
            {
                switch (containingMemberOrLambda.Kind)
                {
                case SymbolKind.Field:
                    if (containingMemberOrLambda.ContainingType.IsScriptClass)
                    {
                        if (((FieldSymbol)containingMemberOrLambda).IsStatic)
                        {
                            info = new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitInStaticVariableInitializer);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    break;

                case SymbolKind.Method:
                    var method = (MethodSymbol)containingMemberOrLambda;
                    if (method.IsAsync)
                    {
                        return(false);
                    }
                    if (method.MethodKind == MethodKind.AnonymousFunction)
                    {
                        info = method.IsImplicitlyDeclared ?
                               // The await expression occurred in a query expression:
                               new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitInQuery) :
                               new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutAsyncLambda, ((LambdaSymbol)method).MessageID.Localize());
                    }
                    else
                    {
                        info = method.ReturnsVoid ?
                               new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod) :
                               new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, method.ReturnType.TypeSymbol);
                    }
                    break;
                }
            }
            if (info == null)
            {
                info = new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutAsync);
            }
            Error(diagnostics, info, node);
            return(true);
        }
Пример #15
0
        public override Diagnostic CreateDiagnostic(
            int code,
            Location location,
            params object[] args
            )
        {
            var info = new CSDiagnosticInfo(
                (ErrorCode)code,
                args,
                ImmutableArray <Symbol> .Empty,
                ImmutableArray <Location> .Empty
                );

            return(new CSDiagnostic(info, location));
        }
Пример #16
0
        /// <summary>
        /// Derive error info from a type symbol.
        /// </summary>
        internal bool DeriveUseSiteDiagnosticFromType(ref DiagnosticInfo result, TypeSymbol type)
        {
            DiagnosticInfo info = type.GetUseSiteDiagnostic();

            if (info != null)
            {
                if (info.Code == (int)ErrorCode.ERR_BogusType)
                {
                    switch (this.Kind)
                    {
                    case SymbolKind.Field:
                    case SymbolKind.Method:
                    case SymbolKind.Property:
                    case SymbolKind.Event:
                        info = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this);
                        break;
                    }
                }
            }

            return(MergeUseSiteDiagnostics(ref result, info));
        }
        private void FindEntryPoint(CancellationToken cancellationToken, out MethodSymbol entryPoint, out ImmutableArray<Diagnostic> sealedDiagnostics)
        {
            using (Logger.LogBlock(FunctionId.CSharp_Compilation_FindEntryPoint, message: this.AssemblyName, cancellationToken: cancellationToken))
            {
                DiagnosticBag diagnostics = DiagnosticBag.GetInstance();

                try
                {
                    entryPoint = null;

                    ArrayBuilder<MethodSymbol> entryPointCandidates;
                    NamedTypeSymbol mainType;

                    string mainTypeName = this.Options.MainTypeName;
                    NamespaceSymbol globalNamespace = this.SourceModule.GlobalNamespace;

                    if (mainTypeName != null)
                    {
                        // Global code is the entry point, ignore all other Mains.
                        // TODO: don't special case scripts (DevDiv #13119).
                        if ((object)this.ScriptClass != null)
                        {
                            // CONSIDER: we could use the symbol instead of just the name.
                            diagnostics.Add(ErrorCode.WRN_MainIgnored, NoLocation.Singleton, mainTypeName);
                            return;
                        }

                        var mainTypeOrNamespace = globalNamespace.GetNamespaceOrTypeByQualifiedName(mainTypeName.Split('.')).OfMinimalArity();
                        if ((object)mainTypeOrNamespace == null)
                        {
                            diagnostics.Add(ErrorCode.ERR_MainClassNotFound, NoLocation.Singleton, mainTypeName);
                            return;
                        }

                        mainType = mainTypeOrNamespace as NamedTypeSymbol;
                        if ((object)mainType == null || mainType.IsGenericType || (mainType.TypeKind != TypeKind.Class && mainType.TypeKind != TypeKind.Struct))
                        {
                            diagnostics.Add(ErrorCode.ERR_MainClassNotClass, mainTypeOrNamespace.Locations.First(), mainTypeOrNamespace);
                            return;
                        }

                        entryPointCandidates = ArrayBuilder<MethodSymbol>.GetInstance();
                        EntryPointCandidateFinder.FindCandidatesInSingleType(mainType, entryPointCandidates, cancellationToken);

                        // NOTE: Any return after this point must free entryPointCandidates.
                    }
                    else
                    {
                        mainType = null;

                        entryPointCandidates = ArrayBuilder<MethodSymbol>.GetInstance();
                        EntryPointCandidateFinder.FindCandidatesInNamespace(globalNamespace, entryPointCandidates, cancellationToken);

                        // NOTE: Any return after this point must free entryPointCandidates.

                        // global code is the entry point, ignore all other Mains:
                        if ((object)this.ScriptClass != null)
                        {
                            foreach (var main in entryPointCandidates)
                            {
                                diagnostics.Add(ErrorCode.WRN_MainIgnored, main.Locations.First(), main);
                            }

                            entryPointCandidates.Free();
                            return;
                        }
                    }

                    DiagnosticBag warnings = DiagnosticBag.GetInstance();
                    var viableEntryPoints = ArrayBuilder<MethodSymbol>.GetInstance();
                    foreach (var candidate in entryPointCandidates)
                    {
                        if (!candidate.HasEntryPointSignature())
                        {
                            // a single error for partial methods:
                            warnings.Add(ErrorCode.WRN_InvalidMainSig, candidate.Locations.First(), candidate);
                            continue;
                        }

                        if (candidate.IsGenericMethod || candidate.ContainingType.IsGenericType)
                        {
                            // a single error for partial methods:
                            warnings.Add(ErrorCode.WRN_MainCantBeGeneric, candidate.Locations.First(), candidate);
                            continue;
                        }

                        if (candidate.IsAsync)
                        {
                            diagnostics.Add(ErrorCode.ERR_MainCantBeAsync, candidate.Locations.First(), candidate);
                        }

                        viableEntryPoints.Add(candidate);
                    }

                    if ((object)mainType == null || viableEntryPoints.Count == 0)
                    {
                        diagnostics.AddRange(warnings);
                    }

                    warnings.Free();

                    if (viableEntryPoints.Count == 0)
                    {
                        if ((object)mainType == null)
                        {
                            diagnostics.Add(ErrorCode.ERR_NoEntryPoint, NoLocation.Singleton);
                        }
                        else
                        {
                            diagnostics.Add(ErrorCode.ERR_NoMainInClass, mainType.Locations.First(), mainType);
                        }

                    }
                    else if (viableEntryPoints.Count > 1)
                    {
                        viableEntryPoints.Sort(LexicalOrderSymbolComparer.Instance);
                        var info = new CSDiagnosticInfo(
                             ErrorCode.ERR_MultipleEntryPoints,
                             args: SpecializedCollections.EmptyArray<object>(),
                             symbols: viableEntryPoints.OfType<Symbol>().AsImmutable(),
                             additionalLocations: viableEntryPoints.Select(m => m.Locations.First()).OfType<Location>().AsImmutable());

                        diagnostics.Add(new CSDiagnostic(info, viableEntryPoints.First().Locations.First()));
                    }
                    else
                    {
                        entryPoint = viableEntryPoints[0];
                    }

                    viableEntryPoints.Free();
                    entryPointCandidates.Free();
                }
                finally
                {
                    sealedDiagnostics = diagnostics.ToReadOnlyAndFree();
                }
            }
        }
Пример #18
0
        internal override void LookupSymbolsInSingleBinder(
            LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(result.IsClear);

            if (_container.IsSubmissionClass)
            {
                this.LookupMembersInternal(result, _container, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);
                return;
            }

            var imports = GetImports(basesBeingResolved);

            // first lookup members of the namespace
            if ((options & LookupOptions.NamespaceAliasesOnly) == 0)
            {
                this.LookupMembersInternal(result, _container, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);

                if (result.IsMultiViable)
                {
                    // symbols cannot conflict with using alias names
                    if (arity == 0 && imports.IsUsingAlias(name, originalBinder.IsSemanticModelBinder))
                    {
                        CSDiagnosticInfo diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_ConflictAliasAndMember, name, _container);
                        var error = new ExtendedErrorTypeSymbol((NamespaceOrTypeSymbol)null, name, arity, diagInfo, unreported: true);
                        result.SetFrom(LookupResult.Good(error)); // force lookup to be done w/ error symbol as result
                    }

                    return;
                }
            }

            // next try using aliases or symbols in imported namespaces
            imports.LookupSymbol(originalBinder, result, name, arity, basesBeingResolved, options, diagnose, ref useSiteDiagnostics);
        }
 private void AddDiagnostic(ErrorCode code, Location location, params object[] args)
 {
     var info = new CSDiagnosticInfo(code, args, ImmutableArray<Symbol>.Empty, ImmutableArray<Location>.Empty);
     var diag = new CSDiagnostic(info, location);
     this.diagnostics.Enqueue(diag);
 }
Пример #20
0
        private bool VOBetterFunctionMember <TMember>(
            MemberResolutionResult <TMember> m1,
            MemberResolutionResult <TMember> m2,
            ArrayBuilder <BoundExpression> arguments,
            out BetterResult result,
            out HashSet <DiagnosticInfo> useSiteDiagnostics
            )
            where TMember : Symbol
        {
            result = BetterResult.Neither;
            bool Ambiguous = false;

            // Prefer the member not declared in VulcanRT, if applicable
            useSiteDiagnostics = null;
            if (Compilation.Options.HasRuntime)
            {
                var asm1 = m1.Member.ContainingAssembly;
                var asm2 = m2.Member.ContainingAssembly;
                if (asm1 != asm2)
                {
                    // prefer XSharpCore over XSharpVO, so typed versions get preference over untyped versions
                    //if (asm1.IsXSharpCore() && asm2.IsXSharpVO())
                    //{
                    //    result = BetterResult.Left;
                    //    return true;
                    //}
                    // prefer non runtime over runtime to allow overriding built-in functions
                    if (asm1.IsRT() != asm2.IsRT())
                    {
                        if (asm1.IsRT())
                        {
                            result = BetterResult.Right;
                            return(true);
                        }
                        else if (asm2.IsRT())
                        {
                            result = BetterResult.Left;
                            return(true);
                        }
                    }
                    // prefer functions/method in the current assembly over external methods
                    if (asm1.IsFromCompilation(Compilation))
                    {
                        result = BetterResult.Left;
                        return(true);
                    }
                    if (asm2.IsFromCompilation(Compilation))
                    {
                        result = BetterResult.Right;
                        return(true);
                    }
                }
                if (m1.Member.HasClipperCallingConvention() != m2.Member.HasClipperCallingConvention())
                {
                    if (m1.Member.HasClipperCallingConvention())
                    {
                        result = BetterResult.Right;
                    }
                    else
                    {
                        result = BetterResult.Left;
                    }
                    return(true);
                }
                if (m1.Member.GetParameterCount() == m2.Member.GetParameterCount())
                {
                    // In case of 2 methods with the same # of parameters
                    // we have different / extended rules compared to C#
                    var parsLeft   = m1.Member.GetParameters();
                    var parsRight  = m2.Member.GetParameters();
                    var usualType  = Compilation.UsualType();
                    var objectType = Compilation.GetSpecialType(SpecialType.System_Object);
                    var len        = parsLeft.Length;
                    if (arguments.Count < len)
                    {
                        len = arguments.Count;
                    }

                    bool equalLeft  = true;
                    bool equalRight = true;
                    // check if all left types are equal
                    if (parsLeft.Length == arguments.Count)
                    {
                        for (int i = 0; i < len; i++)
                        {
                            var parLeft = parsLeft[i];
                            var arg     = arguments[i];
                            if (parLeft.Type != arg.Type)
                            {
                                equalLeft = false;
                                break;
                            }
                        }
                    }
                    // check if all right types are equal
                    if (parsRight.Length == arguments.Count)
                    {
                        for (int i = 0; i < len; i++)
                        {
                            var parRight = parsRight[i];
                            var arg      = arguments[i];
                            if (parRight.Type != arg.Type)
                            {
                                equalRight = false;
                                break;
                            }
                        }
                    }
                    // Only exit here when one of the two is better than the other
                    if (equalLeft && !equalRight)
                    {
                        result = BetterResult.Left;
                        return(true);
                    }
                    if (equalRight && !equalLeft)
                    {
                        result = BetterResult.Right;
                        return(true);
                    }
                    for (int i = 0; i < len; i++)
                    {
                        var  parLeft       = parsLeft[i];
                        var  parRight      = parsRight[i];
                        var  refLeft       = parLeft.RefKind;
                        var  refRight      = parRight.RefKind;
                        var  arg           = arguments[i];
                        bool argCanBeByRef = arg.Kind == BoundKind.AddressOfOperator;
                        var  argType       = arg.Type;
                        if (argCanBeByRef)
                        {
                            var bao = arg as BoundAddressOfOperator;
                            argType = bao.Operand.Type;
                        }

                        if (parLeft.Type != parRight.Type || refLeft != refRight)
                        {
                            // Prefer the method with a more specific parameter which is not an array type over USUAL
                            if (parLeft.Type == usualType && argType != usualType && !parRight.Type.IsArray())
                            {
                                result = BetterResult.Right;
                                return(true);
                            }
                            if (parRight.Type == usualType && argType != usualType && !parLeft.Type.IsArray())
                            {
                                result = BetterResult.Left;
                                return(true);
                            }
                            // Prefer the method with Object type over the one with Object[] type
                            if (parLeft.Type == objectType && parRight.Type.IsArray() && ((ArrayTypeSymbol)parRight.Type).ElementType == objectType)
                            {
                                result = BetterResult.Left;
                                return(true);
                            }
                            if (parRight.Type == objectType && parLeft.Type.IsArray() && ((ArrayTypeSymbol)parLeft.Type).ElementType == objectType)
                            {
                                result = BetterResult.Right;
                                return(true);
                            }
                            // Now check for REF parameters and possible REF arguments
                            if (argCanBeByRef)
                            {
                                var op     = arg as BoundAddressOfOperator;
                                var opType = op?.Operand?.Type;
                                if (refLeft == RefKind.Ref && opType == parLeft.Type)
                                {
                                    result = BetterResult.Left;
                                    return(true);
                                }
                                if (refRight == RefKind.Ref && opType == parRight.Type)
                                {
                                    result = BetterResult.Right;
                                    return(true);
                                }
                                if (refLeft != refRight)
                                {
                                    if (refLeft == RefKind.Ref)
                                    {
                                        result = BetterResult.Left;
                                        return(true);
                                    }
                                    if (refRight == RefKind.Ref)
                                    {
                                        result = BetterResult.Right;
                                        return(true);
                                    }
                                }
                            }
                            if (refLeft != refRight)
                            {
                                if (parLeft.Type == argType && refLeft != RefKind.None && argCanBeByRef)
                                {
                                    result = BetterResult.Left;
                                    return(true);
                                }
                                if (parRight.Type == argType && refRight != RefKind.None && argCanBeByRef)
                                {
                                    result = BetterResult.Right;
                                    return(true);
                                }
                                if (parLeft.Type == argType && refLeft == RefKind.None && !argCanBeByRef)
                                {
                                    result = BetterResult.Left;
                                    return(true);
                                }
                                if (parRight.Type == argType && refRight == RefKind.None && !argCanBeByRef)
                                {
                                    result = BetterResult.Right;
                                    return(true);
                                }
                            }
                            // now fall back to original type (and not addressof type)
                            argType = arg.Type;
                            // Handle passing Enum values to methods that have a non enum parameter
                            if (argType?.TypeKind == TypeKind.Enum)
                            {
                                // First check if they have the enum type itself
                                if (argType == parLeft.Type)
                                {
                                    result = BetterResult.Left;
                                    return(true);
                                }
                                if (argType == parRight.Type)
                                {
                                    result = BetterResult.Right;
                                    return(true);
                                }
                                // Then check the underlying type
                                argType = argType.EnumUnderlyingType();
                                if (argType == parLeft.Type)
                                {
                                    result = BetterResult.Left;
                                    return(true);
                                }
                                if (argType == parRight.Type)
                                {
                                    result = BetterResult.Right;
                                    return(true);
                                }
                            }
                            if (argType == parLeft.Type)
                            {
                                result = BetterResult.Left;
                                return(true);
                            }
                            if (argType == parRight.Type)
                            {
                                result = BetterResult.Right;
                                return(true);
                            }
                            // VoFloat prefers overload with double over all other conversions
                            if (argType == Compilation.FloatType())
                            {
                                var doubleType = Compilation.GetSpecialType(SpecialType.System_Double);
                                if (parLeft.Type == doubleType)
                                {
                                    result = BetterResult.Left;
                                    return(true);
                                }
                                if (parRight.Type == doubleType)
                                {
                                    result = BetterResult.Right;
                                    return(true);
                                }
                            }
                            // handle case where argument is usual and the method is not usual
                            // prefer method with "native VO" parameter type
                            if (argType == Compilation.UsualType())
                            {
                                // no need to check if parleft or parright are usual that was checked above
                                if (parLeft.Type != parRight.Type)
                                {
                                    // is there an VO style conversion possible ?
                                    var leftConvert  = parLeft.Type.IsValidVOUsualType(Compilation);
                                    var rightConvert = parRight.Type.IsValidVOUsualType(Compilation);
                                    if (leftConvert != rightConvert)
                                    {
                                        // One is a valid conversion, the other is not.
                                        if (leftConvert)
                                        {
                                            result = BetterResult.Left;
                                        }
                                        else
                                        {
                                            result = BetterResult.Right;
                                        }
                                        return(true);
                                    }
                                }
                            }
                        }
                    }
                }
                // when both methods are in a functions class from different assemblies
                // pick the first one in the references list
                //
                if (asm1 != asm2 &&
                    string.Equals(m1.Member.ContainingType.Name, XSharpSpecialNames.FunctionsClass, XSharpString.Comparison) &&
                    string.Equals(m2.Member.ContainingType.Name, XSharpSpecialNames.FunctionsClass, XSharpString.Comparison))
                {
                    foreach (var reference in Compilation.ReferencedAssemblyNames)
                    {
                        if (reference.Name == asm1.Name)
                        {
                            result    = BetterResult.Left;
                            Ambiguous = true;
                        }
                        if (reference.Name == asm2.Name)
                        {
                            result    = BetterResult.Right;
                            Ambiguous = true;
                        }
                        if (Ambiguous)
                        {
                            TMember r1, r2;
                            if (result == BetterResult.Left)
                            {
                                r1 = m1.Member;
                                r2 = m2.Member;
                            }
                            else
                            {
                                r1 = m2.Member;
                                r2 = m1.Member;
                            }

                            var info = new CSDiagnosticInfo(ErrorCode.WRN_VulcanAmbiguous,
                                                            new object[] {
                                r1.Name,
                                r1.Kind.ToString(),
                                new FormattedSymbol(r1, SymbolDisplayFormat.CSharpErrorMessageFormat),
                                r2.Kind.ToString(),
                                new FormattedSymbol(r2, SymbolDisplayFormat.CSharpErrorMessageFormat)
                            });
                            useSiteDiagnostics = new HashSet <DiagnosticInfo>();
                            useSiteDiagnostics.Add(info);
                            return(true);
                        }
                    }
                }
            }


            // generate warning that function takes precedence over static method
            var func1 = m1.Member.ContainingType.Name.EndsWith("Functions");
            var func2 = m2.Member.ContainingType.Name.EndsWith("Functions");

            if (func1 && !func2)
            {
                result = BetterResult.Left;
                var info = new CSDiagnosticInfo(ErrorCode.WRN_FunctionsTakePrecedenceOverMethods,
                                                new object[] {
                    m1.Member.Name,
                    new FormattedSymbol(m1.Member, SymbolDisplayFormat.CSharpErrorMessageFormat),
                    new FormattedSymbol(m2.Member, SymbolDisplayFormat.CSharpErrorMessageFormat),
                    m1.Member.Kind.ToString()
                });
                useSiteDiagnostics = new HashSet <DiagnosticInfo>();
                useSiteDiagnostics.Add(info);
            }
            if (func2 && !func1)
            {
                result = BetterResult.Right;
                var info = new CSDiagnosticInfo(ErrorCode.WRN_FunctionsTakePrecedenceOverMethods,
                                                new object[] {
                    m2.Member.Name,
                    new FormattedSymbol(m2.Member, SymbolDisplayFormat.CSharpErrorMessageFormat),
                    new FormattedSymbol(m1.Member, SymbolDisplayFormat.CSharpErrorMessageFormat),
                    m2.Member.Kind.ToString()
                });
                useSiteDiagnostics = new HashSet <DiagnosticInfo>();
                useSiteDiagnostics.Add(info);
            }
            return(false);
        }
Пример #21
0
 public override Diagnostic CreateDiagnostic(int code, Location location, params object[] args)
 {
     var info = new CSDiagnosticInfo((ErrorCode)code, args, ImmutableArray<Symbol>.Empty, ImmutableArray<Location>.Empty);
     return new CSDiagnostic(info, location);
 }
Пример #22
0
        /// <summary>
        /// This method handles duplicate types in a few different ways:
        /// - for types before C# 7, the first candidate is returned with a warning
        /// - for types after C# 7, the type is considered missing
        /// - in both cases, when BinderFlags.IgnoreCorLibraryDuplicatedTypes is set, any duplicate coming from corlib will be ignored (ie not count as a duplicate)
        /// </summary>
        internal NamedTypeSymbol GetWellKnownType(WellKnownType type)
        {
            Debug.Assert(type.IsValid());

            bool ignoreCorLibraryDuplicatedTypes = this.Options.TopLevelBinderFlags.Includes(BinderFlags.IgnoreCorLibraryDuplicatedTypes);

            int index = (int)type - (int)WellKnownType.First;

            if (_lazyWellKnownTypes == null || (object)_lazyWellKnownTypes[index] == null)
            {
                if (_lazyWellKnownTypes == null)
                {
                    Interlocked.CompareExchange(ref _lazyWellKnownTypes, new NamedTypeSymbol[(int)WellKnownTypes.Count], null);
                }

                string          mdName   = type.GetMetadataName();
                var             warnings = DiagnosticBag.GetInstance();
                NamedTypeSymbol result;
                (AssemblySymbol, AssemblySymbol)conflicts = default;

                if (IsTypeMissing(type))
                {
                    result = null;
                }
                else
                {
                    // well-known types introduced before CSharp7 allow lookup ambiguity and report a warning
                    DiagnosticBag legacyWarnings = (type <= WellKnownType.CSharp7Sentinel) ? warnings : null;
                    result = this.Assembly.GetTypeByMetadataName(
                        mdName, includeReferences: true, useCLSCompliantNameArityEncoding: true, isWellKnownType: true, conflicts: out conflicts,
                        warnings: legacyWarnings, ignoreCorLibraryDuplicatedTypes: ignoreCorLibraryDuplicatedTypes);
                }

                if ((object)result == null)
                {
                    // TODO: should GetTypeByMetadataName rather return a missing symbol?
                    MetadataTypeName emittedName = MetadataTypeName.FromFullName(mdName, useCLSCompliantNameArityEncoding: true);
                    if (type.IsValueTupleType())
                    {
                        CSDiagnosticInfo errorInfo;
                        if (conflicts.Item1 is null)
                        {
                            Debug.Assert(conflicts.Item2 is null);
                            errorInfo = new CSDiagnosticInfo(ErrorCode.ERR_PredefinedValueTupleTypeNotFound, emittedName.FullName);
                        }
                        else
                        {
                            errorInfo = new CSDiagnosticInfo(ErrorCode.ERR_PredefinedValueTupleTypeAmbiguous3, emittedName.FullName, conflicts.Item1, conflicts.Item2);
                        }

                        result = new MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(this.Assembly.Modules[0], ref emittedName, errorInfo, type);
                    }
                    else
                    {
                        result = new MissingMetadataTypeSymbol.TopLevel(this.Assembly.Modules[0], ref emittedName, type);
                    }
                }

                if ((object)Interlocked.CompareExchange(ref _lazyWellKnownTypes[index], result, null) != null)
                {
                    Debug.Assert(
                        result == _lazyWellKnownTypes[index] || (_lazyWellKnownTypes[index].IsErrorType() && result.IsErrorType())
                        );
                }
                else
                {
                    AdditionalCodegenWarnings.AddRange(warnings);
                }

                warnings.Free();
            }

            return(_lazyWellKnownTypes[index]);
        }
Пример #23
0
 /// <summary>
 /// Reports an error if the await expression did not occur in an async context.
 /// </summary>
 /// <returns>True if the expression contains errors.</returns>
 private bool ReportBadAwaitWithoutAsync(SyntaxNode node, DiagnosticBag diagnostics)
 {
     DiagnosticInfo info = null;
     var containingMemberOrLambda = this.ContainingMemberOrLambda;
     if ((object)containingMemberOrLambda != null)
     {
         switch (containingMemberOrLambda.Kind)
         {
             case SymbolKind.Field:
                 if (containingMemberOrLambda.ContainingType.IsScriptClass)
                 {
                     if (((FieldSymbol)containingMemberOrLambda).IsStatic)
                     {
                         info = new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitInStaticVariableInitializer);
                     }
                     else
                     {
                         return false;
                     }
                 }
                 break;
             case SymbolKind.Method:
                 var method = (MethodSymbol)containingMemberOrLambda;
                 if (method.IsAsync)
                 {
                     return false;
                 }
                 if (method.MethodKind == MethodKind.AnonymousFunction)
                 {
                     info = method.IsImplicitlyDeclared ?
                         // The await expression occurred in a query expression:
                         new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitInQuery) :
                         new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutAsyncLambda, ((LambdaSymbol)method).MessageID.Localize());
                 }
                 else
                 {
                     info = method.ReturnsVoid ?
                         new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod) :
                         new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, method.ReturnType);
                 }
                 break;
         }
     }
     if (info == null)
     {
         info = new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutAsync);
     }
     Error(diagnostics, info, node);
     return true;
 }
Пример #24
0
 private void AddDiagnostic(ErrorCode code, Location location)
 {
     var info = new CSDiagnosticInfo(code);
     var diag = new CSDiagnostic(info, location);
     _diagnostics.Enqueue(diag);
 }
Пример #25
0
 private void AddDiagnostic(ErrorCode code, Location location, params object[] args)
 {
     var info = new CSDiagnosticInfo(code, args);
     var diag = new CSDiagnostic(info, location);
     _diagnostics.Enqueue(diag);
 }