public override string ComputeMacro(string macroStr)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (macroStr == @"$(UE4ModuleName)")
            {
                Document doc = EditorUtils.GetActiveDocument();
                if (doc == null)
                {
                    return(null);
                }

                string modulePath = ExtractorUnreal.GetModulePath(doc.FullName);
                if (modulePath == null)
                {
                    return(null);
                }

                string moduleName = Path.GetFileName(modulePath);
                OutputLog.Log("UE4 Module Name: " + moduleName);
                return(moduleName);
            }

            return(null);
        }
        protected override void CaptureExtraProperties(ProjectProperties projProperties, IMacroEvaluator evaluator)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (projProperties == null)
            {
                return;
            }

            OutputLog.Log("Capturing Extra configuration from Unreal...");

            //Basic VS context
            Document doc     = EditorUtils.GetActiveDocument();
            Project  project = EditorUtils.GetActiveProject();

            //Find module path & name for the given file
            string modulePath = GetModulePath(doc.FullName);
            string moduleName = modulePath == null ? null : Path.GetFileName(modulePath);

            OutputLog.Log(moduleName == null ? "Unable to find Unreal Engine Module." : "Unreal Engine Module Name: " + moduleName);

            //Open project vcxproj as xml
            //Find the first .cpp file from the given module & steal its configuration
            AppendFileConfiguration(projProperties, SearchInProjectFile(project, modulePath), evaluator);

            //Add basic preprocessor definition
            projProperties.PrepocessorDefinitions.Add("UNREAL_CODE_ANALYZER");
        }
Esempio n. 3
0
        private void FixEmptyBaseOptim(LayoutNode node)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            for (int i = 1; i < node.Children.Count;)
            {
                var thisNode = node.Children[i];
                var prevNode = node.Children[i - 1];

                if (thisNode.Offset == prevNode.Offset)
                {
                    if (prevNode.IsBaseCategory() && prevNode.Size == 1)
                    {
                        //Empty base optimization
                        node.Extra.Add(prevNode);
                        node.Children.RemoveAt(i - 1);
                    }
                    else
                    {
                        //Found unknown overlap
                        OutputLog.Log("Found type overlap without known explanation");
                        ++i;
                    }
                }
                else
                {
                    ++i;
                }
            }
        }
Esempio n. 4
0
        public void ProcessLog()
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            uint   size   = 0;
            IntPtr result = GetLog(ref size);

            if (size > 0)
            {
                byte[] managedArray = new byte[size];
                Marshal.Copy(result, managedArray, 0, (int)size);
                string val = Encoding.UTF8.GetString(managedArray);
                OutputLog.Log("Execution Log:\n" + val);
            }
        }
Esempio n. 5
0
        protected static bool IsMSBuildStringInvalid(string input)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (!StringHasContent(input))
            {
                return(true);
            }

            if (input.Contains('$'))
            {
                OutputLog.Log("Dropped " + input + ". It contains an unknown MSBuild macro");
                return(true);
            }
            return(false);
        }
Esempio n. 6
0
        private bool IsMSBuildStringInvalid(string input)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (input.Length == 0)
            {
                return(true);
            }

            if (input.Contains('$'))
            {
                OutputLog.Log("Dropped " + input + ". It contains an unknown MSBuild macro");
                return(true);
            }
            return(false);
        }
