pascalabcnet/VisualPascalABCNET/IB/CodeCompletion/CodeCompletionParserController.cs
AlexanderZemlyak 0626885b5f
Рефакторинг в Intellisense (#3328)
* Migrate from HashTable to Dictionary<string, string> (StandartDirectories variable)

* Add check to register files for parsing only if they have supported extension

* Delete legacy code in CodeCompletion.cs

* Delete unnecessary fields in CodeCompletionController

* Refactor compiling dependencies code in DomSyntaxTreeVisitor

* Fix AddStandardNetNamespacesToUserScope check

* Comment out uses *some type* support in Intellisense

* Delete unused SemanticOptions in DomSyntaxTreeVisitor

* Comment out unused NamespaceTypeScope
2025-10-01 11:47:05 +03:00

277 lines
12 KiB
C#
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.

// 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.Linq;
namespace VisualPascalABC
{
public delegate void ParseInformationUpdatedDelegate(object obj, string fileName);
public class CodeCompletionParserController : VisualPascalABCPlugins.ICodeCompletionService
{
public static Dictionary<string, bool> filesToParse = new Dictionary<string, bool>(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)
{
th.Abort();
th.Join(); // Это обязательно. По большому счету вообще Abort надо заменить на современное завершение потоков
}
}
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);
filesToParse[NewFileName] = filesToParse[OldFileName];
if (filesToParse.ContainsKey(OldFileName))
filesToParse.Remove(OldFileName);
}
}
public void RegisterFileForParsing(string FileName)
{
if (Languages.Facade.LanguageProvider.Instance.HasLanguageForExtension(FileName))
{
filesToParse[FileName] = true;
CodeCompletion.CodeCompletionController.SetLanguage(FileName);
}
}
public void CloseFile(string FileName)
{
if (CodeCompletion.CodeCompletionController.comp_modules[FileName] != null)
CodeCompletion.CodeCompletionController.comp_modules.Remove(FileName);
filesToParse.Remove(FileName);
}
public void SetAsChanged(string FileName)
{
if (FileName != null && filesToParse.ContainsKey(FileName))
filesToParse[FileName] = true;
}
public void SetAllInProjectChanged()
{
try
{
foreach (string s in filesToParse.Keys.ToArray())
{
if (ProjectFactory.Instance.CurrentProject.ContainsSourceFile(s))
filesToParse[s] = true;
}
}
catch (Exception) { }
}
/// <summary>
/// Запуск потока с Intellisence
/// </summary>
public void SwitchOnIntellisence()
{
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 void InternalParsing()
{
while (true)
{
ParseInThread();
System.Threading.Thread.Sleep(2000);
}
}
private long mem_delta = 0;
internal void ParseInThread()
{
try
{
Dictionary<string, string> recomp_files = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
bool is_comp = false;
foreach (string FileName in filesToParse.Keys.ToArray()) // копирование ключей обязательно, иначе будет InvalidOperationException EVA
{
if (filesToParse[FileName])
{
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;
filesToParse[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;
filesToParse[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 filesToParse.Keys.ToArray()) // копирование ключей обязательно, иначе будет InvalidOperationException EVA
{
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 && filesToParse.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;
filesToParse[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) { }
}
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();
}
}
}
}