pascalabcnet/VisualPascalABCNET/IB/CodeCompletion/CodeCompletionParserController.cs
AlexanderZemlyak efb4a4338f
New checks for directives added (#3099)
* Extract base classes from ParserTools (local) and GPPGParserHelper

* Fix string resources error

* Extract base class for unexpected token error

* Update ParserTools project file

* Add comments for compiler directives usages in compiler

* Add directives checks

* Move string constants to new project

* Implement scalable directives checks

* Remove known directives from compiler

* Fix PABCSystem namespace error

* Allow region and endregion with no params

* Allow parameters to endif directive

* Delete directive parameters extension checks

* Replace error with warning for uknown directive case

* Fix generate native code (semantic rule) assigning

* Improve error messages for directives

* Rename RunParseThread to SwitchOnIntellisence

Для отладки может требоваться отключение Intellisence на уровне кода. Для понятности метод назван SwitchOnIntellisence.

* Resolve merge conflicts

* Add new compiler errors for unsupported target framework and output file type

* Add documentation to directives checks

* Fix directives check loop
2024-05-04 20:21:50 +03:00

284 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;
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)
{
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()
{
CodeCompletion.CodeCompletionController.ParsersController.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)
{
}
}
/// <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
{
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();
}
}
}
}