Esempio n. 7
0
        private void FixOverlaps(LayoutNode node)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (node.Type.Length > 0 && node.Type.StartsWith("union"))
            {
                node.Category = LayoutNode.LayoutCategory.Union;
                node.Extra    = node.Children;
                node.Children = new List <LayoutNode>();
            }

            if (node.Category != LayoutNode.LayoutCategory.Union)
            {
                for (int i = 1; i < node.Children.Count;)
                {
                    var thisNode = node.Children[i];
                    var prevNode = node.Children[i - 1];

                    if (thisNode.Offset == prevNode.Offset)
                    {
                        if (prevNode.IsBaseCategory() && prevNode.Size == 1)
                        {
                            //Empty base optimization
                            node.Extra.Add(prevNode);
                            node.Children.RemoveAt(i - 1);
                        }
                        else
                        {
                            //Found unknown overlap
                            OutputLog.Log("Found type overlap without known explanation");
                            ++i;
                        }
                    }
                    else
                    {
                        ++i;
                    }
                }
            }

            //continue recursion
            foreach (LayoutNode child in node.Children)
            {
                FixOverlaps(child);
            }
        }
        public override ProjectProperties GetProjectData()
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            OutputLog.Log("Capturing configuration from CMake...");

            Document document = EditorUtils.GetActiveDocument();

            if (document == null)
            {
                return(null);
            }

            var    evaluator      = new MacroEvaluatorCMake();
            var    customSettings = SettingsManager.Instance.Settings;
            string commandsFile   = customSettings == null ? null : customSettings.CMakeCommandsFile;

            commandsFile = commandsFile == null ? null : evaluator.Evaluate(commandsFile);

            if (commandsFile == null || commandsFile.Length == 0)
            {
                var activeConfig = GetActiveConfiguration();
                if (activeConfig != null)
                {
                    var cmakeArgsEvaluator = new MacroEvaluatorCMakeArgs();
                    commandsFile = cmakeArgsEvaluator.Evaluate(activeConfig.buildRoot);
                    if (commandsFile.Length > 0)
                    {
                        char lastchar = commandsFile[commandsFile.Length - 1];
                        if (lastchar != '\\' && lastchar != '/')
                        {
                            commandsFile += '\\';
                        }
                        commandsFile += "compile_commands.json";
                    }
                }
            }

            var ret = CaptureCMakeCommands(commandsFile, document.FullName);

            AddCustomSettings(ret, evaluator);

            return(ret);
        }
        protected override void ProcessPostProjectData(ProjectProperties projProperties)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            for (int i = 0; i < projProperties.ForceIncludes.Count; ++i)
            {
                string pchFile = projProperties.ForceIncludes[i] + ".pch";
                if (File.Exists(pchFile))
                {
                    OutputLog.Log("Found incompatible pch file, generating alias for: " + pchFile);

                    string originalName = projProperties.ForceIncludes[i];
                    string newName      = Path.GetDirectoryName(originalName) + @"\SL_" + Path.GetFileName(originalName);
                    projProperties.ForceIncludes[i] = newName;

                    File.Copy(originalName, newName, true);
                }
            }
        }
        private XmlNode SearchInProjectFile(Project project, string modulePath)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            //Get Relative path to modulePath from projectPath
            string projectPath  = Path.GetDirectoryName(project.FullName) + '\\';
            string relativePath = MakeRelativePath(projectPath, modulePath);

            if (relativePath == null)
            {
                return(null);
            }
            relativePath += "\\";

            XmlDocument doc = new XmlDocument();

            doc.Load(project.FullName);
            if (doc == null)
            {
                return(null);
            }

            XmlNodeList compileUnits = doc.GetElementsByTagName("ClCompile");

            foreach (XmlNode tu in compileUnits)
            {
                XmlNode fileName = tu.Attributes.GetNamedItem("Include");
                if (fileName != null && fileName.InnerText.StartsWith(relativePath))
                {
                    string fileRelativeToModule = fileName.InnerText.Substring(relativePath.Length);
                    OutputLog.Log("Found compilation unit in same module: " + fileRelativeToModule);
                    return(tu);
                }
            }

            OutputLog.Log("Could not find any compilation unit in the same Unreal module.");
            return(null);
        }
        private ProjectProperties CaptureCMakeCommands(string commandsFile, string documentName)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var ret = new ProjectProperties();

            if (commandsFile == null || commandsFile.Length == 0)
            {
                OutputLog.Log("Unable to retrieve a CMake commands file.\nMake sure the cmake flag -DCMAKE_EXPORT_COMPILE_COMMANDS=1 is set and the options are pointing to the proper file.");
            }
            else
            {
                if (File.Exists(commandsFile))
                {
                    OutputLog.Log("Capturing commands from CMake commands file: " + commandsFile);

                    List <CMakeCommandEntry> allCommands = null;
                    try
                    {
                        string jsonString = File.ReadAllText(commandsFile);
                        allCommands = JsonConvert.DeserializeObject <List <CMakeCommandEntry> >(jsonString);
                    }
                    catch (Exception e)
                    {
                        OutputLog.Error(e.Message);
                    }

                    ExtractCMakeProjectProperties(ret, FindBestCMakeEntry(allCommands, documentName));
                }
                else
                {
                    OutputLog.Log("Unable to find CMake commands file at " + commandsFile + ".\nMake sure the cmake flag -DCMAKE_EXPORT_COMPILE_COMMANDS=1 is set and the options are pointing to the proper file.");
                }
            }

            return(ret);
        }
