public CppInclusionContextResult CreateInclusionContextResult(CppGlobalSymbolCache cache,
                                                                      CppFileLocation rootFile,
                                                                      FileProcessingOptions options, long cacheVersion, Lifetime lifetime)
        {
            var locationTracker = cache.Solution.GetComponent <InjectedHlslFileLocationTracker>();

            if (!locationTracker.IsValid(rootFile))
            {
                return(CppInclusionContextResult.Fail(CppInclusionContextResult.Status.UNSUITABLE_PROJECT_FILE));
            }


            var properties = new CppCompilationProperties()
            {
                LanguageKind = CppLanguageKind.HLSL, ClrSupport = VCXCompileAsManagedOptions.ManagedNotSet,
            };

            var cgIncludeFolder =
                CgIncludeDirectoryTracker.GetCgIncludeFolderPath(cache.Solution.GetComponent <UnityVersion>());

            if (!cgIncludeFolder.IsEmpty)
            {
                properties.IncludePaths.Add(cgIncludeFolder);
            }
            properties.IncludePaths.Add(cache.Solution.SolutionDirectory);

            return(CreateInclusionContextResult(cache, rootFile, options, properties, null, cacheVersion, lifetime));
        }
        public CppInclusionContextResult CreateInclusionContextResult(CppGlobalSymbolCache cache,
                                                                      CppFileLocation rootFile,
                                                                      FileProcessingOptions options, long cacheVersion, Lifetime lifetime)
        {
            var locationTracker = cache.Solution.GetComponent <InjectedHlslFileLocationTracker>();

            if (!locationTracker.IsValid(rootFile))
            {
                return(CppInclusionContextResult.Fail(CppInclusionContextResult.Status.UNSUITABLE_PROJECT_FILE));
            }


            var properties = new CppCompilationProperties()
            {
                LanguageKind = CppLanguageKind.HLSL, ClrSupport = VCXCompileAsManagedOptions.ManagedNotSet,
            };

            var cgIncludeFolder =
                CgIncludeDirectoryTracker.GetCgIncludeFolderPath(cache.Solution.GetComponent <UnityVersion>());

            if (!cgIncludeFolder.IsEmpty)
            {
                properties.IncludePaths.Add(cgIncludeFolder);
            }
            properties.IncludePaths.Add(cache.Solution.SolutionDirectory);

            var shaderCache = cache.Solution.GetComponent <InjectedHlslFileLocationTracker>();

            // TODO 1) is cache ready? what will happen under document transaction? check for bad moment?
            // TODO 2) what will happen under psi transaction? include in cache could be out-of date. Try use include quickfix when cginclude is after cgprogram where QF is used
            var includeLocation = shaderCache.GetIncludes(rootFile);

            return(CreateInclusionContextResult(cache, rootFile,
                                                includeLocation, options, properties, null, cacheVersion, lifetime));
        }
        public CppCompilationProperties GetCompilationProperties(IProject project, IProjectFile projectFile, CppFileLocation rootFile,
                                                                 CppGlobalSymbolCache globalCache)
        {
            if (project.IsUnityProject() && CppProjectFileType.ALL_HLSL_EXTENSIONS.Contains(rootFile.Location.ExtensionWithDot))
            {
                var properties = new CppCompilationProperties();
                properties.LanguageKind = CppLanguageKind.HLSL;
                var path = CgIncludeDirectoryTracker.GetCgIncludeFolderPath(myUnityVersion);
                if (!path.IsEmpty)
                {
                    properties.IncludePaths.Add(path);
                }

                properties.ForcedIncludes.Add(globalCache.Solution.SolutionDirectory.Combine(Utils.ShaderConfigFile).FullPath);

                properties.PredefinedMacros.Add(CppPPDefineSymbol.ParsePredefinedMacro("SHADER_API_D3D11"));
                properties.IncludePaths.Add(globalCache.Solution.SolutionDirectory);

                return(properties);
            }

            return(null);
        }
        private IEnumerable <CppFileLocation> GetIncludes(IPsiSourceFile sourceFile, InjectedHlslProgramType type, bool isSurface)
        {
            var includeType = GetIncludeProgramType(type);

            var includeList = new List <CppFileLocation>();

            includeList.Add(new CppFileLocation(myCppExternalModule, mySolution.SolutionDirectory.Combine(Utils.ShaderConfigFile)));

            if (includeType != InjectedHlslProgramType.Uknown)
            {
                var includes = GetIncludesLocation(sourceFile, includeType);
                foreach (var include in includes)
                {
                    includeList.Add(include);
                }
            }

            var cgIncludeFolder = CgIncludeDirectoryTracker.GetCgIncludeFolderPath(myUnityVersion);

            if (cgIncludeFolder.ExistsDirectory)
            {
                if (type == InjectedHlslProgramType.CGProgram)
                {
                    var hlslSupport = cgIncludeFolder.Combine("HLSLSupport.cginc");
                    if (hlslSupport.ExistsFile)
                    {
                        includeList.Add(new CppFileLocation(myCppExternalModule, hlslSupport));
                    }

                    var variables = cgIncludeFolder.Combine("UnityShaderVariables.cginc");
                    if (variables.ExistsFile)
                    {
                        includeList.Add(new CppFileLocation(myCppExternalModule, variables));
                    }


                    // from surface shader generated code
                    if (isSurface)
                    {
                        var unityCG = cgIncludeFolder.Combine("UnityCG.cginc");
                        if (unityCG.ExistsFile)
                        {
                            includeList.Add(new CppFileLocation(myCppExternalModule, unityCG));
                        }

                        var lighting = cgIncludeFolder.Combine("Lighting.cginc");
                        if (lighting.ExistsFile)
                        {
                            includeList.Add(new CppFileLocation(myCppExternalModule, lighting));
                        }

                        var unityPbsLighting = cgIncludeFolder.Combine("UnityPBSLighting.cginc");
                        if (unityPbsLighting.ExistsFile)
                        {
                            includeList.Add(new CppFileLocation(myCppExternalModule, unityPbsLighting));
                        }

                        var autoLight = cgIncludeFolder.Combine("AutoLight.cginc");
                        if (autoLight.ExistsFile)
                        {
                            includeList.Add(new CppFileLocation(myCppExternalModule, autoLight));
                        }
                    }
                }
            }

            return(includeList);
        }
        public IEnumerable <CppFileLocation> GetIncludes(CppFileLocation cppFileLocation)
        {
            // PSI is not commited here
            // TODO: cpp global cache should calculate cache only when PSI for file with cpp injects is committed.

            var sourceFile = cppFileLocation.GetRandomSourceFile(mySolution);
            var range      = cppFileLocation.RootRange;

            Assertion.Assert(range.IsValid, "range.IsValid");

            var buffer      = sourceFile.Document.Buffer;
            var type        = GetShaderProgramType(buffer, range.StartOffset);
            var includeType = GetIncludeProgramType(type);

            yield return(new CppFileLocation(myCppExternalModule, mySolution.SolutionDirectory.Combine(Utils.ShaderConfigFile)));

            if (includeType != InjectedHlslProgramType.Uknown)
            {
                var includes = GetIncludesLocation(sourceFile, includeType);
                foreach (var include in includes)
                {
                    yield return(include);
                }
            }


            var cgIncludeFolder = CgIncludeDirectoryTracker.GetCgIncludeFolderPath(myUnityVersion);

            if (!cgIncludeFolder.ExistsDirectory)
            {
                yield break;
            }

            if (type == InjectedHlslProgramType.CGProgram)
            {
                var hlslSupport = cgIncludeFolder.Combine("HLSLSupport.cginc");
                if (hlslSupport.ExistsFile)
                {
                    yield return(new CppFileLocation(myCppExternalModule, hlslSupport));
                }

                var variables = cgIncludeFolder.Combine("UnityShaderVariables.cginc");
                if (variables.ExistsFile)
                {
                    yield return(new CppFileLocation(myCppExternalModule, variables));
                }
            }

            var lexer = CppLexer.Create(ProjectedBuffer.Create(buffer, range));

            lexer.Start();
            while (lexer.TokenType != null)
            {
                var tokenType = lexer.TokenType;
                if (tokenType is CppDirectiveTokenNodeType)
                {
                    lexer.Advance();
                    var context = lexer.GetTokenText().TrimStart();
                    if (context.StartsWith("surface"))
                    {
                        var unityCG = cgIncludeFolder.Combine("UnityCG.cginc");
                        if (unityCG.ExistsFile)
                        {
                            yield return(new CppFileLocation(myCppExternalModule, unityCG));
                        }

                        var lighting = cgIncludeFolder.Combine("Lighting.cginc");
                        if (lighting.ExistsFile)
                        {
                            yield return(new CppFileLocation(myCppExternalModule, lighting));
                        }

                        var unityPbsLighting = cgIncludeFolder.Combine("UnityPBSLighting.cginc");
                        if (unityPbsLighting.ExistsFile)
                        {
                            yield return(new CppFileLocation(myCppExternalModule, unityPbsLighting));
                        }

                        var autoLight = cgIncludeFolder.Combine("AutoLight.cginc");
                        if (autoLight.ExistsFile)
                        {
                            yield return(new CppFileLocation(myCppExternalModule, autoLight));
                        }
                        break;
                    }
                    // TODO: optimization if we found vertex/fragment/geometry/hull/domain?
                }
                lexer.Advance();
            }
        }