<commit_before>/// <reference path="sys.ts" />
/// <reference path="emitter.ts" />

module ts {
    export function createCompilerHost(options: CompilerOptions): CompilerHost {
        var currentDirectory: string;
        var existingDirectories: Map<boolean> = {};

        function getCanonicalFileName(fileName: string): string {
            // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
            // otherwise use toLowerCase as a canonical form.
            return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
        }
        
        // returned by CScript sys environment
        var unsupportedFileEncodingErrorCode = -2147024809;

        function getSourceFile(filename: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
            try {
                var text = sys.readFile(filename, options.charset);
            }
            catch (e) {
                if (onError) {
                    onError(e.number === unsupportedFileEncodingErrorCode ?
                        createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText :
                        e.message);
                }
                text = "";
            }

            return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined;
        }

        function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
            function directoryExists(directoryPath: string): boolean {
                if (hasProperty(existingDirectories, directoryPath)) {
                    return true;
                }
                if (sys.directoryExists(directoryPath)) {
                    existingDirectories[directoryPath] = true;
                    return true;
                }
                return false;
            }

            function ensureDirectoriesExist(directoryPath: string) {
                if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
                    var parentDirectory = getDirectoryPath(directoryPath);
                    ensureDirectoriesExist(parentDirectory);
                    sys.createDirectory(directoryPath);
                }
            }

