void Initialize()
 {
     foreach (string assembly in _coreAssembliesPaths)
     {
         AssemblyDefinition coreAssembly = CompatibilityAnalyzer.LoadAssembly(assembly);
         FillMapOfXmlNsToCsNs(coreAssembly);
         //now we go through all the types of this assembly and remember all their public methods:
         foreach (TypeDefinition type in AnalyzeHelper.GetAllTypesDefinedInAssembly(coreAssembly))
         {
             bool   hasPublicMethods  = false;
             string baseTypeName      = type.BaseType != null ? type.BaseType.Name : null;
             string baseTypeNamespace = type.BaseType != null ? type.BaseType.Namespace : null;
             foreach (MethodDefinition method in AnalyzeHelper.GetAllMethodsDefinedInType(type))
             {
                 if (method.IsPublic || method.IsFamily) //note: we only add the public methods because those are the only ones the user can use.
                 {
                     hasPublicMethods = true;
                     Add(type.Namespace, type.Name, baseTypeNamespace, baseTypeName, method.Name);
                 }
             }
             if (!hasPublicMethods)
             {
                 Add(type.Namespace, type.Name, baseTypeNamespace, baseTypeName, null);
             }
         }
     }
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Main method of the generator. Look in every referenced assemblies to find the unsupported methods and types
 /// </summary>
 public void Run()
 {
     Init();
     foreach (string assembly in _referencedAssembliesToLookInto)
     {
         Dictionary <string, HashSet <string> > unsupportedMethods;
         _unsupportedMethodsInfo.TryGetValue(assembly, out unsupportedMethods);
         if (unsupportedMethods != null)
         {
             AssemblyDefinition assemblyToLookInto = CompatibilityAnalyzer.LoadAssembly(Path.Combine(_referencedAssembliesFolderPath, assembly + ".dll"), Configuration.mscorlibFolderPath);
             _assemblyAnalyzer.Set(assemblyToLookInto, unsupportedMethods);
             _assemblyAnalyzer.Run();
         }
     }
     GenerateAddtionalUnsupportedTypes();
 }
Ejemplo n.º 3
0
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            string coreAssemblyPath      = CoreAssemblyPathTextBox.Text;
            string supportedElementsPath = SupportedElementsPathTextBox.Text;
            string mscorlibFolderPath    = MscorlibFolderPathTextBox.Text;
            string sdkFolderPath         = SDKFolderPathTextBox.Text;
            string otherFoldersPath      = OtherFoldersPathTextBox.Text;

            HashSet <string> xamlFilesToIgnore = null;

            try
            {
                xamlFilesToIgnore = new HashSet <string>(XamlFilesToIgnoreTextBox.Text.Split(',').Select(s => s.Trim().ToLower()));
            }
            catch (Exception ex)
            {
                MessageBox.Show("Invalid list of XAML files to exclude." + Environment.NewLine + Environment.NewLine + ex.ToString());
                return;
            }

            if (string.IsNullOrEmpty(coreAssemblyPath) ||
                string.IsNullOrEmpty(supportedElementsPath) ||
                string.IsNullOrEmpty(mscorlibFolderPath))
            {
                MessageBox.Show("Please fill all the fields before continuing.");
                return;
            }

            if (!File.Exists(supportedElementsPath))
            {
                MessageBox.Show("File not found: " + supportedElementsPath);
                return;
            }

            var featuresAndEstimationsFileProcessor = new FeaturesAndEstimationsFileProcessor(FeaturesAndEstimationsPathTextBox.Text);

            // Save the content of the text boxes for reuse when relaunching the application:
            SaveContentOfTextBoxes();

#if ASK_USER_TO_CHOOSE_ASSEMBLIES_TO_ANALYZE
            // Create OpenFileDialog
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();

            // Set filter for file extension and default file extension
            dlg.DefaultExt  = ".dll";
            dlg.Filter      = "Assemblies and executables (*.dll,*.exe)|*.dll;*.exe";
            dlg.Multiselect = true;

            // Display OpenFileDialog by calling ShowDialog method
            Nullable <bool> result = dlg.ShowDialog();

            if (result == true)
            {
                string[] fileNames = dlg.FileNames;
#else
            string[] fileNames = Configuration.AssembliesToAnalyze;

            if (true)
            {
#endif

                if (_coreSupportedMethods == null)
                {
                    _coreSupportedMethods = new CoreSupportedMethodsContainer(coreAssemblyPath);
                }

                var logger = new LoggerThatAggregatesAllErrors();
                var watch  = Stopwatch.StartNew();
                var listOfUnsupportedMethods = new List <UnsupportedMethodInfo>();

                // Get the path of the folder where the first assembly is located, and add that path to the list of places where to look in for resolving referenced assemblies:
                string firstFileToAnalyze = fileNames.FirstOrDefault();
                string additionalFolderWhereToResolveAssemblies = null;
                if (firstFileToAnalyze != null)
                {
                    additionalFolderWhereToResolveAssemblies = System.IO.Path.GetDirectoryName(firstFileToAnalyze);
                }

                // Do the analysis:
                try
                {
                    foreach (var filename in fileNames)
                    {
                        CompatibilityAnalyzer.Analyze(
                            filename,
                            logger,
                            listOfUnsupportedMethods,
                            _coreSupportedMethods,
                            fileNames,
                            Configuration.UrlNamespacesThatBelongToUserCode,
                            Configuration.AttributesToIgnoreInXamlBecauseTheyAreFromBaseClasses,
                            xamlFilesToIgnore,
                            supportedElementsPath,
                            mscorlibFolderPath,
                            sdkFolderPath,
                            otherFoldersPath,
                            skipTypesWhereNoMethodIsActuallyCalled: true,
                            additionalFolderWhereToResolveAssemblies: additionalFolderWhereToResolveAssemblies);;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }

                // Replace all telerik assembly names with "http://schemas.telerik.com/2008/xaml/presentation" so as to avoid differences between namespaces from .xaml files and namespaces from .cs files:
                foreach (UnsupportedMethodInfo unsupportedMethodInfo in listOfUnsupportedMethods)
                {
                    if (unsupportedMethodInfo.MethodAssemblyName.StartsWith("Telerik."))
                    {
                        unsupportedMethodInfo.MethodAssemblyName = "http://schemas.telerik.com/2008/xaml/presentation";
                    }
                }

                // Replace all Expression Blend-related namespaces with "http://schemas.microsoft.com/expression/2010/..." so as to avoid differences between namespaces from .xaml files and namespaces from .cs files:
                foreach (UnsupportedMethodInfo unsupportedMethodInfo in listOfUnsupportedMethods)
                {
                    if (unsupportedMethodInfo.MethodAssemblyName.StartsWith("Microsoft.Expression.") ||
                        unsupportedMethodInfo.MethodAssemblyName.StartsWith("System.Windows.Interactivity") ||
                        unsupportedMethodInfo.MethodAssemblyName == "http://schemas.microsoft.com/expression/2010/drawing" ||
                        unsupportedMethodInfo.MethodAssemblyName == "http://schemas.microsoft.com/expression/2010/interactivity" ||
                        unsupportedMethodInfo.MethodAssemblyName == "http://schemas.microsoft.com/expression/2010/interactions"
                        )
                    {
                        unsupportedMethodInfo.MethodAssemblyName = "http://schemas.microsoft.com/expression/2010/...";
                    }
                }

                // Aggregate all MEF-related namespaces:
                foreach (UnsupportedMethodInfo unsupportedMethodInfo in listOfUnsupportedMethods)
                {
                    if (unsupportedMethodInfo.MethodAssemblyName.StartsWith("System.ComponentModel.Composition."))
                    {
                        unsupportedMethodInfo.MethodAssemblyName = "System.ComponentModel.Composition";
                    }
                }

                // Aggregate all DomainServices-related namespaces:
                foreach (UnsupportedMethodInfo unsupportedMethodInfo in listOfUnsupportedMethods)
                {
                    if (unsupportedMethodInfo.MethodAssemblyName.StartsWith("System.ServiceModel.DomainServices.Client."))
                    {
                        unsupportedMethodInfo.MethodAssemblyName = "System.ServiceModel.DomainServices.Client";
                    }
                }

                // Replace all the native MS UI-related assembly names with "http://schemas.microsoft.com/winfx/2006/xaml/presentation" so as to avoid differences between namespaces from .xaml files and namespaces from .cs files:
                foreach (UnsupportedMethodInfo unsupportedMethodInfo in listOfUnsupportedMethods)
                {
                    if (unsupportedMethodInfo.MethodAssemblyName == "System.Windows" ||
                        unsupportedMethodInfo.MethodAssemblyName == "System.Windows.Controls" ||
                        unsupportedMethodInfo.MethodAssemblyName == "System.Windows.Controls.Data" ||
                        unsupportedMethodInfo.MethodAssemblyName == "System.Windows.Browser" ||
                        unsupportedMethodInfo.MethodAssemblyName == "System.Windows.Controls.Navigation" ||
                        unsupportedMethodInfo.MethodAssemblyName == "System.Windows.Controls.Toolkit")
                    {
                        unsupportedMethodInfo.MethodAssemblyName = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
                    }
                }

                // Process the list of unsupported methods:
                SortedDictionary <Tuple <string, string>, HashSet <string> > unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed;
                ProcessUnsupportedMethods(listOfUnsupportedMethods, out unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed, rectifyMethodName: true);

                // Remove some stuff:
                foreach (Tuple <string, string> additionalEntryToRemove in Configuration.AdditionalEntriesToRemoveBeforeAggregation)
                {
                    unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed.Remove(additionalEntryToRemove);
                }

                // For classes that are not defined at all (ie. missing constructor), aggregate all the methods into the same line:
                List <Tuple <string, string> > entriesToRemoveFromDictionary = new List <Tuple <string, string> >();                                                                // This is here because we cannot remove the keys while iterating in the dictionary, so we do it afterwards.
                List <KeyValuePair <Tuple <string, string>, HashSet <string> > > entriesToAddToDictionary = new List <KeyValuePair <Tuple <string, string>, HashSet <string> > >(); // This is here because we cannot add entries while iterating in the dictionary, so we do it afterwards.
                HashSet <Tuple <string, string> > classesForWhichTheMethodsHaveAlreadyBeenAggregated      = new HashSet <Tuple <string, string> >();
                foreach (KeyValuePair <Tuple <string, string>, HashSet <string> > pair in unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed)
                {
                    string           theFullMethodName = pair.Key.Item1;
                    string           theAssemblyName   = pair.Key.Item2;
                    HashSet <string> whereItIsUsed     = pair.Value;

                    if (!Configuration.EntriesToNotAggregateWithOtherEntries.Contains(theFullMethodName))
                    {
#if ALWAYS_AGGREGATE_METHODS
                        if (theFullMethodName.Contains("."))
#else
                        if (theFullMethodName.Contains("..ctor"))
#endif
                        {
#if ALWAYS_AGGREGATE_METHODS
                            string className = theFullMethodName.Substring(0, theFullMethodName.IndexOf("."));
#else
                            string className = theFullMethodName.Substring(0, theFullMethodName.IndexOf("..ctor"));
#endif
                            if (!classesForWhichTheMethodsHaveAlreadyBeenAggregated.Contains(new Tuple <string, string>(className, theAssemblyName)))
                            {
                                classesForWhichTheMethodsHaveAlreadyBeenAggregated.Add(new Tuple <string, string>(className, theAssemblyName));
                                List <string> methodNames = new List <string>();

                                // Find all other methods that concern the same class:
                                foreach (KeyValuePair <Tuple <string, string>, HashSet <string> > pair2 in unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed)
                                {
                                    //todo-perf: optimize performance by creating a dictionary beforehand instead of nesting two iterations!

                                    string           theFullMethodName2 = pair2.Key.Item1;
                                    string           theAssemblyName2   = pair2.Key.Item2;
                                    HashSet <string> whereItIsUsed2     = pair.Value;
                                    if (!Configuration.EntriesToNotAggregateWithOtherEntries.Contains(theFullMethodName2))
                                    {
                                        if (theFullMethodName2.Contains('.') &&
                                            !theFullMethodName2.Contains("..ctor")
                                            )
                                        {
                                            string className2 = theFullMethodName2.Substring(0, theFullMethodName2.IndexOf('.'));
                                            if (className2 == className && theAssemblyName2 == theAssemblyName)
                                            {
                                                string methodName2 = theFullMethodName2.Substring(theFullMethodName2.IndexOf('.') + 1);
                                                methodNames.Add(methodName2);
                                                HashSetHelpers.AddItemsFromOneHashSetToAnother(whereItIsUsed2, whereItIsUsed);
                                                entriesToRemoveFromDictionary.Add(pair2.Key);
                                            }
                                        }
                                    }
                                }

                                // Aggregate them:
                                string newMethodName;
                                if (methodNames.Count > 0)
                                {
                                    if (theFullMethodName.Contains("..ctor"))
                                    {
                                        newMethodName = className + " (members used: " + string.Join(", ", methodNames) + ")";
                                    }
                                    else
                                    {
                                        newMethodName = className + "." + string.Join(", .", methodNames);
                                    }
                                }
                                else
                                {
                                    newMethodName = className;
                                }

                                entriesToRemoveFromDictionary.Add(pair.Key);
                                entriesToAddToDictionary.Add(new KeyValuePair <Tuple <string, string>, HashSet <string> >(
                                                                 new Tuple <string, string>(newMethodName, theAssemblyName),
                                                                 whereItIsUsed));
                            }
                        }
                    }
                }
                // Perform the actual removal and addition (note: this cannot be done before because it is not possible to remove or add an item from a collection while iterating it with "foreach");
                foreach (var key in entriesToRemoveFromDictionary)
                {
                    unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed.Remove(key);
                }
                foreach (var entry in entriesToAddToDictionary)
                {
                    unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed.Add(entry.Key, entry.Value);
                }

                //-------------------------------------
                // Merge classes that are related to each other:
                //-------------------------------------
                MergingRelatedClasses.MergeRelatedClasses(Configuration.ClassesRelatedToEachOther, unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed);

                //-------------------------------------
                // Remove elements with an empty assembly name because they are due to "clr-namespace:..." without any assembly being specified, which means that the assembly is the user assembly itself, so we should remove the entry:
                //-------------------------------------
                entriesToRemoveFromDictionary = new List <Tuple <string, string> >();
                foreach (var entry in unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed)
                {
                    if (entry.Key.Item2 == "")
                    {
                        entriesToRemoveFromDictionary.Add(entry.Key);
                    }
                }
                foreach (var key in entriesToRemoveFromDictionary)
                {
                    unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed.Remove(key);
                }

                //-------------------------------------
                // Remove some additional stuff:
                //-------------------------------------

                foreach (Tuple <string, string> additionalEntryToRemove in Configuration.AdditionalEntriesToRemoveAfterAggregation)
                {
                    unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed.Remove(additionalEntryToRemove);
                }

                //-------------------------------------
                // Save the result:
                //-------------------------------------

                // Save as Excel document:
                ExcelGenerator.Generate(
                    OutputExcelFilePathTextBox.Text,
                    featuresAndEstimationsFileProcessor,
                    unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed,
                    fileNames.Select(fileName => System.IO.Path.GetFileName(fileName)));

#if SAVE_CSV_DOCUMENT
                // Save as CSV document:
                CsvGenerator.Generate(OutputCsvFilePathTextBox.Text, unsupportedMethodsAndTheirAssemblyToLocationsWhereTheyAreUsed);
#endif

                var elapsedMs = watch.ElapsedMilliseconds;
                MessageBox.Show(string.Format("Operation completed in {0} seconds.", Math.Floor(elapsedMs / 1000d).ToString()));

                //-------------------------------------
                // Open the result:
                //-------------------------------------

                Process.Start(OutputExcelFilePathTextBox.Text);

                //-------------------------------------
                // Close this app:
                //-------------------------------------

                System.Windows.Application.Current.Shutdown();
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Retrieve all methods and types used in the _inputAssemblies and organize them in a Dictionary
        /// </summary>
        private void GetUnsupportedMethods()
        {
            ILogger logger = new LoggerThatAggregatesAllErrors();
            List <UnsupportedMethodInfo>  unsupportedMethodInfos = new List <UnsupportedMethodInfo>();
            CoreSupportedMethodsContainer coreSupportedMethods   = new CoreSupportedMethodsContainer(Configuration.SLMigrationCoreAssemblyFolderPath);

            foreach (string filename in _inputAssemblies)
            {
                CompatibilityAnalyzer.Analyze(
                    filename,
                    logger,
                    unsupportedMethodInfos,
                    coreSupportedMethods,
                    _inputAssemblies,
                    Configuration.UrlNamespacesThatBelongToUserCode,
                    new HashSet <string>(),
                    Configuration.ExcludedFiles,
                    Configuration.supportedElementsPath,
                    Configuration.mscorlibFolderPath,
                    Configuration.sdkFolderPath,
                    "",
                    skipTypesWhereNoMethodIsActuallyCalled: false,
                    addBothPropertyAndEventWhenNotFound: true,
                    additionalFolderWhereToResolveAssemblies: Configuration.ReferencedAssembliesFolderPath);
            }
            if (_unsupportedMethodsInfo == null)
            {
                _unsupportedMethodsInfo = new Dictionary <string, Dictionary <string, HashSet <string> > >();
            }
            HashSet <MethodInfo> unsupportedMethods = new HashSet <MethodInfo>();

            foreach (UnsupportedMethodInfo method in unsupportedMethodInfos)
            {
                unsupportedMethods.Add(new MethodInfo(method));
            }
            foreach (MethodInfo method in unsupportedMethods)
            {
                Tuple <string, string, string> methodInfo = GetMethodMainInfos(method);
                MethodInfo _method = new MethodInfo(methodInfo.Item1, methodInfo.Item2, methodInfo.Item3, method.NeedToBeCheckedBecauseOfInheritance);
                if (method.NeedToBeCheckedBecauseOfInheritance)
                {
                    _method = GetMethodInfoResolvingInheritance(_method.AssemblyName, _method.TypeName, _method.MethodName);
                }
                if (!_unsupportedMethodsInfo.ContainsKey(_method.AssemblyName))
                {
                    HashSet <string> methodsSet = new HashSet <string>();
                    if (_method.MethodName != "")
                    {
                        methodsSet.Add(_method.MethodName);
                    }
                    Dictionary <string, HashSet <string> > currentTypesDictionary = new Dictionary <string, HashSet <string> >
                    {
                        { _method.TypeName, methodsSet }
                    };
                    _unsupportedMethodsInfo.Add(_method.AssemblyName, currentTypesDictionary);
                }
                else
                {
                    if (!_unsupportedMethodsInfo[_method.AssemblyName].ContainsKey(_method.TypeName))
                    {
                        HashSet <string> methodsSet = new HashSet <string>();
                        if (_method.MethodName != "")
                        {
                            methodsSet.Add(_method.MethodName);
                        }
                        _unsupportedMethodsInfo[_method.AssemblyName].Add(_method.TypeName, methodsSet);
                    }
                    else
                    {
                        if (_method.MethodName != "")
                        {
                            _unsupportedMethodsInfo[_method.AssemblyName][_method.TypeName].Add(_method.MethodName);
                        }
                    }
                }
            }
        }