123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847openStd(** {1 OCaml commandline parsing} *)let{Logger.log}=Logger.for_section"Mconfig"typeocaml={include_dirs:stringlist;hidden_dirs:stringlist;no_std_include:bool;unsafe:bool;classic:bool;principal:bool;real_paths:bool;threads:[`None|`Threads|`Vmthreads];recursive_types:bool;strict_sequence:bool;applicative_functors:bool;nopervasives:bool;strict_formats:bool;open_modules:stringlist;ppx:stringwith_workdirlist;pp:stringwith_workdiroption;warnings:Warnings.state}letdump_warningsst=letst'=Warnings.backup()inWarnings.restorest;Misc.try_finallyWarnings.dump~always:(fun()->Warnings.restorest')letdump_ocamlx=`Assoc[("include_dirs",`List(List.map~f:Json.stringx.include_dirs));("hidden_dirs",`List(List.map~f:Json.stringx.hidden_dirs));("no_std_include",`Boolx.no_std_include);("unsafe",`Boolx.unsafe);("classic",`Boolx.classic);("principal",`Boolx.principal);("real_paths",`Boolx.real_paths);("recursive_types",`Boolx.recursive_types);("strict_sequence",`Boolx.strict_sequence);("applicative_functors",`Boolx.applicative_functors);("nopervasives",`Boolx.nopervasives);("strict_formats",`Boolx.strict_formats);("open_modules",Json.listJson.stringx.open_modules);("ppx",Json.list(dump_with_workdirJson.string)x.ppx);("pp",Json.option(dump_with_workdirJson.string)x.pp);("warnings",dump_warningsx.warnings)](** Some paths can be resolved relative to a current working directory *)letcwd=refNoneletunsafe_get_cwd()=match!cwdwith|None->assertfalse|Somecwd->cwdletcanonicalize_filenamepath=Misc.canonicalize_filename?cwd:!cwdpathletmarg_pathf=Marg.param"path"(funpathacc->f(canonicalize_filenamepath)acc)letmarg_commandlinef=Marg.param"command"(funworkvalacc->f{workdir=unsafe_get_cwd();workval}acc)(** {1 Merlin high-level settings} *)typemerlin={build_path:stringlist;source_path:stringlist;hidden_build_path:stringlist;hidden_source_path:stringlist;cmi_path:stringlist;cmt_path:stringlist;index_files:stringlist;extensions:stringlist;suffixes:(string*string)list;stdlib:stringoption;source_root:stringoption;unit_name:stringoption;wrapping_prefix:stringoption;reader:stringlist;protocol:[`Json|`Sexp];log_file:stringoption;log_sections:stringlist;config_path:stringoption;use_ppx_cache:bool;exclude_query_dir:bool;flags_to_apply:stringlistwith_workdirlist;flags_applied:stringlistwith_workdirlist;failures:stringlist;extension_to_reader:(string*string)list;cache_lifespan:int}letdump_merlinx=letdump_flag_listflags=dump_with_workdir(Json.listJson.string)flagsin`Assoc[("build_path",`List(List.map~f:Json.stringx.build_path));("source_path",`List(List.map~f:Json.stringx.source_path));("hidden_build_path",`List(List.map~f:Json.stringx.hidden_build_path));("hidden_source_path",`List(List.map~f:Json.stringx.hidden_source_path));("cmi_path",`List(List.map~f:Json.stringx.cmi_path));("cmt_path",`List(List.map~f:Json.stringx.cmt_path));("index_files",`List(List.map~f:Json.stringx.index_files));("flags_applied",`List(List.map~f:dump_flag_listx.flags_applied));("extensions",`List(List.map~f:Json.stringx.extensions));("suffixes",`List(List.map~f:(fun(impl,intf)->`Assoc[("impl",`Stringimpl);("intf",`Stringintf)])x.suffixes));("stdlib",Json.optionJson.stringx.stdlib);("source_root",Json.optionJson.stringx.source_root);("unit_name",Json.optionJson.stringx.unit_name);("wrapping_prefix",Json.optionJson.stringx.wrapping_prefix);("reader",`List(List.map~f:Json.stringx.reader));("protocol",matchx.protocolwith|`Json->`String"json"|`Sexp->`String"sexp");("log_file",Json.optionJson.stringx.log_file);("log_sections",Json.listJson.stringx.log_sections);("flags_to_apply",`List(List.map~f:dump_flag_listx.flags_to_apply));("failures",`List(List.map~f:Json.stringx.failures));("assoc_suffixes",`List(List.map~f:(fun(suffix,reader)->`Assoc[("extension",`Stringsuffix);("reader",`Stringreader)])x.extension_to_reader));("cache_lifespan",Json.string(string_of_intx.cache_lifespan))]moduleVerbosity=structtypet=Smart|Lvlofintletdefault=Lvl0letto_intt~for_smart=matchtwith|Smart->for_smart|Lvlv->vletparam_spec="\"smart\" | <integer>"letof_string=function|"smart"->Smart|maybe_int->(tryLvl(int_of_stringmaybe_int)with_->invalid_arg("argument should be: "^param_spec))letto_string=function|Smart->"smart"|Lvlv->"lvl "^string_of_intvletto_jsont=`String(to_stringt)endtypequery={filename:string;directory:string;printer_width:int;verbosity:Verbosity.t}letdump_queryx=`Assoc[("filename",`Stringx.filename);("directory",`Stringx.directory);("printer_width",`Intx.printer_width);("verbosity",Verbosity.to_jsonx.verbosity)]typet={ocaml:ocaml;merlin:merlin;query:query}letdumpx=`Assoc[("ocaml",dump_ocamlx.ocaml);("merlin",dump_merlinx.merlin);("query",dump_queryx.query)]letarguments_table=Hashtbl.create67letstdlib=letenv=trySome(Sys.getenv"OCAMLLIB")withNot_found->(trySome(Sys.getenv"CAMLLIB")withNot_found->None)infunconfig->matchconfig.merlin.stdlibwith|Somestdlib->stdlib|None->(matchenvwith|Somestdlib->stdlib|None->Standard_library.path)letnormalize_stept=letmerlin=t.merlininifmerlin.flags_to_apply<>[]thenletflagss=merlin.flags_to_applyinlett={twithmerlin={merlinwithflags_to_apply=[];flags_applied=flagss@merlin.flags_applied}}inletfailures=ref[]inletwarningfailure=failures:=failure::!failuresinlett=List.fold_left~f:(funt{workdir;workval}->fst(let_refcwd(Someworkdir)(Marg.parse_all~warningarguments_table[]workvalt)))~init:tflagssin{twithmerlin={t.merlinwithfailures=!failures@t.merlin.failures}}elsetletis_normalizedt=letmerlin=t.merlininmerlin.flags_to_apply=[]letrecnormalizet=ifis_normalizedtthen(log~title:"normalize""%a"Logger.json(fun()->dumpt);t)elsenormalize(normalize_stept)letmerge_merlin_configdotmerlin~failures~config_path={merlinwithbuild_path=dot.Mconfig_dot.build_path@merlin.build_path;source_path=dot.source_path@merlin.source_path;hidden_build_path=dot.hidden_build_path@merlin.hidden_build_path;hidden_source_path=dot.hidden_source_path@merlin.hidden_source_path;cmi_path=dot.cmi_path@merlin.cmi_path;cmt_path=dot.cmt_path@merlin.cmt_path;index_files=dot.index_files@merlin.index_files;exclude_query_dir=dot.exclude_query_dir||merlin.exclude_query_dir;use_ppx_cache=dot.use_ppx_cache||merlin.use_ppx_cache;extensions=dot.extensions@merlin.extensions;suffixes=dot.suffixes@merlin.suffixes;stdlib=(ifdot.stdlib=Nonethenmerlin.stdlibelsedot.stdlib);source_root=(ifdot.source_root=Nonethenmerlin.source_rootelsedot.source_root);unit_name=(ifdot.unit_name=Nonethenmerlin.unit_nameelsedot.unit_name);wrapping_prefix=(ifdot.wrapping_prefix=Nonethenmerlin.wrapping_prefixelsedot.wrapping_prefix);reader=(ifdot.reader=[]thenmerlin.readerelsedot.reader);flags_to_apply=dot.flags@merlin.flags_to_apply;failures=failures@merlin.failures;config_path=Someconfig_path}letget_external_configpatht=letpath=Misc.canonicalize_filenamepathinletdirectory=Filename.dirnamepathinmatchMconfig_dot.find_project_contextdirectorywith|None->t|Some(ctxt,config_path)->letdot,failures=Mconfig_dot.get_configctxtpathinletmerlin=merge_merlin_configdott.merlin~failures~config_pathinnormalize{twithmerlin}letmerlin_flags=[("-build-path",marg_path(fundirmerlin->{merlinwithbuild_path=dir::merlin.build_path}),"<dir> Add <dir> to merlin build path");("-source-path",marg_path(fundirmerlin->{merlinwithsource_path=dir::merlin.source_path}),"<dir> Add <dir> to merlin source path");("-hidden-build-path",marg_path(fundirmerlin->{merlinwithhidden_build_path=dir::merlin.hidden_build_path}),"<dir> Add <dir> to merlin hidden build path");("-hidden-source-path",marg_path(fundirmerlin->{merlinwithhidden_source_path=dir::merlin.hidden_source_path}),"<dir> Add <dir> to merlin hidden source path");("-cmi-path",marg_path(fundirmerlin->{merlinwithcmi_path=dir::merlin.cmi_path}),"<dir> Add <dir> to merlin cmi path");("-cmt-path",marg_path(fundirmerlin->{merlinwithcmt_path=dir::merlin.cmt_path}),"<dir> Add <dir> to merlin cmt path");("-index-file",marg_path(funfilemerlin->{merlinwithindex_files=file::merlin.index_files}),"<file> Add <file> to the index files used by merlin");("-reader",Marg.param"command"(funreadermerlin->{merlinwithreader=Shell.split_commandreader}),"<command> Use <command> as a merlin reader");("-assocsuffix",Marg.param"suffix:reader"(funassoc_pairmerlin->matchMisc.rev_string_split~on:':'assoc_pairwith|[reader;suffix]->{merlinwithextension_to_reader=(suffix,reader)::merlin.extension_to_reader}|_->merlin),"Associate suffix with reader");("-addsuffix",Marg.param"implementation Suffix, interface Suffix"(funsuffix_pairmerlin->matchMisc.rev_string_split~on:':'suffix_pairwith|[intf;impl]->{merlinwithsuffixes=(impl,intf)::merlin.suffixes}|_->merlin),"Add a suffix implementation,interface pair");("-extension",Marg.param"extension"(funextensionmerlin->matchExtension.lookupextensionwith|None->invalid_arg"Unknown extension"|Some_->{merlinwithextensions=extension::merlin.extensions}),"<extension> Load merlin syntax extension");("-flags",Marg.param"string"(funflagsmerlin->letflags={workdir=unsafe_get_cwd();workval=Shell.split_commandflags}in{merlinwithflags_to_apply=flags::merlin.flags_to_apply}),"<quoted flags> Unescape argument and interpret it as more flags");("-protocol",Marg.param"protocol"(funprotmerlin->matchprotwith|"json"->{merlinwithprotocol=`Json}|"sexp"->{merlinwithprotocol=`Sexp}|_->invalid_arg"Valid protocols are 'json' and 'sexp'"),"<protocol> Select frontend protocol ('json' or 'sexp')");("-log-file",Marg.param"file"(funfilemerlin->{merlinwithlog_file=Somefile}),"<file> Log messages to specified file ('' for disabling, '-' for stderr)");("-log-section",Marg.param"file"(funsectionmerlin->letsections=String.split_on_char_','sectionin{merlinwithlog_sections=sections@merlin.log_sections}),"<section,...> Only log specific sections (separated by comma)");("-ocamllib-path",marg_path(funpathmerlin->{merlinwithstdlib=Somepath}),"<path> Change path of ocaml standard library");("-cache-lifespan",Marg.param"int"(funprotmerlin->try{merlinwithcache_lifespan=int_of_stringprot}with_->invalid_arg"Valid value is int"),"Change file cache retention period. It's measured in minutes. Default \
value is 5.");((* Legacy support for janestreet. Ignored. To be removed soon. *)"-attributes-allowed",Marg.unit_ignore," DEPRECATED")]letquery_flags=[("-verbosity",Marg.paramVerbosity.param_spec(funverbosityquery->letverbosity=Verbosity.of_stringverbosityin{querywithverbosity}),"\"smart\" | <integer> Verbosity determines the number of expansions of \
aliases in answers. \"smart\" is equivalent to verbosity=0 but expands \
module types.");("-printer-width",Marg.param"integer"(funwidthquery->letprinter_width=tryint_of_stringwidthwith_->invalid_arg"argument should be an integer"in{querywithprinter_width}),"<integer> Optimal width for formatting types, signatures, etc")]letocaml_ignored_flags=["-a";"-absname";"-alias-deps";"-annot";"-app-funct";"-bin-annot";"-c";"-compact";"-compat-32";"-config";"-custom";"-dalloc";"-dclambda";"-dcmm";"-dcombine";"-dcse";"-dflambda";"-dflambda-no-invariants";"-dflambda-verbose";"-dinstr";"-dinterf";"-dlambda";"-dlinear";"-dlive";"-dparsetree";"-dprefer";"-dshape";"-drawclambda";"-drawflambda";"-drawlambda";"-dreload";"-dscheduling";"-dsel";"-dsource";"-dspill";"-dsplit";"-dstartup";"-dtimings";"-dtypedtree";"-dtypes";"-dump-pass";"-fno-PIC";"-fPIC";"-g";"-i";"-inlining-report";"-keep-docs";"-keep-docs";"-keep-locs";"-linkall";"-make_runtime";"-make-runtime";"-modern";"-no-alias-deps";"-noassert";"-noautolink";"-no-check-prims";"-nodynlink";"-no-float-const-prop";"-no-keep-locs";"-no-principal";"-no-rectypes";"-no-strict-formats";"-no-strict-sequence";"-no-unbox-free-vars-of-clos";"-no-unbox-specialised-args";"-no-unboxed-types";"-O2";"-O3";"-Oclassic";"-opaque";"-output-complete-obj";"-output-obj";"-p";"-pack";"-remove-unused-arguments";"-S";"-shared";"-unbox-closures";"-unboxed-types";"-v";"-verbose";"-where"]letocaml_ignored_parametrized_flags=["-cc";"-cclib";"-ccopt";"-color";"-dflambda-let";"-dllib";"-dllpath";"-for-pack";"-impl";"-inline-alloc-cost";"-inline-branch-cost";"-inline-branch-factor";"-inline-call-cost";"-inline-indirect-cost";"-inline-lifting-benefit";"-inline-max-depth";"-inline-max-unroll";"-inline";"-inline-prim-cost";"-inline-toplevel";"-intf";"-intf_suffix";"-intf-suffix";"-o";"-rounds";"-runtime-variant";"-unbox-closures-factor";"-use-prims";"-use_runtime";"-use-runtime";"-error-style";"-dump-dir";"-cmi-file"]letocaml_warnings_spec~error=Marg.param"warning specification"(funspecocaml->letb'=Warnings.backup()inWarnings.restoreocaml.warnings;Misc.try_finally(fun()->ignore@@Warnings.parse_optionserrorspec;{ocamlwithwarnings=Warnings.backup()})~always:(fun()->Warnings.restoreb'))letocaml_alert_spec=Marg.param"alert specification"(funspecocaml->letb'=Warnings.backup()inWarnings.restoreocaml.warnings;Misc.try_finally(fun()->Warnings.parse_alert_optionspec;{ocamlwithwarnings=Warnings.backup()})~always:(fun()->Warnings.restoreb'))letocaml_flags=[("-I",marg_path(fundirocaml->{ocamlwithinclude_dirs=dir::ocaml.include_dirs}),"<dir> Add <dir> to the list of include directories");("-H",marg_path(fundirocaml->{ocamlwithhidden_dirs=dir::ocaml.hidden_dirs}),"<dir> Add <dir> to the list of \"hidden\" include directories\n\
\ (Like -I, but the program can not directly reference these \
dependencies)");("-nostdlib",Marg.unit(funocaml->{ocamlwithno_std_include=true})," Do not add default directory to the list of include directories");("-unsafe",Marg.unit(funocaml->{ocamlwithunsafe=true})," Do not compile bounds checking on array and string access");("-labels",Marg.unit(funocaml->{ocamlwithclassic=false})," Use commuting label mode");("-nolabels",Marg.unit(funocaml->{ocamlwithclassic=true})," Ignore non-optional labels in types");("-principal",Marg.unit(funocaml->{ocamlwithprincipal=true})," Check principality of type inference");("-real-paths",Marg.unit(funocaml->{ocamlwithreal_paths=true})," Display real paths in types rather than short ones");("-short-paths",Marg.unit(funocaml->{ocamlwithreal_paths=false})," Shorten paths in types");("-rectypes",Marg.unit(funocaml->{ocamlwithrecursive_types=true})," Allow arbitrary recursive types");("-strict-sequence",Marg.unit(funocaml->{ocamlwithstrict_sequence=true})," Left-hand part of a sequence must have type unit");("-no-app-funct",Marg.unit(funocaml->{ocamlwithapplicative_functors=false})," Deactivate applicative functors");("-thread",Marg.unit(funocaml->{ocamlwiththreads=`Threads})," Add support for system threads library");("-vmthread",Marg.unit(funocaml->{ocamlwiththreads=`None})," Add support for VM-scheduled threads library");("-safe-string",Marg.unit(funocaml->ocaml)," Default to true unconditionally since 5.00");("-nopervasives",Marg.unit(funocaml->{ocamlwithnopervasives=true})," Don't open Pervasives module (advanced)");("-strict-formats",Marg.unit(funocaml->{ocamlwithstrict_formats=true})," Reject invalid formats accepted by legacy implementations");("-open",Marg.param"module"(funmdocaml->{ocamlwithopen_modules=md::ocaml.open_modules}),"<module> Opens the module <module> before typing");("-ppx",marg_commandline(funcommandocaml->{ocamlwithppx=command::ocaml.ppx}),"<command> Pipe abstract syntax trees through preprocessor <command>");("-pp",marg_commandline(funppocaml->{ocamlwithpp=Somepp}),"<command> Pipe sources through preprocessor <command>");("-w",ocaml_warnings_spec~error:false,Printf.sprintf"<list> Enable or disable warnings according to <list>:\n\
\ +<spec> enable warnings in <spec>\n\
\ -<spec> disable warnings in <spec>\n\
\ @<spec> enable warnings in <spec> and treat them as errors\n\
\ <spec> can be:\n\
\ <num> a single warning number\n\
\ <num1>..<num2> a range of consecutive warning numbers\n\
\ <letter> a predefined set\n\
\ default setting is %S"Warnings.defaults_w);("-warn-error",ocaml_warnings_spec~error:true,Printf.sprintf"<list> Enable or disable error status for warnings according\n\
\ to <list>. See option -w for the syntax of <list>.\n\
\ Default setting is %S"Warnings.defaults_warn_error);("-alert",ocaml_alert_spec,Printf.sprintf"<list> Enable or disable alerts according to <list>:\n\
\ +<alertname> enable alert <alertname>\n\
\ -<alertname> disable alert <alertname>\n\
\ ++<alertname> treat <alertname> as fatal error\n\
\ --<alertname> treat <alertname> as non-fatal\n\
\ @<alertname> enable <alertname> and treat it as fatal error\n\
\ <alertname> can be 'all' to refer to all alert names")](** {1 Main configuration} *)letinitial={ocaml={include_dirs=[];hidden_dirs=[];no_std_include=false;unsafe=false;classic=false;principal=false;real_paths=true;threads=`None;recursive_types=false;strict_sequence=false;applicative_functors=true;nopervasives=false;strict_formats=false;open_modules=[];ppx=[];pp=None;warnings=Warnings.backup()};merlin={build_path=[];source_path=[];hidden_build_path=[];hidden_source_path=[];cmi_path=[];cmt_path=[];index_files=[];extensions=[];suffixes=[(".ml",".mli");(".re",".rei")];stdlib=None;source_root=None;unit_name=None;wrapping_prefix=None;reader=[];protocol=`Json;log_file=None;log_sections=[];config_path=None;exclude_query_dir=false;use_ppx_cache=false;flags_to_apply=[];flags_applied=[];failures=[];extension_to_reader=[(".re","reason");(".rei","reason")];cache_lifespan=5};query={filename="*buffer*";directory=Sys.getcwd();verbosity=Verbosity.default;printer_width=0}}letparse_arguments~wd~warninglocal_specargstlocal=let_refcwd(Somewd)@@fun()->Marg.parse_all~warningarguments_tablelocal_specargstlocalletglobal_flags=[("-filename",marg_path(funpatht->letquery=t.queryinletpath=Misc.canonicalize_filenamepathinletfilename=Filename.basenamepathinletdirectory=Filename.dirnamepathinlett={twithquery={querywithfilename;directory}}inLogger.with_log_filet.merlin.log_file~sections:t.merlin.log_sections@@fun()->get_external_configpatht),"<path> Path of the buffer; extension determines the kind of file \
(interface or implementation), basename is used as name of the module \
being definer, directory is used to resolve other relative paths");("-dot-merlin",marg_path(fundotmerlint->get_external_configdotmerlint),"<path> Load <path> as a .merlin; if it is a directory, look for .merlin \
here or in a parent directory")]let()=List.iter~f:(funname->Hashtbl.addarguments_tablenameMarg.unit_ignore)ocaml_ignored_flags;List.iter~f:(funname->Hashtbl.addarguments_tablenameMarg.param_ignore)ocaml_ignored_parametrized_flags;letlensprjupdflag:_Marg.t=funargsa->letcwd'=match!cwdwith|Nonewhena.query.directory<>""->Somea.query.directory|cwd->cwdinlet_refcwdcwd'@@fun()->letargs,b=flagargs(prja)in(args,updab)inletaddprjupd(name,flag,_doc)=ifHashtbl.memarguments_tablenamethenfailwith("Duplicate flag spec: "^name);Hashtbl.addarguments_tablename(lensprjupdflag)inList.iter~f:(add(funx->x.ocaml)(funxocaml->{xwithocaml}))ocaml_flags;List.iter~f:(add(funx->x.merlin)(funxmerlin->{xwithmerlin}))merlin_flags;List.iter~f:(add(funx->x.query)(funxquery->{xwithquery}))query_flags;List.iter~f:(add(funx->x)(fun_x->x))global_flagsletflags_for_completion()=List.sort~cmp:compare("-dot-merlin"::"-reader"::List.map~f:(fun(x,_,_)->x)ocaml_flags)letdocument_argumentsoc=letprint_docflags=List.iter~f:(fun(name,_flag,doc)->Printf.fprintfoc" %s\t%s\n"namedoc)flagsinoutput_stringoc"Flags affecting Merlin:\n";print_docmerlin_flags;print_docquery_flags;output_stringoc"Flags affecting OCaml frontend:\n";print_dococaml_flags;output_stringoc"Flags accepted by ocamlc and ocamlopt but not affecting merlin will be \
ignored.\n"letsource_pathconfig=letstdlib=ifconfig.ocaml.no_std_includethen[]else[stdlibconfig]inList.concat[[config.query.directory];stdlib;config.merlin.source_path;config.merlin.hidden_source_path]|>List.filter_dupletcollect_paths~log_title~configpaths=letdirs=matchconfig.ocaml.threadswith|`None->config.ocaml.include_dirs|`Threads->"+threads"::config.ocaml.include_dirs|`Vmthreads->"+vmthreads"::config.ocaml.include_dirsinletdirs=paths@dirsinletstdlib=stdlibconfiginletexp_dirs=List.map~f:(Misc.expand_directorystdlib)dirsinletstdlib=ifconfig.ocaml.no_std_includethen[]else[stdlib]inletdirs=List.rev_appendexp_dirsstdlibinletresult=ifconfig.merlin.exclude_query_dirthendirselseconfig.query.directory::dirsinletresult=List.filter_dupresultinlog~title:log_title"%d items in path, %d after deduplication"(List.lengthresult)(List.lengthresult);resultletbuild_pathconfig=collect_paths~log_title:"build_path"~config(config.merlin.cmi_path@config.merlin.build_path)lethidden_build_pathconfig=config.merlin.hidden_build_path@config.ocaml.hidden_dirsletcmt_pathconfig=collect_paths~log_title:"cmt_path"~config(config.merlin.cmt_path@config.merlin.build_path@config.merlin.hidden_build_path)letglobal_modules?(include_current=false)config=letmodules=Misc.modules_in_path~ext:".cmi"(build_pathconfig)inifinclude_currentthenmoduleselsematchconfig.query.filenamewith|""->modules|filename->List.remove(Misc.unitnamefilename)modules(** {1 Accessors for other information} *)letfilenamet=t.query.filenameletunitnamet=matcht.merlin.unit_namewith|Somename->Misc.unitnamename|None->letbasename=Misc.unitnamet.query.filenameinbeginmatcht.merlin.wrapping_prefixwith|Someprefix->prefix^basename|None->basenameendletintf_or_implt=letextension=Filename.extensiont.query.filenameintryList.find_mapt.merlin.suffixes~f:(fun(impl,intf)->ifString.equalextensionimplthenSomeUnit_info.ImplelseifString.equalextensionintfthenSomeUnit_info.IntfelseNone)withNot_found->Unit_info.Implletunit_infot=Unit_info.make~source_file:t.query.filename(intf_or_implt)(unitnamet)