Example #1
0
        public virtual UnitOptionRow Serialize()
        {
            var row = new UnitOptionRow();

            if (sourceScriptGuids.Count == 0)
            {
                // Important to set to null here, because the code relies on
                // null checks, not empty string checks.
                row.sourceScriptGuids = null;
            }
            else
            {
                row.sourceScriptGuids = string.Join(",", sourceScriptGuids.ToArray());
            }

            row.optionType = Codebase.SerializeType(GetType());
            row.unitType   = Codebase.SerializeType(unitType);
            row.unit       = unit.Serialize().json;

            row.category           = category?.fullName;
            row.labelHuman         = labelHuman;
            row.labelProgrammer    = labelProgrammer;
            row.order              = order;
            row.haystackHuman      = haystackHuman;
            row.haystackProgrammer = haystackProgrammer;
            row.favoriteKey        = favoriteKey;

            row.controlInputCount  = controlInputCount;
            row.controlOutputCount = controlOutputCount;
            row.valueInputTypes    = valueInputTypes.Select(Codebase.SerializeType).ToSeparatedString("|").NullIfEmpty();
            row.valueOutputTypes   = valueOutputTypes.Select(Codebase.SerializeType).ToSeparatedString("|").NullIfEmpty();

            return(row);
        }
Example #2
0
        private static Codebase GetCodebase(params string[] projects)
        {
            var codebase = new Codebase(new ProjectFactory());

            codebase.Discover(projects);

            return(codebase);
        }
Example #3
0
        public override UnitOptionRow Serialize()
        {
            var row = base.Serialize();

            row.tag1 = Codebase.SerializeType(structType);

            return(row);
        }
Example #4
0
 private static void WriteProjects(IConsole console, Codebase codebase, IEnumerable <IProject> projects)
 {
     foreach (var project in projects)
     {
         var relativePath = Path.GetRelativePath(codebase.FullPath, project.FullPath);
         console.Out.WriteLine(relativePath);
     }
 }
Example #5
0
        protected override void UpdateTools(IList <ITool> tools)
        {
            tools.Add(modeTool);

            var tabTypes = ListPool <Type> .New();

            try
            {
                foreach (var tabInLayout in PeekPlugin.Configuration.tabsInLayout)
                {
                    if (!Codebase.TryDeserializeType(tabInLayout, out var tabType))
                    {
                        continue;
                    }

                    if (PeekPlugin.Configuration.tabsBlacklist.Contains(tabType))
                    {
                        continue;
                    }

                    if (!tabTypes.Contains(tabType))
                    {
                        tabTypes.Add(tabType);
                    }
                }

                foreach (var tabType in PeekPlugin.Configuration.tabsWhitelist)
                {
                    if (tabType == null)
                    {
                        continue;
                    }

                    if (!tabTypes.Contains(tabType))
                    {
                        tabTypes.Add(tabType);
                    }
                }

                tabTypes.Sort(compareTabTypes);

                foreach (var tabType in tabTypes)
                {
                    var tabTool = tabTools[tabType];

                    tools.Add(tabTool);
                }
            }
            finally
            {
                tabTypes.Free();
            }
        }
        static void Ncca_Is_Used_Properly(Codebase codebase, IScope scope, int maxInstructions)
        {
            var methods = codebase.Methods
                .Where(m => m.HasBody && m.Body.Instructions.Count > maxInstructions)
                .Where(m => m.Has<NoCodeCoverageAttribute>() ||
                    m.DeclaringType.Has<NoCodeCoverageAttribute>());

            foreach (var method in methods)
            {
                scope.Error("Method is too complex to be marked with NCCA: {0}", method);
            }
        }
Example #7
0
        private static void CreateSolutionFilter(IConsole console, string[] projects, FileInfo solution, string destination)
        {
            var codebase = new Codebase(new ProjectFactory());

            if (string.IsNullOrEmpty(destination))
            {
                var solutionFilter = codebase.CreateSolutionFilter(solution, projects);
                console.Out.Write(solutionFilter);
            }
            else
            {
                codebase.CreateSolutionFilter(destination, solution, projects);
            }
        }
        /// <summary>
        /// Ensures that classes marked with <see cref="ImmutableAttribute"/> have only
        /// readonly fields
        /// </summary>
        /// <param name="codebase">The codebase to run against.</param>
        /// <param name="scope">The scope to report to.</param>
        public static void Immutable_Types_Should_Be_Immutable(Codebase codebase, IScope scope)
        {
            var decorated = codebase.Types
                .Where(t => t.Has<ImmutableAttribute>());

            var failing = decorated
                .Where(t => t.GetAllFields(codebase)
                    .Count(f => !f.IsInitOnly && !f.IsStatic) > 0);

            foreach (var definition in failing)
            {
                scope.Error("Type should be immutable: {0}", definition);
            }
        }
        public List <ICodebaseAlert> GenerateAlerts(Codebase codebase)
        {
            var alerts = new List <CodebaseAlert>();

            foreach (var projectDirectory in codebase.ProjectDirectories)
            {
                if (projectDirectory.ProjectFiles.Count > 1)
                {
                    var alert = new CodebaseAlert("MultipleProjectAlert", CodebaseAlertPriority.Warning, projectDirectory)
                                .AddDetail("Multiple project files detected in directory");
                }
            }
            return(alerts.ToList <ICodebaseAlert>());
        }
Example #10
0
        private static void UpdateCodebase(IEnumerable <Type> typeSet = null)
        {
            if (typeSet == null)
            {
                typeSet = Codebase.settingsTypes;
            }
            else
            {
                typeSet = typeSet.Where(t => Codebase.settingsTypes.Contains(t));
            }

            Codebase.UpdateSettings();
            codebase = Codebase.Subset(typeSet, TypeFilter.Any.Configured(), MemberFilter.Any.Configured(), TypeFilter.Any.Configured(false));
            codebase.Cache();
        }
