A model builder knows how to load nit source files and build the associated model

Introduced properties

private var _bad_class_names: MultiHashMap[MModule, String]

nitc :: ModelBuilder :: _bad_class_names

List of already reported bad class names.
private var _conditional_importations: Array[SequenceRead[MModule]]

nitc :: ModelBuilder :: _conditional_importations

Global list of conditional importation rules.
private var _doc_entities: Int

nitc :: ModelBuilder :: _doc_entities

The number of MEntity that have some documentation
private var _failed_entities: Int

nitc :: ModelBuilder :: _failed_entities

The number failed docunits
private var _failed_tests: Int

nitc :: ModelBuilder :: _failed_tests

Number of failed tests.
private var _identified_modules: Array[MModule]

nitc :: ModelBuilder :: _identified_modules

All the currently identified modules.
private var _identified_modules_by_path: HashMap[String, nullable MModule]

nitc :: ModelBuilder :: _identified_modules_by_path

Cache for identify_module by relative and real paths
private var _last_loader_error: nullable String

nitc :: ModelBuilder :: _last_loader_error

Some loader services are silent and return null on error.
private var _mclassdef2nclassdef: HashMap[MClassDef, AClassdef]

nitc :: ModelBuilder :: _mclassdef2nclassdef

Registration of the nclassdef associated to each mclassdef
private var _mgroups: HashMap[String, nullable MGroup]

nitc :: ModelBuilder :: _mgroups

Groups by path
private var _mmodule2nmodule: HashMap[MModule, AModule]

nitc :: ModelBuilder :: _mmodule2nmodule

Register the nmodule associated to each mmodule
private var _model: Model

nitc :: ModelBuilder :: _model

The model where new modules, classes and properties are added
private var _mpropdef2npropdef: HashMap[MPropDef, APropdef]

nitc :: ModelBuilder :: _mpropdef2npropdef

Registration of the npropdef associated to each mpropdef.
private var _nb_invok_by_direct: Int

nitc :: ModelBuilder :: _nb_invok_by_direct

Count number of invocations by direct call
private var _nb_invok_by_inline: Int

nitc :: ModelBuilder :: _nb_invok_by_inline

Count number of invocations by inlining
private var _nb_invok_by_tables: Int

nitc :: ModelBuilder :: _nb_invok_by_tables

Count number of invocations by VFT
private var _nmodules: Array[AModule]

nitc :: ModelBuilder :: _nmodules

All the loaded modules
private var _parsed_modules: Array[MModule]

nitc :: ModelBuilder :: _parsed_modules

All the currently parsed modules.
private var _paths: Array[String]

nitc :: ModelBuilder :: _paths

The list of directories to search for top level modules
private var _the_root_init_mmethod: nullable MMethod

nitc :: ModelBuilder :: _the_root_init_mmethod

the root init of the Object class
private var _toolcontext: ToolContext

nitc :: ModelBuilder :: _toolcontext

The toolcontext used to control the interaction with the user (getting options and displaying messages)
private var _total_classes: Int

nitc :: ModelBuilder :: _total_classes

Number of test classes generated.
private var _total_entities: Int

nitc :: ModelBuilder :: _total_entities

Total number analyzed MEntity
private var _total_tests: Int

nitc :: ModelBuilder :: _total_tests

Number of tests generated.
private var _unit_entities: Int

nitc :: ModelBuilder :: _unit_entities

The total number of executed docunits
fun advice(n: nullable ANode, tag: String, text: String)

nitc :: ModelBuilder :: advice

Helper function to display an advice on a node.
fun apply_conditional_importations(mmodule: MModule)

nitc :: ModelBuilder :: apply_conditional_importations

Extends the current importations according to imported rules about conditional importation
private fun bad_class_names: MultiHashMap[MModule, String]

nitc :: ModelBuilder :: bad_class_names

List of already reported bad class names.
private fun bad_class_names=(bad_class_names: MultiHashMap[MModule, String])

nitc :: ModelBuilder :: bad_class_names=

List of already reported bad class names.
private fun build_a_bound_mtype(nmodule: AModule, nclassdef: AClassdef): nullable MClassType

nitc :: ModelBuilder :: build_a_bound_mtype

Determine the type parameter bounds for nclassdef.
private fun build_a_mclass(nmodule: AModule, nclassdef: AClassdef)

nitc :: ModelBuilder :: build_a_mclass

Visit the AST and create the MClass objects
private fun build_a_mclassdef(nmodule: AModule, nclassdef: AClassdef)

nitc :: ModelBuilder :: build_a_mclassdef

Visit the AST and create the MClassDef objects
private fun build_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)

nitc :: ModelBuilder :: build_a_mclassdef_inheritance

Visit the AST and set the super-types of the MClassDef objects
private fun build_a_mmodule(mgroup: nullable MGroup, nmodule: AModule)

nitc :: ModelBuilder :: build_a_mmodule

Visit the AST and create the MModule object
private fun build_classes(nmodule: AModule)

nitc :: ModelBuilder :: build_classes

Build the classes of the module nmodule.
fun build_module_importation(nmodule: AModule)

nitc :: ModelBuilder :: build_module_importation

Analyze the module importation and fill the module_importation_hierarchy
private fun build_properties(nclassdef: AClassdef)

nitc :: ModelBuilder :: build_properties

Build the properties of nclassdef.
fun build_with_ant(compiler: JavaCompiler, jfiles: Array[String])

nitc :: ModelBuilder :: build_with_ant

Compile Java sources using ant
fun build_with_make(compiler: JavaCompiler, jfiles: Array[String])

nitc :: ModelBuilder :: build_with_make

Compile Java generated files using make
private fun cache_file(filepath: String): FileWriter

nitc :: ModelBuilder :: cache_file

Cache a file as {filepath}.tmp and replace the original if different
fun check_sametype(node: ANode, mmodule: MModule, anchor: nullable MClassType, sub: MType, sup: MType): Bool

nitc :: ModelBuilder :: check_sametype

Check that sub and sup are equvalent types.
fun check_subtype(node: ANode, mmodule: MModule, anchor: nullable MClassType, sub: MType, sup: MType): Bool

nitc :: ModelBuilder :: check_subtype

Check that sub is a subtype of sup.
private fun check_supertypes(nmodule: AModule, nclassdef: AClassdef)

nitc :: ModelBuilder :: check_supertypes

Check the validity of the specialization heirarchy
fun check_virtual_types_circularity(node: ANode, mproperty: MVirtualTypeProp, recv: MType, mmodule: MModule): Bool

nitc :: ModelBuilder :: check_virtual_types_circularity

Detect circularity errors for virtual types.
fun check_visibility(node: ANode, mtype: MType, mpropdef: MPropDef)

nitc :: ModelBuilder :: check_visibility

Check the visibility of mtype as an element of the signature of mpropdef.
fun class_not_found(qid: AQclassid, mmodule: MModule)

nitc :: ModelBuilder :: class_not_found

Print an error and suggest hints when the class identified by qid in mmodule is not found.
private fun close_cache(filepath: String, file: FileWriter)

nitc :: ModelBuilder :: close_cache

Close the writer and move tmp file to original if modified
fun collect_annotations_data(name: String, mmodule: MModule): MModuleData[AAnnotation]

nitc :: ModelBuilder :: collect_annotations_data

Collect all annotations by name in mmodule and its importations (direct and indirect)
fun collect_annotations_on_modules(name: String, mmodule: MModule): Array[AAnnotation]

nitc :: ModelBuilder :: collect_annotations_on_modules

Collect all annotations by name assocated to mmodule and its imported modules.
fun collect_attr_propdef(mclassdef: MClassDef): Array[AAttrPropdef]

nitc :: ModelBuilder :: collect_attr_propdef

Retrieve all the attributes nodes localy definied
private fun collect_supertypes(nmodule: AModule, nclassdef: AClassdef, is_intro: Bool): Array[MClassType]

nitc :: ModelBuilder :: collect_supertypes

List the supertypes specified or implied by nclassdef.
fun compile_antfile(compiler: JavaCompiler, jfiles: Array[String])

nitc :: ModelBuilder :: compile_antfile

The Ant build.xml script used to compile build the final jar
fun conditional_importations: Array[SequenceRead[MModule]]

nitc :: ModelBuilder :: conditional_importations

Global list of conditional importation rules.
protected fun conditional_importations=(conditional_importations: Array[SequenceRead[MModule]])

nitc :: ModelBuilder :: conditional_importations=

Global list of conditional importation rules.
fun create_attribute_from_name(name: String, mclassdef: MClassDef, mtype: MType, visibility: nullable MVisibility): AAttrPropdef

nitc :: ModelBuilder :: create_attribute_from_name

Creation of a new attribute (AST and model representation) with the given name.
fun create_attribute_from_propdef(mattribut_def: MAttributeDef): AAttrPropdef

nitc :: ModelBuilder :: create_attribute_from_propdef

Creation of a new attribute (AST representation) with the given MAttributeDef.
fun create_attribute_from_property(mattribute: MAttribute, mclassdef: MClassDef, mtype: MType): AAttrPropdef

nitc :: ModelBuilder :: create_attribute_from_property

Creation of a new attribute (AST and model representation) with the given MAttribute.
fun create_class_from_mclass(mclass: MClass, super_type: Array[MClassType], mmodule: MModule): AStdClassdef

nitc :: ModelBuilder :: create_class_from_mclass

Creation of a new class (AST and model representation) with the given MClass.
fun create_class_from_mclassdef(mclassdef: MClassDef, mmodule: MModule): AStdClassdef

nitc :: ModelBuilder :: create_class_from_mclassdef

Creation of a new class (AST representation) with the given MClassDef.
fun create_class_from_name(name: String, super_type: Array[MClassType], mmodule: MModule, visibility: nullable MVisibility): AStdClassdef

nitc :: ModelBuilder :: create_class_from_name

Creation of a new class (AST and model representation) with the given name.
fun create_method_from_name(name: String, mclassdef: MClassDef, is_abstract: Bool, msignature: nullable MSignature, visibility: nullable MVisibility): AMethPropdef

nitc :: ModelBuilder :: create_method_from_name

Creation of a new method (AST and model representation) with the given name.
fun create_method_from_property(mproperty: MMethod, mclassdef: MClassDef, is_abstract: Bool, msignature: nullable MSignature): AMethPropdef

nitc :: ModelBuilder :: create_method_from_property

Creation of a new method (AST and model representation) with the given MMethod.
init defaultinit(model: Model, toolcontext: ToolContext)

nitc :: ModelBuilder :: defaultinit

fun do_rapid_type_analysis(mainmodule: MModule): RapidTypeAnalysis

nitc :: ModelBuilder :: do_rapid_type_analysis

Performs a rapid-type-analysis on the program associated with mainmodule.
fun doc_entities: Int

nitc :: ModelBuilder :: doc_entities

The number of MEntity that have some documentation
protected fun doc_entities=(doc_entities: Int)

nitc :: ModelBuilder :: doc_entities=

The number of MEntity that have some documentation
fun error(n: nullable ANode, text: String)

nitc :: ModelBuilder :: error

Helper function to display an error on a node.
fun failed_entities: Int

nitc :: ModelBuilder :: failed_entities

The number failed docunits
protected fun failed_entities=(failed_entities: Int)

nitc :: ModelBuilder :: failed_entities=

The number failed docunits
fun failed_tests: Int

nitc :: ModelBuilder :: failed_tests

Number of failed tests.
protected fun failed_tests=(failed_tests: Int)

nitc :: ModelBuilder :: failed_tests=

Number of failed tests.
fun filter_nit_source(args: Array[String]): Array[String]

nitc :: ModelBuilder :: filter_nit_source

Remove Nit source files from a list of arguments.
fun force_get_primitive_method(n: nullable ANode, name: String, recv: MClass, mmodule: MModule): MMethod

nitc :: ModelBuilder :: force_get_primitive_method

Force to get the primitive method named name on the type recv or do a fatal error on n
fun gen_test_unit(mmodule: MModule)

nitc :: ModelBuilder :: gen_test_unit

Generate NitUnit test file skeleton for mmodule.
fun get_mclass_by_name(node: nullable ANode, mmodule: MModule, name: String): nullable MClass

nitc :: ModelBuilder :: get_mclass_by_name

Like try_get_mclass_by_name but display an error message when the class is not found
private fun get_mmethod(name: String, mclassdef: MClassDef, visibility: nullable MVisibility): MMethod

nitc :: ModelBuilder :: get_mmethod

Try to get MMethod property if exist in the given mclassdef. return new MMethod if not exist.
fun get_mmodule_annotation(name: String, mmodule: MModule): nullable AAnnotation

nitc :: ModelBuilder :: get_mmodule_annotation

Return the single annotation name locally assocated to mmodule, if any.
fun get_mmodule_by_name(anode: nullable ANode, mgroup: nullable MGroup, name: String): nullable MModule

nitc :: ModelBuilder :: get_mmodule_by_name

Get a module by its short name; if required, the module is loaded, parsed and its hierarchies computed.
fun identified_modules: Array[MModule]

nitc :: ModelBuilder :: identified_modules

All the currently identified modules.
protected fun identified_modules=(identified_modules: Array[MModule])

nitc :: ModelBuilder :: identified_modules=

All the currently identified modules.
private fun identified_modules_by_path: HashMap[String, nullable MModule]

nitc :: ModelBuilder :: identified_modules_by_path

Cache for identify_module by relative and real paths
private fun identified_modules_by_path=(identified_modules_by_path: HashMap[String, nullable MModule])

nitc :: ModelBuilder :: identified_modules_by_path=

Cache for identify_module by relative and real paths
fun identify_group(dirpath: String): nullable MGroup

nitc :: ModelBuilder :: identify_group

Return the mgroup associated to a directory path.
fun identify_module(path: String): nullable MModule

nitc :: ModelBuilder :: identify_module

Identify a source file and load the associated package and groups if required.
fun inject_module_subimportation(mmodule: MModule, filename: String)

nitc :: ModelBuilder :: inject_module_subimportation

Load module filename and add it as a conditional importation of mmodule.
fun last_loader_error: nullable String

nitc :: ModelBuilder :: last_loader_error

Some loader services are silent and return null on error.
protected fun last_loader_error=(last_loader_error: nullable String)

nitc :: ModelBuilder :: last_loader_error=

Some loader services are silent and return null on error.
fun load_markdown(filepath: String): MDoc

nitc :: ModelBuilder :: load_markdown

Load a markdown file as a documentation object
fun load_module(filename: String): nullable AModule

nitc :: ModelBuilder :: load_module

Try to load a module using a path.
fun load_module_ast(filename: String): nullable AModule

nitc :: ModelBuilder :: load_module_ast

Try to load a module AST using a path.
fun load_rt_module(parent: nullable MModule, nmodule: AModule, mod_name: String): nullable MModule

nitc :: ModelBuilder :: load_rt_module

Injection of a new module without source.
fun lookup_annotation_on_modules(name: String, mmodule: MModule): nullable AAnnotation

nitc :: ModelBuilder :: lookup_annotation_on_modules

Get an annotation by name from mmodule and its super modules. Will recursively search
private fun match_amodulename(n_name: AModuleName, m: MModule): Bool

nitc :: ModelBuilder :: match_amodulename

Is elements of n_name correspond to the group nesting of m?
private fun mclassdef2nclassdef: HashMap[MClassDef, AClassdef]

nitc :: ModelBuilder :: mclassdef2nclassdef

Registration of the nclassdef associated to each mclassdef
private fun mclassdef2nclassdef=(mclassdef2nclassdef: HashMap[MClassDef, AClassdef])

nitc :: ModelBuilder :: mclassdef2nclassdef=

Registration of the nclassdef associated to each mclassdef
fun mclassdef2node(mclassdef: MClassDef): nullable AClassdef

nitc :: ModelBuilder :: mclassdef2node

Retrieve the associated AST node of a mclassdef.
fun mentity2node(mentity: MEntity): nullable ANode

nitc :: ModelBuilder :: mentity2node

Retrieve the associated AST node of a mentity.
private fun mgroups: HashMap[String, nullable MGroup]

nitc :: ModelBuilder :: mgroups

Groups by path
private fun mgroups=(mgroups: HashMap[String, nullable MGroup])

nitc :: ModelBuilder :: mgroups=

Groups by path
private fun mmodule2nmodule: HashMap[MModule, AModule]

nitc :: ModelBuilder :: mmodule2nmodule

Register the nmodule associated to each mmodule
private fun mmodule2nmodule=(mmodule2nmodule: HashMap[MModule, AModule])

nitc :: ModelBuilder :: mmodule2nmodule=

Register the nmodule associated to each mmodule
fun mmodule2node(mmodule: MModule): nullable AModule

nitc :: ModelBuilder :: mmodule2node

Retrieve the associated AST node of a mmodule.
fun model: Model

nitc :: ModelBuilder :: model

The model where new modules, classes and properties are added
protected fun model=(model: Model)

nitc :: ModelBuilder :: model=

The model where new modules, classes and properties are added
private fun module_absolute_path(path: String): String

nitc :: ModelBuilder :: module_absolute_path

Transform relative paths (starting with '../') into absolute paths
fun mpropdef2node(mpropdef: MPropDef): nullable ANode

nitc :: ModelBuilder :: mpropdef2node

Retrieve the associated AST node of a mpropertydef.
private fun mpropdef2npropdef: HashMap[MPropDef, APropdef]

nitc :: ModelBuilder :: mpropdef2npropdef

Registration of the npropdef associated to each mpropdef.
private fun mpropdef2npropdef=(mpropdef2npropdef: HashMap[MPropDef, APropdef])

nitc :: ModelBuilder :: mpropdef2npropdef=

Registration of the npropdef associated to each mpropdef.
private fun nb_invok_by_direct: Int

nitc :: ModelBuilder :: nb_invok_by_direct

Count number of invocations by direct call
private fun nb_invok_by_direct=(nb_invok_by_direct: Int)

nitc :: ModelBuilder :: nb_invok_by_direct=

Count number of invocations by direct call
private fun nb_invok_by_inline: Int

nitc :: ModelBuilder :: nb_invok_by_inline

Count number of invocations by inlining
private fun nb_invok_by_inline=(nb_invok_by_inline: Int)

nitc :: ModelBuilder :: nb_invok_by_inline=

Count number of invocations by inlining
private fun nb_invok_by_tables: Int

nitc :: ModelBuilder :: nb_invok_by_tables

Count number of invocations by VFT
private fun nb_invok_by_tables=(nb_invok_by_tables: Int)

nitc :: ModelBuilder :: nb_invok_by_tables=

Count number of invocations by VFT
fun nmodules: Array[AModule]

nitc :: ModelBuilder :: nmodules

All the loaded modules
protected fun nmodules=(nmodules: Array[AModule])

nitc :: ModelBuilder :: nmodules=

All the loaded modules
fun parse(modules: Sequence[String]): Array[MModule]

nitc :: ModelBuilder :: parse

Load a bunch of modules.
fun parse_full(names: Sequence[String]): Array[MModule]

nitc :: ModelBuilder :: parse_full

Load a bunch of modules and groups.
fun parsed_modules: Array[MModule]

nitc :: ModelBuilder :: parsed_modules

All the currently parsed modules.
protected fun parsed_modules=(parsed_modules: Array[MModule])

nitc :: ModelBuilder :: parsed_modules=

All the currently parsed modules.
fun paths: Array[String]

nitc :: ModelBuilder :: paths

The list of directories to search for top level modules
protected fun paths=(paths: Array[String])

nitc :: ModelBuilder :: paths=

The list of directories to search for top level modules
private fun process_default_constructors(nclassdef: AClassdef)

nitc :: ModelBuilder :: process_default_constructors

Introduce or inherit default constructor
fun resolve_mtype(mclassdef: MClassDef, ntype: AType): nullable MType

nitc :: ModelBuilder :: resolve_mtype

Return the static type associated to the node ntype.
fun resolve_mtype3(mmodule: MModule, mclass: nullable MClass, anchor: nullable MClassType, ntype: AType): nullable MType

nitc :: ModelBuilder :: resolve_mtype3

Return the static type associated to the node ntype.
fun resolve_mtype3_unchecked(mmodule: MModule, mclass: nullable MClass, anchor: nullable MClassType, ntype: AType, with_virtual: Bool): nullable MType

nitc :: ModelBuilder :: resolve_mtype3_unchecked

Return the static type associated to the node ntype.
fun resolve_mtype_unchecked(mclassdef: MClassDef, ntype: AType, with_virtual: Bool): nullable MType

nitc :: ModelBuilder :: resolve_mtype_unchecked

Return the static type associated to the node ntype.
fun run_global_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)

nitc :: ModelBuilder :: run_global_compiler

Entry point to performs a global compilation on the AST of a complete program.
fun run_java_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)

nitc :: ModelBuilder :: run_java_compiler

Start the Java compiler
fun run_naive_interpreter(mainmodule: MModule, arguments: Array[String])

nitc :: ModelBuilder :: run_naive_interpreter

Execute the program from the entry point (Sys::main) of the mainmodule
fun run_phases

nitc :: ModelBuilder :: run_phases

Run phases on all loaded modules
fun run_separate_compiler(mainmodule: MModule, runtime_type_analysis: nullable RapidTypeAnalysis)

nitc :: ModelBuilder :: run_separate_compiler

fun scan_full(names: Sequence[String]): Array[MModule]

nitc :: ModelBuilder :: scan_full

Identify a bunch of modules and groups.
fun scan_group(mgroup: MGroup)

nitc :: ModelBuilder :: scan_group

Force the identification of all MModule of the group and sub-groups in the file system.
private fun search_group_in_paths(name: String, lookpaths: Collection[String]): ArraySet[MGroup]

nitc :: ModelBuilder :: search_group_in_paths

