Skip to content
This repository was archived by the owner on Dec 1, 2019. It is now read-only.

Commit 99220c1

Browse files
author
Stanislav Panferov
committed
feat(checker-runtime): checker now can resolve imports too
1 parent ddca715 commit 99220c1

File tree

5 files changed

+88
-11
lines changed

5 files changed

+88
-11
lines changed

src/checker-runtime.ts

+73-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import { ICompilerOptions, ICompilerInfo, IFile } from './host';
1+
import { ICompilerOptions, ICompilerInfo, IFile, SyncResolver } from './host';
2+
import makeResolver from './resolver';
23
import * as colors from 'colors';
4+
import * as path from 'path';
35

46
require('babel-polyfill');
57

@@ -16,6 +18,7 @@ export interface IMessage {
1618
export interface IInitPayload {
1719
compilerOptions: ICompilerOptions;
1820
compilerInfo: ICompilerInfo;
21+
webpackOptions: any;
1922
}
2023

2124
export interface ICompilePayload {
@@ -25,6 +28,7 @@ export interface ICompilePayload {
2528

2629
export interface IEnv {
2730
options?: ICompilerOptions;
31+
webpackOptions?: any;
2832
compiler?: typeof ts;
2933
compilerInfo?: ICompilerInfo;
3034
host?: Host;
@@ -36,7 +40,35 @@ export interface IEnv {
3640

3741
let env: IEnv = {};
3842

43+
export class ModuleResolutionHost implements ts.ModuleResolutionHost {
44+
servicesHost: Host;
45+
46+
constructor(servicesHost: Host) {
47+
this.servicesHost = servicesHost;
48+
}
49+
50+
fileExists(fileName: string) {
51+
return this.servicesHost.getScriptSnapshot(fileName) !== undefined;
52+
}
53+
54+
readFile(fileName: string): string {
55+
let snapshot = this.servicesHost.getScriptSnapshot(fileName);
56+
return snapshot && snapshot.getText(0, snapshot.getLength());
57+
}
58+
}
59+
3960
export class Host implements ts.LanguageServiceHost {
61+
moduleResolutionHost: ModuleResolutionHost
62+
resolver: SyncResolver
63+
64+
constructor() {
65+
this.moduleResolutionHost = new ModuleResolutionHost(this);
66+
this.resolver = makeResolver(env.webpackOptions);
67+
}
68+
69+
normalizePath(filePath: string): string {
70+
return path.normalize(filePath);
71+
}
4072

4173
getScriptFileNames() {
4274
return Object.keys(env.files);
@@ -71,9 +103,44 @@ export class Host implements ts.LanguageServiceHost {
71103
let resolvedModules: ts.ResolvedModule[] = [];
72104

73105
for (let moduleName of moduleNames) {
74-
resolvedModules.push(
75-
env.resolutionCache[`${containingFile}::${moduleName}`]
76-
);
106+
let cached = env.resolutionCache[`${containingFile}::${moduleName}`];
107+
if (cached) {
108+
resolvedModules.push(cached);
109+
} else {
110+
let resolvedFileName: string;
111+
let resolvedModule: ts.ResolvedModule;
112+
113+
try {
114+
resolvedFileName = this.resolver.resolveSync(
115+
this.normalizePath(path.dirname(containingFile)),
116+
moduleName
117+
);
118+
119+
if (!resolvedFileName.match(/\.tsx?$/)) {
120+
resolvedFileName = null;
121+
}
122+
}
123+
catch (e) {
124+
resolvedFileName = null
125+
}
126+
127+
let tsResolved = env.compiler.resolveModuleName(
128+
resolvedFileName || moduleName,
129+
containingFile,
130+
env.options,
131+
this.moduleResolutionHost
132+
);
133+
134+
if (tsResolved.resolvedModule) {
135+
resolvedModule = tsResolved.resolvedModule;
136+
} else {
137+
resolvedModule = {
138+
resolvedFileName: resolvedFileName || ''
139+
}
140+
}
141+
142+
resolvedModules.push(resolvedModule);
143+
}
77144
}
78145

79146
return resolvedModules;
@@ -92,9 +159,10 @@ export class Host implements ts.LanguageServiceHost {
92159

93160
function processInit(payload: IInitPayload) {
94161
env.compiler = require(payload.compilerInfo.compilerName);
95-
env.host = new Host();
96162
env.compilerInfo = payload.compilerInfo;
97163
env.options = payload.compilerOptions;
164+
env.webpackOptions = payload.webpackOptions;
165+
env.host = new Host();
98166
env.service = env.compiler.createLanguageService(env.host, env.compiler.createDocumentRegistry());
99167
}
100168

src/checker.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,29 @@ interface ChildProcess extends childProcess.ChildProcess {
77
inProgress?: boolean;
88
compilerInfo?: ICompilerInfo;
99
compilerOptions?: ICompilerOptions;
10+
webpackOptions?: any;
1011
}
1112

12-
export function createChecker(compilerInfo: ICompilerInfo, compilerOptions: ICompilerOptions): ChildProcess {
13+
export function createChecker(
14+
compilerInfo: ICompilerInfo,
15+
compilerOptions: ICompilerOptions,
16+
webpackOptions: any
17+
): ChildProcess {
1318
let checker: ChildProcess = childProcess.fork(path.join(__dirname, 'checker-runtime.js'));
1419

1520
checker.send({
1621
messageType: 'init',
1722
payload: {
1823
compilerInfo: _.omit(compilerInfo, 'tsImpl'),
19-
compilerOptions
24+
compilerOptions,
25+
webpackOptions
2026
}
2127
}, null);
2228

2329
checker.inProgress = false;
2430
checker.compilerInfo = compilerInfo;
2531
checker.compilerOptions = compilerOptions;
32+
checker.webpackOptions = webpackOptions;
2633
checker.on('message', function(msg) {
2734
if (msg.messageType == 'progress') {
2835
checker.inProgress = msg.payload.inProgress;
@@ -35,7 +42,7 @@ export function createChecker(compilerInfo: ICompilerInfo, compilerOptions: ICom
3542
export function resetChecker(checker: ChildProcess) {
3643
if (checker.inProgress) {
3744
checker.kill('SIGKILL');
38-
return createChecker(checker.compilerInfo, checker.compilerOptions);
45+
return createChecker(checker.compilerInfo, checker.compilerOptions, checker.webpackOptions);
3946
} else {
4047
return checker;
4148
}

src/instance.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export function ensureInstance(webpack: IWebPack, options: ICompilerOptions, ins
156156
sourceRoot: process.cwd()
157157
});
158158

159-
options = _.omit(options, 'outDir') as any;
159+
options = _.omit(options, 'outDir', 'files', 'exclude') as any;
160160
options.externals.push.apply(options.externals, tsFiles)
161161

162162
let babelImpl: any;
@@ -202,6 +202,8 @@ export function ensureInstance(webpack: IWebPack, options: ICompilerOptions, ins
202202
setupAfterCompile(compiler, instanceName, forkChecker);
203203
}
204204

205+
let webpackOptions = _.pick(webpack._compiler.options, 'resolve');
206+
205207
return getInstanceStore(webpack._compiler)[instanceName] = {
206208
tsFlow,
207209
tsState,
@@ -210,7 +212,7 @@ export function ensureInstance(webpack: IWebPack, options: ICompilerOptions, ins
210212
options,
211213
externalsInvoked: false,
212214
checker: forkChecker
213-
? createChecker(compilerInfo, options)
215+
? createChecker(compilerInfo, options, webpackOptions)
214216
: null,
215217
cacheIdentifier
216218
}

src/tsconfig-utils.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ function buildEnumMap(tsImpl: typeof ts) {
66
'es3': tsImpl.ScriptTarget.ES3,
77
'es5': tsImpl.ScriptTarget.ES5,
88
'es6': tsImpl.ScriptTarget.ES6,
9+
'es2015': tsImpl.ScriptTarget.ES2015,
910
'latest': tsImpl.ScriptTarget.Latest
1011
},
1112
module: {

src/tsconfig.json

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"declaration": false,
66
"noImplicitAny": false,
77
"removeComments": true,
8-
"moduleResolution": "node",
98
"noLib": false,
109
"preserveConstEnums": true,
1110
"suppressImplicitAnyIndexErrors": true

0 commit comments

Comments
 (0)