dialyzer_gui.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,545 行 · 第 1/4 页
ERL
1,545 行
%% -*- erlang-indent-level: 2 -*-%%------------------------------------------------------------------------%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% Copyright 2006, Tobias Lindahl and Kostis Sagonas%% %% $Id$%%%%%-----------------------------------------------------------------------%%% File : dialyzer_gui.erl%%% Authors : Tobias Lindahl <tobiasl@csd.uu.se>%%% Kostis Sagonas <kostis@it.uu.se>%%% Description : The graphical user interface for the Dialyzer tool.%%%%%% Created : 27 Apr 2004 by Tobias Lindahl <tobiasl@csd.uu.se>%%%------------------------------------------------------------------------module(dialyzer_gui).-export([start/1]).-include("dialyzer.hrl").-record(gui_state, {add_all, add_file, add_rec, chosen_box, analysis_pid, del_file, doc_plt, clear_chosen, clear_log, clear_warn, empty_plt, fixpoint, init_plt, user_plt, dir_entry, file_box, file_wd, gs, log, menu, mode, options, packer, run, stop, top, warnings_box, backend_pid}).-record(menu, {file_save_log, file_save_warn, file_quit, help_about, help_manual, help_overview, help_warnings, opts_supress_inline, opts_macros, opts_includes, plt_empty, plt_search_doc, plt_show_doc, warnings}). -record(mode, {start_byte_code, iter_fixpoint, start_src_code, iter_qad, dataflow, succ_typings, old_style}).start(DialyzerOptions = #options{}) -> process_flag(trap_exit, true), GS = gs:start(), code:add_pathsa(["."]), WH = [{width, 1000}, {height, 550}], {ok,Host} = inet:gethostname(), %% --------- Top Window -------------- TopWin = gs:window(GS, [{title, "Dialyzer "++?VSN++" @ "++Host}, {configure, true}, {default, listbox, {bg, white}}, {default, editor, {bg, white}}, {default, entry, {bg, white}}, {default, button, {font, {helvetica, bold, 12}}}, {default, label, {font, {helvetica, bold, 12}}} |WH]), Packer = gs:frame(TopWin, [{packer_x, [{stretch, 3},{fixed, 200}, {stretch, 7}]}, {packer_y, [{fixed, 25}, {fixed, 20}, {stretch, 1, 50}, {fixed, 25}, {fixed, 20}, {stretch, 1, 50}, {fixed, 25}]}]), %% --------- Chosen box -------------- gs:label(Packer, [{label, {text, "Directories or modules to analyze"}}, {height, 20}, {pack_xy, {1,2}}]), ChosenBox = gs:listbox(Packer, [{pack_xy, {1,3}},{vscroll, right}, {selectmode, multiple}]), %% --------- File box -------------- gs:label(Packer, [{label, {text, "File"}}, {height, 20}, {pack_xy, {1,5}}]), FilePacker = gs:frame(Packer, [{packer_x, [{fixed, 30}, {stretch, 1, 100}]}, {packer_y, [{fixed, 25}, {stretch, 1, 25}]}, {pack_xy, {1, 6}}]), gs:label(FilePacker, [{label, {text, "Dir:"}}, {pack_xy, {1,1}}]), DirEntry = gs:entry(FilePacker, [{height, 30}, {pack_xy, {2,1}}, {keypress, true}]), File = gs:listbox(FilePacker, [{pack_x, {1,2}}, {pack_y, 2}, {selectmode, multiple}, {doubleclick, true}, {vscroll, right}]), %% --------- Options -------------- gs:label(Packer, [{label, {text, "Analysis Options"}}, {height, 20}, {pack_xy, {2, 2}}]), ModePacker = gs:frame(Packer, [{packer_x, [{fixed, 75},{fixed, 120}]}, {packer_y, [{fixed, 20},{fixed, 20}, {fixed, 20}, %%{stretch, 1}, % empty space {fixed, 20}, {fixed, 20}, {fixed, 20}, {stretch, 1} % empty space ]}, {bw, 10}, {relief, flat}, {default, {radiobutton, {align, w}}}, {default, {label, {align, w}}}, {pack_xy, {2, 3}}]), %% Bytecode vs. Source code gs:label(ModePacker, [{label, {text, "File Type:"}}, {height, 20}, {pack_xy, {1,1}}]), ModeByteCode = gs:radiobutton(ModePacker, [{group, start_from}, {label, {text,"ByteCode"}}, {select, true}, {pack_xy, {2,1}}]), ModeSrcCode = gs:radiobutton(ModePacker, [{group, start_from}, {label, {text,"SourceCode"}}, {pack_xy, {2,2}}]), %% Analysis Type gs:label(ModePacker, [{label, {text, "Analysis:"}}, {height, 20}, {pack_xy, {1,4}}]), ModeDataflow = gs:radiobutton(ModePacker, [{group, type}, {label,{text,"Dataflow"}}, {select, true}, {pack_xy, {2,4}}]), ModeSuccTypings = gs:radiobutton(ModePacker, [{group, type}, {label,{text,"Success Typings"}}, {pack_xy, {2,5}}]), ModeOldStyle = gs:radiobutton(ModePacker, [{group, type}, {label,{text,"Old Style"}}, {pack_xy, {2,6}}]), Mode = #mode{start_byte_code=ModeByteCode, start_src_code=ModeSrcCode, dataflow=ModeDataflow, succ_typings=ModeSuccTypings, old_style=ModeOldStyle }, %% --------- Log box -------------- gs:label(Packer, [{label, {text, "Log"}}, {height, 20}, {pack_xy, {3,2}}]), Log = gs:editor(Packer, [{pack_x, 3}, {pack_y, 3}, {enable, false}, {font, {courier, 12}}, {vscroll, right}, {wrap, word}]), %% --------- Warnings box -------------- gs:label(Packer, [{label, {text, "Warnings"}},{height, 20},{pack_xy, {3,5}}]), WarningsBox = gs:editor(Packer, [{pack_x, {2,3}}, {pack_y, 6}, {enable, false}, {font, {courier, 12}},{vscroll, right}, {wrap, word}]), %% --------- Buttons -------------- ButtonPackerHighLeft = gs:frame(Packer, [{packer_x, [{fixed, 50}, {fixed, 65}, {stretch,1}]}, % empty space {pack_xy, {1,4}}]), ButtonPackerHighRight = gs:frame(Packer, [{packer_x, [{fixed, 70}, {fixed, 70}, {stretch,1}]}, % empty space {pack_xy, {3,4}}]), ButtonPackerLowLeft = gs:frame(Packer, [{packer_x, [{fixed, 50}, {fixed, 60}, {fixed, 110}, {stretch,1}]}, % empty space {pack_xy, {1,7}}]), ButtonPackerLowRight = gs:frame(Packer, [{packer_x, [{fixed, 70}, {fixed, 70}, {stretch,1},% empty space {fixed, 70}, {fixed, 70}]}, {pack_x, {2,3}}, {pack_y, 7}]), WHButton = [{width, 60},{height, 20}], AddFile = gs:button(ButtonPackerLowLeft, [{pack_xy, {1,1}}, {label, {text,"Add"}}|WHButton]), AddAll = gs:button(ButtonPackerLowLeft, [{pack_xy, {2,1}}, {label, {text,"Add All"}}|WHButton]), AddRec = gs:button(ButtonPackerLowLeft, [{pack_xy, {3,1}}, {label, {text,"Add Recursively"}} |WHButton]), DelFile = gs:button(ButtonPackerHighLeft, [{pack_xy, {1,1}}, {label, {text,"Delete"}}|WHButton]), ClearChosen = gs:button(ButtonPackerHighLeft, [{pack_xy, {2,1}}, {label, {text,"Delete All"}} |WHButton]), ClearLog = gs:button(ButtonPackerHighRight, [{pack_xy, {1,1}}, {label, {text,"Clear Log"}} |WHButton]), ClearWarn = gs:button(ButtonPackerLowRight, [{pack_xy, {1,1}}, {label, {text,"Clear Warn"}} |WHButton]), Run = gs:button(ButtonPackerLowRight, [{pack_xy, {4,1}}, {label, {text,"Run"}}|WHButton]), Stop = gs:button(ButtonPackerLowRight, [{pack_xy, {5,1}}, {enable, false}, {label, {text,"Stop"}}|WHButton]), %% --------- Menu -------------- MenuBar = gs:menubar(TopWin, []), %% File Menu MenuBarFile = gs:menubutton(MenuBar, [{label,{text,"File"}}]), MenuFile = gs:menu(MenuBarFile, []), MenuFileSaveWarn = gs:menuitem(MenuFile, [{label,{text,"Save Warnings"}}]), MenuFileSaveLog = gs:menuitem(MenuFile, [{label,{text,"Save Log"}}]), MenuFileQuit = gs:menuitem(MenuFile, [{label,{text,"Quit"}}]), %% Warnings Menu MenuBarWarn = gs:menubutton(MenuBar, [{label,{text,"Warnings"}}]), MenuWarn = gs:menu(MenuBarWarn, []), MenuWarnMatch = gs:menuitem(MenuWarn, [{label, {text, "Match failures"}}, {itemtype, check}, {select, true}]), MenuWarnFailingCall = gs:menuitem(MenuWarn, [{label, {text, "Failing function calls"}}, {itemtype, check}, {select, true}]), MenuWarnFunApp = gs:menuitem(MenuWarn, [{label, {text, "Bad fun-applications"}}, {itemtype, check}, {select, true}]), MenuWarnLists = gs:menuitem(MenuWarn, [{label, {text, "Improper list constructions"}}, {itemtype, check}, {select, true}]), MenuWarnGuards = gs:menuitem(MenuWarn, [{label, {text, "Failing guards"}}, {itemtype, check}, {select, true}]), MenuWarnEq = gs:menuitem(MenuWarn, [{label, {text, "Failing term comparisons"}}, {itemtype, check}, {select, true}]), MenuWarnNotCalled = gs:menuitem(MenuWarn, [{label, {text, "Unused functions"}}, {itemtype, check}, {select, true}]), MenuWarnTupleAsFun = gs:menuitem(MenuWarn, [{label, {text, "Tuple used as fun"}}, {itemtype, check}, {select, true}]), MenuWarnBeam = gs:menuitem(MenuWarn, [{label, {text, "Unsafe BEAM code"}}, {itemtype, check}, {select, true}]), MenuWarnReturnOnlyExit = gs:menuitem(MenuWarn, [{label, {text, "Error handling functions"}}, {itemtype, check}, {select, false}]), MenuWarnReturnNoReturn = gs:menuitem(MenuWarn, [{label, {text, "Functions of no return"}}, {itemtype, check}, {select, true}]), MenuWarnCallNonExported = gs:menuitem(MenuWarn, [{label, {text,"Call to unexported function"}}, {itemtype, check}, {select, true}]), %% PLT Menu MenuBarPLT = gs:menubutton(MenuBar, [{label, {text,"PLT"}}]), MenuPLT = gs:menu(MenuBarPLT, []), MenuPLTEmpty = gs:menuitem(MenuPLT, [{label,{text,"Init with empty PLT"}}, {itemtype, check}, {select, false}]), MenuPLTShow = gs:menuitem(MenuPLT, [{label,{text,"Show contents"}}]), MenuPLTSearch = gs:menuitem(MenuPLT, [{label,{text,"Search contents"}}]), %% Options Menu MenuBarOpts = gs:menubutton(MenuBar, [{label,{text,"Options"}}]), MenuOpts = gs:menu(MenuBarOpts, []), MenuOptsCheckInline = gs:menuitem(MenuOpts, [{label, {text, "Ignore inline-compiled bytecode"}}, {itemtype, check}, {select, false}]), MenuOptsMacros = gs:menuitem(MenuOpts,[{label, {text, "Manage Macro Definitions"}}]), MenuOptsIncludes = gs:menuitem(MenuOpts, [{label, {text, "Manage Include Directories"}}]), %% Help MenuBarHelp = gs:menubutton(MenuBar, [{label,{text,"Help"}}, {side, right}]), MenuHelp = gs:menu(MenuBarHelp, []), MenuHelpOverview = gs:menuitem(MenuHelp, [{label,{text,"Overview"}}]), MenuHelpManual = gs:menuitem(MenuHelp, [{label,{text,"Manual"}}]), MenuHelpWarnings = gs:menuitem(MenuHelp, [{label,{text,"Warnings"}}]), MenuHelpAbout = gs:menuitem(MenuHelp, [{label,{text,"About"}}]), Warnings = [{?WARN_RETURN_NO_RETURN, MenuWarnReturnNoReturn}, {?WARN_RETURN_ONLY_EXIT, MenuWarnReturnOnlyExit}, {?WARN_NOT_CALLED, MenuWarnNotCalled}, {?WARN_NON_PROPER_LIST, MenuWarnLists}, {?WARN_TUPLE_AS_FUN, MenuWarnTupleAsFun}, {?WARN_FUN_APP, MenuWarnFunApp}, {?WARN_MATCHING, MenuWarnMatch}, {?WARN_COMP, MenuWarnEq}, {?WARN_GUARDS, MenuWarnGuards}, {?WARN_OLD_BEAM, MenuWarnBeam}, {?WARN_FAILING_CALL, MenuWarnFailingCall}, {?WARN_CALLGRAPH, MenuWarnCallNonExported} ], init_warnings(Warnings, DialyzerOptions#options.legal_warnings), Menu = #menu{file_quit=MenuFileQuit, plt_empty=MenuPLTEmpty, help_overview=MenuHelpOverview, help_manual=MenuHelpManual, help_about=MenuHelpAbout, help_warnings=MenuHelpWarnings, opts_supress_inline=MenuOptsCheckInline, opts_macros=MenuOptsMacros, opts_includes=MenuOptsIncludes, plt_search_doc=MenuPLTSearch, plt_show_doc=MenuPLTShow, file_save_log=MenuFileSaveLog, file_save_warn=MenuFileSaveWarn, warnings=Warnings}, %% --------- Init -------------- gs:config(TopWin, {map, true}), gs:config(Packer, WH), {ok, CWD} = file:get_cwd(), EmptyPlt = dialyzer_plt:new(dialyzer_empty_plt), InitPlt0 = DialyzerOptions#options.init_plt, InitPlt = dialyzer_plt:from_file(dialyzer_init_plt, InitPlt0), State = #gui_state{add_all=AddAll, add_file=AddFile, add_rec=AddRec, chosen_box=ChosenBox, clear_chosen=ClearChosen, clear_log=ClearLog, clear_warn=ClearWarn, del_file=DelFile, dir_entry=DirEntry, empty_plt=EmptyPlt, file_box=File, file_wd=CWD, gs=GS, init_plt=InitPlt, log=Log, menu=Menu, mode=Mode, options=DialyzerOptions, packer=Packer, run=Run, stop=Stop, top=TopWin, warnings_box=WarningsBox}, NewState = change_dir_or_add_file(State, "."), gui_loop(NewState).%% ----------------------------------------------------------------%%%% Main GUI Loop%%gui_loop(State = #gui_state{}) -> TopWin = State#gui_state.top, Packer = State#gui_state.packer, ChosenBox = State#gui_state.chosen_box, File = State#gui_state.file_box, DirEntry = State#gui_state.dir_entry, Run = State#gui_state.run, AddFile = State#gui_state.add_file, AddAll = State#gui_state.add_all, AddRec = State#gui_state.add_rec, DelFile = State#gui_state.del_file, ClearChosen = State#gui_state.clear_chosen, ClearLog = State#gui_state.clear_log, ClearWarn = State#gui_state.clear_warn, Stop = State#gui_state.stop, Log = State#gui_state.log, BackendPid = State#gui_state.backend_pid, Options = State#gui_state.options, %% --- Menu --- Menu = State#gui_state.menu, Quit = Menu#menu.file_quit, Overview = Menu#menu.help_overview, Manual = Menu#menu.help_manual, HelpWarnings = Menu#menu.help_warnings, About = Menu#menu.help_about, SaveLog = Menu#menu.file_save_log, SaveWarn = Menu#menu.file_save_warn, SearchPlt = Menu#menu.plt_search_doc,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?