aboutsummaryrefslogtreecommitdiff
path: root/node_modules/ts-loader/dist/after-compile.js
blob: 7c8cb7ef834fb5ca2b3aadd773c75412e747965c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"use strict";
var path = require("path");
var utils = require("./utils");
var constants = require("./constants");
function makeAfterCompile(instance, configFilePath) {
    var getCompilerOptionDiagnostics = true;
    var checkAllFilesForErrors = true;
    return function (compilation, callback) {
        // Don't add errors for child compilations
        if (compilation.compiler.isChild()) {
            callback();
            return;
        }
        removeTSLoaderErrors(compilation.errors);
        provideCompilerOptionDiagnosticErrorsToWebpack(getCompilerOptionDiagnostics, compilation, instance, configFilePath);
        getCompilerOptionDiagnostics = false;
        var modules = determineModules(compilation);
        var filesToCheckForErrors = determineFilesToCheckForErrors(checkAllFilesForErrors, instance);
        checkAllFilesForErrors = false;
        var filesWithErrors = {};
        provideErrorsToWebpack(filesToCheckForErrors, filesWithErrors, compilation, modules, instance);
        provideDeclarationFilesToWebpack(filesToCheckForErrors, instance.languageService, compilation);
        instance.filesWithErrors = filesWithErrors;
        instance.modifiedFiles = null;
        callback();
    };
}
/**
 * handle compiler option errors after the first compile
 */
function provideCompilerOptionDiagnosticErrorsToWebpack(getCompilerOptionDiagnostics, compilation, instance, configFilePath) {
    if (getCompilerOptionDiagnostics) {
        var languageService = instance.languageService, loaderOptions = instance.loaderOptions, compiler = instance.compiler;
        utils.registerWebpackErrors(compilation.errors, utils.formatErrors(languageService.getCompilerOptionsDiagnostics(), loaderOptions, compiler, { file: configFilePath || 'tsconfig.json' }));
    }
}
/**
 * build map of all modules based on normalized filename
 * this is used for quick-lookup when trying to find modules
 * based on filepath
 */
function determineModules(compilation) {
    var modules = {};
    compilation.modules.forEach(function (module) {
        if (module.resource) {
            var modulePath = path.normalize(module.resource);
            if (utils.hasOwnProperty(modules, modulePath)) {
                var existingModules = modules[modulePath];
                if (existingModules.indexOf(module) === -1) {
                    existingModules.push(module);
                }
            }
            else {
                modules[modulePath] = [module];
            }
        }
    });
    return modules;
}
function determineFilesToCheckForErrors(checkAllFilesForErrors, instance) {
    var files = instance.files, modifiedFiles = instance.modifiedFiles, filesWithErrors = instance.filesWithErrors;
    // calculate array of files to check
    var filesToCheckForErrors = {};
    if (checkAllFilesForErrors) {
        // check all files on initial run
        filesToCheckForErrors = files;
    }
    else if (modifiedFiles) {
        // check all modified files, and all dependants
        Object.keys(modifiedFiles).forEach(function (modifiedFileName) {
            utils.collectAllDependants(instance.reverseDependencyGraph, modifiedFileName)
                .forEach(function (fileName) {
                filesToCheckForErrors[fileName] = files[fileName];
            });
        });
    }
    // re-check files with errors from previous build
    if (filesWithErrors) {
        Object.keys(filesWithErrors).forEach(function (fileWithErrorName) {
            return filesToCheckForErrors[fileWithErrorName] = filesWithErrors[fileWithErrorName];
        });
    }
    return filesToCheckForErrors;
}
function provideErrorsToWebpack(filesToCheckForErrors, filesWithErrors, compilation, modules, instance) {
    var compiler = instance.compiler, languageService = instance.languageService, files = instance.files, loaderOptions = instance.loaderOptions;
    Object.keys(filesToCheckForErrors)
        .filter(function (filePath) { return !!filePath.match(constants.dtsTsTsxRegex); })
        .forEach(function (filePath) {
        var errors = languageService.getSyntacticDiagnostics(filePath).concat(languageService.getSemanticDiagnostics(filePath));
        if (errors.length > 0) {
            filesWithErrors[filePath] = files[filePath];
        }
        // if we have access to a webpack module, use that
        if (utils.hasOwnProperty(modules, filePath)) {
            var associatedModules = modules[filePath];
            associatedModules.forEach(function (module) {
                // remove any existing errors
                removeTSLoaderErrors(module.errors);
                // append errors
                var formattedErrors = utils.formatErrors(errors, loaderOptions, compiler, { module: module });
                utils.registerWebpackErrors(module.errors, formattedErrors);
                utils.registerWebpackErrors(compilation.errors, formattedErrors);
            });
        }
        else {
            // otherwise it's a more generic error
            utils.registerWebpackErrors(compilation.errors, utils.formatErrors(errors, loaderOptions, compiler, { file: filePath }));
        }
    });
}
/**
 * gather all declaration files from TypeScript and output them to webpack
 */
function provideDeclarationFilesToWebpack(filesToCheckForErrors, languageService, compilation) {
    Object.keys(filesToCheckForErrors)
        .filter(function (filePath) { return !!filePath.match(constants.tsTsxRegex); })
        .forEach(function (filePath) {
        var output = languageService.getEmitOutput(filePath);
        var declarationFile = output.outputFiles.filter(function (outputFile) { return !!outputFile.name.match(constants.dtsDtsxRegex); }).pop();
        if (declarationFile) {
            var assetPath = path.relative(compilation.compiler.context, declarationFile.name);
            compilation.assets[assetPath] = {
                source: function () { return declarationFile.text; },
                size: function () { return declarationFile.text.length; },
            };
        }
    });
}
/**
 * handle all other errors. The basic approach here to get accurate error
 * reporting is to start with a "blank slate" each compilation and gather
 * all errors from all files. Since webpack tracks errors in a module from
 * compilation-to-compilation, and since not every module always runs through
 * the loader, we need to detect and remove any pre-existing errors.
 */
function removeTSLoaderErrors(errors) {
    var index = -1;
    var length = errors.length;
    while (++index < length) {
        if (errors[index].loaderSource === 'ts-loader') {
            errors.splice(index--, 1);
            length--;
        }
    }
}
module.exports = makeAfterCompile;