* Implement first version of languages interfaces and classes ParsersController заменен на LanguageProvider. * Update ParserTools.csproj * Update RemoteCompiler.cs * Update TestRunner * Rename LanguageIntegrator project to Languages * Update TestRunner * Rename Parsers folder * Rename PascalABCParser.dll to PascalABCLanguage.dll * Reorganise LanguageIntegrator and rename DocTagsParser * Update Release Generators * Update language loading messages * Update linux version * Move BaseParser fields to ILanguage interface * Revert "Update Release Generators" This reverts commit 26a991c71b81e643d9fbd9a815ddca222768dda9. * Revert "Rename PascalABCParser.dll to PascalABCLanguage.dll" * Clean the mess in parser folders * Organize namespaces properly * Revert "Rename LanguageIntegrator project to Languages" * Add new enclosing folders for standard languages * Organize namespaces of LanguageIntegrator properly * Rename StandardLanguages to Languages * Comment the rest of Visual basic source code * Update OutputPath in pascal parser project * Move BaseParser methods to IParser * Restore Pascal parser project initial structure * Add PascalLanguage project * Move SyntaxTreeConverters project to Languages\Pascal folder * Rename SemanticRules in parser project * Rename Errors1 to Errors in parser project * Delete LambdaConverter dll from installer * Update language integrator to load *Language.dll files * Move lambda converter project to pascal lanuage dir * Revert "Delete LambdaConverter dll from installer" This reverts commit dd56f559ebe4f8c4c5c33752d44e6953001b96a5. * Switch off VBNETParser building * Delete syntax tree converters controller * Delete lambda converter dll from repository * Reorganize syntax tree to semantic tree conversion stage * Add BaseLanguage class to make language initialization more neat * Delete syntax tree post processors entity from ILanguage and refactor ABCStatistics calls * Add new IDocParser interface for documentation comments parser * Clean up folders * Add helper data structures to reduce parameters amount in CompileInterface and CompileImplementation * Add documentation to language classes * Move Union struct in global namespace and project (ParserTools) * Add more comments and a safe select language method * Rename SemanticRules class * Fix directives format null bug * Add System.Linq ref to LanguageIntegrator * Delete SyntaxToSemanticTreeConverter interface * Add BaseSyntaxTreeConverter * Call safe select language method in intellisence * Delete source files providers from parsers * Rename GetSyntaxTree method * Change Prebuild tree to be virtual - not abstract * Refresh documentation a bit * Add temporary language check for ABCHealth button * Add parser reference to parser tools * Move current compilation unit assigning higher to avoid bug with unit check * Delete null DirectiveInfo's and refactor directives' code * Add a few more comments
168 lines
6.5 KiB
C#
168 lines
6.5 KiB
C#
// 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.IO;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using Languages.Facade;
|
||
|
||
namespace Languages.Integration
|
||
{
|
||
/// <summary>
|
||
/// Модуль с функциями загрузки поддерживаемых языков программирования
|
||
/// </summary>
|
||
public static class LanguageIntegrator
|
||
{
|
||
|
||
private static readonly LanguageProvider LanguageProvider = LanguageProvider.Instance;
|
||
|
||
/// <summary>
|
||
/// Имя директории, содержащей установленные плагины языков программирования
|
||
/// </summary>
|
||
private const string languageKitsDirectoryName = "LanguageKits";
|
||
|
||
/// <summary>
|
||
/// Событие, информирующее об успешной загрузке плагина языка
|
||
/// </summary>
|
||
public static event Action<ILanguage> LanguageLoaded;
|
||
|
||
/// <summary>
|
||
/// Событие, информирующее об ошибке загрузки плагина языка
|
||
/// </summary>
|
||
public static event Action<string> LanguageLoadErrorOccured;
|
||
|
||
/// <summary>
|
||
/// Возвращает директорию, содержащую комплекты языков (если ее нет, то вернется null)
|
||
/// </summary>
|
||
private static DirectoryInfo GetLanguageKitsDirectory()
|
||
{
|
||
string binDirectoryPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||
string languageKitsDirectoryPath = Path.Combine(binDirectoryPath, languageKitsDirectoryName);
|
||
|
||
if (Directory.Exists(languageKitsDirectoryPath))
|
||
return new DirectoryInfo(languageKitsDirectoryPath);
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Загружает все языковые комплекты для использования (имя "главной" dll должно заканчиваться на Language)
|
||
/// </summary>
|
||
public static void LoadAllLanguageKits()
|
||
{
|
||
DirectoryInfo languageKitsDirectory = GetLanguageKitsDirectory();
|
||
|
||
if (languageKitsDirectory == null)
|
||
return;
|
||
|
||
foreach (var languageKit in languageKitsDirectory.GetDirectories())
|
||
{
|
||
FileInfo[] dllFiles = languageKit.GetFiles();
|
||
|
||
foreach (var dll in dllFiles)
|
||
{
|
||
if (dll.Name.EndsWith("Language.dll"))
|
||
{
|
||
IntegrateLanguageFromAssembly(dll);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Загружает все языки, доступные в системе
|
||
/// </summary>
|
||
public static void LoadAllLanguages()
|
||
{
|
||
LoadStandardLanguages();
|
||
LoadAllLanguageKits();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Загружает стандартные языки платформы из папки bin
|
||
/// </summary>
|
||
public static void LoadStandardLanguages()
|
||
{
|
||
string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName);
|
||
|
||
DirectoryInfo directory = new DirectoryInfo(directoryName);
|
||
|
||
FileInfo[] dllFiles = directory.GetFiles("*Language.dll");
|
||
|
||
foreach (FileInfo languageFile in dllFiles)
|
||
{
|
||
IntegrateLanguageFromAssembly(languageFile);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Загружает плагин языка из dll, содержащей класс, представляющий язык
|
||
/// (класс должен реализовывать интерфейс ILanguage и его имя должно заканчиваться на Language)
|
||
/// </summary>
|
||
/// <param name="languageFile">dll, содержащая язык</param>
|
||
private static void IntegrateLanguageFromAssembly(FileInfo languageFile)
|
||
{
|
||
try
|
||
{
|
||
ILanguage languageFound = InstantiateLanguageAndAddToLanguagesList(languageFile);
|
||
|
||
if (languageFound == null)
|
||
{
|
||
throw new Exception("Language class wasn't found in language assembly. (To be found it should contain 'Language' in it's name)");
|
||
}
|
||
|
||
LanguageLoaded?.Invoke(languageFound);
|
||
}
|
||
catch (ReflectionTypeLoadException e)
|
||
{
|
||
#if DEBUG
|
||
string errorMessage = e + Environment.NewLine;
|
||
errorMessage += "<Loader exceptions>:" + Environment.NewLine;
|
||
errorMessage += string.Join(Environment.NewLine, e.LoaderExceptions.Select(error => error.ToString())) + Environment.NewLine;
|
||
File.AppendAllText("log.txt", errorMessage);
|
||
#endif
|
||
LanguageLoadErrorOccured?.Invoke(languageFile.Name);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
#if DEBUG
|
||
string errorMessage = e + Environment.NewLine;
|
||
File.AppendAllText("log.txt", errorMessage);
|
||
#endif
|
||
LanguageLoadErrorOccured?.Invoke(languageFile.Name);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Конструирует объект языка и добавляет его в список языков в LanguageProvider
|
||
/// </summary>
|
||
/// <param name="languageFile"></param>
|
||
/// <returns></returns>
|
||
private static ILanguage InstantiateLanguageAndAddToLanguagesList(FileInfo languageFile)
|
||
{
|
||
Assembly assembly = Assembly.LoadFile(languageFile.FullName);
|
||
|
||
Type[] types = assembly.GetTypes();
|
||
|
||
ILanguage languageFound = null;
|
||
foreach (Type type in types)
|
||
{
|
||
if (type.Name.EndsWith("Language") && type.IsClass)
|
||
{
|
||
object obj = Activator.CreateInstance(type);
|
||
if (obj is ILanguage language)
|
||
{
|
||
languageFound = language;
|
||
LanguageProvider.Languages.Add(language);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
return languageFound;
|
||
}
|
||
}
|
||
}
|