| File: Microsoft\CSharp\RuntimeBinder\Errors\ErrorHandling.cs | Web Access |
| Project: src\runtime\src\libraries\Microsoft.CSharp\src\Microsoft.CSharp.csproj (Microsoft.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using Microsoft.CSharp.RuntimeBinder.Semantics; namespace Microsoft.CSharp.RuntimeBinder.Errors { internal static class ErrorHandling { [RequiresDynamicCode(Binder.DynamicCodeWarning)] public static RuntimeBinderException Error(ErrorCode id, params ErrArg[] args) { // Create an argument array manually using the type information in the ErrArgs. string[] prgpsz = new string[args.Length]; int[] prgiarg = new int[args.Length]; int ppsz = 0; int piarg = 0; int cargUnique = 0; UserStringBuilder builder = default; for (int iarg = 0; iarg < args.Length; iarg++) { ErrArg arg = args[iarg]; // If the NoStr bit is set we don't add it to prgpsz. if (0 != (arg.eaf & ErrArgFlags.NoStr)) continue; if (!builder.ErrArgToString(out prgpsz[ppsz], arg, out bool fUserStrings)) { if (arg.eak == ErrArgKind.Int) { prgpsz[ppsz] = arg.n.ToString(CultureInfo.InvariantCulture); } } ppsz++; int iargRec; if (!fUserStrings || 0 == (arg.eaf & ErrArgFlags.Unique)) { iargRec = -1; } else { iargRec = iarg; cargUnique++; } prgiarg[piarg] = iargRec; piarg++; } int cpsz = ppsz; if (cargUnique > 1) { // Copy the strings over to another buffer. string[] prgpszNew = new string[cpsz]; Array.Copy(prgpsz, prgpszNew, cpsz); for (int i = 0; i < cpsz; i++) { if (prgiarg[i] < 0 || prgpszNew[i] != prgpsz[i]) continue; ErrArg arg = args[prgiarg[i]]; Debug.Assert(0 != (arg.eaf & ErrArgFlags.Unique) && 0 == (arg.eaf & ErrArgFlags.NoStr)); Symbol sym = null; CType pType = null; switch (arg.eak) { case ErrArgKind.Sym: sym = arg.sym; break; case ErrArgKind.Type: pType = arg.pType; break; case ErrArgKind.SymWithType: sym = arg.swtMemo.sym; break; case ErrArgKind.MethWithInst: sym = arg.mpwiMemo.sym; break; default: Debug.Fail("Shouldn't be here!"); continue; } bool fMunge = false; for (int j = i + 1; j < cpsz; j++) { if (prgiarg[j] < 0) continue; Debug.Assert(0 != (args[prgiarg[j]].eaf & ErrArgFlags.Unique)); if (prgpsz[i] != prgpsz[j]) continue; // The strings are identical. If they are the same symbol, leave them alone. // Otherwise, munge both strings. If j has already been munged, just make // sure we munge i. if (prgpszNew[j] != prgpsz[j]) { fMunge = true; continue; } ErrArg arg2 = args[prgiarg[j]]; Debug.Assert(0 != (arg2.eaf & ErrArgFlags.Unique) && 0 == (arg2.eaf & ErrArgFlags.NoStr)); Symbol sym2 = null; CType pType2 = null; switch (arg2.eak) { case ErrArgKind.Sym: sym2 = arg2.sym; break; case ErrArgKind.Type: pType2 = arg2.pType; break; case ErrArgKind.SymWithType: sym2 = arg2.swtMemo.sym; break; case ErrArgKind.MethWithInst: sym2 = arg2.mpwiMemo.sym; break; default: Debug.Fail("Shouldn't be here!"); continue; } if (sym2 == sym && pType2 == pType && !fMunge) continue; prgpszNew[j] = prgpsz[j]; fMunge = true; } if (fMunge) { prgpszNew[i] = prgpsz[i]; } } prgpsz = prgpszNew; } return new RuntimeBinderException(string.Format(CultureInfo.InvariantCulture, ErrorFacts.GetMessage(id), prgpsz)); } } }