package ProjectData.Files; import Common.Utils.CommonUtils; import Common_old.Constants; import Common_old.Current; import _VisualDVM.Global; import Common_old.Utils.Utils; import ProjectData.GCOV.GCOV_info; import ProjectData.LanguageName; import ProjectData.Messages.Errors.MessageError; import ProjectData.Messages.Message; import ProjectData.Messages.Notes.MessageNote; import ProjectData.Messages.Warnings.MessageWarning; import ProjectData.Project.db_project_info; import ProjectData.SapforData.Arrays.ArrayDecl; import ProjectData.SapforData.FileObjectWithMessages; import ProjectData.SapforData.Functions.FuncCall; import ProjectData.SapforData.Functions.FuncInfo; import ProjectData.SapforData.Loops.Loop; import Visual_DVM_2021.UI.Main.FileForm; import com.sun.org.glassfish.gmbal.Description; import javafx.util.Pair; import javax.swing.tree.DefaultMutableTreeNode; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.nio.file.Paths; import java.util.LinkedHashMap; import java.util.Vector; //по файлам нет смысла делать совместимость. //так что переименую public class DBProjectFile extends ProjectFile { @Description("PRIMARY KEY, UNIQUE") public String name; //имя относительно корневой папки проекта. нужно только как ключ для бд!! @Description("IGNORE") public String last_assembly_name = ""; //имя объектника. //-------------------------------------- public String options = ""; //пользовательские опции для парсера. //--- @Description("DEFAULT 0") public int lastLine = 0; @Description("DEFAULT ''") public String GCOVLog = ""; public int isMain = 0; //содержит ли ГПЕ @Description("IGNORE") public int lines_count = 0; @Description("IGNORE") public boolean NeedsSave = false; @Description("IGNORE") public String LoopGraphTitle = Constants.no_data; @Description("IGNORE") public String CallGraphTitle = Constants.no_data; @Description("IGNORE") public String ArrayGraphTitle = Constants.no_data; public db_project_info father = null; public DefaultMutableTreeNode node = null; //узел файла в дереве public FileForm form = null; //отображение. //сообщения. //---------------- //анализы public Vector LoopNests = new Vector<>(); public LinkedHashMap AllLoops = new LinkedHashMap<>(); public LinkedHashMap function_decls = new LinkedHashMap<>(); //объявления public Vector array_decls = new Vector<>(); public LinkedHashMap relativeHeaders = new LinkedHashMap<>(); public GCOV_info gcov_info = new GCOV_info(); private PrintStream Sys; public DBProjectFile() { } public DBProjectFile(File file_, db_project_info father_) { Init(file_, father_); //имя относительно папки проекта. RefreshName(); AutoDetectProperties(); } public static Pair decodeParserMessage(String S, String file_in) { Integer line = 1; String file = file_in; String[] data = S.split("\\son\\sline\\s"); if (data.length > 1) { String[] data1 = data[1].split(" "); if (data1.length > 0) line = Integer.parseInt(data1[0]); } data = S.split("\\sof\\s"); if (data.length > 1) { String[] data1 = data[1].split(":"); if (data1.length > 0) { file = CommonUtils.toW(data1[0]);//.substring(1)); //первый символ тут всегда пробел. слеши всегда виндовые. } } return new Pair<>(line, file); } public void UpdateLastLine(int line_in) { if (lastLine != line_in) { try { lastLine = line_in; father.db.Update(this); } catch (Exception ex) { Global.Log.PrintException(ex); } } } //наследуем от объекта, чтобы использовать интерфейс выбора. @Override public Object getPK() { return name; } @Description("IGNORE") public boolean IsMain() { return isMain != 0; } /* * получить имя относительно домашней папки проекта, в рамках текущей ОС * */ public String getLocalName() { return file.getAbsolutePath().substring(father.Home.getAbsolutePath().length()); } public void Init(File file_, db_project_info father_) { father = father_; file = file_; } public void RefreshName() { String path = file.getAbsolutePath(); //для совместимости пусть палки будут от винды всегда. name = path.substring(father.Home.getAbsolutePath().length() + 1).replace('/', '\\'); } public boolean isMakefile() { return file.getName().equalsIgnoreCase("makefile"); } public boolean isActiveProgram() { return fileType.equals(FileType.program) && languageName.equals(father.languageName) && !state.equals(FileState.Excluded); } //у хедера язык может быть неизвестен. потому что зависимости еще не искались. public boolean isActiveHeader() { return fileType.equals(FileType.header) && !state.equals(FileState.Excluded); } public boolean isActive() { return isActiveProgram() || isActiveHeader(); } public File getDepFile() { return Paths.get(father.getOptionsDirectory().getAbsolutePath(), getLocalName() + Constants.dep).toFile(); } public File getParserOutFile() { return Paths.get(father.getOptionsDirectory().getAbsolutePath(), getLocalName() + Constants.out).toFile(); } public File getParserErrFile() { return Paths.get(father.getOptionsDirectory().getAbsolutePath(), getLocalName() + Constants.err).toFile(); } public File getOptionsFile() { String path = file.getAbsolutePath().substring(father.Home.getAbsolutePath().length()); return Paths.get(father.getOptionsDirectory().getAbsolutePath(), path + ".opt").toFile(); } public void CreateParserOptions() throws IOException { String default_options = ""; switch (languageName) { case fortran: default_options += " -spf -noProject -o " + CommonUtils.DQuotes(getDepFile().getAbsolutePath()); switch (style) { case free: default_options += " -f90"; break; case fixed: default_options += " -FI"; break; case extended: default_options += " -extend_source"; break; } break; case c: //TODO break; } Utils.WriteToFile(getOptionsFile(), (default_options + " " + options + "\n")); } public void ReadMessages(String text) throws Exception { String[] nw = text.split("\n"); for (String S : nw) { Pair p = decodeParserMessage(S, name); //---- if (S.toLowerCase().startsWith("note")) { father.db.files.Data.get(p.getValue()).CreateAndAddNewMessage(2, S, p.getKey(), Constants.parser_group); } else if (S.toLowerCase().startsWith("warning")) { father.db.files.Data.get(p.getValue()).CreateAndAddNewMessage(0, S, p.getKey(), Constants.parser_group); } else if (S.toLowerCase().startsWith("error")) father.db.files.Data.get(p.getValue()).CreateAndAddNewMessage(1, S, p.getKey(), Constants.parser_group); } } public void ReadParseMessages() throws Exception { if (getParserOutFile().exists()) ReadMessages(Utils.ReadAllText(getParserOutFile())); if (getParserErrFile().exists()) ReadMessages(Utils.ReadAllText(getParserErrFile())); } //важно. тут транзакция своя, оборачивать ее нельзя! public void CleanMessages() throws Exception { if (!state.equals(FileState.Excluded)) state = FileState.Undefined; father.db.BeginTransaction(); father.db.Update(this); Vector to_delete = new Vector<>(); for (Message message : father.db.notes.Data.values()) { if (message.file.equalsIgnoreCase(name)) to_delete.add(message); } for (Message message : father.db.warnings.Data.values()) { if (message.file.equalsIgnoreCase(name)) to_delete.add(message); } for (Message message : father.db.errors.Data.values()) { if (message.file.equalsIgnoreCase(name)) to_delete.add(message); } for (Message message : to_delete) father.db.Delete(message); father.db.Commit(); } public void CleanAll() throws Exception { lines_count = 0; isMain = 0; CleanMessages(); LoopGraphTitle = Constants.no_data; LoopNests.clear(); ; AllLoops.clear(); CallGraphTitle = Constants.no_data; function_decls.clear(); relativeHeaders.clear(); ArrayGraphTitle = Constants.no_data; array_decls.clear(); gcov_info.clear(); } public void CreateAndAddNewMessage(int m_type, String m_value, int m_line, int m_group) throws Exception { switch (m_type) { case 0: MessageWarning warning = new MessageWarning(name, m_line, m_value, m_group); father.db.Insert(warning); father.db.recommendations.addRecommendation(m_group); if (state != FileState.HasErrors) state = FileState.HasWarnings; break; case 1: MessageError error = new MessageError(name, m_line, m_value, m_group); father.db.Insert(error); father.db.recommendations.addRecommendation(m_group); state = FileState.HasErrors; break; case 2: MessageNote note = new MessageNote(name, m_line, m_value, m_group); father.db.Insert(note); father.db.recommendations.addRecommendation(m_group); if (state != FileState.HasWarnings && state != FileState.HasErrors) state = FileState.HasNotes; break; } } public DefaultMutableTreeNode show_loop_graph_r(FileObjectWithMessages element) { DefaultMutableTreeNode res = new DefaultMutableTreeNode(element); if (element instanceof Loop) { for (FileObjectWithMessages child : ((Loop) element).children) res.add(show_loop_graph_r(child)); } return res; } public DefaultMutableTreeNode getLoopsTree() { DefaultMutableTreeNode root = new DefaultMutableTreeNode(LoopGraphTitle); for (Loop nest : LoopNests) root.add(show_loop_graph_r(nest)); return root; } public DefaultMutableTreeNode getFunctionsTree() { DefaultMutableTreeNode root = new DefaultMutableTreeNode(CallGraphTitle); for (FuncInfo fi : function_decls.values()) { DefaultMutableTreeNode node = new DefaultMutableTreeNode(fi); for (FuncCall fc : fi.calls) node.add(new DefaultMutableTreeNode(fc)); root.add(node); } return root; } public DefaultMutableTreeNode getArraysTree() { DefaultMutableTreeNode root = new DefaultMutableTreeNode(ArrayGraphTitle); for (ArrayDecl a : array_decls) root.add(new DefaultMutableTreeNode(a)); return root; } public boolean UpdateType(FileType type_in) { if (!fileType.equals(type_in)) { fileType = type_in; try { father.db.Update(this); return true; } catch (Exception e) { Global.Log.PrintException(e); } } return false; } public boolean UpdateLanguage(LanguageName lang_in) { if (!languageName.equals(lang_in)) { languageName = lang_in; try { father.db.Update(this); return true; } catch (Exception e) { Global.Log.PrintException(e); } } return false; } public boolean UpdateStyle(LanguageStyle s_in) { if (!style.equals(s_in)) { style = s_in; try { father.db.Update(this); return true; } catch (Exception e) { Global.Log.PrintException(e); } } return false; } public int getFirstBadLine() { for (MessageError error : father.db.errors.Data.values()) if (error.file.equals(this.name)) return error.line; return -1; } public int FragmentLoopCount(int first, int second) { int res = 0; for (Loop l : AllLoops.values()) { if ((l.line >= first) && (l.line <= second)) res++; } return res; } public int FragmentFunctionDeclsCount(int first, int second) { int res = 0; for (FuncInfo fi : function_decls.values()) { if ((fi.line >= first) && (fi.line <= second)) res++; } return res; } public int FragmentFunctionCallsCount(int first, int second) { int res = 0; for (FuncInfo fi : function_decls.values()) for (FuncCall fc : fi.calls) { if ((fc.line >= first) && (fc.line <= second)) res++; } return res; } public FuncCall find_current_func_call() { //------------- for (FuncInfo fi : function_decls.values()) { for (FuncCall fc : fi.calls) { if ((fc.line == form.getEditor().getCurrentLine()) && !Current.getSapfor().isIntrinsic(fc.funcName) ) { return fc; } } } //------------- return null; } public FuncCall find_func_call(String funcName) { for (FuncInfo fi : function_decls.values()) { for (FuncCall fc : fi.calls) { if (fc.funcName.equalsIgnoreCase(funcName) && (fc.line == form.getEditor().getCurrentLine() )) { return fc; } } } return null; } public Loop find_current_loop() { int line = form.getEditor().getCurrentLine(); return AllLoops.getOrDefault(line, null); } public void Exclude() throws Exception { state = FileState.Excluded; father.db.Update(this); } public void Include() throws Exception { state = FileState.Undefined; father.db.Update(this); } public String getUnixName() { return CommonUtils.toU(name); } public String getQObjectName() { return CommonUtils.DQuotes(getUnixName() + ".o"); } @Override public String toString() { return name; } public String getProjectNameWithoutExtension() { String extension = CommonUtils.getExtension(file); return name.substring(0, name.length() - (extension.length() + 1)); } public void importSettings(DBProjectFile parent, boolean sapforStyle) throws Exception { fileType = parent.fileType; switch (parent.state) { case Undefined: case Excluded: state = parent.state; break; default: state = FileState.Undefined; break; } languageName = parent.languageName; if (sapforStyle) style = Current.getSapfor().getStyle(); else style = parent.style; } public void importSourceCodeSettings(DBProjectFile parent, boolean sapforStyle) throws Exception { switch (parent.state) { case Undefined: case Excluded: state = parent.state; break; default: state = FileState.Undefined; break; } languageName = parent.languageName; if (sapforStyle) style = Current.getSapfor().getStyle(); else style = parent.style; } //------------------ public void CheckStateByMessageType(int m_type) throws Exception { switch (m_type) { case 0: if (state != FileState.HasErrors) state = FileState.HasWarnings; break; case 1: state = FileState.HasErrors; break; case 2: if (state != FileState.HasWarnings && state != FileState.HasErrors) state = FileState.HasNotes; break; } } //------------------ public void ReadMessagesNoSave(String text, LinkedHashMap files) throws Exception { String[] nw = text.split("\n"); for (String S : nw) { Pair p = decodeParserMessage(S, name); if (S.toLowerCase().startsWith("note")) { files.get(p.getValue()).CheckStateByMessageType(2); } else if (S.toLowerCase().startsWith("warning")) { files.get(p.getValue()).CheckStateByMessageType(0); } else if (S.toLowerCase().startsWith("error")) files.get(p.getValue()).CheckStateByMessageType(1); } } public void ReadParseMessagesNoSave(LinkedHashMap files) throws Exception { if (getParserOutFile().exists()) ReadMessagesNoSave(Utils.ReadAllText(getParserOutFile()), files); if (getParserErrFile().exists()) ReadMessagesNoSave(Utils.ReadAllText(getParserErrFile()), files); } public int FragmentArraysCount(Integer first, Integer second) { int res = 0; for (ArrayDecl ai : array_decls) { if ((ai.line >= first) && (ai.line <= second)) res++; } return res; } //--- }