summaryrefslogtreecommitdiff
path: root/src/vm/typestring.h
blob: e9b032f8f29ceeed6e6369dd4e521a98a0c4a6a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ---------------------------------------------------------------------------
// typestring.cpp
// ---------------------------------------------------------------------------
//

//
// This module contains all helper functions required to produce
// string representations of types, with options to control the
// appearance of namespace and assembly information.  Its primary use
// is in reflection (Type.Name, Type.FullName, Type.ToString, etc) but
// over time it could replace the use of TypeHandle.GetName etc for
// diagnostic messages.
//
// ---------------------------------------------------------------------------


#ifndef TYPESTRING_H
#define TYPESTRING_H

#include "common.h"
#include "class.h"
#include "typehandle.h"
#include "sstring.h"
#include "typekey.h"
#include "typeparse.h"
#include "field.h"

class TypeLibExporter;
class TypeString;

class TypeNameBuilder
{
    friend class TypeNameBuilderWrapper;

public:
    static void QCALLTYPE _ReleaseTypeNameBuilder(TypeNameBuilder * pTnb);
    static TypeNameBuilder * QCALLTYPE _CreateTypeNameBuilder();
    static void QCALLTYPE _OpenGenericArguments(TypeNameBuilder * pTnb);
    static void QCALLTYPE _CloseGenericArguments(TypeNameBuilder *pTnb);
    static void QCALLTYPE _OpenGenericArgument(TypeNameBuilder * pTnb);
    static void QCALLTYPE _CloseGenericArgument(TypeNameBuilder * pTnb);
    static void QCALLTYPE _AddName(TypeNameBuilder * pTnb, LPCWSTR wszName);
    static void QCALLTYPE _AddPointer(TypeNameBuilder * pTnb);
    static void QCALLTYPE _AddByRef(TypeNameBuilder * pTnb);
    static void QCALLTYPE _AddSzArray(TypeNameBuilder * pTnb);
    static void QCALLTYPE _AddArray(TypeNameBuilder * pTnb, DWORD dwRank);
    static void QCALLTYPE _AddAssemblySpec(TypeNameBuilder * pTnb, LPCWSTR wszAssemblySpec);
    static void QCALLTYPE _ToString(TypeNameBuilder * pTnb, QCall::StringHandleOnStack retString);
    static void QCALLTYPE _Clear(TypeNameBuilder * pTnb);    

private:
    friend class TypeString;
    friend SString* TypeName::ToString(SString*, BOOL, BOOL, BOOL);
    friend TypeHandle TypeName::GetTypeWorker(BOOL, BOOL, BOOL, Assembly*, BOOL, BOOL, StackCrawlMark*, Assembly*, 
        ICLRPrivBinder * pPrivHostBinder,
        BOOL, OBJECTREF *);
    HRESULT OpenGenericArguments(); 
    HRESULT CloseGenericArguments(); 
    HRESULT OpenGenericArgument(); 
    HRESULT CloseGenericArgument();
    HRESULT AddName(LPCWSTR szName); 
    HRESULT AddName(LPCWSTR szName, LPCWSTR szNamespace);
    HRESULT AddPointer(); 
    HRESULT AddByRef(); 
    HRESULT AddSzArray(); 
    HRESULT AddArray(DWORD rank);
    HRESULT AddAssemblySpec(LPCWSTR szAssemblySpec);
    HRESULT ToString(BSTR* pszStringRepresentation);
    HRESULT Clear();

private:
    class Stack
    {
    public:
        Stack() : m_depth(0) { LIMITED_METHOD_CONTRACT; } 
        
    public:  
        COUNT_T Push(COUNT_T element) { WRAPPER_NO_CONTRACT; *m_stack.Append() = element; m_depth++; return Tos(); }
        COUNT_T Pop() 
        { 
            CONTRACTL
            {
                THROWS;
                GC_NOTRIGGER;
                MODE_ANY;
                PRECONDITION(GetDepth() > 0); 
            }
            CONTRACTL_END;

            COUNT_T tos = Tos(); 
            m_stack.Delete(m_stack.End() - 1); 
            m_depth--; 
            return tos; 
        }
        COUNT_T Tos() { WRAPPER_NO_CONTRACT; return m_stack.End()[-1]; }
        void Clear() { WRAPPER_NO_CONTRACT; while(GetDepth()) Pop(); }
        COUNT_T GetDepth() { WRAPPER_NO_CONTRACT; return m_depth; }
        
