Skip to content

Commit b5b4142

Browse files
committed
Refactored to use canonical file names
1 parent d6ea883 commit b5b4142

File tree

2 files changed

+98
-74
lines changed

2 files changed

+98
-74
lines changed

lib/Host.js

Lines changed: 81 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ var path = require('path');
99
var util = require('util');
1010

1111
module.exports = function (ts) {
12-
function Host(currentDirectory, languageVersion) {
13-
this.currentDirectory = currentDirectory;
12+
function replaceFileExtension(file, extension) {
13+
return file.replace(/\.\w+$/i, extension);
14+
}
15+
16+
function Host(currentDirectory, outputDirectory, languageVersion) {
17+
this.currentDirectory = this.getCanonicalFileName(path.resolve(currentDirectory));
18+
this.outputDirectory = this.getCanonicalFileName(path.resolve(outputDirectory));
1419
this.languageVersion = languageVersion;
1520
this.files = {};
1621
this.previousFiles = {};
@@ -31,13 +36,21 @@ module.exports = function (ts) {
3136
log('Resetting (version %d)', this.version);
3237
};
3338

34-
Host.prototype._normalizedRelative = function(filename) {
35-
return ts.normalizePath(path.relative(this.currentDirectory, path.resolve(filename)));
36-
};
37-
3839
Host.prototype._addFile = function (filename, root) {
39-
var normalized = this._normalizedRelative(filename);
40-
log('Parsing %s (norm: %s)', filename, normalized);
40+
41+
// Ensure that the relative, non-canonical file name is what's passed
42+
// to 'createSourceFile', as that's the name that will be used in error
43+
// messages, etc.
44+
45+
var relative = ts.normalizeSlashes(path.relative(
46+
this.currentDirectory,
47+
path.resolve(
48+
this.currentDirectory,
49+
filename
50+
)
51+
));
52+
var canonical = this._currentCanonical(filename);
53+
log('Parsing %s', canonical);
4154

4255
var text;
4356
try {
@@ -47,52 +60,44 @@ module.exports = function (ts) {
4760
}
4861

4962
var file;
50-
var current = this.files[normalized];
51-
var previous = this.previousFiles[normalized];
63+
var current = this.files[canonical];
64+
var previous = this.previousFiles[canonical];
5265
var version;
5366

5467
if (current && current.contents === text) {
5568
file = current.ts;
5669
version = current.version;
57-
log('Reused current file %s (version %d)', normalized, version);
70+
log('Reused current file %s (version %d)', canonical, version);
5871
} else if (previous && previous.contents === text) {
5972
file = previous.ts;
6073
version = previous.version;
61-
log('Reused previous file %s (version %d)', normalized, version);
74+
log('Reused previous file %s (version %d)', canonical, version);
6275
} else {
63-
file = ts.createSourceFile(filename, text, this.languageVersion, true);
76+
file = ts.createSourceFile(relative, text, this.languageVersion, true);
6477
version = this.version;
65-
log('New version of source file %s (version %d)', normalized, version);
78+
log('New version of source file %s (version %d)', canonical, version);
6679
}
6780

68-
this.files[normalized] = {
69-
filename: filename,
81+
this.files[canonical] = {
82+
filename: relative,
7083
contents: text,
7184
ts: file,
7285
root: root,
7386
version: version
7487
};
75-
76-
this._emitFile(normalized);
88+
this.emit('file', canonical, relative);
7789

7890
return file;
7991
};
8092

81-
Host.prototype._emitFile = function (normalized) {
82-
var idPath = './' + normalized;
83-
var fullPath = path.resolve(idPath);
84-
this.emit('file', fullPath, idPath);
85-
}
86-
8793
Host.prototype.getSourceFile = function (filename) {
88-
var normalized = this._normalizedRelative(filename);
89-
90-
if (this.files[normalized])
91-
return this.files[normalized].ts;
92-
93-
if (normalized === '__lib.d.ts')
94+
if (filename === '__lib.d.ts') {
9495
return this.libDefault;
95-
96+
}
97+
var canonical = this._currentCanonical(filename);
98+
if (this.files[canonical]) {
99+
return this.files[canonical].ts;
100+
}
96101
return this._addFile(filename, false);
97102
};
98103

@@ -103,9 +108,9 @@ module.exports = function (ts) {
103108
};
104109

105110
Host.prototype.writeFile = function (filename, data) {
106-
var normalized = this._normalizedRelative(filename);
107-
log('Cache write %s (norm: %s)', filename, normalized);
108-
this.output[normalized] = data;
111+
var canonical = this._currentCanonical(filename);
112+
log('Cache write %s', canonical);
113+
this.output[canonical] = data;
109114
};
110115

111116
Host.prototype.getCurrentDirectory = function () {
@@ -130,21 +135,59 @@ module.exports = function (ts) {
130135
};
131136

132137
Host.prototype.readFile = function (filename) {
133-
var normalized = this._normalizedRelative(filename);
134-
return ts.sys.readFile(normalized);
138+
return ts.sys.readFile(filename);
135139
};
136140

141+
Host.prototype._currentCanonical = function (filename) {
142+
return this.getCanonicalFileName(path.resolve(
143+
this.currentDirectory,
144+
filename
145+
));
146+
}
147+
137148
Host.prototype._rootDir = function () {
138149
var dirs = [];
139150
for (var filename in this.files) {
140151
if (!Object.hasOwnProperty.call(this.files, filename)) continue;
141152
if (/\.d\.ts$/.test(filename)) continue;
142153

143-
dirs.push(path.dirname(filename));
154+
dirs.push(this.getCanonicalFileName(path.dirname(filename)));
144155
}
145156
var result = commondir(this.currentDirectory, dirs);
146-
return result;
157+
return this.getCanonicalFileName(result);
147158
};
148159

160+
Host.prototype._rootFilenames = function () {
161+
162+
var rootFilenames = [];
163+
164+
for (var filename in this.files) {
165+
if (!Object.hasOwnProperty.call(this.files, filename)) continue;
166+
if (!this.files[filename].root) continue;
167+
rootFilenames.push(filename);
168+
}
169+
return rootFilenames;
170+
}
171+
172+
Host.prototype._output = function (filename, extension) {
173+
174+
var inputCanonical = this._currentCanonical(filename);
175+
var outputRelative = path.relative(
176+
this._rootDir(),
177+
replaceFileExtension(inputCanonical, extension)
178+
);
179+
var outputCanonical = this.getCanonicalFileName(path.resolve(
180+
this.outputDirectory,
181+
outputRelative
182+
));
183+
log('Cache read %s', outputCanonical);
184+
185+
var output = this.output[outputCanonical];
186+
if (!output) {
187+
log('Cache miss on %s', outputCanonical);
188+
}
189+
return output;
190+
}
191+
149192
return Host;
150193
};

lib/Tsifier.js

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,6 @@ module.exports = function (ts) {
3434
return (/\.d\.ts$/i).test(file);
3535
}
3636

37-
function replaceFileExtension(file, extension) {
38-
return file.replace(/\.\w+$/i, extension);
39-
}
40-
41-
function getRelativeFilename(file) {
42-
return './' + ts.normalizeSlashes(path.relative(currentDirectory, file));
43-
}
44-
4537
function fileExists(file) {
4638
try {
4739
var stats = fs.lstatSync(file);
@@ -128,7 +120,11 @@ module.exports = function (ts) {
128120
self.opts = parsedOptions.options;
129121
self.files = parsedOptions.fileNames;
130122
self.bopts = bopts;
131-
self.host = new Host(currentDirectory, this.opts.target);
123+
self.host = new Host(
124+
currentDirectory,
125+
this.opts.outDir,
126+
this.opts.target
127+
);
132128

133129
self.host.on('file', function (file, id) {
134130
self.emit('file', file, id);
@@ -140,15 +136,15 @@ module.exports = function (ts) {
140136
Tsifier.prototype.reset = function () {
141137
var self = this;
142138
self.host._reset();
143-
self.addAll(self.files.map(getRelativeFilename));
139+
self.addFiles(self.files);
144140
};
145141

146142
Tsifier.prototype.generateCache = function (files) {
147-
this.addAll(files.map(getRelativeFilename));
143+
this.addFiles(files);
148144
this.compile();
149145
};
150146

151-
Tsifier.prototype.addAll = function (files) {
147+
Tsifier.prototype.addFiles = function (files) {
152148
var self = this;
153149
files.forEach(function (file) {
154150
self.host._addFile(file, true);
@@ -157,12 +153,7 @@ module.exports = function (ts) {
157153

158154
Tsifier.prototype.compile = function () {
159155
var self = this;
160-
var rootFilenames = [];
161-
for (var filename in self.host.files) {
162-
if (!Object.hasOwnProperty.call(self.host.files, filename)) continue;
163-
if (!self.host.files[filename].root) continue;
164-
rootFilenames.push(filename);
165-
}
156+
var rootFilenames = self.host._rootFilenames();
166157

167158
log('Compiling files:');
168159
rootFilenames.forEach(function (file) { log(' %s', file); });
@@ -271,7 +262,7 @@ module.exports = function (ts) {
271262
if (self.host.error)
272263
return;
273264

274-
var compiled = self.getCompiledFile(getRelativeFilename(file));
265+
var compiled = self.getCompiledFile(file);
275266
if (compiled) {
276267
this.push(compiled);
277268
}
@@ -282,40 +273,30 @@ module.exports = function (ts) {
282273

283274
Tsifier.prototype.getCompiledFile = function (inputFile, alreadyMissedCache) {
284275
var self = this;
285-
var normalized = ts.normalizePath(inputFile);
286-
var rootDir = self.host._rootDir();
287-
288276
var outputExtension = (self.opts.jsx === ts.JsxEmit.Preserve && isTsx(inputFile)) ? '.jsx' : '.js';
289-
var outputFile = '__tsify__/' + ts.normalizeSlashes(path.relative(
290-
rootDir,
291-
path.resolve(replaceFileExtension(normalized, outputExtension))
292-
));
293-
var output = self.host.output[outputFile];
294-
295-
log('Cache read %s (norm: %s)', outputFile, normalized);
277+
var output = self.host._output(inputFile, outputExtension);
296278

297279
if (!output) {
298280
if (alreadyMissedCache)
299281
return;
300-
log('Cache miss on %s (norm: %s)', outputFile, normalized);
301282
self.generateCache([inputFile]);
302283
if (self.host.error)
303284
return;
304285
return self.getCompiledFile(inputFile, true);
305286
}
306287

307288
if (self.opts.inlineSourceMap) {
308-
output = self.setFullSourcePathInSourcemap(output, normalized);
289+
output = self.setSourcePathInSourcemap(output, inputFile);
309290
}
310-
311291
return output;
312292
};
313293

314-
Tsifier.prototype.setFullSourcePathInSourcemap = function (output, normalized) {
294+
Tsifier.prototype.setSourcePathInSourcemap = function (output, inputFile) {
315295
var self = this;
316-
if (self.bopts.basedir) {
317-
normalized = ts.normalizeSlashes(path.relative(self.bopts.basedir, normalized));
318-
}
296+
var normalized = ts.normalizePath(path.relative(
297+
self.bopts.basedir || currentDirectory,
298+
inputFile
299+
));
319300

320301
var sourcemap = convert.fromComment(output);
321302
sourcemap.setProperty('sources', [normalized]);

0 commit comments

Comments
 (0)