Esempio n. 12
0
        public override ProjectProperties GetProjectData()
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            OutputLog.Log("Using manual configuration...");

            var ret = new ProjectProperties();

            Project         project  = EditorUtils.GetActiveProject();
            VCProject       prj      = project == null ? null : project.Object as VCProject;
            VCConfiguration config   = prj == null ? null : prj.ActiveConfiguration;
            VCPlatform      platform = config == null ? null : config.Platform;

            if (platform != null)
            {
                AddCustomSettings(ret, new MacroEvaluatorVisualPlatform(platform));
            }
            else
            {
                AddCustomSettings(ret, new MacroEvaluatorCMake());
            }

            return(ret);
        }
        private void ExtractCMakeProjectProperties(ProjectProperties inout, CMakeCommandEntry command)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (command == null)
            {
                return;
            }

            OutputLog.Log("Extracting commands from Translation Unit: " + command.file);

            inout.WorkingDirectory = command.directory;

            List <string> commands = ParseCommands(command.command);

            for (int i = 0; i < commands.Count; ++i)
            {
                string com = commands[i];

                if (com.Length > 2 && com[0] == '-' || com[0] == '/')
                {
                    if (com[1] == 'D')
                    {
                        inout.PrepocessorDefinitions.Add(com.Substring(2, com.Length - 2));
                    }
                    else if (com[1] == 'I')
                    {
                        inout.IncludeDirectories.Add(com.Substring(2, com.Length - 2));
                    }
                    else if (com == "-m32")
                    {
                        inout.Target = ProjectProperties.TargetType.x86;
                    }
                    else if (com == "-m64")
                    {
                        inout.Target = ProjectProperties.TargetType.x64;
                    }
                    else if (com.StartsWith("-std"))
                    {
                        string standard = com.Substring(5, com.Length - 5);
                        if (standard == "c++98")
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Cpp98;
                        }
                        else if (standard == "c++03")
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Cpp03;
                        }
                        else if (standard == "c++14")
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Cpp14;
                        }
                        else if (standard == "c++17")
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Cpp17;
                        }
                        else if (standard == "c++20")
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Cpp20;
                        }
                        else if (standard == "gnu++98")
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Gnu98;
                        }
                        else if (standard == "gnu++03")
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Gnu03;
                        }
                        else if (standard == "gnu++14")
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Gnu14;
                        }
                        else if (standard == "gnu++17")
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Gnu17;
                        }
                        else if (standard == "gnu++20")
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Gnu20;
                        }
                        else
                        {
                            inout.Standard = ProjectProperties.StandardVersion.Latest;
                        }
                    }
                    else if (com.StartsWith("-include"))
                    {
                        inout.IncludeDirectories.Add(com.Substring(8, com.Length - 8));
                    }
                }
            }
        }