Example #11
0
        public IUnitOption ToOption()
        {
            using (ProfilingUtility.SampleBlock("Row to option"))
            {
                var optionType = Codebase.DeserializeType(this.optionType);

                IUnitOption option;

                option = (IUnitOption)Activator.CreateInstance(optionType);

                option.Deserialize(this);

                return(option);
            }
        }
        public TabTool(Type windowType)
        {
            Ensure.That(nameof(windowType)).IsNotNull(windowType);

            this.windowType = windowType;
            tabKey          = Codebase.SerializeType(windowType);

            try
            {
                FromTitleContent((GUIContent)UnityEditorDynamic.EditorWindow.GetLocalizedTitleContentFromType(windowType));
            }
            catch
            {
                label   = windowType.DisplayName();
                icon    = windowType.Icon()?[IconSize.Small];
                tooltip = windowType.DisplayName();
            }
        }
Example #13
0
        private static void BuildBoltUnitOptions()
        {
#if (UNITY_BOLT_EXIST)
            DictionaryAsset          projectSettings = AssetDatabase.LoadAssetAtPath(PathUtility.FromProject(LudiqCore.Paths.projectSettings), typeof(DictionaryAsset)) as DictionaryAsset;
            List <LooseAssemblyName> assemblyOptions = projectSettings.dictionary["assemblyOptions"] as List <LooseAssemblyName>;
#else
            List <LooseAssemblyName> assemblyOptions = BoltCore.Configuration.assemblyOptions;
#endif

            if (!assemblyOptions.Contains("FMODUnity"))
            {
                assemblyOptions.Add("FMODUnity");
            }

            if (!assemblyOptions.Contains("FMODUnityResonance"))
            {
                assemblyOptions.Add("FMODUnityResonance");
            }
#if (UNITY_BOLT_EXIST)
            List <Type> typeOptions = projectSettings.dictionary["typeOptions"] as List <Type>;
#else
            List <Type> typeOptions = BoltCore.Configuration.typeOptions;
#endif
            Assembly fmodUnityAssembly          = Assembly.Load("FMODUnity");
            Assembly fmodUnityResonanceAssembly = Assembly.Load("FMODUnityResonance");

            List <Type> allTypes = new List <Type>(GetTypesForNamespace(fmodUnityAssembly, "FMOD"));
            allTypes.AddRange(GetTypesForNamespace(fmodUnityAssembly, "FMOD.Studio"));

            foreach (Type type in allTypes)
            {
                if (!typeOptions.Contains(type))
                {
                    typeOptions.Add(type);
                }
            }

            Codebase.UpdateSettings();
#if (UNITY_BOLT_EXIST)
            UnitBase.Build();
#else
            UnitBase.Rebuild();
#endif
        }
Example #14
0
        public List <ICodebaseAlert> GenerateAlerts(Codebase codebase)
        {
            var alerts = new List <CodebaseAlert>();

            foreach (var projectDirectory in codebase.ProjectDirectories)
            {
                foreach (var projectFile in projectDirectory.ProjectFiles)
                {
                    foreach (var dllReference in projectFile.ReferencedDlls)
                    {
                        //We only care about NuGet packages here
                        if (!dllReference.IsNuGetDllReference())
                        {
                            continue;
                        }

                        //TODO - we need to make this configurable a bit somehow
                        var expectedPackageName = dllReference.FileReferenced.NameWithoutExtension().Normalised();

                        if (projectDirectory.PackagesFile == null)
                        {
                            var alert = new CodebaseAlert("Missing Packages.config Alert", CodebaseAlertPriority.Bad, projectDirectory)
                                        .AddDetail("Packages.config file missing - expected for dll reference {0}", dllReference.HintPath);
                            alerts.Add(alert);
                        }
                        else
                        {
                            var packageReference = projectDirectory.PackagesFile.PackageReferences.FirstOrDefault(p => p.PackageNameNormalised == expectedPackageName);
                            if (packageReference == null)
                            {
                                var alert = new CodebaseAlert("Missing Packages.config Reference Alert", CodebaseAlertPriority.Bad, projectDirectory)
                                            .AddDetail("Reference to NuGet package {0} should be in packages.config for dll refernece {1}", expectedPackageName, dllReference.HintPath);
                                alerts.Add(alert);
                            }
                        }
                    }
                }
            }
            return(alerts.ToList <ICodebaseAlert>());
        }
Example #15
0
        public virtual void Deserialize(UnitOptionRow row)
        {
            source = row;

            if (row.sourceScriptGuids != null)
            {
                sourceScriptGuids = row.sourceScriptGuids.Split(',').ToHashSet();
            }

            unitType = Codebase.DeserializeType(row.unitType);

            category           = row.category == null ? null : new UnitCategory(row.category);
            labelHuman         = row.labelHuman;
            labelProgrammer    = row.labelProgrammer;
            order              = row.order;
            haystackHuman      = row.haystackHuman;
            haystackProgrammer = row.haystackProgrammer;
            favoriteKey        = row.favoriteKey;

            controlInputCount  = row.controlInputCount;
            controlOutputCount = row.controlOutputCount;
        }
        protected override void OnContentGUI()
        {
            GUILayout.BeginVertical(Styles.background, GUILayout.ExpandHeight(true));

            LudiqGUI.FlexibleSpace();

            LudiqGUI.BeginHorizontal();
            LudiqGUI.FlexibleSpace();

            var text = "Choose the assemblies in which you want to look for units.\n"
                       + "By default, all project and Unity assemblies are included.\n"
                       + "Unless you use a third-party plugin distributed as a DLL, you shouldn't need to change this.";

            GUILayout.Label(text, LudiqStyles.centeredLabel, GUILayout.MaxWidth(370));
            LudiqGUI.FlexibleSpace();
            LudiqGUI.EndHorizontal();

            LudiqGUI.Space(10);

            var height = LudiqGUI.GetInspectorHeight(null, assemblyOptionsMetadata, Styles.optionsWidth, GUIContent.none);

            LudiqGUI.BeginHorizontal();

            LudiqGUI.FlexibleSpace();

            EditorGUI.BeginChangeCheck();

            var position = GUILayoutUtility.GetRect(Styles.optionsWidth, height);

            LudiqGUI.Inspector(assemblyOptionsMetadata, position, GUIContent.none);

            if (EditorGUI.EndChangeCheck())
            {
                assemblyOptionsMetadata.Save();
                Codebase.UpdateSettings();
            }

            LudiqGUI.FlexibleSpace();
            LudiqGUI.EndHorizontal();

            LudiqGUI.Space(10);

            LudiqGUI.BeginHorizontal();
            LudiqGUI.FlexibleSpace();

            if (GUILayout.Button("Reset to Defaults", Styles.defaultsButton))
            {
                assemblyOptionsMetadata.Reset(true);
                assemblyOptionsMetadata.Save();
            }

            LudiqGUI.FlexibleSpace();
            LudiqGUI.EndHorizontal();

            LudiqGUI.FlexibleSpace();

            LudiqGUI.Space(10);

            LudiqGUI.BeginHorizontal();
            LudiqGUI.FlexibleSpace();

            if (GUILayout.Button(completeLabel, Styles.completeButton))
            {
                Complete();
            }

            LudiqGUI.FlexibleSpace();
            LudiqGUI.EndHorizontal();

            LudiqGUI.FlexibleSpace();

            LudiqGUI.EndVertical();
        }
