com.github._1c_syntax.bsl.languageserver.diagnostics.AbstractFindMethodDiagnostic Maven / Gradle / Ivy
/*
* This file is a part of BSL Language Server.
*
* Copyright (c) 2018-2022
* Alexey Sosnoviy , Nikita Fedkin and contributors
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* BSL Language Server is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* BSL Language Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BSL Language Server.
*/
package com.github._1c_syntax.bsl.languageserver.diagnostics;
import com.github._1c_syntax.bsl.parser.BSLParser;
import com.github._1c_syntax.bsl.parser.BSLParserRuleContext;
import lombok.Getter;
import lombok.Setter;
import org.antlr.v4.runtime.tree.ParseTree;
import java.util.regex.Pattern;
/**
* Абстрактная диагностика, предназначенная для поиска вызова обычных методов и методов глобального контекста
* с использованием регулярного выражения.
* {@code AbstractFindMethodDiagnostic} предоставляет для переопределения два метода проверки вызовов и один
* метод генерации сообщения пользователю.
* По умолчанию проверяется, что имя вызываемого метода соответствует переданному в конструкторе регулярному выражению.
* Важно: наследование данной диагностики без переопределения {@code getMessage} подразумевает, что первым
* параметром сообщения пользователю всегда будет имя найденного метода.
*/
public abstract class AbstractFindMethodDiagnostic extends AbstractVisitorDiagnostic {
@Getter
@Setter
private Pattern methodPattern;
/**
* Конструктор по умолчанию
*
* @param pattern регулярное выражение для проверки
*/
AbstractFindMethodDiagnostic(Pattern pattern) {
methodPattern = pattern;
}
/**
* Проверка контекста глобального метода
*
* @param ctx контекст глобального метода
* @return {@code true} если имя метода соответствует регулярному выражению
*/
protected boolean checkGlobalMethodCall(BSLParser.GlobalMethodCallContext ctx) {
return getMethodPattern().matcher(ctx.methodName().getText()).matches();
}
/**
* Проверка контекста обычного метода
*
* @param ctx контекст метода
* @return {@code true} если имя метода соответствует регулярному выражению
*/
protected boolean checkMethodCall(BSLParser.MethodCallContext ctx) {
return getMethodPattern().matcher(ctx.methodName().getText()).matches();
}
/**
* Получает сообщение диагностики для пользователя
*
* @param ctx контекст узла
* @return В случае если передан контекст метода, параметризованное сообщение,
* первым параметром которого всегда будет имя метода.
* В противном случае возвращается обычное сообщение без параметров.
*/
protected String getMessage(BSLParserRuleContext ctx) {
if (ctx instanceof BSLParser.GlobalMethodCallContext) {
return info.getMessage(((BSLParser.GlobalMethodCallContext) ctx).methodName().getText());
} else if (ctx instanceof BSLParser.MethodCallContext) {
return info.getMessage(((BSLParser.MethodCallContext) ctx).methodName().getText());
} else {
return info.getMessage();
}
}
/**
* Обработчик узла глобального метода. Добавляет информацию о сработавшей диагностике
* в случае если проверка метода {@link AbstractFindMethodDiagnostic#checkGlobalMethodCall(BSLParser.GlobalMethodCallContext)}
* возвращает {@code true}
*
* @param ctx контекст глобального метода
* @return результат посещения ноды по умолчанию.
*/
@Override
public ParseTree visitGlobalMethodCall(BSLParser.GlobalMethodCallContext ctx) {
if (checkGlobalMethodCall(ctx)) {
diagnosticStorage.addDiagnostic(ctx.methodName(), getMessage(ctx));
}
return super.visitGlobalMethodCall(ctx);
}
/**
* Обработчик узла обычного метода. Добавляет информацию о сработавшей диагностике
* в случае если проверка метода {@link AbstractFindMethodDiagnostic#checkMethodCall(BSLParser.MethodCallContext)}
* возвращает {@code true}
*
* @param ctx контекст метода
* @return результат посещения ноды по умолчанию.
*/
@Override
public ParseTree visitMethodCall(BSLParser.MethodCallContext ctx) {
if (checkMethodCall(ctx)) {
diagnosticStorage.addDiagnostic(ctx.methodName(), getMessage(ctx));
}
return super.visitMethodCall(ctx);
}
}