1 | // |
---|
2 | // namespace.cs: Tracks namespaces |
---|
3 | // |
---|
4 | // Author: |
---|
5 | // Miguel de Icaza (miguel@ximian.com) |
---|
6 | // Marek Safar (marek.safar@seznam.cz) |
---|
7 | // |
---|
8 | // Copyright 2001 Ximian, Inc. |
---|
9 | // Copyright 2003-2008 Novell, Inc. |
---|
10 | // Copyright 2011 Xamarin Inc |
---|
11 | // |
---|
12 | using System; |
---|
13 | using System.Collections.Generic; |
---|
14 | using System.Linq; |
---|
15 | using Mono.CompilerServices.SymbolWriter; |
---|
16 | |
---|
17 | namespace Mono.CSharp { |
---|
18 | |
---|
19 | public class RootNamespace : Namespace { |
---|
20 | |
---|
21 | readonly string alias_name; |
---|
22 | readonly Dictionary<string, Namespace> all_namespaces; |
---|
23 | |
---|
24 | public RootNamespace (string alias_name) |
---|
25 | : base () |
---|
26 | { |
---|
27 | this.alias_name = alias_name; |
---|
28 | RegisterNamespace (this); |
---|
29 | |
---|
30 | all_namespaces = new Dictionary<string, Namespace> (); |
---|
31 | all_namespaces.Add ("", this); |
---|
32 | } |
---|
33 | |
---|
34 | public string Alias { |
---|
35 | get { |
---|
36 | return alias_name; |
---|
37 | } |
---|
38 | } |
---|
39 | |
---|
40 | public static void Error_GlobalNamespaceRedefined (Report report, Location loc) |
---|
41 | { |
---|
42 | report.Error (1681, loc, "The global extern alias cannot be redefined"); |
---|
43 | } |
---|
44 | |
---|
45 | // |
---|
46 | // For better error reporting where we try to guess missing using directive |
---|
47 | // |
---|
48 | public List<string> FindTypeNamespaces (IMemberContext ctx, string name, int arity) |
---|
49 | { |
---|
50 | List<string> res = null; |
---|
51 | |
---|
52 | foreach (var ns in all_namespaces) { |
---|
53 | var type = ns.Value.LookupType (ctx, name, arity, LookupMode.Normal, Location.Null); |
---|
54 | if (type != null) { |
---|
55 | if (res == null) |
---|
56 | res = new List<string> (); |
---|
57 | |
---|
58 | res.Add (ns.Key); |
---|
59 | } |
---|
60 | } |
---|
61 | |
---|
62 | return res; |
---|
63 | } |
---|
64 | |
---|
65 | // |
---|
66 | // For better error reporting where compiler tries to guess missing using directive |
---|
67 | // |
---|
68 | public List<string> FindExtensionMethodNamespaces (IMemberContext ctx, string name, int arity) |
---|
69 | { |
---|
70 | List<string> res = null; |
---|
71 | |
---|
72 | foreach (var ns in all_namespaces) { |
---|
73 | var methods = ns.Value.LookupExtensionMethod (ctx, name, arity); |
---|
74 | if (methods != null) { |
---|
75 | if (res == null) |
---|
76 | res = new List<string> (); |
---|
77 | |
---|
78 | res.Add (ns.Key); |
---|
79 | } |
---|
80 | } |
---|
81 | |
---|
82 | return res; |
---|
83 | } |
---|
84 | |
---|
85 | public void RegisterNamespace (Namespace child) |
---|
86 | { |
---|
87 | if (child != this) |
---|
88 | all_namespaces.Add (child.Name, child); |
---|
89 | } |
---|
90 | |
---|
91 | public override string GetSignatureForError () |
---|
92 | { |
---|
93 | return alias_name + "::"; |
---|
94 | } |
---|
95 | } |
---|
96 | |
---|
97 | public sealed class GlobalRootNamespace : RootNamespace |
---|
98 | { |
---|
99 | public GlobalRootNamespace () |
---|
100 | : base ("global") |
---|
101 | { |
---|
102 | } |
---|
103 | } |
---|
104 | |
---|
105 | // |
---|
106 | // Namespace cache for imported and compiled namespaces |
---|
107 | // |
---|
108 | public class Namespace |
---|
109 | { |
---|
110 | readonly Namespace parent; |
---|
111 | string fullname; |
---|
112 | protected Dictionary<string, Namespace> namespaces; |
---|
113 | protected Dictionary<string, IList<TypeSpec>> types; |
---|
114 | List<TypeSpec> extension_method_types; |
---|
115 | Dictionary<string, TypeSpec> cached_types; |
---|
116 | bool cls_checked; |
---|
117 | |
---|
118 | /// <summary> |
---|
119 | /// Constructor Takes the current namespace and the |
---|
120 | /// name. This is bootstrapped with parent == null |
---|
121 | /// and name = "" |
---|
122 | /// </summary> |
---|
123 | public Namespace (Namespace parent, string name) |
---|
124 | : this () |
---|
125 | { |
---|
126 | if (name == null) |
---|
127 | throw new ArgumentNullException ("name"); |
---|
128 | |
---|
129 | this.parent = parent; |
---|
130 | |
---|
131 | string pname = parent != null ? parent.fullname : null; |
---|
132 | |
---|
133 | if (pname == null) |
---|
134 | fullname = name; |
---|
135 | else |
---|
136 | fullname = pname + "." + name; |
---|
137 | |
---|
138 | while (parent.parent != null) |
---|
139 | parent = parent.parent; |
---|
140 | |
---|
141 | var root = parent as RootNamespace; |
---|
142 | if (root == null) |
---|
143 | throw new InternalErrorException ("Root namespaces must be created using RootNamespace"); |
---|
144 | |
---|
145 | root.RegisterNamespace (this); |
---|
146 | } |
---|
147 | |
---|
148 | protected Namespace () |
---|
149 | { |
---|
150 | namespaces = new Dictionary<string, Namespace> (); |
---|
151 | cached_types = new Dictionary<string, TypeSpec> (); |
---|
152 | } |
---|
153 | |
---|
154 | #region Properties |
---|
155 | |
---|
156 | /// <summary> |
---|
157 | /// The qualified name of the current namespace |
---|
158 | /// </summary> |
---|
159 | public string Name { |
---|
160 | get { return fullname; } |
---|
161 | } |
---|
162 | |
---|
163 | /// <summary> |
---|
164 | /// The parent of this namespace, used by the parser to "Pop" |
---|
165 | /// the current namespace declaration |
---|
166 | /// </summary> |
---|
167 | public Namespace Parent { |
---|
168 | get { return parent; } |
---|
169 | } |
---|
170 | |
---|
171 | #endregion |
---|
172 | |
---|
173 | public Namespace AddNamespace (MemberName name) |
---|
174 | { |
---|
175 | var ns_parent = name.Left == null ? this : AddNamespace (name.Left); |
---|
176 | return ns_parent.TryAddNamespace (name.Basename); |
---|
177 | } |
---|
178 | |
---|
179 | Namespace TryAddNamespace (string name) |
---|
180 | { |
---|
181 | Namespace ns; |
---|
182 | |
---|
183 | if (!namespaces.TryGetValue (name, out ns)) { |
---|
184 | ns = new Namespace (this, name); |
---|
185 | namespaces.Add (name, ns); |
---|
186 | } |
---|
187 | |
---|
188 | return ns; |
---|
189 | } |
---|
190 | |
---|
191 | public bool TryGetNamespace (string name, out Namespace ns) |
---|
192 | { |
---|
193 | return namespaces.TryGetValue (name, out ns); |
---|
194 | } |
---|
195 | |
---|
196 | // TODO: Replace with CreateNamespace where MemberName is created for the method call |
---|
197 | public Namespace GetNamespace (string name, bool create) |
---|
198 | { |
---|
199 | int pos = name.IndexOf ('.'); |
---|
200 | |
---|
201 | Namespace ns; |
---|
202 | string first; |
---|
203 | if (pos >= 0) |
---|
204 | first = name.Substring (0, pos); |
---|
205 | else |
---|
206 | first = name; |
---|
207 | |
---|
208 | if (!namespaces.TryGetValue (first, out ns)) { |
---|
209 | if (!create) |
---|
210 | return null; |
---|
211 | |
---|
212 | ns = new Namespace (this, first); |
---|
213 | namespaces.Add (first, ns); |
---|
214 | } |
---|
215 | |
---|
216 | if (pos >= 0) |
---|
217 | ns = ns.GetNamespace (name.Substring (pos + 1), create); |
---|
218 | |
---|
219 | return ns; |
---|
220 | } |
---|
221 | |
---|
222 | public IList<TypeSpec> GetAllTypes (string name) |
---|
223 | { |
---|
224 | IList<TypeSpec> found; |
---|
225 | if (types == null || !types.TryGetValue (name, out found)) |
---|
226 | return null; |
---|
227 | |
---|
228 | return found; |
---|
229 | } |
---|
230 | |
---|
231 | public virtual string GetSignatureForError () |
---|
232 | { |
---|
233 | return fullname; |
---|
234 | } |
---|
235 | |
---|
236 | public TypeSpec LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc) |
---|
237 | { |
---|
238 | if (types == null) |
---|
239 | return null; |
---|
240 | |
---|
241 | TypeSpec best = null; |
---|
242 | if (arity == 0 && cached_types.TryGetValue (name, out best)) { |
---|
243 | if (best != null || mode != LookupMode.IgnoreAccessibility) |
---|
244 | return best; |
---|
245 | } |
---|
246 | |
---|
247 | IList<TypeSpec> found; |
---|
248 | if (!types.TryGetValue (name, out found)) |
---|
249 | return null; |
---|
250 | |
---|
251 | foreach (var ts in found) { |
---|
252 | if (ts.Arity == arity || mode == LookupMode.NameOf) { |
---|
253 | if (best == null) { |
---|
254 | if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility) |
---|
255 | continue; |
---|
256 | |
---|
257 | best = ts; |
---|
258 | continue; |
---|
259 | } |
---|
260 | |
---|
261 | if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) { |
---|
262 | if (ts.Kind == MemberKind.MissingType) |
---|
263 | continue; |
---|
264 | |
---|
265 | if (best.Kind == MemberKind.MissingType) { |
---|
266 | best = ts; |
---|
267 | continue; |
---|
268 | } |
---|
269 | |
---|
270 | if (mode == LookupMode.Normal) { |
---|
271 | ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best); |
---|
272 | ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts); |
---|
273 | ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ()); |
---|
274 | } |
---|
275 | |
---|
276 | break; |
---|
277 | } |
---|
278 | |
---|
279 | if (best.MemberDefinition.IsImported) |
---|
280 | best = ts; |
---|
281 | |
---|
282 | if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly)) |
---|
283 | continue; |
---|
284 | |
---|
285 | if (mode != LookupMode.Normal) |
---|
286 | continue; |
---|
287 | |
---|
288 | if (ts.MemberDefinition.IsImported) { |
---|
289 | ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best); |
---|
290 | ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts); |
---|
291 | } |
---|
292 | |
---|
293 | ctx.Module.Compiler.Report.Warning (436, 2, loc, |
---|
294 | "The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition", |
---|
295 | best.GetSignatureForError ()); |
---|
296 | } |
---|
297 | |
---|
298 | // |
---|
299 | // Lookup for the best candidate with the closest arity match |
---|
300 | // |
---|
301 | if (arity < 0) { |
---|
302 | if (best == null) { |
---|
303 | best = ts; |
---|
304 | } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) { |
---|
305 | best = ts; |
---|
306 | } |
---|
307 | } |
---|
308 | } |
---|
309 | |
---|
310 | // TODO MemberCache: Cache more |
---|
311 | if (arity == 0 && mode == LookupMode.Normal) |
---|
312 | cached_types.Add (name, best); |
---|
313 | |
---|
314 | if (best != null) { |
---|
315 | var dep = best.GetMissingDependencies (); |
---|
316 | if (dep != null) |
---|
317 | ImportedTypeDefinition.Error_MissingDependency (ctx, dep, loc); |
---|
318 | } |
---|
319 | |
---|
320 | return best; |
---|
321 | } |
---|
322 | |
---|
323 | public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc) |
---|
324 | { |
---|
325 | var texpr = LookupType (ctx, name, arity, mode, loc); |
---|
326 | |
---|
327 | Namespace ns; |
---|
328 | if (arity == 0 && namespaces.TryGetValue (name, out ns)) { |
---|
329 | if (texpr == null) |
---|
330 | return new NamespaceExpression (ns, loc); |
---|
331 | |
---|
332 | if (mode != LookupMode.Probing) { |
---|
333 | //ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type); |
---|
334 | // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, ""); |
---|
335 | ctx.Module.Compiler.Report.Warning (437, 2, loc, |
---|
336 | "The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file", |
---|
337 | texpr.GetSignatureForError (), ns.GetSignatureForError ()); |
---|
338 | } |
---|
339 | |
---|
340 | if (texpr.MemberDefinition.IsImported) |
---|
341 | return new NamespaceExpression (ns, loc); |
---|
342 | } |
---|
343 | |
---|
344 | if (texpr == null) |
---|
345 | return null; |
---|
346 | |
---|
347 | return new TypeExpression (texpr, loc); |
---|
348 | } |
---|
349 | |
---|
350 | // |
---|
351 | // Completes types with the given `prefix' |
---|
352 | // |
---|
353 | public IEnumerable<string> CompletionGetTypesStartingWith (string prefix) |
---|
354 | { |
---|
355 | if (types == null) |
---|
356 | return Enumerable.Empty<string> (); |
---|
357 | |
---|
358 | var res = from item in types |
---|
359 | where item.Key.StartsWith (prefix) && item.Value.Any (l => (l.Modifiers & Modifiers.PUBLIC) != 0) |
---|
360 | select item.Key; |
---|
361 | |
---|
362 | if (namespaces != null) |
---|
363 | res = res.Concat (from item in namespaces where item.Key.StartsWith (prefix) select item.Key); |
---|
364 | |
---|
365 | return res; |
---|
366 | } |
---|
367 | |
---|
368 | // |
---|
369 | // Looks for extension method in this namespace |
---|
370 | // |
---|
371 | public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, string name, int arity) |
---|
372 | { |
---|
373 | if (extension_method_types == null) |
---|
374 | return null; |
---|
375 | |
---|
376 | List<MethodSpec> found = null; |
---|
377 | for (int i = 0; i < extension_method_types.Count; ++i) { |
---|
378 | var ts = extension_method_types[i]; |
---|
379 | |
---|
380 | // |
---|
381 | // When the list was built we didn't know what members the type |
---|
382 | // contains |
---|
383 | // |
---|
384 | if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) { |
---|
385 | if (extension_method_types.Count == 1) { |
---|
386 | extension_method_types = null; |
---|
387 | return found; |
---|
388 | } |
---|
389 | |
---|
390 | extension_method_types.RemoveAt (i--); |
---|
391 | continue; |
---|
392 | } |
---|
393 | |
---|
394 | var res = ts.MemberCache.FindExtensionMethods (invocationContext, name, arity); |
---|
395 | if (res == null) |
---|
396 | continue; |
---|
397 | |
---|
398 | if (found == null) { |
---|
399 | found = res; |
---|
400 | } else { |
---|
401 | found.AddRange (res); |
---|
402 | } |
---|
403 | } |
---|
404 | |
---|
405 | return found; |
---|
406 | } |
---|
407 | |
---|
408 | public void AddType (ModuleContainer module, TypeSpec ts) |
---|
409 | { |
---|
410 | if (types == null) { |
---|
411 | types = new Dictionary<string, IList<TypeSpec>> (64); |
---|
412 | } |
---|
413 | |
---|
414 | if (ts.IsClass && ts.Arity == 0) { |
---|
415 | var extension_method_allowed = ts.MemberDefinition.IsImported ? (ts.Modifiers & Modifiers.METHOD_EXTENSION) != 0 : (ts.IsStatic || ts.MemberDefinition.IsPartial); |
---|
416 | if (extension_method_allowed) { |
---|
417 | if (extension_method_types == null) |
---|
418 | extension_method_types = new List<TypeSpec> (); |
---|
419 | |
---|
420 | extension_method_types.Add (ts); |
---|
421 | } |
---|
422 | } |
---|
423 | |
---|
424 | var name = ts.Name; |
---|
425 | IList<TypeSpec> existing; |
---|
426 | if (types.TryGetValue (name, out existing)) { |
---|
427 | TypeSpec better_type; |
---|
428 | TypeSpec found; |
---|
429 | if (existing.Count == 1) { |
---|
430 | found = existing[0]; |
---|
431 | if (ts.Arity == found.Arity) { |
---|
432 | better_type = IsImportedTypeOverride (module, ts, found); |
---|
433 | if (better_type == found) |
---|
434 | return; |
---|
435 | |
---|
436 | if (better_type != null) { |
---|
437 | existing [0] = better_type; |
---|
438 | return; |
---|
439 | } |
---|
440 | } |
---|
441 | |
---|
442 | existing = new List<TypeSpec> (); |
---|
443 | existing.Add (found); |
---|
444 | types[name] = existing; |
---|
445 | } else { |
---|
446 | for (int i = 0; i < existing.Count; ++i) { |
---|
447 | found = existing[i]; |
---|
448 | if (ts.Arity != found.Arity) |
---|
449 | continue; |
---|
450 | |
---|
451 | better_type = IsImportedTypeOverride (module, ts, found); |
---|
452 | if (better_type == found) |
---|
453 | return; |
---|
454 | |
---|
455 | if (better_type != null) { |
---|
456 | existing.RemoveAt (i); |
---|
457 | --i; |
---|
458 | continue; |
---|
459 | } |
---|
460 | } |
---|
461 | } |
---|
462 | |
---|
463 | existing.Add (ts); |
---|
464 | } else { |
---|
465 | types.Add (name, new TypeSpec[] { ts }); |
---|
466 | } |
---|
467 | } |
---|
468 | |
---|
469 | // |
---|
470 | // We import any types but in the situation there are same types |
---|
471 | // but one has better visibility (either public or internal with friend) |
---|
472 | // the less visible type is removed from the namespace cache |
---|
473 | // |
---|
474 | public static TypeSpec IsImportedTypeOverride (ModuleContainer module, TypeSpec ts, TypeSpec found) |
---|
475 | { |
---|
476 | var ts_accessible = (ts.Modifiers & Modifiers.PUBLIC) != 0 || ts.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly); |
---|
477 | var found_accessible = (found.Modifiers & Modifiers.PUBLIC) != 0 || found.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly); |
---|
478 | |
---|
479 | if (ts_accessible && !found_accessible) |
---|
480 | return ts; |
---|
481 | |
---|
482 | // found is better always better for accessible or inaccessible ts |
---|
483 | if (!ts_accessible) |
---|
484 | return found; |
---|
485 | |
---|
486 | return null; |
---|
487 | } |
---|
488 | |
---|
489 | public void RemoveContainer (TypeContainer tc) |
---|
490 | { |
---|
491 | types.Remove (tc.Basename); |
---|
492 | cached_types.Remove (tc.Basename); |
---|
493 | } |
---|
494 | |
---|
495 | public void SetBuiltinType (BuiltinTypeSpec pts) |
---|
496 | { |
---|
497 | var found = types[pts.Name]; |
---|
498 | cached_types.Remove (pts.Name); |
---|
499 | if (found.Count == 1) { |
---|
500 | types[pts.Name][0] = pts; |
---|
501 | } else { |
---|
502 | throw new NotImplementedException (); |
---|
503 | } |
---|
504 | } |
---|
505 | |
---|
506 | public void VerifyClsCompliance () |
---|
507 | { |
---|
508 | if (types == null || cls_checked) |
---|
509 | return; |
---|
510 | |
---|
511 | cls_checked = true; |
---|
512 | |
---|
513 | // TODO: This is quite ugly way to check for CLS compliance at namespace level |
---|
514 | |
---|
515 | var locase_types = new Dictionary<string, List<TypeSpec>> (StringComparer.OrdinalIgnoreCase); |
---|
516 | foreach (var tgroup in types.Values) { |
---|
517 | foreach (var tm in tgroup) { |
---|
518 | if ((tm.Modifiers & Modifiers.PUBLIC) == 0 || !tm.IsCLSCompliant ()) |
---|
519 | continue; |
---|
520 | |
---|
521 | List<TypeSpec> found; |
---|
522 | if (!locase_types.TryGetValue (tm.Name, out found)) { |
---|
523 | found = new List<TypeSpec> (); |
---|
524 | locase_types.Add (tm.Name, found); |
---|
525 | } |
---|
526 | |
---|
527 | found.Add (tm); |
---|
528 | } |
---|
529 | } |
---|
530 | |
---|
531 | foreach (var locase in locase_types.Values) { |
---|
532 | if (locase.Count < 2) |
---|
533 | continue; |
---|
534 | |
---|
535 | bool all_same = true; |
---|
536 | foreach (var notcompliant in locase) { |
---|
537 | all_same = notcompliant.Name == locase[0].Name; |
---|
538 | if (!all_same) |
---|
539 | break; |
---|
540 | } |
---|
541 | |
---|
542 | if (all_same) |
---|
543 | continue; |
---|
544 | |
---|
545 | TypeContainer compiled = null; |
---|
546 | foreach (var notcompliant in locase) { |
---|
547 | if (!notcompliant.MemberDefinition.IsImported) { |
---|
548 | if (compiled != null) |
---|
549 | compiled.Compiler.Report.SymbolRelatedToPreviousError (compiled); |
---|
550 | |
---|
551 | compiled = notcompliant.MemberDefinition as TypeContainer; |
---|
552 | } else { |
---|
553 | compiled.Compiler.Report.SymbolRelatedToPreviousError (notcompliant); |
---|
554 | } |
---|
555 | } |
---|
556 | |
---|
557 | compiled.Compiler.Report.Warning (3005, 1, compiled.Location, |
---|
558 | "Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ()); |
---|
559 | } |
---|
560 | } |
---|
561 | } |
---|
562 | |
---|
563 | public class CompilationSourceFile : NamespaceContainer |
---|
564 | { |
---|
565 | readonly SourceFile file; |
---|
566 | CompileUnitEntry comp_unit; |
---|
567 | Dictionary<string, SourceFile> include_files; |
---|
568 | Dictionary<string, bool> conditionals; |
---|
569 | |
---|
570 | public CompilationSourceFile (ModuleContainer parent, SourceFile sourceFile) |
---|
571 | : this (parent) |
---|
572 | { |
---|
573 | this.file = sourceFile; |
---|
574 | } |
---|
575 | |
---|
576 | public CompilationSourceFile (ModuleContainer parent) |
---|
577 | : base (parent) |
---|
578 | { |
---|
579 | } |
---|
580 | |
---|
581 | public CompileUnitEntry SymbolUnitEntry { |
---|
582 | get { |
---|
583 | return comp_unit; |
---|
584 | } |
---|
585 | } |
---|
586 | |
---|
587 | public IDictionary<string, bool> Conditionals { |
---|
588 | get { |
---|
589 | return conditionals ?? new Dictionary<string, bool> (); |
---|
590 | } |
---|
591 | } |
---|
592 | |
---|
593 | public string FileName { |
---|
594 | get { |
---|
595 | return file.Name; |
---|
596 | } |
---|
597 | } |
---|
598 | |
---|
599 | public SourceFile SourceFile { |
---|
600 | get { |
---|
601 | return file; |
---|
602 | } |
---|
603 | } |
---|
604 | |
---|
605 | public void AddIncludeFile (SourceFile file) |
---|
606 | { |
---|
607 | if (file == this.file) |
---|
608 | return; |
---|
609 | |
---|
610 | if (include_files == null) |
---|
611 | include_files = new Dictionary<string, SourceFile> (); |
---|
612 | |
---|
613 | if (!include_files.ContainsKey (file.FullPathName)) |
---|
614 | include_files.Add (file.FullPathName, file); |
---|
615 | } |
---|
616 | |
---|
617 | public void AddDefine (string value) |
---|
618 | { |
---|
619 | if (conditionals == null) |
---|
620 | conditionals = new Dictionary<string, bool> (2); |
---|
621 | |
---|
622 | conditionals[value] = true; |
---|
623 | } |
---|
624 | |
---|
625 | public void AddUndefine (string value) |
---|
626 | { |
---|
627 | if (conditionals == null) |
---|
628 | conditionals = new Dictionary<string, bool> (2); |
---|
629 | |
---|
630 | conditionals[value] = false; |
---|
631 | } |
---|
632 | |
---|
633 | public override void PrepareEmit () |
---|
634 | { |
---|
635 | var sw = Module.DeclaringAssembly.SymbolWriter; |
---|
636 | if (sw != null) { |
---|
637 | CreateUnitSymbolInfo (sw); |
---|
638 | } |
---|
639 | |
---|
640 | base.PrepareEmit (); |
---|
641 | } |
---|
642 | |
---|
643 | // |
---|
644 | // Creates symbol file index in debug symbol file |
---|
645 | // |
---|
646 | void CreateUnitSymbolInfo (MonoSymbolFile symwriter) |
---|
647 | { |
---|
648 | var si = file.CreateSymbolInfo (symwriter); |
---|
649 | comp_unit = new CompileUnitEntry (symwriter, si); |
---|
650 | |
---|
651 | if (include_files != null) { |
---|
652 | foreach (SourceFile include in include_files.Values) { |
---|
653 | si = include.CreateSymbolInfo (symwriter); |
---|
654 | comp_unit.AddFile (si); |
---|
655 | } |
---|
656 | } |
---|
657 | } |
---|
658 | |
---|
659 | public bool IsConditionalDefined (string value) |
---|
660 | { |
---|
661 | if (conditionals != null) { |
---|
662 | bool res; |
---|
663 | if (conditionals.TryGetValue (value, out res)) |
---|
664 | return res; |
---|
665 | |
---|
666 | // When conditional was undefined |
---|
667 | if (conditionals.ContainsKey (value)) |
---|
668 | return false; |
---|
669 | } |
---|
670 | |
---|
671 | return Compiler.Settings.IsConditionalSymbolDefined (value); |
---|
672 | } |
---|
673 | |
---|
674 | public override void Accept (StructuralVisitor visitor) |
---|
675 | { |
---|
676 | visitor.Visit (this); |
---|
677 | } |
---|
678 | } |
---|
679 | |
---|
680 | |
---|
681 | // |
---|
682 | // Namespace block as created by the parser |
---|
683 | // |
---|
684 | public class NamespaceContainer : TypeContainer, IMemberContext |
---|
685 | { |
---|
686 | static readonly Namespace[] empty_namespaces = new Namespace[0]; |
---|
687 | |
---|
688 | readonly Namespace ns; |
---|
689 | |
---|
690 | public new readonly NamespaceContainer Parent; |
---|
691 | |
---|
692 | List<UsingNamespace> clauses; |
---|
693 | |
---|
694 | // Used by parsed to check for parser errors |
---|
695 | public bool DeclarationFound; |
---|
696 | |
---|
697 | Namespace[] namespace_using_table; |
---|
698 | TypeSpec[] types_using_table; |
---|
699 | Dictionary<string, UsingAliasNamespace> aliases; |
---|
700 | public readonly MemberName RealMemberName; |
---|
701 | |
---|
702 | public NamespaceContainer (MemberName name, NamespaceContainer parent) |
---|
703 | : base (parent, name, null, MemberKind.Namespace) |
---|
704 | { |
---|
705 | this.RealMemberName = name; |
---|
706 | this.Parent = parent; |
---|
707 | this.ns = parent.NS.AddNamespace (name); |
---|
708 | |
---|
709 | containers = new List<TypeContainer> (); |
---|
710 | } |
---|
711 | |
---|
712 | protected NamespaceContainer (ModuleContainer parent) |
---|
713 | : base (parent, null, null, MemberKind.Namespace) |
---|
714 | { |
---|
715 | ns = parent.GlobalRootNamespace; |
---|
716 | containers = new List<TypeContainer> (2); |
---|
717 | } |
---|
718 | |
---|
719 | #region Properties |
---|
720 | |
---|
721 | public override AttributeTargets AttributeTargets { |
---|
722 | get { |
---|
723 | throw new NotSupportedException (); |
---|
724 | } |
---|
725 | } |
---|
726 | |
---|
727 | public override string DocCommentHeader { |
---|
728 | get { |
---|
729 | throw new NotSupportedException (); |
---|
730 | } |
---|
731 | } |
---|
732 | |
---|
733 | public Namespace NS { |
---|
734 | get { |
---|
735 | return ns; |
---|
736 | } |
---|
737 | } |
---|
738 | |
---|
739 | public List<UsingNamespace> Usings { |
---|
740 | get { |
---|
741 | return clauses; |
---|
742 | } |
---|
743 | } |
---|
744 | |
---|
745 | public override string[] ValidAttributeTargets { |
---|
746 | get { |
---|
747 | throw new NotSupportedException (); |
---|
748 | } |
---|
749 | } |
---|
750 | |
---|
751 | #endregion |
---|
752 | |
---|
753 | public void AddUsing (UsingNamespace un) |
---|
754 | { |
---|
755 | if (DeclarationFound){ |
---|
756 | Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations"); |
---|
757 | } |
---|
758 | |
---|
759 | if (clauses == null) |
---|
760 | clauses = new List<UsingNamespace> (); |
---|
761 | |
---|
762 | clauses.Add (un); |
---|
763 | } |
---|
764 | |
---|
765 | public void AddUsing (UsingAliasNamespace un) |
---|
766 | { |
---|
767 | if (DeclarationFound){ |
---|
768 | Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations"); |
---|
769 | } |
---|
770 | |
---|
771 | AddAlias (un); |
---|
772 | } |
---|
773 | |
---|
774 | void AddAlias (UsingAliasNamespace un) |
---|
775 | { |
---|
776 | if (clauses == null) { |
---|
777 | clauses = new List<UsingNamespace> (); |
---|
778 | } else { |
---|
779 | foreach (var entry in clauses) { |
---|
780 | var a = entry as UsingAliasNamespace; |
---|
781 | if (a != null && a.Alias.Value == un.Alias.Value) { |
---|
782 | Compiler.Report.SymbolRelatedToPreviousError (a.Location, ""); |
---|
783 | Compiler.Report.Error (1537, un.Location, |
---|
784 | "The using alias `{0}' appeared previously in this namespace", un.Alias.Value); |
---|
785 | } |
---|
786 | } |
---|
787 | } |
---|
788 | |
---|
789 | clauses.Add (un); |
---|
790 | } |
---|
791 | |
---|
792 | public override void AddPartial (TypeDefinition next_part) |
---|
793 | { |
---|
794 | var existing = ns.LookupType (this, next_part.MemberName.Name, next_part.MemberName.Arity, LookupMode.Probing, Location.Null); |
---|
795 | var td = existing != null ? existing.MemberDefinition as TypeDefinition : null; |
---|
796 | AddPartial (next_part, td); |
---|
797 | } |
---|
798 | |
---|
799 | public override void AddTypeContainer (TypeContainer tc) |
---|
800 | { |
---|
801 | string name = tc.Basename; |
---|
802 | |
---|
803 | var mn = tc.MemberName; |
---|
804 | while (mn.Left != null) { |
---|
805 | mn = mn.Left; |
---|
806 | name = mn.Name; |
---|
807 | } |
---|
808 | |
---|
809 | var names_container = Parent == null ? Module : (TypeContainer) this; |
---|
810 | |
---|
811 | MemberCore mc; |
---|
812 | if (names_container.DefinedNames.TryGetValue (name, out mc)) { |
---|
813 | if (tc is NamespaceContainer && mc is NamespaceContainer) { |
---|
814 | AddTypeContainerMember (tc); |
---|
815 | return; |
---|
816 | } |
---|
817 | |
---|
818 | Report.SymbolRelatedToPreviousError (mc); |
---|
819 | if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (tc is ClassOrStruct || tc is Interface)) { |
---|
820 | Error_MissingPartialModifier (tc); |
---|
821 | } else { |
---|
822 | Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'", |
---|
823 | GetSignatureForError (), mn.GetSignatureForError ()); |
---|
824 | } |
---|
825 | } else { |
---|
826 | names_container.DefinedNames.Add (name, tc); |
---|
827 | |
---|
828 | var tdef = tc.PartialContainer; |
---|
829 | if (tdef != null) { |
---|
830 | // |
---|
831 | // Same name conflict in different namespace containers |
---|
832 | // |
---|
833 | var conflict = ns.GetAllTypes (name); |
---|
834 | if (conflict != null) { |
---|
835 | foreach (var e in conflict) { |
---|
836 | if (e.Arity == mn.Arity) { |
---|
837 | mc = (MemberCore) e.MemberDefinition; |
---|
838 | break; |
---|
839 | } |
---|
840 | } |
---|
841 | } |
---|
842 | |
---|
843 | if (mc != null) { |
---|
844 | Report.SymbolRelatedToPreviousError (mc); |
---|
845 | Report.Error (101, tc.Location, "The namespace `{0}' already contains a definition for `{1}'", |
---|
846 | GetSignatureForError (), mn.GetSignatureForError ()); |
---|
847 | } else { |
---|
848 | ns.AddType (Module, tdef.Definition); |
---|
849 | } |
---|
850 | } |
---|
851 | } |
---|
852 | |
---|
853 | base.AddTypeContainer (tc); |
---|
854 | } |
---|
855 | |
---|
856 | public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) |
---|
857 | { |
---|
858 | throw new NotSupportedException (); |
---|
859 | } |
---|
860 | |
---|
861 | public override void EmitContainer () |
---|
862 | { |
---|
863 | VerifyClsCompliance (); |
---|
864 | |
---|
865 | base.EmitContainer (); |
---|
866 | } |
---|
867 | |
---|
868 | public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, int position) |
---|
869 | { |
---|
870 | // |
---|
871 | // Here we try to resume the search for extension method at the point |
---|
872 | // where the last bunch of candidates was found. It's more tricky than |
---|
873 | // it seems as we have to check both namespace containers and namespace |
---|
874 | // in correct order. |
---|
875 | // |
---|
876 | // Consider: |
---|
877 | // |
---|
878 | // namespace A { |
---|
879 | // using N1; |
---|
880 | // namespace B.C.D { |
---|
881 | // <our first search found candidates in A.B.C.D |
---|
882 | // } |
---|
883 | // } |
---|
884 | // |
---|
885 | // In the example above namespace A.B.C.D, A.B.C and A.B have to be |
---|
886 | // checked before we hit A.N1 using |
---|
887 | // |
---|
888 | ExtensionMethodCandidates candidates; |
---|
889 | var container = this; |
---|
890 | do { |
---|
891 | candidates = container.LookupExtensionMethodCandidates (invocationContext, name, arity, ref position); |
---|
892 | if (candidates != null || container.MemberName == null) |
---|
893 | return candidates; |
---|
894 | |
---|
895 | var container_ns = container.ns.Parent; |
---|
896 | var mn = container.MemberName.Left; |
---|
897 | int already_checked = position - 2; |
---|
898 | while (already_checked-- > 0) { |
---|
899 | mn = mn.Left; |
---|
900 | container_ns = container_ns.Parent; |
---|
901 | } |
---|
902 | |
---|
903 | while (mn != null) { |
---|
904 | ++position; |
---|
905 | |
---|
906 | var methods = container_ns.LookupExtensionMethod (invocationContext, name, arity); |
---|
907 | if (methods != null) { |
---|
908 | return new ExtensionMethodCandidates (invocationContext, methods, container, position); |
---|
909 | } |
---|
910 | |
---|
911 | mn = mn.Left; |
---|
912 | container_ns = container_ns.Parent; |
---|
913 | } |
---|
914 | |
---|
915 | position = 0; |
---|
916 | container = container.Parent; |
---|
917 | } while (container != null); |
---|
918 | |
---|
919 | return null; |
---|
920 | } |
---|
921 | |
---|
922 | ExtensionMethodCandidates LookupExtensionMethodCandidates (IMemberContext invocationContext, string name, int arity, ref int position) |
---|
923 | { |
---|
924 | List<MethodSpec> candidates = null; |
---|
925 | |
---|
926 | if (position == 0) { |
---|
927 | ++position; |
---|
928 | |
---|
929 | candidates = ns.LookupExtensionMethod (invocationContext, name, arity); |
---|
930 | if (candidates != null) { |
---|
931 | return new ExtensionMethodCandidates (invocationContext, candidates, this, position); |
---|
932 | } |
---|
933 | } |
---|
934 | |
---|
935 | if (position == 1) { |
---|
936 | ++position; |
---|
937 | |
---|
938 | foreach (Namespace n in namespace_using_table) { |
---|
939 | var a = n.LookupExtensionMethod (invocationContext, name, arity); |
---|
940 | if (a == null) |
---|
941 | continue; |
---|
942 | |
---|
943 | if (candidates == null) |
---|
944 | candidates = a; |
---|
945 | else |
---|
946 | candidates.AddRange (a); |
---|
947 | } |
---|
948 | |
---|
949 | if (candidates != null) |
---|
950 | return new ExtensionMethodCandidates (invocationContext, candidates, this, position); |
---|
951 | } |
---|
952 | |
---|
953 | // LAMESPEC: TODO no spec about priority over normal extension methods yet |
---|
954 | if (types_using_table != null) { |
---|
955 | foreach (var t in types_using_table) { |
---|
956 | |
---|
957 | var res = t.MemberCache.FindExtensionMethods (invocationContext, name, arity); |
---|
958 | if (res == null) |
---|
959 | continue; |
---|
960 | |
---|
961 | if (candidates == null) |
---|
962 | candidates = res; |
---|
963 | else |
---|
964 | candidates.AddRange (res); |
---|
965 | } |
---|
966 | |
---|
967 | if (candidates != null) |
---|
968 | return new ExtensionMethodCandidates (invocationContext, candidates, this, position); |
---|
969 | } |
---|
970 | |
---|
971 | return null; |
---|
972 | } |
---|
973 | |
---|
974 | public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) |
---|
975 | { |
---|
976 | // |
---|
977 | // Only simple names (no dots) will be looked up with this function |
---|
978 | // |
---|
979 | FullNamedExpression resolved; |
---|
980 | for (NamespaceContainer container = this; container != null; container = container.Parent) { |
---|
981 | resolved = container.Lookup (name, arity, mode, loc); |
---|
982 | if (resolved != null || container.MemberName == null) |
---|
983 | return resolved; |
---|
984 | |
---|
985 | var container_ns = container.ns.Parent; |
---|
986 | var mn = container.MemberName.Left; |
---|
987 | while (mn != null) { |
---|
988 | resolved = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc); |
---|
989 | if (resolved != null) |
---|
990 | return resolved; |
---|
991 | |
---|
992 | mn = mn.Left; |
---|
993 | container_ns = container_ns.Parent; |
---|
994 | } |
---|
995 | } |
---|
996 | |
---|
997 | return null; |
---|
998 | } |
---|
999 | |
---|
1000 | public override void GetCompletionStartingWith (string prefix, List<string> results) |
---|
1001 | { |
---|
1002 | if (Usings == null) |
---|
1003 | return; |
---|
1004 | |
---|
1005 | foreach (var un in Usings) { |
---|
1006 | if (un.Alias != null) |
---|
1007 | continue; |
---|
1008 | |
---|
1009 | var name = un.NamespaceExpression.Name; |
---|
1010 | if (name.StartsWith (prefix)) |
---|
1011 | results.Add (name); |
---|
1012 | } |
---|
1013 | |
---|
1014 | |
---|
1015 | IEnumerable<string> all = Enumerable.Empty<string> (); |
---|
1016 | |
---|
1017 | foreach (Namespace using_ns in namespace_using_table) { |
---|
1018 | if (prefix.StartsWith (using_ns.Name)) { |
---|
1019 | int ld = prefix.LastIndexOf ('.'); |
---|
1020 | if (ld != -1) { |
---|
1021 | string rest = prefix.Substring (ld + 1); |
---|
1022 | |
---|
1023 | all = all.Concat (using_ns.CompletionGetTypesStartingWith (rest)); |
---|
1024 | } |
---|
1025 | } |
---|
1026 | all = all.Concat (using_ns.CompletionGetTypesStartingWith (prefix)); |
---|
1027 | } |
---|
1028 | |
---|
1029 | results.AddRange (all); |
---|
1030 | |
---|
1031 | base.GetCompletionStartingWith (prefix, results); |
---|
1032 | } |
---|
1033 | |
---|
1034 | |
---|
1035 | // |
---|
1036 | // Looks-up a alias named @name in this and surrounding namespace declarations |
---|
1037 | // |
---|
1038 | public FullNamedExpression LookupExternAlias (string name) |
---|
1039 | { |
---|
1040 | if (aliases == null) |
---|
1041 | return null; |
---|
1042 | |
---|
1043 | UsingAliasNamespace uan; |
---|
1044 | if (aliases.TryGetValue (name, out uan) && uan is UsingExternAlias) |
---|
1045 | return uan.ResolvedExpression; |
---|
1046 | |
---|
1047 | return null; |
---|
1048 | } |
---|
1049 | |
---|
1050 | // |
---|
1051 | // Looks-up a alias named @name in this and surrounding namespace declarations |
---|
1052 | // |
---|
1053 | public override FullNamedExpression LookupNamespaceAlias (string name) |
---|
1054 | { |
---|
1055 | for (NamespaceContainer n = this; n != null; n = n.Parent) { |
---|
1056 | if (n.aliases == null) |
---|
1057 | continue; |
---|
1058 | |
---|
1059 | UsingAliasNamespace uan; |
---|
1060 | if (n.aliases.TryGetValue (name, out uan)) |
---|
1061 | return uan.ResolvedExpression; |
---|
1062 | } |
---|
1063 | |
---|
1064 | return null; |
---|
1065 | } |
---|
1066 | |
---|
1067 | FullNamedExpression Lookup (string name, int arity, LookupMode mode, Location loc) |
---|
1068 | { |
---|
1069 | // |
---|
1070 | // Check whether it's in the namespace. |
---|
1071 | // |
---|
1072 | FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, mode, loc); |
---|
1073 | |
---|
1074 | // |
---|
1075 | // Check aliases. |
---|
1076 | // |
---|
1077 | if (aliases != null && arity == 0) { |
---|
1078 | UsingAliasNamespace uan; |
---|
1079 | if (aliases.TryGetValue (name, out uan)) { |
---|
1080 | if (fne != null && mode != LookupMode.Probing) { |
---|
1081 | // TODO: Namespace has broken location |
---|
1082 | //Report.SymbolRelatedToPreviousError (fne.Location, null); |
---|
1083 | Compiler.Report.SymbolRelatedToPreviousError (uan.Location, null); |
---|
1084 | Compiler.Report.Error (576, loc, |
---|
1085 | "Namespace `{0}' contains a definition with same name as alias `{1}'", |
---|
1086 | GetSignatureForError (), name); |
---|
1087 | } |
---|
1088 | |
---|
1089 | return uan.ResolvedExpression; |
---|
1090 | } |
---|
1091 | } |
---|
1092 | |
---|
1093 | if (fne != null) |
---|
1094 | return fne; |
---|
1095 | |
---|
1096 | // |
---|
1097 | // Lookup can be called before the namespace is defined from different namespace using alias clause |
---|
1098 | // |
---|
1099 | if (namespace_using_table == null) { |
---|
1100 | DoDefineNamespace (); |
---|
1101 | } |
---|
1102 | |
---|
1103 | // |
---|
1104 | // Check using entries. |
---|
1105 | // |
---|
1106 | FullNamedExpression match = null; |
---|
1107 | foreach (Namespace using_ns in namespace_using_table) { |
---|
1108 | // |
---|
1109 | // A using directive imports only types contained in the namespace, it |
---|
1110 | // does not import any nested namespaces |
---|
1111 | // |
---|
1112 | var t = using_ns.LookupType (this, name, arity, mode, loc); |
---|
1113 | if (t == null) |
---|
1114 | continue; |
---|
1115 | |
---|
1116 | fne = new TypeExpression (t, loc); |
---|
1117 | if (match == null) { |
---|
1118 | match = fne; |
---|
1119 | continue; |
---|
1120 | } |
---|
1121 | |
---|
1122 | // Prefer types over namespaces |
---|
1123 | var texpr_fne = fne as TypeExpr; |
---|
1124 | var texpr_match = match as TypeExpr; |
---|
1125 | if (texpr_fne != null && texpr_match == null) { |
---|
1126 | match = fne; |
---|
1127 | continue; |
---|
1128 | } else if (texpr_fne == null) { |
---|
1129 | continue; |
---|
1130 | } |
---|
1131 | |
---|
1132 | // It can be top level accessibility only |
---|
1133 | var better = Namespace.IsImportedTypeOverride (Module, texpr_match.Type, texpr_fne.Type); |
---|
1134 | if (better == null) { |
---|
1135 | if (mode == LookupMode.Normal) { |
---|
1136 | Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type); |
---|
1137 | Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type); |
---|
1138 | Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'", |
---|
1139 | name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ()); |
---|
1140 | } |
---|
1141 | |
---|
1142 | return match; |
---|
1143 | } |
---|
1144 | |
---|
1145 | if (better == texpr_fne.Type) |
---|
1146 | match = texpr_fne; |
---|
1147 | } |
---|
1148 | |
---|
1149 | return match; |
---|
1150 | } |
---|
1151 | |
---|
1152 | public static MethodGroupExpr LookupStaticUsings (IMemberContext mc, string name, int arity, Location loc) |
---|
1153 | { |
---|
1154 | for (var m = mc.CurrentMemberDefinition; m != null; m = m.Parent) { |
---|
1155 | |
---|
1156 | var nc = m as NamespaceContainer; |
---|
1157 | if (nc == null) |
---|
1158 | continue; |
---|
1159 | |
---|
1160 | List<MemberSpec> candidates = null; |
---|
1161 | if (nc.types_using_table != null) { |
---|
1162 | foreach (var using_type in nc.types_using_table) { |
---|
1163 | var members = MemberCache.FindMembers (using_type, name, true); |
---|
1164 | if (members != null) { |
---|
1165 | foreach (var member in members) { |
---|
1166 | if ((member.Modifiers & Modifiers.METHOD_EXTENSION) != 0) |
---|
1167 | continue; |
---|
1168 | |
---|
1169 | if (arity > 0 && member.Arity != arity) |
---|
1170 | continue; |
---|
1171 | |
---|
1172 | if (candidates == null) |
---|
1173 | candidates = new List<MemberSpec> (); |
---|
1174 | |
---|
1175 | candidates.Add (member); |
---|
1176 | } |
---|
1177 | } |
---|
1178 | } |
---|
1179 | } |
---|
1180 | |
---|
1181 | if (candidates != null) |
---|
1182 | return new MethodGroupExpr (candidates, null, loc); |
---|
1183 | } |
---|
1184 | |
---|
1185 | return null; |
---|
1186 | } |
---|
1187 | |
---|
1188 | protected override void DefineNamespace () |
---|
1189 | { |
---|
1190 | if (namespace_using_table == null) |
---|
1191 | DoDefineNamespace (); |
---|
1192 | |
---|
1193 | base.DefineNamespace (); |
---|
1194 | } |
---|
1195 | |
---|
1196 | void DoDefineNamespace () |
---|
1197 | { |
---|
1198 | namespace_using_table = empty_namespaces; |
---|
1199 | |
---|
1200 | if (clauses != null) { |
---|
1201 | List<Namespace> namespaces = null; |
---|
1202 | List<TypeSpec> types = null; |
---|
1203 | |
---|
1204 | bool post_process_using_aliases = false; |
---|
1205 | |
---|
1206 | for (int i = 0; i < clauses.Count; ++i) { |
---|
1207 | var entry = clauses[i]; |
---|
1208 | |
---|
1209 | if (entry.Alias != null) { |
---|
1210 | if (aliases == null) |
---|
1211 | aliases = new Dictionary<string, UsingAliasNamespace> (); |
---|
1212 | |
---|
1213 | // |
---|
1214 | // Aliases are not available when resolving using section |
---|
1215 | // except extern aliases |
---|
1216 | // |
---|
1217 | if (entry is UsingExternAlias) { |
---|
1218 | entry.Define (this); |
---|
1219 | if (entry.ResolvedExpression != null) |
---|
1220 | aliases.Add (entry.Alias.Value, (UsingExternAlias) entry); |
---|
1221 | |
---|
1222 | clauses.RemoveAt (i--); |
---|
1223 | } else { |
---|
1224 | post_process_using_aliases = true; |
---|
1225 | } |
---|
1226 | |
---|
1227 | continue; |
---|
1228 | } |
---|
1229 | |
---|
1230 | entry.Define (this); |
---|
1231 | |
---|
1232 | // |
---|
1233 | // It's needed for repl only, when using clause cannot be resolved don't hold it in |
---|
1234 | // global list which is resolved for each evaluation |
---|
1235 | // |
---|
1236 | if (entry.ResolvedExpression == null) { |
---|
1237 | clauses.RemoveAt (i--); |
---|
1238 | continue; |
---|
1239 | } |
---|
1240 | |
---|
1241 | var using_ns = entry.ResolvedExpression as NamespaceExpression; |
---|
1242 | if (using_ns == null) { |
---|
1243 | |
---|
1244 | var type = ((TypeExpr)entry.ResolvedExpression).Type; |
---|
1245 | |
---|
1246 | if (types == null) |
---|
1247 | types = new List<TypeSpec> (); |
---|
1248 | |
---|
1249 | if (types.Contains (type)) { |
---|
1250 | Warning_DuplicateEntry (entry); |
---|
1251 | } else { |
---|
1252 | types.Add (type); |
---|
1253 | } |
---|
1254 | } else { |
---|
1255 | if (namespaces == null) |
---|
1256 | namespaces = new List<Namespace> (); |
---|
1257 | |
---|
1258 | if (namespaces.Contains (using_ns.Namespace)) { |
---|
1259 | // Ensure we don't report the warning multiple times in repl |
---|
1260 | clauses.RemoveAt (i--); |
---|
1261 | |
---|
1262 | Warning_DuplicateEntry (entry); |
---|
1263 | } else { |
---|
1264 | namespaces.Add (using_ns.Namespace); |
---|
1265 | } |
---|
1266 | } |
---|
1267 | } |
---|
1268 | |
---|
1269 | namespace_using_table = namespaces == null ? new Namespace [0] : namespaces.ToArray (); |
---|
1270 | if (types != null) |
---|
1271 | types_using_table = types.ToArray (); |
---|
1272 | |
---|
1273 | if (post_process_using_aliases) { |
---|
1274 | for (int i = 0; i < clauses.Count; ++i) { |
---|
1275 | var entry = clauses[i]; |
---|
1276 | if (entry.Alias != null) { |
---|
1277 | entry.Define (this); |
---|
1278 | if (entry.ResolvedExpression != null) { |
---|
1279 | aliases.Add (entry.Alias.Value, (UsingAliasNamespace) entry); |
---|
1280 | } |
---|
1281 | |
---|
1282 | clauses.RemoveAt (i--); |
---|
1283 | } |
---|
1284 | } |
---|
1285 | } |
---|
1286 | } |
---|
1287 | } |
---|
1288 | |
---|
1289 | public void EnableRedefinition () |
---|
1290 | { |
---|
1291 | is_defined = false; |
---|
1292 | namespace_using_table = null; |
---|
1293 | } |
---|
1294 | |
---|
1295 | internal override void GenerateDocComment (DocumentationBuilder builder) |
---|
1296 | { |
---|
1297 | if (containers != null) { |
---|
1298 | foreach (var tc in containers) |
---|
1299 | tc.GenerateDocComment (builder); |
---|
1300 | } |
---|
1301 | } |
---|
1302 | |
---|
1303 | public override string GetSignatureForError () |
---|
1304 | { |
---|
1305 | return MemberName == null ? "global::" : base.GetSignatureForError (); |
---|
1306 | } |
---|
1307 | |
---|
1308 | public override void RemoveContainer (TypeContainer cont) |
---|
1309 | { |
---|
1310 | base.RemoveContainer (cont); |
---|
1311 | NS.RemoveContainer (cont); |
---|
1312 | } |
---|
1313 | |
---|
1314 | protected override bool VerifyClsCompliance () |
---|
1315 | { |
---|
1316 | if (Module.IsClsComplianceRequired ()) { |
---|
1317 | if (MemberName != null && MemberName.Name[0] == '_') { |
---|
1318 | Warning_IdentifierNotCompliant (); |
---|
1319 | } |
---|
1320 | |
---|
1321 | ns.VerifyClsCompliance (); |
---|
1322 | return true; |
---|
1323 | } |
---|
1324 | |
---|
1325 | return false; |
---|
1326 | } |
---|
1327 | |
---|
1328 | void Warning_DuplicateEntry (UsingNamespace entry) |
---|
1329 | { |
---|
1330 | Compiler.Report.Warning (105, 3, entry.Location, |
---|
1331 | "The using directive for `{0}' appeared previously in this namespace", |
---|
1332 | entry.ResolvedExpression.GetSignatureForError ()); |
---|
1333 | } |
---|
1334 | |
---|
1335 | public override void Accept (StructuralVisitor visitor) |
---|
1336 | { |
---|
1337 | visitor.Visit (this); |
---|
1338 | } |
---|
1339 | } |
---|
1340 | |
---|
1341 | public class UsingNamespace |
---|
1342 | { |
---|
1343 | readonly ATypeNameExpression expr; |
---|
1344 | readonly Location loc; |
---|
1345 | protected FullNamedExpression resolved; |
---|
1346 | |
---|
1347 | public UsingNamespace (ATypeNameExpression expr, Location loc) |
---|
1348 | { |
---|
1349 | this.expr = expr; |
---|
1350 | this.loc = loc; |
---|
1351 | } |
---|
1352 | |
---|
1353 | #region Properties |
---|
1354 | |
---|
1355 | public virtual SimpleMemberName Alias { |
---|
1356 | get { |
---|
1357 | return null; |
---|
1358 | } |
---|
1359 | } |
---|
1360 | |
---|
1361 | public Location Location { |
---|
1362 | get { |
---|
1363 | return loc; |
---|
1364 | } |
---|
1365 | } |
---|
1366 | |
---|
1367 | public ATypeNameExpression NamespaceExpression { |
---|
1368 | get { |
---|
1369 | return expr; |
---|
1370 | } |
---|
1371 | } |
---|
1372 | |
---|
1373 | public FullNamedExpression ResolvedExpression { |
---|
1374 | get { |
---|
1375 | return resolved; |
---|
1376 | } |
---|
1377 | } |
---|
1378 | |
---|
1379 | #endregion |
---|
1380 | |
---|
1381 | public string GetSignatureForError () |
---|
1382 | { |
---|
1383 | return expr.GetSignatureForError (); |
---|
1384 | } |
---|
1385 | |
---|
1386 | public virtual void Define (NamespaceContainer ctx) |
---|
1387 | { |
---|
1388 | resolved = expr.ResolveAsTypeOrNamespace (ctx, false); |
---|
1389 | var ns = resolved as NamespaceExpression; |
---|
1390 | if (ns != null) |
---|
1391 | return; |
---|
1392 | |
---|
1393 | if (resolved != null) { |
---|
1394 | var compiler = ctx.Module.Compiler; |
---|
1395 | var type = resolved.Type; |
---|
1396 | if (compiler.Settings.Version >= LanguageVersion.V_6) { |
---|
1397 | if (!type.IsClass || !type.IsStatic) { |
---|
1398 | compiler.Report.SymbolRelatedToPreviousError (type); |
---|
1399 | compiler.Report.Error (7007, Location, |
---|
1400 | "`{0}' is not a static class. A using namespace directive can only be applied to static classes or namespace", |
---|
1401 | GetSignatureForError ()); |
---|
1402 | } |
---|
1403 | |
---|
1404 | return; |
---|
1405 | } |
---|
1406 | |
---|
1407 | compiler.Report.SymbolRelatedToPreviousError (type); |
---|
1408 | compiler.Report.Error (138, Location, |
---|
1409 | "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces", |
---|
1410 | GetSignatureForError ()); |
---|
1411 | } |
---|
1412 | } |
---|
1413 | |
---|
1414 | public virtual void Accept (StructuralVisitor visitor) |
---|
1415 | { |
---|
1416 | visitor.Visit (this); |
---|
1417 | } |
---|
1418 | |
---|
1419 | public override string ToString() |
---|
1420 | { |
---|
1421 | return resolved.ToString(); |
---|
1422 | } |
---|
1423 | } |
---|
1424 | |
---|
1425 | public class UsingExternAlias : UsingAliasNamespace |
---|
1426 | { |
---|
1427 | public UsingExternAlias (SimpleMemberName alias, Location loc) |
---|
1428 | : base (alias, null, loc) |
---|
1429 | { |
---|
1430 | } |
---|
1431 | |
---|
1432 | public override void Define (NamespaceContainer ctx) |
---|
1433 | { |
---|
1434 | var ns = ctx.Module.GetRootNamespace (Alias.Value); |
---|
1435 | if (ns == null) { |
---|
1436 | ctx.Module.Compiler.Report.Error (430, Location, |
---|
1437 | "The extern alias `{0}' was not specified in -reference option", |
---|
1438 | Alias.Value); |
---|
1439 | return; |
---|
1440 | } |
---|
1441 | |
---|
1442 | resolved = new NamespaceExpression (ns, Location); |
---|
1443 | } |
---|
1444 | |
---|
1445 | public override void Accept (StructuralVisitor visitor) |
---|
1446 | { |
---|
1447 | visitor.Visit (this); |
---|
1448 | } |
---|
1449 | } |
---|
1450 | |
---|
1451 | public class UsingAliasNamespace : UsingNamespace |
---|
1452 | { |
---|
1453 | readonly SimpleMemberName alias; |
---|
1454 | |
---|
1455 | public struct AliasContext : IMemberContext |
---|
1456 | { |
---|
1457 | readonly NamespaceContainer ns; |
---|
1458 | |
---|
1459 | public AliasContext (NamespaceContainer ns) |
---|
1460 | { |
---|
1461 | this.ns = ns; |
---|
1462 | } |
---|
1463 | |
---|
1464 | public TypeSpec CurrentType { |
---|
1465 | get { |
---|
1466 | return null; |
---|
1467 | } |
---|
1468 | } |
---|
1469 | |
---|
1470 | public TypeParameters CurrentTypeParameters { |
---|
1471 | get { |
---|
1472 | return null; |
---|
1473 | } |
---|
1474 | } |
---|
1475 | |
---|
1476 | public MemberCore CurrentMemberDefinition { |
---|
1477 | get { |
---|
1478 | return null; |
---|
1479 | } |
---|
1480 | } |
---|
1481 | |
---|
1482 | public bool IsObsolete { |
---|
1483 | get { |
---|
1484 | return false; |
---|
1485 | } |
---|
1486 | } |
---|
1487 | |
---|
1488 | public bool IsUnsafe { |
---|
1489 | get { |
---|
1490 | throw new NotImplementedException (); |
---|
1491 | } |
---|
1492 | } |
---|
1493 | |
---|
1494 | public bool IsStatic { |
---|
1495 | get { |
---|
1496 | throw new NotImplementedException (); |
---|
1497 | } |
---|
1498 | } |
---|
1499 | |
---|
1500 | public ModuleContainer Module { |
---|
1501 | get { |
---|
1502 | return ns.Module; |
---|
1503 | } |
---|
1504 | } |
---|
1505 | |
---|
1506 | public string GetSignatureForError () |
---|
1507 | { |
---|
1508 | throw new NotImplementedException (); |
---|
1509 | } |
---|
1510 | |
---|
1511 | public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity) |
---|
1512 | { |
---|
1513 | return null; |
---|
1514 | } |
---|
1515 | |
---|
1516 | public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) |
---|
1517 | { |
---|
1518 | var fne = ns.NS.LookupTypeOrNamespace (ns, name, arity, mode, loc); |
---|
1519 | if (fne != null) |
---|
1520 | return fne; |
---|
1521 | |
---|
1522 | // |
---|
1523 | // Only extern aliases are allowed in this context |
---|
1524 | // |
---|
1525 | fne = ns.LookupExternAlias (name); |
---|
1526 | if (fne != null || ns.MemberName == null) |
---|
1527 | return fne; |
---|
1528 | |
---|
1529 | var container_ns = ns.NS.Parent; |
---|
1530 | var mn = ns.MemberName.Left; |
---|
1531 | while (mn != null) { |
---|
1532 | fne = container_ns.LookupTypeOrNamespace (this, name, arity, mode, loc); |
---|
1533 | if (fne != null) |
---|
1534 | return fne; |
---|
1535 | |
---|
1536 | mn = mn.Left; |
---|
1537 | container_ns = container_ns.Parent; |
---|
1538 | } |
---|
1539 | |
---|
1540 | if (ns.Parent != null) |
---|
1541 | return ns.Parent.LookupNamespaceOrType (name, arity, mode, loc); |
---|
1542 | |
---|
1543 | return null; |
---|
1544 | } |
---|
1545 | |
---|
1546 | public FullNamedExpression LookupNamespaceAlias (string name) |
---|
1547 | { |
---|
1548 | return ns.LookupNamespaceAlias (name); |
---|
1549 | } |
---|
1550 | } |
---|
1551 | |
---|
1552 | public UsingAliasNamespace (SimpleMemberName alias, ATypeNameExpression expr, Location loc) |
---|
1553 | : base (expr, loc) |
---|
1554 | { |
---|
1555 | this.alias = alias; |
---|
1556 | } |
---|
1557 | |
---|
1558 | public override SimpleMemberName Alias { |
---|
1559 | get { |
---|
1560 | return alias; |
---|
1561 | } |
---|
1562 | } |
---|
1563 | |
---|
1564 | public override void Define (NamespaceContainer ctx) |
---|
1565 | { |
---|
1566 | // |
---|
1567 | // The namespace-or-type-name of a using-alias-directive is resolved as if |
---|
1568 | // the immediately containing compilation unit or namespace body had no |
---|
1569 | // using-directives. A using-alias-directive may however be affected |
---|
1570 | // by extern-alias-directives in the immediately containing compilation |
---|
1571 | // unit or namespace body |
---|
1572 | // |
---|
1573 | // We achieve that by introducing alias-context which redirect any local |
---|
1574 | // namespace or type resolve calls to parent namespace |
---|
1575 | // |
---|
1576 | resolved = NamespaceExpression.ResolveAsTypeOrNamespace (new AliasContext (ctx), false); |
---|
1577 | } |
---|
1578 | |
---|
1579 | public override void Accept (StructuralVisitor visitor) |
---|
1580 | { |
---|
1581 | visitor.Visit (this); |
---|
1582 | } |
---|
1583 | } |
---|
1584 | } |
---|