pascalabcnet/PascalABCLanguageInfo/PascalABCLanguageInformation.cs
AlexanderZemlyak 69149f8c44
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:

commit 7751fe7e75
Author: samuraiGH <87191377+samuraiGH@users.noreply.github.com>
Date:   Sun Mar 16 13:28:03 2025 +0300

    generating language res file at build time (#3252)

commit d1fce63d69
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Tue Mar 4 08:38:09 2025 +0300

    Сборка после pr SDK

commit d491e88aa7
Author: 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

commit 1fd348ec3c
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Sun Feb 23 20:49:26 2025 +0300

    NSIS New 3.10

    Ярлык в меню Пуск у всех пользователей

commit 80b7182dc1
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Wed Feb 19 11:50:00 2025 +0300

    _ in names

commit a2b078960b
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Wed Feb 19 10:52:25 2025 +0300

    cnfc2

commit 58f26d469d
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Tue Feb 18 22:28:13 2025 +0300

    перекомпиляция 3.10.3.3611

commit b78a72977f
Author: 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

commit c3557e388c
Author: 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

commit 9dbac389e1
Author: AlexanderZemlyak <92867056+AlexanderZemlyak@users.noreply.github.com>
Date:   Wed Feb 12 13:57:14 2025 +0300

    Add missing projects to pabcnetc.sln (#3247)

commit 41dfb6f187
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Fri Feb 7 21:41:01 2025 +0300

    [] - преобразование во все контейнеры

    GraphABCHelper - теперь ABCObjects работает под Линукс

    School исправлен согласно последним веяниям []

commit 79bbbd10ff
Author: samuraiGH <87191377+samuraiGH@users.noreply.github.com>
Date:   Wed Jan 29 20:18:37 2025 +0300

    removing files for support fx4.0 (#3240)

commit 88d5c409eb
Author: 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

commit 8fbd7fdfc3
Author: 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)

commit bba132bd5d
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Wed Jan 22 09:14:44 2025 +0300

    Поправил справку по функции

commit 1bd21857cc
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Wed Jan 8 18:46:51 2025 +0300

    Teacher Control Plugin - возможность задать server.dat

commit 0848a1b796
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Sat Jan 4 22:54:38 2025 +0300

    Исправление автоформатирования []

commit d45b782a7b
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Sat Jan 4 18:45:07 2025 +0300

    Rename PABCSistem in test suite

commit c2347e604b
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Sat Jan 4 14:44:51 2025 +0300

    Примеры - устранил неточности

    LightPT - имя сервера вынес в публичную секцию

commit b68b8da970
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Tue Dec 17 15:52:18 2024 +0300

    Примеры Coords1.pas Coords2.pas.pas

commit 8a9788e6f9
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Tue Dec 17 15:06:57 2024 +0300

    Перенес проверку set array на уровень парсера

    Немного поправил Intellisense по наведению для NewSet

    По точке там что то другое работает

commit 874ddebad3
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Sat Dec 14 21:00:38 2024 +0300

    Поправил грамматику []

    Теперь нельзя в режиме ## использовать атрибуты

    Зато можно [1,2,3].Print

commit 080fb487e1
Merge: a53dcd9ed a484b0e82
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Sat Dec 14 15:25:24 2024 +0300

    Merge branch 'master' of https://github.com/pascalabcnet/pascalabcnet

commit a53dcd9ed2
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Sat Dec 14 15:25:16 2024 +0300

    SF Prm Cmb для строк

commit a484b0e82d
Author: Sun Serega <sunserega2@gmail.com>
Date:   Thu Dec 12 13:49:17 2024 +0200

    fix (#3231)

commit 6ef11f249c
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Tue Dec 10 11:05:45 2024 +0300

    3.10.2

commit db9679d89f
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Tue Dec 10 10:59:20 2024 +0300

    Закончил превращение синтаксиса [] по умолчанию в массивы

commit 45fdde24b4
Author: Ivan Bondarev <ibond84@googlemail.com>
Date:   Sun Dec 8 18:08:00 2024 +0100

    #3229

commit 494b47624d
Merge: 5875b9929 7906d73da
Author: Ivan Bondarev <ibond84@googlemail.com>
Date:   Sun Dec 8 10:42:07 2024 +0100

    Merge branch 'master' of https://github.com/pascalabcnet/pascalabcnet

commit 5875b99296
Author: Ivan Bondarev <ibond84@googlemail.com>
Date:   Sun Dec 8 10:41:53 2024 +0100

    platformtarget native - .NET 9.0

commit 7906d73da3
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Tue Dec 3 14:25:37 2024 +0300

    Небольшие изменения в реализации операций с множествами

commit 087591c7b6
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Wed Nov 27 11:37:07 2024 +0300

    3.10.1

    Coords - доработки

    Distance, Middle, DrawText с фоном и рамкой. Глобальные переменные настройки

commit d268d4f83b
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Thu Nov 21 22:24:07 2024 +0300

    NSToBytes переделал с исключением

commit 2bacdc8c28
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Wed Nov 20 13:20:33 2024 +0300

    Комментарии к NewSet

commit e917ac8eca
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Wed Nov 20 12:42:15 2024 +0300

    TypeName для set

commit 206289c6a7
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Tue Nov 19 20:23:03 2024 +0300

    Везде заменил _hs на hs в NewSet

    Убрал вызовы методов расширений NewSet в PABCSystem.pas

    Убрал var в operator +

commit d8262078f6
Author: 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 надо бы сделать исключение

commit f8819665ba
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Sat Nov 16 10:56:11 2024 +0300

    NS2

commit 591d9ebe60
Author: Ivan Bondarev <ibond84@googlemail.com>
Date:   Wed Nov 13 21:34:10 2024 +0100

    fix

commit c6505634f4
Author: Ivan Bondarev <ibond84@googlemail.com>
Date:   Wed Nov 13 21:12:33 2024 +0100

    fix

commit a6564df23c
Author: Ivan Bondarev <ibond84@googlemail.com>
Date:   Wed Nov 13 20:52:29 2024 +0100

    fix in new sets

commit 03be5bd931
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Wed Nov 13 22:13:41 2024 +0300

    Переставил operator:= в NewSet

commit 96c68f1666
Author: Ivan Bondarev <ibond84@googlemail.com>
Date:   Tue Nov 12 21:38:07 2024 +0100

    #3223

commit 82776f3c77
Author: Mikhalkovich Stanislav <miks@math.sfedu.ru>
Date:   Sat Nov 9 12:18:19 2024 +0300

    NewSet - много мелких исправлений.

    Все тесты проходят кроме Tests 5 - видимо с pabcrtl.dll

* Update comments in PascalABCLanguageInformation
2025-04-10 13:13:17 +03:00

4158 lines
166 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using PascalABCCompiler.SyntaxTree;
using System.Reflection;
using PascalABCCompiler.Parsers;
using PascalABCCompiler;
using PascalABCCompiler.ParserTools.Directives;
using static PascalABCCompiler.ParserTools.Directives.DirectiveHelper;
namespace Languages.Pascal.Frontend.Data
{
public class PascalABCLanguageInformation : ILanguageInformation
{
protected IParser Parser
{
get
{
// Поле парсера желательно убрать отсюда EVA
return Facade.LanguageProvider.Instance.SelectLanguageByName(StringConstants.pascalLanguageName).Parser;
}
}
public BaseKeywords KeywordsStorage { get; } = new Core.PascalABCKeywords();
public Dictionary<string, DirectiveInfo> ValidDirectives { get; private set; }
public PascalABCLanguageInformation()
{
InitializeValidDirectives();
}
/// <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
}
public bool IsKeyword(string value)
{
// typeof и sizeof воспринимаются Intellisense по другому EVA
return !value.Equals("typeof", StringComparison.CurrentCultureIgnoreCase) && !value.Equals("sizeof", StringComparison.CurrentCultureIgnoreCase)
&& KeywordsStorage.KeywordsToTokens.ContainsKey(value);
}
public virtual string BodyStartBracket
{
get
{
return "begin";
}
}
public virtual string BodyEndBracket
{
get
{
return "end";
}
}
public virtual string SystemUnitName
{
get
{
return PascalABCCompiler.StringConstants.pascalSystemUnitName;
}
}
public List<string> Keywords
{
get
{
return KeywordsStorage.Keywords;
}
}
public List<string> TypeKeywords
{
get
{
return KeywordsStorage.TypeKeywords;
}
}
public virtual string ParameterDelimiter
{
get
{
return ";";
}
}
public virtual bool CaseSensitive
{
get
{
return false;
}
}
public virtual bool IncludeDotNetEntities
{
get
{
return true;
}
}
public virtual string GetDescription(IBaseScope scope)
{
switch (scope.Kind)
{
case ScopeKind.Type : return GetDescriptionForType(scope as ITypeScope);
case ScopeKind.CompiledType : return GetDescriptionForCompiledType(scope as ICompiledTypeScope);
case ScopeKind.Delegate : return GetDescriptionForDelegate(scope as IProcType);
case ScopeKind.TypeSynonim : return GetSynonimDescription(scope as ITypeSynonimScope);
case ScopeKind.Array : return GetDescriptionForArray(scope as IArrayScope);
case ScopeKind.Diapason : return GetDescriptionForDiapason(scope as IDiapasonScope);
case ScopeKind.File : return GetDescriptionForFile(scope as IFileScope);
case ScopeKind.Pointer : return GetDescriptionForPointer(scope as IPointerScope);
case ScopeKind.Enum : return GetDescriptionForEnum(scope as IEnumScope);
case ScopeKind.Set : return GetDescriptionForSet(scope as ISetScope);
case ScopeKind.ElementScope : return GetDescriptionForElementScope(scope as IElementScope);
case ScopeKind.CompiledField : return GetDescriptionForCompiledField(scope as ICompiledFieldScope);
case ScopeKind.CompiledProperty : return GetDescriptionForCompiledProperty(scope as ICompiledPropertyScope);
case ScopeKind.CompiledMethod : return GetDescriptionForCompiledMethod(scope as ICompiledMethodScope);
case ScopeKind.Namespace : return GetDescriptionForNamespace(scope as INamespaceScope);
case ScopeKind.Procedure : return GetDescriptionForProcedure(scope as IProcScope);
case ScopeKind.CompiledEvent : return GetDescriptionForCompiledEvent(scope as ICompiledEventScope);
case ScopeKind.CompiledConstructor : return GetDescriptionForCompiledConstructor(scope as ICompiledConstructorScope);
case ScopeKind.ShortString : return GetDescriptionForShortString(scope as IShortStringScope);
//case ScopeKind.Procedure : return GetDescriptionForProcedure(scope as IProcScope);
}
return "";
}
public virtual string GetSimpleDescription(IBaseScope scope)
{
if (scope == null)
return "";
switch (scope.Kind)
{
case ScopeKind.Delegate :
case ScopeKind.Array :
case ScopeKind.Diapason :
case ScopeKind.File :
case ScopeKind.Pointer :
case ScopeKind.Enum :
case ScopeKind.Set :
case ScopeKind.ShortString :
if (scope is ITypeScope && (scope as ITypeScope).Aliased)
return scope.Name;
break;
}
switch (scope.Kind)
{
case ScopeKind.Type : return GetSimpleDescriptionForType(scope as ITypeScope);
case ScopeKind.CompiledType : return GetSimpleDescriptionForCompiledType(scope as ICompiledTypeScope);
case ScopeKind.Delegate : return GetDescriptionForDelegate(scope as IProcType);
case ScopeKind.TypeSynonim : return GetSimpleSynonimDescription(scope as ITypeSynonimScope);
case ScopeKind.Array : return GetDescriptionForArray(scope as IArrayScope);
case ScopeKind.Diapason : return GetDescriptionForDiapason(scope as IDiapasonScope);
case ScopeKind.File : return GetDescriptionForFile(scope as IFileScope);
case ScopeKind.Pointer : return GetDescriptionForPointer(scope as IPointerScope);
case ScopeKind.Enum : return GetDescriptionForEnum(scope as IEnumScope);
case ScopeKind.Set : return GetDescriptionForSet(scope as ISetScope);
case ScopeKind.ElementScope : return GetSimpleDescriptionForElementScope(scope as IElementScope);
case ScopeKind.CompiledField : return GetDescriptionForCompiledField(scope as ICompiledFieldScope);
case ScopeKind.CompiledProperty : return GetDescriptionForCompiledProperty(scope as ICompiledPropertyScope);
case ScopeKind.CompiledMethod : return GetDescriptionForCompiledMethod(scope as ICompiledMethodScope);
case ScopeKind.Namespace : return GetDescriptionForNamespace(scope as INamespaceScope);
case ScopeKind.Procedure : return GetSimpleDescriptionForProcedure(scope as IProcScope);
case ScopeKind.CompiledEvent : return GetDescriptionForCompiledEvent(scope as ICompiledEventScope);
case ScopeKind.CompiledConstructor : return GetDescriptionForCompiledConstructor(scope as ICompiledConstructorScope);
case ScopeKind.ShortString : return GetDescriptionForShortString(scope as IShortStringScope);
case ScopeKind.UnitInterface : return GetDescriptionForModule(scope as IInterfaceUnitScope);
//case ScopeKind.Procedure : return GetDescriptionForProcedure(scope as IProcScope);
}
return "";
}
public virtual string GetDescriptionForModule(IInterfaceUnitScope scope)
{
return (scope.IsNamespaceUnit?"namespace ":"unit ")+scope.Name;
}
public virtual string GetShortName(ICompiledTypeScope scope)
{
return GetShortTypeName(scope.CompiledType);
}
public virtual string GetShortName(ICompiledMethodScope scope)
{
return GetShortTypeName(scope.CompiledMethod);
}
public virtual string GetShortName(ICompiledConstructorScope scope)
{
return "Create";
}
public virtual string GetShortName(IProcScope scope)
{
StringBuilder sb = new StringBuilder();
sb.Append(scope.Name);
if (scope.TemplateParameters != null && scope.TemplateParameters.Length > 0)
sb.Append("<>");
return sb.ToString();
}
public virtual string GetFullTypeName(ICompiledTypeScope scope, bool no_alias=true)
{
return GetFullTypeName(scope.CompiledType);
}
public virtual string GetKeyword(SymbolKind kind)
{
switch (kind)
{
case SymbolKind.Class : return "class";
case SymbolKind.Enum : return "enum";
case SymbolKind.Struct : return "record";
case SymbolKind.Type : return "type";
case SymbolKind.Interface : return "interface";
case SymbolKind.Null : return "nil";
}
return "";
}
public virtual string GetArrayDescription(string elementType, int rank)
{
if (rank == 1)
return "array of "+elementType;
else
{
StringBuilder sb = new StringBuilder();
sb.Append('[');
sb.Append(',',rank-1);
sb.Append(']');
return "array"+sb.ToString()+" of "+elementType;
}
}
public string GetCompiledTypeTextRepresentation(Type t)
{
StringBuilder sb = new StringBuilder();
sb.Append("type "+t.Name+" = ");
if (t.IsEnum)
{
//sb.Append(GetEnum(t));
sb.AppendLine(";");
return sb.ToString();
}
else if (t.BaseType == typeof(MulticastDelegate))
{
//sb.Append(GetDelegate(t));
sb.AppendLine(";");
return sb.ToString();
}
else if (t.IsInterface)
sb.Append("interface");
else if (t.IsValueType)
sb.Append("record");
else if (t.IsClass)
sb.Append("class");
if (t.BaseType != null)
{
sb.Append('(');
sb.Append(GetFullTypeName(t.BaseType));
}
Type[] intfs = t.GetInterfaces();
if (intfs.Length > 0)
{
if (t.BaseType == null)
sb.Append('(');
for (int i=0; i<intfs.Length; i++)
{
if (i != 0 || t.BaseType != null)
sb.Append(", ");
sb.Append(GetFullTypeName(intfs[i]));
}
}
return sb.ToString();
}
public virtual string GetStandardTypeByKeyword(KeywordKind keyw)
{
switch (keyw)
{
case KeywordKind.ByteType : return "byte";
case KeywordKind.SByteType : return "shortint";
case KeywordKind.ShortType : return "smallint";
case KeywordKind.UShortType : return "word";
case KeywordKind.IntType : return "integer";
case KeywordKind.UIntType : return "longword";
case KeywordKind.Int64Type : return "int64";
case KeywordKind.UInt64Type : return "uint64";
case KeywordKind.DoubleType : return "real";
case KeywordKind.FloatType : return "single";
case KeywordKind.CharType : return "char";
case KeywordKind.BoolType : return "boolean";
case KeywordKind.PointerType : return "pointer";
}
return null;
}
protected virtual string GetDescriptionForDelegate(IProcType t)
{
StringBuilder sb = new StringBuilder();
if (t.Target.ReturnType != null)
sb.Append("function");
else sb.Append("procedure");
IElementScope[] prms = t.Target.Parameters;
if (prms.Length > 0)
{
sb.Append('(');
for (int i=0; i<prms.Length; i++)
{
sb.Append(GetSimpleDescription(prms[i]));
if (i < prms.Length - 1)
{
sb.Append("; ");
}
}
sb.Append(')');
}
if (t.Target.ReturnType != null)
{
sb.Append(": "+GetSimpleDescription(t.Target.ReturnType));
}
return sb.ToString();
}
protected virtual string GetFullTypeName(Type ctn, bool no_alias = true)
{
TypeCode tc = Type.GetTypeCode(ctn);
if (ctn.FullName == null && !ctn.IsArray && !ctn.IsGenericTypeDefinition && ctn.IsGenericParameter)
return ctn.Name;
if (!ctn.IsEnum)
{
switch (tc)
{
case TypeCode.Int32: return "integer";
case TypeCode.Double: return "real";
case TypeCode.Boolean: return "boolean";
case TypeCode.String: return "string";
case TypeCode.Char: return "char";
case TypeCode.Byte: return "byte";
case TypeCode.SByte: return "shortint";
case TypeCode.Int16: return "smallint";
case TypeCode.Int64: return "int64";
case TypeCode.UInt16: return "word";
case TypeCode.UInt32: return "longword";
case TypeCode.UInt64: return "uint64";
case TypeCode.Single: return "single";
}
if (ctn.IsPointer)
if (ctn.FullName == "System.Void*")
return "pointer";
else
return "^" + GetFullTypeName(ctn.GetElementType());
}
else
return ctn.FullName;
if (!no_alias)
{
if (ctn.Name.Contains("Func`") || ctn.Name.Contains("Predicate`"))
return getLambdaRepresentation(ctn, true, new List<string>());
else if (ctn.Name.Contains("Action`"))
return getLambdaRepresentation(ctn, false, new List<string>());
else if (ctn.Name == "IEnumerable`1")
return "sequence of " + GetShortTypeName(ctn.GetGenericArguments()[0], false);
else if (ctn.Name.Contains("Tuple`"))
return get_tuple_string(ctn);
}
int gen_pos = ctn.Name.IndexOf("`");
if (gen_pos != -1 || ctn.IsGenericType)
{
int len = ctn.GetGenericArguments().Length;
Type[] gen_ps = ctn.GetGenericArguments();
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (gen_pos != -1)
sb.Append(ctn.Namespace + "." + ctn.Name.Substring(0, gen_pos));
else
sb.Append(ctn.Namespace + "." + ctn.Name);
sb.Append('<');
for (int i = 0; i < len; i++)
{
sb.Append(gen_ps[i].Name);
if (i < len - 1)
sb.Append(", ");
}
sb.Append('>');
return sb.ToString();
}
if (ctn.IsArray)
{
var rank = ctn.GetArrayRank();
var strrank = rank > 1 ? "[" + new string(',', rank - 1) + "]" : "";
return $"array{strrank}" + " of " + GetFullTypeName(ctn.GetElementType());
}
if (ctn == Type.GetType("System.Void*")) return "pointer";
if (ctn.IsNested)
return ctn.Name;
return ctn.FullName;
}
private string get_tuple_string(ITypeScope[] generic_args)
{
StringBuilder sb = new StringBuilder();
sb.Append("(");
for (int i = 0; i < generic_args.Length; i++)
{
sb.Append(GetSimpleDescriptionWithoutNamespace(generic_args[i]));
if (i < generic_args.Length - 1)
sb.Append(",");
}
sb.Append(")");
return sb.ToString();
}
private string get_tuple_string(Type t)
{
StringBuilder sb = new StringBuilder();
sb.Append("(");
Type[] generic_args = t.GetGenericArguments();
for (int i = 0; i<generic_args.Length; i++)
{
sb.Append(GetShortTypeName(generic_args[i], false));
if (i < generic_args.Length - 1)
sb.Append(",");
}
sb.Append(")");
return sb.ToString();
}
private bool enum_out_of_order(FieldInfo[] fields) //возвращает true, если значения полей этого enum'а идут не по порядку или не с нуля (IDE issue #117)
{
for (int i = 0; i < fields.Length; i++)
{
if (fields[i].Name != "value__")
{
object o = fields[i].GetRawConstantValue(); //ошибка была здесь, так как я не знал, что у констант enum'а может быть другой тип помимо int
if (o is byte b1)
{
if (b1 != i - 1) return true;
}
else if (o is sbyte b2)
{
if (b2 != i - 1) return true;
}
else if (o is short b3)
{
if (b3 != i - 1) return true;
}
else if (o is ushort b4)
{
if (b4 != i - 1) return true;
}
else if (o is int b5)
{
if (b5 != i - 1) return true;
}
else if (o is uint b6)
{
return true;
}
else if (o is long b7)
{
return true;
}
else if (o is ulong b8)
{
return true;
}
}
}
return false;
}
private string get_enum_constants(Type t)
{
FieldInfo[] fields = t.GetFields(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.Static);
bool outoforder = enum_out_of_order(fields);
bool is_flags = Attribute.IsDefined(t, typeof(FlagsAttribute));
int max_name_len = fields.Max(fi => fi.Name.Length);
StringBuilder sb = new StringBuilder();
sb.AppendLine("(");
for (int i = 0; i < fields.Length; i++)
{
if (fields[i].Name != "value__")
{
sb.Append(' ', 4);
sb.Append(fields[i].Name);
if (outoforder)
{
if (is_flags) sb.Append(' ', max_name_len - fields[i].Name.Length);
sb.Append(" = ");
if (is_flags)
sb.Append('$' + Convert.ToInt64(fields[i].GetRawConstantValue()).ToString("X")); else
sb.Append(fields[i].GetRawConstantValue());
}
if (i < fields.Length - 1)
sb.AppendLine(",");
else
sb.AppendLine();
}
}
sb.Append(");");
return sb.ToString();
}
public virtual string GetCompiledTypeRepresentation(Type t, MemberInfo mi, ref int line, ref int col)
{
StringBuilder sb = new StringBuilder();
int ln = 1;
if (t.Namespace == "System")
sb.AppendLine("unit SystemUnit;");
else
sb.AppendLine("unit " + t.Namespace.Replace(".", "_") + ";");
ln++;
sb.AppendLine(); ln++;
sb.AppendLine("type "); ln++;
if (mi == t)
{
line = ln;
col = 1;
}
string doc = CodeCompletionTools.AssemblyDocCache.GetDocumentation(t);
if (!string.IsNullOrEmpty(doc))
{
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
doc = doc.Replace("<params>", "");
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
doc = doc.Replace("</param>", "");
sb.AppendLine(" /// " + doc);
}
if (mi == t)
{
line = get_line_nr(sb);
col = 1;
}
sb.Append(" ");
int ind = t.Name.IndexOf('`');
if (ind != -1 || t.IsGenericType)
{
if (ind != -1)
sb.Append(prepare_member_name(t.Name.Substring(0, ind)));
else
sb.Append(t.Name);
sb.Append('<');
Type[] gen_args = t.GetGenericArguments();
for (int i = 0; i < gen_args.Length; i++)
{
sb.Append(gen_args[i].Name);
if (i < gen_args.Length - 1)
sb.Append(", ");
}
sb.Append('>');
}
else
sb.Append(prepare_member_name(t.Name));
sb.Append(" = " + (t.IsSealed && t.IsAbstract ? "static ":"")+GetClassKeyword(t));
bool bracket = false;
if (t.IsEnum)
{
sb.AppendLine(get_enum_constants(t));
sb.AppendLine();
sb.AppendLine("end.");
return sb.ToString();
}
if (t.BaseType != null && t.BaseType != typeof(object))
{
sb.Append("(");
bracket = true;
sb.Append(GetFullTypeName(t.BaseType));
}
Type[] intfs = t.GetInterfaces();
if (intfs.Length > 0)
if (!bracket)
{
sb.Append("(");
bracket = true;
}
else
sb.Append(", ");
for (int i = 0; i < intfs.Length; i++)
{
sb.Append(GetFullTypeName(intfs[i]));
if (i < intfs.Length - 1)
sb.Append(", ");
}
if (bracket)
sb.Append(")");
sb.AppendLine(); ln++;
FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (fields.Length > 0)
{
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)
{
doc = CodeCompletionTools.AssemblyDocCache.GetDocumentation(fields[i]);
if (!string.IsNullOrEmpty(doc))
{
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
doc = doc.Replace("<params>", "");
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
doc = doc.Replace("</param>", "");
sb.AppendLine(" /// " + doc);
ln++;
}
if (fields[i] == mi || fields[i].Name == mi.Name)
{
line = get_line_nr(sb);
col = 3;
}
sb.Append(" ");
sb.Append(GetDescriptionForCompiledField(fields[i]));
sb.AppendLine(); ln++;
sb.AppendLine(); ln++;
}
}
sb.AppendLine(" {$endregion}");
sb.AppendLine();
}
EventInfo[] events = t.GetEvents(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (events.Length > 0)
{
sb.AppendLine(" {$region " + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_EVENTS") + "}");
for (int i = 0; i < events.Length; i++)
{
if (events[i].DeclaringType != t)
continue;
MethodInfo add_meth = events[i].GetAddMethod(true);
if (add_meth != null && add_meth.DeclaringType == t && !add_meth.IsPrivate && !add_meth.IsAssembly)
{
doc = CodeCompletionTools.AssemblyDocCache.GetDocumentation(events[i]);
if (!string.IsNullOrEmpty(doc))
{
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
doc = doc.Replace("<params>", "");
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
doc = doc.Replace("</param>", "");
sb.AppendLine(" /// " + doc);
}
if (events[i] == mi || events[i].Name == mi.Name)
{
line = get_line_nr(sb);
col = 3;
}
sb.Append(" ");
sb.Append(GetDescriptionForCompiledEvent(events[i]));
sb.AppendLine(); ln++;
sb.AppendLine(); ln++;
}
}
sb.AppendLine(" {$endregion}");
sb.AppendLine();
}
PropertyInfo[] props = t.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (props.Length > 0)
{
sb.AppendLine(" {$region " + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PROPERTIES") + "}");
for (int i = 0; i < props.Length; i++)
{
if (props[i].DeclaringType != t)
continue;
MethodInfo get_meth = props[i].GetGetMethod(true);
if (get_meth != null && get_meth.DeclaringType == t && !get_meth.IsPrivate && !get_meth.IsAssembly)
{
doc = CodeCompletionTools.AssemblyDocCache.GetDocumentation(props[i]);
if (!string.IsNullOrEmpty(doc))
{
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
doc = doc.Replace("<params>", "");
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
doc = doc.Replace("</param>", "");
sb.AppendLine(" /// " + doc);
}
if (props[i] == mi || props[i].Name == mi.Name)
{
line = get_line_nr(sb);
col = 3;
}
sb.Append(" ");
sb.Append(GetDescriptionForCompiledProperty(props[i]).Replace("; readonly"," read"));
sb.AppendLine(); ln++;
sb.AppendLine(); ln++;
}
}
sb.AppendLine(" {$endregion}");
sb.AppendLine();
}
ConstructorInfo[] constrs = t.GetConstructors(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (constrs.Length > 0)
{
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)
{
doc = CodeCompletionTools.AssemblyDocCache.GetDocumentation(constrs[i]);
if (!string.IsNullOrEmpty(doc))
{
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
doc = doc.Replace("<params>", "");
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
doc = doc.Replace("</param>", "");
sb.AppendLine(" /// " + doc);
}
if (constrs[i] == mi)
{
line = get_line_nr(sb);
col = 3;
}
sb.Append(" ");
sb.Append(GetDescriptionForCompiledConstructor(constrs[i]));
sb.AppendLine(); ln++;
sb.AppendLine(); ln++;
}
}
sb.AppendLine(" {$endregion}");
sb.AppendLine();
}
MethodInfo[] meths = t.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (meths.Length > 0)
{
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_"))
{
doc = CodeCompletionTools.AssemblyDocCache.GetDocumentation(meths[i]);
if (!string.IsNullOrEmpty(doc))
{
doc = doc.Trim(' ', '\n', '\t', '\r').Replace(Environment.NewLine, Environment.NewLine + " /// ");
doc = doc.Replace("<returns>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_RETURN_VALUE"));
doc = doc.Replace("<params>", "");
doc = doc.Replace("<param>", PascalABCCompiler.StringResources.Get("CODE_COMPLETION_PARAMETER"));
doc = doc.Replace("</param>", "");
sb.AppendLine(" /// " + doc);
}
if (meths[i] == mi || (meths[i].Name == mi.Name))
{
line = get_line_nr(sb);
col = 3;
}
sb.Append(" ");
sb.Append(GetDescriptionForCompiledMethod(meths[i]));
sb.AppendLine(); ln++;
sb.AppendLine(); ln++;
}
}
sb.AppendLine(" {$endregion}");
sb.AppendLine();
}
sb.AppendLine(" end;");
sb.AppendLine();
sb.AppendLine("end.");
return sb.ToString();
}
private int get_line_nr(StringBuilder sb)
{
int line = 1;
for (int i = 0; i < sb.Length; i++)
if (sb[i] == '\n')
line++;
return line;
}
public virtual string GetCompiledMethodRepresentation(MethodInfo mi)
{
return null;
}
public virtual string GetCompiledFieldRepresentation(FieldInfo mi)
{
return null;
}
public virtual string GetCompiledPropertyRepresentation(PropertyInfo mi)
{
return null;
}
public virtual string GetCompiledEventRepresentation(EventInfo mi)
{
return null;
}
public virtual string GetCompiledConstructorRepresentation(ConstructorInfo mi)
{
return null;
}
public virtual string GetClassKeyword(Type t)
{
if (t.IsInterface)
return "interface";
if (t.IsEnum)
return "";
if (t.IsValueType)
return "record";
if (t.IsClass)
return "class";
return "";
}
public virtual string GetClassKeyword(PascalABCCompiler.SyntaxTree.class_keyword keyw)
{
switch(keyw)
{
case PascalABCCompiler.SyntaxTree.class_keyword.Class : return "class";
case PascalABCCompiler.SyntaxTree.class_keyword.Interface : return "interface";
case PascalABCCompiler.SyntaxTree.class_keyword.Record : return "record";
case PascalABCCompiler.SyntaxTree.class_keyword.TemplateClass : return "template class";
case PascalABCCompiler.SyntaxTree.class_keyword.TemplateRecord : return "template record";
case PascalABCCompiler.SyntaxTree.class_keyword.TemplateInterface : return "template interface";
}
return null;
}
protected virtual string GetShortTypeName(MethodInfo mi)
{
StringBuilder sb = new StringBuilder();
sb.Append(mi.Name);
if (mi.GetGenericArguments().Length > 0)
sb.Append("<>");
return sb.ToString();
}
public virtual string GetShortTypeName(Type ctn, bool noalias=true)
{
TypeCode tc = Type.GetTypeCode(ctn);
if (ctn.FullName == null && !ctn.IsArray && !ctn.IsGenericTypeDefinition && ctn.IsGenericParameter)
return ctn.Name;
if (!ctn.IsEnum)
{
switch (tc)
{
case TypeCode.Int32: return "integer";
case TypeCode.Double: return "real";
case TypeCode.Boolean: return "boolean";
case TypeCode.String: return "string";
case TypeCode.Char: return "char";
case TypeCode.Byte: return "byte";
case TypeCode.SByte: return "shortint";
case TypeCode.Int16: return "smallint";
case TypeCode.Int64: return "int64";
case TypeCode.UInt16: return "word";
case TypeCode.UInt32: return "longword";
case TypeCode.UInt64: return "uint64";
case TypeCode.Single: return "single";
}
if (ctn.IsPointer)
if (ctn.FullName == "System.Void*")
return "pointer";
else
return "^" + GetShortTypeName(ctn.GetElementType(), noalias);
}
else return ctn.Name;
if (ctn.Name.Contains("`"))
{
if (!noalias)
{
if (ctn.Name.Contains("Func`") || ctn.Name.Contains("Predicate`"))
return getLambdaRepresentation(ctn, true, new List<string>());
else if (ctn.Name.Contains("Action`"))
return getLambdaRepresentation(ctn, false, new List<string>());
else if (ctn.Name == "IEnumerable`1")
return "sequence of " + GetShortTypeName(ctn.GetGenericArguments()[0], false);
else if (ctn.Name.Contains("Tuple`"))
return get_tuple_string(ctn);
}
int len = ctn.GetGenericArguments().Length;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(ctn.Name.Substring(0,ctn.Name.IndexOf('`')));
sb.Append('<');
if (!noalias)
{
Type[] gen_ps = ctn.GetGenericArguments();
for (int i = 0; i < len; i++)
{
sb.Append(gen_ps[i].Name);
if (i < len - 1)
sb.Append(", ");
}
}
sb.Append('>');
/*sb.Append('<');
for (int i=0; i<len; i++)
{
sb.Append('T');
if (i<len-1)
sb.Append(',');
}
sb.Append('>');*/
return sb.ToString();
}
if (ctn.IsArray)
{
var rank = ctn.GetArrayRank();
var strrank = rank > 1 ? "[" + new string(',', rank - 1) + "]" : "";
return $"array{strrank}" + " of " + GetShortTypeName(ctn.GetElementType());
}
//if (ctn == Type.GetType("System.Void*")) return PascalABCCompiler.StringConstants.pointer_type_name;
return ctn.Name;
}
protected virtual string GetTopScopeName(IBaseScope sc)
{
if (sc == null) return "";
if (sc.Name == "" || sc.Name.Contains("$") || sc.Name == "PABCSystem") return "";
if (sc is IProcScope) return "";
if (sc is ITypeScope)
{
return sc.Name+(((sc as ITypeScope).TemplateArguments != null && !sc.Name.EndsWith("<>") && sc.Name != "class")?"<>":"")+".";
}
return sc.Name + ".";
}
private string GetTopScopeNameWithoutDot(IBaseScope sc)
{
if (sc == null) return "";
if (sc.Name == "" || sc.Name.Contains("$") || sc.Name == "PABCSystem") return "";
if (sc is IProcScope) return "";
if (sc is ITypeScope)
{
return sc.Name+(((sc as ITypeScope).TemplateArguments != null && !sc.Name.EndsWith("<>"))? "<>":"");
}
return sc.Name;
}
protected virtual string GetTemplateString(ITypeScope scope)
{
string[] generic_params = scope.TemplateArguments;
if (generic_params != null && generic_params.Length > 0)
{
ITypeScope[] gen_insts = scope.GenericInstances;
if (gen_insts == null || gen_insts.Length == 0)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append('<');
for (int i=0; i<generic_params.Length; i++)
{
sb.Append(generic_params[i]);
if (i < generic_params.Length -1)
sb.Append(',');
}
sb.Append('>');
return sb.ToString();
}
else
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append('<');
for (int i=0; i<gen_insts.Length; i++)
{
sb.Append(GetSimpleDescriptionWithoutNamespace(gen_insts[i]));
if (i < gen_insts.Length -1)
sb.Append(", ");
}
sb.Append('>');
return sb.ToString();
}
}
return null;
}
protected virtual string GetDescriptionForType(ITypeScope scope)
{
string template_str=GetTemplateString(scope);
switch(scope.ElemKind)
{
case SymbolKind.Class :
string mod = "";
if (scope.IsStatic)
mod = "static ";
else
{
if (scope.IsAbstract)
mod = "abstract ";
if (scope.IsFinal)
mod += "sealed ";
}
if (scope.TopScope != null && scope.TopScope.Name != "" && !scope.TopScope.Name.Contains("$"))
return mod+"class "+scope.TopScope.Name + "." +scope.Name+template_str;
else return mod+"class "+scope.Name+template_str;
case SymbolKind.Interface :
if (scope.TopScope != null && scope.TopScope.Name != "" && !scope.TopScope.Name.Contains("$"))
return "interface "+scope.TopScope.Name + "." +scope.Name+template_str;
else return "interface "+scope.Name+template_str;
case SymbolKind.Enum :
if (scope.TopScope != null && scope.TopScope.Name != "" && !scope.TopScope.Name.Contains("$"))
return "enum "+scope.TopScope.Name + "." +scope.Name;
else return "enum "+scope.Name;
case SymbolKind.Delegate :
if (scope.TopScope != null && scope.TopScope.Name != "" && !scope.TopScope.Name.Contains("$"))
return "delegate "+scope.TopScope.Name + "." +scope.Name+template_str;
else return "delegate "+scope.Name+template_str;
case SymbolKind.Struct :
if (scope.TopScope != null && scope.TopScope.Name != "" && !scope.TopScope.Name.Contains("$"))
return "record "+scope.TopScope.Name + "." +scope.Name+template_str;
else return "record "+scope.Name+template_str;
}
if (scope.TopScope != null)
return scope.TopScope.Name + "." +scope.Name;
else return scope.Name;
}
protected virtual string GetSimpleDescriptionForType(ITypeScope scope)
{
string template_str = GetTemplateString(scope);
if (scope.Name.StartsWith("$"))
return scope.Name.Substring(1, scope.Name.Length - 1) + template_str;
if (!string.IsNullOrEmpty(template_str))
return scope.Name.Replace("<>", "") + template_str;
return scope.Name + template_str;
}
protected virtual string GetDescriptionForCompiledType(ICompiledTypeScope scope)
{
string s = GetFullTypeName(scope.CompiledType);
ITypeScope[] instances = scope.GenericInstances;
if (instances.Length > 0)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
int ind = s.IndexOf('<');
if (ind != -1) sb.Append(s.Substring(0,ind));
else
sb.Append(s);
sb.Append('<');
for (int i=0; i<instances.Length; i++)
{
sb.Append(GetSimpleDescriptionWithoutNamespace(instances[i]));
//sb.Append(instances[i].Name);
if (i < instances.Length - 1) sb.Append(", ");
}
sb.Append('>');
s = sb.ToString();
}
switch(scope.ElemKind)
{
case SymbolKind.Class :
string mod = "";
if (scope.IsStatic)
mod = "static ";
else
{
if (scope.IsAbstract)
mod = "abstract ";
if (scope.IsFinal)
mod += "sealed ";
}
return mod+"class "+s;
case SymbolKind.Interface :
return "interface "+s;
case SymbolKind.Enum :
return "enum "+s;
case SymbolKind.Delegate :
return "delegate "+s;
case SymbolKind.Struct :
return "record "+s;
case SymbolKind.Type :
return "type "+s;
}
return s;
}
public virtual string GetSimpleDescriptionWithoutNamespace(ITypeScope scope)
{
ICompiledTypeScope cts = scope as ICompiledTypeScope;
if (cts == null)
return GetSimpleDescription(scope);
string s = GetShortName(cts);
ITypeScope[] instances = scope.GenericInstances;
if (instances != null && instances.Length > 0)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
int ind = s.IndexOf('<');
if (ind != -1) sb.Append(s.Substring(0, ind));
else
sb.Append(s);
sb.Append('<');
for (int i = 0; i < instances.Length; i++)
{
sb.Append(GetSimpleDescriptionWithoutNamespace(instances[i]));
if (i < instances.Length - 1) sb.Append(", ");
}
sb.Append('>');
s = sb.ToString();
}
return s;
}
protected bool isIdentifier(string str)
{
foreach (char c in str)
{
if (!char.IsLetterOrDigit(c))
return false;
}
return true;
}
protected string getLambdaRepresentation(Type t, bool has_return_value, List<string> parameters, Dictionary<string, string> generic_param_args=null)
{
StringBuilder sb = new StringBuilder();
if (parameters.Count != t.GetGenericArguments().Length || true)
{
List<string> old_parameters = parameters;
parameters = new List<string>();
int ind = 0;
foreach (Type generic_arg in t.GetGenericArguments())
{
if (generic_arg.IsGenericParameter)
{
if (generic_param_args != null)
{
if (generic_param_args.ContainsKey(generic_arg.Name))
parameters.Add(generic_param_args[generic_arg.Name]);
else
parameters.Add(generic_arg.Name);
}
else if (ind < old_parameters.Count)
{
parameters.Add(old_parameters[ind]);
ind++;
}
else
parameters.Add(generic_arg.Name);
}
else
//parameters.Add(GetShortTypeName(generic_arg, false));
parameters.Add(get_type_instance(generic_arg,parameters,generic_param_args));
}
}
foreach (string parameter in parameters)
{
if (!isIdentifier(parameter))
return get_type_instance(t, parameters, generic_param_args, true);
}
if (has_return_value)
{
if (parameters.Count > 2)
sb.Append("(" + string.Join(",", parameters.GetRange(0, parameters.Count - 1).ToArray()) + ")->" + parameters[parameters.Count - 1]);
else if (parameters.Count > 1)
sb.Append(parameters[0] + "->" + parameters[1]);
else if (parameters.Count == 1)
{
if (t.FullName == "System.Predicate`1" || t.Name == "Predicate`1")
sb.Append(parameters[0] + "->boolean");
else
sb.Append("()->" + parameters[0]);
}
}
else if (parameters.Count > 0)
{
if (t.FullName == "System.Predicate`1" || t.Name == "Predicate`1")
sb.Append(parameters[0] + "->boolean");
else if (parameters.Count > 1)
sb.Append("(" + string.Join(",", parameters.ToArray()) + ")->()");
else
sb.Append(parameters[0] + "->()");
}
if (sb.Length == 0)
sb.Append(t.Name);
return sb.ToString();
}
protected string getLambdaRepresentation(ICompiledTypeScope scope, bool has_return_value)
{
StringBuilder sb = new StringBuilder();
ITypeScope[] instances = scope.GenericInstances;
List<string> parameters = new List<string>();
if (instances != null && instances.Length > 0)
{
foreach (ITypeScope ts in instances)
parameters.Add(GetSimpleDescriptionWithoutNamespace(ts));
}
/*else
{
foreach (Type t in scope.CompiledType.GetGenericArguments())
parameters.Add(t.Name);
}*/
return getLambdaRepresentation(scope.CompiledType, has_return_value, parameters);
}
protected string GetSimpleDescriptionForCompiledType(ICompiledTypeScope scope, bool fullName)
{
if (scope.CompiledType.Name != null && scope.CompiledType.Name.Contains("Func`"))
{
return getLambdaRepresentation(scope, true);
}
else if (scope.CompiledType.Name != null && scope.CompiledType.Name.Contains("Action`"))
{
return getLambdaRepresentation(scope, false);
}
else if (scope.CompiledType.Name != null && scope.CompiledType.Name.Contains("Predicate`1"))
{
return getLambdaRepresentation(scope, false);
}
else if (scope.CompiledType.Name == "IEnumerable`1")
{
ITypeScope[] instances = scope.GenericInstances;
if (instances != null && instances.Length > 0)
{
return "sequence of " + GetSimpleDescriptionWithoutNamespace(instances[0]);
}
else
return "sequence of T";
}
else if (scope.CompiledType.Name != null && scope.CompiledType.Name.Contains("Tuple`"))
{
ITypeScope[] instances = scope.GenericInstances;
if (instances != null && instances.Length > 0)
{
return get_tuple_string(instances);
}
else
return "(T1,...)";
}
else
{
string s = !fullName?GetShortTypeName(scope.CompiledType):GetFullTypeName(scope.CompiledType);
ITypeScope[] instances = scope.GenericInstances;
if (instances != null && instances.Length > 0)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
int ind = s.IndexOf('<');
if (ind != -1) sb.Append(s.Substring(0, ind));
else
sb.Append(s);
sb.Append('<');
for (int i = 0; i < instances.Length; i++)
{
sb.Append(GetSimpleDescriptionWithoutNamespace(instances[i]));
if (i < instances.Length - 1) sb.Append(", ");
}
sb.Append('>');
s = sb.ToString();
}
return s;
}
}
protected virtual string GetSimpleDescriptionForCompiledType(ICompiledTypeScope scope)
{
return GetSimpleDescriptionForCompiledType(scope, false);
}
protected virtual string GetDescriptionForArray(IArrayScope scope)
{
StringBuilder sb = new StringBuilder();
sb.Append("array");
ITypeScope[] inds = scope.Indexers;
if (!scope.IsDynamic)
{
sb.Append('[');
for (int i=0; i<inds.Length; i++)
{
sb.Append(GetSimpleDescription(inds[i]));
if (i<inds.Length-1) sb.Append(',');
}
sb.Append(']');
}
if (scope.ElementType != null)
{
string s = GetSimpleDescription(scope.ElementType);
if (s.Length > 0 && s[0] == '$') s = s.Substring(1,s.Length-1);
sb.Append(" of "+s);
}
return sb.ToString();
}
protected virtual string GetDescriptionForDiapason(IDiapasonScope scope)
{
return scope.Left.ToString() + ".." + scope.Right.ToString();
}
protected virtual string GetDescriptionForFile(IFileScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("file");
if (scope.ElementType != null)
{
string s = GetSimpleDescription(scope.ElementType);
if (s.Length > 0 && s[0] == '$') s = s.Substring(1,s.Length-1);
sb.Append(" of "+s);
}
return sb.ToString();
}
private Stack<ITypeScope> typs = new Stack<ITypeScope>();
protected virtual string GetDescriptionForPointer(IPointerScope scope)
{
string s = "";
if (scope.ElementType != null)
{
if (!typs.Contains(scope))
{
typs.Push(scope);
s = "^"+GetSimpleDescription(scope.ElementType);
}
else
s = "";
}
else
s = "pointer";
if (typs.Count > 0)
typs.Pop();
return s;
}
protected virtual string GetDescriptionForEnum(IEnumScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append('(');
for (int i=0; i<scope.EnumConsts.Length; i++)
{
sb.Append(scope.EnumConsts[i]);
if (i < scope.EnumConsts.Length-1)
sb.Append(',');
if (i >= 2)
{
sb.Append("...");
break;
}
}
sb.Append(')');
return sb.ToString();
}
protected virtual string GetDescriptionForSet(ISetScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("set of ");
if (scope.ElementType != null)
{
string s = GetSimpleDescription(scope.ElementType);
if (s.Length > 0 && s[0] == '$') s = s.Substring(1,s.Length-1);
sb.Append(s);
}
return sb.ToString();
}
private string kind_of_param(IElementScope scope)
{
switch (scope.ParamKind)
{
case PascalABCCompiler.SyntaxTree.parametr_kind.const_parametr : return "const ";
case PascalABCCompiler.SyntaxTree.parametr_kind.var_parametr : return "var ";
case PascalABCCompiler.SyntaxTree.parametr_kind.params_parametr : return "params ";
case PascalABCCompiler.SyntaxTree.parametr_kind.out_parametr : return "out ";
}
return "";
}
protected virtual string get_index_description(IElementScope scope)
{
ITypeScope[] indexers = scope.Indexers;
if (indexers == null || indexers.Length == 0) return "";
StringBuilder sb = new StringBuilder();
sb.Append('[');
for (int i=0; i<indexers.Length; i++)
{
sb.Append(GetSimpleDescription(indexers[i]));
if (i <indexers.Length-1)
sb.Append(',');
}
sb.Append(']');
return sb.ToString();
}
private void append_modifiers(StringBuilder sb, IElementScope scope)
{
if (scope.IsVirtual) sb.Append("; virtual");
if (scope.IsAbstract) sb.Append("; abstract");
if (scope.IsOverride) sb.Append("; override");
//if (scope.IsStatic) sb.Append("; static");
if (scope.IsReintroduce) sb.Append("; reintroduce");
}
protected virtual string GetDescriptionForElementScope(IElementScope scope)
{
string type_name = null;
StringBuilder sb = new StringBuilder();
if (scope.Type == null) type_name = "";
else
type_name = GetSimpleDescription(scope.Type);
if (type_name.StartsWith("$"))
type_name = type_name.Substring(1, type_name.Length - 1);
switch (scope.ElemKind)
{
case SymbolKind.Variable: sb.Append("var " + GetTopScopeName(scope.TopScope) + scope.Name + ((type_name != "")?": " + type_name:"")); break;
case SymbolKind.Parameter: sb.Append(kind_of_param(scope) + "parameter " + scope.Name + ": " + type_name + (scope.ConstantValue != null ? (":=" + scope.ConstantValue.ToString()) : "")); break;
case SymbolKind.Constant:
{
if (scope.ConstantValue == null)
sb.Append("const " + GetTopScopeName(scope.TopScope) + scope.Name + ": " + type_name);
else sb.Append("const " + GetTopScopeName(scope.TopScope) + scope.Name + ": " + type_name + " = " + scope.ConstantValue.ToString());
}
break;
case SymbolKind.Event:
if (scope.IsStatic) sb.Append("static ");
sb.Append("event " + GetTopScopeName(scope.TopScope) + scope.Name + ": " + type_name);
append_modifiers(sb, scope);
break;
case SymbolKind.Field:
if (scope.IsStatic)
sb.Append("static ");
else
sb.Append("var ");
sb.Append(GetTopScopeName(scope.TopScope) + scope.Name + ": " + type_name);
append_modifiers(sb, scope);
//if (scope.IsStatic) sb.Append("; static");
if (scope.IsReadOnly) sb.Append("; readonly");
break;
case SymbolKind.Property:
if (scope.IsStatic)
sb.Append("static ");
sb.Append("property " + GetTopScopeName(scope.TopScope) + scope.Name + get_index_description(scope) + ": " + type_name);
if (scope.IsReadOnly)
sb.Append("; readonly");
append_modifiers(sb, scope);
break;
}
sb.Append(';');
return sb.ToString();
}
protected virtual string GetSimpleDescriptionForElementScope(IElementScope scope)
{
string type_name = GetSimpleDescription(scope.Type);
if (type_name.StartsWith("$")) type_name = type_name.Substring(1,type_name.Length-1);
return kind_of_param(scope) + scope.Name + ": "+type_name + (scope.ConstantValue!=null?(":="+scope.ConstantValue.ToString()):"");
}
public virtual string GetDescriptionForCompiledField(FieldInfo fi)
{
StringBuilder sb = new StringBuilder();
if (fi.IsPublic)
sb.Append("public ");
else if (fi.IsFamily)
sb.Append("protected ");
if (!fi.IsLiteral)
if (fi.IsStatic) sb.Append("static ");
if (!fi.IsLiteral)
{
sb.Append(prepare_member_name(fi.Name));
sb.Append(" : " + GetFullTypeName(fi.FieldType));
}
else
{
var fitype = GetFullTypeName(fi.FieldType);
sb.Append("const " + fi.Name + " : " + fitype);
sb.Append(" = " + (fitype == "string" ? $"'{fi.GetRawConstantValue().ToString()}'" : fi.GetRawConstantValue().ToString()));
}
sb.Append(";");
return sb.ToString();
}
protected virtual string GetDescriptionForCompiledField(ICompiledFieldScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (!scope.CompiledField.IsLiteral)
if (scope.CompiledField.IsStatic && !scope.IsGlobal) sb.Append("static ");
else sb.Append("var ");
string inst_type = null;
if (scope.GenericArgs != null)
{
inst_type = get_type_instance(scope.CompiledField.FieldType,scope.GenericArgs);
}
if (!scope.CompiledField.IsLiteral)
sb.Append(GetShortTypeName(scope.CompiledField.DeclaringType) +"."+ scope.CompiledField.Name + ": "+(inst_type != null?inst_type:GetSimpleDescription(scope.Type)));
else
sb.Append("const "+GetShortTypeName(scope.CompiledField.DeclaringType) +"."+ scope.CompiledField.Name + ": "+GetSimpleDescription(scope.Type));
//if (scope.CompiledField.IsStatic) sb.Append("; static");
if (scope.IsReadOnly) sb.Append("; readonly");
sb.Append(';');
return sb.ToString();
}
private string get_indexer_for_prop(ICompiledPropertyScope scope)
{
ITypeScope[] indexers = scope.Indexers;
if (indexers.Length == 0) return "";
StringBuilder sb = new StringBuilder();
sb.Append('[');
for (int i=0; i<indexers.Length; i++)
{
sb.Append(GetSimpleDescriptionWithoutNamespace(indexers[i]));
if (i<indexers.Length-1)
sb.Append(',');
}
sb.Append(']');
return sb.ToString();
}
public virtual string GetDescriptionForCompiledProperty(PropertyInfo pi)
{
StringBuilder sb = new StringBuilder();
MethodInfo get_meth = pi.GetGetMethod(true);
MethodInfo set_meth = pi.GetSetMethod(true);
if (get_meth.IsPublic)
sb.Append("public ");
else if (get_meth.IsFamily)
sb.Append("protected ");
if (get_meth.IsStatic) sb.Append("static ");
sb.Append("property " + prepare_member_name(pi.Name));
ParameterInfo[] prms = get_meth.GetParameters();
if (prms.Length > 0)
{
sb.Append('[');
for (int i = 0; i < prms.Length; i++)
{
sb.Append(prepare_member_name(prms[i].Name));
sb.Append(": ");
sb.Append(GetFullTypeName(prms[i].ParameterType));
if (i < prms.Length - 1)
sb.Append("; ");
}
sb.Append(']');
}
sb.Append(" : " + GetFullTypeName(pi.PropertyType));
if (set_meth == null)
sb.Append("; readonly");
sb.Append(";");
return sb.ToString();
}
protected virtual string GetDescriptionForCompiledProperty(ICompiledPropertyScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
MethodInfo acc = scope.CompiledProperty.GetGetMethod();
string inst_type = null;
if (acc != null)
if (acc.IsStatic) sb.Append("static ");
if (scope.Type is ICompiledTypeScope && scope.GenericArgs != null)
{
Type t = (scope.Type as ICompiledTypeScope).CompiledType;
inst_type = get_type_instance(t,scope.GenericArgs);
}
sb.Append("property "+ GetShortTypeName(scope.CompiledProperty.DeclaringType) +"."+ scope.CompiledProperty.Name + get_indexer_for_prop(scope));
if (inst_type == null)
{
if (scope.Type is ICompiledTypeScope)
sb.Append(": " + GetFullTypeName((scope.Type as ICompiledTypeScope).CompiledType, false));
else
sb.Append(": " + GetSimpleDescription(scope.Type));
}
else
sb.Append(": " + inst_type);
if (acc != null)
//if (acc.IsStatic) sb.Append("; static");
if (acc.IsVirtual) sb.Append("; virtual");
else if (acc.IsAbstract) sb.Append("; abstract");
if (scope.IsReadOnly) sb.Append("; readonly");
sb.Append(';');
return sb.ToString();
}
private bool is_params(ParameterInfo _par)
{
object[] objarr = _par.GetCustomAttributes(typeof(ParamArrayAttribute), true);
if ((objarr == null) || (objarr.Length == 0))
{
return false;
}
return true;
}
private string get_type_instance(Type t, List<string> generic_args, Dictionary<string, string> generic_param_args=null, bool no_alias=false)
{
if (t.IsGenericParameter)
{
if (generic_param_args != null)
{
if (generic_param_args.ContainsKey(t.Name))
return generic_param_args[t.Name];
else
return t.Name;
}
else if (t.GenericParameterPosition < generic_args.Count)
return generic_args[t.GenericParameterPosition];
else
return t.Name;
}
if (t.IsArray)
return "array of " + get_type_instance(t.GetElementType(), generic_args, generic_param_args, no_alias);
if (t.ContainsGenericParameters)
{
if (!no_alias)
{
if (t.Name == "IEnumerable`1")
{
Type tt = t.GetGenericArguments()[0];
if (generic_param_args != null)
{
if (tt.IsGenericParameter && generic_param_args.ContainsKey(tt.Name))
return "sequence of " + generic_param_args[tt.Name];
else
return "sequence of " + GetShortTypeName(tt, false);
}
else
return "sequence of " + (generic_args.Count>0?generic_args[0]:GetShortTypeName(tt, false));
}
else if (t.Name.Contains("Func`") || t.Name.Contains("Predicate`"))
return getLambdaRepresentation(t, true, generic_args, generic_param_args);
else if (t.Name.Contains("Action`") )
return getLambdaRepresentation(t, false, generic_args, generic_param_args);
else if (t.Name.Contains("Tuple`"))
return get_tuple_string(t);
}
string name = GetShortTypeName(t);
StringBuilder sb = new StringBuilder();
int ind = name.IndexOf('<');
if (ind == -1)
return name;
sb.Append(name.Substring(0, ind));
Type[] args = t.GetGenericArguments();
sb.Append('<');
for (int i = 0; i < args.Length; i++)
{
if (args[i].IsGenericParameter)
{
if (generic_param_args != null)
{
if (generic_param_args.ContainsKey(args[i].Name))
sb.Append(generic_param_args[args[i].Name]);
else
sb.Append(args[i].Name);
}
else if (args[i].GenericParameterPosition < generic_args.Count)
sb.Append(generic_args[args[i].GenericParameterPosition]);
else
sb.Append(args[i].Name);
}
else
sb.Append(get_type_instance(args[i], generic_args, generic_param_args));
if (i < args.Length - 1)
sb.Append(", ");
}
sb.Append('>');
return sb.ToString();
}
return GetFullTypeName(t, no_alias);
}
public virtual string GetDescriptionForCompiledMethod(MethodInfo mi)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (mi.IsPublic)
sb.Append("public ");
else if (mi.IsFamily)
sb.Append("protected ");
if (mi.IsStatic) sb.Append("static ");
if (mi.ReturnType == typeof(void))
sb.Append("procedure ");
else
sb.Append("function ");
sb.Append(prepare_member_name(mi.Name));
if (mi.GetGenericArguments().Length > 0)
{
Type[] tt = mi.GetGenericArguments();
sb.Append('<');
for (int i = 0; i < tt.Length; i++)
{
sb.Append(tt[i].Name);
if (i < tt.Length - 1) sb.Append(", ");
}
sb.Append('>');
}
sb.Append('(');
ParameterInfo[] pis = mi.GetParameters();
for (int i = 0; i < pis.Length; i++)
{
if (pis[i].ParameterType.IsByRef)
sb.Append("var ");
else if (is_params(pis[i]))
sb.Append("params ");
sb.Append(prepare_member_name(pis[i].Name));
sb.Append(": ");
string inst_type = null;
if (!pis[i].ParameterType.IsByRef)
{
sb.Append(GetFullTypeName(pis[i].ParameterType));
if (pis[i].IsOptional)
{
sb.Append(" := ");
if (pis[i].DefaultValue != null)
{
if (pis[i].DefaultValue is string) sb.Append($"'{pis[i].DefaultValue.ToString()}'");
else sb.Append(pis[i].DefaultValue.ToString());
}
else sb.Append("nil");
}
}
else
{
Type t = pis[i].ParameterType.GetElementType();
sb.Append(GetFullTypeName(t));
}
if (i < pis.Length - 1)
sb.Append("; ");
}
sb.Append(')');
string ret_inst_type = null;
if (mi.ReturnType != typeof(void))
{
sb.Append(": " + GetFullTypeName(mi.ReturnType));
}
//if (scope.CompiledMethod.IsStatic) sb.Append("; static");
if (mi.IsVirtual && !mi.IsFinal) sb.Append("; virtual");
else if (mi.IsAbstract) sb.Append("; abstract");
//else if (scope.CompiledMethod.IsHideBySig) sb.Append("; reintroduce");
sb.Append(';');
return sb.ToString();
}
protected virtual string GetDescriptionForCompiledMethod(ICompiledMethodScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
string extensionType = null;
if (scope.IsExtension && scope.Parameters.Length > 0)
{
extensionType = GetSimpleDescription(scope.Parameters[0].Type);
}
if (scope.IsExtension)
{
if (extensionType.IndexOf(' ') != -1)
{
sb.Append("(" + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_EXTENSION") + " " + extensionType + ") ");
}
else
{
sb.Append("(" + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_EXTENSION") + ") ");
extensionType = null;
}
}
if (scope.IsStatic && !scope.IsGlobal) sb.Append("static ");
if (scope.ReturnType == null)
sb.Append("procedure ");
else
sb.Append("function ");
Dictionary<string, string> generic_param_args = null;
Dictionary<string, int> class_generic_table = new Dictionary<string, int>();
ParameterInfo[] pis = scope.CompiledMethod.GetParameters();
Type[] tt = scope.CompiledMethod.GetGenericArguments();
int gen_ind = 0;
if (!scope.IsExtension)
{
sb.Append(GetShortTypeName(scope.CompiledMethod.DeclaringType));
int ind = 0;
foreach (Type gen_arg in scope.CompiledMethod.DeclaringType.GetGenericArguments())
{
if (gen_arg.IsGenericParameter)
{
if (generic_param_args == null)
generic_param_args = new Dictionary<string, string>();
if (scope.GenericArgs != null && scope.GenericArgs.Count > ind)
generic_param_args.Add(gen_arg.Name, scope.GenericArgs[ind]);
else if (scope.DeclaringType.TemplateArguments != null && scope.DeclaringType.TemplateArguments.Length > ind)
generic_param_args.Add(gen_arg.Name, scope.DeclaringType.TemplateArguments[ind]);
}
ind++;
}
}
else
{
gen_ind = 0;
generic_param_args = new Dictionary<string, string>();
for (int i = 0; i < pis.Length; i++)
{
if (i == 0)
{
Type[] class_generic_args = pis[i].ParameterType.GetGenericArguments();
for (int j = 0; j < class_generic_args.Length; j++)
{
if (!class_generic_table.ContainsKey(class_generic_args[i].Name))
class_generic_table.Add(class_generic_args[i].Name, j);
if (scope.GenericArgs != null && scope.GenericArgs.Count > j)
{
if (scope.DeclaringType.GenericInstances.Length > 0)
generic_param_args[class_generic_args[i].Name] = GetSimpleDescription(scope.DeclaringType.GenericInstances[0]);
else if (scope.DeclaringType is ICompiledTypeScope)
{
Type ctn = (scope.DeclaringType as ICompiledTypeScope).CompiledType;
if (ctn.IsGenericType && !ctn.IsGenericTypeDefinition)
generic_param_args[class_generic_args[i].Name] = GetSimpleDescriptionForCompiledType((scope.DeclaringType as ICompiledTypeScope).GetCompiledGenericArguments()[0]);
}
}
else if (scope.DeclaringType.TemplateArguments != null && scope.DeclaringType.TemplateArguments.Length > j)
generic_param_args[class_generic_args[i].Name] = scope.DeclaringType.TemplateArguments[j];
}
break;
}
}
if (extensionType == null)
sb.Append(GetShortTypeName(scope.CompiledMethod.GetParameters()[0].ParameterType));
}
//if (scope.Name != "Invoke")
{
if (extensionType == null)
sb.Append(".");
sb.Append(scope.Name);
}
if (scope.CompiledMethod.GetGenericArguments().Length > 0)
{
sb.Append('<');
for (int i = gen_ind; i < tt.Length; i++)
{
if (class_generic_table.ContainsKey(tt[i].Name))
{
int ind = class_generic_table[tt[i].Name];
if (scope.GenericArgs != null && scope.GenericArgs.Count > ind)
{
if (scope.DeclaringType.GenericInstances.Length > ind)
{
sb.Append(GetSimpleDescription(scope.DeclaringType.GenericInstances[ind]));
if (!generic_param_args.ContainsKey(tt[i].Name))
generic_param_args.Add(tt[i].Name, GetSimpleDescription(scope.DeclaringType.GenericInstances[ind]));
}
else if (scope.DeclaringType is ICompiledTypeScope)
{
Type ctn = (scope.DeclaringType as ICompiledTypeScope).CompiledType;
if (ctn.IsGenericType && !ctn.IsGenericTypeDefinition)
{
sb.Append(GetSimpleDescription((scope.DeclaringType as ICompiledTypeScope).GetCompiledGenericArguments()[ind]));
if (!generic_param_args.ContainsKey(tt[i].Name))
generic_param_args.Add(tt[i].Name, GetSimpleDescription((scope.DeclaringType as ICompiledTypeScope).GetCompiledGenericArguments()[ind]));
}
}
}
}
else
sb.Append(tt[i].Name);
if (i < tt.Length - 1) sb.Append(", ");
}
sb.Append('>');
}
sb.Append('(');
for (int i = 0; i < pis.Length; i++)
{
if (i == 0 && scope.IsExtension)
continue;
if (pis[i].ParameterType.IsByRef)
sb.Append("var ");
else if (is_params(pis[i]))
sb.Append("params ");
sb.Append(pis[i].Name);
sb.Append(": ");
string inst_type = null;
if (!pis[i].ParameterType.IsByRef)
{
if (scope.GenericArgs != null)
{
inst_type = get_type_instance(pis[i].ParameterType, scope.GenericArgs, generic_param_args);
}
if (inst_type == null)
sb.Append(GetShortTypeName(pis[i].ParameterType, false));
else
sb.Append(inst_type);
if (pis[i].IsOptional)
{
sb.Append(" := ");
if (pis[i].DefaultValue != null)
{
if (pis[i].DefaultValue is string) sb.Append($"'{pis[i].DefaultValue.ToString()}'");
else sb.Append(pis[i].DefaultValue.ToString());
}
else sb.Append("nil");
}
}
else
{
Type t = pis[i].ParameterType.GetElementType();
if (scope.GenericArgs != null)
{
inst_type = get_type_instance(t, scope.GenericArgs, generic_param_args);
}
if (inst_type == null)
sb.Append(GetShortTypeName(t, false));
else
sb.Append(inst_type);
}
if (i < pis.Length - 1)
sb.Append("; ");
}
sb.Append(')');
string ret_inst_type = null;
if (scope.ReturnType != null)
{
if (scope.GenericArgs != null)
{
ret_inst_type = get_type_instance(scope.CompiledMethod.ReturnType, scope.GenericArgs, generic_param_args);
}
if (ret_inst_type == null)
{
if (scope.ReturnType is ICompiledTypeScope)
sb.Append(": " + GetFullTypeName((scope.ReturnType as ICompiledTypeScope).CompiledType, false));
else
sb.Append(": " + GetSimpleDescription(scope.ReturnType));
}
else
sb.Append(": " + ret_inst_type);
}
//if (scope.CompiledMethod.IsStatic) sb.Append("; static");
if (scope.IsVirtual) sb.Append("; virtual");
else if (scope.IsAbstract) sb.Append("; abstract");
//else if (scope.CompiledMethod.IsHideBySig) sb.Append("; reintroduce");
sb.Append(';');
return sb.ToString();
}
protected virtual string GetDescriptionForNamespace(INamespaceScope scope)
{
return "namespace "+scope.Name;
}
protected virtual string GetDescriptionForProcedure(IProcScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
string extensionType = null;
if (scope.IsExtension && scope.Parameters.Length > 0)
{
extensionType = GetSimpleDescription(scope.Parameters[0].Type);
}
if (scope.IsExtension)
{
if (extensionType != null && extensionType.IndexOf(' ') != -1)
{
sb.Append("(" + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_EXTENSION") + " " + extensionType + ") ");
extensionType = null;
}
else
{
sb.Append("(" + PascalABCCompiler.StringResources.Get("CODE_COMPLETION_EXTENSION")+ ") ");
}
}
if (scope.IsStatic) sb.Append("static ");
if (scope.IsConstructor())
sb.Append("constructor ");
else
if (scope.ReturnType == null)
sb.Append("procedure ");
else
sb.Append("function ");
if (!scope.IsConstructor())
{
if (extensionType != null)
{
sb.Append(extensionType+".");
sb.Append(scope.Name);
}
else
{
sb.Append(GetTopScopeName(scope.TopScope));
sb.Append(scope.Name);
}
}
else
{
sb.Append(GetTopScopeNameWithoutDot(scope.TopScope));
}
/*string[] template_args = scope.TemplateParameters;
if (template_args != null)
{
sb.Append('<');
for (int i=0; i<template_args.Length; i++)
{
sb.Append(template_args[i]);
if (i < template_args.Length-1)
sb.Append(',');
}
sb.Append('>');
}*/
sb.Append(GetGenericString(scope.TemplateParameters));
sb.Append('(');
IElementScope[] parameters = scope.Parameters;
for (int i=0; i<parameters.Length; i++)
{
if (scope.IsExtension && i == 0)
continue;
sb.Append(GetSimpleDescription(parameters[i]));
if (i < parameters.Length - 1)
{
sb.Append("; ");
}
}
sb.Append(')');
if (scope.ReturnType != null && !scope.IsConstructor() && !(scope.ReturnType is IProcType && (scope.ReturnType as IProcType).Target == scope))
sb.Append(": "+GetSimpleDescription(scope.ReturnType));
//if (scope.IsStatic) sb.Append("; static");
if (scope.IsVirtual) sb.Append("; virtual");
else if (scope.IsAbstract) sb.Append("; abstract");
else if (scope.IsOverride) sb.Append("; override");
else if (scope.IsReintroduce) sb.Append("; reintroduce");
sb.Append(';');
return sb.ToString();
}
protected virtual string GetGenericString(string[] template_args)
{
StringBuilder sb = new StringBuilder();
if (template_args != null)
{
sb.Append('<');
for (int i=0; i<template_args.Length; i++)
{
sb.Append(template_args[i]);
if (i < template_args.Length-1)
sb.Append(", ");
}
sb.Append('>');
}
return sb.ToString();
}
protected virtual string GetSimpleDescriptionForProcedure(IProcScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (scope.TopScope is ITypeScope && scope.Realization == null)
sb.Append(GetTopScopeName(scope.TopScope));
sb.Append(scope.Name);
sb.Append(GetGenericString(scope.TemplateParameters));
sb.Append('(');
IElementScope[] parameters = scope.Parameters;
for (int i=0; i<parameters.Length; i++)
{
sb.Append(GetSimpleDescription(parameters[i]));
if (i < parameters.Length - 1)
{
sb.Append("; ");
}
}
sb.Append(')');
return sb.ToString();
}
private string prepare_member_name(string s)
{
if (IsKeyword(s))
return "&" + s;
return s;
}
protected virtual string GetDescriptionForCompiledEvent(EventInfo ei)
{
MethodInfo add_meth = ei.GetAddMethod(true);
StringBuilder sb = new StringBuilder();
if (add_meth.IsPublic)
sb.Append("public ");
else if (add_meth.IsFamily)
sb.Append("protected ");
sb.Append((add_meth.IsStatic ? "static " : "") + "event " + prepare_member_name(ei.Name) + ": " + GetFullTypeName(ei.EventHandlerType) + ";");
return sb.ToString();
}
protected virtual string GetDescriptionForCompiledEvent(ICompiledEventScope scope)
{
return (scope.IsStatic?"static ":"")+"event "+ GetShortTypeName(scope.CompiledEvent.DeclaringType, true) +"."+ scope.CompiledEvent.Name + ": "+GetSimpleDescription(scope.Type)+ ";";
}
protected virtual string GetDescriptionForCompiledConstructor(ConstructorInfo ci)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (ci.IsPublic)
sb.Append("public ");
else if (ci.IsFamily)
sb.Append("protected ");
if (ci.IsStatic)
sb.Append("static ");
sb.Append("constructor ");
//sb.Append(".");
//sb.Append("Create");
sb.Append('(');
ParameterInfo[] pis = ci.GetParameters();
for (int i = 0; i < pis.Length; i++)
{
if (pis[i].ParameterType.IsByRef)
sb.Append("var ");
else if (is_params(pis[i]))
sb.Append("params ");
sb.Append(prepare_member_name(pis[i].Name));
sb.Append(": ");
if (!pis[i].ParameterType.IsByRef)
sb.Append(GetFullTypeName(pis[i].ParameterType));
else sb.Append(GetFullTypeName(pis[i].ParameterType.GetElementType()));
if (i < pis.Length - 1)
sb.Append("; ");
}
sb.Append(')');
sb.Append(';');
return sb.ToString();
}
protected virtual string GetDescriptionForCompiledConstructor(ICompiledConstructorScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("constructor ");
sb.Append(GetShortTypeName(scope.CompiledConstructor.DeclaringType));
//sb.Append(".");
//sb.Append("Create");
sb.Append('(');
ParameterInfo[] pis = scope.CompiledConstructor.GetParameters();
for (int i=0; i<pis.Length; i++)
{
if (pis[i].ParameterType.IsByRef)
sb.Append("var ");
else if (is_params(pis[i]))
sb.Append("params ");
sb.Append(pis[i].Name);
sb.Append(": ");
if (!pis[i].ParameterType.IsByRef)
sb.Append(GetFullTypeName(pis[i].ParameterType));
else sb.Append(GetFullTypeName(pis[i].ParameterType.GetElementType()));
if (i < pis.Length - 1)
sb.Append("; ");
}
sb.Append(')');
sb.Append(';');
return sb.ToString();
}
protected virtual string GetDescriptionForShortString(IShortStringScope scope)
{
return "string"+"["+scope.Length+"]";
}
public string GetSynonimDescription(ITypeScope scope)
{
return "type "+scope.Name + GetGenericString(scope.TemplateArguments)+" = " +scope.Description;
}
public string GetSynonimDescription(ITypeSynonimScope scope)
{
if (scope.ActType is ICompiledTypeScope && !(scope.ActType as ICompiledTypeScope).Aliased)
return "type " + scope.Name + GetGenericString(scope.TemplateArguments) + " = " + GetSimpleDescriptionForCompiledType(scope.ActType as ICompiledTypeScope, true);
else
return "type " + scope.Name+GetGenericString(scope.TemplateArguments) + " = " + GetSimpleDescription(scope.ActType);
}
public string GetSynonimDescription(IProcScope scope)
{
return "type "+scope.Name+" = "+scope.Description;
}
public virtual string[] GetIndexerString(IBaseScope scope)
{
IBaseScope tmp_si = scope;
if (scope == null) return null;
if (scope is IElementScope)
if ((scope as IElementScope).Indexers.Length == 0)
scope = (scope as IElementScope).Type;
if (scope is IProcScope) scope = (scope as IProcScope).ReturnType;
if (!(scope is IElementScope))
{
ITypeScope ts = scope as ITypeScope;
if (ts == null) return null;
ITypeScope[] indexers = ts.Indexers;
if (tmp_si is ITypeScope)
indexers = ts.StaticIndexers;
if ((indexers == null || indexers.Length == 0) && !(ts is IArrayScope))
return null;
StringBuilder sb = new StringBuilder();
if (!(tmp_si is ITypeScope))
sb.Append("this");
else
sb.Append(GetSimpleDescriptionWithoutNamespace(tmp_si as ITypeScope));
sb.Append('[');
if (indexers != null)
for (int i = 0; i < indexers.Length; i++)
{
sb.Append(GetSimpleDescriptionWithoutNamespace(indexers[i]));
if (i < indexers.Length - 1)
sb.Append(',');
}
else
sb.Append("integer");
sb.Append("] : ");
sb.Append(GetSimpleDescriptionWithoutNamespace(ts.ElementType));
return new string[1]{sb.ToString()};
}
else
{
IElementScope es = scope as IElementScope;
ITypeScope[] indexers = es.Indexers;
if (indexers == null || indexers.Length == 0 || es.ElementType == null) return null;
StringBuilder sb = new StringBuilder();
sb.Append(es.Name);
sb.Append('[');
for (int i=0; i<indexers.Length; i++)
{
sb.Append(GetSimpleDescriptionWithoutNamespace(indexers[i]));
if (i < indexers.Length - 1)
sb.Append(',');
}
sb.Append("] : ");
sb.Append(GetSimpleDescriptionWithoutNamespace(es.ElementType));
return new string[1]{sb.ToString()};
}
}
protected virtual string GetSimpleSynonimDescription(ITypeSynonimScope scope)
{
return scope.Name;
}
public virtual string GetStringForChar(char c)
{
return "'"+c.ToString()+"'";
}
public virtual string GetStringForSharpChar(int num)
{
return "#"+num.ToString();
}
public virtual string GetStringForString(string s)
{
return "'"+s+"'";
}
public KeywordKind GetKeywordKind(string name)
{
if (KeywordsStorage.KeywordKinds.TryGetValue(name, out var kind))
return kind;
else
return KeywordKind.None;
}
protected virtual string GetAccessModifier(access_modifer mod)
{
switch (mod)
{
case access_modifer.private_modifer : return "private";
case access_modifer.protected_modifer : return "protected";
case access_modifer.public_modifer : return "public";
case access_modifer.published_modifer : return "published";
case access_modifer.internal_modifer : return "internal";
}
return "";
}
public virtual string ConstructOverridedMethodHeader(IProcScope scope, out int off)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (scope.AccessModifier != access_modifer.internal_modifer)
sb.Append(GetAccessModifier(scope.AccessModifier)+" ");
if (scope.ReturnType == null)
sb.Append("procedure ");
else
sb.Append("function ");
off = sb.Length;
sb.Append(scope.Name);
sb.Append(GetGenericString(scope.TemplateParameters));
if (!(scope is ICompiledMethodScope))
{
IElementScope[] parameters = scope.Parameters;
if (parameters != null && parameters.Length > 0)
{
sb.Append('(');
for (int i=0; i<scope.Parameters.Length; i++)
{
sb.Append(GetSimpleDescription(parameters[i]));
if (i < parameters.Length - 1)
{
sb.Append("; ");
}
}
sb.Append(')');
}
}
else
{
ParameterInfo[] pis = (scope as ICompiledMethodScope).CompiledMethod.GetParameters();
if (pis.Length > 0)
{
sb.Append('(');
for (int i = 0; i < pis.Length; i++)
{
if (pis[i].ParameterType.IsByRef)
sb.Append("var ");
else if (is_params(pis[i]))
sb.Append("params ");
sb.Append(pis[i].Name);
sb.Append(": ");
if (!pis[i].ParameterType.IsByRef)
sb.Append(GetFullTypeName(pis[i].ParameterType));
else sb.Append(GetFullTypeName(pis[i].ParameterType.GetElementType()));
if (i < pis.Length - 1)
sb.Append("; ");
}
sb.Append(')');
}
}
if (scope.ReturnType != null)
sb.Append(": "+GetSimpleDescription(scope.ReturnType));
sb.Append("; override;");
return sb.ToString();
}
public virtual string ConstructHeader(IProcRealizationScope scope, int tabCount)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append('\t');
if (!scope.DefProc.IsAbstract)
sb.Append(GetAccessModifier(access_modifer.public_modifer)+" ");
else
if (scope.DefProc.AccessModifier != access_modifer.none && scope.DefProc.AccessModifier != access_modifer.internal_modifer)
sb.Append(GetAccessModifier(scope.DefProc.AccessModifier)+" ");
if (scope.DefProc.ReturnType == null)
sb.Append("procedure ");
else
sb.Append("function ");
sb.Append(scope.Name);
sb.Append(GetGenericString(scope.TemplateParameters));
if (!(scope.DefProc is ICompiledMethodScope))
{
IElementScope[] parameters = scope.DefProc.Parameters;
if (parameters != null && parameters.Length > 0)
{
sb.Append('(');
for (int i = 0; i < scope.DefProc.Parameters.Length; i++)
{
sb.Append(GetSimpleDescription(parameters[i]));
if (i < parameters.Length - 1)
{
sb.Append("; ");
}
}
sb.Append(')');
}
}
else
{
ParameterInfo[] pis = (scope.DefProc as ICompiledMethodScope).CompiledMethod.GetParameters();
if (pis.Length > 0)
{
sb.Append('(');
for (int i=0; i<pis.Length; i++)
{
if (pis[i].ParameterType.IsByRef)
sb.Append("var ");
else if (is_params(pis[i]))
sb.Append("params ");
sb.Append(pis[i].Name);
sb.Append(": ");
if (!pis[i].ParameterType.IsByRef)
sb.Append(GetFullTypeName(pis[i].ParameterType));
else sb.Append(GetFullTypeName(pis[i].ParameterType.GetElementType()));
if (i < pis.Length - 1)
sb.Append("; ");
}
sb.Append(')');
}
}
if (scope.DefProc.ReturnType != null)
sb.Append(": "+GetSimpleDescription(scope.DefProc.ReturnType));
sb.Append(';');
if (scope.DefProc.IsAbstract)
sb.Append("override;");
return sb.ToString();
}
private void get_procedure_template(procedure_header header, StringBuilder res, int col)
{
if (header.parameters != null)
for (int i=0; i<header.parameters.params_list.Count; i++)
for (int j=0; j<header.parameters.params_list[i].idents.idents.Count; j++)
{
res.AppendLine();
for (int k=0;k<col-3; k++)
res.Append(' ');
res.Append("/// <param name=\""+header.parameters.params_list[i].idents.idents[j].name+"\"></param>");
}
if (header is function_header)
{
res.AppendLine();
for (int k=0;k<col-3; k++)
res.Append(' ');
res.Append("/// <returns></returns>");
}
}
public virtual string GetDocumentTemplate(string lineText, string Text, int line, int col, int pos)
{
try
{
if (lineText == null) return "";
StringBuilder res = new StringBuilder();
if (lineText.StartsWith("procedure") || lineText.StartsWith("function") || lineText.StartsWith("constructor") || lineText.StartsWith("destructor"))
{
StringBuilder sb = new StringBuilder();
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;
procedure_header header = (node.program_block.defs.defs[0] as procedure_definition).proc_header;
get_procedure_template(header, res, col);
return res.ToString();
}
else if (lineText.StartsWith("class") || lineText.StartsWith("public") || lineText.StartsWith("private") || lineText.StartsWith("protected") || lineText.StartsWith("internal"))
{
StringBuilder sb = new StringBuilder();
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;
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;
get_procedure_template(header, res, col);
return res.ToString();
}
return "";
}
else return "";
}
catch
{
}
return "";
}
public virtual string ConstructHeader(string meth, IProcScope scope, int tabCount)
{
int i=0;
bool is_cnstr = false;
StringBuilder sb = new StringBuilder();
if (meth.StartsWith("static "))
meth = meth.Remove(0, "static ".Length);
else if (meth.StartsWith("class "))
meth = meth.Remove(0, "class ".Length);
if (scope.IsStatic)
sb.Append("static ");
while (i < meth.Length && char.IsLetterOrDigit(meth[i]))
{
sb.Append(meth[i++]);
}
if (sb.ToString().ToLower() == "constructor") is_cnstr = true;
sb.Append(' ');
while (i < meth.Length && !(char.IsLetterOrDigit(meth[i]) || meth[i] == '_' || meth[i] == '(' || meth[i] == ';'))
if (meth[i] == '{')
while (i<meth.Length && meth[i] != '}') i++;
else
i++;
if (i < meth.Length)
{
if (scope.TopScope is ITypeScope && ((scope.TopScope as ITypeScope).ElemKind == SymbolKind.Class || (scope.TopScope as ITypeScope).ElemKind == SymbolKind.Struct))
sb.Append(GetSimpleDescriptionForType(scope.TopScope as ITypeScope)+".");
//if (meth[i] == '(' || meth[i] == ';')
sb.Append(scope.Name);
sb.Append(GetGenericString(scope.TemplateParameters));
while (i < meth.Length && (char.IsLetterOrDigit(meth[i]) || meth[i] == '_')) i++;
while (i < meth.Length && meth[i] != ';' && meth[i] != '(' && meth[i] != ':')
if (meth[i] == '{') while (i<meth.Length && meth[i] != '}') i++;
else i++;
if (meth[i] == '(')
{
sb.Append('(');
bool in_kav = false;
Stack<char> sk_stack = new Stack<char>();
sk_stack.Push('(');i++;
bool default_value = false;
while (i < meth.Length && sk_stack.Count > 0)
{
if (meth[i] == '\'') in_kav = !in_kav;
else if (meth[i] == '(') {if (!in_kav) sk_stack.Push('(');}
else if (meth[i] == ')') {if (!in_kav) sk_stack.Pop();}
if (meth[i] == ':' && meth[i+1] == '=' && !in_kav)
default_value = true;
else if (meth[i] == ';' && !in_kav)
default_value = false;
if (!default_value || meth[i] == ')' && sk_stack.Count == 0)
{
if (meth[i] == ')' && sk_stack.Count == 0 && default_value)
sb = new StringBuilder(sb.ToString().TrimEnd());
sb.Append(meth[i]);
}
i++;
}
while (i<meth.Length && meth[i] != ':' && meth[i] != ';')
if (meth[i] == '{') while (i<meth.Length && meth[i] != '}') i++;
else sb.Append(meth[i++]);
//sb.Append(')');
}
if (meth[i] == ':')
{
bool in_kav = false;
while (i < meth.Length && !(meth[i] == ';' && !in_kav))
{
if (meth[i] == '{' && !in_kav) while (i<meth.Length && meth[i] != '}') i++;
else if (meth[i] == '\'') in_kav = !in_kav;
sb.Append(meth[i]);
i++;
}
}
sb.Append(';');
}
sb.AppendLine();
sb.AppendLine("begin");
for (int j=0; j<tabCount; j++)
sb.Append(' ');
sb.AppendLine();
sb.AppendLine("end;");
return sb.ToString();
}
private bool isOperator(string Text, int i, out int next)
{
next = i;
if (i >= 3)
{
string op = Text.Substring(i - 2, 3).ToLower().Trim();
if (op == "and" || op == "div" || op == "mod" || op == "xor")
{
if (!char.IsLetterOrDigit(Text[i - 3]) && Text[i - 3] != '_' && Text[i - 3] != '&' && !(i + 1 < Text.Length && char.IsLetterOrDigit(Text[i + 1])))
{
next = i - 3;
return true;
}
return false;
}
}
if (i >= 2)
{
string op = Text.Substring(i - 1, 2).ToLower().Trim();
if (op == "or")
{
if (!char.IsLetterOrDigit(Text[i - 2]) && Text[i - 2] != '_' && Text[i - 2] != '&' && !(i + 1 < Text.Length && char.IsLetterOrDigit(Text[i + 1])))
{
next = i - 2;
return true;
}
return false;
}
}
return false;
}
private void TestForKeyword(string Text, int i, ref int bound, bool sym_punkt, out KeywordKind keyword)
{
StringBuilder sb = new StringBuilder();
while (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_'))
{
sb.Insert(0, Text[i]);
i--;
}
while (i >= 0 && char.IsWhiteSpace(Text[i]))
{
i--;
}
if (i >= 0 && (Text[i] == '.' || Text[i] == '&'))
sb.Insert(0, Text[i]);
string s = sb.ToString().ToLower();
if (s == "new")
{
bound = i + 1;
keyword = KeywordKind.New;
}
else if ((s == "procedure" || s == "function") && !sym_punkt)
{
keyword = KeywordKind.Function;
}
else if (s == "constructor" && !sym_punkt)
{
keyword = KeywordKind.Constructor;
}
else if (s == "destructor" && !sym_punkt)
{
keyword = KeywordKind.Destructor;
}
else if (s == "uses")
{
keyword = KeywordKind.Uses;
}
else if (s == "inherited")
{
bound = i + 1;
keyword = KeywordKind.Inherited;
}
else if (s == "raise")
{
keyword = KeywordKind.Raise;
}
else if (IsKeyword(s))
{
keyword = KeywordKind.CommonKeyword;
}
else keyword = KeywordKind.None;
}
private bool CheckForComment(string Text, int off, out int comment_position, out bool one_line_comment)
{
int i = off;
one_line_comment = false;
comment_position = -1;
Stack<char> kav = new Stack<char>();
bool is_comm = false;
while (i>=0 && !is_comm && Text[i] != '\n' && Text[i] != '\r')
{
if (Text[i] == '\'')
{
if (kav.Count == 0) kav.Push('\'');
else kav.Pop();
}
else if (Text[i] == '{')
{
if (kav.Count == 0)
{
comment_position = i;
while (i >= 0 && Text[i] != '\'')
i--;
if (i >= 1 && Text[i - 1] == '$')
return false;
is_comm = true;
return is_comm;
}
}
else if (Text[i] == '}')
{
return false;
}
else if (Text[i] == '/')
if (i > 0 && Text[i-1] == '/' && kav.Count == 0)
{
is_comm = true;
one_line_comment = true;
comment_position = i - 1;
}
i--;
}
return is_comm;
}
public virtual string FindExpression(int off, string Text, int line, int col, out KeywordKind keyw)
{
int i = off - 1;
int bound = 0;
bool punkt_sym = false;
keyw = KeywordKind.None;
System.Text.StringBuilder sb = new StringBuilder();
Stack<char> tokens = new Stack<char>();
Stack<char> kav = new Stack<char>();
Stack<char> ugl_skobki = new Stack<char>();
int num_in_ident = -1;
keyw = TestForKeyword(Text, i);
if (keyw == KeywordKind.Punkt) return "";
while (i >= bound)
{
bool end = false;
char ch = Text[i];
if (kav.Count == 0 && (char.IsLetterOrDigit(ch) || ch == '_' || ch == '&' || ch == '\'' || ch == '!'))
{
num_in_ident = i;
if (kav.Count == 0 && tokens.Count == 0)
{
int tmp = i;
if (ch == '\'')
{
i--;
if (kav.Count == 0)
kav.Push('\'');
while (i >= 0)
{
if (Text[i] != '\'')
i--;
else
{
if (i >= 1 && Text[i - 1] == '\'')
i -= 2;
else
break;
}
}
if (i >= 0)
i--;
}
else
while (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '!'))
{
i--;
}
while (i >= 0 && (Text[i] == ' ' || char.IsControl(Text[i]) || Text[i] == '}'))
{
if (Text[i] != '}')
i--;
else
{
while (i >= 0 && Text[i] != '{') //propusk kommentariev
i--;
if (i >= 0)
i--;
}
}
if (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '!'))
{
bound = i + 1;
TestForKeyword(Text, i, ref bound, punkt_sym, out keyw);
for (int j = tmp; j > bound; j--)
{
sb.Insert(0, Text[j]);
}
if (sb.ToString().Trim() == "new")
return "";
i = bound;
continue;
}
else if (i >= 0 && Text[i] == '\'') return "";
i = tmp;
}
else
if (ch == '\'')
kav.Push('\'');
sb.Insert(0, ch);//.Append(Text[i]);
}
else if (ch == '.' || ch == '^' || ch == '&' || ch == '?' && IsPunctuation(Text, i + 1))
{
if (ch == '.' && i >= 1 && Text[i - 1] == '.' && tokens.Count == 0)
end = true;
else if (ch == '?' && i + 1 < Text.Length && Text[i + 1] != '.')
end = true;
else
sb.Insert(0, ch);
if (ch != '.')
punkt_sym = true;
}
else if (ch == '}')
{
if (kav.Count == 0)
{
while (i >= 0 && Text[i] != '{')
{
if (Text[i] != '$')//skip {$
sb.Insert(0, Text[i]);
i--;
}
if (i < 0)
{
break;
}
else if (Text[i] == '{')
{
sb.Insert(0, '{');
}
}
else
sb.Insert(0, ch);
}
else if (ch == '{')
{
if (kav.Count == 0)
{
if (keyw == KeywordKind.None)
return sb.ToString();
sb.Insert(0, ch);
break;
}
else sb.Insert(0, ch);
}
else
switch (ch)
{
case ')':
case ']':
if (kav.Count == 0)
{
string tmps = sb.ToString().Trim(' ', '\r', '\t', '\n');
if (tmps.Length >= 1 && (char.IsLetter(tmps[0]) || tmps[0] == '_' || tmps[0] == '&' || tmps[0] == '?' || tmps[0] == '!') && tokens.Count == 0)
end = true;
else
tokens.Push(ch);
}
if (!end)
{
sb.Insert(0, ch);
punkt_sym = true;
}
break;
case '>':
if (tokens.Count == 0)
{
int j = i + 1;
while (j < Text.Length && char.IsWhiteSpace(Text[j]))
j++;
if (ugl_skobki.Count > 0 || i == off - 1 || j == off && off == Text.Length || j < Text.Length && Text[i - 1] != '-' && (Text[j] == '.' || Text[j] == '('))
{
ugl_skobki.Push('>');
sb.Insert(0, ch);
}
else if (i >= 1 && Text[i - 1] == '-')
{
if (!(kav.Count == 0 && tokens.Count == 0))
sb.Insert(0, ch);
}
else
end = true;
}
else
sb.Insert(0, ch);
break;
case '<':
if (tokens.Count == 0)
{
if (ugl_skobki.Count > 0)
{
ugl_skobki.Pop();
sb.Insert(0, ch);
}
else
end = true;
}
else
sb.Insert(0, ch);
break;
case '[':
case '(':
case '|':
if (ch == '|' && ((tokens.Count == 0) || (tokens.Peek()==']') || (tokens.Peek() == ')') || (tokens.Peek() == ',')))
// Закрывающий | - после него (tokens.Pop()) - пусто или ] ) ,
{
if (kav.Count == 0)
{
string tmps = sb.ToString().Trim(' ', '\r', '\t', '\n');
if (tmps.Length >= 1 && (char.IsLetter(tmps[0]) || tmps[0] == '_' || tmps[0] == '&' || tmps[0] == '?' || tmps[0] == '!') && tokens.Count == 0)
end = true;
else
tokens.Push(ch);
}
if (!end)
{
sb.Insert(0, ch);
punkt_sym = true;
}
}
else
{
if (kav.Count == 0) // в т.ч. открывающий |
{
if (tokens.Count > 0)
{
tokens.Pop();
punkt_sym = true;
sb.Insert(0, ch);
if (ch == '(')
{
int tmp = i--;
/*while (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&'))
{
i--;
}*/
while (i >= 0 && (Text[i] == ' ' || char.IsControl(Text[i]) || Text[i] == '}'))
{
if (Text[i] != '}')
i--;
else
{
while (i >= 0 && Text[i] != '{') //propusk kommentariev
i--;
if (i >= 0)
i--;
}
}
if (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '!' || Text[i] == '?' && IsPunctuation(Text, i+1)))
{
bound = i + 1;
TestForKeyword(Text, i, ref bound, punkt_sym, out keyw);
if (keyw != KeywordKind.None && tokens.Count == 0)
{
end = true;
}
else bound = 0;
}
else if (i >= 0 && Text[i] == '\'') return "";
i = tmp;
}
}
else
{
end = true;
if (ch == '[')
{
keyw = KeywordKind.SquareBracket;
}
}
}
else sb.Insert(0, ch); punkt_sym = true;
}
break;
case '\'':
if (kav.Count == 0) kav.Push(ch); else kav.Pop();
sb.Insert(0, ch);
punkt_sym = true; break;
default:
if (!(ch == ' ' || char.IsControl(ch)))
{
if (kav.Count == 0)
{
if (ch == ',' && ugl_skobki.Count > 0)
sb.Insert(0, ch);
else
if (tokens.Count == 0)
end = true;
else
sb.Insert(0, ch);
}
else
sb.Insert(0, ch);
}
else
{
if (Text[i] == '\n')
{
bool one_line_comment = false;
int comment_position = -1;
if (CheckForComment(Text, i - 1, out comment_position, out one_line_comment))
{
if (!one_line_comment)
end = true;
else
{
sb.Insert(0, ch);
i = comment_position;
}
}
else
sb.Insert(0, ch);
}
else
sb.Insert(0, ch);
}
punkt_sym = true;
break;
}
if (end)
{
bool one_line_comment = false;
int comment_position = -1;
if (CheckForComment(Text, i, out comment_position, out one_line_comment))
{
int new_line_ind = sb.ToString().IndexOf('\n');
if (new_line_ind != -1) sb = sb.Remove(0, new_line_ind + 1);
else sb = sb.Remove(0, sb.Length);
}
break;
}
i--;
}
//return RemovePossibleKeywords(sb);
if (sb.Length > 0 && sb[sb.Length - 1] == '?')
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
public virtual string FindExpressionFromAnyPosition(int off, string Text, int line, int col, out string expr_without_brackets)
{
KeywordKind keyw = KeywordKind.None;
return FindExpressionFromAnyPosition(off, Text, line, col, out keyw, out expr_without_brackets);
}
private bool IsPunctuation(string Text, int ind)
{
while (ind < Text.Length && char.IsWhiteSpace(Text[ind]))
ind++;
if (ind >= Text.Length)
return true;
return char.IsPunctuation(Text[ind]);
}
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] == '!'))
{
//sb.Remove(0,sb.Length);
while (i >= 0 && (Char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '?' && IsPunctuation(Text, i + 1) || Text[i] == '!'))
{
//sb.Insert(0,Text[i]);//.Append(Text[i]);
i--;
}
is_char = true;
}
i = off;
if (i < Text.Length && Text[i] != ' ' && (Char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '?' && IsPunctuation(Text, i + 1) || Text[i] == '!'))
{
while (i < Text.Length && (Char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '!'))
{
//sb.Append(Text[i]);//.Append(Text[i]);
i++;
}
is_char = true;
}
if (is_char)
{
expr_without_brackets = FindExpression(i, Text, line, col, out keyw);
}
bool is_new = keyw == KeywordKind.New;
bool meth_call = false;
KeywordKind new_keyw = KeywordKind.None;
int j = i;
bool in_comment = false;
bool brackets = false;
while (j < Text.Length)
{
char c = Text[j];
if (c == '(' && !in_comment)
{
Stack<char> sk_stack = new Stack<char>();
in_comment = false;
bool in_kav = false;
sk_stack.Push('(');
j++;
while (j < Text.Length)
{
c = Text[j];
if (c == '(' && !in_kav)
sk_stack.Push('(');
else
if (c == ')' && !in_kav)
{
if (sk_stack.Count == 0)
{
break;
}
else
{
sk_stack.Pop();
if (sk_stack.Count == 0)
{
i = j + 1;
meth_call = true;
break;
}
}
}
else if (c == '\'' && !in_comment)
{
in_kav = !in_kav;
}
else if (c == '{' && !in_kav)
{
in_comment = true;
}
else if (c == '}' && !in_kav)
{
in_comment = false;
}
else if (c == '/' && !in_kav && !in_comment)
{
if (j + 1 < Text.Length && Text[j + 1] == '/')
break;
}
j++;
}
break;
}
else if ((c == '<' || c == '&' && j < Text.Length - 1 && Text[j+1] == '<') && !in_comment)
{
Stack<char> sk_stack = new Stack<char>();
if (c == '&')
j++;
sk_stack.Push('<');
j++;
bool generic = false;
while (j < Text.Length)
{
c = Text[j];
if (c == '>')
{
sk_stack.Pop();
if (sk_stack.Count == 0)
{
i = j + 1;
generic = true;
break;
}
}
else if (c == '<')
{
sk_stack.Push('<');
}
else if (!char.IsLetterOrDigit(c) && c != '?' && c != '&' && c != '.' && c != ' ' && c != '\t' && c != '\n' && c != ',' && c != '!')
{
break;
}
j++;
}
if (generic)
{
//break;
}
}
else if (c == '[' && !in_comment)
{
brackets = true;
break;
}
else if (c == '{')
{
in_comment = true;
}
else if (c == '}')
{
if (!in_comment)
break;
else
in_comment = false;
}
else if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
{
}
else
{
if (!in_comment)
break;
}
j++;
}
if (is_new && string.Compare(expr_without_brackets.Trim(' ', '\n', '\t', '\r'), "new", true) == 0 && !meth_call)
{
expr_without_brackets = null;
return null;
}
if (is_char)
{
string ss = FindExpression(i, Text, line, col, out new_keyw);
if (brackets && is_new)
{
int ind = ss.ToLower().IndexOf("new");
if (ind != -1)
return ss.Substring(ind + 3);
}
if (is_new && ss != null && ss.IndexOf("new") == -1 && ss.IndexOf(":") != -1)
return expr_without_brackets + "(true?"+ss;
return ss;
}
return null;
}
public virtual KeywordKind TestForKeyword(string Text, int i)
{
StringBuilder sb = new StringBuilder();
int orig_i = i;
int j = i;
bool in_keyw = false;
while (j >= 0 && Text[j] != '\n')
j--;
Stack<char> kav_stack = new Stack<char>();
j++;
bool in_format_str = false;
while (j <= i)
{
if (Text[j] == '\'')
{
if (kav_stack.Count == 0 && !in_keyw)
{
if (j == 0 || Text[j - 1] != '$')
kav_stack.Push('\'');
else
{
in_keyw = false;
in_format_str = true;
}
}
else if (kav_stack.Count > 0)
kav_stack.Pop();
}
else if (Text[j] == '{' && kav_stack.Count == 0 && !in_format_str)
in_keyw = true;
else
if (Text[j] == '}')
in_keyw = false;
j++;
}
j = i;
if ((kav_stack.Count != 0 || in_keyw) && !in_format_str) return PascalABCCompiler.Parsers.KeywordKind.Punkt;
if (j >= 0 && Text[j] == '.') return PascalABCCompiler.Parsers.KeywordKind.Punkt;
while (j >= 0)
{
//if (Text[j] == '{') return PascalABCCompiler.Parsers.KeywordKind.Punkt;
if (!in_keyw && (Text[j] == '\'' || Text[j] == '\n'))
break;
if (Text[j] == '}')
in_keyw = true;
else
if (Text[j] == '/' && !in_keyw)
if (j > 0 && Text[j - 1] == '/') return PascalABCCompiler.Parsers.KeywordKind.Punkt;
j--;
}
//if (j>= 0 && Text[j] == '\'') return CodeCompletion.KeywordKind.kw_punkt;
while (i >= 0 && (Text[i] == ' ' || char.IsControl(Text[i]))) i--;
if (i >= 0 && Text[i] == ':') return PascalABCCompiler.Parsers.KeywordKind.Colon;
if (i >= 0 && Text[i] == ',')
{
while (i >= 0 && Text[i] != '\n')
{
if (char.IsLetterOrDigit(Text[i]))
sb.Insert(0, Text[i]);
else
{
PascalABCCompiler.Parsers.KeywordKind keyw = GetKeywordKind(sb.ToString());
if (keyw == PascalABCCompiler.Parsers.KeywordKind.Uses)
return PascalABCCompiler.Parsers.KeywordKind.Uses;
else if (keyw == PascalABCCompiler.Parsers.KeywordKind.Var)
return PascalABCCompiler.Parsers.KeywordKind.Var;
else sb.Remove(0, sb.Length);
}
i--;
}
}
else
while (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '!'))
{
sb.Insert(0, Text[i]);
i--;
}
string s = sb.ToString().ToLower();
/*if (s == "new")
{
i = orig_i + 1;
while (i < Text.Length && char.IsWhiteSpace(Text[i]))
i++;
if (i < Text.Length && Text[i] != '(')
return KeywordKind.Punkt;
}*/
return GetKeywordKind(s);
}
public virtual string SkipNew(int off, string Text, ref KeywordKind keyw)
{
int tmp = off;
string expr = null;
while (off >= 0 && Char.IsLetterOrDigit(Text[off])) off--;
while (off >= 0 && (Text[off] == ' ' || char.IsControl(Text[off]))) off--;
if (off >= 1 && Text[off] == '=' && Text[off-1] == ':')
{
off -= 2;
while (off >= 0 && (Text[off] == ' ' || char.IsControl(Text[off]))) off--;
if (off >= 0 && (Text[off] == '_' || char.IsLetterOrDigit(Text[off]) || Text[off] == '!' || Text[off] == ']' || Text[off] == '>'))
expr = FindExpression(off+1,Text,0,0,out keyw);
}
return expr;
}
public virtual string FindExpressionForMethod(int off, string Text, int line, int col, char pressed_key, ref int num_param)
{
int i = off - 1;
string pattern = null;
int bound = 0;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
Stack<char> tokens = new Stack<char>();
Stack<char> kav = new Stack<char>();
Stack<char> skobki = new Stack<char>();
Stack<char> ugl_skobki = new Stack<char>();
bool comma_pressed = pressed_key == ',';
int num_in_ident = -1;
bool punkt_sym = false;
int next;
KeywordKind keyw = TestForKeyword(Text, i);
bool on_brace = false;
if (keyw == KeywordKind.Punkt)
return "";
try
{
while (i >= bound)
{
bool end = false;
char ch = Text[i];
if ((char.IsLetterOrDigit(ch) || ch == '_' || ch == '&' || ch == '!') && !isOperator(Text, i, out next))
{
num_in_ident = i;
if (kav.Count == 0 && tokens.Count == 0)
{
int tmp = i;
while (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '!') && !isOperator(Text, i, out next))
{
i--;
}
while (i >= 0 && (Text[i] == ' ' || char.IsControl(Text[i]) || Text[i] == '}'))
{
if (Text[i] != '}')
i--;
else
{
while (i >= 0 && Text[i] != '{') //propusk kommentariev
i--;
if (i >= 0)
i--;
}
}
if (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '!') && !isOperator(Text, i, out next))
{
bound = i + 1;
TestForKeyword(Text, i, ref bound, punkt_sym, out keyw);
if (keyw == KeywordKind.New && comma_pressed)
bound = 0;
if (keyw == KeywordKind.Function || keyw == KeywordKind.Constructor || keyw == KeywordKind.Destructor)
return "";
}
else if (i >= 0 && Text[i] == '\'') return "";
i = tmp;
}
sb.Insert(0, ch);//.Append(Text[i]);
}
else if (ch == '.') sb.Insert(0, ch);
else if (ch == '}')
{
if (kav.Count == 0)
{
while (i >= 0 && Text[i] != '{')
{
sb.Insert(0, Text[i]);
i--;
}
if (i < 0)
{
break;
}
else if (Text[i] == '{')
{
sb.Insert(0, '{');
}
}
else
sb.Insert(0, ch);
}
else if (ch == '{')
{
if (kav.Count == 0)
{
sb.Insert(0, ch);
break;
}
else sb.Insert(0, ch);
}
else
switch (ch)
{
case ')':
case ']':
case '>':
if (kav.Count == 0)
{
int j = i + 1;
while (j < Text.Length && char.IsWhiteSpace(Text[j]))
j++;
if (ch != '>')
tokens.Push(ch);
if (ch == ')')
skobki.Push(ch);
if (tokens.Count > 0 || pressed_key == ',')
sb.Insert(0, ch);
else if (i == off - 1 || j == off && off == Text.Length || ugl_skobki.Count > 0 || j < Text.Length && Text[i-1] != '-' && (Text[j] == '.' || Text[j] == '('))
{
tokens.Push(ch);
ugl_skobki.Push(ch);
sb.Insert(0, ch);
}
else
end = true;
}
else
sb.Insert(0, ch); break;
case '[':
case '<':
case '(':
if (kav.Count == 0)//esli ne v kavychkah
{
if (ch == '(')
if (skobki.Count > 0)
skobki.Pop();
else skobki.Push('(');
//esli byli zakryvaushie tokeny (polagaem, chto skobki korrektny, esli net, to parser v lubom sluchae ne proparsit
if (tokens.Count > 0)
{
if (ch != '<')
tokens.Pop();
else if (ugl_skobki.Count > 0)
{
tokens.Pop();
ugl_skobki.Pop();
}
sb.Insert(0, ch);//dobavljaem k stroke
if (ch == '(')
{
int tmp = i--;
/*while (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&'))
{
i--;
}*/
while (i >= 0 && (Text[i] == ' ' || char.IsControl(Text[i]) || Text[i] == '}'))
{
if (Text[i] != '}')
{
i--;
}
else
{
while (i >= 0 && Text[i] != '{')
{
//propusk kommentariev
i--;
}
if (i >= 0)
i--;
}
}
if (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '!'))
{
bound = i + 1;
TestForKeyword(Text, i, ref bound, punkt_sym, out keyw);
if (keyw == KeywordKind.New)
bound = 0;
else
if (keyw != KeywordKind.None && tokens.Count == 0)
end = true;
else
bound = 0;
}
else if (i >= 0 && Text[i] == '\'') return "";
i = tmp;
}
}
else if (ch == '<' || ch == '>')
{
if (tokens.Count > 0 || pressed_key == ',')
sb.Insert(0, ch);
else
end = true;
}
else
if (!comma_pressed) //esli my ne v parametrah
end = true; //zakonchili, tak kak doshli do pervoj skobki
else
{
sb.Remove(0, sb.Length);//doshli do skobki, byla nazhata zapjataja, poetomu udaljaem vse parametry
if (ch == '(')
on_brace = true;
//on_skobka = true;
comma_pressed = false;
}
}
else sb.Insert(0, ch);
break;
case '\'':
if (kav.Count == 0)
kav.Push(ch);
else
kav.Pop();
sb.Insert(0, ch);
if (kav.Count == 0 && tokens.Count == 0)
end = true;
break;
default:
if (!(ch == ' ' || char.IsControl(ch)))
{
if (ch == '^')
sb.Insert(0, ch);
else
if (kav.Count == 0)//ne v kavychkah
{
if (tokens.Count == 0)
{
if (ch != ',' && !comma_pressed)
end = true;//esli ne na zapjatoj i ne v parametrah, to finish
else if (ch == ',' && !comma_pressed)
end = true;
else if (ch == ',' && (pressed_key == '(' || pressed_key == '['))
end = true;
else
{
sb.Insert(0, ch);//prodolzhaem
if (isOperator(Text, i, out next))
{
i = next;
continue;
}
}
}
else
sb.Insert(0, ch);//esli est skobki, prodolzhaem
if (!end && ch == ',')
{
if (tokens.Count == 0)
num_param++;//esli na zapjatoj, uvelichivaem nomer parametra
}
}
else
sb.Insert(0, ch);//prodolzhaem
}
else
if (Text[i] == '\n')
{
bool one_line_comment = false;
int comment_position = -1;
if (CheckForComment(Text, i - 1, out comment_position, out one_line_comment)) //proverjaem, net li kommenta ne predydushej stroke
{
if (!one_line_comment)
end = true;
else
{
sb.Insert(0, ch);
i = comment_position;
}
}
else
sb.Insert(0, ch);//a inache vyrazhenie na neskolkih strokah
}
else
sb.Insert(0, ch);
break;
}
if (end)
{
if (comma_pressed && !on_brace)
return "";
bool one_line_comment = false;
int comment_position = -1;
if (CheckForComment(Text, i, out comment_position, out one_line_comment))//proverka na kommentarii
{
int new_line_ind = sb.ToString().IndexOf('\n');
if (new_line_ind != -1) sb = sb.Remove(0, new_line_ind + 1);
else sb = sb.Remove(0, sb.Length);
}
break;
}
i--;
}
if (pressed_key == ',')
num_param++;
}
catch (Exception e)
{
}
if (pressed_key == ',' && (!on_brace || skobki.Count == 0))
return "";
//return RemovePossibleKeywords(sb);
return sb.ToString();
}
public virtual string FindOnlyIdentifier(int off, string Text, int line, int col, ref string name)
{
int i = off-1;
if (i < 0)
return "";
bool is_char = false;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (Text[i] != ' ' && !char.IsControl(Text[i]))
{
sb.Remove(0,sb.Length);
while (i >= 0 && (Char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '!'))
{
//sb.Insert(0,Text[i]);//.Append(Text[i]);
i--;
}
is_char = true;
}
i++;
if (i < Text.Length && Text[i] != ' ' && !char.IsControl(Text[i]))
{
while (i < Text.Length && (Char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[i] == '&' || Text[i] == '!'))
{
sb.Append(Text[i]);//.Append(Text[i]);
i++;
}
is_char = true;
}
name = sb.ToString();
KeywordKind keyw = KeywordKind.None;
if (is_char)
{
return FindExpression(i,Text,line,col,out keyw);
}
return null;
}
public virtual string FindPattern(int off, string Text, out bool is_pattern)
{
System.Text.StringBuilder sb=null;
is_pattern = false;
if (off > 0 && (char.IsLetterOrDigit(Text[off - 1]) || Text[off - 1] == '_' || Text[off-1] == '&' || Text[off - 1] == '!'))
{
sb = new System.Text.StringBuilder();
int i = off - 1;
is_pattern = true;
while (i >= 0 && (char.IsLetterOrDigit(Text[i]) || Text[i] == '_' || Text[off-1] == '&' || Text[i] == '!'))
sb.Insert(0, Text[i--]);
return sb.ToString();
}
return null;
}
public virtual bool IsMethodCallParameterSeparator(char key)
{
return key == ',';
}
public virtual bool IsOpenBracketForMethodCall(char key)
{
return key == '(';
}
public virtual bool IsOpenBracketForIndex(char key)
{
return key == '[';
}
public virtual bool IsDefinitionIdentifierAfterKeyword(KeywordKind keyw)
{
if (keyw == PascalABCCompiler.Parsers.KeywordKind.Function || keyw == PascalABCCompiler.Parsers.KeywordKind.Constructor || keyw == PascalABCCompiler.Parsers.KeywordKind.Destructor || keyw == PascalABCCompiler.Parsers.KeywordKind.Type || keyw == PascalABCCompiler.Parsers.KeywordKind.Var
|| keyw == PascalABCCompiler.Parsers.KeywordKind.Unit || keyw == PascalABCCompiler.Parsers.KeywordKind.Const || keyw == PascalABCCompiler.Parsers.KeywordKind.Program || keyw == PascalABCCompiler.Parsers.KeywordKind.Punkt)
return true;
return false;
}
public virtual bool IsTypeAfterKeyword(KeywordKind keyw)
{
if (keyw == PascalABCCompiler.Parsers.KeywordKind.Colon || keyw == PascalABCCompiler.Parsers.KeywordKind.Of || keyw == PascalABCCompiler.Parsers.KeywordKind.TypeDecl)
return true;
return false;
}
public virtual bool IsNamespaceAfterKeyword(KeywordKind keyw)
{
if (keyw == PascalABCCompiler.Parsers.KeywordKind.Uses) return true;
return false;
}
}
#region LEGACY - C language
/*public class CLanguageInformation : DefaultLanguageInformation
{
public CLanguageInformation(IParser p)
{
this.parser = p;
InitKeywords();
}
protected override void InitKeywords()
{
List<string> keys = new List<string>();
List<string> type_keys = new List<string>();
keywords.Add("for", "for"); keys.Add("for");
keywords.Add("while", "while"); keys.Add("while");
keywords.Add("do", "do"); keys.Add("do");
// keywords.Add("class", "class"); keys.Add("class"); type_keys.Add("class");
keywords.Add("struct", "struct"); keys.Add("struct"); type_keys.Add("struct");
keywords.Add("typedef", "typedef"); keys.Add("typedef"); keyword_kinds.Add("typedef", KeywordKind.Type);
// keywords.Add("private", "private"); keys.Add("private");
// keywords.Add("protected", "protected"); keys.Add("protected");
// keywords.Add("public", "public"); keys.Add("public");
// keywords.Add("try", "try"); keys.Add("try");
// keywords.Add("catch", "catch"); keys.Add("catch");
// keywords.Add("finally", "finally"); keys.Add("finally");
// keywords.Add("using", "using"); keys.Add("using"); keyword_kinds.Add("using", KeywordKind.Uses);
//keywords.Add("virtual", "virtual"); keys.Add("virtual");
keywords.Add("static", "static"); keys.Add("static");
keywords.Add("switch", "switch"); keys.Add("switch");
keywords.Add("case", "case"); keys.Add("case");
keywords.Add("const", "const"); keys.Add("const"); keyword_kinds.Add("const", KeywordKind.Const);
keywords.Add("if", "if"); keys.Add("if");
keywords.Add("else", "else"); keys.Add("else");
keywords.Add("new", "new"); keys.Add("new"); keyword_kinds.Add("new", KeywordKind.New);
keywords.Add("char","char"); keys.Add("char"); type_keys.Add("char");
keywords.Add("short","short"); keys.Add("short"); type_keys.Add("short");
keywords.Add("int","int"); keys.Add("int"); type_keys.Add("int");
keywords.Add("long","long"); keys.Add("long"); type_keys.Add("long");
keywords.Add("float","float"); keys.Add("float"); type_keys.Add("float");
keywords.Add("double","double"); keys.Add("double"); type_keys.Add("double");
keywords.Add("bool","bool"); keys.Add("bool"); type_keys.Add("bool");
keywords.Add("unsigned","unsigned"); keys.Add("unsigned");
keywords_array = keys.ToArray();
type_keywords_array = type_keys.ToArray();
}
public override string SystemUnitName
{
get
{
return null;
}
}
public override bool CaseSensitive
{
get
{
return true;
}
}
public override bool IncludeDotNetEntities
{
get
{
return false;
}
}
public override string GetKeyword(SymbolKind kind)
{
switch (kind)
{
case SymbolKind.Class : return "class";
case SymbolKind.Enum : return "enum";
case SymbolKind.Struct : return "struct";
case SymbolKind.Type : return "typedef";
}
return "";
}
public override string GetStandardTypeByKeyword(KeywordKind keyw)
{
return null;
}
protected override string GetFullTypeName(Type ctn, bool no_alias=true)
{
TypeCode tc = Type.GetTypeCode(ctn);
if (ctn.FullName == null && !ctn.IsArray && !ctn.IsGenericTypeDefinition)
return "T";
if (!ctn.IsEnum)
switch (tc)
{
case TypeCode.Int32 : return "int";
case TypeCode.Double : return "double";
case TypeCode.Boolean : return "bool";
case TypeCode.String : return "string";
case TypeCode.Char : return "char";
case TypeCode.Byte : return "unsigned char";
case TypeCode.SByte : return "char";
case TypeCode.Int16 : return "short";
case TypeCode.UInt16 : return "unsigned short";
case TypeCode.UInt32 : return "unsigned int";
case TypeCode.Single : return "float";
default : return ctn.FullName;
}
else return ctn.FullName;
if (ctn.Name.Contains("`"))
{
int len = ctn.GetGenericArguments().Length;
Type[] gen_ps = ctn.GetGenericArguments();
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(ctn.Namespace+"::"+ctn.Name.Substring(0,ctn.Name.IndexOf('`')));
sb.Append('<');
for (int i=0; i<len; i++)
{
sb.Append(gen_ps[i].Name);
if (i<len-1)
sb.Append(',');
}
sb.Append('>');
return sb.ToString();
}
if (ctn.IsArray) return GetFullTypeName(ctn.GetElementType())+"[]";
if (ctn == Type.GetType("System.Void*")) return "void*";
return ctn.FullName;
}
public override string GetShortTypeName(Type ctn, bool noalias=false)
{
TypeCode tc = Type.GetTypeCode(ctn);
if (ctn.FullName == null && !ctn.IsArray && !ctn.IsGenericTypeDefinition)
return "T";
if (ctn.IsEnum) return ctn.Name;
if (ctn.Name.Contains("`"))
{
int len = ctn.GetGenericArguments().Length;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(ctn.Name.Substring(0,ctn.Name.IndexOf('`')));
sb.Append('<');
sb.Append('>');
*//*sb.Append('<');
for (int i=0; i<len; i++)
{
sb.Append('T');
if (i<len-1)
sb.Append(',');
}
sb.Append('>');*//*
return sb.ToString();
}
//if (ctn.IsArray) return "array of "+GetTypeName(ctn.GetElementType());
//if (ctn == Type.GetType("System.Void*")) return PascalABCCompiler.StringConstants.pointer_type_name;
return ctn.Name;
}
protected override string GetTopScopeName(IBaseScope sc)
{
if (sc == null) return "";
if (sc.Name == "" || sc.Name.Contains("$") || sc.Name == "PABCSystem") return "";
if (sc is IProcScope) return "";
return sc.Name + "::";
}
protected override string GetDescriptionForType(ITypeScope scope)
{
string template_str=GetTemplateString(scope);
switch(scope.ElemKind)
{
case SymbolKind.Class :
if (scope.TopScope != null && scope.TopScope.Name != "")
return (scope.IsAbstract ? "abstract " : "") + (scope.IsFinal?"sealed ":"")+"class "+scope.TopScope.Name + "::" +scope.Name+template_str;
else return (scope.IsAbstract ? "abstract " : "") + (scope.IsFinal?"sealed ":"")+"class "+scope.Name+template_str;
case SymbolKind.Interface :
if (scope.TopScope != null && scope.TopScope.Name != "")
return "interface class"+scope.TopScope.Name + "::" +scope.Name+template_str;
else return "interface class"+scope.Name+template_str;
case SymbolKind.Enum :
if (scope.TopScope != null && scope.TopScope.Name != "")
return "enum "+scope.TopScope.Name + "::" +scope.Name;
else return "enum "+scope.Name;
case SymbolKind.Delegate :
if (scope.TopScope != null && scope.TopScope.Name != "")
return "delegate "+scope.TopScope.Name + "::" +scope.Name+template_str;
else return "delegate "+scope.Name+template_str;
case SymbolKind.Struct :
if (scope.TopScope != null && scope.TopScope.Name != "")
return "struct "+scope.TopScope.Name + "::" +scope.Name+template_str;
else return "struct "+scope.Name+template_str;
}
if (scope.TopScope != null)
return scope.TopScope.Name + "::" +scope.Name;
else return scope.Name;
}
protected override string GetSimpleDescriptionForType(ITypeScope scope)
{
string template_str=GetTemplateString(scope);
return scope.Name+template_str;
}
protected override string GetDescriptionForCompiledType(ICompiledTypeScope scope)
{
string s = GetFullTypeName(scope.CompiledType);
ITypeScope[] instances = scope.GenericInstances;
if (instances.Length > 0)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
int ind = s.IndexOf('<');
if (ind != -1) sb.Append(s.Substring(0,ind));
else
sb.Append(s);
sb.Append('<');
for (int i=0; i<instances.Length; i++)
{
sb.Append(instances[i].Name);
if (i < instances.Length - 1) sb.Append(',');
}
sb.Append('>');
s = sb.ToString();
}
switch(scope.ElemKind)
{
case SymbolKind.Class :
return (scope.IsFinal?"sealed ":"")+"class "+s;
case SymbolKind.Interface :
return "class interface "+s;
case SymbolKind.Enum :
return "enum "+s;
case SymbolKind.Delegate :
return "delegate "+s;
case SymbolKind.Struct :
return "struct "+s;
case SymbolKind.Type :
return "typedef "+s;
}
return s;
}
protected override string GetSimpleDescriptionForCompiledType(ICompiledTypeScope scope)
{
string s = GetFullTypeName(scope.CompiledType);
ITypeScope[] instances = scope.GenericInstances;
if (instances.Length > 0)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
int ind = s.IndexOf('<');
if (ind != -1) sb.Append(s.Substring(0,ind));
else
sb.Append(s);
sb.Append('<');
for (int i=0; i<instances.Length; i++)
{
sb.Append(instances[i].Name);
if (i < instances.Length - 1) sb.Append(',');
}
sb.Append('>');
s = sb.ToString();
}
return s;
}
protected override string GetDescriptionForArray(IArrayScope scope)
{
StringBuilder sb = new StringBuilder();
ITypeScope[] inds = scope.Indexers;
if (scope.ElementType != null)
{
string s = GetSimpleDescription(scope.ElementType);
if (s.Length > 0 && s[0] == '$') s = s.Substring(1,s.Length-1);
sb.Append(s);
}
if (!scope.IsDynamic)
{
sb.Append('[');
for (int i=0; i<inds.Length; i++)
{
sb.Append(GetSimpleDescription(inds[i]));
if (i<inds.Length-1) sb.Append(',');
}
sb.Append(']');
}
return sb.ToString();
}
protected override string GetDescriptionForPointer(IPointerScope scope)
{
if (scope.ElementType != null)
return GetSimpleDescription(scope.ElementType)+"*";
return "void*";
}
private void append_modifiers(StringBuilder sb, IElementScope scope)
{
if (scope.IsVirtual) sb.Append("virtual ");
if (scope.IsStatic) sb.Append("static ");
}
private string get_access_modifier(access_modifer mod)
{
switch (mod)
{
case access_modifer.private_modifer : return "private ";
case access_modifer.public_modifer : return "public ";
case access_modifer.protected_modifer : return "protected ";
case access_modifer.none : return "";
}
return "";
}
protected override string GetDescriptionForElementScope(IElementScope scope)
{
string type_name=null;
string s="";
StringBuilder sb = new StringBuilder();
if (scope.Type == null) type_name = "";
else
type_name = GetSimpleDescription(scope.Type);
if (type_name.StartsWith("$"))
type_name = type_name.Substring(1,type_name.Length-1);
switch (scope.ElemKind)
{
case SymbolKind.Variable : sb.Append(type_name+" "+scope.Name); break;
case SymbolKind.Parameter : sb.Append("parameter "+type_name+" "+scope.Name); break;
case SymbolKind.Constant :
{
if (scope.ConstantValue == null)
sb.Append("const "+ scope.Name);
else sb.Append("const "+ scope.Name+" = "+scope.ConstantValue.ToString());
}
break;
case SymbolKind.Event :
sb.Append(get_access_modifier(scope.AccessModifier));
append_modifiers(sb,scope);
sb.Append("event "+ type_name + " "+GetTopScopeName(scope.TopScope)+scope.Name);
break;
case SymbolKind.Field :
sb.Append(get_access_modifier(scope.AccessModifier));
append_modifiers(sb,scope);
sb.Append(type_name+" "+GetTopScopeName(scope.TopScope)+scope.Name );
break;
case SymbolKind.Property :
sb.Append(get_access_modifier(scope.AccessModifier));
append_modifiers(sb,scope);
sb.Append(type_name + " "+GetTopScopeName(scope.TopScope)+scope.Name + get_index_description(scope));
break;
}
return sb.ToString();
}
protected override string GetSimpleDescriptionForElementScope(IElementScope scope)
{
string type_name = GetSimpleDescription(scope.Type);
if (type_name.StartsWith("$")) type_name = type_name.Substring(1,type_name.Length-1);
return type_name + " " + scope.Name;
}
protected override string GetDescriptionForProcedure(IProcScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (scope.ReturnType != null)
sb.Append(GetSimpleDescription(scope.ReturnType)+" ");
else if (!scope.IsConstructor())
sb.Append("void ");
sb.Append(scope.Name); sb.Append('(');
IElementScope[] parameters = scope.Parameters;
for (int i=0; i<parameters.Length; i++)
{
sb.Append(GetSimpleDescription(parameters[i]));
if (i < parameters.Length - 1)
{
sb.Append(", ");
}
}
sb.Append(')');
return sb.ToString();
}
protected override string GetSimpleDescriptionForProcedure(IProcScope scope)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (scope.TopScope is ITypeScope && scope.Realization == null)
sb.Append(GetTopScopeName(scope.TopScope));
sb.Append(scope.Name); sb.Append('(');
IElementScope[] parameters = scope.Parameters;
for (int i=0; i<parameters.Length; i++)
{
sb.Append(GetSimpleDescription(parameters[i]));
if (i < parameters.Length - 1)
{
sb.Append(", ");
}
}
sb.Append(')');
return sb.ToString();
}
}*/
#endregion
}