    private:
        INT32 m_depth;
        InlineSArray<COUNT_T, 16> m_stack;    
    };
        

public:
    typedef enum 
    {
        ParseStateSTART         = 0x0001,
        ParseStateNAME          = 0x0004,
        ParseStateGENARGS       = 0x0008,
        ParseStatePTRARR        = 0x0010,
        ParseStateBYREF         = 0x0020,
        ParseStateASSEMSPEC     = 0x0080,
        ParseStateERROR         = 0x0100,
    } 
    ParseState;

public:
    TypeNameBuilder(SString* pStr, ParseState parseState = ParseStateSTART);
    TypeNameBuilder() { WRAPPER_NO_CONTRACT; m_pStr = &m_str; Clear(); }
    void SetUseAngleBracketsForGenerics(BOOL value) { m_bUseAngleBracketsForGenerics = value; }
    void Append(LPCWSTR pStr) { WRAPPER_NO_CONTRACT; m_pStr->Append(pStr); }
    void Append(WCHAR c) { WRAPPER_NO_CONTRACT; m_pStr->Append(c); }
    SString* GetString() { WRAPPER_NO_CONTRACT; return m_pStr; }

private:
    void EscapeName(LPCWSTR szName);
    void EscapeAssemblyName(LPCWSTR szName);
    void EscapeEmbeddedAssemblyName(LPCWSTR szName);
    BOOL CheckParseState(int validState) { WRAPPER_NO_CONTRACT; return ((int)m_parseState & validState) != 0; }
    //BOOL CheckParseState(int validState) { WRAPPER_NO_CONTRACT; ASSERT(((int)m_parseState & validState) != 0); return TRUE; }
    HRESULT Fail() { WRAPPER_NO_CONTRACT; m_parseState = ParseStateERROR; return E_FAIL; }
    void PushOpenGenericArgument();
    void PopOpenGenericArgument();

private:
    ParseState m_parseState;
    SString* m_pStr;
    InlineSString<256> m_str;       
    DWORD m_instNesting;
    BOOL m_bFirstInstArg;
    BOOL m_bNestedName;
    BOOL m_bHasAssemblySpec;
    BOOL m_bUseAngleBracketsForGenerics;
    Stack m_stack;
};

// Class that's exposed to COM and wraps TypeNameBuilder (so that it can thunk
// all the entry points in order to perform stack probes).
class TypeNameBuilderWrapper : public ITypeNameBuilder
{
public:
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppUnk);
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();

    virtual HRESULT STDMETHODCALLTYPE OpenGenericArguments();
    virtual HRESULT STDMETHODCALLTYPE CloseGenericArguments();
    virtual HRESULT STDMETHODCALLTYPE OpenGenericArgument();
    virtual HRESULT STDMETHODCALLTYPE CloseGenericArgument();
    virtual HRESULT STDMETHODCALLTYPE AddName(LPCWSTR szName);
    virtual HRESULT STDMETHODCALLTYPE AddPointer();
    virtual HRESULT STDMETHODCALLTYPE AddByRef();
    virtual HRESULT STDMETHODCALLTYPE AddSzArray();
    virtual HRESULT STDMETHODCALLTYPE AddArray(DWORD rank);
    virtual HRESULT STDMETHODCALLTYPE AddAssemblySpec(LPCWSTR szAssemblySpec);
    virtual HRESULT STDMETHODCALLTYPE ToString(BSTR* pszStringRepresentation);
    virtual HRESULT STDMETHODCALLTYPE Clear();

    TypeNameBuilderWrapper() : m_ref(0) { WRAPPER_NO_CONTRACT; }
    virtual ~TypeNameBuilderWrapper() {}
    
private:
    LONG            m_ref;
    TypeNameBuilder m_tnb;
};

// --------------------------------------------------------------------------
// This type can generate names for types. It is used by reflection methods
// like System.RuntimeType.RuntimeTypeCache.ConstructName
//