Search groups named name from paths lookpaths.
fun search_mmodule_by_name(anode: nullable ANode, mgroup: nullable MGroup, name: String): nullable MModule

nitc :: ModelBuilder :: search_mmodule_by_name

Like (and used by) get_mmodule_by_name but does not force the parsing of the MModule (cf. identify_module)
fun search_module_by_amodule_name(n_name: AModuleName, mgroup: nullable MGroup): nullable MModule

nitc :: ModelBuilder :: search_module_by_amodule_name

Resolve the module identification for a given AModuleName.
private fun search_module_in_paths(location: nullable Location, name: String, lookpaths: Collection[String]): nullable MModule

nitc :: ModelBuilder :: search_module_in_paths

Search a module name from path lookpaths.
fun test_group(mgroup: MGroup): HTMLTag

nitc :: ModelBuilder :: test_group

Extracts and executes all the docunits in the readme of the mgroup
fun test_markdown(mmodule: MModule): HTMLTag

nitc :: ModelBuilder :: test_markdown

Extracts and executes all the docunits in the mmodule
fun test_mdoc(mdoc: MDoc): HTMLTag

nitc :: ModelBuilder :: test_mdoc

Test a document object unrelated to a Nit entity
fun test_unit(mmodule: MModule): nullable HTMLTag

nitc :: ModelBuilder :: test_unit

Run NitUnit test suite for mmodule (if it is one).
fun the_root_init_mmethod: nullable MMethod

nitc :: ModelBuilder :: the_root_init_mmethod

the root init of the Object class
protected fun the_root_init_mmethod=(the_root_init_mmethod: nullable MMethod)

nitc :: ModelBuilder :: the_root_init_mmethod=

the root init of the Object class
fun toolcontext: ToolContext

nitc :: ModelBuilder :: toolcontext

The toolcontext used to control the interaction with the user (getting options and displaying messages)
protected fun toolcontext=(toolcontext: ToolContext)

nitc :: ModelBuilder :: toolcontext=

The toolcontext used to control the interaction with the user (getting options and displaying messages)
fun total_classes: Int

nitc :: ModelBuilder :: total_classes

Number of test classes generated.
protected fun total_classes=(total_classes: Int)

nitc :: ModelBuilder :: total_classes=

Number of test classes generated.
fun total_entities: Int

nitc :: ModelBuilder :: total_entities

Total number analyzed MEntity
protected fun total_entities=(total_entities: Int)

nitc :: ModelBuilder :: total_entities=

Total number analyzed MEntity
fun total_tests: Int

nitc :: ModelBuilder :: total_tests

Number of tests generated.
protected fun total_tests=(total_tests: Int)

nitc :: ModelBuilder :: total_tests=

Number of tests generated.
fun try_get_mclass_by_name(anode: nullable ANode, mmodule: MModule, name: String): nullable MClass

nitc :: ModelBuilder :: try_get_mclass_by_name

Return a class named name visible by the module mmodule.
fun try_get_mclass_by_qid(qid: AQclassid, mmodule: MModule): nullable MClass

nitc :: ModelBuilder :: try_get_mclass_by_qid

Return a class identified by qid visible by the module mmodule.
fun try_get_mproperty_by_name(anode: nullable ANode, mclassdef: MClassDef, name: String): nullable MProperty

nitc :: ModelBuilder :: try_get_mproperty_by_name

Alias for try_get_mproperty_by_name2(anode, mclassdef.mmodule, mclassdef.mtype, name)
fun try_get_mproperty_by_name2(anode: nullable ANode, mmodule: MModule, mtype: MType, name: String): nullable MProperty

nitc :: ModelBuilder :: try_get_mproperty_by_name2

Return a property named name on the type mtype visible in the module mmodule.
private fun try_get_mproperty_by_name2_cache=(try_get_mproperty_by_name2_cache: HashMap3[MModule, MType, String, nullable MProperty])

nitc :: ModelBuilder :: try_get_mproperty_by_name2_cache=

fun unit_entities: Int

nitc :: ModelBuilder :: unit_entities

The total number of executed docunits
protected fun unit_entities=(unit_entities: Int)

nitc :: ModelBuilder :: unit_entities=

The total number of executed docunits
fun unsafe_add_mclassdef2nclassdef(mclassdef: MClassDef, nclassdef: AClassdef)

nitc :: ModelBuilder :: unsafe_add_mclassdef2nclassdef

Associate a nclassdef with its mclassdef
fun unsafe_add_mpropdef2npropdef(mpropdef: MPropDef, npropdef: APropdef)

nitc :: ModelBuilder :: unsafe_add_mpropdef2npropdef

Associate a npropdef with its mpropdef
fun warning(n: nullable ANode, tag: String, text: String)

nitc :: ModelBuilder :: warning

Helper function to display a warning on a node.
protected fun write_and_make(compiler: AbstractCompiler)

nitc :: ModelBuilder :: write_and_make

Simple indirection to Toolchain::write_and_make
fun write_and_make(compiler: JavaCompiler)

nitc :: ModelBuilder :: write_and_make

Write Java code and compile it into an executable jar
fun write_java_files(compiler: JavaCompiler): Array[String]

nitc :: ModelBuilder :: write_java_files

Write files managed by compiler into concrete files
fun write_makefile(compiler: JavaCompiler, jfiles: Array[String])

nitc :: ModelBuilder :: write_makefile

Write the Makefile used to compile Java generated files into an executable jar
private fun write_manifest(compiler: JavaCompiler)

nitc :: ModelBuilder :: write_manifest

Write the Java manifest file
private fun write_poset_to_file(compiler: AbstractCompiler, name: String, poset: POSet[Object])

nitc :: ModelBuilder :: write_poset_to_file

Write poset to a C file
private fun write_shell_script(compiler: JavaCompiler)

nitc :: ModelBuilder :: write_shell_script

Write a simple bash script that runs the jar like it was a binary generated by nitc

Redefined properties

redef type SELF: ModelBuilder

nitc $ ModelBuilder :: SELF

Type of this instance, automatically specialized in every class
redef fun build_a_mclass(nmodule: AModule, nclassdef: AClassdef)

nitc :: actors_injection_phase $ ModelBuilder :: build_a_mclass

Visit the AST and create the MClass objects
redef fun build_properties(nclassdef: AClassdef)

nitc :: actors_injection_phase $ ModelBuilder :: build_properties

Build the properties of nclassdef.
redef fun check_subtype(node: ANode, mmodule: MModule, anchor: nullable MClassType, sub: MType, sup: MType): Bool

nitc :: detect_covariance $ ModelBuilder :: check_subtype

Check that sub is a subtype of sup.
redef init init

nitc :: loader $ ModelBuilder :: init

redef init init

nitc $ ModelBuilder :: init

Instantiate a modelbuilder for a model and a toolcontext
redef fun run_naive_interpreter(mainmodule: MModule, arguments: Array[String])

nitc :: test_astbuilder $ ModelBuilder :: run_naive_interpreter

Execute the program from the entry point (Sys::main) of the mainmodule
redef fun write_and_make(compiler: AbstractCompiler)

nitc :: compiler_serialization $ ModelBuilder :: write_and_make

Simple indirection to Toolchain::write_and_make

All properties

fun !=(other: nullable Object): Bool

core :: Object :: !=

Have self and other different values?
fun ==(other: nullable Object): Bool

core :: Object :: ==

Have self and other the same value?
type CLASS: Class[SELF]

core :: Object :: CLASS

The type of the class of self.
type SELF: Object

core :: Object :: SELF

Type of this instance, automatically specialized in every class
private var _bad_class_names: MultiHashMap[MModule, String]

nitc :: ModelBuilder :: _bad_class_names

List of already reported bad class names.
private var _conditional_importations: Array[SequenceRead[MModule]]

nitc :: ModelBuilder :: _conditional_importations

Global list of conditional importation rules.
private var _doc_entities: Int

nitc :: ModelBuilder :: _doc_entities

The number of MEntity that have some documentation
private var _failed_entities: Int

nitc :: ModelBuilder :: _failed_entities

The number failed docunits
private var _failed_tests: Int

nitc :: ModelBuilder :: _failed_tests

Number of failed tests.
private var _identified_modules: Array[MModule]

nitc :: ModelBuilder :: _identified_modules

All the currently identified modules.
private var _identified_modules_by_path: HashMap[String, nullable MModule]

nitc :: ModelBuilder :: _identified_modules_by_path

Cache for identify_module by relative and real paths
private var _last_loader_error: nullable String

nitc :: ModelBuilder :: _last_loader_error

Some loader services are silent and return null on error.
private var _mclassdef2nclassdef: HashMap[MClassDef, AClassdef]

nitc :: ModelBuilder :: _mclassdef2nclassdef

Registration of the nclassdef associated to each mclassdef
private var _mgroups: HashMap[String, nullable MGroup]

nitc :: ModelBuilder :: _mgroups

Groups by path
private var _mmodule2nmodule: HashMap[MModule, AModule]

nitc :: ModelBuilder :: _mmodule2nmodule

Register the nmodule associated to each mmodule
private var _model: Model

nitc :: ModelBuilder :: _model

The model where new modules, classes and properties are added
private var _mpropdef2npropdef: HashMap[MPropDef, APropdef]

nitc :: ModelBuilder :: _mpropdef2npropdef

Registration of the npropdef associated to each mpropdef.
private var _nb_invok_by_direct: Int

nitc :: ModelBuilder :: _nb_invok_by_direct

Count number of invocations by direct call
private var _nb_invok_by_inline: Int

nitc :: ModelBuilder :: _nb_invok_by_inline

Count number of invocations by inlining
private var _nb_invok_by_tables: Int

nitc :: ModelBuilder :: _nb_invok_by_tables

Count number of invocations by VFT
private var _nmodules: Array[AModule]

nitc :: ModelBuilder :: _nmodules

All the loaded modules
private var _parsed_modules: Array[MModule]

nitc :: ModelBuilder :: _parsed_modules

All the currently parsed modules.
private var _paths: Array[String]

nitc :: ModelBuilder :: _paths

The list of directories to search for top level modules
private var _the_root_init_mmethod: nullable MMethod

nitc :: ModelBuilder :: _the_root_init_mmethod

the root init of the Object class
private var _toolcontext: ToolContext

nitc :: ModelBuilder :: _toolcontext

The toolcontext used to control the interaction with the user (getting options and displaying messages)
private var _total_classes: Int

nitc :: ModelBuilder :: _total_classes

Number of test classes generated.
private var _total_entities: Int

nitc :: ModelBuilder :: _total_entities

Total number analyzed MEntity
private var _total_tests: Int

nitc :: ModelBuilder :: _total_tests

Number of tests generated.
private var _unit_entities: Int

nitc :: ModelBuilder :: _unit_entities

The total number of executed docunits
fun advice(n: nullable ANode, tag: String, text: String)

nitc :: ModelBuilder :: advice

Helper function to display an advice on a node.
fun apply_conditional_importations(mmodule: MModule)

nitc :: ModelBuilder :: apply_conditional_importations

Extends the current importations according to imported rules about conditional importation
private fun bad_class_names: MultiHashMap[MModule, String]

nitc :: ModelBuilder :: bad_class_names

List of already reported bad class names.
private fun bad_class_names=(bad_class_names: MultiHashMap[MModule, String])

nitc :: ModelBuilder :: bad_class_names=

List of already reported bad class names.
private fun build_a_bound_mtype(nmodule: AModule, nclassdef: AClassdef): nullable MClassType

nitc :: ModelBuilder :: build_a_bound_mtype

Determine the type parameter bounds for nclassdef.
private fun build_a_mclass(nmodule: AModule, nclassdef: AClassdef)

nitc :: ModelBuilder :: build_a_mclass

Visit the AST and create the MClass objects
private fun build_a_mclassdef(nmodule: AModule, nclassdef: AClassdef)

nitc :: ModelBuilder :: build_a_mclassdef

Visit the AST and create the MClassDef objects
private fun build_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)

nitc :: ModelBuilder :: build_a_mclassdef_inheritance

Visit the AST and set the super-types of the MClassDef objects
private fun build_a_mmodule(mgroup: nullable MGroup, nmodule: AModule)

nitc :: ModelBuilder :: build_a_mmodule

Visit the AST and create the MModule object
private fun build_classes(nmodule: AModule)

nitc :: ModelBuilder :: build_classes

Build the classes of the module nmodule.
fun build_module_importation(nmodule: AModule)

nitc :: ModelBuilder :: build_module_importation

Analyze the module importation and fill the module_importation_hierarchy
private fun build_properties(nclassdef: AClassdef)

nitc :: ModelBuilder :: build_properties

Build the properties of nclassdef.
fun build_with_ant(compiler: JavaCompiler, jfiles: Array[String])

nitc :: ModelBuilder :: build_with_ant

Compile Java sources using ant
fun build_with_make(compiler: JavaCompiler, jfiles: Array[String])

nitc :: ModelBuilder :: build_with_make

Compile Java generated files using make
private fun cache_file(filepath: String): FileWriter

nitc :: ModelBuilder :: cache_file

Cache a file as {filepath}.tmp and replace the original if different
fun check_sametype(node: ANode, mmodule: MModule, anchor: nullable MClassType, sub: MType, sup: MType): Bool

nitc :: ModelBuilder :: check_sametype

Check that sub and sup are equvalent types.
fun check_subtype(node: ANode, mmodule: MModule, anchor: nullable MClassType, sub: MType, sup: MType): Bool

nitc :: ModelBuilder :: check_subtype

Check that sub is a subtype of sup.
private fun check_supertypes(nmodule: AModule, nclassdef: AClassdef)

nitc :: ModelBuilder :: check_supertypes

Check the validity of the specialization heirarchy
fun check_virtual_types_circularity(node: ANode, mproperty: MVirtualTypeProp, recv: MType, mmodule: MModule): Bool

nitc :: ModelBuilder :: check_virtual_types_circularity

Detect circularity errors for virtual types.
fun check_visibility(node: ANode, mtype: MType, mpropdef: MPropDef)

nitc :: ModelBuilder :: check_visibility

Check the visibility of mtype as an element of the signature of mpropdef.
protected fun class_factory(name: String): CLASS

core :: Object :: class_factory

Implementation used by get_class to create the specific class.
fun class_name: String

core :: Object :: class_name

The class name of the object.
fun class_not_found(qid: AQclassid, mmodule: MModule)

nitc :: ModelBuilder :: class_not_found

Print an error and suggest hints when the class identified by qid in mmodule is not found.
private fun close_cache(filepath: String, file: FileWriter)

nitc :: ModelBuilder :: close_cache

Close the writer and move tmp file to original if modified
fun collect_annotations_data(name: String, mmodule: MModule): MModuleData[AAnnotation]

nitc :: ModelBuilder :: collect_annotations_data

Collect all annotations by name in mmodule and its importations (direct and indirect)
fun collect_annotations_on_modules(name: String, mmodule: MModule): Array[AAnnotation]

nitc :: ModelBuilder :: collect_annotations_on_modules

Collect all annotations by name assocated to mmodule and its imported modules.
fun collect_attr_propdef(mclassdef: MClassDef): Array[AAttrPropdef]

nitc :: ModelBuilder :: collect_attr_propdef

Retrieve all the attributes nodes localy definied
private fun collect_supertypes(nmodule: AModule, nclassdef: AClassdef, is_intro: Bool): Array[MClassType]

nitc :: ModelBuilder :: collect_supertypes

List the supertypes specified or implied by nclassdef.
fun compile_antfile(compiler: JavaCompiler, jfiles: Array[String])

nitc :: ModelBuilder :: compile_antfile

The Ant build.xml script used to compile build the final jar
fun conditional_importations: Array[SequenceRead[MModule]]

nitc :: ModelBuilder :: conditional_importations

Global list of conditional importation rules.
protected fun conditional_importations=(conditional_importations: Array[SequenceRead[MModule]])

nitc :: ModelBuilder :: conditional_importations=

Global list of conditional importation rules.
fun create_attribute_from_name(name: String, mclassdef: MClassDef, mtype: MType, visibility: nullable MVisibility): AAttrPropdef

nitc :: ModelBuilder :: create_attribute_from_name

Creation of a new attribute (AST and model representation) with the given name.
fun create_attribute_from_propdef(mattribut_def: MAttributeDef): AAttrPropdef

nitc :: ModelBuilder :: create_attribute_from_propdef

Creation of a new attribute (AST representation) with the given MAttributeDef.
fun create_attribute_from_property(mattribute: MAttribute, mclassdef: MClassDef, mtype: MType): AAttrPropdef

nitc :: ModelBuilder :: create_attribute_from_property

Creation of a new attribute (AST and model representation) with the given MAttribute.
fun create_class_from_mclass(mclass: MClass, super_type: Array[MClassType], mmodule: MModule): AStdClassdef

nitc :: ModelBuilder :: create_class_from_mclass

Creation of a new class (AST and model representation) with the given MClass.
fun create_class_from_mclassdef(mclassdef: MClassDef, mmodule: MModule): AStdClassdef

nitc :: ModelBuilder :: create_class_from_mclassdef

Creation of a new class (AST representation) with the given MClassDef.
fun create_class_from_name(name: String, super_type: Array[MClassType], mmodule: MModule, visibility: nullable MVisibility): AStdClassdef

nitc :: ModelBuilder :: create_class_from_name

Creation of a new class (AST and model representation) with the given name.
fun create_method_from_name(name: String, mclassdef: MClassDef, is_abstract: Bool, msignature: nullable MSignature, visibility: nullable MVisibility): AMethPropdef

nitc :: ModelBuilder :: create_method_from_name

Creation of a new method (AST and model representation) with the given name.
fun create_method_from_property(mproperty: MMethod, mclassdef: MClassDef, is_abstract: Bool, msignature: nullable MSignature): AMethPropdef

nitc :: ModelBuilder :: create_method_from_property

Creation of a new method (AST and model representation) with the given MMethod.
init defaultinit(model: Model, toolcontext: ToolContext)

nitc :: ModelBuilder :: defaultinit

fun do_rapid_type_analysis(mainmodule: MModule): RapidTypeAnalysis

nitc :: ModelBuilder :: do_rapid_type_analysis

Performs a rapid-type-analysis on the program associated with mainmodule.
fun doc_entities: Int

nitc :: ModelBuilder :: doc_entities

The number of MEntity that have some documentation
protected fun doc_entities=(doc_entities: Int)

nitc :: ModelBuilder :: doc_entities=

The number of MEntity that have some documentation
fun error(n: nullable ANode, text: String)

nitc :: ModelBuilder :: error

Helper function to display an error on a node.
fun failed_entities: Int

nitc :: ModelBuilder :: failed_entities

The number failed docunits
protected fun failed_entities=(failed_entities: Int)

nitc :: ModelBuilder :: failed_entities=

The number failed docunits
fun failed_tests: Int

nitc :: ModelBuilder :: failed_tests

Number of failed tests.
protected fun failed_tests=(failed_tests: Int)

nitc :: ModelBuilder :: failed_tests=

Number of failed tests.
fun filter_nit_source(args: Array[String]): Array[String]

nitc :: ModelBuilder :: filter_nit_source

Remove Nit source files from a list of arguments.
fun force_get_primitive_method(n: nullable ANode, name: String, recv: MClass, mmodule: MModule): MMethod

nitc :: ModelBuilder :: force_get_primitive_method

Force to get the primitive method named name on the type recv or do a fatal error on n
fun gen_test_unit(mmodule: MModule)

nitc :: ModelBuilder :: gen_test_unit

Generate NitUnit test file skeleton for mmodule.
fun get_class: CLASS

core :: Object :: get_class

The meta-object representing the dynamic type of self.
fun get_mclass_by_name(node: nullable ANode, mmodule: MModule, name: String): nullable MClass

nitc :: ModelBuilder :: get_mclass_by_name

Like try_get_mclass_by_name but display an error message when the class is not found
private fun get_mmethod(name: String, mclassdef: MClassDef, visibility: nullable MVisibility): MMethod

nitc :: ModelBuilder :: get_mmethod

Try to get MMethod property if exist in the given mclassdef. return new MMethod if not exist.
fun get_mmodule_annotation(name: String, mmodule: MModule): nullable AAnnotation

nitc :: ModelBuilder :: get_mmodule_annotation

Return the single annotation name locally assocated to mmodule, if any.
fun get_mmodule_by_name(anode: nullable ANode, mgroup: nullable MGroup, name: String): nullable MModule

nitc :: ModelBuilder :: get_mmodule_by_name

Get a module by its short name; if required, the module is loaded, parsed and its hierarchies computed.
fun hash: Int

core :: Object :: hash

The hash code of the object.
fun identified_modules: Array[MModule]

nitc :: ModelBuilder :: identified_modules

All the currently identified modules.
protected fun identified_modules=(identified_modules: Array[MModule])

nitc :: ModelBuilder :: identified_modules=

All the currently identified modules.
private fun identified_modules_by_path: HashMap[String, nullable MModule]

nitc :: ModelBuilder :: identified_modules_by_path

Cache for identify_module by relative and real paths
private fun identified_modules_by_path=(identified_modules_by_path: HashMap[String, nullable MModule])

nitc :: ModelBuilder :: identified_modules_by_path=

Cache for identify_module by relative and real paths
fun identify_group(dirpath: String): nullable MGroup

nitc :: ModelBuilder :: identify_group

Return the mgroup associated to a directory path.
fun identify_module(path: String): nullable MModule

nitc :: ModelBuilder :: identify_module

Identify a source file and load the associated package and groups if required.
init init

core :: Object :: init

fun inject_module_subimportation(mmodule: MModule, filename: String)

nitc :: ModelBuilder :: inject_module_subimportation

Load module filename and add it as a conditional importation of mmodule.
fun inspect: String

core :: Object :: inspect