Example #17
0
        private static void AnalyzeWindowLayout()
        {
            var tabs = ListPool <EditorWindow> .New();

            try
            {
                foreach (var window in Resources.FindObjectsOfTypeAll <EditorWindow>())
                {
                    // Skip invalid windows
                    if (window == null)
                    {
                        continue;
                    }

                    // Abort the operation if any window is maximized, we don't want to save that layout
                    if (window.maximized)
                    {
                        return;
                    }

                    // Skip windows that are invalid or not part of the layout
                    dynamic dWindow = window.AsDynamic();

                    if (dWindow.m_Parent == null || dWindow.m_Parent.window == null || dWindow.m_Parent.window.m_DontSaveToLayout)
                    {
                        continue;
                    }

                    var parentWindowShowMode = (int)dWindow.m_Parent.window.showMode;

                    // Skip windows not in the main window (4 in the ShowMode enum)
                    if (parentWindowShowMode != 4)
                    {
                        continue;
                    }

                    tabs.Add(window);
                }

                // Sort tabs by screen position
                tabs.Sort(compareLayoutTab);

                // Store the tabs in the configuration
                // To minimize serialization operations, first check if changed from last time
                var config           = PeekPlugin.Configuration;
                var tabsChanged      = tabs.Count != config.tabsInLayout.Count;
                var positionsChanged = false;
                var dataChanged      = false;

                // Store the fact that this tab is in the layout, which we'll need as fallback
                // in case the assembly reloads while the scene view is already maximized
                if (!tabsChanged)
                {
                    for (int i = 0; i < tabs.Count; i++)
                    {
                        var tabKey       = Codebase.SerializeType(tabs[i].GetType());
                        var configTabKey = config.tabsInLayout[i];

                        if (tabKey != configTabKey)
                        {
                            tabsChanged = true;
                            break;
                        }
                    }
                }

                if (tabsChanged)
                {
                    config.tabsInLayout.Clear();

                    foreach (var tab in tabs)
                    {
                        var tabKey = Codebase.SerializeType(tab.GetType());
                        config.tabsInLayout.Add(tabKey);
                    }

                    config.Save(nameof(PeekConfiguration.tabsInLayout));
                }

                foreach (var tab in tabs)
                {
                    var tabKey = Codebase.SerializeType(tab.GetType());

                    // Store the position if the user hasn't configured it already
                    if (!config.tabsPositions.ContainsKey(tabKey))
                    {
                        config.tabsPositions[tabKey] = tab.position;
                        positionsChanged             = true;
                    }

                    // Store the data if the user hasn't configured it already
                    if (!config.tabsData.ContainsKey(tabKey))
                    {
                        config.tabsData[tabKey] = EditorJsonUtility.ToJson(tab);
                        dataChanged             = true;
                    }
                }

                if (positionsChanged)
                {
                    config.Save(nameof(PeekConfiguration.tabsPositions));
                }

                if (dataChanged)
                {
                    config.Save(nameof(PeekConfiguration.tabsData));
                }
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"Failed to analyze window layout:\n{ex}");
            }
            finally
            {
                tabs.Free();
            }
        }