class TypeString
{
    // -----------------------------------------------------------------------
    // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 
    // -----------------------------------------------------------------------
    // Do no change the formatting of these strings as they are used by
    // serialization, and it would break serialization backwards-compatibility.
    
public:

  typedef enum 
  {
      FormatBasic         = 0x00000000, // Not a bitmask, simply the tersest flag settings possible
      FormatNamespace     = 0x00000001, // Include namespace and/or enclosing class names in type names
      FormatFullInst      = 0x00000002, // Include namespace and assembly in generic types (regardless of other flag settings)
      FormatAssembly      = 0x00000004, // Include assembly display name in type names
      FormatSignature     = 0x00000008, // Include signature in method names
      FormatNoVersion     = 0x00000010, // Suppress version and culture information in all assembly names
#ifdef _DEBUG
      FormatDebug         = 0x00000020, // For debug printing of types only
#endif
      FormatAngleBrackets = 0x00000040, // Whether generic types are C<T> or C[T]
      FormatStubInfo      = 0x00000080, // Include stub info like {unbox-stub}
      FormatGenericParam  = 0x00000100, // Use !name and !!name for generic type and method parameters
  }
  FormatFlags;

public:   
    // Append the name of the type td to the string
    // The following flags in the FormatFlags argument are significant: FormatNamespace 
    static void AppendTypeDef(SString& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format = FormatNamespace);

    // Append a square-bracket-enclosed, comma-separated list of n type parameters in inst to the string s
    // and enclose each parameter in square brackets to disambiguate the commas
    // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
    static void AppendInst(SString& s, Instantiation inst, DWORD format = FormatNamespace);

    // Append a representation of the type t to the string s
    // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
    static void AppendType(SString& s, TypeHandle t, DWORD format = FormatNamespace);

    // Append a representation of the type t to the string s, using the generic
    // instantiation info provided, instead of the instantiation in the TypeHandle.
    static void AppendType(SString& s, TypeHandle t, Instantiation typeInstantiation, DWORD format = FormatNamespace);

    static void AppendTypeKey(SString& s, TypeKey *pTypeKey, DWORD format = FormatNamespace);

    // Appends the method name and generic instantiation info.  This might
    // look like "Namespace.ClassName[T].Foo[U, V]()"
    static void AppendMethod(SString& s, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format = FormatNamespace|FormatSignature);

    // Append a representation of the method m to the string s
    // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatSignature  FormatNoVersion
    static void AppendMethodInternal(SString& s, MethodDesc *pMD, const DWORD format = FormatNamespace|FormatSignature|FormatStubInfo);

    // Append the field name and generic instantiation info.
    static void AppendField(SString& s, FieldDesc *pFD, Instantiation typeInstantiation, const DWORD format = FormatNamespace);
#ifdef _DEBUG
    // These versions are NOTHROWS. They are meant for diagnostic purposes only
    // as they may leave "s" in a bad state if there are any problems/exceptions.
    static void AppendMethodDebug(SString& s, MethodDesc *pMD);
    static void AppendTypeDebug(SString& s, TypeHandle t);  
    static void AppendTypeKeyDebug(SString& s, TypeKey* pTypeKey);
#endif

private:
    friend class TypeLibExporter;
    friend class TypeNameBuilder;
    static void AppendMethodImpl(SString& s, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format);
    static void AppendTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format = FormatNamespace);
    static void AppendNestedTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format = FormatNamespace);
    static void AppendInst(TypeNameBuilder& tnb, Instantiation inst, DWORD format = FormatNamespace);
    static void AppendType(TypeNameBuilder& tnb, TypeHandle t, Instantiation typeInstantiation, DWORD format = FormatNamespace); // ????
    static void AppendTypeKey(TypeNameBuilder& tnb, TypeKey *pTypeKey, DWORD format = FormatNamespace);
    static void AppendParamTypeQualifier(TypeNameBuilder& tnb, CorElementType kind, DWORD rank);
    static void EscapeSimpleTypeName(SString* ssTypeName, SString* ssEscapedTypeName);
    static bool ContainsReservedChar(LPCWSTR pTypeName);
};

#endif