4
// Lluis Sanchez Gual <lluis@novell.com>
6
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
8
// Permission is hereby granted, free of charge, to any person obtaining a copy
9
// of this software and associated documentation files (the "Software"), to deal
10
// in the Software without restriction, including without limitation the rights
11
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
// copies of the Software, and to permit persons to whom the Software is
13
// furnished to do so, subject to the following conditions:
15
// The above copyright notice and this permission notice shall be included in
16
// all copies or substantial portions of the Software.
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31
using System.Threading;
32
using System.Collections;
33
using System.Collections.Generic;
34
using System.Collections.Specialized;
35
using System.Diagnostics;
36
using System.Reflection;
37
using System.Runtime.Serialization;
38
using System.Runtime.Serialization.Formatters;
39
using System.Runtime.Serialization.Formatters.Binary;
40
using System.Security;
41
using System.Security.Permissions;
42
using System.Security.Policy;
45
using MonoDevelop.Core;
46
using MonoDevelop.Core.ProgressMonitoring;
48
using MonoDevelop.Projects;
49
using MonoDevelop.Projects.Utility;
50
using MonoDevelop.Projects.Text;
51
using MonoDevelop.Projects.Dom;
52
using MonoDevelop.Projects.Dom.Parser;
53
using MonoDevelop.Core.Assemblies;
55
namespace MonoDevelop.Projects.Dom.Serialization
57
internal class ParserDatabase: IParserDatabase
59
static readonly string[] sharedNameTable = new string[] {
61
"System.Void", // 116020
62
"To be added", // 78598
63
"System.Int32", // 72669
64
"System.String", // 72097
65
"System.Object", // 48530
66
"System.Boolean", // 46200
68
"System.IntPtr", // 35184
69
"To be added.", // 19082
71
"System.Byte", // 8524
72
"To be added: an object of type 'string'", // 7928
75
"System.IAsyncResult", // 7760
76
"System.Type", // 7518
79
"System.UInt32", // 6966
81
"To be added: an object of type 'int'", // 5196
82
"System.Int64", // 4166
84
"System.EventArgs", // 4140
86
"System.Enum", // 3980
90
"System.AsyncCallback", // 3850
91
"System.MulticastDelegate", // 3698
92
"BeginInvoke", // 3650
97
"System.EventHandler", // 3218
98
"System.Double", // 3206
101
"System.Single", // 2940
104
"System.Char", // 2813
108
"System.Drawing.Color", // 2550
110
"To be added: an object of type 'object'", // 2430
111
"System.DateTime", // 2420
113
"GLib.GType", // 2292
115
"a <see cref=\"T:System.Int32\" />", // 2176
118
"Nemerle.Core.list`1", // 1950
119
"System.Windows.Forms", // 1942
120
"System.Collections.ArrayList", // 1918
121
"a <see cref=\"T:System.String\" />", // 1894
125
"System.IO.Stream", // 1794
129
"System.UInt64", // 1700
130
"System.Drawing.Rectangle", // 1684
131
"System.IFormatProvider", // 1684
133
"System.Exception", // 1652
135
"System.Drawing.Pen", // 1584
137
"System.Collections.IEnumerator", // 1546
140
"System.Attribute", // 1494
142
"To be added: an object of type 'Type'", // 1444
143
"System.Collections.Hashtable", // 1416
145
"System.Int16", // 1374
147
"System.ComponentModel.ITypeDescriptorContext", // 1344
148
"System.Collections.ICollection", // 1330
150
"Gtk.Widget", // 1326
151
"System.Runtime.Serialization.StreamingContext", // 1318
152
"Nemerle.Compiler.Parsetree.PExpr", // 1312
153
"System.Guid", // 1310
155
"Gtk.TreeIter", // 1300
157
"System.Runtime.Serialization.SerializationInfo", // 1272
162
public ParserDatabase ()
164
Array.Sort (sharedNameTable);
167
public void Initialize ()
169
DeleteObsoleteDatabases ();
173
public ProjectDom LoadSingleFileDom (string file)
175
return new DatabaseProjectDom (this, new SimpleCodeCompletionDatabase (file, this));
178
public ProjectDom LoadAssemblyDom (TargetRuntime runtime, TargetFramework fx, string file)
180
return new DatabaseProjectDom (this, new AssemblyCodeCompletionDatabase (runtime, fx, file, this));
183
public ProjectDom LoadProjectDom (Project project)
185
DatabaseProjectDom dom = new DatabaseProjectDom (this, new ProjectCodeCompletionDatabase (project, this));
186
dom.Project = project;
190
void DeleteObsoleteDatabases ()
192
string[] files = Directory.GetFiles (ProjectDomService.CodeCompletionPath, "*.pidb");
193
foreach (string file in files)
195
string name = Path.GetFileNameWithoutExtension (file);
196
string baseDir = Path.GetDirectoryName (file);
197
AssemblyCodeCompletionDatabase.CleanDatabase (baseDir, name);
203
#region Default Parser Layer dependent functions
205
public IType GetClass (SerializationCodeCompletionDatabase db, string typeName, IList<IReturnType> genericArguments, bool deepSearchReferences, bool caseSensitive)
207
if (deepSearchReferences)
208
return DeepGetClass (db, typeName, genericArguments, caseSensitive);
210
return GetClass (db, typeName, genericArguments, caseSensitive);
213
IType GetClass (SerializationCodeCompletionDatabase db, string typeName, IList<IReturnType> genericArguments, bool caseSensitive)
216
IType c = db.GetClass (typeName, genericArguments, caseSensitive);
217
if (c != null) return c;
218
foreach (ReferenceEntry re in db.References)
220
SerializationCodeCompletionDatabase cdb = GetDatabase (re.Uri);
221
if (cdb == null) continue;
222
c = cdb.GetClass (typeName, genericArguments, caseSensitive);
223
if (c != null) return c;
229
public IType DeepGetClass (SerializationCodeCompletionDatabase db, string typeName, IList<IReturnType> genericArguments, bool caseSensitive)
231
if (db == null) return null;
233
IType c = db.GetClass (typeName, genericArguments, caseSensitive);
234
if (c != null) return c;
236
foreach (ReferenceEntry re in db.References)
238
SerializationCodeCompletionDatabase cdb = GetDatabase (re.Uri);
239
if (cdb == null) continue;
240
// deep get class should only go to depth 1, to prevent type lookup errors in the form:
241
// A -> B -> C v1.0 / A -> C v2.0 & getTypeName from assembly C. If C isn't referenced directly
242
// it's impossible to get types from assembly A, therefore DeepGetClassRec is incorrect here.
243
c = cdb.GetClass (typeName, genericArguments, caseSensitive);
244
// c = DeepGetClassRec (visitedDbs, cdb, typeName, genericArguments, caseSensitive);
245
if (c != null) return c;
250
/* public string SearchNamespace (SerializationCodeCompletionDatabase db, IUsing usin, string partitialNamespaceName)
252
return SearchNamespace (db, usin, partitialNamespaceName, true);
255
public string SearchNamespace (SerializationCodeCompletionDatabase db, IUsing usin, string partitialNamespaceName, bool caseSensitive)
257
// LoggingService.LogDebug ("SearchNamespace : >{0}<", partitialNamespaceName);
258
if (NamespaceExists (db, partitialNamespaceName, caseSensitive)) {
259
return partitialNamespaceName;
262
// search for partitial namespaces
264
if (usin.Aliases.TryGetValue ("", out alias)) {
265
string declaringNamespace = alias.FullName;
266
while (declaringNamespace.Length > 0) {
267
if ((caseSensitive ? declaringNamespace.EndsWith(partitialNamespaceName) : declaringNamespace.ToLower().EndsWith(partitialNamespaceName.ToLower()) ) && NamespaceExists (db, declaringNamespace, caseSensitive)) {
268
return declaringNamespace;
270
int index = declaringNamespace.IndexOf('.');
272
declaringNamespace = declaringNamespace.Substring(0, index);
280
// Each namespace has an own using object
281
// The namespace name is an alias which has the key ""
282
foreach (string aliasString in usin.Aliases.Keys) {
283
if (caseSensitive ? partitialNamespaceName.StartsWith (aliasString) : partitialNamespaceName.ToLower().StartsWith(aliasString.ToLower())) {
284
if (aliasString.Length > 0) {
285
string nsName = String.Concat (usin.Aliases [aliasString], partitialNamespaceName.Remove(0, aliasString.Length));
286
if (NamespaceExists (db, nsName, caseSensitive)) {
296
public IEnumerable<IType> GetSubclassesTree (SerializationCodeCompletionDatabase db,
298
bool deepSearchReferences,
299
IList<string> namespaces)
301
if (cls.FullName == "System.Object") {
302
// Just return all classes
303
if (!deepSearchReferences)
304
return db.GetClassList (true, namespaces);
306
return GetAllClassesRec (new HashSet<SerializationCodeCompletionDatabase> (), db, namespaces);
309
var visited = new Dictionary<SerializationCodeCompletionDatabase, HashSet<IType>> ();
310
SearchSubclasses (visited, cls, namespaces, db);
312
if (deepSearchReferences) {
313
List<IType> types = new List<IType> ();
314
foreach (HashSet<IType> list in visited.Values) {
315
// Don't use AddRange here. It won't work due to a bug in mono (#459816).
316
foreach (IType tt in list)
326
IEnumerable<IType> GetAllClassesRec (HashSet<SerializationCodeCompletionDatabase> visited, SerializationCodeCompletionDatabase db, IList<string> namespaces)
328
if (visited.Add (db)) {
329
foreach (IType dsub in db.GetClassList (true, namespaces))
331
foreach (ReferenceEntry re in db.References) {
332
SerializationCodeCompletionDatabase cdb = GetDatabase (re.Uri);
333
if (cdb == null) continue;
334
foreach (IType dsub in GetAllClassesRec (visited, cdb, namespaces))
340
HashSet<IType> SearchSubclasses (Dictionary<SerializationCodeCompletionDatabase, HashSet<IType>> visited, IType btype, IList<string> namespaces, SerializationCodeCompletionDatabase db)
342
HashSet<IType> types;
343
if (visited.TryGetValue (db, out types))
346
types = new HashSet<IType> (GetSubclassesTree (db, btype, namespaces));
347
visited [db] = types;
349
// For each reference, get the list of subclasses implemented in that reference,
350
// then look for subclasses of any of those in the current db
352
// A project can only have subclasses of classes implemented in assemblies it references
354
foreach (ReferenceEntry re in db.References) {
355
SerializationCodeCompletionDatabase cdb = GetDatabase (re.Uri);
356
if (cdb != null && cdb != db) {
357
HashSet<IType> refTypes = SearchSubclasses (visited, btype, namespaces, cdb);
358
foreach (IType t in refTypes)
359
foreach (IType st in GetSubclassesTree (db, t, namespaces))
367
IEnumerable<IType> GetSubclassesTree (SerializationCodeCompletionDatabase db, IType btype, IList<string> namespaces)
369
foreach (IType dsub in db.GetSubclasses (btype, namespaces)) {
371
foreach (IType sub in GetSubclassesTree (db, dsub, namespaces))
376
public SerializationCodeCompletionDatabase GetDatabase (string uri)
379
DatabaseProjectDom dom = ProjectDomService.GetDomForUri (uri) as DatabaseProjectDom;
382
} catch (Exception e) {
383
LoggingService.LogError ("Can't load assembly: " + uri, e);
390
internal static string GetDecoratedName (string name, int genericArgumentCount)
392
if (genericArgumentCount <= 0)
394
return name + "`" + genericArgumentCount;
397
internal static string GetDecoratedName (ClassEntry entry)
399
return GetDecoratedName (entry.Name, entry.TypeParameterCount);
402
internal static string GetDecoratedName (IType type)
404
return GetDecoratedName (type.FullName, type.TypeParameters.Count);
407
internal static string GetDecoratedName (IReturnType type)
409
return ((DomReturnType)type).DecoratedFullName;
413
////////////////////////////////////
415
internal INameEncoder CreateNameEncoder ()
417
return new StringNameTable (sharedNameTable);
420
internal INameDecoder CreateNameDecoder ()
422
return new StringNameTable (sharedNameTable);