Example #18
0
        public List <ICodebaseAlert> GenerateAlerts(Codebase codebase)
        {
            var alerts = new List <CodebaseAlert>();

            foreach (var projectDirectory in codebase.ProjectDirectories)
            {
                Dictionary <string, List <ProjectDirectory> > qaOnlyPackages          = new Dictionary <string, List <ProjectDirectory> >();
                Dictionary <string, List <ProjectDirectory> > versionMismatchPackages = new Dictionary <string, List <ProjectDirectory> >();
                Dictionary <string, string> packagesUsingProdVersion = new Dictionary <string, string>();
                Dictionary <string, string> notFoundPackages         = new Dictionary <string, string>();

                if (projectDirectory.PackagesFile == null)
                {
                    continue;
                }

                foreach (var packageReference in projectDirectory.PackagesFile.PackageReferences)
                {
                    if (packageReference.PackageName == null)
                    {
                        continue;
                    }

                    var packageNameNormalised           = packageReference.PackageName.Normalised();
                    var packageNameAndVersionNormalised = packageNameNormalised + "_" + packageReference.Version;


                    //Already checked as in prod - OK
                    if (packagesUsingProdVersion.ContainsKey(packageNameAndVersionNormalised))
                    {
                        continue;
                    }
                    if (notFoundPackages.ContainsKey(packageNameAndVersionNormalised))
                    {
                        continue;
                    }


                    //We are not the first project directory to use this QA package
                    List <ProjectDirectory> directoriesWithQaPackageAlready = new List <ProjectDirectory>();
                    if (qaOnlyPackages.TryGetValue(packageNameAndVersionNormalised, out directoriesWithQaPackageAlready))
                    {
                        directoriesWithQaPackageAlready.Add(projectDirectory);
                        continue;
                    }

                    //We are the first to check this package essentially
                    NuGetPackage latestInProd;
                    NuGetPackage latestInQa;
                    codebase.NuGetSourceProduction.LatestVersionLookup.TryGetValue(packageNameNormalised, out latestInProd);
                    codebase.NuGetSourceQa.LatestVersionLookup.TryGetValue(packageNameNormalised, out latestInQa);

                    //Not in either feed! Better log this
                    if (latestInProd == null && latestInQa == null)
                    {
                        notFoundPackages.Add(packageNameAndVersionNormalised, packageNameAndVersionNormalised);
                        continue;
                    }

                    //If it is in prod - add to that index
                    if (latestInProd != null && packageReference.Version <= latestInProd.Version)
                    {
                        if (!packagesUsingProdVersion.ContainsKey(packageNameAndVersionNormalised))
                        {
                            packagesUsingProdVersion.Add(packageNameAndVersionNormalised, packageNameAndVersionNormalised);
                        }
                        continue;
                    }

                    directoriesWithQaPackageAlready.Add(projectDirectory);
                    qaOnlyPackages.Add(packageNameAndVersionNormalised, directoriesWithQaPackageAlready);
                }

                foreach (var notFoundPackage in notFoundPackages.Keys.OrderBy(k => k))
                {
                    var alert = new CodebaseAlert("Phantom NuGet Package Reference Alert", CodebaseAlertPriority.Critical, null)
                                .AddDetail("Package {0} is not found in either QA or Production Feeds", notFoundPackage);
                    alerts.Add(alert);
                }

                foreach (var qaOnlyPackage in qaOnlyPackages.Keys.OrderBy(k => k))
                {
                    var alert = new CodebaseAlert("QA NuGet Package Reference Alert", CodebaseAlertPriority.Warning, null)
                                .AddDetail("Package {0} is currently only found in QA feed", qaOnlyPackage);
                    alerts.Add(alert);
                }

                foreach (var versionMismatchPackage in versionMismatchPackages.Keys.OrderBy(k => k))
                {
                    PackageVersion expectedVersion = null;
                    var            alert           = new CodebaseAlert("NuGet Package Version Anomaly Alert", CodebaseAlertPriority.Critical, null)
                                                     .AddDetail("Package {0} is referenced instead of the standard version {1}", versionMismatchPackage, expectedVersion.ToString());

                    var affectedProjects = versionMismatchPackages[versionMismatchPackage];
                    foreach (var project in affectedProjects)
                    {
                        alert.AddDetail(" - {0}", project.DisplayPath(codebase.RootSourceDirectory));
                    }

                    alerts.Add(alert);
                }
            }


            return(alerts.ToList <ICodebaseAlert>());
        }
        protected override void OnContentGUI()
        {
            GUILayout.BeginVertical(Styles.background, GUILayout.ExpandHeight(true));

            LudiqGUI.FlexibleSpace();

            LudiqGUI.BeginHorizontal();
            LudiqGUI.FlexibleSpace();

            var text = "Choose the types you want to use for variables and units.\n"
                       + "MonoBehaviour types are always included.";

            GUILayout.Label(text, LudiqStyles.centeredLabel, GUILayout.MaxWidth(370));
            LudiqGUI.FlexibleSpace();
            LudiqGUI.EndHorizontal();

            LudiqGUI.Space(10);

            var height = LudiqGUI.GetInspectorHeight(null, typeOptionsMetadata, Styles.optionsWidth, GUIContent.none);

            LudiqGUI.BeginHorizontal();

            LudiqGUI.FlexibleSpace();

            EditorGUI.BeginChangeCheck();

            var position = GUILayoutUtility.GetRect(Styles.optionsWidth, height);

            LudiqGUI.Inspector(typeOptionsMetadata, position, GUIContent.none);

            if (EditorGUI.EndChangeCheck())
            {
                typeOptionsMetadata.Save();
                Codebase.UpdateSettings();
            }

            LudiqGUI.FlexibleSpace();
            LudiqGUI.EndHorizontal();

            LudiqGUI.Space(10);

            LudiqGUI.BeginHorizontal();
            LudiqGUI.FlexibleSpace();

            if (GUILayout.Button("Reset to Defaults", Styles.defaultsButton))
            {
                typeOptionsMetadata.Reset(true);
                typeOptionsMetadata.Save();
            }

            LudiqGUI.FlexibleSpace();
            LudiqGUI.EndHorizontal();

            LudiqGUI.FlexibleSpace();

            LudiqGUI.Space(10);

            LudiqGUI.BeginHorizontal();
            LudiqGUI.FlexibleSpace();

            if (GUILayout.Button("Generate", Styles.completeButton))
            {
                Complete();
            }

            LudiqGUI.FlexibleSpace();
            LudiqGUI.EndHorizontal();

            LudiqGUI.FlexibleSpace();

            LudiqGUI.EndVertical();
        }
