<PackageReference Include="Microsoft.CSharp" Version="4.4.0" />

UserStringBuilder

sealed class UserStringBuilder
using Microsoft.CSharp.RuntimeBinder.Semantics; using Microsoft.CSharp.RuntimeBinder.Syntax; using System.Globalization; using System.Text; namespace Microsoft.CSharp.RuntimeBinder.Errors { internal sealed class UserStringBuilder { private bool fHadUndisplayableStringInError; private bool m_buildingInProgress; private GlobalSymbolContext m_globalSymbols; private StringBuilder m_strBuilder; public UserStringBuilder(GlobalSymbolContext globalSymbols) { fHadUndisplayableStringInError = false; m_buildingInProgress = false; m_globalSymbols = globalSymbols; } private void BeginString() { m_buildingInProgress = true; m_strBuilder = new StringBuilder(); } private void EndString(out string s) { m_buildingInProgress = false; s = m_strBuilder.ToString(); m_strBuilder = null; } public bool HadUndisplayableString() { return fHadUndisplayableStringInError; } public void ResetUndisplayableStringFlag() { fHadUndisplayableStringInError = false; } private void ErrSK(out string psz, SYMKIND sk) { MessageID id; switch (sk) { case SYMKIND.SK_MethodSymbol: id = MessageID.SK_METHOD; break; case SYMKIND.SK_AggregateSymbol: id = MessageID.SK_CLASS; break; case SYMKIND.SK_NamespaceSymbol: id = MessageID.SK_NAMESPACE; break; case SYMKIND.SK_FieldSymbol: id = MessageID.SK_FIELD; break; case SYMKIND.SK_LocalVariableSymbol: id = MessageID.SK_VARIABLE; break; case SYMKIND.SK_PropertySymbol: id = MessageID.SK_PROPERTY; break; case SYMKIND.SK_EventSymbol: id = MessageID.SK_EVENT; break; case SYMKIND.SK_TypeParameterSymbol: id = MessageID.SK_TYVAR; break; case SYMKIND.SK_AssemblyQualifiedNamespaceSymbol: id = MessageID.SK_ALIAS; break; default: id = MessageID.SK_UNKNOWN; break; } ErrId(out psz, id); } private void ErrAppendParamList(TypeArray params, bool isVarargs, bool isParamArray) { if (params != null) { for (int i = 0; i < params.Count; i++) { if (i > 0) ErrAppendString(", "); if (isParamArray && i == params.Count - 1) ErrAppendString("params "); ErrAppendType(params[i], null); } if (isVarargs) { if (params.Count != 0) ErrAppendString(", "); ErrAppendString("..."); } } } private void ErrAppendString(string str) { m_strBuilder.Append(str); } private void ErrAppendChar(char ch) { m_strBuilder.Append(ch); } private void ErrAppendPrintf(string format, params object[] args) { ErrAppendString(string.Format(CultureInfo.InvariantCulture, format, args)); } private void ErrAppendName(Name name) { CheckDisplayableName(name); if (name == NameManager.GetPredefinedName(PredefinedName.PN_INDEXERINTERNAL)) ErrAppendString("this"); else ErrAppendString(name.Text); } private void ErrAppendMethodParentSym(MethodSymbol sym, SubstContext pcxt, out TypeArray substMethTyParams) { substMethTyParams = null; ErrAppendParentSym(sym, pcxt); } private void ErrAppendParentSym(Symbol sym, SubstContext pctx) { ErrAppendParentCore(sym.parent, pctx); } private void ErrAppendParentType(CType pType, SubstContext pctx) { if (pType.IsErrorType()) { if (pType.AsErrorType().HasTypeParent()) { ErrAppendType(pType.AsErrorType().GetTypeParent(), null); ErrAppendChar('.'); } else ErrAppendParentCore(pType.AsErrorType().GetNSParent(), pctx); } else if (pType.IsAggregateType()) { ErrAppendParentCore(pType.AsAggregateType().GetOwningAggregate(), pctx); } else if (pType.GetBaseOrParameterOrElementType() != null) { ErrAppendType(pType.GetBaseOrParameterOrElementType(), null); ErrAppendChar('.'); } } private void ErrAppendParentCore(Symbol parent, SubstContext pctx) { if (parent != null && parent != getBSymmgr().GetRootNS()) { if (pctx != null && !pctx.FNop() && parent.IsAggregateSymbol() && parent.AsAggregateSymbol().GetTypeVarsAll().Count != 0) { CType pType = GetTypeManager().SubstType(parent.AsAggregateSymbol().getThisType(), pctx); ErrAppendType(pType, null); } else ErrAppendSym(parent, null); ErrAppendChar('.'); } } private void ErrAppendTypeParameters(TypeArray params, SubstContext pctx, bool forClass) { if (params != null && params.Count != 0) { ErrAppendChar('<'); ErrAppendType(params[0], pctx); for (int i = 1; i < params.Count; i++) { ErrAppendString(","); ErrAppendType(params[i], pctx); } ErrAppendChar('>'); } } private void ErrAppendMethod(MethodSymbol meth, SubstContext pctx, bool fArgs) { if (meth.IsExpImpl() && (bool)meth.swtSlot) { ErrAppendParentSym(meth, pctx); SubstContext pctx2 = new SubstContext(GetTypeManager().SubstType(meth.swtSlot.GetType(), pctx).AsAggregateType()); ErrAppendSym(meth.swtSlot.Sym, pctx2, fArgs); } else if (meth.isPropertyAccessor()) { PropertySymbol property = meth.getProperty(); ErrAppendSym(property, pctx); if (property.methGet == meth) ErrAppendString(".get"); else ErrAppendString(".set"); } else if (meth.isEventAccessor()) { EventSymbol event = meth.getEvent(); ErrAppendSym(event, pctx); if (event.methAdd == meth) ErrAppendString(".add"); else ErrAppendString(".remove"); } else { TypeArray substMethTyParams = null; ErrAppendMethodParentSym(meth, pctx, out substMethTyParams); if (meth.IsConstructor()) ErrAppendName(meth.getClass().name); else if (meth.IsDestructor()) { ErrAppendChar('~'); ErrAppendName(meth.getClass().name); } else if (meth.isConversionOperator()) { ErrAppendString(meth.isImplicit() ? "implicit" : "explicit"); ErrAppendString(" operator "); ErrAppendType(meth.RetType, pctx); } else if (meth.isOperator) { ErrAppendString("operator "); OperatorKind op = Operators.OperatorOfMethodName(meth.name); string str = Operators.HasDisplayName(op) ? Operators.GetDisplayName(op) : ((meth.name != NameManager.GetPredefinedName(PredefinedName.PN_OPEQUALS)) ? "compare" : "equals"); ErrAppendString(str); } else if (meth.IsExpImpl()) { if (meth.errExpImpl != null) ErrAppendType(meth.errExpImpl, pctx, fArgs); } else { ErrAppendName(meth.name); } if (substMethTyParams == null) ErrAppendTypeParameters(meth.typeVars, pctx, false); if (fArgs) { ErrAppendChar('('); if (!meth.computeCurrentBogusState()) ErrAppendParamList(GetTypeManager().SubstTypeArray(meth.Params, pctx), meth.isVarargs, meth.isParamArray); ErrAppendChar(')'); } } } private void ErrAppendIndexer(IndexerSymbol indexer, SubstContext pctx) { ErrAppendString("this["); ErrAppendParamList(GetTypeManager().SubstTypeArray(indexer.Params, pctx), false, indexer.isParamArray); ErrAppendChar(']'); } private void ErrAppendProperty(PropertySymbol prop, SubstContext pctx) { ErrAppendParentSym(prop, pctx); if (prop.IsExpImpl() && prop.swtSlot.Sym != null) { SubstContext pctx2 = new SubstContext(GetTypeManager().SubstType(prop.swtSlot.GetType(), pctx).AsAggregateType()); ErrAppendSym(prop.swtSlot.Sym, pctx2); } else if (prop.IsExpImpl()) { if (prop.errExpImpl != null) ErrAppendType(prop.errExpImpl, pctx, false); if (prop.isIndexer()) { ErrAppendChar('.'); ErrAppendIndexer(prop.AsIndexerSymbol(), pctx); } } else if (prop.isIndexer()) { ErrAppendIndexer(prop.AsIndexerSymbol(), pctx); } else { ErrAppendName(prop.name); } } private void ErrAppendEvent(EventSymbol event, SubstContext pctx) { } private void ErrAppendId(MessageID id) { ErrId(out string s, id); ErrAppendString(s); } private void ErrAppendSym(Symbol sym, SubstContext pctx) { ErrAppendSym(sym, pctx, true); } private void ErrAppendSym(Symbol sym, SubstContext pctx, bool fArgs) { switch (sym.getKind()) { case SYMKIND.SK_AliasSymbol: case SYMKIND.SK_ExternalAliasDefinitionSymbol: case SYMKIND.SK_Scope: case SYMKIND.SK_CachedNameSymbol: case SYMKIND.SK_LambdaScope: break; case SYMKIND.SK_NamespaceDeclaration: ErrAppendSym(sym.AsNamespaceDeclaration().NameSpace(), null); break; case SYMKIND.SK_GlobalAttributeDeclaration: ErrAppendName(sym.name); break; case SYMKIND.SK_AggregateDeclaration: ErrAppendSym(sym.AsAggregateDeclaration().Agg(), pctx); break; case SYMKIND.SK_AggregateSymbol: { string niceName = PredefinedTypes.GetNiceName(sym.AsAggregateSymbol()); if (niceName != null) ErrAppendString(niceName); else if (sym.AsAggregateSymbol().IsAnonymousType()) { ErrAppendId(MessageID.AnonymousType); } else { ErrAppendParentSym(sym, pctx); ErrAppendName(sym.name); ErrAppendTypeParameters(sym.AsAggregateSymbol().GetTypeVars(), pctx, true); } break; } case SYMKIND.SK_MethodSymbol: ErrAppendMethod(sym.AsMethodSymbol(), pctx, fArgs); break; case SYMKIND.SK_PropertySymbol: ErrAppendProperty(sym.AsPropertySymbol(), pctx); break; case SYMKIND.SK_EventSymbol: ErrAppendEvent(sym.AsEventSymbol(), pctx); break; case SYMKIND.SK_NamespaceSymbol: case SYMKIND.SK_AssemblyQualifiedNamespaceSymbol: if (sym == getBSymmgr().GetRootNS()) ErrAppendId(MessageID.GlobalNamespace); else { ErrAppendParentSym(sym, null); ErrAppendName(sym.name); } break; case SYMKIND.SK_FieldSymbol: ErrAppendParentSym(sym, pctx); ErrAppendName(sym.name); break; case SYMKIND.SK_TypeParameterSymbol: if (sym.name == null) { if (sym.AsTypeParameterSymbol().IsMethodTypeParameter()) ErrAppendChar('!'); ErrAppendChar('!'); ErrAppendPrintf("{0}", sym.AsTypeParameterSymbol().GetIndexInTotalParameters()); } else ErrAppendName(sym.name); break; case SYMKIND.SK_LocalVariableSymbol: case SYMKIND.SK_TransparentIdentifierMemberSymbol: case SYMKIND.SK_LabelSymbol: ErrAppendName(sym.name); break; } } private void ErrAppendType(CType pType, SubstContext pCtx) { ErrAppendType(pType, pCtx, true); } private void ErrAppendType(CType pType, SubstContext pctx, bool fArgs) { if (pctx != null) { if (!pctx.FNop()) pType = GetTypeManager().SubstType(pType, pctx); pctx = null; } switch (pType.GetTypeKind()) { case TypeKind.TK_OpenTypePlaceholderType: case TypeKind.TK_NaturalIntegerType: break; case TypeKind.TK_AggregateType: { AggregateType aggregateType = pType.AsAggregateType(); string niceName = PredefinedTypes.GetNiceName(aggregateType.getAggregate()); if (niceName != null) ErrAppendString(niceName); else { if (aggregateType.getAggregate().IsAnonymousType()) { ErrAppendPrintf("AnonymousType#{0}", GetTypeID(aggregateType)); break; } if (aggregateType.outerType != null) { ErrAppendType(aggregateType.outerType, pctx); ErrAppendChar('.'); } else ErrAppendParentSym(aggregateType.getAggregate(), pctx); ErrAppendName(aggregateType.getAggregate().name); } ErrAppendTypeParameters(aggregateType.GetTypeArgsThis(), pctx, true); break; } case TypeKind.TK_TypeParameterType: if (pType.GetName() == null) { if (pType.AsTypeParameterType().IsMethodTypeParameter()) ErrAppendChar('!'); ErrAppendChar('!'); ErrAppendPrintf("{0}", pType.AsTypeParameterType().GetIndexInTotalParameters()); } else ErrAppendName(pType.GetName()); break; case TypeKind.TK_ErrorType: if (pType.AsErrorType().HasParent()) { ErrAppendParentType(pType, pctx); ErrAppendName(pType.AsErrorType().nameText); ErrAppendTypeParameters(pType.AsErrorType().typeArgs, pctx, true); } else ErrAppendId(MessageID.ERRORSYM); break; case TypeKind.TK_NullType: ErrAppendId(MessageID.NULL); break; case TypeKind.TK_BoundLambdaType: ErrAppendId(MessageID.AnonMethod); break; case TypeKind.TK_UnboundLambdaType: ErrAppendId(MessageID.Lambda); break; case TypeKind.TK_MethodGroupType: ErrAppendId(MessageID.MethodGroup); break; case TypeKind.TK_ArgumentListType: ErrAppendString(TokenFacts.GetText(TokenKind.ArgList)); break; case TypeKind.TK_ArrayType: { CType baseElementType = pType.AsArrayType().GetBaseElementType(); if (baseElementType != null) { ErrAppendType(baseElementType, pctx); baseElementType = pType; while (baseElementType != null && baseElementType.IsArrayType()) { int rank = baseElementType.AsArrayType().rank; ErrAppendChar('['); if (rank == 1) { if (!baseElementType.AsArrayType().IsSZArray) ErrAppendChar('*'); } else { for (int num = rank; num > 1; num--) { ErrAppendChar(','); } } ErrAppendChar(']'); baseElementType = baseElementType.AsArrayType().GetElementType(); } } break; } case TypeKind.TK_VoidType: ErrAppendName(GetNameManager().Lookup(TokenFacts.GetText(TokenKind.Void))); break; case TypeKind.TK_ParameterModifierType: ErrAppendString(pType.AsParameterModifierType().isOut ? "out " : "ref "); ErrAppendType(pType.AsParameterModifierType().GetParameterType(), pctx); break; case TypeKind.TK_PointerType: ErrAppendType(pType.AsPointerType().GetReferentType(), pctx); ErrAppendChar('*'); break; case TypeKind.TK_NullableType: ErrAppendType(pType.AsNullableType().GetUnderlyingType(), pctx); ErrAppendChar('?'); break; } } public bool ErrArgToString(out string psz, ErrArg parg, out bool fUserStrings) { fUserStrings = false; psz = null; bool result = true; switch (parg.eak) { case ErrArgKind.Ids: ErrId(out psz, parg.ids); break; case ErrArgKind.SymKind: ErrSK(out psz, parg.sk); break; case ErrArgKind.Type: BeginString(); ErrAppendType(parg.pType, null); EndString(out psz); fUserStrings = true; break; case ErrArgKind.Sym: BeginString(); ErrAppendSym(parg.sym, null); EndString(out psz); fUserStrings = true; break; case ErrArgKind.Name: if (parg.name == NameManager.GetPredefinedName(PredefinedName.PN_INDEXERINTERNAL)) psz = "this"; else psz = parg.name.Text; break; case ErrArgKind.Str: psz = parg.psz; break; case ErrArgKind.PredefName: BeginString(); ErrAppendName(NameManager.GetPredefinedName(parg.pdn)); EndString(out psz); break; case ErrArgKind.SymWithType: { SubstContext pctx2 = new SubstContext(parg.swtMemo.ats, null); BeginString(); ErrAppendSym(parg.swtMemo.sym, pctx2, true); EndString(out psz); fUserStrings = true; break; } case ErrArgKind.MethWithInst: { SubstContext pctx = new SubstContext(parg.mpwiMemo.ats, parg.mpwiMemo.typeArgs); BeginString(); ErrAppendSym(parg.mpwiMemo.sym, pctx, true); EndString(out psz); fUserStrings = true; break; } default: result = false; break; } return result; } private bool IsDisplayableName(Name name) { return name != NameManager.GetPredefinedName(PredefinedName.PN_MISSING); } private void CheckDisplayableName(Name name) { if (!IsDisplayableName(name)) fHadUndisplayableStringInError = true; } private NameManager GetNameManager() { return m_globalSymbols.GetNameManager(); } private TypeManager GetTypeManager() { return m_globalSymbols.GetTypes(); } private BSYMMGR getBSymmgr() { return m_globalSymbols.GetGlobalSymbols(); } private int GetTypeID(CType type) { return 0; } private void ErrId(out string s, MessageID id) { s = ErrorFacts.GetMessage(id); } } }