Developer readable representation of self.
protected fun inspect_head: String

core :: Object :: inspect_head

Return "CLASSNAME:#OBJECTID".
intern fun is_same_instance(other: nullable Object): Bool

core :: Object :: is_same_instance

Return true if self and other are the same instance (i.e. same identity).
fun is_same_serialized(other: nullable Object): Bool

core :: Object :: is_same_serialized

Is self the same as other in a serialization context?
intern fun is_same_type(other: Object): Bool

core :: Object :: is_same_type

Return true if self and other have the same dynamic type.
fun last_loader_error: nullable String

nitc :: ModelBuilder :: last_loader_error

Some loader services are silent and return null on error.
protected fun last_loader_error=(last_loader_error: nullable String)

nitc :: ModelBuilder :: last_loader_error=

Some loader services are silent and return null on error.
fun load_markdown(filepath: String): MDoc

nitc :: ModelBuilder :: load_markdown

Load a markdown file as a documentation object
fun load_module(filename: String): nullable AModule

nitc :: ModelBuilder :: load_module

Try to load a module using a path.
fun load_module_ast(filename: String): nullable AModule

nitc :: ModelBuilder :: load_module_ast

Try to load a module AST using a path.
fun load_rt_module(parent: nullable MModule, nmodule: AModule, mod_name: String): nullable MModule

nitc :: ModelBuilder :: load_rt_module

Injection of a new module without source.
fun lookup_annotation_on_modules(name: String, mmodule: MModule): nullable AAnnotation

nitc :: ModelBuilder :: lookup_annotation_on_modules

Get an annotation by name from mmodule and its super modules. Will recursively search
private fun match_amodulename(n_name: AModuleName, m: MModule): Bool

nitc :: ModelBuilder :: match_amodulename

Is elements of n_name correspond to the group nesting of m?
private fun mclassdef2nclassdef: HashMap[MClassDef, AClassdef]

nitc :: ModelBuilder :: mclassdef2nclassdef

Registration of the nclassdef associated to each mclassdef
private fun mclassdef2nclassdef=(mclassdef2nclassdef: HashMap[MClassDef, AClassdef])

nitc :: ModelBuilder :: mclassdef2nclassdef=

Registration of the nclassdef associated to each mclassdef
fun mclassdef2node(mclassdef: MClassDef): nullable AClassdef

nitc :: ModelBuilder :: mclassdef2node

Retrieve the associated AST node of a mclassdef.
fun mentity2node(mentity: MEntity): nullable ANode

nitc :: ModelBuilder :: mentity2node

Retrieve the associated AST node of a mentity.
private fun mgroups: HashMap[String, nullable MGroup]

nitc :: ModelBuilder :: mgroups

Groups by path
private fun mgroups=(mgroups: HashMap[String, nullable MGroup])

nitc :: ModelBuilder :: mgroups=

Groups by path
private fun mmodule2nmodule: HashMap[MModule, AModule]

nitc :: ModelBuilder :: mmodule2nmodule

Register the nmodule associated to each mmodule
private fun mmodule2nmodule=(mmodule2nmodule: HashMap[MModule, AModule])

nitc :: ModelBuilder :: mmodule2nmodule=

Register the nmodule associated to each mmodule
fun mmodule2node(mmodule: MModule): nullable AModule

nitc :: ModelBuilder :: mmodule2node

Retrieve the associated AST node of a mmodule.
fun model: Model

nitc :: ModelBuilder :: model

The model where new modules, classes and properties are added
protected fun model=(model: Model)

nitc :: ModelBuilder :: model=

The model where new modules, classes and properties are added
private fun module_absolute_path(path: String): String

nitc :: ModelBuilder :: module_absolute_path

Transform relative paths (starting with '../') into absolute paths
fun mpropdef2node(mpropdef: MPropDef): nullable ANode

nitc :: ModelBuilder :: mpropdef2node

Retrieve the associated AST node of a mpropertydef.
private fun mpropdef2npropdef: HashMap[MPropDef, APropdef]

nitc :: ModelBuilder :: mpropdef2npropdef

Registration of the npropdef associated to each mpropdef.
private fun mpropdef2npropdef=(mpropdef2npropdef: HashMap[MPropDef, APropdef])

nitc :: ModelBuilder :: mpropdef2npropdef=

Registration of the npropdef associated to each mpropdef.
private intern fun native_class_name: CString

core :: Object :: native_class_name

The class name of the object in CString format.
private fun nb_invok_by_direct: Int

nitc :: ModelBuilder :: nb_invok_by_direct

Count number of invocations by direct call
private fun nb_invok_by_direct=(nb_invok_by_direct: Int)

nitc :: ModelBuilder :: nb_invok_by_direct=

Count number of invocations by direct call
private fun nb_invok_by_inline: Int

nitc :: ModelBuilder :: nb_invok_by_inline

Count number of invocations by inlining
private fun nb_invok_by_inline=(nb_invok_by_inline: Int)

nitc :: ModelBuilder :: nb_invok_by_inline=

Count number of invocations by inlining
private fun nb_invok_by_tables: Int

nitc :: ModelBuilder :: nb_invok_by_tables

Count number of invocations by VFT
private fun nb_invok_by_tables=(nb_invok_by_tables: Int)

nitc :: ModelBuilder :: nb_invok_by_tables=

Count number of invocations by VFT
fun nmodules: Array[AModule]

nitc :: ModelBuilder :: nmodules

All the loaded modules
protected fun nmodules=(nmodules: Array[AModule])

nitc :: ModelBuilder :: nmodules=

All the loaded modules
intern fun object_id: Int

core :: Object :: object_id

An internal hash code for the object based on its identity.
fun output

core :: Object :: output

Display self on stdout (debug only).
intern fun output_class_name

core :: Object :: output_class_name

Display class name on stdout (debug only).
fun parse(modules: Sequence[String]): Array[MModule]

nitc :: ModelBuilder :: parse

Load a bunch of modules.
fun parse_full(names: Sequence[String]): Array[MModule]

nitc :: ModelBuilder :: parse_full

Load a bunch of modules and groups.
fun parsed_modules: Array[MModule]

nitc :: ModelBuilder :: parsed_modules

All the currently parsed modules.
protected fun parsed_modules=(parsed_modules: Array[MModule])

nitc :: ModelBuilder :: parsed_modules=

All the currently parsed modules.
fun paths: Array[String]

nitc :: ModelBuilder :: paths

The list of directories to search for top level modules
protected fun paths=(paths: Array[String])

nitc :: ModelBuilder :: paths=

The list of directories to search for top level modules
private fun process_default_constructors(nclassdef: AClassdef)

nitc :: ModelBuilder :: process_default_constructors

Introduce or inherit default constructor
fun resolve_mtype(mclassdef: MClassDef, ntype: AType): nullable MType

nitc :: ModelBuilder :: resolve_mtype

Return the static type associated to the node ntype.
fun resolve_mtype3(mmodule: MModule, mclass: nullable MClass, anchor: nullable MClassType, ntype: AType): nullable MType

nitc :: ModelBuilder :: resolve_mtype3

Return the static type associated to the node ntype.
fun resolve_mtype3_unchecked(mmodule: MModule, mclass: nullable MClass, anchor: nullable MClassType, ntype: AType, with_virtual: Bool): nullable MType

nitc :: ModelBuilder :: resolve_mtype3_unchecked

Return the static type associated to the node ntype.
fun resolve_mtype_unchecked(mclassdef: MClassDef, ntype: AType, with_virtual: Bool): nullable MType

nitc :: ModelBuilder :: resolve_mtype_unchecked

Return the static type associated to the node ntype.
fun run_global_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)

nitc :: ModelBuilder :: run_global_compiler

Entry point to performs a global compilation on the AST of a complete program.
fun run_java_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)

nitc :: ModelBuilder :: run_java_compiler

Start the Java compiler
fun run_naive_interpreter(mainmodule: MModule, arguments: Array[String])

nitc :: ModelBuilder :: run_naive_interpreter

Execute the program from the entry point (Sys::main) of the mainmodule
fun run_phases

nitc :: ModelBuilder :: run_phases

Run phases on all loaded modules
fun run_separate_compiler(mainmodule: MModule, runtime_type_analysis: nullable RapidTypeAnalysis)

nitc :: ModelBuilder :: run_separate_compiler

fun scan_full(names: Sequence[String]): Array[MModule]

nitc :: ModelBuilder :: scan_full

Identify a bunch of modules and groups.
fun scan_group(mgroup: MGroup)

nitc :: ModelBuilder :: scan_group

Force the identification of all MModule of the group and sub-groups in the file system.
private fun search_group_in_paths(name: String, lookpaths: Collection[String]): ArraySet[MGroup]

nitc :: ModelBuilder :: search_group_in_paths

Search groups named name from paths lookpaths.
fun search_mmodule_by_name(anode: nullable ANode, mgroup: nullable MGroup, name: String): nullable MModule

nitc :: ModelBuilder :: search_mmodule_by_name

Like (and used by) get_mmodule_by_name but does not force the parsing of the MModule (cf. identify_module)
fun search_module_by_amodule_name(n_name: AModuleName, mgroup: nullable MGroup): nullable MModule

nitc :: ModelBuilder :: search_module_by_amodule_name

Resolve the module identification for a given AModuleName.
private fun search_module_in_paths(location: nullable Location, name: String, lookpaths: Collection[String]): nullable MModule

nitc :: ModelBuilder :: search_module_in_paths

Search a module name from path lookpaths.
fun serialization_hash: Int

core :: Object :: serialization_hash

Hash value use for serialization
intern fun sys: Sys

core :: Object :: sys

Return the global sys object, the only instance of the Sys class.
fun test_group(mgroup: MGroup): HTMLTag

nitc :: ModelBuilder :: test_group

Extracts and executes all the docunits in the readme of the mgroup
fun test_markdown(mmodule: MModule): HTMLTag

nitc :: ModelBuilder :: test_markdown

Extracts and executes all the docunits in the mmodule
fun test_mdoc(mdoc: MDoc): HTMLTag

nitc :: ModelBuilder :: test_mdoc

Test a document object unrelated to a Nit entity
fun test_unit(mmodule: MModule): nullable HTMLTag

nitc :: ModelBuilder :: test_unit

Run NitUnit test suite for mmodule (if it is one).
fun the_root_init_mmethod: nullable MMethod

nitc :: ModelBuilder :: the_root_init_mmethod

the root init of the Object class
protected fun the_root_init_mmethod=(the_root_init_mmethod: nullable MMethod)

nitc :: ModelBuilder :: the_root_init_mmethod=

the root init of the Object class
abstract fun to_jvalue(env: JniEnv): JValue

core :: Object :: to_jvalue

fun to_s: String

core :: Object :: to_s

User readable representation of self.
fun toolcontext: ToolContext

nitc :: ModelBuilder :: toolcontext

The toolcontext used to control the interaction with the user (getting options and displaying messages)
protected fun toolcontext=(toolcontext: ToolContext)

nitc :: ModelBuilder :: toolcontext=

The toolcontext used to control the interaction with the user (getting options and displaying messages)
fun total_classes: Int

nitc :: ModelBuilder :: total_classes

Number of test classes generated.
protected fun total_classes=(total_classes: Int)

nitc :: ModelBuilder :: total_classes=

Number of test classes generated.
fun total_entities: Int

nitc :: ModelBuilder :: total_entities

Total number analyzed MEntity
protected fun total_entities=(total_entities: Int)

nitc :: ModelBuilder :: total_entities=

Total number analyzed MEntity
fun total_tests: Int

nitc :: ModelBuilder :: total_tests

Number of tests generated.
protected fun total_tests=(total_tests: Int)

nitc :: ModelBuilder :: total_tests=

Number of tests generated.
fun try_get_mclass_by_name(anode: nullable ANode, mmodule: MModule, name: String): nullable MClass

nitc :: ModelBuilder :: try_get_mclass_by_name

Return a class named name visible by the module mmodule.
fun try_get_mclass_by_qid(qid: AQclassid, mmodule: MModule): nullable MClass

nitc :: ModelBuilder :: try_get_mclass_by_qid

Return a class identified by qid visible by the module mmodule.
fun try_get_mproperty_by_name(anode: nullable ANode, mclassdef: MClassDef, name: String): nullable MProperty

nitc :: ModelBuilder :: try_get_mproperty_by_name

Alias for try_get_mproperty_by_name2(anode, mclassdef.mmodule, mclassdef.mtype, name)
fun try_get_mproperty_by_name2(anode: nullable ANode, mmodule: MModule, mtype: MType, name: String): nullable MProperty

nitc :: ModelBuilder :: try_get_mproperty_by_name2

Return a property named name on the type mtype visible in the module mmodule.
private fun try_get_mproperty_by_name2_cache=(try_get_mproperty_by_name2_cache: HashMap3[MModule, MType, String, nullable MProperty])

nitc :: ModelBuilder :: try_get_mproperty_by_name2_cache=

fun unit_entities: Int

nitc :: ModelBuilder :: unit_entities

The total number of executed docunits
protected fun unit_entities=(unit_entities: Int)

nitc :: ModelBuilder :: unit_entities=

The total number of executed docunits
fun unsafe_add_mclassdef2nclassdef(mclassdef: MClassDef, nclassdef: AClassdef)

nitc :: ModelBuilder :: unsafe_add_mclassdef2nclassdef

Associate a nclassdef with its mclassdef
fun unsafe_add_mpropdef2npropdef(mpropdef: MPropDef, npropdef: APropdef)

nitc :: ModelBuilder :: unsafe_add_mpropdef2npropdef

Associate a npropdef with its mpropdef
fun warning(n: nullable ANode, tag: String, text: String)

nitc :: ModelBuilder :: warning

Helper function to display a warning on a node.
fun write_and_make(compiler: JavaCompiler)

nitc :: ModelBuilder :: write_and_make

Write Java code and compile it into an executable jar
protected fun write_and_make(compiler: AbstractCompiler)

nitc :: ModelBuilder :: write_and_make

Simple indirection to Toolchain::write_and_make
fun write_java_files(compiler: JavaCompiler): Array[String]

nitc :: ModelBuilder :: write_java_files

Write files managed by compiler into concrete files
fun write_makefile(compiler: JavaCompiler, jfiles: Array[String])

nitc :: ModelBuilder :: write_makefile

Write the Makefile used to compile Java generated files into an executable jar
private fun write_manifest(compiler: JavaCompiler)

nitc :: ModelBuilder :: write_manifest

Write the Java manifest file
private fun write_poset_to_file(compiler: AbstractCompiler, name: String, poset: POSet[Object])

nitc :: ModelBuilder :: write_poset_to_file

Write poset to a C file
private fun write_shell_script(compiler: JavaCompiler)

nitc :: ModelBuilder :: write_shell_script

Write a simple bash script that runs the jar like it was a binary generated by nitc
package_diagram nitc::ModelBuilder ModelBuilder core::Object Object nitc::ModelBuilder->core::Object

Parents

interface Object

core :: Object

The root of the class hierarchy.

Class definitions