Example #20
0
        private Expression Expand(Expression expr)
        {
            if (expr == null)
            {
                return(null);
            }
            else if (expr is Addr)
            {
                var addr   = (Addr)expr;
                var target = Expand(addr.Target);
                return(new Addr(target));
            }
            else if (expr is Assign)
            {
                var ass = (Assign)expr;

                var prop = ass.InvokedProp();
                if (prop != null)
                {
                    return(Expand(prop));
                }
                else
                {
                    var rhs = Expand(ass.Rhs);
                    var lhs = Expand(ass.Lhs);
                    return(new Assign(lhs, rhs));
                }
            }
            else if (expr is Operator)
            {
                var op = (Operator)expr;
                if (op.OperatorType.IsAssign())
                {
                    var prop = op.Children.AssertFirst().InvokedProp();
                    if (prop != null)
                    {
                        return(Expand(prop));
                    }
                    else
                    {
                        // todo. implement this with the use of SafeExpandOpAssign
                        var args = op.Args.Select(arg => Expand(arg));
                        return(Operator.Create(op.OperatorType, args));
                    }
                }
                else
                {
                    var args = op.Args.Select(arg => Expand(arg));
                    return(Operator.Create(op.OperatorType, args));
                }
            }
            else if (expr is Conditional)
            {
                var cond    = (Conditional)expr;
                var test    = Expand(cond.Test);
                var iftrue  = Expand(cond.IfTrue);
                var iffalse = Expand(cond.IfFalse);
                return(new Conditional(test, iftrue, iffalse));
            }
            else if (expr is Const)
            {
                // do nothing - nowhere to drill into
                return(expr);
            }
            else if (expr is Convert)
            {
                var cvt    = (Convert)expr;
                var source = Expand(cvt.Source);
                return(new Convert(cvt.Type, source));
            }
            else if (expr is Deref)
            {
                var deref  = (Deref)expr;
                var target = Expand(deref.Target);
                return(new Deref(target));
            }
            else if (expr is Fld)
            {
                var fld   = (Fld)expr;
                var @this = Expand(fld.This);
                return(new Fld(fld.Field, @this));
            }
            else if (expr is Prop)
            {
                // basic investigations
                var prop        = (Prop)expr;
                var is_instance = prop.Property.IsInstance();
                var parent      = prop.Parent;
                var app         = parent as Apply;
                var is_indexer  = app != null && app.Callee == prop;
                if (is_indexer)
                {
                    parent = parent.Parent;
                }

                // we have 5 different cases:
                // 1) foo.P;
                // 2) foo.P = bar;
                // 3) qux = (foo.P = bar);
                // 4) foo.P += bar;
                // 4') foo.P++;
                // 5) qux = (foo.P += bar);
                // 5') qux = (foo.P++);
                var ass           = parent as Assign;
                var is_assigned   = ass != null && (ass.Lhs == prop || ass.Lhs == app);
                var op            = parent as Operator;
                var is_opassigned = op != null && op.OperatorType.IsAssign();
                is_assigned |= is_opassigned;
                var is_rhs_reused = is_assigned && parent.Parent is Expression;

                if (!is_assigned)
                {
                    var impl         = prop.Property.GetGetMethod(true);
                    var this_args    = is_instance ? prop.This.MkArray() : Seq.Empty <Expression>();
                    var indexer_args = is_indexer ? app.Args : Seq.Empty <Expression>();
                    var args         = Seq.Concat(this_args, indexer_args).ToReadOnly();
                    var style        = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual;
                    return(Expand(new Eval(new Apply(new Lambda(impl, style), args))));
                }
                else
                {
                    // abstract away the root
                    // todo. implement this with the use of SafeExpandOpAssign
                    var root = prop.This;
                    if (is_opassigned && !root.IsLvalue())
                    {
                        var opassroot = DeclareLocal("$opassroot", prop.This.Type());
                        Emit(new Assign(opassroot, prop.This));
                        root = opassroot;
                    }

                    // abstract away the RHS
                    var rhs = null as Expression;
                    if (ass != null)
                    {
                        rhs = ass.Rhs;
                    }
                    if (is_opassigned)
                    {
                        if (op.IsUnary())
                        {
                            rhs = new Const(1);
                        }
                        else if (op.IsBinary())
                        {
                            rhs = op.Children.AssertSecond().AssertCast <Expression>();
                        }
                        else
                        {
                            throw AssertionHelper.Fail();
                        }
                    }

                    // abstract away the equivalence transform
                    Func <Expression> equiv = () =>
                    {
                        Func <Expression> equivGetter = () =>
                        {
                            var impl         = prop.Property.GetGetMethod(true);
                            var this_args    = is_instance ? root.MkArray() : Seq.Empty <Expression>();
                            var indexer_args = is_indexer ? app.Args : Seq.Empty <Expression>();
                            var args         = Seq.Concat(this_args, indexer_args).ToReadOnly();
                            var style        = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual;
                            return(new Eval(new Apply(new Lambda(impl, style), args)));
                        };

                        Func <Expression, Expression> equivSetter = assigned_value =>
                        {
                            var impl         = prop.Property.GetSetMethod(true);
                            var this_args    = is_instance ? root.MkArray() : Seq.Empty <Expression>();
                            var indexer_args = is_indexer ? app.Args : Seq.Empty <Expression>();
                            var args         = Seq.Concat(this_args, indexer_args, assigned_value.MkArray()).ToReadOnly();
                            var style        = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual;
                            return(new Eval(new Apply(new Lambda(impl, style), args)));
                        };

                        if (is_opassigned)
                        {
                            return(equivSetter(Operator.Create(op.OperatorType, equivGetter(), rhs)));
                        }
                        else
                        {
                            return(equivSetter(rhs));
                        }
                    };

                    // final transform
                    if (is_rhs_reused)
                    {
                        var cached_rhs = DeclareLocal("$opassrhs", rhs.Type());
                        Emit(new Assign(cached_rhs, rhs));
                        rhs = cached_rhs;
                        Emit(equiv());
                        return(cached_rhs);
                    }
                    else
                    {
                        return(Expand(equiv()));
                    }
                }
            }
            else if (expr is Ref)
            {
                var @ref = (Ref)expr;
                var env  = Env.GetOrDefault(@ref.Sym);
                return(Expand(env) ?? @ref);
            }
            else if (expr is SizeOf)
            {
                // do nothing - nowhere to drill into
                return(expr);
            }
            else if (expr is TypeAs)
            {
                var typeAs = (TypeAs)expr;
                var target = Expand(typeAs.Target);
                return(new TypeAs(typeAs.Type, target));
            }
            else if (expr is TypeIs)
            {
                var typeIs = (TypeIs)expr;
                var target = Expand(typeIs.Target);
                return(new TypeAs(typeIs.Type, target));
            }
            else if (expr is Default)
            {
                // do nothing - nowhere to drill into
                return(expr);
            }
            else if (expr is CollectionInit)
            {
                var ci = (CollectionInit)expr;
                if (ci.Elements.IsEmpty())
                {
                    return(Expand(ci.Ctor));
                }
                else
                {
                    var ctor_coll = ci.InvokedMethod().AssertThat(mb => mb.IsConstructor());
                    var t_coll    = ctor_coll.DeclaringType;

                    var l_coll = DeclareLocal("$", t_coll);
                    Emit(new Assign(l_coll, ci.Ctor));
                    ci.Elements.ForEach((el, i) =>
                    {
                        if (t_coll.IsArray)
                        {
                            (t_coll.GetArrayRank() == 1).AssertTrue();
                            var m_set = t_coll.ArraySetter().AssertNotNull();
                            Emit(new Eval(new Apply(new Lambda(m_set), l_coll, new Const(i), el)));
                        }
                        else
                        {
                            var m_add = t_coll.GetMethods(BF.All).AssertSingle(m => m.Name == "Add");
                            Emit(new Eval(new Apply(new Lambda(m_add), l_coll, el)));
                        }
                    });

                    return(l_coll);
                }
            }
            else if (expr is ObjectInit)
            {
                var oi = (ObjectInit)expr;
                if (oi.Members.IsEmpty())
                {
                    return(Expand(oi.Ctor));
                }
                else
                {
                    var ctor_obj = oi.InvokedMethod().AssertThat(mb => mb.IsConstructor());
                    var t_obj    = ctor_obj.DeclaringType;

                    var l_obj = DeclareLocal("$", t_obj);
                    Emit(new Assign(l_obj, oi.Ctor));
                    foreach (var mi in oi.Members)
                    {
                        if (mi is FieldInfo)
                        {
                            var fi = mi as FieldInfo;
                            Emit(new Assign(new Fld(fi, l_obj), oi.MemberInits[mi]));
                        }
                        else if (mi is PropertyInfo)
                        {
                            var pi = mi as PropertyInfo;
                            // todo. what about virtuality?!
                            Emit(new Assign(new Prop(pi, l_obj), oi.MemberInits[mi]));
                        }
                        else
                        {
                            throw AssertionHelper.Fail();
                        }
                    }

                    return(l_obj);
                }
            }
            else if (expr is Eval)
            {
                var eval      = (Eval)expr;
                var lam       = eval.InvokedLambda();
                var m         = eval.InvokedMethod();
                var child_ctx = Ctx.SpinOff(m);

                var status = Codebase.Classify(m);
                (status != MethodStatus.MustNotBeExecutedOnDevice).AssertTrue();
                var is_redirected = status == MethodStatus.IsRedirected;
                if (is_redirected)
                {
                    var redir = Codebase.Redirect(eval);
                    if (redir == null)
                    {
                        return(null);
                    }
                    else
                    {
                        var m_redir = redir.InvokedMethod();
                        if (m_redir.HasBody())
                        {
                            var raw_body = m_redir.ParseBody().Where(op => !(op is CilNop)).ToReadOnly();
                            if (raw_body.Count() == 2)
                            {
                                var first  = raw_body.First() as CilNew;
                                var second = raw_body.Second() as CilThrow;

                                var tni_ctor = typeof(NotImplementedException).GetConstructor(Type.EmptyTypes);
                                if (first != null && first.Ctor == tni_ctor && second != null)
                                {
                                    throw AssertionHelper.Fail();
                                }
                            }
                        }

                        return(Expand(redir));
                    }
                }
                else
                {
                    var needsExpansion      = status == MethodStatus.CanBeExecutedOnDevice;
                    var doesntNeedExpansion = status == MethodStatus.HasSpecialSemantics;
                    (needsExpansion ^ doesntNeedExpansion).AssertTrue();
                    if (needsExpansion)
                    {
                        // todo. think about what we can do here
                        (lam.InvocationStyle == InvocationStyle.Virtual).AssertFalse();
                        m.DeclaringType.IsInterface.AssertFalse();
                    }

                    var md = m.Decompile();
                    needsExpansion.AssertImplies(m.HasBody());
                    var p_ret = Seq.Empty <ParameterInfo>();
                    var mi    = m as MethodInfo;
                    if (mi != null)
                    {
                        p_ret = mi.ReturnParameter.MkArray();
                    }
                    m.GetParameters().Concat(p_ret).ForEach(pi => pi.IsOptional.AssertFalse());

                    var args = eval.InvocationArgs();
                    var args_include_this = !lam.InvokedAsCtor && m.IsInstance();
                    var @params           = m.GetParameters().AsEnumerable();
                    var p_fakethis        = null as ParameterInfo;
                    if (args_include_this)
                    {
                        @params = p_fakethis.Concat(@params).ToReadOnly();
                    }

                    var l_args = @params.Zip(args, (p, actual_arg) =>
                    {
                        var p_sig  = p == null ? md.Sig.Params.First() : md.Sig.Params.AssertSingle(p1 => p1.Metadata == p);
                        var p_type = p_sig.Type;

                        Func <Expression, Expression> expand_arg = null;
                        expand_arg = arg =>
                        {
                            Func <Expression, String, Expression> default_expand1 = (e, postfix) =>
                            {
                                var prefix    = (m.IsConstructor() ? m.DeclaringType.Name : m.Name).ToLower();
                                var name      = p_sig.Name + (postfix == null ? null : ("_" + postfix.ToLower()));
                                var full_name = String.Format("${0}_{1}", prefix, name);

                                var l_stub = DeclareLocal(full_name, p_type);
                                Emit(new Assign(l_stub, Expand(arg)));
                                return(l_stub);
                            };
                            Func <Expression, Expression> default_expand = e => default_expand1(e, null);

                            if (doesntNeedExpansion)
                            {
                                if (p_type.IsArray && p.IsVarargs())
                                {
                                    var ctor = arg.InvokedCtor();
                                    if (ctor != null && ctor.DeclaringType.IsArray)
                                    {
                                        var arg_eval = arg as Eval;
                                        if (arg_eval != null)
                                        {
                                            var rank = ctor.DeclaringType.GetArrayRank();
                                            if (rank == 1)
                                            {
                                                var sole_arg = arg.InvocationArgs().AssertSingle() as Const;
                                                if (sole_arg != null &&
                                                    sole_arg.Value is int && (int)sole_arg.Value == 0)
                                                {
                                                    return(arg);
                                                }
                                            }
                                        }

                                        var arg_ci = arg as CollectionInit;
                                        if (arg_ci != null)
                                        {
                                            p_type.IsArray().AssertTrue();
                                            (p_type.GetArrayRank() == 1).AssertTrue();

                                            try
                                            {
                                                p_type  = p_type.GetElementType();
                                                var els = arg_ci.Elements.Select(expand_arg).ToReadOnly();
                                                return(new CollectionInit(arg_ci.Ctor, els));
                                            }
                                            finally
                                            {
                                                p_type = p_type.MakeArrayType();
                                            }
                                        }
                                    }
                                }

                                var needs_expansion = arg.Family().Any(c =>
                                                                       c is Eval || c is Apply || c is Lambda || c is Prop || c is CollectionInit || c is ObjectInit);
                                if (!needs_expansion)
                                {
                                    return(arg);
                                }
                                else
                                {
                                    // todo. the stuff below works incorrectly in general case
                                    // since it might disrupt evaluation order of parameters
                                    //
                                    // however for now I trade off introducing a potential bug
                                    // for the ease of debugging and looking at traces

                                    var old_stmtc = Stmts.Count();
                                    var expanded  = default_expand(arg).AssertCast <Ref>();
                                    var new_stmtc = Stmts.Count();
                                    (new_stmtc > old_stmtc).AssertTrue();

                                    // todo. fix possible semantic disruption at the next line
                                    if (new_stmtc - old_stmtc > 1)
                                    {
                                        return(expanded);
                                    }
                                    else
                                    {
                                        var ass = Stmts.Last().AssertCast <Assign>();
                                        ass.Lhs.Equiv(expanded).AssertTrue();
                                        Stmts.RemoveLast();
                                        RemoveLocal(expanded);
                                        return(ass.Rhs);
                                    }
                                }
                            }
                            else
                            {
                                var p_reads = md.Body.Family().OfType <Ref>().Where(r => r.Sym == p_sig.Sym).ToReadOnly();
                                var p_asses = md.Body.Family().OfType <Assign>().Select(ass =>
                                {
                                    var r_lhs    = ass.Lhs as Ref;
                                    var is_write = r_lhs != null && r_lhs.Sym == p_sig.Sym;
                                    return(is_write ? ass : null);
                                }).Where(ass => ass != null).ToReadOnly();
                                var p_byref = md.Body.Family().OfType <Apply>().Select(app =>
                                {
                                    var passes_byref = app.ArgsInfo.Zip((e, pi) =>
                                    {
                                        var e_ref    = e as Ref;
                                        var is_read  = e_ref != null && e_ref.Sym == p_sig.Sym;
                                        var is_byref = pi.Type.IsByRef;
                                        return(is_read && is_byref);
                                    }).Any();
                                    return(passes_byref ? app : null);
                                }).Where(app => app != null).ToReadOnly();
                                var p_writes = Seq.Concat(p_asses.Cast <Expression>(), p_byref.Cast <Expression>()).ToReadOnly();
                                var p_usages = Seq.Concat(p_reads.Cast <Expression>(), p_writes.Cast <Expression>()).ToReadOnly();

                                // todo. below we might disrupt evaluation order
                                // by totally inlining an arg expression if it has a single usage
                                // strictly speaking, before doing that
                                // we need perform additional checks that eval-order is preserved
                                //
                                // note. this semi-correct solution is introduced
                                // solely for the convenience of the back-end
                                // and for the convenience of reading the resulting traces

                                var passed_by_ref = p == null || p.PassedByRef();
                                if (passed_by_ref)
                                {
                                    var @ref = arg as Ref;
                                    if (@ref != null)
                                    {
                                        return(arg);
                                    }

                                    var fld = arg as Fld;
                                    if (fld != null)
                                    {
                                        fld.Field.IsInstance().AssertTrue();

                                        // todo. fix possible semantic disruption at the next line
                                        if (p_usages.Count() <= 1)
                                        {
                                            return(arg);
                                        }
                                        else
                                        {
                                            var root    = fld.This;
                                            var is_atom = root is Ref || root is Const;
                                            if (is_atom)
                                            {
                                                return(arg);
                                            }
                                            else
                                            {
                                                var root_expanded = default_expand1(root, "root");
                                                return(new Fld(fld.Field, root_expanded));
                                            }
                                        }
                                    }

                                    var eval1 = arg as Eval;
                                    if (eval1 != null)
                                    {
                                        var m1 = eval1.InvokedMethod();
                                        m1.IsArrayGetter().AssertTrue();
                                        var args1 = eval1.InvocationArgs();
                                        var lam1  = eval1.InvokedLambda();

                                        var r_ee = eval1.Expand(Ctx.SpinOff(m1));
                                        r_ee.Stmts.ForEach(Stmts.Add);
                                        var ee = r_ee.Result.AssertCast <Eval>().AssertNotNull();

                                        // todo. fix possible semantic disruption at the next line
                                        if (p_usages.Count() <= 1)
                                        {
                                            return(ee);
                                        }
                                        else
                                        {
                                            var root = ee.Callee.Callee;
                                            Func <Expression, bool> is_atom = e => e is Ref || e is Const;
                                            if (is_atom(root) && ee.Callee.Args.All(is_atom))
                                            {
                                                return(ee);
                                            }
                                            else
                                            {
                                                var root_expanded = default_expand1(root, "root");
                                                return(new Eval(new Apply(new Lambda(m1, lam1.InvocationStyle), root_expanded.Concat(args1))));
                                            }
                                        }
                                    }

                                    // arg isn't an lvalue, so it can't be passed by reference
                                    throw AssertionHelper.Fail();
                                }
                                else
                                {
                                    if (p_writes.IsEmpty())
                                    {
                                        // todo. fix possible semantic disruption at the next line
                                        if (p_usages.Count() <= 1)
                                        {
                                            return(arg);
                                        }
                                        else
                                        {
                                            var is_atom = arg is Ref || arg is Const;
                                            if (is_atom)
                                            {
                                                var is_value_type = p_type.IsValueType;
                                                var is_primitive  = p_type.IsPrimitive;
                                                var needs_copying = is_value_type && !is_primitive;
                                                return(needs_copying ? default_expand(arg) : arg);
                                            }
                                            else
                                            {
                                                return(default_expand(arg));
                                            }
                                        }
                                    }
                                    else
                                    {
                                        return(default_expand(arg));
                                    }
                                }
                            }
                        };

                        var preprocessed_arg = actual_arg.Transform((Ref @ref) =>
                        {
                            var env = Env.GetOrDefault(@ref.Sym);
                            return(env ?? @ref);
                        }).AssertCast <Expression>();
                        var expanded_arg = expand_arg(preprocessed_arg);
                        expanded_arg     = expanded_arg.Transform((Ref @ref) =>
                        {
                            var env = Env.GetOrDefault(@ref.Sym);
                            return(env ?? @ref);
                        }).AssertCast <Expression>();

                        if (needsExpansion)
                        {
                            child_ctx.Env.Add(p_sig.Sym, expanded_arg);
                        }
                        return(expanded_arg);
                    }).ToReadOnly();

                    if (needsExpansion)
                    {
                        var env_locals = lam.Body.LocalsRecursive().ToDictionary(l => l as Sym, l =>
                        {
                            var frames    = Stack.Reverse().Skip(1).Concat(m);
                            var qualifier = frames.Select(sf => sf.Name.ToLower()).StringJoin("_");
                            var full_name = String.Format("${0}_{1}", qualifier, l.Name);
                            return(DeclareLocal(full_name, l.Type) as Expression);
                        }).ToReadOnly();
                        child_ctx.Env.AddElements(env_locals);

                        Action <Block> import_locals = blk =>
                        {
                            foreach (var local in blk.Locals.ToArray())
                            {
                                var env_ref = env_locals.GetOrDefault(local) as Ref;
                                var env     = env_ref == null ? null : (Local)env_ref.Sym;
                                if (env != null)
                                {
                                    blk.Locals.Remove(local);
                                    blk.Locals.Add(env);
                                }
                                else
                                {
                                    Scope.Locals.Add(local);
                                }
                            }

                            // todo. also import locals from embedded blocks
                            // here we need to take inlined stuff into account
                        };

                        if (lam.InvokedAsCtor)
                        {
                            var l_this = DeclareLocal(String.Format("${0}_this", m.DeclaringType.Name.ToLower()), m.DeclaringType);
                            child_ctx.Env.Add(lam.Sig.Syms[0], l_this);

                            var malloc      = typeof(Ctm).GetMethod("Malloc", new [] { typeof(Type) }).AssertNotNull();
                            var malloc_type = new Const(m.DeclaringType);
                            Emit(new Assign(l_this, new Eval(new Apply(new Lambda(malloc), malloc_type))));

                            var body = lam.Body.Expand(child_ctx);
                            import_locals(body);

                            if (body.IsEmpty())
                            {
                                var last_stmt    = Stmts.Last() as Assign;
                                var last_invoked = last_stmt == null ? null : last_stmt.Rhs.InvokedMethod();
                                (last_invoked == malloc).AssertTrue();

                                RemoveLocal(l_this);
                                Stmts.RemoveLast();
                                return(last_stmt.Rhs);
                            }
                            else
                            {
                                body.ForEach(Stmts.Add);
                                return(l_this);
                            }
                        }
                        else if (m.Ret() == typeof(void))
                        {
                            var body = lam.Body.Expand(child_ctx).AssertNotEmpty();
                            import_locals(body);

                            if (body.IsNotEmpty())
                            {
                                body.ForEach(Stmts.Add);
                            }
                            return(null);
                        }
                        else
                        {
                            (m.Ret().IsByRef || m.Ret().IsPointer).AssertFalse();

                            var name  = String.Format("${0}_ret", m.Name.ToLower());
                            var l_ret = DeclareLocal(name, m.Ret());
                            child_ctx.Ret = l_ret;

                            var body = lam.Body.Expand(child_ctx).AssertNotEmpty();
                            import_locals(body);

                            var body_last = body.LastOrDefault();
                            if (body_last is Label)
                            {
                                body.ForEach(Stmts.Add);
                                return(l_ret);
                            }
                            else
                            {
                                var ass = body.AssertLast().AssertCast <Assign>();
                                ass.Lhs.Equiv(l_ret).AssertTrue();

                                RemoveLocal(l_ret);
                                body.SkipLast(1).ForEach(Stmts.Add);
                                return(ass.Rhs);
                            }
                        }
                    }
                    else
                    {
                        return(new Eval(new Apply(lam, l_args.Cast <Expression>())));
                    }
                }
            }
            else
            {
                var app      = expr as Apply;
                var app_prop = app == null ? null : app.Callee as Prop;
                if (app_prop != null)
                {
                    return(Expand(app_prop));
                }

                // todo. also support indirect calls and partial applications
                // i.e. process cases when Apply/Lambda nodes ain't wrapped in an Eval
                throw AssertionHelper.Fail();
            }
        }
