13
14:- module(pl_to_graphML, [ 15 write_focus_to_graphML/4,
16 write_global_to_graphML/3,
17 write_dependencies_to_graphML/3,
18 write_logtalk_project_files_to_graphML/4,
19 write_logtalk_library_to_graphML/3,
20 write_logtalk_recursive_library_to_graphML/3,
21 call_term_position/7]). 22
23:- use_module(graphML_api). 24:- use_module(util_for_graphML). 25:- use_module(pdt_common_pl('callgraph/pdt_call_graph')). 26:- use_module(pdt_common_pl(pdt_search)). 27:- use_module(pdt_prolog_library(utils4modules_visibility)). 28:- use_module(library(lists), [list_to_set/2, append/3, member/2]). 29:- use_module( prolog_connector_pl(split_file_path), [
30 split_file_path/5 31]). 32:- use_module(pdt_prolog_library(compatibility), [
33 pdt_source_file/2
34]). 35
36:- op(600, xfy, ::). 37
42
59
60
61write_focus_to_graphML(FocusFile, GraphFile, DependentFiles, Settings):-
62 write_to_graphML(GraphFile, write_focus_facts_to_graphML(FocusFile, DependentFiles, Settings)).
63
64write_global_to_graphML(ProjectFilePaths, GraphFile, Settings):-
65 filter_consulted(ProjectFilePaths, ConsultedFilePaths),
66 write_to_graphML(GraphFile, write_global_facts_to_graphML(ConsultedFilePaths, Settings)).
67
68write_dependencies_to_graphML(ProjectFilePaths, ProjectPath, GraphFile):-
69 filter_consulted(ProjectFilePaths, ConsultedFilePaths),
70 write_to_graphML(GraphFile, write_dependencies_facts_to_graphML(ProjectPath, ConsultedFilePaths)).
71
72write_logtalk_project_files_to_graphML(DiagramType, ProjectFilePaths, ProjectPath, GraphFile):-
73 ( current_predicate(logtalk_load/1)
74 -> filter_consulted(ProjectFilePaths, ConsultedFilePaths),
75 filter_logtalk(ConsultedFilePaths, _, ConsultedLogtalkFilePaths),
76 split_file_path(GraphFile, Directory, FileName, _, _),
77 graphml_writer::set_file_name(FileName),
78 DiagramObject =.. [DiagramType, graphml],
79 DiagramObject::files(ProjectPath, ConsultedLogtalkFilePaths, [output_directory(Directory)])
80 ; true
81 ).
82
83write_logtalk_library_to_graphML(DiagramType, Library, GraphFile):-
84 ( current_predicate(logtalk_load/1)
85 -> split_file_path(GraphFile, Directory, FileName, _, _),
86 graphml_writer::set_file_name(FileName),
87 DiagramObject =.. [DiagramType, graphml],
88 DiagramObject::library(Library, [output_directory(Directory)])
89 ; true
90 ).
91
92write_logtalk_recursive_library_to_graphML(DiagramType, Library, GraphFile):-
93 ( current_predicate(logtalk_load/1)
94 -> split_file_path(GraphFile, Directory, FileName, _, _),
95 graphml_writer::set_file_name(FileName),
96 DiagramObject =.. [DiagramType, graphml],
97 DiagramObject::rlibrary(Library, [output_directory(Directory)])
98 ; true
99 ).
100
101relative_paths(_, [], []).
102relative_paths(BasePath, [H|T], [FormattedH|FormattedT]) :-
103 relative_path(BasePath, H, FormattedH),
104 relative_paths(BasePath, T, FormattedT).
105
106relative_path(BasePath, Path, RelativePath) :-
107 atom_chars(BasePath, BasePathChars),
108 atom_chars(Path, PathChars),
109 relative_path_(BasePathChars, PathChars, RelativePathChars),
110 atom_chars(RelativePath, RelativePathChars).
111
112
113relative_path_([], Head, Head).
114relative_path_([H|T], [H|T2], Result) :-
115 relative_path_(T, T2, Result).
116
117filter_logtalk([], [], []) :- !.
118filter_logtalk([F|Fs], Ps, [F|Ls]) :-
119 ( atom_concat(_, lgt, F)
120 ; atom_concat(_, logtalk, F)
121 ),
122 !,
123 filter_logtalk(Fs, Ps, Ls).
124filter_logtalk([F|Fs], [F|Ps], Ls) :-
125 filter_logtalk(Fs, Ps, Ls).
126
127:- meta_predicate(write_to_graphML(+, 1)). 128write_to_graphML(GraphFile, CALL) :-
129 with_mutex(prolog_factbase,
130 with_mutex(meta_pred_finder,
131 setup_call_cleanup(
132 prepare_for_writing(GraphFile,OutStream),
133 call(CALL, OutStream),
134 finish_writing(OutStream)
135 )
136 )
137 ).
138
139filter_consulted(ProjectFilePaths, ConsultedFilePaths) :-
140 findall(Path, (
141 member(Path, ProjectFilePaths), source_file(Path)
142 ), ConsultedFilePaths).
143
144pdt_location(Location) :-
145 predicate_property(pl_to_graphML:pdt_location(_), file(F)),
146 atom_concat(Location, 'pdt.contextview/pl/pl_to_graphml.pl', F).
147
148hide_swi_predicates(M:F/A) :- functor(H, F, A), not(predicate_property(M:H, built_in)).
149hide_swi_metapredicates(M:F/A) :- functor(H, F, A), not((predicate_property(M:H, built_in), predicate_property(M:H, (meta_predicate _)))).
150
151hide_pdt_predicates(M:F/A) :- functor(H, F, A), not((predicate_property(M:H, file(File)), pdt_location(Location), atom_concat(Location, _, File))).
152hide_pdt_metapredicates(M:F/A) :- functor(H, F, A), not((predicate_property(M:H, file(File)), pdt_location(Location), atom_concat(Location, _, File), predicate_property(M:H, (meta_predicate _)))).
153
154filter(Setting, pl_to_graphML:Setting).
155
156init_filters(Settings, Filters) :-
157 findall(F, (member(S, Settings), filter(S, F)), Filters).
158
159:- dynamic focus_facts_filter/1. 160
161write_focus_facts_to_graphML(FocusFile, DependentFiles, Settings, OutStream):-
162 source_file(FocusFile),
163 !,
164
165 ensure_call_graph_generated,
166 collect_ids_for_focus_file(FocusFile, DependentFiles, ReferencedPredicates, Calls),
167
168 retractall(focus_facts_filter(_)),
169 assert((focus_facts_filter(X) :- member(X, ReferencedPredicates))),
170
171 init_filters(Settings, Filters),
172
173 write_files(FocusFile, DependentFiles, [pl_to_graphML:focus_facts_filter|Filters], OutStream),
174 forall(
175 member((SourceModule:SourceName/SourceArity, TargetModule:TargetName/TargetArity), Calls),
176 write_call_edge(OutStream, SourceModule, SourceName, SourceArity, TargetModule, TargetName, TargetArity, DependentFiles)
177 ).
178
179write_global_facts_to_graphML(ProjectFiles, Settings, OutStream) :-
180
181 ensure_call_graph_generated,
182
183 init_filters(Settings, Filters),
184
185 forall(member(File, ProjectFiles),
186 (
187 main_module_of_file(File, Module),
188 write_file(OutStream, File, Filters, File, Module),
189 flush_output(OutStream)
190 )
191 ),
192
193 findall(Module:Name/Arity,
194 (
195 member(File, ProjectFiles),
196 predicate_in_file(File, Module, Name, Arity)
197 ),
198 Predicates
199 ),
200 forall((
201 member(SourceModule:SourceName/SourceArity, Predicates),
202 calls(TargetModule, TargetName, TargetArity, SourceModule, SourceName, SourceArity, _NumberOfCalls),
203 once(member(TargetModule:TargetName/TargetArity, Predicates))
204 ),(
205 write_call_edge(OutStream, SourceModule, SourceName, SourceArity, TargetModule, TargetName, TargetArity, ProjectFiles)
206 )).
207
208write_dependencies_facts_to_graphML(ProjectPath, ProjectFilePaths, OutStream) :-
209
210 findall((SourceFile, TargetFile),
211 (
212 member(SourceFile, ProjectFilePaths),
213 member(TargetFile, ProjectFilePaths),
214 loaded_by(TargetFile, SourceFile, _, _)
215 ),
216 FoundDependencies
217 ),
218
219 forall(
220 (
221 nth1(Id, ProjectFilePaths, FilePath),
222 file_node_name(FilePath, ProjectPath, FileNodeName),
223 file_exports(FilePath, FileType, ExportedStaticPredicates, ExportedDynamicPredicates)
224 ),
225 write_file_as_element(OutStream, Id, FilePath, FileNodeName, FileType, ExportedStaticPredicates, ExportedDynamicPredicates)
226 ),
227
228 forall(
229 (
230 member((S, T), FoundDependencies),
231 nth1(SId, ProjectFilePaths, S),
232 nth1(TId, ProjectFilePaths, T),
233 file_imports(S, T, Imports),
234 length(Imports, NImports)
235 ),
236 ( NImports > 0
237 -> write_load_edge(OutStream, SId, TId, Imports, NImports)
238 ; write_load_edge(OutStream, SId, TId, Imports)
239 )
240 ).
241
242file_exports(FilePath, module, ExportedStaticPredicates, ExportedDynamicPredicates) :-
243 module_property(Module, file(FilePath)),
244 module_property(Module, exports(Exports)),
245 exports_classification(Exports, ExportedStaticPredicates, ExportedDynamicPredicates, Module),
246 !.
247file_exports(FilePath, non_module_file, StaticPredicates, DynamicPredicates) :-
248 findall(
249 N/A,
250 ( pdt_source_file(user:H, FilePath),
251 functor(H, N, A),
252 \+ atom_concat('$', _, N)
253 ; loaded_by(LoadedFile, FilePath, _, _),
254 file_imports(FilePath, LoadedFile, Imports),
255 member(N/A, Imports)
256 ),
257 Predicates
258 ),
259 exports_classification(Predicates, StaticPredicates, DynamicPredicates, user),
260 !.
261
262exports_classification([Name/Arity|Tail], S, [Name/Arity|DTail], Module) :-
263 functor(H, Name, Arity),
264 predicate_property(Module:H, dynamic),
265 !,
266 exports_classification(Tail, S, DTail, Module).
267exports_classification([E|Tail], [E|STail], D, Module) :-
268 exports_classification(Tail, STail, D, Module).
269exports_classification([], [], [], _Module) :- !.
270
271file_imports(File1, File2, PredNames) :-
272 once(module_of_file(File1,M1)),
273 once(module_of_file(File2,M2)),
274 module_imports_from(M1,M2,Preds),
275 findall(Name/Arity,
276 (
277 member(P, Preds),
278 functor(P, Name, Arity)
279 ),
280 PredNames).
281
282module_imports_from(M1,M2,Preds) :-
283 setof( Head,
284 predicate_property(M1:Head, imported_from(M2)),
285 Preds),
286 !.
287module_imports_from(_M1,_M2,[]).
288
290module_consults_from(Module,File,Preds) :-
291 setof( Head,
292 module_consults_from__(Module,File,Head),
293 Preds).
294
296module_consults_from__(Module,File,Head) :-
297 module_of_file(ModuleFile,Module),
298 declared_in_module(Module, Head),
299 predicate_property(Module:Head, file(File)),
300 File \== ModuleFile.
301
302
303file_node_name(FilePath, _, ModuleName) :-
304 module_property(ModuleName, file(FilePath)), !.
305
306file_node_name(FilePath, _, Name) :-
307 directory_file_path(_, Name, FilePath), !.
308 309
310file_node_name(FilePath, _, FilePath).
311
312
313file_node_type(FilePath, Dependencies, 'top') :-
314 not(member((_, FilePath), Dependencies)), !.
315
316
317file_node_type(FilePath, Dependencies, 'bottom') :-
318 not(member((FilePath, _), Dependencies)), !.
319
320file_node_type(_, _, 'intermediate') :- !.
321
322
323file_node_type(FilePath, Dependencies, 'top') :-
324 not(member((_, FilePath), Dependencies)), !.
325
326file_node_type(FilePath, Dependencies, 'bottom') :-
327 not(member((FilePath, _), Dependencies)), !.
328
329file_node_type(_, _, 'intermediate') :- !.
330
331write_logtalk_entity_facts_to_graphML(ProjectPath, ConsultedLogtalkFilePaths, OutStream) :-
332 lgt_to_graphML::write_logtalk_entity_facts_to_graphML(ProjectPath, ConsultedLogtalkFilePaths, OutStream).
333
334collect_ids_for_focus_file(FocusFile, Files, CalledPredicates, Calls):-
335 findall(
336 Module:Name/Arity,
337 predicate_in_file(FocusFile, Module, Name, Arity),
338 OwnPredicates
339 ),
340 collect_calls_to_predicates(OwnPredicates, [], IncomingCalls),
341 collect_calling_predicates_and_files(IncomingCalls, OwnPredicates, CallingPreds, [FocusFile], CallingFiles),
342 list_to_set(CallingFiles, CallingFiles0),
343 collect_calls_from_predicates(OwnPredicates,[], OutgoingCalls, FocusFile),
344 collect_called_predicates_and_files(OutgoingCalls, CallingPreds, AllPreds, CallingFiles0, AllFiles),
345 list_to_set(AllPreds, CalledPredicates),
346 list_to_set(AllFiles, Files),
347 append(IncomingCalls, OutgoingCalls, CallsList),
348 list_to_set(CallsList, Calls).
349
350collect_calls_to_predicates([],KnownCalls,KnownCalls).
351collect_calls_to_predicates([TargetModule:TargetName/TargetArity|OtherPredicates], KnownCalls, AllCalls):-
352 findall(
353 (SourceModule:SourceName/SourceArity, TargetModule:TargetName/TargetArity),
354 calls(TargetModule, TargetName, TargetArity, SourceModule, SourceName, SourceArity, _NumberOfCalls),
355 FoundCalls
356 ),
357 ( FoundCalls \= []
358 -> ( append(FoundCalls,KnownCalls,CallList),
359 list_to_set(CallList,CallSet)
360 )
361 ; CallSet = KnownCalls
362 ),
363 collect_calls_to_predicates(OtherPredicates,CallSet,AllCalls).
364
365collect_calls_from_predicates([],KnownCalls,KnownCalls, _FocusFile).
366collect_calls_from_predicates([SourceModule:SourceName/SourceArity|OtherPredicates],KnownCalls,AllCalls, FocusFile):-
367 findall(
368 (SourceModule:SourceName/SourceArity, TargetModule:TargetName/TargetArity),
369 ( functor(SourceHead, SourceName, SourceArity),
370 ( predicate_property(SourceModule:SourceHead, multifile)
371 -> calls_multifile(TargetModule, TargetName, TargetArity, SourceModule, SourceName, SourceArity, FocusFile, _)
372 ; calls(TargetModule, TargetName, TargetArity, SourceModule, SourceName, SourceArity, _)
373 )
374 ),
375 FoundCalls
376 ),
377 ( FoundCalls \= []
378 -> ( append(FoundCalls,KnownCalls,CallList),
379 list_to_set(CallList,CallSet)
380 )
381 ; CallSet = KnownCalls
382 ),
383 collect_calls_from_predicates(OtherPredicates, CallSet, AllCalls, FocusFile).
384
385collect_calling_predicates_and_files([],Preds,Preds,Files,Files).
386collect_calling_predicates_and_files([(SourceModule:SourceName/SourceArity,TargetModule:TargetName/TargetArity)|OtherCalls],KnownCalledPreds, CalledPreds,KnownCalledFiles,CalledFiles):-
387 findall(
388 File,
389 ( functor(SourceHead, SourceName, SourceArity),
390 ( predicate_property(SourceModule:SourceHead, multifile)
391 -> calls_multifile(TargetModule, TargetName, TargetArity, SourceModule, SourceName, SourceArity, File, _)
392 ; predicate_property(SourceModule:SourceHead, file(File))
393 )
394 ),
395 Files
396 ),
397 append(Files, KnownCalledFiles, NewKnownCalledFiles),
398 collect_calling_predicates_and_files(OtherCalls,[SourceModule:SourceName/SourceArity|KnownCalledPreds],CalledPreds,NewKnownCalledFiles,CalledFiles).
399
400
401collect_called_predicates_and_files([],Preds,Preds,Files,Files).
402collect_called_predicates_and_files([(_Caller,TargetModule:TargetName/TargetArity)|OtherCalls],KnownCalledPreds, CalledPreds,KnownCalledFiles,CalledFiles):-
403 findall(File, file_of_predicate(TargetModule, TargetName, TargetArity, File), Files),
404 append(Files, KnownCalledFiles, NewKnownCalledFiles),
405 collect_called_predicates_and_files(OtherCalls,[TargetModule:TargetName/TargetArity|KnownCalledPreds],CalledPreds,NewKnownCalledFiles,CalledFiles).
406
417
418
419write_files(RelativePath, Files, Filters, Stream):-
420 forall(
421 member(File,Files),
422 ( main_module_of_file(File,Module),
423 write_file(Stream, RelativePath, Filters, File, Module),
424 flush_output(Stream)
425 )
426 ).
427
438
439
440
441
448
449