Fix XMM scanning on Mac x86.
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / View / TypeBrowser.xaml.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4 namespace System.Activities.Presentation.View
5 {
6     using System;
7     using System.Collections.ObjectModel;
8     using System.ComponentModel;
9     using System.IO;
10     using System.Linq;
11     using System.Reflection;
12     using System.Windows;
13     using System.Windows.Automation.Peers;
14     using System.Windows.Controls;
15     using System.Windows.Input;
16     using System.Collections.Specialized;
17     using System.Collections.Generic;
18     using System.Diagnostics.CodeAnalysis;
19     using System.Text;
20     using System.ComponentModel.Design;
21     using System.Activities.Presentation.Hosting;
22     using System.Windows.Threading;
23     using Microsoft.Activities.Presentation;
24
25     internal sealed partial class TypeBrowser : DialogWindow
26     {
27         static readonly DependencyProperty SelectedTypeProperty =
28             DependencyProperty.Register("SelectedType",
29             typeof(Type),
30             typeof(TypeBrowser),
31             new UIPropertyMetadata());
32
33         static readonly DependencyProperty HasGenericTypesProperty =
34             DependencyProperty.Register("HasGenericTypes",
35             typeof(bool),
36             typeof(TypeBrowser));
37
38         static readonly DependencyProperty GenericTypeNameProperty =
39             DependencyProperty.Register("GenericTypeName",
40             typeof(String),
41             typeof(TypeBrowser));
42
43         static readonly DependencyProperty GenericTypeMappingProperty =
44             DependencyProperty.Register("GenericTypeMapping",
45             typeof(ObservableCollection<TypeKeyValue>),
46             typeof(TypeBrowser));
47
48         static readonly DependencyProperty ConcreteTypeProperty =
49             DependencyProperty.Register("ConcreteType",
50             typeof(Type),
51             typeof(TypeBrowser));
52
53         static Size size = Size.Empty;
54
55         SearchAction currentSearch = null;
56
57         ObservableCollection<AssemblyNode> localAssemblies;
58         ObservableCollection<AssemblyNode> referenceAssemblies;
59         AssemblyContextControlItem assemblyContext;
60         Func<Type, bool> filter;
61         DesignerPerfEventProvider perfEventProvider;
62
63         public TypeBrowser(AssemblyContextControlItem assemblyContext, EditingContext context, Func<Type, bool> filter)
64         {
65             this.assemblyContext = assemblyContext;
66             this.Context = context;
67             this.filter = filter;
68             SetValue(GenericTypeMappingProperty, new ObservableCollection<TypeKeyValue>());
69             GenericTypeMapping.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(GenericTypeMappingCollectionChanged);
70             InitializeComponent();
71             this.typeEntryTextBox.Focus();
72
73             if (!size.IsEmpty)
74             {
75                 this.Height = size.Height;
76                 this.Width = size.Width;
77             }
78
79             this.SizeChanged += new SizeChangedEventHandler(TypeBrowser_SizeChanged);
80
81             this.HelpKeyword = HelpKeywords.TypeBrowser;
82             this.perfEventProvider = new DesignerPerfEventProvider();
83         }
84
85         static void TypeBrowser_SizeChanged(object sender, SizeChangedEventArgs e)
86         {
87             TypeBrowser.size = e.NewSize;
88         }
89
90         Type SelectedType
91         {
92             get { return (Type)GetValue(SelectedTypeProperty); }
93             set { SetValue(SelectedTypeProperty, value); }
94         }
95
96         bool HasGenericTypes
97         {
98             get { return (bool)GetValue(HasGenericTypesProperty); }
99             set { SetValue(HasGenericTypesProperty, value); }
100         }
101
102         string GenericTypeName
103         {
104             get { return (string)GetValue(GenericTypeNameProperty); }
105             set { SetValue(GenericTypeNameProperty, value); }
106         }
107
108         ObservableCollection<TypeKeyValue> GenericTypeMapping
109         {
110             get { return (ObservableCollection<TypeKeyValue>)GetValue(GenericTypeMappingProperty); }
111             set { SetValue(GenericTypeMappingProperty, value); }
112         }
113
114         public Type ConcreteType
115         {
116             get { return (Type)GetValue(ConcreteTypeProperty); }
117             private set { SetValue(ConcreteTypeProperty, value); }
118         }
119
120         public ObservableCollection<AssemblyNode> LocalAssemblies
121         {
122             get
123             {
124                 if (null == this.localAssemblies)
125                 {
126                     this.localAssemblies = new ObservableCollection<AssemblyNode>();
127                     if (null != this.assemblyContext)
128                     {
129                         if (null != this.assemblyContext.LocalAssemblyName)
130                         {
131                             IMultiTargetingSupportService multiTargetingSupportService = this.Context.Services.GetService<IMultiTargetingSupportService>();
132                             Assembly local = AssemblyContextControlItem.GetAssembly(this.assemblyContext.LocalAssemblyName, multiTargetingSupportService);
133                             if (local != null)
134                             {
135                                 this.localAssemblies.Add(new AssemblyNode(local, true, this.filter, this.Context));
136                             }
137                         }
138                     }
139
140                     if (this.localAssemblies.Count == 0)
141                     {
142                         this.LocalAssembly.Visibility = Visibility.Collapsed;
143                     }
144                     else
145                     {
146                         this.LocalAssembly.Visibility = Visibility.Visible;
147                     }
148                 }
149                 return this.localAssemblies;
150             }
151         }
152
153         public ObservableCollection<AssemblyNode> ReferenceAssemblies
154         {
155             get
156             {
157                 if (null == this.referenceAssemblies)
158                 {
159                     this.referenceAssemblies = new ObservableCollection<AssemblyNode>();
160                     if (null != this.assemblyContext)
161                     {
162                         IMultiTargetingSupportService multiTargetingSupportService = this.Context.Services.GetService<IMultiTargetingSupportService>();
163                         IEnumerable<Assembly> assemblies = this.assemblyContext.GetEnvironmentAssemblies(multiTargetingSupportService);
164                         foreach (Assembly assembly in assemblies.OrderBy<Assembly, string>(p => p.FullName))
165                         {
166                             this.referenceAssemblies.Add(new AssemblyNode(assembly, false, this.filter, this.Context));
167                         }
168                     }
169                 }
170                 return this.referenceAssemblies;
171             }
172         }
173
174         public bool? ShowDialog(DependencyObject owner)
175         {
176             WindowHelperService.TrySetWindowOwner(owner, this.Context, this);
177             this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { this.perfEventProvider.TypeBrowserApplicationIdleAfterShowDialog(); }));
178             return base.ShowDialog();
179         }
180
181         protected override void OnKeyDown(KeyEventArgs e)
182         {
183             if (e.Key == Key.Escape)
184             {
185                 this.DialogResult = false;
186                 e.Handled = true;
187             }
188             else if (e.Key == Key.Enter && null != SelectedType)
189             {
190                 OnDialogClose();
191                 e.Handled = true;
192             }
193             else
194             {
195                 base.OnKeyDown(e);
196             }
197         }
198
199         protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
200         {
201             return new UIElementAutomationPeer(this);
202         }
203
204         private void GenericTypeMappingCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
205         {
206             this.HasGenericTypes = GenericTypeMapping.Count > 0 ? true : false;
207             if (this.HasGenericTypes)
208             {
209                 string strName = this.SelectedType.FullName;
210                 this.GenericTypeName = strName.Substring(0, strName.Length - 2) + " <";
211             }
212             else
213             {
214                 this.GenericTypeName = null;
215             }
216         }
217
218         private Type ResolveType(out string errorTitle, out string errorMessage)
219         {
220             errorTitle = null;
221             errorMessage = null;
222             Type result = this.SelectedType;
223
224             try
225             {
226                 IMultiTargetingSupportService multiTargetingSupport = this.Context.Services.GetService<IMultiTargetingSupportService>();
227                 if (multiTargetingSupport != null)
228                 {
229                     result = multiTargetingSupport.GetRuntimeType(result);
230                 }
231
232                 if (result == null)
233                 {
234                     errorTitle = SR.TypeBrowserErrorMessageTitle;
235                     errorMessage = SR.TypeBrowserError;
236                     return null;
237                 }
238
239                 if (result.IsGenericTypeDefinition)
240                 {
241                     bool isValid = true;
242                     //get number of generic parameters in edited type
243                     Type[] arguments = new Type[this.GenericTypeMapping.Count];
244
245                     //for each argument, get resolved type
246                     for (int i = 0; i < this.GenericTypeMapping.Count && isValid; ++i)
247                     {
248                         arguments[i] = this.GenericTypeMapping[i].GetConcreteType();
249                         if (multiTargetingSupport != null && arguments[i] != null)
250                         {
251                             arguments[i] = multiTargetingSupport.GetRuntimeType(arguments[i]);
252                         }
253                         isValid = isValid && (null != arguments[i]);
254                     }
255
256                     //if all parameters are resolved, create concrete type
257                     if (isValid)
258                     {
259                         result = result.MakeGenericType(arguments);
260                     }
261                     else
262                     {
263                         errorTitle = SR.TypeBrowserErrorMessageTitle;
264                         errorMessage = SR.TypeResolverError;
265                         result = null;
266                     }
267                 }
268             }
269             catch (ArgumentException err)
270             {
271                 errorTitle = err.GetType().Name;
272                 errorMessage = err.Message;
273                 return null;
274             }
275
276             return result;
277         }
278
279         private void OnOkClick(object sender, RoutedEventArgs args)
280         {
281             OnDialogClose();
282         }
283
284         private void OnCancelClick(object sender, RoutedEventArgs args)
285         {
286             this.DialogResult = false;
287         }
288
289         private void OnTypeDoubleClick(object sender, RoutedEventArgs args)
290         {
291             if (((System.Windows.Input.MouseButtonEventArgs)(args)).ChangedButton == MouseButton.Left)
292             {
293                 TypeNode entry = ((TreeViewItem)sender).Header as TypeNode;
294                 if (null != entry && entry.Data is Type)
295                 {
296                     OnDialogClose();
297                     args.Handled = true;
298                 }
299             }
300         }
301
302         private void OnDialogClose()
303         {
304             string errorTitle = null;
305             string errorMessage = null;
306
307             Type type = ResolveType(out errorTitle, out errorMessage);
308             if (null != type)
309             {
310                 this.ConcreteType = type;
311                 this.DialogResult = true;
312                 this.perfEventProvider.TypeBrowserOkPressed();
313             }
314             else
315             {
316                 MessageBox.Show(errorMessage, errorTitle, MessageBoxButton.OK, MessageBoxImage.Error);
317             }
318         }
319
320         private void OnTypeBrowserClickStart(object sender, RoutedEventArgs args)
321         {
322             TreeViewItem item = sender as TreeViewItem;
323             NamespaceNode ns = null;
324             if (null != item)
325             {
326                 ns = item.Header as NamespaceNode;
327             }
328
329             if (null != ns && null == ns.Tag)
330             {
331                 ns.Tag = string.Empty;
332                 Mouse.OverrideCursor = Cursors.Wait;
333             }
334         }
335
336         private void OnTypeBrowserClickEnd(object sender, RoutedEventArgs args)
337         {
338             TreeViewItem item = sender as TreeViewItem;
339             if (null != item && item.Header is AssemblyNode && null != Mouse.OverrideCursor)
340             {
341                 Mouse.OverrideCursor = null;
342             }
343         }
344
345         private void OnTypeSearchTextChanged(object sender, TextChangedEventArgs e)
346         {
347             string searchText = ((TextBox)sender).Text;
348
349             SearchAction newSearch = new SearchAction(searchText, this.localAssemblies, this.referenceAssemblies);
350             newSearch.Completed += delegate(object s, EventArgs args)
351             {
352                 SearchAction senderAction = s as SearchAction;
353                 SearchAction currentAction = this.currentSearch;
354                 this.currentSearch = null;
355
356                 if (senderAction == currentAction)
357                 {
358                     TypeNode match = ((SearchActionEventArgs)args).Result as TypeNode;
359
360                     UpdateSelectedItem(match);
361                     if (match != null)
362                     {
363                         match.IsSelected = true;
364                     }
365                 }
366             };
367
368             if (this.currentSearch != null)
369             {
370                 this.currentSearch.Abort();
371             }
372
373             ClearSelection();
374
375             this.currentSearch = newSearch;
376             this.currentSearch.Run();
377         }
378
379         private void ClearSelection()
380         {
381             TypeNode currentSelection = this.typesTreeView.SelectedItem as TypeNode;
382             if (currentSelection != null)
383             {
384                 currentSelection.IsSelected = false;
385             }
386         }
387
388         private void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
389         {
390             TypeNode entry = ((System.Windows.Controls.TreeView)sender).SelectedItem as TypeNode;
391             if (entry != null && this.SelectedType != entry.Data as Type)
392             {
393                 UpdateSelectedItem(entry);
394                 if (null != this.SelectedType)
395                 {
396                     typeEntryTextBox.TextChanged -= new TextChangedEventHandler(OnTypeSearchTextChanged);
397                     typeEntryTextBox.Text = TypeNameHelper.GetDisplayName(this.SelectedType, true);
398                     typeEntryTextBox.TextChanged += new TextChangedEventHandler(OnTypeSearchTextChanged);
399                 }
400             }
401         }
402
403         private void UpdateSelectedItem(TypeNode entry)
404         {
405             GenericTypeMapping.Clear();
406
407             SelectedType = (null != entry ? entry.Data as Type : null);
408
409             if (null != this.SelectedType)
410             {
411                 if (this.SelectedType.IsGenericTypeDefinition)
412                 {
413                     this.ConcreteType = null;
414                     Type[] generics = this.SelectedType.GetGenericArguments();
415                     foreach (Type t in generics)
416                     {
417                         this.GenericTypeMapping.Add(new TypeKeyValue(t, null));
418                     }
419                 }
420                 else
421                 {
422                     this.ConcreteType = this.SelectedType;
423                 }
424             }
425             else
426             {
427                 this.ConcreteType = null;
428             }
429         }
430
431         internal class Node : INotifyPropertyChanged
432         {
433             public event PropertyChangedEventHandler PropertyChanged;
434
435             private bool isExpanded;
436             private bool isSelected;
437             private Visibility visibility;
438
439             protected Node()
440             {
441                 this.isExpanded = false;
442                 this.isSelected = false;
443                 this.visibility = Visibility.Visible;
444             }
445
446             protected void Notify(string property)
447             {
448                 if (PropertyChanged != null)
449                 {
450                     PropertyChanged(this, new PropertyChangedEventArgs(property));
451                 }
452             }
453
454             public bool IsExpanded
455             {
456                 get
457                 {
458                     return this.isExpanded;
459                 }
460                 set
461                 {
462                     if (this.isExpanded != value)
463                     {
464                         this.isExpanded = value;
465                         Notify("IsExpanded");
466                     }
467                 }
468             }
469
470             public bool IsSelected
471             {
472                 get
473                 {
474                     return this.isSelected;
475                 }
476                 set
477                 {
478                     if (this.isSelected != value)
479                     {
480                         this.isSelected = value;
481                         Notify("IsSelected");
482                     }
483                 }
484             }
485
486             public Visibility Visibility
487             {
488                 get
489                 {
490                     return this.visibility;
491                 }
492                 set
493                 {
494                     if (this.visibility != value)
495                     {
496                         this.visibility = value;
497                         Notify("Visibility");
498                     }
499                 }
500             }
501
502             public object Tag
503             {
504                 get;
505                 set;
506             }
507         }
508
509         internal class AssemblyNode : Node
510         {
511             string displayName;
512             Assembly assembly;
513             bool isLocal;
514             Func<Type, bool> filter;
515             EditingContext context;
516
517             public AssemblyNode(Assembly assembly, bool isLocal, Func<Type, bool> filter, EditingContext context)
518             {
519                 if (null == assembly)
520                 {
521                     throw FxTrace.Exception.AsError(new ArgumentNullException("assembly"));
522                 }
523                 this.assembly = assembly;
524                 this.isLocal = isLocal;
525                 this.displayName = GetDisplayName(this.assembly.GetName());
526                 this.filter = filter;
527                 this.context = context;
528             }
529
530             private static string GetDisplayName(AssemblyName name)
531             {
532                 StringBuilder sb = new StringBuilder();
533                 if (name != null && name.Name != null)
534                 {
535                     sb.Append(name.Name);
536                     if (name.Version != null)
537                     {
538                         sb.Append(" [");
539                         sb.Append(name.Version.Major);
540                         sb.Append(".");
541                         sb.Append(name.Version.Minor);
542                         sb.Append(".");
543                         sb.Append(name.Version.Build);
544                         sb.Append(".");
545                         sb.Append(name.Version.Revision);
546                         sb.Append("]");
547                     }
548                 }
549                 return sb.ToString();
550             }
551
552             public string DisplayName
553             {
554                 get { return this.displayName; }
555             }
556
557             private ObservableCollection<NamespaceNode> namespaces;
558             public ObservableCollection<NamespaceNode> Namespaces
559             {
560                 get
561                 {
562                     if (namespaces == null)
563                     {
564                         namespaces = new ObservableCollection<NamespaceNode>();
565
566                         try
567                         {
568                             Func<Type, bool> typeFilter = this.filter;
569                             IMultiTargetingSupportService multiTargetingSupport = this.context.Services.GetService<IMultiTargetingSupportService>();
570                             if (multiTargetingSupport != null && typeFilter != null)
571                             {
572                                 typeFilter = (type) => this.filter(multiTargetingSupport.GetRuntimeType(type));
573                             }
574
575                             var exportedTypes =
576                                 from type in (this.isLocal ? this.assembly.GetTypes() : this.assembly.GetExportedTypes())
577                                 where (type.IsPublic && type.IsVisible && (typeFilter == null || typeFilter(type)))
578                                 orderby type.Namespace, type.Name
579                                 select type;
580
581                             NamespaceNode lastNamespace = null;
582                             foreach (Type type in exportedTypes)
583                             {
584                                 if (lastNamespace == null || !StringComparer.OrdinalIgnoreCase.Equals(lastNamespace.DisplayName, type.Namespace))
585                                 {
586                                     lastNamespace = new NamespaceNode(type.Namespace);
587                                     namespaces.Add(lastNamespace);
588                                 }
589
590                                 lastNamespace.Types.Add(new TypeNode(type));
591                             }
592                         }
593                         catch (NotSupportedException)
594                         {
595                             //Dynamic (in memory) assemblies will throw exception when this method is called
596                             //that's the reason i'm swollowing that exception
597                         }
598
599                     }
600                     return namespaces;
601                 }
602             }
603
604             public string Data
605             {
606                 get { return this.displayName; }
607             }
608
609             public override string ToString()
610             {
611                 return this.displayName;
612             }
613         }
614
615         internal class NamespaceNode : Node
616         {
617
618             private string displayName;
619             public string DisplayName
620             {
621                 get
622                 {
623                     return this.displayName;
624                 }
625             }
626
627             private ObservableCollection<TypeNode> types;
628             public ObservableCollection<TypeNode> Types
629             {
630                 get
631                 {
632                     return this.types;
633                 }
634             }
635
636             public string Data
637             {
638                 get { return this.displayName; }
639             }
640
641             public NamespaceNode(string name)
642             {
643                 this.displayName = name;
644                 this.types = new ObservableCollection<TypeNode>();
645             }
646         }
647
648         internal class TypeNode : Node
649         {
650             private Type type;
651
652             private string displayName;
653             public string DisplayName
654             {
655                 get
656                 {
657                     return this.displayName;
658                 }
659             }
660
661             private string fullName;
662             public string FullName
663             {
664                 get
665                 {
666                     return this.fullName;
667                 }
668             }
669
670             public Type Data
671             {
672                 get { return this.type; }
673             }
674
675             public TypeNode(Type type)
676             {
677                 this.type = type;
678                 this.displayName = TypeNameHelper.GetDisplayName(type, false);
679                 this.fullName = TypeNameHelper.GetDisplayName(type, true);
680             }
681         }
682
683         private class SearchActionEventArgs : EventArgs
684         {
685             public object Result
686             {
687                 get;
688                 set;
689             }
690         }
691
692         private class SearchAction
693         {
694             private string searchText;
695             Collection<AssemblyNode>[] range;
696             DispatcherOperation dispatcherOperation;
697
698             public event EventHandler Completed;
699
700             public SearchAction(string searchText, Collection<AssemblyNode> localAssemblies, Collection<AssemblyNode> referenceAssemblies)
701             {
702                 this.searchText = searchText;
703                 this.range = new Collection<AssemblyNode>[] { localAssemblies, referenceAssemblies };
704             }
705
706
707             public void Run()
708             {
709                 this.dispatcherOperation = Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Input, new Func<TypeNode>(this.OnRun));
710                 this.dispatcherOperation.Completed += this.OnCompleted;
711             }
712
713             public bool Abort()
714             {
715                 if (this.dispatcherOperation != null)
716                 {
717                     return this.dispatcherOperation.Abort();
718                 }
719                 return true;
720             }
721
722             private TypeNode OnRun()
723             {
724                 bool noSearch = string.IsNullOrEmpty(searchText);
725                 Func<TypeNode, string, bool> matchAlgorithm = SearchAction.MatchShortName;
726
727                 TypeNode match = null;
728                 TypeNode firstCandidate = null;
729                 bool tooManyCandiates = false;
730
731                 if (!noSearch && searchText.Contains('.'))
732                 {
733                     matchAlgorithm = SearchAction.MatchFullName;
734                 }
735
736                 foreach (Collection<AssemblyNode> assemblies in this.range)
737                 {
738                     foreach (AssemblyNode assembly in assemblies)
739                     {
740                         Visibility assemblyVisibility = Visibility.Collapsed;
741                         bool assemblyIsExpanded = false;
742
743                         if (noSearch)
744                         {
745                             assemblyVisibility = Visibility.Visible;
746                         }
747
748                         foreach (NamespaceNode ns in assembly.Namespaces)
749                         {
750                             Visibility namespaceVisibility = Visibility.Collapsed;
751                             bool namespaceIsExpanded = false;
752
753                             if (noSearch)
754                             {
755                                 namespaceVisibility = Visibility.Visible;
756                             }
757
758                             foreach (TypeNode entry in ns.Types)
759                             {
760                                 if (noSearch)
761                                 {
762                                     entry.Visibility = Visibility.Visible;
763                                 }
764                                 else if (matchAlgorithm(entry, searchText))
765                                 {
766                                     entry.Visibility = Visibility.Visible;
767                                     assemblyVisibility = Visibility.Visible;
768                                     assemblyIsExpanded = true;
769                                     namespaceVisibility = Visibility.Visible;
770                                     namespaceIsExpanded = true;
771
772                                     if (string.Equals(searchText, entry.FullName, StringComparison.OrdinalIgnoreCase))
773                                     {
774                                         match = entry;
775                                     }
776
777                                     if (firstCandidate == null)
778                                     {
779                                         firstCandidate = entry;
780                                     }
781                                     else if (!tooManyCandiates)
782                                     {
783                                         tooManyCandiates = true;
784                                     }
785                                 }
786                                 else
787                                 {
788                                     entry.Visibility = Visibility.Collapsed;
789                                 }
790                             }
791
792                             if (searchText.Contains('.') && ns.DisplayName != null && ns.DisplayName.StartsWith(searchText, StringComparison.OrdinalIgnoreCase))
793                             {
794                                 namespaceIsExpanded = false;
795                             }
796
797                             if (namespaceIsExpanded)
798                             {
799                                 ns.Tag = string.Empty;
800                             }
801
802                             ns.Visibility = namespaceVisibility;
803                             ns.IsExpanded = namespaceIsExpanded;
804                         }
805
806                         assembly.Visibility = assemblyVisibility;
807                         assembly.IsExpanded = assemblyIsExpanded;
808                     }
809                 }
810
811                 if (match == null && !tooManyCandiates)
812                 {
813                     match = firstCandidate;
814                 }
815
816                 return match;
817             }
818
819             private void OnCompleted(object sender, EventArgs args)
820             {
821                 this.dispatcherOperation.Completed -= this.OnCompleted;
822                 if (this.Completed != null)
823                 {
824                     SearchActionEventArgs arg = new SearchActionEventArgs();
825                     arg.Result = this.dispatcherOperation.Result;
826                     this.Completed(this, arg);
827                 }
828             }
829
830             // "abc.def" matches regex ^.*\.abc\.def.* or ^abc\.def.*, but does not match ^.*[^.]abc\.def.*
831             private static bool MatchFullName(TypeNode type, string searchText)
832             {
833                 if (searchText.StartsWith(".", StringComparison.OrdinalIgnoreCase))
834                 {
835                     return -1 != type.FullName.IndexOf(searchText, StringComparison.OrdinalIgnoreCase);
836                 }
837
838                 if (type.FullName.StartsWith(searchText, StringComparison.OrdinalIgnoreCase))
839                 {
840                     return true;
841                 }
842
843                 if (-1 != type.FullName.IndexOf("." + searchText, StringComparison.OrdinalIgnoreCase))
844                 {
845                     return true;
846                 }
847
848                 return false;
849             }
850
851             private static bool MatchShortName(TypeNode type, string searchText)
852             {
853                 return type.DisplayName.StartsWith(searchText, StringComparison.OrdinalIgnoreCase);
854             }
855         }
856     }
857 }