コード例 #1
0
        /// <summary>
        /// Caches the contents of this directory
        /// </summary>
        public void CacheFiles()
        {
            // Check if we need to update the file list
            if (NameToFile == null)
            {
                // Add all the files in this directory
                Dictionary <string, WorkspaceFile> NewNameToFile = new Dictionary <string, WorkspaceFile>(StringComparer.InvariantCultureIgnoreCase);
                foreach (FileInfo FileInfo in Info.EnumerateFiles())
                {
                    WorkspaceFile File = new WorkspaceFile(FileInfo.Name, this);
                    NewNameToFile.Add(FileInfo.Name, File);
                }
                Interlocked.CompareExchange(ref NameToFile, NewNameToFile, null);

                // Update the project directory if we have one. For programs, we treat the directory containing .target.cs files as the project, because they
                // do not overlap with other programs or projects.
                if (NormalizedPathFromBranchRoot != null && ProjectDirectory == null)
                {
                    if (NormalizedPathFromBranchRoot.StartsWith("/engine/"))
                    {
                        if (NormalizedPathFromBranchRoot.StartsWith("/engine/source/programs/") && Files.Any(x => x.NormalizedPathFromBranchRoot.EndsWith(".target.cs")))
                        {
                            ProjectDirectory = this;
                        }
                    }
                    else
                    {
                        if (Files.Any(x => x.NormalizedPathFromBranchRoot.EndsWith(".uproject")))
                        {
                            ProjectDirectory = this;
                        }
                    }
                }
            }
        }
コード例 #2
0
ファイル: Rules.cs プロジェクト: ragnarula/ActionRPGEngine
        /// <summary>
        /// Gets the flags for a new source file
        /// </summary>
        /// <param name="File">The workspace file being read</param>
        /// <returns>Flags for the corresponding source file</returns>
        public static SourceFileFlags GetSourceFileFlags(WorkspaceFile File)
        {
            string NormalizedPath = File.NormalizedPathFromBranchRoot;

            if (NormalizedPath == null || IsExternalHeaderPath(NormalizedPath))
            {
                return(SourceFileFlags.Pinned | SourceFileFlags.External);
            }

            SourceFileFlags Flags = SourceFileFlags.Standalone;

            if (NormalizedPath.EndsWith(".inl") || NormalizedPath.EndsWith(".inc") || NormalizedPath.EndsWith(".generated.h"))
            {
                Flags = (Flags | SourceFileFlags.Pinned) & ~SourceFileFlags.Standalone;
            }
            if (NormalizedPath.IndexOf("/public/") != -1 || NormalizedPath.IndexOf("/classes/") != -1)
            {
                Flags |= SourceFileFlags.Public;
            }
            if (NormalizedPath.IndexOf("/intermediate/") != -1)
            {
                if (NormalizedPath.EndsWith(".generated.h"))
                {
                    Flags |= SourceFileFlags.GeneratedHeader | SourceFileFlags.Inline | SourceFileFlags.Public;
                }
                else if (NormalizedPath.EndsWith("classes.h"))
                {
                    Flags |= SourceFileFlags.GeneratedClassesHeader | SourceFileFlags.Public;
                }
            }
            if (NormalizedPath.EndsWith(".cpp") || NormalizedPath.IndexOf("/windows/") != -1 || NormalizedPath.IndexOf("/linux/") != -1)
            {
                Flags |= SourceFileFlags.Pinned;
            }

            if (NormalizedPath.EndsWith("fwd.h") && !IgnoreFwdHeaders.Contains(NormalizedPath))
            {
                Flags |= SourceFileFlags.FwdHeader;
            }

            if (InlineFileNames.Contains(NormalizedPath))
            {
                Flags = (Flags | SourceFileFlags.Inline) & ~SourceFileFlags.Standalone;
            }
            if (PinnedFileNames.Contains(NormalizedPath))
            {
                Flags = (Flags | SourceFileFlags.Pinned) & ~SourceFileFlags.Standalone;
            }
            if (NotStandaloneFileNames.Contains(NormalizedPath))
            {
                Flags &= ~SourceFileFlags.Standalone;
            }
            if (AggregateFileNames.Contains(NormalizedPath))
            {
                Flags |= SourceFileFlags.Aggregate;
            }
            if (AllowMultipleFragmentFileNames.Contains(NormalizedPath))
            {
                Flags |= SourceFileFlags.AllowMultipleFragments;
            }
            if (ShouldIgnoreExports(NormalizedPath))
            {
                Flags |= SourceFileFlags.IgnoreExportedSymbols;
            }
            return(Flags);
        }
コード例 #3
0
 /// <summary>
 /// Tries to get a file of the given name from this directory
 /// </summary>
 /// <param name="Name">The name to look for</param>
 /// <param name="Result">If successful, receives the file object</param>
 /// <returns>True if the file was found</returns>
 public bool TryGetFile(string Name, out WorkspaceFile Result)
 {
     CacheFiles();
     return(NameToFile.TryGetValue(Name, out Result));
 }
