Refactor intellisense (#3213)
* Refactor keywords managing to avoid repeating them twice * Fix build error * Fix string comparisons and null reference exception * Manage references in PascalABCLanguageInfo project * Fix inaccuracy in BaseKeywords.cs * Move ValidDirectives field to ILanguageInformation * Basic refactoring of GetPopupHintText + delete ampersend inserting * Delete other cases of ampersend inserting * Add check that we parsing PascalABC.NET in GetPopupHintText Временное решение, нужно будет вынести вторую попытку в интерфейс парсера. * Refactor CodeCompletionProvider (first iteration) * Extract shift space actions in separate class * Replace dollar service character in CodeCompletion by separate boolean (ctrlSpaceAfterDot)) * Refactor GetCompletionDataByFirst method * Fix GetCompletionDataByFirst behaviour when getting symInfos after uses keyword * Another iteration of refactoring in CodeCompletionProvider + comments * Update intellisense documentation * Fix build error * Fix encoding * Squashed commit of the following: commit7751fe7e75Author: samuraiGH <87191377+samuraiGH@users.noreply.github.com> Date: Sun Mar 16 13:28:03 2025 +0300 generating language res file at build time (#3252) commitd1fce63d69Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Mar 4 08:38:09 2025 +0300 Сборка после pr SDK commitd491e88aa7Author: samuraiGH <87191377+samuraiGH@users.noreply.github.com> Date: Mon Mar 3 20:34:51 2025 +0300 migration to new build system (#3241) * converting project files into sdk style * new build commands * adding new dll into nsis * removing unused .cs files commit1fd348ec3cAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sun Feb 23 20:49:26 2025 +0300 NSIS New 3.10 Ярлык в меню Пуск у всех пользователей commit80b7182dc1Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Wed Feb 19 11:50:00 2025 +0300 _ in names commita2b078960bAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Wed Feb 19 10:52:25 2025 +0300 cnfc2 commit58f26d469dAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Feb 18 22:28:13 2025 +0300 перекомпиляция 3.10.3.3611 commitb78a72977fAuthor: nevermind322 <81963698+nevermind322@users.noreply.github.com> Date: Tue Feb 18 22:02:19 2025 +0300 fix build on mono (#3249) * fix build on mono * remove local func * fix again commitc3557e388cAuthor: Nikolay Kuznetsov <adasoft@gmail.com> Date: Sat Feb 15 20:32:46 2025 +0300 Update GraphABC.pas (#3244) 1. Быстрая реализация функции FloodFill Для этого добавлена процедура BitmapFloodFill, которая вызывается из метода Picture.FloodFill и процедуры FloodFill 2.Добавлена поддержка LockDrawing/UnlockDrawing в процедуру FloodFill commit9dbac389e1Author: AlexanderZemlyak <92867056+AlexanderZemlyak@users.noreply.github.com> Date: Wed Feb 12 13:57:14 2025 +0300 Add missing projects to pabcnetc.sln (#3247) commit41dfb6f187Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Fri Feb 7 21:41:01 2025 +0300 [] - преобразование во все контейнеры GraphABCHelper - теперь ABCObjects работает под Линукс School исправлен согласно последним веяниям [] commit79bbbd10ffAuthor: samuraiGH <87191377+samuraiGH@users.noreply.github.com> Date: Wed Jan 29 20:18:37 2025 +0300 removing files for support fx4.0 (#3240) commit88d5c409ebAuthor: samuraiGH <87191377+samuraiGH@users.noreply.github.com> Date: Tue Jan 28 20:41:55 2025 +0300 Рефакторинг PascalABCNET.xshd (#3237) * refactoring PascalABCNET.xshd * removing extra characters commit8fbd7fdfc3Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sun Jan 26 23:42:48 2025 +0300 3.10.3 faststrings EmptyCollection и преобразование ее в List, Dictionary t: (real,real) := (1,2) commitbba132bd5dAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Wed Jan 22 09:14:44 2025 +0300 Поправил справку по функции commit1bd21857ccAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Wed Jan 8 18:46:51 2025 +0300 Teacher Control Plugin - возможность задать server.dat commit0848a1b796Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sat Jan 4 22:54:38 2025 +0300 Исправление автоформатирования [] commitd45b782a7bAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sat Jan 4 18:45:07 2025 +0300 Rename PABCSistem in test suite commitc2347e604bAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sat Jan 4 14:44:51 2025 +0300 Примеры - устранил неточности LightPT - имя сервера вынес в публичную секцию commitb68b8da970Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Dec 17 15:52:18 2024 +0300 Примеры Coords1.pas Coords2.pas.pas commit8a9788e6f9Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Dec 17 15:06:57 2024 +0300 Перенес проверку set array на уровень парсера Немного поправил Intellisense по наведению для NewSet По точке там что то другое работает commit874ddebad3Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sat Dec 14 21:00:38 2024 +0300 Поправил грамматику [] Теперь нельзя в режиме ## использовать атрибуты Зато можно [1,2,3].Print commit080fb487e1Merge:a53dcd9eda484b0e82Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sat Dec 14 15:25:24 2024 +0300 Merge branch 'master' of https://github.com/pascalabcnet/pascalabcnet commita53dcd9ed2Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sat Dec 14 15:25:16 2024 +0300 SF Prm Cmb для строк commita484b0e82dAuthor: Sun Serega <sunserega2@gmail.com> Date: Thu Dec 12 13:49:17 2024 +0200 fix (#3231) commit6ef11f249cAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Dec 10 11:05:45 2024 +0300 3.10.2 commitdb9679d89fAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Dec 10 10:59:20 2024 +0300 Закончил превращение синтаксиса [] по умолчанию в массивы commit45fdde24b4Author: Ivan Bondarev <ibond84@googlemail.com> Date: Sun Dec 8 18:08:00 2024 +0100 #3229 commit494b47624dMerge:5875b99297906d73daAuthor: Ivan Bondarev <ibond84@googlemail.com> Date: Sun Dec 8 10:42:07 2024 +0100 Merge branch 'master' of https://github.com/pascalabcnet/pascalabcnet commit5875b99296Author: Ivan Bondarev <ibond84@googlemail.com> Date: Sun Dec 8 10:41:53 2024 +0100 platformtarget native - .NET 9.0 commit7906d73da3Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Dec 3 14:25:37 2024 +0300 Небольшие изменения в реализации операций с множествами commit087591c7b6Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Wed Nov 27 11:37:07 2024 +0300 3.10.1 Coords - доработки Distance, Middle, DrawText с фоном и рамкой. Глобальные переменные настройки commitd268d4f83bAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Thu Nov 21 22:24:07 2024 +0300 NSToBytes переделал с исключением commit2bacdc8c28Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Wed Nov 20 13:20:33 2024 +0300 Комментарии к NewSet commite917ac8ecaAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Wed Nov 20 12:42:15 2024 +0300 TypeName для set commit206289c6a7Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Nov 19 20:23:03 2024 +0300 Везде заменил _hs на hs в NewSet Убрал вызовы методов расширений NewSet в PABCSystem.pas Убрал var в operator + commitd8262078f6Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Nov 19 13:56:47 2024 +0300 Исправление мелких ошибок NewSet Все тесты проходят. Проблема, которая остаётся - в режиме ускорения такие программы падают: begin var s: set of byte; Print(s = [1]); end. Причина - из dll не вызывается конструктор записи без параметров, хотя он определён. В C# вообще у записей не может быть конструктора по умолчанию - наверное потому. Но для NewSet надо бы сделать исключение commitf8819665baAuthor: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sat Nov 16 10:56:11 2024 +0300 NS2 commit591d9ebe60Author: Ivan Bondarev <ibond84@googlemail.com> Date: Wed Nov 13 21:34:10 2024 +0100 fix commitc6505634f4Author: Ivan Bondarev <ibond84@googlemail.com> Date: Wed Nov 13 21:12:33 2024 +0100 fix commita6564df23cAuthor: Ivan Bondarev <ibond84@googlemail.com> Date: Wed Nov 13 20:52:29 2024 +0100 fix in new sets commit03be5bd931Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Wed Nov 13 22:13:41 2024 +0300 Переставил operator:= в NewSet commit96c68f1666Author: Ivan Bondarev <ibond84@googlemail.com> Date: Tue Nov 12 21:38:07 2024 +0100 #3223 commit82776f3c77Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sat Nov 9 12:18:19 2024 +0300 NewSet - много мелких исправлений. Все тесты проходят кроме Tests 5 - видимо с pabcrtl.dll * Update comments in PascalABCLanguageInformation
This commit is contained in:
parent
cc7d4472c6
commit
69149f8c44
|
|
@ -61,11 +61,7 @@ namespace CodeCompletion
|
|||
pabcNamespaces.Clear();
|
||||
}
|
||||
|
||||
private static string get_doctagsParserExtension(string ext)
|
||||
{
|
||||
return ext + "dt";
|
||||
}
|
||||
|
||||
// нужно переделать на использование ILanguage EVA
|
||||
public static IParser CurrentParser
|
||||
{
|
||||
get
|
||||
|
|
@ -376,18 +372,18 @@ namespace CodeCompletion
|
|||
return false;
|
||||
}
|
||||
|
||||
public string[] GetKeywords()
|
||||
public List<string> GetKeywords()
|
||||
{
|
||||
if (CodeCompletionController.CurrentParser != null)
|
||||
return CodeCompletionController.CurrentParser.LanguageInformation.Keywords;
|
||||
return new string[0];
|
||||
return CodeCompletionController.CurrentParser.LanguageInformation.KeywordsStorage.Keywords;
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
public string[] GetTypeKeywords()
|
||||
public List<string> GetTypeKeywords()
|
||||
{
|
||||
if (CodeCompletionController.CurrentParser != null)
|
||||
return CodeCompletionController.CurrentParser.LanguageInformation.TypeKeywords;
|
||||
return new string[0];
|
||||
return CodeCompletionController.CurrentParser.LanguageInformation.KeywordsStorage.TypeKeywords;
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
const string LibSourceDirectoryIdent = "%LIBSOURCEDIRECTORY%";
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ namespace CodeCompletion
|
|||
//TreeConverterSymbolTable tcst;
|
||||
public CodeCompletionController controller;
|
||||
public bool is_compiled = false;
|
||||
|
||||
// TODO: Требуется адаптировать к многоязычности EVA
|
||||
public static SymInfo[] standard_units;
|
||||
private Hashtable cur_used_assemblies;
|
||||
public CompilationUnit unit;
|
||||
|
|
|
|||
|
|
@ -17,14 +17,16 @@ namespace Languages.Facade
|
|||
/// <summary>
|
||||
/// Все параметры должны быть не null (и не пустым массивом), кроме IDocParser в случае, если он не требуется
|
||||
/// </summary>
|
||||
public BaseLanguage(string name, string version, string copyright, IParser parser, IDocParser docParser,
|
||||
public BaseLanguage(string name, string version, string copyright, ILanguageInformation languageInformation, IParser parser, IDocParser docParser,
|
||||
List<ISyntaxTreeConverter> syntaxTreeConverters, syntax_tree_visitor syntaxTreeToSemanticTreeConverter,
|
||||
string[] filesExtensions, bool caseSensitive, string[] systemUnitNames)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Version = version;
|
||||
this.Copyright = copyright;
|
||||
this.LanguageInformation = languageInformation;
|
||||
this.Parser = parser;
|
||||
this.Parser.LanguageInformation = languageInformation;
|
||||
this.DocParser = docParser;
|
||||
this.SyntaxTreeConverters = syntaxTreeConverters;
|
||||
this.SyntaxTreeToSemanticTreeConverter = syntaxTreeToSemanticTreeConverter;
|
||||
|
|
@ -39,6 +41,8 @@ namespace Languages.Facade
|
|||
|
||||
public virtual string Copyright { get; protected set; }
|
||||
|
||||
public virtual ILanguageInformation LanguageInformation { get; }
|
||||
|
||||
public virtual IParser Parser { get; protected set; }
|
||||
|
||||
public virtual IDocParser DocParser { get; protected set; }
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ namespace Languages.Facade
|
|||
/// </summary>
|
||||
string Copyright { get; }
|
||||
|
||||
ILanguageInformation LanguageInformation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Основной парсер языка
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -17,20 +17,7 @@ namespace PascalABCCompiler.Parsers
|
|||
|
||||
public Func<bool> CheckIfParsingUnit { get; set; }
|
||||
|
||||
public Dictionary<string, ParserTools.Directives.DirectiveInfo> ValidDirectives { get; protected set; }
|
||||
|
||||
private ILanguageInformation languageInformation;
|
||||
public virtual ILanguageInformation LanguageInformation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (languageInformation == null)
|
||||
languageInformation = new DefaultLanguageInformation(this);
|
||||
return languageInformation;
|
||||
}
|
||||
}
|
||||
|
||||
public BaseKeywords Keywords { get; protected set; }
|
||||
public ILanguageInformation LanguageInformation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Возвращеает синтаксическое дерево модуля
|
||||
|
|
|
|||
|
|
@ -129,14 +129,17 @@ namespace PascalABCCompiler.Parsers
|
|||
//char GetParameterDelimiter();
|
||||
string GetCompiledTypeRepresentation(Type t, System.Reflection.MemberInfo mi, ref int line, ref int col);
|
||||
bool IsKeyword(string value);
|
||||
string[] Keywords
|
||||
{
|
||||
get;
|
||||
}
|
||||
string[] TypeKeywords
|
||||
|
||||
BaseKeywords KeywordsStorage
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Данные о всех поддерживаемых директивах компилятора
|
||||
/// </summary>
|
||||
Dictionary<string, ParserTools.Directives.DirectiveInfo> ValidDirectives { get; }
|
||||
|
||||
string SystemUnitName
|
||||
{
|
||||
get;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||||
// 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.Collections.Generic;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
|
@ -20,24 +20,11 @@ namespace PascalABCCompiler.Parsers
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback äëÿ ïðîâåðêè, ïàðñèì ëè ìû ñåé÷àñ ìîäóëü èëè íåò (äëÿ ÿçûêîâ áåç êëþ÷åâûõ ñëîâ ó ìîäóëÿ)
|
||||
/// Callback для проверки, парсим ли мы сейчас модуль или нет (для языков без ключевых слов у модуля)
|
||||
/// </summary>
|
||||
Func<bool> CheckIfParsingUnit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Äàííûå î âñåõ ïîääåðæèâàåìûõ äèðåêòèâàõ êîìïèëÿòîðà
|
||||
/// </summary>
|
||||
Dictionary<string, ParserTools.Directives.DirectiveInfo> ValidDirectives { get; }
|
||||
|
||||
ILanguageInformation LanguageInformation
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Êëàññ, îòâå÷àùèé çà õðàíåíèå è îáðàáîòêó êëþ÷åâûõ ñëîâ ÿçûêà
|
||||
/// </summary>
|
||||
BaseKeywords Keywords { get; }
|
||||
ILanguageInformation LanguageInformation { get; set; }
|
||||
|
||||
compilation_unit GetCompilationUnit(string FileName, string Text, List<Error> Errors, List<CompilerWarning> Warnings, ParseMode parseMode, List<string> DefinesList = null);
|
||||
|
||||
|
|
@ -50,7 +37,6 @@ namespace PascalABCCompiler.Parsers
|
|||
expression GetTypeAsExpression(string FileName, string Text, List<Error> Errors, List<CompilerWarning> Warnings);
|
||||
|
||||
void Reset();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,13 @@ namespace PascalABCCompiler.Parsers
|
|||
/// <summary>
|
||||
/// Соотвествие ключевых слов токенам
|
||||
/// </summary>
|
||||
protected abstract Dictionary<string, int> KeywordsToTokens { get; set; }
|
||||
public Dictionary<string, int> KeywordsToTokens { get; set; }
|
||||
|
||||
public Dictionary<string, KeywordKind> KeywordKinds { get; set; }
|
||||
|
||||
public List<string> Keywords { get; set; } = new List<string>();
|
||||
|
||||
public List<string> TypeKeywords { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Словарь соответствий ключевых слов их эквивалентам (задается пользователем в специальном файле)
|
||||
|
|
@ -43,7 +49,7 @@ namespace PascalABCCompiler.Parsers
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает само эквивалент ключевого слова, либо его само, если эквивалента нет
|
||||
/// Возвращает эквивалент ключевого слова, либо его самого, если эквивалента нет
|
||||
/// </summary>
|
||||
public string ConvertKeyword(string keyword)
|
||||
{
|
||||
|
|
@ -53,9 +59,13 @@ namespace PascalABCCompiler.Parsers
|
|||
return keymap[keyword];
|
||||
}
|
||||
|
||||
public BaseKeywords()
|
||||
public BaseKeywords(bool caseSensitive)
|
||||
{
|
||||
ReloadKeyMap();
|
||||
|
||||
KeywordsToTokens = new Dictionary<string, int>(caseSensitive ? StringComparer.CurrentCulture : StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
KeywordKinds = new Dictionary<string, KeywordKind>(caseSensitive ? StringComparer.CurrentCulture : StringComparer.CurrentCultureIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -73,5 +83,21 @@ namespace PascalABCCompiler.Parsers
|
|||
else
|
||||
return GetIdToken();
|
||||
}
|
||||
|
||||
public void CreateNewKeyword(string name, Enum token, KeywordKind kind = KeywordKind.None, bool isTypeKeyword = false)
|
||||
{
|
||||
name = ConvertKeyword(name);
|
||||
|
||||
if (kind != KeywordKind.None)
|
||||
KeywordKinds[name] = kind;
|
||||
|
||||
Keywords.Add(name);
|
||||
KeywordsToTokens[name] = (int)(object)token;
|
||||
|
||||
if (isTypeKeyword)
|
||||
TypeKeywords.Add(name);
|
||||
|
||||
// return new Keyword(name, token, kind, isTypeKeyword);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,33 +55,23 @@ namespace PascalABCCompiler.Parsers
|
|||
CommonExpressionKeyword
|
||||
}
|
||||
|
||||
/*public class Keyword
|
||||
/*public struct Keyword
|
||||
{
|
||||
string _name;
|
||||
KeywordKind _kind = KeywordKind.None;
|
||||
public string Name
|
||||
public string Name { get; set; }
|
||||
public KeywordKind Kind { get; set; }
|
||||
|
||||
public bool IsTypeKeyword { get; set; }
|
||||
|
||||
public System.Enum Token { get; set; }
|
||||
|
||||
public Keyword(string name, System.Enum token, KeywordKind kind = KeywordKind.None, bool isTypeKeyword = false)
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
KeywordKind Kind
|
||||
{
|
||||
get
|
||||
{
|
||||
return _kind;
|
||||
}
|
||||
}
|
||||
public Keyword(string name, KeywordKind kind)
|
||||
{
|
||||
_name = name;
|
||||
_kind = kind;
|
||||
}
|
||||
public Keyword(string name)
|
||||
{
|
||||
_name = name;
|
||||
Name = name;
|
||||
Token = token;
|
||||
Kind = kind;
|
||||
IsTypeKeyword = isTypeKeyword;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
|
|
|
|||
|
|
@ -1,126 +1,120 @@
|
|||
// 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;
|
||||
using PascalABCCompiler.Parsers;
|
||||
|
||||
namespace Languages.Pascal.Frontend.Core
|
||||
{
|
||||
|
||||
public class PascalABCKeywords : PascalABCCompiler.Parsers.BaseKeywords
|
||||
public class PascalABCKeywords : BaseKeywords
|
||||
{
|
||||
|
||||
protected override string FileName => "keywordsmap.pabc";
|
||||
|
||||
protected override Dictionary<string, int> KeywordsToTokens { get; set; }
|
||||
|
||||
public PascalABCKeywords() : base()
|
||||
public PascalABCKeywords() : base(false)
|
||||
{
|
||||
KeywordsToTokens = new Dictionary<string, int>
|
||||
{
|
||||
["or"] = (int)Tokens.tkOr,
|
||||
["xor"] = (int)Tokens.tkXor,
|
||||
["and"] = (int)Tokens.tkAnd,
|
||||
["div"] = (int)Tokens.tkDiv,
|
||||
["mod"] = (int)Tokens.tkMod,
|
||||
["shl"] = (int)Tokens.tkShl,
|
||||
["shr"] = (int)Tokens.tkShr,
|
||||
["not"] = (int)Tokens.tkNot,
|
||||
["as"] = (int)Tokens.tkAs,
|
||||
["in"] = (int)Tokens.tkIn,
|
||||
["is"] = (int)Tokens.tkIs,
|
||||
["implicit"] = (int)Tokens.tkImplicit,
|
||||
["explicit"] = (int)Tokens.tkExplicit,
|
||||
["sizeof"] = (int)Tokens.tkSizeOf,
|
||||
["typeof"] = (int)Tokens.tkTypeOf,
|
||||
["where"] = (int)Tokens.tkWhere,
|
||||
["array"] = (int)Tokens.tkArray,
|
||||
["begin"] = (int)Tokens.tkBegin,
|
||||
["case"] = (int)Tokens.tkCase,
|
||||
["class"] = (int)Tokens.tkClass,
|
||||
["const"] = (int)Tokens.tkConst,
|
||||
["constructor"] = (int)Tokens.tkConstructor,
|
||||
["default"] = (int)Tokens.tkDefault,
|
||||
["destructor"] = (int)Tokens.tkDestructor,
|
||||
["downto"] = (int)Tokens.tkDownto,
|
||||
["do"] = (int)Tokens.tkDo,
|
||||
["else"] = (int)Tokens.tkElse,
|
||||
["end"] = (int)Tokens.tkEnd,
|
||||
["event"] = (int)Tokens.tkEvent,
|
||||
["except"] = (int)Tokens.tkExcept,
|
||||
["exports"] = (int)Tokens.tkExports,
|
||||
["file"] = (int)Tokens.tkFile,
|
||||
["finalization"] = (int)Tokens.tkFinalization,
|
||||
["finally"] = (int)Tokens.tkFinally,
|
||||
["for"] = (int)Tokens.tkFor,
|
||||
["foreach"] = (int)Tokens.tkForeach,
|
||||
["function"] = (int)Tokens.tkFunction,
|
||||
["goto"] = (int)Tokens.tkGoto,
|
||||
["if"] = (int)Tokens.tkIf,
|
||||
["implementation"] = (int)Tokens.tkImplementation,
|
||||
["inherited"] = (int)Tokens.tkInherited,
|
||||
["initialization"] = (int)Tokens.tkInitialization,
|
||||
["interface"] = (int)Tokens.tkInterface,
|
||||
["label"] = (int)Tokens.tkLabel,
|
||||
["lock"] = (int)Tokens.tkLock,
|
||||
["loop"] = (int)Tokens.tkLoop,
|
||||
["nil"] = (int)Tokens.tkNil,
|
||||
["procedure"] = (int)Tokens.tkProcedure,
|
||||
["of"] = (int)Tokens.tkOf,
|
||||
["operator"] = (int)Tokens.tkOperator,
|
||||
["property"] = (int)Tokens.tkProperty,
|
||||
["raise"] = (int)Tokens.tkRaise,
|
||||
["record"] = (int)Tokens.tkRecord,
|
||||
["repeat"] = (int)Tokens.tkRepeat,
|
||||
["set"] = (int)Tokens.tkSet,
|
||||
["try"] = (int)Tokens.tkTry,
|
||||
["type"] = (int)Tokens.tkType,
|
||||
["then"] = (int)Tokens.tkThen,
|
||||
["to"] = (int)Tokens.tkTo,
|
||||
["until"] = (int)Tokens.tkUntil,
|
||||
["uses"] = (int)Tokens.tkUses,
|
||||
["var"] = (int)Tokens.tkVar,
|
||||
["while"] = (int)Tokens.tkWhile,
|
||||
["with"] = (int)Tokens.tkWith,
|
||||
["program"] = (int)Tokens.tkProgram,
|
||||
["template"] = (int)Tokens.tkTemplate,
|
||||
["resourcestring"] = (int)Tokens.tkResourceString,
|
||||
["threadvar"] = (int)Tokens.tkThreadvar,
|
||||
["sealed"] = (int)Tokens.tkSealed,
|
||||
["partial"] = (int)Tokens.tkPartial,
|
||||
["params"] = (int)Tokens.tkParams,
|
||||
["unit"] = (int)Tokens.tkUnit,
|
||||
["library"] = (int)Tokens.tkLibrary,
|
||||
["external"] = (int)Tokens.tkExternal,
|
||||
["name"] = (int)Tokens.tkName,
|
||||
["private"] = (int)Tokens.tkPrivate,
|
||||
["protected"] = (int)Tokens.tkProtected,
|
||||
["public"] = (int)Tokens.tkPublic,
|
||||
["internal"] = (int)Tokens.tkInternal,
|
||||
["read"] = (int)Tokens.tkRead,
|
||||
["write"] = (int)Tokens.tkWrite,
|
||||
["on"] = (int)Tokens.tkOn,
|
||||
["forward"] = (int)Tokens.tkForward,
|
||||
["abstract"] = (int)Tokens.tkAbstract,
|
||||
["overload"] = (int)Tokens.tkOverload,
|
||||
["reintroduce"] = (int)Tokens.tkReintroduce,
|
||||
["override"] = (int)Tokens.tkOverride,
|
||||
["virtual"] = (int)Tokens.tkVirtual,
|
||||
["extensionmethod"] = (int)Tokens.tkExtensionMethod,
|
||||
["new"] = (int)Tokens.tkNew,
|
||||
["auto"] = (int)Tokens.tkAuto,
|
||||
["sequence"] = (int)Tokens.tkSequence,
|
||||
["yield"] = (int)Tokens.tkYield,
|
||||
["match"] = (int)Tokens.tkMatch,
|
||||
["when"] = (int)Tokens.tkWhen,
|
||||
["namespace"] = (int)Tokens.tkNamespace,
|
||||
["static"] = (int)Tokens.tkStatic,
|
||||
["step"] = (int)Tokens.tkStep,
|
||||
["index"] = (int)Tokens.tkIndex,
|
||||
["async"] = (int)Tokens.tkAsync,
|
||||
["await"] = (int)Tokens.tkAwait
|
||||
}
|
||||
.ToDictionary(kv => ConvertKeyword(kv.Key), kv => kv.Value, StringComparer.CurrentCultureIgnoreCase);
|
||||
#region Keywords Initialization
|
||||
CreateNewKeyword("or", Tokens.tkOr);
|
||||
CreateNewKeyword("xor", Tokens.tkXor);
|
||||
CreateNewKeyword("and", Tokens.tkAnd);
|
||||
CreateNewKeyword("div", Tokens.tkDiv);
|
||||
CreateNewKeyword("mod", Tokens.tkMod);
|
||||
CreateNewKeyword("shl", Tokens.tkShl);
|
||||
CreateNewKeyword("shr", Tokens.tkShr);
|
||||
CreateNewKeyword("not", Tokens.tkNot);
|
||||
CreateNewKeyword("as", Tokens.tkAs);
|
||||
CreateNewKeyword("in", Tokens.tkIn);
|
||||
CreateNewKeyword("is", Tokens.tkIs);
|
||||
CreateNewKeyword("implicit", Tokens.tkImplicit);
|
||||
CreateNewKeyword("explicit", Tokens.tkExplicit);
|
||||
CreateNewKeyword("sizeof", Tokens.tkSizeOf);
|
||||
CreateNewKeyword("typeof", Tokens.tkTypeOf);
|
||||
CreateNewKeyword("where", Tokens.tkWhere);
|
||||
CreateNewKeyword("array", Tokens.tkArray, isTypeKeyword: true);
|
||||
CreateNewKeyword("begin", Tokens.tkBegin);
|
||||
CreateNewKeyword("case", Tokens.tkCase);
|
||||
CreateNewKeyword("class", Tokens.tkClass, isTypeKeyword: true);
|
||||
CreateNewKeyword("const", Tokens.tkConst, KeywordKind.Const);
|
||||
CreateNewKeyword("constructor", Tokens.tkConstructor, KeywordKind.Constructor);
|
||||
CreateNewKeyword("default", Tokens.tkDefault);
|
||||
CreateNewKeyword("destructor", Tokens.tkDestructor, KeywordKind.Destructor);
|
||||
CreateNewKeyword("downto", Tokens.tkDownto);
|
||||
CreateNewKeyword("do", Tokens.tkDo);
|
||||
CreateNewKeyword("else", Tokens.tkElse);
|
||||
CreateNewKeyword("end", Tokens.tkEnd);
|
||||
CreateNewKeyword("event", Tokens.tkEvent);
|
||||
CreateNewKeyword("except", Tokens.tkExcept);
|
||||
CreateNewKeyword("exports", Tokens.tkExports);
|
||||
CreateNewKeyword("file", Tokens.tkFile, isTypeKeyword : true);
|
||||
CreateNewKeyword("finalization", Tokens.tkFinalization);
|
||||
CreateNewKeyword("finally", Tokens.tkFinally);
|
||||
CreateNewKeyword("for", Tokens.tkFor);
|
||||
CreateNewKeyword("foreach", Tokens.tkForeach);
|
||||
CreateNewKeyword("function", Tokens.tkFunction, KeywordKind.Function, true);
|
||||
CreateNewKeyword("goto", Tokens.tkGoto);
|
||||
CreateNewKeyword("if", Tokens.tkIf);
|
||||
CreateNewKeyword("implementation", Tokens.tkImplementation);
|
||||
CreateNewKeyword("inherited", Tokens.tkInherited, KeywordKind.Inherited);
|
||||
CreateNewKeyword("initialization", Tokens.tkInitialization);
|
||||
CreateNewKeyword("interface", Tokens.tkInterface);
|
||||
CreateNewKeyword("label", Tokens.tkLabel);
|
||||
CreateNewKeyword("lock", Tokens.tkLock);
|
||||
CreateNewKeyword("loop", Tokens.tkLoop);
|
||||
CreateNewKeyword("nil", Tokens.tkNil);
|
||||
CreateNewKeyword("procedure", Tokens.tkProcedure, KeywordKind.Function, true);
|
||||
CreateNewKeyword("of", Tokens.tkOf, KeywordKind.Of);
|
||||
CreateNewKeyword("operator", Tokens.tkOperator);
|
||||
CreateNewKeyword("property", Tokens.tkProperty);
|
||||
CreateNewKeyword("raise", Tokens.tkRaise, KeywordKind.Raise);
|
||||
CreateNewKeyword("record", Tokens.tkRecord, isTypeKeyword: true);
|
||||
CreateNewKeyword("repeat", Tokens.tkRepeat);
|
||||
CreateNewKeyword("set", Tokens.tkSet, isTypeKeyword : true);
|
||||
CreateNewKeyword("try", Tokens.tkTry);
|
||||
CreateNewKeyword("type", Tokens.tkType, KeywordKind.Type);
|
||||
CreateNewKeyword("then", Tokens.tkThen);
|
||||
CreateNewKeyword("to", Tokens.tkTo);
|
||||
CreateNewKeyword("until", Tokens.tkUntil);
|
||||
CreateNewKeyword("uses", Tokens.tkUses, KeywordKind.Uses);
|
||||
CreateNewKeyword("var", Tokens.tkVar, KeywordKind.Var);
|
||||
CreateNewKeyword("while", Tokens.tkWhile);
|
||||
CreateNewKeyword("with", Tokens.tkWith);
|
||||
CreateNewKeyword("program", Tokens.tkProgram, KeywordKind.Program);
|
||||
CreateNewKeyword("template", Tokens.tkTemplate);
|
||||
CreateNewKeyword("resourcestring", Tokens.tkResourceString);
|
||||
CreateNewKeyword("threadvar", Tokens.tkThreadvar);
|
||||
CreateNewKeyword("sealed", Tokens.tkSealed);
|
||||
CreateNewKeyword("partial", Tokens.tkPartial);
|
||||
CreateNewKeyword("params", Tokens.tkParams);
|
||||
CreateNewKeyword("unit", Tokens.tkUnit, KeywordKind.Unit);
|
||||
CreateNewKeyword("library", Tokens.tkLibrary);
|
||||
CreateNewKeyword("external", Tokens.tkExternal);
|
||||
CreateNewKeyword("name", Tokens.tkName);
|
||||
CreateNewKeyword("private", Tokens.tkPrivate);
|
||||
CreateNewKeyword("protected", Tokens.tkProtected);
|
||||
CreateNewKeyword("public", Tokens.tkPublic);
|
||||
CreateNewKeyword("internal", Tokens.tkInternal);
|
||||
CreateNewKeyword("read", Tokens.tkRead);
|
||||
CreateNewKeyword("write", Tokens.tkWrite);
|
||||
CreateNewKeyword("on", Tokens.tkOn);
|
||||
CreateNewKeyword("forward", Tokens.tkForward);
|
||||
CreateNewKeyword("abstract", Tokens.tkAbstract);
|
||||
CreateNewKeyword("overload", Tokens.tkOverload);
|
||||
CreateNewKeyword("reintroduce", Tokens.tkReintroduce);
|
||||
CreateNewKeyword("override", Tokens.tkOverride);
|
||||
CreateNewKeyword("virtual", Tokens.tkVirtual);
|
||||
CreateNewKeyword("extensionmethod", Tokens.tkExtensionMethod);
|
||||
CreateNewKeyword("new", Tokens.tkNew, KeywordKind.New);
|
||||
CreateNewKeyword("auto", Tokens.tkAuto);
|
||||
CreateNewKeyword("sequence", Tokens.tkSequence);
|
||||
CreateNewKeyword("yield", Tokens.tkYield);
|
||||
CreateNewKeyword("match", Tokens.tkMatch);
|
||||
CreateNewKeyword("when", Tokens.tkWhen);
|
||||
CreateNewKeyword("namespace", Tokens.tkNamespace);
|
||||
CreateNewKeyword("static", Tokens.tkStatic);
|
||||
CreateNewKeyword("step", Tokens.tkStep);
|
||||
CreateNewKeyword("index", Tokens.tkIndex);
|
||||
CreateNewKeyword("async", Tokens.tkAsync);
|
||||
CreateNewKeyword("await", Tokens.tkAwait);
|
||||
#endregion
|
||||
}
|
||||
|
||||
protected override int GetIdToken() => (int)Tokens.tkIdentifier;
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ using System.IO;
|
|||
using System.Collections.Generic;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
using PascalABCCompiler.Parsers;
|
||||
using PascalABCCompiler;
|
||||
using Languages.Pascal.Frontend.Core;
|
||||
using PascalABCCompiler.ParserTools.Directives;
|
||||
using static PascalABCCompiler.ParserTools.Directives.DirectiveHelper;
|
||||
|
||||
namespace Languages.Pascal.Frontend.Wrapping
|
||||
{
|
||||
|
|
@ -75,66 +72,12 @@ namespace Languages.Pascal.Frontend.Wrapping
|
|||
public class PascalABCNewLanguageParser : BaseParser
|
||||
{
|
||||
|
||||
public PascalABCNewLanguageParser()
|
||||
{
|
||||
InitializeValidDirectives();
|
||||
Keywords = new PascalABCKeywords();
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
CompilerDirectives = new List<compiler_directive>();
|
||||
Errors.Clear();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Здесь записываются все директивы, поддерживаемые языком, а также правила для проверки их параметров (ограничения, накладываемые со стороны языка)
|
||||
/// </summary>
|
||||
private void InitializeValidDirectives()
|
||||
{
|
||||
#region VALID DIRECTIVES
|
||||
ValidDirectives = new Dictionary<string, DirectiveInfo>(StringComparer.CurrentCultureIgnoreCase)
|
||||
{
|
||||
[StringConstants.compiler_directive_apptype] = new DirectiveInfo(SingleAnyOfCheck("console", "windows", "dll", "pcu")),
|
||||
[StringConstants.compiler_directive_reference] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_include_namespace] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_savepcu] = new DirectiveInfo(SingleAnyOfCheck("true", "false")),
|
||||
[StringConstants.compiler_directive_zerobasedstrings] = new DirectiveInfo(SingleAnyOfCheck("on", "off"), paramsNums: new int[2] { 0, 1 }),
|
||||
[StringConstants.compiler_directive_zerobasedstrings_ON] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_zerobasedstrings_OFF] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_nullbasedstrings_ON] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_nullbasedstrings_OFF] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_initstring_as_empty_ON] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_initstring_as_empty_OFF] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_resource] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_platformtarget] = new DirectiveInfo(SingleAnyOfCheck("x86", "x64", "anycpu", "dotnet5win", "dotnet5linux", "dotnet5macos", "native")),
|
||||
[StringConstants.compiler_directive_faststrings] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_gendoc] = new DirectiveInfo(SingleAnyOfCheck("true", "false")),
|
||||
[StringConstants.compiler_directive_region] = new DirectiveInfo(checkParamsNumNeeded: false),
|
||||
[StringConstants.compiler_directive_endregion] = new DirectiveInfo(checkParamsNumNeeded: false),
|
||||
[StringConstants.compiler_directive_ifdef] = new DirectiveInfo(SingleIsValidIdCheck()),
|
||||
[StringConstants.compiler_directive_endif] = new DirectiveInfo(SingleIsValidIdCheck(), paramsNums: new int[2] { 0, 1 }),
|
||||
[StringConstants.compiler_directive_ifndef] = new DirectiveInfo(SingleIsValidIdCheck()),
|
||||
[StringConstants.compiler_directive_else] = new DirectiveInfo(SingleIsValidIdCheck(), paramsNums: new int[2] { 0, 1 }),
|
||||
[StringConstants.compiler_directive_undef] = new DirectiveInfo(SingleIsValidIdCheck()),
|
||||
[StringConstants.compiler_directive_define] = new DirectiveInfo(SingleIsValidIdCheck()),
|
||||
[StringConstants.compiler_directive_include] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_targetframework] = new DirectiveInfo(),
|
||||
[StringConstants.compiler_directive_hidden_idents] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_disable_standard_units] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_version_string] = new DirectiveInfo(IsValidVersionCheck()),
|
||||
[StringConstants.compiler_directive_product_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_company_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_trademark_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_main_resource_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_title_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_description_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_omp] = new DirectiveInfo(SingleAnyOfCheck("critical", "parallel"), checkParamsNumNeeded: false)
|
||||
};
|
||||
#endregion
|
||||
}
|
||||
|
||||
protected override void PreBuildTree(string FileName)
|
||||
{
|
||||
CompilerDirectives = new List<compiler_directive>();
|
||||
|
|
@ -151,11 +94,11 @@ namespace Languages.Pascal.Frontend.Wrapping
|
|||
#endif
|
||||
#endif
|
||||
|
||||
PascalParserTools parserTools = new PascalParserTools(Errors, Warnings, ValidDirectives,
|
||||
PascalParserTools parserTools = new PascalParserTools(Errors, Warnings, LanguageInformation.ValidDirectives,
|
||||
buildTreeForFormatter, false,
|
||||
Path.GetFullPath(fileName), CompilerDirectives); // контекст сканера и парсера
|
||||
|
||||
Scanner scanner = new Scanner(Text, parserTools, Keywords, definesList);
|
||||
Scanner scanner = new Scanner(Text, parserTools, LanguageInformation.KeywordsStorage, definesList);
|
||||
|
||||
GPPGParser parser = new GPPGParser(scanner, parserTools);
|
||||
|
||||
|
|
@ -192,11 +135,12 @@ namespace Languages.Pascal.Frontend.Wrapping
|
|||
|
||||
syntax_tree_node root = Parse(Text, FileName);
|
||||
|
||||
if (root == null && origText != null && origText.Contains("<"))
|
||||
// убрали эту вторую попытку пока, т.к. Intellisense не должен выдавать подсказку в случае, когда компилятор выдает ошибку в такой ситуации EVA 10.10.2024
|
||||
/*if (root == null && origText != null && origText.Contains("<"))
|
||||
{
|
||||
Errors.Clear();
|
||||
root = Parse(String.Concat("<<expression>>", Environment.NewLine, origText.Replace("<", "&<")), FileName);
|
||||
}
|
||||
}*/
|
||||
return root as expression;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ namespace Languages.Pascal
|
|||
version: "1.2",
|
||||
copyright: "Copyright © 2005-2025 by Ivan Bondarev, Stanislav Mikhalkovich",
|
||||
|
||||
languageInformation: new Frontend.Data.PascalABCLanguageInformation(),
|
||||
parser: new Frontend.Wrapping.PascalABCNewLanguageParser(),
|
||||
docParser: new Frontend.Documentation.PascalDocTagsLanguageParser(),
|
||||
|
||||
|
|
|
|||
|
|
@ -3,142 +3,89 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
using System.Reflection;
|
||||
|
||||
namespace PascalABCCompiler.Parsers
|
||||
using PascalABCCompiler.Parsers;
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.ParserTools.Directives;
|
||||
using static PascalABCCompiler.ParserTools.Directives.DirectiveHelper;
|
||||
|
||||
namespace Languages.Pascal.Frontend.Data
|
||||
{
|
||||
public class DefaultLanguageInformation : ILanguageInformation
|
||||
public class PascalABCLanguageInformation : ILanguageInformation
|
||||
{
|
||||
protected IParser parser;
|
||||
protected string[] type_keywords_array;
|
||||
protected string[] keywords_array;
|
||||
protected Dictionary<string, string> keywords = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
|
||||
protected Hashtable ignored_keywords = new Hashtable(StringComparer.CurrentCultureIgnoreCase);
|
||||
protected Hashtable keyword_kinds = new Hashtable(StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
public DefaultLanguageInformation()
|
||||
protected IParser Parser
|
||||
{
|
||||
|
||||
get
|
||||
{
|
||||
// Поле парсера желательно убрать отсюда EVA
|
||||
return Facade.LanguageProvider.Instance.SelectLanguageByName(StringConstants.pascalLanguageName).Parser;
|
||||
}
|
||||
}
|
||||
|
||||
public DefaultLanguageInformation(IParser p)
|
||||
public BaseKeywords KeywordsStorage { get; } = new Core.PascalABCKeywords();
|
||||
|
||||
public Dictionary<string, DirectiveInfo> ValidDirectives { get; private set; }
|
||||
|
||||
public PascalABCLanguageInformation()
|
||||
{
|
||||
this.parser = p;
|
||||
InitKeywords();
|
||||
InitializeValidDirectives();
|
||||
}
|
||||
|
||||
protected virtual void InitKeywords()
|
||||
/// <summary>
|
||||
/// Здесь записываются все директивы, поддерживаемые языком, а также правила для проверки их параметров (ограничения, накладываемые со стороны языка)
|
||||
/// </summary>
|
||||
private void InitializeValidDirectives()
|
||||
{
|
||||
List<string> keys = new List<string>();
|
||||
List<string> type_keys = new List<string>();
|
||||
keywords.Add("and", "and"); keys.Add("and");
|
||||
keywords.Add("or", "or"); keys.Add("or");
|
||||
keywords.Add("xor", "xor"); keys.Add("xor");
|
||||
keywords.Add("begin", "begin"); keys.Add("begin");
|
||||
keywords.Add("end", "end"); keys.Add("end");
|
||||
keywords.Add("for", "for"); keys.Add("for");
|
||||
keywords.Add("while", "while"); keys.Add("while");
|
||||
keywords.Add("repeat", "repeat"); keys.Add("repeat");
|
||||
keywords.Add("until", "until"); keys.Add("until");
|
||||
keywords.Add("do", "do"); keys.Add("do");
|
||||
keywords.Add("to", "to"); keys.Add("to");
|
||||
keywords.Add("downto", "downto"); keys.Add("downto");
|
||||
keywords.Add("class", "class"); keys.Add("class"); type_keys.Add("class");
|
||||
keywords.Add("record", "record"); keys.Add("record"); type_keys.Add("record");
|
||||
keywords.Add("set", "set"); keys.Add("set"); type_keys.Add("set");
|
||||
keywords.Add("file", "file"); keys.Add("file"); type_keys.Add("file");
|
||||
keywords.Add("type", "type"); keys.Add("type"); keyword_kinds.Add("type", KeywordKind.Type);
|
||||
keywords.Add("array", "array"); keys.Add("array"); type_keys.Add("array");
|
||||
keywords.Add("of", "of"); keys.Add("of"); keyword_kinds.Add("of", KeywordKind.Of);
|
||||
keywords.Add("private", "private"); keys.Add("private");
|
||||
keywords.Add("protected", "protected"); keys.Add("protected");
|
||||
keywords.Add("public", "public"); keys.Add("public");
|
||||
keywords.Add("inherited", "inherited"); keys.Add("inherited"); keyword_kinds.Add("inherited", KeywordKind.Inherited);
|
||||
keywords.Add("foreach", "foreach"); keys.Add("foreach");
|
||||
keywords.Add("try", "try"); keys.Add("try");
|
||||
keywords.Add("except", "except"); keys.Add("except");
|
||||
keywords.Add("finally", "finally"); keys.Add("finally");
|
||||
keywords.Add("uses", "uses"); keys.Add("uses"); keyword_kinds.Add("uses", KeywordKind.Uses);
|
||||
keywords.Add("unit", "unit"); keys.Add("unit"); keyword_kinds.Add("unit", KeywordKind.Unit);
|
||||
|
||||
keywords.Add("procedure", "procedure"); keys.Add("procedure"); keyword_kinds.Add("procedure", KeywordKind.Function); type_keys.Add("procedure");
|
||||
keywords.Add("function", "function"); keys.Add("function"); keyword_kinds.Add("function", KeywordKind.Function); type_keys.Add("function");
|
||||
keywords.Add("constructor", "constructor"); keys.Add("constructor"); keyword_kinds.Add("constructor", KeywordKind.Constructor);
|
||||
keywords.Add("destructor", "destructor"); keys.Add("destructor"); keyword_kinds.Add("destructor", KeywordKind.Destructor);
|
||||
keywords.Add("interface", "interface"); keys.Add("interface");
|
||||
keywords.Add("implementation", "implementation"); keys.Add("implementation");
|
||||
keywords.Add("initialization", "initialization"); keys.Add("initialization");
|
||||
keywords.Add("finalization", "finalization"); keys.Add("finalization");
|
||||
keywords.Add("with", "with"); keys.Add("with");
|
||||
keywords.Add("abstract","abstract"); keys.Add("abstract");
|
||||
keywords.Add("virtual", "virtual"); keys.Add("virtual");
|
||||
keywords.Add("override", "override"); keys.Add("override");
|
||||
keywords.Add("reintroduce", "reintroduce"); keys.Add("reintroduce");
|
||||
keywords.Add("sealed", "sealed"); keys.Add("sealed");
|
||||
keywords.Add("case", "case"); keys.Add("case");
|
||||
keywords.Add("var", "var"); keys.Add("var"); keyword_kinds.Add("var", KeywordKind.Var);
|
||||
keywords.Add("const", "const"); keys.Add("const"); keyword_kinds.Add("const", KeywordKind.Const);
|
||||
keywords.Add("if", "if"); keys.Add("if");
|
||||
keywords.Add("then", "then"); keys.Add("then");
|
||||
keywords.Add("else", "else"); keys.Add("else");
|
||||
keywords.Add("in", "in"); keys.Add("in");
|
||||
keywords.Add("operator", "operator"); keys.Add("operator");
|
||||
keywords.Add("raise", "raise"); keys.Add("raise"); keyword_kinds.Add("raise", KeywordKind.Raise);
|
||||
keywords.Add("program", "program"); keys.Add("program"); keyword_kinds.Add("program", KeywordKind.Program);
|
||||
keywords.Add("new", "new"); keys.Add("new"); keyword_kinds.Add("new", KeywordKind.New);
|
||||
keywords.Add("nil", "nil"); keys.Add("nil");
|
||||
keywords.Add("loop", "loop"); keys.Add("loop");
|
||||
keywords.Add("yield", "yield"); keys.Add("yield");
|
||||
keywords.Add("sequence", "sequence"); keys.Add("sequence");
|
||||
keywords.Add("extensionmethod", "extensionmethod"); keys.Add("extensionmethod");
|
||||
keywords.Add("params", "params"); keys.Add("params");
|
||||
keywords.Add("implicit", "implicit"); keys.Add("implicit");
|
||||
keywords.Add("explicit", "explicit"); keys.Add("explicit");
|
||||
keywords.Add("forward", "forward"); keys.Add("forward");
|
||||
keywords.Add("break", "break"); keys.Add("break");
|
||||
keywords.Add("continue", "continue"); keys.Add("continue");
|
||||
keywords.Add("default", "default"); keys.Add("default");
|
||||
keywords.Add("label", "label"); keys.Add("label");
|
||||
keywords.Add("property", "property"); keys.Add("property");
|
||||
keywords.Add("auto", "auto"); keys.Add("auto");
|
||||
keywords.Add("external", "external"); keys.Add("external");
|
||||
keywords.Add("lock", "lock"); keys.Add("lock");
|
||||
keywords.Add("where", "where"); keys.Add("where");
|
||||
keywords.Add("library", "library"); keys.Add("library");
|
||||
keywords.Add("div", "div"); keys.Add("div");
|
||||
keywords.Add("mod", "mod"); keys.Add("mod");
|
||||
keywords.Add("shl", "shl"); keys.Add("shl");
|
||||
keywords.Add("shr", "shr"); keys.Add("shr");
|
||||
keywords.Add("not", "not"); keys.Add("not");
|
||||
keywords.Add("as", "as"); keys.Add("as");
|
||||
keywords.Add("is", "is"); keys.Add("is");
|
||||
keywords.Add("on", "on"); keys.Add("on");
|
||||
keywords.Add("goto", "goto"); keys.Add("goto");
|
||||
keywords.Add("overload", "overload"); keys.Add("overload");
|
||||
keywords.Add("internal", "internal"); keys.Add("internal");
|
||||
//keywords.Add("template", "template"); keys.Add("template");
|
||||
keywords.Add("partial", "partial"); keys.Add("partial");
|
||||
keywords.Add("namespace", "namespace"); keys.Add("namespace");
|
||||
keywords.Add("exit", "exit"); keys.Add("exit");
|
||||
keywords.Add("event", "event"); keys.Add("event");
|
||||
keywords.Add("match", "match"); keys.Add("match");
|
||||
keywords.Add("when", "when"); keys.Add("when");
|
||||
keywords.Add("static", "static"); keys.Add("static");
|
||||
//keywords.Add("typeof", "typeof"); //keys.Add("typeof");
|
||||
//keywords.Add("sizeof", "sizeof"); //keys.Add("sizeof");
|
||||
keywords_array = new string[keywords.Count + 2];
|
||||
keywords_array[0] = "typeof";
|
||||
keywords_array[1] = "sizeof";
|
||||
keywords.Values.CopyTo(keywords_array, 2);
|
||||
type_keywords_array = type_keys.ToArray();
|
||||
#region VALID DIRECTIVES
|
||||
ValidDirectives = new Dictionary<string, DirectiveInfo>(StringComparer.CurrentCultureIgnoreCase)
|
||||
{
|
||||
[StringConstants.compiler_directive_apptype] = new DirectiveInfo(SingleAnyOfCheck("console", "windows", "dll", "pcu")),
|
||||
[StringConstants.compiler_directive_reference] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_include_namespace] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_savepcu] = new DirectiveInfo(SingleAnyOfCheck("true", "false")),
|
||||
[StringConstants.compiler_directive_zerobasedstrings] = new DirectiveInfo(SingleAnyOfCheck("on", "off"), paramsNums: new int[2] { 0, 1 }),
|
||||
[StringConstants.compiler_directive_zerobasedstrings_ON] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_zerobasedstrings_OFF] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_nullbasedstrings_ON] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_nullbasedstrings_OFF] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_initstring_as_empty_ON] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_initstring_as_empty_OFF] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_resource] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_platformtarget] = new DirectiveInfo(SingleAnyOfCheck("x86", "x64", "anycpu", "dotnet5win", "dotnet5linux", "dotnet5macos", "native")),
|
||||
[StringConstants.compiler_directive_faststrings] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_gendoc] = new DirectiveInfo(SingleAnyOfCheck("true", "false")),
|
||||
[StringConstants.compiler_directive_region] = new DirectiveInfo(checkParamsNumNeeded: false),
|
||||
[StringConstants.compiler_directive_endregion] = new DirectiveInfo(checkParamsNumNeeded: false),
|
||||
[StringConstants.compiler_directive_ifdef] = new DirectiveInfo(SingleIsValidIdCheck()),
|
||||
[StringConstants.compiler_directive_endif] = new DirectiveInfo(SingleIsValidIdCheck(), paramsNums: new int[2] { 0, 1 }),
|
||||
[StringConstants.compiler_directive_ifndef] = new DirectiveInfo(SingleIsValidIdCheck()),
|
||||
[StringConstants.compiler_directive_else] = new DirectiveInfo(SingleIsValidIdCheck(), paramsNums: new int[2] { 0, 1 }),
|
||||
[StringConstants.compiler_directive_undef] = new DirectiveInfo(SingleIsValidIdCheck()),
|
||||
[StringConstants.compiler_directive_define] = new DirectiveInfo(SingleIsValidIdCheck()),
|
||||
[StringConstants.compiler_directive_include] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_targetframework] = new DirectiveInfo(),
|
||||
[StringConstants.compiler_directive_hidden_idents] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_disable_standard_units] = NoParamsDirectiveInfo(),
|
||||
[StringConstants.compiler_directive_version_string] = new DirectiveInfo(IsValidVersionCheck()),
|
||||
[StringConstants.compiler_directive_product_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_company_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_trademark_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_main_resource_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_title_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_description_string] = new DirectiveInfo(quotesAreSpecialSymbols: true),
|
||||
[StringConstants.compiler_directive_omp] = new DirectiveInfo(SingleAnyOfCheck("critical", "parallel"), checkParamsNumNeeded: false)
|
||||
};
|
||||
#endregion
|
||||
}
|
||||
|
||||
public bool IsKeyword(string value)
|
||||
{
|
||||
return keywords.ContainsKey(value.ToLower());
|
||||
// typeof и sizeof воспринимаются Intellisense по другому EVA
|
||||
return !value.Equals("typeof", StringComparison.CurrentCultureIgnoreCase) && !value.Equals("sizeof", StringComparison.CurrentCultureIgnoreCase)
|
||||
&& KeywordsStorage.KeywordsToTokens.ContainsKey(value);
|
||||
}
|
||||
|
||||
public virtual string BodyStartBracket
|
||||
|
|
@ -161,23 +108,23 @@ namespace PascalABCCompiler.Parsers
|
|||
{
|
||||
get
|
||||
{
|
||||
return "PABCSystem";
|
||||
return PascalABCCompiler.StringConstants.pascalSystemUnitName;
|
||||
}
|
||||
}
|
||||
|
||||
public string[] Keywords
|
||||
public List<string> Keywords
|
||||
{
|
||||
get
|
||||
{
|
||||
return keywords_array;
|
||||
return KeywordsStorage.Keywords;
|
||||
}
|
||||
}
|
||||
|
||||
public string[] TypeKeywords
|
||||
public List<string> TypeKeywords
|
||||
{
|
||||
get
|
||||
{
|
||||
return type_keywords_array;
|
||||
return KeywordsStorage.TypeKeywords;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -631,9 +578,9 @@ namespace PascalABCCompiler.Parsers
|
|||
if (!string.IsNullOrEmpty(doc))
|
||||
{
|
||||
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
|
||||
doc = doc.Replace("<returns>", StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<params>", "");
|
||||
doc = doc.Replace("<param>", StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("</param>", "");
|
||||
sb.AppendLine(" /// " + doc);
|
||||
}
|
||||
|
|
@ -698,7 +645,7 @@ namespace PascalABCCompiler.Parsers
|
|||
FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (fields.Length > 0)
|
||||
{
|
||||
sb.AppendLine(" {$region " + StringResources.Get("CODE_COMPLETION_FIELDS") + "}");
|
||||
sb.AppendLine(" {$region " + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_FIELDS") + "}");
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
if (fields[i].DeclaringType == t && !fields[i].IsPrivate && !fields[i].IsAssembly)
|
||||
|
|
@ -707,9 +654,9 @@ namespace PascalABCCompiler.Parsers
|
|||
if (!string.IsNullOrEmpty(doc))
|
||||
{
|
||||
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
|
||||
doc = doc.Replace("<returns>", StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<params>", "");
|
||||
doc = doc.Replace("<param>", StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("</param>", "");
|
||||
sb.AppendLine(" /// " + doc);
|
||||
ln++;
|
||||
|
|
@ -731,7 +678,7 @@ namespace PascalABCCompiler.Parsers
|
|||
EventInfo[] events = t.GetEvents(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (events.Length > 0)
|
||||
{
|
||||
sb.AppendLine(" {$region " + StringResources.Get("CODE_COMPLETION_EVENTS") + "}");
|
||||
sb.AppendLine(" {$region " + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_EVENTS") + "}");
|
||||
for (int i = 0; i < events.Length; i++)
|
||||
{
|
||||
if (events[i].DeclaringType != t)
|
||||
|
|
@ -743,9 +690,9 @@ namespace PascalABCCompiler.Parsers
|
|||
if (!string.IsNullOrEmpty(doc))
|
||||
{
|
||||
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
|
||||
doc = doc.Replace("<returns>", StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<params>", "");
|
||||
doc = doc.Replace("<param>", StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("</param>", "");
|
||||
sb.AppendLine(" /// " + doc);
|
||||
}
|
||||
|
|
@ -767,7 +714,7 @@ namespace PascalABCCompiler.Parsers
|
|||
PropertyInfo[] props = t.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (props.Length > 0)
|
||||
{
|
||||
sb.AppendLine(" {$region " + StringResources.Get("CODE_COMPLETION_PROPERTIES") + "}");
|
||||
sb.AppendLine(" {$region " + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PROPERTIES") + "}");
|
||||
for (int i = 0; i < props.Length; i++)
|
||||
{
|
||||
if (props[i].DeclaringType != t)
|
||||
|
|
@ -779,9 +726,9 @@ namespace PascalABCCompiler.Parsers
|
|||
if (!string.IsNullOrEmpty(doc))
|
||||
{
|
||||
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
|
||||
doc = doc.Replace("<returns>", StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<params>", "");
|
||||
doc = doc.Replace("<param>", StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("</param>", "");
|
||||
sb.AppendLine(" /// " + doc);
|
||||
}
|
||||
|
|
@ -803,7 +750,7 @@ namespace PascalABCCompiler.Parsers
|
|||
ConstructorInfo[] constrs = t.GetConstructors(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (constrs.Length > 0)
|
||||
{
|
||||
sb.AppendLine(" {$region " + StringResources.Get("CODE_COMPLETION_CONSTRUCTORS") + "}");
|
||||
sb.AppendLine(" {$region " + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_CONSTRUCTORS") + "}");
|
||||
for (int i = 0; i < constrs.Length; i++)
|
||||
{
|
||||
if (constrs[i].DeclaringType == t && !constrs[i].IsPrivate && !constrs[i].IsAssembly)
|
||||
|
|
@ -812,9 +759,9 @@ namespace PascalABCCompiler.Parsers
|
|||
if (!string.IsNullOrEmpty(doc))
|
||||
{
|
||||
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
|
||||
doc = doc.Replace("<returns>", StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<params>", "");
|
||||
doc = doc.Replace("<param>", StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("</param>", "");
|
||||
sb.AppendLine(" /// " + doc);
|
||||
}
|
||||
|
|
@ -835,7 +782,7 @@ namespace PascalABCCompiler.Parsers
|
|||
MethodInfo[] meths = t.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (meths.Length > 0)
|
||||
{
|
||||
sb.AppendLine(" {$region " + StringResources.Get("CODE_COMPLETION_METHODS") + "}");
|
||||
sb.AppendLine(" {$region " + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_METHODS") + "}");
|
||||
for (int i = 0; i < meths.Length; i++)
|
||||
{
|
||||
if (meths[i].DeclaringType == t && !meths[i].IsPrivate && !meths[i].IsAssembly && !meths[i].Name.StartsWith("get_") && !meths[i].Name.StartsWith("set_") && !meths[i].Name.StartsWith("add_") && !meths[i].Name.StartsWith("remove_"))
|
||||
|
|
@ -844,9 +791,9 @@ namespace PascalABCCompiler.Parsers
|
|||
if (!string.IsNullOrEmpty(doc))
|
||||
{
|
||||
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
|
||||
doc = doc.Replace("<returns>", StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
|
||||
doc = doc.Replace("<params>", "");
|
||||
doc = doc.Replace("<param>", StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
|
||||
doc = doc.Replace("</param>", "");
|
||||
sb.AppendLine(" /// " + doc);
|
||||
}
|
||||
|
|
@ -1015,7 +962,7 @@ namespace PascalABCCompiler.Parsers
|
|||
var strrank = rank > 1 ? "[" + new string(',', rank - 1) + "]" : "";
|
||||
return $"array{strrank}" + " of " + GetShortTypeName(ctn.GetElementType());
|
||||
}
|
||||
//if (ctn == Type.GetType("System.Void*")) return StringConstants.pointer_type_name;
|
||||
//if (ctn == Type.GetType("System.Void*")) return PascalABCCompiler.StringConstants.pointer_type_name;
|
||||
return ctn.Name;
|
||||
}
|
||||
|
||||
|
|
@ -1851,11 +1798,11 @@ namespace PascalABCCompiler.Parsers
|
|||
{
|
||||
if (extensionType.IndexOf(' ') != -1)
|
||||
{
|
||||
sb.Append("(" + StringResources.Get("CODE_COMPLETION_EXTENSION") + " " + extensionType + ") ");
|
||||
sb.Append("(" + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_EXTENSION") + " " + extensionType + ") ");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append("(" + StringResources.Get("CODE_COMPLETION_EXTENSION") + ") ");
|
||||
sb.Append("(" + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_EXTENSION") + ") ");
|
||||
extensionType = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -2056,12 +2003,12 @@ namespace PascalABCCompiler.Parsers
|
|||
{
|
||||
if (extensionType != null && extensionType.IndexOf(' ') != -1)
|
||||
{
|
||||
sb.Append("(" + StringResources.Get("CODE_COMPLETION_EXTENSION") + " " + extensionType + ") ");
|
||||
sb.Append("(" + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_EXTENSION") + " " + extensionType + ") ");
|
||||
extensionType = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append("(" + StringResources.Get("CODE_COMPLETION_EXTENSION")+ ") ");
|
||||
sb.Append("(" + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_EXTENSION")+ ") ");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2167,7 +2114,7 @@ namespace PascalABCCompiler.Parsers
|
|||
|
||||
private string prepare_member_name(string s)
|
||||
{
|
||||
if (keywords.ContainsKey(s))
|
||||
if (IsKeyword(s))
|
||||
return "&" + s;
|
||||
return s;
|
||||
}
|
||||
|
|
@ -2351,9 +2298,10 @@ namespace PascalABCCompiler.Parsers
|
|||
|
||||
public KeywordKind GetKeywordKind(string name)
|
||||
{
|
||||
object o = keyword_kinds[name];
|
||||
if (o != null) return (KeywordKind)o;
|
||||
else return KeywordKind.None;
|
||||
if (KeywordsStorage.KeywordKinds.TryGetValue(name, out var kind))
|
||||
return kind;
|
||||
else
|
||||
return KeywordKind.None;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2526,7 +2474,7 @@ namespace PascalABCCompiler.Parsers
|
|||
sb.AppendLine(lineText);
|
||||
sb.AppendLine("begin end;");
|
||||
sb.AppendLine("begin end.");
|
||||
program_module node = this.parser.GetCompilationUnit("test.pas", sb.ToString(), null, null, ParseMode.Special) as program_module;
|
||||
program_module node = this.Parser.GetCompilationUnit("test.pas", sb.ToString(), null, null, ParseMode.Special) as program_module;
|
||||
procedure_header header = (node.program_block.defs.defs[0] as procedure_definition).proc_header;
|
||||
get_procedure_template(header, res, col);
|
||||
return res.ToString();
|
||||
|
|
@ -2537,7 +2485,7 @@ namespace PascalABCCompiler.Parsers
|
|||
sb.AppendLine(lineText);
|
||||
sb.AppendLine("begin end;");
|
||||
sb.AppendLine("begin end.");
|
||||
program_module node = this.parser.GetCompilationUnit("test.pas", sb.ToString(), null, null, ParseMode.Special) as program_module;
|
||||
program_module node = this.Parser.GetCompilationUnit("test.pas", sb.ToString(), null, null, ParseMode.Special) as program_module;
|
||||
if (node.program_block.defs != null && node.program_block.defs.defs.Count > 0 && node.program_block.defs.defs[0] is procedure_definition)
|
||||
{
|
||||
procedure_header header = (node.program_block.defs.defs[0] as procedure_definition).proc_header;
|
||||
|
|
@ -2718,7 +2666,7 @@ namespace PascalABCCompiler.Parsers
|
|||
{
|
||||
keyword = KeywordKind.Raise;
|
||||
}
|
||||
else if (keywords.ContainsKey(s))
|
||||
else if (IsKeyword(s))
|
||||
{
|
||||
keyword = KeywordKind.CommonKeyword;
|
||||
}
|
||||
|
|
@ -3115,11 +3063,15 @@ namespace PascalABCCompiler.Parsers
|
|||
public virtual string FindExpressionFromAnyPosition(int off, string Text, int line, int col, out KeywordKind keyw, out string expr_without_brackets)
|
||||
{
|
||||
int i = off - 1;
|
||||
|
||||
// это например вызов метода без параметров
|
||||
expr_without_brackets = null;
|
||||
keyw = KeywordKind.None;
|
||||
if (i < 0)
|
||||
return "";
|
||||
bool is_char = false;
|
||||
|
||||
// идем в обе стороны от off
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||
if (Text[i] != ' ' && (Char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '?' && IsPunctuation(Text, i + 1) || Text[i] == '!'))
|
||||
{
|
||||
|
|
@ -3792,8 +3744,8 @@ namespace PascalABCCompiler.Parsers
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
public class CLanguageInformation : DefaultLanguageInformation
|
||||
#region LEGACY - C language
|
||||
/*public class CLanguageInformation : DefaultLanguageInformation
|
||||
{
|
||||
public CLanguageInformation(IParser p)
|
||||
{
|
||||
|
|
@ -3941,18 +3893,18 @@ namespace PascalABCCompiler.Parsers
|
|||
sb.Append(ctn.Name.Substring(0,ctn.Name.IndexOf('`')));
|
||||
sb.Append('<');
|
||||
sb.Append('>');
|
||||
/*sb.Append('<');
|
||||
*//*sb.Append('<');
|
||||
for (int i=0; i<len; i++)
|
||||
{
|
||||
sb.Append('T');
|
||||
if (i<len-1)
|
||||
sb.Append(',');
|
||||
}
|
||||
sb.Append('>');*/
|
||||
sb.Append('>');*//*
|
||||
return sb.ToString();
|
||||
}
|
||||
//if (ctn.IsArray) return "array of "+GetTypeName(ctn.GetElementType());
|
||||
//if (ctn == Type.GetType("System.Void*")) return StringConstants.pointer_type_name;
|
||||
//if (ctn == Type.GetType("System.Void*")) return PascalABCCompiler.StringConstants.pointer_type_name;
|
||||
return ctn.Name;
|
||||
}
|
||||
|
||||
|
|
@ -4199,6 +4151,7 @@ namespace PascalABCCompiler.Parsers
|
|||
sb.Append(')');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ namespace VisualPascalABC
|
|||
public CodeFileDocumentTextEditorControl()
|
||||
{
|
||||
editactions[Keys.Space | Keys.Control] = new CodeCompletionAllNamesAction();
|
||||
editactions[Keys.Space | Keys.Shift] = new CodeCompletionNamesOnlyInModuleAction();
|
||||
editactions[Keys.Space | Keys.Shift] = new CodeCompletionShiftSpaceActions();
|
||||
editactions[Keys.Enter | Keys.Control] = new GotoAction();
|
||||
editactions[Keys.LButton | Keys.Control] = new GotoAction();
|
||||
editactions[Keys.C | Keys.Shift | Keys.Control] = new ClassOrMethodRealizationAction();
|
||||
|
|
|
|||
|
|
@ -118,22 +118,39 @@ namespace VisualPascalABC
|
|||
|
||||
public static List<Position> GetDefinitionPosition(TextArea textArea, bool only_check)
|
||||
{
|
||||
if (CodeCompletion.CodeCompletionController.CurrentParser == null) return new List<Position>();
|
||||
|
||||
IParser parser = CodeCompletion.CodeCompletionController.CurrentParser;
|
||||
|
||||
if (parser == null)
|
||||
return new List<Position>();
|
||||
|
||||
IDocument doc = textArea.Document;
|
||||
string textContent = doc.TextContent;
|
||||
ccp = new CodeCompletionProvider();
|
||||
string full_expr;
|
||||
string expressionResult = FindFullExpression(textContent, textArea, out ccp.keyword, out full_expr);
|
||||
|
||||
if (expressionResult != null)
|
||||
expressionResult = expressionResult.Trim();
|
||||
|
||||
|
||||
// Проверка, что компилируем Паскаль временно EVA 10.11.2024
|
||||
if (parser == Languages.Facade.LanguageProvider.Instance.SelectLanguageByName(StringConstants.pascalLanguageName).Parser)
|
||||
{
|
||||
if (expressionResult != full_expr && full_expr.StartsWith("("))
|
||||
return new List<Position>();
|
||||
|
||||
if (full_expr != null && full_expr.Contains("^"))
|
||||
full_expr = full_expr.Replace("^","");
|
||||
{
|
||||
full_expr = full_expr.Replace("^", "");
|
||||
}
|
||||
}
|
||||
|
||||
List<Position> poses = ccp.GetDefinition(full_expr, textArea.MotherTextEditorControl.FileName, textArea.Caret.Line, textArea.Caret.Column, only_check);
|
||||
|
||||
if (poses == null || poses.Count == 0)
|
||||
poses = ccp.GetDefinition(expressionResult, textArea.MotherTextEditorControl.FileName, textArea.Caret.Line, textArea.Caret.Column, only_check);
|
||||
|
||||
return poses;
|
||||
}
|
||||
|
||||
|
|
@ -574,12 +591,93 @@ namespace VisualPascalABC
|
|||
}
|
||||
}
|
||||
|
||||
public class CodeCompletionNamesOnlyInModuleAction : CodeCompletionAllNamesAction
|
||||
/// <summary>
|
||||
/// Включает в себя три различных действия по shift + space, что не очень хорошо EVA
|
||||
/// </summary>
|
||||
public class CodeCompletionShiftSpaceActions : ICSharpCode.TextEditor.Actions.AbstractEditAction
|
||||
{
|
||||
PABCNETCodeCompletionWindow codeCompletionWindow;
|
||||
public static TextArea textArea = CodeCompletionAllNamesAction.textArea;
|
||||
public static Hashtable comp_windows = CodeCompletionAllNamesAction.comp_windows;
|
||||
public static bool is_begin = false;
|
||||
|
||||
private string get_prev_text(string text, int off)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (off >= 0 && char.IsLetterOrDigit(text[off]))
|
||||
{
|
||||
sb.Insert(0, text[off--]);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public override void Execute(TextArea _textArea)
|
||||
{
|
||||
key = '\0';
|
||||
base.Execute(_textArea);
|
||||
//base.Execute(_textArea);
|
||||
|
||||
textArea = _textArea;
|
||||
int off = textArea.Caret.Offset;
|
||||
string text = textArea.Document.TextContent.Substring(0, textArea.Caret.Offset);
|
||||
|
||||
// автодополнение xml-комментария
|
||||
if (off > 2 && text[off - 1] == '/' && text[off - 2] == '/' && text[off - 3] == '/')
|
||||
{
|
||||
CodeCompletionActionsManager.GenerateCommentTemplate(textArea);
|
||||
return;
|
||||
}
|
||||
// автодополнение некоторого выражения из файла template.pct
|
||||
else
|
||||
{
|
||||
string prev = get_prev_text(text, off - 1);
|
||||
if (!string.IsNullOrEmpty(prev))
|
||||
{
|
||||
CodeCompletionActionsManager.GenerateTemplate(prev, textArea);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// если подсказка по точке выключена дальше не идем
|
||||
if (!WorkbenchServiceFactory.Workbench.UserOptions.CodeCompletionDot)
|
||||
return;
|
||||
|
||||
if (CodeCompletion.CodeCompletionController.CurrentParser == null)
|
||||
return;
|
||||
|
||||
is_begin = true;
|
||||
|
||||
codeCompletionWindow = PABCNETCodeCompletionWindow.ShowCompletionWindow(
|
||||
VisualPABCSingleton.MainForm, // The parent window for the completion window
|
||||
textArea.MotherTextEditorControl, // The text editor to show the window for
|
||||
textArea.MotherTextEditorControl.FileName, // Filename - will be passed back to the provider
|
||||
new CodeCompletionProvider(), // Provider to get the list of possible completions
|
||||
'\0', // Key pressed - will be passed to the provider
|
||||
false,
|
||||
false,
|
||||
KeywordKind.None
|
||||
);
|
||||
|
||||
comp_windows[textArea] = codeCompletionWindow;
|
||||
|
||||
if (codeCompletionWindow != null)
|
||||
{
|
||||
// ShowCompletionWindow can return null when the provider returns an empty list
|
||||
codeCompletionWindow.Closed += new EventHandler(OnCodeCompletionWindowClosed);
|
||||
}
|
||||
}
|
||||
|
||||
// такой же метод есть в CodeCompletionKeyHandler EVA
|
||||
public void OnCodeCompletionWindowClosed(object sender, EventArgs e)
|
||||
{
|
||||
if (codeCompletionWindow != null)
|
||||
{
|
||||
codeCompletionWindow.Closed -= new EventHandler(OnCodeCompletionWindowClosed);
|
||||
CodeCompletionProvider.disp.Reset();
|
||||
CodeCompletion.AssemblyDocCache.Reset();
|
||||
CodeCompletion.UnitDocCache.Reset();
|
||||
codeCompletionWindow.Dispose();
|
||||
codeCompletionWindow = null;
|
||||
}
|
||||
comp_windows[textArea] = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -627,18 +725,6 @@ namespace VisualPascalABC
|
|||
PABCNETCodeCompletionWindow codeCompletionWindow;
|
||||
public static TextArea textArea;
|
||||
public static Hashtable comp_windows = new Hashtable();
|
||||
public static bool is_begin = false;
|
||||
protected char key = '_';
|
||||
|
||||
private string get_prev_text(string text, int off)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (off >= 0 && char.IsLetterOrDigit(text[off]))
|
||||
{
|
||||
sb.Insert(0, text[off--]);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public override void Execute(TextArea _textArea)
|
||||
{
|
||||
|
|
@ -647,52 +733,31 @@ namespace VisualPascalABC
|
|||
textArea = _textArea;
|
||||
int off = textArea.Caret.Offset;
|
||||
string text = textArea.Document.TextContent.Substring(0, textArea.Caret.Offset);
|
||||
if (key == '\0')
|
||||
if (off > 2 && text[off - 1] == '/' && text[off - 2] == '/' && text[off - 3] == '/')
|
||||
{
|
||||
CodeCompletionActionsManager.GenerateCommentTemplate(textArea);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
string prev = get_prev_text(text, off - 1);
|
||||
if (!string.IsNullOrEmpty(prev))
|
||||
{
|
||||
CodeCompletionActionsManager.GenerateTemplate(prev, textArea);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WorkbenchServiceFactory.Workbench.UserOptions.CodeCompletionDot)
|
||||
return;
|
||||
|
||||
if (CodeCompletion.CodeCompletionController.CurrentParser == null) return;
|
||||
CodeCompletionProvider completionDataProvider = new CodeCompletionProvider();
|
||||
|
||||
bool is_pattern = false;
|
||||
completionDataProvider.preSelection = CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.FindPattern(off, text, out var is_pattern);
|
||||
|
||||
|
||||
is_begin = true;
|
||||
|
||||
completionDataProvider.preSelection = CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.FindPattern(off, text, out is_pattern);
|
||||
|
||||
if (!is_pattern && off > 0 && text[off - 1] == '.')
|
||||
key = '$';
|
||||
codeCompletionWindow = PABCNETCodeCompletionWindow.ShowCompletionWindow(
|
||||
VisualPABCSingleton.MainForm, // The parent window for the completion window
|
||||
textArea.MotherTextEditorControl, // The text editor to show the window for
|
||||
textArea.MotherTextEditorControl.FileName, // Filename - will be passed back to the provider
|
||||
completionDataProvider, // Provider to get the list of possible completions
|
||||
key, // Key pressed - will be passed to the provider
|
||||
'_', // Key pressed - will be passed to the provider
|
||||
false,
|
||||
false,
|
||||
PascalABCCompiler.Parsers.KeywordKind.None
|
||||
KeywordKind.None
|
||||
);
|
||||
key = '_';
|
||||
CodeCompletionNamesOnlyInModuleAction.comp_windows[textArea] = codeCompletionWindow;
|
||||
CodeCompletionShiftSpaceActions.comp_windows[textArea] = codeCompletionWindow;
|
||||
|
||||
if (codeCompletionWindow != null)
|
||||
{
|
||||
// ShowCompletionWindow can return null when the provider returns an empty list
|
||||
codeCompletionWindow.Closed += new EventHandler(CloseCodeCompletionWindow);
|
||||
codeCompletionWindow.Closed += new EventHandler(OnCodeCompletionWindowClosed);
|
||||
}
|
||||
}
|
||||
//catch (Exception e)
|
||||
|
|
@ -701,11 +766,12 @@ namespace VisualPascalABC
|
|||
}
|
||||
}
|
||||
|
||||
public void CloseCodeCompletionWindow(object sender, EventArgs e)
|
||||
// такой же метод есть в CodeCompletionKeyHandler EVA
|
||||
public void OnCodeCompletionWindowClosed(object sender, EventArgs e)
|
||||
{
|
||||
if (codeCompletionWindow != null)
|
||||
{
|
||||
codeCompletionWindow.Closed -= new EventHandler(CloseCodeCompletionWindow);
|
||||
codeCompletionWindow.Closed -= new EventHandler(OnCodeCompletionWindowClosed);
|
||||
CodeCompletionProvider.disp.Reset();
|
||||
CodeCompletion.AssemblyDocCache.Reset();
|
||||
CodeCompletion.UnitDocCache.Reset();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||||
// 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;
|
||||
|
|
@ -40,7 +40,7 @@ namespace VisualPascalABC
|
|||
//editor.ActiveTextAreaControl.TextArea.KeyDown += new System.Windows.Forms.KeyEventHandler(TextArea_KeyDown);
|
||||
//editor.ActiveTextAreaControl.KeyDown += h.TextControlEventHandler;
|
||||
// When the editor is disposed, close the code completion window
|
||||
editor.Disposed += h.CloseCodeCompletionWindow;
|
||||
editor.Disposed += h.OnCodeCompletionWindowClosed;
|
||||
return h;
|
||||
}
|
||||
|
||||
|
|
@ -74,11 +74,11 @@ namespace VisualPascalABC
|
|||
}
|
||||
else
|
||||
{
|
||||
PABCNETCodeCompletionWindow ccw = CodeCompletionNamesOnlyInModuleAction.comp_windows[editor.ActiveTextAreaControl.TextArea] as PABCNETCodeCompletionWindow;
|
||||
PABCNETCodeCompletionWindow ccw = CodeCompletionShiftSpaceActions.comp_windows[editor.ActiveTextAreaControl.TextArea] as PABCNETCodeCompletionWindow;
|
||||
|
||||
if (ccw != null && CodeCompletionNamesOnlyInModuleAction.is_begin)
|
||||
if (ccw != null && CodeCompletionShiftSpaceActions.is_begin)
|
||||
{
|
||||
CodeCompletionNamesOnlyInModuleAction.is_begin = false;
|
||||
CodeCompletionShiftSpaceActions.is_begin = false;
|
||||
if (key != ' ')
|
||||
ccw.ProcessKeyEvent(key);
|
||||
else
|
||||
|
|
@ -115,10 +115,10 @@ namespace VisualPascalABC
|
|||
true,
|
||||
PascalABCCompiler.Parsers.KeywordKind.None
|
||||
);
|
||||
CodeCompletionNamesOnlyInModuleAction.is_begin = true;
|
||||
CodeCompletionNamesOnlyInModuleAction.comp_windows[editor.ActiveTextAreaControl.TextArea] = codeCompletionWindow;
|
||||
CodeCompletionShiftSpaceActions.is_begin = true;
|
||||
CodeCompletionShiftSpaceActions.comp_windows[editor.ActiveTextAreaControl.TextArea] = codeCompletionWindow;
|
||||
if (codeCompletionWindow != null)
|
||||
codeCompletionWindow.Closed += new EventHandler(CloseCodeCompletionWindow);
|
||||
codeCompletionWindow.Closed += new EventHandler(OnCodeCompletionWindowClosed);
|
||||
}
|
||||
}
|
||||
else if (key == '(' || key == '[' || key == ',')
|
||||
|
|
@ -131,7 +131,7 @@ namespace VisualPascalABC
|
|||
{
|
||||
insightWindow = new PABCNETInsightWindow(VisualPABCSingleton.MainForm, editor);
|
||||
insightWindow.Font = new Font(Constants.CompletionInsightWindowFontName, insightWindow.Font.Size);
|
||||
insightWindow.Closed += new EventHandler(CloseInsightWindow);
|
||||
insightWindow.Closed += new EventHandler(OnInsightWindowClosed);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -162,9 +162,9 @@ namespace VisualPascalABC
|
|||
false,
|
||||
keyw
|
||||
);
|
||||
CodeCompletionNamesOnlyInModuleAction.comp_windows[editor.ActiveTextAreaControl.TextArea] = codeCompletionWindow;
|
||||
CodeCompletionShiftSpaceActions.comp_windows[editor.ActiveTextAreaControl.TextArea] = codeCompletionWindow;
|
||||
if (codeCompletionWindow != null)
|
||||
codeCompletionWindow.Closed += new EventHandler(CloseCodeCompletionWindow);
|
||||
codeCompletionWindow.Closed += new EventHandler(OnCodeCompletionWindowClosed);
|
||||
//return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -198,8 +198,10 @@ namespace VisualPascalABC
|
|||
if (CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsDefinitionIdentifierAfterKeyword(keyw))
|
||||
return false;
|
||||
|
||||
// если не первый символ выражения (предыдущий тоже буква или "_"), то не открываем новое окно
|
||||
if (editor.ActiveTextAreaControl.TextArea.Caret.Offset > 0 && (char.IsLetterOrDigit(editor.Document.TextContent[editor.ActiveTextAreaControl.TextArea.Caret.Offset - 1]) || editor.Document.TextContent[editor.ActiveTextAreaControl.TextArea.Caret.Offset - 1] == '_'))
|
||||
return false;
|
||||
|
||||
completionDataProvider = new CodeCompletionProvider();
|
||||
codeCompletionWindow = PABCNETCodeCompletionWindow.ShowCompletionWindowWithFirstChar(
|
||||
VisualPABCSingleton.MainForm, // The parent window for the completion window
|
||||
|
|
@ -209,9 +211,9 @@ namespace VisualPascalABC
|
|||
key, // Key pressed - will be passed to the provider
|
||||
keyw
|
||||
);
|
||||
CodeCompletionNamesOnlyInModuleAction.comp_windows[editor.ActiveTextAreaControl.TextArea] = codeCompletionWindow;
|
||||
CodeCompletionShiftSpaceActions.comp_windows[editor.ActiveTextAreaControl.TextArea] = codeCompletionWindow;
|
||||
if (codeCompletionWindow != null)
|
||||
codeCompletionWindow.Closed += new EventHandler(CloseCodeCompletionWindow);
|
||||
codeCompletionWindow.Closed += new EventHandler(OnCodeCompletionWindowClosed);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -253,26 +255,26 @@ namespace VisualPascalABC
|
|||
return false;
|
||||
}
|
||||
|
||||
void CloseInsightWindow(object sender, EventArgs e)
|
||||
void OnInsightWindowClosed(object sender, EventArgs e)
|
||||
{
|
||||
if (insightWindow != null)
|
||||
{
|
||||
insightWindow.Closed -= new EventHandler(CloseInsightWindow);
|
||||
insightWindow.Closed -= new EventHandler(OnInsightWindowClosed);
|
||||
insightWindow.Dispose();
|
||||
insightWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
void CloseCodeCompletionWindow(object sender, EventArgs e)
|
||||
void OnCodeCompletionWindowClosed(object sender, EventArgs e)
|
||||
{
|
||||
if (codeCompletionWindow != null)
|
||||
{
|
||||
codeCompletionWindow.Closed -= new EventHandler(CloseCodeCompletionWindow);
|
||||
codeCompletionWindow.Closed -= new EventHandler(OnCodeCompletionWindowClosed);
|
||||
CodeCompletionProvider.disp.Reset();
|
||||
CodeCompletion.AssemblyDocCache.Reset();
|
||||
CodeCompletion.UnitDocCache.Reset();
|
||||
codeCompletionWindow.Dispose();
|
||||
CodeCompletionNamesOnlyInModuleAction.comp_windows[editor.ActiveTextAreaControl.TextArea] = null;
|
||||
CodeCompletionShiftSpaceActions.comp_windows[editor.ActiveTextAreaControl.TextArea] = null;
|
||||
codeCompletionWindow = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||||
// 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;
|
||||
|
|
@ -9,6 +9,7 @@ using ICSharpCode.TextEditor;
|
|||
using ICSharpCode.TextEditor.Gui.CompletionWindow;
|
||||
using PascalABCCompiler.Parsers;
|
||||
using Languages.Facade;
|
||||
using System.Linq;
|
||||
|
||||
namespace VisualPascalABC
|
||||
{
|
||||
|
|
@ -113,12 +114,6 @@ namespace VisualPascalABC
|
|||
|
||||
if (VisualPABCSingleton.MainForm.VisualEnvironmentCompiler.compilerLoaded)
|
||||
e = language.Parser.GetExpression("test" + System.IO.Path.GetExtension(fileName), expr, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
if (e is PascalABCCompiler.SyntaxTree.bin_expr && expr.Contains("<"))
|
||||
{
|
||||
expr = expr.Replace("<","&<");
|
||||
Errors.Clear();
|
||||
e = language.Parser.GetExpression("test" + System.IO.Path.GetExtension(fileName), expr, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
}
|
||||
if (e == null)
|
||||
return loc;
|
||||
CodeCompletion.DomConverter dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[fileName];
|
||||
|
|
@ -321,11 +316,118 @@ namespace VisualPascalABC
|
|||
return expr;
|
||||
}
|
||||
|
||||
public ICompletionData[] GetCompletionDataByFirst(int off, string Text, int line, int col, char charTyped, PascalABCCompiler.Parsers.KeywordKind keyw)
|
||||
/// <summary>
|
||||
/// Возвращает подсказки определяемые первым символом выражения, введенного пользователем
|
||||
/// </summary>
|
||||
public ICompletionData[] GetCompletionDataByFirst(int line, int col, char charTyped, KeywordKind keyw)
|
||||
{
|
||||
List<ICompletionData> resultList = new List<ICompletionData>();
|
||||
List<ICompletionData> lst = new List<ICompletionData>();
|
||||
try
|
||||
{
|
||||
|
||||
ILanguageInformation languageInformation = CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation;
|
||||
|
||||
List<string> keywords;
|
||||
|
||||
bool isTypeAfterKeyword = false;
|
||||
|
||||
// если по смыслу должен вводиться тип данных
|
||||
if (languageInformation.IsTypeAfterKeyword(keyw))
|
||||
{
|
||||
keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetTypeKeywords();
|
||||
isTypeAfterKeyword = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetKeywords();
|
||||
}
|
||||
|
||||
bool isNamespaceAfterKeyword = false;
|
||||
|
||||
// конструкция типа "uses"
|
||||
if (languageInformation.IsNamespaceAfterKeyword(keyw))
|
||||
{
|
||||
isNamespaceAfterKeyword = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultList.AddRange(keywords.Select(keyword =>
|
||||
new UserDefaultCompletionData(keyword, null, ImagesProvider.IconNumberKeyword, false)));
|
||||
}
|
||||
|
||||
SymInfo[] symInfos = GetSymInfosForCompletionDataByFirst(line, col, isTypeAfterKeyword, isNamespaceAfterKeyword, charTyped.ToString());
|
||||
|
||||
if (symInfos != null)
|
||||
{
|
||||
bool languageCaseSensitive = LanguageProvider.Instance.SelectLanguageByExtension(FileName).CaseSensitive;
|
||||
|
||||
AddCompletionDatasByFirstForSymInfos(resultList, charTyped, symInfos, languageCaseSensitive);
|
||||
|
||||
//resultList.Sort();
|
||||
//defaultCompletionElement = resultList[0] as DefaultCompletionData;
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
this.ByFirstChar = true;
|
||||
|
||||
return resultList.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавляет в resultList (итоговый список подсказок) данные, соответствующие переданному массиву типа SymInfo[].
|
||||
/// Используется для случая ввода пользователем первого символа выражения
|
||||
/// </summary>
|
||||
private void AddCompletionDatasByFirstForSymInfos(List<ICompletionData> resultList, char charTyped, SymInfo[] symInfos, bool languageCaseSensitive)
|
||||
{
|
||||
HashSet<string> symbolsAdded = languageCaseSensitive ? new HashSet<string>() : new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
List<ICompletionData> candidatesForDefault = new List<ICompletionData>();
|
||||
|
||||
bool stop = false;
|
||||
ICompletionData lastUsedItem = CompletionDataDispatcher.GetLastUsedItem(charTyped);
|
||||
|
||||
foreach (SymInfo symInfo in symInfos)
|
||||
{
|
||||
if (symInfo == null || symInfo.not_include) continue;
|
||||
|
||||
if (symbolsAdded.Contains(symInfo.name))
|
||||
continue;
|
||||
|
||||
UserDefaultCompletionData completionData = new UserDefaultCompletionData(symInfo.name, symInfo.description, ImagesProvider.GetPictureNum(symInfo), false);
|
||||
|
||||
StringComparison stringComparison = languageCaseSensitive ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase;
|
||||
|
||||
// если мы выбирали что-то раньше из списка подсказок, то считаем это элементом по умолчанию
|
||||
if (!stop && lastUsedItem != null && string.Equals(symInfo.name, lastUsedItem.Text, stringComparison))
|
||||
{
|
||||
defaultCompletionElement = completionData;
|
||||
stop = true;
|
||||
}
|
||||
// иначе формируем список подходящих подсказок - "кандидатов" для элемента по умолчанию
|
||||
else if (!stop && lastUsedItem == null && symInfo.name.StartsWith(charTyped.ToString(), stringComparison))
|
||||
{
|
||||
//defaultCompletionElement = ddd;
|
||||
candidatesForDefault.Add(completionData);
|
||||
//stop = true;
|
||||
}
|
||||
|
||||
disp.Add(symInfo, completionData);
|
||||
|
||||
resultList.Add(completionData);
|
||||
|
||||
symbolsAdded.Add(symInfo.name);
|
||||
}
|
||||
|
||||
if (candidatesForDefault.Count > 0)
|
||||
defaultCompletionElement = candidatesForDefault.Min() as UserDefaultCompletionData; // здесь выбирается минимальное по длине
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Формирует массив данных из таблицы символов для подсказок в случае введения пользователем первой буквы выражения
|
||||
/// </summary>
|
||||
private SymInfo[] GetSymInfosForCompletionDataByFirst(int line, int col, bool isTypeAfterKeyword, bool isNamespaceAfterKeyword, string pattern)
|
||||
{
|
||||
CodeCompletion.DomConverter dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[FileName];
|
||||
/*if (dconv == null && CodeCompletion.CodeCompletionNameHelper.system_unit_file_full_name != null
|
||||
|
|
@ -334,238 +436,292 @@ namespace VisualPascalABC
|
|||
dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[CodeCompletion.CodeCompletionNameHelper.system_unit_file_full_name];
|
||||
special_module = true;
|
||||
}*/
|
||||
string pattern = charTyped.ToString();
|
||||
string[] keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetKeywords();
|
||||
if (CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsTypeAfterKeyword(keyw))
|
||||
|
||||
SymInfo[] symInfos = null;
|
||||
|
||||
if (dconv == null)
|
||||
{
|
||||
keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetTypeKeywords();
|
||||
}
|
||||
if (!CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsNamespaceAfterKeyword(keyw))
|
||||
foreach (string key in keywords)
|
||||
if (isNamespaceAfterKeyword)
|
||||
{
|
||||
//if (key.StartsWith(pattern, StringComparison.CurrentCultureIgnoreCase))
|
||||
resultList.Add(new UserDefaultCompletionData(key, null, ImagesProvider.IconNumberKeyword, false));
|
||||
symInfos = CodeCompletion.DomConverter.standard_units;
|
||||
}
|
||||
PascalABCCompiler.Parsers.SymInfo[] mis = null;
|
||||
if (CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsNamespaceAfterKeyword(keyw))
|
||||
{
|
||||
mis = CodeCompletion.DomConverter.standard_units;
|
||||
}
|
||||
if (dconv != null)
|
||||
else
|
||||
{
|
||||
//if (keyw == PascalABCCompiler.Parsers.KeywordKind.Colon || keyw == PascalABCCompiler.Parsers.KeywordKind.Of || keyw == PascalABCCompiler.Parsers.KeywordKind.TypeDecl)
|
||||
if (CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsTypeAfterKeyword(keyw))
|
||||
mis = dconv.GetTypeByPattern(pattern, line, col, true, VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
else if (CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsNamespaceAfterKeyword(keyw) && mis == null)
|
||||
mis = dconv.GetNamespaces();
|
||||
if (isTypeAfterKeyword)
|
||||
{
|
||||
symInfos = dconv.GetTypeByPattern(pattern, line, col, true, VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
}
|
||||
else if (isNamespaceAfterKeyword)
|
||||
{
|
||||
if (WorkbenchServiceFactory.Workbench.UserOptions.EnableSmartIntellisense)
|
||||
symInfos = dconv.GetNamespaces();
|
||||
else
|
||||
mis = dconv.GetNameByPattern(null, line, col, true, VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
symInfos = CodeCompletion.DomConverter.standard_units;
|
||||
}
|
||||
Hashtable cache = new Hashtable();
|
||||
if (mis != null)
|
||||
else
|
||||
{
|
||||
bool stop = false;
|
||||
ICompletionData data = CompletionDataDispatcher.GetLastUsedItem(charTyped);
|
||||
foreach (PascalABCCompiler.Parsers.SymInfo mi in mis)
|
||||
{
|
||||
if (mi.not_include) continue;
|
||||
|
||||
if (cache.Contains(mi.name))
|
||||
continue;
|
||||
|
||||
UserDefaultCompletionData ddd = new UserDefaultCompletionData(mi.name, mi.description, ImagesProvider.GetPictureNum(mi), false);
|
||||
if (!stop && data != null && string.Compare(mi.name, data.Text, true) == 0)
|
||||
{
|
||||
defaultCompletionElement = ddd;
|
||||
stop = true;
|
||||
// интересно, что передается pattern = null EVA
|
||||
symInfos = dconv.GetNameByPattern(null, line, col, true, VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
}
|
||||
else if (!stop && data == null && mi.name.StartsWith(charTyped.ToString(), StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
//defaultCompletionElement = ddd;
|
||||
lst.Add(ddd);
|
||||
//stop = true;
|
||||
}
|
||||
disp.Add(mi, ddd);
|
||||
resultList.Add(ddd);
|
||||
cache[mi.name] = mi;
|
||||
}
|
||||
//resultList.Sort();
|
||||
//defaultCompletionElement = resultList[0] as DefaultCompletionData;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
lst.Sort();
|
||||
if (lst.Count > 0) defaultCompletionElement = lst[0] as UserDefaultCompletionData;
|
||||
ICompletionData[] res_arr = resultList.ToArray();
|
||||
this.ByFirstChar = true;
|
||||
return res_arr;
|
||||
return symInfos;
|
||||
}
|
||||
|
||||
public ICompletionData[] GetCompletionData(int off, string Text, int line, int col, char charTyped, PascalABCCompiler.Parsers.KeywordKind keyw)
|
||||
/// <summary>
|
||||
/// Вспомогательная струтура для метода GetCompletionData, хранит информацию о действиях пользователя
|
||||
/// </summary>
|
||||
private struct ActionContext
|
||||
{
|
||||
public bool dotPressed;
|
||||
public bool ctrlSpace;
|
||||
public bool shiftSpace;
|
||||
public bool spaceAfterNew;
|
||||
public bool spaceAfterUses;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает массив подсказок для случая нажатия пользователем "триггерной" клавиши
|
||||
/// </summary>
|
||||
public ICompletionData[] GetCompletionData(int off, string text, int line, int col, char charTyped, KeywordKind keywordKind)
|
||||
{
|
||||
List<ICompletionData> resultList = new List<ICompletionData>();
|
||||
try
|
||||
{
|
||||
string pattern = null;
|
||||
string expr = null;
|
||||
bool ctrl_space = charTyped == '\0' || charTyped == '_';
|
||||
bool shift_space = charTyped == '\0';
|
||||
bool inside_dot_pattern = false;
|
||||
bool new_space = keyw == PascalABCCompiler.Parsers.KeywordKind.New;
|
||||
if (ctrl_space)
|
||||
// поменять на обращение к CodeCompletionController.CurrentLanguage
|
||||
ILanguage currentLanguage = LanguageProvider.Instance.SelectLanguageByExtension(FileName);
|
||||
|
||||
var context = new ActionContext()
|
||||
{
|
||||
bool is_pattern = false;
|
||||
pattern = CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.FindPattern(off, Text, out is_pattern);
|
||||
if (is_pattern && Text[off - pattern.Length - 1] == '.')
|
||||
dotPressed = charTyped == '.',
|
||||
ctrlSpace = charTyped == '_',
|
||||
shiftSpace = charTyped == '\0',
|
||||
spaceAfterNew = keywordKind == KeywordKind.New,
|
||||
spaceAfterUses = keywordKind == KeywordKind.Uses
|
||||
};
|
||||
|
||||
string expressionText = GetExpressionTextForCompletionData(off, text, line, col,
|
||||
currentLanguage.LanguageInformation, in context, out var insidePatternWithDots, out var ctrlOrShiftSpaceAfterDot, out var pattern);
|
||||
|
||||
// добавляем ключевые слова в случае "ctrl + space", нажатых в "пустом" месте
|
||||
if (!ctrlOrShiftSpaceAfterDot && context.ctrlSpace && string.IsNullOrEmpty(pattern))
|
||||
{
|
||||
inside_dot_pattern = true;
|
||||
expr = FindExpression(off - pattern.Length - 1, Text, line, col);
|
||||
var keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetKeywords();
|
||||
|
||||
resultList.AddRange(keywords.Select(keyword =>
|
||||
new UserDefaultCompletionData(keyword, null, ImagesProvider.IconNumberKeyword, false)));
|
||||
}
|
||||
|
||||
}
|
||||
else if (new_space)
|
||||
PascalABCCompiler.SyntaxTree.expression expr = null;
|
||||
|
||||
// для "ctrl + space" и "shift + space" дерево expression не требуется (кроме случая insidePatternWithDots)
|
||||
if ((context.dotPressed || context.spaceAfterNew || context.spaceAfterUses || insidePatternWithDots) && expressionText != null)
|
||||
{
|
||||
expr = CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.SkipNew(off - 1, Text, ref keyword);
|
||||
}
|
||||
else
|
||||
if (!new_space && keyw != PascalABCCompiler.Parsers.KeywordKind.Uses)
|
||||
if (charTyped != '$')
|
||||
expr = FindExpression(off, Text, line, col);
|
||||
else
|
||||
expr = FindExpression(off - 1, Text, line, col);
|
||||
List<PascalABCCompiler.Errors.Error> Errors = new List<PascalABCCompiler.Errors.Error>();
|
||||
PascalABCCompiler.SyntaxTree.expression e = null;
|
||||
if (ctrl_space && !shift_space && (pattern == null || pattern == ""))
|
||||
{
|
||||
string[] keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetKeywords();
|
||||
foreach (string key in keywords)
|
||||
{
|
||||
//if (key.StartsWith(pattern, StringComparison.CurrentCultureIgnoreCase))
|
||||
resultList.Add(new UserDefaultCompletionData(key, null, ImagesProvider.IconNumberKeyword, false));
|
||||
}
|
||||
expr = GetExpressionForCompletionData(currentLanguage.Parser,
|
||||
in context, expressionText, insidePatternWithDots, out var shouldReturnNull);
|
||||
|
||||
if (shouldReturnNull)
|
||||
return null;
|
||||
}
|
||||
|
||||
ILanguage currentLanguage = LanguageProvider.Instance.SelectLanguageByExtensionSafe(FileName);
|
||||
SymInfo[] symInfos = GetSymInfosForCompletionData(line, col, in context, currentLanguage.CaseSensitive,
|
||||
expressionText, ctrlOrShiftSpaceAfterDot, insidePatternWithDots, pattern, expr, out var selectedSymInfo, out var lastUsedMember, out var shouldReturnNull2);
|
||||
|
||||
if (currentLanguage == null)
|
||||
if (shouldReturnNull2)
|
||||
return null;
|
||||
|
||||
if ((!ctrl_space || inside_dot_pattern) && expr != null)
|
||||
if (symInfos != null)
|
||||
{
|
||||
e = currentLanguage.Parser.GetTypeAsExpression("test" + System.IO.Path.GetExtension(FileName), expr, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
if (e == null)
|
||||
{
|
||||
Errors.Clear();
|
||||
e = currentLanguage.Parser.GetExpression("test" + System.IO.Path.GetExtension(FileName), expr, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
AddCompletionDatasForSymInfos(resultList, currentLanguage.CaseSensitive, symInfos, selectedSymInfo, lastUsedMember);
|
||||
}
|
||||
if ((e == null || Errors.Count > 0) && !new_space) return null;
|
||||
}
|
||||
SymInfo[] mis = null;
|
||||
CodeCompletion.DomConverter dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[FileName];
|
||||
if (dconv == null)
|
||||
{
|
||||
if (keyw == PascalABCCompiler.Parsers.KeywordKind.Uses)
|
||||
mis = CodeCompletion.DomConverter.standard_units;
|
||||
else if (!ctrl_space)
|
||||
return new ICompletionData[0];
|
||||
}
|
||||
string fname = FileName;
|
||||
SymInfo sel_si = null;
|
||||
string last_used_member = null;
|
||||
if (dconv != null)
|
||||
{
|
||||
if (new_space)
|
||||
mis = dconv.GetTypes(e, line, col, out sel_si);
|
||||
else if (keyw == PascalABCCompiler.Parsers.KeywordKind.Uses && mis == null)
|
||||
{
|
||||
if (WorkbenchServiceFactory.Workbench.UserOptions.EnableSmartIntellisense)
|
||||
mis = dconv.GetNamespaces();
|
||||
else
|
||||
mis = CodeCompletion.DomConverter.standard_units;
|
||||
catch (Exception) { }
|
||||
|
||||
return resultList.ToArray();
|
||||
}
|
||||
|
||||
else
|
||||
if (!ctrl_space)
|
||||
/// <summary>
|
||||
/// Добавляет в resultList (итоговый список подсказок) данные, соответствующие переданному массиву типа SymInfo[].
|
||||
/// Используется для случая нажатия пользователем "триггерной" клавиши
|
||||
/// </summary>
|
||||
private void AddCompletionDatasForSymInfos(List<ICompletionData> resultList, bool languageCaseSensitive, SymInfo[] symInfos, SymInfo selectedSymInfo, string lastUsedMember)
|
||||
{
|
||||
CodeCompletion.SymScope dot_sc = null;
|
||||
mis = dconv.GetName(e, expr, line, col, keyword, ref dot_sc);
|
||||
if (dot_sc != null && VisualPABCSingleton.MainForm.UserOptions.EnableSmartIntellisense)
|
||||
{
|
||||
CompletionDataDispatcher.AddMemberBeforeDot(dot_sc);
|
||||
last_used_member = CompletionDataDispatcher.GetRecentUsedMember(dot_sc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CodeCompletion.SymScope dot_sc = null;
|
||||
if (inside_dot_pattern)
|
||||
{
|
||||
List<SymInfo> si_list = new List<SymInfo>();
|
||||
SymInfo[] from_list = dconv.GetName(e, expr, line, col, keyword, ref dot_sc);
|
||||
for (int i = 0; i < from_list.Length; i++)
|
||||
{
|
||||
if (from_list[i].name.StartsWith(pattern, StringComparison.OrdinalIgnoreCase))
|
||||
si_list.Add(from_list[i]);
|
||||
}
|
||||
mis = si_list.ToArray();
|
||||
}
|
||||
// ICompletionData data = null;
|
||||
|
||||
else
|
||||
mis = dconv.GetNameByPattern(pattern, line, col, charTyped == '_', VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
}
|
||||
HashSet<string> symbolsAdded = languageCaseSensitive ? new HashSet<string>() : new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
}
|
||||
Hashtable cache = null;
|
||||
if (!currentLanguage.CaseSensitive)
|
||||
cache = new Hashtable(StringComparer.CurrentCultureIgnoreCase);
|
||||
else
|
||||
cache = new Hashtable();
|
||||
int num = 0;
|
||||
if (mis != null)
|
||||
foreach (SymInfo symInfo in symInfos)
|
||||
{
|
||||
bool stop = false;
|
||||
ICompletionData data = null;
|
||||
|
||||
foreach (SymInfo mi in mis)
|
||||
{
|
||||
if (mi == null || mi.not_include) continue;
|
||||
if (cache.Contains(mi.name + mi.kind))
|
||||
if (symInfo == null || symInfo.not_include)
|
||||
continue;
|
||||
|
||||
UserDefaultCompletionData ddd = new UserDefaultCompletionData(mi.addit_name != null ? mi.addit_name : mi.name, mi.description, ImagesProvider.GetPictureNum(mi), false);
|
||||
if (symbolsAdded.Contains(symInfo.name + symInfo.kind))
|
||||
continue;
|
||||
|
||||
UserDefaultCompletionData completionData = new UserDefaultCompletionData(
|
||||
symInfo.addit_name != null ? symInfo.addit_name : symInfo.name,
|
||||
symInfo.description, ImagesProvider.GetPictureNum(symInfo), false
|
||||
);
|
||||
|
||||
disp.Add(symInfo, completionData);
|
||||
|
||||
resultList.Add(completionData);
|
||||
|
||||
symbolsAdded.Add(symInfo.name + symInfo.kind);
|
||||
|
||||
disp.Add(mi, ddd);
|
||||
resultList.Add(ddd);
|
||||
cache[mi.name + mi.kind] = mi;
|
||||
/*if (VisualPABCSingleton.MainForm.UserOptions.EnableSmartIntellisense && mi.name != null && mi.name != "" && data == null)
|
||||
{
|
||||
data = CompletionDataDispatcher.GetLastUsedItem(mi.name[0]);
|
||||
if (data != null && data.Text == ddd.Text) data = ddd;
|
||||
}*/
|
||||
if (last_used_member != null && last_used_member == mi.name)
|
||||
|
||||
if (lastUsedMember != null && lastUsedMember == symInfo.name || selectedSymInfo != null && symInfo == selectedSymInfo)
|
||||
{
|
||||
defaultCompletionElement = ddd;
|
||||
}
|
||||
if (sel_si != null && mi == sel_si)
|
||||
{
|
||||
defaultCompletionElement = ddd;
|
||||
stop = true;
|
||||
defaultCompletionElement = completionData;
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultCompletionElement == null && data != null)
|
||||
defaultCompletionElement = data as UserDefaultCompletionData;
|
||||
/*if (defaultCompletionElement == null && data != null)
|
||||
defaultCompletionElement = data as UserDefaultCompletionData;*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Формирует массив данных из таблицы символов для подсказок в случае нажатия пользователем "триггерной" клавиши
|
||||
/// (в зависимости от введенного выражения и другого контекста)
|
||||
/// </summary>
|
||||
private SymInfo[] GetSymInfosForCompletionData(int line, int col, in ActionContext context, bool languageCaseSensitive, string expressionText, bool ctrlOrShiftSpaceAfterDot, bool insidePatternWithDots, string pattern, PascalABCCompiler.SyntaxTree.expression expr, out SymInfo selectedSymInfo, out string lastUsedMember, out bool shouldReturnNull)
|
||||
{
|
||||
SymInfo[] symInfos = null;
|
||||
|
||||
shouldReturnNull = false;
|
||||
|
||||
selectedSymInfo = null;
|
||||
lastUsedMember = null;
|
||||
|
||||
CodeCompletion.DomConverter dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[FileName];
|
||||
|
||||
if (dconv == null)
|
||||
{
|
||||
// в данном случае возвращаем пустой массив ICompletionData
|
||||
if (!context.spaceAfterUses && !context.ctrlSpace)
|
||||
shouldReturnNull = true;
|
||||
|
||||
if (context.spaceAfterUses)
|
||||
symInfos = CodeCompletion.DomConverter.standard_units;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context.spaceAfterNew)
|
||||
{
|
||||
symInfos = dconv.GetTypes(expr, line, col, out selectedSymInfo);
|
||||
}
|
||||
else if (context.spaceAfterUses)
|
||||
{
|
||||
if (WorkbenchServiceFactory.Workbench.UserOptions.EnableSmartIntellisense)
|
||||
symInfos = dconv.GetNamespaces();
|
||||
else
|
||||
symInfos = CodeCompletion.DomConverter.standard_units;
|
||||
}
|
||||
// нажатие ctrl + space и shift + space сразу после точки приравнивается к нажатию точки
|
||||
else if (context.dotPressed || ctrlOrShiftSpaceAfterDot)
|
||||
{
|
||||
CodeCompletion.SymScope dotScope = null;
|
||||
symInfos = dconv.GetName(expr, expressionText, line, col, keyword, ref dotScope);
|
||||
|
||||
if (dotScope != null && VisualPABCSingleton.MainForm.UserOptions.EnableSmartIntellisense)
|
||||
{
|
||||
CompletionDataDispatcher.AddMemberBeforeDot(dotScope);
|
||||
lastUsedMember = CompletionDataDispatcher.GetRecentUsedMember(dotScope);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
// ctrl + space после некоторого выражения
|
||||
else if (context.ctrlSpace) // context.chiftSpace здесь не может быть true, поскольку такие ситуации обрабатываются в ShiftSpaceActions.Execute()
|
||||
{
|
||||
CodeCompletion.SymScope dotScope = null;
|
||||
|
||||
// если мы в цепочечном выражении с точками
|
||||
if (insidePatternWithDots)
|
||||
{
|
||||
|
||||
symInfos = dconv.GetName(expr, expressionText, line, col, keyword, ref dotScope)
|
||||
.Where(symInfo => symInfo.name.StartsWith(pattern,
|
||||
languageCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))
|
||||
.ToArray();
|
||||
}
|
||||
return resultList.ToArray();
|
||||
else
|
||||
symInfos = dconv.GetNameByPattern(pattern, line, col, context.ctrlSpace, VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return symInfos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает дерево выражения, введенного пользователем перед нажатием "триггерной" клавиши
|
||||
/// </summary>
|
||||
private PascalABCCompiler.SyntaxTree.expression GetExpressionForCompletionData(IParser parser, in ActionContext context, string expressionText, bool insidePatternWithDots, out bool shouldReturnNull)
|
||||
{
|
||||
shouldReturnNull = false;
|
||||
|
||||
List<PascalABCCompiler.Errors.Error> Errors = new List<PascalABCCompiler.Errors.Error>();
|
||||
List<PascalABCCompiler.Errors.CompilerWarning> Warnings = new List<PascalABCCompiler.Errors.CompilerWarning>();
|
||||
|
||||
var expr = parser.GetTypeAsExpression("test" + System.IO.Path.GetExtension(FileName), expressionText, Errors, Warnings);
|
||||
if (expr == null)
|
||||
{
|
||||
Errors.Clear();
|
||||
expr = parser.GetExpression("test" + System.IO.Path.GetExtension(FileName), expressionText, Errors, Warnings);
|
||||
}
|
||||
|
||||
if ((expr == null || Errors.Count > 0) && !context.spaceAfterNew)
|
||||
shouldReturnNull = true;
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение текста выражения, введенного пользователем перед нажатием "триггерной" клавиши
|
||||
/// </summary>
|
||||
private string GetExpressionTextForCompletionData(int off, string text, int line, int col, ILanguageInformation languageInformation, in ActionContext context, out bool insidePatternWithDots, out bool ctrlOrShiftSpaceAfterDot, out string pattern)
|
||||
{
|
||||
|
||||
string expressionText = null;
|
||||
pattern = null;
|
||||
insidePatternWithDots = false;
|
||||
ctrlOrShiftSpaceAfterDot = false;
|
||||
|
||||
if (context.ctrlSpace || context.shiftSpace)
|
||||
{
|
||||
|
||||
pattern = languageInformation.FindPattern(off, text, out var isPattern);
|
||||
|
||||
// в конце выражения точка
|
||||
if (!isPattern && text[off - 1] == '.')
|
||||
{
|
||||
ctrlOrShiftSpaceAfterDot = true;
|
||||
}
|
||||
|
||||
// если нужно подсказать все варианты после точки, то поведение как в случае context.dotPressed
|
||||
if (isPattern && text[off - pattern.Length - 1] == '.' || ctrlOrShiftSpaceAfterDot)
|
||||
{
|
||||
insidePatternWithDots = true;
|
||||
expressionText = FindExpression(off - (pattern?.Length ?? 0) - 1, text, line, col);
|
||||
}
|
||||
|
||||
}
|
||||
else if (context.spaceAfterNew)
|
||||
{
|
||||
expressionText = languageInformation.SkipNew(off - 1, text, ref keyword);
|
||||
}
|
||||
else if (context.dotPressed) // keywordKind != KeywordKind.Uses
|
||||
{
|
||||
expressionText = FindExpression(off, text, line, col);
|
||||
}
|
||||
|
||||
return expressionText;
|
||||
}
|
||||
|
||||
private CodeCompletion.CodeCompletionController controller;
|
||||
|
|
@ -636,11 +792,11 @@ namespace VisualPascalABC
|
|||
public ICompletionData[] GenerateCompletionDataByFirstChar(string fileName, TextArea textArea, char charTyped, PascalABCCompiler.Parsers.KeywordKind keyw)
|
||||
{
|
||||
controller = new CodeCompletion.CodeCompletionController();
|
||||
int off = textArea.Caret.Offset;
|
||||
// int off = textArea.Caret.Offset;
|
||||
string text = textArea.Document.TextContent.Substring(0, textArea.Caret.Offset);
|
||||
//controller.Compile(file_name, text /*+ ")))));end."*/);
|
||||
FileName = fileName; Text = text;
|
||||
ICompletionData[] data = GetCompletionDataByFirst(off, text, textArea.Caret.Line, textArea.Caret.Column, charTyped, keyw);
|
||||
ICompletionData[] data = GetCompletionDataByFirst(textArea.Caret.Line, textArea.Caret.Column, charTyped, keyw);
|
||||
CodeCompletion.AssemblyDocCache.CompleteDocumentation();
|
||||
CodeCompletion.UnitDocCache.CompleteDocumentation();
|
||||
controller = null;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ namespace VisualPascalABC
|
|||
{
|
||||
public Dictionary<string, string> ht = new Dictionary<string, string>();
|
||||
|
||||
// TODO: Требуется адаптация к многоязычности EVA
|
||||
public CodeTemplateManager(string filename = "template.pct", bool searchFromLocalDirectory = false)
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -4,14 +4,10 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using ICSharpCode.Core;
|
||||
using ICSharpCode.TextEditor;
|
||||
using ICSharpCode.TextEditor.Document;
|
||||
using ICSharpCode.TextEditor.Gui.CompletionWindow;
|
||||
using Languages.Integration;
|
||||
using PascalABCCompiler.Parsers;
|
||||
|
||||
namespace VisualPascalABC
|
||||
|
|
@ -22,65 +18,68 @@ namespace VisualPascalABC
|
|||
|
||||
private static string GetPopupHintText(TextArea textArea, ToolTipRequestEventArgs e)
|
||||
{
|
||||
ICSharpCode.TextEditor.TextLocation logicPos = e.LogicalPosition;
|
||||
TextLocation logicPos = e.LogicalPosition;
|
||||
IDocument doc = textArea.Document;
|
||||
LineSegment seg = doc.GetLineSegment(logicPos.Y);
|
||||
string FileName = textArea.MotherTextEditorControl.FileName;
|
||||
PascalABCCompiler.Parsers.KeywordKind keyw = PascalABCCompiler.Parsers.KeywordKind.None;
|
||||
if (logicPos.X > seg.Length - 1)
|
||||
LineSegment lineSegment = doc.GetLineSegment(logicPos.Y);
|
||||
|
||||
string fileName = textArea.MotherTextEditorControl.FileName;
|
||||
|
||||
if (logicPos.X > lineSegment.Length - 1)
|
||||
return null;
|
||||
|
||||
//string expr = FindFullExpression(doc.TextContent, seg.Offset + logicPos.X,e.LogicalPosition.Line,e.LogicalPosition.Column);
|
||||
string expr_without_brackets = null;
|
||||
string expr = CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.FindExpressionFromAnyPosition(seg.Offset + logicPos.X, doc.TextContent, e.LogicalPosition.Line, e.LogicalPosition.Column, out keyw, out expr_without_brackets);
|
||||
|
||||
IParser parser = CodeCompletion.CodeCompletionController.CurrentParser;
|
||||
|
||||
string expr = parser.LanguageInformation.FindExpressionFromAnyPosition(
|
||||
lineSegment.Offset + logicPos.X, doc.TextContent, e.LogicalPosition.Line, e.LogicalPosition.Column, out var keyw, out var exprWithoutBrackets);
|
||||
|
||||
// пока непонятно, когда такое может быть EVA
|
||||
if (expr == null)
|
||||
expr = exprWithoutBrackets;
|
||||
|
||||
if (expr == null)
|
||||
expr = expr_without_brackets;
|
||||
if (expr_without_brackets == null)
|
||||
return null;
|
||||
|
||||
List<PascalABCCompiler.Errors.Error> Errors = new List<PascalABCCompiler.Errors.Error>();
|
||||
List<PascalABCCompiler.Errors.CompilerWarning> Warnings = new List<PascalABCCompiler.Errors.CompilerWarning>();
|
||||
|
||||
IParser parser = Languages.Facade.LanguageProvider.Instance.SelectLanguageByExtension(FileName).Parser;
|
||||
PascalABCCompiler.SyntaxTree.expression expressionTree = parser.GetExpression("test" + Path.GetExtension(fileName),
|
||||
expr, Errors, Warnings);
|
||||
|
||||
PascalABCCompiler.SyntaxTree.expression tree = parser.GetExpression("test" + Path.GetExtension(FileName), expr, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
bool header = false;
|
||||
if (Errors.Count > 0)
|
||||
{
|
||||
if (expr.IndexOf('<') != -1 && expr.IndexOf('>') != -1)
|
||||
{
|
||||
Errors.Clear();
|
||||
tree = parser.GetExpression("test" + Path.GetExtension(FileName), expr.Replace("<", "&<"), Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
}
|
||||
else
|
||||
// Пока добавили проверку, что анализируем Паскаль EVA
|
||||
if (Errors.Count > 0 && parser == Languages.Facade.LanguageProvider.Instance.SelectLanguageByName(PascalABCCompiler.StringConstants.pascalLanguageName).Parser)
|
||||
{
|
||||
string s = expr.TrimStart();
|
||||
if (s.Length > 0 && s[0] == '^')
|
||||
{
|
||||
Errors.Clear();
|
||||
expr_without_brackets = expr_without_brackets.TrimStart().Substring(1);
|
||||
tree = parser.GetExpression("test" + Path.GetExtension(FileName), s.Substring(1), Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
exprWithoutBrackets = exprWithoutBrackets.TrimStart().Substring(1);
|
||||
expressionTree = parser.GetExpression("test" + Path.GetExtension(fileName), s.Substring(1), Errors, Warnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tree == null || Errors.Count > 0)
|
||||
|
||||
List<PascalABCCompiler.Errors.Error> Errors2 = new List<PascalABCCompiler.Errors.Error>();
|
||||
|
||||
// проверка для выражения без скобок
|
||||
PascalABCCompiler.SyntaxTree.expression expressionTree2 = parser.GetExpression("test" + Path.GetExtension(fileName), exprWithoutBrackets, Errors2, Warnings);
|
||||
|
||||
// если не получается, то сразу возврат
|
||||
if (expressionTree2 == null || Errors2.Count > 0)
|
||||
return null;
|
||||
|
||||
bool header = false;
|
||||
if (expressionTree == null || Errors.Count > 0)
|
||||
{
|
||||
Errors.Clear();
|
||||
tree = parser.GetExpression("test" + Path.GetExtension(FileName), expr_without_brackets, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
header = true;
|
||||
if (tree == null || Errors.Count > 0)
|
||||
return null;
|
||||
expressionTree = expressionTree2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Errors.Clear();
|
||||
PascalABCCompiler.SyntaxTree.expression tree2 = parser.GetExpression("test" + Path.GetExtension(FileName), expr_without_brackets, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
//header = true;
|
||||
if (tree2 == null || Errors.Count > 0)
|
||||
return null;
|
||||
//if (tree is PascalABCCompiler.SyntaxTree.new_expr && (tree as PascalABCCompiler.SyntaxTree.new_expr).params_list == null)
|
||||
// tree = tree2;
|
||||
}
|
||||
CodeCompletion.DomConverter dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[FileName];
|
||||
if (dconv == null) return null;
|
||||
return dconv.GetDescription(tree, FileName, expr_without_brackets, e.LogicalPosition.Line, e.LogicalPosition.Column, keyw, header);
|
||||
|
||||
CodeCompletion.DomConverter domConverter = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[fileName];
|
||||
|
||||
if (domConverter == null) return null;
|
||||
|
||||
return domConverter.GetDescription(expressionTree, fileName, exprWithoutBrackets, e.LogicalPosition.Line, e.LogicalPosition.Column, keyw, header);
|
||||
}
|
||||
|
||||
static int _mouse_hint_x = 0, _mouse_hint_y = 0;
|
||||
|
|
|
|||
|
|
@ -118,22 +118,38 @@ namespace VisualPascalABC
|
|||
|
||||
public static List<Position> GetDefinitionPosition(TextArea textArea, bool only_check)
|
||||
{
|
||||
if (CodeCompletion.CodeCompletionController.CurrentParser == null) return new List<Position>();
|
||||
IParser parser = CodeCompletion.CodeCompletionController.CurrentParser;
|
||||
|
||||
if (parser == null)
|
||||
return new List<Position>();
|
||||
|
||||
IDocument doc = textArea.Document;
|
||||
string textContent = doc.TextContent;
|
||||
ccp = new CodeCompletionProvider();
|
||||
string full_expr;
|
||||
string expressionResult = FindFullExpression(textContent, textArea, out ccp.keyword, out full_expr);
|
||||
|
||||
if (expressionResult != null)
|
||||
expressionResult = expressionResult.Trim();
|
||||
|
||||
|
||||
// Проверка, что компилируем Паскаль временно EVA 10.11.2024
|
||||
if (parser == Languages.Facade.LanguageProvider.Instance.SelectLanguageByName(StringConstants.pascalLanguageName).Parser)
|
||||
{
|
||||
if (expressionResult != full_expr && full_expr.StartsWith("("))
|
||||
return new List<Position>();
|
||||
|
||||
if (full_expr != null && full_expr.Contains("^"))
|
||||
full_expr = full_expr.Replace("^","");
|
||||
{
|
||||
full_expr = full_expr.Replace("^", "");
|
||||
}
|
||||
}
|
||||
|
||||
List<Position> poses = ccp.GetDefinition(full_expr, textArea.MotherTextEditorControl.FileName, textArea.Caret.Line, textArea.Caret.Column, only_check);
|
||||
|
||||
if (poses == null || poses.Count == 0)
|
||||
poses = ccp.GetDefinition(expressionResult, textArea.MotherTextEditorControl.FileName, textArea.Caret.Line, textArea.Caret.Column, only_check);
|
||||
|
||||
return poses;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||||
// 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;
|
||||
|
|
@ -199,8 +199,10 @@ namespace VisualPascalABC
|
|||
if (CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsDefinitionIdentifierAfterKeyword(keyw))
|
||||
return false;
|
||||
|
||||
// если не первый символ выражения (предыдущий тоже буква или "_"), то не открываем новое окно
|
||||
if (editor.ActiveTextAreaControl.TextArea.Caret.Offset > 0 && (char.IsLetterOrDigit(editor.Document.TextContent[editor.ActiveTextAreaControl.TextArea.Caret.Offset - 1]) || editor.Document.TextContent[editor.ActiveTextAreaControl.TextArea.Caret.Offset - 1] == '_'))
|
||||
return false;
|
||||
|
||||
completionDataProvider = new CodeCompletionProvider();
|
||||
codeCompletionWindow = PABCNETCodeCompletionWindow.ShowCompletionWindowWithFirstChar(
|
||||
VisualPABCSingleton.MainForm, // The parent window for the completion window
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||||
// 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.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using ICSharpCode.TextEditor;
|
||||
|
|
@ -113,12 +114,6 @@ namespace VisualPascalABC
|
|||
|
||||
if (VisualPABCSingleton.MainForm.VisualEnvironmentCompiler.compilerLoaded)
|
||||
e = language.Parser.GetExpression("test" + System.IO.Path.GetExtension(fileName), expr, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
if (e is PascalABCCompiler.SyntaxTree.bin_expr && expr.Contains("<"))
|
||||
{
|
||||
expr = expr.Replace("<","&<");
|
||||
Errors.Clear();
|
||||
e = language.Parser.GetExpression("test" + System.IO.Path.GetExtension(fileName), expr, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
}
|
||||
if (e == null)
|
||||
return loc;
|
||||
CodeCompletion.DomConverter dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[fileName];
|
||||
|
|
@ -321,11 +316,118 @@ namespace VisualPascalABC
|
|||
return expr;
|
||||
}
|
||||
|
||||
public ICompletionData[] GetCompletionDataByFirst(int off, string Text, int line, int col, char charTyped, PascalABCCompiler.Parsers.KeywordKind keyw)
|
||||
/// <summary>
|
||||
/// Возвращает подсказки определяемые первым символом выражения, введенного пользователем
|
||||
/// </summary>
|
||||
public ICompletionData[] GetCompletionDataByFirst(int line, int col, char charTyped, KeywordKind keyw)
|
||||
{
|
||||
List<ICompletionData> resultList = new List<ICompletionData>();
|
||||
List<ICompletionData> lst = new List<ICompletionData>();
|
||||
try
|
||||
{
|
||||
|
||||
ILanguageInformation languageInformation = CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation;
|
||||
|
||||
List<string> keywords;
|
||||
|
||||
bool isTypeAfterKeyword = false;
|
||||
|
||||
// если по смыслу должен вводиться тип данных
|
||||
if (languageInformation.IsTypeAfterKeyword(keyw))
|
||||
{
|
||||
keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetTypeKeywords();
|
||||
isTypeAfterKeyword = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetKeywords();
|
||||
}
|
||||
|
||||
bool isNamespaceAfterKeyword = false;
|
||||
|
||||
// конструкция типа "uses"
|
||||
if (languageInformation.IsNamespaceAfterKeyword(keyw))
|
||||
{
|
||||
isNamespaceAfterKeyword = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultList.AddRange(keywords.Select(keyword =>
|
||||
new UserDefaultCompletionData(keyword, null, ImagesProvider.IconNumberKeyword, false)));
|
||||
}
|
||||
|
||||
SymInfo[] symInfos = GetSymInfosForCompletionDataByFirst(line, col, isTypeAfterKeyword, isNamespaceAfterKeyword, charTyped.ToString());
|
||||
|
||||
if (symInfos != null)
|
||||
{
|
||||
bool languageCaseSensitive = LanguageProvider.Instance.SelectLanguageByExtension(FileName).CaseSensitive;
|
||||
|
||||
AddCompletionDatasByFirstForSymInfos(resultList, charTyped, symInfos, languageCaseSensitive);
|
||||
|
||||
//resultList.Sort();
|
||||
//defaultCompletionElement = resultList[0] as DefaultCompletionData;
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
this.ByFirstChar = true;
|
||||
|
||||
return resultList.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавляет в resultList (итоговый список подсказок) данные, соответствующие переданному массиву типа SymInfo[].
|
||||
/// Используется для случая ввода пользователем первого символа выражения
|
||||
/// </summary>
|
||||
private void AddCompletionDatasByFirstForSymInfos(List<ICompletionData> resultList, char charTyped, SymInfo[] symInfos, bool languageCaseSensitive)
|
||||
{
|
||||
HashSet<string> symbolsAdded = languageCaseSensitive ? new HashSet<string>() : new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
List<ICompletionData> candidatesForDefault = new List<ICompletionData>();
|
||||
|
||||
bool stop = false;
|
||||
ICompletionData lastUsedItem = CompletionDataDispatcher.GetLastUsedItem(charTyped);
|
||||
|
||||
foreach (SymInfo symInfo in symInfos)
|
||||
{
|
||||
if (symInfo == null || symInfo.not_include) continue;
|
||||
|
||||
if (symbolsAdded.Contains(symInfo.name))
|
||||
continue;
|
||||
|
||||
UserDefaultCompletionData completionData = new UserDefaultCompletionData(symInfo.name, symInfo.description, ImagesProvider.GetPictureNum(symInfo), false);
|
||||
|
||||
StringComparison stringComparison = languageCaseSensitive ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase;
|
||||
|
||||
// если мы выбирали что-то раньше из списка подсказок, то считаем это элементом по умолчанию
|
||||
if (!stop && lastUsedItem != null && string.Equals(symInfo.name, lastUsedItem.Text, stringComparison))
|
||||
{
|
||||
defaultCompletionElement = completionData;
|
||||
stop = true;
|
||||
}
|
||||
// иначе формируем список подходящих подсказок - "кандидатов" для элемента по умолчанию
|
||||
else if (!stop && lastUsedItem == null && symInfo.name.StartsWith(charTyped.ToString(), stringComparison))
|
||||
{
|
||||
//defaultCompletionElement = ddd;
|
||||
candidatesForDefault.Add(completionData);
|
||||
//stop = true;
|
||||
}
|
||||
|
||||
disp.Add(symInfo, completionData);
|
||||
|
||||
resultList.Add(completionData);
|
||||
|
||||
symbolsAdded.Add(symInfo.name);
|
||||
}
|
||||
|
||||
if (candidatesForDefault.Count > 0)
|
||||
defaultCompletionElement = candidatesForDefault.Min() as UserDefaultCompletionData; // здесь выбирается минимальное по длине
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Формирует массив данных из таблицы символов для подсказок в случае введения пользователем первой буквы выражения
|
||||
/// </summary>
|
||||
private SymInfo[] GetSymInfosForCompletionDataByFirst(int line, int col, bool isTypeAfterKeyword, bool isNamespaceAfterKeyword, string pattern)
|
||||
{
|
||||
CodeCompletion.DomConverter dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[FileName];
|
||||
/*if (dconv == null && CodeCompletion.CodeCompletionNameHelper.system_unit_file_full_name != null
|
||||
|
|
@ -334,238 +436,292 @@ namespace VisualPascalABC
|
|||
dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[CodeCompletion.CodeCompletionNameHelper.system_unit_file_full_name];
|
||||
special_module = true;
|
||||
}*/
|
||||
string pattern = charTyped.ToString();
|
||||
string[] keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetKeywords();
|
||||
if (CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsTypeAfterKeyword(keyw))
|
||||
|
||||
SymInfo[] symInfos = null;
|
||||
|
||||
if (dconv == null)
|
||||
{
|
||||
keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetTypeKeywords();
|
||||
}
|
||||
if (!CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsNamespaceAfterKeyword(keyw))
|
||||
foreach (string key in keywords)
|
||||
if (isNamespaceAfterKeyword)
|
||||
{
|
||||
//if (key.StartsWith(pattern, StringComparison.CurrentCultureIgnoreCase))
|
||||
resultList.Add(new UserDefaultCompletionData(key, null, ImagesProvider.IconNumberKeyword, false));
|
||||
symInfos = CodeCompletion.DomConverter.standard_units;
|
||||
}
|
||||
PascalABCCompiler.Parsers.SymInfo[] mis = null;
|
||||
if (CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsNamespaceAfterKeyword(keyw))
|
||||
{
|
||||
mis = CodeCompletion.DomConverter.standard_units;
|
||||
}
|
||||
if (dconv != null)
|
||||
else
|
||||
{
|
||||
//if (keyw == PascalABCCompiler.Parsers.KeywordKind.Colon || keyw == PascalABCCompiler.Parsers.KeywordKind.Of || keyw == PascalABCCompiler.Parsers.KeywordKind.TypeDecl)
|
||||
if (CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsTypeAfterKeyword(keyw))
|
||||
mis = dconv.GetTypeByPattern(pattern, line, col, true, VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
else if (CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.IsNamespaceAfterKeyword(keyw) && mis == null)
|
||||
mis = dconv.GetNamespaces();
|
||||
if (isTypeAfterKeyword)
|
||||
{
|
||||
symInfos = dconv.GetTypeByPattern(pattern, line, col, true, VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
}
|
||||
else if (isNamespaceAfterKeyword)
|
||||
{
|
||||
if (WorkbenchServiceFactory.Workbench.UserOptions.EnableSmartIntellisense)
|
||||
symInfos = dconv.GetNamespaces();
|
||||
else
|
||||
mis = dconv.GetNameByPattern(null, line, col, true, VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
symInfos = CodeCompletion.DomConverter.standard_units;
|
||||
}
|
||||
Hashtable cache = new Hashtable();
|
||||
if (mis != null)
|
||||
else
|
||||
{
|
||||
bool stop = false;
|
||||
ICompletionData data = CompletionDataDispatcher.GetLastUsedItem(charTyped);
|
||||
foreach (PascalABCCompiler.Parsers.SymInfo mi in mis)
|
||||
{
|
||||
if (mi.not_include) continue;
|
||||
|
||||
if (cache.Contains(mi.name))
|
||||
continue;
|
||||
|
||||
UserDefaultCompletionData ddd = new UserDefaultCompletionData(mi.name, mi.description, ImagesProvider.GetPictureNum(mi), false);
|
||||
if (!stop && data != null && string.Compare(mi.name, data.Text, true) == 0)
|
||||
{
|
||||
defaultCompletionElement = ddd;
|
||||
stop = true;
|
||||
// интересно, что передается pattern = null EVA
|
||||
symInfos = dconv.GetNameByPattern(null, line, col, true, VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
}
|
||||
else if (!stop && data == null && mi.name.StartsWith(charTyped.ToString(), StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
//defaultCompletionElement = ddd;
|
||||
lst.Add(ddd);
|
||||
//stop = true;
|
||||
}
|
||||
disp.Add(mi, ddd);
|
||||
resultList.Add(ddd);
|
||||
cache[mi.name] = mi;
|
||||
}
|
||||
//resultList.Sort();
|
||||
//defaultCompletionElement = resultList[0] as DefaultCompletionData;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
lst.Sort();
|
||||
if (lst.Count > 0) defaultCompletionElement = lst[0] as UserDefaultCompletionData;
|
||||
ICompletionData[] res_arr = resultList.ToArray();
|
||||
this.ByFirstChar = true;
|
||||
return res_arr;
|
||||
return symInfos;
|
||||
}
|
||||
|
||||
public ICompletionData[] GetCompletionData(int off, string Text, int line, int col, char charTyped, PascalABCCompiler.Parsers.KeywordKind keyw)
|
||||
/// <summary>
|
||||
/// Вспомогательная струтура для метода GetCompletionData, хранит информацию о действиях пользователя
|
||||
/// </summary>
|
||||
private struct ActionContext
|
||||
{
|
||||
public bool dotPressed;
|
||||
public bool ctrlSpace;
|
||||
public bool shiftSpace;
|
||||
public bool spaceAfterNew;
|
||||
public bool spaceAfterUses;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает массив подсказок для случая нажатия пользователем "триггерной" клавиши
|
||||
/// </summary>
|
||||
public ICompletionData[] GetCompletionData(int off, string text, int line, int col, char charTyped, KeywordKind keywordKind)
|
||||
{
|
||||
List<ICompletionData> resultList = new List<ICompletionData>();
|
||||
try
|
||||
{
|
||||
string pattern = null;
|
||||
string expr = null;
|
||||
bool ctrl_space = charTyped == '\0' || charTyped == '_';
|
||||
bool shift_space = charTyped == '\0';
|
||||
bool inside_dot_pattern = false;
|
||||
bool new_space = keyw == PascalABCCompiler.Parsers.KeywordKind.New;
|
||||
if (ctrl_space)
|
||||
// поменять на обращение к CodeCompletionController.CurrentLanguage
|
||||
ILanguage currentLanguage = LanguageProvider.Instance.SelectLanguageByExtension(FileName);
|
||||
|
||||
var context = new ActionContext()
|
||||
{
|
||||
bool is_pattern = false;
|
||||
pattern = CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.FindPattern(off, Text, out is_pattern);
|
||||
if (is_pattern && Text[off - pattern.Length - 1] == '.')
|
||||
dotPressed = charTyped == '.',
|
||||
ctrlSpace = charTyped == '_',
|
||||
shiftSpace = charTyped == '\0',
|
||||
spaceAfterNew = keywordKind == KeywordKind.New,
|
||||
spaceAfterUses = keywordKind == KeywordKind.Uses
|
||||
};
|
||||
|
||||
string expressionText = GetExpressionTextForCompletionData(off, text, line, col,
|
||||
currentLanguage.LanguageInformation, in context, out var insidePatternWithDots, out var ctrlOrShiftSpaceAfterDot, out var pattern);
|
||||
|
||||
// добавляем ключевые слова в случае "ctrl + space", нажатых в "пустом" месте
|
||||
if (!ctrlOrShiftSpaceAfterDot && context.ctrlSpace && string.IsNullOrEmpty(pattern))
|
||||
{
|
||||
inside_dot_pattern = true;
|
||||
expr = FindExpression(off - pattern.Length - 1, Text, line, col);
|
||||
var keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetKeywords();
|
||||
|
||||
resultList.AddRange(keywords.Select(keyword =>
|
||||
new UserDefaultCompletionData(keyword, null, ImagesProvider.IconNumberKeyword, false)));
|
||||
}
|
||||
|
||||
}
|
||||
else if (new_space)
|
||||
PascalABCCompiler.SyntaxTree.expression expr = null;
|
||||
|
||||
// для "ctrl + space" и "shift + space" дерево expression не требуется (кроме случая insidePatternWithDots)
|
||||
if ((context.dotPressed || context.spaceAfterNew || context.spaceAfterUses || insidePatternWithDots) && expressionText != null)
|
||||
{
|
||||
expr = CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.SkipNew(off - 1, Text, ref keyword);
|
||||
}
|
||||
else
|
||||
if (!new_space && keyw != PascalABCCompiler.Parsers.KeywordKind.Uses)
|
||||
if (charTyped != '$')
|
||||
expr = FindExpression(off, Text, line, col);
|
||||
else
|
||||
expr = FindExpression(off - 1, Text, line, col);
|
||||
List<PascalABCCompiler.Errors.Error> Errors = new List<PascalABCCompiler.Errors.Error>();
|
||||
PascalABCCompiler.SyntaxTree.expression e = null;
|
||||
if (ctrl_space && !shift_space && (pattern == null || pattern == ""))
|
||||
{
|
||||
string[] keywords = CodeCompletion.CodeCompletionNameHelper.Helper.GetKeywords();
|
||||
foreach (string key in keywords)
|
||||
{
|
||||
//if (key.StartsWith(pattern, StringComparison.CurrentCultureIgnoreCase))
|
||||
resultList.Add(new UserDefaultCompletionData(key, null, ImagesProvider.IconNumberKeyword, false));
|
||||
}
|
||||
expr = GetExpressionForCompletionData(currentLanguage.Parser,
|
||||
in context, expressionText, insidePatternWithDots, out var shouldReturnNull);
|
||||
|
||||
if (shouldReturnNull)
|
||||
return null;
|
||||
}
|
||||
|
||||
ILanguage currentLanguage = LanguageProvider.Instance.SelectLanguageByExtensionSafe(FileName);
|
||||
SymInfo[] symInfos = GetSymInfosForCompletionData(line, col, in context, currentLanguage.CaseSensitive,
|
||||
expressionText, ctrlOrShiftSpaceAfterDot, insidePatternWithDots, pattern, expr, out var selectedSymInfo, out var lastUsedMember, out var shouldReturnNull2);
|
||||
|
||||
if (currentLanguage == null)
|
||||
if (shouldReturnNull2)
|
||||
return null;
|
||||
|
||||
if ((!ctrl_space || inside_dot_pattern) && expr != null)
|
||||
if (symInfos != null)
|
||||
{
|
||||
e = currentLanguage.Parser.GetTypeAsExpression("test" + System.IO.Path.GetExtension(FileName), expr, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
if (e == null)
|
||||
{
|
||||
Errors.Clear();
|
||||
e = currentLanguage.Parser.GetExpression("test" + System.IO.Path.GetExtension(FileName), expr, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
AddCompletionDatasForSymInfos(resultList, currentLanguage.CaseSensitive, symInfos, selectedSymInfo, lastUsedMember);
|
||||
}
|
||||
if ((e == null || Errors.Count > 0) && !new_space) return null;
|
||||
}
|
||||
SymInfo[] mis = null;
|
||||
CodeCompletion.DomConverter dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[FileName];
|
||||
if (dconv == null)
|
||||
{
|
||||
if (keyw == PascalABCCompiler.Parsers.KeywordKind.Uses)
|
||||
mis = CodeCompletion.DomConverter.standard_units;
|
||||
else if (!ctrl_space)
|
||||
return new ICompletionData[0];
|
||||
}
|
||||
string fname = FileName;
|
||||
SymInfo sel_si = null;
|
||||
string last_used_member = null;
|
||||
if (dconv != null)
|
||||
{
|
||||
if (new_space)
|
||||
mis = dconv.GetTypes(e, line, col, out sel_si);
|
||||
else if (keyw == PascalABCCompiler.Parsers.KeywordKind.Uses && mis == null)
|
||||
{
|
||||
if (WorkbenchServiceFactory.Workbench.UserOptions.EnableSmartIntellisense)
|
||||
mis = dconv.GetNamespaces();
|
||||
else
|
||||
mis = CodeCompletion.DomConverter.standard_units;
|
||||
catch (Exception) { }
|
||||
|
||||
return resultList.ToArray();
|
||||
}
|
||||
|
||||
else
|
||||
if (!ctrl_space)
|
||||
/// <summary>
|
||||
/// Добавляет в resultList (итоговый список подсказок) данные, соответствующие переданному массиву типа SymInfo[].
|
||||
/// Используется для случая нажатия пользователем "триггерной" клавиши
|
||||
/// </summary>
|
||||
private void AddCompletionDatasForSymInfos(List<ICompletionData> resultList, bool languageCaseSensitive, SymInfo[] symInfos, SymInfo selectedSymInfo, string lastUsedMember)
|
||||
{
|
||||
CodeCompletion.SymScope dot_sc = null;
|
||||
mis = dconv.GetName(e, expr, line, col, keyword, ref dot_sc);
|
||||
if (dot_sc != null && VisualPABCSingleton.MainForm.UserOptions.EnableSmartIntellisense)
|
||||
{
|
||||
CompletionDataDispatcher.AddMemberBeforeDot(dot_sc);
|
||||
last_used_member = CompletionDataDispatcher.GetRecentUsedMember(dot_sc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CodeCompletion.SymScope dot_sc = null;
|
||||
if (inside_dot_pattern)
|
||||
{
|
||||
List<SymInfo> si_list = new List<SymInfo>();
|
||||
SymInfo[] from_list = dconv.GetName(e, expr, line, col, keyword, ref dot_sc);
|
||||
for (int i = 0; i < from_list.Length; i++)
|
||||
{
|
||||
if (from_list[i].name.StartsWith(pattern, StringComparison.OrdinalIgnoreCase))
|
||||
si_list.Add(from_list[i]);
|
||||
}
|
||||
mis = si_list.ToArray();
|
||||
}
|
||||
// ICompletionData data = null;
|
||||
|
||||
else
|
||||
mis = dconv.GetNameByPattern(pattern, line, col, charTyped == '_', VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
}
|
||||
HashSet<string> symbolsAdded = languageCaseSensitive ? new HashSet<string>() : new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
}
|
||||
Hashtable cache = null;
|
||||
if (!currentLanguage.CaseSensitive)
|
||||
cache = new Hashtable(StringComparer.CurrentCultureIgnoreCase);
|
||||
else
|
||||
cache = new Hashtable();
|
||||
int num = 0;
|
||||
if (mis != null)
|
||||
foreach (SymInfo symInfo in symInfos)
|
||||
{
|
||||
bool stop = false;
|
||||
ICompletionData data = null;
|
||||
|
||||
foreach (SymInfo mi in mis)
|
||||
{
|
||||
if (mi.not_include) continue;
|
||||
if (cache.Contains(mi.name + mi.kind))
|
||||
if (symInfo == null || symInfo.not_include)
|
||||
continue;
|
||||
|
||||
UserDefaultCompletionData ddd = new UserDefaultCompletionData(mi.addit_name != null ? mi.addit_name : mi.name, mi.description, ImagesProvider.GetPictureNum(mi), false);
|
||||
if (symbolsAdded.Contains(symInfo.name + symInfo.kind))
|
||||
continue;
|
||||
|
||||
UserDefaultCompletionData completionData = new UserDefaultCompletionData(
|
||||
symInfo.addit_name != null ? symInfo.addit_name : symInfo.name,
|
||||
symInfo.description, ImagesProvider.GetPictureNum(symInfo), false
|
||||
);
|
||||
|
||||
disp.Add(symInfo, completionData);
|
||||
|
||||
resultList.Add(completionData);
|
||||
|
||||
symbolsAdded.Add(symInfo.name + symInfo.kind);
|
||||
|
||||
disp.Add(mi, ddd);
|
||||
resultList.Add(ddd);
|
||||
cache[mi.name + mi.kind] = mi;
|
||||
/*if (VisualPABCSingleton.MainForm.UserOptions.EnableSmartIntellisense && mi.name != null && mi.name != "" && data == null)
|
||||
{
|
||||
data = CompletionDataDispatcher.GetLastUsedItem(mi.name[0]);
|
||||
if (data != null && data.Text == ddd.Text) data = ddd;
|
||||
}*/
|
||||
if (last_used_member != null && last_used_member == mi.name)
|
||||
|
||||
if (lastUsedMember != null && lastUsedMember == symInfo.name || selectedSymInfo != null && symInfo == selectedSymInfo)
|
||||
{
|
||||
defaultCompletionElement = ddd;
|
||||
}
|
||||
if (sel_si != null && mi == sel_si)
|
||||
{
|
||||
defaultCompletionElement = ddd;
|
||||
stop = true;
|
||||
defaultCompletionElement = completionData;
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultCompletionElement == null && data != null)
|
||||
defaultCompletionElement = data as UserDefaultCompletionData;
|
||||
/*if (defaultCompletionElement == null && data != null)
|
||||
defaultCompletionElement = data as UserDefaultCompletionData;*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Формирует массив данных из таблицы символов для подсказок в случае нажатия пользователем "триггерной" клавиши
|
||||
/// (в зависимости от введенного выражения и другого контекста)
|
||||
/// </summary>
|
||||
private SymInfo[] GetSymInfosForCompletionData(int line, int col, in ActionContext context, bool languageCaseSensitive, string expressionText, bool ctrlOrShiftSpaceAfterDot, bool insidePatternWithDots, string pattern, PascalABCCompiler.SyntaxTree.expression expr, out SymInfo selectedSymInfo, out string lastUsedMember, out bool shouldReturnNull)
|
||||
{
|
||||
SymInfo[] symInfos = null;
|
||||
|
||||
shouldReturnNull = false;
|
||||
|
||||
selectedSymInfo = null;
|
||||
lastUsedMember = null;
|
||||
|
||||
CodeCompletion.DomConverter dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[FileName];
|
||||
|
||||
if (dconv == null)
|
||||
{
|
||||
// в данном случае возвращаем пустой массив ICompletionData
|
||||
if (!context.spaceAfterUses && !context.ctrlSpace)
|
||||
shouldReturnNull = true;
|
||||
|
||||
if (context.spaceAfterUses)
|
||||
symInfos = CodeCompletion.DomConverter.standard_units;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context.spaceAfterNew)
|
||||
{
|
||||
symInfos = dconv.GetTypes(expr, line, col, out selectedSymInfo);
|
||||
}
|
||||
else if (context.spaceAfterUses)
|
||||
{
|
||||
if (WorkbenchServiceFactory.Workbench.UserOptions.EnableSmartIntellisense)
|
||||
symInfos = dconv.GetNamespaces();
|
||||
else
|
||||
symInfos = CodeCompletion.DomConverter.standard_units;
|
||||
}
|
||||
// нажатие ctrl + space и shift + space сразу после точки приравнивается к нажатию точки
|
||||
else if (context.dotPressed || ctrlOrShiftSpaceAfterDot)
|
||||
{
|
||||
CodeCompletion.SymScope dotScope = null;
|
||||
symInfos = dconv.GetName(expr, expressionText, line, col, keyword, ref dotScope);
|
||||
|
||||
if (dotScope != null && VisualPABCSingleton.MainForm.UserOptions.EnableSmartIntellisense)
|
||||
{
|
||||
CompletionDataDispatcher.AddMemberBeforeDot(dotScope);
|
||||
lastUsedMember = CompletionDataDispatcher.GetRecentUsedMember(dotScope);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
// ctrl + space после некоторого выражения
|
||||
else if (context.ctrlSpace) // context.chiftSpace здесь не может быть true, поскольку такие ситуации обрабатываются в ShiftSpaceActions.Execute()
|
||||
{
|
||||
CodeCompletion.SymScope dotScope = null;
|
||||
|
||||
// если мы в цепочечном выражении с точками
|
||||
if (insidePatternWithDots)
|
||||
{
|
||||
|
||||
symInfos = dconv.GetName(expr, expressionText, line, col, keyword, ref dotScope)
|
||||
.Where(symInfo => symInfo.name.StartsWith(pattern,
|
||||
languageCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))
|
||||
.ToArray();
|
||||
}
|
||||
return resultList.ToArray();
|
||||
else
|
||||
symInfos = dconv.GetNameByPattern(pattern, line, col, context.ctrlSpace, VisualPABCSingleton.MainForm.UserOptions.CodeCompletionNamespaceVisibleRange);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return symInfos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает дерево выражения, введенного пользователем перед нажатием "триггерной" клавиши
|
||||
/// </summary>
|
||||
private PascalABCCompiler.SyntaxTree.expression GetExpressionForCompletionData(IParser parser, in ActionContext context, string expressionText, bool insidePatternWithDots, out bool shouldReturnNull)
|
||||
{
|
||||
shouldReturnNull = false;
|
||||
|
||||
List<PascalABCCompiler.Errors.Error> Errors = new List<PascalABCCompiler.Errors.Error>();
|
||||
List<PascalABCCompiler.Errors.CompilerWarning> Warnings = new List<PascalABCCompiler.Errors.CompilerWarning>();
|
||||
|
||||
var expr = parser.GetTypeAsExpression("test" + System.IO.Path.GetExtension(FileName), expressionText, Errors, Warnings);
|
||||
if (expr == null)
|
||||
{
|
||||
Errors.Clear();
|
||||
expr = parser.GetExpression("test" + System.IO.Path.GetExtension(FileName), expressionText, Errors, Warnings);
|
||||
}
|
||||
|
||||
if ((expr == null || Errors.Count > 0) && !context.spaceAfterNew)
|
||||
shouldReturnNull = true;
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение текста выражения, введенного пользователем перед нажатием "триггерной" клавиши
|
||||
/// </summary>
|
||||
private string GetExpressionTextForCompletionData(int off, string text, int line, int col, ILanguageInformation languageInformation, in ActionContext context, out bool insidePatternWithDots, out bool ctrlOrShiftSpaceAfterDot, out string pattern)
|
||||
{
|
||||
|
||||
string expressionText = null;
|
||||
pattern = null;
|
||||
insidePatternWithDots = false;
|
||||
ctrlOrShiftSpaceAfterDot = false;
|
||||
|
||||
if (context.ctrlSpace || context.shiftSpace)
|
||||
{
|
||||
|
||||
pattern = languageInformation.FindPattern(off, text, out var isPattern);
|
||||
|
||||
// в конце выражения точка
|
||||
if (!isPattern && text[off - 1] == '.')
|
||||
{
|
||||
ctrlOrShiftSpaceAfterDot = true;
|
||||
}
|
||||
|
||||
// если нужно подсказать все варианты после точки, то поведение как в случае context.dotPressed
|
||||
if (isPattern && text[off - pattern.Length - 1] == '.' || ctrlOrShiftSpaceAfterDot)
|
||||
{
|
||||
insidePatternWithDots = true;
|
||||
expressionText = FindExpression(off - (pattern?.Length ?? 0) - 1, text, line, col);
|
||||
}
|
||||
|
||||
}
|
||||
else if (context.spaceAfterNew)
|
||||
{
|
||||
expressionText = languageInformation.SkipNew(off - 1, text, ref keyword);
|
||||
}
|
||||
else if (context.dotPressed) // keywordKind != KeywordKind.Uses
|
||||
{
|
||||
expressionText = FindExpression(off, text, line, col);
|
||||
}
|
||||
|
||||
return expressionText;
|
||||
}
|
||||
|
||||
private CodeCompletion.CodeCompletionController controller;
|
||||
|
|
@ -640,7 +796,7 @@ namespace VisualPascalABC
|
|||
string text = textArea.Document.TextContent.Substring(0, textArea.Caret.Offset);
|
||||
//controller.Compile(file_name, text /*+ ")))));end."*/);
|
||||
FileName = fileName; Text = text;
|
||||
ICompletionData[] data = GetCompletionDataByFirst(off, text, textArea.Caret.Line, textArea.Caret.Column, charTyped, keyw);
|
||||
ICompletionData[] data = GetCompletionDataByFirst(textArea.Caret.Line, textArea.Caret.Column, charTyped, keyw);
|
||||
CodeCompletion.AssemblyDocCache.CompleteDocumentation();
|
||||
CodeCompletion.UnitDocCache.CompleteDocumentation();
|
||||
controller = null;
|
||||
|
|
|
|||
|
|
@ -18,65 +18,68 @@ namespace VisualPascalABC
|
|||
|
||||
private static string GetPopupHintText(TextArea textArea, ToolTipRequestEventArgs e)
|
||||
{
|
||||
ICSharpCode.TextEditor.TextLocation logicPos = e.LogicalPosition;
|
||||
TextLocation logicPos = e.LogicalPosition;
|
||||
IDocument doc = textArea.Document;
|
||||
LineSegment seg = doc.GetLineSegment(logicPos.Y);
|
||||
string FileName = textArea.MotherTextEditorControl.FileName;
|
||||
PascalABCCompiler.Parsers.KeywordKind keyw = PascalABCCompiler.Parsers.KeywordKind.None;
|
||||
if (logicPos.X > seg.Length - 1)
|
||||
LineSegment lineSegment = doc.GetLineSegment(logicPos.Y);
|
||||
|
||||
string fileName = textArea.MotherTextEditorControl.FileName;
|
||||
|
||||
if (logicPos.X > lineSegment.Length - 1)
|
||||
return null;
|
||||
|
||||
//string expr = FindFullExpression(doc.TextContent, seg.Offset + logicPos.X,e.LogicalPosition.Line,e.LogicalPosition.Column);
|
||||
string expr_without_brackets = null;
|
||||
string expr = CodeCompletion.CodeCompletionController.CurrentParser.LanguageInformation.FindExpressionFromAnyPosition(seg.Offset + logicPos.X, doc.TextContent, e.LogicalPosition.Line, e.LogicalPosition.Column, out keyw, out expr_without_brackets);
|
||||
|
||||
IParser parser = CodeCompletion.CodeCompletionController.CurrentParser;
|
||||
|
||||
string expr = parser.LanguageInformation.FindExpressionFromAnyPosition(
|
||||
lineSegment.Offset + logicPos.X, doc.TextContent, e.LogicalPosition.Line, e.LogicalPosition.Column, out var keyw, out var exprWithoutBrackets);
|
||||
|
||||
// пока непонятно, когда такое может быть EVA
|
||||
if (expr == null)
|
||||
expr = exprWithoutBrackets;
|
||||
|
||||
if (expr == null)
|
||||
expr = expr_without_brackets;
|
||||
if (expr_without_brackets == null)
|
||||
return null;
|
||||
|
||||
List<PascalABCCompiler.Errors.Error> Errors = new List<PascalABCCompiler.Errors.Error>();
|
||||
List<PascalABCCompiler.Errors.CompilerWarning> Warnings = new List<PascalABCCompiler.Errors.CompilerWarning>();
|
||||
|
||||
IParser parser = Languages.Facade.LanguageProvider.Instance.SelectLanguageByExtension(FileName).Parser;
|
||||
PascalABCCompiler.SyntaxTree.expression expressionTree = parser.GetExpression("test" + Path.GetExtension(fileName),
|
||||
expr, Errors, Warnings);
|
||||
|
||||
PascalABCCompiler.SyntaxTree.expression tree = parser.GetExpression("test" + Path.GetExtension(FileName), expr, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
bool header = false;
|
||||
if (Errors.Count > 0)
|
||||
{
|
||||
if (expr.IndexOf('<') != -1 && expr.IndexOf('>') != -1)
|
||||
{
|
||||
Errors.Clear();
|
||||
tree = parser.GetExpression("test" + Path.GetExtension(FileName), expr.Replace("<", "&<"), Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
}
|
||||
else
|
||||
// Пока добавили проверку, что анализируем Паскаль EVA
|
||||
if (Errors.Count > 0 && parser == Languages.Facade.LanguageProvider.Instance.SelectLanguageByName(PascalABCCompiler.StringConstants.pascalLanguageName).Parser)
|
||||
{
|
||||
string s = expr.TrimStart();
|
||||
if (s.Length > 0 && s[0] == '^')
|
||||
{
|
||||
Errors.Clear();
|
||||
expr_without_brackets = expr_without_brackets.TrimStart().Substring(1);
|
||||
tree = parser.GetExpression("test" + Path.GetExtension(FileName), s.Substring(1), Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
exprWithoutBrackets = exprWithoutBrackets.TrimStart().Substring(1);
|
||||
expressionTree = parser.GetExpression("test" + Path.GetExtension(fileName), s.Substring(1), Errors, Warnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tree == null || Errors.Count > 0)
|
||||
|
||||
List<PascalABCCompiler.Errors.Error> Errors2 = new List<PascalABCCompiler.Errors.Error>();
|
||||
|
||||
// проверка для выражения без скобок
|
||||
PascalABCCompiler.SyntaxTree.expression expressionTree2 = parser.GetExpression("test" + Path.GetExtension(fileName), exprWithoutBrackets, Errors2, Warnings);
|
||||
|
||||
// если не получается, то сразу возврат
|
||||
if (expressionTree2 == null || Errors2.Count > 0)
|
||||
return null;
|
||||
|
||||
bool header = false;
|
||||
if (expressionTree == null || Errors.Count > 0)
|
||||
{
|
||||
Errors.Clear();
|
||||
tree = parser.GetExpression("test" + Path.GetExtension(FileName), expr_without_brackets, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
header = true;
|
||||
if (tree == null || Errors.Count > 0)
|
||||
return null;
|
||||
expressionTree = expressionTree2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Errors.Clear();
|
||||
PascalABCCompiler.SyntaxTree.expression tree2 = parser.GetExpression("test" + Path.GetExtension(FileName), expr_without_brackets, Errors, new List<PascalABCCompiler.Errors.CompilerWarning>());
|
||||
//header = true;
|
||||
if (tree2 == null || Errors.Count > 0)
|
||||
return null;
|
||||
//if (tree is PascalABCCompiler.SyntaxTree.new_expr && (tree as PascalABCCompiler.SyntaxTree.new_expr).params_list == null)
|
||||
// tree = tree2;
|
||||
}
|
||||
CodeCompletion.DomConverter dconv = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[FileName];
|
||||
if (dconv == null) return null;
|
||||
return dconv.GetDescription(tree, FileName, expr_without_brackets, e.LogicalPosition.Line, e.LogicalPosition.Column, keyw, header);
|
||||
|
||||
CodeCompletion.DomConverter domConverter = (CodeCompletion.DomConverter)CodeCompletion.CodeCompletionController.comp_modules[fileName];
|
||||
|
||||
if (domConverter == null) return null;
|
||||
|
||||
return domConverter.GetDescription(expressionTree, fileName, exprWithoutBrackets, e.LogicalPosition.Line, e.LogicalPosition.Column, keyw, header);
|
||||
}
|
||||
|
||||
static int _mouse_hint_x = 0, _mouse_hint_y = 0;
|
||||
|
|
|
|||
|
|
@ -1,41 +1,56 @@
|
|||
#### Подсказка при наведении мыши
|
||||
На верхнем уровне реализуется в классе `TooltipServiceManager`. Основная логика реализована в методе `GetPopupHintText`. Вначале вызывается `FindExpressionFromAnyPosition` для получения нужного `expression` в виде строки.
|
||||
Затем вызывается нужный парсер для получения дерева выражения (используется часть грамматики, связанная с нетерминалом parts). Если не получается распарсить, то делается попытка с решением неоднозначности, связанной с шаблонными параметрами (&<).
|
||||
После этого еще попытка с удалением разыменования, пока непонятно зачем это.
|
||||
Еще удаление разыменования было найдено в методе `GetDefinitionPosition` из `CodeCompletionActions`.
|
||||
Затем еще попытка с тем же выражением без скобочек. При этом, если без скобочек распарсить не удается, то вне зависимости от успешности парсинга полного `expression` возвращается `null`.
|
||||
Затем вызывается нужный парсер для получения дерева выражения (используется часть грамматики, связанная с нетерминалом parts). Если не получается распарсить, то делается попытка с удалением символа разыменования в выражении, пока неясно в какой ситуации это требуется.
|
||||
Еще удаление разыменования присутствует в методе `GetDefinitionPosition` из `CodeCompletionActions`.
|
||||
Затем делается еще попытка с тем же выражением без скобочек. При этом, если без скобочек распарсить не удается, то вне зависимости от успешности парсинга полного `expression` возвращается `null`.
|
||||
В конце проверяется был ли успешен обход дерева программы визитором (`DomSyntaxTreeVisitor`). Если это так, то в словаре откомпилированных модулей будет данный модуль и соответствующий ему `DomConverter`.
|
||||
Тогда мы сможем вызвать метод `GetDescription` из этого класса, который выдаст нам описание выражения.
|
||||
Тогда есть возможность вызвать метод `GetDescription` из этого класса, который выдаст нам описание выражения.
|
||||
|
||||
#### Подсказка параметров функции
|
||||
На нажатие клавиш (скобки, квадратной скобки или запятой) реагирует `TextAreaKeyEventHandler` из класса `CodeCompletionKeyHandler`. Там создается экземпляр `DefaultInsightDataProvider`, который загружается в стек провайдеров. Информация для подсказки формируется в методе `SetupDataProvider` инсайт-провайдера. После выяснения кода на текущей подстроке вызывается `FindExpressionForMethod` из `LanguageInformation`.
|
||||
Далее делается попытка парсинга стандартным парсером языка и наконец из `DomConverter` вызывается `GetNameOfMethod`, либо `GetIndex` в зависимости от нажатой клавиши.
|
||||
|
||||
#### Подсказка по нажатию клавиш (по точке или пробелу)
|
||||
#### Подсказка по нажатию клавиш
|
||||
`CodeCompletionKeyHandler` реагирует на нажатие вызовом метода `ShowCompletionWindow`. В нем есть обращение к `GenerateCompletionDataWithKeyword` из класса `CodeCompletionProvider`. В этом методе выделяется нужная подстрока и есть обращение к методу `GetCompletionData`.
|
||||
**Логика этого метода следующая:**
|
||||
1) если был нажат `ctrl + space` (`shift + space` входит в это понятие тоже)
|
||||
Вызывается `FindPattern` из `LanguageInformation` для получения "токена" до каретки. Если в процессе встретится точка, то вызывается `FindExpression`. Ниже если pattern пустой, то в итоговый список `ICompletionData` добавляются ключевые слова языка.
|
||||
Вначале выясняется контекст вызова Intellisense, а именно нажатые пользователем клавиши и т. п. Далее вызывается специальный метод для получения текста выражения, введенного пользователем. При этом
|
||||
1) если был нажат `ctrl + space` или `shift + space`
|
||||
Вызывается `FindPattern` из `LanguageInformation` для получения "токена" до курсора. Если в процессе встретится точка, то вызывается `FindExpression`.
|
||||
2) если был нажат пробел после `new`
|
||||
Вызывается SkipNew для пропуска `new` и поиска expression перед ним.
|
||||
3) иначе, если не было введено `uses`
|
||||
3) иначе, если пользователем была введена точка
|
||||
вызывается `FindExpression` (c текущей позиции)
|
||||
|
||||
Далее, если [**не** `ctrl + space` или была найдена цепочка имен в выражении] и выражение не пусто, то делается попытка вызова функции `GetTypeAsExpression` стандартного парсера. Если это ничего не дало далее попытка вызова `GetExpression`. Если снова ничего не удалось и мы не в случае пробела после `new`, то возврат.
|
||||
Ниже если был нажат `ctrl + space` не после точки и pattern пустой то в итоговый список `ICompletionData` добавляются ключевые слова языка.
|
||||
|
||||
Далее, если Intellisense успешно не обошла текущий модуль, то для случая `uses` мы будем рассматривать SymInfo стандартных модулей (взятых из DomConverter). Если же у нас не `uses`случай и не случай ctrl + space, мы возвращаем пустой массив.
|
||||
Далее, если выражение не пусто, то строится дерево требуемого expression (это не требуется для `ctrl + space` и `shift + space`, кроме случая, когда они нажаты в цепочечном выражении с точками). Внутри метода построения дерева делается попытка вызова функции `GetTypeAsExpression`, а затем `GetExpression`. Если ничего не удалось построить и мы не в случае пробела после `new`, то нужно выходить из внешнего метода `GetCompletionData`.
|
||||
|
||||
Далее получаем необходимую информацию о выражениях для нужного expression из таблицы символов (в специальном методе). Если визитор Intellisense успешно не обошел текущий модуль (тогда мы не получим соотв. экземпляр `DomConverter`), то
|
||||
- Если у нас не случай `ctrl + space` или `shift + space` , нужно вернуть пустой массив `ICompletionData`.
|
||||
- Для случая `uses` сразу добавляем массив стандартных модулей языка
|
||||
|
||||
Иначе, если у нас есть `DomConverter`:
|
||||
- Если пробел после `new`, то вызываем `GetTypes`
|
||||
- Иначе, если `uses`, то работаем со списком стандартных модулей + пр-в имен в случае семантического Intellisense.
|
||||
- Иначе, если не `ctrl + space` (случай, когда мы поставили точку), то вызываем `GetName` для получения всех возможных имен после точки
|
||||
- Иначе, если `ctrl + space`, то либо ищем имена после точки - `GetName` (если точка была раньше), либо ищем имя по его началу - `GetNameByPattern`
|
||||
- Иначе, если была нажата точка, либо `ctrl + space` или `shift + space` сразу после точки, то вызываем `GetName` для получения всех возможных имен после точки
|
||||
- Иначе, если `ctrl + space`, то либо ищем имена, подходящие для помещения после точки, начинающиеся на `pattern` - `GetName` + `StartsWith`, либо просто ищем имя по его началу - `GetNameByPattern`
|
||||
|
||||
|
||||
> [!NOTE] Замечание
|
||||
>Также на нажатие реагирует Execute из CodeCompletionAllNamesAction. key подменяется на доллар если это было нажатие `ctrl + space` сразу после точки.
|
||||
|
||||
В конце по полученным SymInfo строится результирующий список CompletionData (без повторений).
|
||||
|
||||
> [!NOTE] Замечание
|
||||
>Случаи обработки `ctrl + space` и `shift + space` перед вызовом `GetCompletionData` обрабатываются не в классе `CodeCompletionKeyHandler`, а в отдельных классах файла CodeCompletionActions. У `ctrl + space` класс называется `CodeCompletionAllNamesAction`, а у `shift + space` - `CodeCompletionShiftSpaceActions`. При этом для `shift + space` в вышеупомянутом классе предварительно проверяются еще два сценария его применения помимо подсказки локальных имен, реализованной в `GetCompletionData`. Эти сценарии - это автодополнение xml-комментария и автодополнение выражений из файла template.pct языка.
|
||||
|
||||
#### Подсказка по первому символу выражения
|
||||
Данная ситуация обрабатывается в последней ветке метода `TextAreaKeyEventHandler` класса `CodeCompletionKeyHandler`. Оттуда цепочка вызовов приходит к методу `GetCompletionDataByFirst`. В этом методе мы так же как в `GetCompletionData` вначале выясняем контекст, а именно должен ли в данной позиции быть введен тип данных, либо мы находимся в секции "uses". Если мы не в "uses", то можно добавить в результирующий список подсказок нужные ключевые слова.
|
||||
|
||||
Далее получаем нужную информацию из таблицы символов в специальном методе по следующим правилам:
|
||||
Если `DomConverter` данного модуля получить невозможно, то в случае "uses" можно добавить список стандартных модулей.
|
||||
Если же `DomConverter` получен, то
|
||||
- если нужно подсказать типы данных вызывается `GetTypeByPattern`
|
||||
- если секция "uses", то либо вызывается `GetNamespaces` когда включен семантический Intellisense, либо просто добавляется список стандартных модулей
|
||||
- во всех остальных ситуациях вызывается `GetNameByPattern`, причем ему передается пустой `pattern`
|
||||
|
||||
После этого в специальном методе по полученным SymInfo строим результирующий список подсказок без повторений. При этом назначается значение `defaultCompletionElement` (подсказки, которая выбирается по умолчанию). Это будет либо прошлый выбранный вариант подсказки, либо если такого не найдется, то минимальный элемент по длине.
|
||||
#### Переход к определению символа
|
||||
В `CodeCompletionActoins` есть специальный класс GotoAction, в котором вызывается метод `GoToDefinition`. В этом методе используется метод GetDefinitionPosition, который в свою очередь (тоже косвенно) использует `FindExpressionFromAnyPosition` из `LanguageInformation` и `GetDefinition` из `CodeCompletionProvider`. Последний вышеупомянутый метод является оберткой на `GetDefinition` из DomConverter.
|
||||
В `CodeCompletionActions` есть специальный класс `GotoAction`, в котором вызывается метод `GoToDefinition`. В этом методе используется метод `GetDefinitionPosition`, который в свою очередь (тоже косвенно) использует `FindExpressionFromAnyPosition` из `LanguageInformation` и `GetDefinition` из `CodeCompletionProvider`. Последний вышеупомянутый метод является оберткой над `GetDefinition` из `DomConverter`.
|
||||
Loading…
Reference in a new issue