// 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 PascalABCCompiler.SyntaxTree;
using PascalABCCompiler.Parsers;
using PascalABCCompiler.Errors;
using System.IO;
using Languages.Facade;
namespace CodeCompletion
{
public class CodeCompletionController
private static readonly LanguageProvider LanguageProvider = LanguageProvider.Instance;
public Dictionary<syntax_tree_node, string> docs = new Dictionary<syntax_tree_node, string>();
// static bool parsers_loaded=false;
public IParser Parser;
static CodeCompletionController()
//ParsersController.Reload();
}
public CodeCompletionController()
/*if (!parsers_loaded)
parsers_loaded = true;
}*/
//dconv = new DomConverter(this);
public static PascalABCCompiler.Compiler comp;// = new PascalABCCompiler.Compiler();
public static Dictionary<string, string> StandartDirectories = new Dictionary<string, string>();
public static Hashtable comp_modules = new Hashtable(StringComparer.OrdinalIgnoreCase);
// public static Hashtable parsers = new Hashtable(StringComparer.OrdinalIgnoreCase);
public static Dictionary<string, InterfaceUnitScope> pabcNamespaces = new Dictionary<string, InterfaceUnitScope>();
public static string currentLanguageISO;
// public static PascalABCCompiler.Parsers.IParser currentParser;
// static string cur_ext = ".pas";
private static ILanguage currentLanguage;
public static void SetLanguage(string fileName)
currentLanguage = LanguageProvider.SelectLanguageByExtensionSafe(fileName);
public void ResetNamespaces()
pabcNamespaces.Clear();
// нужно переделать на использование ILanguage EVA
public static IParser CurrentParser
get
return currentLanguage?.Parser;
public DomConverter Compile(string FileName, string Text)
List<Error> ErrorsList = new List<Error>();
List<CompilerWarning> Warnings = new List<CompilerWarning>();
compilation_unit cu = null;
ILanguage currentLanguage = LanguageProvider.SelectLanguageByExtension(FileName);
Parser = currentLanguage.Parser;
try
cu = Parser.GetCompilationUnit(FileName, Text, ErrorsList, Warnings, ParseMode.Normal, false);
ErrorsList.Clear();
if (currentLanguage.DocParser != null)
BuildDocs(Text, cu, currentLanguage.DocParser);
catch (Exception e)
#if DEBUG
File.AppendAllText("log.txt", e.Message + Environment.NewLine + e.StackTrace + Environment.NewLine);
#endif
TypeScope.instance_cache.Clear();
// очистка кэша и данных от старых компиляций, чтобы при новой компиляции не появились ссылки на старые данные
TypeTable.Clear();
DomConverter dconv = new DomConverter(this);
if (cu != null)
PascalABCCompiler.NetHelper.NetHelper.reset();
dconv.ConvertToDom(cu);
// Попытка поменять текст программы ниже сработает только для PascalABC.NET
else if (currentLanguage == LanguageProvider.MainLanguage)
Warnings.Clear();
string tmp = ParsersHelper.GetModifiedProgramm(Text);
if (tmp != null)
cu = Parser.GetCompilationUnit(FileName, Text, ErrorsList, Warnings, ParseMode.Special, false);
if (docs != null) docs.Clear();
//if (dconv.is_compiled) comp_modules[file_name]=dconv;
return dconv;
//ConvertToDom(cu);
private void BuildDocs(string Text, compilation_unit cu, IDocParser docParser)
documentation_comment_list dt = docParser.BuildTree(Text);
PascalABCCompiler.DocumentationConstructor docconst = new PascalABCCompiler.DocumentationConstructor();
docs = docconst.Construct(cu, dt);
public compilation_unit ParseOnlySyntaxTree(string FileName, string Text)
var currentLanguage = LanguageProvider.SelectLanguageByExtensionSafe(FileName);
if (currentLanguage == null)
return null;
var cu = currentLanguage.Parser.GetCompilationUnit(FileName, Text, new List<Error>(), new List<CompilerWarning>(), ParseMode.Normal, false);
return cu;
public DomConverter CompileAllIfNeed(string FileName, bool parse_only_interface=false)
string Text = comp.GetSourceFileText(FileName);
ILanguage currentLanguage = LanguageProvider.SelectLanguageByExtensionSafe(FileName);
if (Text != null)
cu = Parser.GetCompilationUnit(FileName, Text, ErrorsList, Warnings, ParseMode.Normal, true);
dconv.visitor.parse_only_interface = parse_only_interface;
if (CodeCompletionTools.XmlDoc.LookupLocalizedXmlDocForUnitWithSources(FileName, CodeCompletionController.currentLanguageISO) != null)
dconv.visitor.add_doc_from_text = false;
if (comp_modules[FileName] == null)
cu = Parser.GetCompilationUnit(FileName, Text, ErrorsList, Warnings, ParseMode.Special, true);
if (dconv.is_compiled) comp_modules[FileName] = dconv;
//comp_modules[file_name] = dconv;
// GC.Collect();
public class CodeCompletionNameHelper
public static readonly string system_unit_file_name = PascalABCCompiler.StringConstants.pascalSystemUnitName;
public static string system_unit_file_full_name;
private static CodeCompletionNameHelper helper;
private CodeCompletionNameHelper()
public PascalABCCompiler.Parsers.KeywordKind GetKeywordKind(string name)
if (CodeCompletionController.CurrentParser != null)
return CodeCompletionController.CurrentParser.LanguageInformation.GetKeywordKind(name);
return PascalABCCompiler.Parsers.KeywordKind.None;
public bool IsKeyword(string name)
return CodeCompletionController.CurrentParser.LanguageInformation.IsKeyword(name);
return false;
public List<string> GetKeywords()
return CodeCompletionController.CurrentParser.LanguageInformation.KeywordsStorage.KeywordsForIntellisenseList;
return new List<string>();
public List<string> GetTypeKeywords()
return CodeCompletionController.CurrentParser.LanguageInformation.KeywordsStorage.TypeKeywords;
const string LibSourceDirectoryIdent = "%LIBSOURCEDIRECTORY%";
public static string FindSourceFileName(string unit_name, out int found_dir_ind, bool caseSensitiveSearch, params string[] ddirs)
// TODO: check error in older version
List<string> Dirs = new List<string>();
Dirs.AddRange(ddirs);
if (CodeCompletionController.comp != null)
Dirs.AddRange(CodeCompletionController.comp.CompilerOptions.SearchDirectories);
// Надо как-то проверять, что мы не в инсталированной версии EVA
if (CodeCompletionController.StandartDirectories.ContainsKey(LibSourceDirectoryIdent) && Directory.Exists(CodeCompletionController.StandartDirectories[LibSourceDirectoryIdent]))
Dirs.Add(CodeCompletionController.StandartDirectories[LibSourceDirectoryIdent]);
return CodeCompletionController.comp.FindSourceFileNameInDirs(unit_name, out found_dir_ind, caseSensitiveSearch, Dirs.ToArray());
public static CodeCompletionNameHelper Helper
if (helper == null) helper = new CodeCompletionNameHelper();
return helper;
public class ParsersHelper
string src;
static StringBuilder sb = new StringBuilder();
public static string GetModifiedProgramm(string src)
sb.Remove(0,sb.Length);
if (!src.TrimEnd().EndsWith("end."))
sb.AppendLine(src);
sb.AppendLine();
sb.Append("end.");
return sb.ToString();