pascalabcnet/VisualPascalABCNETLinux/IB/CodeCompletion/CodeCompletionParserController.cs
AlexanderZemlyak 342375501b
New languages engine (#3120)
* Implement first version of languages interfaces and classes

ParsersController заменен на LanguageProvider.

* Update ParserTools.csproj

* Update RemoteCompiler.cs

* Update TestRunner

* Rename LanguageIntegrator project to Languages

* Update TestRunner

* Rename Parsers folder

* Rename PascalABCParser.dll to PascalABCLanguage.dll

* Reorganise LanguageIntegrator and rename DocTagsParser

* Update Release Generators

* Update language loading messages

* Update linux version

* Move BaseParser fields to ILanguage interface

* Revert "Update Release Generators"

This reverts commit 26a991c71b81e643d9fbd9a815ddca222768dda9.

* Revert "Rename PascalABCParser.dll to PascalABCLanguage.dll"

* Clean the mess in parser folders

* Organize namespaces properly

* Revert "Rename LanguageIntegrator project to Languages"

* Add new enclosing folders for standard languages

* Organize namespaces of LanguageIntegrator properly

* Rename StandardLanguages to Languages

* Comment the rest of Visual basic source code

* Update OutputPath in pascal parser project

* Move BaseParser methods to IParser

* Restore Pascal parser project initial structure

* Add PascalLanguage project

* Move SyntaxTreeConverters project to Languages\Pascal folder

* Rename SemanticRules in parser project

* Rename Errors1 to Errors in parser project

* Delete LambdaConverter dll from installer

* Update language integrator to load *Language.dll files

* Move lambda converter project to pascal lanuage dir

* Revert "Delete LambdaConverter dll from installer"

This reverts commit dd56f559ebe4f8c4c5c33752d44e6953001b96a5.

* Switch off VBNETParser building

* Delete syntax tree converters controller

* Delete lambda converter dll from repository

* Reorganize syntax tree to semantic tree conversion stage

* Add BaseLanguage class to make language initialization more neat

* Delete syntax tree post processors entity from ILanguage and refactor ABCStatistics calls

* Add new IDocParser interface for documentation comments parser

* Clean up folders

* Add helper data structures to reduce parameters amount in CompileInterface and CompileImplementation

* Add documentation to language classes

* Move Union struct in global namespace and project (ParserTools)

* Add more comments and a safe select language method

* Rename SemanticRules class

* Fix directives format null bug

* Add System.Linq ref to LanguageIntegrator

* Delete SyntaxToSemanticTreeConverter interface

* Add BaseSyntaxTreeConverter

* Call safe select language method in intellisence

* Delete source files providers from parsers

* Rename GetSyntaxTree method

* Change Prebuild tree to be virtual - not abstract

* Refresh documentation a bit

* Add temporary language check for ABCHealth button

* Add parser reference to parser tools

* Move current compilation unit assigning higher to avoid bug with unit check

* Delete null DirectiveInfo's and refactor directives' code

* Add a few more comments
2024-05-25 12:26:32 +03:00

293 lines
12 KiB
C#

// 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;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Gui.CompletionWindow;
using ICSharpCode.TextEditor.Document;
using Languages.Integration;
namespace VisualPascalABC
{
public delegate void ParseInformationUpdatedDelegate(object obj, string fileName);
public class CodeCompletionParserController : VisualPascalABCPlugins.ICodeCompletionService
{
public static Hashtable open_files = new Hashtable(StringComparer.OrdinalIgnoreCase);
public VisualEnvironmentCompiler visualEnvironmentCompiler;
private System.Threading.Thread th = null;
private CodeCompletionProvider ccp;
public event ParseInformationUpdatedDelegate ParseInformationUpdated;
public void StopParseThread()
{
try
{
if (th != null)
{
IsDone = true;
th.Abort(); // надо бы заменить на что то современное
th.Join();
}
}
catch
{
}
}
public CodeCompletionParserController()
{
this.th = new System.Threading.Thread(new System.Threading.ThreadStart(ParseInThread));
ccp = new CodeCompletionProvider();
}
public PascalABCCompiler.Parsers.ICodeCompletionDomConverter GetConverter(string fileName)
{
return CodeCompletion.CodeCompletionController.comp_modules[fileName] as PascalABCCompiler.Parsers.ICodeCompletionDomConverter;
}
public static string CurrentTwoLetterISO
{
get
{
return CodeCompletion.CodeCompletionController.currentLanguageISO;
}
set
{
CodeCompletion.CodeCompletionController.currentLanguageISO = value;
}
}
public void Init()
{
//LanguageProvider.Instance.SourceFilesProvider = visualEnvironmentCompiler.SourceFilesProvider;
CodeCompletion.CodeCompletionController.currentLanguageISO = PascalABCCompiler.StringResourcesLanguage.CurrentTwoLetterISO;
}
public void RenameFile(string OldFileName, string NewFileName)
{
if (string.Compare(OldFileName, NewFileName, true) != 0)
{
CodeCompletion.CodeCompletionController.comp_modules[NewFileName] = CodeCompletion.CodeCompletionController.comp_modules[OldFileName];
if (CodeCompletion.CodeCompletionController.comp_modules.ContainsKey(OldFileName))
CodeCompletion.CodeCompletionController.comp_modules.Remove(OldFileName);
open_files[NewFileName] = open_files[OldFileName];
if (open_files.ContainsKey(OldFileName))
open_files.Remove(OldFileName);
}
}
public void RegisterFileForParsing(string FileName)
{
open_files[FileName] = true;
CodeCompletion.CodeCompletionController.SetParser(System.IO.Path.GetExtension(FileName));
//ParseAllFiles();
}
public void CloseFile(string FileName)
{
if (CodeCompletion.CodeCompletionController.comp_modules[FileName] != null)
CodeCompletion.CodeCompletionController.comp_modules.Remove(FileName);
if (open_files[FileName] != null)
open_files.Remove(FileName);
}
public void SetAsChanged(string FileName)
{
if (FileName != null)
open_files[FileName] = true;
}
public void SetAllInProjectChanged()
{
try
{
Hashtable open_files2 = open_files.Clone() as Hashtable;
foreach (string s in open_files2.Keys)
{
if (ProjectFactory.Instance.CurrentProject.ContainsSourceFile(s))
open_files[s] = true;
}
}
catch (Exception e)
{
}
}
public void RunParseThread()
{
th = new System.Threading.Thread(InternalParsing);
th.Priority = System.Threading.ThreadPriority.BelowNormal;
th.IsBackground = true;
th.Start();
}
public void StopParsing()
{
try
{
VisualPABCSingleton.MainForm.StopTimer();
}
catch
{
}
}
private volatile bool IsDone = false;
private void InternalParsing()
{
while (!IsDone)
{
ParseInThread();
if (IsDone)
break;
System.Threading.Thread.Sleep(2000);
}
}
private long mem_delta = 0;
internal void ParseInThread()
{
try
{
Hashtable open_files2 = (Hashtable)open_files.Clone();
Hashtable recomp_files = new Hashtable(StringComparer.OrdinalIgnoreCase);
bool is_comp = false;
foreach (string FileName in open_files2.Keys)
{
//(ssyy) 18.05.08 Вставил проверку на null
object o = open_files[FileName];
if (o != null && (bool)o == true)
{
is_comp = true;
CodeCompletion.CodeCompletionController controller = new CodeCompletion.CodeCompletionController();
string text = visualEnvironmentCompiler.SourceFilesProvider(FileName, PascalABCCompiler.SourceFileOperation.GetText) as string;
if (string.IsNullOrEmpty(text))
text = "begin end.";
CodeCompletion.DomConverter tmp = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
long cur_mem = Environment.WorkingSet;
CodeCompletion.DomConverter dc = controller.Compile(FileName, text);
mem_delta += Environment.WorkingSet - cur_mem;
open_files[FileName] = false;
if (dc.is_compiled)
{
//CodeCompletion.CodeCompletionController.comp_modules.Remove(file_name);
if (tmp != null && tmp.visitor.entry_scope != null)
{
tmp.visitor.entry_scope.Clear();
if (tmp.visitor.cur_scope != null)
tmp.visitor.cur_scope.Clear();
}
CodeCompletion.CodeCompletionController.comp_modules[FileName] = dc;
recomp_files[FileName] = FileName;
open_files[FileName] = false;
if (ParseInformationUpdated != null)
ParseInformationUpdated(dc.visitor.entry_scope, FileName);
}
else if (CodeCompletion.CodeCompletionController.comp_modules[FileName] == null)
CodeCompletion.CodeCompletionController.comp_modules[FileName] = dc;
}
}
foreach (string FileName in open_files2.Keys)
{
CodeCompletion.DomConverter dc = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
CodeCompletion.SymScope ss = null;
if (dc != null)
{
if (dc.visitor.entry_scope != null) ss = dc.visitor.entry_scope;
else if (dc.visitor.impl_scope != null) ss = dc.visitor.impl_scope;
int j = 0;
while (j < 2)
{
if (j == 0)
{
ss = dc.visitor.entry_scope;
j++;
}
else
{
ss = dc.visitor.impl_scope;
j++;
}
if (ss != null)
{
for (int i = 0; i < ss.used_units.Count; i++)
{
string s = ss.used_units[i].file_name;
if (s != null && open_files2.ContainsKey(s) && recomp_files.ContainsKey(s))
{
is_comp = true;
CodeCompletion.CodeCompletionController controller = new CodeCompletion.CodeCompletionController();
string text = visualEnvironmentCompiler.SourceFilesProvider(FileName, PascalABCCompiler.SourceFileOperation.GetText) as string;
CodeCompletion.DomConverter tmp = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
long cur_mem = Environment.WorkingSet;
dc = controller.Compile(FileName, text);
mem_delta += Environment.WorkingSet - cur_mem;
open_files[FileName] = false;
CodeCompletion.CodeCompletionController.comp_modules[FileName] = dc;
if (dc.is_compiled)
{
/*if (tmp != null && tmp.stv.entry_scope != null)
{
tmp.stv.entry_scope.Clear();
if (tmp.stv.cur_scope != null) tmp.stv.cur_scope.Clear();
}*/
CodeCompletion.CodeCompletionController.comp_modules[FileName] = dc;
recomp_files[FileName] = FileName;
ss.used_units[i] = dc.visitor.entry_scope;
if (ParseInformationUpdated != null)
ParseInformationUpdated(dc.visitor.entry_scope, FileName);
}
else if (CodeCompletion.CodeCompletionController.comp_modules[FileName] == null)
CodeCompletion.CodeCompletionController.comp_modules[FileName] = dc;
}
}
}
}
}
}
if (is_comp && mem_delta > 20000000 /*&& mem_delta > 10000000*/)
//postavil delta dlja pamjati, posle kototoj delaetsja sborka musora
{
mem_delta = 0;
GC.Collect();
}
}
catch (Exception e)
{
}
}
public bool IsParsing()
{
return th != null && th.ThreadState == System.Threading.ThreadState.Running;
}
public void ParseAllFiles()
{
if (visualEnvironmentCompiler.UserOptions.AllowCodeCompletion)// && visualEnvironmentCompiler.compilerLoaded)
{
if (th.ThreadState != System.Threading.ThreadState.Running)
{
th = new System.Threading.Thread(new System.Threading.ThreadStart(this.ParseInThread));
th.Priority = System.Threading.ThreadPriority.BelowNormal;
//th.IsBackground = true;
th.Start();
}
//if (th == null)
// RunParseThread();
}
}
}
}