pascalabcnet/CodeCompletion/CodeCompletion.cs

400 lines
18 KiB
C#
Raw Normal View History

2015-06-01 22:15:17 +03:00
// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
2015-05-14 22:35:07 +03:00
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 ICSharpCode.SharpDevelop.Dom;
namespace CodeCompletion
{
public class CodeCompletionController
{
public static Controller ParsersController = new Controller();
string FileName;
string Text;
public Dictionary<PascalABCCompiler.SyntaxTree.syntax_tree_node, string> docs = new Dictionary<PascalABCCompiler.SyntaxTree.syntax_tree_node, string>();
static bool parsers_loaded=false;
public IParser Parser;
static CodeCompletionController()
{
//ParsersController.Reload();
}
public CodeCompletionController()
{
if (!parsers_loaded)
{
//ParsersController.Reload();
parsers_loaded = true;
}
//dconv = new DomConverter(this);
}
public static PascalABCCompiler.Compiler comp;// = new PascalABCCompiler.Compiler();
2016-05-06 14:56:19 +03:00
public static Hashtable StandartDirectories = new Hashtable();
2015-05-14 22:35:07 +03:00
public static Hashtable comp_modules = new Hashtable(StringComparer.OrdinalIgnoreCase);
public static Hashtable parsers = new Hashtable(StringComparer.OrdinalIgnoreCase);
public static string currentLanguageISO;
static string doctagsParserExtension = ".pasdt" + PascalABCCompiler.Parsers.Controller.HideParserExtensionPostfixChar;
//public static PascalABCCompiler.Parsers.IParser currentParser;
static string cur_ext = ".pas";
private static IParser currentParser;
public static void SetParser(string ext)
{
cur_ext = ext;
currentParser = null;
}
private static string get_doctagsParserExtension(string ext)
{
return ext + "dt" + PascalABCCompiler.Parsers.Controller.HideParserExtensionPostfixChar;
}
public static IParser CurrentParser
{
get
{
if (currentParser == null)
currentParser = parsers[cur_ext] as IParser;
return currentParser;
}
}
internal compilation_unit ParsersControllerGetCompilationUnit(string FileName, string Text, List<Error> ErrorsList, List<CompilerWarning> Warnings)
2015-05-14 22:35:07 +03:00
{
string ext = Path.GetExtension(FileName);
Parser = ParsersController.selectParser(ext.ToLower());
parsers[ext] = Parser;
compilation_unit cu = null;
cu = ParsersController.GetCompilationUnit(FileName, Text, ErrorsList, Warnings);
2015-05-14 22:35:07 +03:00
//ParsersController.GetExpression("test.pas", "a+b", new List<PascalABCCompiler.Errors.Error>());
return cu;
}
internal compilation_unit ParsersControllerGetCompilationUnitSpecial(string FileName, string Text, List<Error> ErrorsList, List<CompilerWarning> Warnings)
2015-05-14 22:35:07 +03:00
{
string ext = Path.GetExtension(FileName);
Parser = ParsersController.selectParser(ext.ToLower());
parsers[ext] = Parser;
compilation_unit cu = null;
cu = ParsersController.GetCompilationUnitSpecial(FileName, Text, ErrorsList, Warnings);
2015-05-14 22:35:07 +03:00
//ParsersController.GetExpression("test.pas","a+b",new List<PascalABCCompiler.Errors.Error>());
return cu;
}
public DomConverter Compile(string FileName, string Text)
{
this.Text = Text;
this.FileName = FileName;
List<PascalABCCompiler.Errors.Error> ErrorsList = new List<PascalABCCompiler.Errors.Error>();
List<CompilerWarning> Warnings = new List<CompilerWarning>();
2015-05-14 22:35:07 +03:00
PascalABCCompiler.SyntaxTree.compilation_unit cu = null;
string ext = Path.GetExtension(FileName);
try
{
cu = ParsersControllerGetCompilationUnit(FileName, Text, ErrorsList, Warnings);
2015-05-14 22:35:07 +03:00
ErrorsList.Clear();
PascalABCCompiler.SyntaxTree.documentation_comment_list dt = ParsersController.Compile(System.IO.Path.ChangeExtension(FileName, get_doctagsParserExtension(ext)), Text/*+")))));end."*/, ErrorsList, Warnings, PascalABCCompiler.Parsers.ParseMode.Normal) as PascalABCCompiler.SyntaxTree.documentation_comment_list;
2015-05-14 22:35:07 +03:00
PascalABCCompiler.DocumentationConstructor docconst = new PascalABCCompiler.DocumentationConstructor();
if (cu != null)
docs = docconst.Construct(cu, dt);
}
catch (Exception e)
{
2017-03-02 22:27:17 +03:00
#if DEBUG
File.AppendAllText("log.txt", e.Message + Environment.NewLine + e.StackTrace + Environment.NewLine);
#endif
2015-05-14 22:35:07 +03:00
}
DomConverter dconv = new DomConverter(this);
if (cu != null)
{
PascalABCCompiler.NetHelper.NetHelper.reset();
dconv.ConvertToDom(cu);
}
else
{
ErrorsList.Clear();
Warnings.Clear();
2015-05-14 22:35:07 +03:00
try
{
//cu = ParsersController.GetComilationUnit(FileName, Text+")))));end.",comp.CompilerOptions.ParserSearchPatchs,ErrorsList);
//cu = ParsersControllerGetComilationUnit(FileName, get_temp_text(Text), ErrorsList, true);
string tmp = ParsersHelper.GetModifiedProgramm(Text);
if (tmp != null)
{
cu = ParsersControllerGetCompilationUnitSpecial(FileName, tmp, ErrorsList, Warnings);
2015-05-14 22:35:07 +03:00
}
if (comp_modules[FileName] == null)
{
if (cu == null)
cu = get_fictive_unit(Text, FileName);
}
ErrorsList.Clear();
PascalABCCompiler.SyntaxTree.documentation_comment_list dt = ParsersController.Compile(System.IO.Path.ChangeExtension(FileName, get_doctagsParserExtension(ext)), Text + ")))));end.", ErrorsList, Warnings, PascalABCCompiler.Parsers.ParseMode.Normal) as PascalABCCompiler.SyntaxTree.documentation_comment_list;
2015-05-14 22:35:07 +03:00
PascalABCCompiler.DocumentationConstructor docconst = new PascalABCCompiler.DocumentationConstructor();
if (cu != null)
docs = docconst.Construct(cu, dt);
}
catch (Exception e)
{
2017-03-02 22:27:17 +03:00
#if DEBUG
File.AppendAllText("log.txt", e.Message + Environment.NewLine + e.StackTrace + Environment.NewLine);
#endif
2015-05-14 22:35:07 +03:00
}
if (cu != null)
{
PascalABCCompiler.NetHelper.NetHelper.reset();
dconv.ConvertToDom(cu);
}
}
if (docs != null) docs.Clear();
//if (dconv.is_compiled) comp_modules[FileName]=dconv;
return dconv;
//ConvertToDom(cu);
}
2016-05-26 14:16:32 +03:00
2015-05-14 22:35:07 +03:00
//vremenno, potom ubrat
private compilation_unit get_fictive_unit(string s, string FileName)
{
2016-05-26 14:16:32 +03:00
program_module prog = new program_module();
int line = 1;
int col = 1;
for (int i = 0; i < s.Length; i++)
if (s[i] == '\n')
{
line++;
col = 1;
}
else
{
col++;
}
prog.source_context = new SourceContext(1, 1, line + 3, 3);
prog.program_block = new block();
prog.file_name = FileName;
statement_list sl = new statement_list();
prog.program_block.program_code = sl;
prog.program_block.program_code.left_logical_bracket = new token_info("begin");
prog.program_block.program_code.left_logical_bracket.source_context = new SourceContext(1, 1, 1, 5);
prog.program_block.program_code.right_logical_bracket = new token_info("end");
prog.program_block.program_code.right_logical_bracket.source_context = new SourceContext(line + 3, 1, line + 3, 3);
sl.subnodes.Add(new empty_statement());
return prog;
2015-05-14 22:35:07 +03:00
}
public PascalABCCompiler.SyntaxTree.compilation_unit ParseOnlySyntaxTree(string FileName, string Text)
{
List<PascalABCCompiler.Errors.Error> ErrorsList = new List<PascalABCCompiler.Errors.Error>();
List<CompilerWarning> Warnings = new List<CompilerWarning>();
PascalABCCompiler.SyntaxTree.compilation_unit cu = ParsersControllerGetCompilationUnit(FileName, Text, ErrorsList, Warnings);
2015-05-14 22:35:07 +03:00
return cu;
}
public DomConverter CompileAllIfNeed(string FileName, string Text)
{
DomConverter dconv = (DomConverter)comp_modules[FileName];
if (dconv != null) return dconv;
this.Text = Text;
this.FileName = FileName;
string ext = Path.GetExtension(FileName);
List<PascalABCCompiler.Errors.Error> ErrorsList = new List<PascalABCCompiler.Errors.Error>();
List<CompilerWarning> Warnings = new List<CompilerWarning>();
PascalABCCompiler.SyntaxTree.compilation_unit cu = ParsersController.GetCompilationUnit(FileName, Text, ErrorsList, Warnings);
2015-05-14 22:35:07 +03:00
Parser = ParsersController.selectParser(Path.GetExtension(FileName).ToLower());
ErrorsList.Clear();
PascalABCCompiler.SyntaxTree.documentation_comment_list dt = ParsersController.Compile(System.IO.Path.ChangeExtension(FileName, get_doctagsParserExtension(ext)), Text, ErrorsList, Warnings, PascalABCCompiler.Parsers.ParseMode.Normal) as PascalABCCompiler.SyntaxTree.documentation_comment_list;
2015-05-14 22:35:07 +03:00
PascalABCCompiler.DocumentationConstructor docconst = new PascalABCCompiler.DocumentationConstructor();
if (cu != null)
docs = docconst.Construct(cu, dt);
dconv = new DomConverter(this);
if (CodeCompletionTools.XmlDoc.LookupLocalizedXmlDocForUnitWithSources(FileName, CodeCompletionController.currentLanguageISO) != null)
{
2016-05-06 14:56:19 +03:00
dconv.visitor.add_doc_from_text = false;
2015-05-14 22:35:07 +03:00
}
if (cu != null)
dconv.ConvertToDom(cu);
2016-05-06 14:56:19 +03:00
else
2015-05-14 22:35:07 +03:00
{
ErrorsList.Clear();
Warnings.Clear();
2015-05-14 22:35:07 +03:00
//cu = ParsersControllerGetComilationUnit(FileName, Text, ErrorsList, true);
if (comp_modules[FileName] == null)
{
string tmp = ParsersHelper.GetModifiedProgramm(Text);
if (tmp != null)
{
cu = ParsersControllerGetCompilationUnitSpecial(FileName, tmp, ErrorsList, Warnings);
2015-05-14 22:35:07 +03:00
ErrorsList.Clear();
}
if (cu == null)
cu = get_fictive_unit(Text, FileName);
}
ErrorsList.Clear();
Warnings.Clear();
dt = ParsersController.Compile(System.IO.Path.ChangeExtension(FileName, get_doctagsParserExtension(ext)), Text + ")))));end.", ErrorsList, Warnings, PascalABCCompiler.Parsers.ParseMode.Normal) as PascalABCCompiler.SyntaxTree.documentation_comment_list;
2015-05-14 22:35:07 +03:00
//PascalABCCompiler.DocumentationConstructor docconst = new PascalABCCompiler.DocumentationConstructor();
if (cu != null)
docs = docconst.Construct(cu, dt);
if (CodeCompletionTools.XmlDoc.LookupLocalizedXmlDocForUnitWithSources(FileName, CodeCompletionController.currentLanguageISO) != null)
{
2016-05-06 14:56:19 +03:00
dconv.visitor.add_doc_from_text = false;
2015-05-14 22:35:07 +03:00
}
if (cu != null)
{
dconv.ConvertToDom(cu);
}
}
//comp_modules[FileName] = dconv;
if (dconv.is_compiled) comp_modules[FileName] = dconv;
if (docs != null) docs.Clear();
//GC.Collect();
return dconv;
}
public DomConverter CompileAllIfNeed(string FileName, bool parse_only_interface=false)
{
this.FileName = FileName;
this.Text = comp.GetSourceFileText(FileName);
string ext = Path.GetExtension(FileName);
List<PascalABCCompiler.Errors.Error> ErrorsList = new List<PascalABCCompiler.Errors.Error>();
List<CompilerWarning> Warnings = new List<CompilerWarning>();
2015-05-14 22:35:07 +03:00
PascalABCCompiler.SyntaxTree.compilation_unit cu = null;
if (Text != null)
{
cu = ParsersController.GetCompilationUnit(FileName, Text, ErrorsList, Warnings);
2015-05-14 22:35:07 +03:00
}
Parser = ParsersController.selectParser(Path.GetExtension(FileName).ToLower());
ErrorsList.Clear();
Warnings.Clear();
PascalABCCompiler.SyntaxTree.documentation_comment_list dt = ParsersController.Compile(System.IO.Path.ChangeExtension(FileName, get_doctagsParserExtension(ext)), Text, ErrorsList, Warnings, PascalABCCompiler.Parsers.ParseMode.Normal) as PascalABCCompiler.SyntaxTree.documentation_comment_list;
2015-05-14 22:35:07 +03:00
PascalABCCompiler.DocumentationConstructor docconst = new PascalABCCompiler.DocumentationConstructor();
if (cu != null)
docs = docconst.Construct(cu, dt);
DomConverter dconv = new DomConverter(this);
2016-05-06 14:56:19 +03:00
dconv.visitor.parse_only_interface = parse_only_interface;
2015-05-14 22:35:07 +03:00
if (CodeCompletionTools.XmlDoc.LookupLocalizedXmlDocForUnitWithSources(FileName, CodeCompletionController.currentLanguageISO) != null)
{
2016-05-06 14:56:19 +03:00
dconv.visitor.add_doc_from_text = false;
2015-05-14 22:35:07 +03:00
}
if (cu != null)
dconv.ConvertToDom(cu);
else
{
ErrorsList.Clear();
Warnings.Clear();
2015-05-14 22:35:07 +03:00
//cu = ParsersControllerGetComilationUnit(FileName, Text, ErrorsList, true);
if (comp_modules[FileName] == null)
{
string tmp = ParsersHelper.GetModifiedProgramm(Text);
if (tmp != null)
{
cu = ParsersControllerGetCompilationUnitSpecial(FileName, tmp, ErrorsList, Warnings);
2015-05-14 22:35:07 +03:00
ErrorsList.Clear();
}
if (cu == null)
cu = get_fictive_unit(Text, FileName);
}
ErrorsList.Clear();
Warnings.Clear();
dt = ParsersController.Compile(System.IO.Path.ChangeExtension(FileName, get_doctagsParserExtension(ext)), Text, ErrorsList, Warnings, PascalABCCompiler.Parsers.ParseMode.Normal) as PascalABCCompiler.SyntaxTree.documentation_comment_list;
2015-05-14 22:35:07 +03:00
if (cu != null)
docs = docconst.Construct(cu, dt);
if (CodeCompletionTools.XmlDoc.LookupLocalizedXmlDocForUnitWithSources(FileName, CodeCompletionController.currentLanguageISO) != null)
{
2016-05-06 14:56:19 +03:00
dconv.visitor.add_doc_from_text = false;
2015-05-14 22:35:07 +03:00
}
if (cu != null)
{
dconv.ConvertToDom(cu);
}
}
if (dconv.is_compiled) comp_modules[FileName] = dconv;
if (docs != null) docs.Clear();
//comp_modules[FileName] = dconv;
// GC.Collect();
return dconv;
}
}
public class CodeCompletionNameHelper
{
public static readonly string system_unit_file_name = PascalABCCompiler.TreeConverter.compiler_string_consts.system_unit_file_name;
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 string[] GetKeywords()
{
if (CodeCompletionController.CurrentParser != null)
return CodeCompletionController.CurrentParser.LanguageInformation.Keywords;
return new string[0];
}
public string[] GetTypeKeywords()
{
if (CodeCompletionController.CurrentParser != null)
return CodeCompletionController.CurrentParser.LanguageInformation.TypeKeywords;
return new string[0];
}
const string LibSourceDirectoryIdent = "%LIBSOURCEDIRECTORY%";
public static string FindSourceFileName(string unit_name, params string[] ddirs)
{
List<string> Dirs = new List<string>();
Dirs.AddRange(ddirs);
Dirs.Add(CodeCompletionController.comp.CompilerOptions.SearchDirectory);
if (CodeCompletionController.StandartDirectories.ContainsKey(LibSourceDirectoryIdent))
Dirs.Add((string)CodeCompletionController.StandartDirectories[LibSourceDirectoryIdent]);
return CodeCompletionController.comp.FindSourceFileName(unit_name, Dirs.ToArray());
}
public static CodeCompletionNameHelper Helper
{
get
{
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.EndsWith("end."))
{
sb.AppendLine(src);
sb.AppendLine();
sb.Append("end.");
return sb.ToString();
}
return null;
}
}
}