//ирПортативный Перем ирПортативный Экспорт;
//ирПортативный Перем ирОбщий Экспорт;
//ирПортативный Перем ирСервер Экспорт;
//ирПортативный Перем ирКэш Экспорт;
//ирПортативный Перем ирКлиент Экспорт;

Перем ЧистыйКонтекст;
Перем ВерсияПлатформы Экспорт;
Перем ЭтоФайловаяБаза Экспорт;
Перем мМетаданные Экспорт;
Перем мПустойМодуль; 
Перем ЭтоИнтеграция Экспорт;
Перем СоответствиеВидовСравнения Экспорт;
Перем МаркерНачалаАлгоритма Экспорт;
Перем МаркерКонцаАлгоритма Экспорт;
Перем МакетыКомпонент Экспорт;
Перем мКэшПустыхЗначений Экспорт;
Перем ВложенностьИндикации Экспорт;
Перем КэшОбъектов Экспорт;
Перем ВремяОбъект Экспорт;
Перем мСловарьПеревода;
Перем АрхитектураПроцессора Экспорт;
Перем ВыполнятьАлгоритмыЧерезВнешниеОбработки Экспорт;
Перем ВнешняяОбработкаСервисы Экспорт;
Перем ФайловыйКэшАлгоритмовДопускаетРедактирование Экспорт;
Перем ФормаПустышка Экспорт;
Перем КешАлгоритмов;
Перем СубПутьКФайлуПотокаМодуляВнешнейОбработки;
Перем СубПутьКФайлуПотокаМакетаВнешнейОбработки;
Перем СубПутьКФайлуПотокаЗаголовкаВнешнейОбработки;
Перем СубПутьККонтрольномуФайлуВнешнейОбработки;
Перем ПутьККаталогуСлужебныхВременныхФайлов;
Перем мЕстьАдминистративныеПраваУУчетнойЗаписиОС;
Перем СообщениеОНеобходимостиОбновитьКэшМодулейВыводилось;
Перем ПапкаКешаВнешнихОбработокАлгоритмов Экспорт;
Перем ПапкаВнешнихКомпонент Экспорт;
Перем ПапкаКэшаМодулей Экспорт;
Перем ПапкаКэшаРолей Экспорт;
Перем КаталогФайловогоКэша Экспорт;
Перем СтруктураПодкаталоговФайловогоКэша Экспорт;
Перем ИмяФайлаПакера Экспорт;
Перем ШаблоныВнешнейОбработки;
Перем ШаблоныВнешнейОбработкиСМакетом;
Перем ФайлРегистратораКомпонентCU;
Перем ФайлРегистратораNetКомпонент;
Перем МассивСравненияТекстов Экспорт;
Перем мВопросОтключенияПроверкиМодальностиЗадавался Экспорт;  
Перем мПроверкаСовместимостиКонфигурацииВыполнялась Экспорт;
Перем мПроверкаЗащитыОтОпасныхДействийВыполнялась Экспорт;
Перем мПроверкаСоединенияADOЭтойБДВыполнялась Экспорт;
Перем мПерехватКлавиатуры;
Перем АсинхронностьЗапрещена Экспорт;
Перем РежимОтладки Экспорт; // Отключает использование однострочных сверток кода. Снижает скорость, но облегчает отладку. 
Перем НастройкиКомпьютера Экспорт;
Перем мДиалектыSQL Экспорт; // Используется в Обработка.ирКлсПолеТекстаПрограммы 

Перем WScriptShell;
Перем RegExp Экспорт; // ОбработкаОбъект.ирОболочкаРегВыражение 
Перем RegExp2 Экспорт; // ОбработкаОбъект.ирОболочкаРегВыражение

Перем шЛюбой Экспорт;
Перем шБуква Экспорт;
Перем шБукваЦифра Экспорт;
Перем шИмя Экспорт;
Перем шЧисло Экспорт;
Перем шИндекс Экспорт;
Перем шСкобки Экспорт;
Перем шGUID Экспорт;
Перем шКомментарий Экспорт;
Перем шРазделитель Экспорт;
Перем шПустоеНачалоСтроки Экспорт;
Перем шЛитералПрограммы Экспорт;
Перем шЛитералПростой Экспорт;
Перем шЛитералВЗапросе Экспорт;
Перем шИмяВременнойТаблицы Экспорт;
Перем шГиперСсылка Экспорт;
Перем шДирективаПрепроцессора Экспорт;

Перем МаркерОбъектаМетаданных;
Перем МаркерКоллекцииОбъектовМетаданных;

//#Если Клиент Или ВнешнееСоединение Тогда
Перем ИдентификаторПроцессаОС Экспорт;
Перем VBScript Экспорт;
Перем JavaScript Экспорт;
Перем ДеревоТипов Экспорт;
Перем ТаблицаКонтекстов Экспорт;
Перем ТаблицаОбщихТипов Экспорт;
Перем ТаблицаИменЭлементовКоллекций Экспорт;
Перем ТаблицаРасширенийТипов Экспорт;
Перем ТаблицаТиповМетаданных Экспорт;
Перем ТаблицаШаблоновКонтекстов Экспорт;
Перем ТаблицаТиповМетаОбъектов Экспорт;
Перем ТаблицаПараметров Экспорт;
Перем СлужебноеПолеТекста Экспорт;
Перем СлужебноеПолеТекста2 Экспорт;
//Перем СлужебноеПолеHtmlДокумента Экспорт;
Перем МассивОбычныхЭлементовУправления Экспорт;
Перем МассивУправляемыхЭлементовУправления Экспорт;
Перем мМассивТиповЭлементовОбычнойФормы Экспорт;
Перем ТаблицаСтатистикиВыбора Экспорт;
Перем мМассивТиповСМетаданными Экспорт;
Перем мТаблицаТипов;
Перем мТаблицаСоответствияВидов;
Перем мТаблицаЗамеров Экспорт;
Перем мТаблицаИндикаторов Экспорт;
Перем мИменаОсновныхКлассовБиблиотекCOM; // Кэш имен классов, например Exel - Application
Перем мОбразцыCOMОбъектов; // Для вычисления свойств
Перем мADOUtils; // см. ПолучитьADOUtils()
Перем мКэшСловГлобальногоКонтекста;
Перем мКолонкиБД Экспорт;
Перем мСтруктураХраненияБДСРазмерами Экспорт;
Перем мТаблицаРедактируемыхТипов;
Перем мОписаниеТипаМДТабличнаяЧасть;
Перем мОписаниеТипаМДВнешнийИсточникДанных;
Перем мДеревоОбъектовМД;
Перем мТаблицаВсехТаблицБД;
Перем мПоляТекстаПрограммы;
Перем мШаблоныДляАнализаВстроенногоЯзыка;
Перем мСлужебнаяФорма;
Перем COMНавигатор Экспорт; // см. ПолучитьCOMНавигатор()
Перем ТаблицаШаблоновТекста Экспорт;
Перем мКартинкиТипов;
Перем мМассивИсключенийИменКоллекций;   
Перем мПассивныеФормы;
Перем мИменаТиповМетаданныхСМенеджерами;
Перем мКэшРазбораВыражений Экспорт;

Перем ФайлЗапаковщика1С Экспорт;
Перем ФайлБиблиотекиЗапаковщика;
Перем ФайлОткрывателя1С Экспорт;
Перем ФайлФорматераЗапросовБД Экспорт;
Перем ФайлРаспаковщикаZIP Экспорт;
Перем СинтаксПомощник; 
Перем Парсеры Экспорт;
Перем БуферыСравнения Экспорт;
Перем ПараметрыОбработчикаОжидания Экспорт;
Перем БазовыйФайлРедактораJSON;
Перем БазовыйФайлРедактораКода;
Перем мМаркерИмениЗапросаПакета Экспорт;
Перем мМаркерИмениЧастиОбъединения Экспорт;

Перем СинтаксическийКонтрольПередЗаписью Экспорт;
Перем ОтложенноеОткрытиеИсточникаОшибки Экспорт;
Перем АвторегистрацияComКомпонент Экспорт;
Перем ЛиКомпонентаFormsTextBoxДоступна;
Перем МодальныеГруппы Экспорт;
Перем мМодулиМетаданных;
Перем мВызовыВсехСловПоМодулям;
Перем ОткрытыеФормыПодсистемы Экспорт;
Перем ОтслеживаемыеФормы Экспорт;
Перем ПерехватКлавиатурногоВводаВОбычномПриложении Экспорт;
Перем ОтмененныеФоновыеЗадания Экспорт;
Перем ВнутреннийБуферОбмена Экспорт;
Перем ПроверочноеСоединениеЭтойСУБД Экспорт;
Перем ИспользоватьЭмуляциюНажатияКлавиш Экспорт;
Перем ВыделениеРезультатовПоиска Экспорт;
Перем НеИспользоватьУправляемыеФормыИнструментов Экспорт;
Перем мСвязанныйКонфигуратор Экспорт;
Перем мДатаОбновленияКэшаМодулей;
Перем мДобавленныеОбщиеМодули;
Перем мРежимПроверкиМодуля Экспорт;

// Инициализирует, если необходимо, большие таблицы платформы.
// К ним относятся таблицы методов и свойств.
//
// Параметры:
//  Нет.
//
Процедура ИнициацияОписанияМетодовИСвойств() Экспорт

	Если ТаблицаКонтекстов <> Неопределено Тогда
		Возврат;
	КонецЕсли;
	#Если Клиент Тогда	
		Состояние("Инициализация таблицы методов и свойств...");
	#КонецЕсли
	МассивТаблиц = ЗначениеИзСтрокиВнутр(ПолучитьМакет("ТаблицаМетодовИСвойств").ПолучитьТекст());
	ТаблицаКонтекстов = МассивТаблиц.ТаблицаКонтекстов; // см. Обработка.ирПлатформа.Форма.ОписаниеПлатформы.ТаблицаКонтекстов
	ТаблицаКонтекстов.Колонки.Добавить("Описание");
	ТаблицаКонтекстов.Индексы.Добавить("ТипКонтекста");
	ТаблицаКонтекстов.Индексы.Добавить("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка");
	ТаблицаКонтекстов.Индексы.Добавить("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка, ТипСлова");
	ТаблицаКонтекстов.Индексы.Добавить("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка, НСлово");
	ТаблицаКонтекстов.Индексы.Добавить("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка, НСлово, ТипСлова");    
	ТаблицаШаблоновКонтекстов = МассивТаблиц.ТаблицаШаблоновКонтекстов; // см. Обработка.ирПлатформа.Форма.ОписаниеПлатформы.ТаблицаШаблоновКонтекстов
	ТаблицаШаблоновКонтекстов.Колонки.Добавить("Описание"); // Нужно для вирт. таблицы КритерийОтбора.<Имя критерия отбора>()
	ТаблицаШаблоновКонтекстов.Индексы.Добавить("ТипКонтекста");
	ТаблицаШаблоновКонтекстов.Индексы.Добавить("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка");
	ТаблицаШаблоновКонтекстов.Индексы.Добавить("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка, ТипСлова");
	ТаблицаПараметров = МассивТаблиц.ТаблицаПараметров; // см. Обработка.ирПлатформа.Форма.ОписаниеПлатформы.ТаблицаПараметров 
	ТаблицаПараметров.Колонки.Добавить("Описание"); 
	ТаблицаПараметров.Индексы.Добавить("ТипКонтекста, ЯзыкПрограммы, Слово");
	//ТаблицаПараметров.Индексы.Добавить("ТипКонтекста, ЯзыкПрограммы, Слово, Номер");
	#Если Клиент Тогда
		Состояние("");
	#КонецЕсли

КонецПроцедуры

// Инициализирует, если необходимо, малые таблицы платформы.
// К ним относятся таблицы типов и коллекций.
// 
// Параметры:
//  Нет.
//
Процедура ИнициализацияОписанияОбщихТипов() Экспорт

	Если ТипЗнч(ТаблицаОбщихТипов) = Тип("ТаблицаЗначений") Тогда
		Возврат;
	КонецЕсли;
	МассивТаблиц = ЗначениеИзСтрокиВнутр(ПолучитьМакет("ТаблицаИменЭлементовКоллекций").ПолучитьТекст());
	ТаблицаИменЭлементовКоллекций = МассивТаблиц.ТаблицаИменЭлементовКоллекций;
	#Если Сервер И Не Сервер Тогда
		ТаблицаИменЭлементовКоллекций = НОвый ТаблицаЗначений;
	#КонецЕсли
	ТаблицаИменЭлементовКоллекций.Индексы.Добавить("ИмяКоллекции");
	ТаблицаИменЭлементовКоллекций.Индексы.Добавить("ИмяЭлементаКоллекции");
	ТаблицаИменЭлементовКоллекций.Индексы.Добавить("ИмяОбщегоТипа, ИмяЭлементаКоллекции");
	ТаблицаРасширенийТипов = МассивТаблиц.ТаблицаРасширений;
	#Если Сервер И Не Сервер Тогда
		ТаблицаРасширенийТипов = НОвый ТаблицаЗначений;
	#КонецЕсли
	ТаблицаРасширенийТипов.Индексы.Добавить("Расширение");
	ТаблицаТиповМетаданных = МассивТаблиц.ТаблицаТиповМетаданных;
	МассивТаблиц = ЗначениеИзСтрокиВнутр(ПолучитьМакет("ТаблицаОбщихТипов").ПолучитьТекст());
	ТаблицаОбщихТипов = МассивТаблиц.ТаблицаОбщихТипов; // см. Обработка.ирПлатформа.Форма.ОписаниеПлатформы.ТаблицаОбщихТипов
	#Если Сервер И Не Сервер Тогда
		ТаблицаОбщихТипов = НОвый ТаблицаЗначений;
	#КонецЕсли
	ТаблицаОбщихТипов.Индексы.Добавить("Слово, ЯзыкПрограммы");
	ТаблицаОбщихТипов.Индексы.Добавить("Слово, ТипТипа");
	//ТаблицаОбщихТипов.Индексы.Добавить("Слово, ЯзыкПрограммы, ТипТипа");
	ТаблицаОбщихТипов.Индексы.Добавить("НСлово, ЯзыкПрограммы, ЕстьКонструктор");
	ТаблицаОбщихТипов.Индексы.Добавить("Представление, ТипТипа");
	ТаблицаОбщихТипов.Индексы.Добавить("ИД");
	ТаблицаОбщихТипов.Индексы.Добавить("БазовыйТип, ЯзыкПрограммы");
	
КонецПроцедуры 

// Добавляет дополнительные Свойства для типов контекстов платформы.
Процедура ДобавитьСловоВОписаниеТипаКонтекста(ТипКонтекста, Слово, ТипСлова, ТипЗначения) Экспорт 

	ИнициацияОписанияМетодовИСвойств();
	НоваяСтрока = ТаблицаКонтекстов.Добавить();
	НоваяСтрока.ТипКонтекста = ТипКонтекста;
	НоваяСтрока.Слово        = Слово;
	НоваяСтрока.НСлово       = НРег(Слово);
	НоваяСтрока.ТипСлова     = ТипСлова;
	НоваяСтрока.ТипЗначения  = ТипЗначения;

КонецПроцедуры

// Добавляет в список значений коллекцию объектов метаданных.
//
// Параметры:
//  пСписокМетаданных - СписокЗначений - куда добавляем объекты;
//  пИмяМетаданных - Строка - имя коллекции объектов метаданных или имя корневого типа;
//  *ЛиПолноеИмя - Булево, *Истина - добавлять полные имена, иначе краткие;
//  *ЛиДобавлятьКартинки - Булево, *Истина - добавлять картинки;
//  *ОтборПоПраву - Строка, *Неопределено - проверять перед добавлением право текущего пользователя.
//
Процедура ДобавитьВСписокКоллекциюМетаданных(пСписокМетаданных, пИмяМетаданных, ЛиПолноеИмя = Истина, ЛиДобавлятьКартинки = Истина, ОтборПоПраву = Неопределено) Экспорт
	
	Картинка = Неопределено;
	СтрокаКорневогоТипа = ОписаниеТипаМетаОбъектов(пИмяМетаданных, , 0);
	Если СтрокаКорневогоТипа <> Неопределено Тогда
		ИмяКоллекцииМетаданных = СтрокаКорневогоТипа.Множественное;
		#Если Клиент Тогда
			Если ЛиДобавлятьКартинки Тогда 
				КорневойТип = пИмяМетаданных;
				Картинка = ирКлиент.КартинкаКорневогоТипаМДЛкс(КорневойТип);
			КонецЕсли;
		#КонецЕсли
	Иначе
		ИмяКоллекцииМетаданных = пИмяМетаданных;
		#Если Клиент Тогда
			Если ЛиДобавлятьКартинки Тогда 
				КорневойТип = ОписаниеТипаМетаОбъектов(, пИмяМетаданных, 0).Единственное;
				Картинка = ирКлиент.КартинкаКорневогоТипаМДЛкс(КорневойТип);
			КонецЕсли;
		#КонецЕсли
	КонецЕсли;
	Для Каждого Объект ИЗ мМетаданные[ИмяКоллекцииМетаданных] Цикл
		Если Истина
			И ОтборПоПраву <> Неопределено
			И Не ПравоДоступа(ОтборПоПраву, Объект)
		Тогда
			Продолжить;
		КонецЕсли;
		Если ЛиПолноеИмя Тогда
			ИмяМетаОбъекта = Объект.ПолноеИмя();
		Иначе
			ИмяМетаОбъекта = Объект.Имя;
		КонецЕсли;
		пСписокМетаданных.Добавить(ИмяМетаОбъекта, Объект.Представление(), , Картинка);
	КонецЦикла;
	
КонецПроцедуры

// Получает список ключевых слов языка запросов.
//
// Параметры:
//  *Расширение  - Тип, *Неопределено - для определения расширения языка запросов.
//
// Возвращаемое значение:
//  СписокЗначений - где значение содержит слово.
//
Функция КлючевыеСловаЯзыкаЗапросов(РежимКомпоновкиДанных = Ложь, Русские = Истина, Английские = Ложь) Экспорт

	Список = Новый СписокЗначений;
	
	Если Русские Тогда
		Список.Добавить("АВТОУПОРЯДОЧИВАНИЕ");
		Список.Добавить("ВНУТРЕННЕЕ");
		Список.Добавить("ВОЗР");
		Список.Добавить("ВСЕ");
		Список.Добавить("ВЫБРАТЬ");
		Список.Добавить("ГДЕ");
		Список.Добавить("ДЛЯ");
		Список.Добавить("ИЗ");
		Список.Добавить("ИЗМЕНЕНИЯ");
		Список.Добавить("ИМЕЮЩИЕ");
		Список.Добавить("ИНДЕКСИРОВАТЬ");
		Список.Добавить("ИТОГИ");
		Список.Добавить("КАК");
		Список.Добавить("ЛЕВОЕ");
		Список.Добавить("ОБЩИЕ");
		Список.Добавить("ОБЪЕДИНИТЬ");
		Список.Добавить("ПЕРВЫЕ");
		Список.Добавить("ПО");
		Список.Добавить("ПОЛНОЕ");
		Список.Добавить("ПОМЕСТИТЬ");
		Список.Добавить("ПРАВОЕ");
		Список.Добавить("РАЗЛИЧНЫЕ");
		Список.Добавить("РАЗРЕШЕННЫЕ");
		Список.Добавить("СГРУППИРОВАТЬ");
		Список.Добавить("СОЕДИНЕНИЕ");
		Список.Добавить("УБЫВ");
		Список.Добавить("УНИЧТОЖИТЬ");
		Список.Добавить("УПОРЯДОЧИТЬ");
		
		Список.Добавить("НЕ");
		Список.Добавить("И");
		Список.Добавить("ИЛИ");
		Список.Добавить("ВЫБОР");
		Список.Добавить("КОГДА");
		Список.Добавить("ТОГДА");
		Список.Добавить("ИНАЧЕ");
		Список.Добавить("КОНЕЦ");
		Список.Добавить("ЕСТЬ");
		Список.Добавить("ЕСТЬ NULL");
		Список.Добавить("NULL");
		Список.Добавить("МЕЖДУ");
		Список.Добавить("В");
		Список.Добавить("ПОДОБНО");
		Список.Добавить("СПЕЦСИМВОЛ");
		Список.Добавить("ИЕРАРХИЯ");
		Список.Добавить("ИЕРАРХИИ");
		Список.Добавить("ССЫЛКА");
		
		Если РежимКомпоновкиДанных Тогда
			// Видимо это устаревшие слова
			Список.Добавить("ЗНАЧЕНИЕ");
			Список.Добавить("ЗНАЧЕНИЯ");
			Список.Добавить("ИДЕНТИФИКАТОР");
			Список.Добавить("ИМЯ");
			Список.Добавить("ОБЪЕКТ");
			Список.Добавить("СПИСОК");
			Список.Добавить("ТИПЗНАЧЕНИЯ");
			Список.Добавить("ХАРАКТЕРИСТИКА");
			// Это новые слова
			Список.Добавить("ЗНАЧЕНИЯХАРАКТЕРИСТИК");
			Список.Добавить("ПОЛЕИМЕНИ");
			Список.Добавить("ПОЛЕКЛЮЧА");
			Список.Добавить("ПОЛЕЗНАЧЕНИЯ");
			Список.Добавить("ПОЛЕВИДА");
			Список.Добавить("ПОЛЕТИПАЗНАЧЕНИЯ");
			Список.Добавить("ПОЛЕОБЪЕКТА");
			Список.Добавить("ВИДЫХАРАКТЕРИСТИК");
		КонецЕсли;
	КонецЕсли; 
	Если Английские Тогда
		Список.Добавить("AUTOORDER");
		Список.Добавить("INNER");
		Список.Добавить("ASC");
		Список.Добавить("ALL");
		Список.Добавить("SELECT");
		Список.Добавить("WHERE");
		Список.Добавить("FOR");
		Список.Добавить("FROM");
		Список.Добавить("UPDATE");
		Список.Добавить("HAVING");
		Список.Добавить("INDEX");
		Список.Добавить("TOTALS");
		Список.Добавить("AS");
		Список.Добавить("LEFT");
		//Список.Добавить("ОБЩИЕ"); // ЗАБЫЛ перевод
		Список.Добавить("UNION");
		Список.Добавить("FIRST");
		Список.Добавить("BY");
		Список.Добавить("ON");
		Список.Добавить("FULL");
		Список.Добавить("INTO");
		Список.Добавить("RIGHT");
		Список.Добавить("DISTINCT");
		Список.Добавить("ALLOWED");
		Список.Добавить("GROUP");
		Список.Добавить("JOIN");
		Список.Добавить("DESC");
		Список.Добавить("DROP");
		Список.Добавить("ORDER");
		
		Список.Добавить("NOT");
		Список.Добавить("AND");
		Список.Добавить("OR");
		Список.Добавить("CASE");
		Список.Добавить("WHEN");
		Список.Добавить("THEN");
		Список.Добавить("ELSE");
		Список.Добавить("END");
		Список.Добавить("IS");
		Список.Добавить("NULL");
		Список.Добавить("BETWEEN");
		Список.Добавить("IN");
		Список.Добавить("LIKE");
		Список.Добавить("СПЕЦСИМВОЛ");
		Список.Добавить("HIERARCHY");
		Список.Добавить("REFS");
		
		//Если РежимКомпоновкиДанных Тогда
		//	// Видимо это устаревшие слова
		//	Список.Добавить("VALUE");
		//	Список.Добавить("VALUES");
		//	Список.Добавить("IDENTIFICATOR");
		//	Список.Добавить("NAME");
		//	Список.Добавить("OBJECT");
		//	Список.Добавить("LIST");
		//	Список.Добавить("VALUETYPE");
		//	Список.Добавить("CHARACTERISTIC");
		//	// Это новые слова
		//	Список.Добавить("ЗНАЧЕНИЯХАРАКТЕРИСТИК");
		//	Список.Добавить("ПОЛЕИМЕНИ");
		//	Список.Добавить("ПОЛЕКЛЮЧА");
		//	Список.Добавить("ПОЛЕЗНАЧЕНИЯ");
		//	Список.Добавить("ПОЛЕВИДА");
		//	Список.Добавить("ПОЛЕТИПАЗНАЧЕНИЯ");
		//	Список.Добавить("ПОЛЕОБЪЕКТА");
		//	Список.Добавить("ВИДЫХАРАКТЕРИСТИК");
		//КонецЕсли;
	КонецЕсли; 
	Возврат Список;
	
КонецФункции // ПолучитьСписокСловЯзыкаЗапросов()

// Получает список ключевых встроенного языка.
//
// Параметры:
//  Нет.
//
// Возвращаемое значение:
//  СписокЗначений - где значение содержит слово.
//
Функция КлючевыеСловаВстроенногоЯзыка() Экспорт
	
	Список = Новый СписокЗначений;
	Список.Добавить("Знач");  
	Список.Добавить("Val");
	Список.Добавить("Возврат");
	Список.Добавить("Return");
	Список.Добавить("ВызватьИсключение");
	Список.Добавить("Raise");
	Список.Добавить("Выполнить");
	Список.Добавить("Execute");
	Список.Добавить("Для");
	Список.Добавить("For");
	Список.Добавить("Если");
	Список.Добавить("If");
	Список.Добавить("И");
	Список.Добавить("And");
	Список.Добавить("Из");
	Список.Добавить("In"); // аналог В (запрос) и ИЗ (встроенный)
	Список.Добавить("Или");
	Список.Добавить("Or");
	Список.Добавить("Иначе");
	Список.Добавить("Else");
	Список.Добавить("ИначеЕсли");
	Список.Добавить("ElsIf");
	Список.Добавить("Исключение");
	Список.Добавить("Except");
	Список.Добавить("Каждого");
	Список.Добавить("Each");
	Список.Добавить("КонецЕсли");
	Список.Добавить("EndIf");
	Список.Добавить("КонецПопытки");
	Список.Добавить("EndTry");
	Список.Добавить("КонецПроцедуры");
	Список.Добавить("EndProcedure");
	Список.Добавить("КонецФункции");
	Список.Добавить("EndFunction");
	Список.Добавить("КонецЦикла");
	Список.Добавить("EndDo");
	Список.Добавить("Не");
	Список.Добавить("Not");
	Список.Добавить("Новый");
	Список.Добавить("New");
	Список.Добавить("Перейти");
	Список.Добавить("Goto");
	Список.Добавить("Перем");
	Список.Добавить("Var");
	Список.Добавить("По");
	Список.Добавить("To");
	Список.Добавить("Пока");
	Список.Добавить("While");
	Список.Добавить("Попытка");
	Список.Добавить("Try");
	Список.Добавить("Прервать");
	Список.Добавить("Break");
	Список.Добавить("Продолжить");
	Список.Добавить("Continue");
	Список.Добавить("Процедура");
	Список.Добавить("Procedure");
	Список.Добавить("Тогда");
	Список.Добавить("Then");
	Список.Добавить("Функция");
	Список.Добавить("Function");
	Список.Добавить("Цикл");
	Список.Добавить("Do");
	Список.Добавить("Экспорт");
	Список.Добавить("Export");
	// 8.3
	Список.Добавить("Ждать");
	Список.Добавить("Await");
	Список.Добавить("Асинх");
	Список.Добавить("Async");
	
	//// Инструкции препроцессора. Добавлено 28.01.2012
	//// Здесь им не место, т.к. по этому списку проверяется валидность имен переменных
	//Список.Добавить("Клиент");
	//Список.Добавить("Сервер");
	//Список.Добавить("ВнешнееСоединение");
	//Список.Добавить("ТолстыйКлиентУправляемоеПриложение");
	//Список.Добавить("ТолстыйКлиентОбычноеПриложение");
	//Список.Добавить("ТонкийКлиент");
	//Список.Добавить("ВебКлиент");
	
	Возврат Список;
	
КонецФункции

Функция ЛитералыЗначенияВсехЯзыков1С() Экспорт
	Список = Новый СписокЗначений;
	Список.Добавить("Истина", "Истина");
	Список.Добавить("True", "Истина");
	Список.Добавить("Ложь", "Ложь");
	Список.Добавить("False", "Ложь");
	Список.Добавить("Неопределено", "Неопределено");
	Список.Добавить("Undefined", "Неопределено");
	Список.Добавить("Null", "Null");
	Возврат Список;
КонецФункции

// Размаскирует обращения к временным таблицам в тексте запроса.
//
// Параметры:
//  ТекстЗапроса - Строка;
//  МассивВременныхТаблиц - Массив - элементами являются имена временных таблиц, замаскированных ранее.
//
// Возвращаемое значение:
//  Строка - новые текст запроса.
//
Функция РазмаскироватьВременныеТаблицы(ТекстЗапроса, МассивВременныхТаблиц, выхВсеРазмаскировано = Ложь) Экспорт 

	Если МассивВременныхТаблиц.Количество() = 0 Тогда
		Возврат ТекстЗапроса;
	КонецЕсли;
	// Допустимы 2 уровня скобок внутри имитатора временной таблицы.
	RegExp.Global = Истина;
	RegExp.MultiLine = Ложь;
	RegExp.IgnoreCase = Истина;
	ИмяВременнойТаблицы = "";
	Для Каждого ПодмененнаяВременнаяТаблица Из МассивВременныхТаблиц Цикл
		ИмяВременнойТаблицы = ИмяВременнойТаблицы + "|" + ПодмененнаяВременнаяТаблица;
	КонецЦикла;
	ИмяВременнойТаблицы = Сред(ИмяВременнойТаблицы, 2);
	НовыйТекстЗапроса = ТекстЗапроса;
	
	// Сначала делаем красивые замены - подзапрос на имя временной таблицы
	//RegExp.Pattern = "\(ВЫБРАТЬ(?:" + шСкобки + "|[^$\(\)])*?""ВременнаяТаблица"" = ""(" + ИмяВременнойТаблицы + ")""\)";
	RegExp.Pattern = "\(ВЫБРАТЬ(?:[^\(\)]*(?:" + шСкобки + "[^\(\)]*)*)""ВременнаяТаблица"" = ""(" 
		+ ИмяВременнойТаблицы + ")""\s*\)";
	НовыйТекстЗапроса = RegExp.Заменить(НовыйТекстЗапроса, "$2");
	выхВсеРазмаскировано = Найти(НовыйТекстЗапроса, """ВременнаяТаблица"" = """) = 0;
	Если Не выхВсеРазмаскировано Тогда
		// А теперь делаем некрасивые замены - оставляем подзапросы но заменяем в них имена полей и временной таблицы
		RegExp.Pattern = "\(ВЫБРАТЬ(?:[^\(\)]*(?:" + шСкобки + "[^\(\)]*)*)""ВременнаяТаблица"" = ""(" 
			+ ИмяВременнойТаблицы + ")""";
		НовыйТекстЗапроса = RegExp.Заменить(НовыйТекстЗапроса, "(ВЫБРАТЬ Т.* ИЗ $2 КАК Т ГДЕ ИСТИНА");
		// и0ие90цаун787
		RegExp.Pattern = "ВЫБОР\s+КОГДА\s+""!ИмяПоля!""\s+=\s+""(.+?)""\s+ТОГДА\s+.+?\n\s*(?:КОГДА\s+ЛОЖЬ\s+ТОГДА\s+.+?\n)*\s*КОНЕЦ";
		НовыйТекстЗапроса = RegExp.Заменить(НовыйТекстЗапроса, "Т.$1");
		выхВсеРазмаскировано = Найти(НовыйТекстЗапроса, """ВременнаяТаблица"" = """) = 0;
	КонецЕсли; 
	Если Не выхВсеРазмаскировано Тогда
		ВызватьИсключение "Не удалось размаскировать временные таблицы в тексте запроса. Возможно на них был наложен несовместимый с маскировкой отбор компоновки.";
	КонецЕсли; 
	Возврат НовыйТекстЗапроса;

КонецФункции // РазмаскироватьВременныеТаблицы()

// Получает текст запроса, где каждая временная таблица заменена своим имитатором.
//
// Параметры:
//  ОбъектЗапроса - Запрос -
//  *ТекстЗапроса  - Строка, *Неопределено -
//  *МассивВременныхТаблиц - Массив, *Неопределено - все подменяемые таблицы заносятся сюда.
//
// Возвращаемое значение:
//  Строка - новый текст запроса.
//
Функция ЗамаскироватьВременныеТаблицы(ОбъектЗапроса, Знач ТекстЗапроса = Неопределено, МассивВременныхТаблиц = Неопределено) Экспорт 

	Если ТекстЗапроса = Неопределено Тогда
		ТекстЗапроса = ОбъектЗапроса.Текст;
	КонецЕсли;
	ВременныйЗапрос = Новый Запрос;
	ВременныйЗапрос.МенеджерВременныхТаблиц = ОбъектЗапроса.МенеджерВременныхТаблиц;
	ПроверочныйЗапрос = Новый ПостроительЗапроса;
	Если ТипЗнч(МассивВременныхТаблиц) <> Тип("Массив") Тогда
		МассивВременныхТаблиц = Новый Массив;
	КонецЕсли; 
	ТекстовыйДокумент = Новый ТекстовыйДокумент;
	ТекстовыйДокумент.УстановитьТекст(ТекстЗапроса);
	Пока Истина Цикл
		Попытка
			ПроверочныйЗапрос.Текст = ТекстЗапроса;
			Прервать;
		Исключение
			ИнформацияОбОшибке = ИнформацияОбОшибке();
			//ИмяВременнойТаблицы = ирОбщий.ТекстМеждуМаркерамиЛкс(ИнформацияОбОшибке.Причина.Описание, """", """");
			ИмяВременнойТаблицы = ирОбщий.ТекстМеждуМаркерамиЛкс(ИнформацияОбОшибке.Причина.Описание, "Таблица не найдена """, """", Ложь);
			Если ЗначениеЗаполнено(ИмяВременнойТаблицы) Тогда
				ВременныйЗапрос.Текст = "ВЫБРАТЬ * ИЗ " + ИмяВременнойТаблицы;
				Попытка
					КолонкиВременнойТаблицы = ВременныйЗапрос.Выполнить().Колонки;
				Исключение
					Прервать;
				КонецПопытки;
			КонецЕсли; 
			// В 8.2.15 такой прием лишен смысла, т.к. движок запросов потом не сможет обработать обращения к дочерним полям
			//Если Не ЗначениеЗаполнено(ИмяВременнойТаблицы) Тогда
			//	ИмяВременнойТаблицы = ирОбщий.ТекстМеждуМаркерамиЛкс(ИнформацияОбОшибке.Причина.Описание, "Неверные параметры """, """", Ложь);
			//	Если ЗначениеЗаполнено(ИмяВременнойТаблицы) Тогда
			//		Попытка
			//			КолонкиВременнойТаблицы = ОбъектЗапроса.Параметры[ИмяВременнойТаблицы].Колонки;
			//		Исключение
			//			Попытка
			//				КолонкиВременнойТаблицы = ВременныйЗапрос.Выполнить().Колонки;
			//			Исключение
			//				Прервать;
			//			КонецПопытки;
			//		КонецПопытки;
			//		ИмяВременнойТаблицы = "&" + ИмяВременнойТаблицы;
			//	КонецЕсли; 
			//КонецЕсли; 
			Если Не ЗначениеЗаполнено(ИмяВременнойТаблицы) Тогда
				Прервать;
			КонецЕсли;
			ИмитаторВременнойТаблицы = ирОбщий.ЗапросИмитаторКоллекцииПолейЛкс(КолонкиВременнойТаблицы) 
				+ " ГДЕ ""ВременнаяТаблица"" = """ + ИмяВременнойТаблицы +  """";
			КоординатыОбращения = ирОбщий.ТекстМеждуМаркерамиЛкс(ИнформацияОбОшибке.Причина.Описание, "{(", ")}");
			НомерСтроки = Число(ирОбщий.ПервыйФрагментЛкс(КоординатыОбращения, ", "));    
			НомерКолонки = Число(ирОбщий.ПоследнийФрагментЛкс(КоординатыОбращения, ","));
			СтрокаЗапроса = ТекстовыйДокумент.ПолучитьСтроку(НомерСтроки);
			ТекстПосле = Сред(СтрокаЗапроса, НомерКолонки + СтрДлина(ИмяВременнойТаблицы));
			СтрокаКАК = "КАК";
			Если Не ирОбщий.СтрокиРавныЛкс(Лев(СокрЛ(ТекстПосле), СтрДлина(СтрокаКАК)), СтрокаКАК) Тогда
				ТекстПосле = " КАК " + ИмяВременнойТаблицы + " " + ТекстПосле;
			КонецЕсли; 
			НоваяСтрока = Лев(СтрокаЗапроса, НомерКолонки - 1) + "(" + ИмитаторВременнойТаблицы + ")" + ТекстПосле;
			ТекстовыйДокумент.ЗаменитьСтроку(НомерСтроки, НоваяСтрока);
			ТекстЗапроса = ТекстовыйДокумент.ПолучитьТекст();
			МассивВременныхТаблиц.Добавить(ИмяВременнойТаблицы);
		КонецПопытки;
	КонецЦикла;
	Возврат ТекстЗапроса;

КонецФункции

// Результат - Массив
Функция НайтиВозможныеИменаВременныхТаблиц(ТекстЗапроса, ЛиДиалект1С = Истина) Экспорт
	
	Имена = Новый Соответствие;
	RegExp.Global = Истина;
	RegExp.pattern = "(?:ИЗ|FROM|СОЕДИНЕНИЕ|JOIN|УНИЧТОЖИТЬ|DROP|,)\s+(" + шИмяВременнойТаблицы + ")(?:\s|$|[^\(\._\d" + шБуква + "])";
	РезультатПоиска = RegExp.НайтиВхождения(ТекстЗапроса);
	Для Каждого Вхождение Из РезультатПоиска Цикл
		Имена.Вставить(Нрег(Вхождение.SubMatches(0)), Вхождение.SubMatches(0));
	КонецЦикла;
	Результат = Новый Массив();
	Для Каждого КлючИЗначение Из Имена Цикл
		Если Истина
			И ЛиДиалект1С
			И (Ложь
				Или ирОбщий.СтрокиРавныЛкс(КлючИЗначение.Значение, "Константы")
				Или Найти(КлючИЗначение.Значение, ".") > 0)
		Тогда
			Продолжить;
		КонецЕсли; 
		Результат.Добавить(КлючИЗначение.Значение);
	КонецЦикла;
	Возврат Результат;
	
КонецФункции

Функция РазбитьГрубоТекстПакетногоЗапросаНаЗапросы(Знач ТекстПакета, Знач ПозицияКурсора = Неопределено, выхПозиции0 = Неопределено) Экспорт 

	#Если Сервер И Не Сервер Тогда
		RegExp = Обработки.ирОболочкаРегВыражение.Создать();
	#КонецЕсли
	МассивТекстовЗапросов = Новый Массив;
	Если Не ирКэш.ДоступныРегВыраженияЛкс() Тогда
		Если ирКэш.ДоступноСхемаЗапросаЛкс() Тогда
			Схема = Вычислить("Новый СхемаЗапроса");
			#Если Сервер И Не Сервер Тогда
				Схема = Новый СхемаЗапроса;
			#КонецЕсли
			Попытка
				Схема.УстановитьТекстЗапроса(ТекстПакета);
			Исключение
				ОписаниеОшибки = ОписаниеОшибки(); // Для отладки
				Возврат МассивТекстовЗапросов;
			КонецПопытки;
			Для Каждого ЗапросПакета Из Схема.ПакетЗапросов Цикл
				МассивТекстовЗапросов.Добавить(ЗапросПакета.ПолучитьТекстЗапроса());
			КонецЦикла;
		КонецЕсли; 
		Возврат МассивТекстовЗапросов;
	КонецЕсли; 
	RegExp.Global = Истина;
	RegExp.Multiline = Ложь;
	//RegExp.Pattern = "(?:" + шЛитералВЗапросе + ")|" + шКомментарий + "|;(?:\s*\n)*|$";
	RegExp.Pattern = "[^^](?:" + шЛитералВЗапросе + ")|" + шКомментарий + "|;|$";
	Результат = RegExp.НайтиВхождения(ТекстПакета,, Истина);
	НачалоЗапроса = 1;
	ОстальнойТекст = ТекстПакета;
	ДлинаТекстаПакета = СтрДлина(ТекстПакета);
	выхПозиции0 = Новый Массив;
	выхПозиции0.Добавить(0);
	Для Каждого Match Из Результат Цикл
		ПозицияВхождения = Match.FirstIndex;
		Если Истина
			И Не ирОбщий.СтрНачинаетсяСЛкс(Match.Value, ";")
			И ПозицияВхождения <> ДлинаТекстаПакета
		Тогда
			Продолжить;
		КонецЕсли;
		ДлинаТекстаЗапроса = ПозицияВхождения + Match.Length;
		ТекстЗапроса = Сред(ТекстПакета, НачалоЗапроса, ДлинаТекстаЗапроса - НачалоЗапроса + 1);
		Если ПустаяСтрока(ТекстЗапроса) Тогда
			Продолжить;
		КонецЕсли;
		//Если ТекстЗапроса = ";" Тогда
		//	Продолжить;
		//КонецЕсли; 
		ОстальнойТекст = Сред(ОстальнойТекст, ДлинаТекстаЗапроса + 1);
		НачалоЗапроса = НачалоЗапроса + СтрДлина(ТекстЗапроса);
		МассивТекстовЗапросов.Добавить(ТекстЗапроса);
		выхПозиции0.Добавить(ПозицияВхождения + 1);
		Если ПозицияКурсора <> Неопределено И ПозицияКурсора < ПозицияВхождения Тогда
			Прервать;
		КонецЕсли; 
	КонецЦикла;
	Если МассивТекстовЗапросов.Количество() = 0 Тогда
		МассивТекстовЗапросов.Добавить(ТекстПакета);
	КонецЕсли;
	Возврат МассивТекстовЗапросов;

КонецФункции

// Структура результата пакетного запроса на основе разметки в комментариях.
//
// Параметры:
//  ТекстПакетаИлиМассивТекстовЗапросов	 - 	 - 
//  ПрефиксКомментария					 - 	 - 
// 
// Возвращаемое значение:
//   - 
//
Функция СтруктураРезультатаПакетногоЗапроса(Знач ТекстПакетаИлиМассивТекстовЗапросов, Знач ПрефиксКомментария = "//") Экспорт 
	
	Результат = Новый Структура;
	Если Не ирКэш.ДоступныРегВыраженияЛкс() Тогда
		Возврат Результат;
	КонецЕсли; 
	Если ТипЗнч(ТекстПакетаИлиМассивТекстовЗапросов) = Тип("Строка") Тогда 
		МассивТекстовЗапросов = РазбитьГрубоТекстПакетногоЗапросаНаЗапросы(ТекстПакетаИлиМассивТекстовЗапросов);
	Иначе 
		МассивТекстовЗапросов = ТекстПакетаИлиМассивТекстовЗапросов;
	КонецЕсли;
	RegExp.Global = Ложь;
	RegExp.Multiline = Ложь;
	RegExp.Pattern = ирОбщий.ПодготовитьТекстДляРегВыраженияЛкс(ПрефиксКомментария + мМаркерИмениЗапросаПакета) + "(" + шИмя + ")(?: |\n|\r)";
	Индекс = -1;
	Для Каждого ТекстЗапроса Из МассивТекстовЗапросов Цикл
		Индекс = Индекс + 1;
		Вхождения = RegExp.НайтиВхождения(ТекстЗапроса);
		Если Вхождения.Количество() = 0 Тогда
			Продолжить;
		КонецЕсли; 
		ИмяЗапроса = Вхождения[0].SubMatches(0);
		Если ирОбщий.ЛиИмяПеременнойЛкс(ИмяЗапроса) Тогда
			Результат.Вставить(ИмяЗапроса, Индекс);
		КонецЕсли; 
	КонецЦикла;
	Возврат Результат;
	
КонецФункции

Функция ПреобразоватьЗапросВПодзапрос(Текст, ТекстВыбранныхПолей = "*", ПсевдонимВложенногоЗапроса = "ВложенныйЗапрос",
	ОбрезатьНачинаяСУпорядочивания = Ложь, ЭтоРусскийЯзык = Истина, Знач Смещение = "") Экспорт

	//ЭтоРусскийЯзык = ЭтоРусскийВариантТекстаЗапроса(ТекстЗапроса);
	RegExp.Pattern = "^(?:\s|(" + шКомментарий + "))*((?:ВЫБРАТЬ|SELECT)\s+((?:РАЗРЕШЕННЫЕ|ALLOWED)\s+)?)((?:(?:.|\r|\n)*\s((?:УПОРЯДОЧИТЬ|ORDER)\s+(?:ПО|BY)\s+" + шИмя 
		+ "(?:\s*,\s*" + шИмя + ")*(?:\s+(?:АВТОУПОРЯДОЧИВАНИЕ|AUTOORDER))?|(?:АВТОУПОРЯДОЧИВАНИЕ|AUTOORDER)))*)((?:.|\r|\n)*)$";
	РезультатПоиска = RegExp.НайтиВхождения(Текст)[0];
	Если ЭтоРусскийЯзык Тогда
		Результат = "ВЫБРАТЬ";
	Иначе
		Результат = "SELECT";
	КонецЕсли; 
	Если Не ирОбщий.ЛиПустаяПодгруппаRegExpЛкс(РезультатПоиска.SubMatches(2)) Тогда
		Если ЭтоРусскийЯзык Тогда
			Результат = Результат + " РАЗРЕШЕННЫЕ";
		Иначе
			Результат = Результат + " ALLOWED";
		КонецЕсли; 
	КонецЕсли; 
	Смещение = Смещение + Символы.Таб;
	Если ЭтоРусскийЯзык Тогда
		Результат = Результат + " " + ТекстВыбранныхПолей + " ИЗ (";
	Иначе
		Результат = Результат + " " + ТекстВыбранныхПолей + " FROM (";
	КонецЕсли; 
	НачальныйКомментарий = РезультатПоиска.SubMatches(0);
	Если ЗначениеЗаполнено(НачальныйКомментарий) Тогда
		Результат = Результат + Символы.ПС + Смещение + НачальныйКомментарий;
	Иначе
		Результат = Результат + Символы.ПС;
	КонецЕсли; 
	Если ЭтоРусскийЯзык Тогда
		Результат = Результат + Смещение + "ВЫБРАТЬ ";
	Иначе
		Результат = Результат + Смещение + "SELECT ";
	КонецЕсли; 
	ТекстДоПоследнегоУПОРЯДОЧИТЬ = РезультатПоиска.SubMatches(3);
	Если ЗначениеЗаполнено(ТекстДоПоследнегоУПОРЯДОЧИТЬ) Тогда
		ТекстДоПоследнегоУПОРЯДОЧИТЬ = ирОбщий.СтрокаБезКонцаЛкс(ТекстДоПоследнегоУПОРЯДОЧИТЬ, СтрДлина(РезультатПоиска.SubMatches(4)));
		ирОбщий.ДобавитьМногострочнуюСтрокуВТекстЛкс(Результат, ТекстДоПоследнегоУПОРЯДОЧИТЬ, Смещение);
	Иначе
		ирОбщий.ДобавитьМногострочнуюСтрокуВТекстЛкс(Результат, РезультатПоиска.SubMatches(5), Смещение);
	КонецЕсли; 
	Если ЭтоРусскийЯзык Тогда
		Результат = Результат + ") КАК ";
	Иначе
		Результат = Результат + ") AS ";
	КонецЕсли; 
	Результат = Результат + ПсевдонимВложенногоЗапроса;
	Если Истина
		//И ТекстДоПоследнегоУПОРЯДОЧИТЬ <> Неопределено 
		И Не ПустаяСтрока(ТекстДоПоследнегоУПОРЯДОЧИТЬ)
		И Не ОбрезатьНачинаяСУпорядочивания 
	Тогда
		Результат = Результат + Символы.ПС + РезультатПоиска.SubMatches(4) + РезультатПоиска.SubMatches(5);
	КонецЕсли; 
	Возврат Результат;

КонецФункции // ПолучитьТекстЗапросаДоУпорядочивания()
  
Функция СоздаваемыеВременныеТаблицыПакетаЗапросов(Знач ТекстПакетаИлиМассивТекстовЗапросов, Знач ТолькоТребующиеУничтоженияНаВходе = Ложь, Знач ВместеСУничтожениями = Ложь) Экспорт 

	#Если Сервер И Не Сервер Тогда
		RegExp2 = Обработки.ирОболочкаРегВыражение.Создать();
	#КонецЕсли
	СозданныеТаблицы = Новый СписокЗначений;
	Если ТипЗнч(ТекстПакетаИлиМассивТекстовЗапросов) = Тип("Массив") Тогда
		ТекстыЗапросовПакета = ТекстПакетаИлиМассивТекстовЗапросов;
	Иначе
		Если Не ирКэш.ДоступныРегВыраженияЛкс() Тогда
			Если ирКэш.ДоступноСхемаЗапросаЛкс() Тогда
				Схема = Вычислить("Новый СхемаЗапроса");
				#Если Сервер И Не Сервер Тогда
					Схема = Новый СхемаЗапроса;
				#КонецЕсли
				Попытка
					Схема.УстановитьТекстЗапроса(ТекстПакетаИлиМассивТекстовЗапросов);
				Исключение
					ОписаниеОшибки = ОписаниеОшибки(); // Для отладки
					Возврат СозданныеТаблицы;
				КонецПопытки;
				Для Каждого ЗапросПакета Из Схема.ПакетЗапросов Цикл
					ИмяСоздаваемойТаблицы = Неопределено;
					Если Истина
						И ТипЗнч(ЗапросПакета) = Тип("ЗапросВыбораСхемыЗапроса") 
						И ЗначениеЗаполнено(ЗапросПакета.ТаблицаДляПомещения) 
					Тогда
						ИмяСоздаваемойТаблицы = ЗапросПакета.ТаблицаДляПомещения;
					КонецЕсли; 
					СозданныеТаблицы.Добавить(НРег(ИмяСоздаваемойТаблицы), ИмяСоздаваемойТаблицы);
				КонецЦикла;
			КонецЕсли; 
			Возврат СозданныеТаблицы;
		КонецЕсли;
		ТекстыЗапросовПакета = РазбитьГрубоТекстПакетногоЗапросаНаЗапросы(ТекстПакетаИлиМассивТекстовЗапросов);
	КонецЕсли;
	RegExp2.Global = Истина;
	// Ищем в каждом запросе пакета предложение ПОМЕСТИТЬ/УНИЧТОЖИТЬ
	// Теперь мы работаем с возможно грязным текстом в виде литерала встроенного языка
	ШаблонПОМЕСТИТЬИЗ = "(?:(?:" + шРазделитель + "|\|)(?:(ПОМЕСТИТЬ|INTO\s+TABLE|INTO)|(УНИЧТОЖИТЬ|DROP|DROP\s+TABLE))(?:" + шРазделитель + "|\|)" 
		+ "+(" + шИмяВременнойТаблицы + ")(" + шРазделитель + "|;|'|"")|\s)|" + шРазделитель + "|.+?";
	RegExp2.Pattern = ШаблонПОМЕСТИТЬИЗ;
	СозданныеТаблицыНрег = Новый Массив;
	СначалаУничтоженныеТаблицы = Новый Массив;
	Для Каждого ТекстЗапроса Из ТекстыЗапросовПакета Цикл
		ИмяСозданнойВременнойТаблицы = Неопределено;
		СозданиеВременнойТаблицы = RegExp2.Заменить(ТекстЗапроса, "$1");
		ИмяВременнойТаблицы = RegExp2.Заменить(ТекстЗапроса, "$3");
		Если ЗначениеЗаполнено(СозданиеВременнойТаблицы) Тогда
			Если Ложь
				Или Не ТолькоТребующиеУничтоженияНаВходе 
				Или СначалаУничтоженныеТаблицы.Найти(НРег(ИмяВременнойТаблицы)) = Неопределено
			Тогда
				ИмяСозданнойВременнойТаблицы = ИмяВременнойТаблицы;
				Если ИмяСозданнойВременнойТаблицы <> Неопределено Тогда
					СозданныеТаблицыНрег.Добавить(НРег(ИмяСозданнойВременнойТаблицы));
				КонецЕсли; 
			КонецЕсли;
		ИначеЕсли ЗначениеЗаполнено(ИмяВременнойТаблицы) Тогда 
			Если ВместеСУничтожениями Тогда
				ИмяСозданнойВременнойТаблицы = "-" + ИмяВременнойТаблицы;
			КонецЕсли;
			ИмяВременнойТаблицы = НРег(ИмяВременнойТаблицы);
			Если ТолькоТребующиеУничтоженияНаВходе Тогда 
				Если СозданныеТаблицыНрег.Найти(ИмяВременнойТаблицы) = Неопределено Тогда
					СначалаУничтоженныеТаблицы.Добавить(ИмяВременнойТаблицы);
				КонецЕсли; 
			КонецЕсли;
		КонецЕсли;
		СозданныеТаблицы.Добавить(НРег(ИмяСозданнойВременнойТаблицы), ИмяСозданнойВременнойТаблицы);
	КонецЦикла;
	Возврат СозданныеТаблицы;
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// РАБОТА С ТИПАМИ

// Получает чистую внутреннюю таблицу предопределенных слов.
//
// Параметры:
//  Нет.
//
// Возвращаемое значение:
//  ТаблицаЗначений - с колонками "Слово", "ТипСлова", "ТаблицаТипов".
//
Функция НоваяТаблицаСлов() Экспорт 

	ВнутрТаблицаСлов = Новый ТаблицаЗначений;
	ВнутрТаблицаСлов.Колонки.Добавить("Слово");
	ВнутрТаблицаСлов.Колонки.Добавить("ТипСлова");
	ВнутрТаблицаСлов.Колонки.Добавить("ТаблицаТипов"); // см. НоваяТаблицаТипов()
	ВнутрТаблицаСлов.Колонки.Добавить("ТипЗначения");
	ВнутрТаблицаСлов.Колонки.Добавить("Определение");
	ВнутрТаблицаСлов.Колонки.Добавить("МожноУточнитьТип"); // Булево - используется только для частично рассчитанных
	ВнутрТаблицаСлов.Индексы.Добавить("Слово, ТипСлова");
	Возврат ВнутрТаблицаСлов;

КонецФункции

// Функция - Подобрать вариант синтаксиса метода
//
// Параметры:
//  ТаблицаВариантов - 	 - содержимое будет утеряно!
// 
// Возвращаемое значение:
//   строка - название варианта синтаксиса
//
Функция ПодобратьВариантСинтаксисаМетода(Знач ТаблицаВариантов, Знач КоличествоФактПараметровМетода = 0, Знач ТекущийВариант = "", Знач ТекущийВариантУстановленВручную = Ложь, выхНомер = 0) Экспорт
	
	#Если Сервер И Не Сервер Тогда
		ТаблицаВариантов = Новый ТаблицаЗначений;
	#КонецЕсли
	ТаблицаВариантов.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
	ТаблицаВариантов.ЗаполнитьЗначения(1, "Количество");
	ТаблицаВариантов.Свернуть("ВариантСинтаксиса", "Количество");
	//ТаблицаВариантов.Сортировать("Количество"); // Если закомментировано, то ОткрытьФорму("") правильно показывает и ближе к поведению конфигуратора
	НовыйТекущийВариант = "";
	Если ТаблицаВариантов.Количество() > 0 Тогда
		Для Каждого СтрокаВарианта Из ТаблицаВариантов Цикл
			Если ТекущийВариантУстановленВручную И СтрокаВарианта.ВариантСинтаксиса = ТекущийВариант Тогда    
				НовыйТекущийВариант = ТекущийВариант;
				выхНомер = ТаблицаВариантов.Индекс(СтрокаВарианта);
				Прервать;
			КонецЕсли;
			Если СтрокаВарианта.Количество >= КоличествоФактПараметровМетода Тогда
				НовыйТекущийВариант = СтрокаВарианта.ВариантСинтаксиса;
				выхНомер = ТаблицаВариантов.Индекс(СтрокаВарианта);
				Если Не ТекущийВариантУстановленВручную Тогда
					Прервать;
				КонецЕсли;
			КонецЕсли; 
		КонецЦикла;
		Если СтрокаВарианта.Количество < КоличествоФактПараметровМетода Тогда 
			НовыйТекущийВариант = СтрокаВарианта.ВариантСинтаксиса;
			выхНомер = ТаблицаВариантов.Индекс(СтрокаВарианта);
		КонецЕсли; 
	КонецЕсли;
	выхНомер = выхНомер + 1;
	Возврат НовыйТекущийВариант;

КонецФункции

Функция СинтаксПомощник() Экспорт
	Если СинтаксПомощник = Неопределено Тогда
		СинтаксПомощник = ирОбщий.СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирСинтаксПомощник");
	КонецЕсли;
	Возврат СинтаксПомощник;
КонецФункции

Функция ДоступныеЗначенияТипа(Знач ИмяТипаИлиТипЗначения) Экспорт 
	
	ИнициацияОписанияМетодовИСвойств();
	Если ТипЗнч(ИмяТипаИлиТипЗначения) = Тип("Тип") Тогда
		ИмяТипаИлиТипЗначения = СтруктураТипаИзКонкретногоТипа(ИмяТипаИлиТипЗначения).ИмяОбщегоТипа;  
	КонецЕсли; 
	//Пустышка = Вычислить("Метаданные.СвойстваОбъектов." + ИмяТипаЗначения);
	СтрокиЗначений = ТаблицаКонтекстов.НайтиСтроки(Новый Структура("ТипКонтекста, ТипСлова", "ПеречислениеМетаданных" + ИмяТипаИлиТипЗначения, "Свойство"));
	Если СтрокиЗначений.Количество() = 0 Тогда
		ИмяТипаПеречисления = ИмяТипаИлиТипЗначения;
		Если Не ирОбщий.СтрНачинаетсяСЛкс(ИмяТипаИлиТипЗначения, "Перечисление") Тогда
			ИмяТипаПеречисления = "Перечисление" + ИмяТипаПеречисления;
		КонецЕсли; 
		СтрокиЗначений = ТаблицаКонтекстов.НайтиСтроки(Новый Структура("ТипКонтекста, ТипСлова", ИмяТипаПеречисления, "Свойство"));
	КонецЕсли; 
	СтрокиЗначений = ТаблицаКонтекстов.Скопировать(СтрокиЗначений);
	СписокЗначений = Новый СписокЗначений;
	СписокЗначений.ЗагрузитьЗначения(СтрокиЗначений.ВыгрузитьКолонку("Слово"));
	Возврат СписокЗначений;

КонецФункции

// Формирует построитель запроса по структуре типа.
//
// Параметры:
//  СтруктураТипа - Структура - описатель типа.
//
// Возвращаемое значение:
//   ПостроительЗапроса.
//
Функция ПостроительЗапросаПоСтруктуреТипа(СтрокаОбщегоТипа, ВиртуальнаяТаблица = Неопределено)

	МетаданныеРодителя = СтрокаОбщегоТипа.Метаданные;
	Если ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") Тогда
		ПолноеИмя = МетаданныеРодителя.ПолноеИмя(); 
	Иначе
		ПолноеИмя = ирОбщий.КорневойТипКонфигурацииЛкс(КэшОбъект(МетаданныеРодителя).ПолноеИмя);
	КонецЕсли; 
	МассивФрагментов = ирОбщий.СтрРазделитьЛкс(ПолноеИмя);
	КорневойТипРодителя = МассивФрагментов[0];
	Если ОписаниеТипаМетаОбъектов(КорневойТипРодителя, , 0) <> Неопределено Тогда
		Если Ложь
			Или (Истина
				И МассивФрагментов.Количество() = 2
				И МассивФрагментов[0] <> "ВнешнийИсточникДанных")
			Или (Истина
				И МассивФрагментов.Количество() = 4
				И МассивФрагментов[2] = "ТабличнаяЧасть")
		Тогда
			ПостроительЗапроса = Новый Структура("ДоступныеПоля", Новый Массив);
			Если СтрокаОбщегоТипа.ИмяОбщегоТипа = "Константы.<Имя константы>" Тогда 
				ИмяТаблицы = "Константы." + МассивФрагментов[1];
			Иначе
				ИмяТаблицы = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмя, Ложь, ВиртуальнаяТаблица = Неопределено);
			КонецЕсли;
			Если ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") Тогда
				Если Ложь
					Или ВиртуальнаяТаблица = Неопределено 
					Или Найти(ВиртуальнаяТаблица.Выражение, "(") = 0
				Тогда
					ТаблицаРезультата = ирКэш.ПоляТаблицыБДЛкс(ИмяТаблицы + ВиртуальнаяТаблица.Выражение);
					#Если Сервер И Не Сервер Тогда
						ТаблицаРезультата = Новый ТаблицаЗначений;
					#КонецЕсли
					ТаблицаРезультата = ТаблицаРезультата.Скопировать(, "Имя, ТипЗначения"); // Делаем копию, т.к. будем ее модифицировать
					ПостроительЗапроса = Новый Структура("ДоступныеПоля", ТаблицаРезультата);
				Иначе
					Если СтрокаОбщегоТипа.ИмяОбщегоТипа = "Константы.<Имя константы>" Тогда
						ОпределениеТаблицы = "ВЫБРАТЬ " + ИмяТаблицы;
					Иначе
						УникальноеИмяТаблицы = "______________________";
						ОпределениеТаблицы = "ВЫБРАТЬ * ИЗ " + ИмяТаблицы ;
						Если ВиртуальнаяТаблица <> Неопределено Тогда
							ОпределениеТаблицы = ОпределениеТаблицы + ВиртуальнаяТаблица.Выражение;
						КонецЕсли; 
						ОпределениеТаблицы = ОпределениеТаблицы + " КАК " + УникальноеИмяТаблицы;
					КонецЕсли;
					Попытка
						//ПостроительЗапроса.Текст = ОпределениеТаблицы;
						ТаблицаРезультата = ирОбщий.ПустаяТаблицаЗначенийИзТекстаЗапросаЛкс(ОпределениеТаблицы,,, Ложь);
					Исключение
						Успех = Ложь;
						Если ВиртуальнаяТаблица <> Неопределено Тогда
							ПозицияСкобки = Найти(ВиртуальнаяТаблица.Выражение, "(");
							Если ПозицияСкобки > 0 Тогда
								ОпределениеТаблицы = "ВЫБРАТЬ * ИЗ " + ИмяТаблицы ;
								ОпределениеТаблицы = ОпределениеТаблицы + Лев(ВиртуальнаяТаблица.Выражение, ПозицияСкобки - 1);
								ОпределениеТаблицы = ОпределениеТаблицы + " КАК " + УникальноеИмяТаблицы;
								Попытка
									//ПостроительЗапроса.Текст = ОпределениеТаблицы;
									ТаблицаРезультата = ирОбщий.ПустаяТаблицаЗначенийИзТекстаЗапросаЛкс(ОпределениеТаблицы);
									Успех = Истина;
								Исключение
								КонецПопытки; 
							КонецЕсли; 
						КонецЕсли; 
						Если Не Успех Тогда
							ВызватьИсключение "ОшибкаВычисленияВиртуальнойТаблицы";
						КонецЕсли; 
					КонецПопытки;
					ТаблицаРезультата = ирОбщий.ТаблицаЗначенийВТаблицуПолейБДЛкс(ТаблицаРезультата);
					ПостроительЗапроса = Новый Структура("ДоступныеПоля", ТаблицаРезультата);
				КонецЕсли;
				ТаблицаРезультата.Колонки.Добавить("НИмя");
				ирОбщий.ОбновитьКопиюКолонкиВНижнемРегистреЛкс(ТаблицаРезультата);
				ирОбщий.ДополнитьТаблицуПолейТаблицыБДВиртуальнымиПолямиЛкс(ПостроительЗапроса.ДоступныеПоля, ирОбщий.ОписаниеТаблицыБДЛкс(ИмяТаблицы));
			Иначе
				// Внешние метаданные
				ПостроительЗапроса = Новый ПостроительЗапроса;
				ЗапросРеквизитов = Новый Запрос("ВЫБРАТЬ Имя, ТипыСтрокой ИЗ Справочник.СвойстваМетаданных ГДЕ Владелец = &СсылкаМД");
				ЗапросРеквизитов.УстановитьПараметр("СсылкаМД", МетаданныеРодителя);
				ТаблицаРеквизитов = ЗапросРеквизитов.Выполнить().Выгрузить();
				Для Каждого СтрокаРеквизита Из ТаблицаРеквизитов Цикл
					ДоступноеПоле = ПостроительЗапроса.ДоступныеПоля.Добавить(СтрокаРеквизита.Имя);
					Для Каждого СтрокаТипа Из СтрокаРеквизита.Типы Цикл
						МассивТипов = Новый Массив;
						ОбъектМД = КэшОбъект(СтрокаТипа.Объект);
						МассивТипов.Добавить(Тип(ОбъектМД.Наименование));
					КонецЦикла; 
					ДоступноеПоле.ТипЗначения = Новый ОписаниеТипов(МассивТипов);
				КонецЦикла;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли; 
	Возврат ПостроительЗапроса;

КонецФункции

// Получает массив общих типов, дополняя исходный тип расширениями.
//
// Параметры:
//  СтруктураТипа - Структура.
//
// Возвращаемое значение:
//
Функция ТаблицаОбщихТиповИзСтруктурыТипа(Знач СтруктураТипа, Знач ЭтоЛокальныйКонтекст, Знач ДляФиксированныхСлов = Истина) Экспорт 

	МассивОбщихТипов = НоваяТаблицаДополнительныхТипов();
	Если СтруктураТипа.ТипЯзыка <> "" Тогда
		ЗаполнитьЗначенияСвойств(МассивОбщихТипов.Добавить(), СтруктураТипа);
		Возврат МассивОбщихТипов;
	КонецЕсли;
	Если Ложь
		Или (Истина
			И ТипЗнч(СтруктураТипа.Метаданные) <> Тип("COMОбъект")
			И (Ложь
				Или СтруктураТипа.ИмяОбщегоТипа = "Локальный" // Для подстраховки
				Или ЭтоЛокальныйКонтекст И СтруктураТипа.ИмяОбщегоТипа <> "Глобальный"))
		Или СтруктураТипа.ИмяОбщегоТипа = "AutomationСервер" 
		Или СтруктураТипа.ИмяОбщегоТипа = "ВнешнееСоединение"
	Тогда
		// Должен идти первым в списке!
		НоваяСтрока = МассивОбщихТипов.Добавить();
		//ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа,, "ИмяОбщегоТипа, Метаданные");
		НоваяСтрока.ИмяОбщегоТипа = "Глобальный";
		НоваяСтрока.Метаданные = Метаданные;
	КонецЕсли;
	НоваяСтрока = МассивОбщихТипов.Добавить();
	ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа);
	Если СтруктураТипа.ИмяОбщегоТипа = "УправляемаяФорма" Тогда
		СтруктураТипа.ИмяОбщегоТипа = "ФормаКлиентскогоПриложения";
	КонецЕсли;
	Если Найти(СтруктураТипа.ИмяОбщегоТипа, "ТабличнаяЧасть.") > 0 Тогда
		НоваяСтрока = МассивОбщихТипов.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
		НоваяСтрока.ИмяОбщегоТипа = "ТабличнаяЧасть";
	ИначеЕсли Найти(СтруктураТипа.ИмяОбщегоТипа, "ТабличнаяЧастьСтрока.") > 0 Тогда
		НоваяСтрока = МассивОбщихТипов.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
		НоваяСтрока.ИмяОбщегоТипа = "СтрокаТабличнойЧасти";
	ИначеЕсли СтруктураТипа.ИмяОбщегоТипа = "ПолеТекстовогоДокумента" Тогда
		НоваяСтрока = МассивОбщихТипов.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
		НоваяСтрока.ИмяОбщегоТипа = "ТекстовыйДокумент";
	ИначеЕсли СтруктураТипа.ИмяОбщегоТипа = "ПолеГрафическойСхемы" Тогда
		НоваяСтрока = МассивОбщихТипов.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
		НоваяСтрока.ИмяОбщегоТипа = "ГрафическаяСхема";
	ИначеЕсли СтруктураТипа.ИмяОбщегоТипа = "ПолеТабличногоДокумента" Тогда
		НоваяСтрока = МассивОбщихТипов.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
		НоваяСтрока.ИмяОбщегоТипа = "ТабличныйДокумент";
	ИначеЕсли Найти(СтруктураТипа.ИмяОбщегоТипа, "КоллекцияМетаданных") > 0 Тогда
		Если ДляФиксированныхСлов Тогда
			НоваяСтрока = МассивОбщихТипов.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
			НоваяСтрока.ИмяОбщегоТипа = "КоллекцияОбъектовМетаданных";
		КонецЕсли;
	ИначеЕсли СтруктураТипа.ИмяОбщегоТипа = "ОбъектМетаданных" Тогда
		Для Каждого СтрокаТипа Из ТаблицаТиповМетаОбъектов Цикл
			НоваяСтрока = МассивОбщихТипов.Добавить();
			//ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
			НоваяСтрока.ИмяОбщегоТипа = "ОбъектМетаданных" + СтрокаТипа.Единственное;
		КонецЦикла;
	//ИначеЕсли Найти(СтруктураТипа.ИмяОбщегоТипа, "РасширениеФормы") > 0 Тогда
	//	НоваяСтрока = МассивОбщихТипов.Добавить();
	//	ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
	//	НоваяСтрока.ИмяОбщегоТипа = "Форма";

	//Иначе
	//	ОбщийТипМетаданных = ирОбщий.ТекстМеждуМаркерамиЛкс(СтруктураТипа.ИмяОбщегоТипа, , ": ", Ложь);
	//	//Если ОбщийТипМетаданных <> "" Тогда
	//	Если ЗначениеЗаполнено(ОбщийТипМетаданных) Тогда
	//		НоваяСтрока = МассивОбщихТипов.Добавить();
	//		ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
	//		НоваяСтрока.ИмяОбщегоТипа = ОбщийТипМетаданных;
	//	КонецЕсли;
	КонецЕсли;
	
	// TODO добавить расширения управляемой формы Мультиметка638663811
	
	// Расширения, образованные элементом управления и типом связанных с ним данных
	СтрокаРасширения = ТаблицаРасширенийТипов.Найти(СтруктураТипа.ИмяОбщегоТипа, "Расширение");
	Если Истина
		И СтрокаРасширения <> Неопределено 
		И ЗначениеЗаполнено(СтрокаРасширения.ОсновнойТип) 
	Тогда
		Если Истина
			И СтрокаРасширения.ОсновнойТип = "Форма"
			И СтруктураТипа.ДополнительныеТипы = Неопределено
		Тогда
			НоваяСтрока = МассивОбщихТипов.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
			НоваяСтрока.ИмяОбщегоТипа = СтрокаРасширения.РасширяющийТип;
			#Если Клиент Тогда
				Если ТипЗнч(СтруктураТипа.Метаданные) = Тип("Форма") Тогда
					СтруктураТипаОбъекта = СтруктураТипаОбъектаОбычнойФормы(СтруктураТипа.Метаданные);
					ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипаОбъекта);
				КонецЕсли;
			#КонецЕсли 
		КонецЕсли;
		НоваяСтрока = МассивОбщихТипов.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
		НоваяСтрока.ИмяОбщегоТипа = СтрокаРасширения.ОсновнойТип;
	КонецЕсли;
	
	// Общие расширения элементов управления
	Для Счетчик = 1 По Мин(2, МассивОбщихТипов.Количество()) Цикл // Для поля табличного документа будет 2 типа https://www.hostedredmine.com/issues/956247
		лИмяОбщегоТипа = МассивОбщихТипов[МассивОбщихТипов.Количество() - Счетчик].ИмяОбщегоТипа;
		Если МассивОбычныхЭлементовУправления.Найти(лИмяОбщегоТипа) <> Неопределено Тогда
			НоваяСтрока = МассивОбщихТипов.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
			НоваяСтрока.ИмяОбщегоТипа = "РасширениеЭлементовУправленияРасположенныхВФорме";
			НоваяСтрока = МассивОбщихТипов.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
			НоваяСтрока.ИмяОбщегоТипа = "РасширениеЭлементовУправленияРасположенныхНаПанели";
		//ИначеЕсли МассивУправляемыхЭлементовУправления.Найти(лИмяОбщегоТипа) <> Неопределено Тогда
		//  // http://www.hostedredmine.com/issues/882998
		//	НоваяСтрока = МассивОбщихТипов.Добавить();
		//	ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураТипа, "Метаданные");
		//	НоваяСтрока.ИмяОбщегоТипа = "РасширениеЭлементовУправленияРасположенныхВФорме";
		КонецЕсли;
	КонецЦикла;

	Если СтруктураТипа.ДополнительныеТипы <> Неопределено Тогда
		ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(СтруктураТипа.ДополнительныеТипы, МассивОбщихТипов);
	КонецЕсли;
	Возврат МассивОбщихТипов;

КонецФункции

Процедура ОчиститьКэшАнализатораЯзыка() Экспорт 
	мМодулиМетаданных = Неопределено;
	мВызовыВсехМетодовПоМодулям = Неопределено;
	мКэшСловГлобальногоКонтекста = Неопределено;
	мПассивныеФормы.Очистить();
КонецПроцедуры

Процедура ПроверитьОбновитьКэш() Экспорт 
	НоваяДатаОбновленияКэшаМодулей = ирОбщий.ДатаОбновленияКэшаМодулейЛкс();
	Если мДатаОбновленияКэшаМодулей <> НоваяДатаОбновленияКэшаМодулей Тогда 
		ОчиститьКэшАнализатораЯзыка();
		мДатаОбновленияКэшаМодулей = НоваяДатаОбновленияКэшаМодулей;
	КонецЕсли;
КонецПроцедуры

// Получает внутреннюю таблицу предопределенных слов заданного родительского типа.
//
// Параметры:
//  РодительскаяСтруктураТипа - Структура;
//  *Слово       - Строка, *Неопределено - для отбора;
//  *ТипСлова    - Строка, *Неопределено - для отбора;
//  *ВиртуальнаяТаблица - Структура, *Неопределено - описание виртуальной таблицы;
//  *ЯзыкПрограммы - *Число, 0;
//
// Возвращаемое значение:
//  ТаблицаЗначений - с колонками "Слово", "ТипСлова", "ТаблицаТипов".
//
Функция СловаКонтекстаПредопределенные(Знач РодительскаяСтруктураТипа, Знач Слово = Неопределено, Знач ТипСлова = Неопределено, Знач ВиртуальнаяТаблица = Неопределено, Знач ЯзыкПрограммы = 0,
	Знач Конфигурация = Неопределено, Знач ВычислятьТипы = Истина, Знач ФлагиКомпиляции = Неопределено, Знач ТаблицаСлов = Неопределено, Знач ЭтоЛокальныйКонтекст = Ложь, Знач НаборыСлов = Неопределено,
	Знач БазовоеРасширениеКонфигурации = "") Экспорт 
	
	Если Истина
		И Не РодительскаяСтруктураТипа.Конструктор 
		И Не ЗначениеЗаполнено(РодительскаяСтруктураТипа.ИмяОбщегоТипа) 
		И РодительскаяСтруктураТипа.ТипЯзыка = ""
	Тогда
		// родительский контекст является Процедурой
		Если ТаблицаСлов = Неопределено Тогда
			ТаблицаСлов = НоваяТаблицаСлов();
		КонецЕсли;
		Возврат ТаблицаСлов;
	КонецЕсли;
	КлючПоискаКонструктора = Новый Структура;
	Если РодительскаяСтруктураТипа.Конструктор Тогда
		КлючПоискаКонструктора = Новый Структура("ЕстьКонструктор, ЯзыкПрограммы, НСлово", Истина, ЯзыкПрограммы);
	КонецЕсли;
	ИмяОбщегоТипаРодителяБезДеталей = РодительскаяСтруктураТипа.ИмяОбщегоТипа; 
	Если Найти(ИмяОбщегоТипаРодителяБезДеталей, " {V") > 0 Тогда
		ЧистоеИмяТипа = ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипаРодителяБезДеталей, " ");
		Если Найти(ЧистоеИмяТипа, "IV8COMConnector") = 1 Тогда 
			РодительскаяСтруктураТипа.ИмяОбщегоТипа = "МенеджерCOMСоединений";
		ИначеЕсли Найти(ЧистоеИмяТипа, "IServerAgentConnection") = 1 Тогда 
			РодительскаяСтруктураТипа.ИмяОбщегоТипа = "Соединение с агентом сервера";
		ИначеЕсли Найти(ИмяОбщегоТипаРодителяБезДеталей, "IWorkingProcessConnection") Тогда 
			РодительскаяСтруктураТипа.ИмяОбщегоТипа = "Соединение с рабочим процессом";
		ИначеЕсли Найти(ИмяОбщегоТипаРодителяБезДеталей, "Application") Тогда  
			РодительскаяСтруктураТипа.ИмяОбщегоТипа = "AutomationСервер";
		КонецЕсли;
	КонецЕсли; 
	МассивОбщихТипов = ТаблицаОбщихТиповИзСтруктурыТипа(РодительскаяСтруктураТипа, ЭтоЛокальныйКонтекст, Истина);
	#Если Сервер И Не Сервер Тогда
		МассивОбщихТипов = Новый ТаблицаЗначений;
		ТаблицаСлов = Новый ТаблицаЗначений;
	#КонецЕсли
	ЛиКэшАгрегатный = Ложь;
	НомерВерсииПлатформы = ирКэш.НомерВерсииПлатформыЛкс();
	Для Каждого СтрокаОбщегоТипа Из МассивОбщихТипов Цикл
		ИмяОбщегоТипаРодителяБезДеталей = ирОбщий.ПервыйФрагментЛкс(СтрокаОбщегоТипа.ИмяОбщегоТипа, "["); 
		Если Не ЛиКэшАгрегатный Тогда
			ИспользоватьКэширование = Истина
				И Слово = Неопределено
				И (Ложь
					Или ИмяОбщегоТипаРодителяБезДеталей = "Глобальный"
					Или ИмяОбщегоТипаРодителяБезДеталей = "ОбъектМетаданных" И РодительскаяСтруктураТипа.ТипЯзыка = ""
					Или ИмяОбщегоТипаРодителяБезДеталей = "" // ИмяТипа
					);
			Если ИспользоватьКэширование Тогда
				Если ИмяОбщегоТипаРодителяБезДеталей = "ОбъектМетаданных" Тогда
					ЛиКэшАгрегатный = Истина;
					КлючКэширования = ИмяОбщегоТипаРодителяБезДеталей;
				Иначе
					// Мультиметка3398476724
					ЛиСеансТолстогоКлиентаУП = ирКэш.ЛиСеансТолстогоКлиентаУПЛкс();
					НаСервере = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "Сервер", Истина);
					КлиентОбычноеПриложение = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "КлиентОбычноеПриложение", Не ЛиСеансТолстогоКлиентаУП);
					КлиентУправляемоеПриложение = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "КлиентУправляемоеПриложение", ЛиСеансТолстогоКлиентаУП);
					
					ЛиКэшАгрегатный = ИмяОбщегоТипаРодителяБезДеталей = "ОбъектМетаданных";
					КлючКэширования = ИмяОбщегоТипаРодителяБезДеталей + ";" + ЯзыкПрограммы + ";" + Конфигурация + ";" + ВычислятьТипы + ";" + ТипСлова + ";" + НаСервере + ";" + КлиентОбычноеПриложение + ";" 
						+ КлиентУправляемоеПриложение + ";" + РодительскаяСтруктураТипа.ТипЯзыка + ";" + БазовоеРасширениеКонфигурации + ";" + РодительскаяСтруктураТипа.Конструктор;
				КонецЕсли;
				Если мКэшСловГлобальногоКонтекста = Неопределено Тогда
					мКэшСловГлобальногоКонтекста = Новый Соответствие;
				КонецЕсли; 
				ТаблицаСловИзКэша = мКэшСловГлобальногоКонтекста[КлючКэширования];
				#Если Сервер И Не Сервер Тогда
					ТаблицаСловИзКэша = Новый ТаблицаЗначений;
				#КонецЕсли
				Если ТаблицаСловИзКэша <> Неопределено Тогда
					Если ТаблицаСлов <> Неопределено Тогда
						ВызватьИсключение "Для глобального контекста нельзя передавать таблицу-приемник";
					КонецЕсли;
					Если НаборыСлов <> Неопределено Тогда
						НаборыСлов.Вставить(КлючКэширования, ТаблицаСловИзКэша);
						ТаблицаСлов = НоваяТаблицаСлов();
					Иначе 
						ТаблицаСлов = ТаблицаСловИзКэша.Скопировать();
					КонецЕсли;
					Если ЛиКэшАгрегатный Тогда
						ИспользоватьКэширование = Ложь;
						Прервать;
					Иначе
						Продолжить;
					КонецЕсли;
				КонецЕсли; 
			КонецЕсли; 
		КонецЕсли;
		Если ТаблицаСлов = Неопределено Тогда
			ТаблицаСлов = НоваяТаблицаСлов();
		КонецЕсли; 
		Если Истина
			И ИмяОбщегоТипаРодителяБезДеталей <> "Глобальный"
			И ФлагиКомпиляции <> Неопределено 
			И ФлагиКомпиляции.БезКонтекста 
			И ЭтоЛокальныйКонтекст
		Тогда
			Продолжить;
		КонецЕсли; 
		МетаданныеРодителя = СтрокаОбщегоТипа.Метаданные;
		Если Истина
			И ТипЗнч(МетаданныеРодителя) = Тип("Структура") 
			И ирОбщий.СвойствоСтруктурыЛкс(МетаданныеРодителя, "Форма") <> Неопределено 
		Тогда
			МетаданныеРодителя = МетаданныеРодителя.Форма;
		КонецЕсли;
		КорневойТипРодителя = Неопределено;
		ПостроительЗапросаРодителя = Неопределено;
		ТипМетаданныхРодителя = ТипЗнч(МетаданныеРодителя);
		Если Истина
			И ТипМетаданныхРодителя = Тип("ОбъектМетаданных")
			И РодительскаяСтруктураТипа.ТипЯзыка <> "ИмяТипа"
		Тогда 
			Если ТипМетаданныхРодителя = Тип("ОбъектМетаданных") Тогда
				КорневойТипРодителя = ирОбщий.КорневойТипКонфигурацииЛкс(МетаданныеРодителя);
			Иначе
				КорневойТипРодителя = ирОбщий.КорневойТипКонфигурацииЛкс(КэшОбъект(МетаданныеРодителя).ПолноеИмя);
			КонецЕсли; 
			ПостроительЗапросаРодителя = ПостроительЗапросаПоСтруктуреТипа(СтрокаОбщегоТипа, РодительскаяСтруктураТипа.ВиртуальнаяТаблица);
		КонецЕсли;
		Если ИмяОбщегоТипаРодителяБезДеталей = "Локальный" Тогда
			НайденныеСтроки = Новый Массив;
		ИначеЕсли ТипСлова = "Конструктор" Тогда
			НайденныеСтроки = Новый Массив;
			Если ИмяОбщегоТипаРодителяБезДеталей = "Глобальный" Тогда 
				СтруктураКлюча = Новый Структура("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка, ТипСлова", 
					Слово, ЯзыкПрограммы, РодительскаяСтруктураТипа.ТипЯзыка, ТипСлова);
				НайденныеСтроки = ТаблицаКонтекстов.НайтиСтроки(СтруктураКлюча);
			КонецЕсли; 
		Иначе
			// Состав полей совпадает с индексом
			СтруктураКлюча = Новый Структура("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка",
				ИмяОбщегоТипаРодителяБезДеталей, ЯзыкПрограммы, РодительскаяСтруктураТипа.ТипЯзыка);
			Если Слово <> Неопределено Тогда
				СтруктураКлюча.Вставить("НСлово", НРег(Слово));
				Если Истина
					И ЯзыкПрограммы = 0 // В языке запросов может быть неоднозначность между типами слов Таблица и Поле. Поэтому для них жертвуем попаданием в индекс
					И ТипСлова = Неопределено 
				Тогда
					//ирОбщий.СообщитьЛкс("Использован медленный поиск по таблице контекстов");
					ТипСлова = "Свойство"; // Так будем всегда попадать в индекс
				КонецЕсли; 
			КонецЕсли;
			Если ТипСлова <> Неопределено Тогда
				СтруктураКлюча.Вставить("ТипСлова", ТипСлова);
			КонецЕсли;
			Если ЯзыкПрограммы <> 0 Тогда
				ирОбщий.ДобавитьИндексВТаблицуЛкс(ТаблицаКонтекстов, СтруктураКлюча);  // спасает в случае языка запросов, где ТипСлова не используется
			КонецЕсли;
			НайденныеСтроки = ТаблицаКонтекстов.НайтиСтроки(СтруктураКлюча);
		КонецЕсли; 
		ПредыдущаяСтрокаСлова = Неопределено; // Для регистра бухгалтерии
		ВычислятьТипыЦикл = ВычислятьТипы Или НайденныеСтроки.Количество() < 100;
		Для Каждого СтрокаСлова Из НайденныеСтроки Цикл
			Если Истина
				И ПредыдущаяСтрокаСлова <> Неопределено
				И ПредыдущаяСтрокаСлова.НСлово = СтрокаСлова.НСлово 
				И ПредыдущаяСтрокаСлова.ТипСлова = СтрокаСлова.ТипСлова
			Тогда
				Продолжить;
			КонецЕсли;
			ПредыдущаяСтрокаСлова = СтрокаСлова;
			Если СтрокаСлова.НомерВерсииПлатформы > НомерВерсииПлатформы Тогда
				Продолжить;
			КонецЕсли; 
			Если Истина
				И СтрокаСлова.ТипСлова = "Метод" 
				И СтрокаОбщегоТипа.НеВключатьМетоды
			Тогда
				Продолжить;
			КонецЕсли;
			Если Истина
				И ТипСлова = Неопределено
				И (Ложь
					Или СтрокаСлова.ТипСлова = "Событие"
					Или СтрокаСлова.ТипСлова = "Параметр"
					Или СтрокаСлова.ТипСлова = "Конструктор")
			Тогда
				Продолжить;
			КонецЕсли;
			Если РодительскаяСтруктураТипа.Конструктор Тогда 
				КлючПоискаКонструктора.НСлово = НРег(СтрокаСлова.Слово);
				Если ТаблицаОбщихТипов.НайтиСтроки(КлючПоискаКонструктора).Количество() = 0 Тогда 
					Продолжить;
				КонецЕсли;
			КонецЕсли; 
			МожноУточнитьТип = СтрокаСлова.Слово = "ВладелецФормы";
			ЛиТипСКвалификаторами = Истина
				И (Ложь
					Или СтрокаСлова.ТипСлова = "Свойство"
					Или СтрокаСлова.ТипСлова = "Поле")
				И ирОбщий.ЛиИмяТипаСКвалификаторамиЛкс(СтрокаСлова.ТипЗначения)
				И Не ирОбщий.СтрНачинаетсяСЛкс(РодительскаяСтруктураТипа.ИмяОбщегоТипа, "ОбъектМетаданных");
			ТаблицаТипов = Неопределено;
			Если ВычислятьТипыЦикл Тогда
				ТаблицаТипов = НоваяТаблицаТипов();
				ЛиДобавляемСлово = Истина;
				Если Найти(СтрокаСлова.ТипЗначения, "[") > 0 Тогда
					МассивТиповЗначения = ирОбщий.ЗначенияВМассивЛкс(СтрокаСлова.ТипЗначения);
				Иначе 
					МассивТиповЗначения = ирОбщий.СтрРазделитьЛкс(СтрокаСлова.ТипЗначения, ", ");
				КонецЕсли;
				Для Каждого ИмяОбщегоТипаСлова Из МассивТиповЗначения Цикл
					СтруктураТипа = НоваяСтруктураТипа();
					СтруктураТипа.СтрокаОписания = СтрокаСлова;
					ЗаполнитьЗначенияСвойств(СтруктураТипа, РодительскаяСтруктураТипа, , "ИмяОбщегоТипа, СтрокаОписания, Метаданные");
					Если Истина
						И ЛиИмяТипаЭлементаУправляемойФормы(ИмяОбщегоТипаРодителяБезДеталей) 
						И ТипЗнч(МетаданныеРодителя) <> Тип(ИмяОбщегоТипаРодителяБезДеталей)
						И ТипЗнч(МетаданныеРодителя) <> Тип("Структура")
					Тогда
						СтруктураТипа.Метаданные = Новый Структура("Тип");
						СтруктураТипа.Метаданные.Тип = Тип(ИмяОбщегоТипаРодителяБезДеталей);
						Если ИмяОбщегоТипаРодителяБезДеталей <> РодительскаяСтруктураТипа.ИмяОбщегоТипа Тогда
							СтруктураТипа.Метаданные.Вставить("ИмяТипаРасширения", РодительскаяСтруктураТипа.ИмяОбщегоТипа);
						КонецЕсли;
					ИначеЕсли Истина
						//И ТипЗнч(МетаданныеРодителя) <> Тип("COMОбъект")
						//И СтрокаСлова.ТипСлова = "Свойство"
						И СтрокаСлова.Слово <> "ВладелецФормы"
						И ИмяОбщегоТипаРодителяБезДеталей <> "КлючИЗначение" // Для проверки выражений
						И ИмяОбщегоТипаРодителяБезДеталей <> "ЭлементСпискаЗначений" // Для проверки выражений
						И ИмяОбщегоТипаРодителяБезДеталей <> "Структура" // Исключаем общее описание значений элементов структуры (Метаданные = ТаблицаЗначений)
					Тогда
						ЗаполнитьЗначенияСвойств(СтруктураТипа, СтрокаОбщегоТипа, "Метаданные");
					КонецЕсли; 
					Если ИмяОбщегоТипаСлова = "ОбъектМетаданныхКонфигурация" Тогда
						//СтруктураТипа.Метаданные = Конфигурация;
						Если Конфигурация <> Неопределено Тогда
							СтруктураТипа.Метаданные = Конфигурация;
						Иначе
							СтруктураТипа.Метаданные = мМетаданные;
						КонецЕсли;
					ИначеЕсли ИмяОбщегоТипаСлова = "Отбор" Тогда 
						Если Истина
							И ТипЗнч(СтрокаОбщегоТипа.Метаданные) = Тип("ОбъектМетаданных")
							И (Ложь
								//Или Найти(НРег(СтрокаОбщегоТипа.ИмяОбщегоТипа), "объект.") > 0
								Или Найти(НРег(СтрокаОбщегоТипа.ИмяОбщегоТипа), "наборзаписей.") > 0)
						Тогда
							ИмяТаблицыБД = ирКэш.ИмяТаблицыИзМетаданныхЛкс(СтрокаОбщегоТипа.Метаданные.ПолноеИмя());
							СтруктураОбъекта = ирОбщий.ОбъектБДПоКлючуЛкс(ИмяТаблицыБД);
							СтруктураТипа.Метаданные = СтруктураОбъекта.Методы; 
						ИначеЕсли СтрокаОбщегоТипа.ИмяОбщегоТипа = "РасширениеТабличногоПоляТабличнойЧасти" Тогда
							Если ТипЗнч(СтрокаОбщегоТипа.Метаданные) = Тип("ТабличноеПоле") Тогда
								СтруктураТипа.Метаданные = Метаданные.НайтиПоТипу(ТипЗнч(СтрокаОбщегоТипа.Метаданные.Значение));
							КонецЕсли;
						Иначе
							КонкретныйТип = ИмяТипаИзСтруктурыТипа(СтрокаОбщегоТипа);
							Если Истина
								И Найти(КонкретныйТип, "<") = 0 
								И ТипЗнч(СтруктураТипа.Метаданные) <> Тип(КонкретныйТип)
							Тогда
								Попытка
									Образователь = Новый (КонкретныйТип);
									СтруктураТипа.Метаданные = Образователь;
								Исключение
									// Срабатывает для табличных полей
								КонецПопытки;
							КонецЕсли; 
						КонецЕсли;  
					КонецЕсли;
					СтруктураТипа.ИмяОбщегоТипа = ИмяОбщегоТипаСлова;
					Если ВиртуальнаяТаблица <> Неопределено Тогда
						ЗаполнитьЗначенияСвойств(СтруктураТипа.ВиртуальнаяТаблица, ВиртуальнаяТаблица);
					КонецЕсли;
					
					Если РодительскаяСтруктураТипа.ТипЯзыка = "ИмяТипа" Тогда
						СтруктураТипа.ИмяОбщегоТипа = СтрокаСлова.Слово;
						Если СтрокаСлова.ТипКонтекста <> "" Тогда
							СтруктураТипа.ИмяОбщегоТипа = СтрокаСлова.ТипКонтекста + "." + СтруктураТипа.ИмяОбщегоТипа;
						КонецЕсли;
					КонецЕсли;
					
					Если Истина
						И Найти(СтруктураТипа.ИмяОбщегоТипа, "СтрокаТабличнойЧасти") > 0
						И Найти(РодительскаяСтруктураТипа.ИмяОбщегоТипа, "ТабличнаяЧасть.") > 0
					Тогда
						ИмяТипаСтрокиТЧ = СтрЗаменить(РодительскаяСтруктураТипа.ИмяОбщегоТипа, "ТабличнаяЧасть.", "ТабличнаяЧастьСтрока.");
						СтруктураТипа.ИмяОбщегоТипа = СтрЗаменить(СтруктураТипа.ИмяОбщегоТипа, "СтрокаТабличнойЧасти", ИмяТипаСтрокиТЧ);
					КонецЕсли;
					
					#Если Клиент Тогда
						Если Истина
							И ТипЗнч(МетаданныеРодителя) = Тип("ТабличноеПоле")
							И ИмяОбщегоТипаСлова = "КолонкаТабличногоПоля"
						Тогда
							ИмяОбщегоТипаРасширения = ИмяТипаРасширенияЭлементаФормы(ИмяОбщегоТипаСлова, МетаданныеРодителя);
							Если ИмяОбщегоТипаРасширения <> Неопределено Тогда
								СтруктураТипа.ИмяОбщегоТипа = ИмяОбщегоТипаРасширения;
							КонецЕсли;
						КонецЕсли;
					#КонецЕсли  
					
					МаркерРасширений = "Расширение";
					Если Истина
						И Лев(РодительскаяСтруктураТипа.ИмяОбщегоТипа, СтрДлина(МаркерРасширений)) = МаркерРасширений
						И СтрокаСлова.Слово = "Значение"
					Тогда
						Если РодительскаяСтруктураТипа.Метаданные <> Неопределено Тогда
							ЭлементФормы = РодительскаяСтруктураТипа.Метаданные; // ПолеВвода
							СтруктураТипа = СтруктураТипаИзЗначения(ЭлементФормы.Значение);
						Иначе
							СтрокаРасширения = ТаблицаРасширенийТипов.Найти(РодительскаяСтруктураТипа.ИмяОбщегоТипа, "Расширение");
							//Если СтрокаРасширения <> Неопределено Тогда
								СтруктураТипа.ИмяОбщегоТипа = СтрокаРасширения.РасширяющийТип;
							//КонецЕсли;
						КонецЕсли;
					КонецЕсли;
					Если Истина
						И МетаданныеРодителя <> Неопределено
						И СтрокаСлова.ТипСлова = "Свойство"
					Тогда
						Если Ложь 
							Или ТипЗнч(МетаданныеРодителя) = Тип("ПостроительЗапроса")
							Или (Истина // Нельзя допускать неявного выполнения запроса при обращении к свойству "Результат" построителя
								И СтруктураТипа.ИмяОбщегоТипа = "РезультатЗапроса"
								И ТипЗнч(МетаданныеРодителя) = Тип("ПостроительЗапроса"))
							Или (Истина // Здесь свойство есть у объекта метаданных, но имеет другой смысл
								И СтрокаСлова.Слово = "ВидыСубконто"
								И СтруктураТипа.ИмяОбщегоТипа = "ПланСчетовВидыСубконто.<Имя плана счетов>")
						Тогда
							ЗначениеСвойства = МетаданныеРодителя;
						Иначе
							Если Истина
								#Если Клиент Тогда
									И ТипЗнч(МетаданныеРодителя) = Тип("ТабличноеПоле")
								#Иначе
									И Ложь
								#КонецЕсли 
								И СтрокаСлова.Слово = "ТекущийРодитель"
							Тогда
								// Антибаг платформы 8.2.16. Вывести в чистом виде не удалось. Падает при вычислении свойства ТекущийРодитель в форме списка РС.ООП_ВаучерыТез
								ЗначениеСвойства = Неопределено;
							Иначе
								Попытка
									ЗначениеСвойства = МетаданныеРодителя[СтрокаСлова.Слово];
								Исключение
									ЗначениеСвойства = Неопределено;
								КонецПопытки;
							КонецЕсли; 
						КонецЕсли; 
						Если ЗначениеСвойства <> Неопределено Тогда
							Если Истина 
								И ТипЗнч(ЗначениеСвойства) = Тип("ТаблицаЗначений")
								И ЗначениеСвойства.Колонки.Найти(ИмяКолонкиФлагаВнутриТаблицы()) <> Неопределено
							Тогда 
								// Например КлючИЗначение, ЭлементСпискаЗначений
							ИначеЕсли мМассивТиповСМетаданными.Найти(ТипЗнч(ЗначениеСвойства)) <> Неопределено Тогда 
								Если СтрокаСлова.ТипЗначения = "ВсеЭлементыФормы" Тогда 
									// Для имитатора формы
								Иначе
									СтруктураТипа.Метаданные = ЗначениеСвойства;
								КонецЕсли;
								Если ирОбщий.ЛиФормаИлиИмитаторЛкс(МетаданныеРодителя, Ложь) Тогда
									СтруктураТипа.ДержательМетаданных = МетаданныеРодителя;
								КонецЕсли;
							КонецЕсли;
						КонецЕсли;
					КонецЕсли;
					
					// Для методов метаданных нужна специфическая обработка для усечения типов
					Если Истина
						И СтрокаСлова.ТипСлова = "Метод"
						И ирОбщий.СтрНачинаетсяСЛкс(ИмяОбщегоТипаСлова, МаркерОбъектаМетаданных)
						И СтрокаСлова.Слово = "Родитель"
					Тогда
						Родитель = Неопределено;
						Если ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") Тогда
							Родитель = МетаданныеРодителя.Родитель();
						КонецЕсли;
						Если Родитель <> Неопределено Тогда
							МассивФрагментов = ирОбщий.СтрРазделитьЛкс(Родитель.ПолноеИмя());
							СтруктураТипа.ИмяОбщегоТипа = МаркерОбъектаМетаданных + МассивФрагментов[МассивФрагментов.ВГраница() - 1];
						Иначе
							СтруктураТипа.ИмяОбщегоТипа = ИмяОбщегоТипаОбъектаМетаданных();
						КонецЕсли; 
						СтруктураТипа.Метаданные = Родитель;
						ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
						Прервать;
					ИначеЕсли Истина
						И СтрокаСлова.ТипСлова = "Метод"
						И Лев(ИмяОбщегоТипаСлова, СтрДлина(МаркерКоллекцииОбъектовМетаданных)) = МаркерКоллекцииОбъектовМетаданных
						И (Ложь
							Или СтрокаСлова.Слово = "Найти"
							Или СтрокаСлова.Слово = "Получить")
					Тогда
						СтруктураКлюча = Новый Структура("БазовыйТип, ЯзыкПрограммы", ИмяОбщегоТипаСлова, ЯзыкПрограммы);
						НайденныеСтроки = ТаблицаОбщихТипов.НайтиСтроки(СтруктураКлюча);
						СтруктураТипа.ИмяОбщегоТипа = НайденныеСтроки[0].ТипЭлементаКоллекции;
						ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
						Прервать;
					ИначеЕсли Истина                    
						И ТипЗнч(МетаданныеРодителя) = Тип("ОписаниеТипов")
						И СтрокаСлова.ТипКонтекста = "ОписаниеТипов"
						И СтрокаСлова.Слово = "ПривестиЗначение"
					Тогда
						Если МетаданныеРодителя.Типы().Количество() = 1 Тогда 
							ДобавитьВТаблицуТипов(ТаблицаТипов, МетаданныеРодителя);
						КонецЕсли;
						Прервать;
					ИначеЕсли Истина
						И ТипЗнч(МетаданныеРодителя) = Тип("ТекстовыйДокумент")
						И ИмяОбщегоТипаРодителяБезДеталей = "ТекстовыйДокумент"
						И СтрокаСлова.Слово = "ПолучитьТекст"
					Тогда
						СтруктураТипа = НоваяСтруктураТипа("Строка");
						СтруктураТипа.Метаданные = МетаданныеРодителя.ПолучитьТекст();
						ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
						Прервать;
					ИначеЕсли Истина
						И (Ложь
							Или ИмяОбщегоТипаРодителяБезДеталей = "КлючИЗначение"
							Или ИмяОбщегоТипаРодителяБезДеталей = "ЭлементСпискаЗначений")
						И ТипЗнч(МетаданныеРодителя) = Тип("Структура")
						И МетаданныеРодителя.Свойство(СтрокаСлова.Слово)
					Тогда
						ТаблицаТипов = МетаданныеРодителя[СтрокаСлова.Слово];
						Если ТаблицаТипов <> Неопределено Тогда
							МожноУточнитьТип = Истина;
							Прервать;
						КонецЕсли;
					//ИначеЕсли Истина
					//	И ИмяОбщегоТипаРодителяБезДеталей = "КлючИЗначение"
					//	И ТипЗнч(МетаданныеРодителя) = Тип("ТаблицаЗначений")
					//	И СтрокаСлова.Слово = "Значение"
					//Тогда
					//	ТаблицаТипов = МетаданныеРодителя;
					//	МожноУточнитьТип = Истина;
					ИначеЕсли Истина
						И ИмяОбщегоТипаРодителяБезДеталей = "Соответствие"
						И СтрокаСлова.Слово = "Получить"
						И ТипЗнч(МетаданныеРодителя) = Тип("Структура")
					Тогда
						ТаблицаТипов = МетаданныеРодителя.Значение;
						Если ТаблицаТипов <> Неопределено Тогда
							МожноУточнитьТип = Истина;
							Прервать;
						КонецЕсли;
					ИначеЕсли Истина
						И ИмяОбщегоТипаРодителяБезДеталей = "Запрос"
						И ИмяОбщегоТипаСлова = "МенеджерВременныхТаблиц"
					Тогда 
						МенеджерВременныхТаблиц = РодительскаяСтруктураТипа.ДержательМетаданных;
						Если Истина
							И ТипЗнч(МенеджерВременныхТаблиц) = Тип("Структура") 
							//И МенеджерВременныхТаблиц.Тип = Тип("МенеджерВременныхТаблиц")
							//И МенеджерВременныхТаблиц.Активен 
						Тогда
							СтруктураТипа = СтруктураТипаИзКонкретногоТипа(Тип("МенеджерВременныхТаблиц"));
							СтруктураТипа.Метаданные = МенеджерВременныхТаблиц;
							ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
							Продолжить;
						Иначе 
							СтруктураТипа.Метаданные = Неопределено;
						КонецЕсли;
					ИначеЕсли Истина
						И РодительскаяСтруктураТипа.ИмяОбщегоТипа = "Массив[РезультатЗапроса]"
						И СтрокаСлова.ТипСлова = "Метод"
						И ТипЗнч(МетаданныеРодителя) = Тип("ПостроительЗапроса")
						И (Ложь
							Или СтрокаСлова.Слово = "Количество"
							Или СтрокаСлова.Слово = "ВГраница")
					Тогда
						КоличествоЗапросов = РазбитьГрубоТекстПакетногоЗапросаНаЗапросы(МетаданныеРодителя.Текст).Количество(); 
						Если СтрокаСлова.Слово = "Количество" Тогда 
							СтруктураТипа.Метаданные = КоличествоЗапросов;
						Иначе
							СтруктураТипа.Метаданные = КоличествоЗапросов - 1;
						КонецЕсли;
						ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
						Прервать;
					ИначеЕсли Истина
						И СтрокаСлова.Слово = "ИсходныйКлючЗаписи"
						//И ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыСтруктура") // Такое условие будет часто не давать срабатывать ветке и потому это редко полезное свойство будет неоправданно добавляться
					Тогда
						ЛиДобавляемСлово = Истина
							И ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыСтруктура")
							И ЗначениеСвойства <> Неопределено;
						Если ЛиДобавляемСлово Тогда
							СтруктураТипа = СтруктураТипаИзЗначения(ЗначениеСвойства, СтруктураТипа);
						КонецЕсли;
						Прервать;
					ИначеЕсли Ложь
						Или СтрокаСлова.Слово = "ЭтотОбъект"
						Или СтрокаСлова.Слово = "ЭтаФорма"
					Тогда
						ЛиДобавляемСлово = Истина;
						СтруктураТипа = РодительскаяСтруктураТипа;
						Прервать;

					#Если Клиент Тогда
					ИначеЕсли Ложь
						Или (Истина
							И СтрокаСлова.ТипСлова = "Метод"
							И СтрокаСлова.Слово = "ДанныеСтроки"
							И (Ложь
								Или ТипЗнч(МетаданныеРодителя) = Тип("ТаблицаФормы")
								Или ТипЗнч(МетаданныеРодителя) = Тип("ТабличноеПоле")
								Или ТипЗнч(МетаданныеРодителя) = Тип("Структура") И МетаданныеРодителя.Тип = Тип("ТаблицаФормы"))) 
						Или (Истина      
							И СтрокаСлова.ТипСлова = "Свойство"
							И (Ложь
								Или (Истина
									И (Ложь
										Или СтрокаСлова.Слово = "ТекущиеДанные"
										Или СтрокаСлова.Слово = "ОформленияЯчеекДинамическогоСписка")
									И (Ложь
										Или ТипЗнч(МетаданныеРодителя) = Тип("ТаблицаФормы") 
										Или ТипЗнч(МетаданныеРодителя) = Тип("Структура") И МетаданныеРодителя.Тип = Тип("ТаблицаФормы")))
								Или (Истина
									И ТипЗнч(МетаданныеРодителя) = Тип("ТабличноеПоле") 
									И (Ложь
										Или СтрокаСлова.Слово = "ДанныеСтроки"
										Или СтрокаСлова.Слово = "ТекущаяСтрока"
										Или СтрокаСлова.Слово = "ТекущиеДанные"))))
					Тогда 
						ИмяРеквизитаФормы = "";
						Форма = РодительскаяСтруктураТипа.ДержательМетаданных;
						ДанныеЭлементаФормы = ирОбщий.ДанныеЭлементаФормыЛкс(МетаданныеРодителя, ИмяРеквизитаФормы, Форма);
						НоваяТаблицаТипов = Неопределено;
						Если ДанныеЭлементаФормы <> Неопределено Тогда
							Если Форма = Неопределено Тогда
								Форма = ирОбщий.РодительЭлементаУправляемойФормыЛкс(МетаданныеРодителя);
							КонецЕсли;
							Если ТипЗнч(ДанныеЭлементаФормы) = Тип("НастройкиКомпоновкиДанных") Тогда
								НоваяТаблицаТипов = ТаблицаТиповЭлементовКоллекции(СтруктураТипаИзЗначения(ДанныеЭлементаФормы.Структура));
							ИначеЕсли ирОбщий.ЛиКоллекцияКомпоновкиЛкс(ДанныеЭлементаФормы) Тогда 
								НоваяТаблицаТипов = ТаблицаТиповЭлементовКоллекции(СтруктураТипаИзЗначения(ДанныеЭлементаФормы.Элементы));
							ИначеЕсли ТипЗнч(ДанныеЭлементаФормы) = Тип("ДинамическийСписок") Тогда
								Если СтрокаСлова.ТипЗначения <> "Произвольный" Тогда
									//СтруктураТипа = НоваяСтруктураТипа("ДанныеФормыСтруктура");
									СтруктураТипа.Метаданные = ИменаРеквизитовФормы(Форма, ИмяРеквизитаФормы, Истина).Все; 
								КонецЕсли;
							Иначе
								НоваяТаблицаТипов = ТаблицаТиповЭлементовКоллекции(СтруктураТипаИзЗначения(ДанныеЭлементаФормы));
								Если НоваяТаблицаТипов.Количество() = 0 Тогда                           
									// Деревья
									#Если Клиент Тогда
									ТаблицаЗначений = ирКлиент.ТаблицаИлиДеревоЗначенийИзТаблицыФормыСКоллекциейЛкс(МетаданныеРодителя, Новый Массив);
									Если ТаблицаЗначений <> Неопределено Тогда
										НоваяТаблицаТипов = ТаблицаТиповЭлементовКоллекции(СтруктураТипаИзЗначения(ТаблицаЗначений));
										НоваяТаблицаТипов[0].ИмяОбщегоТипа = "СтрокаДереваЗначений";
									КонецЕсли;
									#КонецЕсли
								КонецЕсли;
							КонецЕсли;
						ИначеЕсли ТипЗнч(МетаданныеРодителя) = Тип("Структура") Тогда 
							ОписаниеТипов = МетаданныеРодителя.ОписаниеТипов; //ОписаниеТипов
							Если ОписаниеТипов <> Неопределено Тогда
								Если ОписаниеТипов.СодержитТип(Тип("ДинамическийСписок")) Тогда 
									Если СтрокаСлова.ТипЗначения <> "Произвольный" Тогда 
										//СтруктураТипа = НоваяСтруктураТипа("ДанныеФормыСтруктура");
										СтруктураТипа.Метаданные = ИменаРеквизитовФормы(Форма, ИмяРеквизитаФормы, Истина).Все; 
									КонецЕсли;
								Иначе
									ТаблицаТиповКоллекции = ТаблицаТиповИзОписанияТипов(ОписаниеТипов);
									НоваяТаблицаТипов = ТаблицаТиповЭлементовКоллекции(ТаблицаТиповКоллекции[0]);
								КонецЕсли;
							Иначе
								СтруктураТипа.Метаданные = Неопределено;
							КонецЕсли;
						КонецЕсли; 
						Если НоваяТаблицаТипов <> Неопределено Тогда
							НоваяТаблицаТипов.ЗаполнитьЗначения(СтрокаСлова, "СтрокаОписания");
							Если Форма <> Неопределено Тогда
								НоваяТаблицаТипов.ЗаполнитьЗначения(Форма, "ДержательМетаданных");
							КонецЕсли;
							ТаблицаТипов = НоваяТаблицаТипов;
							Прервать; 
						КонецЕсли;
					#КонецЕсли
					
					ИначеЕсли Истина 
						// Опасно широкое условие. Не подходит для Соответствие
						И КорневойТипРодителя = Неопределено
						И СтрокаСлова.ТипСлова = "Метод"
						И СтрокаСлова.Слово = "Получить"
						И СтрокаСлова.ТипЗначения = "Произвольный"
						И ТипЗнч(МетаданныеРодителя) <> Тип("ПостроительЗапроса")
					Тогда
						ТаблицаТипов = ТаблицаТиповЭлементовКоллекции(РодительскаяСтруктураТипа,, ЯзыкПрограммы);
						Прервать;
					КонецЕсли;
					
					Если КорневойТипРодителя <> Неопределено Тогда 
						ДоступноеПолеСлова = Неопределено;
						Если ПостроительЗапросаРодителя <> Неопределено Тогда
							ДоступноеПолеСлова = ПостроительЗапросаРодителя.ДоступныеПоля.Найти(НРег(СтрокаСлова.Слово));
						КонецЕсли;
						// Частные случаи
						Если Истина
							И ПостроительЗапросаРодителя <> Неопределено
							И (Ложь
								Или СтрокаСлова.ТипСлова = "Поле"
								Или СтрокаСлова.Слово = "Активность"
								Или СтрокаСлова.Слово = "Владелец"
								Или СтрокаСлова.Слово = "ВидДвижения"
								Или СтрокаСлова.Слово = "Код"
								Или СтрокаСлова.Слово = "МоментВремени"
								Или СтрокаСлова.Слово = "НомерСтроки"
								Или СтрокаСлова.Слово = "Период"
								Или СтрокаСлова.Слово = "Регистратор"
								//Или СтрокаСлова.Слово = "СубконтоДт" // Закомментировано 14.04.2012
								//Или СтрокаСлова.Слово = "СубконтоКт" // Закомментировано 14.04.2012
								Или СтрокаСлова.Слово = "СчетДт"
								Или СтрокаСлова.Слово = "СчетКт"   
								Или ЛиТипСКвалификаторами И ДоступноеПолеСлова <> Неопределено)
						Тогда
							Если ДоступноеПолеСлова = Неопределено Тогда
								ЛиДобавляемСлово = Ложь;
							Иначе
								ОписаниеТиповСлова = ДоступноеПолеСлова.ТипЗначения;
								// Мультиметка73777324
								Для Каждого ТипЗначенияСлова Из ОписаниеТиповСлова.Типы() Цикл
									ШаблонСтруктурыТипа = Новый Структура("СтрокаОписания, ТипЯзыка, Квалификаторы");
									ШаблонСтруктурыТипа.СтрокаОписания = СтрокаСлова;
									ШаблонСтруктурыТипа.Квалификаторы = ОписаниеТиповСлова;
									ЗаполнитьЗначенияСвойств(ШаблонСтруктурыТипа, РодительскаяСтруктураТипа, "ТипЯзыка");
									СтруктураТипа = СтруктураТипаИзКонкретногоТипа(ТипЗначенияСлова, ЯзыкПрограммы, ШаблонСтруктурыТипа);
									ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
								КонецЦикла;
							КонецЕсли;
							Прервать;
						ИначеЕсли Ложь
							Или (Истина
								И ИмяОбщегоТипаРодителяБезДеталей = "КонстантаМенеджер.<Имя константы>" 
								И СтрокаСлова.Слово = "Получить")
							Или (Истина
								И ИмяОбщегоТипаРодителяБезДеталей = "КонстантаМенеджерЗначения.<Имя константы>" 
								И СтрокаСлова.Слово = "Значение")
						Тогда
							ОписаниеТиповСлова = МетаданныеРодителя.Тип;
							// Мультиметка73777324
							Для Каждого ТипЗначенияСлова Из ОписаниеТиповСлова.Типы() Цикл
								ШаблонСтруктурыТипа = Новый Структура("СтрокаОписания, ТипЯзыка, Квалификаторы");
								ШаблонСтруктурыТипа.СтрокаОписания = СтрокаСлова;
								ШаблонСтруктурыТипа.Квалификаторы = ОписаниеТиповСлова;
								ЗаполнитьЗначенияСвойств(ШаблонСтруктурыТипа, РодительскаяСтруктураТипа, "ТипЯзыка");
								СтруктураТипа = СтруктураТипаИзКонкретногоТипа(ТипЗначенияСлова, ЯзыкПрограммы, ШаблонСтруктурыТипа);
								ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
							КонецЦикла;
						ИначеЕсли Истина
							И СтрокаСлова.ТипСлова = "Метод"
							И (Ложь
								Или СтрокаСлова.Слово = "Выгрузить"
								Или СтрокаСлова.Слово = "ВыгрузитьКолонки")
							И ТипЗнч(СтрокаОбщегоТипа.Метаданные) = Тип("ОбъектМетаданных")
						Тогда 
							КонкретныйТип = ИмяТипаИзСтруктурыТипа(СтрокаОбщегоТипа);
							Образователь = Неопределено;
							Если НРег(КонкретныйТип) = Нрег("ТабличнаяЧасть") Тогда
								МассивФрагментов = ирОбщий.СтрРазделитьЛкс(СтрокаОбщегоТипа.Метаданные.ПолноеИмя()); 
								Если МассивФрагментов[1] = Метаданные().Имя Тогда 
									Если Метаданные().ТабличныеЧасти.Найти(МассивФрагментов[3]) <> Неопределено Тогда
										Образователь = ЭтотОбъект[МассивФрагментов[3]];
									КонецЕсли;
								ИначеЕсли Ложь
									Или МассивФрагментов[0] = "Обработка"
									Или МассивФрагментов[0] = "Отчет"
								Тогда
									Образователь = Новый (МассивФрагментов[0] + "Объект." + МассивФрагментов[1]); // Опасно. Можно быть долго. Могут быть ошибки на толстом клиенте.
									Образователь = Образователь[МассивФрагментов[3]];
								Иначе
									СтруктураОбъекта = ирОбщий.ОбъектБДПоКлючуЛкс(МассивФрагментов[0] + "." + МассивФрагментов[1]);
									Образователь = СтруктураОбъекта.Данные[МассивФрагментов[3]]; 
								КонецЕсли; 
							ИначеЕсли НРег(СтрокаОбщегоТипа.ИмяОбщегоТипа) = Нрег("ПланСчетовВидыСубконто.<Имя плана счетов>") Тогда
								МассивФрагментов = ирОбщий.СтрРазделитьЛкс(СтрокаОбщегоТипа.Метаданные.ПолноеИмя());
								СтруктураОбъекта = ирОбщий.ОбъектБДПоКлючуЛкс(МассивФрагментов[0] + "." + МассивФрагментов[1]);
								РеквизитыСчета = СтруктураОбъекта.Данные; // ПланСчетовОбъект
								Образователь = РеквизитыСчета.ВидыСубконто;
							ИначеЕсли Ложь
								Или НРег(СтрокаОбщегоТипа.ИмяОбщегоТипа) = Нрег("ВытесняющиеВидыРасчета.<Имя плана видов расчета>")
								Или НРег(СтрокаОбщегоТипа.ИмяОбщегоТипа) = Нрег("БазовыеВидыРасчета.<Имя плана видов расчета>")
								Или НРег(СтрокаОбщегоТипа.ИмяОбщегоТипа) = Нрег("ВедущиеВидыРасчета.<Имя плана видов расчета>")
							Тогда
								МассивФрагментов = ирОбщий.СтрРазделитьЛкс(СтрокаОбщегоТипа.Метаданные.ПолноеИмя());
								СтруктураОбъекта = ирОбщий.ОбъектБДПоКлючуЛкс(МассивФрагментов[0] + "." + МассивФрагментов[1]);
								ИмяТЧ = ирОбщий.ПервыйФрагментЛкс(СтрокаОбщегоТипа.ИмяОбщегоТипа);
								Попытка
									Образователь = СтруктураОбъекта.Данные[ИмяТЧ];
								Исключение
								КонецПопытки; 
							ИначеЕсли Найти(КонкретныйТип, "<") = 0 Тогда
								СтруктураОбъекта = ирОбщий.ОбъектБДПоКлючуЛкс(ирКэш.ИмяТаблицыИзМетаданныхЛкс(СтрокаОбщегоТипа.Метаданные.ПолноеИмя()));
								Образователь = СтруктураОбъекта.Данные; 
							КонецЕсли;
							Если Образователь <> Неопределено Тогда
								Если ТипЗнч(Образователь) <> Тип("ТаблицаЗначений") Тогда
									//! Образователь = 0; // ТабличнаяЧасть
									Образователь = Образователь.ВыгрузитьКолонки();
								КонецЕсли;
								СтруктураТипа.Метаданные = Образователь;
							КонецЕсли; 
						ИначеЕсли Истина
							И (Ложь
								Или СтрокаСлова.Слово = "СрезПервых"
								Или СтрокаСлова.Слово = "СрезПоследних")
							И КорневойТипРодителя = "РегистрСведений"
							И МетаданныеРодителя.ПериодичностьРегистраСведений = мМетаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический
						Тогда
							ЛиДобавляемСлово = Ложь;
							Прервать;
						ИначеЕсли Истина
							И (Ложь
								Или СтрокаСлова.Слово = "Остатки"
								Или СтрокаСлова.Слово = "ОстаткиИОбороты")
							И КорневойТипРодителя = "РегистрНакопления"
							И МетаданныеРодителя.ВидРегистра = мМетаданные.СвойстваОбъектов.ВидРегистраНакопления.Обороты
						Тогда
							ЛиДобавляемСлово = Ложь;
							Прервать;
						ИначеЕсли Истина
							И (Ложь
								Или СтрокаСлова.Слово = "ОборотыДтКт")
							И КорневойТипРодителя = "РегистрБухгалтерии"
							И Не МетаданныеРодителя.Корреспонденция
						Тогда
							ЛиДобавляемСлово = Ложь;
							Прервать;
						Иначе
							ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
						КонецЕсли;
					ИначеЕсли Истина
						И СтрокаСлова.Слово = "Выполнить"
						И СтрокаСлова.ТипСлова = "Метод"
						И ТипЗнч(МетаданныеРодителя) = Тип("Запрос")
					Тогда 
						ПостроительЗапроса = ПостроительЗапросаИзТекстаДляТипа(МетаданныеРодителя.Текст);
						СтруктураТипа.Метаданные = ПостроительЗапроса;
						ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа, Ложь);
					ИначеЕсли Истина
						И СтрокаСлова.Слово = "Выгрузить"
						И СтрокаСлова.ТипСлова = "Метод"
						И (Ложь
							Или ТипЗнч(МетаданныеРодителя) = Тип("Запрос")
							Или ТипЗнч(МетаданныеРодителя) = Тип("ПостроительЗапроса"))
					Тогда 
						ПостроительЗапроса = МетаданныеРодителя;
						Если ТипЗнч(ПостроительЗапроса) = Тип("Запрос") Тогда 
							ПостроительЗапроса = ПостроительЗапросаИзТекстаДляТипа(ПостроительЗапроса.Текст);
						КонецЕсли;
						ПодготовитьМетаданныеПостроителяЗапроса(ПостроительЗапроса, РодительскаяСтруктураТипа.ДержательМетаданных);
						СтруктураТипа.Метаданные = ПустаяТаблицаЗначенийИзПостроителя(ПостроительЗапроса);
						ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа, Ложь);
					ИначеЕсли Истина
						И СтрокаСлова.Слово = "Выгрузить"
						И СтрокаСлова.ТипСлова = "Метод"
						И (Ложь
							Или ТипЗнч(СтрокаОбщегоТипа.Метаданные) = Тип("ДанныеФормыКоллекция")
							Или ТипЗнч(СтрокаОбщегоТипа.Метаданные) = Тип("ДанныеФормыСтруктураСКоллекцией"))
					Тогда
						#Если Клиент Тогда
						ТаблицаЗначений = Новый ТаблицаЗначений;
						Для Каждого КлючИЗначение Из ДочерниеСвойстваДанныхФормы(МетаданныеРодителя,, РодительскаяСтруктураТипа.ДержательМетаданных, Слово) Цикл
							ТаблицаЗначений.Колонки.Добавить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
						КонецЦикла;
						СтруктураТипа.Метаданные = ТаблицаЗначений;
						ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа, Ложь);
						#КонецЕсли
					ИначеЕсли Истина
						И СтрокаСлова.Слово = "Значение"
						И СтрокаСлова.ТипСлова = "Свойство"
						И ТипЗнч(СтрокаОбщегоТипа.Метаданные) = Тип("СписокЗначений")
						И СтрокаОбщегоТипа.Метаданные.ТипЗначения.Типы().Количество() = 1
					Тогда 
						СтруктураТипа = СтруктураТипаИзКонкретногоТипа(СтрокаОбщегоТипа.Метаданные.ТипЗначения.Типы()[0]);
						ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа, Ложь);
					Иначе
						Если Истина
							И ИмяОбщегоТипаСлова = "Форма" // TODO возможно нужно заменить на ирОбщий.ЛиИмяТипаФормыЛкс()
							И СтрокаСлова.Слово = "ЭтаФорма"
						Тогда
							ДобавитьВТаблицуТипов(ТаблицаТипов, РодительскаяСтруктураТипа, Истина);
						Иначе
							ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа, Ложь);
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
				Если Не ЛиДобавляемСлово Тогда
					Продолжить;
				КонецЕсли;
				Если ТаблицаТипов.Количество() = 0 Тогда
					ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
				КонецЕсли;
			КонецЕсли; 
			ТипЗначения = СтрокаСлова.ТипЗначения;
			Если ЛиТипСКвалификаторами Или МожноУточнитьТип Тогда
				ТипЗначения = "??," + ТипЗначения;
			КонецЕсли;
			ДобавитьВТаблицуСлов(ТаблицаСлов, СтрокаСлова.Слово, СтрокаСлова.ТипСлова, ТаблицаТипов, ТипЗначения, "Предопределенный");
		КонецЦикла;
		Если ИспользоватьКэширование И Не ЛиКэшАгрегатный Тогда
			СтруктураТипаГлобальный = НоваяСтруктураТипа("Глобальный");
			СтруктураТипаГлобальный.Метаданные = Метаданные;
			СтруктураТипаГлобальный.Конструктор = РодительскаяСтруктураТипа.Конструктор;
			СтруктураТипаГлобальный.ТипЯзыка = РодительскаяСтруктураТипа.ТипЯзыка;
			СловаКонтекстаМетаданные(СтруктураТипаГлобальный,, ТипСлова,, ЯзыкПрограммы,,, ВычислятьТипы, ФлагиКомпиляции,, ТаблицаСлов,,,, БазовоеРасширениеКонфигурации);
			ДобавитьТаблицуСловВГлобальныйКэш(ТаблицаСлов, КлючКэширования, НаборыСлов);
		КонецЕсли; 
	КонецЦикла;
	Если ИспользоватьКэширование И ЛиКэшАгрегатный Тогда
		ДобавитьТаблицуСловВГлобальныйКэш(ТаблицаСлов, КлючКэширования, НаборыСлов);
	КонецЕсли;
	Возврат ТаблицаСлов;

КонецФункции

//.
// Параметры:
//    ТаблицаСлов - ТаблицаЗначений - 
//    КлючКэширования - Строка - 
//    НаборыСлов -  - 
Процедура ДобавитьТаблицуСловВГлобальныйКэш(Знач ТаблицаСлов, Знач КлючКэширования, Знач НаборыСлов) Экспорт
	ТаблицаСловИзКэша = ТаблицаСлов.Скопировать();
	мКэшСловГлобальногоКонтекста[КлючКэширования] = ТаблицаСловИзКэша;
	Если НаборыСлов <> Неопределено Тогда
		НаборыСлов.Вставить(КлючКэширования, ТаблицаСловИзКэша);
		ТаблицаСлов.Очистить();
	КонецЕсли;
КонецПроцедуры

//.
// Параметры:
//    ПостроительЗапроса - ПостроительЗапроса - 
// Возвращаемое значение:
//    ТаблицаЗначений, Неопределено - 
Функция ПустаяТаблицаЗначенийИзПостроителя(Знач ПостроительЗапроса) Экспорт
	ТаблицаЗначений = Новый ТаблицаЗначений;
	Для Каждого ВыбранноеПоле Из ПостроительЗапроса.ВыбранныеПоля Цикл
		ТаблицаЗначений.Колонки.Добавить(ВыбранноеПоле.Имя, ПостроительЗапроса.ДоступныеПоля[ВыбранноеПоле.Имя].ТипЗначения);
	КонецЦикла;
	Возврат ТаблицаЗначений;
КонецФункции

// Получает внутреннюю таблицу метаданных слов заданного родительского типа.
//
// Параметры:
//  РодительскаяСтруктураТипа		 - 	 - Структура;
//  Слово							 - 	 - Строка, *Неопределено - для отбора;
//  ТипСлова						 - 	 - Строка, *Неопределено - для отбора;
//  ВнутриГруппыОбщихМодулей - Булево - ;
//  ЯзыкПрограммы					 - 	 - *Число, 0;
//  ТекущийИндекс					 - Строка	 - выражение в квадратных скобках.
//  ВнешниеФункцииКомпоновкиДанных	 - 			 - 
//  ВычислятьТипы					 - 			 - 
//  ФлагиКомпиляции					 - см. НовыеФлагиКомпиляции() - 
//  МодульМетаданныхДинамический	 - 			 - 
//  ТаблицаСлов						 - 			 - 
//  ВычислятьТипыМетодовМодулей		 - Булево, Неопределено - 
//  ЭтоЛокальныйКонтекст			 - Булево - 
//  БазовоеРасширениеКонфигурации    - Строка - "" - основная конфигурация, "*" - все расширения
// 
// Возвращаемое значение:
//  ТаблицаЗначений - с колонками "Слово", "ТипСлова", "ТаблицаТипов".
//
Функция СловаКонтекстаМетаданные(Знач РодительскаяСтруктураТипа, Знач Слово = Неопределено, Знач ТипСлова = Неопределено, Знач ВнутриГруппыОбщихМодулей = Ложь, Знач ЯзыкПрограммы = 0,
	Знач ТекущийИндекс = Неопределено, Знач ВнешниеФункцииКомпоновкиДанных = Истина, Знач ВычислятьТипы = Истина, Знач ФлагиКомпиляции = Неопределено, Знач МодульМетаданныхДинамический = Неопределено,
	Знач ТаблицаСлов = Неопределено, Знач ВычислятьТипыМетодовМодулей = Неопределено, Знач ЭтоЛокальныйКонтекст = Ложь, Знач ЛиВместеСЛокальнымКонтекстом = Ложь, Знач БазовоеРасширениеКонфигурации = "",
	Знач ДляСвойства = "") Экспорт 
	
	Если ТаблицаСлов = Неопределено Тогда
		ТаблицаСлов = НоваяТаблицаСлов();
	КонецЕсли;
	Если Ложь           
		Или ТипСлова = "Конструктор"
		Или РодительскаяСтруктураТипа.Конструктор
		Или Не ЗначениеЗаполнено(РодительскаяСтруктураТипа.ИмяОбщегоТипа) // родительский контекст является процедурой
		Или РодительскаяСтруктураТипа.ИмяОбщегоТипа = "Произвольный"
		Или РодительскаяСтруктураТипа.ИмяОбщегоТипа = "Неопределено"
	Тогда
		Возврат ТаблицаСлов;
	КонецЕсли;
	
	// Мультиметка3398476724
	ЛиСеансТолстогоКлиентаУП = ирКэш.ЛиСеансТолстогоКлиентаУПЛкс();
	НаСервере = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "Сервер", Истина);
	КлиентОбычноеПриложение = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "КлиентОбычноеПриложение", Не ЛиСеансТолстогоКлиентаУП);
	КлиентУправляемоеПриложение = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "КлиентУправляемоеПриложение", ЛиСеансТолстогоКлиентаУП);
	
	БезКонтекста = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "БезКонтекста", ЛиСеансТолстогоКлиентаУП);
	ПредставлениеМетаданных = ирОбщий.ПредставлениеЗначенияЛкс(РодительскаяСтруктураТипа.Метаданные);
	ЭтоМетаданныеТабличнойЧастиВнешнейОбработки = ирОбщий.ПервыйФрагментЛкс(ПредставлениеМетаданных) = "ВнешняяОбработкаТабличнаяЧасть";
	Если Не ирОбщий.СтрНачинаетсяСЛкс(ПредставлениеМетаданных, "Внешн") Тогда
		КонкретныйТип = ИмяТипаИзСтруктурыТипа(РодительскаяСтруктураТипа);
		Если Найти(ирОбщий.ПервыйФрагментЛкс(КонкретныйТип, "["), "<") > 0 Тогда
			// Такой конкретный тип не разрешен
			Возврат ТаблицаСлов;
		КонецЕсли;
	КонецЕсли;
	ЛиВместеСЛокальнымКонтекстом = ЛиВместеСЛокальнымКонтекстом Или ЭтоЛокальныйКонтекст;
	Если ВычислятьТипыМетодовМодулей = Неопределено Тогда
		ВычислятьТипыМетодовМодулей = Слово <> Неопределено;
	КонецЕсли;
	Если Слово <> Неопределено И ТекущийИндекс <> Неопределено Тогда 
		Если Ложь
			Или РодительскаяСтруктураТипа.ИмяОбщегоТипа = "Соответствие"
			Или РодительскаяСтруктураТипа.ИмяОбщегоТипа = "ФиксированноеСоответствие"
		Тогда 
			Если Истина
				И ТипЗнч(РодительскаяСтруктураТипа.Метаданные) = Тип("Структура") 
				И РодительскаяСтруктураТипа.Метаданные.Значение <> Неопределено  
			Тогда
				ТаблицаТипов = ДобавитьВТаблицуТипов(, РодительскаяСтруктураТипа.Метаданные.Значение);
				ДобавитьВТаблицуСлов(ТаблицаСлов, "*", "Свойство", ТаблицаТипов,, "Метаданные1");
				Возврат ТаблицаСлов;
			КонецЕсли;
		Иначе
			ЛиИндексИдентификатор = Ложь;
			RegExp.Pattern = "^""(" + шИмя + ")""$";
			РезультатСтроковойКонстанты = RegExp.НайтиВхождения(Слово);
			Если РезультатСтроковойКонстанты.Количество() > 0 Тогда
				Слово = РезультатСтроковойКонстанты[0].SubMatches(0);
				ЛиИндексИдентификатор = Истина;
			КонецЕсли;
			Если Ложь
				Или РодительскаяСтруктураТипа.ИмяОбщегоТипа = "Структура" 
				Или РодительскаяСтруктураТипа.ИмяОбщегоТипа = "ФиксированнаяСтруктура"
			Тогда         
				// у них значениями именованных свойств являются произвольные типы
			Иначе 
				Если Не ЛиИндексИдентификатор Тогда
					ТаблицаТипов = ТаблицаТиповЭлементовКоллекции(РодительскаяСтруктураТипа, Слово, ЯзыкПрограммы);
					ДобавитьВТаблицуСлов(ТаблицаСлов, "*", "Свойство", ТаблицаТипов,, "Метаданные1");
					Возврат ТаблицаСлов;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	ЭтоГруппаОбщихМодулей = Ложь; 
	ПолноеИмяПодсистемыИР = ирОбщий.ИмяПродуктаЛкс();
	МаксЧислоТиповДляАнализа = МаксЧислоТиповДляАнализа();
	ТаблицаОбщихТиповСтруктурыТипа = ТаблицаОбщихТиповИзСтруктурыТипа(РодительскаяСтруктураТипа, ЭтоЛокальныйКонтекст, Ложь);
	НомерВерсииПлатформы = ирКэш.НомерВерсииПлатформыЛкс();    
	ЕдинственнаяСтрокаВида = Неопределено;
	Для Каждого СтрокаОбщегоТипа Из ТаблицаОбщихТиповСтруктурыТипа Цикл
		ИмяОбщегоТипаРодителя = СтрокаОбщегоТипа.ИмяОбщегоТипа;
		Если Истина
			И ИмяОбщегоТипаРодителя = "Глобальный"
			И РодительскаяСтруктураТипа.ИмяОбщегоТипа <> "Глобальный" // пропускаем вызов для заполнения кэша
			И Слово = Неопределено 
			И ТекущийИндекс = Неопределено
		Тогда
			// Подразумеваем, что в ТаблицаСлов уже помещен кэш Предопределенные+Метаданные
			Продолжить;
		КонецЕсли;
		Если ирОбщий.СтрокиРавныЛкс(ИмяОбщегоТипаРодителя, "ISWbemObject {WbemScripting.SwbemLocator}") Тогда
			Если ТипЗнч(СтрокаОбщегоТипа.Метаданные) = Тип("COMОбъект") Тогда
				СтруктураЦикла = Новый Структура();
				Попытка
					СтруктураЦикла.Вставить("Свойство", СтрокаОбщегоТипа.Метаданные.Properties_);
					СтруктураЦикла.Вставить("Метод", СтрокаОбщегоТипа.Метаданные.Methods_);
				Исключение
				КонецПопытки;
				Для Каждого КлючИЗначение Из СтруктураЦикла Цикл
					КоллекцияСвойств = КлючИЗначение.Значение;
					ТипСловаЧленаКласса = КлючИЗначение.Ключ;
					Если Истина
						И ТипСлова <> Неопределено
						И Не ирОбщий.СтрокиРавныЛкс(ТипСловаЧленаКласса, ТипСлова)
					Тогда
						Продолжить;
					КонецЕсли; 
					Для Каждого Свойство Из КоллекцияСвойств Цикл
						ИмяСвойства = Свойство.Name;
						Если Истина
							И Слово <> Неопределено 
							И Не ирОбщий.СтрокиРавныЛкс(ИмяСвойства, Слово)
						Тогда
							Продолжить;
						КонецЕсли;
						ТаблицаТипов = НоваяТаблицаТипов();
						СтруктураТипа = ТаблицаТипов.Добавить();
						СтруктураТипа.СтрокаОписания = Свойство;
						СтруктураТипа.ИмяОбщегоТипа  = ирОбщий.ИмяТипаИзКвалификаторовWMIЛкс(Свойство);
						СтруктураТипа.Метаданные = РодительскаяСтруктураТипа.Метаданные;
						ДобавитьВТаблицуСлов(ТаблицаСлов, ИмяСвойства, ТипСловаЧленаКласса, ТаблицаТипов,, "Метаданные");
					КонецЦикла;
				КонецЦикла; 
			КонецЕсли; 
		КонецЕсли;
		МетаданныеРодителя = СтрокаОбщегоТипа.Метаданные; 
		Если Ложь
			Или ИмяОбщегоТипаРодителя = "Локальный"
			Или (Истина
				И ИмяОбщегоТипаРодителя <> "Глобальный"
				И ФлагиКомпиляции <> Неопределено 
				И ФлагиКомпиляции.БезКонтекста 
				И ЭтоЛокальныйКонтекст)
		Тогда
			НайденныеСтроки = Новый Массив;
		Иначе 
			КорневойТипРодителя = Неопределено;
			ПостроительЗапросаРодителя = Неопределено;
			Если РодительскаяСтруктураТипа.ТипЯзыка <> "ИмяТипа" Тогда 
				ТипМетаданныхРодителя = ТипЗнч(МетаданныеРодителя);
				Если Ложь 
					Или ТипМетаданныхРодителя = Тип("ОбъектМетаданных")
					Или (Истина
						И ЭтоИнтеграция
						И (Ложь
							Или ТипМетаданныхРодителя = Тип("СправочникСсылка.МетаданныеИис")
							Или ТипМетаданныхРодителя = Тип("СправочникСсылка.СвойстваМетаданныхИис")))
				Тогда
					Если ТипМетаданныхРодителя = Тип("ОбъектМетаданных") Тогда
						КорневойТипРодителя = ирОбщий.КорневойТипКонфигурацииЛкс(МетаданныеРодителя);
					Иначе
						КорневойТипРодителя = ирОбщий.КорневойТипКонфигурацииЛкс(КэшОбъект(МетаданныеРодителя).ПолноеИмя);
					КонецЕсли; 
					ПостроительЗапросаРодителя = ПостроительЗапросаПоСтруктуреТипа(СтрокаОбщегоТипа, РодительскаяСтруктураТипа.ВиртуальнаяТаблица);
				КонецЕсли;
			КонецЕсли;
			Если Истина
				И ЯзыкПрограммы = 2
				И ИмяОбщегоТипаРодителя = "Глобальный"
				И ВнешниеФункцииКомпоновкиДанных
			Тогда
				СтруктураКлюча = Новый Структура("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка, НСлово", ИмяОбщегоТипаРодителя, 0, РодительскаяСтруктураТипа.ТипЯзыка, НРег("<Имя общего модуля>"));
			Иначе
				СтруктураКлюча = Новый Структура("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка", ИмяОбщегоТипаРодителя, ЯзыкПрограммы, РодительскаяСтруктураТипа.ТипЯзыка);
			КонецЕсли;
			Если ТипСлова <> Неопределено Тогда
				СтруктураКлюча.Вставить("ТипСлова", ТипСлова);
			КонецЕсли;
			НайденныеСтроки = ТаблицаШаблоновКонтекстов.НайтиСтроки(СтруктураКлюча);
		КонецЕсли;
		ПредыдущаяСтрокаВида = Неопределено; // Для регистра бухгалтерии
		Для Каждого СтрокаВида Из НайденныеСтроки Цикл
			Если Ложь
				Или (Истина
					И ПредыдущаяСтрокаВида <> Неопределено
					И ПредыдущаяСтрокаВида.НСлово = СтрокаВида.НСлово 
					И ПредыдущаяСтрокаВида.ТипСлова = СтрокаВида.ТипСлова)
				Или СтрокаВида.НомерВерсииПлатформы > НомерВерсииПлатформы
				Или СтрокаВида.ТипСлова = "Событие"
			Тогда
				Продолжить;
			КонецЕсли; 
			Если ЕдинственнаяСтрокаВида = Неопределено Тогда
				ЕдинственнаяСтрокаВида = СтрокаВида;
			Иначе 
				ЕдинственнаяСтрокаВида = Null;
			КонецЕсли;
			ПредыдущаяСтрокаВида = СтрокаВида;
			ЛиТипСКвалификаторами = ирОбщий.ЛиИмяТипаСКвалификаторамиЛкс(СтрокаВида.ТипЗначения);
			СхемаКоллекции = Новый Соответствие;
			МетаданныеЭлементов = Новый Соответствие;
			КоллекцияЗначений = Неопределено;
			ИмяЭлементаКоллекции = ирОбщий.ТекстМеждуМаркерамиЛкс(СтрокаВида.Слово, "<", ">", Ложь, Истина);
			
			КлючПоиска = Новый Структура("ИмяОбщегоТипа, ИмяЭлементаКоллекции", ИмяОбщегоТипаРодителя, ИмяЭлементаКоллекции);
			СтрокаОписанияВида = Неопределено;
			НайденныеСтрокиКоллекций = ТаблицаИменЭлементовКоллекций.НайтиСтроки(КлючПоиска);
			Если НайденныеСтрокиКоллекций.Количество() > 0 Тогда
				СтрокаОписанияВида = НайденныеСтрокиКоллекций[0];
				Если НайденныеСтрокиКоллекций.Количество() > 1 Тогда
					#Если Клиент Тогда
					Если Истина
						И СтрокаОписанияВида.ИмяКоллекции = "ПодчиненныеЭлементы" 
						И ТипЗнч(РодительскаяСтруктураТипа.Метаданные) = Тип("Форма")
					Тогда 
						// Устранение неоднозначности одноименных типов "ЭлементыФормы" обычной и упрвляемой формы
						СтрокаОписанияВида = НайденныеСтрокиКоллекций[1];
					КонецЕсли;
					#КонецЕсли
				КонецЕсли;
			КонецЕсли; 
			Если СтрокаОписанияВида = Неопределено Тогда
				КлючПоиска.Удалить("ИмяОбщегоТипа");
				НайденныеСтрокиКоллекций = ТаблицаИменЭлементовКоллекций.НайтиСтроки(КлючПоиска);
				Если НайденныеСтрокиКоллекций.Количество() > 0 Тогда
					СтрокаОписанияВида = НайденныеСтрокиКоллекций[0];
				КонецЕсли; 
			КонецЕсли; 
			//// Исправление кривоты платформенной справки (неуникальные имена шаблона элемента коллекции между разными типами коллекций)
			//Если ИмяЭлементаКоллекции = "<Имя элемента управления>" Тогда
			//	СтруктураОтбора = Новый Структура("ИмяЭлементаКоллекции, ИмяКоллекции", ИмяЭлементаКоллекции);
			//	Если ИмяОбщегоТипа = "ВсеЭлементыФормы" Тогда
			//		СтруктураОтбора.ИмяКоллекции = "Элементы";
			//	Иначе//Если ИмяОбщегоТипа = "ЭлементыФормы" Тогда
			//		СтруктураОтбора.ИмяКоллекции = "ЭлементыФормы";
			//	КонецЕсли; 
			//	СтрокаОписанияВида = ТаблицаИменЭлементовКоллекций.НайтиСтроки(СтруктураОтбора)[0];
			//ИначеЕсли ИмяЭлементаКоллекции = "<Имя колонки>" Тогда
			//	СтруктураОтбора = Новый Структура("ИмяЭлементаКоллекции, ИмяКоллекции", ИмяЭлементаКоллекции);
			//	Если ИмяОбщегоТипа = "Ячейки" Тогда
			//		СтруктураОтбора.ИмяКоллекции = "ОформленияЯчеек";
			//	Иначе//Если ИмяОбщегоТипа = "СтрокаТаблицыЗначений" Тогда
			//		СтруктураОтбора.ИмяКоллекции = "Колонки";
			//	КонецЕсли; 
			//	СтрокаОписанияВида = ТаблицаИменЭлементовКоллекций.НайтиСтроки(СтруктураОтбора)[0];
			//КонецЕсли; 
			Если Слово <> Неопределено Тогда 
				МассивФрагментов = ирОбщий.СтрРазделитьЛкс(СтрокаВида.Слово, ИмяЭлементаКоллекции);
				НачалоТекущегоСлова = Лев(Слово, СтрДлина(МассивФрагментов[0]));
				КонецТекущегоСлова = Прав(Слово, СтрДлина(МассивФрагментов[1]));
				ИмяТекущегоСлова = Сред(Слово, СтрДлина(НачалоТекущегоСлова) + 1,
					СтрДлина(Слово) - СтрДлина(КонецТекущегоСлова));
				Если НачалоТекущегоСлова + ИмяЭлементаКоллекции + КонецТекущегоСлова <> СтрокаВида.Слово Тогда
					Продолжить;
				КонецЕсли;
			КонецЕсли;
			Если СтрокаОписанияВида = Неопределено Тогда
				// Имя элемента коллекции не внесено в служебную таблицу
				Продолжить;
			КонецЕсли; 
			Если Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Предопределенные"
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") //
			Тогда
				Запрос = Новый Запрос;
				Запрос.Текст = "ВЫБРАТЬ Т.Ссылка ИЗ " + МетаданныеРодителя.ПолноеИмя() + " КАК Т
				|ГДЕ Т.Предопределенный
				|";
				Результат = Запрос.Выполнить().Выгрузить();
				МенеджерТипа = ирОбщий.ПолучитьМенеджерЛкс(МетаданныеРодителя);
				Для Каждого СтрокаРезультата Из Результат Цикл
					СхемаКоллекции.Вставить(МенеджерТипа.ПолучитьИмяПредопределенного(СтрокаРезультата.Ссылка), Новый ОписаниеТипов(ирОбщий.ЗначенияВМассивЛкс(ТипЗнч(СтрокаРезультата.Ссылка))));
				КонецЦикла;
			ИначеЕсли Ложь
				Или (Истина
					И (Ложь
						Или СтрокаОписанияВида.ИмяКоллекции = "Колонки" 
						Или СтрокаОписанияВида.ИмяКоллекции = "Поля")
					И (Ложь
						Или ТипЗнч(МетаданныеРодителя) = Тип("Структура")
						Или ТипЗнч(МетаданныеРодителя) = Тип("РезультатЗапроса")
						Или ТипЗнч(МетаданныеРодителя) = Тип("ТаблицаЗначений")
						Или ТипЗнч(МетаданныеРодителя) = Тип("ДеревоЗначений")
						Или ТипЗнч(МетаданныеРодителя) = Тип("ВыборкаИзРезультатаЗапроса")
						Или ТипЗнч(МетаданныеРодителя) = Тип("СтрокаТаблицыЗначений")
						Или ТипЗнч(МетаданныеРодителя) = Тип("СтрокаДереваЗначений")
						))
				Или (Истина
					И СтрокаОписанияВида.ИмяЭлементаКоллекции = "<Имя колонки списка>" 
					И ТипЗнч(МетаданныеРодителя) = Тип("ТабличноеПоле"))
			Тогда
				Если ТипЗнч(МетаданныеРодителя) = Тип("Структура") Тогда 
					Если Ложь
						Или СтрокаВида.ТипЗначения = "КолонкаТаблицыЗначений" 
						Или СтрокаВида.ТипЗначения = "КолонкаДереваЗначений" 
					Тогда 
						СхемаКоллекции = Новый Структура;
						ОписаниеТиповКолонки = Новый ОписаниеТипов(СтрокаВида.ТипЗначения);
						Для Каждого КлючИЗначение Из МетаданныеРодителя Цикл
							СхемаКоллекции.Вставить(КлючИЗначение.Ключ, ОписаниеТиповКолонки);
						КонецЦикла;
					Иначе
						КоллекцияЗначений = МетаданныеРодителя;
					КонецЕсли;
				ИначеЕсли Найти(ИмяОбщегоТипаРодителя, "Колон") = 0 Тогда // %%%% Некрасиво, но работает
					Если СтрокаОписанияВида.ИмяЭлементаКоллекции = "<Имя колонки списка>" Тогда
						ДинамическийСписок = МетаданныеРодителя.Значение;
						ПостроительСписка = ПостроительЗапросаПоСтруктуреТипа(СтруктураТипаИзЗначения(ДинамическийСписок));
						КоллекцияКолонок = ДинамическийСписок.Колонки;
						Для Каждого Колонка Из КоллекцияКолонок Цикл
							Если Колонка.Имя = "" Тогда
								// Антибаг платформы 8.2.16
								Продолжить;
							КонецЕсли; 
							СхемаКоллекции.Вставить(Колонка.Имя, ПостроительСписка.ДоступныеПоля[Колонка.Имя].ТипЗначения);
						КонецЦикла;
					Иначе
						Если Ложь
							Или ТипЗнч(МетаданныеРодителя) = Тип("ВыборкаИзРезультатаЗапроса")
							Или ТипЗнч(МетаданныеРодителя) = Тип("СтрокаТаблицыЗначений")
							Или ТипЗнч(МетаданныеРодителя) = Тип("СтрокаДереваЗначений")
						Тогда 
							Попытка
								МетаОбъект = МетаданныеРодителя.Владелец();
							Исключение
								// Строка была удалена
								МетаОбъект = Неопределено;
							КонецПопытки; 
							Если МетаОбъект <> Неопределено Тогда
								Для Каждого Колонка Из МетаОбъект.Колонки Цикл
									Если Колонка.Имя = "" Тогда
										// Строка таблицы/дерева при перетаскивании имеет такую колонку (вероятно ошибка платформы)
										Продолжить;
									КонецЕсли; 
									СхемаКоллекции.Вставить(Колонка.Имя, МетаданныеРодителя[Колонка.Имя]);
								КонецЦикла;
							КонецЕсли;
						Иначе
							Для Каждого Колонка Из МетаданныеРодителя.Колонки Цикл
								СхемаКоллекции.Вставить(Колонка.Имя, Колонка.ТипЗначения);
							КонецЦикла;
						КонецЕсли; 
					КонецЕсли;
				Иначе
					Если Ложь
						Или ТипЗнч(МетаданныеРодителя) = Тип("ВыборкаИзРезультатаЗапроса")
						Или ТипЗнч(МетаданныеРодителя) = Тип("СтрокаТаблицыЗначений")
						Или ТипЗнч(МетаданныеРодителя) = Тип("СтрокаДереваЗначений")
					Тогда 
						КоллекцияЗначений = МетаданныеРодителя.Владелец().Колонки;
					Иначе
						КоллекцияЗначений = МетаданныеРодителя.Колонки;
					КонецЕсли; 
				КонецЕсли;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Колонки" 
				И ЭтоМетаданныеТабличнойЧастиВнешнейОбработки
			Тогда
				//! МетаданныеРодителя = 0 // ТабличнаяЧасть
				Для Каждого Колонка Из МетаданныеРодителя.ВыгрузитьКолонки().Колонки Цикл
					Если Колонка.Имя = "НомерСтроки" Тогда
						Продолжить;
					КонецЕсли; 
					СхемаКоллекции.Вставить(Колонка.Имя, Колонка.ТипЗначения);
				КонецЦикла;
			ИначеЕсли Истина
				И ТипЗнч(МетаданныеРодителя) = Тип("ПостроительЗапроса")
				И СтрокаОписанияВида.ИмяКоллекции = "Колонки"
			Тогда
				ПодготовитьМетаданныеПостроителяЗапроса(МетаданныеРодителя);
				Если СтрокаВида.ТипЗначения <> "Произвольный" Тогда
					Попытка
						ОписаниеТиповЭлемента = Новый ОписаниеТипов(СтрокаВида.ТипЗначения);
					Исключение
						ОписаниеТиповЭлемента = Неопределено;
					КонецПопытки;
				КонецЕсли;
				Для Каждого ВыбранноеПоле Из МетаданныеРодителя.ВыбранныеПоля Цикл    
					лДоступноеПоле = МетаданныеРодителя.ДоступныеПоля.Найти(ВыбранноеПоле.Имя);
					Если СтрокаВида.ТипЗначения = "Произвольный" Тогда
						ОписаниеТиповЭлемента = лДоступноеПоле.ТипЗначения;
					КонецЕсли;
					СхемаКоллекции.Вставить(ВыбранноеПоле.Имя, ОписаниеТиповЭлемента);
				КонецЦикла;
			ИначеЕсли Истина
				И ТипЗнч(МетаданныеРодителя) = Тип("ПостроительЗапроса")
				И СтрокаОписанияВида.ИмяКоллекции = "Поля" 
			Тогда
				ПодготовитьМетаданныеПостроителяЗапроса(МетаданныеРодителя);
				Для Каждого ДоступноеПоле Из МетаданныеРодителя.ДоступныеПоля Цикл
					ТипЗначения = ДоступноеПоле.ТипЗначения;
					Если Истина
						И ТипЗначения.СодержитТип(Тип("ТаблицаЗначений")) 
						И ИмяОбщегоТипаРодителя = "ВыборкаИзРезультатаЗапроса" 
					Тогда
						ТипЗначения = Новый ОписаниеТипов("РезультатЗапроса");
					КонецЕсли;
					СхемаКоллекции.Вставить(ДоступноеПоле.Имя, ТипЗначения);
				КонецЦикла;
			ИначеЕсли Истина
				И ТипЗнч(МетаданныеРодителя) = Тип("ПостроительЗапроса")
				И СтрокаОписанияВида.ИмяКоллекции = "Структура" 
			Тогда
				// Вроде бы мертвая ветка, т.к. для свойства "Параметры" всегда передается готовая структура вместо построителя
				Для Каждого КлючИЗначение Из МетаданныеРодителя.Параметры Цикл
					СхемаКоллекции.Вставить(ДоступноеПоле.Имя, ДоступноеПоле.ТипЗначения);
				КонецЦикла;
			ИначеЕсли Ложь
				Или (Истина
					И СтрокаОписанияВида.ИмяКоллекции = "Структура" 
					И ТипЗнч(МетаданныеРодителя) = Тип("Структура"))
				Или (Истина
					И СтрокаОписанияВида.ИмяКоллекции = "ФиксированнаяСтруктура" 
					И (Ложь
						Или ТипЗнч(МетаданныеРодителя) = Тип("Структура")
						Или ТипЗнч(МетаданныеРодителя) = Тип("ФиксированнаяСтруктура")))
				Или (Истина
					И СтрокаОписанияВида.ИмяКоллекции = "НастройкаОформления" 
					И ТипЗнч(МетаданныеРодителя) = Тип("НастройкаОформления"))
				Или (Истина
					И СтрокаОписанияВида.ИмяКоллекции = "Отбор" 
					И ТипЗнч(МетаданныеРодителя) = Тип("Отбор"))
			Тогда
				КоллекцияЗначений = МетаданныеРодителя;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Структура" 
				И ТипЗнч(МетаданныеРодителя) = Тип("ТаблицаЗначений")
				И ЗначениеЗаполнено(Слово)
			Тогда
				СхемаКоллекции.Вставить(Слово, МетаданныеРодителя);
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Колонки" 
				И (Ложь
					Или ТипЗнч(МетаданныеРодителя) = Тип("ДоступноеПолеКомпоновкиДанных")
					Или ТипЗнч(МетаданныеРодителя) = Тип("ДоступноеПолеОтбораКомпоновкиДанных"))
			Тогда
				Для Каждого ДоступноеПоле Из МетаданныеРодителя.Элементы Цикл
					СхемаКоллекции.Вставить(ирОбщий.ПоследнийФрагментЛкс("" + ДоступноеПоле.Поле), ДоступноеПоле.ТипЗначения);
				КонецЦикла;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "ОбщиеРеквизиты" 
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных")
			Тогда
				Попытка
					ОбщиеРеквизиты = Метаданные.ОбщиеРеквизиты;
				Исключение
					// Платформа 8.2.13 и ниже
					ОбщиеРеквизиты = Новый Массив;
				КонецПопытки; 
				СхемаКоллекции = Новый Массив();
				Для Каждого ОбщийРеквизит Из ОбщиеРеквизиты Цикл
					Если ирОбщий.ЛиОбщийРеквизитИспользуетсяВОбъектеМетаданныхЛкс(ОбщийРеквизит, МетаданныеРодителя) Тогда
						СхемаКоллекции.Добавить(ОбщийРеквизит);
					КонецЕсли; 
				КонецЦикла;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Картинки" 
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданныхКонфигурация")
			Тогда
				Если ЗначениеЗаполнено(Слово) Тогда
					МетаКартинка = Метаданные.ОбщиеКартинки.Найти(Слово);
					Если МетаКартинка <> Неопределено Тогда
						СхемаКоллекции.Вставить(МетаКартинка.Имя, МетаКартинка);
					КонецЕсли; 
				Иначе
					// Долго
					СхемаКоллекции = Новый Структура;
					Для Каждого МетаКартинка Из Метаданные.ОбщиеКартинки Цикл
						СхемаКоллекции.Вставить(МетаКартинка.Имя, МетаКартинка);
					КонецЦикла;
				КонецЕсли; 
			ИначеЕсли Истина //
				И СтрокаОписанияВида.ИмяКоллекции = "Свойства" 
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектXDTO")
			Тогда
				КоллекцияЗначений = Новый Структура;
				ОбъектXDTO = МетаданныеРодителя;
				Для Каждого Свойство Из ОбъектXDTO.Свойства() Цикл
					Если Истина
						И ЗначениеЗаполнено(Свойство.Имя) 
						//И ОбъектXDTO.Установлено(Свойство.Имя) 
					Тогда
						Если Свойство.ВерхняяГраница > 1 Или Свойство.ВерхняяГраница = -1 Тогда
							ЗначениеСвойства = ОбъектXDTO.ПолучитьСписок(Свойство.Имя);
						Иначе
							ЗначениеСвойства = ОбъектXDTO.Получить(Свойство.Имя);
						КонецЕсли; 
						КоллекцияЗначений.Вставить(Свойство.Имя, ЗначениеСвойства);
					КонецЕсли; 
				КонецЦикла; 
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Свойства" 
				И ТипЗнч(МетаданныеРодителя) = Тип("СвойствоXDTO")
			Тогда
				КоллекцияЗначений = Новый Структура;
				ОбъектXDTO = МетаданныеРодителя.ОбъектВладелец;
				Свойство = МетаданныеРодителя;
				Если ОбъектXDTO.Установлено(Свойство.Имя) Тогда
					Если Свойство.ВерхняяГраница > 1 Или Свойство.ВерхняяГраница = -1 Тогда
						ЗначениеСвойства = ОбъектXDTO.ПолучитьСписок(Свойство.Имя);
					Иначе
						ЗначениеСвойства = ОбъектXDTO.Получить(Свойство.Имя);
					КонецЕсли; 
					КоллекцияЗначений.Вставить(Свойство.Имя, ЗначениеСвойства);
				КонецЕсли;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Параметры" 
				И ТипЗнч(МетаданныеРодителя) = Тип("ТабличныйДокумент")
				И МетаданныеРодителя.ВысотаТаблицы * МетаданныеРодителя.ШиринаТаблицы < 20000 
			Тогда
				КоллекцияЗначений = Новый Структура;
				СписокПараметров = ирОбщий.ПараметрыТабличногоДокументаЛкс(МетаданныеРодителя);
				Для Каждого ЭлементСписка Из СписокПараметров Цикл
					Попытка
						КоллекцияЗначений.Вставить(ЭлементСписка.Значение);
					Исключение
						// Имена параметров могут содержать запрещенные символы
					КонецПопытки;
				КонецЦикла;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Свойства" // коллекция упр. формы 
				И (Ложь
					Или ТипЗнч(МетаданныеРодителя) = Тип("ТаблицаЗначений")
					Или ТипЗнч(МетаданныеРодителя) = Тип("ДеревоЗначений"))
			Тогда
				СхемаКоллекции = МетаданныеРодителя.Колонки;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Свойства" // коллекция упр. формы 
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных")
			Тогда
				СхемаКоллекции = ирКэш.ПоляТаблицыБДЛкс(ирКэш.ИмяТаблицыИзМетаданныхЛкс(МетаданныеРодителя.ПолноеИмя()), Истина);
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Свойства" // коллекция упр. формы 
				И ТипЗнч(МетаданныеРодителя) = Тип("Структура") 
				И ирОбщий.СвойствоСтруктурыЛкс(МетаданныеРодителя, "Тип") <> ирОбщий.ТипУправляемаяФормаЛкс()
			Тогда
				СхемаКоллекции = МетаданныеРодителя;
				
			#Если Клиент Тогда
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Структура" 
				И ТипЗнч(МетаданныеРодителя) = Тип("Форма")
			Тогда
				КоллекцияЗначений = МетаданныеРодителя[РодительскаяСтруктураТипа.СтрокаОписания.Слово];
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Реквизиты" 
				И ирОбщий.ЛиФормаИлиИмитаторЛкс(МетаданныеРодителя)
			Тогда
				Если ЗначениеЗаполнено(Слово) Тогда
					ИмитаторФормы = МетаданныеРодителя;
					Если ТипЗнч(МетаданныеРодителя) = ирОбщий.ТипУправляемаяФормаЛкс() Тогда 
						Попытка
							ЗначениеРеквизита = МетаданныеРодителя[Слово];
						Исключение
							ИмитаторФормы = ирОбщий.СлужебныеДанныеФормыЛкс(МетаданныеРодителя);
						КонецПопытки;
					КонецЕсли;
					Если ТипЗнч(ИмитаторФормы) = Тип("Структура") Тогда
						СтруктураИмен = ИменаРеквизитовФормы(ИмитаторФормы, "").Все;
						Если СтруктураИмен.Свойство(Слово) Тогда
							ЗначениеСлова = СтруктураИмен[Слово];
							СхемаКоллекции.Вставить(Слово, ЗначениеСлова);
						ИначеЕсли Не ЛиВместеСЛокальнымКонтекстом Тогда
							ДобавитьОтсутствиеЭлементаФормы(ИмитаторФормы, "Реквизит:" + Слово);
						КонецЕсли;
					Иначе
						// Для ускорения особенно для управляемой формы
						КоллекцияЗначений = Новый Структура;
						Попытка
							ЗначениеРеквизита = МетаданныеРодителя[Слово];
						Исключение
							ЗначениеРеквизита = Null;
						КонецПопытки;
						Если ЗначениеРеквизита <> Null Тогда
							КоллекцияЗначений.Вставить(Слово, ЗначениеРеквизита);
						КонецЕсли;
					КонецЕсли;
				Иначе
					Если ТипЗнч(МетаданныеРодителя) = Тип("Форма") Тогда 
						ПутьКРодителю = Неопределено;
					Иначе
						ПутьКРодителю = "";
					КонецЕсли;
					СтруктураИмен = ИменаРеквизитовФормы(МетаданныеРодителя, ПутьКРодителю).Все;
					Если ТипЗнч(МетаданныеРодителя) = Тип("Структура") Тогда
						СхемаКоллекции = СтруктураИмен; 
					Иначе 
						КоллекцияЗначений = Новый Структура;
						Для Каждого КлючИЗначение Из СтруктураИмен Цикл
							Попытка
								ЗначениеРеквизита = МетаданныеРодителя[КлючИЗначение.Ключ];
							Исключение
								Если КлючИЗначение.Значение <> Неопределено Тогда
									// Добавленный реквизит был получен через буфер обмена, но пока отсутствует в натуральной форме
									ЗначениеРеквизита = ТаблицаТиповИзОписанияТипов(КлючИЗначение.Значение);
								Иначе 
									ЗначениеРеквизита = Неопределено;
								КонецЕсли;
							КонецПопытки;
							КоллекцияЗначений.Вставить(КлючИЗначение.Ключ, ЗначениеРеквизита);
						КонецЦикла;
					КонецЕсли;
				КонецЕсли;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "Команды"
				И ирОбщий.ЛиФормаИлиИмитаторЛкс(РодительскаяСтруктураТипа.ДержательМетаданных, Ложь)
			Тогда
				Форма = РодительскаяСтруктураТипа.ДержательМетаданных; 
				СлужебныеДанные = ирОбщий.СлужебныеДанныеФормыЛкс(Форма);
				Если СлужебныеДанные <> Неопределено И СлужебныеДанные.Свойство("Команды") Тогда
					СхемаКоллекции = СлужебныеДанные.Команды;
					Если ЗначениеЗаполнено(Слово) И Не СхемаКоллекции.Свойство(Слово) Тогда
						ДобавитьОтсутствиеЭлементаФормы(Форма, "Команда:" + Слово);
					КонецЕсли;
				Иначе 
					Если ТипЗнч(Форма) = ирОбщий.ТипУправляемаяФормаЛкс() Тогда 
						СхемаКоллекции = Форма.Команды;
					КонецЕсли;
				КонецЕсли;
			ИначеЕсли Истина
				И ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыСтруктура")
				И РодительскаяСтруктураТипа.СтрокаОписания <> Неопределено
				И РодительскаяСтруктураТипа.СтрокаОписания.Слово = "Параметры"
			Тогда
				Форма = РодительскаяСтруктураТипа.ДержательМетаданных;
				СтруктураТипаФормы = СтруктураТипаИзЗначения(Форма);
				ТаблицаПараметровФормы = ТаблицаСловИзСтруктурыТипа(СтруктураТипаФормы,,,,,, "Параметр");
				Для Каждого СтрокаПараметра Из ТаблицаПараметровФормы Цикл
					ТаблицаТипов = СтрокаПараметра.ТаблицаТипов;
					Если СтрокаПараметра.Слово = "Ключ" Тогда
						КлючФормы = ирОбщий.КлючОсновногоОбъектаФормыЛкс(Форма);
						ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(КлючФормы));
						ТаблицаТипов[0].Метаданные = ОбъектМД;
					КонецЕсли;
					СхемаКоллекции.Вставить(СтрокаПараметра.Слово, ТаблицаТипов);
				КонецЦикла;
				СлужебныеДанные = ирОбщий.СлужебныеДанныеФормыЛкс(Форма);
				Если СлужебныеДанные <> Неопределено И СлужебныеДанные.Свойство("Параметры") Тогда
					ирОбщий.СкопироватьКоллекциюЛкс(СлужебныеДанные.Параметры, СхемаКоллекции);
					// Параметры часто не описаны в структуре формы
					//Если ЗначениеЗаполнено(Слово) И Не СхемаКоллекции.Свойство(Слово) Тогда
					//	ДобавитьОтсутствиеЭлементаФормы(Форма, "Параметр:" + Слово);
					//КонецЕсли;
				КонецЕсли;
			ИначеЕсли Ложь
				Или ТипЗнч(МетаданныеРодителя) = Тип("ДинамическийСписок")
				Или ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыДерево")
				Или ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыСтруктура")
				Или ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыСтруктураСКоллекцией")
				Или ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыКоллекция")
				Или ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыКоллекцияЭлементовДерева")
				// Для следующих сериализация вызывает ошибку
				//Или ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыЭлементДерева")
				//Или ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыЭлементКоллекции")
			Тогда
				Форма = РодительскаяСтруктураТипа.ДержательМетаданных;
				ЛиКоллекция = Ложь
					Или ирОбщий.ЛиКоллекцияЛкс(МетаданныеРодителя) 
					Или ТипЗнч(МетаданныеРодителя) = Тип("ДанныеФормыДерево");
				СтруктураИмен = ДочерниеСвойстваДанныхФормы(МетаданныеРодителя, ЛиКоллекция, Форма, Слово);
				СхемаКоллекции = СтруктураИмен;
				Если Не ЛиКоллекция Тогда
					Для Каждого КлючИЗначение Из СтруктураИмен Цикл
						ЗначениеСвойства = КлючИЗначение.Значение;  // ОписаниеТипов
						Если Ложь
							Или ЗначениеСвойства = Неопределено
							Или ЗначениеСвойства.Типы().Количество() = 0 
						Тогда
							ЗначениеСвойства = ТаблицаТиповИзЗначения(МетаданныеРодителя[КлючИЗначение.Ключ]);
						Иначе 
							ЗначениеСвойства = ТаблицаТиповИзОписанияТипов(ЗначениеСвойства);
						КонецЕсли;
						ЗначениеСвойства.ЗаполнитьЗначения(Форма, "ДержательМетаданных");
						Если КоллекцияЗначений = Неопределено Тогда 
							КоллекцияЗначений = Новый Структура;
						КонецЕсли;
						КоллекцияЗначений.Вставить(КлючИЗначение.Ключ, ЗначениеСвойства);
					КонецЦикла; 
				КонецЕсли;
			ИначеЕсли Ложь
				Или (Истина
					И СтрокаОписанияВида.ИмяКоллекции = "ЭлементыФормы" 
					И ТипЗнч(МетаданныеРодителя) = Тип("Форма"))
				Или (Истина
					И СтрокаОписанияВида.ИмяКоллекции = "Элементы" 
					И ирОбщий.ЛиФормаИлиИмитаторЛкс(МетаданныеРодителя, Ложь))
				Или (Истина
					И СтрокаОписанияВида.ИмяКоллекции = "Страницы" 
					И ТипЗнч(МетаданныеРодителя) = Тип("Панель"))
				Или (Истина
					И СтрокаОписанияВида.ИмяКоллекции = "Колонки" 
					И ТипЗнч(МетаданныеРодителя) = Тип("ТабличноеПоле"))
				Или (Истина
					И СтрокаОписанияВида.ИмяКоллекции = "Кнопки" 
					И (Ложь
						Или ТипЗнч(МетаданныеРодителя) = Тип("КнопкаКоманднойПанели")
						Или ТипЗнч(МетаданныеРодителя) = Тип("КнопкиКоманднойПанели")))
			Тогда
				СловаКонтекстаМетаданныеФормы(Слово, ИмяОбщегоТипаРодителя, МетаданныеРодителя, СтрокаОписанияВида, КоллекцияЗначений, СхемаКоллекции);
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "ПодчиненныеЭлементы" 
				И (Ложь
					Или ТипЗнч(МетаданныеРодителя) = ирОбщий.ТипУправляемаяФормаЛкс()
					Или ТипЗнч(МетаданныеРодителя) = Тип("ТаблицаФормы")
					Или ТипЗнч(МетаданныеРодителя) = Тип("ГруппаФормы"))
			Тогда
				КоллекцияЗначений = МетаданныеРодителя[СтрокаОписанияВида.ИмяКоллекции];
			#КонецЕсли
			
			ИначеЕсли ТипЗнч(МетаданныеРодителя) = Тип("НаборыДанныхСхемыКомпоновкиДанных") Тогда 
				КоллекцияЗначений = МетаданныеРодителя;
			//ИначеЕсли СтрокаОписанияВида.ИмяКоллекции = "Оформление" Тогда
			//	Для Каждого МетаОбщийМодуль Из МетаданныеРодителя[СтрокаОписанияВида.ИмяКоллекции] Цикл
			//		Если МетаОбщийМодуль.Глобальный Тогда
			//			Продолжить;
			//		КонецЕсли;
			//		СхемаКоллекции.Вставить(МетаОбщийМодуль.Имя);
			//	КонецЦикла;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "ОбщиеМодули"
				И ИмяОбщегоТипаРодителя = "Глобальный"
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданныхКонфигурация") //
			Тогда
				СхемаКоллекции = ирКэш.ДоступныеОбщиеМодулиЛкс(НаСервере, КлиентОбычноеПриложение, КлиентУправляемоеПриложение);
				Если мДобавленныеОбщиеМодули.Количество() > 0 Тогда
					ирОбщий.СкопироватьКоллекциюЛкс(мДобавленныеОбщиеМодули, СхемаКоллекции);
				КонецЕсли;
				Если Прав(Слово, 1) = "_" Тогда
					ЭтоГруппаОбщихМодулей = Истина;
					НачальныйФрагмент = НРег(ирОбщий.СтрокаБезКонцаЛкс(Слово));
					Слово = Неопределено;
					ТаблицаСлов.Очистить();
					НоваяСхема = Новый Структура;
					Для Каждого КлючИЗначение Из СхемаКоллекции Цикл
						Если ирОбщий.СтрНачинаетсяСЛкс(КлючИЗначение.Ключ, НачальныйФрагмент) Тогда 
							НоваяСхема.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
						КонецЕсли;
					КонецЦикла;
					СхемаКоллекции = НоваяСхема;
				ИначеЕсли Не ЗначениеЗаполнено(Слово) Тогда 
					СписокЗначений = Новый СписокЗначений;
					НоваяСхема = Новый Структура;
					Для Каждого КлючИЗначение Из СхемаКоллекции Цикл
						СписокЗначений.Добавить(КлючИЗначение.Ключ);
						НоваяСхема.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
					КонецЦикла;
					СписокЗначений.СортироватьПоЗначению();
					СхемаКоллекции = НоваяСхема;
					ИмяГруппы = Неопределено;
					ЧленыГруппы = Новый Массив;
					Для Каждого ИмяМодуляЦикл Из СписокЗначений.ВыгрузитьЗначения() Цикл
						Если Истина
							И ИмяГруппы <> Неопределено 
							И ирОбщий.СтрНачинаетсяСЛкс(ИмяМодуляЦикл, ИмяГруппы, Истина) 
						Тогда
							ЧленыГруппы.Добавить(ИмяМодуляЦикл);
						Иначе 
							Если ЧленыГруппы.Количество() > 2 Тогда
								СхемаКоллекции.Вставить(ИмяГруппы + "_");
							КонецЕсли;
							ИмяГруппы = ИмяМодуляЦикл;
							ЧленыГруппы.Очистить();
						КонецЕсли;
					КонецЦикла;
				КонецЕсли;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "ВидыСубконто"
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") 
			Тогда
				//! МетаданныеРодителя = 0; // ОбъектМетаданныхРегистрБухгалтерии
				Для Счетчик = 1 По МетаданныеРодителя.ПланСчетов.МаксКоличествоСубконто Цикл 
					СхемаКоллекции.Вставить(Строка(Счетчик), МетаданныеРодителя.ПланСчетов.ВидыСубконто);
				КонецЦикла;
			ИначеЕсли СтрокаОписанияВида.ИмяКоллекции = "Движения" Тогда
				Если ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") Тогда
					//! МетаданныеРодителя = 0; // ОбъектМетаданныхДокумент
					Для Каждого МетаРегистр Из МетаданныеРодителя.Движения Цикл  
						МассивФрагментов = ирОбщий.СтрРазделитьЛкс(МетаРегистр.ПолноеИмя());
						СхемаКоллекции.Вставить(МетаРегистр.Имя, Новый ОписаниеТипов(МассивФрагментов[0] + "НаборЗаписей." + МассивФрагментов[1]));
					КонецЦикла;
				ИначеЕсли ТипЗнч(МетаданныеРодителя) = Тип("КоллекцияДвижений") Тогда
					Для Каждого НаборЗаписейРегистра Из МетаданныеРодителя Цикл // РегистрСведенийНаборЗаписей.КурсыВалют
						СхемаКоллекции.Вставить(НаборЗаписейРегистра.Метаданные().Имя, НаборЗаписейРегистра);
					КонецЦикла;
				ИначеЕсли Истина
					И Слово <> Неопределено
					И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданныхКонфигурация") //
				Тогда 
					МетаданныеРегистра = Метаданные.РегистрыСведений.Найти(Слово);
					Если МетаданныеРегистра = Неопределено Тогда
						МетаданныеРегистра = Метаданные.РегистрыНакопления.Найти(Слово);
					КонецЕсли;  
					Если МетаданныеРегистра = Неопределено Тогда
						МетаданныеРегистра = Метаданные.РегистрыБухгалтерии.Найти(Слово);
					КонецЕсли;  
					Если МетаданныеРегистра = Неопределено Тогда
						МетаданныеРегистра = Метаданные.РегистрыРасчета.Найти(Слово);
					КонецЕсли;  
					Если МетаданныеРегистра <> Неопределено Тогда
						МассивФрагментов = ирОбщий.СтрРазделитьЛкс(МетаданныеРегистра.ПолноеИмя());
						СхемаКоллекции.Вставить(МассивФрагментов[1], Новый ОписаниеТипов(МассивФрагментов[0] + "НаборЗаписей." + МассивФрагментов[1]));
					КонецЕсли;  
				КонецЕсли;
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "ТочкиМаршрута"
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных")
			Тогда
				КоллекцияЗначений = ирОбщий.ПолучитьМенеджерЛкс(МетаданныеРодителя)[СтрокаОписанияВида.ИмяКоллекции];
			ИначеЕсли Истина
				И СтрокаОписанияВида.ИмяКоллекции = "<Имя коллекции метаданных>"
				И (Ложь
					Или ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных")
					Или ТипЗнч(МетаданныеРодителя) = Тип("КоллекцияОбъектовМетаданных")
					Или ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданныхКонфигурация"))
			Тогда
				Если ТипЗнч(МетаданныеРодителя) = Тип("КоллекцияОбъектовМетаданных") Тогда
					КоллекцияЗначений = МетаданныеРодителя; 
				Иначе
					ИмяКоллекцииОбъектовМетаданных = ирОбщий.ТекстМеждуМаркерамиЛкс(ИмяОбщегоТипаРодителя, МаркерКоллекцииОбъектовМетаданных, , Ложь);
					Если ЗначениеЗаполнено(ИмяКоллекцииОбъектовМетаданных) Тогда
						СтрокаКорневогоТипа = ОписаниеТипаМетаОбъектов(, ИмяКоллекцииОбъектовМетаданных);
						Если СтрокаКорневогоТипа <> Неопределено Тогда
							//КоллекцияЗначений = МетаданныеРодителя[ИмяКоллекцииОбъектовМетаданных];
							Попытка
								КоллекцияЗначений = МетаданныеРодителя[РодительскаяСтруктураТипа.СтрокаОписания.Слово];
							Исключение
								ИнформацияОбОшибке = ИнформацияОбОшибке(); // Для отладки
							КонецПопытки;
						КонецЕсли;
					КонецЕсли; 
				КонецЕсли;
			ИначеЕсли Истина
				//И СтрокаОписанияВида.ИмяКоллекции = "<Имя коллекции метаданных>"
				И ЭтоИнтеграция
				И (Ложь
					Или ТипЗнч(МетаданныеРодителя) = Тип("СправочникСсылка.КонфигурацииМетаданныхИис") 
					Или ТипЗнч(МетаданныеРодителя) = Тип("СправочникСсылка.МетаданныеИис"))
			Тогда
				Если СтрокаОписанияВида.ИмяКоллекции = "<Имя коллекции метаданных>" Тогда 
					ИмяКоллекцииОбъектовМетаданных = ирОбщий.ТекстМеждуМаркерамиЛкс(ИмяОбщегоТипаРодителя, МаркерКоллекцииОбъектовМетаданных, , Ложь);
				Иначе
					ИмяКоллекцииОбъектовМетаданных = СтрокаОписанияВида.ИмяКоллекции;
				КонецЕсли;
				Если ЗначениеЗаполнено(ИмяКоллекцииОбъектовМетаданных) Тогда
					СтрокаКорневогоТипа = ОписаниеТипаМетаОбъектов(, ИмяКоллекцииОбъектовМетаданных);
					Запрос = Новый Запрос;
					Если СтрокаКорневогоТипа <> Неопределено Тогда
						//лИмяКоллекции = РодительскаяСтруктураТипа.СтрокаОписания.Слово;
						Если ИмяКоллекцииОбъектовМетаданных = "Реквизиты" Тогда
							ТекстЗапроса = "ВЫБРАТЬ Наименование КАК Имя, Типы Как Значение ИЗ Справочник.СвойстваМетаданныхИис 
							|ГДЕ КонфигурацияМетаданных = &Владелец И Вид <> ЗНАЧЕНИЕ(Перечисление.ВидыСвойствМетаданныхИис.Свойство)"; 
							Запрос.Текст = ТекстЗапроса;
							Запрос.УстановитьПараметр("Владелец", МетаданныеРодителя);
							Выборка = Запрос.Выполнить().Выбрать();
							Пока Выборка.Следующий() Цикл
								СхемаКоллекции[Выборка.Имя] = Выборка.Значение.Выгрузить().ВыгрузитьКолонку("Тип");
							КонецЦикла;
						Иначе
							ТекстЗапроса = "ВЫБРАТЬ Имя, Ссылка КАК Значение ИЗ Справочник.МетаданныеИис 
							|ГДЕ КонфигурацияМетаданных = &Владелец И ТипМетаданных.ИмяМножественное = &ИмяРодителя";
							Запрос.УстановитьПараметр("ИмяРодителя", ИмяКоллекцииОбъектовМетаданных);
							Запрос.Текст = ТекстЗапроса;
							Запрос.УстановитьПараметр("Владелец", МетаданныеРодителя);
							Выборка = Запрос.Выполнить().Выбрать();
							Пока Выборка.Следующий() Цикл
								СхемаКоллекции[Выборка.Имя] = Выборка.Значение;  
							КонецЦикла;
						КонецЕсли;
					КонецЕсли;
				Иначе
					//КоллекцияЗначений = МетаданныеРодителя;
				КонецЕсли;
			ИначеЕсли Истина
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбщийМодуль")
			Тогда 
				// Платформа пока не дает узнать имя модуля 
			Иначе
				Если мМассивИсключенийИменКоллекций.НайтиПоЗначению(СтрокаОписанияВида.ИмяКоллекции) <> Неопределено Тогда 
					Продолжить;
				КонецЕсли;
				СхемаКоллекции = МетаданныеРодителя;
				Если ТипЗнч(МетаданныеРодителя) <> Тип("КоллекцияОбъектовМетаданных") Тогда
					ЦелевойТип = Неопределено;
					Если Найти(СтрокаОбщегоТипа.ИмяОбщегоТипа, "<") = 0 Тогда
						Попытка
							ЦелевойТип = Тип(СтрокаОбщегоТипа.ИмяОбщегоТипа);
						Исключение
						КонецПопытки;
					КонецЕсли; 
					Попытка
						Если ТипЗнч(МетаданныеРодителя) = ЦелевойТип Тогда
							СхемаКоллекции = МетаданныеРодителя;
						Иначе
							СхемаКоллекции = МетаданныеРодителя[СтрокаОписанияВида.ИмяКоллекции];
						КонецЕсли; 
					Исключение
						Продолжить;
					КонецПопытки;
				КонецЕсли; 
			КонецЕсли;
			
			Если КоллекцияЗначений = Неопределено Тогда
				КоллекцияЗначений = СхемаКоллекции;
				Если Слово <> Неопределено Тогда 
					ЭлементСхемы = Неопределено;
					Если Ложь
						Или ТипЗнч(КоллекцияЗначений) = Тип("ФиксированнаяСтруктура")
						Или ТипЗнч(КоллекцияЗначений) = Тип("ФиксированноеСоответствие")
						Или ТипЗнч(КоллекцияЗначений) = Тип("Структура")
						Или ТипЗнч(КоллекцияЗначений) = Тип("Соответствие")
					Тогда
						//Для Каждого ЭлементКоллекции Из КоллекцияЗначений Цикл
						//	Если ЭлементКоллекции.Ключ = ИмяТекущегоСлова Тогда
						//		ЭлементСхемы = ЭлементКоллекции.Значение;
						//		Прервать;
						//	КонецЕсли;
						//КонецЦикла;
						Попытка
							ЭлементСхемы = КоллекцияЗначений[ИмяТекущегоСлова];
						Исключение
						КонецПопытки; 
					Иначе
						ЭлементСхемы = Null;
						Если ТипЗнч(КоллекцияЗначений) <> Тип("Массив") Тогда
							Попытка
								ЭлементСхемы = КоллекцияЗначений.Найти(ИмяТекущегоСлова);
							Исключение 
							КонецПопытки;
						КонецЕсли; 
						Если ЭлементСхемы = Null Тогда
							ЭлементСхемы = Неопределено;
							Для Каждого ЭлементКоллекции Из КоллекцияЗначений Цикл
								Если ЭлементКоллекции.Имя = ИмяТекущегоСлова Тогда
									ЭлементСхемы = ЭлементКоллекции;
									Прервать;
								КонецЕсли;
							КонецЦикла;
						КонецЕсли;
					КонецЕсли;
					КоллекцияЗначений = Новый Соответствие;
					Если ЭлементСхемы <> Неопределено Тогда
						КоллекцияЗначений.Вставить(ИмяТекущегоСлова, ЭлементСхемы); 
					КонецЕсли;
				КонецЕсли;
			Иначе
				Если Слово <> Неопределено Тогда
					Попытка
						ЭлементСхемы = КоллекцияЗначений[ИмяТекущегоСлова];
					Исключение
						ЭлементСхемы = Null;
					КонецПопытки;
					КоллекцияЗначений = Новый Соответствие;
					Если ЭлементСхемы <> Null Тогда
						КоллекцияЗначений.Вставить(ИмяТекущегоСлова, ЭлементСхемы); 
					КонецЕсли;
				КонецЕсли;
			КонецЕсли;
			
			Если КоллекцияЗначений = Неопределено Тогда
				КоллекцияЗначений = Новый Массив();
			КонецЕсли; 
			//! СхемаКоллекции = 0 // Соответствие, Структура
			
			ЭтоСубконто = Найти(СтрокаВида.Слово, "Субконто") = 1; 
			ПредыдущаяТаблицаТипов = Неопределено;
			ВычислятьТипыЦикл = ВычислятьТипы Или КоллекцияЗначений.Количество() < 100;
			ИмяКолонкиФлага = ИмяКолонкиФлагаВнутриТаблицы();  
			Если ЗначениеЗаполнено(СтрокаВида.ТипЗначения) Тогда
				ТипЗначенияСлова = "," + СтрокаВида.ТипЗначения;
				ТипЗначенияСлова = СтрЗаменить(ТипЗначенияСлова, ",Произвольный", "");
			Иначе
				ТипЗначенияСлова = "";
			КонецЕсли;
			Для Каждого ЭлементКоллекции Из КоллекцияЗначений Цикл
				Если ЭлементКоллекции = Неопределено Тогда
					// ПараметрыМакетаТабличногоДокумента
					Продолжить;
				КонецЕсли; 
				Если ТипЗнч(ЭлементКоллекции) = Тип("КлючИЗначение") Тогда 
					ИмяСвойства = ЭлементКоллекции.Ключ;
					ЗначениеСвойства = ЭлементКоллекции.Значение;
				Иначе 
					ИмяСвойства = ЭлементКоллекции.Имя;
					ЗначениеСвойства = ЭлементКоллекции;
				КонецЕсли;
				КонечноеСлово = СтрЗаменить(СтрокаВида.Слово, ИмяЭлементаКоллекции, ИмяСвойства);
				ТаблицаТипов = Неопределено;
				Если ВычислятьТипыЦикл Тогда
					Если ЭтоСубконто И ПредыдущаяТаблицаТипов <> Неопределено Тогда
						ТаблицаТипов = ПредыдущаяТаблицаТипов; 
					ИначеЕсли Истина
						И ТипЗнч(ЗначениеСвойства) = Тип("ТаблицаЗначений") 
						И ЗначениеСвойства.Количество() > 0
						И ЗначениеСвойства.Колонки.Найти(ИмяКолонкиФлага) <> Неопределено
						//И ЗначениеСвойства.Колонки.Найти("ИмяОбщегоТипа") <> Неопределено 
					Тогда
						ТаблицаТипов = ЗначениеСвойства;
					Иначе
						ТаблицаТипов = НоваяТаблицаТипов();
						ПредыдущаяТаблицаТипов = ТаблицаТипов;
						МассивТипов = Новый Массив;
						Квалификаторы = Неопределено;
						ОписаниеТиповЗначения = Неопределено;
						Если Истина
							И СхемаКоллекции.Количество() > 0 
							И (Ложь
								Или СтрокаВида.ТипЗначения = ""
								Или СтрокаВида.ТипЗначения = "Произвольный"
								Или СтрокаВида.ТипЗначения = "Набор записей регистра"
								Или Найти(СтрокаВида.ТипЗначения, "<") > 0
								Или ЛиТипСКвалификаторами)
						Тогда 
							Если ТипЗнч(ЗначениеСвойства) = Тип("ОписаниеТипов") Тогда
								ОписаниеТиповЗначения = ЗначениеСвойства;
							КонецЕсли;
							Если Истина
								И ЯзыкПрограммы = 1
								И РодительскаяСтруктураТипа.ТипЯзыка <> "ЗначениеВЗапросе"
								//И КорневойТипРодителя <> Неопределено
								//И КорневойТипРодителя <> "ВнешнийИсточникДанных" 
								И ПостроительЗапросаРодителя <> Неопределено
							Тогда 
								ДоступноеПолеСлова = ПостроительЗапросаРодителя.ДоступныеПоля.Найти(НРег(КонечноеСлово));
								Если ДоступноеПолеСлова = Неопределено Тогда
									Продолжить;
								КонецЕсли;
								Если ДоступноеПолеСлова.ТипЗначения <> Новый ОписаниеТипов("ТаблицаЗначений") Тогда
									ОписаниеТиповЗначения = ДоступноеПолеСлова.ТипЗначения;
								КонецЕсли; 
							КонецЕсли;
							Если Истина 
								И ОписаниеТиповЗначения = Неопределено
								И СтрокаОписанияВида.ИмяКоллекции <> "КритерииОтбора"
								И СтрокаОписанияВида.ИмяКоллекции <> "ПланыВидовХарактеристик"
								И ИмяОбщегоТипаРодителя <> "Константа"
							Тогда
								Попытка 
									ОписаниеТиповЗначения = ЗначениеСвойства.Тип;
								Исключение
									Попытка
										ОписаниеТиповЗначения = ЗначениеСвойства.ТипЗначения;
									Исключение
									КонецПопытки;
								КонецПопытки;
								Если ТипЗнч(ОписаниеТиповЗначения) <> Тип("ОписаниеТипов") Тогда
									ОписаниеТиповЗначения = Неопределено;
								КонецЕсли;
							КонецЕсли;
							Если ТипЗнч(ОписаниеТиповЗначения) = Тип("ОписаниеТипов") Тогда
								МассивТипов = ОписаниеТиповЗначения.Типы();
								Квалификаторы = ОписаниеТиповЗначения;
							ИначеЕсли ТипЗнч(ЗначениеСвойства) = Тип("Массив") Тогда
								МассивТипов = ЗначениеСвойства;
							КонецЕсли;
						КонецЕсли;
						Если Истина
							И МассивТипов.Количество() = 0 
							И (Ложь
								Или СхемаКоллекции.Количество() = 0
								//Или ОписаниеТиповЗначения = Неопределено И СтрокаВида.ТипЗначения = "Произвольный"
							)
						Тогда
							МассивТипов.Добавить(ТипЗнч(ЗначениеСвойства));
						КонецЕсли;
						Если Истина
							//И ОписаниеТиповЗначения <> Неопределено
							И МассивТипов.Количество() > 0
							И СтрокаОписанияВида.ИмяКоллекции <> "<Имя коллекции метаданных>"
							И (Ложь
								Или СтрокаОписанияВида.ИмяКоллекции <> "Константы"
								Или ЯзыкПрограммы = 1)
						Тогда
							ШаблонСтруктурыТипа = Новый Структура("СтрокаОписания, ТипЯзыка, Метаданные, ДержательМетаданных, Квалификаторы");
							ШаблонСтруктурыТипа.СтрокаОписания = СтрокаВида;
							ШаблонСтруктурыТипа.ТипЯзыка = РодительскаяСтруктураТипа.ТипЯзыка;
							Если ирОбщий.ЛиФормаИлиИмитаторЛкс(МетаданныеРодителя) Тогда
								ШаблонСтруктурыТипа.ДержательМетаданных = МетаданныеРодителя;
							Иначе 
								ШаблонСтруктурыТипа.ДержательМетаданных = РодительскаяСтруктураТипа.ДержательМетаданных;
							КонецЕсли;
							ШаблонСтруктурыТипа.Квалификаторы = Квалификаторы;
							//ШаблонСтруктурыТипа.Метаданные = МетаданныеРодителя;
							ПередаватьЗначениеСвойства = ТипЗнч(ЗначениеСвойства) = Тип("ОбъектМетаданных");
							ПередаватьМетаданныеРодителя = НЕ (ИмяОбщегоТипаРодителя = "Структура" И ТипЗнч(МетаданныеРодителя) = Тип("Структура"));
							Если МассивТипов.Количество() > МаксЧислоТиповДляАнализа Тогда 
								СтруктураТипаСвойства = СтруктураТипаИзКонкретногоТипа(МассивТипов[0], ЯзыкПрограммы, ШаблонСтруктурыТипа);
								СтруктураОбщегоТипа = НоваяСтруктураТипа(СтруктураТипаСвойства.ИмяОбщегоТипа);
								ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураОбщегоТипа);
							Иначе
								МассивНакопления = Новый Массив;
								Для Каждого Тип Из МассивТипов Цикл
									Если Истина
										И Тип = ТипЗнч(ЗначениеСвойства)
										//И (Ложь
										//	Или мМассивТиповСМетаданными.Найти(Тип) <> Неопределено 
										//	Или мМассивТиповЭлементовОбычнойФормы.Найти(Тип) <> Неопределено)
									Тогда 
										МетаданныеЭлемента = МетаданныеЭлементов[ИмяСвойства];
										Если МетаданныеЭлемента = Неопределено Тогда
											МетаданныеЭлемента = ЗначениеСвойства;
										КонецЕсли; 
										ШаблонСтруктурыТипа.Метаданные = МетаданныеЭлемента;
										СтруктураТипаСвойства = СтруктураТипаИзЗначения(ЗначениеСвойства, ЯзыкПрограммы, ШаблонСтруктурыТипа);
									Иначе
										Если ПередаватьЗначениеСвойства Тогда
											ШаблонСтруктурыТипа.Метаданные = ЗначениеСвойства;
										ИначеЕсли ПередаватьМетаданныеРодителя Тогда
											ШаблонСтруктурыТипа.Метаданные = МетаданныеРодителя;
										КонецЕсли;
										СтруктураТипаСвойства = СтруктураТипаИзКонкретногоТипа(Тип, ЯзыкПрограммы, ШаблонСтруктурыТипа);
									КонецЕсли;  
									Если СтруктураТипаСвойства.Метаданные = Неопределено Тогда
										СтруктураТипаСвойства.Метаданные = мМетаданные; // Чтобы проверка модуля не считала слово неизвестным, например колонку таблицы значений без указанного типа
									КонецЕсли;
									МассивНакопления.Добавить(СтруктураТипаСвойства);
								КонецЦикла;
								ДобавитьВТаблицуТипов(ТаблицаТипов, МассивНакопления);
							КонецЕсли;
						Иначе
							СтруктураТипаСвойства = НоваяСтруктураТипа();
							ЗаполнитьЗначенияСвойств(СтруктураТипаСвойства, РодительскаяСтруктураТипа, "ТипЯзыка");
							Если ТипЗнч(МетаданныеРодителя) = ирОбщий.ТипУправляемаяФормаЛкс() Тогда
								СтруктураТипаСвойства.ДержательМетаданных = МетаданныеРодителя;
							Иначе 
								СтруктураТипаСвойства.ДержательМетаданных = РодительскаяСтруктураТипа.ДержательМетаданных;
							КонецЕсли;
							Если РодительскаяСтруктураТипа.ТипЯзыка = "ИмяТипа" Тогда
								СтруктураТипаСвойства.ИмяОбщегоТипа = СтрокаВида.Слово;
								Если СтрокаВида.ТипКонтекста <> "" Тогда
									СтруктураТипаСвойства.ИмяОбщегоТипа = СтрокаВида.ТипКонтекста + "." + СтруктураТипаСвойства.ИмяОбщегоТипа;
								КонецЕсли;
							Иначе
								СтруктураТипаСвойства.ИмяОбщегоТипа = СтрокаВида.ТипЗначения;
								СтруктураТипаСвойства.СтрокаОписания = СтрокаВида;
							КонецЕсли;
							СтруктураТипаСвойства.Метаданные = ЗначениеСвойства;
							//Если ПустаяСтрока(СтруктураТипаСвойства.ИмяОбщегоТипа) Тогда
							//КонецЕсли;
							ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипаСвойства);
						КонецЕсли;
					КонецЕсли; 
				Иначе
					//
				КонецЕсли;
				ДобавитьВТаблицуСлов(ТаблицаСлов, КонечноеСлово, СтрокаВида.ТипСлова, ТаблицаТипов, "??" + ТипЗначенияСлова, "Метаданные");
			КонецЦикла;
			Если ЭтоГруппаОбщихМодулей Тогда
				Прервать;
			КонецЕсли;
		КонецЦикла;
		Если ЭтоГруппаОбщихМодулей Тогда
			Прервать;
		КонецЕсли;
		// Модуль
		Если Истина
			И Не ирОбщий.СтрНачинаетсяСЛкс(СтрокаОбщегоТипа.ИмяОбщегоТипа, "РасширениеФормы")
			И (Ложь
				Или РодительскаяСтруктураТипа.ТипЯзыка = ""
				Или СтрокаОбщегоТипа.ИмяОбщегоТипа <> "Глобальный")
			И (Ложь
				Или ЯзыкПрограммы = 0 
				Или ЯзыкПрограммы = 2)
		Тогда
			Если СтрокаОбщегоТипа.ИмяОбщегоТипа = "Глобальный" Тогда
				ДобавитьВТаблицуСловЭлементыГлобальныхМодулей(СтрокаОбщегоТипа, Слово, ТипСлова, ВычислятьТипы, ВычислятьТипыМетодовМодулей, Не ЭтоЛокальныйКонтекст, 
					КлиентОбычноеПриложение, КлиентУправляемоеПриложение, НаСервере, ТаблицаСлов);
			Иначе
				МодульМетаданныхКомпонента = МодульМетаданныхДинамический;
				Если Истина
					И МодульМетаданныхКомпонента = Неопределено 
					И ИмяОбщегоТипаРодителя <> "НеизвестныйКонтекст" 
					И ТипЗнч(МетаданныеРодителя) <> Тип("ОбъектМетаданныхКонфигурация")
				Тогда
					СтруктураТипаМодуля = НоваяСтруктураТипа(ИмяОбщегоТипаРодителя); 
					СтруктураТипаМодуля.ДержательМетаданных = РодительскаяСтруктураТипа.ДержательМетаданных; // Имя расширения конфигурации
					СтруктураТипаМодуля.Метаданные = МетаданныеРодителя;
					МодульМетаданныхКомпонента = ПодготовитьМодульМетаданных(СтруктураТипаМодуля);
				КонецЕсли;
				Если МодульМетаданныхКомпонента <> Неопределено Тогда
					РасширениеМодуля = "";
					Если Истина
						И МодульМетаданныхКомпонента.СтруктураТипа <> Неопределено
						И ТипЗнч(МодульМетаданныхКомпонента.СтруктураТипа.ДержательМетаданных) = Тип("Строка")
						И ЗначениеЗаполнено(МодульМетаданныхКомпонента.СтруктураТипа.ДержательМетаданных) 
					Тогда 
						РасширениеМодуля = МодульМетаданныхКомпонента.СтруктураТипа.ДержательМетаданных;
					КонецЕсли;
					Если Ложь
						Или Не ЗначениеЗаполнено(РасширениеМодуля) // методы конфигурации всегда видны расширению
						Или БазовоеРасширениеКонфигурации = "*" // методы конфигурации всегда видны внешнему модулю
						Или РасширениеМодуля = БазовоеРасширениеКонфигурации
						Или РасширениеМодуля = ПолноеИмяПодсистемыИР // расширение ИР видно всем
					Тогда
						ТаблицаСлов = ДобавитьВТаблицуСловЭлементыМодуляМетаданных(СтрокаОбщегоТипа, Слово, ТипСлова, ТаблицаСлов, МодульМетаданныхКомпонента, ВычислятьТипыМетодовМодулей, ВычислятьТипы, Не ЭтоЛокальныйКонтекст,
							ФлагиКомпиляции, ВнутриГруппыОбщихМодулей, ДляСвойства, ЛиВместеСЛокальнымКонтекстом);
					КонецЕсли;
					ВидимыеРасширения = Новый Массив;
					Если Истина
						И ТипЗнч(РасширениеМодуля) = Тип("Строка")
						И ЗначениеЗаполнено(РасширениеМодуля) 
						И (Ложь
							Или ТипЗнч(МетаданныеРодителя) <> Тип("ОбъектМетаданных")
							Или МетаданныеРодителя.РасширениеКонфигурации() = Неопределено)      
					Тогда 
						// Для расширения модуля добавляем базовый модуль
						ВидимыеРасширения.Добавить(Неопределено); 
					ИначеЕсли БазовоеРасширениеКонфигурации = "*" Тогда 
						// При вызове из внешнего модуля, добавляем расширение модуля этого расширения
						Для Каждого РасширениеКонфигурации Из ирКэш.РасширенияКонфигурацииЛкс() Цикл
							ВидимыеРасширения.Добавить(РасширениеКонфигурации.Ключ.Имя); 
						КонецЦикла;
					ИначеЕсли ЗначениеЗаполнено(БазовоеРасширениеКонфигурации) И Не ЗначениеЗаполнено(РасширениеМодуля) Тогда 
						// При вызове из модуля расширения, добавляем расширение модуля этого расширения
						ВидимыеРасширения.Добавить(БазовоеРасширениеКонфигурации); 
					КонецЕсли;
					Для Каждого ВидимоеРасширение Из ВидимыеРасширения Цикл
						СтруктураТипаМодуля = НоваяСтруктураТипа(ИмяОбщегоТипаРодителя);
						СтруктураТипаМодуля.ДержательМетаданных = ВидимоеРасширение; 
						СтруктураТипаМодуля.Метаданные = МетаданныеРодителя;
						МодульМетаданныхРасширение = ПодготовитьМодульМетаданных(СтруктураТипаМодуля);
						Если МодульМетаданныхРасширение <> Неопределено Тогда
							ТаблицаСлов = ДобавитьВТаблицуСловЭлементыМодуляМетаданных(СтрокаОбщегоТипа, Слово, ТипСлова, ТаблицаСлов, МодульМетаданныхРасширение, ВычислятьТипыМетодовМодулей, ВычислятьТипы, Не ЭтоЛокальныйКонтекст,
									ФлагиКомпиляции, ВнутриГруппыОбщихМодулей, ДляСвойства, ЛиВместеСЛокальнымКонтекстом);
						КонецЕсли;
					КонецЦикла;
				КонецЕсли;
			КонецЕсли;
			#Если Клиент Тогда
				СловаКонтекстаМетаданныеCOM(Слово, ТипСлова, ИмяОбщегоТипаРодителя, МетаданныеРодителя, ТаблицаСлов);
			#КонецЕсли
		КонецЕсли; 
	КонецЦикла;
	Если Истина
		И Слово <> Неопределено
		И ТаблицаСлов.Количество() = 0
		И ЕдинственнаяСтрокаВида <> Неопределено
		И ЕдинственнаяСтрокаВида <> Null
		И ЕдинственнаяСтрокаВида.Слово <> "<Имя общего модуля>"
		И (Ложь
			Или ЕдинственнаяСтрокаВида.ТипЗначения <> "Произвольный" // Иначе проверка модуля не будет обнаруживать ошибки в таких переменных
			Или Не ЛиВместеСЛокальнымКонтекстом)
		// Иначе при вычислении результата метода модуля менеджера все локальные переменные будут срабатывать
		И Найти(ЕдинственнаяСтрокаВида.Слово, "<Имя предопределенного") = 0 
		И Найти(ЕдинственнаяСтрокаВида.Слово, "<Имя значения перечисления") = 0 
	Тогда 
		// Шаблон только один. Берем его даже если имя элемента коллекции не подошло.
		МассивТиповЗначения = ирОбщий.СтрРазделитьЛкс(ЕдинственнаяСтрокаВида.ТипЗначения, ", ");
		Для Каждого ТипЗначения Из МассивТиповЗначения Цикл
			Если Истина
				И Не ЗначениеЗаполнено(ТипЗначения) 
				И ЕдинственнаяСтрокаВида.ТипКонтекста <> "COMОбъект"
			Тогда
				ТипЗначения = "НеизвестныйКонтекст"; // Для ЭлементыФормы[0]
			КонецЕсли;
			СтруктураТипа = НоваяСтруктураТипа();
			СтруктураТипа.ИмяОбщегоТипа = ТипЗначения;
			СтруктураТипа.СтрокаОписания = ЕдинственнаяСтрокаВида;
			СтруктураТипа.ТипЯзыка = ЕдинственнаяСтрокаВида.ТипЯзыка; 
			Если ТипЗнч(МетаданныеРодителя) <> Тип("ОбъектМетаданных") Тогда
				СтруктураТипа.Метаданные = МетаданныеРодителя;
			Иначе
				// Мультиметка29332671 Не передаем метаданные, иначе проверка модуля не найдет обращение к несуществующему реквизиту ТЧ в языке запросов
			КонецЕсли;
			ТаблицаТипов = ДобавитьВТаблицуТипов(, СтруктураТипа);
			ДобавитьВТаблицуСлов(ТаблицаСлов, ЕдинственнаяСтрокаВида.Слово, ЕдинственнаяСтрокаВида.ТипСлова, ТаблицаТипов,, "Метаданные");
		КонецЦикла;
	КонецЕсли;
	Возврат ТаблицаСлов;
	
КонецФункции

Процедура СловаКонтекстаМетаданныеCOM(Знач Слово, Знач ТипСлова, Знач ИмяОбщегоТипаРодителя, Знач МетаданныеРодителя, Знач ТаблицаСлов) Экспорт
	Если Истина
		И (Ложь
			Или ТипЗнч(МетаданныеРодителя) = Тип("COMОбъект") 
			Или ТипЗнч(МетаданныеРодителя) = Тип("ВнешнийОбъект") 
			Или Найти(ИмяОбщегоТипаРодителя, " {") > 0)
		И ЛиИмяТипаComОбъекта(ИмяОбщегоТипаРодителя)
	Тогда 
		ИмяБиблиотеки = "";
		ИнфоТипа = ПолучитьИнфоТипаCOMОбъекта(МетаданныеРодителя, ИмяОбщегоТипаРодителя, ИмяБиблиотеки);
		Если ИнфоТипа <> Неопределено Тогда
			МассивИнфоТипа = ИнтерфейсыCOMОбъекта(ИнфоТипа, ИмяОбщегоТипаРодителя);
			Для Каждого ИнфоТипа Из МассивИнфоТипа Цикл
				Для Каждого Член Из ИнфоТипа.Members Цикл
					Если Член.AttributeMask = 1 Тогда
						// Это члены IDispatch
						Продолжить;
					КонецЕсли; 
					ИмяЧлена = Член.Name;
					Если Член.InvokeKind = 1 Или Член.Parameters.Count > 0 Тогда 
						ТипСловаЧленаКласса = "Метод";
					ИначеЕсли Член.InvokeKind = 2 Тогда //Get
						ТипСловаЧленаКласса = "Свойство";
					Иначе 
						Продолжить;
					КонецЕсли;
					Если Ложь
						Или Слово = Неопределено 
						Или Истина
						И ирОбщий.СтрокиРавныЛкс(Слово, ИмяЧлена)
						И ирОбщий.СтрокиРавныЛкс(ТипСлова, ТипСловаЧленаКласса) 
					Тогда
						СтруктураТипа = НоваяСтруктураТипа();
						СтруктураТипа.ИмяОбщегоТипа = ПолучитьТипЗначенияЧленаИнтерфейса(Член.ReturnType, ИмяБиблиотеки, ИнфоТипа.Parent);
						СтруктураТипа.СтрокаОписания = Член;
						СтруктураТипа.Метаданные = МетаданныеРодителя;
						ТаблицаТипов = ДобавитьВТаблицуТипов(, СтруктураТипа);
						ДобавитьВТаблицуСлов(ТаблицаСлов, ИмяЧлена, ТипСловаЧленаКласса, ТаблицаТипов,, "Метаданные");
					КонецЕсли; 
					Если Истина    
						И ТипСловаЧленаКласса = "Свойство"                               
						И Член.ReturnType.TypeInfo <> Неопределено
					Тогда 
						ТипСловаЧленаКласса = "Метод";
						Если Ложь
							Или Слово = Неопределено 
							Или (Истина
								И ирОбщий.СтрокиРавныЛкс(Слово, ИмяЧлена)
								И ирОбщий.СтрокиРавныЛкс(ТипСлова, ТипСловаЧленаКласса))
						Тогда 
							ИнфоТипаЧлена = Член.ReturnType.TypeInfo;
							Попытка
								ОписаниеЭлементаКоллекции = ИнфоТипаЧлена.GetMember("Item");
							Исключение
								ОписаниеЭлементаКоллекции = Неопределено;
							КонецПопытки;
							Если ОписаниеЭлементаКоллекции <> Неопределено Тогда 
								// Например ADODB.Connection.Properties("DBMS Name").Value
								СтруктураТипа = НоваяСтруктураТипа();
								СтруктураТипа.ИмяОбщегоТипа = ПолучитьТипЗначенияЧленаИнтерфейса(ОписаниеЭлементаКоллекции.ReturnType, ИмяБиблиотеки, ИнфоТипа.Parent);
								СтруктураТипа.СтрокаОписания = Член;
								СтруктураТипа.Метаданные = МетаданныеРодителя;
								ТаблицаТипов = ДобавитьВТаблицуТипов(, СтруктураТипа);
								ДобавитьВТаблицуСлов(ТаблицаСлов, ИмяЧлена, ТипСловаЧленаКласса, ТаблицаТипов,, "Метаданные");
							КонецЕсли;
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
			КонецЦикла;
		КонецЕсли; 
	КонецЕсли;
КонецПроцедуры

// Процедура - Слова контекста метаданные формы
//
// Параметры:
//  Слово					 - 	 - 
//  ИмяОбщегоТипаРодителя	 - 	 - 
//  МетаданныеРодителя		 - Форма, УправляемаяФорма, Структура, ТабличноеПоле, Панель, КнопкаКоманднойПанели, КнопкиКоманднойПанели - 
//  СтрокаОписанияВида		 - 	 - 
//  КоллекцияЗначений		 - 	 - 
//  СхемаКоллекции			 - 	 - 
//
Процедура СловаКонтекстаМетаданныеФормы(Знач Слово, Знач ИмяОбщегоТипаРодителя, Знач МетаданныеРодителя, Знач СтрокаОписанияВида, КоллекцияЗначений = Неопределено, СхемаКоллекции = Неопределено) Экспорт
	ДочерниеЭлементы = МетаданныеРодителя[СтрокаОписанияВида.ИмяКоллекции]; 
	Если ИмяОбщегоТипаРодителя = "ОформленияЯчеек" Тогда
		СхемаКоллекции = ДочерниеЭлементы;
	Иначе
		ИмитаторФормы = МетаданныеРодителя;
		Если ТипЗнч(МетаданныеРодителя) = ирОбщий.ТипУправляемаяФормаЛкс() Тогда
			//! ДочерниеЭлементы = 0 // ВсеЭлементыФормы
			КоллекцияЗначений = Новый Соответствие; 
			Если ЗначениеЗаполнено(Слово) Тогда
				ЦелевойЭлемент = ДочерниеЭлементы.Найти(Слово);
				ДочерниеЭлементы = Новый Массив;
				Если ЦелевойЭлемент <> Неопределено Тогда
					ДочерниеЭлементы.Добавить(ЦелевойЭлемент);
				КонецЕсли;
			КонецЕсли;
			Для Каждого ЭлементФормы Из ДочерниеЭлементы Цикл
				КоллекцияЗначений.Вставить(ЭлементФормы.Имя, ЭлементФормы);
			КонецЦикла;
			ИмитаторФормы = ирОбщий.СлужебныеДанныеФормыЛкс(МетаданныеРодителя);
		ИначеЕсли ТипЗнч(ИмитаторФормы) = Тип("Структура") Тогда 
			КоллекцияЗначений = Новый Соответствие; 
		Иначе 
			КоллекцияЗначений = ДочерниеЭлементы;
		КонецЕсли;
		Если Истина
			И ТипЗнч(ИмитаторФормы) = Тип("Структура") 
			И ИмитаторФормы.Свойство(СтрокаОписанияВида.ИмяКоллекции)
		Тогда
			// имитатор формы
			ЭлементыИзИмитатора = ИмитаторФормы[СтрокаОписанияВида.ИмяКоллекции]; // Структура
			Если ЗначениеЗаполнено(Слово) Тогда
				ЭлементыИзИмитатора.Свойство(Слово, ЦелевойЭлемент);
				ЭлементыИзИмитатора = Новый Структура;
				Если ЦелевойЭлемент <> Неопределено Тогда
					ЭлементыИзИмитатора.Вставить(Слово, ЦелевойЭлемент);
				КонецЕсли;
			КонецЕсли;
			Для Каждого КлючИЗначение Из ЭлементыИзИмитатора Цикл
				Если КоллекцияЗначений[КлючИЗначение.Ключ] <> Неопределено Тогда
					Продолжить;
				КонецЕсли;
				СтруктураЭлемента = КлючИЗначение.Значение;
				ЗначениеЭлемента = Новый ОписаниеТипов(ирОбщий.ЗначенияВМассивЛкс(СтруктураЭлемента.Тип));  //
				Если ЗначениеЗаполнено(Слово) Тогда
					ЗначениеЭлемента = ТаблицаТиповИзОписанияТипов(ЗначениеЭлемента);
					ЗначениеЭлемента[0].Метаданные = СтруктураЭлемента;
					ЗначениеЭлемента[0].ДержательМетаданных = ИмитаторФормы;
					ИмяОбщегоТипаРасширения = ИмяТипаРасширенияЭлементаФормы(ЗначениеЭлемента[0].ИмяОбщегоТипа, СтруктураЭлемента);
					Если ИмяОбщегоТипаРасширения <> Неопределено Тогда
						ЗначениеЭлемента[0].ИмяОбщегоТипа = ИмяОбщегоТипаРасширения;
					КонецЕсли;
				КонецЕсли;
				КоллекцияЗначений.Вставить(КлючИЗначение.Ключ, ЗначениеЭлемента);
			КонецЦикла;       
			Если ЗначениеЗаполнено(Слово) И КоллекцияЗначений[Слово] = Неопределено Тогда
				ДобавитьОтсутствиеЭлементаФормы(ИмитаторФормы, "Элемент:" + Слово);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
КонецПроцедуры

// Функция - Добавить в таблицу слов элементы глобальных модулей
//
// Параметры:
//  СтрокаОбщегоТипа			 - см. ТаблицаОбщихТиповИзСтруктурыТипа()[0] - 
// 
Функция ДобавитьВТаблицуСловЭлементыГлобальныхМодулей(Знач СтрокаОбщегоТипа, Знач Слово = Неопределено, Знач ТипСлова = Неопределено, Знач ВычислятьТипы = Истина, Знач ВычислятьТипыМетодовМодулей = Ложь,
	Знач ТолькоЭкспорт = Истина, Знач КлиентОбычноеПриложение = Истина, Знач КлиентУправляемоеПриложение = Истина, Знач НаСервере = Ложь, Знач ТаблицаСлов = Неопределено) Экспорт
	
	Если ТаблицаСлов = Неопределено Тогда
		ТаблицаСлов = НоваяТаблицаСлов();
	КонецЕсли;
	Если ПустаяСтрока(ТипСлова) Или ТипСлова = "Метод" Тогда
		// Глобальные общие модули
		СтруктураТипаМодуля = НоваяСтруктураТипа();
		СтруктураТипаМодуля.ИмяОбщегоТипа = "ОбщийМодуль";
		Для Каждого ОбщийМодульМД Из ирКэш.ГлобальныеОбщиеМодулиЛкс(НаСервере, КлиентОбычноеПриложение, КлиентУправляемоеПриложение) Цикл
			СтруктураТипаМодуля.Метаданные = ОбщийМодульМД;
			МодульМетаданныхКомпонента = ПодготовитьМодульМетаданных(СтруктураТипаМодуля);
			ДобавитьВТаблицуСловЭлементыМодуляМетаданных(СтрокаОбщегоТипа, Слово, "Метод", ТаблицаСлов, МодульМетаданныхКомпонента, ВычислятьТипыМетодовМодулей, ВычислятьТипы, ТолькоЭкспорт);
		КонецЦикла;
	КонецЕсли;
	СтруктураТипаМодуля = НоваяСтруктураТипа(СтрокаОбщегоТипа.ИмяОбщегоТипа);
	СтруктураТипаМодуля.Метаданные = СтрокаОбщегоТипа.Метаданные;
	Если КлиентОбычноеПриложение Тогда
		МодульМетаданныхКомпонента = ПодготовитьМодульМетаданных(СтруктураТипаМодуля, "МодульОбычногоПриложения");
		ДобавитьВТаблицуСловЭлементыМодуляМетаданных(СтрокаОбщегоТипа, Слово, ТипСлова, ТаблицаСлов, МодульМетаданныхКомпонента, ВычислятьТипыМетодовМодулей, ВычислятьТипы, ТолькоЭкспорт);
	КонецЕсли;
	Если КлиентУправляемоеПриложение Тогда
		МодульМетаданныхКомпонента = ПодготовитьМодульМетаданных(СтруктураТипаМодуля, "МодульУправляемогоПриложения");
		ДобавитьВТаблицуСловЭлементыМодуляМетаданных(СтрокаОбщегоТипа, Слово, ТипСлова, ТаблицаСлов, МодульМетаданныхКомпонента, ВычислятьТипыМетодовМодулей, ВычислятьТипы, ТолькоЭкспорт);
	КонецЕсли;
	Возврат ТаблицаСлов;
КонецФункции

Функция ИнтерфейсыCOMОбъекта(Знач ИнфоТипа, Знач ИмяОбщегоТипаРодителя) Экспорт
	МассивИнфоТипа = Новый Массив;
	Если Найти(ИмяОбщегоТипаРодителя, " {") > 0 Тогда
		ИнфоТипа = ИнфоТипа.Parent.TypeInfos.NamedItem(ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипаРодителя, " {"));
	КонецЕсли; 
	//Если ИмяCOMКласса = "" Тогда 
	//	Если Описатель.Parent.Name = "V" + ирКэш.НомерИзданияПлатформыЛкс() Тогда 
	//		ИмяОбщегоТипа = "COM-соединитель";
	//	КонецЕсли;
	//КонецЕсли; 
	Если ИнфоТипа = Неопределено Тогда
		//
	ИначеЕсли НРег(ИнфоТипа.TypeKindString) = "coclass" Тогда
		//! ИнфоТипа = 0 // TypeInfo {TLI.TLIApplication}
		МассивИнфоТипа = ИнфоТипа.Interfaces;
	ИначеЕсли НРег(ИнфоТипа.TypeKindString) = "enum" Тогда
		//
	Иначе
		//! ИнфоТипа = 0 // InterfaceInfo {TLI.TLIApplication}
		МассивИнфоТипа = Новый Массив;
		МассивИнфоТипа.Добавить(ИнфоТипа);
		Для Каждого ИнтерфейсОбъекта Из ИнфоТипа.ImpliedInterfaces Цикл
			МассивИнфоТипа.Добавить(ИнтерфейсОбъекта);
		КонецЦикла;
	КонецЕсли;
	Возврат МассивИнфоТипа;
КонецФункции

// Помогает обновлять кэш управляемой формы из конфигуратора при следующем вызове автодополнения
// Параметры:
//    ФормаИлиСтруктура - Форма, Структура - 
//    Ключ - Строка - 
Процедура ДобавитьОтсутствиеЭлементаФормы(Знач ФормаИлиСтруктура, Знач Ключ) Экспорт
	СлужебныеДанные = ирОбщий.СлужебныеДанныеФормыЛкс(ФормаИлиСтруктура);  
	ОтсутствуютЭлементы = Неопределено;
	Если Не СлужебныеДанные.Свойство("ОтсутствуютЭлементы", ОтсутствуютЭлементы) Тогда
		ОтсутствуютЭлементы = Новый Соответствие;
		СлужебныеДанные.Вставить("ОтсутствуютЭлементы", ОтсутствуютЭлементы);
	КонецЕсли;
	Если ОтсутствуютЭлементы[Ключ] = Неопределено Тогда
		ОтсутствуютЭлементы[Ключ] = 1;
		СлужебныеДанные.Вставить("ДатаОбновления", Дата(1,1,1));
	КонецЕсли;
КонецПроцедуры

Функция ТаблицаТиповЭлементовКоллекции(Знач РодительскаяСтруктураТипа, Знач ТекстИндексаЭлемента = "", Знач ЯзыкПрограммы = 0, Знач ТаблицаТипов = Неопределено) Экспорт 
	
	НужнаПроверкаТипов = Истина; 
	МетаданныеКоллекции = РодительскаяСтруктураТипа.Метаданные; // Массив
	Если Истина
		И ТипЗнч(МетаданныеКоллекции) = Тип("Массив")
		И МетаданныеКоллекции.Количество() > 0
		И (Ложь
			Или ирОбщий.ПервыйФрагментЛкс(РодительскаяСтруктураТипа.ИмяОбщегоТипа, "[") = "Массив" 
			Или ирОбщий.ПервыйФрагментЛкс(РодительскаяСтруктураТипа.ИмяОбщегоТипа, "[") = "ФиксированныйМассив")
	Тогда
		ТаблицаТипов = ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипаИзЗначения(МетаданныеКоллекции[0]));
	ИначеЕсли Истина
		И ТипЗнч(МетаданныеКоллекции) = Тип("ТаблицаЗначений")
		И МетаданныеКоллекции.Количество() > 0
		И (Ложь
			Или ирОбщий.ПервыйФрагментЛкс(РодительскаяСтруктураТипа.ИмяОбщегоТипа, "[") = "Структура" 
			Или ирОбщий.ПервыйФрагментЛкс(РодительскаяСтруктураТипа.ИмяОбщегоТипа, "[") = "ФиксированнаяСтруктура")
	Тогда
		СтруктураТипаЭлемента = НоваяСтруктураТипа("КлючИЗначение");
		СтруктураТипаЭлемента.Метаданные = Новый Структура("Значение", МетаданныеКоллекции);
		ТаблицаТипов = ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипаЭлемента);
	ИначеЕсли Истина
		И ТипЗнч(МетаданныеКоллекции) = Тип("Структура")
		И РодительскаяСтруктураТипа.ИмяОбщегоТипа = "Соответствие"
	Тогда
		СтруктураТипаЭлемента = НоваяСтруктураТипа("КлючИЗначение");
		СтруктураТипаЭлемента.Метаданные = МетаданныеКоллекции;
		ТаблицаТипов = ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипаЭлемента);
	ИначеЕсли Истина
		И ТипЗнч(МетаданныеКоллекции) = Тип("Структура")
		И РодительскаяСтруктураТипа.ИмяОбщегоТипа = "СписокЗначений"
	Тогда
		СтруктураТипаЭлемента = НоваяСтруктураТипа("ЭлементСпискаЗначений");
		СтруктураТипаЭлемента.Метаданные = МетаданныеКоллекции;
		ТаблицаТипов = ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипаЭлемента);
	Иначе 
		ТипыЭлементовКоллекции = ТипыЭлементовКоллекции(РодительскаяСтруктураТипа, ЯзыкПрограммы, НужнаПроверкаТипов);
		Если ТипыЭлементовКоллекции.Количество() > 0 Тогда
			Если ТаблицаТипов = Неопределено Тогда
				ТаблицаТипов = НоваяТаблицаТипов(); 
			КонецЕсли;
			ТипТип = Тип("Тип");
			Для Каждого БазовыйТипЭлемента Из ТипыЭлементовКоллекции Цикл
				Если ТипЗнч(БазовыйТипЭлемента) = ТипТип Тогда
					КонкретныйТип = БазовыйТипЭлемента;
				Иначе
					Попытка
						КонкретныйТип = Тип(БазовыйТипЭлемента);
					Исключение
						КонкретныйТип = Неопределено;
					КонецПопытки;
				КонецЕсли;
				Если КонкретныйТип <> Неопределено Тогда
					СтруктураТипаЭлемента = СтруктураТипаИзКонкретногоТипа(КонкретныйТип);
				Иначе
					СтруктураТипаЭлемента = НоваяСтруктураТипа();
					СтруктураТипаЭлемента.ИмяОбщегоТипа = БазовыйТипЭлемента; 
					СтруктураТипаЭлемента.Метаданные = мМетаданные;
				КонецЕсли;
				Если ТипЗнч(СтруктураТипаЭлемента.Метаданные) = Тип("ОбъектМетаданныхКонфигурация") Тогда
					СтруктураТипаЭлемента.Метаданные = МетаданныеКоллекции;
				КонецЕсли;
				СтруктураТипаЭлемента.ДержательМетаданных = РодительскаяСтруктураТипа.ДержательМетаданных;
				Если КонкретныйТип = Неопределено И НужнаПроверкаТипов Тогда
					СтруктураКлюча = Новый Структура("БазовыйТип, ЯзыкПрограммы", БазовыйТипЭлемента, ЯзыкПрограммы);
					НайденныеСтроки = ТаблицаОбщихТипов.НайтиСтроки(СтруктураКлюча);
					Если НайденныеСтроки.Количество() > 0 Тогда
						СтруктураТипаЭлемента.СтрокаОписания = НайденныеСтроки[0];
						СтруктураТипаЭлемента.ИмяОбщегоТипа  = НайденныеСтроки[0].Слово;
						Если ТипЗнч(МетаданныеКоллекции) <> Тип("КоллекцияОбъектовМетаданных") Тогда
							СтруктураТипаЭлемента.Метаданные = МетаданныеКоллекции;
						КонецЕсли; 
					КонецЕсли;
				КонецЕсли;
				Если ТипЗнч(МетаданныеКоллекции) = Тип("ПостроительЗапроса") Тогда 
					ПостроительЗапроса = МетаданныеКоллекции;
					Попытка
						ИндексВПакете = Число(ТекстИндексаЭлемента);
					Исключение
						ИндексВПакете = Неопределено;
					КонецПопытки;
					Если ИндексВПакете <> Неопределено И ЗначениеЗаполнено(МетаданныеКоллекции.Текст) Тогда
						ТекстыЗапросов = РазбитьГрубоТекстПакетногоЗапросаНаЗапросы(МетаданныеКоллекции.Текст);   
						#Если Сервер И Не Сервер Тогда
							ТекстыЗапросов = Новый Массив;
						#КонецЕсли
						ПостроительЗапроса = ПостроительПакетаЗапросовДоИндекса(ТекстыЗапросов, ИндексВПакете, МетаданныеКоллекции.Параметры);
						Если ПостроительЗапроса <> Неопределено Тогда
							СтруктураТипаЭлемента.Метаданные = ПостроительЗапроса;
							МенеджерВременныхТаблиц = РодительскаяСтруктураТипа.ДержательМетаданных; // см. Обработки.ирКлсПолеТекстаПрограммы.Создать().НовыйМенеджерВременныхТаблиц()
							ПоследнийПакетЗапросов = МенеджерВременныхТаблиц.ПакетыЗапросов[МенеджерВременныхТаблиц.ПакетыЗапросов.ВГраница()];  // см. Обработки.ирКлсПолеТекстаПрограммы.Создать().НовыйПакетЗапросов()
							ПоследнийПакетЗапросов = ирОбщий.СкопироватьКоллекциюЛкс(ПоследнийПакетЗапросов);
							ПоследнийПакетЗапросов.Вставить("ИндексВПакете", ИндексВПакете);
							СтруктураТипаЭлемента.ДержательМетаданных = ПоследнийПакетЗапросов;
						КонецЕсли;
					КонецЕсли; 
				КонецЕсли;
				ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипаЭлемента);
			КонецЦикла;
		Иначе
			ТаблицаТипов = ДобавитьВТаблицуТипов(ТаблицаТипов, НоваяСтруктураТипа());
		КонецЕсли; 
	КонецЕсли;
	Возврат ТаблицаТипов;

КонецФункции

Функция ПараметрыИзТекстаЗапроса(Знач ТекстЗапроса, Знач ВВидеСтруктуры = Ложь, Знач СтруктураПриемник = Неопределено) Экспорт
	Запрос = Новый Запрос(ТекстЗапроса);
	Попытка
		ПараметрыЗапроса = Запрос.НайтиПараметры();
	Исключение
		ПараметрыЗапроса = Новый Массив;
	КонецПопытки;            
	Если ВВидеСтруктуры Тогда
		Результат = СтруктураПриемник;
		Если СтруктураПриемник = Неопределено Тогда
			Результат = Новый Структура;
		КонецЕсли;
		Если ПараметрыЗапроса <> Неопределено Тогда
			Для Каждого ОписаниеПараметра Из ПараметрыЗапроса Цикл
				Результат.Вставить(ОписаниеПараметра.Имя, ТаблицаТиповИзОписанияТипов(ОписаниеПараметра.ТипЗначения));
			КонецЦикла;
		КонецЕсли;
	Иначе
		Результат = ПараметрыЗапроса;
	КонецЕсли;
	Возврат Результат;
КонецФункции

//.
// Параметры:
//    ТекстЗапроса - Строка - 
// Возвращаемое значение:
//    ПостроительЗапроса - 
Функция ПостроительЗапросаИзТекстаДляТипа(Знач ТекстЗапроса, Знач ПостроительЗапроса = Неопределено) Экспорт
	Если ПостроительЗапроса = Неопределено Тогда
		ПостроительЗапроса = Новый ПостроительЗапроса;
	КонецЕсли;
	Попытка
		ПостроительЗапроса.Текст = ТекстЗапроса;
	Исключение
		// Даже если текст некорректный, он сохраняется в свойстве
	КонецПопытки; 
	ПараметрыИзТекстаЗапроса(ТекстЗапроса, Истина, ПостроительЗапроса.Параметры);
	Возврат ПостроительЗапроса;  
КонецФункции

// Функция - Построитель пакета запросов до индекса включительно
//
// Параметры:
//  ТекстыЗапросов		 - Массив - 
//  ИндексЭлемента		 - 	 - 
//  ИмяРождаемойТаблицы	 -  - 
//  Параметры			 - Структура - 
// 
// Возвращаемое значение:
//   - 
//
Функция ПостроительПакетаЗапросовДоИндекса(Знач ТекстыЗапросов, Знач ИндексЭлемента, Знач Параметры, Знач ИмяРождаемойТаблицы = "") Экспорт 
	ТекстЗапроса = "";
	Если ТекстыЗапросов.Количество() <= ИндексЭлемента Тогда
		Возврат Неопределено;
	КонецЕсли;
	ТекстыЗапросов = ирОбщий.СкопироватьКоллекциюЛкс(ТекстыЗапросов);
	Если ЗначениеЗаполнено(ИмяРождаемойТаблицы) Тогда
		// Построитель сначала ищет последний запрос выборки, а затем создания. Поэтому сделаем последний запрос выборкой.
		ТекстЗапроса = ТекстыЗапросов[ИндексЭлемента];
		Если Найти(ТекстЗапроса, "ИНДЕКСИРОВАТЬ ПО") = 0 Тогда
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПОМЕСТИТЬ " + ИмяРождаемойТаблицы, "");
			ТекстыЗапросов[ИндексЭлемента] = ТекстЗапроса;
		КонецЕсли;
	КонецЕсли;
	ТекстЗапроса = ирОбщий.СтрСоединитьЛкс(ТекстыЗапросов, Символы.ПС, ИндексЭлемента + 1);
	Если Лев(ТекстЗапроса, 1) = """" Тогда
		ТекстЗапроса = ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(ТекстЗапроса);
	КонецЕсли;
	ПостроительЗапроса = Новый ПостроительЗапроса;
	ирОбщий.СкопироватьКоллекциюЛкс(Параметры, ПостроительЗапроса.Параметры);
	Попытка
		ПостроительЗапроса.Текст = ТекстЗапроса; // Текст в любом случае установится, но еще может быть выброшено исключение
	Исключение
	КонецПопытки;
	ПодготовитьМетаданныеПостроителяЗапроса(ПостроительЗапроса);
	Возврат ПостроительЗапроса;
КонецФункции

//.
// Параметры:
//    ТекстЗапроса - Строка - 
//    Параметры - Структура -  
Функция ДобавитьВременныеТаблицыПараметровВТекстЗапроса(ТекстЗапроса, Знач Параметры) Экспорт
	ПрефиксСлужебнойТаблицы = "ъ_";
	//Если Найти(ТекстЗапроса, "ПОМЕСТИТЬ " + ПрефиксСлужебнойТаблицы) > 0 Тогда
	//	Возврат "";
	//КонецЕсли;
	СлужебныеЗапросы = Новый Массив;
	ИменаСлужебныхЗапросов = Новый Массив;
	Для Каждого КлючИЗначение Из Параметры Цикл
		ЗначениеПараметра = ПодготовитьЗначениеПараметраЗапроса(КлючИЗначение.Значение);
		Если ТипЗнч(ЗначениеПараметра) = Тип("ТаблицаЗначений") Тогда
			ТекстСлужебногоЗапроса = ирОбщий.ТекстЗапросаПоместитьИзПараметраЛкс(ПрефиксСлужебнойТаблицы + КлючИЗначение.Ключ, КлючИЗначение.Ключ, Истина, ЗначениеПараметра.Колонки,, Истина);
			СлужебныеЗапросы.Добавить(ТекстСлужебногоЗапроса);
			ИменаСлужебныхЗапросов.Добавить(КлючИЗначение.Ключ);
		КонецЕсли;
	КонецЦикла;
	Если СлужебныеЗапросы.Количество() > 0 Тогда
		НовыйТекст = ТекстЗапроса;
		Для Каждого ИмяТаблицы Из ИменаСлужебныхЗапросов Цикл
			НовыйТекст = СтрЗаменить(НовыйТекст, "&" + ИмяТаблицы, ПрефиксСлужебнойТаблицы + ИмяТаблицы); // TODO избавиться от чувствительности к регистру
		КонецЦикла;
		НовыйТекст = ирОбщий.СтрСоединитьЛкс(СлужебныеЗапросы, ";" + Символы.ПС) + ";" + Символы.ПС + НовыйТекст;
	КонецЕсли;
	Возврат НовыйТекст;
КонецФункции

Функция ПодготовитьЗначениеПараметраЗапроса(Знач ЗначениеПараметра, выхОписаниеТипов = Неопределено) Экспорт
	Если Истина
		И ТипЗнч(ЗначениеПараметра) = Тип("ТаблицаЗначений") 
		И ЗначениеПараметра.Колонки.Найти(ИмяКолонкиФлагаВнутриТаблицы()) <> Неопределено
	Тогда
		выхОписаниеТипов = ОписаниеТиповИзТаблицыТипов(ЗначениеПараметра);
		ЛучшийТип = Неопределено; // см. НоваяСтруктураТипа()
		Если ЛиДетальностьТиповДостаточна(ЗначениеПараметра, 5, Истина, ЛучшийТип) Тогда 
			ЗначениеПараметра = ЛучшийТип.Метаданные;
		Иначе
			ЗначениеПараметра = выхОписаниеТипов.ПривестиЗначение();
		КонецЕсли;
	КонецЕсли;
	Если ТипЗнч(ЗначениеПараметра) = Тип("Структура") Тогда
		ТаблицаЗначений = Новый ТаблицаЗначений;
		Для Каждого ОписаниеКолонки Из ЗначениеПараметра Цикл
			ТаблицаЗначений.Колонки.Добавить(ОписаниеКолонки.Ключ, ОписаниеТиповИзТаблицыТипов(ОписаниеКолонки.Значение));
		КонецЦикла;
		ЗначениеПараметра = ТаблицаЗначений;
	КонецЕсли;
	Возврат ЗначениеПараметра;
КонецФункции

// Процедура - Подготовить выбранные поля построителя
//
// Параметры:
//  ПостроительЗапроса		 - ПостроительЗапроса - 
//  ДержательМетаданных	 - см. ОбработкаОбъект.ирКлсПолеТекстаПрограммы.НовыйМенеджерВременныхТаблиц() -  
//
Процедура ПодготовитьМетаданныеПостроителяЗапроса(Знач ПостроительЗапроса, Знач ДержательМетаданных = Неопределено) Экспорт  
	
	Если ПостроительЗапроса.ВыбранныеПоля.Количество() = 0 Тогда 
		Попытка
			ПостроительЗапроса.ЗаполнитьНастройки();
		Исключение
		КонецПопытки;
	КонецЕсли;
	Если ПостроительЗапроса.ВыбранныеПоля.Количество() = 0 И ирКэш.ДоступноСхемаЗапросаЛкс() Тогда
		Текст = ПостроительЗапроса.Текст;
		НовыйТекст = ДобавитьВременныеТаблицыПараметровВТекстЗапроса(Текст, ПостроительЗапроса.Параметры);
		Если ЗначениеЗаполнено(НовыйТекст) Тогда
			Текст = НовыйТекст;
		КонецЕсли;
		Если Истина
			И ДержательМетаданных <> Неопределено
			И ДержательМетаданных.Тип = Тип("МенеджерВременныхТаблиц") 
			//И ДержательМетаданных.Активен 
		Тогда
			ТекстыПакетов = Новый Массив;
			Для Индекс = 0 По ДержательМетаданных.ПакетыЗапросов.ВГраница() - 1 Цикл
				ТекстыПакетов.Добавить(ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(ДержательМетаданных.ПакетыЗапросов[Индекс].Текст));
			КонецЦикла;
			ТекстыПакетов.Добавить(Текст);
			Текст = ирОбщий.СтрСоединитьЛкс(ТекстыПакетов, ";" + Символы.ПС);
		КонецЕсли;
		Попытка
			ПустаяТаблица = ирОбщий.ПустаяТаблицаЗначенийИзТекстаЗапросаЛкс(Текст,, Истина);
		Исключение
			Возврат;
		КонецПопытки;
		ПостроительЗапроса.ИсточникДанных = Новый ОписаниеИсточникаДанных(ПустаяТаблица);
		ПостроительЗапроса.ЗаполнитьНастройки();
	КонецЕсли;

КонецПроцедуры

Функция ЛиИмяТипаComОбъекта(ИмяОбщегоТипа) Экспорт 
	
	Результат = Ложь
		Или ирОбщий.СтрокиРавныЛкс(ИмяОбщегоТипа, "COMОбъект")
		Или Найти(ИмяОбщегоТипа, " {") > 0;
	Возврат Результат;

КонецФункции

Функция ДобавитьВТаблицуСловЭлементыМодуляМетаданных(Знач СтруктураТипаМини, Знач Слово = Неопределено, Знач ТипСлова = Неопределено, Знач ТаблицаСловПриемник = Неопределено,
	Знач МодульМетаданных, Знач ВычислятьТипыМетодовМодулей = Ложь, Знач ВычислятьТипы = Истина, Знач ТолькоЭкспорт = Истина, Знач ФлагиКомпиляции = Неопределено,
	Знач ВнутриГруппыОбщихМодулей = Ложь, Знач ДляСвойства = "", Знач ЛиВместеСЛокальнымКонтекстом = Ложь) Экспорт 
	
	Если Истина
		И СтруктураТипаМини.ИмяОбщегоТипа <> "Глобальный" 
		И Не ВнутриГруппыОбщихМодулей 
	Тогда
		ЛиСеансТолстогоКлиентаУП = ирКэш.ЛиСеансТолстогоКлиентаУПЛкс();
		НаСервере = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "Сервер", Истина);
		БезКонтекста = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "БезКонтекста", Ложь);
		КлиентОбычноеПриложение = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "КлиентОбычноеПриложение", Не ЛиСеансТолстогоКлиентаУП);
		КлиентУправляемоеПриложение = ирОбщий.СвойствоСтруктурыЛкс(ФлагиКомпиляции, "КлиентУправляемоеПриложение", ЛиСеансТолстогоКлиентаУП);
		КлючКэша = "" + ТолькоЭкспорт + ";" + НаСервере + ";" + БезКонтекста + ";" + КлиентОбычноеПриложение + ";" + КлиентУправляемоеПриложение;
		ТаблицаИзКэша = МодульМетаданных.ТаблицыСлов[КлючКэша]; // см. НоваяТаблицаСлов()
		Если Истина
			И Не ВычислятьТипыМетодовМодулей 
			И Слово = Неопределено
			И ТипСлова = Неопределено
			И Не ЗначениеЗаполнено(ДляСвойства)
		Тогда
			Если ТаблицаИзКэша <> Неопределено Тогда
				Если ТаблицаИзКэша.Количество() > ТаблицаСловПриемник.Количество() Тогда
					ТаблицаИзКэша = ТаблицаИзКэша.Скопировать();
					ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(ТаблицаСловПриемник, ТаблицаИзКэша);
					ТаблицаСловПриемник = ТаблицаИзКэша;
				Иначе
					ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(ТаблицаИзКэша, ТаблицаСловПриемник);
				КонецЕсли;
				Возврат ТаблицаСловПриемник;
			КонецЕсли;
		Иначе
			КлючКэша = Неопределено;
		КонецЕсли;
	КонецЕсли;
	Если ТаблицаСловПриемник = Неопределено Или КлючКэша <> Неопределено Тогда
		ТаблицаСлов = НоваяТаблицаСлов();
	Иначе
		ТаблицаСлов = ТаблицаСловПриемник;
	КонецЕсли;
	МетаданныеРодителя = СтруктураТипаМини.Метаданные; // см. Метаданные.ОбщиеМодули[0]
	ОтборСловМодуля = Новый Структура; 
	Если ТолькоЭкспорт Тогда
		ОтборСловМодуля.Вставить("ЛиЭкспорт", Истина);
	КонецЕсли;
	Если ЗначениеЗаполнено(Слово) Тогда
		ОтборСловМодуля.Вставить("НИмя", НРег(Слово));
	КонецЕсли; 
	Если Истина
		И (Ложь
			Или ФлагиКомпиляции = Неопределено 
			Или Не ФлагиКомпиляции.БезКонтекста)
		И (Ложь
			Или ТипСлова = Неопределено
			Или ТипСлова = "Свойство")
	Тогда
		ПеременныеМодуля = МодульМетаданных.Переменные;
		#Если Сервер И Не Сервер Тогда
			ПеременныеМодуля = Новый ТаблицаЗначений;
		#КонецЕсли
		Если ОтборСловМодуля.Количество() > 0 Тогда
			ПодходящиеПеременные = ПеременныеМодуля.НайтиСтроки(ОтборСловМодуля);
		Иначе
			ПодходящиеПеременные = ПеременныеМодуля;
		КонецЕсли; 
		КомпонентаПодсказки = Неопределено;
		ТипСловаЦикл = "Свойство";
		Для Каждого ПеременнаяМодуля Из ПодходящиеПеременные Цикл
			Если Истина
				И Не ЗначениеЗаполнено(Слово) 
				И ПеременнаяМодуля.ПозицияСОписанием = 0 
			Тогда
				Продолжить;
			КонецЕсли;
			ТаблицаТипов = Неопределено; 
			Если ВычислятьТипы Тогда
				Если ВычислятьТипыМетодовМодулей Тогда
					ТаблицаТипов = ПодготовитьТипЗначенияПеременнойМодуля(ПеременнаяМодуля, МодульМетаданных, КомпонентаПодсказки, ДляСвойства); 
				КонецЕсли;
				ТаблицаТипов = ТаблицаТиповСловаМодуля(ПеременнаяМодуля, МодульМетаданных, ТаблицаТипов);
			КонецЕсли;
			ДобавитьВТаблицуСловЭлементМодуляМетаданных(ТаблицаСлов, ПеременнаяМодуля.Имя, ВычислятьТипы, ТаблицаИзКэша, ТаблицаТипов, ПеременнаяМодуля.ТипЗначения, ТипСловаЦикл);
		КонецЦикла;
	КонецЕсли; 
	Если Истина
		И Не ТолькоЭкспорт 
		И ФлагиКомпиляции <> Неопределено 
		И ЛиИмяМодуляФормы(МодульМетаданных.Имя)
	Тогда 
		//Если ФлагиКомпиляции.Сервер Тогда 
		//	ОтборСловМодуля.Вставить("Сервер", Истина);
		//КонецЕсли;
		//Если ФлагиКомпиляции.КлиентОбычноеПриложение Или ФлагиКомпиляции.КлиентУправляемоеПриложение Тогда 
		//	ОтборСловМодуля.Вставить("Клиент", Истина);
		//КонецЕсли;
		Если Не (ФлагиКомпиляции.КлиентОбычноеПриложение Или ФлагиКомпиляции.КлиентУправляемоеПриложение) Тогда 
			ОтборСловМодуля.Вставить("Клиент", Ложь);
		КонецЕсли;
		Если ФлагиКомпиляции.БезКонтекста Тогда 
			ОтборСловМодуля.Вставить("БезКонтекста", Истина);
		КонецЕсли;
	КонецЕсли; 
	Если Ложь
		Или ТипСлова = Неопределено
		Или ТипСлова = "Метод"
	Тогда
		МетодыМодуля = МодульМетаданных.Методы;
		#Если Сервер И Не Сервер Тогда
			МетодыМодуля = Новый ТаблицаЗначений;
		#КонецЕсли
		Если ОтборСловМодуля.Количество() > 0 Тогда
			ПодходящиеМетоды = МетодыМодуля.НайтиСтроки(ОтборСловМодуля);
			Если Истина
				И Не ЛиВместеСЛокальнымКонтекстом
				И ПодходящиеМетоды.Количество() = 0 
				И ЗначениеЗаполнено(Слово) 
				И СтруктураТипаМини.ИмяОбщегоТипа <> "Глобальный"
			Тогда
				ОтборСловМодуля.Вставить("НИмя", "<>");
				ПодходящиеМетоды = МетодыМодуля.НайтиСтроки(ОтборСловМодуля);
			КонецЕсли; 
		Иначе
			ПодходящиеМетоды = МетодыМодуля;
		КонецЕсли; 
		ВычислятьТипы = Ложь
			Или ЗначениеЗаполнено(Слово)
			Или ВычислятьТипы;
		Если ЗначениеЗаполнено(Слово) Тогда
			ВычислятьТипыМетодовМодулей = Истина;
		КонецЕсли; 
		Если ВычислятьТипыМетодовМодулей И ПодходящиеМетоды.Количество() > 100 Тогда
			Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ПодходящиеМетоды.Количество(), "Вычисление типов функций");
		Иначе
			Индикатор = Неопределено;
		КонецЕсли; 
		ТипСловаЦикл = "Метод";
		РазделительВариантаКонтекста = РазделительВариантаКонтекста();
		Для Каждого МетодМодуля Из ПодходящиеМетоды Цикл
			Если Индикатор <> Неопределено Тогда
				ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
			КонецЕсли;
			ИмяМетода = МетодМодуля.Имя;
			Если ИмяМетода = "<>" И Не ЗначениеЗаполнено(Слово) Тогда
				Продолжить;
			КонецЕсли;
			Если ВнутриГруппыОбщихМодулей Тогда
				ИмяМетода = ИмяМетода + " - " + МетаданныеРодителя.Имя;
			КонецЕсли;
			ТаблицаТипов = Неопределено;
			Если ВычислятьТипы Тогда
				Если ВычислятьТипыМетодовМодулей Тогда
					ТаблицаТипов = ПодготовитьТипРезультатаМетода(МетодМодуля, МодульМетаданных,,, ДляСвойства); 
				КонецЕсли;
				ТаблицаТипов = ТаблицаТиповСловаМодуля(МетодМодуля, МодульМетаданных, ТаблицаТипов);
			КонецЕсли;
			ДобавитьВТаблицуСловЭлементМодуляМетаданных(ТаблицаСлов, ИмяМетода, ВычислятьТипы, ТаблицаИзКэша, ТаблицаТипов, МетодМодуля.ТипЗначения, ТипСловаЦикл);
		КонецЦикла;
		Если Индикатор <> Неопределено Тогда
			ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
		КонецЕсли; 
	КонецЕсли;
	Если КлючКэша <> Неопределено Тогда
		МодульМетаданных.ТаблицыСлов[КлючКэша] = ТаблицаСлов;
		Если ТаблицаСловПриемник.Количество() > ТаблицаСлов.Количество() Тогда
			ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(ТаблицаСлов, ТаблицаСловПриемник);
		Иначе
			ТаблицаСлов = ТаблицаСлов.Скопировать();
			ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(ТаблицаСловПриемник, ТаблицаСлов);
			ТаблицаСловПриемник = ТаблицаСлов;
		КонецЕсли;
	КонецЕсли;
	Возврат ТаблицаСловПриемник;

КонецФункции

Функция ДобавитьВТаблицуСловЭлементМодуляМетаданных(Знач ТаблицаСлов, Знач Слово, Знач ВычислятьТипы, Знач ТаблицаИзКэша, Знач ТаблицаТипов, Знач ТипЗначения, Знач ТипСлова) Экспорт
	Если Слово <> "<>" Тогда
		Если Истина
			И ВычислятьТипы 
			И ТаблицаИзКэша <> Неопределено 
		Тогда
			Если Найти(ТипЗначения, "см.") > 0 Тогда
				ТипЗначения = ПредставлениеМассиваСтруктурТипов(ТаблицаТипов);
			КонецЕсли;
			Если Не ирОбщий.СтрНачинаетсяСЛкс(ТипЗначения, "??") Тогда
				ТипЗначения = "??" + ?(ПустаяСтрока(ТипЗначения), "", "," + ТипЗначения);
			КонецЕсли;
			КлючПоиска = Новый Структура("Слово, ТипСлова", Слово, ТипСлова);
			Найденные = ТаблицаИзКэша.НайтиСтроки(КлючПоиска);
			Если Найденные.Количество() > 0 Тогда
				Найденные[0].ТипЗначения = ТипЗначения;
			КонецЕсли;
		Иначе
			Если Не ирОбщий.СтрНачинаетсяСЛкс(ТипЗначения, "??") Тогда
				ТипЗначения = "??" + ?(ПустаяСтрока(ТипЗначения), "", "," + ТипЗначения);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	ДобавитьВТаблицуСлов(ТаблицаСлов, Слово, ТипСлова, ТаблицаТипов, ТипЗначения, "Метаданные");
	Возврат ТипЗначения;
КонецФункции

Функция РазделительВариантаКонтекста() Экспорт 
	Возврат " - ";
КонецФункции

//.
// Параметры:
//    МетодМодуля - СтрокаТаблицыЗначений - 
// Возвращаемое значение:
//    ТаблицаЗначений - 
Функция ТаблицаТиповСловаМодуля(Знач СловоМодуля, Знач МодульМетаданных, Знач ТаблицаТипов = Неопределено) Экспорт
	Если ТаблицаТипов = Неопределено Тогда
		ТаблицаТипов = СловоМодуля.ТаблицаТипов;
	КонецЕсли;
	Если ТаблицаТипов = Неопределено Тогда
		ТаблицаТипов = НоваяТаблицаТипов();
	ИначеЕсли СловоМодуля.ТаблицаТипов = ТаблицаТипов Тогда
		ТаблицаТипов = ТаблицаТипов.Скопировать(); // Мультиметка4529884 против циклической ссылки
	КонецЕсли;
	Если ТаблицаТипов.Количество() = 0 Тогда
		СтруктураТипа = ТаблицаТипов.Добавить();
		Если ЗначениеЗаполнено(СловоМодуля.ТипЗначения) Тогда
			Если СловоМодуля.Имя = "<>" Тогда
				СтруктураТипа.ИмяОбщегоТипа = СловоМодуля.ТипЗначения;
			Иначе
				СтруктураТипа.ИмяОбщегоТипа = "??";  // в этом варианте некрасиво выглядит тип результата ирОбщий.НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс()
				//СтруктураТипа.ИмяОбщегоТипа = "?"; // так сломается вычисление типов методов в Обработка.ирКлсПолеТекстаПрограммы.Форма.МетодыМодулей
			КонецЕсли;                                          
		КонецЕсли;
		ОбновитьДетальностьСтруктурыТипа(СтруктураТипа);
	КонецЕсли; 
	ТаблицаТипов.ЗаполнитьЗначения(СловоМодуля, "СтрокаОписания"); // Мультиметка4529884 против циклической ссылки
	СловоМодуля.ИмяМодуля = МодульМетаданных.Имя;
	Возврат ТаблицаТипов; 
КонецФункции

Функция ПодготовитьМодульМетаданных(Знач СтруктураТипа, Знач ТипМодуля = "", выхИмяМодуля = "", Знач НовыйТекст = Неопределено, Знач ТекущаяПозиция = Неопределено) Экспорт 
	
	ВерсияФормата = ВерсияФорматаКэшаМодулей();
	СтрокаСозданияРодителя = "";
	ФлагиКомпиляции = Неопределено; // см. НовыеФлагиКомпиляции()
	выхИмяМодуля = ИмяМодуляИзСтруктурыТипа(СтруктураТипа, ТипМодуля, СтрокаСозданияРодителя, ФлагиКомпиляции);
	Если ЗначениеЗаполнено(выхИмяМодуля) Тогда
		Если мМодулиМетаданных = Неопределено Тогда
			мМодулиМетаданных = Новый Соответствие;
		КонецЕсли; 
		МодульМетаданных = МодульМетаданныхИзКэша(выхИмяМодуля);
		Если Ложь
			Или МодульМетаданных = Неопределено 
			Или НовыйТекст <> Неопределено И МодульМетаданных.Текст <> НовыйТекст
		Тогда
			//ПроверитьСтруктуруФайловогоКэша();
			#Если Сервер И Не Сервер Тогда
				ПапкаКэшаМодулей = Новый Файл;
			#КонецЕсли
			ФайлМодуля = ФайлМодуляИзИмениМодуля(выхИмяМодуля);
			ТекстовыйДокумент = Новый ТекстовыйДокумент;
			СтарыйТекст = Неопределено;
			Если НовыйТекст <> Неопределено Тогда 
				Если МодульМетаданных <> Неопределено Тогда
					СтарыйТекст = МодульМетаданных.Текст;
				КонецЕсли;
				Если СтарыйТекст = Неопределено И ФайлМодуля.Существует() Тогда
					ТекстовыйДокумент.Прочитать(ФайлМодуля.ПолноеИмя);
					СтарыйТекст = ТекстовыйДокумент.ПолучитьТекст();
				КонецЕсли;
				Если СтарыйТекст <> НовыйТекст Тогда
					ТекстовыйДокумент.УстановитьТекст(НовыйТекст);
					Для Счетчик = 1 По 2 Цикл
						Попытка
							Если ирКэш.НомерРежимаСовместимостиЛкс() > 803018 Тогда
								ТекстовыйДокумент.ЗаписатьАсинх(ФайлМодуля.ПолноеИмя);
							Иначе
								ТекстовыйДокумент.Записать(ФайлМодуля.ПолноеИмя);
							КонецЕсли;
							Прервать;
						Исключение    
							Если Счетчик = 2 Тогда
								ВызватьИсключение;
							КонецЕсли;
							СоздатьКаталог(ФайлМодуля.Путь); // Нужно для подкаталогов расширений 23мс
						КонецПопытки;
					КонецЦикла;
				КонецЕсли;     
			КонецЕсли;
			ФайлОписанияМодуля = ФайлМодуляИзИмениМодуля(выхИмяМодуля, "ixd");
			ОбновитьФайлОписания = Истина;
			Если ФайлОписанияМодуля.Существует() Тогда
				МодульМетаданных = ирОбщий.ЗагрузитьЗначениеИзФайлаЛкс(ФайлОписанияМодуля.ПолноеИмя); // см. МодульМетаданных()
				ОбновитьФайлОписания = Ложь
					Или СтарыйТекст <> НовыйТекст
					Или (Истина
						И ФайлМодуля.Существует() 
						И ФайлМодуля.ПолучитьВремяИзменения() > ФайлОписанияМодуля.ПолучитьВремяИзменения());
				Если Ложь
					Или ТипЗнч(МодульМетаданных) <> Тип("Структура") 
					Или ирОбщий.СвойствоСтруктурыЛкс(МодульМетаданных, "ВерсияФормата")  <> ВерсияФормата
					Или МодульМетаданных.Имя <> выхИмяМодуля // Антибаг ИР. В старых версиях где то писалось пустое имя в кэш
				Тогда
					// Старый формат кэша
					ОбновитьФайлОписания = Истина;
					МодульМетаданных = Неопределено;
				Иначе
					// Мультиметка723368140
					МодульМетаданных.Текст = СтарыйТекст; // Может установиться Неопределено      
				КонецЕсли; 
			КонецЕсли; 
			СтарыйМодуль = Неопределено;
			Если ОбновитьФайлОписания Тогда
				Если Не ФайлМодуля.Существует() Тогда
					Если СообщениеОНеобходимостиОбновитьКэшМодулейВыводилось <> Истина Тогда
						// Может выводиться неоправданно, если модуль пуст. В этом случае конфигуратор не выгружает файл. Поэтому уведомляем только о полной пустоте кэша
						ФайлыМодулей = НайтиФайлы(ПапкаКэшаМодулей.ПолноеИмя, ИмяКонтрольногоФайлаКэшаМодулей());
						Если ФайлыМодулей.Количество() = 0 Тогда
							#Если Клиент Тогда
								ирКлиент.ОткрытьНастройкиПоляТекстаПрограммыНаЗаднемПланеЛкс();
							#КонецЕсли
						КонецЕсли; 
						СообщениеОНеобходимостиОбновитьКэшМодулейВыводилось = Истина;
					КонецЕсли; 
					МодульМетаданных = МодульМетаданных("", СтруктураТипа, выхИмяМодуля);
				Иначе 
					Если НовыйТекст = Неопределено Тогда
						ТекстовыйДокумент.Прочитать(ФайлМодуля.ПолноеИмя);
						НовыйТекст = ТекстовыйДокумент.ПолучитьТекст();
						МодульМетаданных = МодульМетаданных(НовыйТекст, СтруктураТипа, выхИмяМодуля);
						ЗаписатьМодульВКэш(МодульМетаданных);
					Иначе
						СтарыйМодуль = МодульМетаданных;
						МодульМетаданных = МодульМетаданных(НовыйТекст, СтруктураТипа, выхИмяМодуля, Ложь, МодульМетаданных, ТекущаяПозиция);
						// Т.к. в этом сценарии часто будет обновление текста модуля происходить, то не будем тратить время на обновление индекса в файле, но удалим его чтобы потом дату изменения не сверять
						УдалитьФайлы(ФайлОписанияМодуля.Путь, ФайлОписанияМодуля.ИмяБезРасширения + ".i*"); // Все расширения файлов индексов начинаются с "i"
						Если мВызовыВсехСловПоМодулям <> Неопределено Тогда
							мВызовыВсехСловПоМодулям[КлючКэшаВызововСловаПоМодулю(выхИмяМодуля, Истина)] = Неопределено;
							мВызовыВсехСловПоМодулям[КлючКэшаВызововСловаПоМодулю(выхИмяМодуля, Ложь)] = Неопределено;
						КонецЕсли;  
					КонецЕсли;
					//ирОбщий.СообщитьЛкс(ФайлМодуля.ПолноеИмя);    // Отладка
					//УдалитьФайлы(ФайлМодуля.ПолноеИмя);
				КонецЕсли; 
			КонецЕсли; 
			мМодулиМетаданных[НРег(выхИмяМодуля)] = МодульМетаданных;
			МодульМетаданных.СтруктураТипа = СтруктураТипа;
			МодульМетаданных.ФлагиКомпиляции = ФлагиКомпиляции;
			МодульМетаданных.Вставить("СтрокаСоздания", СтрокаСозданияРодителя);
			МодульМетаданных.Вставить("ТипМодуля", ТипМодуля);
			МодульМетаданных.Вставить("ВерсияФормата", ВерсияФормата);
			Если МодульМетаданных <> Неопределено И СтарыйМодуль <> МодульМетаданных Тогда
				#Если Сервер И Не Сервер Тогда
					МетодыМодуля = Новый ТаблицаЗначений;
				#КонецЕсли
				БазовыйТип = ирОбщий.ПервыйФрагментЛкс(СтруктураТипа.ИмяОбщегоТипа);
				ЛиИмяТипаФормы = ирОбщий.ЛиИмяТипаФормыЛкс(БазовыйТип, Истина);
				Если Истина
					И МодульМетаданных <> мПустойМодуль
					И (Ложь
						Или ирОбщий.СтрКончаетсяНаЛкс(БазовыйТип, "Объект") 
						Или ЛиИмяТипаФормы)
				Тогда
					// Добавим в переменные модуля реквизиты объекта с изменяемыми метаданными, чтобы уточнять их тип по коду
					Для Каждого СтрокаПеременной Из МодульМетаданных.Переменные.НайтиСтроки(Новый Структура("ПозицияСОписанием", 0)) Цикл   
						МодульМетаданных.Переменные.Удалить(СтрокаПеременной);
					КонецЦикла;
					МодульВременный = МодульМетаданных("",, "кэш");
					МодульВременный.Переменные.Очистить(); // Иногда там остаются какие то переменные
					//ТаблицаСлов = ТаблицаСловИзСтруктурыТипа(СтруктураТипа,,,, Ложь,, "Свойство",,, МодульВременный);
					ИнициацияОписанияМетодовИСвойств();    
					ТаблицаСлов = СловаКонтекстаМетаданные(СтруктураТипа,, "Свойство",,,,,,, МодульВременный);
					Если ЛиИмяТипаФормы Тогда
						ТаблицаСлов.Добавить().Слово = "ВладелецФормы";
					КонецЕсли;
					Для Каждого СтрокаСлова Из ТаблицаСлов Цикл // TODO добавить фильтр по типу 
						Если ЛиДетальностьТиповДостаточна(СтрокаСлова.ТаблицаТипов) Тогда 
							ИмяОбщегоТипаСлова = СтрокаСлова.ТаблицаТипов[0].ИмяОбщегоТипа;
							Если Истина
								И ИмяОбщегоТипаСлова <> "ТаблицаЗначений"
								И ИмяОбщегоТипаСлова <> "ДеревоЗначений"
							Тогда
								Продолжить;
							Иначе 
								// В них часто добавляются неинтерактивные колонки
							КонецЕсли;
						КонецЕсли;
						СтрокаПеременной = МодульМетаданных.Переменные.Добавить();
						СтрокаПеременной.Имя = СтрокаСлова.Слово;
						СтрокаПеременной.НИмя = Нрег(СтрокаПеременной.Имя);
						СтрокаПеременной.ЛиЭкспорт = Истина; 
						//СтрокаПеременной.ТаблицаТипов = СтрокаСлова.ТаблицаТипов; // Нельзя опираться на эти типы, т.к. они очищаются чаще чем сюда приходим 
					КонецЦикла;
				КонецЕсли;
			КонецЕсли; 
		Иначе 
			МодульМетаданных.Имя = выхИмяМодуля; // Нужно для единого пустого модуля, чтобы виртуальные методы в нем имели правильное имя модуля
		КонецЕсли; 
	КонецЕсли;
	Возврат МодульМетаданных;

КонецФункции

//.
// Возвращаемое значение:
//    Число - 
Функция ВерсияФорматаКэшаМодулей() Экспорт
	ВерсияФормата = 18; // Мультиметка91237881041 Каждый раз при изменении структуры увеличиваем на 1
	Возврат ВерсияФормата;
КонецФункции

Функция ПеречислениеТипСлова() Экспорт 
	Структура = Новый Структура("Свойство, Метод, Конструктор");        
	Возврат ирОбщий.ЗаполнитьЗначенияКлючамиВСтруктуреЛкс(Структура);    
КонецФункции

// Возращает таблицу вызовов слова через точку.
// Параметры:
//    ИмяМодуля - Строка - 
//    ТекстовыйДокумент - ТекстовыйДокумент - 
//    Файл - Файл - 
//    ПолеТекстаПрограммы - ОбработкаОбъект.ирКлсПолеТекстаПрограммы
// Возвращаемое значение:
//    ТаблицаЗначений - 
Функция НепрямыеВызовыСловаВМодуле(Знач ИмяМодуля, Знач ТекстовыйДокумент, Знач Файл, Знач ПолеТекстаПрограммы, Знач ИскатьСлово, Знач ЛиМетод = Истина) Экспорт
	// TODO Поддержать ссылки внутри параметров вызова вида А().Б(В()) - не находит ссылку на Б()
	Если ЛиМетод Тогда
		ШаблонВнешнегоВызова = ПолеТекстаПрограммы.шПредИмяПрямое+"(?:"+ПолеТекстаПрограммы.шИмяСТочками+"\.)("+шИмя+")\s*\(((?:(?:"+ПолеТекстаПрограммы.шВыражениеПрограммы+")?"+шРазделитель+"*(?=[,\)])|,)*)\)";
		Расширение = "icl";
	Иначе 
		ШаблонВнешнегоВызова = ПолеТекстаПрограммы.шПредИмяПрямое+"(?:"+ПолеТекстаПрограммы.шИмяСТочками+"\.)("+шИмя+")(?!\s*[\(])"+ПолеТекстаПрограммы.шПостИмяСвойства;
		Расширение = "ipr";
	КонецЕсли;
	Если мВызовыВсехСловПоМодулям = Неопределено Тогда
		мВызовыВсехСловПоМодулям = Новый Соответствие;
	КонецЕсли;
	КлючКэша = КлючКэшаВызововСловаПоМодулю(ИмяМодуля, ЛиМетод);
	ИндексВызововМодуля = мВызовыВсехСловПоМодулям[КлючКэша];
	Если ИндексВызововМодуля = Неопределено Тогда
		ВерсияФорматаИндекса = 11;
		ФайлИндекса = ФайлМодуляИзИмениМодуля(ИмяМодуля, Расширение);
		ОбновитьИндекс = Не ФайлИндекса.Существует();
		Если Не ОбновитьИндекс Тогда 
			ИндексВызововМодуля = ирОбщий.ЗагрузитьЗначениеИзФайлаЛкс(ФайлИндекса.ПолноеИмя);
			//! ИндексВызововМодуля = Новый Структура(ИменаСвойствИндекса);
			Если Ложь
				Или ТипЗнч(ИндексВызововМодуля) <> Тип("Структура") 
				Или ИндексВызововМодуля.ВерсияФормата <> ВерсияФорматаИндекса
			Тогда
				// Старый формат кэша
				ОбновитьИндекс = Истина;
				ИндексВызововМодуля = Неопределено;
			КонецЕсли; 
		КонецЕсли;
		Если ОбновитьИндекс Тогда
			ТекстМодуля = ТекстовыйДокумент.ПолучитьТекст();
			ИндексВызововМодуля = НовыйИндексПоискаВызововСловаВМодуле(, ВерсияФорматаИндекса);
			ЗаполнитьИндексПоискаВызововСловаВМодуле(ИндексВызововМодуля, ТекстМодуля, ШаблонВнешнегоВызова,, Истина);
			ирОбщий.СохранитьЗначениеВФайлЛкс(ИндексВызововМодуля, ФайлИндекса.ПолноеИмя);
		КонецЕсли;
		ирОбщий.ДобавитьИндексВТаблицуЛкс(ИндексВызововМодуля.Вызовы, "НомерСлова");
		мВызовыВсехСловПоМодулям[КлючКэша] = ИндексВызововМодуля;
	КонецЕсли;
	НомерСлова = 0;
	Результат = Новый Массив;
	Если ИндексВызововМодуля.СтруктураСлов.Свойство(ИскатьСлово, НомерСлова) Тогда 
		Результат = ИндексВызововМодуля.Вызовы.НайтиСтроки(Новый Структура("НомерСлова", НомерСлова));
	КонецЕсли;
	Возврат Результат;
КонецФункции

//.
// Параметры:
//    ТекстМодуля - Строка - 
//    ШаблонВнешнегоВызова - Строка - регулярное выражение, где в первой группе находится слово
Функция НовыйИндексПоискаВызововСловаВМодуле(Знач Модуль = Неопределено, Знач ВерсияФорматаИндекса = 0) Экспорт

	ЛиИскатьОповещения = Истина
		И Модуль <> Неопределено
		И Модуль.СтруктураТипа <> Неопределено
		И ирОбщий.ЛиИмяТипаФормыЛкс(Модуль.СтруктураТипа.ИмяОбщегоТипа);
	ТаблицаВызовов = Новый ТаблицаЗначений;
	ТаблицаВызовов.Колонки.Добавить("ПозицияВхождения", Новый ОписаниеТипов("Число"));
	ТаблицаВызовов.Колонки.Добавить("ДлинаВхождения", Новый ОписаниеТипов("Число"));
	ТаблицаВызовов.Колонки.Добавить("Слово", Новый ОписаниеТипов("Строка"));
	ТаблицаВызовов.Колонки.Добавить("НомерСлова", Новый ОписаниеТипов("Число"));
	СтруктураСлов = Новый Структура;
	Если ЛиИскатьОповещения Тогда
		ТаблицаОповещений = Новый ТаблицаЗначений;
		ТаблицаОповещений.Колонки.Добавить("ПозицияВхождения", Новый ОписаниеТипов("Число"));
		ТаблицаОповещений.Колонки.Добавить("ДлинаВхождения", Новый ОписаниеТипов("Число"));
		ТаблицаОповещений.Колонки.Добавить("Слово", Новый ОписаниеТипов("Строка"));
		ТаблицаОповещений.Колонки.Добавить("Параметр", Новый ОписаниеТипов("Строка"));
		ТаблицаОповещений.Колонки.Добавить("НомерСлова", Новый ОписаниеТипов("Число"));
	КонецЕсли;
	ИндексВызововМодуля = Новый Структура("ВерсияФормата, Вызовы, СтруктураСлов, Оповещения");
	ИндексВызововМодуля.ВерсияФормата = ВерсияФорматаИндекса;
	ИндексВызововМодуля.Вызовы = ТаблицаВызовов; 
	ИндексВызововМодуля.Оповещения = ТаблицаОповещений; 
	ИндексВызововМодуля.СтруктураСлов = СтруктураСлов;
	Возврат ИндексВызововМодуля;
КонецФункции

//.
// Параметры:
//    ТекстБлока - Строка  -  
//    ШаблонВнешнегоВызова - Строка  -  регулярное выражение, где в первой группе находится слово
//    ШаблонОповещения - Строка - 
//    СВложенными - Булево - 
//    Смещение - Число - 
//    ТаблицаВызовов - ТаблицаЗначений - 
//    ТаблицаОповещений - ТаблицаЗначений - 
Процедура ЗаполнитьИндексПоискаВызововСловаВМодуле(Знач ИндексВызововМодуля, Знач ТекстБлока, Знач ШаблонВнешнегоВызова, Знач ШаблонОповещения = "", Знач СВложенными = Ложь,
	Знач Смещение = 0) Экспорт
	
	ТаблицаВызовов = ИндексВызововМодуля.Вызовы;
	РегВыражение = ирКэш.ВычислительРегВыраженийЛкс();
	РегВыражение.IgnoreCase = Истина; 
	РегВыражение.Global = Истина;
	РегВыражение.Pattern = ШаблонВнешнегоВызова;
	Вхождения = РегВыражение.НайтиВхождения(ТекстБлока,, Истина);
	ДобавитьВхожденияСловаВИндекс(Вхождения, РегВыражение, ТаблицаВызовов, СВложенными, Смещение);
	НумероватьСловаВИндексе(ТаблицаВызовов, ИндексВызововМодуля.СтруктураСлов);
	Если ЗначениеЗаполнено(ШаблонОповещения) Тогда
		ТаблицаОповещений = ИндексВызововМодуля.Оповещения;
		РегВыражение.Pattern = ШаблонОповещения;
		Вхождения = РегВыражение.НайтиВхождения(ТекстБлока,, Истина);
		Для Каждого Вхождение Из Вхождения Цикл
			СтрокаРезультата = ТаблицаОповещений.Добавить();
			СтрокаРезультата.ПозицияВхождения = Смещение + Вхождение.FirstIndex;
			СтрокаРезультата.ДлинаВхождения = Вхождение.Length;
			СтрокаРезультата.Слово = Вхождение.SubMatches(0);
			СтрокаРезультата.Параметр = Вхождение.SubMatches(1);
		КонецЦикла;
		НумероватьСловаВИндексе(ТаблицаОповещений, ИндексВызововМодуля.СтруктураСлов);
	КонецЕсли;
КонецПроцедуры

//.
// Параметры:
//    Вхождения - Массив[ОбработкаОбъект.ирОболочкаРегВхождение] - 
//    РегВыражение - ОбработкаОбъект.ирОболочкаРегВыражение - 
//    ТаблицаВызовов - ТаблицаЗначений - 
//    Смещение - Число - 
//    _РежимОтладки - Булево - 
Процедура ДобавитьВхожденияСловаВИндекс(Знач Вхождения, Знач РегВыражение, Знач ТаблицаВызовов, Знач СВложенными = Ложь, Знач Смещение = 0) Экспорт
	_РежимОтладки = Ложь;
	Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
		// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
		Для Каждого Вхождение Из Вхождения Цикл
			СтрокаРезультата = ТаблицаВызовов.Добавить();
			СтрокаРезультата.ПозицияВхождения = Смещение + Вхождение.FirstIndex;
			СтрокаРезультата.ДлинаВхождения = Вхождение.Length;
			СтрокаРезультата.Слово = Вхождение.SubMatches(0); 
			Если СВложенными Тогда
				Если Вхождение.SubMatches.Count > 1 Тогда
					ПараметрыВызова = Вхождение.SubMatches(1);  
					Если Найти(ПараметрыВызова, "(") > 0 Тогда
						ВхожденияВложенные = РегВыражение.НайтиВхождения(ПараметрыВызова,, Истина);
						ДобавитьВхожденияСловаВИндекс(ВхожденияВложенные, РегВыражение, ТаблицаВызовов, Истина, Вхождение.FirstIndex + Найти(Вхождение.Value, ПараметрыВызова));
					КонецЕсли;
				Иначе 
					Если Вхождение.FirstIndex > 0 Тогда
						Текст = Сред(Вхождение.Value, 2);
						СмещениеДлины = 1;
					Иначе
						Текст = Вхождение.Value;
						СмещениеДлины = 0;
					КонецЕсли;
					ЧислоТочек = СтрЧислоВхождений(Текст, ".");
					Пока ЧислоТочек > 0 Цикл
						Текст = ирОбщий.СтрокаБезПоследнегоФрагментаЛкс(Текст);
						СтрокаВложенная = ТаблицаВызовов.Добавить();
						СтрокаВложенная.ПозицияВхождения = СтрокаРезультата.ПозицияВхождения;
						СтрокаВложенная.ДлинаВхождения = СтрДлина(Текст) + СмещениеДлины; 
						СтрокаВложенная.Слово = ирОбщий.ПоследнийФрагментЛкс(Текст);
						ЧислоТочек = ЧислоТочек - 1;
					КонецЦикла;
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
	Иначе
		// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
		Для Каждого Вхождение Из Вхождения Цикл  			СтрокаРезультата = ТаблицаВызовов.Добавить();  			СтрокаРезультата.ПозицияВхождения = Смещение + Вхождение.FirstIndex;  			СтрокаРезультата.ДлинаВхождения = Вхождение.Length;  			СтрокаРезультата.Слово = Вхождение.SubMatches(0);  			Если СВложенными Тогда  				Если Вхождение.SubMatches.Count > 1 Тогда  					ПараметрыВызова = Вхождение.SubMatches(1);  					Если Найти(ПараметрыВызова, "(") > 0 Тогда  						ВхожденияВложенные = РегВыражение.НайтиВхождения(ПараметрыВызова,, Истина);  						ДобавитьВхожденияСловаВИндекс(ВхожденияВложенные, РегВыражение, ТаблицаВызовов, Истина, Вхождение.FirstIndex + Найти(Вхождение.Value, ПараметрыВызова));  					КонецЕсли;  				Иначе  					Если Вхождение.FirstIndex > 0 Тогда  						Текст = Сред(Вхождение.Value, 2);  						СмещениеДлины = 1;  					Иначе  						Текст = Вхождение.Value;  						СмещениеДлины = 0;  					КонецЕсли;  					ЧислоТочек = СтрЧислоВхождений(Текст, ".");  					Пока ЧислоТочек > 0 Цикл  						Текст = ирОбщий.СтрокаБезПоследнегоФрагментаЛкс(Текст);  						СтрокаВложенная = ТаблицаВызовов.Добавить();  						СтрокаВложенная.ПозицияВхождения = СтрокаРезультата.ПозицияВхождения;  						СтрокаВложенная.ДлинаВхождения = СтрДлина(Текст) + СмещениеДлины;  						СтрокаВложенная.Слово = ирОбщий.ПоследнийФрагментЛкс(Текст);  						ЧислоТочек = ЧислоТочек - 1;  					КонецЦикла;  				КонецЕсли;  			КонецЕсли;  		КонецЦикла;  
	КонецЕсли;
КонецПроцедуры

//.
// Параметры:
//    ТаблицаВызовов - ТаблицаЗначений - 
//    Слово - Строка(0) - 
//    _РежимОтладки - Булево - 
// Возвращаемое значение:
//    Структура - 
Функция НумероватьСловаВИндексе(ТаблицаВызовов, СтруктураСлов) Экспорт
	_РежимОтладки = Ложь;
	ирОбщий.ДобавитьИндексВТаблицуЛкс(ТаблицаВызовов, "Слово");
	МассивСлов = ирОбщий.РазличныеЗначенияКолонкиТаблицыЛкс(ТаблицаВызовов, "Слово");
	ПервыйСвободныйНомерСлова = СтруктураСлов.Количество();
	СтарыйНомерСлова = 0;
	//ТаблицаВызовов.Колонки.Добавить("НомерСлова", Новый ОписаниеТипов("Число")); // Вынес наружу для анализатора кода
	Для Каждого Слово Из МассивСлов Цикл
		Если Не СтруктураСлов.Свойство(Слово, СтарыйНомерСлова) Тогда
			ПервыйСвободныйНомерСлова = ПервыйСвободныйНомерСлова + 1;
			СтруктураСлов.Вставить(Слово, ПервыйСвободныйНомерСлова);
			НомерСлова = ПервыйСвободныйНомерСлова;
		Иначе
			НомерСлова = СтарыйНомерСлова;
		КонецЕсли;
		ВызовыСлова = ТаблицаВызовов.НайтиСтроки(Новый Структура("Слово", Слово));
		Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
			// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
			Для Каждого СтрокаВызова Из ВызовыСлова Цикл
				СтрокаВызова.НомерСлова = НомерСлова;
			КонецЦикла;
		Иначе
			// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
			Для Каждого СтрокаВызова Из ВызовыСлова Цикл  					СтрокаВызова.НомерСлова = НомерСлова;  				КонецЦикла;  
		КонецЕсли;
	КонецЦикла;
	ТаблицаВызовов.Колонки.Удалить("Слово");
	Возврат СтруктураСлов;
КонецФункции

Функция КлючКэшаВызововСловаПоМодулю(Знач Модуль, Знач ЛиМетод) Экспорт
	Возврат НРег(Модуль) + "." + ЛиМетод;
КонецФункции

// Возвращаемое значение:
//    Строка - 
Функция ИмяКонтрольногоФайлаКэшаМодулей() Экспорт
	Возврат "КонтрольныйФайл.ixd";
КонецФункции

Функция ИмяДинамическогоМодуля() Экспорт
	Возврат "Динамический.Модуль";
КонецФункции

Функция ИмяМетодаИнициация() Экспорт
	Возврат "<Инициация>";
КонецФункции

//.
// Параметры:
//    МодульМетаданных - Структура - 
//    ОбнулятьВычисляемое - Булево - немного дольше, но гарантирует успех
Процедура ЗаписатьМодульВКэш(Знач МодульМетаданных, Знач ЧерезКопию = Ложь) Экспорт 
	Если МодульМетаданных = мПустойМодуль Тогда
		Возврат;
	КонецЕсли;
	ФайлОписанияМодуля = ФайлМодуляИзИмениМодуля(МодульМетаданных.Имя, "ixd");
	Если ЧерезКопию Тогда
		// Мультиметка723368140
		КопияМодуля = ирОбщий.СкопироватьКоллекциюЛкс(МодульМетаданных);
		КопияМодуля.Текст = Неопределено;   
		КопияМодуля.СтруктураТипа = Неопределено;  
		КопияМодуля.ТекущийМетод = Неопределено;  
		КопияМодуля.ТекстПоискаОпределенияСловМодуля = Неопределено; 
		КопияМодуля.ПрямыеВызовыМетодов = Неопределено;  
		Если Не ЛиСохранятьОшибкиМодуля(КопияМодуля) Тогда
			КопияМодуля.Ошибки = Неопределено; 
		КонецЕсли;
		КопияМодуля.Переменные = КопияМодуля.Переменные.Скопировать();
		КопияМодуля.Методы = КопияМодуля.Методы.Скопировать();
		КопияМодуля.Методы.ЗаполнитьЗначения(Неопределено, "КэшПоиска, ТелоБезВозвратов");     
		СброситьКэшТиповВыраженийМодуля(КопияМодуля);
		МодульМетаданных = КопияМодуля;
	КонецЕсли;
	МодульМетаданных.Вставить("ВерсияФормата", ВерсияФорматаКэшаМодулей());
	Текст = МодульМетаданных.Текст;
	СтруктураТипа = МодульМетаданных.СтруктураТипа;
	МодульМетаданных.Текст = Неопределено;
	МодульМетаданных.СтруктураТипа = Неопределено;
	ирОбщий.СохранитьЗначениеВФайлЛкс(МодульМетаданных, ФайлОписанияМодуля.ПолноеИмя);
	МодульМетаданных.Текст = Текст;
	МодульМетаданных.СтруктураТипа = СтруктураТипа;
КонецПроцедуры

//.
// Параметры:
//    Модуль - Структура - 
// Возвращаемое значение:
//   Булево  - 
Функция ЛиСохранятьОшибкиМодуля(Модуль) Экспорт
	Результат = Истина
		И Модуль.Имя <> ИмяДинамическогоМодуля() // Там типы переменных модуля не очищаем
		И Модуль.Ошибки <> Неопределено
		И Модуль.Ошибки.Количество() < 50;
	Возврат Результат;
КонецФункции

//.
// Параметры:
//    ИмяМодуля - Строка - 
// Возвращаемое значение:
//    см. МодульМетаданных() - 
Функция МодульМетаданныхИзКэша(Знач ИмяМодуля) Экспорт
	МодульМетаданных = мМодулиМетаданных[НРег(ИмяМодуля)];
	Возврат МодульМетаданных;
КонецФункции 

Процедура СброситьКэшиТиповВыраженийМодулей(Знач КромеМодуля = "") Экспорт 
	Для Каждого КлючИЗначение Из мМодулиМетаданных Цикл
		Если КлючИЗначение.Ключ = НРег(КромеМодуля) Тогда
			Продолжить; 
		КонецЕсли;
		СброситьКэшТиповВыраженийМодуля(КлючИЗначение.Значение); 
	КонецЦикла;
КонецПроцедуры

//.
// Параметры:
//    Модуль - см. МодульМетаданных() - 
Процедура СброситьКэшТиповВыраженийМодуля(Знач Модуль) Экспорт
	Если Модуль.Имя <> ИмяДинамическогоМодуля() Тогда
		Переменные = Модуль.Переменные;
		Переменные.ЗаполнитьЗначения(, "ТаблицаТипов, Вычислено"); // Чтобы не отслеживать зависимости 
	КонецЕсли;
	Модуль.ТипыВыраженийПрограммы.Очистить();
	Модуль.КэшПоискаПрограммы.Очистить();
	Модуль.ТаблицыСлов.Очистить();   
	Методы = Модуль.Методы;
	Методы.ЗаполнитьЗначения(, "ТаблицаТипов, Вычислено, ТипыВыражений"); // Чтобы не отслеживать зависимости. ТипыВыражений - самые тяжелые             
	_РежимОтладки = Ложь;
	Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1) 
		// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах. 
		Для Каждого СтрокаМетода Из Методы Цикл
			Если ТипЗнч(СтрокаМетода.Параметры) = Тип("ТаблицаЗначений") Тогда
				СтрокаМетода.Параметры.ЗаполнитьЗначения(, "ТаблицаТипов, Вычислено");
			КонецЕсли;
		КонецЦикла;
	Иначе
		// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
		Для Каждого СтрокаМетода Из Методы Цикл  		Если ТипЗнч(СтрокаМетода.Параметры) = Тип("ТаблицаЗначений") Тогда  			СтрокаМетода.Параметры.ЗаполнитьЗначения(, "ТаблицаТипов, Вычислено");  		КонецЕсли;  	КонецЦикла;  
	КонецЕсли; 
	
	//Для Каждого СтрокаМетода Из Методы Цикл
	//	Если ТипЗнч(СтрокаМетода.Параметры) = Тип("ТаблицаЗначений") Тогда
	//		СтрокаМетода.Параметры.ЗаполнитьЗначения(, "ТаблицаТипов");
	//	КонецЕсли;
	//	Если СтрокаМетода.ТаблицаТипов <> Неопределено Тогда
	//		СтрокаМетода.ТаблицаТипов = Неопределено;
	//	КонецЕсли;
	//	Если СтрокаМетода.ТипыВыражений <> Неопределено Тогда
	//		СтрокаМетода.ТипыВыражений = Неопределено;
	//	КонецЕсли;
	//КонецЦикла;

КонецПроцедуры

//.
// Параметры:
//    ИмяМодуля - Строка - например "ИнструментыРазработчикаTormozit ОбщийМодуль.ирОбщий.Модуль"
// Возвращаемое значение:
//    Файл - 
Функция ФайлМодуляИзИмениМодуля(Знач ИмяМодуля, Знач Расширение = "txt", Знач ЗаменитьНедопустимыеСимволы = Ложь) Экспорт    
	ИмяМодуля = СтрЗаменить(ИмяМодуля, " ", "\");
	Если ЗаменитьНедопустимыеСимволы Тогда
		ИмяМодуля = ирОбщий.ЗаменитьНедопустимыеСимволыВИмениФайлаЛкс(ИмяМодуля, "_");
	КонецЕсли;
	ФайлМодуля = Новый Файл(ПапкаКэшаМодулей.ПолноеИмя + ирОбщий.РазделительПутиКФайлуЛкс() + ИмяМодуля + "." + Расширение);
	Возврат ФайлМодуля;
КонецФункции

// Функция - Имя файла модуля без расширения
//
// Параметры:
//  СтруктураТипа			 - см. НоваяСтруктураТипа() - 
//  ТипМодуля				 - Строка - входное значение имеет смысл только для модулей приложения (безобъектных)
//  СтрокаСозданияРодителя	 - Строка - 
//  ФлагиКомпиляции			 - Структура - выход, заполняется если ТипМодуля на входе пустой
// 
// Возвращаемое значение:
//  Строка - 
//
Функция ИмяМодуляИзСтруктурыТипа(Знач СтруктураТипа, ТипМодуля = "", СтрокаСозданияРодителя = "", ФлагиКомпиляции = Неопределено) Экспорт 
	
	ИмяОбщегоТипа = СтруктураТипа.ИмяОбщегоТипа;
	МетаданныеРодителя = СтруктураТипа.Метаданные;
	ТипыМетаОбъектов = ирКэш.ТипыМетаОбъектов();
	Результат = "";    
	ФлагиКомпиляции = НовыеФлагиКомпиляции(Ложь, Ложь, Ложь);
	Если ТипМодуля = "МодульОбычногоПриложения" Тогда
		ФлагиКомпиляции.Вставить("КлиентОбычноеПриложение", Истина);
	ИначеЕсли ТипМодуля = "МодульУправляемогоПриложения" Тогда
		ФлагиКомпиляции.Вставить("КлиентУправляемоеПриложение", Истина);
	ИначеЕсли ТипМодуля = "МодульСеанса" Тогда
		ФлагиКомпиляции.Вставить("Сервер", Истина);
	Иначе
		ФлагиКомпиляции = НовыеФлагиКомпиляции();
	КонецЕсли;
	Если ИмяОбщегоТипа = "Глобальный" Тогда
	//Если ИмяОбщегоТипа = "ОбъектМетаданныхКонфигурация" Тогда
		//#Если ТолстыйКлиентОбычноеПриложение Тогда
		//	ТипМодуля = "МодульОбычногоПриложения";
		//#Иначе
		//	ТипМодуля = "МодульУправляемогоПриложения";
		//#КонецЕсли
		Если Не ЗначениеЗаполнено(ТипМодуля) Тогда
			ВызватьИсключение "Требуется передача типа модуля конфигурации";
		КонецЕсли;
	ИначеЕсли Ложь
		Или ИмяОбщегоТипа = "Команда"
		Или ИмяОбщегоТипа = "ОбщаяКоманда" 
	Тогда
		ТипМодуля = "МодульКоманды";
	ИначеЕсли Ложь
		Или ИмяОбщегоТипа = "WebСервис"
		Или ИмяОбщегоТипа = "HttpСервис"
		Или ИмяОбщегоТипа = "ОбщийМодуль"
	Тогда
		ТипМодуля = "Модуль";
		Если ИмяОбщегоТипа = "ОбщийМодуль" Тогда
			Если ТипЗнч(МетаданныеРодителя) = Тип("Строка") Тогда
				// Добавленный/переименованный объект метаданных
				Фрагменты = ирОбщий.СтрРазделитьЛкс(МетаданныеРодителя);
				МетаданныеРодителя = Новый Структура;
				МетаданныеРодителя.Вставить("ВызовСервера", Истина);
				МетаданныеРодителя.Вставить("Сервер", Истина);
				МетаданныеРодителя.Вставить("КлиентУправляемоеПриложение", Истина);
				МетаданныеРодителя.Вставить("КлиентОбычноеПриложение", Истина);
				МетаданныеРодителя.Вставить("Имя", Фрагменты[1]);
				//МетаданныеРодителя.Вставить("ИмяРасширения", СтруктураТипа.ДержательМетаданных);
				мДобавленныеОбщиеМодули.Вставить(Фрагменты[1], МетаданныеРодителя);
			КонецЕсли;
			Если Ложь
				Или ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных")    
				Или ТипЗнч(МетаданныеРодителя) = Тип("Структура")
			Тогда
				ФлагиКомпиляции.Сервер = МетаданныеРодителя.Сервер;
				ФлагиКомпиляции.КлиентОбычноеПриложение = МетаданныеРодителя.КлиентОбычноеПриложение;
				ФлагиКомпиляции.КлиентУправляемоеПриложение = МетаданныеРодителя.КлиентУправляемоеПриложение;
				СтрокаСозданияРодителя = МетаданныеРодителя.Имя;
				Результат = ИмяОбщегоТипа + "." + МетаданныеРодителя.Имя + "." + ТипМодуля;
			Иначе 
				// Если ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданныхКонфигурация") Тогда
				//   см. ОбработкаОбъект.ирКлсПолеТекстаПрограммы.СтруктураТипаМодуля
			КонецЕсли;
		Иначе
			ФлагиКомпиляции.КлиентОбычноеПриложение = Ложь;
			ФлагиКомпиляции.КлиентУправляемоеПриложение = Ложь;
		КонецЕсли;
	ИначеЕсли ирОбщий.ЛиИмяТипаФормыЛкс(ИмяОбщегоТипа, Истина) Тогда 
		Если Ложь
			#Если Клиент Тогда
			Или ТипЗнч(МетаданныеРодителя) = Тип("Форма") 
			#КонецЕсли
		Тогда
			СлужебныеДанныеФормы = ирОбщий.СлужебныеДанныеФормыЛкс(МетаданныеРодителя);
			Если СлужебныеДанныеФормы.Свойство("ИмяФормы") Тогда
				МетаданныеРодителя = СлужебныеДанныеФормы.ИмяФормы;
			КонецЕсли;
		ИначеЕсли ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") Тогда  
			МетаданныеРодителя = МетаданныеРодителя.ПолноеИмя();
		ИначеЕсли ирОбщий.ЛиФормаИлиИмитаторЛкс(МетаданныеРодителя, Ложь) Тогда
			МетаданныеРодителя = МетаданныеРодителя.ИмяФормы;
		КонецЕсли;
		ТипМодуля = "Модуль";
		Если ТипЗнч(МетаданныеРодителя) = Тип("Строка") Тогда
			МетаданныеРодителя = МетаданныеРодителя + ".Форма";
		КонецЕсли;
	ИначеЕсли Истина
		И ТипЗнч(МетаданныеРодителя) = Тип("Структура")
		И ирОбщий.ЛиИмяТипаВнешнегоОбъектаМетаданныхЛкс(ИмяОбщегоТипа)
	Тогда
		// Нужно для некомпилируемых внешних объектов
		МетаданныеРодителя = ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипа, "Объект.", Ложь) + "." + МетаданныеРодителя.Имя; 
		ТипМодуля = "МодульОбъекта";
	Иначе
		КорневойТипОбъекта = ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипа, "Объект.", Ложь);
		Если ЗначениеЗаполнено(КорневойТипОбъекта) Тогда
			ТипМодуля = "МодульОбъекта";
			СтрокаТипаМетаОбъекта = ТипыМетаОбъектов.Найти(КорневойТипОбъекта, "Единственное");
			Если Истина
				И СтрокаТипаМетаОбъекта <> Неопределено 
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") 
			Тогда
				Множественное = СтрокаТипаМетаОбъекта.Множественное;
				Если СтрокаТипаМетаОбъекта.Категория = 1 Тогда
					СтрокаСозданияРодителя = Множественное + "." + МетаданныеРодителя.Имя + ".Создать()";
				ИначеЕсли СтрокаТипаМетаОбъекта.Категория = 0 Тогда
					СтрокаСозданияРодителя = Множественное + "." + МетаданныеРодителя.Имя + ".ПустаяСсылка().ПолучитьОбъект()";
				КонецЕсли; 
			КонецЕсли; 
		ИначеЕсли ЗначениеЗаполнено(ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипа, "НаборЗаписей.", Ложь)) Тогда
			ТипМодуля = "МодульНабораЗаписей";
			КорневойТип = ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипа, "НаборЗаписей");
			СтрокаТипаМетаОбъекта = ТипыМетаОбъектов.Найти(КорневойТип, "Единственное");
			Если Истина
				И СтрокаТипаМетаОбъекта <> Неопределено 
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") 
			Тогда
				Множественное = СтрокаТипаМетаОбъекта.Множественное;
				СтрокаСозданияРодителя = Множественное + "." + МетаданныеРодителя.Имя + ".СоздатьНаборЗаписей()"; 
			КонецЕсли; 
		ИначеЕсли ЗначениеЗаполнено(ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипа, "МенеджерЗначения.", Ложь)) Тогда
			ТипМодуля = "МодульМенеджераЗначения";
			Если ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") Тогда
				СтрокаСозданияРодителя = "Константы." + МетаданныеРодителя.Имя + ".СоздатьМенеджерЗначения()";
			КонецЕсли;
		ИначеЕсли ЗначениеЗаполнено(ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипа, "Менеджер.", Ложь)) Тогда
			ТипМодуля = "МодульМенеджера";
			КорневойТип = ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипа, "Менеджер");
			СтрокаТипаМетаОбъекта = ТипыМетаОбъектов.Найти(КорневойТип, "Единственное");
			Если Истина
				И СтрокаТипаМетаОбъекта <> Неопределено 
				И ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") 
			Тогда
				Множественное = СтрокаТипаМетаОбъекта.Множественное;
				СтрокаСозданияРодителя = Множественное + "." + МетаданныеРодителя.Имя;
			КонецЕсли; 
		Иначе
			// Тип объекта не имеет модуля
			ТипМодуля = Неопределено;
		КонецЕсли; 
	КонецЕсли;
	Если Не ЗначениеЗаполнено(Результат) Тогда
		Если ЗначениеЗаполнено(ТипМодуля) Тогда
			Если ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданныхКонфигурация") Тогда
				Результат = "Конфигурация" + "." + ТипМодуля;
			Иначе
				Если ТипЗнч(МетаданныеРодителя) = Тип("ОбъектМетаданных") Тогда
					МетаданныеРодителя = МетаданныеРодителя.ПолноеИмя();
				КонецЕсли;
				Если ТипЗнч(МетаданныеРодителя) = Тип("Строка") Тогда
					Результат = МетаданныеРодителя + "." + ТипМодуля;
				КонецЕсли;
			КонецЕсли;
			Если Найти(Результат, ":") > 0 Тогда // для ускорения
				Результат = ирОбщий.ЗаменитьНедопустимыеСимволыВИмениФайлаЛкс(Результат, "_");
			КонецЕсли;
		ИначеЕсли ТипЗнч(МетаданныеРодителя) = Тип("Строка") Тогда
			Результат = МетаданныеРодителя;
		КонецЕсли;
	КонецЕсли;
	Если Истина
		И ирКэш.НомерВерсииПлатформыЛкс() >= 803008
		И СтруктураТипа.ДержательМетаданных = Неопределено 
	Тогда 
		Если ТипЗнч(СтруктураТипа.Метаданные) = Тип("ОбъектМетаданных") Тогда
			МетаданныеРасширения = СтруктураТипа.Метаданные.РасширениеКонфигурации();
		ИначеЕсли ирОбщий.ЛиФормаИлиИмитаторЛкс(СтруктураТипа.Метаданные) Тогда
			МетаданныеРасширения = ирОбщий.ОбъектМДПоПолномуИмениЛкс(ирОбщий.ПолноеИмяФормыЛкс(СтруктураТипа.Метаданные));
			Если МетаданныеРасширения <> Неопределено Тогда
				МетаданныеРасширения = МетаданныеРасширения.РасширениеКонфигурации();
			КонецЕсли;
		КонецЕсли;
		Если МетаданныеРасширения <> Неопределено Тогда
			СтруктураТипа.ДержательМетаданных = МетаданныеРасширения.Имя;
		КонецЕсли;
	КонецЕсли;
	Если ТипЗнч(СтруктураТипа.ДержательМетаданных) = Тип("Строка") Тогда 
		Результат = СтруктураТипа.ДержательМетаданных + " " + Результат;
	КонецЕсли;
	Возврат Результат;

КонецФункции

// Функция - Обновить кэш структуры формы из буфера
//
// Параметры:
//  СлужебныеДанные		 - см. ирОбщий.СлужебныеДанныеФормыЛкс() - 
//  ТекстБуфераОбмена	 - 	 - 
//  Форма				 - 	 - 
// 
// Возвращаемое значение:
//   - 
//
Функция ОбновитьКэшСтруктурыФормыИзБуфера(Знач СлужебныеДанные, Знач ТекстБуфераОбмена, Знач Форма = Неопределено) Экспорт 
	Если СлужебныеДанные.Свойство("КорневыеИменаРеквизитов") Тогда
		//! СлужебныеДанные.Вставить("КорневыеИменаРеквизитов")
		СлужебныеДанные.Удалить("КорневыеИменаРеквизитов");
	КонецЕсли;
	ИмитаторФормы = ИмитаторУправляемойФормы();
	ЛиОбычнаяФорма = Ложь;
	Попытка                          
		ДвоичныеДанные = Base64Значение(ирОбщий.ТекстМеждуМаркерамиЛкс(ТекстБуфераОбмена, "#base64:", "}"));
		Текст = Новый ТекстовыйДокумент;
		Текст.Прочитать(ДвоичныеДанные.ОткрытьПотокДляЧтения());
		ТекстФайла = Текст.ПолучитьТекст(); 
		ЛиОбычнаяФорма = Лев(ТекстФайла, 1) <> "{";
		Если ЛиОбычнаяФорма Тогда 
			СлужебныеДанные.Тип = Тип("Форма");
			// Обычная форма
			ВызватьИсключение "ОбычнаяФорма";
		КонецЕсли;
		XMLСтрока = ирОбщий.СтрокаВнутрВХМЛТелоЛкс(ТекстФайла);  // Если ошибка, то обычная форма 
		ДокументDOM = ирОбщий.ТекстВДокументDOMЛкс(XMLСтрока); // Если ошибка, то не поддерживаемый формат управляемой формы. Например Обработка.упРМПланированиеРейсов.ФормаРедактированияРейса 
	Исключение
		ОписаниеОшибки = ОписаниеОшибки();
		ДополнитьСлужебныеДанныеИзКэшаФормы(СлужебныеДанные, ИмитаторФормы, ТекущаяДата());
		Если Не ЛиОбычнаяФорма И ЗначениеЗаполнено(ТекстБуфераОбмена) Тогда
			ирОбщий.СообщитьЛкс("Ошибка разбора буферного описания формы " + ирОбщий.ПолноеИмяФормыЛкс(СлужебныеДанные) + ": " + ОписаниеОшибки);
		КонецЕсли;
		Возврат Ложь;
	КонецПопытки; 
	Разыменователь = Новый РазыменовательПространствИменDOM(Новый Соответствие); 
	ШаблонУровня = "";
	Для Счетчик = 0 По 8 Цикл
		Выражение = "/e/e[1]/e/" + ШаблонУровня + "d[text()='02023637-7868-4a5f-8576-835a76e0c9ba']";
		ШаблонУровня = ШаблонУровня + "*/";
		НаборУзлов = ДокументDOM.ВычислитьВыражениеXPath(Выражение, ДокументDOM, Разыменователь);
		УзелDOM = НаборУзлов.ПолучитьСледующий();
		Если УзелDOM <> Неопределено Тогда
			ИмитаторФормы.ИменаОбработчиков = ИменаОбработчиковИзУзлаФормы(ДокументDOM, УзелDOM.РодительскийУзел.РодительскийУзел.ПредыдущийСоседний.ПредыдущийСоседний.ПредыдущийСоседний, Разыменователь);
			Прервать;
		КонецЕсли;
	КонецЦикла; 
	
	// реквизиты
	Выражение = "/e/e[2]/e/d[3]/text()";
	НаборУзлов = ДокументDOM.ВычислитьВыражениеXPath(Выражение, ДокументDOM, Разыменователь, ТипРезультатаDOMXPath.Строка);
	УзелDOM = НаборУзлов.ПолучитьСледующий();
	ИмитаторФормы.Реквизиты = НоваяТаблицаРеквизитовФормы();
	Пока УзелDOM <> Неопределено Цикл 
		ИмяРеквизита = ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(УзелDOM.ТекстовоеСодержимое);
		ОписаниеРеквизита = Новый Структура;
		РеквизитыКоллекции = НоваяТаблицаРеквизитовФормы();
		НомерУзлаВложенных = 13;  
		ОписаниеТипов = ТипЗначенияИзУзлаФормы(УзелDOM.РодительскийУзел.РодительскийУзел.ДочерниеУзлы[5]);
		Если ОписаниеТипов = Новый ОписаниеТипов("ДинамическийСписок") Тогда
			ДинамическийСписок = Новый Структура("ОсновнаяТаблица, ТекстЗапроса");
			УзелДинамическийСписок = УзелDOM.РодительскийУзел.РодительскийУзел.ДочерниеУзлы[14];
			//ДинамическийСписок.ОсновнаяТаблица = УзелДинамическийСписок.ДочерниеУзлы[5].ТекстовоеСодержимое;
			УзелДинамическийСписок.ДочерниеУзлы[3].УдалитьДочерний(УзелДинамическийСписок.ДочерниеУзлы[3].ПервыйДочерний);
			ДинамическийСписок.ТекстЗапроса = ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(УзелДинамическийСписок.ДочерниеУзлы[3].ТекстовоеСодержимое);
			ИмитаторФормы.ДинамическиеСписки.Вставить(ИмяРеквизита, ДинамическийСписок);
			Для Каждого ДочернийУзел Из УзелДинамическийСписок.ДочерниеУзлы Цикл
				ТекстУзла = ДочернийУзел.ПоследнийДочерний.ТекстовоеСодержимое;
				Если Ложь
					Или ирОбщий.СтрНачинаетсяСЛкс(ТекстУзла, """FieldsMapItemName") 
					Или ирОбщий.СтрНачинаетсяСЛкс(ТекстУзла, """FieldsMapItemSecondaryName") 
				Тогда
					ИмяДочернегоРеквизита = ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(ДочернийУзел.СледующийСоседний.ПоследнийДочерний.ТекстовоеСодержимое);
					Если Найти(ИмяДочернегоРеквизита, ".") = 0 Тогда
						ОписаниеРеквизита = РеквизитыКоллекции.Добавить();
						ОписаниеРеквизита.Имя = ИмяДочернегоРеквизита;
						ирОбщий.ОбновитьКопиюСвойстваВНижнемРегистреЛкс(ОписаниеРеквизита);
						ОписаниеРеквизита.ОписаниеТипов = ТипЗначенияИзУзлаФормы(ДочернийУзел.СледующийСоседний.ПервыйДочерний);
					КонецЕсли;
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
		ЗначениеРеквизита = Неопределено;
		КоличествоРеквизитовКоллекции = Число(УзелDOM.РодительскийУзел.РодительскийУзел.ДочерниеУзлы[НомерУзлаВложенных].ТекстовоеСодержимое);
		Если КоличествоРеквизитовКоллекции > 0 Тогда
			Если Ложь
				Или ОписаниеТипов = Новый ОписаниеТипов("ТаблицаЗначений") 
				Или ОписаниеТипов = Новый ОписаниеТипов("ДеревоЗначений")
			Тогда
				ЗначениеРеквизита = Новый (ОписаниеТипов.Типы()[0]); // ТаблицаЗначений
			Иначе 
				ЗначениеРеквизита = Новый Структура; // Мультиметка7726614
			КонецЕсли; 
			Для НомерРеквизита = 1 По КоличествоРеквизитовКоллекции Цикл
				УзелДочерний = УзелDOM.РодительскийУзел.РодительскийУзел.ДочерниеУзлы[НомерУзлаВложенных + НомерРеквизита].ДочерниеУзлы[3];
				ОписаниеРеквизита = РеквизитыКоллекции.Добавить();
				ОписаниеРеквизита.Имя = ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(УзелДочерний.ТекстовоеСодержимое);
				ирОбщий.ОбновитьКопиюСвойстваВНижнемРегистреЛкс(ОписаниеРеквизита);
				ОписаниеРеквизита.Индекс = УзелДочерний.РодительскийУзел.ДочерниеУзлы[1].ПервыйДочерний.ТекстовоеСодержимое; 
				ОписаниеРеквизита.ОписаниеТипов = ТипЗначенияИзУзлаФормы(УзелДочерний.СледующийСоседний.СледующийСоседний);
				Если ТипЗнч(ЗначениеРеквизита) = Тип("Структура") Тогда
					ЗначениеРеквизита.Вставить(ОписаниеРеквизита.Имя, ОписаниеРеквизита.ОписаниеТипов);
				Иначе
					ЗначениеРеквизита.Колонки.Добавить(ОписаниеРеквизита.Имя, ОписаниеРеквизита.ОписаниеТипов);
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
		ОписаниеРеквизита = ИмитаторФормы.Реквизиты.Добавить();
		ОписаниеРеквизита.Имя = ИмяРеквизита;
		ирОбщий.ОбновитьКопиюСвойстваВНижнемРегистреЛкс(ОписаниеРеквизита);
		ОписаниеРеквизита.Индекс = УзелDOM.РодительскийУзел.РодительскийУзел.ДочерниеУзлы[1].ПервыйДочерний.ТекстовоеСодержимое; 
		ОписаниеРеквизита.ОписаниеТипов = ОписаниеТипов;
		ОписаниеРеквизита.Реквизиты = РеквизитыКоллекции;
		ОписаниеРеквизита.Значение = ЗначениеРеквизита;
		УзелDOM = НаборУзлов.ПолучитьСледующий();
	КонецЦикла;
	
	// Элементы         
	ВсеТипыЭлементов = Новый Соответствие;
	ВсеТипыЭлементов.Вставить("1", Тип("ДополнениеЭлементаФормы"));
	ВсеТипыЭлементов.Вставить("cd5394d0-7dda-4b56-8927-93ccbe967a01", Тип("ГруппаФормы"));
	ВсеТипыЭлементов.Вставить("77ffcc29-7f2d-4223-b22f-19666e7250ba", Тип("ПолеФормы"));
	ВсеТипыЭлементов.Вставить("143c00f7-a42d-4cd7-9189-88e4467dc768", Тип("ТаблицаФормы"));
	ВсеТипыЭлементов.Вставить("a9f3b1ac-f51b-431e-b102-55a69acdecad", Тип("КнопкаФормы"));
	ВсеТипыЭлементов.Вставить("3d3cb80c-508b-41fa-8a18-680cdf5f1712", Тип("ДекорацияФормы"));
	ВидыЭлементовПоля = Новый Соответствие;
	ВидыЭлементовПоля.Вставить("1", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеНадписи));
	ВидыЭлементовПоля.Вставить("2", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеВвода));
	ВидыЭлементовПоля.Вставить("3", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеФлажка));
	ВидыЭлементовПоля.Вставить("4", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеКартинки));
	ВидыЭлементовПоля.Вставить("5", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеПереключателя));
	ВидыЭлементовПоля.Вставить("6", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеТабличногоДокумента));
	ВидыЭлементовПоля.Вставить("7", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеТекстовогоДокумента));
	ВидыЭлементовПоля.Вставить("8", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеКалендаря));
	ВидыЭлементовПоля.Вставить("9", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеИндикатора));
	ВидыЭлементовПоля.Вставить("10", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеПолосыРегулирования));
	ВидыЭлементовПоля.Вставить("11", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеДиаграммы));
	ВидыЭлементовПоля.Вставить("12", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеДиаграммыГанта));
	ВидыЭлементовПоля.Вставить("14", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеГрафическойСхемы));
	ВидыЭлементовПоля.Вставить("15", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеHTMLДокумента));
	ВидыЭлементовПоля.Вставить("17", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеФорматированногоДокумента));
	ВидыЭлементовПоля.Вставить("18", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеПериода));
	ВидыЭлементовПоля.Вставить("19", ПолучитьПолноеИмяПредопределенногоЗначения(ВидПоляФормы.ПолеПланировщика));
	ПутиКРодителям = Новый Соответствие;
	//Выражение = "/e/e[1]/e/d[6]/text()"; // Корневые элементы
	// Антибаг платформы 8.3.23. Просмотр поддерева "//" работает крайне медленно https://www.hostedredmine.com/issues/977092
	//Выражение = "/e/e[1]/e//d[(position()=5 or position()=6) and starts-with(text(), '""') and text()!='""""']/text()"; // Все элементы
	ШаблонУровня = "";
	Для Счетчик = 0 По 8 Цикл
		Выражение = "/e/e[1]/e/" + ШаблонУровня + "d[(position()=5 or position()=6) and starts-with(text(), '""') and text()!='""""']/text()"; // Все элементы
		ШаблонУровня = ШаблонУровня + "*/";
		НаборУзлов = ДокументDOM.ВычислитьВыражениеXPath(Выражение, ДокументDOM, Разыменователь, ТипРезультатаDOMXPath.Строка);
		УзелDOM = НаборУзлов.ПолучитьСледующий();
		Пока УзелDOM <> Неопределено Цикл 
			ИмяЭлемента = ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(УзелDOM.ТекстовоеСодержимое);
			Если Ложь
				Или Не ирОбщий.ЛиИмяПеременнойЛкс(ИмяЭлемента)
				Или ирОбщий.СтрНачинаетсяСЛкс(ИмяЭлемента, "Navigator") 
			Тогда
				Перейти ~СледующийЭлемент;
			КонецЕсли;
			ПутьКДанным = Новый Массив;
			Если УзелDOM.РодительскийУзел.РодительскийУзел.ДочерниеУзлы.Количество() <= 12 Тогда
				УзлыПутиКДанным = Новый Массив;
			Иначе 
				УзлыПутиКДанным = УзелDOM.РодительскийУзел.РодительскийУзел.ДочерниеУзлы[12].ДочерниеУзлы;
			КонецЕсли;
			Если УзлыПутиКДанным.Количество() > 1 Тогда
				ГлубинаПутиКДанным = Число(УзлыПутиКДанным[0].ТекстовоеСодержимое);
				Если ГлубинаПутиКДанным > 0 Тогда
					ИдентификаторыРеквизитов = Новый Соответствие;
					РеквизитыРодителя = ИмитаторФормы.Реквизиты;
					Для Индекс = 1 По ГлубинаПутиКДанным Цикл
						ИндексРеквизита = УзлыПутиКДанным[Индекс].ТекстовоеСодержимое;
						СтрокаРеквизита = РеквизитыРодителя.Найти(ИндексРеквизита, "Индекс");
						Если СтрокаРеквизита <> Неопределено Тогда
							ИмяРеквизита = СтрокаРеквизита.Имя;
						Иначе
							ИмяРеквизита = ИндексРеквизита;
							#Если Клиент Тогда
							Если Форма <> Неопределено И Найти(ИмяРеквизита, "-") > 0 Тогда
								ПутьКРодителю = ирОбщий.СтрСоединитьЛкс(ПутьКДанным, ".");
								ИдентификаторыРеквизитов = ПутиКРодителям[ПутьКРодителю];
								Если ИдентификаторыРеквизитов = Неопределено Тогда
									ИменаРеквизитовФормы(Форма, ПутьКРодителю,, ИдентификаторыРеквизитов);
									ПутиКРодителям[ПутьКРодителю] = ИдентификаторыРеквизитов;
								КонецЕсли;
								Идентификатор = ирОбщий.СтрСоединитьЛкс(ирОбщий.ВыгрузитьСвойствоЛкс(УзлыПутиКДанным[Индекс].ДочерниеУзлы, "текстовоеСодержимое"), ":");
								ИмяРеквизита = ИдентификаторыРеквизитов[Идентификатор];
							КонецЕсли;
							#КонецЕсли
						КонецЕсли;      
						ПутьКДанным.Добавить(ИмяРеквизита);
						Если Ложь
							Или СтрокаРеквизита = Неопределено 
							Или СтрокаРеквизита.Реквизиты = Неопределено
						Тогда
							Прервать;
						КонецЕсли;
						РеквизитыРодителя = СтрокаРеквизита.Реквизиты;
					КонецЦикла;
				КонецЕсли;
			КонецЕсли;
			ПутьКДанным = ирОбщий.СтрСоединитьЛкс(ПутьКДанным, ".");
			ТипЭлемента = ВсеТипыЭлементов[УзелDOM.РодительскийУзел.РодительскийУзел.ПредыдущийСоседний.ТекстовоеСодержимое]; 
			ВидЭлемента = Неопределено;
			ВидЭлементаИмя = "";
			ОписаниеЭлемента = Новый Структура;
			Если ТипЭлемента = Неопределено Тогда
				Если ирОбщий.СтрКончаетсяНаЛкс(ИмяЭлемента, "РасширеннаяПодсказка") Тогда 
					ТипЭлемента = Тип("ДекорацияФормы");
				ИначеЕсли ирОбщий.СтрКончаетсяНаЛкс(ИмяЭлемента, "КонтекстноеМеню") Тогда 
					ТипЭлемента = Тип("ГруппаФормы");
					ВидЭлемента = ВидГруппыФормы.КонтекстноеМеню;
				ИначеЕсли ирОбщий.СтрКончаетсяНаЛкс(ИмяЭлемента, "КоманднаяПанель") Тогда 
					ТипЭлемента = Тип("ГруппаФормы");
					ВидЭлемента = ВидГруппыФормы.КоманднаяПанель;
				Иначе 
					// Опасно. Можно отсечь что то полезное  
					Перейти ~СледующийЭлемент;
				КонецЕсли;
				Если ВидЭлемента <> Неопределено Тогда
					ВидЭлементаИмя = ПолучитьПолноеИмяПредопределенногоЗначения(ВидЭлемента);
				КонецЕсли;
			ИначеЕсли ТипЭлемента = Тип("ПолеФормы") Тогда
				ВидЭлементаИмя = ВидыЭлементовПоля[УзелDOM.РодительскийУзел.ПредыдущийСоседний.ТекстовоеСодержимое];
			КонецЕсли;
			Если Ложь
				Или ВидЭлемента = ВидГруппыФормы.КоманднаяПанель 
				Или ВидЭлемента = ВидГруппыФормы.КонтекстноеМеню 
			Тогда 
				//
			Иначе 
				ИменаОбработчиков = ИменаОбработчиковИзУзлаФормы(ДокументDOM, УзелDOM.РодительскийУзел.РодительскийУзел, Разыменователь);
				ОписаниеЭлемента.Вставить("ИменаОбработчиков", ИменаОбработчиков);
			КонецЕсли;
			ОписаниеЭлемента.Вставить("ПутьКДанным", ПутьКДанным);
			ОписаниеЭлемента.Вставить("Тип", ТипЭлемента);
			ОписаниеЭлемента.Вставить("Вид", ВидЭлементаИмя);
			ИмитаторФормы.Элементы.Вставить(ИмяЭлемента, ОписаниеЭлемента);
	~СледующийЭлемент:
			УзелDOM = НаборУзлов.ПолучитьСледующий();
		КонецЦикла;
	КонецЦикла;
	
	// параметры
	Выражение = "/e/e[3]/e/d[2]/text()"; // Все параметры
	НаборУзлов = ДокументDOM.ВычислитьВыражениеXPath(Выражение, ДокументDOM, Разыменователь, ТипРезультатаDOMXPath.Строка);
	УзелDOM = НаборУзлов.ПолучитьСледующий();
	Пока УзелDOM <> Неопределено Цикл
		ИмитаторФормы.Параметры.Вставить(ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(УзелDOM.ТекстовоеСодержимое), ТипЗначенияИзУзлаФормы(УзелDOM.РодительскийУзел.СледующийСоседний));
		УзелDOM = НаборУзлов.ПолучитьСледующий();
	КонецЦикла;    
	
	// команды
	Выражение = "/e/e[4]/e/d[2]/text()"; // Все команды
	НаборУзлов = ДокументDOM.ВычислитьВыражениеXPath(Выражение, ДокументDOM, Разыменователь, ТипРезультатаDOMXPath.Строка);
	УзелDOM = НаборУзлов.ПолучитьСледующий();
	Пока УзелDOM <> Неопределено Цикл
		ИмитаторФормы.Команды.Вставить(ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(УзелDOM.ТекстовоеСодержимое));
		УзелDOM = НаборУзлов.ПолучитьСледующий();
	КонецЦикла;
	
	ФайлФормы = ФайлМодуляИзИмениМодуля(СлужебныеДанные.ИмяФормы, "xml", Истина);
	ирОбщий.СохранитьЗначениеВФайлЛкс(ИмитаторФормы, ФайлФормы.ПолноеИмя); 
	ДополнитьСлужебныеДанныеИзКэшаФормы(СлужебныеДанные, ИмитаторФормы, ТекущаяДата()); 
	Возврат Истина;
КонецФункции

//.
// Возвращаемое значение:
//    Структура - 
Функция ИмитаторУправляемойФормы() Экспорт
	ИмитаторФормы = Новый Структура;
	ИмитаторФормы.Вставить("ВерсияФормата", ВерсияФорматаСтруктурыФормы());
	ИмитаторФормы.Вставить("Элементы", Новый Структура);
	ИмитаторФормы.Вставить("Параметры", Новый Структура);
	ИмитаторФормы.Вставить("Команды", Новый Структура);
	ИмитаторФормы.Вставить("ДинамическиеСписки", Новый Структура);
	ИмитаторФормы.Вставить("ИменаОбработчиков", Новый Массив);
	ИмитаторФормы.Вставить("Реквизиты"); // см. НоваяТаблицаРеквизитовФормы()
	Возврат ИмитаторФормы;
КонецФункции

Функция ВерсияФорматаСтруктурыФормы()
	Возврат 3; // Каждый раз при изменении структуры увеличиваем на 1
КонецФункции

Процедура ДополнитьСлужебныеДанныеИзКэшаФормы(Знач СлужебныеДанные, Знач ИмитаторФормы, Знач ДатаОбновления) Экспорт 
	
	Если Ложь
		Или Не СлужебныеДанные.Свойство("Элементы")
		Или ИмитаторФормы.Элементы.Количество() > 0 
	Тогда
		ирОбщий.СкопироватьКоллекциюЛкс(ИмитаторФормы, СлужебныеДанные); 
		Для Каждого СтрокаЭлемента Из СлужебныеДанные.Элементы Цикл
			Если ЗначениеЗаполнено(СтрокаЭлемента.Значение.Вид) Тогда
				СтрокаЭлемента.Значение.Вид = ПредопределенноеЗначение(СтрокаЭлемента.Значение.Вид);
			КонецЕсли;
			ЗначениеРеквизита = Неопределено; 
			ПутьКДанным = СтрокаЭлемента.Значение.ПутьКДанным;
			Если ЗначениеЗаполнено(ПутьКДанным) Тогда
				СтрокаРеквизита = ИмитаторФормы.Реквизиты.Найти(ПутьКДанным, "Имя");
				Если СтрокаРеквизита <> Неопределено Тогда
					ЗначениеРеквизита = СтрокаРеквизита.Значение;
					ОписаниеТипов = СтрокаРеквизита.ОписаниеТипов;
				КонецЕсли;
			КонецЕсли;
			СтрокаЭлемента.Значение.Вставить("ОписаниеТипов", ОписаниеТипов);
			СтрокаЭлемента.Значение.Вставить("Значение", ЗначениеРеквизита);
		КонецЦикла;
	КонецЕсли;
	//СлужебныеДанные.Вставить("ПутиКДанным", ИмитаторФормы.Элементы);
	СлужебныеДанные.Вставить("ДатаОбновления", ДатаОбновления);
	СлужебныеДанные.Вставить("Тип", ирОбщий.ТипУправляемаяФормаЛкс());

КонецПроцедуры

//.
// Параметры:
//    ДокументDOM - ДокументDOM, ДокументHTML - 
//    УзелDOM - АтрибутDOM, ДокументDOM, КомментарийDOM, НотацияDOM, ОпределениеТипаДокументаDOM, СекцияCDATADOM, СущностьDOM, ТекстDOM, ФрагментДокументаDOM, ЭлементDOM, ... - 
//    Разыменователь - РазыменовательПространствИменDOM - 
// Возвращаемое значение:
//    Массив - 
Функция ИменаОбработчиковИзУзлаФормы(Знач ДокументDOM, Знач УзелDOM, Знач Разыменователь)
	ОбработчикиСобытий = Новый Массив;
	// Тут цикл поиска по глубине давал замедление!
	ВыражениеОбработчиков = ".//d[contains(text(),'-') and not(starts-with(text(),'-') or text()='00000000-0000-0000-0000-000000000000')]/following-sibling::d[1][not(text()='0' or contains(text(),'""""') or contains(text(),'-'))]/text()";
	НаборУзловОбработчиков = ДокументDOM.ВычислитьВыражениеXPath(ВыражениеОбработчиков, УзелDOM, Разыменователь, ТипРезультатаDOMXPath.Строка); // Долго!
	УзелОбработчика = НаборУзловОбработчиков.ПолучитьСледующий();
	Пока УзелОбработчика <> Неопределено Цикл 
		ОбработчикиСобытий.Добавить(ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(УзелОбработчика.ТекстовоеСодержимое));
		УзелОбработчика = НаборУзловОбработчиков.ПолучитьСледующий();
	КонецЦикла;
	Возврат ОбработчикиСобытий;
КонецФункции

// .
// Возвращаемое значение:
//    ТаблицаЗначений - 
Функция НоваяТаблицаРеквизитовФормы() Экспорт 
	Реквизиты = Новый ТаблицаЗначений;
	Реквизиты.Колонки.Добавить("Индекс");
	Реквизиты.Колонки.Добавить("Имя");
	Реквизиты.Колонки.Добавить("НИмя");
	Реквизиты.Колонки.Добавить("ОписаниеТипов");
	Реквизиты.Колонки.Добавить("Реквизиты");
	Реквизиты.Колонки.Добавить("Значение");
	//Реквизиты.Колонки.Добавить("ЛиДляКоллекции", Новый ОписаниеТипов("Булево"));
	Возврат Реквизиты;
КонецФункции

//.
// Параметры:
//    УзелТипа - ЭлементDOM - 
// Возвращаемое значение:
//    ОписаниеТипов - 
Функция ТипЗначенияИзУзлаФормы(Знач УзелТипа)
	Тип = Неопределено;
	Если УзелТипа.ДочерниеУзлы.Количество() > 1 Тогда
		РодТипа = УзелТипа.ДочерниеУзлы[1].ДочерниеУзлы[0].ДочерниеУзлы[0];
		Если РодТипа.ТекстовоеСодержимое = """S""" Тогда
			Тип = Тип("Строка");
		ИначеЕсли РодТипа.ТекстовоеСодержимое = """B""" Тогда
			Тип = Тип("Булево");
		ИначеЕсли РодТипа.ТекстовоеСодержимое = """N""" Тогда
			Тип = Тип("Число");
		ИначеЕсли РодТипа.ТекстовоеСодержимое = """D""" Тогда
			Тип = Тип("Число");
		ИначеЕсли РодТипа.ТекстовоеСодержимое = """#""" Тогда
			ИДТипа = УзелТипа.ДочерниеУзлы[1].ДочерниеУзлы[1].ТекстовоеСодержимое;
			Попытка
				Тип = ЗначениеИзСтрокиВнутр("{""T""," + ИДТипа + "}");
			Исключение
			КонецПопытки;
		Иначе
			Пустышка = 0;
		КонецЕсли;
	КонецЕсли;
	Возврат новый ОписаниеТипов(ирОбщий.ЗначенияВМассивЛкс(Тип));
КонецФункции

// Возвращаемое значение:
//    Структура - 
Функция НовыеФлагиКомпиляции(Знач Сервер = Истина, Знач КлиентОбычноеПриложение = Истина, Знач КлиентУправляемоеПриложение = Истина, Знач БезКонтекста = Ложь) Экспорт
	ФлагиКомпиляции = Новый Структура;
	ФлагиКомпиляции.Вставить("Сервер", Сервер);
	ФлагиКомпиляции.Вставить("КлиентОбычноеПриложение", КлиентОбычноеПриложение);
	ФлагиКомпиляции.Вставить("КлиентУправляемоеПриложение", КлиентУправляемоеПриложение);
	ФлагиКомпиляции.Вставить("БезКонтекста", БезКонтекста);
	Возврат ФлагиКомпиляции;
КонецФункции

Функция ОписаниеМетодаМодуля(ПолноеИмяМетода) Экспорт 
	
	СтруктураТипа = НоваяСтруктураТипа();
	СтруктураТипа.ИмяОбщегоТипа = "ОбщийМодуль";
	СтруктураТипа.Метаданные = Метаданные.ОбщиеМодули[ирОбщий.ПервыйФрагментЛкс(ПолноеИмяМетода)];
	МодульМетаданных = ПодготовитьМодульМетаданных(СтруктураТипа);
	Если МодульМетаданных = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли; 
	МетодыМодуля = МодульМетаданных.Методы;
	#Если Сервер И Не Сервер Тогда
		МетодыМодуля = Новый ТаблицаЗначений;
	#КонецЕсли
	ОписаниеМетода = МетодыМодуля.Найти(ирОбщий.ПоследнийФрагментЛкс(ПолноеИмяМетода), "Имя");
	Возврат ОписаниеМетода;

КонецФункции

Функция ПолучитьРазделыМодуля1С(Знач ТекстМодуля = "") Экспорт
	
	#Если Сервер И Не Сервер Тогда
		RegExp = Обработки.ирОболочкаРегВыражение.Создать();
	#КонецЕсли
	Шаблоны = ШаблоныДляАнализаВстроенногоЯзыка();
	RegExp.IgnoreCase = Истина;
	RegExp.MultiLine = Ложь;
	RegExp.Global = Истина;
	RegExp.Pattern = Шаблоны.ЭлементОбластиМетодов;
	ВхожденияМетодов = RegExp.НайтиВхождения(ТекстМодуля); 
	ПозицияНачалаПервогоМетода = 1;
	ПозицияКонцаПоследнегоМетода = 1; 
	Для Индекс = 0 По ВхожденияМетодов.Количество() - 1 Цикл
		Вхождение = ВхожденияМетодов[Индекс];
		Если Вхождение.SubMatches(1) <> Неопределено Тогда
			ПозицияНачалаПервогоМетода = Вхождение.FirstIndex + 1;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Для Индекс = 1 - ВхожденияМетодов.Количество() По 0 Цикл // Обратный обход
		Вхождение = ВхожденияМетодов[-Индекс];
		Если Вхождение.SubMatches(1) <> Неопределено Тогда
			ПозицияКонцаПоследнегоМетода = Вхождение.FirstIndex + Вхождение.Length + 1;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Если ПозицияКонцаПоследнегоМетода = 1 Тогда
		RegExp.Pattern = Шаблоны.ОписаниеСтрокиПеременных;
		ВхожденияПеременных = RegExp.НайтиВхождения(ТекстМодуля);
		Для Индекс = 1 - ВхожденияПеременных.Количество() По 0 Цикл // Обратный обход
			Вхождение = ВхожденияПеременных[-Индекс];
			ПозицияНачалаПервогоМетода = Вхождение.FirstIndex + Вхождение.Length + 1;
			ПозицияКонцаПоследнегоМетода = ПозицияНачалаПервогоМетода;
			Прервать;
		КонецЦикла;
	КонецЕсли; 
	Результат = Новый Структура;
	Результат.Вставить("ПеременныеТекст", Сред(ТекстМодуля, 1, ПозицияНачалаПервогоМетода - 1));
	Результат.Вставить("МетодыТекст", Сред(ТекстМодуля, ПозицияНачалаПервогоМетода, ПозицияКонцаПоследнегоМетода - ПозицияНачалаПервогоМетода));
	Если ПозицияНачалаПервогоМетода < ПозицияКонцаПоследнегоМетода Тогда
		ПозицияКонцаПоследнегоМетода = ПозицияКонцаПоследнегоМетода + 1;
	КонецЕсли;
	Результат.Вставить("ПозицияМетодов", ПозицияНачалаПервогоМетода);  // начиная с 1
	Результат.Вставить("ПозицияПрограммы", ПозицияКонцаПоследнегоМетода); // начиная с 1
	Результат.Вставить("Программа", Сред(ТекстМодуля, Результат.ПозицияПрограммы));
	Результат.Вставить("ВхожденияМетодов", ВхожденияМетодов);
	Возврат Результат;
	
КонецФункции

Функция ШаблоныДляАнализаВстроенногоЯзыка() Экспорт
Перем шИмя, шПустоеНачалоСтроки, шКомментарий, шРазделитель, шСтруктураКомментаПарам, шСтруктураКомментаВозвр, шВозврат, шСтруктураКомментаОписаниеПараметров, шКомментМетода, шОписаниеПеременной,
шСтрокаПеременныхБезКомментов, шСтрокаПеременных, шЛитералПрограммы, шПараметрыМетода, шДирективаИлиАннотация, шБлокКомментов, шМетодЧистый, шМетод1, шМетодСПредКомментом, шСтруктураМодуля, шЭлементОбластиМетодов;

	Если мШаблоныДляАнализаВстроенногоЯзыка <> Неопределено Тогда
		Возврат мШаблоныДляАнализаВстроенногоЯзыка;
	КонецЕсли;
// {ОписаниеРегулярногоВыражения.Начало} конструктор из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
// {Шаблон.Начало}
// + <шИмя> = [_ЁА-ЯA-Z][_ЁА-ЯA-Z\d]*
// + <шПустоеНачалоСтроки> = (?:\n|^)(?:\t| )*
// + <шКомментарий> = //[^\n]*(?=(?:\n|$))
// + <шРазделитель> = (?:<шКомментарий>|\s|\xa0|$)
// + <шСтруктураКомментаПарам> = Параметры(?:\s*:\s*)?((([^\n]\n)*|.|\n)*)(?:\n\s*Возвращаемое значение\s*\:?\s*\n|$)
// + <шСтруктураКомментаВозвр> = Возвращаемое значение(?:\s*:\s*)?((([^\n]\n)*|.|\n)*)(?:\n\s*Параметры\s*\:?\s*\n|$)
// + <шВозврат> = Возврат\s+(?:Неопределено|Undefined|Null|(<шИмя>))(?:;|\n|\r|$)
// + <шСтруктураКомментаОписаниеПараметров> = (<шИмя>)(?:\s*[-–])([^\n]*(?:\n|$)(\s{4}[^\n]*(?:\n|$))*)
// + <шКомментМетода> = ((?:[\f\r\t\v]*//[^\n]*\n)+)(?:Функция|Процедура)<шРазделитель>*(<шИмя>)
// + <шОписаниеПеременной> = (<шИмя>)(<шРазделитель>+Экспорт)?
// + <шСтрокаПеременныхБезКомментов> = <шПустоеНачалоСтроки>Перем((?:<шРазделитель>*<шОписаниеПеременной><шРазделитель>*[;,])+)
// + <шСтрокаПеременных> = <шСтрокаПеременныхБезКомментов>([^\n\S]*//[^\n]*)?
// + <шЛитералПрограммы> = "(?:(?:"")|[^"\n])*(?:<шРазделитель>*\|(?:(?:"")|[^"\n])*)*(?:"|$)
// + <шПараметрыМетода> = <шРазделитель>*(Знач\s)?<шРазделитель>*(<шИмя>)<шРазделитель>*=?((?:<шРазделитель>*|(<шЛитералПрограммы>)|(?:[^,\n]*))+)(?:,|$)
// + <шДирективаИлиАннотация> = (?:\n\s*)?<шПустоеНачалоСтроки>[#&][^\n]*(?=\n|$)
// + <шБлокКомментов> = <шКомментарий>(?:<шПустоеНачалоСтроки><шКомментарий>)*(?=(?:\n|$))
// + <шМетодЧистый> = ([\t ]*(?:Асинх\s+)?(Процедура|Функция)<шРазделитель>*(<шИмя>)<шРазделитель>*\(([^\)]*)\)(<шРазделитель>*Экспорт)?(?:\s*?(?=\n))?(?:\n\s*Перем .*(?=\n))*)((?:<шЛитералПрограммы>|<шБлокКомментов>|\.Конец(?:Процедуры|Функции)|(?:\r|\n|.)(?!Конец(?:Процедуры|Функции)))*)(?:$|[^а-яё_a-z0-9\."]Конец(?:Процедуры|Функции)(?=(?:<шКомментарий>|[^а-яё_a-z0-9\."]|$)))
// + <шМетодСПредКомментом> = (?:(<шБлокКомментов>\n)|\n|^)[\t ]*<шМетодЧистый>
// + <шЭлементОбластиМетодов> = <шМетодСПредКомментом>|(<шБлокКомментов>)|(<шДирективаИлиАннотация>)
// {Шаблон.Конец}

шИмя = ЭтотОбъект.шИмя;
шПустоеНачалоСтроки = ЭтотОбъект.шПустоеНачалоСтроки;
шКомментарий = ЭтотОбъект.шКомментарий;
шРазделитель = ЭтотОбъект.шРазделитель;
шЛитералПрограммы = ЭтотОбъект.шЛитералПрограммы;
шСтруктураКомментаПарам = "Параметры(?:\s*:\s*)?((([^\n]\n)*|.|\n)*)(?=\n\s*Возвращаемое значение\s*\:?\s*\n|$)"; // Всегда захватывает блок возвращаемого значения
шСтруктураКомментаВозвр = "Возвращаемое значение(?:\s*:\s*)?((([^\n]\n)*|.|\n)*)(?:\n\s*Параметры\s*\:?\s*\n|$)";
//шВозврат = "Возврат\s+(?:Неопределено|Undefined|Null|(" + шИмя + "))(?:;|\n|\r|$)";
шВозврат = "Возврат\s+(.+?)(?:;| КонецЕсли|\n|\r|$)";
шСтруктураКомментаОписаниеПараметров = "(" + шИмя + ")(?:\s*[-–])([^\n]*(?:\n|$)(\s{4}[^\n]*(?:\n|$))*)";
шКомментМетода = "((?:[\f\r\t\v]*//[^\n]*\n)+)(?:Функция|Процедура)" + шРазделитель + "+(" + шИмя + ")";
шОписаниеПеременной = "(" + шИмя + ")(" + шРазделитель + "+Экспорт)?";
шСтрокаПеременныхБезКомментов = "Перем((?:" + шРазделитель + "*" + шОписаниеПеременной + "" + шРазделитель + "*[;,])+)";
шСтрокаПеременных = "" + шПустоеНачалоСтроки + шСтрокаПеременныхБезКомментов + "([^\n\S]*//[^\n]*)?";
шПараметрыМетода = "" + шРазделитель + "*(Знач\s)?" + шРазделитель + "*(" + шИмя + ")" + шРазделитель + "*=?((?:" + шРазделитель + "*|(" + шЛитералПрограммы + ")|(?:[^,\n]*))+)(?:,|$)";
шДирективаИлиАннотация = "(?:\n\s*)?" + шПустоеНачалоСтроки + "[#&][^\n]*(?=\n|$)";
шБлокКомментов = "" + шКомментарий + "(?:" + шПустоеНачалоСтроки + "" + шКомментарий + ")*(?=(?:\n|$))";
шМетодЧистый = "([\t ]*(?:Асинх\s+)?(Процедура|Функция)" + шРазделитель + "+(" + шИмя + ")" + шРазделитель + "*\(([^\)]*)\)(" + шРазделитель + "*Экспорт)?(?:\s*?(?=\n))?(?:\n\s*Перем .*(?=\n))*)"
	+ "((?:" + шЛитералПрограммы + "|" + шБлокКомментов + "|\.Конец(?:Процедуры|Функции)|(?:\r|\n|.)(?!Конец(?:Процедуры|Функции)))*)(?:$|[^а-яё_a-z0-9\.""]Конец(?:Процедуры|Функции)(?=(?:" + шКомментарий + "|[^а-яё_a-z0-9\.""]|$)))";
шМетодСПредКомментом = "(?:(" + шБлокКомментов + "\n)|\n|^)" + шМетодЧистый + "";
шЭлементОбластиМетодов = "" + шМетодСПредКомментом + "|(" + шБлокКомментов + ")|(" + шДирективаИлиАннотация + ")";
// {ОписаниеРегулярногоВыражения.Конец}
		
	Результат = Новый Структура;
	Результат.Вставить("СтрокаПрограммы", шЛитералПрограммы);
	Результат.Вставить("ДирективаПрепроцессора", шДирективаИлиАннотация);
	Результат.Вставить("БлокКомментариев", шБлокКомментов);
	Результат.Вставить("ОписаниеМетодаСКомментарием", шМетодСПредКомментом);
	Результат.Вставить("ОписаниеМетодаЧистое", шМетодЧистый);
	Результат.Вставить("ЭлементОбластиМетодов", шЭлементОбластиМетодов);
	Результат.Вставить("ОписаниеПеременной", шОписаниеПеременной);
	Результат.Вставить("ОписаниеСтрокиПеременных", шСтрокаПеременных);
	Результат.Вставить("ОписаниеСтрокиПеременныхБезКомментов", шСтрокаПеременныхБезКомментов);
	Результат.Вставить("КомментарийОписаниеМетода", шКомментМетода);
	Результат.Вставить("ПараметрыМетода", шПараметрыМетода);
	Результат.Вставить("СтруктураКомментарияВозвр", шСтруктураКомментаВозвр);
	Результат.Вставить("СтруктураКомментарияПарам", шСтруктураКомментаПарам);
	Результат.Вставить("СтруктураКомментарияОписаниеПараметров", шСтруктураКомментаОписаниеПараметров);
	Результат.Вставить("Возврат", шВозврат);
	Результат.Вставить("ОписаниеПараметра", ".*(?:\n(?://)?(?:[\t ]{5,}|[\t ]+\*).*)*");
	мШаблоныДляАнализаВстроенногоЯзыка = Результат;
    Возврат Результат;
КонецФункции

// Функция - Модуль метаданных. Для пустого текста и НЕ пустого имени возращает единый модуль с именем "<Пустой>"!
//
// Параметры:
//  ТекстМодуля								 - Строка	 - 
//  СтруктураТипа							 - см. НоваяСтруктураТипа() -
//  ИмяМодуля								 - Строка	 - 
//  ПодготовитьОписанияРезультатовМетодов	 - Булево	 - 
//  СтарыйМодуль							 - см. МодульМетаданных() -
//  ТекущийМетод							 - см. НоваяТаблицаМетодовМодуля()[0] -
//  ТекущаяПозиция							 - Число - позиция в модуле
// 
// Возвращаемое значение:
//  Структура - 
//
Функция МодульМетаданных(Знач ТекстМодуля, Знач СтруктураТипа = Неопределено, Знач ИмяМодуля = "", Знач ПодготовитьОписанияРезультатовМетодов = Истина, Знач СтарыйМодуль = Неопределено,
	Знач ТекущаяПозиция = 0) Экспорт
	
	РазрешитьЕдиныйПустойМодуль = Истина
		И ПустаяСтрока(ТекстМодуля) 
		И ИмяМодуля <> ИмяДинамическогоМодуля() 
		И ЗначениеЗаполнено(ИмяМодуля);
	Если РазрешитьЕдиныйПустойМодуль И мПустойМодуль <> Неопределено Тогда
		// Для ускорения заполнения списка в Обработка.ирКлсПолеТекстаПрограммы.Форма.МетодыМодулей
		Возврат мПустойМодуль;
	КонецЕсли;
	ЛиНачальныйДиапазонСовпал = Ложь;
	ЛиКонечныйДиапазонСовпал = Ложь;
	Если Истина
		И Не ПустаяСтрока(ТекстМодуля)
		И СтарыйМодуль <> Неопределено        
		//И СтарыйМодуль.Свойство("Текст")
		И ЗначениеЗаполнено(ТекущаяПозиция)
		И ирКэш.НомерРежимаСовместимостиЛкс() >= 803006 // СтрНайти()
	Тогда
		МетодыСтарые = СтарыйМодуль.Методы;
		ТекущийМетод = СтарыйМодуль.ТекущийМетод; // см. МетодыСтарые.Добавить()   
		Если ТекущийМетод <> Неопределено Тогда
			Если Ложь
				Или МетодыСтарые.Индекс(ТекущийМетод) = -1
				Или ТекущийМетод.ПозицияСОписанием - ТекущаяПозиция > 1000 
				Или ТекущаяПозиция - (ТекущийМетод.ПозицияСОписанием + ТекущийМетод.ДлинаСОписанием) > 1000
			Тогда
				ТекущийМетод = Неопределено;
			КонецЕсли;
		КонецЕсли;
		ИндексТекущегоМетода = -1;
		Если ТекущийМетод <> Неопределено Тогда
			ИндексТекущегоМетода = МетодыСтарые.Индекс(ТекущийМетод); 
		КонецЕсли;
		Если ИндексТекущегоМетода = -1 Тогда
			ИндексТекущегоМетода = МетодыСтарые.Количество();
			Для Каждого Метод Из МетодыСтарые Цикл
				Если Метод.ПозицияСОписанием = 0 Тогда 
					Продолжить;
				КонецЕсли;
				Если Метод.ПозицияСОписанием + Метод.ДлинаСОписанием + 100 > ТекущаяПозиция Тогда 
					ИндексТекущегоМетода = МетодыСтарые.Индекс(Метод);
					ТекущийМетод = Метод;
					Прервать;
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
		Если ТекущийМетод <> Неопределено Тогда   
			ПозицияНачалаСтарая = ТекущийМетод.ПозицияСОписанием; 
			ПозицияКонцаСтарая = ПозицияНачалаСтарая + ТекущийМетод.ДлинаСОписанием;
		Иначе
			ПозицияНачалаСтарая = СтарыйМодуль.ПозицияПрограммы; 
			ПозицияКонцаСтарая = СтрДлина(СтарыйМодуль.Текст);
		КонецЕсли;
		ЧастьДоМетодаСтарая = Лев(СтарыйМодуль.Текст, ПозицияНачалаСтарая);
		ЧастьДоМетодаНовая = Лев(ТекстМодуля, ПозицияНачалаСтарая);
		Если ЧастьДоМетодаСтарая = ЧастьДоМетодаНовая Тогда
			ЛиНачальныйДиапазонСовпал = Истина;
			Если ТекущийМетод <> Неопределено Тогда
				Если ТекущийМетод.ТипЗначения = Неопределено Тогда 
					МаркерКонца = Символы.ПС + "КонецПроцедуры";
				Иначе 
					МаркерКонца = Символы.ПС + "КонецФункции";
				КонецЕсли;
				ПозицияКонцаНовая = ирОбщий.СтрНайтиЛкс(ТекстМодуля, МаркерКонца,, ПозицияНачалаСтарая) + СтрДлина(МаркерКонца);
			Иначе 
				ПозицияКонцаНовая = СтрДлина(ТекстМодуля);
				Если Ложь
					Или ирОбщий.СтрНайтиЛкс(ТекстМодуля, "КонецФункции",, ПозицияНачалаСтарая) > 0
					Или ирОбщий.СтрНайтиЛкс(ТекстМодуля, "КонецПроцедуры",, ПозицияНачалаСтарая) > 0
				Тогда 
					// в конец модуля вставлен метод
					ПозицияКонцаСтарая = 0;
				КонецЕсли;
			КонецЕсли;
			ЧастьПослеМетодаНовая = Сред(ТекстМодуля, ПозицияКонцаНовая);
			ЧастьПослеМетодаСтарая = Сред(СтарыйМодуль.Текст, ПозицияКонцаСтарая); 
			ЛиКонечныйДиапазонСовпал = ЧастьПослеМетодаНовая = ЧастьПослеМетодаСтарая;
			СмещениеКонечногоДиапазона = ПозицияКонцаНовая - ПозицияКонцаСтарая;
		КонецЕсли;
	КонецЕсли;
	НачальнаяПозицияДиапазона = 0;
	Если ЛиНачальныйДиапазонСовпал Тогда
		Модуль = СтарыйМодуль;
		СброситьКэшТиповВыраженийМодуля(Модуль);
		Методы = Модуль.Методы;
		Ошибки = Модуль.Ошибки; // ОбработкаТабличнаяЧасть.ирКлсПолеТекстаПрограммы.ОшибкиМодуля
		Если Ошибки <> Неопределено Тогда
			УдалитьОшибкиМетода(ТекущийМетод, Ошибки);
		КонецЕсли;
		НачальнаяПозицияДиапазона = ПозицияНачалаСтарая - 1;
		Если ЛиКонечныйДиапазонСовпал Тогда
			Если ТекущийМетод = Неопределено Тогда
				//СтароеНачалоБлока = ирОбщий.СтрокаБезПоследнегоФрагментаЛкс(Сред(СтарыйМодуль.Текст, ПозицияНачалаСтарая, ТекущаяПозиция - ПозицияНачалаСтарая), Символы.ПС);
				//СтароеКонецБлока = ирОбщий.СтрокаБезПервогоФрагментаЛкс(Сред(СтарыйМодуль.Текст, ТекущаяПозиция), Символы.ПС);
				//НовоеНачалоБлока = ирОбщий.СтрокаБезПоследнегоФрагментаЛкс(Сред(ТекстМодуля, ПозицияНачалаСтарая, ТекущаяПозиция - ПозицияНачалаСтарая), Символы.ПС);
				//НовоеКонецБлока = ирОбщий.СтрокаБезПервогоФрагментаЛкс(Сред(ТекстМодуля, ТекущаяПозиция), Символы.ПС);
				СтарыйТекстБлока = Модуль.Программа;
				ОпределениеСОписанием = Сред(ТекстМодуля, ПозицияНачалаСтарая);
				Модуль.Программа = ОпределениеСОписанием;
				ВхожденияМетодов = Новый Массив;
			Иначе 
				//СтароеНачалоБлока = ирОбщий.СтрокаБезПоследнегоФрагментаЛкс(Сред(СтарыйМодуль.Текст, ПозицияНачалаСтарая, ТекущаяПозиция - ПозицияНачалаСтарая), Символы.ПС);
				//СтароеКонецБлока = ирОбщий.СтрокаБезПервогоФрагментаЛкс(Сред(СтарыйМодуль.Текст, ТекущаяПозиция, ТекущийМетод.ДлинаСОписанием - (ТекущаяПозиция - ПозицияНачалаСтарая)), Символы.ПС); 
				//НовоеНачалоБлока = ирОбщий.СтрокаБезПоследнегоФрагментаЛкс(Сред(ТекстМодуля, ПозицияНачалаСтарая, ТекущаяПозиция - ПозицияНачалаСтарая), Символы.ПС);
				//НовоеКонецБлока = ирОбщий.СтрокаБезПервогоФрагментаЛкс(Сред(ТекстМодуля, ТекущаяПозиция, ТекущийМетод.ДлинаСОписанием + СмещениеКонечногоДиапазона - (ТекущаяПозиция - ПозицияНачалаСтарая)), Символы.ПС); 
				ТекущийМетод.КэшПоиска = Неопределено;
				ОпределениеСОписанием = Сред(ТекстМодуля, ПозицияНачалаСтарая, ТекущийМетод.ДлинаСОписанием + СмещениеКонечногоДиапазона);
				ВхожденияМетодов = ПолучитьРазделыМодуля1С(ОпределениеСОписанием).ВхожденияМетодов;
				_РежимОтладки = Ложь;
				Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
					// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
					Для ИндексМетодаЦикл = ИндексТекущегоМетода + 1 По Методы.Количество() - 1 Цикл
						СтрокаМетода = Методы[ИндексМетодаЦикл];
						Если СтрокаМетода.ПозицияСОписанием = 0 Тогда
							Продолжить; // Возможно даже Прервать
						КонецЕсли;
						СтрокаМетода.ПозицияСОписанием = СтрокаМетода.ПозицияСОписанием + СмещениеКонечногоДиапазона;
						СтрокаМетода.ПозицияОпределения = СтрокаМетода.ПозицияОпределения + СмещениеКонечногоДиапазона;
						СтрокаМетода.ПозицияТела = СтрокаМетода.ПозицияТела + СмещениеКонечногоДиапазона;
						Если Ошибки <> Неопределено И СтрокаМетода.ЕстьОшибки = Истина Тогда
							Для Каждого СтрокаОшибки Из Ошибки.НайтиСтроки(Новый Структура("Метод", СтрокаМетода.Имя)) Цикл
								СтрокаОшибки.Позиция = СтрокаОшибки.Позиция + СмещениеКонечногоДиапазона;
							КонецЦикла;  
						КонецЕсли;
					КонецЦикла;
				Иначе
					// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
					Для ИндексМетодаЦикл = ИндексТекущегоМетода + 1 По Методы.Количество() - 1 Цикл  					СтрокаМетода = Методы[ИндексМетодаЦикл];  					Если СтрокаМетода.ПозицияСОписанием = 0 Тогда  						Продолжить;  					КонецЕсли;  					СтрокаМетода.ПозицияСОписанием = СтрокаМетода.ПозицияСОписанием + СмещениеКонечногоДиапазона;  					СтрокаМетода.ПозицияОпределения = СтрокаМетода.ПозицияОпределения + СмещениеКонечногоДиапазона;  					СтрокаМетода.ПозицияТела = СтрокаМетода.ПозицияТела + СмещениеКонечногоДиапазона;  					Если Ошибки <> Неопределено И СтрокаМетода.ЕстьОшибки = Истина Тогда  						Для Каждого СтрокаОшибки Из Ошибки.НайтиСтроки(Новый Структура("Метод", СтрокаМетода.Имя)) Цикл  							СтрокаОшибки.Позиция = СтрокаОшибки.Позиция + СмещениеКонечногоДиапазона;  						КонецЦикла;  					КонецЕсли;  				КонецЦикла;  
				КонецЕсли;
				Модуль.ПозицияПрограммы = Модуль.ПозицияПрограммы + СмещениеКонечногоДиапазона;
			КонецЕсли;
			Если Модуль.ПрямыеВызовыМетодов <> Неопределено Тогда
				ВыполнитьОтложенноеОбновлениеВызововСловМодуля(Модуль, ПозицияНачалаСтарая);
				ОтложенныйСдвиг = НовыйОтложенныйСдвигВызововСловМодуля();
				ОтложенныйСдвиг.ПозицияНачалаСтарая = ПозицияНачалаСтарая;
				ОтложенныйСдвиг.ПозицияКонцаСтарая = ПозицияКонцаСтарая;
				ОтложенныйСдвиг.СмещениеКонечногоДиапазона = СмещениеКонечногоДиапазона;
				ОтложенныйСдвиг.ОпределениеСОписанием = ОпределениеСОписанием; 
				Модуль.ПрямыеВызовыМетодов.Вставить("ОтложенныйСдвиг", ОтложенныйСдвиг);     
				//Модуль.ФлагиКомпиляции. 
			КонецЕсли;
			//ИзмененаТолькоОднаСтрока = СтароеНачалоБлока = НовоеНачалоБлока И СтароеКонецБлока = НовоеКонецБлока; 
		Иначе
			Модуль.ТаблицыСлов.Очистить();
			КонечныйДиапазон = Сред(ТекстМодуля, ПозицияНачалаСтарая);
			РазделыМодуля = ПолучитьРазделыМодуля1С(КонечныйДиапазон); 
			Модуль.Программа = РазделыМодуля.Программа;
			Модуль.ПозицияПрограммы = ПозицияНачалаСтарая + РазделыМодуля.ПозицияПрограммы - 1;
			ВхожденияМетодов = РазделыМодуля.ВхожденияМетодов;
			Пока Методы.Количество() > ИндексТекущегоМетода Цикл
				Если Ошибки <> Неопределено Тогда
					УдалитьОшибкиМетода(Методы[ИндексТекущегоМетода], Ошибки);
				КонецЕсли;
				Методы.Удалить(ИндексТекущегоМетода);
			КонецЦикла;
			ТекущийМетод = Неопределено;
		КонецЕсли;
		Модуль.Текст = ТекстМодуля;
	Иначе 
		ТекущийМетод = Неопределено;
		Ошибки = Неопределено;
		Модуль = ПолучитьРазделыМодуля1С(ТекстМодуля);
		// При изменении нужно увеличивать версию формата Мультиметка91237881041
		Модуль.Вставить("СтруктураТипа", СтруктураТипа);
		Модуль.Вставить("Имя", ИмяМодуля);
		Модуль.Вставить("ФлагиКомпиляции"); // см. НовыеФлагиКомпиляции()
		Модуль.Вставить("ТекущийМетод");
		Модуль.Вставить("ТипыВыраженийПрограммы", Новый Соответствие);
		Модуль.Вставить("КэшПоискаПрограммы", Новый Соответствие);
		Модуль.Вставить("ТаблицыСлов", Новый Соответствие);
		Модуль.Вставить("ПрямыеВызовыМетодов"); // см. НовыйИндексПоискаВызововСловаВМодуле()
		Шаблоны = ШаблоныДляАнализаВстроенногоЯзыка();
		RegExp.IgnoreCase = Истина;
		RegExp.Multiline = Ложь; 
		
		// При изменении нужно увеличивать версию формата Мультиметка91237881041
		Переменные = Новый ТаблицаЗначений;
		Переменные.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
		Переменные.Колонки.Добавить("НИмя", Новый ОписаниеТипов("Строка"));
		Переменные.Колонки.Добавить("ЛиЭкспорт", Новый ОписаниеТипов("Булево"));
		Переменные.Колонки.Добавить("Вычислено", Новый ОписаниеТипов("Булево")); // вычислено по коду
		Переменные.Колонки.Добавить("ПозицияСОписанием", Новый ОписаниеТипов("Число")); // Начиная с 1. 
		Переменные.Колонки.Добавить("ПозицияОпределения", Новый ОписаниеТипов("Число")); // Начиная с 1. 
		Переменные.Колонки.Добавить("ТипЗначения", Новый ОписаниеТипов("Строка"));
		Переменные.Колонки.Добавить("Описание", Новый ОписаниеТипов("Строка"));
		Переменные.Колонки.Добавить("ИмяМодуля", Новый ОписаниеТипов("Строка"));
		Переменные.Колонки.Добавить("ТаблицаТипов"); // см. НоваяТаблицаТипов()
		//RegExp.Pattern = Шаблоны.ОписаниеСтрокиПеременных + "|(" + Шаблоны.БлокКомментариев + ")|(" + Шаблоны.ДирективаПрепроцессора + ")";
		RegExp.Pattern = Шаблоны.ОписаниеСтрокиПеременных + "|(" + Шаблоны.БлокКомментариев + ")|(" + Шаблоны.ДирективаПрепроцессора + ")";
		Вхождения = RegExp.НайтиВхождения(Модуль.ПеременныеТекст);
		Для Каждого Вхождение Из Вхождения Цикл
			Если Вхождение.SubMatches(0) <> Неопределено Тогда
				ТекстСтроки = Вхождение.SubMatches(0);
				ОписаниеСтроки = ОчиститьТекстМодуляОтПрефиксаКомментария(Вхождение.SubMatches(3));
				ПозицияСОписанием = Вхождение.FirstIndex + 2; 
				Если Найти(ТекстСтроки, ",") = 0 Тогда
					// Одна переменная в строке
					ИмяПеременной = ирОбщий.ПервыйФрагментЛкс(Вхождение.SubMatches(1));
					ЭкспортПеременной = ?(Вхождение.SubMatches(2) = Неопределено, Ложь, Истина);
					ДобавитьПеременную(Переменные, ИмяПеременной, ЭкспортПеременной, ОписаниеСтроки, ПозицияСОписанием);
				Иначе  
					// Несколько переменных в строке
					RegExp2.Pattern = Шаблоны.ОписаниеПеременной + "|\s*(?:;|,)"; 
					Результат2 = RegExp2.НайтиВхождения(ТекстСтроки); // тяжелая операция
					Для Каждого Вхождение2 Из Результат2 Цикл
						Если Вхождение2.SubMatches(0) <> Неопределено Тогда
							ИмяПеременной = Вхождение2.SubMatches(0);
							ЭкспортПеременной = ?(Вхождение2.SubMatches(1) = Неопределено, Ложь, Истина);
							ДобавитьПеременную(Переменные, ИмяПеременной, ЭкспортПеременной, ОписаниеСтроки, ПозицияСОписанием);
						КонецЕсли;
					КонецЦикла;
				КонецЕсли;
			//ИначеЕсли Вхождение.SubMatches(4) <> Неопределено Тогда
			//	СтрокаПеременной.Тип = "Комментарий";
			//ИначеЕсли Вхождение.SubMatches(5) <> Неопределено Тогда
			//	СтрокаПеременной.Тип = "Директива";
			КонецЕсли;
		КонецЦикла;  
		Модуль.Удалить("ПеременныеТекст");
		Модуль.Вставить("Переменные", Переменные);
		Методы = НоваяТаблицаМетодовМодуля();
		ВхожденияМетодов = Модуль.ВхожденияМетодов;
		Если СтруктураТипа <> Неопределено Тогда
			СтрокаМетода = Методы.Добавить();
			СтрокаМетода.Сервер = Истина;
			СтрокаМетода.Клиент = Истина; 
			СтрокаМетода.ЛиЭкспорт = Истина;
			СтрокаМетода.ЕстьОшибки = Ложь;
			СтрокаМетода.Имя = "<>";
			СтрокаМетода.ТипЗначения = "НеизвестныйКонтекст"; 
			ирОбщий.ОбновитьКопиюСвойстваВНижнемРегистреЛкс(СтрокаМетода);
		КонецЕсли;
	КонецЕсли;
	ПоследняяАннотация = "";
	ПоследнееОписание = "";
	ПоследнееНачалоОписания = Неопределено;
	ПоследнееНачалоАннотации = Неопределено;
	ПорогДлиныМаркераТела = 20;
	НачальнаяПозицияДиапазона = НачальнаяПозицияДиапазона + 1;
	ЭтоМодульФормы = ЛиИмяМодуляФормы(Модуль.Имя);
	Для Каждого Вхождение Из ВхожденияМетодов Цикл
		ПозицияВхождения = Вхождение.FirstIndex + НачальнаяПозицияДиапазона;
		Заголовок = Вхождение.SubMatches(1);
		Если Заголовок <> Неопределено Тогда
			Если ТекущийМетод <> Неопределено Тогда
				СтрокаМетода = ТекущийМетод;
				СтрокаМетода.ОписаниеРезультата = Неопределено;
				СтрокаМетода.ТелоБезВозвратов = Неопределено;
			Иначе 
				СтрокаМетода = Методы.Добавить();
			КонецЕсли;
			ОписаниеМетода = Вхождение.SubMatches(0);
			ДлинаОписания = СтрДлина(ОписаниеМетода);
			ОпределениеБезОписания = Сред(Вхождение.Value, ДлинаОписания + 1);
			Если Лев(ОпределениеБезОписания, 1) = Символы.ПС Тогда
				ОпределениеБезОписания = Сред(ОпределениеБезОписания, 2);
				ДлинаОписания = ДлинаОписания + 1;
			КонецЕсли;
			СтрокаМетода.ПозицияСОписанием = ПозицияВхождения;
			СтрокаМетода.ДлинаСОписанием = Вхождение.Length;
			СтрокаМетода.ПозицияОпределения = СтрокаМетода.ПозицияСОписанием + ДлинаОписания;
			СтрокаМетода.ДлинаОпределения = СтрДлина(ОпределениеБезОписания); 
			//СтрокаМетода.Индекс = Вхождение.FirstIndex + Смещение;
			СтрокаМетода.Имя = Вхождение.SubMatches(3);
			СтрокаМетода.НИмя = Нрег(СтрокаМетода.Имя);
			ТекстПараметров = Вхождение.SubMatches(4); 
			ТекстЭкспорта = Вхождение.SubMatches(5);
			ЛиЭкспорт = ?(ТекстЭкспорта = Неопределено, Ложь, Истина);
			Тело = Вхождение.SubMatches(6);
			ПерваяСтрокаТела = ирОбщий.ПервыйФрагментЛкс(Тело, Символы.ПС);
			ПозицияЭкспортаВТеле = Найти(ПерваяСтрокаТела, ") Экспорт");
			ДлинаЗаголовка = СтрДлина(Заголовок);
			Если ПозицияЭкспортаВТеле > 0 Тогда
				// Сработал ложный конец секции параметров из-за ")" в значении по умолчанию
				ДобавкаЗаголовка = ")" + Лев(ПерваяСтрокаТела, ПозицияЭкспортаВТеле - 1);
				ТекстПараметров = ТекстПараметров + ДобавкаЗаголовка;
				ДлинаЗаголовка = ДлинаЗаголовка + СтрДлина(ДобавкаЗаголовка);
				ЛиЭкспорт = Истина;
			КонецЕсли;
			СтрокаМетода.ЛиЭкспорт = ЛиЭкспорт;
			Тело = Сред(Тело, 2); // Мультиметка38422941 Сдвиг добавлен после вынужденного переноса символа "переноса строки" из заголовка в тело
			СтрокаМетода.ДлинаТела = СтрДлина(Тело);
			Если СтрокаМетода.ДлинаТела = 0 Тогда
				// TODO надо полностью перейти на этот способ
				СтрокаМетода.ПозицияТела = СтрокаМетода.ПозицияОпределения + ДлинаЗаголовка;
			Иначе
				МаркерНачалаТела = Тело;
				//Если СтрДлина(МаркерНачалаТела) < ПорогДлиныМаркераТела Тогда
				//	МаркерНачалаТела = МаркерНачалаТела + Символы.ПС;
				//КонецЕсли;
				МаркерНачалаТела = Лев(МаркерНачалаТела, ПорогДлиныМаркераТела);
				СтрокаМетода.ПозицияТела = СтрокаМетода.ПозицияОпределения + Найти(ОпределениеБезОписания, МаркерНачалаТела) - 2; // Мультиметка38422941
			КонецЕсли;
			Если ЗначениеЗаполнено(ПоследняяАннотация) И Не ЗначениеЗаполнено(ОписаниеМетода) Тогда
				ОписаниеМетода = ПоследнееОписание;
			КонецЕсли;
			ПоследнееОписание = "";
			СтрокаМетода.Описание = ОписаниеМетода;
			СтрокаМетода.Аннотация = ПоследняяАннотация;
			Если НРег(Вхождение.SubMatches(2)) = "функция" Тогда
				СтрокаМетода.ТипЗначения = "??";
			КонецЕсли; 
			СтрокаМетода.Параметры = ТекстПараметров; // Сначала тип "Строка". Позже разбираем их в ПараметрыМетодаМодуля() 
			Если ПодготовитьОписанияРезультатовМетодов Тогда 
				// очень небольшая экономия времени
				ПодготовитьОписаниеРезультатаМетода(СтрокаМетода);
			КонецЕсли;
			Если ЗначениеЗаполнено(ПоследняяАннотация) Тогда
				СтрокаМетода.РасширяемыйМетод = ирОбщий.ТекстМеждуМаркерамиЛкс(ПоследняяАннотация, "(""", """)", Ложь);
			КонецЕсли;
			ПоследняяАннотация = НРег(ПоследняяАннотация);
			СтрокаМетода.Сервер = ПустаяСтрока(ПоследняяАннотация) Или Найти(ПоследняяАннотация, "насервере") > 0;
			СтрокаМетода.Клиент = Ложь
				Или Найти(ПоследняяАннотация, "наклиенте") > 0
				Или (Истина
					И ПустаяСтрока(ПоследняяАннотация) 
					И Не ЭтоМодульФормы);
			СтрокаМетода.БезКонтекста = Найти(ПоследняяАннотация, "безконтекста") > 0;
			СтрокаМетода.ЛиАсинх = НРег(Лев(Заголовок, 1)) = "а";
			Если СтарыйМодуль <> Неопределено Тогда
				//СтарыйМетод = СтарыйМодуль.Методы.Найти(СтрокаМетода.НИмя, "НИмя");
				//Если Истина
				//	//И СтарыйМетод.Вычислено
				//	И ТипЗнч(СтарыйМетод.Параметры) <> Тип("Строка")
				//	И Сред(СтарыйМодуль.Текст, СтарыйМетод.ПозицияСОписанием, СтарыйМетод.ДлинаСОписанием) = Вхождение.Value
				//	И СтарыйМетод.Аннотация = СтрокаМетода.Аннотация
				//Тогда
				//	СтрокаМетода.Параметры = СтарыйМетод.Параметры;
				//	СтрокаМетода.Параметры.ЗаполнитьЗначения(, "ТаблицаТипов");
				//	СтрокаМетода.ОписаниеРезультата = СтарыйМетод.ОписаниеРезультата;
				//	СтрокаМетода.ТипЗначения = СтарыйМетод.ТипЗначения;
				//КонецЕсли;
			КонецЕсли;
			ПозицияНачалаМетода = ПозицияВхождения;
			Если ПоследнееНачалоОписания <> Неопределено Тогда
				ПозицияНачалаМетода = Мин(ПозицияНачалаМетода, ПоследнееНачалоОписания);
			КонецЕсли;
			Если ПоследнееНачалоАннотации <> Неопределено Тогда
				ПозицияНачалаМетода = Мин(ПозицияНачалаМетода, ПоследнееНачалоАннотации);
			КонецЕсли;
			СмещениеНазад = ПозицияВхождения - ПозицияНачалаМетода;
			Если СмещениеНазад > 0 Тогда
				СтрокаМетода.ПозицияСОписанием = СтрокаМетода.ПозицияСОписанием - СмещениеНазад;
				СтрокаМетода.ДлинаСОписанием = СтрокаМетода.ДлинаСОписанием + СмещениеНазад;
			КонецЕсли;
			ПоследняяАннотация = ""; 
			ПоследнееНачалоОписания = Неопределено;
			ПоследнееНачалоАннотации = Неопределено;
		ИначеЕсли Вхождение.SubMatches(7) <> Неопределено Тогда
			Если Модуль.ПозицияМетодов > ПозицияВхождения Тогда
				Продолжить;
			КонецЕсли;
			ПоследнееОписание = Вхождение.SubMatches(7); 
			ПоследнееНачалоОписания = Вхождение.FirstIndex + НачальнаяПозицияДиапазона;
		ИначеЕсли Вхождение.SubMatches(8) <> Неопределено Тогда
			НоваяАннотация = Вхождение.SubMatches(8);  
			Если СтрЧислоСтрок(НоваяАннотация) = 3 Тогда
				ПоследнееОписание = "";
			КонецЕсли;
			НоваяАннотация = СокрЛП(НоваяАннотация);
			Если Лев(НоваяАннотация, 1) = "&" Тогда
				ПоследняяАннотация = НоваяАннотация;
				ПоследнееНачалоАннотации = Вхождение.FirstIndex + НачальнаяПозицияДиапазона;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;  
	Модуль.Удалить("МетодыТекст");
	Модуль.Удалить("ВхожденияМетодов"); 
	// Мультиметка723368140
	Модуль.Вставить("Методы", Методы);
	Модуль.Вставить("Текст", ТекстМодуля);
	Модуль.Вставить("Ошибки", Ошибки);
	Модуль.Вставить("ТекстПоискаОпределенияСловМодуля");
	Методы.Индексы.Добавить("ЛиЭкспорт");
	Методы.Индексы.Добавить("ЛиЭкспорт, НИмя");   
	Методы.Индексы.Добавить("НИмя");
	Если РазрешитьЕдиныйПустойМодуль Тогда
		Модуль.Имя = "<Пустой>";
		мПустойМодуль = Модуль;
	КонецЕсли;
	Возврат Модуль;
КонецФункции

Функция ЛиИмяМодуляФормы(Знач Имя) Экспорт
	Возврат ирОбщий.СтрКончаетсяНаЛкс(Имя, ".Форма.Модуль");
КонецФункции

//.
// Параметры:
//    Модуль - Структура - 
Процедура ВыполнитьОтложенноеОбновлениеВызововСловМодуля(Модуль, Знач ПозицияНачалаСтарая = Неопределено) Экспорт
	ПрямыеВызовыМетодов = Модуль.ПрямыеВызовыМетодов; 
	Если Не ПрямыеВызовыМетодов.Свойство("ОтложенныйСдвиг") Тогда
		Возврат;
	КонецЕсли;
	ВыполнитьОтложенныйСдвигВызововСловМодуля(ПрямыеВызовыМетодов);
	ОтложенныйСдвиг = ПрямыеВызовыМетодов.ОтложенныйСдвиг; // см. НовыйОтложенныйСдвигВызововСловМодуля()
	Если ОтложенныйСдвиг.ПозицияНачалаСтарая = ПозицияНачалаСтарая Тогда
		Возврат;
	КонецЕсли;
	ПолеТекстаМодуля = ПолеТекстаМодуля(Модуль);
	ПрямыеВызовыМетодовВМетоде = НовыйИндексПоискаВызововСловаВМодуле(Модуль);
	ПрямыеВызовыМетодовВМетоде.СтруктураСлов = ПрямыеВызовыМетодов.СтруктураСлов; 
	ПолеТекстаМодуля.ЗаполнитьИндексПоискаВызововМетодовВМодуле(ПрямыеВызовыМетодовВМетоде, ОтложенныйСдвиг.ОпределениеСОписанием, ОтложенныйСдвиг.ПозицияНачалаСтарая);
	НачальныйИндекс = ОтложенныйСдвиг.НачальныеИндексы[ПрямыеВызовыМетодов.Вызовы];
	ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(ПрямыеВызовыМетодовВМетоде.Вызовы, ПрямыеВызовыМетодов.Вызовы,,,,, НачальныйИндекс);
	Если ПрямыеВызовыМетодов.Оповещения <> Неопределено Тогда 
		НачальныйИндекс = ОтложенныйСдвиг.НачальныеИндексы[ПрямыеВызовыМетодов.Оповещения];
		ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(ПрямыеВызовыМетодовВМетоде.Оповещения, ПрямыеВызовыМетодов.Оповещения,,,,, НачальныйИндекс);
	КонецЕсли;
	ПрямыеВызовыМетодов.Удалить("ОтложенныйСдвиг");
КонецПроцедуры

Процедура ВыполнитьОтложенныйСдвигВызововСловМодуля(ПрямыеВызовыМетодов) Экспорт
	ОтложенныйСдвиг = ПрямыеВызовыМетодов.ОтложенныйСдвиг; // см. НовыйОтложенныйСдвигВызововСловМодуля()
	СдвинутьПозицииВТаблицеВызовов(ПрямыеВызовыМетодов.Вызовы, ОтложенныйСдвиг);
	Если ПрямыеВызовыМетодов.Оповещения <> Неопределено Тогда 
		СдвинутьПозицииВТаблицеВызовов(ПрямыеВызовыМетодов.Оповещения, ОтложенныйСдвиг);
	КонецЕсли;
КонецПроцедуры

//.
// Возвращаемое значение:
//    Структура - 
Функция НовыйОтложенныйСдвигВызововСловМодуля() Экспорт
	ОтложенныйСдвиг = Новый Структура;
	ОтложенныйСдвиг.Вставить("ПозицияНачалаСтарая", 0);
	ОтложенныйСдвиг.Вставить("ПозицияКонцаСтарая", 0);
	ОтложенныйСдвиг.Вставить("СмещениеКонечногоДиапазона", 0);
	ОтложенныйСдвиг.Вставить("ОпределениеСОписанием", "");
	ОтложенныйСдвиг.Вставить("НачальныеИндексы", Новый Соответствие);
	Возврат ОтложенныйСдвиг;
КонецФункции

//.
// Параметры:
//    ТаблицаВызовов - ТаблицаЗначений - 
//    ПозицияКонцаСтарая - Число - 
//    ПозицияНачалаСтарая - Число(10,0) - 
//    СмещениеКонечногоДиапазона - Число, Неопределено - 
Процедура СдвинутьПозицииВТаблицеВызовов(Знач ТаблицаВызовов, Знач ОтложенныйСдвиг) Экспорт
	ПозицияНачалаСтарая = ОтложенныйСдвиг.ПозицияНачалаСтарая;
	ПозицияКонцаСтарая = ОтложенныйСдвиг.ПозицияКонцаСтарая;
	СмещениеКонечногоДиапазона = ОтложенныйСдвиг.СмещениеКонечногоДиапазона;
	ОпределениеСОписанием = ОтложенныйСдвиг.ОпределениеСОписанием;
	_РежимОтладки = Ложь;
	Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
		// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
		Для ИндексВызова = -ТаблицаВызовов.Количество()+1 По 0 Цикл
			СтрокаВызова = ТаблицаВызовов[-ИндексВызова];
			Если СтрокаВызова.ПозицияВхождения < ПозицияНачалаСтарая Тогда
				Прервать;
			КонецЕсли;
			Если СтрокаВызова.ПозицияВхождения < ПозицияКонцаСтарая Тогда
				ТаблицаВызовов.Удалить(СтрокаВызова);
				Продолжить;
			КонецЕсли;
			СтрокаВызова.ПозицияВхождения = СтрокаВызова.ПозицияВхождения + СмещениеКонечногоДиапазона;
		КонецЦикла;
	Иначе
		// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
		Для ИндексВызова = -ТаблицаВызовов.Количество()+1 По 0 Цикл  			СтрокаВызова = ТаблицаВызовов[-ИндексВызова];  			Если СтрокаВызова.ПозицияВхождения < ПозицияНачалаСтарая Тогда  				Прервать;  			КонецЕсли;  			Если СтрокаВызова.ПозицияВхождения < ПозицияКонцаСтарая Тогда  				ТаблицаВызовов.Удалить(СтрокаВызова);  				Продолжить;  			КонецЕсли;  			СтрокаВызова.ПозицияВхождения = СтрокаВызова.ПозицияВхождения + СмещениеКонечногоДиапазона;  		КонецЦикла;  
	КонецЕсли;
	ОтложенныйСдвиг.НачальныеИндексы[ТаблицаВызовов] = -ИндексВызова + 1;
КонецПроцедуры

//.
// Параметры:
//    СтрокаМетода - СтрокаТаблицыЗначений - 
//    Ошибки - ОбработкаТабличнаяЧасть.ирКлсПолеТекстаПрограммы.ОшибкиМодуля - 
Процедура УдалитьОшибкиМетода(Знач СтрокаМетода, Знач Ошибки) Экспорт
	Если СтрокаМетода = Неопределено Тогда
		ИмяМетода = "<Инициация>";
	Иначе 
		БылиОшибки = СтрокаМетода.ЕстьОшибки = Истина;
		СтрокаМетода.ЕстьОшибки = Неопределено;
		Если Не БылиОшибки Тогда
			Возврат;
		КонецЕсли;
		ИмяМетода = СтрокаМетода.Имя;
	КонецЕсли;
	Для Каждого СтрокаОшибки Из Ошибки.НайтиСтроки(Новый Структура("Метод", ИмяМетода)) Цикл
		Ошибки.Удалить(СтрокаОшибки); 
	КонецЦикла; 
КонецПроцедуры

// Функция - Новая таблица методов модуля
// 
// Возвращаемое значение:
//  ТаблицаЗначений
//
Функция НоваяТаблицаМетодовМодуля() Экспорт 
	
	// При добавлении колонок нужно увеличивать версию формата Мультиметка91237881041
	Методы = Новый ТаблицаЗначений;
	Методы.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
	//Методы.Колонки.Добавить("Тип", Новый ОписаниеТипов("Строка"));
	//Методы.Колонки.Добавить("Индекс", Новый ОписаниеТипов("Число"));
	Методы.Колонки.Добавить("НИмя", Новый ОписаниеТипов("Строка"));
	Методы.Колонки.Добавить("Аннотация", Новый ОписаниеТипов("Строка"));
	Методы.Колонки.Добавить("РасширяемыйМетод", Новый ОписаниеТипов("Строка"));
	Методы.Колонки.Добавить("Параметры"); // Строка, см. НоваяТаблицаПараметровМетодаМодуля
	Методы.Колонки.Добавить("МинЧислоПараметров"); // Число
	Методы.Колонки.Добавить("ПозицияСОписанием", Новый ОписаниеТипов("Число")); // Начиная с 1. 
	Методы.Колонки.Добавить("ДлинаСОписанием", Новый ОписаниеТипов("Число"));
	Методы.Колонки.Добавить("ПозицияОпределения", Новый ОписаниеТипов("Число")); // Начиная с 1. Может содержать непечатное смещение от начала строки
	Методы.Колонки.Добавить("ДлинаОпределения", Новый ОписаниеТипов("Число"));
	Методы.Колонки.Добавить("ПозицияТела", Новый ОписаниеТипов("Число")); // Начиная с 1
	Методы.Колонки.Добавить("ДлинаТела", Новый ОписаниеТипов("Число"));
	Методы.Колонки.Добавить("ТелоБезВозвратов");
	Методы.Колонки.Добавить("Описание", Новый ОписаниеТипов("Строка"));
	Методы.Колонки.Добавить("ОписаниеРезультата");
	Методы.Колонки.Добавить("ТипЗначения"); // Используем значение Неопределено
	Методы.Колонки.Добавить("ТаблицаТипов"); // см. НоваяТаблицаТипов
	Методы.Колонки.Добавить("Сервер", Новый ОписаниеТипов("Булево"));
	Методы.Колонки.Добавить("Клиент", Новый ОписаниеТипов("Булево"));
	Методы.Колонки.Добавить("БезКонтекста", Новый ОписаниеТипов("Булево"));
	Методы.Колонки.Добавить("ЛиЭкспорт", Новый ОписаниеТипов("Булево"));
	Методы.Колонки.Добавить("ЛиАсинх", Новый ОписаниеТипов("Булево"));
	Методы.Колонки.Добавить("Вычислено", Новый ОписаниеТипов("Булево")); // тип значения вычислен по коду
	Методы.Колонки.Добавить("ЕстьОшибки");
	Методы.Колонки.Добавить("ИмяМодуля", Новый ОписаниеТипов("Строка"));
	Методы.Колонки.Добавить("КлючевыеПараметры"); // Структура
	Методы.Колонки.Добавить("КэшПоиска");
	Методы.Колонки.Добавить("ТипыВыражений");
	Возврат Методы;             

КонецФункции

Функция ПрефиксВременногоКомментирования() Экспорт
	Возврат "СлужебноИР ";
КонецФункции  

Функция ЗамаскироватьДирективыПрепроцессора(Знач Текст) Экспорт 
	Префикс = "//" + ПрефиксВременногоКомментирования();
	ВхожденияБлоков = ирОбщий.НайтиРегВыражениеЛкс(Текст, шПустоеНачалоСтроки + "#Удаление\s[\S\s]*?" +  шПустоеНачалоСтроки + "#КонецУдаления",, Ложь);
	Для Каждого Вхождение Из ВхожденияБлоков Цикл
		НовыйФрагмент = СтрЗаменить(Вхождение.ТекстВхождения, Символы.ПС, Символы.ПС + "|" + Префикс);
		Текст = СтрЗаменить(Текст, Вхождение.ТекстВхождения, НовыйФрагмент);
	КонецЦикла;
	Текст = ирОбщий.ЗаменитьРегВыражениеЛкс(Текст, "(\n)(\t| )*(#|//)", "$1|$2" + Префикс + "$3", Ложь);
	Возврат Текст;
КонецФункции

Функция РазмаскироватьДирективыПрепроцессора(Знач Текст) Экспорт 
	Текст = СтрЗаменить(Текст, Символы.ПС + "|//" + ПрефиксВременногоКомментирования(), Символы.ПС);
	Возврат Текст;
КонецФункции

//.
// Параметры:
//    Переменные - ТаблицаЗначений - 
//    ИмяПеременной - ? - 
//    ЭкспортПеременной - ? - 
//    ОписаниеСтроки - Строка - 
//    ПозицияСОписанием - ? - 
Процедура ДобавитьПеременную(Переменные, ИмяПеременной, ЭкспортПеременной, Знач ОписаниеСтроки, Знач ПозицияСОписанием) Экспорт
	СтрокаПеременной = Переменные.Добавить();
	СтрокаПеременной.Имя = ИмяПеременной;
	СтрокаПеременной.НИмя = Нрег(СтрокаПеременной.Имя);
	СтрокаПеременной.ЛиЭкспорт = ЭкспортПеременной;
	СтрокаПеременной.ПозицияСОписанием = ПозицияСОписанием;
	СтрокаПеременной.ПозицияОпределения = ПозицияСОписанием;
	СтрокаПеременной.Описание = ОписаниеСтроки;
КонецПроцедуры

//.
// Параметры:
//  СтрокаМетода - см. НоваяТаблицаМетодовМодуля()[0] - 
//  выхБылиИзменения - Булево - 
// Возвращаемое значение:
//  ТаблицаЗначений - 
Функция ПараметрыМетодаМодуля(СтрокаМетода, выхБылиИзменения = Ложь) Экспорт
	Если СтрокаМетода = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	Результат = СтрокаМетода.Параметры; 
	Если ТипЗнч(Результат) = Тип("Строка") Тогда
		выхБылиИзменения = Истина;
		МинЧислоПараметров = 0;
		СтрокаМетода.Описание = ОчиститьТекстМодуляОтПрефиксаКомментария(СтрокаМетода.Описание);
		Если Не ЗначениеЗаполнено(СтрокаМетода.Параметры) Тогда
			Результат = Неопределено;
		Иначе
			Шаблоны = ШаблоныДляАнализаВстроенногоЯзыка();
			RegExp2.Global = Истина;
			RegExp2.Pattern = Шаблоны.ПараметрыМетода;
			РезультатПараметров = RegExp2.НайтиВхождения(СтрокаМетода.Параметры);
			Если РезультатПараметров.Количество() > 0 Тогда
				Результат = НоваяТаблицаПараметровМетодаМодуля();
				Для Каждого ВхождениеПараметра Из РезультатПараметров Цикл
					СтрокаПраметра = Результат.Добавить();
					СтрокаПраметра.Имя = ВхождениеПараметра.SubMatches(1);
					СтрокаПраметра.НИмя = НРег(СтрокаПраметра.Имя);
					СтрокаПраметра.Знач = ?(ВхождениеПараметра.SubMatches(0) = Неопределено, Ложь, Истина);
					СтрокаПраметра.Значение = ВхождениеПараметра.SubMatches(2);
					Если СтрокаПраметра.Значение = "" Тогда
						МинЧислоПараметров = Результат.Количество();
					КонецЕсли;
				КонецЦикла;
				Если ЗначениеЗаполнено(СтрокаМетода.Описание) Тогда
					ОписанияПараметровЗагружены = Ложь;
					Если СтрЧислоСтрок(СтрокаМетода.Описание) = 1 Тогда 
						СсылкаНаОписание = СтрокаМетода.Описание;
						Если УдалитьПрефиксИзТекстаТипов(СсылкаНаОписание) Тогда
							// Ссылка на описание друго метода. Параметры сопоставляются по позиции.
							//СтрокаМетода.Описание = СтрокаБазовогоМетода.Описание; 
							Методы = Неопределено;
							Если Найти(СсылкаНаОписание, ".") = 0 Тогда
								Методы = СтрокаМетода.Владелец();
							Иначе
								Если Прав(СсылкаНаОписание, 1) = "." Тогда
									СсылкаНаОписание = СокрП(ирОбщий.СтрокаБезКонцаЛкс(СсылкаНаОписание));
								КонецЕсли;
								КраткоеИмяМодуля = ирОбщий.СтрокаБезПоследнегоФрагментаЛкс(СсылкаНаОписание);
								Анализатор = ирКэш.ПолеТекстаМодуляБезСтруктурыТипаЛкс("");
								ТаблицаТиповМодуля = Анализатор.ВычислитьТипЗначенияВыражения(КраткоеИмяМодуля,,,,,, Ложь);
								Если ТаблицаТиповМодуля.Количество() > 0 Тогда
									Модуль = ПодготовитьМодульМетаданных(ТаблицаТиповМодуля[0]);
									Если Модуль <> Неопределено Тогда
										Методы = Модуль.Методы;
									КонецЕсли;
								КонецЕсли;
							КонецЕсли;
							Если Методы <> Неопределено Тогда
								ИмяБазовогоМетода = ирОбщий.ПервыйФрагментЛкс(ирОбщий.ПоследнийФрагментЛкс(СсылкаНаОписание), "(");
								СтрокаБазовогоМетода = Методы.Найти(НРег(ИмяБазовогоМетода), "НИмя");
								Если СтрокаБазовогоМетода <> Неопределено Тогда
									ПараметрыБазовогоМетода = ПараметрыМетодаМодуля(СтрокаБазовогоМетода);
									Если ПараметрыБазовогоМетода <> Неопределено Тогда
										Для Индекс = 0 По Мин(ПараметрыБазовогоМетода.Количество(), Результат.Количество()) - 1 Цикл
											Результат[Индекс].Описание = ПараметрыБазовогоМетода[Индекс].Описание;
											Результат[Индекс].ТипЗначения = ПараметрыБазовогоМетода[Индекс].ТипЗначения;
										КонецЦикла;
									КонецЕсли;
									ОписанияПараметровЗагружены = Истина;
								КонецЕсли;
							КонецЕсли;
						КонецЕсли;
					КонецЕсли;
					Если Не ОписанияПараметровЗагружены Тогда
						ВхожденияОписаний = ПараметрыМетодаИзКомментария(СтрокаМетода.Описание, Шаблоны);
						Для каждого ВхождениеОписания Из ВхожденияОписаний Цикл
							СтрокаПараметра = Результат.Найти(НРег(ВхождениеОписания.Имя));
							Если СтрокаПараметра <> Неопределено Тогда
								Если ВхождениеОписания.ТипЗначения = Неопределено Тогда
									ИмяТипа = СокрЛП(ВхождениеОписания.Описание);
									Попытка
										Пустышка = Тип(ИмяТипа);
										ЭтоТип = Истина;
									Исключение
										ЭтоТип = Ложь;
									КонецПопытки;
									Если ЭтоТип Тогда
										СтрокаПараметра.ТипЗначения = ИмяТипа;
									Иначе 
										СтрокаПараметра.Описание = ВхождениеОписания.Описание;
									КонецЕсли;
								Иначе 
									СтрокаПараметра.Описание = ВхождениеОписания.Описание;
									СтрокаПараметра.ТипЗначения = ВхождениеОписания.ТипЗначения;
								КонецЕсли;
							КонецЕсли; 
						КонецЦикла;
					КонецЕсли;
				КонецЕсли; 
			КонецЕсли;
		КонецЕсли;
		СтрокаМетода.МинЧислоПараметров = МинЧислоПараметров;
		СтрокаМетода.Параметры = Результат;
	КонецЕсли;
	Возврат Результат;
КонецФункции

//.
// Возвращаемое значение:
//  ТаблицаЗначений - 
Функция НоваяТаблицаПараметровМетодаМодуля() Экспорт
	Результат = Новый ТаблицаЗначений;
	Результат.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
	Результат.Колонки.Добавить("НИмя", Новый ОписаниеТипов("Строка"));
	Результат.Колонки.Добавить("ТипЗначения", Новый ОписаниеТипов("Строка"));
	Результат.Колонки.Добавить("Описание", Новый ОписаниеТипов("Строка"));
	Результат.Колонки.Добавить("Значение");
	Результат.Колонки.Добавить("Знач", Новый ОписаниеТипов("Булево"));
	Результат.Колонки.Добавить("Вычислено", Новый ОписаниеТипов("Булево"));
	Результат.Колонки.Добавить("ТаблицаТипов"); // см. НоваяТаблицаТипов()
	Возврат Результат;
КонецФункции

// Вызывается из других конфигураций!
// Параметры:
//    ОписаниеМетода - Строка - 
//    Шаблоны - Структура - для ускорения
// Возвращаемое значение:
//    ТаблицаЗначений - 
Функция ПараметрыМетодаИзКомментария(Знач ОписаниеМетода, Шаблоны = Неопределено) Экспорт
	Если Шаблоны = Неопределено Тогда
		Шаблоны = ШаблоныДляАнализаВстроенногоЯзыка();
	КонецЕсли;
	шРазделительВнутриСтроки = "[-–]"; // Здесь 2 разных символа
	шОписаниеПараметра = "\n\s{0,8}(" + шИмя + ")\*?\s*(?:" + шРазделительВнутриСтроки + "\s*([^-–\n]*)\s*)?" + шРазделительВнутриСтроки + "\s*?(" + Шаблоны.ОписаниеПараметра + ")[\.;]?";
	ВхожденияОписаний = ирОбщий.НайтиРегВыражениеЛкс(ОписаниеМетода, шОписаниеПараметра, "Имя, ТипЗначения, Описание",,, Ложь, Ложь);
	Возврат ВхожденияОписаний;
КонецФункции

Функция ОчиститьТекстМодуляОтПрефиксаКомментария(Знач ТекстМодуля)

	Если Не ЗначениеЗаполнено(ТекстМодуля) Тогда
		Возврат "";
	КонецЕсли;
	RegExp.Global = Истина;
	RegExp.Pattern = шПустоеНачалоСтроки + "(?:/){2,}"; 
	Результат = RegExp.Заменить(ТекстМодуля, Символы.ПС);
	Если Лев(Результат, 1) = Символы.ПС Тогда
		Результат = Сред(Результат, 2); // Отрезаем начальный перенос строки
	КонецЕсли;
	Возврат Результат;

КонецФункции

Функция ПодготовитьТипРезультатаМетода(МетодМодуля, ИмяИлиМодуль, ПолеТекстаМодуляКэш = Неопределено, Знач СФактическимиПараметрами = Ложь, Знач ДляСвойства = "") Экспорт 
	Если МетодМодуля.ТипЗначения = Неопределено Тогда
		// тип метода - "процедура"   
		Возврат Неопределено;
	КонецЕсли;
	Если МетодМодуля.ТаблицаТипов = Неопределено Тогда
		МетодМодуля.ТаблицаТипов = НоваяТаблицаТипов();
	КонецЕсли;
	ПодготовитьОписаниеРезультатаМетода(МетодМодуля);
	ПолеТекстаМодуляКэш = ПолеТекстаМодуля(ИмяИлиМодуль, ПолеТекстаМодуляКэш);
	ПолеТекстаМодуляКэш.ЗагрузитьМетодМодуля(МетодМодуля, Истина);
	ТаблицаТипов = ПодготовитьТипЗначенияСловаМодуля(ПолеТекстаМодуляКэш.ИмяПеременнойВозвращаемогоЗначения(), ПолеТекстаМодуляКэш, МетодМодуля, ИмяИлиМодуль, МетодМодуля, 
		МетодМодуля.ОписаниеРезультата, СФактическимиПараметрами, Истина, ДляСвойства);
	Возврат ТаблицаТипов;  
КонецФункции

//.
// Параметры:
//    СтрокаОпределения - СтрокаТаблицыЗначений - 
Процедура ПодготовитьОписаниеРезультатаМетода(СтрокаОпределения) Экспорт
	Если Истина
		И ЗначениеЗаполнено(СтрокаОпределения.Описание) 
		И СтрокаОпределения.ОписаниеРезультата = Неопределено
		И СтрокаОпределения.ТипЗначения <> Неопределено
	Тогда
		Шаблоны = ШаблоныДляАнализаВстроенногоЯзыка();
		ШаблонОписанияРезультата = "(?:Возвращаемое\s+значение|Результат)[:-]\s*(?:([^-–:\n]+)\s*(?=[-–:\n]))?\s*(" + Шаблоны.ОписаниеПараметра + ")";
		ВхожденияОписаний = ирОбщий.НайтиРегВыражениеЛкс(СтрокаОпределения.Описание, ШаблонОписанияРезультата, "ТипЗначения, Описание", Ложь,, Ложь, Ложь);
		Если ВхожденияОписаний.Количество() > 0 Тогда
			ВхождениеОписания = ВхожденияОписаний[ВхожденияОписаний.Количество() - 1];
			ТекстТипаЗначения = СокрЛ(СтрЗаменить(ВхождениеОписания.ТипЗначения, "//", "")); 
			КопияТекстТипаЗначения = ТекстТипаЗначения;
			Если УдалитьПрефиксИзТекстаТипов(КопияТекстТипаЗначения) Тогда
				СтрокаОпределения.ТипЗначения = ТекстТипаЗначения;
			ИначеЕсли ЗначениеЗаполнено(ТекстТипаЗначения) Тогда 
				СтрокаОпределения.ТипЗначения = СтрокаОпределения.ТипЗначения + ", " + ТекстТипаЗначения; // TODO удаление дублей
			КонецЕсли;
			ОписаниеРезультата = СокрЛП(ВхождениеОписания.Описание);
			СтрокаОпределения.ОписаниеРезультата = ОчиститьТекстМодуляОтПрефиксаКомментария(ОписаниеРезультата);
		Иначе
			СтрокаОпределения.ОписаниеРезультата = "";
		КонецЕсли; 
	КонецЕсли;
КонецПроцедуры 

// Функция - Удалить префикс из текста типов
//
// Параметры:
//  Текст	 - 	 - 
// 
// Возвращаемое значение:
//   Булево - является ли именем типа
//
Функция УдалитьПрефиксИзТекстаТипов(Текст) Экспорт 
	Текст = СокрЛП(Текст);
	МаркерСм = "см.";
	Если ирОбщий.СтрНачинаетсяСЛкс(Текст, МаркерСм) Тогда
		Текст = СокрЛ(Сред(Текст, СтрДлина(МаркерСм) + 1));
		Возврат Истина;
	КонецЕсли;
	Если Найти(Текст, "(") > 0 И Найти(Текст, " ") = 0 Тогда
		Возврат Истина;
	КонецЕсли;
	Возврат Ложь;
КонецФункции

Функция ПодготовитьТипЗначенияПеременнойМодуля(СтрокаОпределения, ИмяИлиМодуль, Знач ПолеТекстаМодуляКэш = Неопределено, Знач ДляСвойства = "") Экспорт 
	Если СтрокаОпределения.ТаблицаТипов = Неопределено Тогда
		СтрокаОпределения.ТаблицаТипов = НоваяТаблицаТипов();
	КонецЕсли;
	Если Истина
		И ЗначениеЗаполнено(СтрокаОпределения.Описание) 
		И Не ЗначениеЗаполнено(СтрокаОпределения.ТипЗначения)
	Тогда
		ТипЗначения = ирОбщий.ПервыйФрагментЛкс(СтрокаОпределения.Описание, "-"); 
		СтрокаОпределения.Описание = Сред(СтрокаОпределения.Описание, СтрДлина(ТипЗначения) + 1);
		СтрокаОпределения.ТипЗначения = СокрЛ(ТипЗначения);
	КонецЕсли;
	ПолеТекстаМодуляКэш = ПолеТекстаМодуля(ИмяИлиМодуль, ПолеТекстаМодуляКэш);
	ТаблицаТипов = ПодготовитьТипЗначенияСловаМодуля(СтрокаОпределения.Имя, ПолеТекстаМодуляКэш,, ИмяИлиМодуль, СтрокаОпределения, СтрокаОпределения.Описание,,, ДляСвойства);
	Если ТаблицаТипов.Количество() > 1 Тогда
		ирОбщий.УдалитьСтрокиТаблицыИлиДереваПоЗначениюВКолонкеЛкс(ТаблицаТипов, "ИмяОбщегоТипа", "Произвольный"); // Нужно для проверок выражений
	КонецЕсли;
	Возврат ТаблицаТипов;  
КонецФункции

Функция ПодготовитьТипЗначенияСловаМодуля(Знач ИмяПеременной, Знач ПолеТекстаМодуляКэш, Знач МетодМодуля, Знач ИмяИлиМодуль, Знач СтрокаОпределения, Знач ОписаниеТипа = "",
	Знач СФактическимиПараметрами = Ложь, Знач ЭтоПрисвоенноеВыражение = Ложь, Знач ДляСвойства = "")
	
	Если ПустаяСтрока(ИмяПеременной) Тогда
		ВызватьИсключение "Э";
	КонецЕсли;
	Если СФактическимиПараметрами Тогда
		ДопКлючКэша = Неопределено;
		ТаблицаТипов = ПолеТекстаМодуляКэш.ВычислитьТипЗначенияВыражения(ИмяПеременной,,,,,,, МетодМодуля = Неопределено, НоваяТаблицаТипов(), Истина,,, ДопКлючКэша, ДляСвойства);
		ТаблицаТипов.ЗаполнитьЗначения(СтрокаОпределения, "СтрокаОписания");
	Иначе 
		ТаблицаТипов = СтрокаОпределения.ТаблицаТипов;
		Если Ложь
			Или СтрокаОпределения.Вычислено
			Или СтрокаОпределения.Имя = "<>"
		Тогда
			ТаблицаТипов = СтрокаОпределения.ТаблицаТипов;
		Иначе
			СтрокаОпределения.ТаблицаТипов = Неопределено; // На случай рекурсивного обращения до завершения вычисления
			СтрокаОпределения.Вычислено = Истина;
			Если Истина
				И ЗначениеЗаполнено(СтрокаОпределения.ТипЗначения) 
				И СтрокаОпределения.ТипЗначения <> "??" 
				И СтрокаОпределения.ТипЗначения <> "?"
			Тогда
				ТаблицаТиповИзКомментария = ПолеТекстаМодуляКэш.ТаблицаТиповИзТекста(СтрокаОпределения.ТипЗначения, ОписаниеТипа,, ДляСвойства);  
				Если ТаблицаТиповИзКомментария.Колонки.Метаданные.Заголовок = "" Тогда
					ДобавитьВТаблицуТипов(СтрокаОпределения.ТаблицаТипов, ТаблицаТиповИзКомментария);
				КонецЕсли;
			КонецЕсли;
			УказанКонструктор = Найти(НРег(СтрокаОпределения.ТипЗначения), "см.") > 0;
			Если Истина
				И Не УказанКонструктор
				И ЗначениеЗаполнено(ТаблицаТиповИзКомментария) 
				И Лев(СтрокаОпределения.ТипЗначения, 1) = "?" 
			Тогда
				СтрокаОпределения.ТипЗначения = ПредставлениеМассиваСтруктурТипов(ТаблицаТиповИзКомментария);
			КонецЕсли;
			Если Ложь
				Или (Истина
					И УказанКонструктор
					И ЛиДетальностьТиповДостаточна(ТаблицаТиповИзКомментария))
				Или (Истина
					И МетодМодуля = Неопределено // только для переменных
					И ЗначениеЗаполнено(СтрокаОпределения.ТипЗначения)
					И Не УказанКонструктор
					И ЛиДетальностьТиповДостаточна(ТаблицаТиповИзКомментария, 4)) // Мультиметка481662548
			Тогда
				// Считаем что тип в комментарии описан достаточно подробно
				ТаблицаТипов = ТаблицаТиповИзКомментария;
			Иначе
				ТаблицаТипов = ПолеТекстаМодуляКэш.ВычислитьТипЗначенияВыражения(ИмяПеременной,,,,,,, МетодМодуля = Неопределено, НоваяТаблицаТипов(), Истина,,,, ДляСвойства);
				Если ТаблицаТипов.Количество() > 0 Тогда
					// Мультиметка4529884 против циклической ссылки
					Для Каждого СтрокаТипа Из ТаблицаТипов.НайтиСтроки(Новый Структура("СтрокаОписания", СтрокаОпределения)) Цикл
						Если СтрокаТипа.Метаданные = Неопределено Тогда
							ТаблицаТипов.Удалить(СтрокаТипа);
						Иначе 
							СтрокаТипа.СтрокаОписания = Неопределено;
						КонецЕсли; 
					КонецЦикла;
				КонецЕсли;
				Если ТаблицаТипов.Колонки.Метаданные.Заголовок = "" Тогда
					ДобавитьВТаблицуТипов(СтрокаОпределения.ТаблицаТипов, ТаблицаТипов);
					ТаблицаТипов = СтрокаОпределения.ТаблицаТипов;
				Иначе
					ДобавитьВТаблицуТипов(ТаблицаТипов, ТаблицаТиповИзКомментария);
				КонецЕсли;
				Если ТаблицаТипов.Количество() = 0 И ТаблицаТипов.Колонки.Метаданные.Заголовок = "" Тогда
					СтруктураТипа = НоваяСтруктураТипа("Произвольный");
					ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
				КонецЕсли; 
				//СтрокаОпределения.ТаблицаТипов.ЗаполнитьЗначения(СтрокаОпределения, "СтрокаОписания"); // Мультиметка4529884 Была циклическая ссылка ! Теперь заполняем ссылку позже уже в копии таблицы
			КонецЕсли;
			Если ТаблицаТипов.Колонки.Метаданные.Заголовок <> "" Тогда
				СтрокаОпределения.Вычислено = Ложь;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	Возврат ТаблицаТипов;
КонецФункции

//.
// Параметры:
//    ИмяИлиМодуль - Структура - 
//    ПолеТекстаМодуляКэш - ОбработкаОбъект.ирКлсПолеТекстаПрограммы, Неопределено - 
// Возвращаемое значение:
//    ОбработкаОбъект.ирКлсПолеТекстаПрограммы, Неопределено - 
Функция ПолеТекстаМодуля(Знач ИмяИлиМодуль, ПолеТекстаМодуляКэш = Неопределено) Экспорт
	Если ПолеТекстаМодуляКэш = Неопределено Тогда
		Если ТипЗнч(ИмяИлиМодуль) = Тип("Строка") Тогда
			ИмяМодуля = ИмяИлиМодуль;
		Иначе 
			ИмяМодуля = ИмяИлиМодуль.Имя
		КонецЕсли;
		ПолеТекстаМодуляКэш = ирКэш.ПолеТекстаМодуляЛкс(ИмяМодуля);
		Если ТипЗнч(ИмяИлиМодуль) = Тип("Структура") Тогда
			НовыйМодуль = ИмяИлиМодуль; // Точно из кэша
		Иначе 
			НовыйМодуль = МодульМетаданныхИзКэша(ИмяМодуля);
		КонецЕсли;
		Если НовыйМодуль <> Неопределено Тогда
			ПолеТекстаМодуляКэш.ЗагрузитьМодульМетаданных(НовыйМодуль);
		КонецЕсли;
		ПолеТекстаМодуляКэш = ПолеТекстаМодуляКэш.КопияКомпоненты(); // Иначе при вызовах в рамках одного модуля будет переиспользоваться один объект и портиться контекст
	КонецЕсли;
	Возврат ПолеТекстаМодуляКэш;
КонецФункции

// Получает представление массива типов.
//
// Параметры:
//  ТаблицаТиповКонтекста - ТаблицаЗначений.
//
// Возвращаемое значение:
//   Строка - представление массива типов.
//
Функция ПредставлениеМассиваСтруктурТипов(ТаблицаТиповКонтекста, БезДублей = Ложь, МаксКоличествоТипов = 10) Экспорт 

	#Если Сервер И Не Сервер Тогда
		ТаблицаТиповКонтекста = Новый ТаблицаЗначений;
	#КонецЕсли
	ПредставлениеТипаКонтекста = "";
	Если ТаблицаТиповКонтекста <> Неопределено Тогда
		Если ТаблицаТиповКонтекста.Количество() = 0 Тогда
		ИначеЕсли ТаблицаТиповКонтекста.Количество() = 1 Тогда
			ПредставлениеТипаКонтекста = ИмяТипаИзСтруктурыТипа(ТаблицаТиповКонтекста[0]);
		Иначе
			СписокОбрезан = Неопределено;
			СписокИменТипов = ТаблицаТиповДляПользователя(ТаблицаТиповКонтекста, БезДублей, МаксКоличествоТипов, СписокОбрезан);
			Если СписокОбрезан Тогда
				СписокИменТипов.Добавить().Имя = "...";
			КонецЕсли; 
			ПредставлениеТипаКонтекста = ирОбщий.СтрСоединитьЛкс(СписокИменТипов.ВыгрузитьКолонку("Имя"), ", ");
			ПредставлениеТипаКонтекста = СтрЗаменить(ПредставлениеТипаКонтекста, "?, ", "");
		КонецЕсли;
	КонецЕсли; 
	Возврат ПредставлениеТипаКонтекста;

КонецФункции

Функция ТаблицаТиповДляПользователя(Знач ТаблицаТиповКонтекста, Знач БезДублей = Истина, Знач МаксКоличествоТипов = 0, выхСписокОбрезан = Ложь) Экспорт 
	
	#Если Сервер И Не Сервер Тогда
		ТаблицаТиповКонтекста = Новый ТаблицаЗначений;
	#КонецЕсли
	Счетчик = 0;
	выхСписокОбрезан = Ложь;
	СписокИменТипов = Новый ТаблицаЗначений;
	СписокИменТипов.Колонки.Добавить("Имя");
	СписокИменТипов.Колонки.Добавить("СтруктураТипа");
	СтруктураТипаНеопределено = Неопределено;
	Для Каждого СтруктураТипаКонтекста Из ТаблицаТиповКонтекста Цикл
		Счетчик = Счетчик + 1;
		Если МаксКоличествоТипов > 0 И Счетчик > МаксКоличествоТипов Тогда
			выхСписокОбрезан = Истина;
			Прервать;
		КонецЕсли; 
		ИмяТипа = ИмяТипаИзСтруктурыТипа(СтруктураТипаКонтекста);
		Если Не ЗначениеЗаполнено(ИмяТипа) Тогда
			Продолжить;
		КонецЕсли;
		Если ИмяТипа = "Неопределено" Тогда
			СтруктураТипаНеопределено = СтруктураТипаКонтекста;
			Продолжить;
		КонецЕсли;
		СтрокаИменТипов = СписокИменТипов.Добавить();
		СтрокаИменТипов.Имя = ИмяТипа;
		СтрокаИменТипов.СтруктураТипа = СтруктураТипаКонтекста;
	КонецЦикла;
	Если БезДублей Тогда
		СписокИменТипов.Свернуть("Имя");
	КонецЕсли; 
	СписокИменТипов.Сортировать("Имя");
	Если СтруктураТипаНеопределено <> Неопределено Тогда
		// Чтобы Неопределено всегда шло последним
		СтрокаИменТипов = СписокИменТипов.Добавить();
		СтрокаИменТипов.Имя = "Неопределено";
		СтрокаИменТипов.СтруктураТипа = СтруктураТипаНеопределено;
	КонецЕсли;
	Возврат СписокИменТипов;

КонецФункции

// Функция - Отбор параметров метода
//
// Параметры:
//  СтрокаОписания	 - СтрокаТаблицыЗначений - строка таблицы ТаблицаКонтекстов
// 
// Возвращаемое значение:
//   - 
//
Функция ОтборПараметровМетода(Знач СтрокаОписания) Экспорт 
	
	ОтборПараметров = Новый Структура;
	ОтборПараметров.Вставить("ТипКонтекста", СтрокаОписания.ТипКонтекста);
	Если СтрокаОписания.ТипСлова = "Конструктор" Тогда
		ОтборПараметров.Вставить("Слово", "<Новый>");
	Иначе
		ОтборПараметров.Вставить("Слово", СтрокаОписания.Слово);
	КонецЕсли;
	ОтборПараметров.Вставить("ЯзыкПрограммы", СтрокаОписания.ЯзыкПрограммы);
	Возврат ОтборПараметров;

КонецФункции

// Функция - Таблица параметров метода для всех вариантов синтаксиса
//
// Параметры:
//  СтрокаОписания	 - СтрокаТаблицыЗначений - строка глобальной таблицы ТаблицаКонтекстов
//  ОтборПараметров	 - 	 - 
// 
// Возвращаемое значение:
//   - 
//
Функция ПараметрыМетодаПлатформы(Знач СтрокаОписания) Экспорт 
	
	ОтборПараметров = ОтборПараметровМетода(СтрокаОписания);
	КоличествоПараметров = 0;
	Если Не ЗначениеЗаполнено(СтрокаОписания.Описание) Тогда // Мультиметка443985642
		СинтаксПомощник = СинтаксПомощник();
		#Если Сервер И Не Сервер Тогда
			СинтаксПомощник = Обработки.ирСинтаксПомощник.Создать();
		#КонецЕсли
		МассивВариантов = Новый Массив;
		Если СтрокаОписания.ТипСлова = "Конструктор" Тогда
			//Отбор = Новый Структура("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка, НСлово"); // Так будет только для одного варианта синтаксиса
			Отбор = Новый Структура("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка"); // индекс
			ЗаполнитьЗначенияСвойств(Отбор, СтрокаОписания);
			Для Каждого СтрокаВарианта Из ТаблицаКонтекстов.НайтиСтроки(Отбор) Цикл
				МассивВариантов.Добавить(СтрокаВарианта);
			КонецЦикла;
		Иначе
			МассивВариантов.Добавить(СтрокаОписания);
		КонецЕсли;
		Для Каждого ВариантМетода Из МассивВариантов Цикл
			ПутьКЭлементуАрхива = ВариантМетода.ПутьКОписанию;
			Если Не ЗначениеЗаполнено(ПутьКЭлементуАрхива) Тогда
				Продолжить;
			КонецЕсли;
			НовыйАдрес = СинтаксПомощник.РаспаковатьФайлАрхиваСинтаксПомощника(ПутьКЭлементуАрхива);
			КоличествоПараметров = 100;
			Если НовыйАдрес <> Неопределено Тогда
				ТекстовыйДокумент = Новый ТекстовыйДокумент;
				ТекстовыйДокумент.Прочитать(ирОбщий.ПервыйФрагментЛкс(НовыйАдрес, "#"));
				ТекстДокумента = ТекстовыйДокумент.ПолучитьТекст();
				КоличествоПараметров = СинтаксПомощник.ЗагрузитьОписаниеМетода(ВариантМетода.ТипКонтекста, ВариантМетода.Слово, ТекстДокумента, ВариантМетода.ТипСлова, ВариантМетода.ЯзыкПрограммы,,, ВариантМетода);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	СтрокиПараметров = ТаблицаПараметров.Скопировать(ОтборПараметров);
	Пока Истина
		И КоличествоПараметров > 0
		И КоличествоПараметров < СтрокиПараметров.Количество() 
		И СтрокиПараметров[0].ВариантСинтаксиса = СтрокиПараметров[КоличествоПараметров].ВариантСинтаксиса
	Цикл
		// Удаляем дубли параметров виртуальных таблиц регистра бухгалтерии https://www.hostedredmine.com/issues/952173
		СтрокиПараметров.Удалить(КоличествоПараметров); 
	КонецЦикла;
	Возврат СтрокиПараметров;

КонецФункции

Функция ПолучитьТипЗначенияЧленаИнтерфейса(ОписаниеРезультата, ИмяБиблиотеки = "", _БиблиотекаТипов = Неопределено) Экспорт

	//Тест = ПолучитьИмяТипаCOMVariant(Член);
	ИнфоТипаРезультата = ОписаниеРезультата.TypeInfo;
	Если ИнфоТипаРезультата <> Неопределено Тогда
		ТипЗначенияРезультата = ПолноеИмяТипаCOMОбъектаИзИнфоТипа(ИнфоТипаРезультата, ИмяБиблиотеки);
	Иначе
		НомерТипа = ОписаниеРезультата.VarType;
		ТипЗначенияРезультата = "Произвольный" + ", " + НомерТипа;
		Если НомерТипа = 0 Тогда
			ТипЗначенияРезультата = Неопределено;
		ИначеЕсли НомерТипа = 1 Тогда
			ТипЗначенияРезультата = Null;
		ИначеЕсли НомерТипа >= 2 И НомерТипа <= 5 Тогда
			ТипЗначенияРезультата = "Число";
		ИначеЕсли НомерТипа = 7 Тогда
			ТипЗначенияРезультата = "Дата";
		ИначеЕсли НомерТипа = 8 Тогда
			ТипЗначенияРезультата = "Строка";
		ИначеЕсли НомерТипа = 11 Тогда
			ТипЗначенияРезультата = "Булево";
		ИначеЕсли НомерТипа = 12 Тогда
			ТипЗначенияРезультата = "Строка";
		ИначеЕсли НомерТипа >= 14 И НомерТипа <= 23 Тогда
			ТипЗначенияРезультата = "Число";
		ИначеЕсли НомерТипа = 24 Тогда
			// Метод не возвращает значение - Процедура
			ТипЗначенияРезультата = "";
		ИначеЕсли НомерТипа = 9 Тогда
			// Тип этого значения станет известен только при его появлении
			//ТипЗначенияРезультата = ПолучитьИмяТипаCOMVariant(ОписаниеРезультата); // Тоже не дает результат
			ТипЗначенияРезультата = "Произвольный";
		КонецЕсли; 
	КонецЕсли;

	Возврат ТипЗначенияРезультата;

 //'OLE Automation VARIANT types
 // Enum TliVarType
 // VT_EMPTY = 0  '&H0
 // VT_NULL = 1  '&H1
 // VT_I2 = 2  '&H2
 // VT_I4 = 3  '&H3
 // VT_R4 = 4  '&H4
 // VT_R8 = 5  '&H5
 // VT_CY = 6  '&H6
 // VT_DATE = 7  '&H7
 // VT_BSTR = 8  '&H8
 // VT_DISPATCH = 9  '&H9
 // VT_ERROR = 10  '&HA
 // VT_BOOL = 11  '&HB
 // VT_VARIANT = 12  '&HC
 // VT_UNKNOWN = 13  '&HD
 // VT_DECIMAL = 14  '&HE
 // VT_I1 = 16  '&H10
 // VT_UI1 = 17  '&H11
 // VT_UI2 = 18  '&H12
 // VT_UI4 = 19  '&H13
 // VT_I8 = 20  '&H14
 // VT_UI8 = 21  '&H15
 // VT_INT = 22  '&H16
 // VT_UINT = 23  '&H17
 // VT_VOID = 24  '&H18
 // VT_HRESULT = 25  '&H19
 // VT_PTR = 26  '&H1A
 // VT_SAFEARRAY = 27  '&H1B
 // VT_CARRAY = 28  '&H1C
 // VT_USERDEFINED = 29  '&H1D
 // VT_LPSTR = 30  '&H1E
 // VT_LPWSTR = 31  '&H1F
 // VT_RECORD = 36  '&H24
 // VT_FILETIME = 64  '&H40
 // VT_BLOB = 65  '&H41
 // VT_STREAM = 66  '&H42
 // VT_STORAGE = 67  '&H43
 // VT_STREAMED_OBJECT = 68  '&H44
 // VT_STORED_OBJECT = 69  '&H45
 // VT_BLOB_OBJECT = 70  '&H46
 // VT_CF = 71  '&H47
 // VT_CLSID = 72  '&H48
 // VT_VECTOR = 4096  '&H1000
 // VT_ARRAY = 8192  '&H2000
 // VT_BYREF = 16384  '&H4000
 // VT_RESERVED = 32768  '&H8000
  
КонецФункции

Функция ПолноеИмяТипаCOMОбъектаИзИнфоТипа(ИнфоИнтерфейса, Знач ИмяБиблиотеки = "") Экспорт

	Если Не ЗначениеЗаполнено(ИмяБиблиотеки) Тогда
		ИмяБиблиотеки = "COMОбъект";
	КонецЕсли; 
	Результат = ИнфоИнтерфейса.Name + " {" + ИмяБиблиотеки + "}";
	Возврат Результат;

КонецФункции

Функция ПолноеИмяТипаCOMОбъекта(COMОбъект, Знач ПолноеИмяОсновногоКласса = "") Экспорт

	ИнфоИнтерфейса = ПолучитьИнфоТипаCOMОбъекта(COMОбъект, , ПолноеИмяОсновногоКласса);
	Если ИнфоИнтерфейса <> Неопределено Тогда
		Результат = ПолноеИмяТипаCOMОбъектаИзИнфоТипа(ИнфоИнтерфейса, ПолноеИмяОсновногоКласса);
	Иначе
		Результат = "COMОбъект";
	КонецЕсли; 
	Возврат Результат;

КонецФункции

// Функция - Получить инфо типа COMОбъекта
//
// Параметры:
//  выхCOMОбъект				 - 	 - 
//  ИмяОбщегоТипа				 - 	 - 
//  выхПолноеИмяОсновногоКласса	 - 	 - 
// 
// Возвращаемое значение:
//  TypeInfo {TLI.TLIApplication}, InterfaceInfo {TLI.TLIApplication} - 
//
Функция ПолучитьИнфоТипаCOMОбъекта(выхCOMОбъект, Знач ИмяОбщегоТипа = Неопределено, выхПолноеИмяОсновногоКласса = "") Экспорт

	ПолучитьCOMНавигатор();
	Если COMНавигатор = "Отказ" Тогда
		Возврат Неопределено;
	КонецЕсли;
	Если ТипЗнч(выхCOMОбъект) = Тип("COMОбъект") Тогда 
		Попытка
			COMНавигатор.ResolveAliases = Ложь;    // Тут бывает кривой объект без свойств и методов и при выводе строки эта ошибка очень раздражает
			//ИнфоКласса = COMНавигатор.TypeLibInfoFromRegistry(); // По ИУД
			//ИнфоКласса = COMНавигатор.ClassInfoFromObject(выхCOMОбъект); // Этот способ не поддерживается в большинстве классов
			ИнфоИнтерфейса = COMНавигатор.InterfaceInfoFromObject(выхCOMОбъект); // Тут возникает ошибка для некоторых объектов, например V83.Application, ADODB.Recorset.Fields(*).Precision, WindowsInstaller.Installer
		Исключение
			ОписаниеОшибки = ОписаниеОшибки();
			//ирОбщий.СообщитьЛкс(ОписаниеОшибки);
			Возврат Неопределено;
		КонецПопытки; 
	КонецЕсли; 
	Если ЗначениеЗаполнено(ИмяОбщегоТипа) Тогда
		выхПолноеИмяОсновногоКласса = ирОбщий.ТекстМеждуМаркерамиЛкс(ИмяОбщегоТипа, "{", "}", Ложь);
		ИмяОбщегоТипа = ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипа, " "); 
	КонецЕсли; 
	Если Не ЗначениеЗаполнено(выхПолноеИмяОсновногоКласса) Тогда
		Если ТипЗнч(выхCOMОбъект) = Тип("COMОбъект") Тогда 
			ИмяБиблиотеки = ИнфоИнтерфейса.Parent.Name;
			ИмяОсновногоКласса = мИменаОсновныхКлассовБиблиотекCOM[ИмяБиблиотеки];
			Если ИмяОсновногоКласса = Неопределено Тогда
				//КаталогПриложений = Новый COMОбъект("COMAdmin.COMAdminCatalog");
				//КаталогПриложений.Connect("localhost");
				//Компоненты = КаталогПриложений.GetCollection("InprocServers");
				//Компоненты.PopulateByKey("" + ИнфоИнтерфейса.Parent.GUID);
				//Компоненты.PopulateByKey("{F935DC26-1CF0-11D0-ADB9-00C04FD58A0B}");
				//Если Компоненты.Count > 0 Тогда
				//	ИмяОсновногоКласса = Компоненты.Item(0).Name;
				//Иначе
					ПробныйОбъект = Неопределено;
					Для Каждого Претендент Из ИнфоИнтерфейса.Parent.CoClasses Цикл
						Попытка
							ПробныйОбъект = Новый COMОбъект(ИмяБиблиотеки + "." + Претендент.Name);
						Исключение
							Продолжить;
						КонецПопытки;
						Прервать;
					КонецЦикла;
					Если ПробныйОбъект <> Неопределено Тогда
						ИмяОсновногоКласса = Претендент.Name;
					Иначе
						ИмяОсновногоКласса = "?";
					КонецЕсли; 
					мИменаОсновныхКлассовБиблиотекCOM[ИмяБиблиотеки] = ИмяОсновногоКласса;
				//КонецЕсли; 
			КонецЕсли; 
			выхПолноеИмяОсновногоКласса = ИмяБиблиотеки + "." + ИмяОсновногоКласса;
		Иначе
			Возврат Неопределено;
		КонецЕсли;
	КонецЕсли;
	Если ИнфоИнтерфейса = Неопределено Тогда
		выхCOMОбъект = ПолучитьОбразецCOMОбъекта(выхПолноеИмяОсновногоКласса);
		Попытка
			ИнфоИнтерфейса = COMНавигатор.InterfaceInfoFromObject(выхCOMОбъект);
		Исключение
			//ирОбщий.СообщитьЛкс(ОписаниеОшибки());
			Возврат Неопределено;
		КонецПопытки; 
		лИнфоИнтерфейса = ИнфоИнтерфейса.Parent.TypeInfos.NamedItem(ИмяОбщегоТипа);
		Если лИнфоИнтерфейса <> Неопределено Тогда
			ИнфоИнтерфейса = лИнфоИнтерфейса;
		Иначе
			// Например для Shell.Application выполняется
		КонецЕсли; 
	КонецЕсли;
	Возврат ИнфоИнтерфейса;

КонецФункции

Функция ПолучитьОбразецCOMОбъекта(ПолноеИмяОсновногоКлассаCOM) Экспорт

	КлючКэша = НРег(ПолноеИмяОсновногоКлассаCOM);
	Результат = мОбразцыCOMОбъектов[КлючКэша];
	// Закомментировал т.к. замедляет работу анализатора кода например для V83.Application
	//Если Результат <> Неопределено Тогда
	//	ИнфоИнтерфейса = ПолучитьИнфоТипаCOMОбъекта(Результат,, ПолноеИмяОсновногоКлассаCOM);
	//	Если ИнфоИнтерфейса = Неопределено Тогда
	//		// Объект испорчен
	//		Результат = Неопределено;
	//	КонецЕсли; 
	//КонецЕсли; 
	Если Результат = Неопределено Тогда
		Попытка
			Результат = Новый COMОбъект(ПолноеИмяОсновногоКлассаCOM);
		Исключение
			Возврат Неопределено;
		КонецПопытки;
		мОбразцыCOMОбъектов[КлючКэша] = Результат;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

// Получает новый экземпляр ком-объекта парсера.
//
// Параметры:
//  Нет.
//
// Возвращаемое значение:
//  Com-объект, Неопределено.
//
Функция ПолучитьCOMНавигатор() Экспорт

	Если COMНавигатор = "НеИнициализирован" Тогда
		COMНавигатор = ПолучитьCOMОбъектИзМакета("TLBINF32", "TLI.TLIApplication");
		//! COMНавигатор = Новый COMОбъект("TLI.TLIApplication");
	КонецЕсли;
	Возврат COMНавигатор;

КонецФункции

Функция ТипыЭлементовКоллекции(Знач СтруктураТипаКоллекции, Знач ЯзыкПрограммы = 0, выхНужнаПроверкаТипов = Истина) Экспорт
	
	выхНужнаПроверкаТипов = Истина;
	ТипыЭлементовКоллекции = Новый Массив();
	ИмяОбщегоТипаКоллекции = ирОбщий.ПервыйФрагментЛкс(СтруктураТипаКоллекции.ИмяОбщегоТипа, "["); 
	Если Ложь
		Или ИмяОбщегоТипаКоллекции = "Массив" 
		Или ИмяОбщегоТипаКоллекции = "ФиксированныйМассив"
	Тогда
		выхНужнаПроверкаТипов = Ложь;
		ТекстТипыЭлементов = ирОбщий.ТекстМеждуМаркерамиЛкс(СтруктураТипаКоллекции.ИмяОбщегоТипа, "[", "]", Ложь);
		Если ЗначениеЗаполнено(ТекстТипыЭлементов) Тогда
			ТипыЭлементовКоллекции = ирОбщий.СтрРазделитьЛкс(ТекстТипыЭлементов, ", ");
		КонецЕсли;
	ИначеЕсли ЛиИмяТипаComОбъекта(СтруктураТипаКоллекции.ИмяОбщегоТипа) Тогда
		ИмяОбщегоТипа = СтруктураТипаКоллекции.ИмяОбщегоТипа;
		ТаблицаСтруктурТипаЭлемента = НоваяТаблицаТипов();
		ИмяБиблиотеки = "";
		МетаданныеОбъекта = СтруктураТипаКоллекции.Метаданные;
		ИнфоТипа = ПолучитьИнфоТипаCOMОбъекта(МетаданныеОбъекта, ИмяОбщегоТипа, ИмяБиблиотеки);
		Если ИнфоТипа = Неопределено Тогда
			Возврат ТаблицаСтруктурТипаЭлемента;
		КонецЕсли; 
		МассивИнфоТипа = ИнтерфейсыCOMОбъекта(ИнфоТипа, ИмяОбщегоТипа);
		Для Каждого ИнфоТипа Из МассивИнфоТипа Цикл
			Для Каждого Член Из ИнфоТипа.Members Цикл
				Если Истина
					//И Член.InvokeKind = 1 // метод // почему то иногда у него стоит 2 (например ADODB.Fields)
					И ирОбщий.СтрокиРавныЛкс(Член.Name, "Item") 
				Тогда
					ИнфоТипаЭлемента = Член.ReturnType.TypeInfo;
					ИмяОбщегоТипаЭлемента = ПолучитьТипЗначенияЧленаИнтерфейса(Член.ReturnType, ИмяБиблиотеки, ИнфоТипа.Parent);
					ТипыЭлементовКоллекции.Добавить(ИмяОбщегоТипаЭлемента);
					Прервать;
				КонецЕсли; 
			КонецЦикла;
		КонецЦикла;
	ИначеЕсли Истина
		И СтруктураТипаКоллекции.ИмяОбщегоТипа = "ЭлементыФормы" 
		И ТипЗнч(СтруктураТипаКоллекции.СтрокаОписания) = Тип("СтрокаТаблицыЗначений")
		И СтруктураТипаКоллекции.СтрокаОписания.ТипКонтекста = "Форма"
	Тогда 
		ТипыЭлементовКоллекции = мМассивТиповЭлементовОбычнойФормы;
	Иначе
		СтруктураКлюча = Новый Структура("Слово, ЯзыкПрограммы", СтруктураТипаКоллекции.ИмяОбщегоТипа, ЯзыкПрограммы);
		НайденныеСтроки = ТаблицаОбщихТипов.НайтиСтроки(СтруктураКлюча);
		Если НайденныеСтроки.Количество() > 0 Тогда
			Если НайденныеСтроки[0].ТипЭлементаКоллекции <> "" Тогда
				ТипыЭлементовКоллекции = ирОбщий.СтрРазделитьЛкс(НайденныеСтроки[0].ТипЭлементаКоллекции, ",", Истина);
			КонецЕсли;
		КонецЕсли; 
	КонецЕсли; 
	Возврат ТипыЭлементовКоллекции;

КонецФункции

// Добавляет и заполяет строку в таблицу слов при условии отсутствия там строк по ключу (Слово, ТипСлова)
//
// Параметры:
//  ТаблицаСлов  - ТаблицаЗначений - НоваяТаблицаСлов();
//  Слово        - Строка;
//  ТипСлова     - Строка;
//  ТаблицаТипов - ТаблицаЗначений.
//
Функция ДобавитьВТаблицуСлов(Знач ТаблицаСлов, Знач Слово, Знач ТипСлова, Знач ТаблицаТипов = Неопределено, Знач ТипЗначения = "??", Знач Определение = "") Экспорт

	#Если Сервер И Не Сервер Тогда
		ТаблицаСлов = Новый ТаблицаЗначений
	#КонецЕсли
	КлючПоиска = Новый Структура("Слово, ТипСлова", Слово, ТипСлова);
	Если ТипСлова <> "Метод" Тогда // Для ускорения, т.к. платформа не позволяет перегружать методы
		НайденныеСтроки = ТаблицаСлов.НайтиСтроки(КлючПоиска);
		Если НайденныеСтроки.Количество() > 0 Тогда  
			Если ТаблицаТипов <> Неопределено Тогда
				ДобавитьВТаблицуТипов(НайденныеСтроки[0].ТаблицаТипов, ТаблицаТипов);
			КонецЕсли;
			Возврат НайденныеСтроки[0];
		КонецЕсли;
	КонецЕсли;
	СтрокаСлова = ТаблицаСлов.Добавить();
	ЗаполнитьЗначенияСвойств(СтрокаСлова, КлючПоиска);
	СтрокаСлова.ТипЗначения = ТипЗначения;
	СтрокаСлова.Определение = Определение;
	Если ТаблицаТипов <> Неопределено Тогда
		СтрокаСлова.ТаблицаТипов = ТаблицаТипов;
		Попытка
			ТипЗначенияВложенный = ТаблицаТипов[0].СтрокаОписания.ТипЗначения;
		Исключение
			ТипЗначенияВложенный = Неопределено;
		КонецПопытки; 
		Если Ложь
			//Или ТипЗначенияВложенный = Неопределено // Отключил, чтобы вычисление представлений примитивных типов не откладывалось
			//Или ТипЗначенияВложенный = "Произвольный"
		Тогда
			ТипЗначенияВложенный = "??";
		КонецЕсли;
		СтрокаСлова.МожноУточнитьТип = Ложь 
			Или (Истина
				И ТипЗначенияВложенный <> "??" // Нужно чтобы вычисляемые по коду свойства и функции не вычислялись сразу при заполнении списка автодополнения
				И Лев(ТипЗначения, 2) = "??") 
			Или Найти(ТипЗначения, "<") > 0;
	КонецЕсли;
	Возврат СтрокаСлова;

КонецФункции

// Получает таблицу слов указанной структуры типа.
//
// Параметры:
// СтруктураТипа - Структура - описание типа.
//  БазовоеРасширениеКонфигурации    - Строка - "" - основная конфигурация, "*" - все расширения
//
// Возвращаемое значение:
//  ТаблицаЗначений - с колонками "Слово", "ТипСлова", "ТаблицаТипов", "Определение".
//
Функция ТаблицаСловИзСтруктурыТипа(СтруктураТипа, ЯзыкПрограммы = 0, Конфигурация = Неопределено, ВнешниеФункцииКомпоновкиДанных = Истина, Знач ВычислятьТипы = Истина,
	Знач ВнутриГруппыОбщихМодулей = Ложь, ТипСлова = Неопределено, Знач ФлагиКомпиляции = Неопределено, Знач Слово = Неопределено, Знач МодульМетаданных = Неопределено,
	Знач ВычислятьТипыМетодовМодулей = Неопределено, Знач ТаблицаСвойств = Неопределено, Знач ЭтоЛокальныйКонтекст = Ложь, Знач НаборыСлов = Неопределено, Знач БазовоеРасширениеКонфигурации = "") Экспорт 

	ИнициацияОписанияМетодовИСвойств();    
	Если ФлагиКомпиляции = Неопределено Тогда
		ФлагиКомпиляции = НовыеФлагиКомпиляции();
	КонецЕсли;
	Если Не ВнутриГруппыОбщихМодулей Тогда
		ТаблицаСвойств = СловаКонтекстаПредопределенные(СтруктураТипа, Слово, ТипСлова,, ЯзыкПрограммы, Конфигурация, ВычислятьТипы, ФлагиКомпиляции, ТаблицаСвойств, ЭтоЛокальныйКонтекст, НаборыСлов,
			БазовоеРасширениеКонфигурации);
	КонецЕсли;
	ТаблицаСвойств = СловаКонтекстаМетаданные(СтруктураТипа, Слово, ТипСлова, ВнутриГруппыОбщихМодулей, ЯзыкПрограммы,, ВнешниеФункцииКомпоновкиДанных, ВычислятьТипы, ФлагиКомпиляции, 
		МодульМетаданных, ТаблицаСвойств, ВычислятьТипыМетодовМодулей, ЭтоЛокальныйКонтекст,, БазовоеРасширениеКонфигурации);
	Возврат ТаблицаСвойств; 

КонецФункции

Функция ИмяКолонкиФлагаВнутриТаблицы() Экспорт 
	Возврат "ДержательМетаданных";
КонецФункции

// Получает новую структуру типа.
//
// Параметры:
//  Нет.
//
// Возвращаемое значение:
//
Функция НоваяТаблицаДополнительныхТипов() Экспорт

	ТаблицаСтруктурТипа = Новый ТаблицаЗначений;
	ТаблицаСтруктурТипа.Колонки.Добавить("ИмяОбщегоТипа", Новый ОписаниеТипов("Строка"));
	ТаблицаСтруктурТипа.Колонки.Добавить("Метаданные");
	//ТаблицаСтруктурТипа.Колонки.Добавить("ВключатьСвойства", Новый  ОписаниеТипов("Булево"));
	ТаблицаСтруктурТипа.Колонки.Добавить("НеВключатьМетоды", Новый  ОписаниеТипов("Булево"));
	Возврат ТаблицаСтруктурТипа;

КонецФункции

// Получает допустимые типы (строку) из таблицы структур типа.
//
// Параметры:
//  ТаблицаТипов - ТаблицаЗначений.
//
// Возвращаемое значение:
//  Строка.
//
Функция ДопустимыеТипыИзТаблицыСтруктурТипа(ТаблицаТипов) Экспорт

	СтрокаСериализованныхТипов = "";
	Для Каждого СтруктураТипа Из ТаблицаТипов Цикл
		СтрокаСериализованныхТипов = СтрокаСериализованныхТипов + ";" + СтруктураТипаВСтрокуВнутр(СтруктураТипа);
	КонецЦикла;
	СтрокаСериализованныхТипов = Сред(СтрокаСериализованныхТипов, 2);
	Возврат СтрокаСериализованныхТипов;

КонецФункции

Функция ДопустимыеТипыИзОписанияТипов(ОписаниеТипов) Экспорт

	ТаблицаТипов = ТаблицаТиповИзОписанияТипов(ОписаниеТипов);
	ДопустимыеТипы = ДопустимыеТипыИзТаблицыСтруктурТипа(ТаблицаТипов);
	Возврат ДопустимыеТипы;

КонецФункции

// Получает представление допустимых типов.
//
// Параметры:
//  ДопустимыеТипы - Строка.
//
// Возвращаемое значение:
//  СтрокаПредставления - Строка.
//
Функция ПредставлениеДопустимыхТипов(ДопустимыеТипы) Экспорт

	ТаблицаТипов = ТаблицаТиповИзДопустимыхТипов(ДопустимыеТипы);
	СтрокаПредставления = "";
	Для Каждого СтруктураТипа Из ТаблицаТипов Цикл
		СтрокаПредставления = СтрокаПредставления + ", " + ИмяТипаИзСтруктурыТипа(СтруктураТипа);
		ТипМетаданных = ТипЗнч(СтруктураТипа.Метаданные);
		Если ТипМетаданных = Тип("КвалификаторыДаты") Тогда 
			Квалификаторы = СтруктураТипа.Метаданные;
			Если Квалификаторы.ЧастиДаты = ЧастиДаты.Время Тогда
				ПредставлениеСоставаДаты = "В";
			ИначеЕсли Квалификаторы.ЧастиДаты = ЧастиДаты.Дата Тогда
				ПредставлениеСоставаДаты = "Д";
			ИначеЕсли Квалификаторы.ЧастиДаты = ЧастиДаты.ДатаВремя Тогда
				ПредставлениеСоставаДаты = "ДВ";
			КонецЕсли;
			СтрокаПредставления = СтрокаПредставления + "(" + ПредставлениеСоставаДаты + ")";
		ИначеЕсли ТипМетаданных = Тип("КвалификаторыСтроки") Тогда 
			Квалификаторы = СтруктураТипа.Метаданные;
			СтрокаПредставления = СтрокаПредставления + "(" 
				+ Квалификаторы.Длина + "," 
				+ ?(Квалификаторы.ДопустимаяДлина = ДопустимаяДлина.Фиксированная, "Ф", "П") + ")";
		ИначеЕсли ТипМетаданных = Тип("КвалификаторыЧисла") Тогда 
			Квалификаторы = СтруктураТипа.Метаданные;
			СтрокаПредставления = СтрокаПредставления + "("
				+ ?(Квалификаторы.ДопустимыйЗнак = ДопустимыйЗнак.Неотрицательный, "Н", "")
				+ Квалификаторы.Разрядность + "," 
				+ Квалификаторы.РазрядностьДробнойЧасти + ")";
        КонецЕсли; 
	КонецЦикла;
	СтрокаПредставления = Сред(СтрокаПредставления, 3);
	Возврат СтрокаПредставления;

КонецФункции // ПредставлениеДопустимыхТипов()

// Получает структуру типа из значения.
//
// Параметры:
//  Значение - Произвольный;
//  *ЯзыкПрограммы - Число, *0;
//  *ШаблонСтруктурыТипа - Структура, СтрокаТаблицыЗначений, *Неопределено - содержит значения по умолчанию для новой структуры типа.
//
// Возвращаемое значение:
//  см. НоваяСтруктураТипа() -
//
Функция СтруктураТипаИзЗначения(Значение, ЯзыкПрограммы = 0, ШаблонСтруктурыТипа = Неопределено) Экспорт
	
	Если мМассивТиповСМетаданными.Найти(ТипЗнч(Значение)) <> Неопределено Тогда 
		Если ШаблонСтруктурыТипа = Неопределено Тогда
			ШаблонСтруктурыТипа = Новый Структура;
		КонецЕсли;
		Если ТипЗнч(ШаблонСтруктурыТипа) = Тип("Структура") Тогда
			Если Ложь
				Или Не ШаблонСтруктурыТипа.Свойство("Метаданные")
				Или ШаблонСтруктурыТипа.Метаданные = Неопределено
			Тогда
				ШаблонСтруктурыТипа.Вставить("Метаданные", Значение);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли; 
	СтруктураТипа = СтруктураТипаИзКонкретногоТипа(ТипЗнч(Значение), ЯзыкПрограммы, ШаблонСтруктурыТипа);
	Если СтруктураТипа.ИмяОбщегоТипа = "COMОбъект" Тогда
		СтруктураТипа.ИмяОбщегоТипа = ПолноеИмяТипаCOMОбъекта(Значение);
	//ИначеЕсли СтруктураТипа.ИмяОбщегоТипа = "ПеречислимоеСвойствоОбъектовМетаданных" Тогда
	//  // Не работает. Оказывается одно ПеречислимоеСвойствоОбъектовМетаданных может иметь много экземпляров
	//	СтрокиСвойствПеречислений = ТаблицаКонтекстов.НайтиСтроки(Новый Структура("ТипКонтекста", "ПеречислимыеСвойстваОбъектовМетаданных"));
	//	Для Каждого СтрокиСвойстваПеречисления Из СтрокиСвойствПеречислений Цикл
	//		Если Метаданные.СвойстваОбъектов[СтрокиСвойстваПеречисления.Слово] = Значение Тогда
	//			СтруктураТипа.ИмяОбщегоТипа = "ПеречислениеМетаданных" + СтрокиСвойстваПеречисления.Слово;
	//			Прервать;
	//		КонецЕсли; 
	//	КонецЦикла;
	КонецЕсли; 
	ИмяОбщегоТипа = СтруктураТипа.ИмяОбщегоТипа;
	//Если Ложь
	//	Или (Истина
	//		И ИмяОбщегоТипа = "СтрокаТаблицыЗначений"
	//		И ТипЗнч(СтруктураТипа.Метаданные) <> Тип("ТаблицаЗначений"))
	//	Или (Истина
	//		И ИмяОбщегоТипа = "СтрокаДереваЗначений"
	//		И ТипЗнч(СтруктураТипа.Метаданные) <> Тип("ДеревоЗначений"))
	//	Или (Истина
	//		И ИмяОбщегоТипа = "ВыборкаИзРезультатаЗапроса"
	//		И ТипЗнч(СтруктураТипа.Метаданные) <> Тип("РезультатЗапроса"))
	//Тогда 
	//	Попытка
	//		СтруктураТипа.Метаданные = Значение.Владелец();
	//	Исключение
	//		// Строка была удалена из коллекции
	//	КонецПопытки; 
	//КонецЕсли;
	Если ирОбщий.ЛиИмяТипаВнешнегоОбъектаМетаданныхЛкс(ИмяОбщегоТипа) Тогда 
		//! Значение = 0 // ВнешняяОбработкаОбъект
		МетаданныеЗначения = Значение.Метаданные();
		ЛиНеУчитыватьПодтип = (ЯзыкПрограммы <> 0) И СтруктураТипа.ТипЯзыка <> "ЗначениеВЗапросе";
		ИмяОбщегоТипа = ИмяОбщегоТипаИзТипаЗначенияСМетаданными(ТипЗнч(Значение), МетаданныеЗначения, ЛиНеУчитыватьПодтип);
		СтруктураТипа.Метаданные = МетаданныеЗначения;
		КлючПоиска = Новый Структура("Слово", ИмяОбщегоТипа);
		НайденныеСтроки = ТаблицаОбщихТипов.НайтиСтроки(КлючПоиска);
		Если НайденныеСтроки.Количество() > 0 Тогда
			СтруктураТипа.ИмяОбщегоТипа = НайденныеСтроки[0].Слово;
			Если СтруктураТипа.СтрокаОписания = Неопределено Тогда
				СтруктураТипа.СтрокаОписания = НайденныеСтроки[0];
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	Если Ложь
		Или ИмяОбщегоТипа = "Форма"
		Или ИмяОбщегоТипа = "ПолеВвода"
		//Или ИмяОбщегоТипа = "КолонкаТабличногоПоля" // в другом месте делаем
		Или ИмяОбщегоТипа = "ТабличноеПоле"
		
		Или ИмяОбщегоТипа = "УправляемаяФорма"
		Или ИмяОбщегоТипа = "ФормаКлиентскогоПриложения"
		Или ЛиИмяТипаЭлементаУправляемойФормы(ИмяОбщегоТипа)
	Тогда 
		ИмяОбщегоТипаРасширения = ИмяТипаРасширенияЭлементаФормы(ИмяОбщегоТипа, Значение);
		Если ИмяОбщегоТипаРасширения <> Неопределено Тогда
			СтруктураТипа.ИмяОбщегоТипа = ИмяОбщегоТипаРасширения;
		КонецЕсли;
	КонецЕсли;
	Если ИмяОбщегоТипа = "Форма" Тогда 
		СтруктураТипа.ДержательМетаданных = Значение;
	КонецЕсли;
	Возврат СтруктураТипа;

КонецФункции

Функция ЛиИмяТипаЭлементаУправляемойФормы(Знач ИмяОбщегоТипа) Экспорт
	Результат = Ложь
		Или ИмяОбщегоТипа = "ДекорацияФормы"
		Или ИмяОбщегоТипа = "ПолеФормы"
		Или ИмяОбщегоТипа = "ГруппаФормы"
		Или ИмяОбщегоТипа = "ТаблицаФормы";
	Возврат Результат;
КонецФункции

// . Мультиметка638663811
//
// Параметры:
//  БазовоеИмяОбщегоТипа - 	 - 
//  ЭлементИлиФорма		 - Форма, ПолеФормы, ПолеВвода - 
// 
// Возвращаемое значение:
//   - 
//
Функция ИмяТипаРасширенияЭлементаФормы(БазовоеИмяОбщегоТипа, ЭлементИлиФорма = Неопределено) Экспорт
	ИмяОбщегоТипаРасширения = Неопределено;
	РасширяющийТип = Неопределено;
	Если Ложь
		Или БазовоеИмяОбщегоТипа = "УправляемаяФорма"
		Или БазовоеИмяОбщегоТипа = "ФормаКлиентскогоПриложения"
	Тогда
		БазовоеИмяОбщегоТипа = "ФормаКлиентскогоПриложения";
		КлючОсновногоОбъекта = ирОбщий.КлючОсновногоОбъектаФормыЛкс(ЭлементИлиФорма);
		Если КлючОсновногоОбъекта <> Неопределено Тогда
			СтруктураРасширяющегоТипа = СтруктураТипаИзЗначения(КлючОсновногоОбъекта); 
			ИмяОбщегоТипаОбъекта = СтруктураРасширяющегоТипа.ИмяОбщегоТипа;
			Если Найти(ИмяОбщегоТипаОбъекта, "Ссылка.") > 0 Тогда
				Если Ложь
					Или ирОбщий.СтрНачинаетсяСЛкс(ИмяОбщегоТипаОбъекта, "Справочник") 
					Или ирОбщий.СтрНачинаетсяСЛкс(ИмяОбщегоТипаОбъекта, "Документ")
					Или ирОбщий.СтрНачинаетсяСЛкс(ИмяОбщегоТипаОбъекта, "ПланВидовХарактеристик")
					Или ирОбщий.СтрНачинаетсяСЛкс(ИмяОбщегоТипаОбъекта, "Задача")
					Или ирОбщий.СтрНачинаетсяСЛкс(ИмяОбщегоТипаОбъекта, "БизнесПроцесс")
				Тогда 
					РасширяющийТип = СтрЗаменить(ИмяОбщегоТипаОбъекта, "Ссылка.", "Объект.");
				Иначе 
					РасширяющийТип = "СсылочныйОбъект";
				КонецЕсли;
			Иначе
				РасширяющийТип = СтрЗаменить(СтруктураРасширяющегоТипа.ИмяОбщегоТипа, "КлючЗаписи.", "Запись.");
			КонецЕсли; 
		Иначе
			Попытка
				Пустышка = ЭлементИлиФорма.Параметры.РежимВыбора;
				ЭтоФормаДинамическогоСписка = ТипЗнч(ЭлементИлиФорма.Список) = Тип("ДинамическийСписок");
			Исключение
				ЭтоФормаДинамическогоСписка = Ложь;
			КонецПопытки;
			Если ЭтоФормаДинамическогоСписка Тогда
				РасширяющийТип = "ДинамическийСписок";
			КонецЕсли; 
		КонецЕсли; 
	ИначеЕсли Ложь
		Или БазовоеИмяОбщегоТипа = "ДекорацияФормы"
		Или БазовоеИмяОбщегоТипа = "ПолеФормы"
		Или БазовоеИмяОбщегоТипа = "ГруппаФормы" 
	Тогда 
		Если ирОбщий.ЛиФормаИлиИмитаторЛкс(ЭлементИлиФорма) Тогда
			Пустышка = 0; // TODO Приходим союда при вводе имени события в ДинамическоеПолеФормы.Установитьдействие(" 
		Иначе
			Если ТипЗнч(ЭлементИлиФорма.Вид) <> Тип("Строка") Тогда 
				ИмяВида = ПолучитьПолноеИмяПредопределенногоЗначения(ЭлементИлиФорма.Вид);
			Иначе 
				ИмяВида = ЭлементИлиФорма.Вид;
			КонецЕсли;
			РасширяющийТип = ирОбщий.ПоследнийФрагментЛкс(ИмяВида);
		КонецЕсли;
	ИначеЕсли БазовоеИмяОбщегоТипа = "ТаблицаФормы" Тогда
		РасширяющийТип = ирОбщий.ОбщийТипДанныхТабличногоПоляЛкс(ЭлементИлиФорма);
		Если РасширяющийТип = "Список" Тогда
			РасширяющийТип = "ДинамическийСписок";
		КонецЕсли;
	ИначеЕсли БазовоеИмяОбщегоТипа = "Форма" Тогда 
		#Если Клиент Тогда
		СтруктураРасширяющегоТипа = СтруктураТипаОбъектаОбычнойФормы(ЭлементИлиФорма);
		Если СтруктураРасширяющегоТипа <> Неопределено Тогда
			РасширяющийТип = СтруктураРасширяющегоТипа.ИмяОбщегоТипа;
		КонецЕсли;
		#КонецЕсли
	Иначе
		Попытка
			ДанныеЭлементаФормы = ЭлементИлиФорма.Значение;
		Исключение
			// Случается из-за особенностей платформы. Иногда она убирает это свойство из элемента управления.
		КонецПопытки;
		СтруктураРасширяющегоТипа = СтруктураТипаИзЗначения(ДанныеЭлементаФормы);
		РасширяющийТип = СтруктураРасширяющегоТипа.ИмяОбщегоТипа;
		Если ирОбщий.СтрКончаетсяНаЛкс(РасширяющийТип, ".<Имя табличной части>") Тогда
			РасширяющийТип = "ТабличнаяЧасть";
		КонецЕсли;
		Попытка 
			Пустышка = Тип("Перечисление" + СтруктураРасширяющегоТипа.ИмяОбщегоТипа);
			РасширяющийТип = "Системное перечисление";
		Исключение
		КонецПопытки;
	КонецЕсли;
	Если РасширяющийТип <> Неопределено Тогда
		Если РасширяющийТип = "ВнешняяОбработкаОбъект.<Имя внешней обработки>" Тогда 
			РасширяющийТип = "ОбработкаОбъект.<Имя обработки>";
		ИначеЕсли РасширяющийТип = "ВнешнийОтчетОбъект.<Имя внешнего отчета>" Тогда 
			РасширяющийТип = "ОтчетОбъект.<Имя отчета>";
		КонецЕсли;
		СтруктураКлюча = Новый Структура("РасширяющийТип, ОсновнойТип", РасширяющийТип, БазовоеИмяОбщегоТипа);
		МассивНайденных = ТаблицаРасширенийТипов.НайтиСтроки(СтруктураКлюча);
		Если МассивНайденных.Количество() > 0 Тогда
			ИмяОбщегоТипаРасширения = МассивНайденных[0].Расширение;
		КонецЕсли;
	КонецЕсли;
	Возврат ИмяОбщегоТипаРасширения;
КонецФункции

// <Описание функции>
//
// Параметры:
//  <Параметр1>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>;
//  <Параметр2>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>.
//
// Возвращаемое значение:
//               - <Тип.Вид> - <описание значения>
//                 <продолжение описания значения>;
//  <Значение2>  - <Тип.Вид> - <описание значения>
//                 <продолжение описания значения>.
//
Функция УникальныйИдентификаторИзСтроки(Текст) Экспорт

	Цифра = "[a-fA-F0-9]";
	RegExp.Pattern = "(" + ирОбщий.СтрокаПовторомЛкс(Цифра, 32) + ")|(" 
		+ ирОбщий.СтрокаПовторомЛкс(Цифра, 8) + "-" 
		+ ирОбщий.СтрокаПовторомЛкс(Цифра, 4) + "-"
		+ ирОбщий.СтрокаПовторомЛкс(Цифра, 4) + "-"
		+ ирОбщий.СтрокаПовторомЛкс(Цифра, 4) + "-"
		+ ирОбщий.СтрокаПовторомЛкс(Цифра, 12) + ")";
	Вхождения = RegExp.НайтиВхождения(Текст);
	Если Вхождения.Количество() > 0 Тогда
		Вхождение = Вхождения[0];
		Если Не ирОбщий.ЛиПустаяПодгруппаRegExpЛкс(Вхождение.SubMatches(1)) Тогда
			УникальныйИдентификатор = Новый УникальныйИдентификатор(Вхождение.SubMatches(1));
		Иначе
			УникальныйИдентификатор = Новый УникальныйИдентификатор(ирОбщий.ПолучитьГУИДПрямойИзИнверсногоЛкс(Вхождение.SubMatches(0)));
		КонецЕсли;
	КонецЕсли;
	Возврат УникальныйИдентификатор;

КонецФункции

// Неполный сериализатор структуры типа.
//
// Параметры:
// СтруктураТипа - Структура.
//
// Возвращаемое значение:
//  Строка.
//
Функция СтруктураТипаВСтрокуВнутр(СтруктураТипа) Экспорт

	ОписательТипа = Новый Структура("ИмяОбщегоТипа, Метаданные");
	ЗаполнитьЗначенияСвойств(ОписательТипа, СтруктураТипа, "ИмяОбщегоТипа");
	ТипМетаданных = ТипЗнч(СтруктураТипа.Метаданные);
	Если ТипМетаданных = Тип("ОбъектМетаданныхКонфигурация") Тогда
		//ОписательТипа.Метаданные = СтруктураТипа.Метаданные.ПолноеИмя();
	ИначеЕсли ТипМетаданных = Тип("ОбъектМетаданных") Тогда
		ОписательТипа.Метаданные = СтруктураТипа.Метаданные.ПолноеИмя();
	ИначеЕсли Ложь
		Или ТипМетаданных = Тип("КвалификаторыДаты")
		Или ТипМетаданных = Тип("КвалификаторыСтроки")
		Или ТипМетаданных = Тип("КвалификаторыЧисла")
	Тогда
		Поток = Новый ЗаписьXML;
		Поток.УстановитьСтроку();
		СериализаторXDTO.ЗаписатьXML(Поток, СтруктураТипа.Метаданные);
		ОписательТипа.Метаданные = Новый ХранилищеЗначения(Поток.Закрыть());
	Иначе
		//ОписательТипа.Метаданные = СтруктураТипа.Метаданные;
	КонецЕсли;
	Результат = ЗначениеВСтрокуВнутр(ОписательТипа);
	Возврат Результат;

КонецФункции // СтруктураТипаВСтрокуВнутр()

// Зависит от текущего языка системы. Поддерживаются Рус и Анг языки.
//
// Параметры:
//  КонкрентыйТип		 - Тип - 
//  МетаданныеТипа		 - ОбъектМетаданных - 
//  ЛиНеУчитыватьПодтип	 - Булево - 
// 
// Возвращаемое значение:
//  Строка - 
//
Функция ИмяОбщегоТипаИзТипаЗначенияСМетаданными(Знач КонкрентыйТип, Знач МетаданныеТипа, Знач ЛиНеУчитыватьПодтип)

	КонкрентыйТип = НРег(КонкрентыйТип);
	Если Ложь
		Или Найти(КонкрентыйТип, "(точка маршрута)") > 0
		Или Найти(КонкрентыйТип, "(route point)") > 0
	Тогда
		ИмяОбщегоТипа = "ТочкаМаршрутаБизнесПроцессаСсылка.<Имя бизнес-процесса>";
		Возврат ИмяОбщегоТипа;
	КонецЕсли;
	ИмяОбщегоТипа = ирОбщий.КорневойТипКонфигурацииЛкс(МетаданныеТипа);
	Подтип = "";
	ИмяЭлементаПодтипа = "";
	Если ЛиНеУчитыватьПодтип Тогда 
		Подтип = "";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "объект:") > 0 
		Или Найти(КонкрентыйТип, "object:") > 0 
	Тогда
		//Если Истина
		//	И Не ИмяОбщегоТипа = "ВнешняяОбработка"
		//	И Не ИмяОбщегоТипа = "ВнешнийОтчет"
		//Тогда
			Подтип = "Объект";
		//КонецЕсли;
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "выборка:") > 0 
		Или Найти(КонкрентыйТип, "selection:") > 0 
	Тогда
		Подтип = "Выборка";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "список:") > 0 
		Или Найти(КонкрентыйТип, "list:") > 0 
	Тогда
		Подтип = "Список";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "менеджер:") > 0 
		Или Найти(КонкрентыйТип, "manager:") > 0 
	Тогда
		Подтип = "Менеджер";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "менеджер значения:") > 0 
		Или Найти(КонкрентыйТип, "value manager:") > 0 
	Тогда
		Подтип = "МенеджерЗначения";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "менеджер ws-ссылки:") > 0 
		Или Найти(КонкрентыйТип, "ws-reference manager:") > 0 
	Тогда
		Подтип = "Менеджер";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "табличная часть:") > 0 
		Или Найти(КонкрентыйТип, "tabular section:") > 0 
	Тогда
		Подтип = "ТабличнаяЧасть";
		ИмяЭлементаПодтипа = "<Имя табличной части>";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "табличная часть строка:") > 0 
		Или Найти(КонкрентыйТип, "tabular section row:") > 0 
	Тогда
		Подтип = "ТабличнаяЧастьСтрока";
		ИмяЭлементаПодтипа = "<Имя табличной части>";
	ИначеЕсли Ложь                                         // Связано со следующим условием!
		Или Найти(КонкрентыйТип, "виды субконто:") > 0 
		Или Найти(КонкрентыйТип, "ext dimension types:") > 0 
	Тогда
		Подтип = "ВидыСубконто";
	ИначеЕсли Ложь                                         // Связано со следующим условием!
		Или Найти(КонкрентыйТип, "ext dimensions:") > 0 
		Или Найти(КонкрентыйТип, "субконто:") > 0 
	Тогда
		Подтип = "Субконто";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "виды субконто строка:") > 0 
		Или Найти(КонкрентыйТип, "ext dimension types row:") > 0 
	Тогда
		Подтип = "ВидыСубконтоСтрока";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "набор записей:") > 0 
		Или Найти(КонкрентыйТип, "record set:") > 0 
	Тогда
		Подтип = "НаборЗаписей";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "ключ записи:") > 0 
		Или Найти(КонкрентыйТип, "record key:") > 0 
	Тогда
		Подтип = "КлючЗаписи";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "запись:") > 0 
		Или Найти(КонкрентыйТип, "record:") > 0 
	Тогда
		Подтип = "Запись";
	ИначеЕсли Ложь
		Или Найти(КонкрентыйТип, "менеджер записи:") > 0 
		Или Найти(КонкрентыйТип, "record manager:") > 0 
	Тогда
		Подтип = "МенеджерЗаписи";
	// Пришлось сделать так из-за изменения представления ссылочных типов в 8.2 http://partners.v8.1c.ru/forum/thread.jsp?id=830683#830683
	//ИначеЕсли Найти(КонкрентыйТип, "ссылка:") > 0 Тогда 
	Иначе//Если Найти(КонкрентыйТип, ":") = 0 Тогда 
		Подтип = "Ссылка";
	КонецЕсли;
	СтрокаКорневогоТипа = ОписаниеТипаМетаОбъектов(ИмяОбщегоТипа);
	СтрокаВида = ТаблицаИменЭлементовКоллекций.Найти(СтрокаКорневогоТипа.Множественное, "ИмяКоллекции");
	Если СтрокаВида <> Неопределено Тогда
		Если ИмяОбщегоТипа = "ВнешнийИсточникДанных" Тогда
			ИмяОбщегоТипа = ИмяОбщегоТипа + "Таблица" + Подтип + "." + СтрокаВида.ИмяЭлементаКоллекции;
			СтрокаВида = ТаблицаИменЭлементовКоллекций.Найти("Таблицы", "ИмяКоллекции");
			ИмяОбщегоТипа = ИмяОбщегоТипа + "." + СтрокаВида.ИмяЭлементаКоллекции;
		Иначе
			ИмяОбщегоТипа = ИмяОбщегоТипа + Подтип + "." + СтрокаВида.ИмяЭлементаКоллекции;
		КонецЕсли; 
	КонецЕсли;
	Если ИмяЭлементаПодтипа <> "" Тогда
		ИмяОбщегоТипа = ИмяОбщегоТипа + "." + ИмяЭлементаПодтипа;
	КонецЕсли;
	
	Возврат ИмяОбщегоТипа;

КонецФункции

//.
// Возвращаемое значение:
//    Структура - 
Функция ИменаТиповМетаданныхСМенеджерами() Экспорт
	Если мИменаТиповМетаданныхСМенеджерами <> Неопределено Тогда
		Возврат мИменаТиповМетаданныхСМенеджерами;
	КонецЕсли;
	мИменаТиповМетаданныхСМенеджерами = Новый Структура;
	ИмяДочернегоТипаМД = "МодульМенеджера";
	Для Каждого СтрокаТипаМетаОбъекта Из ирКэш.ТипыМетаОбъектов(Истина, Ложь) Цикл
		ОтборСвойств = Новый Структура("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка, НСлово, ТипСлова", 
			"ОбъектМетаданных" + СтрокаТипаМетаОбъекта.Единственное, 0, "", НРег(ИмяДочернегоТипаМД), "Свойство");
		Если ТаблицаКонтекстов.НайтиСтроки(ОтборСвойств).Количество() = 0 Тогда 
			Продолжить;
		КонецЕсли;
		мИменаТиповМетаданныхСМенеджерами.Вставить(СтрокаТипаМетаОбъекта.Множественное);
	КонецЦикла;
	Возврат мИменаТиповМетаданныхСМенеджерами;
КонецФункции

// Получает структуру типа из конкретного типа.
//
// Параметры:
//  КонкрентыйТип - Тип, Строка - тип либо его представление (для неметаданных типов);
//  *ЯзыкПрограммы - Число, *0;
//  *ШаблонСтруктурыТипа - Структура, *Неопределено - содержит значения по умолчанию для новой структуры типа.
//
// Возвращаемое значение:
//  см. НоваяСтруктураТипа() -
//
Функция СтруктураТипаИзКонкретногоТипа(КонкрентыйТип, ЯзыкПрограммы = 0, ШаблонСтруктурыТипа = Неопределено) Экспорт
	
	СтруктураТипа = НоваяСтруктураТипа();
	СтруктураТипа.Метаданные = мМетаданные;
	Если ШаблонСтруктурыТипа <> Неопределено Тогда
		ЗаполнитьЗначенияСвойств(СтруктураТипа, ШаблонСтруктурыТипа);
	КонецЕсли; 
	Если ЯзыкПрограммы = 1 И КонкрентыйТип = Тип("ТаблицаЗначений") Тогда
		СтруктураТипа.ИмяОбщегоТипа = "ВременнаяТаблица";
		
	// Для ускорения
	ИначеЕсли КонкрентыйТип = Тип("Число") Тогда 
		СтруктураТипа.ИмяОбщегоТипа = "Число";
	ИначеЕсли КонкрентыйТип = Тип("Строка") Тогда 
		СтруктураТипа.ИмяОбщегоТипа = "Строка";
	ИначеЕсли КонкрентыйТип = Тип("Булево") Тогда 
		СтруктураТипа.ИмяОбщегоТипа = "Булево";
	ИначеЕсли КонкрентыйТип = Тип("ОписаниеТипов") Тогда 
		СтруктураТипа.ИмяОбщегоТипа = "ОписаниеТипов";
	ИначеЕсли КонкрентыйТип = Тип("Массив") Тогда 
		СтруктураТипа.ИмяОбщегоТипа = "Массив";
	ИначеЕсли КонкрентыйТип = Тип("Структура") Тогда 
		СтруктураТипа.ИмяОбщегоТипа = "Структура";
		
	ИначеЕсли КонкрентыйТип = Тип("ОбъектМетаданных") Тогда
		Если Истина
			И ШаблонСтруктурыТипа <> Неопределено // было закомментировано
			И ТипЗнч(ШаблонСтруктурыТипа.Метаданные) = Тип("ОбъектМетаданных")
		Тогда
			МассивФрагментов = ирОбщий.СтрРазделитьЛкс(ШаблонСтруктурыТипа.Метаданные.ПолноеИмя());
			// Исключения из общего правила
			Если МассивФрагментов[0] = "ОбщаяФорма" Тогда
				МассивФрагментов[0] = "Форма";
			ИначеЕсли МассивФрагментов[0] = "ОбщийМакет" Тогда
				МассивФрагментов[0] = "Макет";
			КонецЕсли; 
			СтруктураТипа.ИмяОбщегоТипа = МаркерОбъектаМетаданных + МассивФрагментов[МассивФрагментов.ВГраница() - 1];
		Иначе
			СтруктураТипа.ИмяОбщегоТипа = ИмяОбщегоТипаОбъектаМетаданных(); 
		КонецЕсли;
	ИначеЕсли Истина
		И КонкрентыйТип = Тип("КоллекцияОбъектовМетаданных")
		И ШаблонСтруктурыТипа <> Неопределено
		И СтруктураТипа.ИмяОбщегоТипа <> "НеизвестныйКонтекст"
	Тогда
		//
	Иначе
		Если Истина
			И ТипЗнч(КонкрентыйТип) = Тип("Тип")
			И КонкрентыйТип <> Тип("КонстантыНабор") // Антибаг платформы http://partners.v8.1c.ru/forum/thread.jsp?id=876094#876094
		Тогда 
			МетаданныеТипа = мМетаданные.НайтиПоТипу(КонкрентыйТип);
		КонецЕсли;
		Если МетаданныеТипа = Неопределено Тогда
			ПредставлениеТипа = Строка(КонкрентыйТип);
			Если Найти(ПредставлениеТипа, ":") = 0 Тогда
				ИдентификаторТипа = ирОбщий.ИдентификаторТипаЛкс(КонкрентыйТип);
			Иначе
				// Внешние метаданные
				ИдентификаторТипа = "";
				ПредставлениеТипа = ирОбщий.ПервыйФрагментЛкс(ПредставлениеТипа, ":");
				Если НРег(ПредставлениеТипа) = Нрег("External data processor") Тогда
					ПредставлениеТипа = "Внешняя обработка";
				ИначеЕсли НРег(ПредставлениеТипа) = Нрег("External data processor tabular section") Тогда
					ПредставлениеТипа = "Внешняя обработка табличная часть";
				КонецЕсли; 
			КонецЕсли; 
			Если ИдентификаторТипа <> "" Тогда
				КлючПоиска = Новый Структура("ИД", ИдентификаторТипа);
			Иначе
				//КлючПоиска = Новый Структура("Представление, ТипТипа", ирОбщий.ПервыйФрагментЛкс(ПредставлениеТипа, ":"), "Основной");
				КлючПоиска = Новый Структура("Представление", ирОбщий.ПервыйФрагментЛкс(ПредставлениеТипа, ":"));
			КонецЕсли; 
		Иначе
			ЛиНеУчитыватьПодтип = (ЯзыкПрограммы <> 0) И СтруктураТипа.ТипЯзыка <> "ЗначениеВЗапросе";
			ИмяОбщегоТипа = ИмяОбщегоТипаИзТипаЗначенияСМетаданными(КонкрентыйТип, МетаданныеТипа, ЛиНеУчитыватьПодтип);
			СтруктураТипа.Метаданные = МетаданныеТипа;
			КлючПоиска = Новый Структура("Слово, ТипТипа", ИмяОбщегоТипа, "Основной");
		КонецЕсли;
		НайденныеСтроки = ТаблицаОбщихТипов.НайтиСтроки(КлючПоиска);
		Если НайденныеСтроки.Количество() > 0 Тогда
			СтруктураТипа.ИмяОбщегоТипа = НайденныеСтроки[0].Слово;
			Если СтруктураТипа.СтрокаОписания = Неопределено Тогда
				СтруктураТипа.СтрокаОписания = НайденныеСтроки[0];
			КонецЕсли;
		ИначеЕсли Найти(КонкрентыйТип, " ") = 0 Тогда 
			СтруктураТипа.ИмяОбщегоТипа = Строка(КонкрентыйТип);
		Иначе 
			// Например тупиковый устаревший ПолеТабличногоДокументаФормы
			//ирОбщий.СообщитьЛкс("Невозможно восстановить имя типа """ + КонкрентыйТип + """", СтатусСообщения.Важное);
		КонецЕсли;
	КонецЕсли;
	Возврат СтруктураТипа;

КонецФункции

// Наиболее частый тип объекта метаданных. Это лучше чем абстрактный тип "ОбъектМетаданных" без членов.
Функция ИмяОбщегоТипаОбъектаМетаданных() Экспорт
	//Возврат "ОбъектМетаданныхСправочник";
	Возврат "ОбъектМетаданных";
КонецФункции

// Получает таблицу структур типов из описания типов.
//
// Параметры:
//  ОписаниеТипов - ОписаниеТипов - 
//  *ТаблицаТипов - см. НоваяТаблицаТипов(), *Неопределено - существующая таблица.
//
// Возвращаемое значение:
//  см. НоваяТаблицаТипов()
//
Функция ТаблицаТиповИзОписанияТипов(ОписаниеТипов, ТаблицаТипов = Неопределено) Экспорт

	// TODO Заменить на прямой вызов ДобавитьВТаблицуТипов
	Возврат ДобавитьВТаблицуТипов(ТаблицаТипов, ОписаниеТипов);

КонецФункции  

Функция МаксЧислоТиповДляАнализа() Экспорт 
	Возврат 100;
КонецФункции

Функция ТаблицаТиповИзЗначения(Значение, ТаблицаТипов = Неопределено, ЯзыкПрограммы = 0) Экспорт

	Если ТаблицаТипов = Неопределено Тогда
		ТаблицаТипов = НоваяТаблицаТипов();
	КонецЕсли;
	СтруктураТипа = СтруктураТипаИзЗначения(Значение, ЯзыкПрограммы);
	ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
	Возврат ТаблицаТипов;

КонецФункции

// Получает объект по ссылке, кэшируя результат в соответствии.
//
// Параметры:
//  Ссылка       - Ссылка;
//  ПринудительноОбновить - Булево, *Ложь.
//
// Возвращаемое значение:
//  Объект.
//
Функция КэшОбъект(Ссылка, ПринудительноОбновить = Ложь) Экспорт

	ТипСсылки = ТипЗнч(Ссылка);
	Кэш = КэшОбъектов[ТипСсылки];
	Если Кэш = Неопределено Тогда
		Кэш = Новый Соответствие;
		КэшОбъектов[ТипСсылки] = Кэш;
	КонецЕсли;
	Если Не ПринудительноОбновить Тогда
		Результат = Кэш[Ссылка];
	КонецЕсли;
	Если Результат = Неопределено Тогда
		Результат = Ссылка.ПолучитьОбъект();
		Кэш[Ссылка] = Результат;
	КонецЕсли;
	Возврат Результат;

КонецФункции 

// Получает строку конкретного типа.
//
// Параметры:
//  СтруктураТипа - Структура - описание типа.
//
// Возвращаемое значение:
//  Строка - конкрентого типа.
//
Функция ИмяТипаИзСтруктурыТипа(Знач СтруктураТипа, Знач Подробное = Истина) Экспорт
	
	КонкретныйТип = СтруктураТипа.ИмяОбщегоТипа; 
	МаркерРасширенияФормы = "РасширениеФормы";
	Если Лев(КонкретныйТип, СтрДлина(МаркерРасширенияФормы)) = МаркерРасширенияФормы Тогда
		КонкретныйТип = "Форма";
	КонецЕсли;
	Если Подробное Тогда 
		Если КонкретныйТип = "Форма" И ирОбщий.ЛиФормаИлиИмитаторЛкс(СтруктураТипа.Метаданные) Тогда
			КонкретныйТип = КонкретныйТип + "[" + ирОбщий.ПолноеИмяФормыЛкс(СтруктураТипа.Метаданные) + "]";  
		ИначеЕсли КонкретныйТип = "ОбщийМодуль" И ТипЗнч(СтруктураТипа.Метаданные) = Тип("ОбъектМетаданных") Тогда
			КонкретныйТип = КонкретныйТип + "[" + СтруктураТипа.Метаданные.Имя + "]";  
		КонецЕсли;
	КонецЕсли;
	//Если Лев(КонкретныйТип, СтрДлина(МаркерКоллекцииМетаданных)) = МаркерКоллекцииМетаданных Тогда
	//	КонкретныйТип = МаркерКоллекцииМетаданных;
	//КонецЕсли;
	ОбъектМД = СтруктураТипа.Метаданные;
	Если Истина
		И ТипЗнч(ОбъектМД) = Тип("КоллекцияОбъектовМетаданных") 
		И ОбъектМД.Количество() > 0
	Тогда
		ОбъектМД = ОбъектМД[0].Родитель();
	КонецЕсли; 
	ТипМетаданных = ТипЗнч(ОбъектМД);
	Если Истина
		И ТипМетаданных = Тип("ОбъектМетаданных") 
		И Найти(КонкретныйТип, "<") > 0 
	Тогда
		ПолноеИмя = ОбъектМД.ПолноеИмя();
		МассивФрагментов = ирОбщий.СтрРазделитьЛкс(ПолноеИмя);
		Если МассивФрагментов[0] = "ТабличнаяЧасть" Тогда
			// Баг платформы. У внешних метаданных полное имя не включает сам внешний метаобъект
			МассивФрагментов.Вставить(0, "Имя");
			МассивФрагментов.Вставить(0, "");
		КонецЕсли;
		Для Счетчик = 0 По МассивФрагментов.Количество() / 2 - 1 Цикл
			ИмяЭлементаКоллекции = ирОбщий.ТекстМеждуМаркерамиЛкс(КонкретныйТип, "<", ">", Ложь, Истина);
			КонкретныйТип = СтрЗаменить(КонкретныйТип, ИмяЭлементаКоллекции, МассивФрагментов[Счетчик * 2 + 1]);
		КонецЦикла;
	//ИначеЕсли ТипЗнч(СтруктураТипа.Метаданные) = Тип("Соответствие") Тогда
	//	Для Каждого ЭлементВида Из СтруктураТипа.Метаданные Цикл
	//		КонкретныйТип = СтрЗаменить(КонкретныйТип, ЭлементВида.Ключ, ЭлементВида.Значение);
	//	КонецЦикла;
	ИначеЕсли Ложь
		Или КонкретныйТип = "НеизвестныйКонтекст"
		Или КонкретныйТип = "Произвольный"
	Тогда 
		КонкретныйТип = "?";
	КонецЕсли;
	Попытка
		Квалификаторы = СтруктураТипа.Квалификаторы;
	Исключение
		Квалификаторы = Неопределено;
	КонецПопытки; 
	Если Истина
		И Подробное
		И Квалификаторы <> Неопределено
		И ирОбщий.ЛиИмяТипаСКвалификаторамиЛкс(КонкретныйТип)
	Тогда
		ирОбщий.ДобавитьКвалификаторыВПредставлениеТипаЛкс(КонкретныйТип, Тип(КонкретныйТип), СтруктураТипа.Квалификаторы);
	КонецЕсли; 
	Возврат КонкретныйТип;
	
КонецФункции

// Десериализатор структуры типа из неполной сериализации.
//
// Параметры:
//  СтрокаСтруктурыТипа - Строка.
//
// Возвращаемое значение:
// СтруктураТипа - Структура.
//
Функция СтруктураТипаИзСтрокиВнутр(СтрокаСтруктурыТипа) Экспорт

	СтруктураТипа = НоваяСтруктураТипа();
	Если ПустаяСтрока(СтрокаСтруктурыТипа) Тогда
		Возврат СтруктураТипа;
	КонецЕсли;
	Успех = Ложь;
	Попытка
		ОписательТипа = ЗначениеИзСтрокиВнутр(СтрокаСтруктурыТипа);
		Успех = Истина;
	Исключение
		ОписательТипа = НоваяСтруктураТипа();
		ОписательТипа.ИмяОбщегоТипа = "<Ошибка преобразования>";
	КонецПопытки;
	Если Успех Тогда
		СтруктураТипа.ИмяОбщегоТипа = ОписательТипа.ИмяОбщегоТипа;
		Если ТипЗнч(ОписательТипа.Метаданные) = Тип("Строка") Тогда
			СтруктураТипа.Метаданные = ирКэш.ОбъектМДПоПолномуИмениЛкс(ОписательТипа.Метаданные);
		ИначеЕсли ТипЗнч(ОписательТипа.Метаданные) = Тип("ХранилищеЗначения") Тогда
			Поток = Новый ЧтениеXML;
			Поток.УстановитьСтроку(ОписательТипа.Метаданные.Получить());
			// Тут тормоз
			СтруктураТипа.Метаданные = СериализаторXDTO.ПрочитатьXML(Поток);
		Иначе
			СтруктураТипа.Метаданные = ОписательТипа.Метаданные;
		КонецЕсли;
	КонецЕсли; 
	Возврат СтруктураТипа;

КонецФункции // СтруктураТипаВСтрокуВнутр()

// Получает новую структуру типа.
//
// Параметры:
//  ИмяОбщегоТипа	 - Строка - 
// 
// Возвращаемое значение:
//  Структура - :
//     *ИмяОбщегоТипа - Строка
//     *Метаданные
//     *СтрокаОписания - СтрокаТаблицыЗначений
//     *ТипЯзыка - Строка
//     *ВиртуальнаяТаблица - Структура
//
Функция НоваяСтруктураТипа(ИмяОбщегоТипа = "НеизвестныйКонтекст") Экспорт
	// Мультиметка73327878378078
	Возврат Новый Структура("ИмяОбщегоТипа, Метаданные, СтрокаОписания, ТипЯзыка, Конструктор, ВиртуальнаяТаблица, ДополнительныеТипы, ДержательМетаданных, Квалификаторы",
		ИмяОбщегоТипа, Неопределено, Неопределено, "", Ложь, Новый Структура("Выражение, НомерСтроки", "", 0)); 
КонецФункции

Функция НоваяТаблицаТипов() Экспорт
	Если мТаблицаТипов = Неопределено Тогда
		// Мультиметка73327878378078
		мТаблицаТипов = Новый ТаблицаЗначений;
		мТаблицаТипов.Колонки.Добавить("ИмяОбщегоТипа", Новый ОписаниеТипов("Строка"));
		мТаблицаТипов.Колонки.Добавить("Метаданные");
		мТаблицаТипов.Колонки.Добавить("СтрокаОписания"); // СтрокаТаблицыЗначений
		мТаблицаТипов.Колонки.Добавить("ТипЯзыка", Новый ОписаниеТипов("Строка"));
		мТаблицаТипов.Колонки.Добавить("ВиртуальнаяТаблица");
		мТаблицаТипов.Колонки.Добавить("Конструктор", Новый  ОписаниеТипов("Булево"));
		мТаблицаТипов.Колонки.Добавить("ДополнительныеТипы");
		мТаблицаТипов.Колонки.Добавить("ДержательМетаданных");
		мТаблицаТипов.Колонки.Добавить("Квалификаторы");
		мТаблицаТипов.Колонки.Добавить("Детальность");
	КонецЕсли;
	Возврат мТаблицаТипов.Скопировать(); 
КонецФункции

// Добавляет структуру типа в таблицу структур типов с поглощением.
//
// Параметры:
//  ТаблицаПриемник - ТаблицаЗначений - ;
//  ОписаниеТипов - Структура, ТаблицаЗначений, ОписаниеТипов, Массив[Структура] - считаем что внутри этой коллекции типы не пересекаются.
//
Функция ДобавитьВТаблицуТипов(ТаблицаПриемник = Неопределено, Знач ОписаниеТипов, Знач ПередаватьДополнительныеТипы = Ложь, Знач ВытеснятьБезУчетаОписания = Истина) Экспорт 
	
	Если ТаблицаПриемник = Неопределено Тогда
		ТаблицаПриемник = НоваяТаблицаТипов();    
	КонецЕсли;
	Если ОписаниеТипов = Неопределено Тогда
		Возврат ТаблицаПриемник;
	КонецЕсли;
	ТипОписания = ТипЗнч(ОписаниеТипов);
	Если ТипОписания = Тип("ОписаниеТипов") Тогда
		//! ОписаниеТипов=0 // ОписаниеТипов
		ТаблицаИсточник = Новый Массив;
		Типы = ОписаниеТипов.Типы();
		СлишкомМногоТипов = Типы.Количество() > МаксЧислоТиповДляАнализа();
		Для Каждого Тип Из Типы Цикл       
			СтруктураТипа = СтруктураТипаИзКонкретногоТипа(Тип); // Циклическая ссылка СтрокаОписания
			СтруктураТипа.Квалификаторы = ОписаниеТипов;
			СтруктураТипа.Вставить("Детальность");
			ТаблицаИсточник.Добавить(СтруктураТипа);
			Если СлишкомМногоТипов И ТаблицаИсточник.Количество() = 10 Тогда
				Прервать;
			КонецЕсли;
		КонецЦикла;
	ИначеЕсли Истина
		И ТипОписания <> Тип("ТаблицаЗначений") 
		И ТипОписания <> Тип("Массив")
	Тогда
		ТаблицаИсточник = Новый Массив;
		ТаблицаИсточник.Добавить(ОписаниеТипов);
	Иначе
		ТаблицаИсточник = ОписаниеТипов; // см. НоваяТаблицаТипов()
		Если Истина
			И ТипОписания = Тип("ТаблицаЗначений")
			И ТаблицаИсточник.Колонки.Метаданные.Заголовок <> ""
		Тогда
			ТаблицаПриемник.Колонки.Метаданные.Заголовок = ТаблицаИсточник.Колонки.Метаданные.Заголовок; // Флаги
		КонецЕсли;
	КонецЕсли;
	КоличествоТипов = ТаблицаИсточник.Количество();
	Если КоличествоТипов > МаксЧислоТиповДляАнализа() Тогда
		// Для подстраховки. Нужно в вызывающем контексте это контролировать
		Возврат ТаблицаПриемник;
	КонецЕсли;
	НужноВытеснять = КоличествоТипов > 0 И ТаблицаПриемник.Количество() > 0;
	Детальность = Неопределено;
	ИсключаемыеСвойства = Неопределено;
	Если Не ПередаватьДополнительныеТипы Тогда
		ИсключаемыеСвойства = "ДополнительныеТипы";
	КонецЕсли; 
	Если ВытеснятьБезУчетаОписания Тогда
		ИменаПоиска = "ИмяОбщегоТипа";
	Иначе
		ИменаПоиска = "ИмяОбщегоТипа,СтрокаОписания";
	КонецЕсли;
	Для Каждого СтрокаИсточника Из ТаблицаИсточник Цикл
		Если Истина
			//И НужноВытеснять 
			И СтрокаИсточника.ИмяОбщегоТипа = "НеизвестныйКонтекст" 
			И СтрокаИсточника.СтрокаОписания = Неопределено
		Тогда
			Продолжить;
		КонецЕсли;                 
		Если Истина
			И ТипЗнч(СтрокаИсточника) = Тип("Структура") 
			И Не СтрокаИсточника.Свойство("Детальность", Детальность) 
		Тогда 
			СтрокаИсточника.Вставить("Детальность", Неопределено);
		Иначе 
			Детальность = СтрокаИсточника.Детальность;
		КонецЕсли;
		Если Детальность = Неопределено Тогда
			ОбновитьДетальностьСтруктурыТипа(СтрокаИсточника);
		КонецЕсли;
		Если НужноВытеснять Тогда 
			Если Найти(СтрокаИсточника.ИмяОбщегоТипа, "Массив") = 1 Тогда
				ДобавлятьТип = Истина;
				Для Каждого СтрокаПриемника Из ТаблицаПриемник Цикл
					Если Найти(СтрокаПриемника.ИмяОбщегоТипа, "Массив") = 1 Тогда
						ЕстьВложенныеИсточника = Найти(СтрокаИсточника.ИмяОбщегоТипа, "[") > 0;
						ЕстьВложенныеПриемника = Найти(СтрокаПриемника.ИмяОбщегоТипа, "[") > 0;
						Если Истина
							И ЕстьВложенныеИсточника
							И ЕстьВложенныеПриемника
						Тогда
							ТипыЭлементовИсточника = ТипыЭлементовКоллекции(СтрокаИсточника,, Ложь);
							СписокЗначений = Новый СписокЗначений;
							СписокЗначений.ЗагрузитьЗначения(ТипыЭлементовИсточника);
							ТипыЭлементовПриемника = ТипыЭлементовКоллекции(СтрокаПриемника,, Ложь);
							Для Каждого ИмяТипа Из ТипыЭлементовПриемника Цикл
								Если СписокЗначений.НайтиПоЗначению(ИмяТипа) = Неопределено Тогда
									СписокЗначений.Добавить(ИмяТипа);
								КонецЕсли;
							КонецЦикла;
							СписокЗначений.СортироватьПоЗначению();
							СтрокаПриемника.ИмяОбщегоТипа = "Массив[" + ирОбщий.СтрСоединитьЛкс(СписокЗначений.ВыгрузитьЗначения()) + "]";
						ИначеЕсли ЕстьВложенныеИсточника Тогда
							СтрокаПриемника.ИмяОбщегоТипа = СтрокаИсточника.ИмяОбщегоТипа;
						КонецЕсли;
						ДобавлятьТип = Ложь;
						Прервать;
					КонецЕсли;
				КонецЦикла;
				Если Не ДобавлятьТип Тогда
					Прервать;
				КонецЕсли;
			Иначе
				КлючПоиска = Новый Структура(ИменаПоиска);
				ЗаполнитьЗначенияСвойств(КлючПоиска, СтрокаИсточника);
				Найденные = ТаблицаПриемник.НайтиСтроки(КлючПоиска);
				Если СтрокаИсточника.Детальность > 0 Тогда 
					Для Каждого СтрокаПриемника Из ТаблицаПриемник.НайтиСтроки(Новый Структура("Детальность", 0)) Цикл
						ТаблицаПриемник.Удалить(СтрокаПриемника);
					КонецЦикла;
					Если ирОбщий.СтрНачинаетсяСЛкс(СтрокаИсточника.ИмяОбщегоТипа, "РасширениеФормы", Истина) Тогда  // Учитывам регистр для ускорения
						НайденныеФормы = ТаблицаПриемник.НайтиСтроки(Новый Структура("ИмяОбщегоТипа", "Форма"));
						ирОбщий.ДополнитьМассивЛкс(Найденные, НайденныеФормы);
					КонецЕсли;
				КонецЕсли;
				Если Найденные.Количество() > 0 Тогда 
					СтрокаПриемника = Найденные[0];
					ТипМетаданныхИсточника = ТипЗнч(СтрокаИсточника.Метаданные);
					ТипМетаданныхПриемника = ТипЗнч(СтрокаПриемника.Метаданные);
					// Считаем что "Найденные" всегда содержит не более одной строки
					Если Ложь
						Или СтрокаПриемника.Метаданные = СтрокаИсточника.Метаданные
						Или Истина
							И ТипМетаданныхПриемника = Тип("ОбъектМетаданныхКонфигурация") 
							И ТипМетаданныхИсточника = Тип("ОбъектМетаданныхКонфигурация") // Почему то часто равенство значений не выполняется
						Или СтрокаПриемника.Детальность > СтрокаИсточника.Детальность
					Тогда
						Продолжить;
					КонецЕсли;
					Если СтрокаПриемника.Детальность < СтрокаИсточника.Детальность Тогда 
						ТаблицаПриемник.Удалить(СтрокаПриемника);
					Иначе
						// Далее детальности равны
						Если Ложь
							Или ТаблицаПриемник.Количество() > 10
							Или СтрокаПриемника.ИмяОбщегоТипа = "Строка" // Для ускорения вычисления типа результата ИмяМодуляИзСтруктурыТипа()
							Или СтрокаПриемника.ИмяОбщегоТипа = "Число"
							Или СтрокаПриемника.ИмяОбщегоТипа = "Булево"
							Или СтрокаПриемника.ИмяОбщегоТипа = "Тип"
						Тогда
							Продолжить;
						КонецЕсли;
						Если Ложь
							Или (Истина
								И ТипМетаданныхИсточника = Тип("ТаблицаЗначений") 
								И ТипМетаданныхПриемника = Тип("ТаблицаЗначений"))
							Или (Истина
								И ТипМетаданныхИсточника = Тип("ДеревоЗначений") 
								И ТипМетаданныхПриемника = Тип("ДеревоЗначений"))
						Тогда
							ирОбщий.СкопироватьКолонкиКоллекцииЛкс(СтрокаИсточника.Метаданные, СтрокаПриемника.Метаданные);
							Продолжить;
						КонецЕсли;
						Если Истина
							И ТипМетаданныхИсточника = Тип("ТаблицаЗначений") 
							И ТипМетаданныхПриемника = Тип("Структура")
						Тогда
							Для Каждого Колонка Из СтрокаИсточника.Метаданные.Колонки Цикл
								Если ирОбщий.СвойствоСтруктурыЛкс(СтрокаПриемника.Метаданные, Колонка.Имя) = Неопределено Тогда
									ТаблицаТиповКолонки = ТаблицаТиповИзОписанияТипов(Колонка.ТипЗначения);
									Если ТаблицаТиповКолонки.Количество() = 0 Тогда
										ТаблицаТиповКолонки = Неопределено;
									КонецЕсли;
									СтрокаПриемника.Метаданные.Вставить(Колонка.Имя, ТаблицаТиповКолонки);
								КонецЕсли;
							КонецЦикла;
							Продолжить;
						КонецЕсли;
						Если Истина
							И ТипМетаданныхИсточника = Тип("Структура") 
							И ТипМетаданныхПриемника = Тип("Структура")
						Тогда
							Для Каждого КлючИЗначение Из СтрокаИсточника.Метаданные Цикл
								Если ирОбщий.СвойствоСтруктурыЛкс(СтрокаПриемника.Метаданные, КлючИЗначение.Ключ) = Неопределено Тогда
									СтрокаПриемника.Метаданные.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
								КонецЕсли;
							КонецЦикла;
							Продолжить;
						КонецЕсли;
						Если Истина
							И ТипМетаданныхИсточника = Тип("Массив") 
							И ТипМетаданныхПриемника = Тип("Массив")
						Тогда
							ирОбщий.СкопироватьКоллекциюЛкс(СтрокаИсточника.Метаданные, СтрокаПриемника.Метаданные);
							Продолжить;
						КонецЕсли;
					КонецЕсли;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
		ЗаполнитьЗначенияСвойств(ТаблицаПриемник.Добавить(), СтрокаИсточника, , ИсключаемыеСвойства);
	КонецЦикла;
	Возврат ТаблицаПриемник;

КонецФункции 

Функция ОбновитьДетальностьСтруктурыТипа(СтруктураТипа) Экспорт 
	ТипМетаданных = ТипЗнч(СтруктураТипа.Метаданные); 
	ИмяОбщегоТипа = СтруктураТипа.ИмяОбщегоТипа;
	Если Ложь
		Или ИмяОбщегоТипа = "??"
		Или ИмяОбщегоТипа = "НеизвестныйКонтекст"
	Тогда 
		Результат = 0;
	ИначеЕсли Ложь
		Или ИмяОбщегоТипа = "" // Процедура 
		Или ИмяОбщегоТипа = "Произвольный"
		Или ИмяОбщегоТипа = "Неопределено"
	Тогда 
		Результат = 1;
		// Отключил из-за Мультиметка29332671
		//Если ИмяОбщегоТипа = "Неопределено" Тогда
		//	СтруктураТипа.Метаданные = Неопределено; // Чтобы раньше склеивались типы в ДобавитьВТаблицуТипов
		//КонецЕсли;
	ИначеЕсли Ложь
		Или ИмяОбщегоТипа = "Строка"
		Или ИмяОбщегоТипа = "Число"
		Или ИмяОбщегоТипа = "Булево"
		Или ИмяОбщегоТипа = "Дата"
		Или ИмяОбщегоТипа = "Null"
		Или ИмяОбщегоТипа = "Тип"
		//Или ИмяОбщегоТипа = "Примитивный"
	Тогда 
		Если ТипМетаданных = Тип(ИмяОбщегоТипа) Тогда
			Результат = 3;
		Иначе 
			Результат = 2;
			Если Истина
				И ИмяОбщегоТипа = "Строка" 
				И ТипМетаданных = Тип("ТаблицаЗначений") 
			Тогда
				Результат = 5;
			КонецЕсли;
		КонецЕсли;
	ИначеЕсли Ложь
		Или ТипМетаданных = Тип("Неопределено")
		Или ТипМетаданных = Тип("ОбъектМетаданныхКонфигурация") 
		Или ТипМетаданных = Тип("КоллекцияОбъектовМетаданных")
		Или ТипМетаданных = Тип("ОбщийМодуль") // Пока платформа не позволяет узнать его имя
	Тогда
		Результат = 3;
	ИначеЕсли ТипМетаданных = Тип("ОбъектМетаданных") Тогда
		Результат = 4;
	ИначеЕсли Ложь 
		#Если Клиент Тогда
		Или ТипМетаданных = Тип("Форма") 
		Или ТипМетаданных = Тип("УправляемаяФорма")  
		#КонецЕсли
	Тогда
		Результат = 6;
	ИначеЕсли ТипМетаданных = Тип("ПостроительЗапроса") Тогда
		Результат = 7;
	Иначе
		Результат = 5;
	КонецЕсли; 
	СтруктураТипа.Детальность = Результат;
	Возврат Результат;
КонецФункции

//.
// Параметры:
//    ТаблицаТипов - ТаблицаЗначений - 
//    МинДетальность - Число - минимальное достаточное значение детальности
// Возвращаемое значение:
//    Булево - 
Функция ЛиДетальностьТиповДостаточна(ТаблицаТипов, Знач МинДетальность = 3, Знач ВыбратьЛучшийТип = Ложь, выхЛучшийТип = Неопределено, Знач УчитыватьПримитивные = Истина) Экспорт
	Если Ложь
		Или ТаблицаТипов = Неопределено
		Или ТаблицаТипов.Количество() = 0 
	Тогда
		Возврат Ложь;
	КонецЕсли;
	Счетчик = 1;        
	МинДетальность = МинДетальность - 1;
	Для Индекс = 1 - ТаблицаТипов.Количество() По 0 Цикл // Обратный обход
		СтрокаТипа = ТаблицаТипов[-Индекс];
		Если Ложь
			Или СтрокаТипа.Детальность > МинДетальность
			Или (Истина
				И УчитыватьПримитивные
				И (Ложь
					Или СтрокаТипа.ИмяОбщегоТипа = "Строка" 
					Или СтрокаТипа.ИмяОбщегоТипа = "Число"
					Или СтрокаТипа.ИмяОбщегоТипа = "Булево" // почему закомментировал?
					))
		Тогда
			выхЛучшийТип = СтрокаТипа;
			МинДетальность = СтрокаТипа.Детальность; 
			Если Не ВыбратьЛучшийТип Тогда
				Прервать;
			КонецЕсли;
		КонецЕсли;
		Если Счетчик = 3 Тогда
			// Проверяем не больше 3-х, т.к. бесполезных типов обычно очень мало указывают в описании, например Неопределено, Null
			Прервать;
		КонецЕсли;
		Счетчик = Счетчик + 1;
	КонецЦикла;
	Возврат выхЛучшийТип <> Неопределено;
КонецФункции

// Получает массив структур типов из строки допустимых типов.
//
// Параметры:
//  ДопустимыеТипы - Строка;
//  *ШаблонСтруктурыТипа - Структура, *Неопределено - содержит значения по умолчанию для новой структуры типа.
//
Функция ТаблицаТиповИзДопустимыхТипов(ДопустимыеТипы, ШаблонСтруктурыТипа = Неопределено) Экспорт 

	ТаблицаТипов = НоваяТаблицаТипов();
	Если ПустаяСтрока(ДопустимыеТипы) Тогда
		Возврат ТаблицаТипов;
	КонецЕсли;
	МассивСериализованныхТипов = ирОбщий.СтрРазделитьЛкс(ДопустимыеТипы, ";");
	Для Каждого СериализованныйТип Из МассивСериализованныхТипов Цикл
		СтруктураТипа = СтруктураТипаИзСтрокиВнутр(СериализованныйТип);
		Если ШаблонСтруктурыТипа <> Неопределено Тогда
			ЗаполнитьЗначенияСвойств(СтруктураТипа, ШаблонСтруктурыТипа);
		КонецЕсли;
		ДобавитьВТаблицуТипов(ТаблицаТипов, СтруктураТипа);
	КонецЦикла;
	Возврат ТаблицаТипов;

КонецФункции

// Получает описание типов из допустимых типов.
//
// Параметры:
//  ДопустимыеТипы - Строка;
//  ТипЗначенияЭУ  - ОписаниеТипов - все возможные типы из элемента управления.
//
// Возвращаемое значение:
//  ОписаниеТипов.
//
Функция ОписаниеТиповИзДопустимыхТипов(ДопустимыеТипы, ТипЗначенияЭУ = Неопределено) Экспорт

	ТаблицаТипов = ТаблицаТиповИзДопустимыхТипов(ДопустимыеТипы);
	ОписаниеТипов = ОписаниеТиповИзТаблицыТипов(ТаблицаТипов, ТипЗначенияЭУ);
	Возврат ОписаниеТипов;

КонецФункции

// Получает описание типов из таблицы структур типов.
//
// Параметры:
//  ДопустимыеТипы - Строка;
//  ТипЗначенияЭУ  - ОписаниеТипов - все возможные типы из элемента управления.
//
// Возвращаемое значение:
//  ОписаниеТипов.
//
Функция ОписаниеТиповИзТаблицыТипов(ТаблицаТипов, ТипЗначенияЭУ = Неопределено) Экспорт

	Если ТаблицаТипов = Неопределено Тогда
		Возврат Новый ОписаниеТипов;
	КонецЕсли; 
	МассивТипов = Новый Массив;
	Для Каждого СтруктураТипа Из ТаблицаТипов Цикл
		СтрокаКонкретногоТипа = ИмяТипаИзСтруктурыТипа(СтруктураТипа, Ложь);
		Попытка
			ТекущийТип = Тип(СтрокаКонкретногоТипа);
		Исключение
			Продолжить;
		КонецПопытки;
		ТипМетаданных = ТипЗнч(СтруктураТипа.Метаданные);
		Если ТипМетаданных = Тип("КвалификаторыСтроки") Тогда
			КвалификаторыСтроки = СтруктураТипа.Метаданные;
		ИначеЕсли ТипМетаданных = Тип("КвалификаторыЧисла") Тогда
			КвалификаторыЧисла = СтруктураТипа.Метаданные;
		ИначеЕсли ТипМетаданных = Тип("КвалификаторыДаты") Тогда
			КвалификаторыДаты = СтруктураТипа.Метаданные;
		КонецЕсли; 
		Если ТипЗначенияЭУ <> Неопределено Тогда
			Если Не ТипЗначенияЭУ.СодержитТип(ТекущийТип) Тогда
				Продолжить;
			КонецЕсли;
		КонецЕсли;
		МассивТипов.Добавить(ТекущийТип);
	КонецЦикла;
	ОписаниеТипов = Новый ОписаниеТипов(МассивТипов, КвалификаторыЧисла, КвалификаторыСтроки, КвалификаторыСтроки);
	Возврат ОписаниеТипов; 

КонецФункции

// Получает строку типа метаобъектов по единственному или множественному числу.
//
// Параметры:
//  *Единственное - Строка, *Неопределено - единственное число типа;
//  *Множественное - Строка, *Неопределено - множественное число типа.
//  *Категория  - Число, *Неопределено.
//
// Возвращаемое значение:
//  СтрокаТаблицыЗначений - найденная строка типа;
//  Неопределено - корневой тип не найден.
//
Функция ОписаниеТипаМетаОбъектов(Знач Единственное = Неопределено, Знач Множественное = Неопределено, Категория = Неопределено) Экспорт
	
	СтруктураПоиска = Новый Структура;
	Если Категория <> Неопределено Тогда
		СтруктураПоиска.Вставить("Категория", Категория);
	КонецЕсли;
	Если Единственное <> Неопределено Тогда
		СтруктураПоиска.Вставить("НЕдинственное", НРег(Единственное));
	КонецЕсли;  
	Если Множественное <> Неопределено Тогда 
		СтруктураПоиска.Вставить("НМножественное", НРег(Множественное));
	КонецЕсли;
	НайденныеСтроки = ТаблицаТиповМетаОбъектов.НайтиСтроки(СтруктураПоиска);
	Если НайденныеСтроки.Количество() = 0 Тогда
		Результат = Неопределено;
	Иначе
		Результат = НайденныеСтроки[0];
	КонецЕсли;
	Возврат Результат;

КонецФункции

Процедура ПроверитьЗагрузитьКэшМДСеанса()
	ПереданныйКэш = ирКэш.ПараметрыСеансаЛкс().ПереданныйКэш;
	КэшМДСеанса = Неопределено;
	Если ЗначениеЗаполнено(ПереданныйКэш) Тогда
		КэшМДСеанса = ПолучитьИзВременногоХранилища(ПереданныйКэш);
	КонецЕсли;
	Если КэшМДСеанса = Неопределено Тогда
		СостояниеРасчета = ирКэш.СостояниеПодготовкиКэшМДСеансаЛкс();
		Если СостояниеРасчета <> Неопределено Тогда
			ФоновоеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(СостояниеРасчета.ИдентификаторЗадания);
		КонецЕсли; 
		Если ФоновоеЗадание <> Неопределено Тогда 
			Если ФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.Активно Тогда 
				ирОбщий.ОжидатьЗавершенияФоновойОперацииЛкс(ФоновоеЗадание);
			КонецЕсли; 
			Если ФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.Завершено Тогда 
				КэшМДСеанса = ирОбщий.ПрочитатьРезультатФоновогоЗаданияЛкс(СостояниеРасчета.АдресРезультата, СостояниеРасчета.ФормаРезультата);
				Если КэшМДСеанса = Null Тогда
					КэшМДСеанса = Неопределено;
				КонецЕсли;
			КонецЕсли; 
		КонецЕсли; 
	КонецЕсли; 
	Если КэшМДСеанса <> Неопределено Тогда
		#Если Сервер И Не Сервер Тогда
			КэшМДСеанса = Новый Структура;
		#КонецЕсли
		мТаблицаВсехТаблицБД = КэшМДСеанса.ТаблицаВсехТаблицБД;
		Если КэшМДСеанса.Свойство("ДеревоОбъектовМД") Тогда
			мДеревоОбъектовМД = КэшМДСеанса.ДеревоОбъектовМД;
		КонецЕсли; 
		Возврат;
	КонецЕсли; 

КонецПроцедуры

Функция ДеревоОбъектовМД() Экспорт
	ПроверитьЗагрузитьКэшМДСеанса();
	Если мДеревоОбъектовМД <> Неопределено Тогда
		#Если Сервер И Не Сервер Тогда
			мДеревоОбъектовМД = Новый ДеревоЗначений;
		#КонецЕсли
		#Если Клиент Тогда 
			Если мДеревоОбъектовМД.Колонки.Найти("КоличествоСтрок") = Неопределено Тогда
				мДеревоОбъектовМД.Колонки.Добавить("КоличествоСтрок", Новый ОписаниеТипов("Строка, Число"));
			КонецЕсли; 
		#КонецЕсли 
		Возврат мДеревоОбъектовМД;
	КонецЕсли; 
	ДеревоОбъектовМД = Новый ДеревоЗначений;
	ДеревоОбъектовМД.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
	ДеревоОбъектовМД.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
	ДеревоОбъектовМД.Колонки.Добавить("ПолноеИмяОбъекта", Новый ОписаниеТипов("Строка"));
	ДеревоОбъектовМД.Колонки.Добавить("ИндексКартинки", Новый ОписаниеТипов("Число"));
	ДеревоОбъектовМД.Колонки.Добавить("ЕстьДоступ", Новый ОписаниеТипов("Булево"));
	ДеревоОбъектовМД.Колонки.Добавить("ПравоПросмотр", Новый ОписаниеТипов("Булево"));
	ДеревоОбъектовМД.Колонки.Добавить("ТипТаблицы", Новый ОписаниеТипов("Строка"));
	АнализаторКода = ирОбщий.НовыйАнализаторКодаЛкс();
	#Если Сервер И Не Сервер Тогда
		АнализаторКода = Обработки.ирКлсПолеТекстаПрограммы.Создать();
	#КонецЕсли
	мТаблицаВсехТаблицБД = АнализаторКода.ДоступныеТаблицы.ВыгрузитьКолонки();
	мТаблицаВсехТаблицБД.Колонки.Удалить("ПородившийЗапрос"); // Для экономии памяти
	мТаблицаВсехТаблицБД.Колонки.Добавить("ТипСсылки");
	//ТаблицаВсехТаблицБД.Колонки.Добавить("СтруктураКлюча");
	Если Метаданные.Константы.Количество() > 0 Тогда
		ирОбщий.ДобавитьДоступнуюТаблицуБДЛкс(мТаблицаВсехТаблицБД, ирОбщий.ПеревестиСтроку("Константы"),, "Константы"); // Мультиметка0012741388 опираемся на то, что эта таблица БД идет первой в списке
	КонецЕсли; 
	КоллекцияКорневыхТипов = Новый Массив;
	СтрокиМетаОбъектов = ТаблицаТиповМетаОбъектов.НайтиСтроки(Новый Структура("Категория", 0));
	Для Каждого СтрокаТаблицыМетаОбъектов Из СтрокиМетаОбъектов Цикл
		КоллекцияКорневыхТипов.Добавить(СтрокаТаблицыМетаОбъектов.Единственное);
	КонецЦикла;
	Если ирКэш.ДоступныВнешниеИсточникДанныхЛкс() Тогда
		Для Каждого МетаВнешнийИсточникДанных Из Метаданные.ВнешниеИсточникиДанных Цикл
			КоллекцияКорневыхТипов.Добавить(МетаВнешнийИсточникДанных.ПолноеИмя());
		КонецЦикла; 
	КонецЕсли; 
	КоллекцияКорневыхТипов.Добавить("Отчет");
	КоллекцияКорневыхТипов.Добавить("Обработка");
	КоллекцияКорневыхТипов.Добавить("Роль");
	КоллекцияКорневыхТипов.Добавить("Подсистема");
	КоллекцияКорневыхТипов.Добавить("РегламентноеЗадание");
	КоллекцияКорневыхТипов.Добавить("HTTPСервис");
	КоллекцияКорневыхТипов.Добавить("WebСервис");
	КоллекцияКорневыхТипов.Добавить("ОбщаяКоманда");
	ИмяДвиженияССубконто = ирОбщий.ПеревестиСтроку("ДвиженияССубконто");
	ИмяГраницы = ирОбщий.ПеревестиСтроку("Границы");
	ИмяЗадачиПоИсполнителю = ирОбщий.ПеревестиСтроку("ЗадачиПоИсполнителю");
	ИмяКонстанта = ирОбщий.ПеревестиСтроку("Константа");
	ИмяОбороты = ирОбщий.ПеревестиСтроку("Обороты");
	ИмяОборотыДтКт = ирОбщий.ПеревестиСтроку("ОборотыДтКт");
	ИмяОстатки = ирОбщий.ПеревестиСтроку("Остатки");
	ИмяОстаткиИОбороты = ирОбщий.ПеревестиСтроку("ОстаткиИОбороты");
	ИмяСрезПервых = ирОбщий.ПеревестиСтроку("СрезПервых");
	ИмяСрезПоследних = ирОбщий.ПеревестиСтроку("СрезПоследних");
	ИмяСубконто = ирОбщий.ПеревестиСтроку("Субконто");
	ИмяТабличнаяЧасть = ирОбщий.ПеревестиСтроку("ТабличнаяЧасть");
	ИмяТочки = ирОбщий.ПеревестиСтроку("Точки");
	ИндексКартинкиТЧ = мОписаниеТипаМДТабличнаяЧасть.ИндексКартинкиЕдинственное;
	ИндикаторТиповМД = ирОбщий.ПолучитьИндикаторПроцессаЛкс(КоллекцияКорневыхТипов.Количество(), "Анализ конфигурации");
	Для Каждого КорневойТип Из КоллекцияКорневыхТипов Цикл
		ирОбщий.ОбработатьИндикаторЛкс(ИндикаторТиповМД);
		ОписаниеКорневогоТипа = ОписаниеТипаМетаОбъектов(КорневойТип);
		Если ОписаниеКорневогоТипа = Неопределено Тогда
			Если Найти(КорневойТип, ".") = 0 Тогда
				// В текущей версии платформы нет поддержки такого типа метаданных
				Продолжить;
			КонецЕсли; 
			// Внешний источник данных
			ОписаниеКорневогоТипа = мОписаниеТипаМДВнешнийИсточникДанных;
			ОбъектМДКорневогоТипа = ирКэш.ОбъектМДПоПолномуИмениЛкс(КорневойТип);
			МножественноеКорневогоТипа = КорневойТип;
			ЕдинственноеКорневогоТипа = ОбъектМДКорневогоТипа.Имя;
			ПредставлениеКатегории = ОбъектМДКорневогоТипа.Представление();
			ЕстьДоступ = ПравоДоступа("Использование", ОбъектМДКорневогоТипа);
			СхемаТаблиц = ОбъектМДКорневогоТипа.Имя;
			ТипТаблицы = "Внешняя";
			КоллекцияМетаОбъектов = ОбъектМДКорневогоТипа.Таблицы;
			ЕстьТаблицаБД = Истина;
		Иначе
			МножественноеКорневогоТипа = ОписаниеКорневогоТипа.Множественное;
			ЕдинственноеКорневогоТипа = ОписаниеКорневогоТипа.Единственное;
			ПредставлениеКатегории = ирОбщий.ПредставлениеИзИдентификатораЛкс(МножественноеКорневогоТипа);
			ЕстьДоступ = Истина;
			СхемаТаблиц = "";
			//Если КорневойТип = "КритерийОтбора" Тогда
			//	ТипТаблицы = "ВиртуальнаяТаблица";
			//Иначе
				ТипТаблицы = КорневойТип;
			//КонецЕсли; 
			Если КорневойТип = "Перерасчет" Тогда 
				КоллекцияМетаОбъектов = Новый Массив;
				Для Каждого МетаРегистрРасчета Из Метаданные.РегистрыРасчета Цикл
					Для Каждого Перерасчет Из МетаРегистрРасчета.Перерасчеты Цикл
						КоллекцияМетаОбъектов.Добавить(Перерасчет);
					КонецЦикла;
				КонецЦикла;
			Иначе
				КоллекцияМетаОбъектов = Метаданные[МножественноеКорневогоТипа];
			КонецЕсли; 
			ЕстьТаблицаБД = Истина
				И (Ложь
					Или КорневойТип <> "Константа"
					Или ирКэш.ДоступныТаблицыКонстантЛкс())
				И (Ложь
					Или КорневойТип = "Константа"
					Или КорневойТип = "КритерийОтбора"
					Или КорневойТип = "ЖурналДокументов"
					Или ирОбщий.ЛиКорневойТипПеречисленияЛкс(КорневойТип)
					Или ирОбщий.ЛиКорневойТипСсылочногоОбъектаБДЛкс(КорневойТип)
					Или ирОбщий.ЛиКорневойТипРегистраБДЛкс(КорневойТип)
					Или ирОбщий.ЛиКорневойТипПоследовательностиЛкс(КорневойТип));
		КонецЕсли; 
		Если КоллекцияМетаОбъектов.Количество() = 0 Тогда
			Продолжить;
		КонецЕсли;
		СтрокаТипаМетаданных = ДеревоОбъектовМД.Строки.Добавить();
		СтрокаТипаМетаданных.Представление = ПредставлениеКатегории;
		СтрокаТипаМетаданных.Имя = ЕдинственноеКорневогоТипа;
		СтрокаТипаМетаданных.ПолноеИмяОбъекта = МножественноеКорневогоТипа;
		СтрокаТипаМетаданных.ИндексКартинки = ОписаниеКорневогоТипа.ИндексКартинкиМножественное;
		СтрокаТипаМетаданных.ЕстьДоступ = ЕстьДоступ;
		ЛиКорневойТипОбъектаСТабличнымиЧастями = ирОбщий.ЛиКорневойТипСсылочногоОбъектаБДЛкс(КорневойТип);
		ИндикаторОбъектовМД = ирОбщий.ПолучитьИндикаторПроцессаЛкс(КоллекцияМетаОбъектов.Количество(), "Анализ " + КорневойТип);
		Для Каждого ОбъектМД Из КоллекцияМетаОбъектов Цикл
			#Если Сервер И Не Сервер Тогда
				ОбъектМД = Метаданные.Справочники.ирАлгоритмы;
			#КонецЕсли
			ирОбщий.ОбработатьИндикаторЛкс(ИндикаторОбъектовМД);
			ПолноеИмяМД = ОбъектМД.ПолноеИмя();
			ПредставлениеМД = ОбъектМД.Представление();
			ПолноеИмяТаблицыБД = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмяМД,, Ложь);
			ФрагментыИмениТаблицы = ирОбщий.СтрРазделитьЛкс(ПолноеИмяТаблицыБД);
			ИмяОбъектаМД = ОбъектМД.Имя;
			Если КорневойТип = "Перерасчет" Тогда
				МетаРегистрРасчета = ОбъектМД.Родитель();
				ИмяОбъектаМД = МетаРегистрРасчета.Имя + "." + ИмяОбъектаМД;
				ПредставлениеМД = МетаРегистрРасчета.Представление() + "." + ПредставлениеМД;
			КонецЕсли;
			СтрокаОбъектаМД = ДобавитьСтрокуДереваМД(СтрокаТипаМетаданных, ПолноеИмяТаблицыБД, ИмяОбъектаМД, ПредставлениеМД, ТипТаблицы, ОписаниеКорневогоТипа.ИндексКартинкиЕдинственное, 
				ЕстьТаблицаБД, мТаблицаВсехТаблицБД, ПолноеИмяМД, ОбъектМД.Имя, ПредставлениеМД, СхемаТаблиц, ОбъектМД,, ФрагментыИмениТаблицы);
			Попытка
				СтрокаОбъектаМД.ПравоПросмотр = ПравоДоступа("Просмотр", ОбъектМД);
			Исключение
				СтрокаОбъектаМД.ПравоПросмотр = Истина;
			КонецПопытки; 
			Если ЛиКорневойТипОбъектаСТабличнымиЧастями Тогда
				СтруктураТЧ = ирОбщий.ТабличныеЧастиОбъектаЛкс(ОбъектМД, ФрагментыИмениТаблицы);
				Для Каждого КлючИЗначение Из СтруктураТЧ Цикл
					СтрокаТЧВДереве = ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + КлючИЗначение.Ключ, КлючИЗначение.Ключ, КлючИЗначение.Значение, "ТабличнаяЧасть", ИндексКартинкиТЧ,
						ЕстьТаблицаБД, мТаблицаВсехТаблицБД, ПолноеИмяМД + "." + ИмяТабличнаяЧасть + "." + КлючИЗначение.Ключ,, ПредставлениеМД + "." + КлючИЗначение.Значение,, ОбъектМД);
					МетаТЧ = ОбъектМД.ТабличныеЧасти.Найти(КлючИЗначение.Ключ);
					Если МетаТЧ <> Неопределено Тогда
						СтрокаТЧВДереве.ПравоПросмотр = ПравоДоступа("Просмотр", МетаТЧ);
					КонецЕсли; 
				КонецЦикла;
				Если КорневойТип = "БизнесПроцесс" Тогда 
					//! ОбъектМД = 0 // ОбъектМетаданныхБизнесПроцесс
					ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяТочки, "Точки", "Точки", "Точки", ИндексКартинкиТЧ,
						ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Точки",, ОбъектМД);
				КонецЕсли; 
				Если КорневойТип = "Задача" Тогда 
					//! ОбъектМД = 0 // ОбъектМетаданныхЗадача
					Если ОбъектМД.Адресация <> Неопределено Тогда
						ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяЗадачиПоИсполнителю, "ЗадачиПоИсполнителю", "Задачи по исполнителю", "ВиртуальнаяТаблица", ИндексКартинкиТЧ, 
							ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Задачи по исполнителю",, ОбъектМД, 1);
					КонецЕсли; 
				КонецЕсли; 
			КонецЕсли; 
			Если КорневойТип = "РегистрСведений" Тогда 
				//! ОбъектМД = 0 // ОбъектМетаданныхРегистрСведений
				Если ОбъектМД.ПериодичностьРегистраСведений <> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический Тогда
					ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяСрезПоследних, "СрезПоследних", "срез последних", "ВиртуальнаяТаблица", ИндексКартинкиТЧ,
						ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Срез последних",, ОбъектМД, 1); 
					ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяСрезПервых,    "СрезПервых", "срез первых", "ВиртуальнаяТаблица", ИндексКартинкиТЧ,
						ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Срез первых",, ОбъектМД, 1); 
				КонецЕсли;
			ИначеЕсли КорневойТип = "РегистрНакопления" Тогда 
				//! ОбъектМД = 0 // ОбъектМетаданныхРегистрНакопления
				ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяОбороты, "Обороты", "Обороты", "ВиртуальнаяТаблица", ИндексКартинкиТЧ, 
					ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Обороты",, ОбъектМД, 3);  
				Если ОбъектМД.ВидРегистра = Метаданные.СвойстваОбъектов.ВидРегистраНакопления.Остатки Тогда
					ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяОстатки,         "Остатки", "Остатки", "ВиртуальнаяТаблица", ИндексКартинкиТЧ, 
						ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Остатки",, ОбъектМД, 1);  
					ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяОстаткиИОбороты, "ОстаткиИОбороты", "Остатки и обороты", "ВиртуальнаяТаблица", ИндексКартинкиТЧ,
						ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Остатки и обороты",, ОбъектМД, 4);  
				КонецЕсли;
			ИначеЕсли КорневойТип = "РегистрБухгалтерии" Тогда 
				//! ОбъектМД = 0 // ОбъектМетаданныхРегистрБухгалтерии
				ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяОбороты,           "Обороты", "Обороты", "ВиртуальнаяТаблица", ИндексКартинкиТЧ,
					ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Обороты",, ОбъектМД, 5);  
				ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяОстатки,           "Остатки", "Остатки", "ВиртуальнаяТаблица", ИндексКартинкиТЧ,
					ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Остатки",, ОбъектМД, 3);  
				ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяОстаткиИОбороты,   "ОстаткиИОбороты", "Остатки и обороты", "ВиртуальнаяТаблица", ИндексКартинкиТЧ,
					ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Остатки и обороты",, ОбъектМД, 6);  
				ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяДвиженияССубконто, "ДвиженияССубконто", "Движения с субконто", "ДвиженияССубконто", ИндексКартинкиТЧ,
					ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Движения с субконто",, ОбъектМД, 2);  
				Если ОбъектМД.ПланСчетов.МаксКоличествоСубконто > 0 Тогда
					ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяСубконто, "Субконто", "Субконто", "Субконто", ИндексКартинкиТЧ,
						ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Субконто",, ОбъектМД);
				КонецЕсли; 
				Если ОбъектМД.Корреспонденция Тогда
					ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяОборотыДтКт, "ОборотыДтКт", "Обороты Дт Кт", "ВиртуальнаяТаблица", ИндексКартинкиТЧ,
						ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Обороты Дт Кт",, ОбъектМД, 7);
				КонецЕсли;
			ИначеЕсли КорневойТип = "Последовательность" Тогда 
				//! ОбъектМД = 0 // ОбъектМетаданныхПоследовательность
				ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ПолноеИмяМД + "." + ИмяГраницы, "Границы", "Границы", "ВиртуальнаяТаблица", ИндексКартинкиТЧ,
					ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Границы",, ОбъектМД);  
			КонецЕсли;
			Если ирОбщий.ЕстьТаблицаИзмененийОбъектаМетаданных(ОбъектМД) Тогда
				ДобавитьСтрокуДереваМД(СтрокаОбъектаМД, ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмяМД, Истина, Ложь), "Изменения", "Изменения", "Изменения", ИндексКартинкиТЧ,
					ЕстьТаблицаБД, мТаблицаВсехТаблицБД,,, ПредставлениеМД + "." + "Изменения",, ОбъектМД);
			КонецЕсли;
		КонецЦикла;
		ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
		Если СтрокаТипаМетаданных.Строки.Количество() = 0 Тогда
			ДеревоОбъектовМД.Строки.Удалить(СтрокаТипаМетаданных);
		КонецЕсли; 
	КонецЦикла;
	ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
	мТаблицаВсехТаблицБД.Индексы.Добавить("НПолноеИмя");
	//мТаблицаВсехТаблицБД.Сортировать("НПолноеИмя"); // Вроде бы сортировка хранения уже не используется
	мДеревоОбъектовМД = ДеревоОбъектовМД;
	Возврат мДеревоОбъектовМД;
	
КонецФункции

Функция ДобавитьСтрокуДереваМД(СтрокаРодителяМД, ПолноеИмяТаблицы, Имя, Представление, ТипТаблицы = "", ИндексКартинки = 0, ЕстьТаблицаБД = Ложь, мТаблицаВсехТаблицБД = Неопределено,
	ПолноеИмяМД ="", ИмяТаблицы = "", ПредставлениеТаблицы = "", СхемаТаблицы = "", ОбъектМД = Неопределено, ИндексПараметраОтбора = Неопределено, ФрагментыИмениТаблицы = Неопределено) 
	
	ДочерняяТаблица = СтрокаРодителяМД.Строки.Добавить();
	ДочерняяТаблица.Имя = Имя;
	ДочерняяТаблица.Представление = Представление;
	ДочерняяТаблица.ПолноеИмяОбъекта = ПолноеИмяТаблицы;
	ДочерняяТаблица.ИндексКартинки = ИндексКартинки;
	ДочерняяТаблица.ПравоПросмотр = СтрокаРодителяМД.ПравоПросмотр;
	ДочерняяТаблица.ТипТаблицы = ТипТаблицы;
	Если ЕстьТаблицаБД Тогда
		ОписаниеТаблицы = ирОбщий.ДобавитьДоступнуюТаблицуБДЛкс(мТаблицаВсехТаблицБД, ПолноеИмяТаблицы, ПолноеИмяМД, ТипТаблицы, ИмяТаблицы, ПредставлениеТаблицы, СхемаТаблицы,, ОбъектМД,
			ИндексПараметраОтбора, ФрагментыИмениТаблицы);
		ДочерняяТаблица.ЕстьДоступ = ОписаниеТаблицы.ЕстьДоступ;
	Иначе
		ДочерняяТаблица.ЕстьДоступ = СтрокаРодителяМД.ЕстьДоступ;
	КонецЕсли; 
	Возврат ДочерняяТаблица;
	
КонецФункции

Функция ТаблицаВсехТаблицБД() Экспорт 
	ПроверитьЗагрузитьКэшМДСеанса();
	Если мТаблицаВсехТаблицБД <> Неопределено Тогда
		Возврат мТаблицаВсехТаблицБД;
	КонецЕсли; 
	ДеревоОбъектовМД();
	Возврат мТаблицаВсехТаблицБД;
КонецФункции
	
// Проверяет общий тип на агрегатность.
//
// Параметры:
//  ИмяОбщегоТипа - Строка;
//  *ЯзыкПрограммы - *Число, 0.
//
// Возвращаемое значение:
//  Булево.
//
Функция ЭтоАгрегатныйОбщийТип(Знач ИмяОбщегоТипа, Знач ЯзыкПрограммы = 0) Экспорт 

	Если ИмяОбщегоТипа = "" Тогда
		Возврат Ложь;
	КонецЕсли;
	ИмяОбщегоТипа = ирОбщий.ПервыйФрагментЛкс(ИмяОбщегоТипа, "[");
	СтруктураКлюча = Новый Структура("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка", ИмяОбщегоТипа, ЯзыкПрограммы, "");  // 2021 добавил ТипЯзыка для попадания в индекс
	Если Ложь
		Или ирОбщий.СтрокиРавныЛкс(ИмяОбщегоТипа, "COMОбъект")
		Или (Истина
			И Найти(ИмяОбщегоТипа, " {") = 0 // подробный COM 
			И ТаблицаКонтекстов.НайтиСтроки(СтруктураКлюча).Количество() = 0
			И ТаблицаШаблоновКонтекстов.НайтиСтроки(СтруктураКлюча).Количество() = 0
			)
	Тогда
		Результат = Ложь;
	Иначе
		Результат = Истина;
	КонецЕсли;
	Возврат Результат;

КонецФункции

Функция БазовыйФайлРедактораJSON() Экспорт 
	Если БазовыйФайлРедактораJSON = Неопределено Тогда
		БазовыйКаталог = КаталогВременныхФайлов();
		КаталогКомпоненты = "JSONEditor";
		ДвоичныеДанные = ПолучитьМакет("JSONEditor");
		Чтение = Вычислить("Новый ЧтениеДанных(ДвоичныеДанные)"); // 8.3.9+
		Файл = Новый ЧтениеZipФайла(Чтение.ИсходныйПоток());
		Файл.ИзвлечьВсе(БазовыйКаталог + КаталогКомпоненты);
		БазовыйФайлРедактораJSON = БазовыйКаталог + КаталогКомпоненты + ирОбщий.РазделительПутиКФайлуЛкс() + "index.html";
	КонецЕсли; 
	Возврат БазовыйФайлРедактораJSON;
КонецФункции

Функция БазовыйФайлРедактораКода() Экспорт 
	Если БазовыйФайлРедактораКода = Неопределено Тогда
		БазовыйКаталог = КаталогВременныхФайлов();
		КаталогКомпоненты = "MonacoEditor";
		ДвоичныеДанные = ПолучитьМакет("MonacoEditor");
		Чтение = Вычислить("Новый ЧтениеДанных(ДвоичныеДанные)"); // 8.3.9+
		Файл = Новый ЧтениеZipФайла(Чтение.ИсходныйПоток());
		Файл.ИзвлечьВсе(БазовыйКаталог + КаталогКомпоненты);
		ИмяФайла = БазовыйКаталог + КаталогКомпоненты + ирОбщий.РазделительПутиКФайлуЛкс() + "editor.js";
		ТекстовыйДокумент = Новый ТекстовыйДокумент;
		ТекстовыйДокумент.Прочитать(ИмяФайла, КодировкаТекста.UTF8);
		ТекстФайла = ТекстовыйДокумент.ПолучитьТекст();
		ТекстФайла = ирОбщий.СтрЗаменитьЛкс(ТекстФайла, "customOptions: true",
			", lineHeight: 15" 
			", suggestFontSize: 13, suggestLineHeight: 15" 
			, Истина);
		ТекстовыйДокумент.УстановитьТекст(ТекстФайла);
		ТекстовыйДокумент.Записать(ИмяФайла);
		//ИмяФайла = БазовыйКаталог + КаталогКомпоненты + ирОбщий.РазделительПутиКФайлуЛкс() + "decorations.css";
		//ТекстовыйДокумент = Новый ТекстовыйДокумент;
		//ТекстовыйДокумент.Прочитать(ИмяФайла);
		//ТекстовыйДокумент.ДобавитьСтроку("body {overflow: hidden;}");
		//// Цвета статусной строки
		//ТекстовыйДокумент.ДобавитьСтроку("
		//|.statusbar-widget {
		//|	background: #c2dfef;
		//|	color: #000;
		//|}");
		//// Ширина списка автодополнения
		//ТекстовыйДокумент.ДобавитьСтроку("
		//|.monaco-editor .suggest-widget {
		//|	width: 500px;
		//|}");
		//// Ширина списка автодополнения вместе с окном детальной инфы
		//ТекстовыйДокумент.ДобавитьСтроку("
		//|.monaco-editor .suggest-widget.docs-side {
		//|	width: 1000px;
		//|}");
		//ТекстовыйДокумент.Записать(ИмяФайла);
		БазовыйФайлРедактораКода = БазовыйКаталог + КаталогКомпоненты + ирОбщий.РазделительПутиКФайлуЛкс() + "index.html";
	КонецЕсли; 
	Возврат БазовыйФайлРедактораКода;
КонецФункции

//.
// Параметры:
//    МодульМетаданных - см. МодульМетаданных() -
//    ИмяМетода - ? - 
// Возвращаемое значение:
//    СтрокаТаблицыЗначений, Неопределено - 
Функция СтрокаМетодаМодуляПоИмени(Знач МодульМетаданных, Знач ИмяМетода) Экспорт 
	Если Ложь
		Или Не ЗначениеЗаполнено(ИмяМетода)
		Или ИмяМетода = ИмяМетодаИнициация()
	Тогда
		Возврат Неопределено;
	КонецЕсли;
	СтрокаМетода = МодульМетаданных.Методы.Найти(НРег(ИмяМетода), "НИмя");
	Если Истина
		И СтрокаМетода <> Неопределено
		И Не ЗначениеЗаполнено(СтрокаМетода.ИмяМодуля) 
	Тогда
		СтрокаМетода.ИмяМодуля = МодульМетаданных.Имя;
	КонецЕсли;
	Возврат СтрокаМетода;
КонецФункции

#Если Клиент Тогда

// Не применяется для имитаторов.
// Параметры:
//    ДанныеФормы - ДанныеФормы - 
//    ЛиКоллекция - Булево, Неопределено -
//    Форма - УправляемаяФорма -
// Возвращаемое значение:
//    Структура - "Ключ" содержит имя реквизита, а "Значение" содержит описание типов реквизита
Функция ДочерниеСвойстваДанныхФормы(ДанныеФормы, Знач ЛиДляКоллекции = Неопределено, Знач Форма, Знач ИмяСвойства = "") Экспорт
	Если ЛиДляКоллекции = Неопределено Тогда
		ЛиДляКоллекции = ирОбщий.ЛиКоллекцияЛкс(ДанныеФормы);
	КонецЕсли;
	ДокументДОМ = ирОбщий.ТекстВДокументDOMЛкс(ирОбщий.ОбъектВСтрокуXMLЛкс(ДанныеФормы)); // 1.2 мс на малой форме
	Разыменователь = РазыменовательПространствИменDOM();
	Выражение = "/*[last()]/t:type[1]/text()";
	ПутьКРодителю = ДокументДОМ.ВычислитьВыражениеXPath(Выражение, ДокументДОМ, Разыменователь, ТипРезультатаDOMXPath.Строка).СтроковоеЗначение;
	СтруктураИмен = Новый Структура;
	Если Найти(ПутьКРодителю, "root.") = 1 Тогда
		ПутьКРодителю = Сред(ПутьКРодителю, СтрДлина("root.") + 1);  
		СтруктураИмен = ИменаРеквизитовФормы(Форма, ПутьКРодителю, ЛиДляКоллекции,, ДокументДОМ).Все;
		Если ЗначениеЗаполнено(ИмяСвойства) И Не СтруктураИмен.Свойство(ИмяСвойства) Тогда
			ДобавитьОтсутствиеЭлементаФормы(Форма, "Реквизит:" + ПутьКРодителю + "." + ИмяСвойства);
		КонецЕсли;
	Иначе
		// parameters - там почему то всегда пусто
	КонецЕсли;
	Возврат СтруктураИмен;
КонецФункции

// Позволяет пользователю выбрать один из возможных вариантов описания слова.
//
// Параметры:
//  СтруктураЦикла - Соответствие - где ключи - имена ветвей дерева, а значения - таблицы структур типов;
//  *ВключатьПутьКОписаниюТипаЗначения - Булево, *Неопределено - признак добавления в список выбора тип значения слова.
//
// Возвращаемое значение:
//  СтрокаТаблицыЗначений, Структура - описание слова.
//
Функция ВыбратьСтрокуОписанияИзМассиваСтруктурТипов(СтруктураЦикла, ВключатьПутьКОписаниюТипаЗначения = Ложь, ВладелецФормы = Неопределено, Слово = "",
	НомерПараметраМетода = 0, БезусловнаяАктивизацияРезультатов = Истина, выхФормаВыбора = Неопределено, КоличествоФактПараметровМетода = 0) Экспорт

	ДеревоВыбора = Новый ДеревоЗначений;
	ДеревоВыбора.Колонки.Добавить("Ключ");
	ДеревоВыбора.Колонки.Добавить("Представление");
	ДеревоВыбора.Колонки.Добавить("ТипСлова");
	СчетчикСтрокВторогоУровня = 0;
	НачальнаяСтрокаВыбора = Неопределено;
	Для Каждого ЭлементЦикла Из СтруктураЦикла Цикл
		СтрокаЭлементаЦикла = ДеревоВыбора.Строки.Добавить();
		СтрокаЭлементаЦикла.Представление = ЭлементЦикла.Ключ;
	КонецЦикла;
	ДеревоВыбора.Строки.Сортировать("Представление");
	Для Каждого СтрокаЭлементаЦикла Из ДеревоВыбора.Строки Цикл
		Для Каждого СтруктураТипаКонтекста Из СтруктураЦикла[СтрокаЭлементаЦикла.Представление] Цикл
			//Если СтруктураТипаКонтекста.СтрокаОписания = Неопределено Тогда 
			//	Продолжить;
			//КонецЕсли;
			Если СтруктураТипаКонтекста.ИмяОбщегоТипа = "НеизвестныйКонтекст" Тогда
				Продолжить;
			КонецЕсли;
			СтрокаОписания = СтруктураТипаКонтекста.СтрокаОписания;
			
			// Ранее среди параметров были: ПутьКСлову = "", ТекущееСлово = "",
			//// Добавим строку описания слова
			//ЭтоИмяТипа = Ложь;
			//Попытка
			//	Если СтрокаОписания.ТипЯзыка = "ИмяТипа" Тогда
			//		ЭтоИмяТипа = Истина;
			//	КонецЕсли;
			//Исключение
			//КонецПопытки;
			//
			//Если ЭтоИмяТипа Тогда
			//	
			//	Если Прав(ПутьКСлову, 1) = "(" Тогда 
			//		ЧистыйПутьКСлову = Лев(ПутьКСлову, СтрДлина(ПутьКСлову) - 1);
			//	Иначе
			//		ЧистыйПутьКСлову = ТекущееСлово;
			//	КонецЕсли;
			//	
			//	БазовыйТип = ирОбщий.ПервыйФрагментЛкс(ЧистыйПутьКСлову);
			//	Если БазовыйТип = "" Тогда
			//		// НеизвестныйКонтекст
			//		СтрокаОписания = Неопределено;
			//	Иначе
			//		СтрокаОписания = ТаблицаОбщихТипов.Найти(БазовыйТип, "БазовыйТип");
			//	КонецЕсли;
			//КонецЕсли;
			
			Если Истина
				И СтрокаОписания <> Неопределено
				И ТипЗнч(СтрокаОписания) <> Тип("COMОбъект")
				И СтрокаЭлементаЦикла.Строки.Найти(СтрокаОписания, "Ключ") = Неопределено
				И СтрокаОписания.Владелец().Колонки.Найти("ЛиЭкспорт") = Неопределено
				И (Ложь
					Или СтрокаОписания.Владелец().Колонки.Найти("ТипЯзыка") = Неопределено
					Или СтрокаОписания.ТипЯзыка <> "ИмяТипа")
			Тогда
				ПредставлениеТипа = СтрокаОписания.Слово;
				Если Истина
					И СтрокаОписания.Владелец().Колонки.Найти("ТипКонтекста") <> Неопределено
					И ЗначениеЗаполнено(СтрокаОписания.ТипКонтекста)
				Тогда
					ПредставлениеТипа = СтрокаОписания.ТипКонтекста + "." + ПредставлениеТипа;
				КонецЕсли;
				СтрокаДереваВыбора = СтрокаЭлементаЦикла.Строки.Добавить();
				СтрокаДереваВыбора.Ключ = СтрокаОписания;
				Попытка
					СтрокаДереваВыбора.ТипСлова = СтрокаОписания.ТипСлова;
				Исключение
					СтрокаДереваВыбора.ТипСлова = "Тип";
				КонецПопытки;
				СтрокаДереваВыбора.Представление = ПредставлениеТипа;
			КонецЕсли;
			
			Если ВключатьПутьКОписаниюТипаЗначения Тогда
				// Добавим строку описания типа значения
				СтрокаОписанияТипаЗначения = ТаблицаОбщихТипов.Найти(НРег(СтруктураТипаКонтекста.ИмяОбщегоТипа), "НСлово");
				Если СтрокаОписанияТипаЗначения <> Неопределено Тогда
					Если СтрокаЭлементаЦикла.Строки.Найти(СтрокаОписанияТипаЗначения, "Ключ") = Неопределено Тогда
						ПредставлениеТипа = СтрокаОписанияТипаЗначения.Слово;
						СтрокаДереваВыбора = СтрокаЭлементаЦикла.Строки.Добавить();
						СтрокаДереваВыбора.Ключ = СтрокаОписанияТипаЗначения;
						СтрокаДереваВыбора.ТипСлова = "Тип";
						СтрокаДереваВыбора.Представление = ПредставлениеТипа;
					КонецЕсли;
				КонецЕсли;
			КонецЕсли;
			
		КонецЦикла;
		СчетчикСтрокВторогоУровня = СчетчикСтрокВторогоУровня + СтрокаЭлементаЦикла.Строки.Количество();
		Если Истина
			И НачальнаяСтрокаВыбора = Неопределено
			И СтрокаЭлементаЦикла.Строки.Количество() > 0
		Тогда
			Если СтрокаДереваВыбора.ТипСлова = "Конструктор" Тогда
				Отбор = Новый Структура;
				Отбор.Вставить("ТипКонтекста", СтрокаОписания.ТипКонтекста);
				Отбор.Вставить("Слово", "<Новый>");
				Отбор.Вставить("ЯзыкПрограммы", 0);
				ТаблицаВариантов = ТаблицаПараметров.Скопировать(Отбор);
				НовыйТекущийВариант = ПодобратьВариантСинтаксисаМетода(ТаблицаВариантов, КоличествоФактПараметровМетода);
				Для Каждого СтрокаВарианта Из СтрокаЭлементаЦикла.Строки Цикл
					Если НовыйТекущийВариант = СтрокаВарианта.Ключ.Слово Тогда
						НачальнаяСтрокаВыбора = СтрокаВарианта;
						Прервать;
					КонецЕсли; 
				КонецЦикла;
			Иначе
				НачальнаяСтрокаВыбора = СтрокаЭлементаЦикла.Строки[0];
			КонецЕсли; 
		КонецЕсли;
		СтрокаЭлементаЦикла.Строки.Сортировать("Представление");
	КонецЦикла;
	Если выхФормаВыбора = Неопределено Тогда
		выхФормаВыбора = ирКлиент.ПолучитьФормуЛкс("Обработка.ирСинтаксПомощник.Форма");
	КонецЕсли;
	Если СчетчикСтрокВторогоУровня > 0 Или выхФормаВыбора.Открыта() Тогда
		выхФормаВыбора.ДеревоТиповСлова = ДеревоВыбора;
		выхФормаВыбора.ИскомоеСлово = Слово;
		выхФормаВыбора.ПоискСУчетомТипаСлова = Истина;
		выхФормаВыбора.НомерИскомогоПараметра = НомерПараметраМетода;
		выхФормаВыбора.ВладелецФормы = ВладелецФормы;
		выхФормаВыбора.ЗакрыватьПриЗакрытииВладельца = Ложь;
		Если НачальнаяСтрокаВыбора <> Неопределено Тогда
			выхФормаВыбора.ВыбратьИскомуюСтроку(НачальнаяСтрокаВыбора, БезусловнаяАктивизацияРезультатов);
		КонецЕсли; 
		выхФормаВыбора.ВладелецФормы = Неопределено; // Перенес в саму форму
	КонецЕсли; 
	Если Ложь
		Или СчетчикСтрокВторогоУровня = 1
		Или (Истина
			И СчетчикСтрокВторогоУровня = 2
			И ДеревоВыбора.Строки[0].Строки.Количество() = 1
			И НачальнаяСтрокаВыбора.Ключ = ДеревоВыбора.Строки[1].Строки[0].Ключ)
	Тогда 
		ВыбранныйЭлементТипа = НачальнаяСтрокаВыбора;
	ИначеЕсли СчетчикСтрокВторогоУровня > 1 Тогда
		//ФормаВыбора = ПолучитьФорму("ФормаВыбораСправкиПоСлову");
		//ФормаВыбора.ДеревоТиповСлова = ДеревоВыбора;
		//ФормаВыбора.НачальноеЗначениеВыбора = НачальнаяСтрокаВыбора;
		//ВыбранныйЭлементТипа = ФормаВыбора.ОткрытьМодально();
		ВыбранныйЭлементТипа = НачальнаяСтрокаВыбора;
	Иначе
		ВыбранныйЭлементТипа = Неопределено;
	КонецЕсли;
	Если ВыбранныйЭлементТипа = Неопределено Тогда
		СтрокаОписания = Неопределено;
	Иначе
		СтрокаОписания = ВыбранныйЭлементТипа.Ключ;
	КонецЕсли;
	Возврат СтрокаОписания;

КонецФункции

Функция НайтиИмяМетодаСтрокиМодуля(Знач ИмяМодуля, Знач НомерСтроки, Знач СодержаниеСтроки = Неопределено, ТекстыМодулей = Неопределено, СтароеИмяФайлаМодуляБезРасширения = "",
	Знач ЧислоСтрокДляПоискаИмениМетода = 1000) Экспорт 
	
	Если Не ЗначениеЗаполнено(ИмяМодуля) Тогда
		// Динамический код
		Возврат "";
	КонецЕсли;
	ОписаниеМодуля = ирКлиент.ОписаниеМодуляПоСжатомуИмениЛкс(ИмяМодуля);
	ИмяМетода = НайтиИмяМетодаСтрокиФайлаМодуля(ОписаниеМодуля.ИмяМодуля, НомерСтроки, СодержаниеСтроки, ТекстыМодулей, СтароеИмяФайлаМодуляБезРасширения, ЧислоСтрокДляПоискаИмениМетода);
	Возврат ИмяМетода;

КонецФункции

Функция НайтиИмяМетодаСтрокиФайлаМодуля(Знач ИмяМодуля, Знач НомерСтроки, Знач СодержаниеСтроки = Неопределено, ТекстыМодулей = Неопределено, СтароеИмяФайлаМодуляБезРасширения = "",
	Знач ЧислоСтрокДляПоискаИмениМетода = 2000, выхСмещениеСтрокиМетода = 0, Знач ПолеТекстаМодуля = Неопределено) Экспорт
	
	Если ПолеТекстаМодуля = Неопределено Тогда
		ПолеТекстаМодуля = ирКлиент.ПолеТекстаМодуляБезСтруктурыТипаЛкс(ИмяМодуля);
	КонецЕсли; 
	Если ПолеТекстаМодуля = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	Если Ложь
		Или СодержаниеСтроки = Неопределено
		Или СокрЛП(ПолеТекстаМодуля.ПолеТекста.ПолучитьСтроку(НомерСтроки)) = СодержаниеСтроки
	Тогда   
		Если ТекстыМодулей = Неопределено Тогда
			ТекстыМодулей = Новый Соответствие;
		КонецЕсли;
		КэшРазметкиМодулей = ТекстыМодулей[ИмяМодуля];
		Если КэшРазметкиМодулей = Неопределено Тогда
			Методы = Новый ТаблицаЗначений;
			Методы.Колонки.Добавить("Метод");
			Методы.Индексы.Добавить("Метод");
			Методы.Колонки.Добавить("НачальнаяСтрока");
			Методы.Колонки.Добавить("КонечнаяСтрока", Новый ОписаниеТипов("Число"));
			КэшРазметкиМодулей = Новый Структура("Методы", Методы);
			ТекстыМодулей[ИмяМодуля] = КэшРазметкиМодулей;
			Методы = Неопределено;
		КонецЕсли;
		НужноеОписаниеМетода = Неопределено;
		Если ирКэш.РежимОтладкиЛкс() Тогда 
			// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
			Для Каждого ОписаниеМетода Из КэшРазметкиМодулей.Методы Цикл
				Если Истина
					И ОписаниеМетода.НачальнаяСтрока <= НомерСтроки 
					И ОписаниеМетода.КонечнаяСтрока >= НомерСтроки  
				Тогда
					НужноеОписаниеМетода = ОписаниеМетода;
					Прервать;
				КонецЕсли;
			КонецЦикла;
		Иначе
			// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
			Для Каждого ОписаниеМетода Из КэшРазметкиМодулей.Методы Цикл  			Если Истина  				И ОписаниеМетода.НачальнаяСтрока <= НомерСтроки  				И ОписаниеМетода.КонечнаяСтрока >= НомерСтроки  			Тогда  				НужноеОписаниеМетода = ОписаниеМетода;  				Прервать;  			КонецЕсли;  		КонецЦикла;  
		КонецЕсли; 
		Если НужноеОписаниеМетода = Неопределено Тогда 
			РегВыражение = ирКэш.ВычислительРегВыраженийЛкс();
			#Если Сервер И Не Сервер Тогда
				РегВыражение = Обработки.ирОболочкаРегВыражение.Создать();
			#КонецЕсли
			РегВыражение.Global = Истина;
			РегВыражение.Pattern = "(?:" + шПустоеНачалоСтроки + "(?:Процедура|Функция)" + шРазделитель + "+(" + шИмя + ")" + шРазделитель + "*\()"
			+ "|(?:" + шПустоеНачалоСтроки + "(?:КонецПроцедуры|КонецФункции)" + шРазделитель + "+?(?=\n))";
			НачальнаяСтрокаДиапазона = Макс(1, НомерСтроки - ЧислоСтрокДляПоискаИмениМетода);
			ПолеТекстаМодуля.ПолеТекста.УстановитьГраницыВыделения(НомерСтроки + 1, 1, НачальнаяСтрокаДиапазона, 1);
			Вхождения = РегВыражение.НайтиВхождения(ПолеТекстаМодуля.ВыделенныйТекст(), Истина); 
			Если Вхождения.Количество() > 0 Тогда
				Вхождение = Вхождения[Вхождения.Количество() - 1];
				ИмяМетода = Вхождение.SubMatches(0);
				Если ИмяМетода = Неопределено Тогда
					ИмяМетода = ИмяМетодаИнициация();
				КонецЕсли;
				НужноеОписаниеМетода = КэшРазметкиМодулей.Методы.Найти(ИмяМетода, "Метод");
				Если НужноеОписаниеМетода = Неопределено Тогда
					НужноеОписаниеМетода = КэшРазметкиМодулей.Методы.Вставить(0);
					НужноеОписаниеМетода.Метод = ИмяМетода;
					НужноеОписаниеМетода.НачальнаяСтрока = НачальнаяСтрокаДиапазона + СтрЧислоСтрок(Лев(ПолеТекстаМодуля.ВыделенныйТекст(), Вхождение.FirstIndex + Вхождение.Length)) - 1;
					Если ИмяМетода = ИмяМетодаИнициация() Тогда
						НужноеОписаниеМетода.КонечнаяСтрока = 100000000;
					КонецЕсли;
				КонецЕсли;
			Иначе
				Пустышка = 0; // Для отладки
			КонецЕсли;
		Иначе
			ИмяМетода = НужноеОписаниеМетода.Метод;
		КонецЕсли;
		Если НужноеОписаниеМетода <> Неопределено Тогда 
			выхСмещениеСтрокиМетода = НомерСтроки - НужноеОписаниеМетода.НачальнаяСтрока;
			Если НомерСтроки > НужноеОписаниеМетода.КонечнаяСтрока Тогда 
				НужноеОписаниеМетода.КонечнаяСтрока = НомерСтроки;
			КонецЕсли;
		КонецЕсли;
	Иначе          
		Пустышка = 0; // Для отладки
	КонецЕсли;
	Возврат ИмяМетода;

КонецФункции

Функция ЗаполнитьСписокИнструментов() Экспорт 
	
	Если СписокИнструментов.Количество() = 0 Тогда
		ТабличныйДокумент = ПолучитьМакет("СписокИнструментов");
		СписокИнструментов.Загрузить(ирОбщий.ТаблицаЗначенийИзТабличногоДокументаЛкс(ТабличныйДокумент,,,, Истина));
	КонецЕсли; 
	Возврат СписокИнструментов;
	
КонецФункции

// Инициализирует полное дерево типов платформы.
//
// Параметры:
//  Нет.
//
Процедура ИнициироватьДеревоТипов() Экспорт

	ИнициацияОписанияМетодовИСвойств();
	Состояние("Инициализация дерева типов...");
	Если ДеревоТипов <> Неопределено Тогда
		Возврат;
	КонецЕсли;
	ДеревоТипов = Новый ДеревоЗначений;
	ДеревоТипов.Колонки.Добавить("Пометка", Новый ОписаниеТипов("Булево"));
	ДеревоТипов.Колонки.Добавить("Имя");
	ДеревоТипов.Колонки.Добавить("ИндексКартинки", Новый ОписаниеТипов("Число"));
	ДеревоТипов.Колонки.Добавить("СтруктураТипа");
	лТаблицаТипов = ТаблицаОбщихТипов.Скопировать(Новый Структура("ЯзыкПрограммы", 0), "Слово");
	лТаблицаТипов.Колонки.Слово.Имя = "Имя";
	Для Каждого СтрокаТипа Из лТаблицаТипов Цикл
		ЗаполнитьЗначенияСвойств(ДеревоТипов.Строки.Добавить(), СтрокаТипа);
	КонецЦикла;
	СтруктураТипа = НоваяСтруктураТипа();
	СтруктураТипа.Метаданные = мМетаданные;
	СтруктураТипа.ТипЯзыка = "ИмяТипа";
	СтруктураТипа.ИмяОбщегоТипа = "";
	ОбработатьСтрокиДереваТипов(ДеревоТипов.Строки, СтруктураТипа);
	ДеревоТипов.Строки.Сортировать("Имя", Истина);
	ВсеТипы.Сортировать("Имя");
	МассивВажныхТипов = Новый Массив; 
	// Порядок обратный
	МассивВажныхТипов.Добавить("Массив");
	МассивВажныхТипов.Добавить("Булево");
	МассивВажныхТипов.Добавить("Дата");
	МассивВажныхТипов.Добавить("Строка");
	МассивВажныхТипов.Добавить("Число");
	Для Каждого ВажныйТип Из МассивВажныхТипов Цикл
		СтрокаТипа = ВсеТипы.Найти(ВажныйТип, "Имя");
		ВсеТипы.Сдвинуть(СтрокаТипа, -ВсеТипы.Индекс(СтрокаТипа));
		СтрокаТипа = ДеревоТипов.Строки.Найти(ВажныйТип, "Имя");
		ДеревоТипов.Строки.Сдвинуть(СтрокаТипа, -ДеревоТипов.Строки.Индекс(СтрокаТипа));
	КонецЦикла; 
	Состояние("");

КонецПроцедуры

Процедура ОбработатьСтрокиДереваТипов(Строки, КорневаяСтруктураТипа = Неопределено, ОкончаниеСтрокиТипа = "", _МетаданныеТипа = Неопределено) Экспорт

	МассивСтрокКУдалению = Новый Массив;
	Для Каждого СтрокаТипа Из Строки Цикл
		ТекущееИмяТипа = СтрокаТипа.Имя;
		СтрокаТипа.Имя = СтрокаТипа.Имя + ОкончаниеСтрокиТипа;
		Уровень = СтрокаТипа.Уровень();
		ФрагментыОбщегоТипа = Неопределено;
		Если Уровень = 0 Тогда
			Если Найти(ТекущееИмяТипа, ".") > 0 Тогда
				ФрагментыОбщегоТипа = ирОбщий.СтрРазделитьЛкс(ТекущееИмяТипа);
				ТекущееИмяТипа = ФрагментыОбщегоТипа[0];
			КонецЕсли;
			СтрокаТипаМетаОбъектов = ОписаниеТипаМетаОбъектов(ТекущееИмяТипа);
			Если СтрокаТипаМетаОбъектов <> Неопределено Тогда
				СтрокаТипа.ИндексКартинки = СтрокаТипаМетаОбъектов.ИндексКартинкиЕдинственное;
			КонецЕсли;
			Уровень = 0;
			//СтрокаТипа.ИмяОбщегоТипа = ТекущееИмяТипа;
		Иначе
			Если КорневаяСтруктураТипа <> Неопределено Тогда
				КорневаяСтруктураТипа.Свойство("ФрагментыОбщегоТипа", ФрагментыОбщегоТипа);
			КонецЕсли; 
			СтрокаТипа.ИндексКартинки = Строки.Родитель.ИндексКартинки;
		КонецЕсли; 
		Если ФрагментыОбщегоТипа <> Неопределено Тогда
			Если ФрагментыОбщегоТипа.ВГраница() > Уровень Тогда
				ТекущийФрагмент = ФрагментыОбщегоТипа[Уровень + 1];
			КонецЕсли; 
			Если Найти(ТекущийФрагмент, "<") > 0 Тогда 
				Если Истина
					И КорневаяСтруктураТипа = Неопределено 
				Тогда
					КорневаяСтруктураТипа = НоваяСтруктураТипа();
					КорневаяСтруктураТипа.Метаданные = мМетаданные;
					КорневаяСтруктураТипа.ТипЯзыка = "ИмяТипа";
					КорневаяСтруктураТипа.ИмяОбщегоТипа = СтрокаТипа.Имя;
				КонецЕсли; 
				Если Уровень = 0 Тогда
					КорневаяСтруктураТипа.Вставить("ФрагментыОбщегоТипа", ФрагментыОбщегоТипа);
					СтруктураТипа = НоваяСтруктураТипа();
					ЗаполнитьЗначенияСвойств(СтруктураТипа, КорневаяСтруктураТипа);
					СтруктураТипа.ИмяОбщегоТипа = ТекущееИмяТипа;
				Иначе
					СтруктураТипа = СтрокаТипа.СтруктураТипа;
				КонецЕсли;
				
				Попытка
					ВнутренняяТаблицаСлов = СловаКонтекстаМетаданные(СтруктураТипа, , "Свойство");
				Исключение
					ВнутренняяТаблицаСлов = Новый ТаблицаЗначений;
				КонецПопытки;
				Если Истина
					И Уровень > 0
					И ВнутренняяТаблицаСлов.Количество() = 0
				Тогда
					МассивСтрокКУдалению.Добавить(СтрокаТипа);
					Продолжить;
				Иначе
					ОкончаниеСтрокиТипаВниз = "";
					Для Счетчик = Уровень + 2 По ФрагментыОбщегоТипа.ВГраница() Цикл 
						Фрагмент = ФрагментыОбщегоТипа[Счетчик];
						ОкончаниеСтрокиТипаВниз = ОкончаниеСтрокиТипаВниз + "." + Фрагмент;
					КонецЦикла;
					Для Каждого СтрокаСлова Из ВнутренняяТаблицаСлов Цикл
						НоваяСтрока = СтрокаТипа.Строки.Добавить();
						СтруктураТипаВниз = СтрокаСлова.ТаблицаТипов[0];
						НоваяСтрока.СтруктураТипа = СтруктураТипаВниз;
						//НоваяСтрока.Имя = ИмяТипаИзСтруктурыТипа(СтруктураТипаВниз);
						НоваяСтрока.Имя = ТекущееИмяТипа + "." + СтруктураТипаВниз.Метаданные.Имя;
					КонецЦикла;
					ОбработатьСтрокиДереваТипов(СтрокаТипа.Строки, КорневаяСтруктураТипа, ОкончаниеСтрокиТипаВниз);
				КонецЕсли;
			КонецЕсли;
		КонецЕсли; 
		//ЗаполнитьЗначенияСвойств(СтруктураТипа, КорневаяСтруктураТипа, "ИмяОбщегоТипа");
		ЗаполнитьЗначенияСвойств(ВсеТипы.Добавить(), СтрокаТипа);
	КонецЦикла;
	РодительСтрок = Строки.Родитель;
	Для Каждого СтрокаКУдалению Из МассивСтрокКУдалению Цикл
		РодительСтрок.Строки.Удалить(СтрокаКУдалению);
	КонецЦикла;

КонецПроцедуры

// Открыть диалог для редактирования допустимых типов.
//
// Параметры:
//  ДопустимыеТипы - Строка - сериализованные допустимые типы;
//  *ТолькоПросмотр - Булево, *Истина - открыть только для просмотра.
//
// Возвращаемое значение:
//  Строка - сериализованных допустимых типов;
//  Неопределено - отмена.
//
Функция РедактироватьДопустимыеТипы(ДопустимыеТипы, ТолькоПросмотр = Ложь) Экспорт

	ФормаВыбора = ПолучитьФорму("ВыборДопустимыхТипов");
	ФормаВыбора.ДопустимыеТипы = ДопустимыеТипы;
	ФормаВыбора.ТолькоПросмотр = ТолькоПросмотр;
	Если ФормаВыбора.ОткрытьМодально() = Истина Тогда 
		Возврат ФормаВыбора.ДопустимыеТипы;
	Иначе
		Возврат Неопределено;
	КонецЕсли;

КонецФункции

// Убирает из строки лишние кавычки.
//
// Параметры:
//  ПервичнаяСтрока - Строка.
//
// Возвращаемое значение:
//  Строка.
//
Функция ИзвлечьСтрокуШаблонаТекста(ПервичнаяСтрока)

	RegExp.Global = Истина;
	СтрокаБезГраниц = Сред(ПервичнаяСтрока, 2, СтрДлина(ПервичнаяСтрока) - 2);
	RegExp.Pattern = "([^""]*"")""";
	Результат = RegExp.Заменить(СтрокаБезГраниц, "$1"); 
	Возврат Результат;

КонецФункции // ИзвлечьСтрокуШаблонаТекста ()

// Загружает шаблоны текста из файла.
//
// Параметры:
//  Нет.
//
// Возвращаемое значение:
//   Булево - успешность операции.
//
Функция ПолучитьТаблицуШаблоновТекста(ИмяКласса, _мСообщенияЧерезПредупреждения = Ложь, ПринудительноОбновить = Ложь) Экспорт 

	Если Истина
		И Не ПринудительноОбновить
		И ТаблицаШаблоновТекста <> Неопределено 
	Тогда
		Возврат ТаблицаШаблоновТекста;
	КонецЕсли; 
	ТаблицаШаблоновТекста = Новый ТаблицаЗначений;
	ТаблицаШаблоновТекста.Колонки.Добавить("Шаблон");
	ТаблицаШаблоновТекста.Колонки.Добавить("Замена");
	ТаблицаШаблоновТекста.Индексы.Добавить("Шаблон");
	
	ФайлШаблонов = ирОбщий.ВосстановитьЗначениеЛкс(ИмяКласса + ".ФайлШаблоновТекста");
	Файл = Новый Файл(ФайлШаблонов);
	Если Не Файл.Существует() Тогда
		Если ЗначениеЗаполнено(ФайлШаблонов) Тогда
			ирОбщий.СообщитьСУчетомМодальностиЛкс("Не обнаружен файл шаблонов текста """ + ФайлШаблонов + """, указанный в настройках компоненты ""Контекстная подсказка""");
		КонецЕсли; 
		Возврат Неопределено;
	КонецЕсли;
	Парсер = мПолучитьПарсер("ГрамматикаФайлаШаблоновТекста");
	Если Парсер = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;

	ТекстовыйДокументФайла = Новый ТекстовыйДокумент;
	ТекстовыйДокументФайла.Прочитать(ФайлШаблонов);
	
	Состояние("Идет загрузка файла шаблонов текста...");
		
	gpMsgReduction			= 2;
	gpMsgAccept				= 3;
	gpMsgNotLoadedError		= 4;
	gpMsgLexicalError		= 5;
	gpMsgSyntaxError 		= 6;
	gpMsgInternalError		= 8;
	
	Парсер.OpenTextString(ТекстовыйДокументФайла.ПолучитьТекст());

	Закончили = Ложь;
    ТекущаяСтрокаТаблицыШаблоновТекста = Неопределено;
	
	Пока Не Закончили Цикл 
		Ответ = Парсер.Parse();
		Если Ложь
			Или Ответ = gpMsgLexicalError
			Или Ответ = gpMsgSyntaxError
			Или Ответ = gpMsgInternalError
			Или Ответ = gpMsgNotLoadedError
			Или Ответ = gpMsgAccept
		Тогда
		    Закончили = Истина;
		ИначеЕсли Ответ = gpMsgReduction Тогда
			ИмяПравила = Парсер.CurrentReduction.ParentRule.RuleNonterminal.Text;
			Если ИмяПравила = "<Match>" Тогда 
				СтартовыйТокен = Парсер.CurrentReduction.Tokens(0);
				ТекущаяСтрокаТаблицыШаблоновТекста = ТаблицаШаблоновТекста.Добавить();
				ТекущаяСтрокаТаблицыШаблоновТекста.Шаблон = Нрег(ИзвлечьСтрокуШаблонаТекста(СтартовыйТокен.Data));
			ИначеЕсли ИмяПравила = "<Replacement>" Тогда 
				СтартовыйТокен = Парсер.CurrentReduction.Tokens(0);
				ТекущаяСтрокаТаблицыШаблоновТекста.Замена = ИзвлечьСтрокуШаблонаТекста(СтартовыйТокен.Data);
			КонецЕсли;  
		КонецЕсли;
	КонецЦикла;
	
	Состояние();
	Если Ответ <> gpMsgAccept Тогда
		ирОбщий.СообщитьСУчетомМодальностиЛкс("Указан неправильный файл шаблонов """ + ФайлШаблонов + """");
		ТаблицаШаблоновТекста = Неопределено;
	КонецЕсли;
	Возврат ТаблицаШаблоновТекста;
	
КонецФункции // ЗагрузитьШаблоныТекста()

// .
// Параметры:
//   Параметры - ТаблицаЗначений - :
//     *ИмяПараметра
//     *Значение
//     *ТипЗначения
//   ТипЗапроса - Строка, *"Построитель" - "Обычный", "Компоновка", "Построитель"
Функция РедактироватьЗапрос(Текст, Параметры = Неопределено, Знач ТипЗапроса = "Построитель", ПараметрыADO = Неопределено, ПараметрыWMI = Неопределено,
	ВыделениеДвумерное = Неопределено) Экспорт
	
	СтруктураЗапроса = Новый Структура;
	СтруктураЗапроса.Вставить("ТекстЗапроса", Текст);
	Если ПараметрыADO <> Неопределено Тогда
		СтруктураЗапроса.Вставить("ПараметрыADO", ПараметрыADO);
	КонецЕсли; 
	Если ПараметрыWMI <> Неопределено Тогда
		СтруктураЗапроса.Вставить("ПараметрыWMI", ПараметрыWMI);
	КонецЕсли; 
	СтруктураЗапроса.Вставить("ТипЗапроса", ТипЗапроса);
	СтруктураЗапроса.Вставить("Имя", "Запрос");
	СтруктураЗапроса.Вставить("ВыделениеДвумерное", ВыделениеДвумерное);
	КонсольЗапросов = ирОбщий.СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольЗапросов");
	#Если Сервер И Не Сервер Тогда
		КонсольЗапросов = Обработки.ирКонсольЗапросов.Создать();
	#КонецЕсли
	Если Параметры <> Неопределено Тогда
		ПолныеПараметры = КонсольЗапросов.НоваяТаблицаПараметров();
		ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(Параметры, ПолныеПараметры);
		СтруктураЗапроса.Вставить("Параметры", ПолныеПараметры);
	КонецЕсли;
	РезультатФормы = КонсольЗапросов.РедактироватьСтруктуруЗапроса(, СтруктураЗапроса);
	Результат = РезультатФормы <> Неопределено;
	Если Результат Тогда
		Текст = РезультатФормы.ТекстЗапроса;
		Параметры = РезультатФормы.Параметры;
		ПараметрыADO = РезультатФормы.ПараметрыADO;
		ПараметрыWMI = РезультатФормы.ПараметрыWMI;
		ВыделениеДвумерное = РезультатФормы.ВыделениеДвумерное;
	КонецЕсли;
	Возврат Результат;
	
КонецФункции

#КонецЕсли

////////////////////////////////////////////////////////////////////////////////
// РАБОТА С АЛГОРИТМАМИ

// Выполняет текст программы.
//
// Параметры:
//  ТекстДляВыполнения - Строка;
//  *ЛиСинтаксическийКонтроль - Булево, *Ложь - признак вызова только для синтаксического контроля.
//
Функция ВыполнитьЛокально(ТекстДляВыполнения, ЛиСинтаксическийКонтроль = Ложь) Экспорт 
	
	Если ЛиСинтаксическийКонтроль Тогда
		ирОбщий.ВыполнитьАлгоритмБезРезультата(ТекстДляВыполнения);
	Иначе
		Результат = ирОбщий.ВыполнитьАлгоритм(ТекстДляВыполнения);
	КонецЕсли; 
	Возврат Результат;

КонецФункции

// Выполняет программный код в контексте.
//
// Параметры:
//  ТекстДляВыполнения - Строка;
//  *ЛиСинтаксическийКонтроль - Булево, *Ложь - признак вызова только для синтаксического контроля.
//
Функция ВыполнитьПрограммныйКодВКонтексте(КонтекстВыполнения, МетодВыполнения = "ВыполнитьЛокально", ТекстДляВыполнения, ЛиСинтаксическийКонтроль = Ложь) Экспорт 

	Если ПустаяСтрока(МетодВыполнения) Тогда
		ВызватьИсключение "Не указан метод выполнения";
	КонецЕсли; 
	Если КонтекстВыполнения = Неопределено Тогда
		ИнформацияОбОшибке = Вычислить(МетодВыполнения + "(ТекстДляВыполнения, ЛиСинтаксическийКонтроль)");
	Иначе
		ИнформацияОбОшибке = Вычислить("КонтекстВыполнения." + МетодВыполнения + "(ТекстДляВыполнения, ЛиСинтаксическийКонтроль)");
	КонецЕсли;
	Возврат ИнформацияОбОшибке;

КонецФункции

// Получает новый экземпляр ком-объекта парсера.
//
// Параметры:
//  Нет.
//
// Возвращаемое значение:
//  Com-объект, Неопределено.
//
Функция ПолучитьADOUtils(_ПытатьсяУстанавливать = Ложь, Знач СмещениеГодаADO = Неопределено, Знач Типизировать1С = Ложь, Знач БинарныеВСтроку = Ложь) Экспорт

	Если мADOUtils = Неопределено Тогда
		ИдентификаторКласса = "GameWithFire.ADOUtils";
		ИмяОбъекта = "ADOUtils";
		ПодключитьВнешнююКомпоненту(ИдентификаторКласса);
		Попытка
			мADOUtils = Новый ("AddIn." + ИмяОбъекта);
			мADOUtils.BinaryDataAs1C = Истина; // Для проверки актуальности версии библиотеки
		Исключение
			мADOUtils = Неопределено;
		КонецПопытки;
		Если Истина
			И мADOUtils = Неопределено 
			//И ПытатьсяУстанавливать
			И Ложь
		Тогда
			ИмяМакетаДополнительнойБиблиотеки = "Zlib1";
			ИмяМакетаКомпоненты = "GameWithFire";
			ПолучитьCOMОбъектИзМакета(ИмяМакетаКомпоненты, ИдентификаторКласса,, ИмяМакетаДополнительнойБиблиотеки, ИмяОбъекта);
			ПодключитьВнешнююКомпоненту(ИдентификаторКласса);
			Попытка
				мADOUtils = Новый ("AddIn." + ИмяОбъекта);
				мADOUtils.BinaryDataAs1C = Истина; // Для проверки актуальности версии библиотеки
			Исключение
			КонецПопытки;
		КонецЕсли; 
		// такой способ почему то не работает
		//мADOUtils = ПолучитьОбъектВнешнейКомпонентыИзМакета(ИмяМакетаКомпоненты, , ИдентификаторКласса, ТипВнешнейКомпоненты.COM, ИмяМакетаДополнительнойБиблиотеки);
	КонецЕсли; 
	Если мADOUtils <> Неопределено Тогда
		мADOUtils.BinaryDataAsStrings = БинарныеВСтроку;
		мADOUtils.BinaryDataAs1C = Типизировать1С;
		мADOUtils.YearOffset = СмещениеГодаADO;
	КонецЕсли; 
	Возврат мADOUtils;

КонецФункции

//#КонецЕсли

Функция ИдентификаторыПроцессовОтладчиков() Экспорт
	
	Перем Результат;
	ПортДляПодключенияОтладчика(Результат);
	Возврат Результат;
	
КонецФункции

Функция ПортДляПодключенияОтладчика(выхИдентификаторыОтладчиков = Неопределено, выхПротокол = "") Экспорт
	
	Результат = "";
	ирОбщий.ПараметрыЗапускаСеансаТекущиеЛкс(Результат);
	ИдентификаторЭтогоПроцесса = ирКэш.ИдентификаторПроцессаОСЛкс();
	ТекстРезультата = ТекстРезультатаКомандыСистемы("netstat -n -a -o");
	выхИдентификаторыОтладчиков = Новый Массив;
	шАдресIP4 = "(?:[0-9]{1,3}\.){3}[0-9]{1,3}";
	Результат = ирОбщий.ТекстМеждуМаркерамиЛкс(Результат, "/DEBUGGERURL""", """");
	Если Истина
		И ЗначениеЗаполнено(Результат) 
		И ирОбщий.СтрокиРавныЛкс(ирОбщий.ПервыйФрагментЛкс(Результат, ":"), "http")
	Тогда
		// http://CORTEX:1550  
		выхПротокол = "http";
		ПортСервераОтладки = ирОбщий.ПоследнийФрагментЛкс(Результат, ":", Ложь);
		Если ПортСервераОтладки = "" Тогда
			ПортСервераОтладки = Неопределено;
		КонецЕсли; 
		RegExp.Global = Истина;
		шСоединениеССерверомОтладки = "TCP(?:\s+)(" + шАдресIP4 +"):(?:\d+)(?:\s+)" + шАдресIP4 + ":" + ПортСервераОтладки +"(?:\s+)ESTABLISHED(?:\s+)";
		RegExp.Pattern = шСоединениеССерверомОтладки + Формат(ИдентификаторЭтогоПроцесса, "ЧГ=");
		Вхождения = RegExp.НайтиВхождения(ТекстРезультата);
		Для Каждого Вхождение Из Вхождения Цикл
			ЛокальныйАдрес4 = Вхождение.SubMatches(0);
			Прервать;
		КонецЦикла;
		RegExp.Pattern = шСоединениеССерверомОтладки + "(\d+)";
		Вхождения = RegExp.НайтиВхождения(ТекстРезультата);
		Для Каждого Вхождение Из Вхождения Цикл
			ИдентификаторОтладчика = Вхождение.SubMatches(1);
			Если Истина
				И ИдентификаторОтладчика <> Формат(ИдентификаторЭтогоПроцесса, "ЧГ=")
				И выхИдентификаторыОтладчиков.Найти(ИдентификаторОтладчика) = Неопределено
			Тогда
				ПроцессОС = ирОбщий.ПолучитьПроцессОСЛкс(ИдентификаторОтладчика);
				Если Истина
					И ирОбщий.СтрокиРавныЛкс(ПроцессОС.Name, ирОбщий.ИмяИсполняемогоФайлаКлиентаПлатформыЛкс(Ложь))
					И ирОбщий.ЛиПроцессОСКонфигуратораЛкс(ПроцессОС)
				Тогда
					выхИдентификаторыОтладчиков.Добавить(ИдентификаторОтладчика);
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
		выхИдентификаторыОтладчиков.Добавить("0"); // Чтобы неоднозначность сохранялась и с одним найденным отладчиком
	Иначе
		выхПротокол = "tcp";
		RegExp.Global = Истина;
		RegExp.Pattern = "TCP(?:\s+)0\.0\.0\.0:(\d+)(?:\s+)" + шАдресIP4 + ":(\d+)(?:\s+)LISTENING(?:\s+)" + Формат(ИдентификаторЭтогоПроцесса, "ЧГ=");
		Вхождения = RegExp.НайтиВхождения(ТекстРезультата);
		МассивСлушающихПортов = Новый Массив;
		СтрокаПоиска = "";
		// Т.к. неясно какой из портов для отладки, используем все
		Для Каждого Вхождение Из Вхождения Цикл
			МассивСлушающихПортов.Добавить(Вхождение.SubMatches(0));
			СтрокаПоиска = СтрокаПоиска + "|" + Вхождение.SubMatches(0);
		КонецЦикла;
		Если МассивСлушающихПортов.Количество() = 0 Тогда
			Результат = Неопределено;
			Возврат Результат;
		КонецЕсли;
		СтрокаПоиска = Сред(СтрокаПоиска, 2);
		ЛокальныйАдрес = ирОбщий.ПодготовитьТекстДляРегВыраженияЛкс("127.0.0.1");
		RegExp.Pattern = "TCP(?:\s+)" + ЛокальныйАдрес + ":(?:\d+)(?:\s+)" + ЛокальныйАдрес + ":(" + СтрокаПоиска + ")(?:\s+)ESTABLISHED(?:\s+)(\d+)";
		Вхождения = RegExp.НайтиВхождения(ТекстРезультата);
		Для Каждого Вхождение Из Вхождения Цикл
			ИдентификаторКорреспондента = Вхождение.SubMatches(1);
			Если ИдентификаторКорреспондента <> Формат(ИдентификаторЭтогоПроцесса, "ЧГ=") Тогда
				выхИдентификаторыОтладчиков.Добавить(ИдентификаторКорреспондента);
			Иначе
				МассивСлушающихПортов.Удалить(МассивСлушающихПортов.Найти(Вхождение.SubMatches(0)));
			КонецЕсли;
		КонецЦикла;
		Если МассивСлушающихПортов.Количество() > 0 Тогда
			Результат = "tcp://127.0.0.1:" + МассивСлушающихПортов[0];
		КонецЕсли;
	КонецЕсли;
	Возврат Результат;
	
КонецФункции
	
#Если Клиент Тогда

//.
// Параметры:
//  ИмяФормы - Строка - 
// Возвращаемое значение:
//  Форма -
Функция ПассивнаяФормаПоИмениКэш(Знач ИмяФормы) Экспорт
	Результат = мПассивныеФормы[НРег(ИмяФормы)]; 
	Если Результат = Неопределено Тогда
		Попытка
			ОбъектМД = ирОбщий.ОбъектМДПоПолномуИмениЛкс(ИмяФормы);
			Если ОбъектМД <> Неопределено Тогда
				ИмяФормы = ОбъектМД.ПолноеИмя(); // Нормализуем имя, чтобы файл в кэше модулей имел оригинальные регистры букв
			КонецЕсли;
			Форма = ирКлиент.ПассивнаяФормаПоИмениЛкс(ИмяФормы);
		Исключение
			ОписаниеОшибки = ОписаниеОшибки(); // Для отладки
		КонецПопытки;
		Если Форма <> Неопределено Тогда
			СлужебныеДанные = ирОбщий.СлужебныеДанныеФормыЛкс(Форма);
			Результат = Форма;
		Иначе 
			СлужебныеДанные = Новый Структура;  
			Результат = СлужебныеДанные;
		КонецЕсли;
		Если Не СлужебныеДанные.Свойство("ИмяФормы") Тогда
			СлужебныеДанные.Вставить("ИмяФормы", ИмяФормы);
		КонецЕсли;
		ФайлФормы = ирКэш.Получить().ФайлМодуляИзИмениМодуля(СлужебныеДанные.ИмяФормы, "xml", Истина);
		Если ФайлФормы.Существует() Тогда 
			ИмитаторФормы = ирОбщий.ЗагрузитьЗначениеИзФайлаЛкс(ФайлФормы.ПолноеИмя); // Структура
			Если ИмитаторФормы.ВерсияФормата = ВерсияФорматаСтруктурыФормы() Тогда
				//ДатаОбновления = ФайлФормы.ПолучитьВремяИзменения();
				ДатаОбновления = Дата(1,1,1);
				ирКэш.Получить().ДополнитьСлужебныеДанныеИзКэшаФормы(СлужебныеДанные, ИмитаторФормы, ДатаОбновления);
			КонецЕсли;  
		КонецЕсли;
		Если Результат = СлужебныеДанные И Не СлужебныеДанные.Свойство("Тип") Тогда 
			СлужебныеДанные.Вставить("Тип", ирОбщий.ТипУправляемаяФормаЛкс());
		КонецЕсли; 
		мПассивныеФормы[НРег(ИмяФормы)] = Результат;
	КонецЕсли;
	Возврат Результат;
КонецФункции

Функция ПолучитьДокументDOMФормы(Форма) Экспорт 
	СтрокаФормы = ЗначениеВСтрокуВнутр(Форма);
	XMLСтрокаФормы = ирОбщий.СтрокаВнутрВХМЛТелоЛкс(СтрокаФормы);
	ЧтениеXML = Новый ЧтениеXML;
	ЧтениеXML.УстановитьСтроку(XMLСтрокаФормы);
	ПостроительDOM = Новый ПостроительDOM;
	ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
	Возврат ДокументDOM;
КонецФункции

Функция ПолучитьXPathИмениРеквизитаВОписанииРеквизита()

	ИДВерсииПлатформы = ирКэш.НомерИзданияПлатформыЛкс();
	Если ИДВерсииПлатформы = "81" Тогда
		Результат = "/d[3]";
	ИначеЕсли Ложь
		Или ИДВерсииПлатформы = "82"
		Или ИДВерсииПлатформы = "83"
	Тогда
		Результат = "/d[4]";
	КонецЕсли; 
	Возврат Результат;

КонецФункции // ПолучитьXPathИмениРеквизитаВОписанииРеквизита()

Функция ИмяОсновногоРеквизитаФормы(Знач ФормаИлиДокументDOM) Экспорт
	Возврат ИменаРеквизитовФормы(ФормаИлиДокументDOM).Основной;
КонецФункции

// Функция - Имена реквизитов формы
//
// Параметры:
//  ФормаИлиДокументDOM	 - 	 - 
//  ПутьКРодителю		 - Строка, Неопределено - если тип "Строка", то подразумевается управляемая форма, иначе - обычная форма
//  ЛиДляЭлементаКоллекции - Булево - пока не используем это разделение в имитаторе
// 
// Возвращаемое значение:
//   - 
//
Функция ИменаРеквизитовФормы(Знач ФормаИлиДокументDOM, Знач ПутьКРодителю = Неопределено, Знач ЛиДляКоллекции = Ложь, выхИдентификаторыРеквизитов = Неопределено, ДокументДОМ = Неопределено) Экспорт
	
	Если ПутьКРодителю <> Неопределено Тогда
		// Управляемая форма
		ИменаРеквизитов = Неопределено;
		КорневыеИменаРеквизитов = Неопределено;
		выхИдентификаторыРеквизитов = Новый Соответствие;
		ИмяОсновногоРеквизита = "";  
		ТипУправляемаяФорма = ирОбщий.ТипУправляемаяФормаЛкс();
		Форма = ФормаИлиДокументDOM;  
		Если Форма <> Неопределено Тогда
			СлужебныеДанные = ирОбщий.СлужебныеДанныеФормыЛкс(Форма); 
		Иначе 
			Пустышка = 0; // Для отладки. Желательно чтобы сюда не было приходов
		КонецЕсли;
		Если СлужебныеДанные = Неопределено Тогда
			// Редко. Открытая форма. Фактически не используем кэш
			СлужебныеДанные = Новый Структура;
		КонецЕсли;
		Если СлужебныеДанные.Свойство("КорневыеИменаРеквизитов") Тогда
			КорневыеИменаРеквизитов = СлужебныеДанные.КорневыеИменаРеквизитов.Все;
		КонецЕсли;
		Если ДокументДОМ = Неопределено И СлужебныеДанные.Свойство("ДокументДОМ") Тогда
			ДокументДОМ = СлужебныеДанные.ДокументДОМ;
		КонецЕсли;
		Если ТипЗнч(Форма) = ТипУправляемаяФорма И ДокументДОМ = Неопределено Тогда
			СтруктураТипа = НоваяСтруктураТипа("ФормаКлиентскогоПриложения");
			СтруктураТипа.Метаданные = Форма; 
			//МодульФормы = ПодготовитьМодульМетаданных(СтруктураТипа); // Раньше кэш ДокументДОМ хранился тут
			ЛюбыеДанныеФормы = Неопределено;
			КорневыеИменаРеквизитов = Новый Структура;
			ИмяМодуля = ИмяМодуляИзСтруктурыТипа(СтруктураТипа);
			КандидатыИменРеквизитов = ирОбщий.КандидатыИменОбъектныхРеквизитовФормыЛкс(Форма);
			ПолеТекстаПрограммы = Неопределено;
			МодульПроанализирован = Ложь;
			Пока Истина Цикл
				Для Каждого ИмяРеквизита Из КандидатыИменРеквизитов Цикл
					Попытка
						ЗначениеРеквизита = Форма[ИмяРеквизита];
					Исключение
						Продолжить;
					КонецПопытки;
					КорневыеИменаРеквизитов.Вставить(ИмяРеквизита);
					Если Истина
						И ТипЗнч(ЗначениеРеквизита) <> Тип("СписокЗначений")
						И мМассивТиповСМетаданными.Найти(ТипЗнч(ЗначениеРеквизита)) <> Неопределено 
					Тогда
						ЛюбыеДанныеФормы = ЗначениеРеквизита;
						Перейти ~Конец;
					КонецЕсли;
				КонецЦикла;
				Если МодульПроанализирован Тогда
					Прервать;
				КонецЕсли;
				Для Каждого ЭлементФормы Из Форма.Элементы Цикл
					ИмяРеквизита = ирОбщий.ПервыйФрагментЛкс(ирОбщий.ПутьКДаннымЭлементаУправляемойФормыЛкс(ЭлементФормы,, Форма));
					Если Истина
						И ЗначениеЗаполнено(ИмяРеквизита) 
						И Не КорневыеИменаРеквизитов.Свойство(ИмяРеквизита) 
					Тогда
						КорневыеИменаРеквизитов.Вставить(ИмяРеквизита);
						ЗначениеРеквизита = Форма[ИмяРеквизита];
						ТипЗначения = ТипЗнч(ЗначениеРеквизита);
						Если мМассивТиповСМетаданными.Найти(ТипЗначения) <> Неопределено Тогда  
							ИмяТипа = ирОбщий.ИмяТипаЛкс(ТипЗначения);
							Если МассивУправляемыхЭлементовУправления.Найти(ИмяТипа) = Неопределено Тогда
								ЛюбыеДанныеФормы = ЗначениеРеквизита;
								Перейти ~Конец;
							КонецЕсли;
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
				Если ЛюбыеДанныеФормы = Неопределено Тогда
					// Самый долгий способ
					ПолеТекстаМодуля = ПолеТекстаМодуля(ИмяМодуля);
					#Если Сервер И Не Сервер Тогда
						ПолеТекстаМодуля = Обработки.ирКлсПолеТекстаПрограммы.Создать();
					#КонецЕсли
					ТаблицаТипов = ДобавитьВТаблицуТипов(, СтруктураТипаИзКонкретногоТипа(ирОбщий.ТипУправляемаяФормаЛкс()));
					ПолеТекстаМодуля.ЗаполнитьТаблицуСлов(ТаблицаТипов,,, Ложь, Ложь);
					ПолеТекстаМодуля.ЗаполнитьЛокальныеСвойстваИМетодыПоТексту(Ложь, Ложь,,,,,, Истина);
					ПолеТекстаМодуля.мРодительскийКонтекст = "ЭтаФорма"; // TODO добавить слова от ЭтотОбъект
					ПолеТекстаМодуля.ЗаполнитьЛокальныеСвойстваИМетодыПоТексту(Ложь, Ложь, Истина, Ложь,,,, Истина);
					КандидатыИменРеквизитов = ПолеТекстаМодуля.ТаблицаСлов.Выгрузить(Новый Структура("Определение", "Статистический")).ВыгрузитьКолонку("НСлово");
					ВредныйКандидат = КандидатыИменРеквизитов.Найти(НРег("ЭтаФорма"));
					Если ВредныйКандидат <> Неопределено Тогда
						КандидатыИменРеквизитов.Удалить(ВредныйКандидат);
					КонецЕсли;
					ВредныйКандидат = КандидатыИменРеквизитов.Найти(НРег("ЭтотОбъект"));
					Если ВредныйКандидат <> Неопределено Тогда
						КандидатыИменРеквизитов.Удалить(ВредныйКандидат);
					КонецЕсли;
				КонецЕсли;
				МодульПроанализирован = Истина;
			КонецЦикла;
			~Конец:
			Если ЛюбыеДанныеФормы <> Неопределено Тогда
				ДокументДОМ = ирОбщий.ТекстВДокументDOMЛкс(ирОбщий.ОбъектВСтрокуXMLЛкс(ЛюбыеДанныеФормы)); // Обычно выполняется достаточно быстро
			КонецЕсли; 
		КонецЕсли;
		Если ПутьКРодителю = "" И Не ЛиДляКоллекции Тогда 
			ИменаРеквизитов = КорневыеИменаРеквизитов;
		КонецЕсли;
		Если ИменаРеквизитов = Неопределено Тогда
			ИменаРеквизитов = Новый Структура;
		КонецЕсли;
		Если СлужебныеДанные.Свойство("Реквизиты") Тогда
			ТаблицаРеквизитов = СлужебныеДанные.Реквизиты;
			Если ТаблицаРеквизитов <> Неопределено Тогда
				УспехРеквизита = Истина;
				Для Каждого ИмяРодителя Из ирОбщий.СтрРазделитьЛкс(НРег(ПутьКРодителю),,, Ложь) Цикл
					СтрокаРодителя = ТаблицаРеквизитов.Найти(ИмяРодителя, "НИмя");
					Если СтрокаРодителя = Неопределено Тогда
						УспехРеквизита = Ложь;
						Прервать;
					КонецЕсли;
					ТаблицаРеквизитов = СтрокаРодителя.Реквизиты;
				КонецЦикла;
				ЭтоКоллекция = Истина
					И СтрокаРодителя <> Неопределено 
					И ТипЗнч(СтрокаРодителя.Значение) <> Тип("Структура"); // Мультиметка7726614
				Если Истина
					И УспехРеквизита 
					И (Ложь
						Или ЛиДляКоллекции И ЭтоКоллекция
						Или Не ЛиДляКоллекции И Не ЭтоКоллекция)
				Тогда
					Для Каждого СтрокаРеквизита Из ТаблицаРеквизитов Цикл
						ОписаниеТипов = СтрокаРеквизита.ОписаниеТипов; // ОписаниеТипов
						Если СтрокаРеквизита.Значение = Неопределено Тогда 
							Если ОписаниеТипов = Неопределено Тогда
								//ОписаниеТипов = Новый ОписаниеТипов;
							Иначе 
								Типы = ОписаниеТипов.Типы();
								Если Типы.Количество() > 0 Тогда
									ТипЗначения = Типы[0];
									Если Ложь
										Или ирОбщий.ЛиНаборЗаписейРегистраЛкс(ТипЗначения) 
										//Или ирОбщий.ЛиТипОбъектаБДЛкс(ТипЗначения) // TODO сделать для объектов генерацию структуры их свойств
									Тогда
										ОписаниеТипов = ТаблицаТиповИзОписанияТипов(ОписаниеТипов);
										ОписаниеТипов[0].ИмяОбщегоТипа = "ДанныеФормыСтруктураСКоллекцией";
									КонецЕсли;
								КонецЕсли;
							КонецЕсли;
						Иначе 
							Если ТипЗнч(СтрокаРеквизита.Значение) = Тип("ТаблицаЗначений") Тогда
								СтруктураТипа = НоваяСтруктураТипа("ДанныеФормыКоллекция");
							ИначеЕсли ТипЗнч(СтрокаРеквизита.Значение) = Тип("ДеревоЗначений") Тогда
								СтруктураТипа = НоваяСтруктураТипа("ДанныеФормыДерево");
							Иначе 
								СтруктураТипа = СтруктураТипаИзЗначения(СтрокаРеквизита.Значение);
							КонецЕсли;
							СтруктураТипа.Метаданные = СтрокаРеквизита.Значение;
							ОписаниеТипов = ДобавитьВТаблицуТипов(, СтруктураТипа);
						КонецЕсли;
						ИменаРеквизитов.Вставить(СтрокаРеквизита.Имя, ОписаниеТипов);
					КонецЦикла;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
		Если ДокументДОМ <> Неопределено Тогда  
			Если ЗначениеЗаполнено(ПутьКРодителю) Тогда
				ПутьКРодителю = "." + ПутьКРодителю;
			КонецЕсли;
			Разыменователь = РазыменовательПространствИменDOM();
			Если ЛиДляКоллекции Тогда
				ПутьКРодителю = ПутьКРодителю + ".item";
			КонецЕсли;
			Выражение = "/*/*/*[@name=""root" + ПутьКРодителю + """]/*";
			НаборУзлов = ДокументДОМ.ВычислитьВыражениеXPath(Выражение, ДокументДОМ, Разыменователь, ТипРезультатаDOMXPath.Любой);
			УзелDOM = НаборУзлов.ПолучитьСледующий();
			Пока УзелDOM <> Неопределено Цикл
				ИмяРеквизита = УзелDOM.Атрибуты.ПолучитьИменованныйЭлемент("nameRu");
				Если ИмяРеквизита = Неопределено Тогда
					ИмяРеквизита = УзелDOM.Атрибуты.ПолучитьИменованныйЭлемент("name");
				КонецЕсли;
				Если ИмяРеквизита <> Неопределено Тогда
					ИмяРеквизита = ИмяРеквизита.ТекстовоеСодержимое;
					Если Истина
						И Найти(ИмяРеквизита, ".") = 0 // Защита от нахождения "root" + ПутьКРодителю
						И УзелDOM.ПервыйДочерний <> Неопределено 
					Тогда 
						Типы = Новый Массив;
						УзелТипаЗначения = УзелDOM.ПервыйДочерний.ПервыйДочерний;
						Если УзелТипаЗначения <> Неопределено Тогда
							ИменаТипов = ирОбщий.СтрРазделитьЛкс(УзелТипаЗначения.ТекстовоеСодержимое, " ");
							Если ИменаТипов.Количество() < 11 Тогда
								Для Каждого ИДТипа Из ИменаТипов Цикл
									Попытка
										Тип = ЗначениеИзСтрокиВнутр("{""T""," + ИДТипа + "}");
									Исключение
										Тип = Неопределено;
									КонецПопытки;
									Если Тип <> Неопределено Тогда
										Типы.Добавить(Тип);
									КонецЕсли;
								КонецЦикла;
							КонецЕсли;
						КонецЕсли;
						Если Истина
							И ПутьКРодителю = "" 
							И Типы.Количество() = 0 
							И ТипЗнч(Форма) = ТипУправляемаяФорма
						Тогда
							Типы.Добавить(ТипЗнч(Форма[ИмяРеквизита]));
						КонецЕсли;
						ИменаРеквизитов.Вставить(ИмяРеквизита, Новый ОписаниеТипов(Типы));
						выхИдентификаторыРеквизитов.Вставить(УзелDOM.Атрибуты[0].ТекстовоеСодержимое, ИмяРеквизита);
					КонецЕсли;
				КонецЕсли;
				УзелDOM = НаборУзлов.ПолучитьСледующий();
			КонецЦикла;
		КонецЕсли; 
		Если ТипЗнч(Форма) = ТипУправляемаяФорма И Форма.Открыта() Тогда
			// Нельзя размещать ДокументДОМ, т.к. он не сериализуется
		Иначе 
			СлужебныеДанные.Вставить("ДокументДОМ", ДокументДОМ);
		КонецЕсли;
	Иначе
		// Обычная форма
		ИменаРеквизитов = Новый Структура;
		ДокументДОМ = ФормаИлиДокументDOM;
		Если ТипЗнч(ФормаИлиДокументDOM) <> Тип("ДокументDOM") Тогда
			СлужебныеДанные = ирОбщий.СлужебныеДанныеФормыЛкс(ФормаИлиДокументDOM);
			Если СлужебныеДанные <> Неопределено Тогда
				Результат = Неопределено;
				Если СлужебныеДанные.Свойство("КорневыеИменаРеквизитов", Результат) Тогда
					Возврат Результат;
				КонецЕсли;
			КонецЕсли;
			ДокументДОМ = ПолучитьДокументDOMФормы(ФормаИлиДокументDOM);
		КонецЕсли;
		РазыменовательПИ = Новый РазыменовательПространствИменDOM(ДокументДОМ);
		
		СтрокаXPath = "/e[1]/e[1]/e[2]/e[2]/e" + ПолучитьXPathИмениРеквизитаВОписанииРеквизита() + "/text()";
		РезультатXPath = ДокументДОМ.ВычислитьВыражениеXPath(СтрокаXPath, ДокументДОМ, РазыменовательПИ, ТипРезультатаDOMXPath.НеупорядоченныйИтераторУзлов);
		Пока Истина Цикл
			Узел = РезультатXPath.ПолучитьСледующий();
			Если Узел = Неопределено Тогда
				Прервать;
			КонецЕсли;
			ИмяРеквизита = Узел.ТекстовоеСодержимое;
			Длина = СтрДлина(ИмяРеквизита);
			ИмяРеквизита = Сред(ИмяРеквизита, 2, Длина - 2);
			ИменаРеквизитов.Вставить(ИмяРеквизита);
		КонецЦикла;  
		
		ИмяЭлемента = "/e[1]/e[1]/e[2]/e[1]/d[1]/text()";
		РезультатXPath = ДокументДОМ.ВычислитьВыражениеXPath(ИмяЭлемента, ДокументДОМ, РазыменовательПИ, ТипРезультатаDOMXPath.Строка);
		КлючОсновногоРеквизита = РезультатXPath.СтроковоеЗначение;
		ИмяЭлемента = "/e[1]/e[1]/e[2]/e[2]/e/e[1]/d[1]/text()";
		РезультатXPath = ДокументДОМ.ВычислитьВыражениеXPath(ИмяЭлемента, ДокументДОМ, РазыменовательПИ,
			ТипРезультатаDOMXPath.УпорядоченныйИтераторУзлов);
		Счетчик = 1;
		Пока 1 = 1 Цикл
			Узел = РезультатXPath.ПолучитьСледующий();
			Если Узел = Неопределено Тогда
				Прервать;
			КонецЕсли;
			Если Узел.ТекстовоеСодержимое = КлючОсновногоРеквизита Тогда
				Прервать;
			КонецЕсли;
			Счетчик = Счетчик + 1;
		КонецЦикла;
		Если Узел <> Неопределено Тогда
			СтрокаXPath = "/e[1]/e[1]/e[2]/e[2]/e[" + Счетчик + "]" + ПолучитьXPathИмениРеквизитаВОписанииРеквизита() + "/text()";
			РезультатXPath = ДокументДОМ.ВычислитьВыражениеXPath(СтрокаXPath, ДокументДОМ, РазыменовательПИ, ТипРезультатаDOMXPath.Строка);
			Длина = СтрДлина(РезультатXPath.СтроковоеЗначение);
			ИмяОсновногоРеквизита = Сред(РезультатXPath.СтроковоеЗначение, 2, Длина - 2);
		КонецЕсли;
	КонецЕсли;
	Результат = Новый Структура;
	Результат.Вставить("Основной", ИмяОсновногоРеквизита);
	Результат.Вставить("Все", ИменаРеквизитов);
	Если СлужебныеДанные <> Неопределено И Не ЗначениеЗаполнено(ПутьКРодителю) Тогда
		СлужебныеДанные.Вставить("КорневыеИменаРеквизитов", Результат);
	КонецЕсли;
	Возврат Результат;

КонецФункции

//.
// Возвращаемое значение:
//    РазыменовательПространствИменDOM - 
Функция РазыменовательПространствИменDOM() Экспорт
	СоответствиеПИ = Новый Соответствие;
	СоответствиеПИ.Вставить("t", "http://v8.1c.ru/8.2/uobjects");
	СоответствиеПИ.Вставить("xs", "http://www.w3.org/2001/XMLSchema");
	СоответствиеПИ.Вставить("xsi", "http://www.w3.org/2001/XMLSchema-instance");
	Разыменователь = Новый РазыменовательПространствИменDOM(СоответствиеПИ);
	Возврат Разыменователь;
КонецФункции

//.
// Параметры:
//    Форма - Форма - 
// Возвращаемое значение:
//    Структура, Неопределено - 
Функция СтруктураТипаОбъектаОбычнойФормы(Знач Форма) Экспорт
	СлужебныеДанные = ирОбщий.СлужебныеДанныеФормыЛкс(Форма);
	СтруктураТипаОбъекта = Неопределено;
	Если Не СлужебныеДанные.Свойство("СтруктураТипаОбъекта", СтруктураТипаОбъекта) Тогда 
		ОсновнойРеквизитФормы = ИмяОсновногоРеквизитаФормы(Форма);
		Если ЗначениеЗаполнено(ОсновнойРеквизитФормы) Тогда
			СтруктураТипаОбъекта = СтруктураТипаИзЗначения(Форма[ОсновнойРеквизитФормы]);
			СлужебныеДанные.Вставить("СтруктураТипаОбъекта", СтруктураТипаОбъекта);
		КонецЕсли;
	КонецЕсли;
	Возврат СтруктураТипаОбъекта;
КонецФункции

//.
// Возвращаемое значение:
//    Структура - 
Функция ВсеИменаСтандартныхФорм() Экспорт   
	ВсеИменаСтандартныхФорм = Новый Структура;
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаОбъекта", "Форма объекта");
	ИменаСтандартныхФорм.Добавить("ФормаГруппы", "Форма группы");
	ИменаСтандартныхФорм.Добавить("ФормаСписка", "Форма списка");
	ИменаСтандартныхФорм.Добавить("ФормаВыбора", "Форма выбора");
	ИменаСтандартныхФорм.Добавить("ФормаВыбораГруппы", "Форма выбора группы");
	ВсеИменаСтандартныхФорм.Вставить("Справочник", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаСохранения", "Форма сохранения");
	ИменаСтандартныхФорм.Добавить("ФормаЗагрузки", "Форма выбора");
	ВсеИменаСтандартныхФорм.Вставить("ХранилищеНастроек", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаОбъекта", "Форма объекта");
	ИменаСтандартныхФорм.Добавить("ФормаСписка", "Форма списка");
	ИменаСтандартныхФорм.Добавить("ФормаВыбора", "Форма выбора");
	ВсеИменаСтандартныхФорм.Вставить("Документ", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаСписка", "Форма списка");
	ИменаСтандартныхФорм.Добавить("ФормаВыбора", "Форма выбора");
	ВсеИменаСтандартныхФорм.Вставить("Перечисление", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("Форма", "Форма");
	ИменаСтандартныхФорм.Добавить("ФормаНастроек", "Форма настроек");
	ИменаСтандартныхФорм.Добавить("ФормаВарианта", "Форма варианта");
	ВсеИменаСтандартныхФорм.Вставить("Отчет", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаЗаписи", "Форма записи");
	ИменаСтандартныхФорм.Добавить("ФормаСписка", "Форма списка");
	ВсеИменаСтандартныхФорм.Вставить("РегистрСведений", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаОбъекта", "Форма объекта");
	ИменаСтандартныхФорм.Добавить("ФормаГруппы", "Форма группы");
	ИменаСтандартныхФорм.Добавить("ФормаСписка", "Форма списка");
	ИменаСтандартныхФорм.Добавить("ФормаВыбора", "Форма выбора");
	ИменаСтандартныхФорм.Добавить("ФормаВыбораГруппы", "Форма выбора группы");
	ВсеИменаСтандартныхФорм.Вставить("ПланВидовХарактеристик", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаОбъекта", "Форма объекта");
	ИменаСтандартныхФорм.Добавить("ФормаСписка", "Форма списка");
	ИменаСтандартныхФорм.Добавить("ФормаВыбора", "Форма выбора");
	ВсеИменаСтандартныхФорм.Вставить("ПланСчетов", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаОбъекта", "Форма объекта");
	ИменаСтандартныхФорм.Добавить("ФормаСписка", "Форма списка");
	ИменаСтандартныхФорм.Добавить("ФормаВыбора", "Форма выбора");
	ВсеИменаСтандартныхФорм.Вставить("ПланВидовРасчета", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаОбъекта", "Форма объекта");
	ИменаСтандартныхФорм.Добавить("ФормаСписка", "Форма списка");
	ИменаСтандартныхФорм.Добавить("ФормаВыбора", "Форма выбора");
	ВсеИменаСтандартныхФорм.Вставить("БизнесПроцесс", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаОбъекта", "Форма объекта");
	ИменаСтандартныхФорм.Добавить("ФормаСписка", "Форма списка");
	ИменаСтандартныхФорм.Добавить("ФормаВыбора", "Форма выбора");
	ВсеИменаСтандартныхФорм.Вставить("Задача", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("ФормаСписка", "Форма списка");
	ВсеИменаСтандартныхФорм.Вставить("РегистрБухгалтерии", ИменаСтандартныхФорм);
	ВсеИменаСтандартныхФорм.Вставить("РегистрРасчета", ИменаСтандартныхФорм);
	ВсеИменаСтандартныхФорм.Вставить("РегистрНакопления", ИменаСтандартныхФорм);
	ИменаСтандартныхФорм = Новый СписокЗначений;
	ИменаСтандартныхФорм.Добавить("Форма", "Форма");
	ВсеИменаСтандартныхФорм.Вставить("КритерийОтбора", ИменаСтандартныхФорм);
	ВсеИменаСтандартныхФорм.Вставить("ЖурналДокументов", ИменаСтандартныхФорм);
	ВсеИменаСтандартныхФорм.Вставить("Обработка", ИменаСтандартныхФорм);
	Возврат ВсеИменаСтандартныхФорм;
КонецФункции

// Функция - Получить макет компоненты
//
// Параметры:
//  Компонента	 - ОбработкаОбъект, ОбработкаОбъект.ирКлсПолеТекстаПрограммы - 
// 
// Возвращаемое значение:
//   Форма - 
//
Функция ПолучитьМакетКомпоненты(Компонента) Экспорт

	Макет = 0;
	Если Не МакетыКомпонент.Свойство(Компонента.ИмяКласса, Макет) Тогда
		Макет = Компонента.ПолучитьФорму("ФормаМакет");
		Попытка
			Пустышка = Макет.мПлатформа;
			Успех = Истина;
		Исключение
			Успех = Ложь;
		КонецПопытки;
		Если Успех Тогда
			ирОбщий.СообщитьЛкс("Образована циклическая ссылка на ирПлатформа", СтатусСообщения.Внимание);
		КонецЕсли; 
		МакетыКомпонент.Вставить(Компонента.ИмяКласса, Макет);
	КонецЕсли;
	Возврат Макет;

КонецФункции

// <Описание функции>
//
// Параметры:
//  <Параметр1>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>;
//  <Параметр2>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>.
//
// Возвращаемое значение:
//               - <Тип.Вид> - <описание значения>
//                 <продолжение описания значения>;
//  <Значение2>  - <Тип.Вид> - <описание значения>
//                 <продолжение описания значения>.
//
Функция ПолучитьТекстМодуляВнешнейОбработкиАлгоритма(ФайлВнешнейОбработки) Экспорт

	Если Не ФайлВнешнейОбработки.Существует() Тогда
		Возврат Неопределено;
	КонецЕсли; 
	ТекстМодуля = ТекстМодуляСгенерированнойВнешнейОбработки(ФайлВнешнейОбработки);
	Если ТекстМодуля = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	ТекстАлгоритма = ирОбщий.ТекстМеждуМаркерамиЛкс(ТекстМодуля, МаркерНачалаАлгоритма, МаркерКонцаАлгоритма);
	Результат = "";
	ТекстАлгоритмаТД = Новый ТекстовыйДокумент;
	ТекстАлгоритмаТД.УстановитьТекст(ТекстАлгоритма);
	Для Счетчик = 1 По ТекстАлгоритмаТД.КоличествоСтрок() Цикл
		СтрокаАлгоритма = ТекстАлгоритмаТД.ПолучитьСтроку(Счетчик);
		Если Лев(СтрокаАлгоритма, 1) = Символы.Таб Тогда
			СтрокаАлгоритма = Сред(СтрокаАлгоритма, 2);
		КонецЕсли;
		Результат = Результат + СтрокаАлгоритма + Символы.ПС;
	КонецЦикла;
		
	Возврат Результат;

КонецФункции // ПолучитьТекстМодуляВнешнейОбработкиАлгоритма()

// <Описание функции>
//
// Параметры:
//  <Параметр1>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>;
//  <Параметр2>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>.
//
// Возвращаемое значение:
//               - <Тип.Вид> - <описание значения>
//                 <продолжение описания значения>;
//  <Значение2>  - <Тип.Вид> - <описание значения>
//                 <продолжение описания значения>.
//
Функция ТекстМодуляСгенерированнойВнешнейОбработки(ФайлВнешнейОбработки) Экспорт 

	#Если Сервер И Не Сервер Тогда
		ФайлВнешнейОбработки = Новый Файл;
	#КонецЕсли
	ИспользоватьБыструюРаспаковку = ЛиИспользоватьБыструюРаспаковкуВнешнейОбработки();
	Если Не ИспользоватьБыструюРаспаковку Тогда
		// Штатный способ платформы, но работает только на 8.3.8+
		ТекстЛога = Неопределено;
		ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
		Если Не ирОбщий.ВыполнитьКомандуКонфигуратораЛкс("/DumpExternalDataProcessorOrReportToFiles """ + ИмяВременногоФайла + """ """ + ФайлВнешнейОбработки.ПолноеИмя + """",, ТекстЛога, Истина) Тогда 
			УдалитьФайлы(ИмяВременногоФайла);
			ирОбщий.СообщитьЛкс(ТекстЛога);
			Возврат Ложь;
		КонецЕсли; 
		Файлы = НайтиФайлы(ИмяВременногоФайла, "ObjectModule.bsl", Истина);
		ТекстовыйДокумент = Новый ТекстовыйДокумент;
		ТекстовыйДокумент.Прочитать(Файлы[0].ПолноеИмя);
		ТекстМодуля = ТекстовыйДокумент.ПолучитьТекст();
	Иначе
		КаталогРаспаковки = ПолучитьИмяВременногоФайла();
		СоздатьКаталог(КаталогРаспаковки);
		РаспаковатьФайлВнешнейОбработки(ФайлВнешнейОбработки.ПолноеИмя, КаталогРаспаковки);
		ФайлТекстаМодуляОбработки = Новый Файл(КаталогРаспаковки + ирОбщий.РазделительПутиКФайлуЛкс() + СубПутьКФайлуПотокаМодуляВнешнейОбработки);
		ТекстовыйДокументМодуля = Новый ТекстовыйДокумент();
		ТекстовыйДокументМодуля.Прочитать(ФайлТекстаМодуляОбработки.ПолноеИмя);
		ТекстМодуля = ТекстовыйДокументМодуля.ПолучитьТекст();
		УдалитьФайлы(КаталогРаспаковки);
	КонецЕсли; 
	Возврат ТекстМодуля;

КонецФункции

// Открывает модуль внешней обработки алгоритма в конфигураторе.
//
// Параметры:
//  АлгоритмОбъект - СправочникОбъект.Сервисы2iS;
//  *НомерСтрокиВМодуле - Число, *0 - если указана, устанавливает текущую строку в модуле;
//  *ИдентификаторПроцесса - Число, *0 - если указан, будет открываться только в заданном процессе;
//  *Переоткрыть   - Булево, *Истина - переоткрыть, если уже открыт
//
Процедура ОткрытьАлгоритмВОтладчике(АлгоритмОбъект, НомерСтрокиВМодуле = 0, ИдентификаторПроцесса = 0, Переоткрыть = Истина) Экспорт 

	Если Не ВыполнятьАлгоритмыЧерезВнешниеОбработки Тогда
		ирОбщий.СообщитьЛкс("Данная функция доступна только в режиме выполнения сервисов через внешние обработки", СтатусСообщения.Информация);
		Возврат;
	КонецЕсли; 
	Если Не ФайловыйКэшАлгоритмовДопускаетРедактирование Тогда
		ирОбщий.СообщитьЛкс("Изменения файла будут игнорироваться, т.к. в настройках алгоритмов не включено разрешение редактирования файлового кэша",
			СтатусСообщения.Информация);
	КонецЕсли;
	ПолучитьФайлОткрывателя1С();
	ФайлВнешнейОбработки = ПолучитьОбновитьФайлВнешнейОбработкиАлгоритма(АлгоритмОбъект);
	Если ФайлВнешнейОбработки <> Неопределено Тогда
		СтрокаЗапуска = """" + ФайлОткрывателя1С.ПолноеИмя + """ -com -ob1""" + ФайлВнешнейОбработки.ПолноеИмя + """";
		Если ЗначениеЗаполнено(НомерСтрокиВМодуле) Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -num" + Формат(НомерСтрокиВМодуле, "ЧГ=");
		КонецЕсли;
		Если ЗначениеЗаполнено(ИдентификаторПроцесса) Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -pid" + Формат(ИдентификаторПроцесса, "ЧГ=");
		КонецЕсли;
		Если Переоткрыть Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -reopen";
		КонецЕсли;
		WshShell().Run(СтрокаЗапуска, 0, Ложь);
	КонецЕсли;

КонецПроцедуры 

Функция ПодключитьПерехватКлавиатуры(_НовоеЗначение = Неопределено) Экспорт 
	
	Если мПерехватКлавиатуры = Неопределено Тогда
		Попытка
			мПерехватКлавиатуры = Вычислить("ирПерехватКлавиатуры");
		Исключение
		КонецПопытки; 
	КонецЕсли;
	Если мПерехватКлавиатуры <> Неопределено Тогда
		Попытка
			Пустышка = мПерехватКлавиатуры.ЗахватРазрешен;
		Исключение     
			// Антибаг платформы 8.3.21 https://www.hostedredmine.com/issues/956250
			мПерехватКлавиатуры = Неопределено;
		КонецПопытки;
	КонецЕсли;
	Если мПерехватКлавиатуры = Неопределено Тогда
		Если Не ирКлиент.ЛиПерехватКлавиатурногоВводаЛкс() Тогда
			мПерехватКлавиатуры = Новый Структура("ЗахватПервым,СобытиеПриНажатии,ЗахватРазрешен");
			ПерехватКлавиатурногоВводаВОбычномПриложении = Ложь;
		Иначе
			мПерехватКлавиатуры = ПолучитьОбъектВнешнейКомпонентыИзМакета("KeyboardHook", "AddIn.ПерехватКлавиатуры.KeyboardHook", "ПерехватКлавиатуры", ТипВнешнейКомпоненты.Native);
		КонецЕсли; 
		Если мПерехватКлавиатуры = Неопределено Тогда
			ирОбщий.СообщитьЛкс("Не удалось подключить внешнюю компоненту ПерехватКлавиатуры. Поэтому некоторые функции инструментов отключены.", СтатусСообщения.Внимание);
			Возврат Неопределено;
		КонецЕсли; 
		мПерехватКлавиатуры.СобытиеПриНажатии = Истина;
		Попытка
			Выполнить("ирПерехватКлавиатуры = мПерехватКлавиатуры");
		Исключение
		КонецПопытки; 
	КонецЕсли; 
	мПерехватКлавиатуры.ЗахватРазрешен = ирКлиент.ЛиПерехватКлавиатурногоВводаЛкс();
	Возврат мПерехватКлавиатуры;

КонецФункции

Функция ИспользоватьЭмуляциюНажатияКлавиш(Обновить = Ложь) Экспорт
	Если ИспользоватьЭмуляциюНажатияКлавиш = Неопределено Или Обновить Тогда
		ИспользоватьЭмуляциюНажатияКлавиш = ирОбщий.ВосстановитьЗначениеЛкс("ИспользоватьЭмуляциюНажатияКлавиш") <> Ложь;
	КонецЕсли;  
	Возврат ИспользоватьЭмуляциюНажатияКлавиш;
КонецФункции

// Открывает модуль внешней обработки в конфигураторе.
//
// Параметры:
//  ПолноеИмяФайла - Строка;
//  *НомерСтрокиВМодуле - Число, *0 - если указана, устанавливает текущую строку в модуле;
//  *ИдентификаторПроцесса - Число, *0 - если указан, будет открываться только в заданном процессе;
//  *Переоткрыть   - Булево, *Истина - переоткрыть, если уже открыт
//
Процедура ОткрытьМодульВнешнейОбработкиВКонфигураторе(ПолноеИмяФайла, НомерСтрокиВМодуле = 0, ИдентификаторПроцесса = 0, _Переоткрыть = Истина, ВнутреннееИмя = "") Экспорт 

	ФайлВнешнейОбработки = Новый Файл(ПолноеИмяФайла);
	Если Ложь
		Или ирКэш.НомерВерсииПлатформыЛкс() >= 803008 И ирКэш.НомерВерсииPowerShellЛкс() >= 3
	Тогда
		Если Не ЗначениеЗаполнено(ИдентификаторПроцесса) Тогда
			ИдентификаторПроцесса = ВыбратьПроцессКонфигуратора();
			Если ИдентификаторПроцесса = Неопределено Тогда
				Возврат;
			КонецЕсли; 
		КонецЕсли; 
		ТекстСкрипта = ПолучитьМакет("СкриптОткрытьМодульВнешнейОбработки");
		ФайлСкрипта = Новый Файл(ПолучитьИмяВременногоФайла("ps1"));
		ТекстСкрипта.Записать(ФайлСкрипта.ПолноеИмя);
		СтрокаЗапуска = ирОбщий.КомандаСистемыЗапускаСкриптаPowerShellЛкс(ФайлСкрипта.Имя + " -processID " + ИдентификаторПроцесса + " -file """ + ПолноеИмяФайла + """");
		Если НомерСтрокиВМодуле > 0 Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -line " + Формат(НомерСтрокиВМодуле, "ЧГ=");
		КонецЕсли;
		Если ЗначениеЗаполнено(ВнутреннееИмя) Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -internalName """ + ВнутреннееИмя + """";
		КонецЕсли;
		//РезультатКоманды = ирОбщий.ВыполнитьКомандуОСЛкс(СтрокаЗапуска); // Так возникает 20с ожидание на инструкции $mainWindow = $rootElement.FindFirst(...)
		ЗапуститьПриложение(СтрокаЗапуска, КаталогВременныхФайлов());
	Иначе
		ПолучитьФайлОткрывателя1С();
		СтрокаЗапуска = """" + ФайлОткрывателя1С.ПолноеИмя + """ -com -ob1""" + ФайлВнешнейОбработки.ПолноеИмя + """";
		Если НомерСтрокиВМодуле > 0 Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -num" + Формат(НомерСтрокиВМодуле, "ЧГ=");
		КонецЕсли;
		Если ЗначениеЗаполнено(ИдентификаторПроцесса) Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -pid" + Формат(ИдентификаторПроцесса, "ЧГ=");
		КонецЕсли;
		//Если Переоткрыть Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -reopen";
		//КонецЕсли;
		WshShell().Run(СтрокаЗапуска, 0, Ложь);
	КонецЕсли; 

КонецПроцедуры

Функция ВыбратьПроцессКонфигуратора(Знач ИдентификаторыОтладчиков = Неопределено) Экспорт 
	
	Если ИдентификаторыОтладчиков = Неопределено Тогда
		ИдентификаторыОтладчиков = ИдентификаторыПроцессовОтладчиков();
		#Если Сервер И Не Сервер Тогда
			ИдентификаторыОтладчиков = Новый Массив;
		#КонецЕсли
	КонецЕсли; 
	ТекстСкрипта = ПолучитьМакет("СкриптОткрытыеПриложения1С");
	ФайлСкрипта = Новый Файл(ПолучитьИмяВременногоФайла("ps1"));
	ТекстСкрипта.Записать(ФайлСкрипта.ПолноеИмя);
	КомандаСистемыЗапускаСкрипта = ирОбщий.КомандаСистемыЗапускаСкриптаPowerShellЛкс(ФайлСкрипта.Имя);
	РезультатСкрипта = ирОбщий.ВыполнитьКомандуОСЛкс(КомандаСистемыЗапускаСкрипта);
	ТаблицаКонфигураторов = ирОбщий.ТаблицаИзСтрокиСРазделителемЛкс(РезультатСкрипта,,, Истина);
	НачальноеЗначениеВыбора = Неопределено;
	СписокКонфигураторов = Новый СписокЗначений;
	Для Каждого СтрокаКонфигуратора Из ТаблицаКонфигураторов Цикл
		ПроцессОС = ирОбщий.ПолучитьПроцессОСЛкс(СтрокаКонфигуратора.Id);
		Если Не ирОбщий.ЛиПроцессОСКонфигуратораЛкс(ПроцессОС) Тогда
			Продолжить;
		КонецЕсли; 
		ПредставлениеПроцесса = СтрокаКонфигуратора.MainWindowTitle;
		ЛиОтладчик = ИдентификаторыОтладчиков.Найти(СтрокаКонфигуратора.Id) <> Неопределено;
		Если ЛиОтладчик Тогда 
			ПредставлениеПроцесса = "<Отладчик>" + ПредставлениеПроцесса;
		КонецЕсли; 
		НовыйЭлемент = СписокКонфигураторов.Добавить(СтрокаКонфигуратора.Id, ПредставлениеПроцесса);
		Если ЛиОтладчик Тогда
			НачальноеЗначениеВыбора = НовыйЭлемент;
		КонецЕсли; 
	КонецЦикла;
	Если СписокКонфигураторов.Количество() = 1 Тогда
		РезультатВыбора = СписокКонфигураторов[0];
	ИначеЕсли СписокКонфигураторов.Количество() > 1 Тогда 
		РезультатВыбора = СписокКонфигураторов.ВыбратьЭлемент("Выберите окно конфигуратора", НачальноеЗначениеВыбора);
	Иначе
		РезультатВыбора = Неопределено;
	КонецЕсли; 
	Если РезультатВыбора <> Неопределено Тогда
		РезультатВыбора = РезультатВыбора.Значение;
	КонецЕсли;
	Возврат РезультатВыбора;

КонецФункции 

// Открывает файл в конфигураторе.
//
// Параметры:
//  ПолноеИмя    - Строка;
//  *ЭлементОбработки - "Форма", "Модуль", *Неопределено$
//  *ИдентификаторПроцесса - Число, *0 - если указан, будет открываться только в заданном процессе.
//
Процедура ОткрытьФайлВКонфигураторе(ПолноеИмя, ЭлементОбработки = "", ИдентификаторПроцесса = 0) Экспорт 

	ПолучитьФайлОткрывателя1С();
	ФайлВнешнейОбработки = Новый Файл(ПолноеИмя);
	Если ФайлВнешнейОбработки.Существует() Тогда
		СтрокаЗапуска = """" + ФайлОткрывателя1С.ПолноеИмя + """";
		Если ЭлементОбработки = "Форма" Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -cof";
		ИначеЕсли ЭлементОбработки = "Модуль" Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -com";
		Иначе
			СтрокаЗапуска = СтрокаЗапуска + " -coa";
		КонецЕсли;
		СтрокаЗапуска = СтрокаЗапуска + " -ob1""" + ПолноеИмя + """";
		Если ИдентификаторПроцесса > 0 Тогда
			СтрокаЗапуска = СтрокаЗапуска + " -pid" + Формат(ИдентификаторПроцесса, "ЧГ=");
		КонецЕсли;
		WshShell().Run(СтрокаЗапуска, 0, Ложь);
	КонецЕсли;

КонецПроцедуры

// Открывает диалог глобального поиска в конфигураторе и устанавливает каталог файлов.
//
// Параметры:
//  КаталогРасположения - Строка;
//  *ИдентификаторПроцесса - Число, *0 - если указан, будет открываться только в заданном процессе.
//
Процедура ОткрытьДиалогГлобальногоПоискаВКонфигураторе(КаталогРасположения, ИдентификаторПроцесса = 0) Экспорт 

	ПолучитьФайлОткрывателя1С();
	СтрокаЗапуска = """" + ФайлОткрывателя1С.ПолноеИмя + """";
	СтрокаЗапуска = СтрокаЗапуска + " -cgf";
	СтрокаЗапуска = СтрокаЗапуска + " -ob1""" + КаталогРасположения + """";
	Если ИдентификаторПроцесса > 0 Тогда
		СтрокаЗапуска = СтрокаЗапуска + " -pid" + Формат(ИдентификаторПроцесса, "ЧГ=");
	КонецЕсли;
	WshShell().Run(СтрокаЗапуска, 0, Ложь);

КонецПроцедуры // ОткрытьДиалогГлобальногоПоискаВКонфигураторе()

// Активизирует главное окно процесса по PID.
//
// Параметры:
//  *ИдентификаторПроцесса - Число.
//
Процедура АктивизироватьОкноПроцесса1С8(ИдентификаторПроцесса = 0) Экспорт 

	ПолучитьФайлОткрывателя1С();
	СтрокаЗапуска = """" + ФайлОткрывателя1С.ПолноеИмя + """";
	СтрокаЗапуска = СтрокаЗапуска + " -aaa -pid" + Формат(ИдентификаторПроцесса, "ЧГ=");
	WshShell().Run(СтрокаЗапуска, 0, Ложь);

КонецПроцедуры

Процедура ПодключитьСвязанныйКонфигуратор(Знач ИД, Знач ИмяФайлаБуфера) Экспорт 
	мСвязанныйКонфигуратор = Новый Структура("ИД, ИмяФайлаБуфера", ИД, ИмяФайлаБуфера);
КонецПроцедуры

Процедура АктивизироватьОкноКонфигуратора(Знач ПередаваемыйТекст = "") Экспорт 
	АктивизироватьОкноПроцесса1С8(мСвязанныйКонфигуратор.ИД);
	ТекстДок = Новый ТекстовыйДокумент;
	ТекстДок.УстановитьТекст(ПередаваемыйТекст);
	ТекстДок.Записать(мСвязанныйКонфигуратор.ИмяФайлаБуфера);
КонецПроцедуры

// <Описание процедуры>
//
// Параметры:
//  <Параметр1>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>;
//  <Параметр2>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>.
//
Процедура СохранитьНастройкиАлгоритмов() Экспорт 

	ирОбщий.СохранитьЗначениеЛкс("СинтаксическийКонтрольПередЗаписью", СинтаксическийКонтрольПередЗаписью);
	ирОбщий.СохранитьЗначениеЛкс("ВыполнятьАлгоритмыЧерезВнешниеОбработки", ВыполнятьАлгоритмыЧерезВнешниеОбработки);
	ирОбщий.СохранитьЗначениеЛкс("ФайловыйКэшАлгоритмовДопускаетРедактирование", ФайловыйКэшАлгоритмовДопускаетРедактирование);

КонецПроцедуры // СохранитьНастройкиАлгоритмов()

Функция ТаблицаРедактируемыхТиповИзОписанияТипов(ОписаниеТипов = Неопределено) Экспорт
	
	#Если Сервер И Не Сервер Тогда
		ОписаниеТипов = Новый ОписаниеТипов;
	#КонецЕсли
	ПоляКлюча = "Имя, URIПространстваИмен";
	Если мТаблицаРедактируемыхТипов = Неопределено Тогда
		мТаблицаРедактируемыхТипов = РедактируемыеТипы.ВыгрузитьКолонки();
		мТаблицаРедактируемыхТипов.Индексы.Добавить(ПоляКлюча);
		Для Каждого Тип Из ирОбщий.ОписаниеТиповВсеРедактируемыеТипыЛкс().Типы() Цикл
			СтрокаТипа = мТаблицаРедактируемыхТипов.Добавить();
			//СтрокаТипа.Представление = "" + Тип;
			ТипXML = СериализаторXDTO.XMLТип(Тип);
			Если Тип = Тип("Число") Тогда
				СтрокаТипа.Порядок = -4;
			ИначеЕсли Тип = Тип("Строка") Тогда
				СтрокаТипа.Порядок = -3;
			ИначеЕсли Тип = Тип("Дата") Тогда
				СтрокаТипа.Порядок = -2;
			ИначеЕсли Тип = Тип("Булево") Тогда
				СтрокаТипа.Порядок = -1;
			ИначеЕсли Найти(ТипXML.ИмяТипа, ".") > 0 Тогда
				СтрокаТипа.Порядок = 100;
				ОбъектМД = Метаданные.НайтиПоТипу(Тип);
				ТекущееИмяТипа = ОбъектМД.ПолноеИмя();
				ИмяТипаМетаданных = ирОбщий.ПервыйФрагментЛкс(ТекущееИмяТипа);
				СтрокаТипаМетаОбъектов = ОписаниеТипаМетаОбъектов(ИмяТипаМетаданных);
				Если СтрокаТипаМетаОбъектов <> Неопределено Тогда
					СтрокаТипа.ИндексКартинки = СтрокаТипаМетаОбъектов.ИндексКартинкиЕдинственное;
					СтрокаТипа.Порядок = СтрокаТипаМетаОбъектов.Владелец().Индекс(СтрокаТипаМетаОбъектов);
				КонецЕсли;
			КонецЕсли; 
			СтрокаТипа.Имя = ТипXML.ИмяТипа;
			СтрокаТипа.URIПространстваИмен = ТипXML.URIПространстваИмен;
			СтрокаТипа.Представление = "" + Тип;
		КонецЦикла;
	КонецЕсли;
	Если Ложь
		Или ОписаниеТипов = Неопределено 
		Или ОписаниеТипов.Типы().Количество() = 0
	Тогда
		НоваяТаблица = мТаблицаРедактируемыхТипов;
	Иначе
		СтрокиДляКопирования = Новый Массив;
		КлючПоиска = Новый Структура(ПоляКлюча);
		Для Каждого Тип Из ОписаниеТипов.Типы() Цикл
			ТипXML = СериализаторXDTO.XMLТип(Тип);
			Если ТипXML = Неопределено Тогда
				// Экзотические типы - Например НаправлениеСортировки
				Продолжить;
			КонецЕсли; 
			КлючПоиска.Имя = ТипXML.ИмяТипа;
			КлючПоиска.URIПространстваИмен = ТипXML.URIПространстваИмен;
			Найденные = мТаблицаРедактируемыхТипов.НайтиСтроки(КлючПоиска);
			Если Найденные.Количество() = 0 Тогда
				// Экзотические типы - например ТипИзмеренияПостроителяОтчета
				Продолжить;
			КонецЕсли; 
			СтрокиДляКопирования.Добавить(Найденные[0]);
		КонецЦикла;
		НоваяТаблица = мТаблицаРедактируемыхТипов.Скопировать(СтрокиДляКопирования);
	КонецЕсли;
	НоваяТаблица.Сортировать("Порядок, Представление");
	Возврат НоваяТаблица;
	
КонецФункции

Функция ЛиКомпонентаFormsTextBoxДоступна() Экспорт 
	
	Если ЛиКомпонентаFormsTextBoxДоступна = Неопределено Тогда
		ЛиКомпонентаFormsTextBoxДоступна = Истина;
		ИдентификаторКласса = "Forms.TextBox.1";
		Попытка
			Пустышка = Новый COMОбъект(ИдентификаторКласса);
		Исключение
			ИмяМакетаДополнительнойБиблиотеки = "FM20ENU";
			ИмяМакетаКомпоненты = "FM20";
			Пустышка = ПолучитьCOMОбъектИзМакета(ИмяМакетаКомпоненты, ИдентификаторКласса,, ИмяМакетаДополнительнойБиблиотеки);
			Если Пустышка = Неопределено Тогда
				ТекстСообщения = "Для полной функциональности контекстной подсказки нужно выполнить одно из условий:";
				#Если ТолстыйКлиентОбычноеПриложение Тогда
					Если Не ирКлиент.ЛиПерехватКлавиатурногоВводаВОбычномПриложенииЛкс() Тогда
						ТекстСообщения = ТекстСообщения + "
						|- Включить флажок ""Перехват клавиатурного ввода в обычном приложении"" в окне ""Список инструментов и общие настройки""";
					КонецЕсли;
				#КонецЕсли
				ТекстСообщения = ТекстСообщения + "
				|- Использовать 32б приложение и зарегистрировать библиотеки FM20.dll и FM20ENU.dll из состава MS Office 97-2007. Это можно сделать с помощью формы ""Регистрация COM-компонент"" из состава подсистемы";
				ирОбщий.СообщитьЛкс(ТекстСообщения);
				ЛиКомпонентаFormsTextBoxДоступна = Ложь;
			КонецЕсли; 
		КонецПопытки;
	КонецЕсли; 
	Возврат ЛиКомпонентаFormsTextBoxДоступна;
	
КонецФункции

#КонецЕсли

////////////////////////////////////////////////////////////////////////////////////////////////////

// Получает новый экземпляр ком-объекта парсера.
//
// Параметры:
//  Нет.
//
// Возвращаемое значение:
//  Com-объект, Неопределено.
//
Функция мПолучитьПарсер(ИмяГрамматики, Кэшировать = Истина, СообщениеПользователюПриНеудаче = "") Экспорт

	Если Кэшировать Тогда
		Если Парсеры.Свойство(ИмяГрамматики) Тогда
			Парсер = Парсеры[ИмяГрамматики];
			Если Парсер <> Неопределено Тогда
				Парсер.Restart(); // Без этого что то не очищается и приводит к зависанию парсинга.
			КонецЕсли; 
			Возврат Парсер;
		КонецЕсли; 
	КонецЕсли;
	Парсер = ПолучитьCOMОбъектИзМакета("GoldParser", "GoldParserForNet.Parser"); // Новый Parser
	Если Парсер <> Неопределено Тогда 
		Парсер.TrimReductions = Истина;
		МакетГрамматики = ПолучитьМакет(ИмяГрамматики);
		ФайлСкомпилированнойГрамматики = ПолучитьИмяВременногоФайла("cgt");
		МакетГрамматики.Записать(ФайлСкомпилированнойГрамматики);
		Если Не Парсер.LoadCompiledGrammar(ФайлСкомпилированнойГрамматики) Тогда
			ирОбщий.СообщитьСУчетомМодальностиЛкс("Не удалось загрузить файл грамматики """ + ФайлСкомпилированнойГрамматики + """",
				Истина, СтатусСообщения.Важное);
			Парсер = Неопределено;
		КонецЕсли;
		УдалитьФайлы(ФайлСкомпилированнойГрамматики);
	Иначе
		ирОбщий.СообщитьЛкс(СообщениеПользователюПриНеудаче, СтатусСообщения.Внимание);
	КонецЕсли;
	Если Кэшировать Тогда
		Парсеры.Вставить(ИмяГрамматики, Парсер);
	КонецЕсли;
	Возврат Парсер;

КонецФункции

// <Описание  процедуры>
//
// Параметры:
//  <Параметр1>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>;
//  <Параметр2>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>.
//
Процедура ПроверитьСтруктуруФайловогоКэша() Экспорт 

	ПроверитьКаталогФайловогоКэша();
	СтруктураПодкаталоговФайловогоКэша = Новый Структура;
	СтруктураПодкаталоговФайловогоКэша.Вставить("a"); // Внешние обработки алгоритмов
	//СтруктураПодкаталоговФайловогоКэша.Вставить("b"); // Внешние обработки архива 2iS 
	СтруктураПодкаталоговФайловогоКэша.Вставить("c"); // Внешние компоненты
	СтруктураПодкаталоговФайловогоКэша.Вставить("КэшМодулей"); 
	СтруктураПодкаталоговФайловогоКэша.Вставить("КэшРолей"); 
	Разделитель = ирОбщий.РазделительПутиКФайлуЛкс();
	Для Каждого ЭлементПодкаталога Из СтруктураПодкаталоговФайловогоКэша Цикл
		ПолныйПутьКаталога = КаталогФайловогоКэша + Разделитель + ЭлементПодкаталога.Ключ;
		ФайлКаталога = Новый Файл(ПолныйПутьКаталога);
		Если Не ФайлКаталога.Существует() Тогда
			Попытка
				СоздатьКаталог(ФайлКаталога.ПолноеИмя);
				ПробныйФайл = Новый ТекстовыйДокумент;
				ПробныйФайл.Записать(ФайлКаталога.ПолноеИмя + Разделитель + "1.txt");
			Исключение
				ОписаниеОшибки = ОписаниеОшибки();
				Сообщить("Файловый кэш """ + ЭлементПодкаталога.Ключ + """ отключен из-за ошибки: " + ОписаниеОшибки, СтатусСообщения.Важное); // При использовании ирОбщий.СообщитьЛкс() может происходить переполнение стека
				Продолжить;
			КонецПопытки;
		КонецЕсли;
		СтруктураПодкаталоговФайловогоКэша[ЭлементПодкаталога.Ключ] = ФайлКаталога;
		Если ЭлементПодкаталога.Ключ = "a" Тогда
			//КаталогДинамическихВнешнихОбработок = ПолныйПутьКаталога;
			ПапкаКешаВнешнихОбработокАлгоритмов = ФайлКаталога;
			
			ТекущаяДатаДвижка = Дата("20100927"); // Здесь меняем редко. Будет приводить к разовой очистке кэша перед началом его использования
			ФайлКэшаДвижка = Новый Файл(ПолныйПутьКаталога + Разделитель + "_EngineTimeStamp.mll");
			ДатаКэшаДвижка = Неопределено;
			Если ФайлКэшаДвижка.Существует() Тогда
				Попытка
					ДатаКэшаДвижка = ЗначениеИзФайла(ФайлКэшаДвижка.ПолноеИмя);
				Исключение КонецПопытки;
			КонецЕсли;
			Если ДатаКэшаДвижка <> ТекущаяДатаДвижка Тогда
				Попытка
					УдалитьФайлы(ПолныйПутьКаталога + Разделитель, "*.*");
				Исключение
					Неудача = Истина;
				КонецПопытки; 
				Если Неудача <> Истина Тогда
					ЗначениеВФайл(ФайлКэшаДвижка.ПолноеИмя, ТекущаяДатаДвижка);
				КонецЕсли; 
			КонецЕсли;
		//ИначеЕсли ЭлементПодкаталога.Ключ = "b" Тогда
		//	ПапкаКешаВнешнихОбработокАрхива = ФайлКаталога;
		ИначеЕсли ЭлементПодкаталога.Ключ = "c" Тогда
			ПапкаВнешнихКомпонент = ФайлКаталога;
		ИначеЕсли ЭлементПодкаталога.Ключ = "КэшМодулей" Тогда
			ПапкаКэшаМодулей = ФайлКаталога;
		ИначеЕсли ЭлементПодкаталога.Ключ = "КэшРолей" Тогда
			ПапкаКэшаРолей = ФайлКаталога;
		КонецЕсли;
	КонецЦикла;
	
	ПутьККаталогуСлужебныхВременныхФайлов = КаталогВременныхФайлов() + "temp1template\";
	СоздатьКаталог(ПутьККаталогуСлужебныхВременныхФайлов);
	МассивЗамков = НайтиФайлы(ПутьККаталогуСлужебныхВременныхФайлов, "*.lck");
	Для Каждого Замок Из МассивЗамков Цикл
		Попытка
			УдалитьФайлы(Замок.ПолноеИмя);
			УдалитьФайлы(Замок.Путь + Замок.ИмяБезРасширения);
		Исключение
		КонецПопытки; 
	КонецЦикла;
	НастройкиКомпьютера();
	
КонецПроцедуры

Функция ФайлРоли(Знач ИмяРоли) Экспорт 
	
	ФайлРоли = Новый Файл("" + ПапкаКэшаРолей.ПолноеИмя + "\Role." + ИмяРоли + ".Rights.xml");
	Возврат ФайлРоли;

КонецФункции

Функция СловарьПеревода() Экспорт 
	
	Если мСловарьПеревода = Неопределено Тогда
		Результат = ПолучитьМакет("РусскийАнглийский");
		СловарьПеревода = ирОбщий.ТаблицаЗначенийИзТабличногоДокументаЛкс(Результат,,,,,,, Истина);
		ирОбщий.ОбновитьКопиюКолонкиВНижнемРегистреЛкс(СловарьПеревода, "Русский");
		ирОбщий.ОбновитьКопиюКолонкиВНижнемРегистреЛкс(СловарьПеревода, "Английский");
		//! СловарьПеревода.Колонки.Добавить("НРусский")
		//! СловарьПеревода.Колонки.Добавить("НАнглийский")
		мСловарьПеревода = СловарьПеревода;
	КонецЕсли; 
	Возврат мСловарьПеревода;
	
КонецФункции

Функция ПеревестиСтроку(РусскаяСтрока, Принудительно = Ложь) Экспорт 

	Если Не Принудительно И Метаданные.ВариантВстроенногоЯзыка = Метаданные.СвойстваОбъектов.ВариантВстроенногоЯзыка.Русский Тогда
		Возврат РусскаяСтрока;
	Иначе
		Словарь = СловарьПеревода();
		СтрокаПеревода = Словарь.Найти(НРег(РусскаяСтрока), "НРусский");
		Если СтрокаПеревода = Неопределено Тогда
			Английский = РусскаяСтрока;
		Иначе
			Английский = СтрокаПеревода.Английский;
		КонецЕсли; 
		Возврат Английский;
	КонецЕсли; 

КонецФункции

Функция ПеревестиВРусский(ЛокальнаяСтрока, Принудительно = Ложь) Экспорт 

	Если Не Принудительно И Метаданные.ВариантВстроенногоЯзыка = Метаданные.СвойстваОбъектов.ВариантВстроенногоЯзыка.Русский Тогда
		Возврат ЛокальнаяСтрока;
	Иначе
		Словарь = СловарьПеревода();
		СтрокаПеревода = Словарь.НайтиСтроки(Новый Структура("НАнглийский", НРег(ЛокальнаяСтрока)));
		КоличествоПереводов = СтрокаПеревода.Количество();
		Если КоличествоПереводов = 0 Тогда
			Русский = ЛокальнаяСтрока; 
		Иначе
			Русский = СтрокаПеревода[0].Русский;
			Если КоличествоПереводов > 1 Тогда
				ирОбщий.СообщитьЛкс("Неоднозначный перевод на русский идентификатора """ + ЛокальнаяСтрока + """", СтатусСообщения.Внимание);
			КонецЕсли; 
		КонецЕсли; 
		Возврат Русский;
	КонецЕсли; 

КонецФункции

Функция ТекстРезультатаКомандыСистемы(Знач Команда = "", Знач ИмяСервера = "", Элевация = Ложь) Экспорт
	
	Если Не ЗначениеЗаполнено(ИмяСервера) Тогда
		ФайлРезультата = Новый Файл(ПолучитьИмяВременногоФайла());
		СтрокаЗапуска = Команда;
		ирОбщий.ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс(СтрокаЗапуска, ФайлРезультата.Путь, ФайлРезультата.Имя, , Элевация);
		Если ФайлРезультата.Существует() Тогда 
			ТекстовыйДокумент = Новый ТекстовыйДокумент;
			ТекстовыйДокумент.Прочитать(ФайлРезультата.ПолноеИмя, КодировкаТекста.OEM);
			УдалитьФайлы(ФайлРезультата.ПолноеИмя);
			Результат = ТекстовыйДокумент.ПолучитьТекст();
		Иначе
			Результат = "Файл результата команды системы не найден! Попробуйте отключить антивирусное ПО.";
		КонецЕсли;
	Иначе
		ВызватьИсключение "Получение результата команды системы на удаленном сервере не реализовано";
	КонецЕсли;
	Возврат Результат;
	
КонецФункции

Функция ЗарегистрироватьПолучитьCOMОбъект(КлассКомпоненты, ПолноеИмяDll, Административная = Ложь, ИмяТипаВК = Ложь, ИмяМакетаКомпоненты = "", Знач Зарегистрировать = Истина) Экспорт
	
	Если ирКэш.Это64битныйПроцессЛкс() Тогда 
		ТипПроцесса = "64";
	Иначе
		ТипПроцесса = "32";
	КонецЕсли; 
	Если Найти(КлассКомпоненты, "ForNet") > 0 Тогда
		ТипCOMКомпоненты = "-Net";
	Иначе
		ТипCOMКомпоненты = "";
	КонецЕсли; 
	Если Зарегистрировать Тогда
		ПрефикДействия = "За";
	Иначе
		ПрефикДействия = "Раз";
	КонецЕсли; 
	Если Истина
		И Не Административная 
		И Зарегистрировать
		И ЗначениеЗаполнено(ИмяМакетаКомпоненты) 
	Тогда
		Если Метаданные().Макеты.Найти(ИмяМакетаКомпоненты + "Reg") <> Неопределено Тогда 
			// http://stackoverflow.com/questions/37193356/registering-net-com-dlls-without-admin-rights-regasm
			// http://stackoverflow.com/questions/35782404/registering-a-com-without-admin-rights
			СкриптРегистрации = ПолучитьМакет(ИмяМакетаКомпоненты + "Reg").ПолучитьТекст();
			СкриптРегистрации = ирОбщий.СтрЗаменитьЛкс(СкриптРегистрации, "HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER\Software\Classes");
			РезультатКоманды = ВнестиФайлCOMКомпонентыВРеестр(СкриптРегистрации, СтрЗаменить(ПолноеИмяDll, "\", "/"));
			Компонента = ПолучитьПроверитьCOMОбъект(КлассКомпоненты, ИмяТипаВК);
			Если Компонента <> Неопределено Тогда 
				ирОбщий.СообщитьЛкс(ПрефикДействия + "регистрирована COM" + ТипCOMКомпоненты + "-компонента " + КлассКомпоненты, СтатусСообщения.Информация);
				Возврат Компонента;
			Иначе
				ирОбщий.СообщитьЛкс(РезультатКоманды);
			КонецЕсли;
		КонецЕсли; 
	КонецЕсли; 
	Если ТипCOMКомпоненты = "-Net" Тогда
		Если Административная Тогда
			Если ФайлРегистратораNetКомпонент = Неопределено Тогда
				ФайлРегистратораNetКомпонент = ПроверитьЗаписатьКомпонентуИзМакетаВФайл("RegasmExeWin" + ТипПроцесса, , "exe");
			КонецЕсли;
			КоманднаяСтрока = """" + ФайлРегистратораNetКомпонент.ПолноеИмя + """ """ + ПолноеИмяDll + """ /unregister"; // сначала надо отменить регистрацию, иначе новая может не выполниться
			ИмяФайлаРезультата = "";
			РезультатКоманды = ТекстРезультатаКомандыСистемы(КоманднаяСтрока,, Административная);
			Если Зарегистрировать Тогда
				КоманднаяСтрока = """" + ФайлРегистратораNetКомпонент.ПолноеИмя + """ """ + ПолноеИмяDll + """ /codebase";
				ИмяФайлаРезультата = "";
				РезультатКоманды = ТекстРезультатаКомандыСистемы(КоманднаяСтрока,, Административная);
				Компонента = ПолучитьПроверитьCOMОбъект(КлассКомпоненты, ИмяТипаВК);
			КонецЕсли; 
			Если Компонента <> Неопределено Тогда 
				ирОбщий.СообщитьЛкс(ПрефикДействия + "регистрирована COM" + ТипCOMКомпоненты + "-компонента " + КлассКомпоненты, СтатусСообщения.Информация);
				Возврат Компонента;
			Иначе
				ирОбщий.СообщитьЛкс(РезультатКоманды);
			КонецЕсли;
		КонецЕсли; 
	Иначе
		Если Административная Тогда
			// HKLM
			КоманднаяСтрока = "regsvr32 /s """ + ПолноеИмяDll + """";
			Если Не Зарегистрировать Тогда
				КоманднаяСтрока = КоманднаяСтрока + " /u";
			КонецЕсли; 
			//ТекстРезультата = ТекстРезультатаКомандыСистемы(КоманднаяСтрока);
			ирОбщий.ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс(КоманднаяСтрока,,,, Административная);
			Компонента = ПолучитьПроверитьCOMОбъект(КлассКомпоненты, ИмяТипаВК);
			Если Компонента <> Неопределено Тогда 
				ирОбщий.СообщитьЛкс(ПрефикДействия + "регистрирована COM" + ТипCOMКомпоненты + "-компонента " + КлассКомпоненты, СтатусСообщения.Информация);
				Возврат Компонента;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли; 
	//Если ирКэш.Это64битныйПроцессЛкс() Тогда
	//	ирОбщий.СообщитьЛкс("Невозможно загрузить 32-битную COM" + ТипCOMКомпоненты + "-компоненту " + КлассКомпоненты + " в 64-битном приложении. Запустите 32-битное приложение.", СтатусСообщения.Внимание);
	//Иначе
		ТекстСообщения = "Не удалось " + ПрефикДействия + "регистрировать COM" + ТипCOMКомпоненты + "-компоненту " + КлассКомпоненты;
		Если Истина
			И Административная
			И (Ложь
				Или ирОбщий.ВКОбщаяЛкс().IsAdmin() 
				//Или ЕстьАдминистративныеПраваУУчетнойЗаписиОС()
				) 
		Тогда
			ТекстСообщения = ТекстСообщения + " от имени администратора!"
		Иначе
			ТекстСообщения = ТекстСообщения + ". Запустите приложение от имени администратора или используйте инструмент ""Регистрация COM-компонент"", чтобы ее " + ПрефикДействия + "регистрировать"
		КонецЕсли; 
	//КонецЕсли; 
	ирОбщий.СообщитьЛкс(ТекстСообщения, СтатусСообщения.Внимание);
	Возврат Неопределено;
	
КонецФункции

Функция ВнестиФайлCOMКомпонентыВРеестр(Знач СкриптРегистрации, Знач ПолноеИмяDll, Знач ИдентификаторКласса = "", Знач x64 = Неопределено) Экспорт 
	
	Если x64 = Неопределено Тогда
		x64 = ирКэш.Это64битныйПроцессЛкс();
	КонецЕсли; 
	СкриптРегистрации = ирОбщий.СтрЗаменитьЛкс(СкриптРегистрации, "%ComDllFilename%", ПолноеИмяDll);
	Если ЗначениеЗаполнено(ИдентификаторКласса) Тогда
		СкриптРегистрации = ирОбщий.СтрЗаменитьЛкс(СкриптРегистрации, "%ComDllCLSID%", ИдентификаторКласса);
	КонецЕсли; 
	ИмяФайлаСкрипта = ПолучитьИмяВременногоФайла("reg");
	ТекстовыйДокумент = Новый ТекстовыйДокумент;
	ТекстовыйДокумент.УстановитьТекст(СкриптРегистрации);
	ТекстовыйДокумент.Записать(ИмяФайлаСкрипта, КодировкаТекста.ANSI);
	//РезультатКоманды = ТекстРезультатаКомандыСистемы("regedit /s """ + ИмяФайлаСкрипта + """); // Поддержка Windows XP
	РезультатКоманды = ТекстРезультатаКомандыСистемы("reg import """ + ИмяФайлаСкрипта + """ /reg:" + ?(x64, "64", "32")); // Windows Vista и выше
	Возврат РезультатКоманды;

КонецФункции

Функция ПолучитьПроверитьCOMОбъект(Знач КлассКомпоненты, ИмяТипаВК = "") Экспорт
	
	Если ЗначениеЗаполнено(ИмяТипаВК)  Тогда
		ПодключитьВнешнююКомпоненту(КлассКомпоненты);
		Попытка
			Компонента = Новый ("AddIn." + ИмяТипаВК);
		Исключение
		КонецПопытки; 
		Возврат Компонента;
	Иначе
		Попытка
			Компонента = Новый COMОбъект(КлассКомпоненты);
			Если КлассКомпоненты = "GoldParserForNet.Parser" Тогда
				Попытка
					Если Компонента.Version = "5.08" Тогда 
						Возврат Компонента;
					КонецЕсли; 
				Исключение
					Компонента = Неопределено;
				КонецПопытки;
			Иначе
				Возврат Компонента;
			КонецЕсли;
		Исключение
			ОписаниеОшибки = ОписаниеОшибки(); // Для отладки
		КонецПопытки;
	КонецЕсли; 
	Возврат Неопределено;
	
КонецФункции

// Возвращает нужный com-объект. Если компонента не зарегистрирована, то пытается ее сохранить из макета и зарегистрировать.
//
// Параметры:
//  Нет.
//
// Возвращаемое значение:
//  COM-объект, Неопределено.
//
Функция ПолучитьCOMОбъектИзМакета(ИмяМакетаКомпоненты, КлассКомпоненты, КаталогУстановки = "авто", ИмяМакетаДополнительнойБиблиотеки = "",
	ИмяТипаВК = "") Экспорт

	Результат = ПолучитьПроверитьCOMОбъект(КлассКомпоненты, ИмяТипаВК);
	Если Результат = Неопределено И АвторегистрацияComКомпонент Тогда
		Если Нрег(КаталогУстановки) = Нрег("авто") Тогда
			КаталогУстановки = ПапкаВнешнихКомпонент.ПолноеИмя;
		КонецЕсли; 
		#Если Клиент Тогда
		Если КаталогУстановки = "" Тогда
			Ответ = Вопрос("Для работы данной функции необходимо зарегистрировать 
				//|(необходимы права локального администратора)
				|	COM-компоненту """ + ИмяМакетаКомпоненты + """. Выполнить регистрацию?",
				РежимДиалогаВопрос.ОКОтмена, 30, КодВозвратаДиалога.Отмена);
			Если Ответ = КодВозвратаДиалога.Отмена Тогда
				Возврат Неопределено;
			КонецЕсли;
			ВыборФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
			ВыборФайла.Заголовок = "Укажите папку, куда установить компоненту.";
			Если Не ВыборФайла.Выбрать() Тогда
				Возврат Неопределено;
			КонецЕсли;
			КаталогУстановки = ВыборФайла.Каталог;
		КонецЕсли;
		#КонецЕсли
		ФайлКомпоненты = ПроверитьЗаписатьКомпонентуИзМакетаВФайл(ИмяМакетаКомпоненты, КаталогУстановки);
		Если ЗначениеЗаполнено(ИмяМакетаДополнительнойБиблиотеки) Тогда
			ПроверитьЗаписатьКомпонентуИзМакетаВФайл(ИмяМакетаДополнительнойБиблиотеки, КаталогУстановки);
		КонецЕсли; 
		Результат = ЗарегистрироватьПолучитьCOMОбъект(КлассКомпоненты, ФайлКомпоненты.ПолноеИмя, , ИмяТипаВК, ИмяМакетаКомпоненты);
	КонецЕсли; 
	Возврат Результат;

КонецФункции

// Параметры:
//   ИмяКомпоненты - Строка - имя макета компоненты
//   КлассКомпоненты - Строка - имя 
//   ТипВнешнейКомпоненты - ТипВнешнейКомпоненты, * - по умолчанию Native
Функция ПолучитьОбъектВнешнейКомпонентыИзМакета(ИмяМакетаКомпоненты, ИмяОбъекта, ИмяКомпоненты = Неопределено, Знач ТипКомпоненты = Неопределено,
	ИмяМакетаДополнительнойБиблиотеки = "") Экспорт
	
	Если ТипКомпоненты = Неопределено Тогда
		ТипКомпоненты = ТипВнешнейКомпоненты.Native;
	КонецЕсли; 
	Попытка
		Результат = Новый (ИмяОбъекта);
	Исключение
		Если ИмяКомпоненты = Неопределено Тогда
			ИмяКомпоненты = ИмяМакетаКомпоненты;
		КонецЕсли;
		Если КодСимвола(ИмяМакетаКомпоненты, 1) >= 128 Тогда
			// https://www.hostedredmine.com/issues/890335
			ВызватьИсключение "Нельзя использовать кириллические буквы в именах файлов внешних компонент";
		КонецЕсли; 
		ФайлКомпоненты = ПроверитьЗаписатьКомпонентуИзМакетаВФайл(ИмяМакетаКомпоненты);
		Местоположение = ФайлКомпоненты.ПолноеИмя;
		Если ЗначениеЗаполнено(ИмяМакетаДополнительнойБиблиотеки) Тогда
			ФайлДополнительнойБиблиотеки = ПроверитьЗаписатьКомпонентуИзМакетаВФайл(ИмяМакетаДополнительнойБиблиотеки);
		КонецЕсли; 
		Успех = ПодключитьВнешнююКомпоненту(Местоположение, ИмяКомпоненты, ТипКомпоненты);
		ПодключитьВнешнююКомпоненту(ИмяОбъекта);
		Попытка
			Результат = Новый (ИмяОбъекта);
		Исключение
		КонецПопытки;
	КонецПопытки;
	Возврат Результат;
	
КонецФункции

Функция ПроверитьЗаписатьКомпонентуИзМакетаВФайл(Знач ИмяМакетаКомпоненты, КаталогУстановки = "", Расширение = "dll") Экспорт 

	Если Не ЗначениеЗаполнено(КаталогУстановки) Тогда
		КаталогУстановки = ПапкаВнешнихКомпонент.ПолноеИмя;
	КонецЕсли;
	ДвоичныеДанныеМакета = ПолучитьДвоичныеДанныеКомпоненты(ИмяМакетаКомпоненты);
	ФайлКомпоненты = Новый Файл(КаталогУстановки + ирОбщий.РазделительПутиКФайлуЛкс() + ИмяМакетаКомпоненты + "." + Расширение);
	ВременныйФайл = Новый Файл(ПолучитьИмяВременногоФайла());
	Попытка
		ДвоичныеДанныеМакета.Записать(ВременныйФайл.ПолноеИмя);
	Исключение
		ирОбщий.СообщитьЛкс("Не удалось создать временный файл компоненты """ + ИмяМакетаКомпоненты + """: " + ОписаниеОшибки(), СтатусСообщения.Внимание);
		Возврат Неопределено;
	КонецПопытки;
	Счетчик = 1;
	ФайлПодходит = Ложь;
	Пока ФайлКомпоненты.Существует() Цикл
		#Если Клиент Тогда
		СравнениеФайлов = Новый СравнениеФайлов;
		СравнениеФайлов.СпособСравнения = СпособСравненияФайлов.Двоичное;
		СравнениеФайлов.ПервыйФайл = ВременныйФайл.ПолноеИмя;
		СравнениеФайлов.ВторойФайл = ФайлКомпоненты.ПолноеИмя;
		Если СравнениеФайлов.Сравнить() Тогда
			ФайлПодходит = Истина;
			Прервать;
		КонецЕсли; 
		#Иначе
			// Внешняя компонента может собираться с одинаковым размером (сборщик ее дополняет пустотой до нужного размера)
			//Если ВременныйФайл.Размер() = ФайлКомпоненты.Размер() Тогда // Опасно. Переделать на Хэш
			//	ФайлПодходит = Истина;
			//	Прервать;
			//КонецЕсли; 
		#КонецЕсли
		Попытка
			УдалитьФайлы(ФайлКомпоненты.ПолноеИмя);
		Исключение
			ФайлКомпоненты = Новый Файл(КаталогУстановки + ирОбщий.РазделительПутиКФайлуЛкс() + ИмяМакетаКомпоненты +  "_" + Формат(Счетчик, "ЧГ=") + "." + Расширение);
			Счетчик = Счетчик + 1;
		КонецПопытки; 
	КонецЦикла; 
	Если Не ФайлПодходит Тогда
		Попытка
			ПереместитьФайлКакАдминистратор(ВременныйФайл.ПолноеИмя, ФайлКомпоненты.ПолноеИмя);
		Исключение
			УдалитьФайлы(ВременныйФайл.ПолноеИмя);
			ирОбщий.СообщитьЛкс("Файл """ + ФайлКомпоненты.ПолноеИмя + """ недоступен для изменения и не был перезаписан.", СтатусСообщения.Внимание);
			Возврат Неопределено;
		КонецПопытки; 
	КонецЕсли; 
	Возврат ФайлКомпоненты;

КонецФункции

// Способ через ZIP архив (32+64) появился только в 8.3
Функция ПолучитьДвоичныеДанныеКомпоненты(БазовоеИмяМакетаКомпоненты) Экспорт 
	
	Если Метаданные().Макеты.Найти(БазовоеИмяМакетаКомпоненты) = Неопределено Тогда
		Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
			БазовоеИмяМакетаКомпоненты = БазовоеИмяМакетаКомпоненты + "Win";
		Иначе
			БазовоеИмяМакетаКомпоненты = БазовоеИмяМакетаКомпоненты + "Lin";
		КонецЕсли; 
		Если ирКэш.Это64битныйПроцессЛкс() Тогда
			БазовоеИмяМакетаКомпоненты = БазовоеИмяМакетаКомпоненты + "64";
		Иначе
			БазовоеИмяМакетаКомпоненты = БазовоеИмяМакетаКомпоненты + "32";
		КонецЕсли; 
	КонецЕсли; 
	ДвоичныеДанныеМакета = ПолучитьМакет(БазовоеИмяМакетаКомпоненты);
	Возврат ДвоичныеДанныеМакета;

КонецФункции

// <Описание функции>
//
// Параметры:
//  <Параметр1>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>;
//  <Параметр2>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>.
//
// Возвращаемое значение:
//               - <Тип.Вид> - <описание значения>
//                 <продолжение описания значения>;
//  <Значение2>  - <Тип.Вид> - <описание значения>
//                 <продолжение описания значения>.
//
Функция СоздатьОбъектВнешнихМетаданных(ПолноеИмяФайла, МенеджерВнешнихОбъектов = Неопределено, Конвертировать = Истина) Экспорт

	Если МенеджерВнешнихОбъектов = Неопределено Тогда
		МенеджерВнешнихОбъектов = ВнешниеОбработки;
	КонецЕсли; 
	Попытка
		ВнешнийОбъект = МенеджерВнешнихОбъектов.Создать(ПолноеИмяФайла, Ложь);
	Исключение
		#Если Клиент Тогда
		ОписаниеОшибки = ОписаниеОшибки();
		Если Истина
			И Конвертировать
			И Найти(НРег(ОписаниеОшибки), НРег("не может быть прочитан")) > 0 
			//И ирКэш.НомерВерсииПлатформыЛкс() <> 802015 // Антибаг 8.2.15 http://partners.v8.1c.ru/forum/thread.jsp?id=1003164#1003164
		Тогда
			СтрокаЗапуска = "DESIGNER /ConvertFiles""" + ПолноеИмяФайла + """";
			ЗапуститьСистему(СтрокаЗапуска, Истина);
			ВнешнийОбъект = МенеджерВнешнихОбъектов.Создать(ПолноеИмяФайла, Ложь);
		Иначе
		#КонецЕсли 
			ВызватьИсключение;
		#Если Клиент Тогда
		КонецЕсли;
		#КонецЕсли 
	КонецПопытки;
	Возврат ВнешнийОбъект;

КонецФункции

Функция СоздатьВнешнююОбработкуАлгоритма(АлгоритмОбъект, ПолноеИмя) Экспорт 

	Попытка
		ВнешняяОбработка = СоздатьОбъектВнешнихМетаданных(ПолноеИмя);
		Результат = ВнешняяОбработка;
	Исключение
		ИнформацияОбОшибке = ИнформацияОбОшибке();
		ОписаниеОшибки = ирОбщий.ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке);
		Если Найти(НРег(ОписаниеОшибки), НРег("не может быть прочитана текущей версией")) > 0 Тогда
			УдалитьФайлы(ПолноеИмя);
		КонецЕсли; 
		
		СобытиеОшибки = "Ошибка создания внешнего объекта";
		ОписаниеОшибки = "Загрузка сервиса """ + АлгоритмОбъект.Наименование + """";
		Если ИнформацияОбОшибке.Причина <> Неопределено Тогда
			ОписаниеОшибки = ОписаниеОшибки + "
			|" + ПредставлениеИнформацииОбОшибке(ИнформацияОбОшибке.Причина);
		КонецЕсли;
		ОписаниеОшибки = СобытиеОшибки + ": " + ОписаниеОшибки;
		ОписаниеОшибки = ОписаниеОшибки + ": " + ИнформацияОбОшибке.Описание
			+ Символы.ПС + ИнформацияОбОшибке.ИсходнаяСтрока;
		ирОбщий.СообщитьЛкс(ОписаниеОшибки, СтатусСообщения.Важное);
		ЗаписьЖурналаРегистрации(СобытиеОшибки, УровеньЖурналаРегистрации.Ошибка, Метаданные.НайтиПоТипу(ТипЗнч(АлгоритмОбъект.Ссылка)),
			АлгоритмОбъект.Ссылка, ОписаниеОшибки);
		Результат = Неопределено;
	КонецПопытки;
	Возврат Результат;

КонецФункции // СоздатьВнешнююОбработкуАлгоритма()

// Проверяет актуальность кэша. Вызывается когда кэш в памяти уже точно не соотвествует объекту БД.
Функция ПроверитьАктуальностьКэшаВнешнейОбработки(ЭлементКэша, ДатаИзмененияКэша, ФайлВнешнейОбработки, ДатаИзмененияОбъекта, 
	КэшВнешнейОбработкиАктуален, ФайлВнешнейОбработкиАктуален, ФайловыйКэшДопускаетРедактирование) Экспорт

	Попытка
		ДатаИзмененияФайла = ФайлВнешнейОбработки.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс();
		ФайлВнешнейОбработкиСуществует = Истина;
	Исключение
		ФайлВнешнейОбработкиСуществует = Ложь;
	КонецПопытки;
	Если ФайлВнешнейОбработкиСуществует Тогда 
		Если Истина 
			И ЭлементКэша <> Неопределено
			И ЭлементКэша.ДатаИзменения >= ДатаИзмененияФайла
			И ЭлементКэша.ДатаИзменения >= ДатаИзмененияОбъекта
		Тогда
			КэшВнешнейОбработкиАктуален = Истина;
		ИначеЕсли Ложь
			Или (Истина
				И ЭлементКэша = Неопределено
				И ДатаИзмененияФайла = ДатаИзмененияОбъекта)
			Или (Истина 
				И ЭлементКэша <> Неопределено
				И ДатаИзмененияФайла = ЭлементКэша.ДатаИзменения 
				И ДатаИзмененияФайла = ДатаИзмененияОбъекта)
			Или (Истина
				И ФайловыйКэшДопускаетРедактирование
                И (Ложь
					Или (Истина
						И ЭлементКэша = Неопределено
						И ДатаИзмененияФайла >= ДатаИзмененияОбъекта)
					Или (Истина 
						И ЭлементКэша <> Неопределено
						И ДатаИзмененияФайла >= ЭлементКэша.ДатаИзменения 
						И ДатаИзмененияФайла >= ДатаИзмененияОбъекта)))
		Тогда
			ФайлВнешнейОбработкиАктуален = Истина;
			ДатаИзмененияКэша = ДатаИзмененияФайла;
		КонецЕсли;
	КонецЕсли;

КонецФункции // ПроверитьАктуальностьКэшаВнешнейОбработки()

// <Описание процедуры>
//
// Параметры:
//  <Параметр1>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>;
//  <Параметр2>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>.
//
Функция РазвернутьНовыйШаблонВнешнейОбработки(СМакетом = Ложь, ГлобальныйКлюч = Неопределено,
	ФайлСИменем, ТекстПотокаСИменем, Знач ДляИДВерсииПлатформы = "") Экспорт 

	Если ПустаяСтрока(ДляИДВерсииПлатформы) Тогда
		ДляИДВерсииПлатформы = ирКэш.НомерИзданияПлатформыЛкс();
	КонецЕсли; 
	Если ДляИДВерсииПлатформы = "83" Тогда
		ДляИДВерсииПлатформы = "82";
	КонецЕсли; 
	Если ГлобальныйКлюч = Неопределено Тогда
		ГлобальныйКлюч = "" + Новый УникальныйИдентификатор;
	КонецЕсли; 
	лПутьКШаблонуВнешнейОбработки = ПутьККаталогуСлужебныхВременныхФайлов + ГлобальныйКлюч;
	Файл = Новый Файл(ПолучитьИмяВременногоФайла());
	//ПолучитьМакет("ВнешняяОбработка").Записать(Файл.ПолноеИмя);
	Если СМакетом Тогда
		ИмяМакета = "ШаблонВнешнейОбработкиСМакетом";
	Иначе
		ИмяМакета = "ШаблонВнешнейОбработкиСервиса";
	КонецЕсли;
	ИмяМакета = ИмяМакета + ДляИДВерсииПлатформы;
	ПолучитьМакет(ИмяМакета).Записать(Файл.ПолноеИмя);
	ЧтениеZip = Новый ЧтениеZipФайла(Файл.ПолноеИмя);
	ЧтениеZip.ИзвлечьВсе(лПутьКШаблонуВнешнейОбработки);
	ФайлСИменем = Новый Файл(лПутьКШаблонуВнешнейОбработки + ирОбщий.РазделительПутиКФайлуЛкс() + СубПутьКФайлуПотокаЗаголовкаВнешнейОбработки);
	ПотокСИменемОбработки = Новый ТекстовыйДокумент;
	ПотокСИменемОбработки.Прочитать(ФайлСИменем.ПолноеИмя);
	ТекстПотокаСИменем = ПотокСИменемОбработки.ПолучитьТекст();
	СоздатьКомандныйФайлДляУпаковкиФайлаВнешнейОбработки(лПутьКШаблонуВнешнейОбработки);
	
	Возврат лПутьКШаблонуВнешнейОбработки;

КонецФункции

Процедура СоздатьКомандныйФайлДляУпаковкиФайлаВнешнейОбработки(Каталог, выхИмяКомандногоФайла = "") Экспорт

	Если Не ЗначениеЗаполнено(выхИмяКомандногоФайла) Тогда
		выхИмяКомандногоФайла = "pack.bat";
	КонецЕсли; 
	Разделитель = ирОбщий.РазделительПутиКФайлуЛкс();
	ПодготовитьПакер(Каталог);
	ТекстовыйДокумент = Новый ТекстовыйДокумент;
	ТекстовыйДокумент.УстановитьТекст("
	|FOR /D %%I IN (*.unp) DO " + ИмяФайлаПакера + " -pack    %%I %%~nI
	|FOR    %%I IN (*.und) DO " + ИмяФайлаПакера + " -deflate %%I %%~nI
	|" + ИмяФайлаПакера + " -pack .\ %1");
	ТекстовыйДокумент.Записать(Каталог + Разделитель + выхИмяКомандногоФайла, КодировкаТекста.ANSI);

КонецПроцедуры

Процедура ПодготовитьПакер(Знач Каталог)
	
	Разделитель = ирОбщий.РазделительПутиКФайлуЛкс();
	Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
		ДвоичныеДанны = ПолучитьМакет("V8unpackExeWin");
		ПолучитьМакет("Zlib1").Записать(Каталог + Разделитель + "Zlib1.dll");
	Иначе
		//Если ирКэш.Это64битнаяОСЛкс() Тогда // Зависит от COM
		Если ирКэш.Это64битныйПроцессЛкс() Тогда // В Linux равнозначно ирКэш.Это64битнаяОСЛкс()
			ДвоичныеДанны = ПолучитьМакет("V8unpackExeLinux64");
		Иначе
			ирОбщий.СообщитьЛкс("Механизм распаковки файлов платформы 1С для Linux не поддерживает 32-разрядные ОС");
			Возврат;
		КонецЕсли; 
	КонецЕсли;
	ПолноеИмяФайла = Каталог + ?(Прав(Каталог, 1) = Разделитель, "", Разделитель) + ИмяФайлаПакера;
	ДвоичныеДанны.Записать(ПолноеИмяФайла);
	Если Не ирКэш.ЛиПлатформаWindowsЛкс() Тогда
		ирОбщий.ВыполнитьКомандуОСЛкс("chmod +x " + ПолноеИмяФайла); // Установим признак "Исполняемый файл"
	КонецЕсли;

КонецПроцедуры

Процедура УпаковатьФайлВнешнейОбработки(КаталогРаспаковки, ПолноеИмяФайлаВнешнейОбработки) Экспорт

	Если ирОбщий.ПроверитьПлатформаНеWindowsЛкс() Тогда 
		Возврат;
	КонецЕсли; 
	ИмяКомандногоФайла = "";
	СоздатьКомандныйФайлДляУпаковкиФайлаВнешнейОбработки(КаталогРаспаковки, ИмяКомандногоФайла);
	ирОбщий.ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс(ИмяКомандногоФайла + " """ + ПолноеИмяФайлаВнешнейОбработки + """", КаталогРаспаковки);

КонецПроцедуры

// ПолноеИмяФайла - не должно содержать не английских букв
Процедура РаспаковатьФайлВнешнейОбработки(ПолноеИмяФайла, ПутьРаспаковки) Экспорт 

	Разделитель = ирОбщий.РазделительПутиКФайлуЛкс();
	ПодготовитьПакер(ПутьРаспаковки);
	ИмяФайлаЛога = "unpack.log";
	Если Истина
		//И Ложь // Для отладки
		И ирКэш.ЛиПлатформаWindowsЛкс()
		И ирКэш.ЛиДоступноВыполнениеКомандныхФайловЛкс()
	Тогда
		ИмяКомандногоФайла = "unpack.bat";
		ТекстовыйДокумент = Новый ТекстовыйДокумент;
		ТекстовыйДокумент.УстановитьТекст("
		|" + ИмяФайлаПакера + " -unpack  %1 .\
		|FOR %%I IN (*.data) DO " + ИмяФайлаПакера + " -undeflate %%I %%~nI.data.und
		|FOR %%I IN (*.und)  DO " + ИмяФайлаПакера + " -unpack    %%I %%~nI.und.unp
		|");
		ПолноеИмяКомандногоФайла = ПутьРаспаковки + Разделитель + ИмяКомандногоФайла;
		ТекстовыйДокумент.Записать(ПолноеИмяКомандногоФайла, КодировкаТекста.ANSI);
		ирОбщий.ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс(ИмяКомандногоФайла + " """ + ПолноеИмяФайла + """", ПутьРаспаковки, ИмяФайлаЛога);
	Иначе
		// Под Windows этот способ медленнее в 5 раз
		// У версии под Linux немного отличаются параметры запуска по сравнению с Windows https://github.com/e8tools/v8unpack
		ирОбщий.ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс("./" + ИмяФайлаПакера + " -unpack """ + ПолноеИмяФайла + """ ./", ПутьРаспаковки, ИмяФайлаЛога,,, Истина);
		Для Каждого Файл Из НайтиФайлы(ПутьРаспаковки, "*.data") Цикл
			#Если Сервер И Не Сервер Тогда
				Файл = Новый Файл;
			#КонецЕсли
			//  Можно наверное ускорить созданием командного файла
			ирОбщий.ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс("./" + ИмяФайлаПакера + " -undeflate " + Файл.Имя + " " + Файл.Имя + ".und", ПутьРаспаковки, ИмяФайлаЛога,,, Истина);
			ирОбщий.ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс("./" + ИмяФайлаПакера + " -unpack " + Файл.Имя + ".und " + Файл.Имя + ".und.unp", ПутьРаспаковки, ИмяФайлаЛога,,, Истина);
		КонецЦикла;
	КонецЕсли;
	ЧитатьЛог = Ложь; // Для отладки
	Если ЧитатьЛог Тогда
		ТекстовыйДокумент = Новый ТекстовыйДокумент;
		ТекстовыйДокумент.Прочитать(ПутьРаспаковки + Разделитель + ИмяФайлаЛога, ирОбщий.СистемнаяКодировкаТекстаОСЛкс());
		ТекстЛога = ТекстовыйДокумент.ПолучитьТекст(); 
	КонецЕсли; 
	УдалитьФайлы(ИмяФайлаЛога);

КонецПроцедуры

Функция ЛиИспользоватьБыструюРаспаковкуВнешнейОбработки() Экспорт 
	
	ИспользоватьБыстрыйГенератор = Истина;
	Если ирОбщий.СтрокиРавныЛкс(ирКэш.ТекущийСеансЛкс().ИмяПриложения, "1cv8") Тогда 
		// Антибаг 8.3.11-?. Testplatform@1c.ru - Support #17972. В обычном приложении на клиенте при повторном создании с одним именем файла и внутренней версией используются метаданные первой обработки в сеансе.
		// Начиная с 8.3.11 кэширование внешних обработок проверяет только Ид версии, которые в старом способе не меняются, поэтому на 8.3.11+ используется штатный долгий метод генерации внешней обработки
		ИспользоватьБыстрыйГенератор = ирКэш.НомерВерсииПлатформыЛкс() < 803011;
	КонецЕсли; 
	Возврат ИспользоватьБыстрыйГенератор;

КонецФункции

// <Описание функции>
//
// Параметры:
//  <Параметр1>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>;
//  <Параметр2>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>.
//
// Возвращаемое значение:
//               - <Тип.Вид> - <описание значения>
//                 <продолжение описания значения>;
//  <Значение2>  - <Тип.Вид> - <описание значения>
//                 <продолжение описания значения>.
//
Функция СформироватьВнешнююОбработку(Знач ФайлОбработки, Знач ИмяОбработки, Знач ТекстМодуля, Знач ТекстМакета = Неопределено, Знач ДляИДВерсииПлатформы = "", ИспользоватьБыструюРаспаковку = Неопределено) Экспорт
	
	#Если Сервер И Не Сервер Тогда
	    ФайлОбработки = Новый файл;
	#КонецЕсли
	//Если ИспользоватьБыструюРаспаковку = Неопределено Тогда
	//	ИспользоватьБыструюРаспаковку = ЛиИспользоватьБыструюРаспаковкуВнешнейОбработки();
	//КонецЕсли;
	ИспользоватьБыструюРаспаковку = Истина; // используется шаблон с макетом, то там надо добавить файл versions.data.und - https://github.com/e8tools/v8unpack/issues/69
	Если Не ИспользоватьБыструюРаспаковку Тогда
		// Штатный способ платформы, но работает только на 8.3.8+
		Если ТекстМакета <> Неопределено Тогда
			ВызватьИсключение "Парамер ТекстМакета для 8.3.11+ не поддерживается";
		КонецЕсли; 
		ШаблонВнешнейОбработки = ШаблоныВнешнейОбработки["8"]; 
		Если ШаблонВнешнейОбработки = Неопределено Тогда
			ИмяВременногоФайла = ПолучитьИмяВременногоФайла("epf");
			ПолучитьМакет("ВнешняяОбработка").Записать(ИмяВременногоФайла);
			ШаблонВнешнейОбработки = ПолучитьИмяВременногоФайла();
			СоздатьКаталог(ШаблонВнешнейОбработки);
			ТекстЛога = Неопределено;
			Если Не ирОбщий.ВыполнитьКомандуКонфигуратораЛкс("/DumpExternalDataProcessorOrReportToFiles """ + ШаблонВнешнейОбработки + """ """ + ИмяВременногоФайла + """",, ТекстЛога, Истина,,,,,,, Ложь) Тогда 
				УдалитьФайлы(ШаблонВнешнейОбработки);
				УдалитьФайлы(ИмяВременногоФайла);
				ирОбщий.СообщитьЛкс(ТекстЛога);
				Возврат Ложь;
			КонецЕсли; 
			ШаблоныВнешнейОбработки["8"] = ШаблонВнешнейОбработки;
		КонецЕсли; 
		Файлы = НайтиФайлы(ШаблонВнешнейОбработки, "ObjectModule.bsl", Истина);
		ТекстовыйДокумент = Новый ТекстовыйДокумент;
		ТекстовыйДокумент.УстановитьТекст(ТекстМодуля);
		ТекстовыйДокумент.Записать(Файлы[0].ПолноеИмя);
		ТекстЛога = Неопределено;
		ИмяКорневогоФайла = ШаблонВнешнейОбработки + ирОбщий.РазделительПутиКФайлуЛкс() + "ИмяВнешнейОбработки.xml";
		Если ЗначениеЗаполнено(ИмяОбработки) Тогда
			ПотокСИменемОбработки = Новый ТекстовыйДокумент;
			ПотокСИменемОбработки.Прочитать(ИмяКорневогоФайла);
			ПотокСИменемОбработки.УстановитьТекст(СтрЗаменить(ПотокСИменемОбработки.ПолучитьТекст(), "ИмяВнешнейОбработки", ИмяОбработки));
			ПотокСИменемОбработки.Записать(ИмяКорневогоФайла);
		КонецЕсли; 
		Если Не ирОбщий.ВыполнитьКомандуКонфигуратораЛкс("/LoadExternalDataProcessorOrReportFromFiles """ + ИмяКорневогоФайла + """ """ + ФайлОбработки.ПолноеИмя + """", , ТекстЛога, Истина,,,,,,, Ложь) Тогда 
			УдалитьФайлы(ШаблонВнешнейОбработки);
			УдалитьФайлы(ИмяВременногоФайла);
			ирОбщий.СообщитьЛкс(ТекстЛога);
			Возврат Ложь;
		КонецЕсли; 
		Результат = Истина;
	Иначе
		Если ПустаяСтрока(ДляИДВерсииПлатформы) Тогда
			ДляИДВерсииПлатформы = ирКэш.НомерИзданияПлатформыЛкс();
		КонецЕсли; 
		Если ДляИДВерсииПлатформы = "83" Тогда
			ДляИДВерсииПлатформы = "82";
		КонецЕсли; 

		Если ТекстМакета <> Неопределено Тогда
			ШаблонВнешнейОбработкиСМакетом = ШаблоныВнешнейОбработкиСМакетом[ДляИДВерсииПлатформы];
			Если ШаблонВнешнейОбработкиСМакетом = Неопределено Тогда
				ШаблонВнешнейОбработкиСМакетом = Новый Структура("Путь, ФайлСИменем, ФайлЗамок, ТекстПотокаСИменем");
				ШаблонВнешнейОбработкиСМакетом.Путь = РазвернутьНовыйШаблонВнешнейОбработки(Истина,,
					ШаблонВнешнейОбработкиСМакетом.ФайлСИменем, ШаблонВнешнейОбработкиСМакетом.ТекстПотокаСИменем, ДляИДВерсииПлатформы);
				ФайлЗамокШаблонаСМакетом = Новый ЗаписьТекста;
				ФайлЗамокШаблонаСМакетом.Открыть(ШаблонВнешнейОбработкиСМакетом.Путь + ".lck");
				ШаблонВнешнейОбработкиСМакетом.ФайлЗамок = ФайлЗамокШаблонаСМакетом;
				ШаблоныВнешнейОбработкиСМакетом[ДляИДВерсииПлатформы] = ШаблонВнешнейОбработкиСМакетом;
			КонецЕсли;
			ПутьКШаблону = ШаблонВнешнейОбработкиСМакетом.Путь;
			ФайлСИменем = ШаблонВнешнейОбработкиСМакетом.ФайлСИменем;
			ТекстПотокаСИменем = ШаблонВнешнейОбработкиСМакетом.ТекстПотокаСИменем;
		Иначе
			ШаблонВнешнейОбработки = ШаблоныВнешнейОбработки[ДляИДВерсииПлатформы];
			Если ШаблонВнешнейОбработки = Неопределено Тогда
				ШаблонВнешнейОбработки = Новый Структура("Путь, ФайлСИменем, ФайлЗамок, ТекстПотокаСИменем");
				ШаблонВнешнейОбработки.Путь = РазвернутьНовыйШаблонВнешнейОбработки(,,
					ШаблонВнешнейОбработки.ФайлСИменем, ШаблонВнешнейОбработки.ТекстПотокаСИменем, ДляИДВерсииПлатформы);
				ФайлЗамокШаблона = Новый ЗаписьТекста;
				ФайлЗамокШаблона.Открыть(ШаблонВнешнейОбработки.Путь + ".lck");
				ШаблонВнешнейОбработки.ФайлЗамок = ФайлЗамокШаблона;
				ШаблоныВнешнейОбработки[ДляИДВерсииПлатформы] = ШаблонВнешнейОбработки;
			КонецЕсли;
			ПутьКШаблону = ШаблонВнешнейОбработки.Путь;
			ФайлСИменем = ШаблонВнешнейОбработки.ФайлСИменем; 
			ТекстПотокаСИменем = ШаблонВнешнейОбработки.ТекстПотокаСИменем;
		КонецЕсли;
		
		ИмяФайлаВерсий = "versions.data.und";
		ФайлЗаголовка = Новый Файл(ПутьКШаблону + ирОбщий.РазделительПутиКФайлуЛкс() + ИмяФайлаВерсий);
		//	ДвоичныеДанныеЗаголовка = Новый ДвоичныеДанные(ФайлЗаголовка.ПолноеИмя);
		//	ПотокЗаписи = ФайловыеПотоки.ОткрытьДляЗаписи(ФайлЗаголовка.ПолноеИмя);   
		//	Читатель = Новый ЧтениеДанных(ДвоичныеДанныеЗаголовка);
		//	Писатель = Новый ЗаписьДанных(ПотокЗаписи);
		//	Счетчик = 1;
		//	Пока Истина Цикл
		//		Целое16 = Читатель.ПрочитатьЦелое16();
		//		Если Целое16 = Неопределено Тогда
		//			Прервать;
		//		КонецЕсли;
		//		Если Ложь
		//			Или Счетчик = 1
		//		Тогда
		//			Целое16 = Целое16 + 1; // Увеличиваем номер версии содержимого
		//		КонецЕсли; 
		//		Писатель.ЗаписатьЦелое16(Целое16);
		//		Счетчик = Счетчик + 1;
		//	КонецЦикла;
		//	Писатель.Закрыть();
		//	ПотокЗаписи.Закрыть();
		ТекстовыйДокумент = Новый ТекстовыйДокумент;
		ТекстовыйДокумент.Прочитать(ФайлЗаголовка.ПолноеИмя);
		ТекстФайла = ТекстовыйДокумент.ПолучитьТекст();
		ФрагментТекста = ирОбщий.ТекстМеждуМаркерамиЛкс(ТекстФайла, """4eb1cc18-835d-4f8c-a120-3f9d886d75d4""", """902f74d3-f929-4b0f-8719-4cbb655891aa""", Ложь, Истина);
		ТекстФайла = ирОбщий.СтрЗаменитьЛкс(ТекстФайла, ФрагментТекста, """4eb1cc18-835d-4f8c-a120-3f9d886d75d4""," + Новый УникальныйИдентификатор + ",""902f74d3-f929-4b0f-8719-4cbb655891aa""");
		ТекстовыйДокумент.УстановитьТекст(ТекстФайла);
		ТекстовыйДокумент.Записать(ФайлЗаголовка.ПолноеИмя);
		
		ПутьКШаблону = ПутьКШаблону + ирОбщий.РазделительПутиКФайлуЛкс();
		Если ЗначениеЗаполнено(ИмяОбработки) Тогда
			ТекстПотокаСИменем = СтрЗаменить(ТекстПотокаСИменем, "ИмяВнешнейОбработки", ИмяОбработки);
		КонецЕсли; 
		ПотокСИменемОбработки = Новый ТекстовыйДокумент;
		ПотокСИменемОбработки.УстановитьТекст(ТекстПотокаСИменем);
		ПотокСИменемОбработки.Записать(ФайлСИменем.ПолноеИмя);
		
		ФайлТекстаМодуляОбработки = Новый Файл(ПутьКШаблону + СубПутьКФайлуПотокаМодуляВнешнейОбработки);
		ТекстовыйДокументМодуля = Новый ТекстовыйДокумент();
		ТекстовыйДокументМодуля.УстановитьТекст(ТекстМодуля);
		ТекстовыйДокументМодуля.Записать(ФайлТекстаМодуляОбработки.ПолноеИмя);
		
		Если ТекстМакета <> Неопределено Тогда
			ФайлТекстаМакетаПараметров = Новый Файл(ПутьКШаблону + СубПутьКФайлуПотокаМакетаВнешнейОбработки);
			ТекстовыйДокументМакета = Новый ТекстовыйДокумент();
			ТекстовыйДокументМакета.УстановитьТекст(ТекстМакета);
			ТекстовыйДокументМакета.Записать(ФайлТекстаМакетаПараметров.ПолноеИмя);
		КонецЕсли;
		
		Результат = УпаковатьВнешнююОбработку(ПутьКШаблону, ФайлОбработки.ПолноеИмя);
	КонецЕсли; 
	Возврат Результат;

КонецФункции

// Файлы "Zlib1.dll" и "v8unpack.exe" должны быть в этом каталоге.
Функция УпаковатьВнешнююОбработку(ПутьКШаблонуВнешнейОбработки, ИмяВыходногоФайла, СоздатьФайлыУпаковщика = Ложь) Экспорт

	// Небольшой накладной расход, но надежность повышаем
	УдалитьФайлы(ПутьКШаблонуВнешнейОбработки + СубПутьККонтрольномуФайлуВнешнейОбработки);
	Попытка
		УдалитьФайлы(ИмяВыходногоФайла);
	Исключение
		Событие = "Ошибка создания служебного объекта (1)";
		//ирОбщий.СообщитьЛкс(Событие, СтатусСообщения.Важное);
		//ЗаписьЖурналаРегистрации(Событие, УровеньЖурналаРегистрации.Ошибка);
		//Возврат Неопределено;
		ВызватьИсключение Событие;
	КонецПопытки;
	Если СоздатьФайлыУпаковщика Тогда 
		ПодготовитьПакер(ПутьКШаблонуВнешнейОбработки);
	КонецЕсли;
	ИмяКомандногоФайла = "pack.bat";
	ирОбщий.ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс(ИмяКомандногоФайла + " """ + ИмяВыходногоФайла + """", ПутьКШаблонуВнешнейОбработки);
	КонтрольныйФайл1 = Новый Файл(ПутьКШаблонуВнешнейОбработки + СубПутьККонтрольномуФайлуВнешнейОбработки);
	КонтрольныйФайл2 = Новый Файл(ИмяВыходногоФайла);
	Если Ложь
		Или Не КонтрольныйФайл1.Существует() 
		//Или Не КонтрольныйФайл2.Существует()  // Отключил для повышения скорости
	Тогда
		Если ирКэш.ЛиДоступноВыполнениеКомандныхФайловЛкс(Истина) Тогда
			ВызватьИсключение "Ошибка выполнения приложения V8unpack";
		КонецЕсли;
	КонецЕсли;
	Возврат Истина;

КонецФункции

Функция ПолучитьФайлВнешнейОбработкиАлгоритма(АлгоритмОбъект) Экспорт 

	Если Ложь
		Или СтрДлина(ПапкаКешаВнешнихОбработокАлгоритмов.ПолноеИмя) + СтрДлина(АлгоритмОбъект.Наименование) > 250
	Тогда
		// Ограничение WinAPI на путь к файлу
		КлючСервиса = "" + АлгоритмОбъект.Ссылка.УникальныйИдентификатор();
	Иначе
		КлючСервиса = АлгоритмОбъект.Наименование;
	КонецЕсли; 
	ИмяФайла = КлючСервиса + ".epf";
	ФайлВнешнейОбработки = Новый Файл(ПапкаКешаВнешнихОбработокАлгоритмов.ПолноеИмя + ирОбщий.РазделительПутиКФайлуЛкс() + ИмяФайла);
	Возврат ФайлВнешнейОбработки;

КонецФункции

Функция ПолучитьОбновитьФайлВнешнейОбработкиАлгоритма(ДескрипторСервиса, ЭлементКэша = Неопределено, ДатаИзмененияКэша = Неопределено) Экспорт

	ФайлВнешнейОбработкиАктуален = Ложь;
	КэшВнешнейОбработкиАктуален = Ложь;
	ФайлВнешнейОбработки = ПолучитьФайлВнешнейОбработкиАлгоритма(ДескрипторСервиса);
	ДатаИзмененияОбъекта = ДескрипторСервиса.ДатаИзмененияКонтекста;
	
	//// Условие добавлено для мягкого перехода на новый кэш параметров сервисов 21.10.2010. Потом нужно убрать
	//Если ЗначениеЗаполнено(ДескрипторСервиса.ДатаИзмененияКэша) Тогда 
		ПроверитьАктуальностьКэшаВнешнейОбработки(ЭлементКэша, ДатаИзмененияКэша, ФайлВнешнейОбработки, ДатаИзмененияОбъекта, 
			КэшВнешнейОбработкиАктуален, ФайлВнешнейОбработкиАктуален, ФайловыйКэшАлгоритмовДопускаетРедактирование);
	//КонецЕсли; 
	Если Истина
		И Не КэшВнешнейОбработкиАктуален
		И Не ФайлВнешнейОбработкиАктуален
	Тогда
		СервисОбъект = ПроверитьПолучитьОбъектСервиса(ДескрипторСервиса); 
		СервисОбъект.СобратьКонтекст();
		СформироватьВнешнююОбработку(ФайлВнешнейОбработки, СервисОбъект.Наименование,
			СервисОбъект.ПолучитьТекстМодуляОбработки()
			//, СервисОбъект.ПолучитьТекстМакетаПараметров()
			);
		Попытка
			ФайлВнешнейОбработки.УстановитьВремяИзменения(СервисОбъект.ДатаИзмененияКонтекста);
		Исключение
			Если Не ФайлВнешнейОбработки.Существует() Тогда
				ирОбщий.ПроверитьКодЯзыкаОСЛкс();
				ВызватьИсключение "Файл внешней обработки сервиса """ + СервисОбъект.Наименование + """ не сформирован";
			Иначе
				ВызватьИсключение;
			КонецЕсли; 
		КонецПопытки;
	КонецЕсли; 
	Если КэшВнешнейОбработкиАктуален Тогда 
		Возврат Неопределено;
	Иначе
		Возврат ФайлВнешнейОбработки;
	КонецЕсли;

КонецФункции

Функция ПолучитьВнешнююОбработкуПоАлгоритму(ДескрипторСервиса) Экспорт

	// %%%% Здесь можно было бы структуру попробовать вместо ТЗ
	//ЭлементКэша = 0;
	//КешВнешнихОбработокАлгоритмов.Свойство(ДескрипторСервиса.Наименование, ЭлементКэша);
	ЭлементКэша = ДескрипторСервиса.мСтруктураВнешнейОбработки;
	Если Ложь
		Или ЭлементКэша = Неопределено
		Или ЭлементКэша.ДатаИзменения < ДескрипторСервиса.ДатаИзмененияКонтекста
		Или ФайловыйКэшАлгоритмовДопускаетРедактирование
	Тогда
		ДатаИзмененияКэша = ДескрипторСервиса.ДатаИзмененияКонтекста;
		// Для обхода бага платформы WshShell().Run(,,True)
		Для Счетчик = 1 По 3 Цикл
			
			ФайлВнешнейОбработки = ПолучитьОбновитьФайлВнешнейОбработкиАлгоритма(ДескрипторСервиса, ЭлементКэша,
				ДатаИзмененияКэша);
			Если ФайлВнешнейОбработки <> Неопределено Тогда
				ВнешняяОбработка = СоздатьВнешнююОбработкуАлгоритма(ДескрипторСервиса, ФайлВнешнейОбработки.ПолноеИмя);
				
				// Для обхода бага платформы.
				Если ВнешняяОбработка <> Неопределено Тогда
					ИмяАлгоритмаВнешнейОбработки = ВнешняяОбработка.Метаданные().Имя;
					Если ИмяАлгоритмаВнешнейОбработки <> ДескрипторСервиса.Наименование Тогда
						ЗаписьЖурналаРегистрации("Несоответствие внешней обработки и сервиса", УровеньЖурналаРегистрации.Ошибка, ,
							ДескрипторСервиса.Ссылка, "Попытка №" + Счетчик + ". Внешняя обработка """ + ИмяАлгоритмаВнешнейОбработки + """");
						УдалитьФайлы(ФайлВнешнейОбработки.ПолноеИмя);
						Продолжить;
					КонецЕсли;
				КонецЕсли;
			КонецЕсли;
			Прервать;
		КонецЦикла;
		Если ФайлВнешнейОбработки <> Неопределено Тогда
			Если ЭлементКэша = Неопределено Тогда
				ЭлементКэша = Новый Структура("ДатаИзменения, ВнешняяОбработка");
				//КешВнешнихОбработокАлгоритмов.Вставить(ДескрипторСервиса.Наименование, ЭлементКэша);
				ДескрипторСервиса.мСтруктураВнешнейОбработки = ЭлементКэша;
			КонецЕсли;
			Если ВнешняяОбработка <> Неопределено Тогда
				ЭлементКэша.ДатаИзменения = ДатаИзмененияКэша;
				ЭлементКэша.ВнешняяОбработка = ВнешняяОбработка;
			Иначе
				ЭлементКэша.ДатаИзменения = Дата("00010101");
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	Если ЭлементКэша <> Неопределено Тогда
		Результат = ЭлементКэша.ВнешняяОбработка; 
	Иначе
		Результат = Неопределено;
	КонецЕсли;
	Возврат Результат;

КонецФункции // ПолучитьВнешнююОбработкуПоАлгоритму()

Функция ЕстьАдминистративныеПраваУУчетнойЗаписиОС() Экспорт 
	
	Если мЕстьАдминистративныеПраваУУчетнойЗаписиОС <> Неопределено Тогда
		Возврат мЕстьАдминистративныеПраваУУчетнойЗаписиОС;
	КонецЕсли; 
	Попытка
		Network = Новый COMОбъект("WScript.Network");
	Исключение
		// Например Linux
		ОписаниеОшибки = ОписаниеОшибки();
		Возврат Ложь;
	КонецПопытки;
	//ПользовательОС = Network.UserDomain + "\" + Network.UserName;
	ПользовательОС = Network.UserName;
	КомандаСистемы = "Net user " + ПользовательОС;
	РезультатКоманды = ТекстРезультатаКомандыСистемы(КомандаСистемы);
	мЕстьАдминистративныеПраваУУчетнойЗаписиОС = Ложь
		Или Найти(РезультатКоманды, "Администраторы") > 0
		Или Найти(РезультатКоманды, "Administrators") > 0;
	Возврат мЕстьАдминистративныеПраваУУчетнойЗаписиОС;
	
КонецФункции

Функция ПереместитьФайлКакАдминистратор(ИмяИсточника, ИмяПриемника) Экспорт 
	
	Успех = Истина;
	Попытка
		//ПереместитьФайл(ИмяИсточника, ИмяПриемника); // так не работает наследование прав от каталога-приемника!
		КопироватьФайл(ИмяИсточника, ИмяПриемника);
	Исключение
		ОписаниеОшибки = ОписаниеОшибки();
	КонецПопытки; 
	Если ОписаниеОшибки <> Неопределено Тогда
		//КомандаСистемы = "cmd.exe /c move """ + ИмяИсточника + """ """ + ИмяПриемника + """"; // так не работает наследование прав от каталога-приемника!
		КомандаСистемы = "cmd.exe /c copy """ + ИмяИсточника + """ """ + ИмяПриемника + """";
		ОписаниеОшибки = ТекстРезультатаКомандыСистемы(КомандаСистемы,, Истина);
		// При успехе возвращает:
		//   Скопировано файлов:         1.
		Если Найти(ОписаниеОшибки, "1") = 0 Тогда 
			ВызватьИсключение "Ошибка доступа к файлу """ + ИмяПриемника + """: " + ОписаниеОшибки;
		КонецЕсли; 
	КонецЕсли;
	Если Успех Тогда
		Попытка
			УдалитьФайлы(ИмяИсточника);
		Исключение
			КомандаСистемы = "cmd.exe /c del """ + ИмяИсточника + """";
			ОписаниеОшибки = ТекстРезультатаКомандыСистемы(КомандаСистемы,, Истина);
			// При успехе возвращает пустую строку
			Если Не ПустаяСтрока(ОписаниеОшибки) Тогда 
				ВызватьИсключение "Ошибка доступа к файлу """ + ИмяИсточника + """: " + ОписаниеОшибки;
			КонецЕсли; 
		КонецПопытки; 
	КонецЕсли; 
	Возврат Успех;
	
КонецФункции

Функция ПолучитьПолноеИмяКомпьютераСетиПоЛюбомуИмени(ИмяКомпьютера) Экспорт

	ФайлРезультата = Новый Файл(ПолучитьИмяВременногоФайла());
	ирОбщий.ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс("nslookup " + ИмяКомпьютера, ФайлРезультата.Путь, ФайлРезультата.Имя);
	Если Не ФайлРезультата.Существует() Тогда
		ПолноеИмяКомпьютера = "";
	Иначе
		ТекстовыйДокумент = Новый ТекстовыйДокумент;
		ТекстовыйДокумент.Прочитать(ФайлРезультата.ПолноеИмя);
		УдалитьФайлы(ФайлРезультата.ПолноеИмя);
		ТекстРезультата = ТекстовыйДокумент.ПолучитьТекст();
		RegExp.IgnoreCase = Истина;
		RegExp.Pattern = "(?:name|имя|╚ь ):\s*([-" + шБукваЦифра + "]+(\.([-" + шБукваЦифра + "]+))*)\s*";
		Результат = RegExp.НайтиВхождения(ТекстРезультата);
		Если Результат.Количество() > 0 Тогда
			ПолноеИмяКомпьютера = Результат[0].SubMatches(0);
		Иначе
			ПолноеИмяКомпьютера = "";
		КонецЕсли;
	КонецЕсли;
	//ASPDNS = ПолучитьCOMОбъектИзМакета("ASPDNS", "ASPDNS.DNSLookup");
	//IP = ASPDNS.GetIPFromName(ИмяКомпьютера);
	//ПолноеИмяКомпьютера = ASPDNS.GetNameFromIP(IP);
	Возврат ПолноеИмяКомпьютера;

КонецФункции

Функция ПроверитьКаталогФайловогоКэша() Экспорт

	//http://www.hostedredmine.com/issues/851201
	//СтрокаСоединения = ирКэш.СтрокаСоединенияСервераЛкс();
	СтрокаСоединения = СтрокаСоединенияИнформационнойБазы();
	
	КаталогВерсииПлатформыВПрофиле = ирКэш.КаталогИзданияПлатформыВПрофилеЛкс();
	КаталогФайловогоКэша = КаталогВерсииПлатформыВПрофиле + ирОбщий.РазделительПутиКФайлуЛкс() + ирОбщий.ИдентификаторИзПредставленияЛкс(СтрокаСоединения);
	ПапкаФайловогоКэша = Новый Файл(КаталогФайловогоКэша);
	Если Не ПапкаФайловогоКэша.Существует() Тогда
		Попытка
			СоздатьКаталог(ПапкаФайловогоКэша.ПолноеИмя);
			ПробныйФайл = Новый ТекстовыйДокумент;
			ПробныйФайл.Записать(ПапкаФайловогоКэша.ПолноеИмя + ирОбщий.РазделительПутиКФайлуЛкс() + "1.txt");
		Исключение
			ОписаниеОшибки = ОписаниеОшибки();
			Сообщить("Файловые кэши отключены из-за ошибки: " + ОписаниеОшибки, СтатусСообщения.Важное); // При использовании ирОбщий.СообщитьЛкс() может происходить переполнение стека
			ВыполнятьАлгоритмыЧерезВнешниеОбработки = Ложь;
			Возврат Ложь;
		КонецПопытки;
	КонецЕсли;
	Возврат Истина;

КонецФункции

Функция НастройкиКомпьютера() Экспорт 
	Если НастройкиКомпьютера = Неопределено Тогда
		ФайлаНастроекКомпьютера = Новый Файл(ИмяФайлаНастроекКомпьютера());
		Если ФайлаНастроекКомпьютера.Существует() Тогда
			НастройкиКомпьютера = ирОбщий.ЗагрузитьЗначениеИзФайлаЛкс(ФайлаНастроекКомпьютера.ПолноеИмя);
			Если НастройкиКомпьютера <> Неопределено Тогда
				ЗначениеНастройки = НастройкиКомпьютера["ПапкаКэшаМодулей"];
				ЗначениеНастройки = Новый Файл(ЗначениеНастройки);
				Если ЗначениеНастройки.Существует() Тогда
					ПапкаКэшаМодулей = ЗначениеНастройки;
				КонецЕсли; 
				ЗначениеНастройки = НастройкиКомпьютера["ПапкаКэшаРолей"];
				ЗначениеНастройки = Новый Файл(ЗначениеНастройки);
				Если ЗначениеНастройки.Существует() Тогда
					ПапкаКэшаРолей = ЗначениеНастройки;
				КонецЕсли; 
			КонецЕсли; 
		КонецЕсли; 
	КонецЕсли; 
	Если НастройкиКомпьютера = Неопределено Тогда
		НастройкиКомпьютера = Новый Соответствие;
	КонецЕсли; 
	Возврат НастройкиКомпьютера;
КонецФункции

Процедура СохранитьНастройкиКомпьтера() Экспорт 
	
	ИмяФайлаНастроекКомпьютера = ИмяФайлаНастроекКомпьютера();
	ирОбщий.СохранитьЗначениеВФайлЛкс(НастройкиКомпьютера, ИмяФайлаНастроекКомпьютера);

КонецПроцедуры

Функция ИмяФайлаНастроекКомпьютера()
	
	ПапкаФайловогоКэша = Новый Файл(КаталогФайловогоКэша);
	ИмяФайлаНастроекКомпьютера = ПапкаФайловогоКэша.ПолноеИмя + ирОбщий.РазделительПутиКФайлуЛкс() + "ComputerSettings.xml";
	Возврат ИмяФайлаНастроекКомпьютера;

КонецФункции

Функция ИмяНеопределеннойПеременнойИзИнформацииОбОшибке(ИнформацияОбОшибке, СообщитьНеобрабатываемуюОшибку = Ложь) Экспорт

	Если ИнформацияОбОшибке <> Неопределено Тогда
		RegExp.Global = Ложь;
		//ОписаниеОшибки = ирОбщий.ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке);
		Пока ИнформацияОбОшибке.Причина <> Неопределено Цикл // Добавлено 26.07.2011 из-за доработки синтаксического контроля в COM сеансе
			ИнформацияОбОшибке = ИнформацияОбОшибке.Причина;
		КонецЦикла;
		ОписаниеОшибки = ИнформацияОбОшибке.Описание;
		
		RegExp.Pattern = "(?:Переменная не определена |Variable is not defined )\(([_0-9" + шБуква + "]+)\)";
		Результат = RegExp.НайтиВхождения(ОписаниеОшибки);
		Если Результат.Количество() > 0 Тогда 
			ИмяПеременнойРезультата = Результат[0].SubMatches(0);
		Иначе
			Если СообщитьНеобрабатываемуюОшибку Тогда
				ирОбщий.СообщитьЛкс(ирОбщий.ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке), СтатусСообщения.Важное);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли; 
	Возврат ИмяПеременнойРезультата;

КонецФункции

Функция ИмяНеопределенногоМетодаИзИнформацииОбОшибке(ИнформацияОбОшибке, СообщитьНеобрабатываемуюОшибку = Ложь) Экспорт

	Если ИнформацияОбОшибке <> Неопределено Тогда
		RegExp.Global = Ложь;
		//ОписаниеОшибки = ирОбщий.ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке);
		Пока ИнформацияОбОшибке.Причина <> Неопределено Цикл // Добавлено 26.07.2011 из-за доработки синтаксического контроля в COM сеансе
			ИнформацияОбОшибке = ИнформацияОбОшибке.Причина;
		КонецЦикла;
		ОписаниеОшибки = ИнформацияОбОшибке.Описание;
		
		RegExp.Pattern = "(?:Процедура или функция с указанным именем не определена |TODO_xxxx9469326459823 )\(([_0-9" + шБуква + "]+)\)";
		Результат = RegExp.НайтиВхождения(ОписаниеОшибки);
		Если Результат.Количество() > 0 Тогда 
			ИмяМетодаРезультата = Результат[0].SubMatches(0);
		Иначе
			Если СообщитьНеобрабатываемуюОшибку Тогда
				ирОбщий.СообщитьЛкс(ирОбщий.ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке), СтатусСообщения.Важное);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли; 
	Возврат ИмяМетодаРезультата;

КонецФункции

#Если Клиент Или ВнешнееСоединение Тогда

Функция ВыполнитьАлгоритм(СсылкаАлгоритма, СтруктураПараметров = Неопределено) Экспорт 

	Если СтруктураПараметров = Неопределено Тогда
		СтруктураПараметров = Новый Структура;
	КонецЕсли;
	АлгоритмОбъект = Неопределено;
	Если Не КешАлгоритмов.Свойство(СсылкаАлгоритма, АлгоритмОбъект) Тогда
		АлгоритмОбъект = СсылкаАлгоритма.ПолучитьОбъект();
		КешАлгоритмов.Вставить(СсылкаАлгоритма, АлгоритмОбъект);
	КонецЕсли;
	Результат = ВыполнитьМетодАлгоритма(АлгоритмОбъект, 1, СтруктураПараметров);
	Возврат Результат;

КонецФункции

Процедура ОчиститьКешАлгоритмов(ОчиститьКэшНаДиске = Ложь) Экспорт 

	КешАлгоритмов.Очистить();
	//КешВнешнихОбработокАлгоритмов.Очистить();
	Если ОчиститьКэшНаДиске Тогда 
		//Для Каждого ЭлементПодкаталога Из СтруктураПодкаталоговФайловогоКэша Цикл
		//	УдалитьФайлы(ЭлементПодкаталога.Значение.ПолноеИмя, "*.dat");
		//	УдалитьФайлы(ЭлементПодкаталога.Значение.ПолноеИмя, "*.epf");
		//КонецЦикла;
		
		ФайлПодкаталога = СтруктураПодкаталоговФайловогоКэша["a"];
		УдалитьФайлы(ФайлПодкаталога.ПолноеИмя + ирОбщий.РазделительПутиКФайлуЛкс(), "*.*");
		ПроверитьСтруктуруФайловогоКэша();
	КонецЕсли;

КонецПроцедуры // ОчиститьКешАлгоритмов()

Процедура ОбновитьАлгоритмВКеше(АлгоритмОбъект) Экспорт 

	КешАлгоритмов.Вставить(АлгоритмОбъект.Ссылка, АлгоритмОбъект);

КонецПроцедуры // УдалитьАлгоритмИзКеша()

Функция ПолучитьФайлОткрывателя1С(БыстраяПроверка = Истина) Экспорт 

	Если Ложь
		Или Не БыстраяПроверка
		Или ФайлОткрывателя1С = Неопределено
	Тогда
		ФайлОткрывателя1С = Новый Файл(ПолучитьИмяВременногоФайла("exe"));
		ПолучитьМакет("OpenIn1Cv8ExeWin").Записать(ФайлОткрывателя1С.ПолноеИмя);
	КонецЕсли;
	Возврат ФайлОткрывателя1С;

КонецФункции

Функция ФайлФорматераЗапросовБД(БыстраяПроверка = Истина) Экспорт 

	Если Ложь
		Или Не БыстраяПроверка
		Или ФайлФорматераЗапросовБД = Неопределено
	Тогда
		ФайлФорматераЗапросовБД = Новый Файл(ПолучитьИмяВременногоФайла("exe"));
		ПолучитьМакет("SqlFormatter").Записать(ФайлФорматераЗапросовБД.ПолноеИмя);
	КонецЕсли;
	Возврат ФайлФорматераЗапросовБД;

КонецФункции

Функция ПолучитьФайлРаспаковщикаZIP(БыстраяПроверка = Ложь) Экспорт 

	Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
		Если Ложь
			Или Не БыстраяПроверка
			Или ФайлРаспаковщикаZIP = Неопределено
		Тогда
			ФайлРаспаковщикаZIP = Новый Файл(ПолучитьИмяВременногоФайла("exe"));
			ПолучитьМакет("unzip").Записать(ФайлРаспаковщикаZIP.ПолноеИмя);
		КонецЕсли;
	Иначе
		// Может потребоваться установка - sudo apt install unzip
		ФайлРаспаковщикаZIP = Новый Файл("unzip");
	КонецЕсли; 
	Возврат ФайлРаспаковщикаZIP;

КонецФункции

// Получает из длинного пути к файлу короткий в формате DOS (8.3) 
//
// Параметры:
//  ПолноеИмяФайла - Строка;
//
// Возвращаемое значение:
//  Строка;
//
Функция ПолучитьИмяФайлаВФорматеDOS(ПолноеИмяФайла) Экспорт
	
	Если Не ирКэш.ЛиПлатформаWindowsЛкс() Тогда
		Возврат ПолноеИмяФайла;
	КонецЕсли;
	Если ирКэш.Это64битныйПроцессЛкс() Тогда
		ВызватьИсключение "Получение имени файла в формате ""8.3"" недоступно в 64б процессе";
	КонецЕсли;
	Если VBScript = Неопределено Тогда
		VBScript = Новый COMОбъект("MSScriptControl.ScriptControl"); // Не работает в 64б процессе
		VBScript.language = "vbscript";
	КонецЕсли;
	VBScript.addcode("
	|Public Function GetShortPath()
	|Set fso = CreateObject(""scripting.filesystemobject"")
	|Set fsoFile = fso.GetFile(""" + ПолноеИмяФайла + """)
	|GetShortPath = fsoFile.ShortPath
	|End Function
	|");
	DOSИмя = VBScript.Run("GetShortPath");
	Возврат DOSИмя;
	
КонецФункции

Процедура УдалитьСлужебныеФайлы() Экспорт
	
	СтруктураЦикла = Новый Массив;
	СтруктураЦикла.Добавить(ШаблоныВнешнейОбработки);
	СтруктураЦикла.Добавить(ШаблоныВнешнейОбработкиСМакетом);
	Для Каждого ЭлементЦикла Из СтруктураЦикла Цикл
		Для Каждого КлючИЗначение Из ЭлементЦикла Цикл
			ШаблонВнешнейОбработки = КлючИЗначение.Значение;
			Если ШаблонВнешнейОбработки.ФайлЗамок <> Неопределено Тогда
				ШаблонВнешнейОбработки.ФайлЗамок.Закрыть();
				Попытка
					УдалитьФайлы(ШаблонВнешнейОбработки.Путь + ".lck");
					УдалитьФайлы(ШаблонВнешнейОбработки.Путь);
				Исключение
				КонецПопытки;
			КонецЕсли;
		КонецЦикла; 
	КонецЦикла;

КонецПроцедуры // УдалитьСлужебныеФайлы()

// Функция - Поле текста программы
//
// Параметры:
//  ЯзыкПрограммы	 - Число - 
//  НачалоТекста	 - Строка - первые 1000 символов текста для определения его языка
// 
// Возвращаемое значение:
//   - 
//
Функция ПолеТекстаПрограммы(Знач ЯзыкПрограммы = 0, Знач НачалоТекста = "") Экспорт
	Если мПоляТекстаПрограммы = Неопределено Тогда
		мПоляТекстаПрограммы = Новый Соответствие;
	КонецЕсли;
	Если ЯзыкПрограммы = 0 И ирОбщий.ЛиТекстЯзыкаЗапросовЛкс(НачалоТекста) Тогда
		ЯзыкПрограммы = 1;
	КонецЕсли;
	ПолеТекстаПрограммы = мПоляТекстаПрограммы[ЯзыкПрограммы];
	Если ПолеТекстаПрограммы = Неопределено Тогда
		ПолеТекстаПрограммы = ирОбщий.НовыйАнализаторКодаЛкс();
		#Если Сервер И Не Сервер Тогда
		    ПолеТекстаПрограммы = Обработки.ирКлсПолеТекстаПрограммы.Создать();
		#КонецЕсли 
		ПолеТекстаПрограммы.ИнициироватьНеинтерактивно(ЯзыкПрограммы);
		ПолеТекстаПрограммы.ЭтоМодуль = Истина;
		мПоляТекстаПрограммы[ЯзыкПрограммы] = ПолеТекстаПрограммы;
	КонецЕсли;
	Возврат ПолеТекстаПрограммы;
КонецФункции

#КонецЕсли

Функция ПредставлениеПустогоЗначенияЛкс(ПустоеЗначение) Экспорт

	Если ПустоеЗначение = Неопределено Тогда
		Результат = "<Неопределено>";
	Иначе
		Результат = мКэшПустыхЗначений[ПустоеЗначение];
		Если Результат = Неопределено Тогда
			Если ПустоеЗначение = Null Тогда
				Результат = "<Null>";
			ИначеЕсли ТипЗнч(ПустоеЗначение) = Тип("Булево") И ПустоеЗначение = Ложь Тогда
				//Результат = "<Булево: Нет>";
				Результат = "" + ПустоеЗначение;
			ИначеЕсли ПустоеЗначение = "" Тогда
				Результат = "<Строка>";
			ИначеЕсли ПустоеЗначение = 0 Тогда
				//Результат = "<Пустое число>";
				Результат = Формат(ПустоеЗначение, "ЧН=");
			ИначеЕсли ПустоеЗначение = Дата("00010101") Тогда
				Результат = "<Дата>";
			ИначеЕсли ТипЗнч(ПустоеЗначение) = Тип("УникальныйИдентификатор") Тогда
				Результат = "<Идентификатор>";
			ИначеЕсли ТипЗнч(ПустоеЗначение) = Тип("Картинка") Тогда
				Результат = "<Картинка>";
			Иначе 
				ОбъектМД = ирОбщий.ПолучитьМетаданныеЛкс(ПустоеЗначение);
				Если ОбъектМД <> Неопределено Тогда
					Результат = "<" + ОбъектМД.ПолноеИмя() + ".Ссылка>";
				КонецЕсли;
			КонецЕсли; 
			мКэшПустыхЗначений[ПустоеЗначение] = Результат;
		КонецЕсли;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

// Возвращает текущее время в миллисекундах.
//
// Параметры:
//  Нет.
//
// Возвращаемое значение:
//  Число.
//
Функция ПолучитьТекущееВремяВМиллисекундах() Экспорт
	
	Если ирКэш.НомерИзданияПлатформыЛкс() >= "83" Тогда
		Результат = Вычислить("ТекущаяУниверсальнаяДатаВМиллисекундах()");
	КонецЕсли; 
	Если Результат = Неопределено Тогда 
		Если JavaScript = Неопределено Тогда
			Попытка
		    	JavaScript = Новый COMОбъект("MSScriptControl.ScriptControl");
			Исключение
				ирОбщий.СообщитьЛкс("Ошибка создания MSScriptControl.ScriptControl: " + ОписаниеОшибки(), СтатусСообщения.Внимание);
				Возврат 0;
			КонецПопытки;
		    JavaScript.Language = "javascript";
		КонецЕсли;
		Результат = JavaScript.Eval("new Date().getTime()");
	КонецЕсли; 
    Возврат Результат;
	
КонецФункции

Функция ПроверитьПолучитьОбъектСервиса(Знач АлгоритмОбъект) Экспорт

	Если ТипЗнч(АлгоритмОбъект) = Тип("СтрокаТаблицыЗначений") Тогда
		лОбъект = АлгоритмОбъект.ЭтотОбъект;
		Если лОбъект = Неопределено Тогда
			лОбъект = АлгоритмОбъект.Ссылка.ПолучитьОбъект();
			ЗаполнитьЗначенияСвойств(лОбъект, АлгоритмОбъект, , "ЭтотОбъект, Ссылка, мПолнаяТаблицаПараметров"); ////%!%
			АлгоритмОбъект.ЭтотОбъект = лОбъект;
		КонецЕсли; 
		АлгоритмОбъект = лОбъект;
	КонецЕсли; 
	Возврат АлгоритмОбъект;

КонецФункции // ПроверитьПолучитьОбъектСервиса()

Функция ПредставлениеИнформацииОбОшибке(Знач ИнформацияОбОшибке) Экспорт 

	// Антибаг платформы. В описании повторяется причина и описание между уровнями. В общем бардак.
	ОписаниеОшибки = ИнформацияОбОшибке.Описание;
	Если ИнформацияОбОшибке.Причина <> Неопределено Тогда
		Пока Истина
			И ИнформацияОбОшибке.Причина <> Неопределено 
			И ИнформацияОбОшибке.Описание = ОписаниеОшибки
		Цикл
			ИнформацияОбОшибке = ИнформацияОбОшибке.Причина;
		КонецЦикла;
		Если ИнформацияОбОшибке.Описание <> ОписаниеОшибки Тогда
			ОписаниеОшибки = ОписаниеОшибки + Символы.ПС + ПредставлениеИнформацииОбОшибке(ИнформацияОбОшибке);
		КонецЕсли;
	Иначе
		Фрагмент = ирОбщий.ПоследнийФрагментЛкс(ОписаниеОшибки, "по причине:" + Символы.ПС);
		Позиция = Найти(ОписаниеОшибки, Фрагмент + Символы.ПС + "по причине:" + Символы.ПС + Фрагмент);
		Если Позиция > 0 Тогда
			ОписаниеОшибки = Лев(ОписаниеОшибки, Позиция) + Фрагмент;
		КонецЕсли;
	КонецЕсли;
	Возврат ОписаниеОшибки;

КонецФункции // ПредставлениеИнформацииОбОшибке()

Функция ОбработатьВнешнееИсключениеАлгоритма(ДескрипторСервиса, ИнформацияОбОшибке, РежимВыполненияАлгоритма, Интерактивно = Истина) Экспорт 

	//СервисОбъект = ПроверитьПолучитьОбъектСервиса(ДескрипторСервиса); 
	// Такой прием применен для избежания обращения к БД внутри сломанной транзакции
	Если ТипЗнч(ДескрипторСервиса) = Тип("СтрокаТаблицыЗначений") Тогда
		лОбъект = ДескрипторСервиса.ЭтотОбъект;
		Если лОбъект = Неопределено Тогда
			//лОбъект = Справочники.Сервисы2iS.СоздатьЭлемент();
			//ЗаполнитьЗначенияСвойств(лОбъект, ДескрипторСервиса, , "ЭтотОбъект, Ссылка, КэшПараметров"); 
			лОбъект = Новый ("СправочникОбъект.Сервисы2iS");
			ЗаполнитьЗначенияСвойств(лОбъект, ДескрипторСервиса, "мЗначенияПоУмолчанию, мВнешниеПараметры, мВнутренниеПараметры"); 
		КонецЕсли; 
		СервисОбъект = лОбъект;
	Иначе
		//! ДескрипторСервиса = Справочники.ирАлгоритмы.СоздатьЭлемент();
		СервисОбъект = ДескрипторСервиса;
	КонецЕсли; 
	
	Если РежимВыполненияАлгоритма = 2 Тогда
		Смещение = СервисОбъект.ПолучитьСтартовуюСтрокуАлгоритмаВТексте();
		ИмяМодуляСервиса = "";
	ИначеЕсли Ложь
		Или РежимВыполненияАлгоритма = 1
		Или РежимВыполненияАлгоритма = 0
	Тогда 
		Смещение = СервисОбъект.ПолучитьСтартовуюСтрокуМетодаВМодуле();
		ИмяМодуляСервиса = "ВнешняяОбработка." + ДескрипторСервиса.Наименование;
		Если Ложь
			Или ирКэш.НомерИзданияПлатформыЛкс() = "82"
			Или ирКэш.НомерИзданияПлатформыЛкс() = "83"
		Тогда
			ИмяМодуляСервиса = ИмяМодуляСервиса + ".МодульОбъекта";
		КонецЕсли;
	КонецЕсли;
	ПрефиксСервиса = "Сервис ";
	Если ИмяМодуляСервиса = ИнформацияОбОшибке.ИмяМодуля Тогда
		НомерСтрокиАлгоритма = ИнформацияОбОшибке.НомерСтроки;
		НомерСтрокиАлгоритма = НомерСтрокиАлгоритма - Смещение;
		ОписаниеОшибки = ПрефиксСервиса + """" + ДескрипторСервиса.Наименование + """[" + РежимВыполненияАлгоритма + "]{" 
			+ НомерСтрокиАлгоритма + "}:" + Символы.ПС + "==========================================================================" + Символы.ПС
			+ ИнформацияОбОшибке.Описание + Символы.ПС + ИнформацияОбОшибке.ИсходнаяСтрока;
	Иначе
		ОписаниеОшибки = ПрефиксСервиса + """" + ДескрипторСервиса.Наименование + """[" + РежимВыполненияАлгоритма + "]";
		МаркерСлужебногоИсключения = "ВызватьИсключение Ошибка;//#Служебное";
		Если Найти(ИнформацияОбОшибке.ИсходнаяСтрока, МаркерСлужебногоИсключения) = 0 Тогда
			ОписаниеОшибки = ОписаниеОшибки + "{" + ИнформацияОбОшибке.ИмяМодуля + "(" + ИнформацияОбОшибке.НомерСтроки + ")}: ";
		КонецЕсли; 
		ОписаниеОшибки = ОписаниеОшибки + Символы.ПС + ИнформацияОбОшибке.Описание;
		Если Найти(ИнформацияОбОшибке.ИсходнаяСтрока, МаркерСлужебногоИсключения) = 0 Тогда
			ОписаниеОшибки = ОписаниеОшибки + Символы.ПС + ИнформацияОбОшибке.ИсходнаяСтрока;
		КонецЕсли;
	КонецЕсли;
	Если ИнформацияОбОшибке.Причина <> Неопределено Тогда
		ОписаниеОшибки = ОписаниеОшибки + "
		|" + ПредставлениеИнформацииОбОшибке(ИнформацияОбОшибке.Причина);
	КонецЕсли;
	Возврат ОписаниеОшибки;

КонецФункции

Функция ВыполнитьМетодАлгоритма(ДескрипторСервиса, Режим, П0 = Null, П1 = Null, П2 = Null, П3 = Null, П4 = Null,
	П5 = Null, П6 = Null, П7 = Null, П8 = Null, П9 = Null) Экспорт 

	//#Если Клиент Тогда
	Если ВыполнятьАлгоритмыЧерезВнешниеОбработки Тогда
		Если Ложь
			Или ВнешняяОбработкаСервисы = Неопределено
			Или ДескрипторСервиса.ИндивидуальнаяВнешняяОбработка
		Тогда
			ВнешняяОбработкаАлгоритма = ПолучитьВнешнююОбработкуПоАлгоритму(ДескрипторСервиса);
			//Иначе
			//	ВнешняяОбработкаАлгоритма = ДескрипторСервиса.мСтруктураВнешнейОбработки;
			//	Если ВнешняяОбработкаАлгоритма = Неопределено Тогда 
			//		ВнешняяОбработкаАлгоритма = ВнешняяОбработкаСервисы.ПолучитьФорму(ДескрипторСервиса.Наименование);
			//		ДескрипторСервиса.мСтруктураВнешнейОбработки = ВнешняяОбработкаАлгоритма;
			//	КонецЕсли;
			//КонецЕсли;
			Если ВнешняяОбработкаАлгоритма <> Неопределено Тогда
				Результат = ВнешняяОбработкаАлгоритма.мМетод(ДескрипторСервиса, Режим, П0, П1, П2, П3, П4, П5, П6, П7, П8, П9);
			Иначе
				//ирОбщий.СообщитьЛкс("Ошибка компиляции сервиса """ + ДескрипторСервиса.Наименование + """. Сервис не выполнен.", СтатусСообщения.Внимание);
				ВызватьИсключение "Ошибка компиляции сервиса """ + ДескрипторСервиса.Наименование + """"; 
			КонецЕсли;
		Иначе
			Результат = Вычислить("ВнешняяОбработкаСервисы._" + ДескрипторСервиса.Наименование 
				+ "(ДескрипторСервиса, Режим, П0, П1, П2, П3, П4, П5, П6, П7, П8, П9)");
		КонецЕсли;
	Иначе
	//#КонецЕсли
		//#Если Не Клиент И Не ВнешнееСоединение Тогда
		//ДескрипторСервиса.ирПлатформа = ЭтотОбъект;
		//#КонецЕсли
		СервисОбъект = ПроверитьПолучитьОбъектСервиса(ДескрипторСервиса);
		#Если Сервер И Не Сервер Тогда
		    СервисОбъект = Обработки.ирИмитаторАлгоритмОбъект.Создать();
		#КонецЕсли
		ТекстАлгоритмаСПараметрами = СервисОбъект.ПолучитьТелоМетода();
		Результат = ирОбщий.ВыполнитьАлгоритм(ТекстАлгоритмаСПараметрами, СервисОбъект, Режим, П0, П1, П2, П3, П4, П5, П6, П7, П8, П9);
	//#Если Клиент Тогда
	КонецЕсли;
	//#КонецЕсли

	Возврат Результат;

КонецФункции

Функция ПолучитьИмяТипаCOMVariant(ReturnType) Экспорт
	
	Перем ScrptCtrl;
	
	ТекстМодуля = "
	|Function getMemberReturn( ReturnType )
	|  Dim ret
	|    On Error Resume Next
	|    If ReturnType Is Nothing Then
	|        ret = """"
	|    ElseIf Not IsEmpty(ReturnType.TypedVariant) Then
	|		 ff = ReturnType.TypedVariant
	|		 ff.VariantInit()
	|        ret = ff.Name
	|    ElseIf Not ReturnType.TypeInfo Is Nothing Then
	|        ret = ReturnType.TypeInfo.Name
	|    Else
	|        ret = """"
	|    End If
	|    getMemberReturn = ret
	|End Function";
	ScrptCtrl = Новый COMОбъект("MSScriptControl.ScriptControl");
	ScrptCtrl.Language = "vbscript";
	Попытка
		ScrptCtrl.AddCode(ТекстМодуля);
	Исключение
		ирОбщий.СообщитьЛкс(ScrptCtrl.Error.Description);
		ирОбщий.СообщитьЛкс(ScrptCtrl.Error.Source);
		ирОбщий.СообщитьЛкс(ScrptCtrl.Error.Text);
		ирОбщий.СообщитьЛкс(ScrptCtrl.Error.Line);
	КонецПопытки;
	Результат = ScrptCtrl.Run("getMemberReturn", ReturnType);
	Возврат Результат;
	
КонецФункции

Функция WshShell() Экспорт 
	
	Если WScriptShell = Неопределено Тогда
		WScriptShell = Новый COMОбъект("WScript.Shell");
	КонецЕсли; 
	Возврат WScriptShell;

КонецФункции

Процедура ПрочитатьОбщиеНастройки()
	
	ОбщиеНастройки = ирОбщий.ВосстановитьЗначениеЛкс("ОбщиеНастройки");
	Если ОбщиеНастройки = Неопределено Тогда
		// Старый формат настроек
		ФайловыйКэшАлгоритмовДопускаетРедактирование = ирОбщий.ВосстановитьЗначениеЛкс("ФайловыйКэшАлгоритмовДопускаетРедактирование");
		АвторегистрацияComКомпонент = ирОбщий.ВосстановитьЗначениеЛкс("АвторегистрацияComКомпонент");
		ПерехватКлавиатурногоВводаВОбычномПриложении = ирОбщий.ВосстановитьЗначениеЛкс("ПерехватКлавиатурногоВводаВОбычномПриложении");
		ВыделениеРезультатовПоиска = ирОбщий.ВосстановитьЗначениеЛкс("ВыделениеРезультатовПоиска");
		НеИспользоватьУправляемыеФормыИнструментов = ирОбщий.ВосстановитьЗначениеЛкс("НеИспользоватьУправляемыеФормыИнструментов");
	Иначе
		ФайловыйКэшАлгоритмовДопускаетРедактирование = ОбщиеНастройки.ФайловыйКэшАлгоритмовДопускаетРедактирование;
		АвторегистрацияComКомпонент = ОбщиеНастройки.АвторегистрацияComКомпонент;
		ПерехватКлавиатурногоВводаВОбычномПриложении = ОбщиеНастройки.ПерехватКлавиатурногоВводаВОбычномПриложении;
		ВыделениеРезультатовПоиска = ОбщиеНастройки.ВыделениеРезультатовПоиска;
		НеИспользоватьУправляемыеФормыИнструментов = ОбщиеНастройки.НеИспользоватьУправляемыеФормыИнструментов;
	КонецЕсли;
	
	// Фиксированные. Больше не меняем.
	ВыполнятьАлгоритмыЧерезВнешниеОбработки = Ложь;
	
	Если ФайловыйКэшАлгоритмовДопускаетРедактирование = Неопределено Тогда
		ФайловыйКэшАлгоритмовДопускаетРедактирование = Ложь;
	КонецЕсли;
	Если НеИспользоватьУправляемыеФормыИнструментов = Неопределено Тогда
		НеИспользоватьУправляемыеФормыИнструментов = Ложь;
	КонецЕсли;
	// Антибаг http://partners.v8.1c.ru/forum/thread.jsp?id=861032#861032
	Если АвторегистрацияComКомпонент = Неопределено Тогда
		АвторегистрацияComКомпонент = Истина;
	КонецЕсли;
	#Если Клиент Тогда
		Если ПерехватКлавиатурногоВводаВОбычномПриложении = Неопределено Тогда
			ПерехватКлавиатурногоВводаВОбычномПриложении = Метаданные.ОсновнойРежимЗапуска = РежимЗапускаКлиентскогоПриложения.УправляемоеПриложение;
		КонецЕсли; 
		//СинтаксическийКонтрольПередЗаписью = ирОбщий.ВосстановитьЗначениеЛкс("СинтаксическийКонтрольПередЗаписью");
		//Если СинтаксическийКонтрольПередЗаписью = Неопределено Тогда
		СинтаксическийКонтрольПередЗаписью = Истина;
		//КонецЕсли;
		Если ВыделениеРезультатовПоиска = Неопределено Тогда
			ВыделениеРезультатовПоиска = "⧼⧽";
		КонецЕсли;
	#КонецЕсли
	Если ОбщиеНастройки = Неопределено Тогда
		СохранитьОбщиеНастройки();
	КонецЕсли;

КонецПроцедуры

Процедура СохранитьОбщиеНастройки() Экспорт 
	
	ОбщиеНастройки = Новый Структура;
	ОбщиеНастройки.Вставить("ФайловыйКэшАлгоритмовДопускаетРедактирование", ФайловыйКэшАлгоритмовДопускаетРедактирование);
	ОбщиеНастройки.Вставить("АвторегистрацияComКомпонент", АвторегистрацияComКомпонент);
	ОбщиеНастройки.Вставить("ПерехватКлавиатурногоВводаВОбычномПриложении", ПерехватКлавиатурногоВводаВОбычномПриложении);
	ОбщиеНастройки.Вставить("ВыделениеРезультатовПоиска", ВыделениеРезультатовПоиска);
	ОбщиеНастройки.Вставить("НеИспользоватьУправляемыеФормыИнструментов", НеИспользоватьУправляемыеФормыИнструментов);
	ирОбщий.СохранитьЗначениеЛкс("ОбщиеНастройки", ОбщиеНастройки);

КонецПроцедуры

Функция НовоеСлужебноеПолеТекста(Знач СлужебнаяФорма = Неопределено, Знач Суффикс = "") Экспорт 
	Перем ПолеТекста;
	Если СлужебнаяФорма = Неопределено Тогда
		СлужебнаяФорма = мСлужебнаяФорма;
	КонецЕсли;
	ПолеТекста = СлужебнаяФорма.ЭлементыФормы.Добавить(Тип("ПолеТекстовогоДокумента"), "СлужебноеПолеТекста" + Суффикс, Ложь);
	Возврат ПолеТекста;

КонецФункции

//ирПортативный Контейнер = Новый Структура();
//ирПортативный #Если Клиент Тогда
//ирПортативный Оповестить("ирПолучитьБазовуюФорму", Контейнер);
//ирПортативный #КонецЕсли
//ирПортативный Если Не Контейнер.Свойство("ирПортативный", ирПортативный) Тогда
//ирПортативный 	Файл = Новый Файл(ИспользуемоеИмяФайла);
//ирПортативный 	ПолноеИмяФайлаБазовогоМодуля = Лев(Файл.Путь, СтрДлина(Файл.Путь) - СтрДлина("Модули\")) + "ирПортативный.epf";
//ирПортативный 	ирПортативный = ВнешниеОбработки.Создать(ПолноеИмяФайлаБазовогоМодуля, Ложь); // Это будет второй экземпляр объекта
//ирПортативный КонецЕсли; 
//ирПортативный ирОбщий = ирПортативный.ОбщийМодульЛкс("ирОбщий");
//ирПортативный ирКэш = ирПортативный.ОбщийМодульЛкс("ирКэш");
//ирПортативный ирСервер = ирПортативный.ОбщийМодульЛкс("ирСервер");
//ирПортативный ирКлиент = ирПортативный.ОбщийМодульЛкс("ирКлиент");

#Если Сервер И Не Сервер Тогда
	мТаблицаВсехТаблицБД = Обработки.ирКлсПолеТекстаПрограммы.Создать().ДоступныеТаблицы.ВыгрузитьКолонки();
	ИнициацияОписанияМетодовИСвойств();
	НоваяТаблицаТипов();
#КонецЕсли
ИнициализацияОписанияОбщихТипов();
мМетаданные = Метаданные;
КэшОбъектов = Новый Соответствие;
мКэшПустыхЗначений = Новый Соответствие;
мПассивныеФормы = новый Соответствие;
СисИнфо = Новый СистемнаяИнформация;
Фрагменты = ирОбщий.СтрРазделитьЛкс(СисИнфо.ВерсияПриложения);
ВерсияПлатформы = Число(Фрагменты[0]) * 100 * 1000 + Число(Фрагменты[1]) * 1000 + Число(Фрагменты[2]);
ЭтоИнтеграция = Метаданные.Справочники.Найти("иисМетаданные") <> Неопределено;
МаркерНачалаАлгоритма = "//НАЧАЛО.СЕРВИС" + Символы.ПС;
МаркерКонцаАлгоритма  = "//КОНЕЦ_.СЕРВИС" + Символы.ПС;
мМаркерИмениЗапросаПакета = "{Запрос: ";
мМаркерИмениЧастиОбъединения = "{Выборка: ";

шЛюбой = "(?:.|\n|\r)";
шБуква = "_ЁА-ЯA-Z";
шБукваЦифра = "_ЁА-ЯA-Z0-9";
шБукваСРешеткой = "_ЁА-ЯA-Z#";
шКомментарий = "//[^\n]*(?=(?:\n|$))";
шРазделитель = "(?:" + шКомментарий + "|\s|\xa0|$)"; // Возможно стоит добавить |\n|\r . Пришлось явно добавить неразрывный пробел (\xa0), т.к. VBScript не находит его через \s
шПустоеНачалоСтроки = "(?:\n|^)(?:\t| )*";   
шДирективаПрепроцессора = "#[^\n]*(?=(?:\n|$))";

// Когда внутри шРазделитель был управляющий символ <начало строки>, то возникали зависания на больших литералах https://www.hostedredmine.com/issues/966307
//шЛитералПрограммы = """(?:""""|[^""\n])*(?:" + шРазделитель + "*\|(?:""""|[^""\n])*)*(?:""|$)"; // 
шЛитералПрограммы = """(?:""""|[^""\n\r])*(?:(?:\n|\r|^)(?:\t| )*(?:" + шКомментарий + "|" + шДирективаПрепроцессора + "|\|(?:""""|[^""\n\r])*)|\s|\xa0)*(?:""|(?=\n|\r|$))"; // Так быстрее (меньше откатов) 14.08.2023 . \r добавил для защиты от зависаний на экзотических файлах с OD-OD-OA

шЛитералВЗапросе = """(?:(?:"""")|[^""\n])*(?:""|\n|$)"; // Есть сильно связанный шаблон шНачалоЛитералаВЗапросе в ирКлсПолеТекстаПрограммы
шGUID = "[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}";
шЧисло = "\d+(\.\d+)?";
шИндекс = "(\[[^\]\[]+?(?:(?:\[[^\]]+?\][^\]\[]*?)*)*\])";
шЛитералПростой = """[^""]*""";
//шЛитералПростой = шЛитералПрограммы; // Так будут зависания при анализе Мультиметка59234971
шМеждуСкобок = "[^\(\);""]";
шСкобки = "(\(" + шМеждуСкобок + "*(?:(?:" + шЛитералПростой + "|\((?:" + "[^\);""]" + "|" + шЛитералПростой + ")*\))" + шМеждуСкобок + "*)*\))"; // МультиМетка82355611
шИмя = "[" + шБуква + "][" + шБуква + "\d]*";
шИмяСРешеткой = "[" + шБукваСРешеткой + "][" + шБукваСРешеткой + "\d]*";
шИмяВременнойТаблицы = шИмяСРешеткой + "(?:\." + шИмяСРешеткой + ")*";
шГиперСсылка = "(\b(?:[" + шБукваЦифра + "]+)://[" + шБукваЦифра + "-+&@#\\/%?=~_|!:,.;()]+)";

ВложенностьИндикации = 0;
ИмяКластераСерверов = НСтр(СтрокаСоединенияИнформационнойБазы(), "Srvr");
ЭтоФайловаяБаза = ПустаяСтрока(ИмяКластераСерверов);
ПрочитатьОбщиеНастройки();

Парсеры = Новый Структура;
ШаблоныВнешнейОбработки = Новый Соответствие;
ШаблоныВнешнейОбработкиСМакетом = Новый Соответствие;
ПроверитьСтруктуруФайловогоКэша();
ИмяФайлаПакера = "v8unpack.exe";
МассивОбычныхЭлементовУправления = Новый Массив;
РежимОтладки = Ложь;
АсинхронностьЗапрещена = Ложь;

#Если Клиент Тогда
ТаблицаСтатистикиВыбора = ирОбщий.ВосстановитьЗначениеЛкс("ирПлатформа.ТаблицаСтатистикиВыбора");
Если ТаблицаСтатистикиВыбора <> Неопределено Тогда
	Если ТаблицаСтатистикиВыбора.Колонки.Найти("ЯзыкПрограммы") = Неопределено Тогда 
		ТаблицаСтатистикиВыбора = Неопределено;
	КонецЕсли; 
КонецЕсли; 
Если ТаблицаСтатистикиВыбора = Неопределено Тогда
	ТаблицаСтатистикиВыбора = Новый ТаблицаЗначений;
	ТаблицаСтатистикиВыбора.Колонки.Добавить("ТипКонтекста");
	ТаблицаСтатистикиВыбора.Колонки.Добавить("Слово");
	ТаблицаСтатистикиВыбора.Колонки.Добавить("ЯзыкПрограммы");
	ТаблицаСтатистикиВыбора.Колонки.Добавить("Рейтинг", Новый ОписаниеТипов("Число"));
КонецЕсли;

РежимОтладки = Найти(НРег(ПараметрЗапуска), НРег("РежимОтладкиИР")) > 0;
АсинхронностьЗапрещена = Найти(НРег(ПараметрЗапуска), НРег("ЗапретитьАсинхронностьИР")) > 0;
COMНавигатор = "НеИнициализирован";

ОтложенноеОткрытиеИсточникаОшибки = Новый ТаблицаЗначений;
ОтложенноеОткрытиеИсточникаОшибки.Колонки.Добавить("АлгоритмОбъект");
ОтложенноеОткрытиеИсточникаОшибки.Колонки.Добавить("ИнформацияОбОшибке");
ОтложенноеОткрытиеИсточникаОшибки.Колонки.Добавить("РежимВыполненияАлгоритма");
ОтложенноеОткрытиеИсточникаОшибки.Колонки.Добавить("Смещение", Новый ОписаниеТипов("Число"));
мСлужебнаяФорма = ПолучитьФорму("Служебная");
Если мСлужебнаяФорма <> Неопределено Тогда // Для портативного режима управляемого приложения
	СлужебноеПолеТекста = НовоеСлужебноеПолеТекста();
	СлужебноеПолеТекста2 = НовоеСлужебноеПолеТекста(, "2");
	//СлужебноеПолеHtmlДокумента = СлужебнаяФорма.ЭлементыФормы.Добавить(Тип("ПолеHTMLДокумента"), "СлужебноеПолеHTMLДокумента", Ложь); // Тяжелая операция
КонецЕсли; 

МассивОбычныхЭлементовУправления.Добавить("Диаграмма"); 
МассивОбычныхЭлементовУправления.Добавить("ДиаграммаГанта"); 
МассивОбычныхЭлементовУправления.Добавить("Дендрограмма"); 
МассивОбычныхЭлементовУправления.Добавить("Индикатор"); 
МассивОбычныхЭлементовУправления.Добавить("ПолеКалендаря"); 
МассивОбычныхЭлементовУправления.Добавить("Кнопка"); 
МассивОбычныхЭлементовУправления.Добавить("КолонкаТабличногоПоля"); 
МассивОбычныхЭлементовУправления.Добавить("КоманднаяПанель"); 
МассивОбычныхЭлементовУправления.Добавить("Надпись"); 
МассивОбычныхЭлементовУправления.Добавить("Панель"); 
МассивОбычныхЭлементовУправления.Добавить("Переключатель"); 
МассивОбычныхЭлементовУправления.Добавить("ПолеГрафическойСхемы"); 
МассивОбычныхЭлементовУправления.Добавить("ПолеГеографическойСхемы");
МассивОбычныхЭлементовУправления.Добавить("ПолеТабличногоДокумента"); 
МассивОбычныхЭлементовУправления.Добавить("ПолеHTMLДокумента"); 
МассивОбычныхЭлементовУправления.Добавить("ПолеТекстовогоДокумента"); 
МассивОбычныхЭлементовУправления.Добавить("ПолеВвода"); 
МассивОбычныхЭлементовУправления.Добавить("ПолеВыбора"); 
МассивОбычныхЭлементовУправления.Добавить("ПолеСписка"); 
МассивОбычныхЭлементовУправления.Добавить("ПолеКартинки"); 
МассивОбычныхЭлементовУправления.Добавить("ПолосаРегулирования"); 
МассивОбычныхЭлементовУправления.Добавить("Разделитель"); 
МассивОбычныхЭлементовУправления.Добавить("РамкаГруппы"); 
МассивОбычныхЭлементовУправления.Добавить("СводнаяДиаграмма"); 
МассивОбычныхЭлементовУправления.Добавить("СтраницаПанели"); 
МассивОбычныхЭлементовУправления.Добавить("ТабличноеПоле"); 
МассивОбычныхЭлементовУправления.Добавить("Флажок"); 

мМассивТиповЭлементовОбычнойФормы = Новый Массив;
Для Каждого ИмяТипа Из МассивОбычныхЭлементовУправления Цикл
	мМассивТиповЭлементовОбычнойФормы.Добавить(Тип(ИмяТипа));
КонецЦикла;
#КонецЕсли

МассивУправляемыхЭлементовУправления = Новый Массив;
МассивУправляемыхЭлементовУправления.Добавить("ПолеФормы"); 
МассивУправляемыхЭлементовУправления.Добавить("КнопкаФормы"); 
МассивУправляемыхЭлементовУправления.Добавить("ТаблицаФормы"); 
МассивУправляемыхЭлементовУправления.Добавить("ГруппаФормы"); 
МассивУправляемыхЭлементовУправления.Добавить("ДекорацияФормы"); 

мМассивТиповСМетаданными = Новый Массив;
мМассивТиповСМетаданными.Добавить(Тип("ОбъектМетаданных"));
мМассивТиповСМетаданными.Добавить(Тип("КоллекцияОбъектовМетаданных"));
мМассивТиповСМетаданными.Добавить(Тип("КоллекцияДвижений")); 
мМассивТиповСМетаданными.Добавить(Тип("ОписанияСтандартныхРеквизитов")); 
мМассивТиповСМетаданными.Добавить(Тип("СписокПолей")); 
мМассивТиповСМетаданными.Добавить(Тип("Структура"));
мМассивТиповСМетаданными.Добавить(Тип("СписокЗначений"));
мМассивТиповСМетаданными.Добавить(Тип("ФиксированнаяСтруктура"));
мМассивТиповСМетаданными.Добавить(Тип("ТаблицаЗначений"));
мМассивТиповСМетаданными.Добавить(Тип("ДеревоЗначений"));
мМассивТиповСМетаданными.Добавить(Тип("СтрокаТаблицыЗначений"));
мМассивТиповСМетаданными.Добавить(Тип("СтрокаДереваЗначений"));
мМассивТиповСМетаданными.Добавить(Тип("ВыборкаИзРезультатаЗапроса"));
мМассивТиповСМетаданными.Добавить(Тип("РезультатЗапроса"));
мМассивТиповСМетаданными.Добавить(Тип("Отбор"));
мМассивТиповСМетаданными.Добавить(Тип("НастройкаОформления"));
мМассивТиповСМетаданными.Добавить(Тип("COMОбъект"));
мМассивТиповСМетаданными.Добавить(Тип("ВнешнийОбъект"));
мМассивТиповСМетаданными.Добавить(Тип("ОбъектXDTO"));
мМассивТиповСМетаданными.Добавить(Тип("СвойствоXDTO"));
//мМассивТиповСМетаданными.Добавить(Тип("ОбщийМодуль"));
мМассивТиповСМетаданными.Добавить(Тип("ПостроительЗапроса"));
мМассивТиповСМетаданными.Добавить(Тип("ПостроительОтчета"));
мМассивТиповСМетаданными.Добавить(Тип("ПоляНастройки"));
мМассивТиповСМетаданными.Добавить(Тип("СхемаКомпоновкиДанных"));
мМассивТиповСМетаданными.Добавить(Тип("ТабличныйДокумент"));
мМассивТиповСМетаданными.Добавить(Тип("ТекстовыйДокумент"));
мМассивТиповСМетаданными.Добавить(Тип("НаборыДанныхСхемыКомпоновкиДанных"));
мМассивТиповСМетаданными.Добавить(Тип("ПараметрыСхемыКомпоновкиДанных"));
//мМассивТиповСМетаданными.Добавить(Тип("ДинамическийСписок")); // Будет давать ошибку сериализации
мМассивТиповСМетаданными.Добавить(Тип("ДанныеФормыДерево"));
мМассивТиповСМетаданными.Добавить(Тип("ДанныеФормыКоллекция"));
мМассивТиповСМетаданными.Добавить(Тип("ДанныеФормыКоллекцияЭлементовДерева"));
мМассивТиповСМетаданными.Добавить(Тип("ДанныеФормыСтруктура"));
мМассивТиповСМетаданными.Добавить(Тип("ДанныеФормыСтруктураСКоллекцией"));
мМассивТиповСМетаданными.Добавить(Тип("ДанныеФормыЭлементДерева"));
мМассивТиповСМетаданными.Добавить(Тип("ДанныеФормыЭлементКоллекции"));
мМассивТиповСМетаданными.Добавить(ирОбщий.ТипУправляемаяФормаЛкс());
мМассивТиповСМетаданными.Добавить(Тип("ПолеФормы"));
мМассивТиповСМетаданными.Добавить(Тип("ГруппаФормы"));
мМассивТиповСМетаданными.Добавить(Тип("ТаблицаФормы"));
мМассивТиповСМетаданными.Добавить(Тип("КомандыФормы"));
#Если Клиент Тогда
мМассивТиповСМетаданными.Добавить(Тип("Форма"));
мМассивТиповСМетаданными.Добавить(Тип("ТабличноеПоле"));
мМассивТиповСМетаданными.Добавить(Тип("Панель"));
мМассивТиповСМетаданными.Добавить(Тип("КнопкаКоманднойПанели"));
мМассивТиповСМетаданными.Добавить(Тип("КоманднаяПанель"));
мМассивТиповСМетаданными.Добавить(Тип("ПолеВвода"));
#КонецЕсли

//#Если Клиент Или ВнешнееСоединение Тогда

СубПутьКФайлуПотокаМодуляВнешнейОбработки    = "1ad4dbd4-e136-4202-8121-02c33ad2af45.0.data.und.unp\text.data";
СубПутьКФайлуПотокаМакетаВнешнейОбработки    = "902f74d3-f929-4b0f-8719-4cbb655891aa.0.data.und";
СубПутьКФайлуПотокаЗаголовкаВнешнейОбработки = "4eb1cc18-835d-4f8c-a120-3f9d886d75d4.data.und";
СубПутьККонтрольномуФайлуВнешнейОбработки    = "1ad4dbd4-e136-4202-8121-02c33ad2af45.0.data";

//КешВнешнихОбработокАлгоритмов = Новый Структура;

КешАлгоритмов = Новый Структура;
ТаблицаТиповМетаОбъектов = ирКэш.ТипыМетаОбъектов();
МакетыКомпонент = Новый Структура;
МаркерКоллекцииОбъектовМетаданных = "КоллекцияОбъектовМетаданных";
МаркерОбъектаМетаданных = "ОбъектМетаданных";
мМассивИсключенийИменКоллекций = Новый СписокЗначений;
мМассивИсключенийИменКоллекций.Добавить("Свойства");
мМассивИсключенийИменКоллекций.Добавить("Методы");
мМассивИсключенийИменКоллекций.Добавить("");

СоответствиеВидовСравнения = Новый ТаблицаЗначений;
СоответствиеВидовСравнения.Колонки.Добавить("Построитель");
СоответствиеВидовСравнения.Колонки.Добавить("Компоновка");
СоответствиеВидовСравнения.Колонки.Добавить("Имя");
СоответствиеВидовСравнения.Индексы.Добавить("Построитель");
СоответствиеВидовСравнения.Индексы.Добавить("Компоновка");
//Интервал
//ИнтервалВключаяГраницы
//ИнтервалВключаяНачало
//ИнтервалВключаяОкончание
СоответствиеВидовСравнения.Добавить().Имя = "Больше";
СоответствиеВидовСравнения.Добавить().Имя = "БольшеИлиРавно";
СоответствиеВидовСравнения.Добавить().Имя = "ВИерархии";
СоответствиеВидовСравнения.Добавить().Имя = "ВСписке";
СоответствиеВидовСравнения.Добавить().Имя = "ВСпискеПоИерархии";
СоответствиеВидовСравнения.Добавить().Имя = "Меньше";
СоответствиеВидовСравнения.Добавить().Имя = "МеньшеИлиРавно";
СоответствиеВидовСравнения.Добавить().Имя = "НеВИерархии";
СоответствиеВидовСравнения.Добавить().Имя = "НеВСписке";
СоответствиеВидовСравнения.Добавить().Имя = "НеВСпискеПоИерархии";
СоответствиеВидовСравнения.Добавить().Имя = "НеРавно";
СоответствиеВидовСравнения.Добавить().Имя = "НеСодержит";
СоответствиеВидовСравнения.Добавить().Имя = "Равно";
СоответствиеВидовСравнения.Добавить().Имя = "Содержит";
Для Каждого СтрокаСоответствия Из СоответствиеВидовСравнения Цикл
	СтрокаСоответствия.Построитель = Вычислить("ВидСравнения." + СтрокаСоответствия.Имя);
	СтрокаСоответствия.Компоновка  = Вычислить("ВидСравненияКомпоновкиДанных." + СтрокаСоответствия.Имя);
КонецЦикла;

мТаблицаЗамеров = Новый ТаблицаЗначений;
мТаблицаЗамеров.Колонки.Добавить("_0");
мТаблицаЗамеров.Колонки.Добавить("Ключ");
мТаблицаЗамеров.Колонки.Добавить("ДатаНачала");
мТаблицаЗамеров.Колонки.Добавить("ОтладкаРазрешена", Новый ОписаниеТипов("Булево"));
мТаблицаЗамеров.Колонки.Добавить("КоличествоПроходов", Новый ОписаниеТипов("Число"));

мТаблицаИндикаторов = Новый ТаблицаЗначений;
мТаблицаИндикаторов.Колонки.Добавить("КоличествоПроходов", Новый ОписаниеТипов("Число"));
мТаблицаИндикаторов.Колонки.Добавить("ПредставлениеПроцесса", Новый ОписаниеТипов("Строка"));
мТаблицаИндикаторов.Колонки.Добавить("ЛиВыводитьВремя", Новый ОписаниеТипов("Булево"));
мТаблицаИндикаторов.Колонки.Добавить("РазрешитьПрерывание", Новый ОписаниеТипов("Булево"));
мТаблицаИндикаторов.Колонки.Добавить("ДатаНачалаПроцесса", Новый ОписаниеТипов("Дата"));
мТаблицаИндикаторов.Колонки.Добавить("МинимальныйПериодОбновления", Новый ОписаниеТипов("Число"));
мТаблицаИндикаторов.Колонки.Добавить("СледующееОбновление", Новый ОписаниеТипов("Дата"));
мТаблицаИндикаторов.Колонки.Добавить("Шаг", Новый ОписаниеТипов("Число"));
мТаблицаИндикаторов.Колонки.Добавить("ТекстСостояния", Новый ОписаниеТипов("Строка"));
мТаблицаИндикаторов.Колонки.Добавить("СледующийСчетчик", Новый ОписаниеТипов("Число"));
мТаблицаИндикаторов.Колонки.Добавить("Счетчик", Новый ОписаниеТипов("Число"));
мТаблицаИндикаторов.Колонки.Добавить("РежимОтладки", Новый ОписаниеТипов("Булево")); // Для ускорения
мТаблицаИндикаторов.Колонки.Добавить("СледующаяПроверкаПрерывания", Новый ОписаниеТипов("Дата"));

//#КонецЕсли
RegExp = ирОбщий.НовоеРегВыражениеЛкс();
RegExp.IgnoreCase = Истина;
RegExp.MultiLine = Ложь;
RegExp2 = ирОбщий.НовоеРегВыражениеЛкс();
RegExp2.IgnoreCase = Истина;
RegExp2.MultiLine = Ложь;
мИменаОсновныхКлассовБиблиотекCOM = Новый Соответствие;
мОбразцыCOMОбъектов = Новый Соответствие;
БуферыСравнения = Новый Соответствие;
МодальныеГруппы = Новый СписокЗначений;
ОтмененныеФоновыеЗадания = Новый Массив;
мДобавленныеОбщиеМодули = Новый Структура;
мОписаниеТипаМДТабличнаяЧасть = ОписаниеТипаМетаОбъектов("ТабличнаяЧасть");
мОписаниеТипаМДВнешнийИсточникДанных = ОписаниеТипаМетаОбъектов("ВнешнийИсточникДанных");
мРежимПроверкиМодуля = Ложь;
