pascalabcnet/VisualPascalABCNETLinux/Workbench/RunService.cs

344 lines
18 KiB
C#
Raw Normal View History

// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using VisualPascalABCPlugins;
namespace VisualPascalABC
{
public partial class WorkbenchRunService : IWorkbenchRunService
{
string RedirectIOModeModuleName = "__RedirectIOMode";
string RunModeModuleName = "__RunMode";
string RedirectIOModeName = "[REDIRECTIOMODE]";
string RunModeName = "[RUNMODE]";
private bool TerminateAllPrograms = false;
public RunManager RunnerManager;
private IWorkbench Workbench;
//private IWorkbenchDesignerService DesignerService;
private IWorkbenchBuildService BuildService;
private IWorkbenchDocumentService DocumentService;
private IWorkbenchDebuggerOperationsService DebuggerOperationsService;
private DebugHelper DebuggerManager;
private Dictionary<string, ICodeFileDocument> RunTabs = new Dictionary<string, ICodeFileDocument>();
private Dictionary<ICodeFileDocument, string> ReadRequests = new Dictionary<ICodeFileDocument, string>();
private Dictionary<string, string> RunArgumentsTable = new Dictionary<string, string>();
bool RunActiveTabPage = false;
// SSM 16/05/22 - добавил чтобы иметь возможность добавлять обработчики во внешнем плагине
public event RunnerManagerActionDelegate Starting
{
add
{
RunnerManager.Starting += value;
}
remove
{
RunnerManager.Starting -= value;
}
}
public event RunnerManagerActionDelegate Exited
{
add
{
RunnerManager.Exited += value;
}
remove
{
RunnerManager.Exited -= value;
}
}
public WorkbenchRunService()
{
Workbench = WorkbenchServiceFactory.Workbench;
RunnerManager = new RunManager(ReadStringRequest);
RunnerManager.Exited += new RunnerManagerActionDelegate(RunnerManager_Exited);
RunnerManager.Starting += new RunnerManagerActionDelegate(RunnerManager_Started);
RunnerManager.OutputStringReceived += new RunManager.TextRecivedDelegate(RunnerManager_OutputStringReceived);
RunnerManager.RunnerManagerUnhanledRuntimeException += new RunManager.RunnerManagerUnhanledRuntimeExceptionDelegate(RunnerManager_RunnerManagerUnhanledRuntimeException);
//DesignerService = WorkbenchServiceFactory.DesignerService;
this.DebuggerManager = WorkbenchServiceFactory.DebuggerManager;
BuildService = WorkbenchServiceFactory.BuildService;
DebuggerOperationsService = WorkbenchServiceFactory.DebuggerOperationsService;
DocumentService = WorkbenchServiceFactory.DocumentService;
}
public bool Run(bool RedirectConsoleIO)
{
Workbench.UserOptions.RedirectConsoleIO = RedirectConsoleIO;
if (Workbench.UserOptions.RedirectConsoleIO)
if (!DebuggerManager.IsRunning)
return Run(DocumentService.CurrentCodeFileDocument, true, false, false);
else if (DebuggerManager.IsRunAndInThisTabPage())
{
DebuggerManager.Continue();
return true;
}
return Run(DocumentService.CurrentCodeFileDocument);
}
public bool Run(bool forDebugging, bool startWithGoto, bool need_first_brpt)
{
return Run(DocumentService.CurrentCodeFileDocument, forDebugging, startWithGoto, need_first_brpt);
}
public void Run(string fileName, bool redirectIO, string ModeName, bool RunWithPause, string WorkingDirectory, string CommandLineArguments, bool attachDebugger, bool fictive_attach)
{
RunnerManager.Run(fileName,
Workbench.UserOptions.RedirectConsoleIO, RedirectIOModeName, RunWithPause,
Workbench.VisualEnvironmentCompiler.Compiler.CompilerOptions.SourceFileDirectory,
CommandLineArguments, attachDebugger, fictive_attach);
}
public bool Run(ICodeFileDocument tabPage, bool forDebugging, bool startWithGoto, bool needFirstBreakpoint)
{
lock (o)
{
bool attachdbg = forDebugging || startWithGoto || needFirstBreakpoint; //|| WorkbenchServiceFactory.DebuggerManager.HasBreakpoints();
bool fictive_attach = false;
BuildService.CompilerOptions.UseDllForSystemUnits = false;
BuildService.CompilerOptions.OutputFileType = PascalABCCompiler.CompilerOptions.OutputType.ConsoleApplicaton;
if (ProjectFactory.Instance.ProjectLoaded)
tabPage = DocumentService.GetTabPageForMainFile();
if (attachdbg && !Workbench.UserOptions.AlwaysAttachDebuggerAtStart)
Деактивация кнопок, связанных с Intellisense, для языков без Intellisense + разделение ILanguageInformation на два интерфейса (#3378) * Refactor language information classes * Implement SimpleLanguageInformation abstract class * Move some properties to SimpleLanguageInformation * Implement format and debug buttons disabling if Intellisense is not supported for current language * Add Intellisense available check in FormsExtensions to deactivate menu items if needed * Change function interfaces in VisibilityService * Replace CodeCompletionController.CurrentParser null checks with IntellisenseAvailable method call * Refactor IParser and BaseParser to deduplicate code * Fix BuildTreeInSpecialMode in SPythonParser * Add SimpleParser class for new languages without Intellisense * Delete duplicate SetDebugButtonsEnabled function * Add Intellisense available check in RunService when attaching debugger * Delete inner check in SetDebugButtonsEnabled to improve architecture * Change CurrentParser property in CodeCompletion to be CurrentLanguage * Divide ILanguageInformation into two interfaces (creating new ILanguageIntellisenseSupport) * Fix LanguageIntellisenseSupport initialization in BaseLanguage * Fix RunService fictive_attach logic * Disable Intellisense parsing for languages without Intellisense support * Add DefaultLanguageInformation abstract class * Add default implementation for SetSemanticConstants in BaseLanguage * Simplify IParser interface * Update developer guide documentation
2026-01-27 22:25:28 +03:00
fictive_attach = !startWithGoto && !needFirstBreakpoint && !DebuggerManager.HasBreakpoints() || !CodeCompletion.CodeCompletionController.IntellisenseAvailable();
WorkbenchServiceFactory.OperationsService.ClearOutputTextBoxForTabPage(tabPage);
Workbench.ErrorsListWindow.ClearErrorList();
//DesignerService.GenerateAllDesignersCode();
string runtimeModule;
string ModeName;
bool RunWithPause = false;
if (Workbench.UserOptions.RedirectConsoleIO || forDebugging)
{
runtimeModule = RedirectIOModeModuleName;
ModeName = RedirectIOModeName;
if (Workbench.UserOptions.UseDllForSystemUnits && !Workbench.UserOptions.PABCDllChecked)
{
if (typeof(System.Runtime.CompilerServices.ExtensionAttribute).Assembly != typeof(int).Assembly || PascalABCCompiler.Compiler.get_assembly_path("PABCRtl.dll", false) == null)
Workbench.UserOptions.UseDllForSystemUnits = false;
Workbench.UserOptions.PABCDllChecked = true;
}
// SSM 09.02.20 - UseDllForSystemUnits включать когда флаг установлен - безо всяких доп. условий
if (/*Workbench.UserOptions.DeleteEXEAfterExecute &&*/ Workbench.UserOptions.UseDllForSystemUnits && !startWithGoto && !needFirstBreakpoint)
BuildService.CompilerOptions.UseDllForSystemUnits = true;
}
else
{
runtimeModule = RunModeModuleName;
ModeName = RunModeName;
RunWithPause = Workbench.UserOptions.PauseInRunModeIfConsole;
}
bool debug = BuildService.CompilerOptions.Debug;
if (forDebugging)
{
BuildService.CompilerOptions.Debug = true;
BuildService.CompilerOptions.ForDebugging = true;
Workbench.UserOptions.RedirectConsoleIO = true;
}
string OutputFileName = null;
if (!forDebugging)
{
if (!ProjectFactory.Instance.ProjectLoaded)
OutputFileName = BuildService.Compile(tabPage.FileName, false, runtimeModule, true, Workbench.UserOptions.RedirectConsoleIO);
else
OutputFileName = BuildService.Compile(ProjectFactory.Instance.CurrentProject, false, runtimeModule, true, Workbench.UserOptions.RedirectConsoleIO);
}
else
{
if (!ProjectFactory.Instance.ProjectLoaded)
OutputFileName = BuildService.Compile(tabPage.FileName, false, runtimeModule, true, true);
else
OutputFileName = BuildService.Compile(ProjectFactory.Instance.CurrentProject, false, runtimeModule, true, true);
}
if (RunWithPause)
RunWithPause = RunWithPause && Workbench.VisualEnvironmentCompiler.Compiler.CompilerOptions.OutputFileType == PascalABCCompiler.CompilerOptions.OutputType.ConsoleApplicaton;
if (OutputFileName != null)
{
switch (Workbench.VisualEnvironmentCompiler.Compiler.CompilerOptions.OutputFileType)
{
case PascalABCCompiler.CompilerOptions.OutputType.ClassLibrary:
if (DocumentService.ActiveCodeFileDocument != null && DocumentService.ActiveCodeFileDocument != DocumentService.CurrentCodeFileDocument && !DocumentService.ActiveCodeFileDocument.Run)
if (!RunActiveTabPage)
{
RunActiveTabPage = true;
return Run(DocumentService.ActiveCodeFileDocument, forDebugging, startWithGoto, needFirstBreakpoint);
}
MessageBox.Show(Form1StringResources.Get("RUN_DLL_WARNING_TEXT"), PascalABCCompiler.StringResources.Get("!WARNING"), MessageBoxButtons.OK, MessageBoxIcon.Warning);
RunActiveTabPage = false;
break;
case PascalABCCompiler.CompilerOptions.OutputType.PascalCompiledUnit:
if (DocumentService.ActiveCodeFileDocument != null && DocumentService.ActiveCodeFileDocument != DocumentService.CurrentCodeFileDocument && !DocumentService.ActiveCodeFileDocument.Run)
if (!RunActiveTabPage)
{
RunActiveTabPage = true;
return Run(DocumentService.ActiveCodeFileDocument, forDebugging, startWithGoto, needFirstBreakpoint);
}
RunActiveTabPage = false;
MessageBox.Show(Form1StringResources.Get("RUN_PCU_WARNING_TEXT"), PascalABCCompiler.StringResources.Get("!WARNING"), MessageBoxButtons.OK, MessageBoxIcon.Warning);
break;
case PascalABCCompiler.CompilerOptions.OutputType.ConsoleApplicaton:
case PascalABCCompiler.CompilerOptions.OutputType.WindowsApplication:
if (forDebugging)
{
BuildService.CompilerOptions.Debug = debug;
BuildService.CompilerOptions.ForDebugging = false;
if (startWithGoto)
{
DebuggerManager.ShowDebugTabs = true;
DebuggerManager.UpdateBreakpoints();
2023-06-05 21:55:35 +03:00
DebuggerManager.CurrentBreakpoint = DebuggerManager.AddBreakPoint(DocumentService.CurrentCodeFileDocument.FileName, DocumentService.CurrentCodeFileDocument.TextEditor.ActiveTextAreaControl.Caret.Line + 1, false);
DebuggerManager.AddGoToBreakPoint(DebuggerManager.CurrentBreakpoint);
}
else if (needFirstBreakpoint)
{
DebuggerManager.ShowDebugTabs = true;
DebuggerManager.UpdateBreakpoints();
if (Workbench.VisualEnvironmentCompiler.Compiler.VarBeginOffset != 0)
{
DebuggerManager.SetFirstBreakpoint(tabPage.FileName, Workbench.VisualEnvironmentCompiler.Compiler.VarBeginOffset);
DebuggerManager.AddGoToBreakPoint(tabPage.FileName, Workbench.VisualEnvironmentCompiler.Compiler.BeginOffset);
}
else
DebuggerManager.SetFirstBreakpoint(tabPage.FileName, Workbench.VisualEnvironmentCompiler.Compiler.BeginOffset);
}
else
{
DebuggerManager.UpdateBreakpoints();
DebuggerManager.ShowDebugTabs = false;
}
}
RunActiveTabPage = false;
try
{
RunTabsAdd(Workbench.VisualEnvironmentCompiler.Compiler.CompilerOptions.OutputFileName, tabPage);
RunnerManager.Run(Workbench.VisualEnvironmentCompiler.Compiler.CompilerOptions.OutputFileName,
Workbench.UserOptions.RedirectConsoleIO, ModeName, RunWithPause,
// Path.GetDirectoryName(Workbench.VisualEnvironmentCompiler.Compiler.CompilerOptions.OutputFileName), // SSM 21.05.19 - исправил. Теперь текущим является каталог, в котором расположен исходник.
// Если компилировать программы на сетевом диске, а exe создавать локально, то работает шустро
Workbench.VisualEnvironmentCompiler.Compiler.CompilerOptions.SourceFileDirectory,
RunArgumentsTable[tabPage.FileName.ToLower()], attachdbg, fictive_attach);
}
catch (System.Exception e)
{
// SSM 22/04/19 - исправляю вылет оболочки при отсутствии exe файла
// this.RunnerManager_Exited(OutputFileName); // - это всё равно не срабатывает. Кнопки оказываются в заблокированном состоянии
Console.WriteLine(e.Message+" "+e.StackTrace);
WorkbenchServiceFactory.OperationsService.AddTextToOutputWindowSync(OutputFileName, "Произошла непредвиденная ошибка. Вероятно, на диске отсутствует .exe-файл. Повторите запуск");
//throw;
return false;
}
if (!ProjectFactory.Instance.ProjectLoaded)
DocumentService.ActiveCodeFileDocument = tabPage;
if (forDebugging)
{
DebuggerOperationsService.AddDebugPage(tabPage);
}
WorkbenchStorage.SetCurrentTabPageIfWriteToOutputWindow = Workbench.UserOptions.RedirectConsoleIO;
//if (UserOptions1.ConsoleOutput)
//AddTextToOutputWindow("Ïðîãðàììà çàïóùåíà");
return true;
}
}
RunActiveTabPage = false;
return false;
}
}
public bool Run(ICodeFileDocument tabPage)
{
return Run(tabPage, false, false, false);
}
private bool __runInThreadDebug;
private void __runInThread(object state)
{
Run(__runInThreadDebug);
}
private void runInThread(bool debug)
{
__runInThreadDebug = debug;
if (!ThreadPool.QueueUserWorkItem(new WaitCallback(__runInThread)))
Run(debug);
}
public bool Stop() // Èíòåðåñíî, çà÷åì ñäåëàëè private
{
if (RunnerManager.IsRun(Workbench.CurrentEXEFileName))
{
RunnerManager.Stop(Workbench.CurrentEXEFileName);
return true;
}
return true;
}
void RunTabsAdd(string name, ICodeFileDocument p)
{
name = Tools.FileNameToLower(name);
if (RunTabs.ContainsKey(name))
RunTabs[name] = p;
else
RunTabs.Add(name, p);
}
public void SendInputTextToProcess()
{
ReadRequests.Remove(DocumentService.CurrentCodeFileDocument);
RunnerManager.WritelnStringToProcess(Workbench.CurrentEXEFileName, Workbench.OutputWindow.InputTextBoxText);
Workbench.OutputWindow.AppendTextToOutputBox(Environment.NewLine);
WorkbenchServiceFactory.OperationsService.SendNewLineToInputTextBox();
Workbench.OutputWindow.InputPanelVisible = false;
}
public bool IsRun()
{
return RunnerManager.IsRun();
}
public bool IsRun(string FileName)
{
return RunnerManager.IsRun(FileName);
}
public void Stop(string FileName)
{
RunnerManager.Stop(FileName);
}
public bool HasRunArgument(string FileName)
{
return RunArgumentsTable.ContainsKey(FileName);
}
public void AddRunArgument(string FileName, string argument)
{
RunArgumentsTable[FileName] = argument;
}
public ICodeFileDocument GetRunTab(string FileName)
{
return RunTabs[FileName];
}
public string GetRunArgument(string FileName)
{
return RunArgumentsTable[FileName];
}
public void KillAll()
{
TerminateAllPrograms = true;
RunnerManager.KillAll();
TerminateAllPrograms = false;
}
}
}