1/*****************************************************************************
    2 * This file is part of the Prolog Development Tool (PDT)
    3 * 
    4 * WWW: http://sewiki.iai.uni-bonn.de/research/pdt/start
    5 * Mail: pdt@lists.iai.uni-bonn.de
    6 * Copyright (C): 2004-2012, CS Dept. III, University of Bonn
    7 * 
    8 * All rights reserved. This program is  made available under the terms
    9 * of the Eclipse Public License v1.0 which accompanies this distribution,
   10 * and is available at http://www.eclipse.org/legal/epl-v10.html
   11 * 
   12 ****************************************************************************/
   13
   14:- module( pdt_search,
   15         [ find_predicate_reference/9                  % (+Functor,+Arity,?DefFile,?DefModule,?RefModule,?RefName,?RefArity,?RefFile,?RefLine,?PropertyList)
   16         , update_predicate_reference_search_term_to_context/5
   17         , find_categorized_predicate_definitions/11       % (+EnclFile,+SelectionLine, +Term, -Functor, -Arity, -This, -DeclOrDef, -DefiningEntity, -FullPath, -Line, -Properties,-Visibility,+ExactMatch)
   18         , find_predicate_definitions/10
   19         , find_primary_definition_visible_in/9
   20         , find_definition_contained_in/9
   21         , find_definition_contained_in/10
   22         , find_completion/14
   23         , find_entity_definition/6
   24         , find_module_reference/9
   25         , loaded_file/1
   26         , loaded_by/4
   27         ]).   28
   29:- use_module( prolog_connector_pl(split_file_path),
   30             [ split_file_path/5                % (File,Folder,FileName,BaseName,Extension)
   31             ] ).   32:- use_module( 'xref/pdt_xref', 
   33             [ find_reference_to/9             % ...
   34             ] ).   35:- use_module( properties, 
   36             [ properties_for_predicate/4
   37             ] ).   38%:- use_module( pdt_prolog_library(utils4modules_visibility),
   39%             [ module_of_file/2                 % (File,FileModule)
   40%             , defined_in_module/3              % (Module,Name,Arity),
   41%             , declared_in_file/4               % (Module,Name,Arity,Location)
   42%             , defined_in_files/4               % (Module,Name,Arity,Locations)
   43%             ] ).
   44:- use_module(pdt_prolog_library(utils4modules_visibility)).   45:- use_module(pdt_manual_entry).   46:- use_module(library(charsio)). 
   47:- use_module(library(lists)). 
   48:- use_module(library(prolog_clause)).   49:- use_module(library(prolog_source), [
   50	read_source_term_at_location/3
   51]).   52:- use_module(pdt_prolog_library(compatibility), [
   53	pdt_source_file/2
   54]).   55:- use_module('callgraph/pdt_call_graph', [
   56	ensure_call_graph_generated/0,
   57	pdt_walk_code/1
   58]).   59
   60:- op(600, xfy, ::).   % Logtalk message sending operator
   61
   62%%% find_predicate_reference(Term, ExactMatch, Root, EnclFile, LineInEnclFile, RefModule, RefName, RefArity, RefFile, Position, PropertyList)
   63%find_predicate_reference(Term0, ExactMatch, Root, EnclFile, _LineInEnclFile, RefModule, RefName, RefArity, RefFile, Position, PropertyList) :-
   64%	(	nonvar(EnclFile),
   65%		\+ split_file_path(EnclFile, _, _, _, lgt),
   66%		Term0 = predicate(M, S0, F, S1, A),
   67%		var(M)
   68%	->	once(module_of_file(EnclFile, FileModule)),
   69%		(	nonvar(F),
   70%			nonvar(A),
   71%			functor(H, F, A),
   72%			predicate_property(FileModule:H, imported_from(ImportedModule))
   73%		->	Term = predicate(ImportedModule, S0, F, S1, A)
   74%		;	Term = predicate(FileModule, S0, F, S1, A)
   75%		)
   76%	;	Term = Term0
   77%	),
   78%	find_reference_to(Term, ExactMatch, Root, RefModule, RefName, RefArity, RefFile, Position, PropertyList).
 find_predicate_reference(Term, ExactMatch, Root, RefModule, RefName, RefArity, RefFile, Position, PropertyList)
   81find_predicate_reference(Term, ExactMatch, Root, RefModule, RefName, RefArity, RefFile, Position, PropertyList) :-
   82	current_predicate(logtalk_load/1),
   83	logtalk_adapter::find_reference_to(Term, ExactMatch, Root, RefModule, RefName, RefArity, RefFile, Line, PropertyList),
   84	(	var(RefName),
   85		read_term_position_at_location(RefFile, Line, user, Position)
   86	->	true
   87	;	Position = Line
   88	).
   89find_predicate_reference(Term, ExactMatch, Root, RefModule, RefName, RefArity, RefFile, Position, PropertyList) :-
   90	find_reference_to(Term, ExactMatch, Root, RefModule, RefName, RefArity, RefFile, Position, PropertyList).
 update_predicate_reference_search_term_to_context(+Term, +EnclFile, +LineInEnclFile, -NewModule, -NewTerm)
   93update_predicate_reference_search_term_to_context(Term, EnclFile, _LineInEnclFile, NewModule, NewTerm) :-
   94	(	nonvar(EnclFile),
   95		\+ split_file_path(EnclFile, _, _, _, lgt),
   96		Term = predicate(M, S0, F, S1, A),
   97		var(M)
   98	->	once(module_of_file(EnclFile, FileModule)),
   99		(	nonvar(F),
  100			nonvar(A),
  101			functor(H, F, A),
  102			predicate_property(FileModule:H, imported_from(ImportedModule))
  103		->	NewModule = ImportedModule
  104		;	NewModule = FileModule
  105		),
  106		NewTerm = predicate(NewModule, S0, F, S1, A)
  107	;	NewTerm = Term
  108	).
  109
  110        /***********************************************************************
  111         * Find Definitions and Declarations and categorize them by visibility *
  112         * --------------------------------------------------------------------*
  113         * for "Find All Declarations" (Ctrl+G) action                         *
  114         ***********************************************************************/ 
 find_predicate_definitions(+Term, +ExactMatch, ?Root, -DefiningModule, -Functor, -Arity, -DeclOrDef, -File, -Location, -Properties) is nondet
  118find_predicate_definitions(Term, ExactMatch, Root, DefiningModule, Functor, Arity, DeclOrDef, File, Location, PropertyList) :-
  119	Term = predicate(DefiningModule, _, SearchFunctor, Separator, Arity0),
  120	(	Separator == (//),
  121		nonvar(Arity0)
  122	->	Arity is Arity0 + 2
  123	;	Arity = Arity0
  124	),
  125	(	ExactMatch == true
  126	->	Functor = SearchFunctor,
  127		declared_in_module(DefiningModule, Functor, Arity, DefiningModule)
  128	;	declared_in_module(DefiningModule, Functor, Arity, DefiningModule),
  129		once(sub_atom(Functor,_,_,_,SearchFunctor))
  130	),
  131    find_decl_or_def_2(Functor,Arity,Sources),              % Unique, grouped sources (--> setof)
  132    member(DeclOrDef-DefiningModule-Locations,Sources),
  133    member(File-Lines,Locations),
  134	(	nonvar(Root)
  135	->	sub_atom(File, 0, _, _, Root)
  136	;	true
  137	),
  138    member(location(Line, Ref),Lines),
  139    properties_for_predicate(DefiningModule,Functor,Arity,PropertyList0),
  140    (	head_position_of_clause(Ref, Position)
  141    ->	Location = Position,
  142    	PropertyList = [line(Line)|PropertyList0]
  143    ;	Location = Line,
  144    	PropertyList = PropertyList0
  145    ).
  146
  147find_predicate_definitions(Term, ExactMatch, Root, DefiningModule, Functor, Arity, DeclOrDef, File,Line, PropertyList) :-
  148	current_predicate(logtalk_load/1),
  149	logtalk_adapter::find_predicate_definitions(Term, ExactMatch, Root, DefiningModule, Functor, Arity, DeclOrDef, File,Line, PropertyList).
 find_categorized_predicate_definitions(+Term, +EnclFile, +SelectionLine, Functor, Arity, DeclOrDef, DefiningEntity, FullPath, Line, Properties, Visibility)
  154find_categorized_predicate_definitions(Term, EnclFile, SelectionLine, Functor, Arity, DeclOrDef, DefiningEntity, FullPath, Line, Properties, Visibility):-
  155    Term \= _:_,
  156    split_file_path(EnclFile, _Directory,_FileName,_,lgt),
  157    !,
  158    logtalk_adapter::find_categorized_predicate_definitions(Term, EnclFile, SelectionLine, Functor, Arity, DeclOrDef, DefiningEntity, FullPath, Line, Properties, Visibility).
  159
  160find_categorized_predicate_definitions(Term, EnclFile, _SelectionLine, Functor, Arity, DeclOrDef, DefiningModule, File, Location, PropertyList, Visibility):-
  161    referenced_entity(EnclFile, ReferencedModule),    
  162    Term = predicate(_, _, Functor, _, Arity),
  163    find_decl_or_def(ReferencedModule,Functor,Arity,Sources),              % Unique, grouped sources (--> setof)
  164    member(DeclOrDef-Visibility-DefiningModule-Locations,Sources),
  165    member(File-Lines,Locations),
  166    member(location(Line, Ref),Lines),
  167    properties_for_predicate(DefiningModule,Functor,Arity,PropertyList0),
  168    (	head_position_of_clause(Ref, Position)
  169    ->	Location = Position,
  170    	PropertyList = [line(Line)|PropertyList0]
  171    ;	Location = Line,
  172    	PropertyList = PropertyList0
  173    ).
  174
  175head_position_of_clause(Ref, Position) :-
  176	catch(clause_info(Ref, _, TermPosition, _),_,fail),
  177	(	clause_property(Ref, fact)
  178	->	% fact
  179		TermPosition = HeadPosition
  180	;	% clause with body
  181		TermPosition = term_position(_, _, _, _, [HeadPosition|_])
  182	),
  183	(	HeadPosition = Start-End
  184	->	% no arguments
  185		true
  186	;	% at least one argument
  187		HeadPosition = term_position(Start, End, _, _, _)
  188	),
  189	format(atom(Position), '~w-~w', [Start, End]).
  190
  191find_decl_or_def_2(Name,Arity,Declarations) :-
  192   setof( declaration-DeclModule-Location, Name^Arity^ 
  193          ( declared_but_undefined(DeclModule,Name,Arity),
  194            declared_in_file(DeclModule,Name,Arity,Location)
  195          ),
  196          Declarations).
  197    
  198find_decl_or_def_2(Name,Arity,Definitions) :-
  199   setof( definition-DefiningModule-Locations, Name^Arity^  % Locations is list of File-Lines terms
  200          ( defined_in_module(DefiningModule,Name,Arity),
  201            defined_in_files(DefiningModule,Name,Arity,Locations)
  202%            results_context_category_label(defined, Visibility, VisibilityText)
  203          ),
  204          Definitions
  205    ). 
  206
  207referenced_entity(EnclFile, ReferencedModule) :- 
  208    (  atom(ReferencedModule)
  209    -> true                            % Explicit entity reference ReferencedModule:Term (or ReferencedModule::Term
  210    ;  module_of_file(EnclFile,ReferencedModule)   % Implicit module reference
  211    ).
  212
  213search_term_to_predicate_indicator(_:Functor/(-1), Functor/_Arity) :- !.
  214search_term_to_predicate_indicator(Functor/(-1), Functor/_Arity) :- !.
  215search_term_to_predicate_indicator(_:Functor/Arity, Functor/Arity) :- !.
  216search_term_to_predicate_indicator(Functor/Arity, Functor/Arity) :- !.
  217search_term_to_predicate_indicator(_:Term, Functor/Arity) :- !, functor(Term, Functor, Arity).
  218search_term_to_predicate_indicator(Term, Functor/Arity) :- functor(Term, Functor, Arity).
 find_decl_or_def(+ContextModule, +Name, ?Arity, -Visibility, -Sources)
  223find_decl_or_def(Module,Name,Arity,Sources) :-
  224    ( var(Module)
  225    ; var(Name)
  226    ),
  227    throw( input_argument_free(find_decl_or_def(Module,Name,Arity,Sources)) ).
  228
  229%find_decl_or_def(CallingModule,Name,Arity,['Missing declarations'-DeclModule-[File-[Line]]]) :-
  230%   referenced_but_undeclared(CallingModule,Name,Arity),
  231%   DeclModule = 'none',
  232%   File = 'none',
  233%   Line = 0.
  234find_decl_or_def(CallingModule,Name,Arity,[declaration-none-none-[none-[none]]]) :-
  235   referenced_but_undeclared(CallingModule,Name,Arity).
  236      
  237find_decl_or_def(ContextModule,Name,Arity,Declarations) :-
  238   setof( declaration-Visibility-DeclModule-Location, ContextModule^Name^Arity^ 
  239          ( declared_but_undefined(DeclModule,Name,Arity),
  240            visibility(Visibility, ContextModule,Name,Arity,DeclModule),
  241            declared_in_file(DeclModule,Name,Arity,Location)
  242%            results_context_category_label(declared, Visibility, VisibilityText)
  243          ),
  244          Declarations).
  245    
  246find_decl_or_def(ContextModule,Name,Arity,Definitions) :-
  247   setof( definition-Visibility-DefiningModule-Locations, ContextModule^Name^Arity^  % Locations is list of File-Lines terms
  248          ( defined_in_module(DefiningModule,Name,Arity),
  249            visibility(Visibility, ContextModule,Name,Arity,DefiningModule),
  250            defined_in_files(DefiningModule,Name,Arity,Locations)
  251%            results_context_category_label(defined, Visibility, VisibilityText)
  252          ),
  253          Definitions
  254    ). 
  255
  256:- multifile(results_category_label/2).  257
  258
  259:- multifile(results_context_category_label/3).  260%results_context_category_label(declared, local,      'Local declaration' ) :- !.
  261%results_context_category_label(declared, supermodule,'Imported declaration' ) :- !.
  262%results_context_category_label(declared, submodule,  'Submodule declaration') :- !.
  263%results_context_category_label(declared, invisible,  'Locally invisible declaration') :- !.
  264%
  265%results_context_category_label(defined, local,      'Local definitions' ) :- !.
  266%results_context_category_label(defined, supermodule,'Imported definitions' ) :- !.
  267%results_context_category_label(defined, submodule,  'Submodule definitions') :- !.
  268%results_context_category_label(defined, invisible,  'Locally invisible definitions') :- !.
  269
  270    
  271% These clauses must stay in this order since they determine
  272% the order of elements in the result of  find_decl_or_def
  273% and hence the order of elements in the search result view
  274% (which is the INVERSE of the order of elements that we
  275% compute here).               
  276         
  277
  278visibility(super, ContextModule,Name,Arity,DeclModule) :-
  279	(	module_imports_predicate_from(ContextModule, Name, Arity, DeclModule, overridden)
  280	;	module_imports_predicate_from(ContextModule, Name, Arity, DeclModule, imported)
  281	),
  282	!.
  283%    declared_in_module(ContextModule,Name,Arity,DeclModule),
  284%    ContextModule \== DeclModule. 
  285    
  286   
  287visibility(local, ContextModule,Name,Arity,DeclModule) :-
  288    declared_in_module(ContextModule,Name,Arity,DeclModule),
  289    ContextModule == DeclModule,
  290    !.
  291    
  292visibility(sub, ContextModule,Name,Arity,DeclModule) :-
  293	(	module_imports_predicate_from(DeclModule, Name, Arity, ContextModule, overridden)
  294	;	module_imports_predicate_from(DeclModule, Name, Arity, ContextModule, imported)
  295	),
  296	!.
  297%    declared_in_module(DeclModule,Name,Arity,DeclModule),
  298%    % DeclModule is a submodule of ContextModule
  299%    declared_in_module(DeclModule,_,_,ContextModule), % submodule
  300%    ContextModule \== DeclModule. 
  301visibility(invisible, ContextModule,Name,Arity,DeclModule) :-
  302    % Take care to generate all values befor using negation.
  303    % Otherwise the clause will not be able to generate values.
  304    % Negation DOES NOT generate values for unbound variables!
  305    
  306    % There is some DeclaringModule
  307    declared_in_module(DeclModule,Name,Arity,DeclModule),
  308    ContextModule \== DeclModule,
  309	\+ module_imports_predicate_from(DeclModule, Name, Arity, ContextModule, overridden),
  310	\+ module_imports_predicate_from(DeclModule, Name, Arity, ContextModule, imported),
  311	\+ module_imports_predicate_from(ContextModule, Name, Arity, DeclModule, overridden),
  312	\+ module_imports_predicate_from(ContextModule, Name, Arity, DeclModule, imported).
  313%    \+ declared_in_module(ContextModule,Name,Arity,DeclModule),
  314%    \+ declared_in_module(DeclModule,_,_,ContextModule).
  315
  316        /***********************************************************************
  317         * Find Primary Definition                                             *
  318         * --------------------------------------------------------------------*
  319         * for "Open Primary Declaration" (F3) action                          *
  320         ***********************************************************************/ 
 find_primary_definition_visible_in(+File, +Line, +OffsetStart, +OffsetEnd, +TermString, -TargetKind, -TargetFile, -TargetLine, -TargetLabel)
Find first line of first clause in the primary file defining the predicate Name/Arity visible in ReferencedModule. In case of multifile predicates, the primary file is either the file whose module is the DefiningModule or otherwise (this case only occurs for "magic" system modules, (e.g. 'system')) the file containing most clauses.

Used for the open declaration action in pdt/src/org/cs3/pdt/internal/actions/FindPredicateActionDelegate.java

ResultKind is one of: single, multifile, foreign, dynamic

  334find_primary_definition_visible_in(File, Line, OffsetStart, OffsetEnd, TermString, TargetKind, TargetFile, TargetLine, TargetLabel) :-
  335	retrieve_term_from_atom(File, TermString, Term),
  336	nonvar(Term),
  337	find_primary_definition_visible_in_(File, Line, OffsetStart, OffsetEnd, Term, TargetKind, TargetFile, TargetLine, TargetLabel).
  338
  339retrieve_term_from_atom(File, TermString, Term) :-
  340	(	module_property(Module, file(File))
  341	->	atom_concat(TermString, '.', TermStringWithDot),
  342		open_chars_stream(TermStringWithDot, Stream),
  343		read_term(Stream, Term, [module(Module)])
  344	;	atom_to_term(TermString, Term, _)
  345	).
  346
  347% Logtalk file
  348find_primary_definition_visible_in_(File, Line, _OffsetStart, _OffsetEnd, Term, single, TargetFile, TargetLine, _TargetLabel) :-
  349    split_file_path(File, _Directory, _FileName, _, lgt),
  350    !,
  351    current_predicate(logtalk_load/1),
  352    logtalk_adapter::find_primary_definition_visible_in(File, Line, Term, _Functor, _Arity, TargetFile, TargetLine),
  353    !.
  354
  355% Logtalk message in non-Logtalk file
  356find_primary_definition_visible_in_(_File, _Line, _OffsetStart, _OffsetEnd, Term, single, TargetFile, TargetLine, _TargetLabel) :-
  357	Term = Obj::Call,
  358	!,
  359    current_predicate(logtalk_load/1),
  360    nonvar(Obj),
  361    nonvar(Call),
  362    functor(Call, Name, Arity),
  363	(	object_property(Obj, defines(Name/Arity, Properties))
  364	;	object_property(Obj, declares(Name/Arity, Properties))
  365	),
  366	memberchk(line_count(TargetLine), Properties),
  367	object_property(Obj, file(FileName, Directory)),
  368	atom_concat(Directory, FileName, TargetFile),
  369	!.
  370
  371% file specification/loading directive
  372find_primary_definition_visible_in_(File, _Line, _OffsetStart, _OffsetEnd, Term, single, TargetFile, TargetLine, _TargetLabel) :-
  373	find_file(File, Term, TargetFile, TargetLine),
  374	!.
  375
  376% metacall in a transparent predicate
  377find_primary_definition_visible_in_(File, Line, OffsetStart, OffsetEnd, Term, transparent, TargetFile, TargetLine, TargetLabel) :-
  378	'$clause_from_source'(File, File, Line, ClauseRef),
  379        % '$clause_from_source'(File, Line, ClauseRef),
  380	clause_property(ClauseRef, predicate(SrcModule:SrcName/SrcArity)),
  381	functor(SrcHead, SrcName, SrcArity),
  382	predicate_property(SrcModule:SrcHead, transparent),
  383	\+ predicate_property(SrcModule:SrcHead, meta_predicate(_)),
  384	(	Term = _:_
  385	->	RefTerm = Term
  386	;	RefTerm = _:Term
  387	),
  388	retractall(alternative(_, _, _, _, _)),
  389	pdt_walk_code([clauses([ClauseRef]), trace_reference(RefTerm), reiterate(false), on_trace(pdt_search:assert_alternative(OffsetStart, OffsetEnd))]),
  390	findall(a(Module, Name, Arity, File2, Line2), retract(alternative(Module, Name, Arity, File2, Line2)), Alternatives),
  391	Alternatives \== [],
  392	!,
  393	member(a(RefModule, RefName, RefArity, TargetFile, TargetLine), Alternatives),
  394	format(atom(TargetLabel), '~w:~w/~w', [RefModule, RefName, RefArity]).
  395
  396% any other term
  397find_primary_definition_visible_in_(File, _Line, _OffsetStart, _OffsetEnd, Term, TargetKind, TargetFile, TargetLine, TargetLabel) :-
  398	extract_name_arity(Term, Module, _Head, Name, Arity),
  399	find_definition_visible_in(File, Module, Name, Arity, _DefiningModule, Locations),
  400	(	Locations = [_,_|_]
  401	->	TargetKind = (multifile)
  402	;	Locations = [Location],
  403		(	Location = (dynamic)-_ ->
  404			TargetKind = (dynamic)
  405		; 	Location = foreign-_ -> 
  406			TargetKind = foreign
  407		; 	TargetKind = single
  408		)
  409	),
  410	!,
  411	member(TargetFile-[location(TargetLine, _)|_], Locations),
  412	format(atom(TargetLabel), '~w:~w', [TargetFile, TargetLine]).
  413
  414:- if(current_prolog_flag(dialect, swi)).  415find_primary_definition_visible_in_(File, _Line, _OffsetStart, _OffsetEnd, Term, dwim, TargetFile, TargetLine, TargetLabel) :-
  416	extract_name_arity(Term, Module, Head, _Name, _Arity),
  417	(	var(Module)
  418	->	once(module_of_file(File,FileModule)),
  419		dwim_predicate(FileModule:Head, RefModule:RefHead)
  420	;	dwim_predicate(Module:Head, RefModule:RefHead)
  421	),
  422	functor(RefHead, RefName, RefArity),
  423	(	predicate_property(RefModule:RefHead, file(TargetFile)),
  424		predicate_property(RefModule:RefHead, line_count(TargetLine))
  425	->	true
  426	;	TargetFile = foreign,
  427		TargetLine = -1
  428	),
  429	format(atom(TargetLabel), '~w:~w/~w', [RefModule, RefName, RefArity]).
  430:- endif.  431
  432% If Term is a loading directive, find the related file,
  433% eventually interpreting a FileSPec that contains an alias
  434find_file(EnclFile,Term,File,Line) :-
  435    extract_file_spec(Term,FileSpec),
  436    catch( absolute_file_name(FileSpec,[relative_to(EnclFile), solutions(all),extensions(['.pl', '.lgt', '.ct', '.ctc'])], File),
  437           _,
  438           fail
  439    ),
  440    access_file(File, read),
  441    !,
  442    Line=1.
  443    
  444% Work regardelessly whether the user selected the entire consult/use_module
  445% statement or just the file spec. Does NOT work if he only selected a file
  446% name within an alias but not the complete alias.
  447extract_file_spec(consult(FileSpec),FileSpec) :- !.
  448extract_file_spec(use_module(FileSpec),FileSpec) :- !.
  449extract_file_spec(use_module(FileSpec,_),FileSpec) :- !.
  450extract_file_spec(reexport(FileSpec),FileSpec) :- !.
  451extract_file_spec(reexport(FileSpec,_),FileSpec) :- !.
  452extract_file_spec(ensure_loaded(FileSpec),FileSpec) :- !.
  453extract_file_spec(Term,Term).
  454	
  455:- dynamic(alternative/5).  456assert_alternative(GivenStart, GivenEnd, Module0:Goal, _Caller, clause_term_position(_Ref, TermPosition), metacall(_, _)) :-
  457	(	TermPosition = term_position(Start, End, _, _, _)
  458	;	TermPosition = Start-End
  459	),
  460	GivenStart =< Start,
  461	End =< GivenEnd,
  462	functor(Goal, Name, Arity),
  463	declared_in_module(Module0, Name, Arity, Module),
  464	predicate_property(Module:Goal, file(File)),
  465	predicate_property(Module:Goal, line_count(Line)),
  466	!,
  467	assertz(alternative(Module, Name, Arity, File, Line)).
  468assert_alternative(_, _, _, _, _, _).
  469
  470extract_name_arity(Term,Module,Head,Name,Arity) :-
  471	% Special treatment of Name/Arity terms:
  472	(	Term = Module:Name/Arity
  473	->	true
  474	;	(	Term = Name/Arity
  475		->	true
  476		;	(	Term = Module:Term2
  477			->	functor(Term2, Name, Arity)
  478			;	functor(Term,Name,Arity)
  479			)
  480		)
  481	),
  482	% Create most general head
  483	functor(Head,Name,Arity).
  484
  485
  486find_definition_visible_in(EnclFile,ReferencedModule,Name,Arity,DefiningModule,Locations) :-
  487	module_of_file(EnclFile,FileModule),
  488	(	atom(ReferencedModule)
  489	->	true                            % Explicit module reference
  490	;	ReferencedModule = FileModule   % Implicit module reference
  491	),
  492	declared_in_module(ReferencedModule,Name,Arity,DeclaringModule),
  493	defined_in_files(DeclaringModule,Name,Arity,Locations0),
  494	(	Locations0 == []
  495	->	declared_in_file(DefiningModule, Name, Arity, Locations)
  496	;	Locations0 = Locations
  497	).
  498
  499
  500        /***********************************************************************
  501         * Find Definitions in File                                            *
  502         * --------------------------------------------------------------------*
  503         * for Outline                                                         *
  504         ***********************************************************************/ 
  505         
  506% TODO: This is meanwhile subsumed by other predicates. Integrate!
 find_definition_contained_in(+File, +Options, -Entity, -EntityLine, -EntityKind, -Name, -Arity, -SearchCategory, -Line, -PropertyList) is nondet
Look up the starting line of a clause of a predicate Name/Arity defined in File. Do this upon backtracking for each clause of each predicate in File.
Arguments:
File- The file to search for definitions.
Options- multifile(boolean): show clauses of other files for multifile predicates all_clauses(boolean): show all clauses or only the first of a predicate in a file
Entity- The module (in Prolog) or Entity (in logtalk) to which a predicate belongs. Note that there can be multiple entities in a file.
EntityKind- "module" (in Prolog) or "object|category|protocoll" (in Logtalk)
Name- The name of the defined predicate
Arity- The arity of the defined predicate
SearchCategory- "multifile|definition"
Line- The starting line of a clause of Name/Arity contained in File.
PropertyList- A list of properties of the predicate. TODO: Enumerate values expected by the Java GUI.
  526% Called from PDTOutlineQuery.java
  527
  528find_definition_contained_in(File, Entity, EntityLine, EntityKind, Functor, Arity, SearchCategory, Line, PropertyList) :-
  529	find_definition_contained_in(File, [multifile(true), all_clauses(true), first_arg_size_limit(102400)], Entity, EntityLine, EntityKind, Functor, Arity, SearchCategory, Line, PropertyList).
  530
  531find_definition_contained_in(File, Options, Entity, EntityLine, EntityKind, Functor, Arity, SearchCategory, Line, PropertyList) :-
  532    split_file_path(File, _Directory,_FileName,_,lgt),
  533    !,
  534    current_predicate(logtalk_load/1),
  535    logtalk_adapter::find_definition_contained_in(File, Options, Entity, EntityLine, EntityKind, Functor, Arity, SearchCategory, Line, PropertyList).
  536
  537find_definition_contained_in(ContextFile, Options, DefiningModule, ModuleLine, module, Functor, Arity, SearchCategory, Line, PropertyList) :-
  538    SearchCategory = definition,
  539    
  540%    module_of_file(ContextFile, ContextModule),
  541    % Backtrack over all predicates defined in File
  542    % including multifile contributions to other modules:
  543    (	pdt_source_file(DefiningModule:Head, ContextFile)
  544    ;	source_file_property(ContextFile, included_in(ParentFile, _)),
  545    	pdt_source_file(DefiningModule:Head, ParentFile)
  546    ),
  547    (	module_property(DefiningModule, line_count(ModuleLine))
  548    ->	true
  549    ;	ModuleLine = 1
  550    ),
  551    
  552    % Predicate properties:
  553    functor(Head, Functor, Arity),
  554    \+ find_blacklist(Functor,Arity,DefiningModule),
  555    properties_for_predicate(DefiningModule,Functor, Arity, PropertyList0),
  556
  557    % In the case of a multifile predicate, we want to find all clauses for this 
  558    % predicate, even when they occur in other files
  559    %defined_in_file(DefiningModule, Functor, Arity, Ref, _, DefiningFile, Line),
  560    find_definition_in_file(Options, ContextFile, DefiningModule, Functor, Arity, Ref, DefiningFile, Line),
  561    (	nonvar(ParentFile)
  562    ->	DefiningFile \== ParentFile
  563    ;	true
  564    ),
  565    (	DefiningFile == ContextFile
  566    ->	(	module_of_file(ContextFile, DefiningModule)%DefiningModule == ContextModule
  567    	->	% local definition
  568    		PropertyList1 = [local(DefiningModule)|PropertyList0]
  569	    ;	% contribution of ContextModule for DefiningModule	
  570    		PropertyList1 = [for(DefiningModule), defining_file(DefiningFile) | PropertyList0]
  571    	)
  572    ;	(	module_of_file(ContextFile, DefiningModule)%DefiningModule == ContextModule
  573    	->	% contribution from DefiningFile to ContextModule, ContextFile
  574    		PropertyList1 = [from(DefiningModule), defining_file(DefiningFile) | PropertyList0]
  575    	;	% other file to itself
  576    		PropertyList1 = [remote(DefiningModule), defining_file(DefiningFile) | PropertyList0]
  577    	)
  578    ),
  579    (	first_argument_of_clause(Ref, Options, FirstArg)
  580    ->	PropertyList = [FirstArg|PropertyList1]
  581    ;	PropertyList = PropertyList1
  582    ).
  583
  584find_definition_in_file(Options, ContextFile, Module, Name, Arity, Ref, File, Line) :-
  585	once(member(multifile(IsMultifile), Options)),
  586	once(member(all_clauses(IsAllClauses), Options)),
  587	find_definition_in_file(IsAllClauses, IsMultifile, ContextFile, Module, Name, Arity, Ref, File, Line).
  588
  589find_definition_in_file(true, IsMultifile, ContextFile, Module, Name, Arity, Ref, File, Line) :-
  590	!,
  591	(	IsMultifile == true
  592	->	true
  593	;	ContextFile = File
  594	),
  595	defined_in_file(Module, Name, Arity, Ref, _, File, Line).
  596find_definition_in_file(_/*false*/, IsMultifile, ContextFile, Module, Name, Arity, Ref, File, Line) :-
  597	functor(Head, Name, Arity),
  598	(	predicate_property(Module:Head, multifile)
  599	->	(	IsMultifile == true
  600		->	true
  601		;	ContextFile = File
  602		),
  603		find_lines(Module:Head, File, Line, Ref)
  604	;	ContextFile = File,
  605		predicate_property(Module:Head, line_count(Line)),
  606		nth_clause(Module:Head, _, Ref),
  607		clause_property(Ref, line_count(Line)),
  608		!
  609	).
  610
  611:- dynamic(file_line/3).  612find_lines(Head, File, Line, Ref) :-
  613	predicate_property(Head, number_of_clauses(N)), 
  614	N > 1000,
  615	!,
  616	findall(F, (source_file(F), pdt_source_file(Head, F)), Files),
  617	Line = 1,
  618	Ref = [],
  619	member(File, Files).
  620find_lines(Head, File, Line, Ref) :-
  621	with_mutex(find_lines, (
  622		retractall(file_line(_, _, _)),
  623		walk_clauses(Head, 1),
  624		findall(F-L-R, file_line(F, L, R), Locations)
  625	)),
  626	member(File-Line-Ref, Locations).
  627walk_clauses(Head, N) :-
  628	nth_clause(Head, N, Ref),
  629	!,
  630	(	clause_property(Ref, file(File)),
  631		clause_property(Ref, line_count(Line))
  632	->	(	file_line(File, L, _)
  633		->	(	Line < L
  634			->	retract(file_line(File, L, _)),
  635				assertz(file_line(File, Line, Ref))
  636			;	true
  637			)
  638		;	assertz(file_line(File, Line, Ref))
  639		)
  640	;	true
  641	),
  642	succ(N, N2),
  643	walk_clauses(Head, N2).
  644walk_clauses(_, _).
  645
  646first_argument_of_clause(Ref, Options, first_argument(Arg)) :-
  647	catch(clause(_:Head, _, Ref), _, fail),
  648	compound(Head),
  649	arg(1, Head, FirstArg),
  650	(	var(FirstArg)
  651	->	clause_property(Ref, file(File)),
  652		(	memberchk(first_arg_size_limit(Limit), Options)
  653		->	true
  654		;	Limit = 102400
  655		),
  656		size_file(File, Size),
  657		Size =< Limit,
  658		clause_info(Ref, _, _, Varnames), 
  659		arg(1, Varnames, FirstVarName),
  660		Arg = FirstVarName
  661	;	functor(FirstArg, F, N),
  662		(	N == 0
  663		->	Arg = F
  664		;	format(atom(Arg), '~w/~w', [F, N])
  665		)
  666	).
  667
  668% TODO: Reconcile the above with utils4modules_visibility.pl::module_of_file/2   
 find_blacklist(?Functor, ?Arity, ?Module) is nondet
Used to remove (internal) predicates from the results of find_definition_contained_in/8.
  675find_blacklist('$load_context_module',2,_).
  676find_blacklist('$load_context_module',3,_).
  677find_blacklist('$mode',2,_).
  678find_blacklist('$pldoc',4,_).
  679
  680    
  681    
  682
  683
  684               /***********************************************
  685                * FIND VISIBLE PREDICATE (FOR AUTOCOMPLETION) *
  686                ***********************************************/
 find_completion(+Prefix, ?EnclosingFile, ?LineInFile, -Kind, -Entity, -Name, -Arity, -Visibility, -IsBuiltin, -IsDeprecated, -ArgNames, -DocKind, -Doc, -NeedsQuotes) is nondet
  690find_completion(Prefix, EnclosingFile, LineInFile, Kind, Entity, Name, Arity, Visibility, IsBuiltin, IsDeprecated, ArgNames, DocKind, Doc, NeedsQuotes) :-
  691	var(Prefix),
  692	!,
  693	throw(prefix_not_bound(find_completion(Prefix, EnclosingFile, LineInFile, Kind, Entity, Name, Arity, Visibility, IsBuiltin, IsDeprecated, ArgNames, DocKind, Doc, NeedsQuotes))).
  694
  695find_completion(Prefix, EnclosingFile, LineInFile, Kind, Entity, Name, Arity, Visibility, IsBuiltin, IsDeprecated, ArgNames, DocKind, Doc, NeedsQuotes) :-
  696	nonvar(EnclosingFile),
  697	!,
  698	(	split_file_path(EnclosingFile, _, _, _, lgt)
  699	->	current_predicate(logtalk_load/1),
  700		IsDeprecated = false,
  701		logtalk_adapter::find_completion(Prefix, EnclosingFile, LineInFile, Kind, Entity, Name, Arity, Visibility, IsBuiltin, ArgNames, DocKind, Doc)
  702	;	find_completion_(Prefix, EnclosingFile, LineInFile, Kind, Entity, Name, Arity, Visibility, IsBuiltin, IsDeprecated, ArgNames, DocKind, Doc)
  703	),
  704	needs_quotes(Name, NeedsQuotes).
  705
  706find_completion(Prefix, EnclosingFile, LineInFile, Kind, Entity, Name, Arity, Visibility, IsBuiltin, IsDeprecated, ArgNames, DocKind, Doc, NeedsQuotes) :-
  707	(	find_completion_(Prefix, EnclosingFile, LineInFile, Kind, Entity, Name, Arity, Visibility, IsBuiltin, IsDeprecated, ArgNames, DocKind, Doc)
  708	;	current_predicate(logtalk_load/1),
  709		IsDeprecated = false,
  710		logtalk_adapter::find_completion(Prefix, EnclosingFile, LineInFile, Kind, Entity, Name, Arity, Visibility, IsBuiltin, ArgNames, DocKind, Doc)
  711	),
  712	needs_quotes(Name, NeedsQuotes).
  713
  714needs_quotes(Value, NeedsQuotes) :-
  715	(	atom(Value)
  716	->	with_output_to(atom(A), writeq(Value)),
  717		(	atom_length(Value, VL),
  718			atom_length(A, AL),
  719			AL > VL
  720		->	NeedsQuotes = true
  721		;	NeedsQuotes = false
  722		)
  723	;	NeedsQuotes = false
  724	).
  725
  726:- discontiguous(find_completion_/13).  727
  728find_completion_(SpecifiedModule:PredicatePrefix, _EnclosingFile, _LineInFile, predicate, Module, Name, Arity, Visibility, IsBuiltin, IsDeprecated, ArgNames, DocKind, Doc) :-
  729	!,
  730	(	PredicatePrefix \== ''
  731	->	setof(
  732			Module-Name-Arity,
  733			SpecifiedModule^(
  734				declared_in_module(SpecifiedModule, Name, Arity, Module),
  735				is_case_insensitive_prefix_of(PredicatePrefix, Name)
  736			),
  737			Predicates
  738		)
  739	;	nonvar(SpecifiedModule),
  740		setof(
  741			SpecifiedModule-Name-Arity,
  742			SpecifiedModule^(declared_in_module(SpecifiedModule, Name, Arity, SpecifiedModule)),
  743			Predicates
  744		)
  745	),
  746	member(Module-Name-Arity, Predicates),
  747	predicate_information(Module, Name, Arity, IsBuiltin, IsDeprecated, Visibility, ArgNames, DocKind, Doc).
  748
  749find_completion_(PredicatePrefix, EnclosingFile, _LineInFile, predicate, Module, Name, Arity, Visibility, IsBuiltin, IsDeprecated, ArgNames, DocKind, Doc) :-
  750	atomic(PredicatePrefix),
  751	nonvar(EnclosingFile),
  752	setof(
  753		Module-Name-Arity,
  754		EnclosingFile^FileModule^IncludeLine^File^(
  755			(	File = EnclosingFile
  756			;	source_file_property(EnclosingFile, included_in(File, IncludeLine))
  757			),
  758			module_of_file(File, FileModule),
  759			declared_in_module(FileModule, Name, Arity, Module),
  760			is_case_insensitive_prefix_of(PredicatePrefix, Name)
  761		),
  762		Predicates
  763	),
  764	member(Module-Name-Arity, Predicates),
  765	predicate_information(Module, Name, Arity, IsBuiltin, IsDeprecated, Visibility, ArgNames, DocKind, Doc).
  766
  767find_completion_(PredicatePrefix, EnclosingFile, _LineInFile, predicate, Module, Name, Arity, Visibility, IsBuiltin, IsDeprecated, ArgNames, DocKind, Doc) :-
  768	atomic(PredicatePrefix),
  769	var(EnclosingFile),
  770	setof(Module-Name-Arity, (
  771		declared_in_module(user, Name, Arity, Module),
  772		is_case_insensitive_prefix_of(PredicatePrefix, Name)
  773	), Predicates),
  774	member(Module-Name-Arity, Predicates),
  775	predicate_information(Module, Name, Arity, IsBuiltin, IsDeprecated, Visibility, ArgNames, DocKind, Doc).
  776
  777predicate_information(Module, Name, Arity, IsBuiltin, IsDeprecated, Visibility, ArgNames, DocKind, Doc) :-
  778	functor(Head, Name, Arity),
  779	(	predicate_property(Module:Head, built_in)
  780	->	IsBuiltin = true
  781	;	IsBuiltin = false
  782	),
  783	(	(	Module == user
  784		;	predicate_property(Module:Head, exported)
  785		)
  786	->	Visibility = (public)
  787	;	Visibility = protected
  788	),
  789	(	predicate_completion_documentation_hook(Module, Name, Arity, ArgNames, DocKind, Doc)
  790	->	true
  791	;	predicate_manual_entry(Module, Name, Arity, Content, IsDeprecated),
  792		(	Content == nodoc
  793		->	DocKind = nodoc
  794		;	DocKind = html,
  795			Doc = Content,
  796			(	Arity == 0
  797			->	ArgNames = []
  798			;	ignore(predicate_arg_list(Content, ArgNames))
  799			)
  800		)
  801	),
  802	(	var(IsDeprecated)
  803	->	IsDeprecated = false
  804	;	true
  805	).
  806
  807:- multifile(predicate_completion_documentation_hook/6).  808
  809predicate_arg_list(Comment, ArgList) :-
  810	sub_atom(Comment, End, _, _, '</var>'),
  811	sub_atom(Comment, BeforeBegin, BeforeBeginLength, _, '"arglist">'),
  812	!,
  813	Begin is BeforeBegin + BeforeBeginLength,
  814	Length is End - Begin,
  815	sub_atom(Comment, Begin, Length, _, Args),
  816	format(atom(ArgsWithDot), '~w.', [Args]),
  817	open_chars_stream(ArgsWithDot, Stream),
  818	call_cleanup(read_term(Stream, Term, [variable_names(Vars), module(pldoc_modes)]), close(Stream)),
  819	args_from_mode_term(Term, ArgList, Vars).
  820
  821args_from_mode_term(Arg, [ArgName], Vars) :-
  822	var(Arg),
  823	!,
  824	var_to_arg(Arg, ArgName, Vars).
  825
  826args_from_mode_term((Arg, Args), [ArgName|ArgNames], Vars) :-
  827	!,
  828	var_to_arg(Arg, ArgName, Vars),
  829	args_from_mode_term(Args, ArgNames, Vars).
  830
  831args_from_mode_term(Arg, [ArgName], Vars) :-
  832	var_to_arg(Arg, ArgName, Vars).
  833
  834var_to_arg(Arg, ArgName, Vars) :-
  835	(	var(Arg)
  836	->	Arg = Var
  837	;	Arg =.. [_Mode|Other],
  838		(	Other = [Var:_]
  839		;	Other = [Var]
  840		)
  841	),
  842	member(ArgName=V, Vars),
  843	V == Var,
  844	!.
  845
  846find_completion_(ModulePrefix, _EnclosingFile, _LineInFile, module, _, Name, _, _, _, _, _, _, _) :- 
  847	atomic(ModulePrefix),
  848	current_module(Name),
  849	is_case_insensitive_prefix_of(ModulePrefix,Name).
  850
  851:- if(current_prolog_flag(dialect, swi)).  852find_completion_(AtomPrefix, _EnclosingFile, _LineInFile, atom, _, Atom, _, _, _, _, _, _, _) :- 
  853	atomic(AtomPrefix),
  854	garbage_collect_atoms,
  855	'$atom_completions'(AtomPrefix, Atoms),
  856	member(Atom,Atoms),
  857	'$atom_references'(Atom, ReferenceCount),
  858	ReferenceCount > 0, 
  859%	Atom \= AtomPrefix,
  860	\+ current_predicate(Atom/_Arity).
  861:- endif.  862
  863is_case_insensitive_prefix_of(Prefix, Name) :-
  864	downcase_atom(Prefix, PrefixDowncase),
  865	downcase_atom(Name, NameDowncase),
  866	atom_concat(PrefixDowncase, _, NameDowncase).
 find_entity_definition(SearchString, ExactMatch, Root, File, Line, Entity)
  870find_entity_definition(SearchString, ExactMatch, Root, File, Line, Entity) :-
  871	current_predicate(logtalk_load/1),
  872	logtalk_adapter::find_entity_definition(SearchString, ExactMatch, Root, File, Line, Entity).
  873
  874find_entity_definition(SearchString, ExactMatch, Root, File, Line, Entity) :-
  875	find_module_definition(SearchString, ExactMatch, Root, File, Line, Entity).
  876	
  877
  878find_module_definition(SearchModule, ExactMatch, Root, File, Line, Module) :-
  879	current_module(Module),
  880	(	ExactMatch == true
  881	->	SearchModule = Module
  882	;	once(sub_atom(Module, _, _, _, SearchModule))
  883	),
  884	module_property(Module, file(File)),
  885	(	nonvar(Root)
  886	->	sub_atom(File, 0, _, _, Root)
  887	;	true
  888	),
  889	module_property(Module, line_count(Line)).
 find_module_reference(Module, ExactMatch, Root, File, Line, ReferencingModule, RefName, RefArity, PropertyList)
  894find_module_reference(Module, ExactMatch, Root, File, Location, LoadingModule, _, _, [line(Line), label(Label)]) :-
  895	find_use_module(Module, ExactMatch, _, LoadingModule, File, Line, OptionList),
  896	(	nonvar(Root)
  897	->	sub_atom(File, 0, _, _, Root)
  898	;	true
  899	),
  900	format(atom(Label), ':- load_files(~w, ~w).', [Module, OptionList]),
  901	(	read_term_position_at_location(File, Line, LoadingModule, Location)
  902	->	true
  903	;	Location = Line
  904	).
  905
  906find_module_reference(Module, ExactMatch, Root, File, Line, ReferencingModule, RefName, RefArity, PropertyList) :-
  907	search_module_name(Module, ExactMatch, SearchModule),
  908	find_reference_to(predicate(SearchModule, _, _, _, _), ExactMatch, Root, ReferencingModule, RefName, RefArity, File, Line, PropertyList).
  909
  910find_module_reference(Module, ExactMatch, Root, File, Location, ReferencingModule, RefName, RefArity, PropertyList) :-
  911	current_predicate(logtalk_load/1),
  912	logtalk_adapter::find_entity_reference(Module, ExactMatch, Root, File, Line, ReferencingModule, RefName, RefArity, PropertyList),
  913	(	var(RefName),
  914		read_term_position_at_location(File, Line, user, Location)
  915	->	true
  916	;	Location = Line
  917	).
  918
  919read_term_position_at_location(File, Line, Module, Location) :-
  920	catch(open(File, read, In), _, fail),
  921	set_stream(In, newline(detect)),
  922	call_cleanup(
  923	    read_source_term_at_location(
  924			In,
  925			_Clause,
  926			[	line(Line),
  927				module(Module),
  928				subterm_positions(TermPos)
  929			]
  930		),
  931		close(In)
  932	),
  933	TermPos = term_position(Start, End, _, _, _),
  934	format(atom(Location), '~w-~w', [Start, End]),
  935	!.
  936
  937search_module_name(Module, true, Module) :- !.
  938search_module_name(ModulePart, false, Module) :-
  939	current_module(Module),
  940	once(sub_atom(Module, _, _, _, ModulePart)).
 loaded_by(LoadedFile, LoadingFile, Line, Directive)
  944/* For Load File Dependency Graph: */
  945loaded_by(LoadedFile, LoadingFile, Line, Directive) :-
  946	nonvar(LoadedFile),
  947	(	split_file_path(LoadedFile, _, _, _, lgt)
  948	;	split_file_path(LoadedFile, _, _, _, logtalk)
  949	),
  950	% Logtalk source file
  951	!,
  952	logtalk_adapter::loaded_by(LoadedFile, LoadingFile, Line, Directive).
  953
  954loaded_by(LoadedFile, LoadingFile, Line, Directive) :-
  955	source_file_property(LoadedFile, load_context(_LoadingModule, LoadingFile:Line, _OptionList)),
  956	% If the loaded file is a module conclude that the
  957	% loading directive should have been 'use_module'.
  958	% Otherwise, treat it as a 'consult': 
  959	( module_property(_Module, file(LoadedFile))
  960	-> Directive = use_module
  961	;  Directive = consult
  962	).
  963	
  964find_use_module(ModuleOrPart, ExactMatch, ModuleFile, LoadingModule, File, Line, OptionList) :-
  965	(	ExactMatch == true
  966	->	ModuleOrPart = Module
  967	;	current_module(Module),
  968		once(sub_atom(Module, _, _, _, ModuleOrPart))
  969	),
  970	module_property(Module, file(ModuleFile)),
  971	source_file_property(ModuleFile, load_context(LoadingModule, File:Line, OptionList)).
  972%	member(if(not_loaded), OptionList),
  973%	member(must_be_module(true), OptionList).
  974	
  975module_imports_predicate_from(Module, Name, Arity, SuperModule, Case) :-
  976	has_super_module(Module, SuperModule),
  977	visible_in_module(Module, Name, Arity),
  978	
  979	(	defined_in_module(Module, Name, Arity)
  980	->	(	module_property(SuperModule, exports(ExportList)),
  981			member(Name/Arity, ExportList)
  982		->	Case = overridden
  983		;	Case = local
  984		)
  985	;	functor(Head, Name, Arity),
  986		(	predicate_property(Module:Head, imported_from(SuperModule))
  987		->	Case = imported
  988		;	Case = not_imported
  989		)
  990	).
  991
  992has_super_module(Module, SuperModule) :-	
  993	module_property(SuperModule, file(SuperModuleFile)),
  994	source_file_property(SuperModuleFile, load_context(Module, _, _OptionList)).
  995 
  996
  997loaded_file(FullPath) :-
  998	(	(	split_file_path(FullPath, Directory, Basename, _, lgt)
  999		;	split_file_path(FullPath, Directory, Basename, _, logtalk)
 1000		) ->
 1001		% Logtalk source file
 1002		current_predicate(logtalk_load/1),
 1003		% assume that Logtalk is loaded
 1004		(	current_logtalk_flag(version, version(3, _, _)) ->
 1005			logtalk::loaded_file(FullPath)
 1006		;	logtalk::loaded_file(Basename, Directory)
 1007		)
 1008	;	% assume Prolog source file
 1009		source_file(FullPath)
 1010	)