Skip to content

Commit

Permalink
Allow simultaneous named and default imports
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffmo committed Jul 4, 2015
1 parent ad0e301 commit a50ae40
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 98 deletions.
189 changes: 92 additions & 97 deletions src/typing/type_inference_js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1205,8 +1205,8 @@ and statement_decl cx = Ast.Statement.(
| ImportDeclaration.ImportTypeof -> "import typeof", true
| ImportDeclaration.ImportValue -> "import", false
) in
(
match default with

(match default with
| Some(_, local_ident) ->
let local_name = local_ident.Ast.Identifier.name in
let reason_str =
Expand All @@ -1219,47 +1219,45 @@ and statement_decl cx = Ast.Statement.(
(Scope.create_entry ~for_type:isType tvar tvar (Some loc))
in
Env_js.init_var cx local_name env_entry
| None -> (
match specifier with
| Some(ImportDeclaration.Named(_, named_specifiers)) ->
let init_specifier (specifier_loc, specifier) = (
let (loc, remote_ident) =
specifier.ImportDeclaration.NamedSpecifier.id
in
let remote_name = remote_ident.Ast.Identifier.name in
let (local_name, reason) = (
match specifier.ImportDeclaration.NamedSpecifier.name with
| Some(_, { Ast.Identifier.name = local_name; _; }) ->
let reason_str =
spf "%s { %s as %s }" import_str remote_name local_name
in
(local_name, (mk_reason reason_str loc))
| None ->
let reason_str = spf "%s { %s }" import_str remote_name in
(remote_name, (mk_reason reason_str loc))
) in
let tvar = Flow_js.mk_tvar cx reason in
let env_entry =
Scope.create_entry ~for_type:isType tvar tvar (Some specifier_loc)
in
Env_js.init_var cx local_name env_entry;
) in
List.iter init_specifier named_specifiers
| Some(ImportDeclaration.NameSpace(_, (loc, local_ident))) ->
let local_name = local_ident.Ast.Identifier.name in
let reason =
mk_reason (spf "%s * as %s" import_str local_name) loc
| None -> ()
);

(match specifier with
| Some(ImportDeclaration.Named(_, named_specifiers)) ->
let init_specifier (specifier_loc, specifier) = (
let (loc, remote_ident) =
specifier.ImportDeclaration.NamedSpecifier.id
in
let remote_name = remote_ident.Ast.Identifier.name in
let (local_name, reason) = (
match specifier.ImportDeclaration.NamedSpecifier.name with
| Some(_, { Ast.Identifier.name = local_name; _; }) ->
let reason_str =
spf "%s { %s as %s }" import_str remote_name local_name
in
(local_name, (mk_reason reason_str loc))
| None ->
let reason_str = spf "%s { %s }" import_str remote_name in
(remote_name, (mk_reason reason_str loc))
) in
let tvar = Flow_js.mk_tvar cx reason in
let env_entry =
Scope.create_entry ~for_type:isType tvar tvar (Some loc)
Scope.create_entry ~for_type:isType tvar tvar (Some specifier_loc)
in
Env_js.init_var cx local_name env_entry
| None -> failwith (
"Parser error: Non-default imports must always have a " ^
"specifier!"
)
)
Env_js.init_var cx local_name env_entry;
) in
List.iter init_specifier named_specifiers
| Some(ImportDeclaration.NameSpace(_, (loc, local_ident))) ->
let local_name = local_ident.Ast.Identifier.name in
let reason =
mk_reason (spf "%s * as %s" import_str local_name) loc
in
let tvar = Flow_js.mk_tvar cx reason in
let env_entry =
Scope.create_entry ~for_type:isType tvar tvar (Some loc)
in
Env_js.init_var cx local_name env_entry
| None -> ()
)
)

Expand Down Expand Up @@ -2458,68 +2456,65 @@ and statement cx = Ast.Statement.(
loc
in
set_imported_binding reason local_name imported_t
| None -> (
match specifier with
| Some(ImportDeclaration.Named(_, named_specifiers)) ->
let import_specifier (specifier_loc, specifier) = (
let (remote_ident_loc, remote_ident) =
specifier.ImportDeclaration.NamedSpecifier.id
in
let remote_name = remote_ident.Ast.Identifier.name in
| None -> ()
);

let get_reason_str =
spf "\"%s\" export of \"%s\"" remote_name module_name
in
(match specifier with
| Some(ImportDeclaration.Named(_, named_specifiers)) ->
let import_specifier (specifier_loc, specifier) = (
let (remote_ident_loc, remote_ident) =
specifier.ImportDeclaration.NamedSpecifier.id
in
let remote_name = remote_ident.Ast.Identifier.name in

let (local_name, get_reason, set_reason) = (
match specifier.ImportDeclaration.NamedSpecifier.name with
| Some(local_ident_loc, { Ast.Identifier.name = local_name; _; }) ->
let get_reason = mk_reason get_reason_str remote_ident_loc in
let set_reason = mk_reason
(spf "%s { %s as %s }" import_str remote_name local_name)
specifier_loc
in
(local_name, get_reason, set_reason)
| None ->
let get_reason = mk_reason get_reason_str specifier_loc in
let set_reason = mk_reason
(spf "%s { %s }" import_str remote_name)
specifier_loc
in
(remote_name, get_reason, set_reason)
) in
let imported_t = get_imported_t get_reason set_reason remote_name in
let get_reason_str =
spf "\"%s\" export of \"%s\"" remote_name module_name
in

set_imported_binding get_reason local_name imported_t
let (local_name, get_reason, set_reason) = (
match specifier.ImportDeclaration.NamedSpecifier.name with
| Some(local_ident_loc, { Ast.Identifier.name = local_name; _; }) ->
let get_reason = mk_reason get_reason_str remote_ident_loc in
let set_reason = mk_reason
(spf "%s { %s as %s }" import_str remote_name local_name)
specifier_loc
in
(local_name, get_reason, set_reason)
| None ->
let get_reason = mk_reason get_reason_str specifier_loc in
let set_reason = mk_reason
(spf "%s { %s }" import_str remote_name)
specifier_loc
in
(remote_name, get_reason, set_reason)
) in
List.iter import_specifier named_specifiers
| Some(ImportDeclaration.NameSpace(_, (ident_loc, local_ident))) ->
let local_name = local_ident.Ast.Identifier.name in
let reason = mk_reason
(spf "%s * as %s" import_str local_name)
ident_loc
in
if isType then (
(**
* TODO: `import type * as` really doesn't make much sense with
* our current CommonJS interop table. Here we support
* this in the same way we treat import-default as a
* temporary means of transitioning our old interop table
* to the new one. Once the transition is finished, we
* should make `import type * as` a hard error.
*)
let module_ = Module_js.imported_module cx.file module_name in
let module_type = require cx module_ module_name source_loc in
set_imported_binding reason local_name module_type
) else (
set_imported_binding reason local_name module_ns_tvar
)
| None ->
failwith (
"Parser error: Non-default imports must always have a " ^
"specifier!"
)
)
let imported_t = get_imported_t get_reason set_reason remote_name in

set_imported_binding get_reason local_name imported_t
) in
List.iter import_specifier named_specifiers
| Some(ImportDeclaration.NameSpace(_, (ident_loc, local_ident))) ->
let local_name = local_ident.Ast.Identifier.name in
let reason = mk_reason
(spf "%s * as %s" import_str local_name)
ident_loc
in
if isType then (
(**
* TODO: `import type * as` really doesn't make much sense with
* our current CommonJS interop table. Here we support
* this in the same way we treat import-default as a
* temporary means of transitioning our old interop table
* to the new one. Once the transition is finished, we
* should make `import type * as` a hard error.
*)
let module_ = Module_js.imported_module cx.file module_name in
let module_type = require cx module_ module_name source_loc in
set_imported_binding reason local_name module_type
) else (
set_imported_binding reason local_name module_ns_tvar
)
| None -> ()
)
)

Expand Down
4 changes: 4 additions & 0 deletions tests/es6modules/ES6_DefaultAndNamed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* @flow */

export default 42;
export var str = 'asdf';
1 change: 1 addition & 0 deletions tests/es6modules/SideEffects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* @flow */
10 changes: 9 additions & 1 deletion tests/es6modules/es6modules.exp
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,12 @@ es6modules.js:251:20,74: number
This type is incompatible with
es6modules.js:253:10,15: string

Found 67 errors
es6modules.js:259:8,17: number
This type is incompatible with
es6modules.js:262:10,15: string

es6modules.js:259:21,23: string
This type is incompatible with
es6modules.js:265:10,15: number

Found 69 errors
18 changes: 18 additions & 0 deletions tests/es6modules/es6modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,21 @@ var aq2: string = numberValue2_renamed2; // Error: number ~> string
var numberValue7 = require("ES6_ExportAllFrom_Intermediary2").numberValue1;
var ar1: number = numberValue7;
var ar2: string = numberValue7; // Error: number ~> string

////////////////////////////////////////////////////////
// == ES6 Default+Named -> ES6 import Default+Named== //
////////////////////////////////////////////////////////

import defaultNum, {str as namedStr} from "./ES6_DefaultAndNamed";

var as1: number = defaultNum;
var as2: string = defaultNum; // Error: number ~> string

var as3: string = namedStr;
var as4: number = namedStr; // Error: string ~> number

////////////////////////////////////////
// == Side-effect only ES6 imports == //
////////////////////////////////////////

import "./SideEffects";

0 comments on commit a50ae40

Please sign in to comment.