            try {
                ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
                sys.writeFile(fileName, data, writeByteOrderMark);
            }
            catch (e) {
                if (onError) {
                    onError(e.message);
                }
            }
        }

        return {
            getSourceFile,
            getDefaultLibFilename: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFilename(options)),
            writeFile,
            getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()),
            useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
            getCanonicalFileName,
            getNewLine: () => sys.newLine
        };
    }

    export function createProgram(rootNames: string[], options: CompilerOptions, host: CompilerHost): Program {
        var program: Program;
        var files: SourceFile[] = [];
        var filesByName: Map<SourceFile> = {};
        var errors: Diagnostic[] = [];
        var seenNoDefaultLib = options.noLib;
        var commonSourceDirectory: string;

        forEach(rootNames, name => processRootFile(name, false));
        if (!seenNoDefaultLib) {
            processRootFile(host.getDefaultLibFilename(options), true);
        }
        verifyCompilerOptions();
        errors.sort(compareDiagnostics);


        var diagnosticsProducingTypeChecker: TypeChecker;
        var noDiagnosticsTypeChecker: TypeChecker;
        var emitHost: EmitHost;

        program = {
            getSourceFile: getSourceFile,
            getSourceFiles: () => files,
            getCompilerOptions: () => options,
            getCompilerHost: () => host,
            getDiagnostics: getDiagnostics,
            getGlobalDiagnostics: getGlobalDiagnostics,
            getDeclarationDiagnostics: getDeclarationDiagnostics,
            getTypeChecker,
            getCommonSourceDirectory: () => commonSourceDirectory,
            emitFiles: invokeEmitter,
            isEmitBlocked,
            getCurrentDirectory: host.getCurrentDirectory,
        };
        return program;

        function getEmitHost() {
            return emitHost || (emitHost = createEmitHostFromProgram(program));
        }

        function hasEarlyErrors(sourceFile?: SourceFile): boolean {
            return forEach(getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile), d => d.isEarly);
        }

        function isEmitBlocked(sourceFile?: SourceFile): boolean {
            return getDiagnostics(sourceFile).length !== 0 ||
                hasEarlyErrors(sourceFile) ||
                (options.noEmitOnError && getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile).length !== 0);
        }

        function getDiagnosticsProducingTypeChecker() {
            return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true));
        }

        function getTypeChecker(produceDiagnostics: boolean) {
            if (produceDiagnostics) {
                return getDiagnosticsProducingTypeChecker();
            }
            else {
                return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, produceDiagnostics));
            }
        }

        function getDeclarationDiagnostics(targetSourceFile: SourceFile): Diagnostic[]{
            var typeChecker = getDiagnosticsProducingTypeChecker();
            typeChecker.getDiagnostics(targetSourceFile);
            var resolver = typeChecker.getEmitResolver();
            return ts.getDeclarationDiagnostics(getEmitHost(), resolver, targetSourceFile);
        }

        function invokeEmitter(targetSourceFile?: SourceFile) {
            var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver();
            return emitFiles(resolver, getEmitHost(), targetSourceFile);
        }
        
        function getSourceFile(filename: string) {
            filename = host.getCanonicalFileName(filename);
            return hasProperty(filesByName, filename) ? filesByName[filename] : undefined;
        }

        function getDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
            return sourceFile ? filter(errors, e => e.file === sourceFile) : errors;
        }

        function getGlobalDiagnostics(): Diagnostic[] {
            return filter(errors, e => !e.file);
        }

        function hasExtension(filename: string): boolean {
            return getBaseFilename(filename).indexOf(".") >= 0;
        }

        function processRootFile(filename: string, isDefaultLib: boolean) {
            processSourceFile(normalizePath(filename), isDefaultLib);
        }

        function processSourceFile(filename: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) {
            if (refEnd !== undefined && refPos !== undefined) {
                var start = refPos;
                var length = refEnd - refPos;
            }
            var diagnostic: DiagnosticMessage;
            if (hasExtension(filename)) {
                if (!options.allowNonTsExtensions && !fileExtensionIs(filename, ".ts")) {
                    diagnostic = Diagnostics.File_0_must_have_extension_ts_or_d_ts;
                }<commit_msg>Fix #1871 by ensuring the at we get the canonical filename before we check the extension<commit_after>/// <reference path="sys.ts" />
/// <reference path="emitter.ts" />

module ts {
    export function createCompilerHost(options: CompilerOptions): CompilerHost {
        var currentDirectory: string;
        var existingDirectories: Map<boolean> = {};

        function getCanonicalFileName(fileName: string): string {
            // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
            // otherwise use toLowerCase as a canonical form.
            return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
        }
        
        // returned by CScript sys environment
        var unsupportedFileEncodingErrorCode = -2147024809;

        function getSourceFile(filename: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
            try {
                var text = sys.readFile(filename, options.charset);
            }
            catch (e) {
                if (onError) {
                    onError(e.number === unsupportedFileEncodingErrorCode ?
                        createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText :
                        e.message);
                }
                text = "";
            }

            return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined;
        }

        function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
            function directoryExists(directoryPath: string): boolean {
                if (hasProperty(existingDirectories, directoryPath)) {
                    return true;
                }
                if (sys.directoryExists(directoryPath)) {
                    existingDirectories[directoryPath] = true;
                    return true;
                }
                return false;
            }

            function ensureDirectoriesExist(directoryPath: string) {
                if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
                    var parentDirectory = getDirectoryPath(directoryPath);
                    ensureDirectoriesExist(parentDirectory);
                    sys.createDirectory(directoryPath);
                }
            }

            try {
                ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
                sys.writeFile(fileName, data, writeByteOrderMark);
            }
            catch (e) {
                if (onError) {
                    onError(e.message);
                }
            }
        }

        return {
            getSourceFile,
            getDefaultLibFilename: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFilename(options)),
            writeFile,
            getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()),
            useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
            getCanonicalFileName,
            getNewLine: () => sys.newLine
        };
    }

    export function createProgram(rootNames: string[], options: CompilerOptions, host: CompilerHost): Program {
        var program: Program;
        var files: SourceFile[] = [];
        var filesByName: Map<SourceFile> = {};
        var errors: Diagnostic[] = [];
        var seenNoDefaultLib = options.noLib;
        var commonSourceDirectory: string;

        forEach(rootNames, name => processRootFile(name, false));
        if (!seenNoDefaultLib) {
            processRootFile(host.getDefaultLibFilename(options), true);
        }
        verifyCompilerOptions();
        errors.sort(compareDiagnostics);


        var diagnosticsProducingTypeChecker: TypeChecker;
        var noDiagnosticsTypeChecker: TypeChecker;
        var emitHost: EmitHost;

        program = {
            getSourceFile: getSourceFile,
            getSourceFiles: () => files,
            getCompilerOptions: () => options,
            getCompilerHost: () => host,
            getDiagnostics: getDiagnostics,
            getGlobalDiagnostics: getGlobalDiagnostics,
            getDeclarationDiagnostics: getDeclarationDiagnostics,
            getTypeChecker,
            getCommonSourceDirectory: () => commonSourceDirectory,
            emitFiles: invokeEmitter,
            isEmitBlocked,
            getCurrentDirectory: host.getCurrentDirectory,
        };
        return program;

        function getEmitHost() {
            return emitHost || (emitHost = createEmitHostFromProgram(program));
        }

        function hasEarlyErrors(sourceFile?: SourceFile): boolean {
            return forEach(getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile), d => d.isEarly);
        }

        function isEmitBlocked(sourceFile?: SourceFile): boolean {
            return getDiagnostics(sourceFile).length !== 0 ||
                hasEarlyErrors(sourceFile) ||
                (options.noEmitOnError && getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile).length !== 0);
        }

        function getDiagnosticsProducingTypeChecker() {
            return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true));
        }

        function getTypeChecker(produceDiagnostics: boolean) {
            if (produceDiagnostics) {
                return getDiagnosticsProducingTypeChecker();
            }
            else {
                return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, produceDiagnostics));
            }
        }

        function getDeclarationDiagnostics(targetSourceFile: SourceFile): Diagnostic[]{
            var typeChecker = getDiagnosticsProducingTypeChecker();
            typeChecker.getDiagnostics(targetSourceFile);
            var resolver = typeChecker.getEmitResolver();
            return ts.getDeclarationDiagnostics(getEmitHost(), resolver, targetSourceFile);
        }

        function invokeEmitter(targetSourceFile?: SourceFile) {
            var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver();
            return emitFiles(resolver, getEmitHost(), targetSourceFile);
        }
        
        function getSourceFile(filename: string) {
            filename = host.getCanonicalFileName(filename);
            return hasProperty(filesByName, filename) ? filesByName[filename] : undefined;
        }

        function getDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
            return sourceFile ? filter(errors, e => e.file === sourceFile) : errors;
        }

        function getGlobalDiagnostics(): Diagnostic[] {
            return filter(errors, e => !e.file);
        }

        function hasExtension(filename: string): boolean {
            return getBaseFilename(filename).indexOf(".") >= 0;
        }

        function processRootFile(filename: string, isDefaultLib: boolean) {
            processSourceFile(normalizePath(filename), isDefaultLib);
        }

        function processSourceFile(filename: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) {
            if (refEnd !== undefined && refPos !== undefined) {
                var start = refPos;
                var length = refEnd - refPos;
            }
            var diagnostic: DiagnosticMessage;
            if (hasExtension(filename)) {
                if (!options.allowNonTsExtensions && !fileExtensionIs(host.getCanonicalFileName(filename), ".ts")) {
                    diagnostic = Diagnostics.File_0_must_have_extension_ts_or_d_ts;
                }
{'fraction_non_alphanumeric': 0.08847736625514403, 'fraction_numerical': 0.00205761316872428, 'mean_word_length': 2.235489910547119, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1038288', 'n_tokens_mistral': 3607, 'n_tokens_neox': 3615, 'n_words': 769}