Существует ли в компиляторе какой-то механизм, позволяющий подписаться на уведомления об ошибках в процессе компиляции?
Что хочется:
— узнать сигнатуру метода внутри которого обнаружена ошибка (самое важное)
— изменить текст сообщения об ошибке
— не отображать ошибку в определенных случаях
Здравствуйте, VladD2, Вы писали:
VD>Подписаться можно. Изменить что либо нельзя. Ну, и в списке ошибок ошибки ужи имеют строковый вид. Понять в них что за метод будет очень сложно.
VD>Для решения этой задачи нужно в компилятор залезать и его править.
А если методы, предположительно содержащие ошибки, генерирую я сам? Могу я как-то на этапе определения метода заставить компилятор вернуть мне список ошибок или что-то в этом роде?
Конкретный сценарий. Есть куча сгенерированных автоматом типов, которые либо не имеют общего предка, либо он бесполезен.
Но структурно эти типы похожи (поля также имеют различные типы, но они как правило тоже структурно похожи).
Потому я генерируют перегрузки
| Скрытый текст |
| [Overloads(src, zfcs_notificationEFType
, zfcs_notificationEPType
, zfcs_notificationISMType
, zfcs_notificationISOType
, zfcs_notificationOKDType
, zfcs_notificationOKOUType
, zfcs_notificationOKType
, zfcs_notificationPOType
, zfcs_notificationZakAType
, zfcs_notificationZakKDType
, zfcs_notificationZakKOUType
, zfcs_notificationZakKType
, zfcs_notificationZKBIType
, zfcs_notificationZKType
, zfcs_notificationZPType
, zfcs_notificationLotChangeType)]
public notificationBase(src: zfcs_notificationLotChangeType) : TenderType
{
entity() <-
{
Attachments =
from attach in src.attachments
select attachment(attach);
IdentityInfo <-
{
TenderIdentity = src.purchaseNumber;
}
MainInfo <-
{
DirectDeal = nullable(TenderTypeMainInfoDirectDeal.Demand);
Name = src.purchaseObjectInfo;
PlacingWay <-
{
Code = src.placingWay.code;
Name = src.placingWay.name;
}
PurchaseType = nullable(TenderTypeMainInfoPurchaseType.OOS_44);
}
PublishInfo <-
{
Date = date(src.docPublishDate);
ModificationInfo = src.modification?.info;
Url = src.href;
}
StateInfo <-
{
State = TenderTypeStateInfoState.Published;
StatePublishDate = date(src.docPublishDate);
}
}
}
|
| |
Это в целом решает проблему, но если в какой-то из перегружаемых типов не имеет поля specializedOrg
то ошибка будет весьма скупой
error : unbound name `specializedOrg' in `src'
И приходится вручную перебирать типы в сигнатуре. А поскольку для разных типов сообщения в основном идентичные, то хотелось бы собрать что-то вроде
unbound name `specializedOrg' in `src' (zfcs_notificationZakKDType, zfcs_notificationISOType)
Если бы на этапе генерации перегрузки, я бы мог получить список ошибок, то к такому виду я бы схлопнул без проблем.
Здравствуйте, VladD2, Вы писали:
VD>Подписаться можно. Изменить что либо нельзя. Ну, и в списке ошибок ошибки ужи имеют строковый вид. Понять в них что за метод будет очень сложно.
VD>Для решения этой задачи нужно в компилятор залезать и его править.
Пытался изобразить иное решение, но опять проблемы.
Суть такова.
Я генерирую перегрузки метода для определенного параметра по списку типов.
И когда этих перегрузок много, если в какой-то из перегрузок что-то где-то не сошлось, то определить это достаточно сложно.
Приходится руками подставлять типы из списка перегрузок в сигнатуры и смотреть, на каком "покраснеет".
Я решил пойти в обход.
В макросе, который генерирует перегрузки на стадии BeforeTypedMembers, я добавляю макроатрибут с параметром, содержащим тип из которого перегрузка возникла.
Дальше этот макроатрибут работает на стадии WithTypedMembers.
Он пытается типизировать тело метода, а потом его обойти в поисках TExpr.Error, чтобы сгенерить в нужном месте ошибку с указанием типа, перегрузка которого упала.
Вот примерно такой код.
public DoTransform(typer : Typer, _ : TypeBuilder, method : MethodBuilder, src : PExpr) : void
{
Macros.DefineCTX(typer);
def methodTyper = Typer(method);
methodTyper.RunFullTyping();
match(method.GetHeader().Body)
{
| FunBody.Typed(t) =>
_ = t.Walk(e => match(e)
{
| TExpr.Error =>
Message.FatalError(e.Location, src.ToString());
null;
| _ => null;
});
| _ => ();
}
К сожалению, Walk выбрасывает что-то вроде
Common.n(96,6): warning : invalid expr in walk: Nemerle.Compiler.Typedtree.TExpr+Block: block (_N_return) :
5> DEBUG_INFO(DEBUG_INFO(def res = macro_Macros.DSL._N_operator1214590017_4673Macro:
5> def _N_initializedObject_4959 = Functions.entity.[XMLSchema.SharedCore.AttachmentType+] ();
5> DEBUG_INFO(_N_initializedObject_4959.FileName) = DEBUG_INFO((ERROR));
5> DEBUG_INFO(_N_initializedObject_4959.Description) = DEBUG_INFO((ERROR));
5> DEBUG_INFO(_N_initializedObject_4959.Identity) = DEBUG_INFO((ERROR));
5> _N_initializedObject_4959;
5> );
5> DEBUG_INFO(def item = (ERROR);
5> );
5> DEBUG_INFO(macro_Macros.DSL.ChoiceMacro:
5> TExpr.Delayed(delayed macro));
5> DEBUG_INFO(res))
5> confused by earlier errors bailing out
То есть никакого свое сообщения я не вижу. И все места, где используется отложенная типизация разваливаются.
Мне надо как-то по другом типизировать тело метода?
Или, может, мне надо как-то по другому его обходить?
Или, может, такая задача решается как-то иначе или проще?