@@ -4,14 +4,13 @@ import {INameGetter} from "../getter/interface/INameGetter";
4
4
import { ISourceFilePropertiesGetter } from "../getter/interface/ISourceFilePropertiesGetter" ;
5
5
import { IMapper } from "../mapper/interface/IMapper" ;
6
6
import { IBindingIdentifier } from "../model/interface/IBindingIdentifier" ;
7
- import { isCallExpression , isExternalModuleReference , isIdentifierObject , isImportDeclaration , isImportEqualsDeclaration , isNamedImports , isNamespaceImport , isVariableDeclaration , isVariableDeclarationList , isVariableStatement } from "../predicate/PredicateFunctions" ;
7
+ import { isArrayBindingPattern , isCallExpression , isExternalModuleReference , isIdentifierObject , isImportDeclaration , isImportEqualsDeclaration , isNamedImports , isNamespaceImport , isObjectBindingPattern , isOmittedExpression , isVariableDeclaration , isVariableDeclarationList , isVariableStatement } from "../predicate/PredicateFunctions" ;
8
8
import { ICodeAnalyzer , IdentifierMapKind , IImportDeclaration , ImportExportIndexer , ImportExportKind , IRequire , ModuleDependencyKind , NAMESPACE_NAME } from "../service/interface/ICodeAnalyzer" ;
9
9
import { ITracer } from "../tracer/interface/ITracer" ;
10
10
import { IStringUtil } from "../util/interface/IStringUtil" ;
11
11
import { IImportFormatter } from "./interface/IImportFormatter" ;
12
12
import { ModuleFormatter } from "./ModuleFormatter" ;
13
13
import { IRequireFormatter } from "./interface/IRequireFormatter" ;
14
- import { IMarshaller } from "@wessberg/marshaller" ;
15
14
16
15
export class ImportFormatter extends ModuleFormatter implements IImportFormatter {
17
16
constructor ( private languageService : ICodeAnalyzer ,
@@ -20,10 +19,9 @@ export class ImportFormatter extends ModuleFormatter implements IImportFormatter
20
19
private requireFormatter : IRequireFormatter ,
21
20
private mapper : IMapper ,
22
21
private tracer : ITracer ,
23
- marshaller : IMarshaller ,
24
22
stringUtil : IStringUtil ,
25
23
fileLoader : IFileLoader ) {
26
- super ( stringUtil , marshaller , fileLoader ) ;
24
+ super ( stringUtil , fileLoader ) ;
27
25
}
28
26
29
27
public format ( statement : ImportDeclaration | ImportEqualsDeclaration | VariableStatement | CallExpression ) : IImportDeclaration | null {
@@ -123,7 +121,12 @@ export class ImportFormatter extends ModuleFormatter implements IImportFormatter
123
121
const clojure = this . tracer . traceClojure ( statement ) ;
124
122
125
123
const payload = ( ) => {
126
- return typeof clojure === "string" ? clojure : this . tracer . findNearestMatchingIdentifier ( statement , block , source . toString ( ) , clojure ) ;
124
+ return clojure == null ? {
125
+ ___kind : IdentifierMapKind . LITERAL ,
126
+ startsAt : statement . moduleReference . pos ,
127
+ endsAt : statement . moduleReference . end ,
128
+ value : ( ) => clojure
129
+ } : this . tracer . findNearestMatchingIdentifier ( statement , block , source . toString ( ) , clojure ) ;
127
130
} ;
128
131
129
132
const map : IImportDeclaration = {
@@ -169,15 +172,59 @@ export class ImportFormatter extends ModuleFormatter implements IImportFormatter
169
172
}
170
173
171
174
private formatVariableDeclaration ( statement : VariableDeclaration ) : IImportDeclaration | null {
172
- const name = this . nameGetter . getName ( statement . name ) ;
173
- return this . formatCallExpression ( statement , name == null ? undefined : name ) ;
175
+ return this . formatCallExpression ( statement ) ;
174
176
}
175
177
176
- private formatCallExpression ( statement : CallExpression | VariableStatement | VariableDeclaration | VariableDeclarationList , name : string = NAMESPACE_NAME ) : IImportDeclaration | null {
178
+ private formatCallExpression ( statement : CallExpression | VariableDeclaration ) : IImportDeclaration | null {
177
179
const requireCall = this . requireFormatter . format ( statement ) ;
178
180
if ( requireCall == null ) return null ;
179
181
const { startsAt, endsAt, relativePath, fullPath, filePath, payload} = requireCall ;
180
182
183
+ let bindings : ImportExportIndexer = { } ;
184
+ const name : ( string | undefined ) [ ] = [ ] ;
185
+ let kind : ImportExportKind ;
186
+
187
+ if ( isCallExpression ( statement ) ) {
188
+ name . push ( NAMESPACE_NAME ) ;
189
+ kind = ImportExportKind . NAMESPACE ;
190
+ } else {
191
+
192
+ if ( isObjectBindingPattern ( statement . name ) ) {
193
+ statement . name . elements . forEach ( binding => {
194
+ name . push ( < string > this . nameGetter . getName ( binding ) ) ;
195
+ kind = ImportExportKind . NAMED ;
196
+ } ) ;
197
+ }
198
+
199
+ else if ( isArrayBindingPattern ( statement . name ) ) {
200
+ statement . name . elements . forEach ( ( binding ) => {
201
+ if ( isOmittedExpression ( binding ) ) name . push ( undefined ) ;
202
+ name . push ( < string > this . nameGetter . getName ( binding ) ) ;
203
+ kind = ImportExportKind . NAMED ;
204
+ } ) ;
205
+ }
206
+
207
+ else {
208
+ name . push ( < string > this . nameGetter . getNameOfMember ( statement . name , false , true ) ) ;
209
+ kind = ImportExportKind . NAMESPACE ;
210
+ }
211
+ }
212
+
213
+ name . forEach ( part => {
214
+ // TODO: Respect ArrayBindingPatterns or ObjectBindingPatterns.
215
+ if ( part == null ) return ;
216
+
217
+ bindings [ part ] = {
218
+ startsAt : requireCall . arguments . startsAt ,
219
+ endsAt : requireCall . arguments . endsAt ,
220
+ ___kind : IdentifierMapKind . IMPORT_EXPORT_BINDING ,
221
+ name : part ,
222
+ payload,
223
+ kind
224
+ } ;
225
+ this . mapper . set ( bindings [ part ] , statement ) ;
226
+ } ) ;
227
+
181
228
const map : IImportDeclaration = {
182
229
___kind : IdentifierMapKind . IMPORT ,
183
230
startsAt,
@@ -188,18 +235,9 @@ export class ImportFormatter extends ModuleFormatter implements IImportFormatter
188
235
fullPath
189
236
} ,
190
237
filePath,
191
- bindings : {
192
- [ name ] : {
193
- startsAt : requireCall . arguments . startsAt ,
194
- endsAt : requireCall . arguments . endsAt ,
195
- ___kind : IdentifierMapKind . IMPORT_EXPORT_BINDING ,
196
- name,
197
- payload,
198
- kind : ImportExportKind . NAMESPACE
199
- }
200
- }
238
+ bindings
201
239
} ;
202
- this . mapper . set ( map . bindings [ name ] , statement ) ;
240
+
203
241
// Make the kind non-enumerable.
204
242
Object . defineProperty ( map , "___kind" , {
205
243
value : IdentifierMapKind . IMPORT ,
@@ -219,30 +257,41 @@ export class ImportFormatter extends ModuleFormatter implements IImportFormatter
219
257
private formatImportClause ( clause : ImportClause , modulePath : ( ) => string ) : ImportExportIndexer {
220
258
const indexer : ImportExportIndexer = { } ;
221
259
222
- if ( clause . namedBindings != null && isNamespaceImport ( clause . namedBindings ) ) {
260
+ const namedBindings = clause . namedBindings ;
261
+ if ( namedBindings != null && isNamespaceImport ( namedBindings ) ) {
223
262
const payload = ( ) => {
224
263
const path = modulePath ( ) ;
225
- return this . moduleToNamespacedObjectLiteral ( this . languageService . getExportDeclarationsForFile ( path , true ) ) ;
264
+ return {
265
+ ___kind : IdentifierMapKind . LITERAL ,
266
+ startsAt : namedBindings . pos ,
267
+ endsAt : namedBindings . end ,
268
+ value : ( ) => this . moduleToNamespacedObjectLiteral ( this . languageService . getExportDeclarationsForFile ( path , true ) )
269
+ } ;
226
270
} ;
227
271
228
- indexer [ clause . namedBindings . name . text ] = {
229
- startsAt : clause . namedBindings . name . pos ,
230
- endsAt : clause . namedBindings . name . end ,
272
+ indexer [ namedBindings . name . text ] = {
273
+ startsAt : namedBindings . name . pos ,
274
+ endsAt : namedBindings . name . end ,
231
275
___kind : IdentifierMapKind . IMPORT_EXPORT_BINDING ,
232
- name : clause . namedBindings . name . text ,
276
+ name : namedBindings . name . text ,
233
277
payload,
234
278
kind : ImportExportKind . NAMESPACE
235
279
} ;
236
- this . mapper . set ( indexer [ clause . namedBindings . name . text ] , clause . namedBindings ) ;
280
+ this . mapper . set ( indexer [ namedBindings . name . text ] , namedBindings ) ;
237
281
}
238
282
239
- else if ( clause . namedBindings != null && isNamedImports ( clause . namedBindings ) ) {
240
- clause . namedBindings . elements . forEach ( element => {
283
+ else if ( namedBindings != null && isNamedImports ( namedBindings ) ) {
284
+ namedBindings . elements . forEach ( element => {
241
285
const block = this . tracer . traceBlockScopeName ( clause ) ;
242
286
const payload = ( ) => {
243
287
const path = modulePath ( ) ;
244
288
const clojure = this . tracer . traceClojure ( path ) ;
245
- return typeof clojure === "string" ? clojure : this . tracer . findNearestMatchingIdentifier ( element , block , element . name . text , clojure ) ;
289
+ return clojure == null ? {
290
+ ___kind : IdentifierMapKind . LITERAL ,
291
+ startsAt : element . pos ,
292
+ endsAt : element . end ,
293
+ value : ( ) => path
294
+ } : this . tracer . findNearestMatchingIdentifier ( element , block , element . name . text , clojure ) ;
246
295
} ;
247
296
248
297
indexer [ element . name . text ] = {
@@ -263,7 +312,7 @@ export class ImportFormatter extends ModuleFormatter implements IImportFormatter
263
312
const fileExports = this . languageService . getExportDeclarationsForFile ( path , true ) ;
264
313
const match = fileExports . find ( exportDeclaration => exportDeclaration . bindings [ "default" ] != null ) ;
265
314
if ( match == null ) throw new ReferenceError ( `${ this . formatImportClause . name } could not extract a default export from ${ modulePath } ! The module doesn't contain a default export.` ) ;
266
- return match . bindings [ "default" ] . payload ;
315
+ return match . bindings [ "default" ] . payload ( ) ;
267
316
} ;
268
317
269
318
indexer [ clause . name . text ] = {
0 commit comments