コード例 #4
0
        /// <summary>
        /// Tries to resolve an include path from a file, given a set of candidates
        /// </summary>
        /// <param name="FromFile">The file containing the #include directive</param>
        /// <param name="IncludePath">The path being included</param>
        /// <param name="InitialCandidateFiles">Set of candidate files to pick from</param>
        /// <param name="bIsSystemInclude">Whether the include path is for a system header. If these aren't found, we don't fail.</param>
        /// <param name="IncludedFile">On success, the matching file</param>
        /// <param name="Log">Log instance for output messages</param>
        /// <returns>True if the include path was resolved, false otherwise</returns>
        public static bool ResolveInclude(WorkspaceFile FromFile, string IncludePath, IEnumerable <WorkspaceFile> InitialCandidateFiles, bool bIsSystemInclude, out WorkspaceFile IncludedFile, TextWriter Log)
        {
            List <WorkspaceFile> CandidateFiles = new List <WorkspaceFile>(InitialCandidateFiles);

            // Check if it's a direct file reference
            WorkspaceFile DirectlyReferencedFile = CandidateFiles.FirstOrDefault(x => x.Location == FileReference.Combine(FromFile.Location.Directory, IncludePath));

            if (DirectlyReferencedFile != null)
            {
                IncludedFile = DirectlyReferencedFile;
                return(true);
            }

            // Apply any of the ignore patterns
            for (int Idx = 0; Idx < IgnoreIncludePatterns.GetLength(0); Idx++)
            {
                if (FromFile.NormalizedPathFromBranchRoot.StartsWith(IgnoreIncludePatterns[Idx, 0]))
                {
                    CandidateFiles.RemoveAll(x => x.NormalizedPathFromBranchRoot.Contains(IgnoreIncludePatterns[Idx, 1]));
                }
            }

            // Remove any candidate files that don't have the same suffix as the include path
            string IncludeSuffix = IncludePath.ToLowerInvariant().Replace('\\', '/');

            while (IncludeSuffix.StartsWith("../"))
            {
                IncludeSuffix = IncludeSuffix.Substring(3);
            }
            CandidateFiles.RemoveAll(x => !x.NormalizedPathFromBranchRoot.EndsWith(IncludeSuffix));

            // Remove any files from a different project. We do occasionally cross this boundary via explicitly referenced paths, so skip if there's already only one match.
            if (CandidateFiles.Count > 1)
            {
                if (FromFile.ProjectDirectory == null)
                {
                    CandidateFiles.RemoveAll(x => x.ProjectDirectory != null);
                }
                else
                {
                    CandidateFiles.RemoveAll(x => x.ProjectDirectory != FromFile.ProjectDirectory && x.ProjectDirectory != null);
                }
            }

            // If we're including Engine.h and haven't explicitly referenced the UEngine header, assume it's referencing the header for the engine module
            if (CandidateFiles.Count > 2 && IncludeSuffix == "engine.h")
            {
                if (CandidateFiles.Any(x => x.NormalizedPathFromBranchRoot == "/engine/source/runtime/engine/public/engine.h"))
                {
                    CandidateFiles.RemoveAll(x => x.NormalizedPathFromBranchRoot == "/engine/source/runtime/engine/classes/engine/engine.h");
                }
            }

            // Use case to disambiguate if we still have mismatches. This actually weeds out quite a lot of false positives, expecially with TPS
            // (the typical pattern is that Epic code uses TitleCase but OSS uses all lowercase).
            if (CandidateFiles.Count > 1)
            {
                List <WorkspaceFile> ExactCaseMatches = CandidateFiles.Where(x => x.Location.FullName.EndsWith(IncludePath.Replace('/', Path.DirectorySeparatorChar))).ToList();
                if (ExactCaseMatches.Count == 1)
                {
                    CandidateFiles.Clear();
                    CandidateFiles.AddRange(ExactCaseMatches);
                }
            }

            // Use case to disambiguate if we still have mismatches. This actually weeds out quite a lot of false positives, expecially with TPS
            // (the typical pattern is that Epic code uses TitleCase but OSS uses all lowercase).
            if (CandidateFiles.Count > 1)
            {
                List <WorkspaceFile> NonThirdPartyCandidates = CandidateFiles.Where(x => !x.NormalizedPathFromBranchRoot.Contains("/thirdparty/")).ToList();
                if (NonThirdPartyCandidates.Count == 1)
                {
                    CandidateFiles.Clear();
                    CandidateFiles.AddRange(NonThirdPartyCandidates);
                }
            }

            // Check if we've got an exact match
            if (CandidateFiles.Count == 1)
            {
                IncludedFile = CandidateFiles[0];
                return(true);
            }

            // If it's a system header, it's ok if we didn't resolve it
            if (CandidateFiles.Count == 0 && bIsSystemInclude)
            {
                IncludedFile = null;
                return(true);
            }

            // If they're all third party files, just treat it as an external include
            if (CandidateFiles.Count > 1 && CandidateFiles.All(x => x.NormalizedPathFromBranchRoot.Contains("/thirdparty/")))
            {
                IncludedFile = null;
                return(true);
            }

            // Allow generated headers to be excluded for now
            if (IncludePath.EndsWith("Classes.h") || IncludePath.EndsWith(".generated.h"))
            {
                IncludedFile = null;
                return(true);
            }

            // Otherwise print the remaining candidates
            Log.WriteLine("Failed to resolve include of \"{0}\" from \"{1}\". {2} candidate files.", IncludePath, FromFile.Location, CandidateFiles.Count);
            foreach (WorkspaceFile FinalCandidateFile in CandidateFiles)
            {
                Log.WriteLine("  Could be: {0}", FinalCandidateFile.Location);
            }
            Log.WriteLine();

            // ...and fail
            IncludedFile = null;
            return(false);
        }