private getClangPath()

in Extension/src/LanguageServer/settings.ts [111:163]


    private getClangPath(isFormat: boolean): string | undefined {
        let path: string | undefined | null = super.Section.get<string>(isFormat ? "clang_format_path" : "codeAnalysis.clangTidy.path");
        if (!path) {
            const cachedClangPath: string | null | undefined = isFormat ? getCachedClangFormatPath() : getCachedClangTidyPath();
            if (cachedClangPath !== undefined) {
                if (cachedClangPath === null) {
                    return undefined;
                }
                return cachedClangPath;
            }
            const clangStr: string = isFormat ? this.clangFormatStr : this.clangTidyStr;
            const clangName: string = isFormat ? this.clangFormatName : this.clangTidyName;
            const setCachedClangPath: (path: string | null) => void = isFormat ? setCachedClangFormatPath : setCachedClangTidyPath;
            path = which.sync(clangName, { nothrow: true });
            setCachedClangPath(path);
            if (!path) {
                return undefined;
            } else {
                // Attempt to invoke both our own version of clang-* to see if we can successfully execute it, and to get its version.
                let clangVersion: string;
                try {
                    const exePath: string = getExtensionFilePath(`./LLVM/bin/${clangName}`);
                    const output: string[] = execSync(`${exePath} --version`).toString().split(" ");
                    if (output.length < 3 || output[0] !== clangStr || output[1] !== "version" || !semver.valid(output[2])) {
                        if (output.length === 3) {
                            return path;
                        }
                        const versionIndex: number = output.findIndex((value: string) => value === "version");
                        if (versionIndex < 0 || versionIndex + 1 >= output.length || !semver.valid(output[versionIndex + 1].trim())) {
                            return path;
                        }
                    }
                    clangVersion = output[2];
                } catch (e) {
                    // Unable to invoke our own clang-*.  Use the system installed clang-*.
                    return path;
                }

                // Invoke the version on the system to compare versions.  Use ours if it's more recent.
                try {
                    const output: string[] = execSync(`"${path}" --version`).toString().split(" ");
                    if (output.length < 3 || output[0] !== clangStr || output[1] !== "version" || semver.ltr(output[2], clangVersion)) {
                        path = "";
                        setCachedClangPath(path);
                    }
                } catch (e) {
                    path = "";
                    setCachedClangPath(path);
                }
            }
        }
        return path;
    }