internal CSDiagnosticInfo Add(ErrorCode code, Location location, params object[] args) { var info = new CSDiagnosticInfo(code, args); Add(info, location); return(info); }
internal CSDiagnosticInfo Add(ErrorCode code, Location location) { var info = new CSDiagnosticInfo(code); Add(info, location); return(info); }
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; } } }
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); }
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); }
/// <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); }
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; }
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); }
/// <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); }
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)); }
/// <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(); } } }
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); }
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); }
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); }
/// <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]); }
/// <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; }
private void AddDiagnostic(ErrorCode code, Location location) { var info = new CSDiagnosticInfo(code); var diag = new CSDiagnostic(info, location); _diagnostics.Enqueue(diag); }
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); }