Files
VisualSapfor/src/ProjectData/Files/DBProjectFile.java
2024-10-09 22:15:56 +03:00

477 lines
18 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package ProjectData.Files;
import Common.Utils.CommonUtils;
import _VisualDVM.Constants;
import _VisualDVM.Current;
import _VisualDVM.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 _VisualDVM.Visual.Windows.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<Loop> LoopNests = new Vector<>();
public LinkedHashMap<Integer, Loop> AllLoops = new LinkedHashMap<>();
public LinkedHashMap<String, FuncInfo> function_decls = new LinkedHashMap<>(); //объявления
public Vector<ArrayDecl> array_decls = new Vector<>();
public LinkedHashMap<String, DBProjectFile> 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<Integer, String> 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) {
CommonUtils.MainLog.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<Integer, String> 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<Message> 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) {
CommonUtils.MainLog.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) {
CommonUtils.MainLog.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) {
CommonUtils.MainLog.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<String, DBProjectFile> files) throws Exception {
String[] nw = text.split("\n");
for (String S : nw) {
Pair<Integer, String> 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<String, DBProjectFile> 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;
}
//---
}