Esempio n. 14
0
        public async Task <ParseResult> ParseAsync(ProjectProperties projProperties, DocumentLocation location)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            ParseResult ret = new ParseResult();

            if (location.Filename == null || location.Filename.Length == 0)
            {
                OutputLog.Error("No file provided for parsing");
                ret.Status = ParseResult.StatusCode.InvalidInput;
                return(ret);
            }

            AdjustPaths(projProperties.IncludeDirectories);
            AdjustPaths(projProperties.ForceIncludes);

            string includes = GenerateCommandStr("-I", projProperties.IncludeDirectories);
            string forceInc = GenerateCommandStr("-include", projProperties.ForceIncludes);
            string defines  = GenerateCommandStr("-D", projProperties.PrepocessorDefinitions);
            string workDir  = projProperties.WorkingDirectory.Length == 0 ? "" : " -working-directory=" + AdjustPath(projProperties.WorkingDirectory);
            string flags    = projProperties.ShowWarnings? "" : " -w";
            string extra    = projProperties.ExtraArguments.Length == 0? "" : " " + projProperties.ExtraArguments;

            string standard = GetStandardFlag(projProperties.Standard);
            string archStr  = projProperties != null && projProperties.Target == ProjectProperties.TargetType.x86 ? "-m32" : "-m64";

            string toolCmd = AdjustPath(location.Filename) + " -- -x c++ " + archStr + standard + flags + defines + includes + forceInc + workDir + extra;

            OutputLog.Focus();
            OutputLog.Log("Looking for structures at " + location.Filename + ":" + location.Line + ":" + location.Column + "...");

            if (PrintCommandLine)
            {
                OutputLog.Log("COMMAND LINE: " + toolCmd);
            }

            Log = "";

            var watch = System.Diagnostics.Stopwatch.StartNew();

            var valid = false;

            valid = await System.Threading.Tasks.Task.Run(() => LayoutParser_ParseLocation(toolCmd, location.Filename, location.Line, location.Column));

            watch.Stop();
            const long TicksPerMicrosecond = (TimeSpan.TicksPerMillisecond / 1000);
            string     timeStr             = " (" + GetTimeStr((ulong)(watch.ElapsedTicks / TicksPerMicrosecond)) + ")";

            if (Log.Length > 0)
            {
                OutputLog.Log("Execution Log:\n" + Log);
                ret.ParserLog = Log;
                Log           = "";
            }

            if (valid)
            {
                //capture data
                uint   size   = 0;
                IntPtr result = LayoutParser_GetData(ref size);

                if (size > 0)
                {
                    byte[] managedArray = new byte[size];
                    Marshal.Copy(result, managedArray, 0, (int)size);

                    using (BinaryReader reader = new BinaryReader(new MemoryStream(managedArray)))
                    {
                        ret.Layout = ReadNode(reader);
                        FinalizeNode(ret.Layout);
                    }

                    OutputLog.Log("Found structure " + ret.Layout.Type + "." + timeStr);
                    ret.Status = ParseResult.StatusCode.Found;
                }
                else
                {
                    OutputLog.Log("No structure found at the given location." + timeStr);
                    ret.Status = ParseResult.StatusCode.NotFound;
                }
            }
            else
            {
                OutputLog.Error("Unable to scan the given location." + timeStr);
                ret.Status = ParseResult.StatusCode.ParseFailed;
            }

            LayoutParser_Clear();

            return(ret);
        }
        public override ProjectProperties GetProjectData()
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            OutputLog.Log("Capturing configuration from VS projects...");

            Project project = EditorUtils.GetActiveProject();

            VCProject prj = project.Object as VCProject;

            if (prj == null)
            {
                return(null);
            }

            VCConfiguration config = prj.ActiveConfiguration;

            if (config == null)
            {
                return(null);
            }

            VCPlatform platform = config.Platform;

            if (platform == null)
            {
                return(null);
            }

            var vctools = config.Tools as IVCCollection;

            if (vctools == null)
            {
                return(null);
            }

            var midl = vctools.Item("VCMidlTool") as VCMidlTool;

            var evaluator = new MacroEvaluatorVisualPlatform(platform);

            ProjectProperties ret = new ProjectProperties();

            ret.Target   = midl != null && midl.TargetEnvironment == midlTargetEnvironment.midlTargetWin32 ? ProjectProperties.TargetType.x86 : ProjectProperties.TargetType.x64;
            ret.Standard = GetStandardVersion(config);

            //Working directory (always local to processed file)
            ret.WorkingDirectory = Path.GetDirectoryName(project.FullName);

            //Include dirs / files and preprocessor
            AppendMSBuildStringToList(ret.IncludeDirectories, evaluator.Evaluate(platform.IncludeDirectories));
            AppendProjectProperties(ret, vctools.Item("VCCLCompilerTool") as VCCLCompilerTool, vctools.Item("VCNMakeTool") as VCNMakeTool, evaluator);

            //Get settings from the single file (this might fail badly if there are no settings to catpure)
            var applicationObject = EditorUtils.ServiceProvider.GetService(typeof(DTE)) as EnvDTE80.DTE2;

            Assumes.Present(applicationObject);
            ProjectItem         item       = applicationObject.ActiveDocument.ProjectItem;
            VCFile              vcfile     = item != null ? item.Object as VCFile : null;
            IVCCollection       fileCfgs   = vcfile != null ? (IVCCollection)vcfile.FileConfigurations : null;
            VCFileConfiguration fileConfig = fileCfgs != null?fileCfgs.Item(config.Name) as VCFileConfiguration : null;

            VCCLCompilerTool fileToolCL    = null;
            VCNMakeTool      fileToolNMake = null;

            try
            {
                fileToolCL    = fileConfig.Tool as VCCLCompilerTool;
                fileToolNMake = fileConfig.Tool as VCNMakeTool;
            }
            catch (Exception e)
            {
                //If we really need this data we can always parse the vcxproj as an xml
                OutputLog.Log("File specific properties not found, only project properties used (" + e.Message + ")");
            }

            AppendProjectProperties(ret, fileToolCL, fileToolNMake, evaluator);

            CaptureExtraProperties(ret, evaluator);

            AddCustomSettings(ret, evaluator);

            RemoveMSBuildStringFromList(ret.IncludeDirectories, evaluator.Evaluate(platform.ExcludeDirectories)); //Exclude directories

            ProcessPostProjectData(ret);

            return(ret);
        }