nitc $ ModelBuilder
# A model builder knows how to load nit source files and build the associated model
class ModelBuilder
	# The model where new modules, classes and properties are added
	var model: Model

	# The toolcontext used to control the interaction with the user (getting options and displaying messages)
	var toolcontext: ToolContext

	# Instantiate a modelbuilder for a model and a toolcontext
	# Important, the options of the toolcontext must be correctly set (parse_option already called)
	init
	do
		assert toolcontext.modelbuilder_real == null
		toolcontext.modelbuilder_real = self
	end

	# Return a class named `name` visible by the module `mmodule`.
	# Visibility in modules is correctly handled.
	# If no such a class exists, then null is returned.
	# If more than one class exists, then an error on `anode` is displayed and null is returned.
	# FIXME: add a way to handle class name conflict
	fun try_get_mclass_by_name(anode: nullable ANode, mmodule: MModule, name: String): nullable MClass
	do
		var classes = model.get_mclasses_by_name(name)
		if classes == null then
			return null
		end

		var res: nullable MClass = null
		for mclass in classes do
			if not mmodule.in_importation <= mclass.intro_mmodule then continue
			if not mmodule.is_visible(mclass.intro_mmodule, mclass.visibility) then continue
			if res == null then
				res = mclass
			else
				error(anode, "Error: ambiguous class name `{name}`; conflict between `{mclass.full_name}` and `{res.full_name}`.")
				return null
			end
		end
		return res
	end

	# Return a class identified by `qid` visible by the module `mmodule`.
	# Visibility in modules and qualified names are correctly handled.
	#
	# If more than one class exists, then null is silently returned.
	# It is up to the caller to post-analysis the result and display a correct error message.
	# The method `class_not_found` can be used to display such a message.
	fun try_get_mclass_by_qid(qid: AQclassid, mmodule: MModule): nullable MClass
	do
		var name = qid.n_id.text

		var classes = model.get_mclasses_by_name(name)
		if classes == null then
			return null
		end

		var res: nullable MClass = null
		for mclass in classes do
			if not mmodule.in_importation <= mclass.intro_mmodule then continue
			if not mmodule.is_visible(mclass.intro_mmodule, mclass.visibility) then continue
			if not qid.accept(mclass) then continue
			if res == null then
				res = mclass
			else
				return null
			end
		end

		return res
	end

	# Like `try_get_mclass_by_name` but display an error message when the class is not found
	fun get_mclass_by_name(node: nullable ANode, mmodule: MModule, name: String): nullable MClass
	do
		var mclass = try_get_mclass_by_name(node, mmodule, name)
		if mclass == null then
			error(node, "Type Error: missing primitive class `{name}'.")
		end
		return mclass
	end

	# Return a property named `name` on the type `mtype` visible in the module `mmodule`.
	# Visibility in modules is correctly handled.
	# Protected properties are returned (it is up to the caller to check and reject protected properties).
	# If no such a property exists, then null is returned.
	# If more than one property exists, then an error on `anode` is displayed and null is returned.
	# FIXME: add a way to handle property name conflict
	fun try_get_mproperty_by_name2(anode: nullable ANode, mmodule: MModule, mtype: MType, name: String): nullable MProperty
	do
		var props = self.model.get_mproperties_by_name(name)
		if props == null then
			return null
		end

		var cache = self.try_get_mproperty_by_name2_cache[mmodule, mtype, name]
		if cache != null then return cache

		var res: nullable MProperty = null
		var ress: nullable Array[MProperty] = null
		for mprop in props do
			if not mtype.has_mproperty(mmodule, mprop) then continue
			if not mmodule.is_visible(mprop.intro_mclassdef.mmodule, mprop.visibility) then continue

			# new-factories are invisible outside of the class
			if mprop isa MMethod and mprop.is_new and (not mtype isa MClassType or mprop.intro_mclassdef.mclass != mtype.mclass) then
				continue
			end

			if res == null then
				res = mprop
				continue
			end

			# Two global properties?
			# First, special case for init, keep the most specific ones
			if res isa MMethod and mprop isa MMethod and res.is_init and mprop.is_init then
				var restype = res.intro_mclassdef.bound_mtype
				var mproptype = mprop.intro_mclassdef.bound_mtype
				if mproptype.is_subtype(mmodule, null, restype) then
					# found a most specific constructor, so keep it
					res = mprop
					continue
				end
			end

			# Ok, just keep all prop in the ress table
			if ress == null then
				ress = new Array[MProperty]
				ress.add(res)
			end
			ress.add(mprop)
		end

		# There is conflict?
		if ress != null and res isa MMethod and res.is_init then
			# special case forinit again
			var restype = res.intro_mclassdef.bound_mtype
			var ress2 = new Array[MProperty]
			for mprop in ress do
				var mproptype = mprop.intro_mclassdef.bound_mtype
				if not restype.is_subtype(mmodule, null, mproptype) then
					ress2.add(mprop)
				else if not mprop isa MMethod or not mprop.is_init then
					ress2.add(mprop)
				end
			end
			if ress2.is_empty then
				ress = null
			else
				ress = ress2
				ress.add(res)
			end
		end

		if ress != null then
			assert ress.length > 1
			var s = new Array[String]
			for mprop in ress do s.add mprop.full_name
			self.error(anode, "Error: ambiguous property name `{name}` for `{mtype}`; conflict between {s.join(" and ")}.")
		end

		self.try_get_mproperty_by_name2_cache[mmodule, mtype, name] = res
		return res
	end

	private var try_get_mproperty_by_name2_cache = new HashMap3[MModule, MType, String, nullable MProperty]


	# Alias for try_get_mproperty_by_name2(anode, mclassdef.mmodule, mclassdef.mtype, name)
	fun try_get_mproperty_by_name(anode: nullable ANode, mclassdef: MClassDef, name: String): nullable MProperty
	do
		return try_get_mproperty_by_name2(anode, mclassdef.mmodule, mclassdef.bound_mtype, name)
	end

	# Helper function to display an error on a node.
	# Alias for `self.toolcontext.error(n.hot_location, text)`
	#
	# This automatically sets `n.is_broken` to true.
	fun error(n: nullable ANode, text: String)
	do
		var l = null
		if n != null then
			l = n.hot_location
			n.is_broken = true
		end
		self.toolcontext.error(l, text)
	end

	# Helper function to display a warning on a node.
	# Alias for: `self.toolcontext.warning(n.hot_location, text)`
	fun warning(n: nullable ANode, tag, text: String)
	do
		var l = null
		if n != null then l = n.hot_location
		self.toolcontext.warning(l, tag, text)
	end

	# Helper function to display an advice on a node.
	# Alias for: `self.toolcontext.advice(n.hot_location, text)`
	fun advice(n: nullable ANode, tag, text: String)
	do
		var l = null
		if n != null then l = n.hot_location
		self.toolcontext.advice(l, tag, text)
	end

	# Force to get the primitive method named `name` on the type `recv` or do a fatal error on `n`
	fun force_get_primitive_method(n: nullable ANode, name: String, recv: MClass, mmodule: MModule): MMethod
	do
		var res = mmodule.try_get_primitive_method(name, recv)
		if res == null then
			var l = null
			if n != null then l = n.hot_location
			self.toolcontext.fatal_error(l, "Fatal Error: `{recv}` must have a property named `{name}`.")
			abort
		end
		return res
	end

	# Return the static type associated to the node `ntype`.
	#
	# `mclassdef` is the context where the call is made (used to understand
	# formal types).
	# In case of problem, an error is displayed on `ntype` and null is returned.
	#
	# Same as `resolve_mtype_unchecked3`, but get the context (module, class and
	# anchor) from `mclassdef`.
	#
	# SEE: `resolve_mtype`
	# SEE: `resolve_mtype3_unchecked`
	#
	# FIXME: Find a better name for this method.
	fun resolve_mtype_unchecked(mclassdef: MClassDef, ntype: AType, with_virtual: Bool): nullable MType
	do
		return resolve_mtype3_unchecked(
			mclassdef.mmodule,
			mclassdef.mclass,
			mclassdef.bound_mtype,
			ntype,
			with_virtual
		)
	end

	# Return the static type associated to the node `ntype`.
	#
	# `mmodule`, `mclass` and `anchor` compose the context where the call is
	# made (used to understand formal types).
	# In case of problem, an error is displayed on `ntype` and null is returned.
	#
	# Note: The “3” is for 3 contextual parameters.
	#
	# SEE: `resolve_mtype`
	# SEE: `resolve_mtype_unchecked`
	#
	# FIXME: Find a better name for this method.
	fun resolve_mtype3_unchecked(mmodule: MModule, mclass: nullable MClass, anchor: nullable MClassType, ntype: AType, with_virtual: Bool): nullable MType
	do
		var qid = ntype.n_qid
		var name = qid.n_id.text
		var res: MType

		# Check virtual type
		if anchor != null and with_virtual then
			var prop = try_get_mproperty_by_name2(ntype, mmodule, anchor, name).as(nullable MVirtualTypeProp)
			if prop != null then
				if not ntype.n_types.is_empty then
					error(ntype, "Type Error: formal type `{name}` cannot have formal parameters.")
				end
				res = prop.mvirtualtype
				if ntype.n_kwnullable != null then res = res.as_nullable
				ntype.mtype = res
				return res
			end
		end

		# Check parameter type
		if mclass != null then
			for p in mclass.mparameters do
				if p.name != name then continue

				if not ntype.n_types.is_empty then
					error(ntype, "Type Error: formal type `{name}` cannot have formal parameters.")
				end

				res = p
				if ntype.n_kwnullable != null then res = res.as_nullable
				ntype.mtype = res
				return res
			end
		end

		# Check class
		var found_class = try_get_mclass_by_qid(qid, mmodule)
		if found_class != null then
			var arity = ntype.n_types.length
			if arity != found_class.arity then
				if arity == 0 then
					error(ntype, "Type Error: `{found_class.signature_to_s}` is a generic class.")
				else if found_class.arity == 0 then
					error(ntype, "Type Error: `{name}` is not a generic class.")
				else
					error(ntype, "Type Error: expected {found_class.arity} formal argument(s) for `{found_class.signature_to_s}`; got {arity}.")
				end
				return null
			end
			if arity == 0 then
				res = found_class.mclass_type
				if ntype.n_kwnullable != null then res = res.as_nullable
				ntype.mtype = res
				return res
			else
				var mtypes = new Array[MType]
				for nt in ntype.n_types do
					var mt = resolve_mtype3_unchecked(mmodule, mclass, anchor, nt, with_virtual)
					if mt == null then return null # Forward error
					mtypes.add(mt)
				end
				res = found_class.get_mtype(mtypes)
				if ntype.n_kwnullable != null then res = res.as_nullable
				ntype.mtype = res
				return res
			end
		end

		# If everything fail, then give up with class by proposing things.
		#
		# TODO Give hints on formal types (param and virtual)
		class_not_found(qid, mmodule)
		ntype.is_broken = true
		return null
	end

	# Print an error and suggest hints when the class identified by `qid` in `mmodule` is not found.
	#
	# This just print error messages.
	fun class_not_found(qid: AQclassid, mmodule: MModule)
	do
		var name = qid.n_id.text
		var qname = qid.full_name

		if bad_class_names[mmodule].has(qname) then
			error(qid, "Error: class `{qname}` not found in module `{mmodule}`.")
			return
		end
		bad_class_names[mmodule].add(qname)

		var all_classes = model.get_mclasses_by_name(name)
		var hints = new Array[String]

		# Look for conflicting classes.
		if all_classes != null then for c in all_classes do
			if not mmodule.is_visible(c.intro_mmodule, c.visibility) then continue
			if not qid.accept(c) then continue
			hints.add "`{c.full_name}`"
		end
		if hints.length > 1 then
			error(qid, "Error: ambiguous class name `{qname}` in module `{mmodule}`. Conflicts are between {hints.join(",", " and ")}.")
			return
		end
		hints.clear

		# Look for imported but invisible classes.
		if all_classes != null then for c in all_classes do
			if not mmodule.in_importation <= c.intro_mmodule then continue
			if mmodule.is_visible(c.intro_mmodule, c.visibility) then continue
			if not qid.accept(c) then continue
			error(qid, "Error: class `{c.full_name}` not visible in module `{mmodule}`.")
			return
		end

		# Look for not imported but known classes from importable modules
		if all_classes != null then for c in all_classes do
			if mmodule.in_importation <= c.intro_mmodule then continue
			if c.intro_mmodule.in_importation <= mmodule then continue
			if c.visibility <= private_visibility then continue
			if not qid.accept(c) then continue
			hints.add "`{c.intro_mmodule.full_name}`"
		end
		if hints.not_empty then
			error(qid, "Error: class `{qname}` not found in module `{mmodule}`. Maybe import {hints.join(",", " or ")}?")
			return
		end

		# Look for classes with an approximative name.
		var bests = new BestDistance[MClass](qname.length - name.length / 2) # limit up to 50% name change
		for c in model.mclasses do
			if not mmodule.in_importation <= c.intro_mmodule then continue
			if not mmodule.is_visible(c.intro_mmodule, c.visibility) then continue
			var d = qname.levenshtein_distance(c.name)
			bests.update(d, c)
			d = qname.levenshtein_distance(c.full_name)
			bests.update(d, c)
		end
		if bests.best_items.not_empty then
			for c in bests.best_items do hints.add "`{c.full_name}`"
			error(qid, "Error: class `{qname}` not found in module `{mmodule}`. Did you mean {hints.join(",", " or ")}?")
			return
		end

		error(qid, "Error: class `{qname}` not found in module `{mmodule}`.")
	end

	# List of already reported bad class names.
	# Used to not perform and repeat hints again and again.
	private var bad_class_names = new MultiHashMap[MModule, String]

	# Return the static type associated to the node `ntype`.
	#
	# `mclassdef` is the context where the call is made (used to understand
	# formal types).
	# In case of problem, an error is displayed on `ntype` and null is returned.
	#
	# Same as `resolve_mtype3`, but get the context (module, class and ) from
	# `mclassdef`.
	#
	# SEE: `resolve_mtype3`
	# SEE: `resolve_mtype_unchecked`
	#
	# FIXME: Find a better name for this method.
	fun resolve_mtype(mclassdef: MClassDef, ntype: AType): nullable MType
	do
		return resolve_mtype3(
			mclassdef.mmodule,
			mclassdef.mclass,
			mclassdef.bound_mtype,
			ntype
		)
	end

	# Return the static type associated to the node `ntype`.
	#
	# `mmodule`, `mclass` and `anchor` compose the context where the call is
	# made (used to understand formal types).
	# In case of problem, an error is displayed on `ntype` and null is returned.
	#
	# Note: The “3” is for 3 contextual parameters.
	#
	# SEE: `resolve_mtype`
	# SEE: `resolve_mtype_unchecked`
	#
	# FIXME: Find a better name for this method.
	fun resolve_mtype3(mmodule: MModule, mclass: nullable MClass, anchor: nullable MClassType, ntype: AType): nullable MType
	do
		var mtype = ntype.mtype
		if mtype == null then mtype = resolve_mtype3_unchecked(mmodule, mclass, anchor, ntype, true)
		if mtype == null then return null # Forward error

		if ntype.checked_mtype then return mtype
		if mtype isa MGenericType then
			var found_class = mtype.mclass
			for i in [0..found_class.arity[ do
				var intro = found_class.try_intro
				if intro == null then return null # skip error
				var bound = intro.bound_mtype.arguments[i]
				var nt = ntype.n_types[i]
				var mt = resolve_mtype3(mmodule, mclass, anchor, nt)
				if mt == null then return null # forward error
				if not check_subtype(nt, mmodule, anchor, mt, bound) then
					error(nt, "Type Error: expected `{bound}`, got `{mt}`.")
					return null
				end
			end
		end
		ntype.checked_mtype = true
		return mtype
	end

	# Check that `sub` is a subtype of `sup`.
	# Do not display an error message.
	#
	# This method is used a an entry point for the modelize phase to test static subtypes.
	# Some refinements could redefine it to collect statictics.
	fun check_subtype(node: ANode, mmodule: MModule, anchor: nullable MClassType, sub, sup: MType): Bool
	do
		return sub.is_subtype(mmodule, anchor, sup)
	end

	# Check that `sub` and `sup` are equvalent types.
	# Do not display an error message.
	#
	# This method is used a an entry point for the modelize phase to test static equivalent types.
	# Some refinements could redefine it to collect statictics.
	fun check_sametype(node: ANode, mmodule: MModule, anchor: nullable MClassType, sub, sup: MType): Bool
	do
		return sub.is_subtype(mmodule, anchor, sup) and sup.is_subtype(mmodule, anchor, sub)
	end
end
src/modelbuilder_base.nit:42,1--529,3

nitc :: loader $ ModelBuilder
redef class ModelBuilder
	redef init
	do
		super

		# Setup the paths value
		paths.append(toolcontext.opt_path.value)

		# Packages managed by nitpm, only use when not testing with tests.sh
		if "NIT_TESTING_TESTS_SH".environ != "true" then
			paths.add nitpm_lib_dir
		end

		var path_env = "NIT_PATH".environ
		if not path_env.is_empty then
			paths.append(path_env.split_with(':'))
		end

		var nit_dir = toolcontext.nit_dir
		if nit_dir != null then
			var libname = nit_dir/"lib"
			if libname.file_exists then paths.add(libname)
			libname = nit_dir/"contrib"
			if libname.file_exists then paths.add(libname)
		end
	end

	# Load a bunch of modules.
	# `modules` can contains filenames or module names.
	# Imported modules are automatically loaded and modelized.
	# The result is the corresponding model elements.
	# Errors and warnings are printed with the toolcontext.
	#
	# Note: class and property model elements are not analysed.
	fun parse(modules: Sequence[String]): Array[MModule]
	do
		var time0 = get_time
		# Parse and recursively load
		self.toolcontext.info("*** PARSE ***", 1)
		var mmodules = new ArraySet[MModule]
		for a in modules do
			var nmodule = self.load_module(a)
			if nmodule == null then continue # Skip error
			var mmodule = nmodule.mmodule
			if mmodule == null then continue # skip error
			mmodules.add mmodule
		end
		var time1 = get_time
		self.toolcontext.info("*** END PARSE: {time1-time0} ***", 2)

		self.toolcontext.check_errors

		if toolcontext.opt_only_parse.value then
			self.toolcontext.info("*** ONLY PARSE...", 1)
			self.toolcontext.quit
		end

		return mmodules.to_a
	end

	# Identify a bunch of modules and groups.
	#
	# This does the same as `parse_full` but does only the identification (cf. `identify_module`)
	fun scan_full(names: Sequence[String]): Array[MModule]
	do
		var mmodules = new Array[MModule]
		for a in names do
			# Case of a group (root or sub-directory)
			var mgroup = self.identify_group(a)
			if mgroup != null then
				scan_group(mgroup)
				for mg in mgroup.in_nesting.smallers do mmodules.add_all mg.mmodules
				continue
			end

			# Case of a directory that is not a group
			var stat = a.to_path.stat
			if stat != null and stat.is_dir then
				self.toolcontext.info("look in directory {a}", 2)
				var fs = a.files
				alpha_comparator.sort(fs)
				# Try each entry as a group or a module
				for f in fs do
					if f.first == '.' then continue
					var af = a/f
					mgroup = identify_group(af)
					if mgroup != null then
						scan_group(mgroup)
						for mg in mgroup.in_nesting.smallers do mmodules.add_all mg.mmodules
						continue
					end
					var mmodule = identify_module(af)
					if mmodule != null then
						mmodules.add mmodule
					else
						self.toolcontext.info("ignore file {af}", 2)
					end
				end
				continue
			end

			var mmodule = identify_module(a)
			if mmodule == null then
				var le = last_loader_error
				if le != null then
					toolcontext.error(null, le)
				else if a.file_exists then
					toolcontext.error(null, "Error: `{a}` is not a Nit source file.")
				else
					toolcontext.error(null, "Error: cannot find module `{a}`.")
				end
				continue
			end

			mmodules.add mmodule
		end
		return mmodules
	end

	# Load a bunch of modules and groups.
	#
	# Each name can be:
	#
	# * a path to a module, a group or a directory of packages.
	# * a short name of a module or a group that are looked in the `paths` (-I)
	#
	# Then, for each entry, if it is:
	#
	# * a module, then is it parsed and returned.
	# * a group then recursively all its modules are parsed.
	# * a directory of packages then all the modules of all packages are parsed.
	# * else an error is displayed.
	#
	# See `parse` for details.
	fun parse_full(names: Sequence[String]): Array[MModule]
	do
		var time0 = get_time
		# Parse and recursively load
		self.toolcontext.info("*** PARSE ***", 1)
		var mmodules = new ArraySet[MModule]
		var scans = scan_full(names)
		for mmodule in scans do
			var ast = mmodule.load(self)
			if ast == null then continue # Skip error
			mmodules.add mmodule
		end
		var time1 = get_time
		self.toolcontext.info("*** END PARSE: {time1-time0} ***", 2)

		self.toolcontext.check_errors

		if toolcontext.opt_only_parse.value then
			self.toolcontext.info("*** ONLY PARSE...", 1)
			self.toolcontext.quit
		end

		return mmodules.to_a
	end

	# The list of directories to search for top level modules
	# The list is initially set with:
	#
	#   * the toolcontext --path option
	#   * the NIT_PATH environment variable
	#   * `toolcontext.nit_dir`
	# Path can be added (or removed) by the client
	var paths = new Array[String]

	# Like (and used by) `get_mmodule_by_name` but does not force the parsing of the MModule (cf. `identify_module`)
	fun search_mmodule_by_name(anode: nullable ANode, mgroup: nullable MGroup, name: String): nullable MModule
	do
		# First, look in groups
		var c = mgroup
		if c != null then
			var r = c.mpackage.root
			assert r != null
			scan_group(r)
			var res = r.mmodules_by_name(name)
			if res.not_empty then return res.first
		end

		# Look at some known directories
		var lookpaths = self.paths

		# Look in the directory of the group package also (even if not explicitly in the path)
		if mgroup != null then
			# path of the root group
			var dirname = mgroup.mpackage.root.filepath
			if dirname != null then
				dirname = dirname.join_path("..").simplify_path
				if not lookpaths.has(dirname) and dirname.file_exists then
					lookpaths = lookpaths.to_a
					lookpaths.add(dirname)
				end
			end
		end

		if mgroup != null then
			var alias = mgroup.mpackage.import_alias(name)
			if alias != null then name = alias
		end

		var loc = null
		if anode != null then loc = anode.hot_location
		var candidate = search_module_in_paths(loc, name, lookpaths)

		if candidate == null then
			if mgroup != null then
				error(anode, "Error: cannot find module `{name}` from `{mgroup.name}`. Tried: {lookpaths.join(", ")}.")
			else
				error(anode, "Error: cannot find module `{name}`. Tried: {lookpaths.join(", ")}.")
			end
			return null
		end
		return candidate
	end

	# Get a module by its short name; if required, the module is loaded, parsed and its hierarchies computed.
	# If `mgroup` is set, then the module search starts from it up to the top level (see `paths`);
	# if `mgroup` is null then the module is searched in the top level only.
	# If no module exists or there is a name conflict, then an error on `anode` is displayed and null is returned.
	fun get_mmodule_by_name(anode: nullable ANode, mgroup: nullable MGroup, name: String): nullable MModule
	do
		var mmodule = search_mmodule_by_name(anode, mgroup, name)
		if mmodule == null then return null # Forward error
		var ast = mmodule.load(self)
		if ast == null then return null # Forward error
		return mmodule
	end

	# Search a module `name` from path `lookpaths`.
	# If found, the module is returned.
	private fun search_module_in_paths(location: nullable Location, name: String, lookpaths: Collection[String]): nullable MModule
	do
		var name_no_version
		if name.has('=') then
			name_no_version = name.split('=').first
		else name_no_version = name

		var res = new ArraySet[MModule]
		for dirname in lookpaths do
			# Try a single module file
			var mp = identify_module((dirname/"{name}.nit").simplify_path)
			if mp != null then res.add mp
			# Try the default module of a group
			var g = identify_group((dirname/name).simplify_path)
			if g != null then
				scan_group(g)
				res.add_all g.mmodules_by_name(name_no_version)
			end
		end
		if res.is_empty then return null
		if res.length > 1 then
			toolcontext.error(location, "Error: conflicting module files for `{name}`: `{[for x in res do x.filepath or else x.full_name].join("`, `")}`")
		end
		return res.first
	end

	# Search groups named `name` from paths `lookpaths`.
	private fun search_group_in_paths(name: String, lookpaths: Collection[String]): ArraySet[MGroup]
	do
		var res = new ArraySet[MGroup]
		for dirname in lookpaths do
			# try a single group directory
			var mg = identify_group(dirname/name)
			if mg != null then
				res.add mg
			end
		end
		return res
	end

	# Cache for `identify_module` by relative and real paths
	private var identified_modules_by_path = new HashMap[String, nullable MModule]

	# All the currently identified modules.
	# See `identify_module`.
	#
	# An identified module exists in the model but might be not yet parsed (no AST), or not yet analysed (no importation).
	var identified_modules = new Array[MModule]

	# All the currently parsed modules.
	#
	# A parsed module exists in the model but might be not yet analysed (no importation).
	var parsed_modules = new Array[MModule]

	# Some `loader` services are silent and return `null` on error.
	#
	# Those services can set `last_loader_error` to precise an specific error message.
	# if `last_loader_error == null` then a generic error message can be used.
	#
	# See `identified_modules` and `identify_group` for details.
	var last_loader_error: nullable String = null

	# Identify a source file and load the associated package and groups if required.
	#
	# This method does what the user expects when giving an argument to a Nit tool.
	#
	# * If `path` is an existing Nit source file (with the `.nit` extension),
	#   then the associated MModule is returned
	# * If `path` is a directory (with a `/`),
	#   then the MModule of its default module is returned (if any)
	# * If `path` is a simple identifier (eg. `digraph`),
	#   then the main module of the package `digraph` is searched in `paths` and returned.
	#
	# Silently return `null` if `path` does not exists or cannot be identified.
	# If `null` is returned, `last_loader_error` can be set to a specific error message.
	#
	# On success, it returns a module that is possibly not yet parsed (no AST), or not yet analysed (no importation).
	# If the module was already identified, or loaded, it is returned.
	fun identify_module(path: String): nullable MModule
	do
		last_loader_error = null

		# special case for not a nit file
		if not path.has_suffix(".nit") then do
			# search dirless files in known -I paths
			if not path.chars.has('/') then
				var res = search_module_in_paths(null, path, self.paths)
				if res != null then return res
			end

			# Found nothing? maybe it is a group...
			if path.file_exists then
				var mgroup = identify_group(path)
				if mgroup != null then
					var owner_path = mgroup.filepath.join_path(mgroup.name + ".nit")
					if owner_path.file_exists then
						path = owner_path
						break
					end
				end
			end

			# Found nothing? maybe it is a qualified name
			if path.chars.has(':') then
				var ids = path.split("::")
				var g = identify_group(ids.first)
				if g != null then
					scan_group(g)
					var ms = g.mmodules_by_name(ids.last)

					# Return exact match
					for m in ms do
						if m.full_name == path then
							return m
						end
					end

					# Where there is only one or two names `foo::bar`
					# then accept module that matches `foo::*::bar`
					if ids.length <= 2 then
						if ms.length == 1 then return ms.first
						if ms.length > 1 then
							var l = new Array[String]
							for m in ms do
								var fp = m.filepath
								if fp != null then fp = " ({fp})" else fp = ""
								l.add "`{m.full_name}`{fp}"
							end
							last_loader_error = "Error: conflicting module for `{path}`: {l.join(", ")} "
							return null
						end
					end

					var bests = new BestDistance[String](path.length / 2)
					# We found nothing. But propose something in the package?
					for sg in g.mpackage.mgroups do
						for m in sg.mmodules do
							var d = path.levenshtein_distance(m.full_name)
							bests.update(d, m.full_name)
						end
					end
					var last_loader_error = "Error: cannot find module `{path}`."
					if bests.best_items.not_empty then
						last_loader_error += " Did you mean " + bests.best_items.join(", ", " or ") + "?"
					end
					self.last_loader_error = last_loader_error
					return null
				end
			end

			return null
		end

		# Does the file exists?
		if not path.file_exists then
			return null
		end

		# Fast track, the path is already known
		if identified_modules_by_path.has_key(path) then return identified_modules_by_path[path]
		var rp = module_absolute_path(path)
		if identified_modules_by_path.has_key(rp) then return identified_modules_by_path[rp]

		var pn = path.basename(".nit")

		# Search for a group
		var mgrouppath = path.join_path("..").simplify_path
		var mgroup = identify_group(mgrouppath)

		if mgroup != null then
			var mpackage = mgroup.mpackage
			if not mpackage.accept(path) then
				mgroup = null
				toolcontext.info("module `{path}` excluded from package `{mpackage}`", 2)
			end
		end
		if mgroup == null then
			# singleton package
			var loc = new Location.opaque_file(path)
			var mpackage = new MPackage(pn, model, loc)
			mgroup = new MGroup(pn, loc, mpackage, null) # same name for the root group
			mpackage.root = mgroup
			toolcontext.info("found singleton package `{pn}` at {path}", 2)

			# Attach homonymous `ini` file to the package
			var inipath = path.dirname / "{pn}.ini"
			if inipath.file_exists then
				var ini = new IniFile.from_file(inipath)
				mpackage.ini = ini
			end
		end

		var loc = new Location.opaque_file(path)
		var res = new MModule(model, mgroup, pn, loc)

		identified_modules_by_path[rp] = res
		identified_modules_by_path[path] = res
		identified_modules.add(res)
		return res
	end

	# Groups by path
	private var mgroups = new HashMap[String, nullable MGroup]

	# Return the mgroup associated to a directory path.
	# If the directory is not a group null is returned.
	#
	# Silently return `null` if `dirpath` does not exists, is not a directory,
	# cannot be identified or cannot be attached to a mpackage.
	# If `null` is returned, `last_loader_error` can be set to a specific error message.
	#
	# Note: `paths` is also used to look for mgroups
	fun identify_group(dirpath: String): nullable MGroup
	do
		# Reset error
		last_loader_error = null

		var stat = dirpath.file_stat

		if stat == null or not stat.is_dir then do
			# search dirless directories in known -I paths
			if dirpath.chars.has('/') then return null
			for p in paths do
				var try = p / dirpath
				stat = try.file_stat
				if stat != null then
					dirpath = try
					break label
				end
			end
			return null
		end label

		# Filter out non-directories
		if not stat.is_dir then
			last_loader_error = "Error: `{dirpath}` is not a directory."
			return null
		end

		# Fast track, the path is already known
		var rdp = module_absolute_path(dirpath)
		if mgroups.has_key(rdp) then
			return mgroups[rdp]
		end

		# By default, the name of the package or group is the base_name of the directory
		var pn = rdp.basename

		# Check `package.ini` that indicate a package
		var ini = null
		var parent = null
		var inipath = dirpath / "package.ini"
		if inipath.file_exists then
			ini = new IniFile.from_file(inipath)
		end

		if ini == null then
			# No ini, multiple course of action

			# The root of the directory hierarchy in the file system.
			if rdp == "/" then
				mgroups[rdp] = null
				last_loader_error = "Error: `{dirpath}` is not a Nit package."
				return null
			end

			# Special stopper `packages.ini`
			if (dirpath/"packages.ini").file_exists then
				# dirpath cannot be a package since it is a package directory
				mgroups[rdp] = null
				last_loader_error = "Error: `{dirpath}` is not a Nit package."
				return null
			end

			# check the parent directory (if it does not contain the stopper file)
			var parentpath = dirpath.join_path("..").simplify_path
			var stopper = parentpath / "packages.ini"
			if not stopper.file_exists then
				# Recursively get the parent group
				parent = identify_group(parentpath)
				if parent != null then do
					var mpackage = parent.mpackage
					if not mpackage.accept(dirpath) then
						toolcontext.info("directory `{dirpath}` excluded from package `{mpackage}`", 2)
						parent = null
					end
				end
				if parent == null then
					# Parent is not a group, thus we are not a group either
					mgroups[rdp] = null
					last_loader_error = "Error: `{dirpath}` is not a Nit package."
					return null
				end
			end
		end

		var loc = new Location.opaque_file(dirpath)
		var mgroup
		if parent == null then
			# no parent, thus new package
			if ini != null then pn = ini["package.name"] or else pn
			var mpackage = new MPackage(pn, model, loc)
			mgroup = new MGroup(pn, loc, mpackage, null) # same name for the root group
			mpackage.root = mgroup
			toolcontext.info("found package `{mpackage}` at {dirpath}", 2)
			mpackage.ini = ini
		else
			mgroup = new MGroup(pn, loc, parent.mpackage, parent)
			toolcontext.info("found sub group `{mgroup.full_name}` at {dirpath}", 2)
		end

		# search documentation
		# in src first so the documentation of the package code can be distinct for the documentation of the package usage
		var readme = dirpath.join_path("README.md")
		if not readme.file_exists then readme = dirpath.join_path("README")
		if readme.file_exists then
			var mdoc = load_markdown(readme)
			mgroup.mdoc = mdoc
			mdoc.original_mentity = mgroup
		end

		mgroups[rdp] = mgroup
		return mgroup
	end

	# Load a markdown file as a documentation object
	fun load_markdown(filepath: String): MDoc
	do
		var s = new FileReader.open(filepath)
		var lines = new Array[String]
		var line_starts = new Array[Int]
		var len = 1
		while not s.eof do
			var line = s.read_line
			lines.add(line)
			line_starts.add(len)
			len += line.length + 1
		end
		s.close
		var source = new SourceFile.from_string(filepath, lines.join("\n"))
		source.line_starts.add_all line_starts
		var mdoc = new MDoc(new Location(source, 1, lines.length, 0, 0))
		mdoc.content.add_all(lines)
		return mdoc
	end

	# Force the identification of all MModule of the group and sub-groups in the file system.
	#
	# When a group is scanned, its sub-groups hierarchy is filled (see `MGroup::in_nesting`)
	# and the potential modules (and nested modules) are identified (see `MGroup::modules`).
	#
	# Basically, this recursively call `identify_group` and `identify_module` on each directory entry.
	#
	# No-op if the group was already scanned (see `MGroup::scanned`).
	fun scan_group(mgroup: MGroup) do
		if mgroup.scanned then return
		mgroup.scanned = true
		var p = mgroup.filepath
		# a virtual group has nothing to scan
		if p == null then return
		var files = p.files
		alpha_comparator.sort(files)
		for f in files do
			if f.first == '.' then continue
			var fp = p/f
			var g = identify_group(fp)
			# Recursively scan for groups of the same package
			if g == null then
				identify_module(fp)
			else if g.mpackage == mgroup.mpackage then
				scan_group(g)
			end
		end
	end

	# Transform relative paths (starting with '../') into absolute paths
	private fun module_absolute_path(path: String): String do
		return path.realpath
	end

	# Try to load a module AST using a path.
	# Display an error if there is a problem (IO / lexer / parser) and return null
	#
	# The AST is loaded as is total independence of the model and its entities.
	#
	# AST are not cached or reused thus a new AST is returned on success.
	fun load_module_ast(filename: String): nullable AModule
	do
		if not filename.has_suffix(".nit") then
			self.toolcontext.error(null, "Error: file `{filename}` is not a valid nit module.")
			return null
		end
		if not filename.file_exists then
			self.toolcontext.error(null, "Error: file `{filename}` not found.")
			return null
		end

		self.toolcontext.info("load module {filename}", 2)

		# Load the file
		var file = new FileReader.open(filename)
		var lexer = new Lexer(new SourceFile(filename, file))
		var parser = new Parser(lexer)
		var tree = parser.parse
		file.close

		# Handle lexer and parser error
		var nmodule = tree.n_base
		if nmodule == null then
			var neof = tree.n_eof
			assert neof isa AError
			error(neof, neof.message)
			return null
		end

		return nmodule
	end

	# Remove Nit source files from a list of arguments.
	#
	# Items of `args` that can be loaded as a nit file will be removed from `args` and returned.
	fun filter_nit_source(args: Array[String]): Array[String]
	do
		var keep = new Array[String]
		var res = new Array[String]
		for a in args do
			var stat = a.to_path.stat
			if stat != null and stat.is_dir then
				res.add a
				continue
			end
			var l = identify_module(a)
			if l == null then
				keep.add a
			else
				res.add a
			end
		end
		args.clear
		args.add_all(keep)
		return res
	end

	# Try to load a module using a path.
	# Display an error if there is a problem (IO / lexer / parser) and return null.
	# Note: usually, you do not need this method, use `get_mmodule_by_name` instead.
	#
	# The MModule is located, created, parsed and the importation is performed.
	fun load_module(filename: String): nullable AModule
	do
		# Look for the module
		var mmodule = identify_module(filename)
		if mmodule == null then
			var le = last_loader_error
			if le != null then
				toolcontext.error(null, le)
			else if filename.file_exists then
				toolcontext.error(null, "Error: `{filename}` is not a Nit source file.")
			else
				toolcontext.error(null, "Error: cannot find module `{filename}`.")
			end
			return null
		end

		# Load it
		return mmodule.load(self)
	end

	# Injection of a new module without source.
	# Used by the interpreter.
	fun load_rt_module(parent: nullable MModule, nmodule: AModule, mod_name: String): nullable MModule
	do
		# Create the module

		var mgroup = null
		if parent != null then mgroup = parent.mgroup
		var mmodule = new MModule(model, mgroup, mod_name, nmodule.location)
		nmodule.mmodule = mmodule
		nmodules.add(nmodule)
		parsed_modules.add mmodule
		self.mmodule2nmodule[mmodule] = nmodule

		if parent!= null then
			var imported_modules = new Array[MModule]
			imported_modules.add(parent)
			mmodule.set_visibility_for(parent, intrude_visibility)
			mmodule.set_imported_mmodules(imported_modules)
		end
		build_module_importation(nmodule)

		return mmodule
	end

	# Visit the AST and create the `MModule` object
	private fun build_a_mmodule(mgroup: nullable MGroup, nmodule: AModule)
	do
		var mmodule = nmodule.mmodule
		assert mmodule != null

		# Check the module name
		var decl = nmodule.n_moduledecl
		if decl != null then
			var decl_name = decl.n_name.n_id.text
			if decl_name != mmodule.name then
				warning(decl.n_name, "module-name-mismatch", "Error: module name mismatch; declared {decl_name} file named {mmodule.name}.")
			end
		end

		# Check for conflicting module names in the package
		if mgroup != null then
			var others = model.get_mmodules_by_name(mmodule.name)
			if others != null then for other in others do
				if other != mmodule and mmodule2nmodule.has_key(mmodule) and other.mgroup!= null and other.mgroup.mpackage == mgroup.mpackage then
					var node: ANode
					if decl == null then node = nmodule else node = decl.n_name
					error(node, "Error: a module named `{other.full_name}` already exists at {other.location}.")
					break
				end
			end
		end

		nmodules.add(nmodule)
		self.mmodule2nmodule[mmodule] = nmodule

		var source = nmodule.location.file
		if source != null then
			assert source.mmodule == null
			source.mmodule = mmodule
		end

		if decl != null then
			# Extract documentation
			var ndoc = decl.n_doc
			if ndoc != null then
				var mdoc = ndoc.to_mdoc
				mmodule.mdoc = mdoc
				mdoc.original_mentity = mmodule
			end
			# Is the module generated?
			mmodule.is_generated = not decl.get_annotations("generated").is_empty
		end
	end

	# Resolve the module identification for a given `AModuleName`.
	#
	# This method handles qualified names as used in `AModuleName`.
	fun search_module_by_amodule_name(n_name: AModuleName, mgroup: nullable MGroup): nullable MModule
	do
		var mod_name = n_name.n_id.text

		# If a quad is given, we ignore the starting group (go from path)
		if n_name.n_quad != null then mgroup = null

		# If name not qualified, just search the name
		if n_name.n_path.is_empty then
			# Fast search if no n_path
			return search_mmodule_by_name(n_name, mgroup, mod_name)
		end

		# If qualified and in a group
		if mgroup != null then
			# First search in the package
			var r = mgroup.mpackage.root
			assert r != null
			scan_group(r)
			# Get all modules with the final name
			var res = r.mmodules_by_name(mod_name)
			# Filter out the name that does not match the qualifiers
			res = [for x in res do if match_amodulename(n_name, x) then x]
			if res.not_empty then
				if res.length > 1 then
					error(n_name, "Error: conflicting module files for `{mod_name}`: `{[for x in res do x.filepath or else x.full_name].join("`, `")}`")
				end
				return res.first
			end
		end

		# If no module yet, then assume that the first element of the path
		# Is to be searched in the path.
		var root_name = n_name.n_path.first.text

		# Search for an alias in required external packages
		if mgroup != null then
			var alias = mgroup.mpackage.import_alias(root_name)
			if alias != null then root_name = alias
		end

		var roots = search_group_in_paths(root_name, paths)
		if roots.is_empty then
			error(n_name, "Error: cannot find `{root_name}`. Tried: {paths.join(", ")}.")
			return null
		end

		var res = new ArraySet[MModule]
		for r in roots do
			# Then, for each root, collect modules that matches the qualifiers
			scan_group(r)
			var root_res = r.mmodules_by_name(mod_name)
			for x in root_res do if match_amodulename(n_name, x) then res.add x
		end
		if res.not_empty then
			if res.length > 1 then
				error(n_name, "Error: conflicting module files for `{mod_name}`: `{[for x in res do x.filepath or else x.full_name].join("`, `")}`")
			end
			return res.first
		end
		# If still nothing, just call a basic search that will fail and will produce an error message
		error(n_name, "Error: cannot find module `{mod_name}` from `{root_name}`. Tried: {paths.join(", ")}.")
		return null
	end

	# Is elements of `n_name` correspond to the group nesting of `m`?
	#
	# Basically it check that `bar::foo` matches `bar/foo.nit` and `bar/baz/foo.nit`
	# but not `baz/foo.nit` nor `foo/bar.nit`
	#
	# Is used by `search_module_by_amodule_name` to validate qualified names.
	private fun match_amodulename(n_name: AModuleName, m: MModule): Bool
	do
		var g: nullable MGroup = m.mgroup
		for grp in n_name.n_path.reverse_iterator do
			while g != null and grp.text != g.name do
				g = g.parent
			end
		end
		return g != null
	end

	# Analyze the module importation and fill the module_importation_hierarchy
	#
	# If the importation was already done (`nmodule.is_importation_done`), this method does a no-op.
	#
	# REQUIRE `nmodule.mmodule != null`
	# ENSURE `nmodule.is_importation_done`
	fun build_module_importation(nmodule: AModule)
	do
		if nmodule.is_importation_done then return
		nmodule.is_importation_done = true
		var mmodule = nmodule.mmodule.as(not null)
		var stdimport = true
		var imported_modules = new Array[MModule]
		for aimport in nmodule.n_imports do
			# Do not imports conditional
			var atconditionals = aimport.get_annotations("conditional")
			if atconditionals.not_empty then continue

			stdimport = false
			if not aimport isa AStdImport then
				continue
			end

			# Load the imported module
			var sup = search_module_by_amodule_name(aimport.n_name, mmodule.mgroup)
			if sup == null then
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
				continue # Skip error
			end
			var ast = sup.load(self)
			if ast == null then
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
				continue # Skip error
			end

			aimport.mmodule = sup
			imported_modules.add(sup)
			var mvisibility = aimport.n_visibility.mvisibility
			if mvisibility == protected_visibility then
				mmodule.is_broken = true
				error(aimport.n_visibility, "Error: only properties can be protected.")
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
				return
			end
			if sup == mmodule then
				error(aimport.n_name, "Error: dependency loop in module {mmodule}.")
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
			end
			if sup.in_importation < mmodule then
				error(aimport.n_name, "Error: dependency loop between modules {mmodule} and {sup}.")
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
				return
			end
			mmodule.set_visibility_for(sup, mvisibility)
		end
		if stdimport then
			var mod_name = "core"
			var sup = self.get_mmodule_by_name(nmodule, null, mod_name)
			if sup == null then
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
			else # Skip error
				imported_modules.add(sup)
				mmodule.set_visibility_for(sup, public_visibility)
			end
		end

		# Declare conditional importation
		for aimport in nmodule.n_imports do
			if not aimport isa AStdImport then continue
			var atconditionals = aimport.get_annotations("conditional")
			if atconditionals.is_empty then continue

			var suppath = search_module_by_amodule_name(aimport.n_name, mmodule.mgroup)
			if suppath == null then continue # skip error

			for atconditional in atconditionals do
				var nargs = atconditional.n_args
				if nargs.is_empty then
					error(atconditional, "Syntax Error: `conditional` expects module identifiers as arguments.")
					continue
				end

				# The rule
				var rule = new Array[MModule]

				# First element is the goal, thus
				rule.add suppath

				# Second element is the first condition, that is to be a client of the current module
				rule.add mmodule

				# Other condition are to be also a client of each modules indicated as arguments of the annotation
				for narg in nargs do
					var id = narg.as_id
					if id == null then
						error(narg, "Syntax Error: `conditional` expects module identifier as arguments.")
						continue
					end

					var mp = search_mmodule_by_name(narg, mmodule.mgroup, id)
					if mp == null then continue

					rule.add mp
				end

				conditional_importations.add rule
			end
		end

		mmodule.set_imported_mmodules(imported_modules)

		apply_conditional_importations(mmodule)

		self.toolcontext.info("{mmodule} imports {mmodule.in_importation.direct_greaters.join(", ")}", 3)

		# Force `core` to be public if imported
		for sup in mmodule.in_importation.greaters do
			if sup.name == "core" then
				mmodule.set_visibility_for(sup, public_visibility)
			end
		end

		# TODO: Correctly check for useless importation
		# It is even doable?
		var directs = mmodule.in_importation.direct_greaters
		for nim in nmodule.n_imports do
			if not nim isa AStdImport then continue
			var im = nim.mmodule
			if im == null then continue
			if directs.has(im) then continue
			# This generates so much noise that it is simpler to just comment it
			#warning(nim, "Warning: possible useless importation of {im}")
		end
	end

	# Global list of conditional importation rules.
	#
	# Each rule is a "Horn clause"-like sequence of modules.
	# It means that the first module is the module to automatically import.
	# The remaining modules are the conditions of the rule.
	#
	# Rules are declared by `build_module_importation` and are applied by `apply_conditional_importations`
	# (and `build_module_importation` that calls it).
	#
	# TODO (when the loader will be rewritten): use a better representation and move up rules in the model.
	var conditional_importations = new Array[SequenceRead[MModule]]

	# Extends the current importations according to imported rules about conditional importation
	fun apply_conditional_importations(mmodule: MModule)
	do
		# Because a conditional importation may cause additional conditional importation, use a fixed point
		# The rules are checked naively because we assume that it does not worth to be optimized
		var check_conditional_importations = true
		while check_conditional_importations do
			check_conditional_importations = false

			for ci in conditional_importations do
				# Check conditions
				for i in [1..ci.length[ do
					var m = ci[i]
					# Is imported?
					if mmodule == m or not mmodule.in_importation.greaters.has(m) then continue label
				end
				# Still here? It means that all conditions modules are loaded and imported

				# Identify the module to automatically import
				var sup = ci.first
				var ast = sup.load(self)
				if ast == null then continue

				# Do nothing if already imported
				if mmodule.in_importation.greaters.has(sup) then continue label

				# Import it
				self.toolcontext.info("{mmodule} conditionally imports {sup}", 3)
				# TODO visibility rules (currently always public)
				mmodule.set_visibility_for(sup, public_visibility)
				# TODO linearization rules (currently added at the end in the order of the rules)
				mmodule.set_imported_mmodules([sup])

				# Prepare to reapply the rules
				check_conditional_importations = true
			end label
		end
	end

	# All the loaded modules
	var nmodules = new Array[AModule]

	# Register the nmodule associated to each mmodule
	#
	# Public clients need to use `mmodule2node` to access stuff.
	private var mmodule2nmodule = new HashMap[MModule, AModule]

	# Retrieve the associated AST node of a mmodule.
	# This method is used to associate model entity with syntactic entities.
	#
	# If the module is not associated with a node, returns null.
	fun mmodule2node(mmodule: MModule): nullable AModule
	do
		return mmodule2nmodule.get_or_null(mmodule)
	end
end
src/loader.nit:61,1--1129,3

nitc :: modelbuilder $ ModelBuilder
redef class ModelBuilder
	# Run phases on all loaded modules
	fun run_phases
	do
		var mmodules = parsed_modules.to_a
		model.mmodule_importation_hierarchy.sort(mmodules)
		var nmodules = new Array[AModule]
		for mm in mmodules do
			if mm.is_fictive then continue
			nmodules.add(mmodule2node(mm).as(not null))
		end
		toolcontext.run_phases(nmodules)

		if toolcontext.opt_only_metamodel.value then
			self.toolcontext.info("*** ONLY METAMODEL", 1)
			toolcontext.quit
		end
	end

	# Load module `filename` and add it as a conditional importation of `mmodule`.
	#
	# This means that current (and future) submodules of `module` will also import `filename`.
	fun inject_module_subimportation(mmodule: MModule, filename: String)
	do
		var am = load_module(filename)
		if am == null then return # forward error
		var mm = am.mmodule
		if mm == null then return # forward error
		# Add the new module before the existing submodules in the hierarchy
		for subm in mmodule.in_importation.direct_smallers do
			subm.set_imported_mmodules([mm])
		end
		# Register the new module as a conditional_importations for future submodules
		conditional_importations.add([mm, mmodule])
		# Register the new amodule to be processed by `run_phases`
		toolcontext.todo_nmodules.unshift am
	end
end
src/modelbuilder.nit:91,1--128,3

nitc :: modelize_class $ ModelBuilder
redef class ModelBuilder
	# Visit the AST and create the `MClass` objects
	private fun build_a_mclass(nmodule: AModule, nclassdef: AClassdef)
	do
		var mmodule = nmodule.mmodule.as(not null)

		var name: String
		var nkind: nullable AClasskind
		var mkind: MClassKind
		var nvisibility: nullable AVisibility
		var mvisibility: nullable MVisibility
		var arity = 0
		var names = new Array[String]
		var mclass
		if nclassdef isa AStdClassdef then
			var qid = nclassdef.n_qid
			assert qid != null
			name = qid.n_id.text
			nkind = nclassdef.n_classkind
			mkind = nkind.mkind
			nvisibility = nclassdef.n_visibility
			mvisibility = nvisibility.mvisibility
			arity = nclassdef.n_formaldefs.length
			if mvisibility == protected_visibility then
				error(nvisibility, "Error: only properties can be protected.")
				return
			else if mvisibility == intrude_visibility then
				error(nvisibility, "Error: intrude is not a legal visibility for classes.")
				return
			end
			# Collect formal parameter names
			for i in [0..arity[ do
				var nfd = nclassdef.n_formaldefs[i]
				var ptname = nfd.n_id.text
				if names.has(ptname) then
					error(nfd, "Error: a formal parameter type `{ptname}` already exists.")
					return
				end
				for c in ptname.chars do if c >= 'a' and c<= 'z' then
					warning(nfd, "formal-type-name", "Warning: lowercase in the formal parameter type `{ptname}`.")
					break
				end
				names.add(ptname)
			end
			mclass = try_get_mclass_by_qid(qid, mmodule)
			if mclass == null and (qid.n_qualified != null or nclassdef.n_kwredef != null) then
				class_not_found(qid, mmodule)
				nclassdef.is_broken = true
				return
			end

		else if nclassdef isa ATopClassdef and nclassdef.n_propdefs.first.as(AMethPropdef).n_methid.collect_text == "sys" then
			# Special case to keep `sys` in object.
			# Needed to keep working bootstrap and a working java FFI together.
			# TODO: remove once safe to remove
			name = "Object"
			nkind = null
			mkind = interface_kind
			nvisibility = null
			mvisibility = public_visibility
			mclass = try_get_mclass_by_name(nclassdef, mmodule, name)
		else
			name = "Sys"
			nkind = null
			mkind = concrete_kind
			nvisibility = null
			mvisibility = public_visibility
			mclass = try_get_mclass_by_name(nclassdef, mmodule, name)
		end

		if mclass == null then
			# Check for conflicting class full-names in the package
			if mmodule.mgroup != null and mvisibility >= protected_visibility then
				var mclasses = model.get_mclasses_by_name(name)
				if mclasses != null then for other in mclasses do
					if other.intro_mmodule.mgroup != null and other.intro_mmodule.mgroup.mpackage == mmodule.mgroup.mpackage then
						# Skip classes that are buggy
						if other.try_intro == null then continue
						warning(nclassdef, "full-name-conflict", "Error: a class named `{other.full_name}` is already defined in module `{other.intro_mmodule}` at {other.intro.location}.")
						break
					end
				end
			end

			mclass = new MClass(mmodule, name, nclassdef.location, names, mkind, mvisibility)
			#print "new class {mclass}"
		else if nclassdef isa AStdClassdef and nmodule.mclass2nclassdef.has_key(mclass) then
			error(nclassdef, "Error: a class `{name}` is already defined at line {nmodule.mclass2nclassdef[mclass].location.line_start}.")
			mclass.is_broken = true
			return
		else if nclassdef isa AStdClassdef and nclassdef.n_kwredef == null then
			error(nclassdef, "Redef Error: `{name}` is an imported class. Add the `redef` keyword to refine it.")
			mclass.is_broken = true
			return
		else if arity != 0 and mclass.arity != arity then
			error(nclassdef, "Redef Error: expected {mclass.arity} formal parameter(s) for {mclass.signature_to_s}; got {arity}.")
			mclass.is_broken = true
			return
		else if nkind != null and mkind != concrete_kind and mclass.kind != mkind then
			error(nkind, "Redef Error: refinement changed the kind from `{mclass.kind}` to `{mkind}`.")
		else if nvisibility != null and mvisibility != public_visibility and mclass.visibility != mvisibility then
			error(nvisibility, "Redef Error: refinement changed the visibility from `{mclass.visibility}` to `{mvisibility}`")
		end
		nclassdef.mclass = mclass
		if not nmodule.mclass2nclassdef.has_key(mclass) then
			nmodule.mclass2nclassdef[mclass] = nclassdef
			nclassdef.all_defs = [nclassdef]
		else
			nmodule.mclass2nclassdef[mclass].all_defs.add(nclassdef)
		end
	end

	# Visit the AST and create the `MClassDef` objects
	private fun build_a_mclassdef(nmodule: AModule, nclassdef: AClassdef)
	do
		var mmodule = nmodule.mmodule.as(not null)
		var mclass = nclassdef.mclass
		if mclass == null then return # Skip error

		# In case of non-standard AClassdef, try to attach to an already existing mclassdef
		var other_nclassdef = nmodule.mclass2nclassdef[mclass]
		if other_nclassdef != nclassdef then
			assert not nclassdef isa AStdClassdef
			nclassdef.mclassdef = other_nclassdef.mclassdef
			return
		end

		var bound_mtype = build_a_bound_mtype(nmodule, nclassdef)
		if bound_mtype == null then return
		var mclassdef = new MClassDef(mmodule, bound_mtype, nclassdef.location)
		nclassdef.mclassdef = mclassdef
		self.mclassdef2nclassdef[mclassdef] = nclassdef

		if nclassdef isa AStdClassdef then
			var ndoc = nclassdef.n_doc
			if ndoc != null then
				var mdoc = ndoc.to_mdoc
				mclassdef.mdoc = mdoc
				mdoc.original_mentity = mclassdef
			else if mclassdef.is_intro and mclass.visibility >= public_visibility then
				advice(nclassdef, "missing-doc", "Documentation warning: Undocumented public class `{mclass}`")
			end
		end

		if mclassdef.is_intro then
			self.toolcontext.info("{mclassdef} introduces new {mclass.kind} {mclass.full_name}", 3)
		else
			self.toolcontext.info("{mclassdef} refines {mclass.kind} {mclass.full_name}", 3)
		end
	end

	# Determine the type parameter bounds for `nclassdef`.
	#
	# In case of error, return `null`.
	#
	# REQUIRE: `nmodule.mmodule != null`
	# REQUIRE: `nclassdef.mclass != null`
	private fun build_a_bound_mtype(nmodule: AModule, nclassdef: AClassdef): nullable MClassType
	do
		var mmodule = nmodule.mmodule.as(not null)
		var mclass = nclassdef.mclass.as(not null)

		var bounds = new Array[MType]
		if nclassdef isa AStdClassdef and mclass.arity > 0 then
			var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")

			# Revolve bound for formal parameters
			for i in [0..mclass.arity[ do
				if nclassdef.n_formaldefs.is_empty then
					# Inherit the bound
					var bound = mclass.intro.bound_mtype.arguments[i]
					bounds.add(bound)
					continue
				end

				var nfd = nclassdef.n_formaldefs[i]
				var pname = mclass.mparameters[i].name
				if nfd.n_id.text != pname then
					error(nfd.n_id, "Error: formal parameter type #{i} `{nfd.n_id.text}` must be named `{pname}` as in the original definition in module `{mclass.intro.mmodule}`.")
				end
				var nfdt = nfd.n_type
				if nfdt != null then
					var bound = resolve_mtype3_unchecked(mmodule, null, null, nfdt, false)
					if bound == null then return null # Forward error
					if bound.need_anchor then
						# No F-bounds!
						error(nfd, "Error: formal parameter type `{pname}` bounded with a formal parameter type.")
					else
						bounds.add(bound)
						nfd.bound = bound
					end
				else if mclass.mclassdefs.is_empty then
					if objectclass == null then
						error(nfd, "Error: formal parameter type `{pname}` unbounded but no `Object` class exists.")
						return null
					end
					# No bound, then implicitely bound by nullable Object
					var bound = objectclass.mclass_type.as_nullable
					bounds.add(bound)
					nfd.bound = bound
				else
					# Inherit the bound
					var bound = mclass.intro.bound_mtype.arguments[i]
					bounds.add(bound)
					nfd.bound = bound
				end
			end
		end

		return mclass.get_mtype(bounds)
	end

	# Visit the AST and set the super-types of the `MClassDef` objects
	private fun build_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)
	do
		var mmodule = nmodule.mmodule
		if mmodule == null then return
		var mclass = nclassdef.mclass
		if mclass == null then return
		var mclassdef = nclassdef.mclassdef
		if mclassdef == null then return

		var supertypes = collect_supertypes(nmodule, nclassdef, mclassdef.is_intro)
		mclassdef.set_supertypes(supertypes)
		if not supertypes.is_empty then self.toolcontext.info("{mclassdef} new super-types: {supertypes.join(", ")}", 3)
	end

	# List the supertypes specified or implied by `nclassdef`.
	#
	# REQUIRE: `nmodule.mmodule != null`
	# REQUIRE: `nclassdef.mclass != null`
	private fun collect_supertypes(nmodule: AModule, nclassdef: AClassdef,
			is_intro: Bool): Array[MClassType]
	do
		var mmodule = nmodule.mmodule.as(not null)
		var mclass = nclassdef.mclass.as(not null)
		var name = mclass.name
		var kind = mclass.kind

		var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
		var pointerclass = try_get_mclass_by_name(nmodule, mmodule, "Pointer")

		# Do we need to specify Object as a super class?
		var specobject = true

		# Do we need to specify Pointer as a super class? (is only valid
		# if `nclassdef` is an extern class)
		var specpointer = true

		var supertypes = new Array[MClassType]
		if nclassdef isa AStdClassdef then
			for nsc in nclassdef.n_superclasses do
				specobject = false
				var ntype = nsc.n_type
				var mtype = resolve_mtype3_unchecked(mmodule, mclass, null,
						ntype, false)
				if mtype == null then continue # Skip because of error
				if not mtype isa MClassType then
					error(ntype, "Error: a supertype cannot be a formal type.")
					continue
				end
				var superclass = mtype.mclass
				var super_kind = superclass.kind
				if not kind.can_specialize(super_kind) then
					error(ntype, "Error: {kind} `{mclass}` cannot specialize {super_kind} `{superclass}`.")
				end
				supertypes.add mtype
				#print "new super : {mclass} < {mtype}"
				if super_kind == extern_kind then specpointer = false
			end
		end

		if is_intro and objectclass != null then
			if kind == extern_kind and name != "Pointer" then
				# it is an extern class, but not a Pointer
				if pointerclass == null then
					error(nclassdef, "Error: `Pointer` must be defined first.")
					return supertypes
				end
				if specpointer then supertypes.add pointerclass.mclass_type
			else if specobject then
				if name != "Object" then
					# it is a standard class without super class (but is not Object)
					supertypes.add objectclass.mclass_type
				else if kind != interface_kind then
					error(nclassdef, "Error: `Object` must be an {interface_kind}.")
				end
			end
		end

		return supertypes
	end

	# Check the validity of the specialization heirarchy
	private fun check_supertypes(nmodule: AModule, nclassdef: AClassdef)
	do
		var mmodule = nmodule.mmodule
		if mmodule == null then return
		var mclass = nclassdef.mclass
		if mclass == null then return
		var mclassdef = nclassdef.mclassdef
		if mclassdef == null then return

		for s in mclassdef.supertypes do
			if s.is_subtype(mmodule, mclassdef.bound_mtype, mclassdef.bound_mtype) then
				error(nclassdef, "Error: inheritance loop for class `{mclass}` with type `{s}`.")
			end
		end
	end

	# Build the classes of the module `nmodule`.
	private fun build_classes(nmodule: AModule)
	do
		# Force building recursively
		if nmodule.build_classes_is_done then return
		nmodule.build_classes_is_done = true
		var mmodule = nmodule.mmodule
		if mmodule == null then return
		for imp in mmodule.in_importation.direct_greaters do
			var nimp = mmodule2node(imp)
			if nimp != null then build_classes(nimp)
		end

		# Create all classes
		# process AStdClassdef before so that non-AStdClassdef classes can be attached to existing ones, if any
		for nclassdef in nmodule.n_classdefs do
			if not nclassdef isa AStdClassdef then continue
			self.build_a_mclass(nmodule, nclassdef)
		end
		for nclassdef in nmodule.n_classdefs do
			if nclassdef isa AStdClassdef then continue
			self.build_a_mclass(nmodule, nclassdef)
		end

		# Create all classdefs
		for nclassdef in nmodule.n_classdefs do
			if not nclassdef isa AStdClassdef then continue
			self.build_a_mclassdef(nmodule, nclassdef)
		end
		for nclassdef in nmodule.n_classdefs do
			if nclassdef isa AStdClassdef then continue
			self.build_a_mclassdef(nmodule, nclassdef)
		end

		# Create inheritance on all classdefs
		for nclassdef in nmodule.n_classdefs do
			self.build_a_mclassdef_inheritance(nmodule, nclassdef)
		end

		# Create the mclassdef hierarchy
		for mclassdef in mmodule.mclassdefs do
			mclassdef.add_in_hierarchy
		end

		# Check inheritance
		for nclassdef in nmodule.n_classdefs do
			self.check_supertypes(nmodule, nclassdef)
		end

		# Check unchecked ntypes
		for nclassdef in nmodule.n_classdefs do
			if nclassdef isa AStdClassdef then
				var mclassdef = nclassdef.mclassdef
				var mclass
				var anchor
				if mclassdef == null then
					mclass = null
					anchor = null
				else
					mclass = mclassdef.mclass
					anchor = mclassdef.bound_mtype
				end

				# check bound of formal parameter
				for nfd in nclassdef.n_formaldefs do
					var nfdt = nfd.n_type
					if nfdt != null and nfdt.mtype != null then
						var bound = resolve_mtype3(mmodule, mclass, anchor, nfdt)
						if bound == null then return # Forward error
					end
				end
				# check declared super types
				for nsc in nclassdef.n_superclasses do
					var ntype = nsc.n_type
					if ntype.mtype != null then
						var mtype = resolve_mtype3(mmodule, mclass, anchor, ntype)
						if mtype == null then return # Forward error
					end
				end
			end
		end

		# Check clash of ancestors
		for nclassdef in nmodule.n_classdefs do
			var mclassdef = nclassdef.mclassdef
			if mclassdef == null then continue
			var superclasses = new HashMap[MClass, MClassType]
			for scd in mclassdef.in_hierarchy.greaters do
				for st in scd.supertypes do
					if not superclasses.has_key(st.mclass) then
						superclasses[st.mclass] = st
					else if superclasses[st.mclass] != st then
						var st1 = superclasses[st.mclass].resolve_for(mclassdef.mclass.mclass_type, mclassdef.bound_mtype, mmodule, false)
						var st2 = st.resolve_for(mclassdef.mclass.mclass_type, mclassdef.bound_mtype, mmodule, false)
						if st1 != st2 then
							error(nclassdef, "Error: incompatible ancestors for `{mclassdef.mclass}`; conflict: `{st1}` and `{st2}`")
						end
					end
				end
			end
		end

		# TODO: Check that the super-class is not intrusive

		# Check that the superclasses are not already known (by transitivity)
		for nclassdef in nmodule.n_classdefs do
			if not nclassdef isa AStdClassdef or nclassdef.is_broken then continue
			var mclassdef = nclassdef.mclassdef
			if mclassdef == null then continue

			# Get the direct superclasses
			# Since we are a mclassdef, just look at the mclassdef hierarchy
			var parents = new Array[MClass]
			for sup in mclassdef.in_hierarchy.direct_greaters do
				parents.add(sup.mclass)
			end

			# Used to track duplicates of superclasses
			var seen_parents = new ArrayMap[MClass, AType]

			# The Object class
			var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")

			# Check each declared superclass to see if it belong to the direct superclass
			for nsc in nclassdef.n_superclasses do
				var ntype = nsc.n_type
				var mtype = ntype.mtype

				# If the supertype is `null` or don’t refer to a class, we
				# already raised an error.
				if not mtype isa MClassType then continue

				var sc = mtype.mclass
				if not parents.has(sc) or sc == objectclass then
					# Skip the warning on generated code
					if ntype.location.file != null and not ntype.location.file.filename.is_empty then
						warning(ntype, "useless-superclass", "Warning: superfluous super-class `{mtype}` in class `{mclassdef.mclass}`.")
					end
				else if not seen_parents.has_key(sc) then
					seen_parents[sc] = ntype
				else
					warning(ntype, "useless-superclass", "Warning: duplicated super-class `{mtype}` in class `{mclassdef.mclass}`.")
				end
			end
		end
	end

	# Registration of the nclassdef associated to each mclassdef
	private var mclassdef2nclassdef = new HashMap[MClassDef, AClassdef]

	# Retrieve the associated AST node of a mclassdef.
	#
	# This method is used to associate model entity with syntactic entities.
	# If the class definition is not associated with a node, returns `null`.
	fun mclassdef2node(mclassdef: MClassDef): nullable AClassdef do
		return mclassdef2nclassdef.get_or_null(mclassdef)
	end
end
src/modelize/modelize_class.nit:36,1--503,3

nitc :: annotation $ ModelBuilder
redef class ModelBuilder
	# Collect all annotations by `name` assocated to `mmodule` and its imported modules.
	# Note that visibility is not considered.
	fun collect_annotations_on_modules(name: String, mmodule: MModule): Array[AAnnotation]
	do
		var annotations = new Array[AAnnotation]
		for mmod in mmodule.in_importation.greaters do
			var amod = mmodule2node(mmod)
			if amod == null then continue
			var module_decl = amod.n_moduledecl
			if module_decl == null then continue
			var aas = module_decl.get_annotations(name)
			annotations.add_all aas
		end
		return annotations
	end

	# Return the single annotation `name` locally assocated to `mmodule`, if any.
	# Obviously, if there is no ast associated to `mmodule`, then nothing is returned.
	fun get_mmodule_annotation(name: String, mmodule: MModule): nullable AAnnotation
	do
		var amod = mmodule2node(mmodule)
		if amod == null then return null
		var module_decl = amod.n_moduledecl
		if module_decl == null then return null
		var res = module_decl.get_single_annotation(name, self)
		return res
	end

	private var collect_annotations_data_cache = new HashMap[String, MModuleData[AAnnotation]]

	# Collect all annotations by `name` in `mmodule` and its importations (direct and indirect)
	# Note that visibility is not considered.
	fun collect_annotations_data(name: String, mmodule: MModule): MModuleData[AAnnotation]
	do
		var res = collect_annotations_data_cache.get_or_null(name)
		if res == null then
			res = new MModuleData[AAnnotation](model)
			collect_annotations_data_cache[name] = res
		end

		for mmod in mmodule.in_importation.greaters do
			if res.has_mmodule(mmod) then continue
			var ass = get_mmodule_annotation(name, mmod)
			if ass == null then continue
			res[mmod] = ass
		end
		return res
	end

	# Get an annotation by name from `mmodule` and its super modules. Will recursively search
	# in imported module to find the "latest" declaration and detects priority conflicts.
	fun lookup_annotation_on_modules(name: String, mmodule: MModule): nullable AAnnotation
	do
		var data = collect_annotations_data(name, mmodule)
		var annotations = data.lookup_values(mmodule, none_visibility)
		if annotations.is_empty then return null
		if annotations.length > 1 then
			var locs = new Array[Location]
			for annot in annotations do locs.add(annot.location)

			toolcontext.error(mmodule.location,
				"Error: priority conflict on annotation `{name}`, it has been defined in: {locs.join(", ")}.")
		end
		return annotations.first
	end
end
src/annotation.nit:83,1--149,3

nitc :: modelize_property $ ModelBuilder
redef class ModelBuilder
	# Registration of the npropdef associated to each mpropdef.
	#
	# Public clients need to use `mpropdef2node` to access stuff.
	private var mpropdef2npropdef = new HashMap[MPropDef, APropdef]

	# Associate a `npropdef` with its `mpropdef`
	#
	# Be careful, this method is unsafe, no checking is done when it's used.
	# The safe way to add method it's to use the `build_property`
	#
	# See `mpropdef2npropdef`
	fun unsafe_add_mpropdef2npropdef(mpropdef: MPropDef,npropdef: APropdef)
	do
		mpropdef2npropdef[mpropdef] = npropdef
	end

	# Associate a `nclassdef` with its `mclassdef`
	#
	# Be careful, this method is unsafe, no checking is done when it's used.
	# The safe way to add mclass it's to use the `build_property`
	#
	# See `mclassdef2nclassdef`
	fun unsafe_add_mclassdef2nclassdef(mclassdef: MClassDef, nclassdef: AClassdef)
	do
		mclassdef2nclassdef[mclassdef] = nclassdef
	end

	# Retrieve the associated AST node of a mpropertydef.
	# This method is used to associate model entity with syntactic entities.
	#
	# If the property definition is not associated with a node, returns `null`.
	fun mpropdef2node(mpropdef: MPropDef): nullable ANode
	do
		var res
		res = mpropdef2npropdef.get_or_null(mpropdef)
		if res != null then
			# Run the phases on it
			toolcontext.run_phases_on_npropdef(res)
			return res
		end
		# Fall back to the class node if any.
		res = mclassdef2nclassdef.get_or_null(mpropdef.mclassdef)
		if res != null then return res
		return null
	end

	# Retrieve all the attributes nodes localy definied
	# FIXME think more about this method and how the separations separate/global and ast/model should be done.
	fun collect_attr_propdef(mclassdef: MClassDef): Array[AAttrPropdef]
	do
		var res = new Array[AAttrPropdef]
		var n = mclassdef2nclassdef.get_or_null(mclassdef)
		if n == null then return res
		for npropdef in n.n_propdefs do
			if npropdef isa AAttrPropdef then
				# Run the phases on it
				toolcontext.run_phases_on_npropdef(npropdef)
				res.add(npropdef)
			end
		end
		return res
	end

	# Build the properties of `nclassdef`.
	private fun build_properties(nclassdef: AClassdef)
	do
		# Force building recursively
		if nclassdef.build_properties_is_done then return
		nclassdef.build_properties_is_done = true
		var mclassdef = nclassdef.mclassdef
		if mclassdef == null then return # skip error
		if mclassdef.in_hierarchy == null then return # Skip error
		for superclassdef in mclassdef.in_hierarchy.direct_greaters do
			if not mclassdef2nclassdef.has_key(superclassdef) then continue
			build_properties(mclassdef2nclassdef[superclassdef])
		end

		mclassdef.build_self_type(self, nclassdef)
		for nclassdef2 in nclassdef.all_defs do
			for npropdef in nclassdef2.n_propdefs do
				npropdef.build_property(self, mclassdef)
			end
			for npropdef in nclassdef2.n_propdefs do
				npropdef.build_signature(self)
			end
			for npropdef in nclassdef2.n_propdefs do
				if not npropdef isa ATypePropdef then continue
				# Check circularity
				var mpropdef = npropdef.mpropdef
				if mpropdef == null then continue
				if mpropdef.bound == null then continue
				if not check_virtual_types_circularity(npropdef, mpropdef.mproperty, mclassdef.bound_mtype, mclassdef.mmodule) then
					# Invalidate the bound
					mpropdef.is_broken = true
					mpropdef.bound = new MErrorType(mclassdef.mmodule.model)
				end
			end
			for npropdef in nclassdef2.n_propdefs do
				# Check ATypePropdef first since they may be required for the other properties
				if not npropdef isa ATypePropdef then continue
				npropdef.check_signature(self)
			end

			for npropdef in nclassdef2.n_propdefs do
				if npropdef isa ATypePropdef then continue
				npropdef.check_signature(self)
			end
		end
		process_default_constructors(nclassdef)
	end

	# the root init of the Object class
	# Is usually implicitly defined
	# Then explicit or implicit definitions of root-init are attached to it
	var the_root_init_mmethod: nullable MMethod

	# Introduce or inherit default constructor
	# This is the last part of `build_properties`.
	private fun process_default_constructors(nclassdef: AClassdef)
	do
		var mclassdef = nclassdef.mclassdef.as(not null)

		# Are we a refinement
		if not mclassdef.is_intro then
			# Set the default_init of the mclassdef with the intro default_init
			mclassdef.default_init = mclassdef.mclass.intro.default_init
			return
		end

		# Look for the init in Object, or create it
		if mclassdef.mclass.name == "Object" and the_root_init_mmethod == null then
			# Create the implicit root-init method
			var mprop = new MMethod(mclassdef, "init", nclassdef.location, mclassdef.mclass.visibility)
			mprop.is_root_init = true
			var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
			var mparameters = new Array[MParameter]
			var msignature = new MSignature(mparameters, null)
			mpropdef.msignature = msignature
			mprop.is_init = true
			self.toolcontext.info("{mclassdef} gets a free empty constructor {mpropdef}{msignature}", 3)
			the_root_init_mmethod = mprop
		end

		# Is there already a constructor defined?
		var defined_init: nullable MMethodDef = null
		for mpropdef in mclassdef.mpropdefs do
			if not mpropdef isa MMethodDef then continue
			if not mpropdef.mproperty.is_init then continue
			if mpropdef.mproperty.is_root_init then
				assert defined_init == null
				defined_init = mpropdef
			else if mpropdef.name == "defaultinit" then
				return
			end
		end

		if mclassdef.default_init != null then return

		# If the class is not AStdClassdef or it's an enum just return. No defaultinit is need.
		if not nclassdef isa AStdClassdef or nclassdef.n_classkind isa AEnumClasskind then return

		# Collect undefined attributes
		var mparameters = new Array[MParameter]
		var initializers = new Array[MProperty]
		for npropdef in nclassdef.n_propdefs do
			if npropdef isa AMethPropdef then
				if not npropdef.is_autoinit then continue # Skip non tagged autoinit
				var mpropdef = npropdef.mpropdef
				if mpropdef == null then return # Skip broken method
				var sig = mpropdef.msignature
				if sig == null then continue # Skip broken method
				mparameters.add_all sig.mparameters
				initializers.add(mpropdef.mproperty)
				mpropdef.mproperty.is_autoinit = true
			end
			if npropdef isa AAttrPropdef then
				var mreadpropdef = npropdef.mreadpropdef
				if mreadpropdef == null then return # Skip broken attribute
				var msignature = mreadpropdef.msignature
				if msignature == null then return # Skip broken attribute
				if npropdef.noinit then continue # Skip noinit attribute
				var atlateinit = npropdef.get_single_annotation("lateinit", self)
				if atlateinit != null then
					# For lateinit attributes, call the reader to force
					# the lazy initialization of the attribute.
					initializers.add(mreadpropdef.mproperty)
					mreadpropdef.mproperty.is_autoinit = true
					continue
				end
				if npropdef.has_value and not npropdef.is_optional then continue
				var msetter = npropdef.mwritepropdef
				if msetter == null then
					# No setter, it is a readonly attribute, so just add it
					var paramname = mreadpropdef.mproperty.name
					var ret_type = msignature.return_mtype
					if ret_type == null then return
					var mparameter = new MParameter(paramname, ret_type, false)
					mparameters.add(mparameter)

					initializers.add(npropdef.mpropdef.mproperty)
					npropdef.mpropdef.mproperty.is_autoinit = true
				else
					# Add the setter to the list
					mparameters.add_all msetter.msignature.mparameters
					initializers.add(msetter.mproperty)
					msetter.mproperty.is_autoinit = true
				end
			end
		end

		var the_root_init_mmethod = self.the_root_init_mmethod
		if the_root_init_mmethod == null then return

		# Look for most-specific new-stype init definitions
		var spropdefs = new ArraySet[MMethodDef]

		for x in mclassdef.get_direct_supermtype do
			var y = x.mclass.intro.default_init
			if y == null then continue
			if y.is_broken or y.msignature == null then return
			spropdefs.add y
		end

		# Look at the autoinit class-annotation
		var autoinit = nclassdef.get_single_annotation("autoinit", self)
		var noautoinit = nclassdef.get_single_annotation("noautoinit", self)
		if autoinit != null then
			# Just throws the collected initializers
			mparameters.clear
			initializers.clear

			if noautoinit != null then
				error(autoinit, "Error: `autoinit` and `noautoinit` are incompatible.")
			end

			if autoinit.n_args.is_empty then
				error(autoinit, "Syntax Error: `autoinit` expects method identifiers, use `noautoinit` to clear all autoinits.")
			end

			# Get and check each argument
			for narg in autoinit.n_args do
				var id = narg.as_id
				if id == null then
					error(narg, "Syntax Error: `autoinit` expects method identifiers.")
					return
				end

				# Search the property.
				# To avoid bad surprises, try to get the setter first.
				var p = try_get_mproperty_by_name(narg, mclassdef, id + "=")
				if p == null then
					p = try_get_mproperty_by_name(narg, mclassdef, id)
				end
				if p == null then
					error(narg, "Error: unknown method `{id}`")
					return
				end
				if not p.is_autoinit then
					error(narg, "Error: `{p}` is not an autoinit method")
					return
				end

				# Register the initializer and the parameters
				initializers.add(p)
				var pd = p.intro
				if pd isa MMethodDef then
					# Get the signature resolved for the current receiver
					var sig = pd.msignature.resolve_for(mclassdef.mclass.mclass_type, mclassdef.bound_mtype, mclassdef.mmodule, false)
					mparameters.add_all(sig.mparameters)
				else
					# TODO attributes?
					abort
				end
			end
		else if spropdefs.not_empty then
			# Search for inherited manual defaultinit
			var manual = null
			for s in spropdefs do
				if mpropdef2npropdef.has_key(s) then
					self.toolcontext.info("{mclassdef} inherits a manual defaultinit {s}", 3)
					manual = s
				end
			end
			# Search the longest-one and checks for conflict
			var longest = spropdefs.first
			if spropdefs.length > 1 then
				# part 1. find the longest list
				for spd in spropdefs do
					if spd.initializers.length > longest.initializers.length then longest = spd

					if spd != manual and manual != null then
						self.toolcontext.info("{mclassdef} conflict between manual defaultinit {manual} and automatic defaultinit {spd}.", 3)
					end
				end
				# conflict with manual autoinit?
				if longest != manual and manual != null then
					self.error(nclassdef, "Error: conflict between manual defaultinit {manual} and automatic defaultinit {longest}.")
				end
				# part 2. compare
				# Check for conflict in the order of initializers
				# Each initializer list must me a prefix of the longest list
				# If `noautoinit` is set, just ignore conflicts
				if noautoinit == null then for spd in spropdefs do
					var i = 0
					for p in spd.initializers do
						if p != longest.initializers[i] then
							var proposal = new ArraySet[MProperty]
							for spd2 in spropdefs do
								proposal.add_all spd2.initializers
							end
							proposal.add_all initializers
							self.error(nclassdef, "Error: cannot generate automatic init for class {mclassdef.mclass}. Conflict in the order in inherited initializers {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")}). Use `autoinit` to order initializers. eg `autoinit {proposal.join(", ")}`")
							# TODO: invalidate the initializer to avoid more errors
							return
						end
						i += 1
					end
				end
			end

			if noautoinit != null then
				# If there is local or inherited initializers, then complain.
				if initializers.is_empty and longest.initializers.is_empty then
					warning(noautoinit, "useless-noautoinit", "Warning: the list of autoinit is already empty.")
				end
				# Just clear initializers
				mparameters.clear
				initializers.clear
			else
				# Combine the inherited list to what is collected
				if longest.initializers.length > 0 then
					mparameters.prepend longest.msignature.mparameters
					initializers.prepend longest.initializers
				end
			end
		end

		# Create a specific new autoinit constructor
		do
			var mprop = new MMethod(mclassdef, "defaultinit", nclassdef.location, public_visibility)
			mprop.is_init = true
			var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
			mpropdef.initializers.add_all(initializers)
			var msignature = new MSignature(mparameters, null)
			mpropdef.msignature = msignature
			mclassdef.default_init = mpropdef
			self.toolcontext.info("{mclassdef} gets a free auto constructor `{mpropdef}{msignature}`. {spropdefs}", 3)
			mclassdef.mclass.the_root_init_mmethod = the_root_init_mmethod
		end
	end

	# Check the visibility of `mtype` as an element of the signature of `mpropdef`.
	fun check_visibility(node: ANode, mtype: MType, mpropdef: MPropDef)
	do
		var mmodule = mpropdef.mclassdef.mmodule
		var mproperty = mpropdef.mproperty

		# Extract visibility information of the main part of `mtype`
		# It is a case-by case
		var vis_type: nullable MVisibility = null # The own visibility of the type
		var mmodule_type: nullable MModule = null # The original module of the type
		mtype = mtype.undecorate
		if mtype isa MClassType then
			vis_type = mtype.mclass.visibility
			mmodule_type = mtype.mclass.intro_mmodule
		else if mtype isa MVirtualType then
			vis_type = mtype.mproperty.visibility
			mmodule_type = mtype.mproperty.intro_mclassdef.mmodule
		else if mtype isa MParameterType then
			# nothing, always visible
		else if mtype isa MNullType then
			# nothing to do.
		else if mtype isa MBottomType then
			# nothing to do.
		else if mtype isa MErrorType then
			# nothing to do.
		else
			node.debug "Unexpected type {mtype}"
			abort
		end

		if vis_type != null then
			assert mmodule_type != null
			var vis_module_type = mmodule.visibility_for(mmodule_type) # the visibility of the original module
			if mproperty.visibility > vis_type then
				error(node, "Error: the {mproperty.visibility} property `{mproperty}` cannot contain the {vis_type} type `{mtype}`.")
				return
			else if mproperty.visibility > vis_module_type then
				error(node, "Error: the {mproperty.visibility} property `{mproperty}` cannot contain the type `{mtype}` from the {vis_module_type} module `{mmodule_type}`.")
				return
			end
		end

		# No error, try to go deeper in generic types
		if node isa AType then
			for a in node.n_types do
				var t = a.mtype
				if t == null then continue # Error, thus skipped
				check_visibility(a, t, mpropdef)
			end
		else if mtype isa MGenericType then
			for t in mtype.arguments do check_visibility(node, t, mpropdef)
		end
	end

	# Detect circularity errors for virtual types.
	fun check_virtual_types_circularity(node: ANode, mproperty: MVirtualTypeProp, recv: MType, mmodule: MModule): Bool
	do
		# Check circularity
		# Slow case: progress on each resolution until we visit all without getting a loop

		# The graph used to detect loops
		var mtype = mproperty.mvirtualtype
		var poset = new POSet[MType]

		# The work-list of types to resolve
		var todo = new List[MType]
		todo.add mtype

		while not todo.is_empty do
			# The visited type
			var t = todo.pop

			if not t.need_anchor then continue

			# Get the types derived of `t` (subtypes and bounds)
			var nexts
			if t isa MNullableType then
				nexts = [t.mtype]
			else if t isa MGenericType then
				nexts = t.arguments
			else if t isa MVirtualType then
				var vt = t.mproperty
				# Because `vt` is possibly unchecked, we have to do the bound-lookup manually
				var defs = vt.lookup_definitions(mmodule, recv)
				if defs.is_empty then return false
				nexts = new Array[MType]
				for d in defs do
					var next = defs.first.bound
					if next == null then return false
					nexts.add next
				end
			else if t isa MClassType then
				# Basic type, nothing to to
				continue
			else if t isa MParameterType then
				# Parameter types cannot depend on virtual types, so nothing to do
				continue
			else
				abort
			end

			# For each one
			for next in nexts do
				if poset.has_edge(next, t) then
					if mtype == next then
						error(node, "Error: circularity of virtual type definition: {next} <-> {t}.")
					else
						error(node, "Error: circularity of virtual type definition: {mtype} -> {next} <-> {t}.")
					end
					return false
				else
					poset.add_edge(t, next)
					todo.add next
				end
			end
		end
		return true
	end
end
src/modelize/modelize_property.nit:39,1--509,3

nitc :: modelize $ ModelBuilder
redef class ModelBuilder
	# Retrieve the associated AST node of a mentity.
	# This method is used to associate model entity with syntactic entities.
	#
	# If the mentity is not associated with a node, returns null.
	# This is always the case for MPackage, Mgroup, MClass and MProperty.
	# MModule, MClassDef and MPropDef can also have no node associated
	# (like fictive modules of generated attributes/methods).
	fun mentity2node(mentity: MEntity): nullable ANode
	do
		if mentity isa MModule then
			return mmodule2node(mentity)
		else if mentity isa MClassDef then
			return mclassdef2node(mentity)
		else if mentity isa MPropDef then
			return mpropdef2node(mentity)
		end
		return null
	end
end
src/modelize/modelize.nit:20,1--39,3

nitc :: actors_injection_phase $ ModelBuilder
redef class ModelBuilder
	redef fun build_a_mclass(nmodule, nclassdef)
	do
		super

		# Catch the wanted annotation
		var at = nclassdef.get_single_annotation("actor", self)
		if at == null then return

		# Get context information
		var mod = nmodule.mmodule
		if mod == null then return
		var mclass = nclassdef.mclass
		if mclass == null then return
		if mclass.intro_mmodule != mod then
			error(at, "`actor` can only be used at introductions.")
			return
		end

		var l = at.location

		var injected_name = "Proxy"

		# Create the actor class
		var actor_class = new MClass(mod, injected_name + mclass.name, l, null, concrete_kind, public_visibility)
		var actor_class_definition = new MClassDef(mod, actor_class.mclass_type, l)
		actor_class_definition.set_supertypes([mod.object_type])
		var proxy_classes = mclass.model.get_mclasses_by_name("Proxy")
		assert proxy_classes != null
		var proxy_class = proxy_classes.first
		actor_class_definition.supertypes.add(proxy_class.mclass_type)

		# Register it
		mclass.actor = actor_class
	end

	redef fun build_properties(nclassdef)
	do
		if nclassdef.build_properties_is_done then return
		super

		# Get context information
		var mclass = nclassdef.mclass
		if mclass == null then return
		var mclass_def = nclassdef.mclassdef
		if mclass_def == null then return

		var actor_mclass = mclass.actor
		if actor_mclass == null then return
		var actor_mclass_def = actor_mclass.mclassdefs.first

		# Adds an `async` attribute in the worker class which is the actor class
		if mclass_def.is_intro then
			var async = new MMethod(mclass_def, "async", mclass.location, public_visibility)
			var async_def = new MMethodDef(mclass_def, async, mclass.location)
			async_def.msignature = new MSignature(new Array[MParameter], actor_mclass.mclass_type)
			async_def.is_abstract = true
		end

		# For each introduced property
		for method in mclass_def.mpropdefs do
			if not method isa MMethodDef then continue
			if not method.is_intro then continue
			if method.name == "async" then continue

			# Create a proxied method
			var actor_method = new MMethod(actor_mclass_def, method.name, actor_mclass.location, method.mproperty.visibility)
			var actor_method_def = new MMethodDef(actor_mclass_def, actor_method, actor_mclass.location)

			# Get the signature of the method ( replacing the return value with a Future if there is one)
			var signature = method.msignature
			if signature != null then
				var parameters = signature.mparameters
				var s_return_type = signature.return_mtype
				if s_return_type != null then
					var future_mclasses = mclass_def.model.get_mclasses_by_name("Future")
					assert future_mclasses != null
					var future_mclass = future_mclasses.first
					var return_type = future_mclass.get_mtype([s_return_type])
					actor_method_def.msignature = new MSignature(parameters, return_type)
				else
					actor_method_def.msignature = new MSignature(parameters, null)
				end
			end
			actor_method_def.is_abstract = true
		end
	end
end
src/frontend/actors_injection_phase.nit:22,1--109,3

nitc :: testing_gen $ ModelBuilder
redef class ModelBuilder
	# Generate NitUnit test file skeleton for `mmodule`.
	fun gen_test_unit(mmodule: MModule) do
		var test_file = "test_{mmodule.name}.nit"
		if test_file.file_exists and not toolcontext.opt_gen_force.value and not toolcontext.opt_gen_show.value then
			toolcontext.info("Skip generation for {mmodule}, file {test_file} already exists", 1)
			return
		end
		var generator = new NitUnitGenerator(toolcontext)
		var tpl = generator.gen_unit(mmodule, test_file)
		if toolcontext.opt_gen_show.value then
			tpl.write_to(sys.stdout)
		else
			tpl.write_to_file(test_file)
		end
	end
end
src/testing/testing_gen.nit:157,1--173,3

nitc :: astbuilder $ ModelBuilder
redef class ModelBuilder
	# Try to get MMethod property if exist in the given mclassdef. return new `MMethod` if not exist.
	private fun get_mmethod(name: String, mclassdef: MClassDef, visibility: nullable MVisibility): MMethod do
		visibility = visibility or else public_visibility
		var mproperty = try_get_mproperty_by_name(null, mclassdef, name).as(nullable MMethod)
		if mproperty == null then mproperty = new MMethod(mclassdef, name, mclassdef.location, visibility)
		return mproperty
	end

	# Creation of a new method (AST and model representation) with the given name.
	# See `create_method_from_property` for more information.
	fun create_method_from_name(name: String, mclassdef: MClassDef, is_abstract: Bool, msignature: nullable MSignature, visibility: nullable MVisibility): AMethPropdef do
		var mproperty = get_mmethod(name, mclassdef, visibility)
		return create_method_from_property(mproperty, mclassdef, is_abstract, msignature)
	end

	# Creation of a new method (AST and model representation) with the given MMethod.
	# Take care, if `is_abstract == false` the AMethPropdef returned has an empty body (potential error if the given signature has an return type).
	fun create_method_from_property(mproperty: MMethod,  mclassdef: MClassDef, is_abstract: Bool, msignature: nullable MSignature): AMethPropdef do
		var m_def = new MMethodDef(mclassdef, mproperty, mclassdef.location)

		if msignature == null then msignature = new MSignature(new Array[MParameter])

		m_def.msignature = msignature
		m_def.is_abstract = true
		var n_def = m_def.create_ast_representation
		# Association new npropdef to mpropdef
		unsafe_add_mpropdef2npropdef(m_def,n_def)

		if not is_abstract then
			n_def.mpropdef.is_abstract = false
			n_def.n_block = new ABlockExpr.make
		end

		return n_def
	end

	# Creation of a new attribute (AST and model representation) with the given name.
	# See `create_attribute_from_property` for more information.
	fun create_attribute_from_name(name: String, mclassdef: MClassDef, mtype: MType, visibility: nullable MVisibility): AAttrPropdef do
		if visibility == null then visibility = public_visibility
		var mattribute = try_get_mproperty_by_name(null, mclassdef, name)
		if mattribute == null then mattribute = new MAttribute(mclassdef, name, mclassdef.location, visibility)
		return create_attribute_from_property(mattribute.as(MAttribute), mclassdef, mtype)
	end

	# Creation of a new attribute (AST and model representation) with the given MAttribute.
	# See `create_attribute_from_propdef` for more information.
	fun create_attribute_from_property(mattribute: MAttribute, mclassdef: MClassDef, mtype: MType): AAttrPropdef do
		var attribut_def = new MAttributeDef(mclassdef, mattribute, mclassdef.location)
		attribut_def.static_mtype = mtype
		return create_attribute_from_propdef(attribut_def)
	end

	# Creation of a new attribute (AST representation) with the given MAttributeDef.
	fun create_attribute_from_propdef(mattribut_def: MAttributeDef): AAttrPropdef
	is
		expect(mclassdef2node(mattribut_def.mclassdef) != null)
	do
		var n_attribute = mattribut_def.create_ast_representation

		var nclass = mclassdef2node(mattribut_def.mclassdef)

		n_attribute.location = mattribut_def.location
		n_attribute.validate

		nclass.n_propdefs.unsafe_add_all([n_attribute])
		nclass.validate

		n_attribute.build_read_property(self, mattribut_def.mclassdef)
		n_attribute.build_read_signature

		mpropdef2npropdef[mattribut_def] = n_attribute
		return n_attribute
	end

	# Creation of a new class (AST and model representation) with the given name.
	# `visibility` : Define the visibility of the method. If it's `null` the default is `public_visibility`
	# See `create_class_from_mclass` for more information.
	fun create_class_from_name(name: String, super_type: Array[MClassType], mmodule: MModule, visibility: nullable MVisibility): AStdClassdef do
		if visibility == null then visibility = public_visibility
		var mclass = try_get_mclass_by_name(null, mmodule, name)
		if mclass == null then mclass = new MClass(mmodule, name, mmodule.location, new Array[String], concrete_kind, visibility)
		return create_class_from_mclass(mclass, super_type, mmodule)
	end

	# Creation of a new class (AST and model representation) with the given MClass.
	# This method creates a new concrete class definition `MClassDef`, and adds it to the class hierarchy.
	# See `create_class_from_mclassdef` for more information.
	fun create_class_from_mclass(mclass: MClass, super_type: Array[MClassType], mmodule: MModule): AStdClassdef do
		var mclassdef = new MClassDef(mmodule, mclass.mclass_type, mmodule.location)
		mclassdef.set_supertypes(super_type)
		mclassdef.add_in_hierarchy

		return create_class_from_mclassdef(mclassdef, mmodule)
	end

	# Creation of a new class (AST representation) with the given MClassDef.
	# Note all the properties of our MClassDef will also generate an AST representation.
	# Make an error if the attribute already has a representation in the modelbuilder.
	# This method also create the default constructor.
	fun create_class_from_mclassdef(mclassdef: MClassDef, mmodule: MModule): AStdClassdef do
		var n_classdef = mclassdef.create_ast_representation
		n_classdef.location = mclassdef.location
		n_classdef.validate

		for n_propdef in n_classdef.n_propdefs do
			var mpropdef = n_propdef.mpropdef
			assert mpropdef != null

			var p_npropdef = mpropdef2node(mpropdef)
			if  p_npropdef != null then error(null, "The property `{mpropdef.name}` already has a representation in the AST.")
			unsafe_add_mpropdef2npropdef(mpropdef, n_propdef)
		end

		process_default_constructors(n_classdef)
		unsafe_add_mclassdef2nclassdef(mclassdef, n_classdef)

		return n_classdef
	end
end
src/astbuilder.nit:1038,1--1158,3

nitc :: testing_suite $ ModelBuilder
redef class ModelBuilder
	# Number of test classes generated.
	var total_classes = 0

	# Number of tests generated.
	var total_tests = 0

	# Number of failed tests.
	var failed_tests = 0

	# Run NitUnit test suite for `mmodule` (if it is one).
	fun test_unit(mmodule: MModule): nullable HTMLTag do
		# is the module a test_suite?
		if not mmodule.is_test then return null
		toolcontext.info("nitunit: test-suite {mmodule}", 2)

		var tester = new NitUnitTester(self)
		var res = tester.test_module_unit(mmodule)
		return res.to_xml
	end
end
src/testing/testing_suite.nit:580,1--600,3

nitc :: detect_covariance $ ModelBuilder
redef class ModelBuilder
	redef fun check_subtype(node, mmodule, anchor, sub, sup)
	do
		var res = super
		var dcp = toolcontext.detect_covariance_phase

		if dcp.is_disabled then return res

		if res then
			dcp.count_types(node, node, sub, sup, mmodule, anchor)
		else
			dcp.cpt_total_variance.inc("bad mb subtype")
		end

		return res
	end
end
src/metrics/detect_covariance.nit:299,1--315,3

nitc :: rapid_type_analysis $ ModelBuilder
redef class ModelBuilder
	# Performs a rapid-type-analysis on the program associated with `mainmodule`.
	fun do_rapid_type_analysis(mainmodule: MModule): RapidTypeAnalysis
	do
		var analysis = new RapidTypeAnalysis(self, mainmodule)
		analysis.run_analysis

		if toolcontext.opt_log.value then
			var basename = toolcontext.log_directory / mainmodule.name
			analysis.live_methods_to_tree.write_to_file(basename + ".rta_methods.txt")
			analysis.live_types_to_csv.write_to_file(basename + ".rta_types.csv")
		end

		return analysis
	end
end
src/rapid_type_analysis.nit:33,1--48,3

nitc :: naive_interpreter $ ModelBuilder
redef class ModelBuilder
	# Execute the program from the entry point (`Sys::main`) of the `mainmodule`
	# `arguments` are the command-line arguments in order
	# REQUIRE that:
	#   1. the AST is fully loaded.
	#   2. the model is fully built.
	#   3. the instructions are fully analysed.
	fun run_naive_interpreter(mainmodule: MModule, arguments: Array[String])
	do
		var time0 = get_time
		self.toolcontext.info("*** START INTERPRETING ***", 1)

		var interpreter = new NaiveInterpreter(self, mainmodule, arguments)
		interpreter.start(mainmodule)

		var time1 = get_time
		self.toolcontext.info("*** END INTERPRETING: {time1-time0} ***", 2)
	end
end
src/interpreter/naive_interpreter.nit:38,1--56,3

nitc :: testing_doc $ ModelBuilder
redef class ModelBuilder
	# Total number analyzed `MEntity`
	var total_entities = 0

	# The number of `MEntity` that have some documentation
	var doc_entities = 0

	# The total number of executed docunits
	var unit_entities = 0

	# The number failed docunits
	var failed_entities = 0

	# Extracts and executes all the docunits in the `mmodule`
	# Returns a JUnit-compatible `<testsuite>` XML element that contains the results of the executions.
	fun test_markdown(mmodule: MModule): HTMLTag
	do
		var ts = new HTMLTag("testsuite")
		toolcontext.info("nitunit: doc-unit {mmodule}", 2)

		var nmodule = mmodule2node(mmodule)
		if nmodule == null then return ts

		# usualy, only the original module must be imported in the unit test.
		var o = mmodule
		var g = o.mgroup
		if g != null and g.mpackage.name == "core" then
			# except for a unit test in a module of `core`
			# in this case, the whole `core` must be imported
			o = get_mmodule_by_name(nmodule, g, g.mpackage.name).as(not null)
		end

		ts.attr("package", mmodule.full_name)

		var prefix = toolcontext.test_dir
		prefix = prefix.join_path(mmodule.to_s)
		var d2m = new NitUnitExecutor(toolcontext, prefix, o, ts, "Docunits of module {mmodule.full_name}")

		do
			total_entities += 1
			var nmoduledecl = nmodule.n_moduledecl
			if nmoduledecl == null then break label x
			var ndoc = nmoduledecl.n_doc
			if ndoc == null then break label x
			doc_entities += 1
			# NOTE: jenkins expects a '.' in the classname attr
			d2m.extract(ndoc.to_mdoc, "nitunit." + mmodule.full_name + ".<module>", "<module>")
		end label x
		for nclassdef in nmodule.n_classdefs do
			var mclassdef = nclassdef.mclassdef
			if mclassdef == null then continue
			if nclassdef isa AStdClassdef then
				total_entities += 1
				var ndoc = nclassdef.n_doc
				if ndoc != null then
					doc_entities += 1
					d2m.extract(ndoc.to_mdoc, "nitunit." + mclassdef.full_name.replace("$", "."), "<class>")
				end
			end
			for npropdef in nclassdef.n_propdefs do
				var mpropdef = npropdef.mpropdef
				if mpropdef == null then continue
				total_entities += 1
				var ndoc = npropdef.n_doc
				if ndoc != null then
					doc_entities += 1
					var a = mpropdef.full_name.split("$")
					d2m.extract(ndoc.to_mdoc, "nitunit." + a[0] + "." + a[1], a[2])
				end
			end
		end

		d2m.run_tests

		return ts
	end

	# Extracts and executes all the docunits in the readme of the `mgroup`
	# Returns a JUnit-compatible `<testsuite>` XML element that contains the results of the executions.
	fun test_group(mgroup: MGroup): HTMLTag
	do
		var ts = new HTMLTag("testsuite")
		toolcontext.info("nitunit: doc-unit group {mgroup}", 2)

		# usually, only the default module must be imported in the unit test.
		var o = mgroup.default_mmodule

		ts.attr("package", mgroup.full_name)

		var prefix = toolcontext.test_dir
		prefix = prefix.join_path(mgroup.to_s)
		var d2m = new NitUnitExecutor(toolcontext, prefix, o, ts, "Docunits of group {mgroup.full_name}")

		total_entities += 1
		var mdoc = mgroup.mdoc
		if mdoc == null then return ts

		doc_entities += 1
		# NOTE: jenkins expects a '.' in the classname attr
		d2m.extract(mdoc, "nitunit." + mgroup.mpackage.name + "." + mgroup.name + ".<group>", "<group>")

		d2m.run_tests

		return ts
	end

	# Test a document object unrelated to a Nit entity
	fun test_mdoc(mdoc: MDoc): HTMLTag
	do
		var ts = new HTMLTag("testsuite")
		var file = mdoc.location.file.as(not null).filename

		toolcontext.info("nitunit: doc-unit file {file}", 2)

		ts.attr("package", file)

		var prefix = toolcontext.test_dir / "file"
		var d2m = new NitUnitExecutor(toolcontext, prefix, null, ts, "Docunits of file {file}")

		total_entities += 1
		doc_entities += 1

		# NOTE: jenkins expects a '.' in the classname attr
		d2m.extract(mdoc, "nitunit.<file>", file)
		d2m.run_tests

		return ts
	end
end
src/testing/testing_doc.nit:550,1--678,3

nitc :: virtual_machine $ ModelBuilder
redef class ModelBuilder
	fun run_virtual_machine(mainmodule: MModule, arguments: Array[String])
	do
		var time0 = get_time
		self.toolcontext.info("*** NITVM STARTING ***", 1)

		var interpreter = new VirtualMachine(self, mainmodule, arguments)
		interpreter.start(mainmodule)

		var time1 = get_time
		self.toolcontext.info("*** NITVM STOPPING : {time1-time0} ***", 2)
	end
end
src/vm/virtual_machine.nit:23,1--35,3

nitc :: abstract_compiler $ ModelBuilder
redef class ModelBuilder
	# Simple indirection to `Toolchain::write_and_make`
	protected fun write_and_make(compiler: AbstractCompiler)
	do
		var platform = compiler.target_platform
		var toolchain = platform.toolchain(toolcontext, compiler)
		compiler.toolchain = toolchain
		toolchain.write_and_make
	end
end
src/compiler/abstract_compiler.nit:119,1--128,3

nitc :: global_compiler $ ModelBuilder
redef class ModelBuilder
	# Entry point to performs a global compilation on the AST of a complete program.
	# `mainmodule` is the main module of the program
	# `runtime_type_analysis` is a already computer type analysis.
	fun run_global_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)
	do
		var time0 = get_time
		self.toolcontext.info("*** GENERATING C ***", 1)

		var compiler = new GlobalCompiler(mainmodule, self, runtime_type_analysis)
		compiler.do_compilation
		compiler.display_stats

		var time1 = get_time
		self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
		write_and_make(compiler)
	end
end
src/compiler/global_compiler.nit:52,1--69,3

nitc :: separate_compiler $ ModelBuilder
redef class ModelBuilder
	fun run_separate_compiler(mainmodule: MModule, runtime_type_analysis: nullable RapidTypeAnalysis)
	do
		var time0 = get_time
		self.toolcontext.info("*** GENERATING C ***", 1)

		var compiler = new SeparateCompiler(mainmodule, self, runtime_type_analysis)
		compiler.do_compilation
		compiler.display_stats

		var time1 = get_time
		self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
		write_and_make(compiler)
	end

	# Count number of invocations by VFT
	private var nb_invok_by_tables = 0
	# Count number of invocations by direct call
	private var nb_invok_by_direct = 0
	# Count number of invocations by inlining
	private var nb_invok_by_inline = 0
end
src/compiler/separate_compiler.nit:114,1--135,3

nitc :: compiler_serialization $ ModelBuilder
redef class ModelBuilder
	redef fun write_and_make(compiler)
	do
		var uses_json_serialization_read = false
		for mod in compiler.mainmodule.in_importation.greaters do
			var concern = mod.parent_concern
			if mod.name == "serialization_read" and concern != null and concern.name == "json" then
				uses_json_serialization_read = true
				break
			end
		end

		if uses_json_serialization_read then
			write_poset_to_file(compiler, "nit_class_inheritance_metamodel", compiler.mainmodule.flatten_mclass_hierarchy)
		end

		super
	end

	# Write `poset` to a C file
	private fun write_poset_to_file(compiler: AbstractCompiler, name: String, poset: POSet[Object])
	do
		var json = poset.to_thin_json

		var code = new CodeFile(name)
		compiler.files.add code

		var writer = new CodeWriter(code)
		writer.add """
char *{{{name}}} = "{{{json.escape_to_c}}}";
		"""
	end
end
src/compiler/compiler_serialization.nit:21,1--53,3

nitc :: java_compiler $ ModelBuilder
redef class ModelBuilder

	# Start the Java compiler
	fun run_java_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis) do
		var time0 = get_time
		toolcontext.info("*** GENERATING JAVA ***", 1)

		var compiler = new JavaCompiler(mainmodule, self, runtime_type_analysis)
		compiler.do_compilation

		var time1 = get_time
		toolcontext.info("*** END GENERATING JAVA: {time1-time0} ***", 2)
		write_and_make(compiler)
	end

	# Write Java code and compile it into an executable jar
	fun write_and_make(compiler: JavaCompiler) do
		var time0 = get_time
		toolcontext.info("*** WRITING JAVA ***", 1)

		compiler.compile_dir.mkdir

		var jfiles = write_java_files(compiler)

		var time1 = get_time
		toolcontext.info("*** END WRITING JAVA: {time1-time0} ***", 2)

		time0 = time1
		toolcontext.info("*** COMPILING JAVA ***", 1)

		if toolcontext.opt_ant.value then
			build_with_ant(compiler, jfiles)
		else
			build_with_make(compiler, jfiles)
		end
		write_shell_script(compiler)

		time1 = get_time
		toolcontext.info("*** END COMPILING JAVA: {time1-time0} ***", 2)
	end

	# Write files managed by `compiler` into concrete files
	fun write_java_files(compiler: JavaCompiler): Array[String] do
		var jfiles = new Array[String]
		for f in compiler.files do
			var filepath = "{compiler.compile_dir}/{f.filename}"
			var file = cache_file(filepath)
			for line in f.lines do file.write(line)
			close_cache(filepath, file)
			jfiles.add(f.filename)
		end
		return jfiles
	end

	# Cache a file as `{filepath}.tmp` and replace the original if different
	private fun cache_file(filepath: String): FileWriter do
		if toolcontext.opt_ant.value and filepath.file_exists then
			return new FileWriter.open("{filepath}.tmp")
		else
			return new FileWriter.open(filepath)
		end
	end

	# Close the writer and move tmp file to original if modified
	private fun close_cache(filepath: String, file: FileWriter) do
		file.close
		if "{filepath}.tmp".file_exists then
			sys.system("if ! diff {filepath}.tmp {filepath} > /dev/null; then mv {filepath}.tmp {filepath}; else rm {filepath}.tmp; fi")
		end
	end

	# Compile Java generated files using `make`
	fun build_with_make(compiler: JavaCompiler, jfiles: Array[String]) do
		write_manifest(compiler)
		write_makefile(compiler, jfiles)
		var compile_dir = compiler.compile_dir
		var outname = compiler.outname.to_path.filename
		toolcontext.info("make -N -C {compile_dir} -f {outname}.mk", 2)
		var res
		if toolcontext.verbose_level >= 3 then
			res = sys.system("make -B -C {compile_dir} -f {outname}.mk 2>&1")
		else
			res = sys.system("make -B -C {compile_dir} -f {outname}.mk 2>&1 > /dev/null")
		end
		if res != 0 then toolcontext.error(null, "make failed! Error code: {res}.")
	end

	# Compile Java sources using `ant`
	fun build_with_ant(compiler: JavaCompiler, jfiles: Array[String]) do
		compile_antfile(compiler, jfiles)
		var outname = compiler.outname.to_path.filename
		var antpath = "{compiler.compile_dir}/{outname}.xml"
		self.toolcontext.info("ant jar -f {antpath}", 2)
		var res
		if self.toolcontext.verbose_level >= 3 then
			res = sys.system("ant jar -f {antpath} 2>&1")
		else
			res = sys.system("ant jar -f {antpath} 2>&1 > /dev/null")
		end
		if res != 0 then
			toolcontext.error(null, "ant compile failed! Error code: {res}.")
		end
	end

	# Write the Makefile used to compile Java generated files into an executable jar
	fun write_makefile(compiler: JavaCompiler, jfiles: Array[String]) do
		# list class files from jfiles
		var ofiles = new List[String]
		for f in jfiles do ofiles.add(f.strip_extension(".java") + ".class")

		var compile_dir = compiler.compile_dir
		var outname = compiler.outname.to_path.filename
		var outpath = (sys.getcwd / compiler.outname).simplify_path
		var makename = "{compile_dir}/{outname}.mk"
		var makefile = new FileWriter.open(makename)

		makefile.write("JC = javac\n")
		makefile.write("JAR = jar\n\n")

		makefile.write("all: {outpath}.jar\n\n")

		makefile.write("{outpath}.jar: {compiler.mainmodule.jname}_Main.class\n")
		makefile.write("\t$(JAR) cfm {outpath}.jar {outname}.mf {ofiles.join(" ")}\n\n")

		makefile.write("{compiler.mainmodule.jname}_Main.class:\n")
		makefile.write("\t$(JC) {jfiles.join(" ")}\n\n")

		makefile.write("clean:\n")
		makefile.write("\trm {ofiles.join(" ")} 2>/dev/null\n\n")

		makefile.close
		toolcontext.info("Generated makefile: {makename}", 2)
	end

	# The Ant `build.xml` script used to compile build the final jar
	fun compile_antfile(compiler: JavaCompiler, jfiles: Array[String]) do
		var compile_dir = compiler.compile_dir
		var outname = compiler.outname.to_path.filename
		var outpath = (sys.getcwd / compiler.outname).simplify_path
		var antname = "{compile_dir}/{outname}.xml"
		var antfile = new FileWriter.open(antname)
		var jname = compiler.mainmodule.jname
		antfile.write("<project>")
		antfile.write(" <target name=\"compile\">")
		antfile.write("  <mkdir dir=\"classes\"/>")
		antfile.write("  <javac includes=\"{compiler.mainmodule.jname}_Main.java {jfiles.join(" ")}\" srcdir=\".\" destdir=\"classes\"/>")
		antfile.write(" </target>")
		antfile.write(" <target name=\"jar\" depends=\"compile\">")
		antfile.write("  <jar destfile=\"{outpath}.jar\" basedir=\"classes\">")
		antfile.write("   <manifest>")
		antfile.write("    <attribute name=\"Main-Class\" value=\"{jname}_Main\"/>")
		antfile.write("   </manifest>")
		antfile.write("  </jar>")
		antfile.write(" </target>")
		antfile.write("</project>")
		antfile.close
		toolcontext.info("Generated antfile: {antname}", 2)
	end

	# Write the Java manifest file
	private fun write_manifest(compiler: JavaCompiler) do
		var compile_dir = compiler.compile_dir
		var outname = compiler.outname.to_path.filename
		var maniffile = new FileWriter.open("{compile_dir}/{outname}.mf")
		maniffile.write("Manifest-Version: 1.0\n")
		maniffile.write("Main-Class: {compiler.mainmodule.jname}_Main\n")
		maniffile.close
	end

	# Write a simple bash script that runs the jar like it was a binary generated by nitc
	private fun write_shell_script(compiler: JavaCompiler) do
		var outname = compiler.outname
		var shfile = new FileWriter.open(outname)
		shfile.write("#!/bin/bash\n")
		shfile.write("java -jar {outname}.jar \"$@\"\n")
		shfile.close
		sys.system("chmod +x {outname}")
	end
end
src/compiler/java_compiler.nit:48,1--226,3

nitc :: separate_erasure_compiler $ ModelBuilder
redef class ModelBuilder
	fun run_separate_erasure_compiler(mainmodule: MModule, runtime_type_analysis: nullable RapidTypeAnalysis)
	do
		var time0 = get_time
		self.toolcontext.info("*** GENERATING C ***", 1)

		var compiler = new SeparateErasureCompiler(mainmodule, self, runtime_type_analysis)
		compiler.do_compilation
		compiler.display_stats
		var time1 = get_time
		self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
		write_and_make(compiler)
	end
end
src/compiler/separate_erasure_compiler.nit:66,1--79,3

nitc :: test_astbuilder $ ModelBuilder
redef class ModelBuilder
	redef fun run_naive_interpreter(mainmodule: MModule, arguments: Array[String])
	do
		var clone_visitor = new CloneVisitor
		for nmodule in self.nmodules do
			clone_visitor.enter_visit(nmodule)
		end
		super
	end
end
src/test_astbuilder.nit:25,1--34,3