Example #21
0
        public override void Deserialize(UnitOptionRow row)
        {
            base.Deserialize(row);

            structType = Codebase.DeserializeType(row.tag1);
        }
        private void Load(string path = null)
        {
            if (string.IsNullOrEmpty(path))
            {
                var dlg = new OpenFileDialog
                {
                    Filter          = "All Files|*.*",
                    CheckFileExists = true,
                    Multiselect     = false,
                    Title           = "Please choose UMDH delta file"
                };
                if (dlg.ShowDialog().Value)
                {
                    path = dlg.FileName;
                }
                else
                {
                    return;
                }
            }

            try
            {
                var loadingWindow = new ProgressWindow();
                loadingWindow.Title = "Loading - " + path;

                bool continueWithLoading = true;
                loadingWindow.Closed += (s, e) =>
                {
                    continueWithLoading = false;
                };

                Codebase codebase = null;
                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        codebase = UMDHParser.Parse(path, (progress) =>
                        {
                            Dispatcher.BeginInvoke(new Action(() =>
                            {
                                loadingWindow.progressBar.Value = progress;
                            }));
                        });
                        codebase.Normalize();

                        Dispatcher.BeginInvoke(new Action(() =>
                        {
                            if (continueWithLoading)
                            {
                                codebase.Owner = this;
                                Codebase       = codebase;
                                Title          = "UMDH Visualize - " + path;
                                SelectedTab    = tabRawView;
                            }

                            loadingWindow.Close();
                        }));
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(string.Format("Cannot parse file \"{0}\":\r\n{1}", path, ex));
                    }
                });

                loadingWindow.ShowDialog();
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("Cannot parse file \"{0}\":\r\n{1}", path, ex));
            }
        }