From 1bcce78983140866da80ee982c9ee6bd66265b6b Mon Sep 17 00:00:00 2001 From: Vadim Geraskin Date: Thu, 10 Feb 2022 22:18:53 +0700 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B8=20=D0=BA=D0=B2=D0=B8=D0=BA-=D1=84=D0=B8=D0=BA?= =?UTF-8?q?=D1=81=D1=8B=20=D0=B4=D0=BB=D1=8F=20BSL-=D0=BC=D0=BE=D0=B4?= =?UTF-8?q?=D1=83=D0=BB=D0=B5=D0=B9=20(#955)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org.eclipse.core.resources.prefs | 1 + .../META-INF/MANIFEST.MF | 11 + bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml | 6 + .../e1c/v8codestyle/bsl/ui/qfix/Messages.java | 44 +++ .../bsl/ui/qfix/QuickFixMethodsHelper.java | 232 ++++++++++++++ .../bsl/ui/qfix/UndefinedFunctionFix.java | 46 +++ .../bsl/ui/qfix/UndefinedMethodFix.java | 72 +++++ .../bsl/ui/qfix/UndefinedVariableFix.java | 129 ++++++++ .../bsl/ui/qfix/messages.properties | 22 ++ .../bsl/ui/qfix/messages_ru.properties | 21 ++ .../META-INF/MANIFEST.MF | 24 +- bundles/com.e1c.v8codestyle.bsl/plugin.xml | 11 +- .../e1c/v8codestyle/bsl/check/Messages.java | 14 +- .../bsl/check/UndefinedFunctionCheck.java | 82 +++++ .../bsl/check/UndefinedMethodCheck.java | 78 +++++ .../bsl/check/UndefinedVariableCheck.java | 133 ++++++++ .../v8codestyle/bsl/check/messages.properties | 14 +- .../bsl/check/messages_ru.properties | 13 +- .../qfix/external/BslCheckFixBoostrap.java | 43 +++ .../external/BslIssueModificationContext.java | 109 +++++++ ...tiVariantXtextModuleFixChangeDelegate.java | 35 +++ ...leVariantXtextModuleFixChangeDelegate.java | 30 ++ .../external/IXtextBslModuleFixModel.java | 83 +++++ .../external/IXtextBslModuleFixProvider.java | 37 +++ .../IXtextInteractiveBslModuleFixModel.java | 92 ++++++ .../MultiVariantXtextBslModuleFix.java | 257 ++++++++++++++++ .../SingleVariantXtextBslModuleFix.java | 285 ++++++++++++++++++ ...SingleVariantXtextBslModuleFixContext.java | 79 +++++ ...ariantXtextBslModuleFixContextFactory.java | 54 ++++ .../qfix/external/XtextBslModuleFixModel.java | 158 ++++++++++ .../external/XtextBslModuleFixProvider.java | 79 +++++ .../XtextInteractiveBslModuleFixModel.java | 186 ++++++++++++ .../v8codestyle/internal/bsl/BslPlugin.java | 19 +- .../bsl/ExternalDependenciesModule.java | 10 +- checkstyle.xml | 10 +- 35 files changed, 2502 insertions(+), 17 deletions(-) create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/Messages.java create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/QuickFixMethodsHelper.java create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedFunctionFix.java create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedMethodFix.java create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedVariableFix.java create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages.properties create mode 100644 bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages_ru.properties create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/UndefinedFunctionCheck.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/UndefinedMethodCheck.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/UndefinedVariableCheck.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/BslCheckFixBoostrap.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/BslIssueModificationContext.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IMultiVariantXtextModuleFixChangeDelegate.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/ISingleVariantXtextModuleFixChangeDelegate.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextBslModuleFixModel.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextBslModuleFixProvider.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextInteractiveBslModuleFixModel.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/MultiVariantXtextBslModuleFix.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFix.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFixContext.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFixContextFactory.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextBslModuleFixModel.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextBslModuleFixProvider.java create mode 100644 bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextInteractiveBslModuleFixModel.java diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/.settings/org.eclipse.core.resources.prefs b/bundles/com.e1c.v8codestyle.bsl.ui/.settings/org.eclipse.core.resources.prefs index 6342b631..884eda01 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/.settings/org.eclipse.core.resources.prefs +++ b/bundles/com.e1c.v8codestyle.bsl.ui/.settings/org.eclipse.core.resources.prefs @@ -1,4 +1,5 @@ eclipse.preferences.version=1 +encoding//src/com/e1c/v8codestyle/bsl/ui/qfix/messages_ru.properties=UTF-8 encoding//src/com/e1c/v8codestyle/internal/bsl/ui/preferences/messages_ru.properties=UTF-8 encoding//src/com/e1c/v8codestyle/internal/bsl/ui/properties/messages_ru.properties=UTF-8 encoding//src/com/e1c/v8codestyle/internal/bsl/ui/views/messages_ru.properties=UTF-8 diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/META-INF/MANIFEST.MF b/bundles/com.e1c.v8codestyle.bsl.ui/META-INF/MANIFEST.MF index 9d38deba..240d1d50 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/META-INF/MANIFEST.MF +++ b/bundles/com.e1c.v8codestyle.bsl.ui/META-INF/MANIFEST.MF @@ -25,13 +25,20 @@ Import-Package: com._1c.g5.ides.ui.texteditor.xtext.embedded;version="[5.0.0,6.0 com._1c.g5.v8.dt.bsl.common;version="[6.0.0,7.0.0)", com._1c.g5.v8.dt.bsl.documentation.comment;version="[3.0.0,4.0.0)", com._1c.g5.v8.dt.bsl.model;version="[5.0.0,6.0.0)", + com._1c.g5.v8.dt.bsl.services;version="[6.0.0,7.0.0)", + com._1c.g5.v8.dt.bsl.ui;version="[8.2.0,9.0.0)", + com._1c.g5.v8.dt.bsl.ui.contentassist;version="[8.0.0,9.0.0)", com._1c.g5.v8.dt.bsl.ui.editor;version="[8.0.0,9.0.0)", com._1c.g5.v8.dt.bsl.ui.menu;version="[6.0.0,7.0.0)", + com._1c.g5.v8.dt.bsl.ui.quickfix;version="[4.1.0,5.0.0)", com._1c.g5.v8.dt.bsl.util;version="[7.0.0,8.0.0)", com._1c.g5.v8.dt.common;version="[6.0.0,7.0.0)", com._1c.g5.v8.dt.core.filesystem;version="[5.0.0,6.0.0)", com._1c.g5.v8.dt.core.model;version="[6.0.0,7.0.0)", com._1c.g5.v8.dt.core.platform;version="[10.0.0,11.0.0)", + com._1c.g5.v8.dt.lcore.ui.editor;version="[2.3.0,3.0.0)", + com._1c.g5.v8.dt.lcore.ui.texteditor;version="[1.1.0,2.0.0)", + com._1c.g5.v8.dt.lcore.util;version="[2.0.0,3.0.0)", com._1c.g5.v8.dt.mcore;version="[6.0.0,7.0.0)", com._1c.g5.v8.dt.metadata.mdclass;version="[8.0.0,9.0.0)", com._1c.g5.v8.dt.theming.ui.util;version="[1.0.0,2.0.0)", @@ -39,5 +46,9 @@ Import-Package: com._1c.g5.ides.ui.texteditor.xtext.embedded;version="[5.0.0,6.0 com._1c.g5.v8.dt.ui.wizards;version="[8.0.0,9.0.0)", com._1c.g5.wiring;version="[2.2.0,3.0.0)", com._1c.g5.wiring.binder;version="[1.1.0,2.0.0)", + com.e1c.g5.v8.dt.bsl.check.qfix;version="[1.0.0,2.0.0)", + com.e1c.g5.v8.dt.check.qfix;version="[1.0.0,2.0.0)", + com.e1c.g5.v8.dt.check.qfix.components;version="[1.0.0,2.0.0)", com.e1c.v8codestyle.bsl;version="[0.2.0,0.3.0)", + com.e1c.v8codestyle.bsl.qfix.external;version="[0.2.0,0.3.0)", com.e1c.v8codestyle.bsl.strict;version="[0.2.0,0.3.0)" diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml b/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml index deee5579..3dd043d5 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml +++ b/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml @@ -344,5 +344,11 @@ + + + + + + diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/Messages.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/Messages.java new file mode 100644 index 00000000..21ca7ba1 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/Messages.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.ui.qfix; + +import org.eclipse.osgi.util.NLS; + +/** + * NLS messages + * + * @author Vadim Geraskin + */ +final class Messages + extends NLS +{ + private static final String BUNDLE_NAME = "com.e1c.v8codestyle.bsl.ui.qfix.messages"; //$NON-NLS-1$ + + public static String UndefinedMethodFix_func_title; + public static String UndefinedMethodFix_func_desc; + public static String UndefinedMethodFix_proc_title; + public static String UndefinedMethodFix_proc_desc; + public static String UndefinedVariableFix_title; + public static String UndefinedVariableFix_desc; + + static + { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() + { + // N/A + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/QuickFixMethodsHelper.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/QuickFixMethodsHelper.java new file mode 100644 index 00000000..e3bfee7f --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/QuickFixMethodsHelper.java @@ -0,0 +1,232 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.ui.qfix; + +import java.util.Optional; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.link.LinkedModeModel; +import org.eclipse.jface.text.link.LinkedPosition; +import org.eclipse.jface.text.link.LinkedPositionGroup; +import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.xtext.nodemodel.util.NodeModelUtils; +import org.eclipse.xtext.ui.editor.model.IXtextDocument; + +import com._1c.g5.v8.dt.bsl.model.Method; +import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; +import com._1c.g5.v8.dt.bsl.ui.contentassist.BslProposalProvider; +import com._1c.g5.v8.dt.bsl.ui.quickfix.BslQuickFixUtil; +import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant; +import com.e1c.v8codestyle.bsl.qfix.external.IXtextBslModuleFixModel; +import com.e1c.v8codestyle.bsl.qfix.external.IXtextInteractiveBslModuleFixModel; +import com.google.common.base.Strings; + +/** + * Helper methods for xtext-based quick fixes + * + * @author Vadim Geraskin + */ +public final class QuickFixMethodsHelper +{ + /** + * Creates method and writes it to module + * + * @param model the xtext BSL quick fix model, cannot be {@code null} + * @param isFunc indicates whether the method is function or procedure + * @throws BadLocationException + */ + static void createMethod(IXtextInteractiveBslModuleFixModel model, boolean isFunc) throws BadLocationException + { + EObject element = model.getElement(); + + String methodName = getMethodName(((StaticFeatureAccess)element).getName()); + String directiveName = ""; //$NON-NLS-1$ + + //up to Method class + Method method = EcoreUtil2.getContainerOfType(element, Method.class); + + if (method != null) + { + String methodKeywordType = getTypeMethodName(model, isFunc); + String methodEndKeywordType = getTypeEndMethodName(model, isFunc); + + //calculation offset + int totalEndOffset = NodeModelUtils.getNode(method).getTotalEndOffset(); + Optional indent = model.getFormatString(method); + + if (indent.isPresent()) + { + String func = createMethod(model, indent.get(), directiveName, methodName, methodKeywordType, + methodEndKeywordType); + + // Write method to module + IXtextDocument document = (IXtextDocument)model.getDocument(); + BslQuickFixUtil.writeToDoc(document, totalEndOffset, func); + flushMethod(model, indent.get(), methodKeywordType, totalEndOffset, directiveName); + } + } + } + + /** + * Provides offset for the given {@Method} + * + * @param method the method, cannot be {@code null} + * @return offset + */ + static int getMethodOffset(Method method) + { + //method always has statement + return NodeModelUtils.findActualNodeFor(method.allStatements().get(0)).getOffset(); + } + + /** + * Gets 'Procedure' or 'Function' + * + * @param model {@link IXtextBslModuleFixModel}, cannot be {@code null} + * @param isFunc defines what will be return + * @return 'Procedure' if isFunc == false, else return 'Function' + */ + static String getTypeMethodName(IXtextBslModuleFixModel model, boolean isFunc) + { + boolean isRussion = model.getScriptVariant() == ScriptVariant.RUSSIAN; + return BslProposalProvider.getTypeMethodName(model.getBslGrammar(), isFunc, isRussion); + } + + /** + * Gets 'EndProcedure' or 'EndFunction' + * + * @param model {@link IXtextBslModuleFixModel}, cannot be {@code null} + * @param isFunc defines what will be return + * @return 'EndProcedure' if isFunc == false, else return 'EndFunction' + */ + static String getTypeEndMethodName(IXtextBslModuleFixModel model, boolean isFunc) + { + boolean isRussion = model.getScriptVariant() == ScriptVariant.RUSSIAN; + return BslProposalProvider.getTypeEndMethodName(model.getBslGrammar(), isFunc, isRussion); + } + + private static String getMethodName(String name) + { + StringBuilder builder = new StringBuilder(); + + builder.append(name); + builder.append('('); + builder.append(')'); + return builder.toString(); + } + + private static String createMethod(IXtextInteractiveBslModuleFixModel model, String indent, String directive, + String methodName, String methodKeyword, String methodEndKeyword) + { + String lineSeparator = model.getLineSeparator(); + String commentContent = Strings.repeat(lineSeparator, 2); + String todoComment = indent + model.getIndentProvider().getIndent() + + model.getBslGeneratorMultiLangProposals().getImplementationPropStr(); + + StringBuilder builder = new StringBuilder(); + //add comment above function + builder.append(commentContent); + //create function body + if (!Strings.isNullOrEmpty(directive)) + { + builder.append(indent).append('&').append(directive).append(lineSeparator); + } + builder.append(indent).append(methodKeyword).append(' '); + builder.append(methodName); + builder.append(lineSeparator).append(todoComment).append(lineSeparator); + builder.append(indent).append(methodEndKeyword); + return builder.toString(); + } + + private static void flushMethod(IXtextInteractiveBslModuleFixModel model, String indent, String methodKeywordType, + int totalEndOffset, String directiveName) + { + IXtextDocument document = (IXtextDocument)model.getDocument(); + String lineSeparator = model.getLineSeparator(); + String commentContent = Strings.repeat(lineSeparator, 2); + //creating LinkedModeModel + LinkedPosition[] groupParams = calculateParamsGroupForMethod(commentContent, indent, lineSeparator, + methodKeywordType, document, model.getIssueData(), totalEndOffset); + int posDec = totalEndOffset + indent.length() + methodKeywordType.length() + 1 + commentContent.length(); + if (!Strings.isNullOrEmpty(directiveName)) + { + posDec += indent.length() + 1 + directiveName.length() + lineSeparator.length(); + } + int posUse = model.getIssue().getOffset(); + + int nameLen = ((StaticFeatureAccess)model.getElement()).getName().length(); + createLinkedModeModel(model, posDec, posUse, nameLen, groupParams); + } + + private static LinkedPosition[] calculateParamsGroupForMethod(String commentContent, String indent, + String lineSeparator, String functionKeywordType, IXtextDocument doc, String[] data, int offset) + { + if (data != null && data.length >= 2) + { + int numParams = Integer.parseInt(data[2]); + LinkedPosition[] groupParams = new LinkedPosition[numParams]; + int startLen = data[1].length() + 2 + offset + commentContent.length() + indent.length() + + functionKeywordType.length(); + if (!Strings.isNullOrEmpty(data[0])) + { + startLen += indent.length() + data[0].length() + lineSeparator.length() + 1; + } + for (int i = 3; i < data.length; ++i) + { + groupParams[i - 3] = new LinkedPosition(doc, startLen, data[i].length()); + startLen += data[i].length() + 2; + } + return groupParams; + } + else + { + return new LinkedPosition[0]; + } + } + + private static void createLinkedModeModel(IXtextInteractiveBslModuleFixModel model, int posDec, int posUse, + int length, LinkedPosition[] params) + { + IXtextDocument document = (IXtextDocument)model.getDocument(); + try + { + // create groups - this step is independent of the linked mode + LinkedPositionGroup group = new LinkedPositionGroup(); + group.addPosition(new LinkedPosition(document, posDec, length)); + group.addPosition(new LinkedPosition(document, posUse, length)); + /* set up linked mode */ + LinkedModeModel linkedModeModel = model.getLinkedModeModel(); + linkedModeModel.addGroup(group); + for (int i = 0; i < params.length; ++i) + { + LinkedPositionGroup groupParam = new LinkedPositionGroup(); + groupParam.addPosition(params[i]); + linkedModeModel.addGroup(groupParam); + } + LinkedModeModel.closeAllModels(document); + linkedModeModel.forceInstall(); + model.enterUiMode(); + model.selectAndRevealForLinkedModeModel(posDec, length); + } + catch (Exception e) + { + model.selectAndRevealForLinkedModeModel(posUse, length); + } + } + + private QuickFixMethodsHelper() + { + // Not to be instantiated + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedFunctionFix.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedFunctionFix.java new file mode 100644 index 00000000..76bee21a --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedFunctionFix.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.ui.qfix; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.text.edits.TextEdit; +import org.eclipse.xtext.resource.XtextResource; + +import com.e1c.g5.v8.dt.check.qfix.components.QuickFix; +import com.e1c.v8codestyle.bsl.qfix.external.IXtextBslModuleFixModel; +import com.e1c.v8codestyle.bsl.qfix.external.IXtextInteractiveBslModuleFixModel; +import com.e1c.v8codestyle.bsl.qfix.external.SingleVariantXtextBslModuleFix; + + +/** + * Quick fix for check com.e1c.v8codestyle.bsl.check:undefined-function + * + * @author Vadim Geraskin + */ +@QuickFix(checkId = "module-undefined-function", supplierId = "com.e1c.v8codestyle.bsl") +public class UndefinedFunctionFix + extends SingleVariantXtextBslModuleFix +{ + @Override + protected void configureFix(FixConfigurer configurer) + { + configurer.interactive(true).description(Messages.UndefinedMethodFix_func_title); + } + + @Override + protected TextEdit fixIssue(XtextResource state, IXtextBslModuleFixModel model) throws BadLocationException + { + QuickFixMethodsHelper.createMethod((IXtextInteractiveBslModuleFixModel)model, true); + return null; + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedMethodFix.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedMethodFix.java new file mode 100644 index 00000000..2be4e38a --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedMethodFix.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.ui.qfix; + +import org.eclipse.jface.text.BadLocationException; + +import com.e1c.g5.v8.dt.check.qfix.components.QuickFix; +import com.e1c.v8codestyle.bsl.qfix.external.IXtextInteractiveBslModuleFixModel; +import com.e1c.v8codestyle.bsl.qfix.external.MultiVariantXtextBslModuleFix; +import com.e1c.v8codestyle.internal.bsl.ui.UiPlugin; + +/** + * Quick fix for check com.e1c.v8codestyle.bsl.check:undefined-method + * + * @author Vadim Geraskin + */ +@QuickFix(checkId = "module-undefined-method", supplierId = "com.e1c.v8codestyle.bsl") +public class UndefinedMethodFix + extends MultiVariantXtextBslModuleFix +{ + @Override + protected void buildVariants() + { + // 1-st variant of issue qf: create function + VariantBuilder.create(this) + .description(Messages.UndefinedMethodFix_func_title, Messages.UndefinedMethodFix_func_desc) + .interactive(true) + .change((context, session, state, model) -> createFunction((IXtextInteractiveBslModuleFixModel)model)) + .build(); + + // 2-nd variant of issue qf: create procedure + VariantBuilder.create(this) + .description(Messages.UndefinedMethodFix_proc_title, Messages.UndefinedMethodFix_proc_desc) + .interactive(true) + .change((context, session, state, model) -> createProcedure((IXtextInteractiveBslModuleFixModel)model)) + .build(); + } + + private void createFunction(IXtextInteractiveBslModuleFixModel model) + { + try + { + QuickFixMethodsHelper.createMethod(model, true); + } + catch (BadLocationException e) + { + UiPlugin.log(UiPlugin.createErrorStatus("Error occured when creating function", e)); //$NON-NLS-1$ + } + } + + private void createProcedure(IXtextInteractiveBslModuleFixModel model) + { + try + { + QuickFixMethodsHelper.createMethod(model, false); + } + catch (BadLocationException e) + { + UiPlugin.log(UiPlugin.createErrorStatus("Error occured when creating procedure", e)); //$NON-NLS-1$ + } + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedVariableFix.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedVariableFix.java new file mode 100644 index 00000000..110fffda --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/UndefinedVariableFix.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.ui.qfix; + +import java.util.Optional; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.link.LinkedModeModel; +import org.eclipse.jface.text.link.LinkedPosition; +import org.eclipse.jface.text.link.LinkedPositionGroup; +import org.eclipse.text.edits.TextEdit; +import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.ui.editor.model.IXtextDocument; + +import com._1c.g5.v8.dt.bsl.model.Method; +import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; +import com._1c.g5.v8.dt.bsl.ui.quickfix.BslQuickFixUtil; +import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant; +import com.e1c.g5.v8.dt.check.qfix.components.QuickFix; +import com.e1c.v8codestyle.bsl.qfix.external.IXtextBslModuleFixModel; +import com.e1c.v8codestyle.bsl.qfix.external.IXtextInteractiveBslModuleFixModel; +import com.e1c.v8codestyle.bsl.qfix.external.SingleVariantXtextBslModuleFix; + +/** + * Quick fix for check com.e1c.v8codestyle.bsl.check:undefined-variable + * + * @author Vadim Geraskin + */ +@QuickFix(checkId = "module-undefined-variable", supplierId = "com.e1c.v8codestyle.bsl") +public class UndefinedVariableFix + extends SingleVariantXtextBslModuleFix +{ + @Override + protected void configureFix(FixConfigurer configurer) + { + configurer.interactive(true) + .description(Messages.UndefinedVariableFix_title) + .details(Messages.UndefinedVariableFix_desc); + } + + @Override + protected TextEdit fixIssue(XtextResource state, IXtextBslModuleFixModel model) throws BadLocationException + { + IXtextInteractiveBslModuleFixModel interactiveModel = (IXtextInteractiveBslModuleFixModel)model; + + EObject element = model.getElement(); + String declarationKeyWord = getDeclarationKeyword(model); + + //up to Method class + Method method = EcoreUtil2.getContainerOfType(element, Method.class); + + if (method != null) + { + Optional indent = interactiveModel.getFormatString(method); + if (indent.isPresent()) + { + int offset = QuickFixMethodsHelper.getMethodOffset(method); + + String variableName = ((StaticFeatureAccess)model.getElement()).getName(); + IXtextDocument document = (IXtextDocument)interactiveModel.getDocument(); + String lineSeparator = model.getLineSeparator(); + + String variable = BslQuickFixUtil.createVariable(declarationKeyWord, variableName, + indent.get() + interactiveModel.getIndentProvider().getIndent(), lineSeparator); + + //write var to module + BslQuickFixUtil.writeToDoc(document, offset, variable); + + //linked mode model + int posDec = offset + declarationKeyWord.length() + 1; + int posUse = model.getIssue().getOffset() + variable.length(); + int length = variableName.length(); + + createLinkedModeModel(interactiveModel, posDec, posUse, length); + } + } + return null; + } + + //CHECKSTYLE.OFF: LineLength + private static String getDeclarationKeyword(IXtextBslModuleFixModel model) + { + boolean isRussion = model.getScriptVariant() == ScriptVariant.RUSSIAN; + return !isRussion ? model.getBslGrammar().getDeclareStatementAccess().getVarKeyword_0_0().getValue() : model + .getBslGrammar() + .getDeclareStatementAccess() + .getCyrillicCapitalLetterPeCyrillicSmallLetterIeCyrillicSmallLetterErCyrillicSmallLetterIeCyrillicSmallLetterEmKeyword_0_1() + .getValue(); + } + //CHECKSTYLE.ON: LineLength + + private static void createLinkedModeModel(IXtextInteractiveBslModuleFixModel model, int posDec, int posUse, + int length) + { + IXtextDocument document = (IXtextDocument)model.getDocument(); + try + { + //create groups - this step is independent of the linked mode + LinkedPositionGroup group = new LinkedPositionGroup(); + group.addPosition(new LinkedPosition(document, posDec, length)); + group.addPosition(new LinkedPosition(document, posUse, length)); + //set up linked mode + LinkedModeModel linkedModeModel = model.getLinkedModeModel(); + linkedModeModel.addGroup(group); + LinkedModeModel.closeAllModels(document); + linkedModeModel.forceInstall(); + + model.enterUiMode(); + model.selectAndRevealForLinkedModeModel(posUse, length); + } + catch (Exception e) + { + //mark using varible + model.selectAndRevealForLinkedModeModel(posUse, length); + } + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages.properties b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages.properties new file mode 100644 index 00000000..c086e1c0 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages.properties @@ -0,0 +1,22 @@ + +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) +############################################################################### +# Copyright (C) 2022, 1C-Soft LLC and others. +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# 1C-Soft LLC - initial API and implementation +# Vadim Geraskin - initial contibution +############################################################################### + +UndefinedMethodFix_func_title=Create function +UndefinedMethodFix_func_desc=Create a new function in the module +UndefinedMethodFix_proc_title=Create procedure +UndefinedMethodFix_proc_desc=Create a new procedure in the module +UndefinedVariableFix_title=Create variable +UndefinedVariableFix_desc=Create a missing variable in the method or module.\nSave changes in the editor after quick fix is applied. diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages_ru.properties b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages_ru.properties new file mode 100644 index 00000000..d83ff315 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages_ru.properties @@ -0,0 +1,21 @@ +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) +############################################################################### +# Copyright (C) 2022, 1C-Soft LLC and others. +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# 1C-Soft LLC - initial API and implementation +# Vadim Geraskin - initial contibution +############################################################################### + +UndefinedMethodFix_func_title=Создать функцию +UndefinedMethodFix_func_desc=Создать новую функцию в модуле +UndefinedMethodFix_proc_title=Создать процедуру +UndefinedMethodFix_proc_desc=Создать новую процедуру в модуле +UndefinedVariableFix_title=Создать переменную +UndefinedVariableFix_desc=Создать пропущенную переменную на уровне метода или модуля.\nПосле применения исправления сохраните изменения в редакторе. diff --git a/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF b/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF index e300ae53..78611bed 100644 --- a/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF +++ b/bundles/com.e1c.v8codestyle.bsl/META-INF/MANIFEST.MF @@ -6,16 +6,22 @@ Bundle-Version: 0.2.0.qualifier Bundle-Activator: com.e1c.v8codestyle.internal.bsl.BslPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin -Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.0.0,4.0.0)", +Require-Bundle: org.eclipse.core.resources;bundle-version="[3.13.0,4.0.0)", + org.eclipse.core.runtime;bundle-version="[3.0.0,4.0.0)", org.eclipse.emf.common;bundle-version="[2.15.0,3.0.0)", + org.eclipse.text;bundle-version="[3.8.100,4.0.0)", org.eclipse.xtext;bundle-version="[2.17.0,3.0.0)", - org.eclipse.core.resources;bundle-version="[3.13.0,4.0.0)", org.eclipse.xtext.builder;bundle-version="[2.18.0,3.0.0)", + org.eclipse.xtext.ui;bundle-version="[2.24.0,3.0.0)", + org.eclipse.handly;bundle-version="[1.5.0,2.0.0)", + org.eclipse.xtext.ui.shared;bundle-version="[2.19.0,3.0.0)", org.eclipse.jface.text;bundle-version="[3.17.0,4.0.0)" Bundle-RequiredExecutionEnvironment: JavaSE-11 Automatic-Module-Name: com.e1c.v8codestyle.bsl Bundle-ActivationPolicy: lazy -Import-Package: com._1c.g5.v8.bm.core;version="[7.0.0,8.0.0)", +Import-Package: com._1c.g5.ides.ui.texteditor.xtext.embedded;version="[5.0.0,6.0.0)", + com._1c.g5.v8.bm.core;version="[7.0.0,8.0.0)", + com._1c.g5.v8.dt.bsl;version="[4.4.0,5.0.0)", com._1c.g5.v8.dt.bsl.comment;version="[3.0.0,4.0.0)", com._1c.g5.v8.dt.bsl.common;version="[6.0.0,7.0.0)", com._1c.g5.v8.dt.bsl.contextdef;version="[2.0.0,3.0.0)", @@ -24,25 +30,37 @@ Import-Package: com._1c.g5.v8.bm.core;version="[7.0.0,8.0.0)", com._1c.g5.v8.dt.bsl.model.resource.owner;version="[2.0.0,3.0.0)", com._1c.g5.v8.dt.bsl.model.util;version="[4.0.0,5.0.0)", com._1c.g5.v8.dt.bsl.resource;version="[13.0.0,14.0.0)", + com._1c.g5.v8.dt.bsl.services;version="[6.0.0,7.0.0)", com._1c.g5.v8.dt.bsl.typesystem;version="[9.0.0,10.0.0)", com._1c.g5.v8.dt.bsl.typesystem.util;version="[9.0.0,10.0.0)", + com._1c.g5.v8.dt.bsl.ui;version="[8.2.0,9.0.0)", + com._1c.g5.v8.dt.bsl.ui.contentassist;version="[8.0.0,9.0.0)", + com._1c.g5.v8.dt.bsl.ui.quickfix;version="[4.1.0,5.0.0)", com._1c.g5.v8.dt.bsl.util;version="[7.0.0,8.0.0)", + com._1c.g5.v8.dt.bsl.validation;version="[16.0.0,17.0.0)", com._1c.g5.v8.dt.common;version="[6.0.0,7.0.0)", com._1c.g5.v8.dt.core.platform;version="[10.0.0,11.0.0)", com._1c.g5.v8.dt.form.model;version="[10.0.0,11.0.0)", + com._1c.g5.v8.dt.lcore.ui.editor;version="[2.3.0,3.0.0)", + com._1c.g5.v8.dt.lcore.ui.texteditor;version="[1.1.0,2.0.0)", com._1c.g5.v8.dt.lcore.util;version="[2.0.0,3.0.0)", com._1c.g5.v8.dt.mcore;version="[6.0.0,7.0.0)", com._1c.g5.v8.dt.mcore.util;version="[3.6.0,4.0.0)", com._1c.g5.v8.dt.metadata.mdclass;version="[8.0.0,9.0.0)", com._1c.g5.v8.dt.platform;version="[5.0.0,6.0.0)", com._1c.g5.v8.dt.platform.version;version="[2.13.0,3.0.0)", + com._1c.g5.v8.dt.validation.marker;version="[5.0.0,6.0.0)", com._1c.g5.wiring;version="[2.0.0,3.0.0)", com._1c.g5.wiring.binder;version="[1.0.0,2.0.0)", com.e1c.g5.v8.dt.bsl.check;version="[1.0.0,2.0.0)", + com.e1c.g5.v8.dt.bsl.check.qfix;version="[1.0.0,3.0.0)", com.e1c.g5.v8.dt.check;version="[2.0.0,3.0.0)", com.e1c.g5.v8.dt.check.components;version="[2.0.0,3.0.0)", + com.e1c.g5.v8.dt.check.qfix;version="[1.0.0,2.0.0)", + com.e1c.g5.v8.dt.check.qfix.components;version="[1.0.0,2.0.0)", com.e1c.g5.v8.dt.check.settings;version="[2.0.0,3.0.0)", com.e1c.v8codestyle;version="[0.2.0,0.3.0)", com.e1c.v8codestyle.check;version="[0.2.0,0.3.0)" Export-Package: com.e1c.v8codestyle.bsl;version="0.2.0", + com.e1c.v8codestyle.bsl.qfix.external;version="0.2.0", com.e1c.v8codestyle.bsl.strict;version="0.2.0" diff --git a/bundles/com.e1c.v8codestyle.bsl/plugin.xml b/bundles/com.e1c.v8codestyle.bsl/plugin.xml index 50a85fa2..7d807d6a 100644 --- a/bundles/com.e1c.v8codestyle.bsl/plugin.xml +++ b/bundles/com.e1c.v8codestyle.bsl/plugin.xml @@ -214,6 +214,15 @@ category="com.e1c.v8codestyle.bsl" class="com.e1c.v8codestyle.bsl.check.IsInRoleCheck"> + + + + + + @@ -226,8 +235,8 @@ category="com.e1c.v8codestyle.bsl" class="com.e1c.v8codestyle.bsl.check.ExportMethodInCommandFormModuleCheck"> - + ds.getVariables().stream()) + .anyMatch(v -> v.getName().equals(varName)); + } + + private static Environments getEnv(FeatureEntry entry) + { + Environments envs = new Environments(entry.getEnvironments().toArray()); + if (entry.eContainer() instanceof StaticFeatureAccess && envs.contains(Environment.MNG_CLIENT) + && !envs.contains(Environment.SERVER) && !BslPreferences.detectIsClientServer(entry)) + { + StaticFeatureAccess sfa = (StaticFeatureAccess)entry.eContainer(); + if (sfa.getFeatureEntries() + .stream() + .anyMatch(item -> item != entry && item.getEnvironments().contains(Environment.SERVER))) + { + envs = envs.remove(Environment.MNG_CLIENT); + } + } + + return envs; + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties index c4bd7e74..d05918d7 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties @@ -1,7 +1,7 @@ #Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) ############################################################################### -# Copyright (C) 2021, 1C-Soft LLC and others. +# Copyright (C) 2021-2022, 1C-Soft LLC and others. # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 @@ -211,3 +211,15 @@ UseNonRecommendedMethods_message = Using non-recommended method UseNonRecommendedMethods_parameter = List of non-recommended methods UseNonRecommendedMethods_title = Using non-recommended methods + +ModuleUndefinedVariableCheck_Title = Undefined variable +ModuleUndefinedVariableCheck_Description = Undefined variable +ModuleUndefinedVariable_msg = Variable "{0}" is not defined + +ModuleUndefinedMethodCheck_Title = Undefined method +ModuleUndefinedMethodCheck_Description = Undefined function or procedure + +ModuleUndefinedFunctionCheck_Title = Undefined function +ModuleUndefinedFunctionCheck_Description = Undefined function +ModuleUndefinedFunction_msg = Function "{0}" is not defined +ModuleUndefinedMethod_msg = Procedure or function "{0}" is not defined diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties index ff239d84..f9cf3c92 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties @@ -1,6 +1,6 @@ #Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) ############################################################################### -# Copyright (C) 2021, 1C-Soft LLC and others. +# Copyright (C) 2021-2022, 1C-Soft LLC and others. # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 @@ -211,3 +211,14 @@ UseNonRecommendedMethods_message = Используется не рекомен UseNonRecommendedMethods_parameter = Список дополнительных не рекомендуемых методов для проверки UseNonRecommendedMethods_title = Использование не рекомендуемых методов + +ModuleUndefinedVariableCheck_Title = Переменная не определена +ModuleUndefinedVariableCheck_Description = Переменная не определена +ModuleUndefinedVariable_msg = Переменная "{0}" не определена + +ModuleUndefinedMethodCheck_Title = Метод не определен +ModuleUndefinedMethodCheck_Description = Функция или процедура не определена +ModuleUndefinedFunctionCheck_Title = Функция не определена +ModuleUndefinedFunctionCheck_Description = Функция не определена +ModuleUndefinedFunction_msg = Функция "{0}" не определена +ModuleUndefinedMethod_msg = Процедура или функция "{0}" не определена diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/BslCheckFixBoostrap.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/BslCheckFixBoostrap.java new file mode 100644 index 00000000..28bf7cec --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/BslCheckFixBoostrap.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import com._1c.g5.wiring.IManagedService; +import com.e1c.g5.v8.dt.check.qfix.IFixRepository; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +/** + * Java-based registrar of BSL quick fix components + * + * @author Alexander Tretyakevich + */ +@Singleton +public class BslCheckFixBoostrap + implements IManagedService +{ + @Inject + private IFixRepository fixRepository; + + @Inject + private SingleVariantXtextBslModuleFixContextFactory singleVariantXtextBslModuleFixContextFactory; + + @Override + public void activate() + { + fixRepository.registerContextFactory(singleVariantXtextBslModuleFixContextFactory); + } + + @Override + public void deactivate() + { + // Not necessary at the moment + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/BslIssueModificationContext.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/BslIssueModificationContext.java new file mode 100644 index 00000000..1f1b6399 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/BslIssueModificationContext.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.ui.IEditorPart; +import org.eclipse.xtext.ui.editor.IURIEditorOpener; +import org.eclipse.xtext.ui.editor.XtextEditor; +import org.eclipse.xtext.ui.editor.model.IXtextDocument; +import org.eclipse.xtext.ui.editor.model.edit.IssueModificationContext; +import org.eclipse.xtext.validation.Issue; + +import com._1c.g5.v8.dt.lcore.ui.editor.ViewerAwareIssueModificationContext; +import com.google.common.base.Preconditions; + +/** + * Extension of {@link IssueModificationContext} to be used by quick fixes and suppressions + * + * @author Vadim Geraskin + */ +public class BslIssueModificationContext + extends ViewerAwareIssueModificationContext +{ + private final AtomicReference viewerRef = new AtomicReference<>(); + private final Issue issue; + private final IURIEditorOpener editorOpener; + + private IXtextDocument document; + + /** + * Instantiates modification context + * + * @param issue the issue, cannot be {@code null} + * @param editorOpener the editor opener, cannot be {@code null} + */ + public BslIssueModificationContext(Issue issue, IURIEditorOpener editorOpener) + { + this.issue = Preconditions.checkNotNull(issue); + this.editorOpener = Preconditions.checkNotNull(editorOpener); + } + + @Override + public IXtextDocument getXtextDocument() + { + return getXtextDocument(issue.getUriToProblem()); + } + + @Override + public IXtextDocument getXtextDocument(URI uri) + { + if (document != null) + { + return document; + } + + document = getXtextDocument(uri, editorOpener, editor -> viewerRef.set(extractLocalTextViewer(editor))); + setTextViewer(viewerRef.get()); + + return document; + } + + /* + * Extract text viewer from editor. Can return {@code null} + */ + private static ITextViewer extractLocalTextViewer(IEditorPart editor) + { + ITextOperationTarget target = editor.getAdapter(ITextOperationTarget.class); + if (target instanceof ITextViewer) + { + return (ITextViewer)target; + } + return null; + } + + private static IXtextDocument getXtextDocument(URI uri, IURIEditorOpener editorOpener, + Consumer editorConsumer) + { + for (int trial = 0; trial < 2; trial++) + { + IEditorPart editor = editorOpener.open(uri, false); + if (editor == null) + { + return null; + } + if (editorConsumer != null) + { + editorConsumer.accept(editor); + } + if (editor instanceof XtextEditor) + { + XtextEditor xtextEditor = (XtextEditor)editor; + return xtextEditor.getDocument(); + } + } + return null; + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IMultiVariantXtextModuleFixChangeDelegate.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IMultiVariantXtextModuleFixChangeDelegate.java new file mode 100644 index 00000000..a1e6e15a --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IMultiVariantXtextModuleFixChangeDelegate.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import org.eclipse.xtext.resource.XtextResource; + +import com.e1c.g5.v8.dt.check.qfix.IFixSession; + +/** + * Functional delegate that allows to specify the matching method as a change execution logic for multi-variant + * quick fixes + * + * @author Vadim Geraskin + */ +@FunctionalInterface +public interface IMultiVariantXtextModuleFixChangeDelegate +{ + /** + * Performs the fix application + * + * @param context the quick fix context, cannot be {@code null} + * @param session the fix session, cannot be {@code null} + * @param state the xtext resource, cannot be {@code null} + * @param model the quick fix model, cannot be {@code null} + */ + void applyFix(SingleVariantXtextBslModuleFixContext context, IFixSession session, XtextResource state, + IXtextBslModuleFixModel model); +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/ISingleVariantXtextModuleFixChangeDelegate.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/ISingleVariantXtextModuleFixChangeDelegate.java new file mode 100644 index 00000000..2adb5fc6 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/ISingleVariantXtextModuleFixChangeDelegate.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import com.e1c.g5.v8.dt.check.qfix.IFixSession; + +/** + * Functional delegate that allows to specify the matching method as a change execution logic for multi-variant + * quick fixes + * + * @author Vadim Geraskin + */ +@FunctionalInterface +public interface ISingleVariantXtextModuleFixChangeDelegate +{ + /** + * Perfoms apply of the fix + * + * @param context the quick fix context, cannot be {@code null} + * @param session the session, cannot be {@code null} + */ + void applyFix(SingleVariantXtextBslModuleFixContext context, IFixSession session); +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextBslModuleFixModel.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextBslModuleFixModel.java new file mode 100644 index 00000000..d24e3236 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextBslModuleFixModel.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.IDocument; +import org.eclipse.xtext.validation.Issue; + +import com._1c.g5.v8.dt.bsl.services.BslGrammarAccess; +import com._1c.g5.v8.dt.core.platform.IResourceLookup; +import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant; + +/** + * Contract for xtext BSL quick fix model + * + * @author Vadim Geraskin + */ +public interface IXtextBslModuleFixModel +{ + /** + * Provides {@link IDocument} + * + * @return {@link IDocument}, never {@code null} + */ + IDocument getDocument(); + + /** + * Provides module {@link IResourceLookup} + * + * @return {link IResourceLookup}, never {@code null} + */ + IResourceLookup getResourceLookup(); + + /** + * Provides the element which is used to create a quick fix + * + * @return the element, can be {@code null} + */ + EObject getElement(); + + /** + * xtext validation issue reference + * + * @return {@link Issue}, never {@code null} + */ + Issue getIssue(); + + /** + * The associated user data. May be {@code null} or empty but may not contain {@code null} entries. + * + * @return user data, can be {@code null} + */ + String[] getIssueData(); + + /** + * Provides {@link BslGrammarAccess} + * + * @return {@link BslGrammarAccess}, never {@code null} + */ + BslGrammarAccess getBslGrammar(); + + /** + * Returns {@code ScriptVariant} for current project + * + * @return {@code ScriptVariant}, never {@code null} + */ + ScriptVariant getScriptVariant(); + + /** + * Gets line separator preference set for current project. If the preference is not set for the project then + * the canonical lookup order is used (instance, configuration, default). + * + * @return the line separator preference. Never {@code null}. + */ + String getLineSeparator(); +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextBslModuleFixProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextBslModuleFixProvider.java new file mode 100644 index 00000000..1b55fb22 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextBslModuleFixProvider.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.xtext.validation.Issue; + +import com._1c.g5.v8.dt.core.platform.IDtProject; +import com.e1c.g5.v8.dt.check.qfix.IFixSession; + +/** + * Contract for {@link XtextBslModuleFixProvider} + * + * @author Vadim Geraskin + */ +public interface IXtextBslModuleFixProvider +{ + /** + * Returns xtext quick fix model + * + * @param dtProject the {@IDtProject}, cannot be {@code null} + * @param issue instance of the {@link Issue}, cannot be {@code null} + * @param session the {@code IFixSession}, cannot be {@code null} + * @param targetModuleUri the target module Uri, cannot be {@code null} + * @param isInteractive {@code true} if quick fix supports interactive (UI) model, {@code false} otherwise + * @return the quick fix model, never {@code null} + */ + IXtextBslModuleFixModel getXtextFixModel(IDtProject dtProject, Issue issue, IFixSession session, + URI targetModuleUri, boolean isInteractive); +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextInteractiveBslModuleFixModel.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextInteractiveBslModuleFixModel.java new file mode 100644 index 00000000..c914aa60 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/IXtextInteractiveBslModuleFixModel.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import java.util.Optional; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.link.LinkedModeModel; +import org.eclipse.xtext.ui.editor.model.edit.IModificationContext; + +import com._1c.g5.v8.dt.bsl.ui.BslGeneratorMultiLangProposals; +import com._1c.g5.v8.dt.lcore.ui.texteditor.IndentTextEditorProvider; + +/** + * Contract for xtext BSL interactive quick fix model + * + * @author Vadim Geraskin + */ +public interface IXtextInteractiveBslModuleFixModel + extends IXtextBslModuleFixModel +{ + /** + * Provides {@link IndentTextEditorProvider} + * + * @return {@link IndentTextEditorProvider}, never {@code null} + */ + IndentTextEditorProvider getIndentProvider(); + + /** + * Multilanguage proposals for quick-fix and content-assist for Bsl + * + * @return reference to {@link BslGeneratorMultiLangProposals}, never {@code null} + */ + BslGeneratorMultiLangProposals getBslGeneratorMultiLangProposals(); + + /** + * Provides modification context + * + * @return {@link IModificationContext}, never {@code null} + */ + IModificationContext getModificationContext(); + + /** + * Provides the format string for the given {@code EObject} which is the semantic object whose node should + * be provided {@code NodeModelUtils.findActualNodeFor()} + * + * @param eObject the object, cannot be {@code null} + * @return format string, never {@code null} + * @throws BadLocationException + */ + Optional getFormatString(EObject eObject) throws BadLocationException; + + /** + * Provides {@code LinkedModeModel} + * + * @return {@code LinkedModeModel}, never {@code null} + */ + LinkedModeModel getLinkedModeModel(); + + /** + * Returns a description of the line at the given offset.The description contains the offset and the length of the + * line excluding the line's delimiter. + * + * @param offset the offset whose line should be described + * @return a region describing the line, never {@code null} + * @throws BadLocationException + */ + IRegion getLineInformationOfOffset(int offset) throws BadLocationException; + + /** + * Connects the ui mode for linked mode and starts UI on the first position + * Should be called write after installation of linkedModeModel: {@code linkedModeModel.forceInstall()} + */ + void enterUiMode(); + + /** + * Sets the selected range and reveals it + * + * @param posStart the start position + * @param length the length of selection + */ + void selectAndRevealForLinkedModeModel(int posStart, int length); +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/MultiVariantXtextBslModuleFix.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/MultiVariantXtextBslModuleFix.java new file mode 100644 index 00000000..5ca20a58 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/MultiVariantXtextBslModuleFix.java @@ -0,0 +1,257 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; + +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.ui.editor.model.IXtextDocument; +import org.eclipse.xtext.util.concurrent.IUnitOfWork; + +import com.e1c.g5.v8.dt.check.qfix.FixDescriptor; +import com.e1c.g5.v8.dt.check.qfix.FixVariantDescriptor; +import com.e1c.g5.v8.dt.check.qfix.IFix; +import com.e1c.g5.v8.dt.check.qfix.IFixChange; +import com.e1c.g5.v8.dt.check.qfix.IFixChangeProcessor; +import com.e1c.g5.v8.dt.check.qfix.IFixSession; +import com.e1c.g5.v8.dt.check.qfix.IFixVariant; +import com.e1c.g5.v8.dt.check.qfix.components.BasicFix; + +/** + * Multi-variant xtext module fix definition + * + * @author Alexander Tretyakevich - Initial contribution + * @author Vadim Geraskin - Additional features + */ +public abstract class MultiVariantXtextBslModuleFix + extends BasicFix + implements IFix +{ + private Collection> fixVariants = new HashSet<>(); + + @Override + public Class getRequiredContextType() + { + return SingleVariantXtextBslModuleFixContext.class; + } + + @Override + public Collection> getVariants( + SingleVariantXtextBslModuleFixContext context, IFixSession session) + { + return fixVariants; + } + + @Override + public void onRegistration(FixDescriptor registrationContext) + { + VariantXtextBslModuleFixChangeProcessor changeProcessor = new VariantXtextBslModuleFixChangeProcessor(); + registrationContext.setChangeProcessor(changeProcessor); + buildVariants(); + } + + /** + * Creates and sets up fix variants + */ + protected abstract void buildVariants(); + + /** + * Provides a builder of the quick fix variant + * + * @author Vadim Geraskin + */ + protected static class VariantBuilder + { + private final MultiVariantXtextBslModuleFix fix; + private IMultiVariantXtextModuleFixChangeDelegate delegate; + private String description; + private String details; + private boolean isInteractive; + + /** + * Creates variant builder instance + * + * @param fix the reference to the model fix, cannot be {@code null} + */ + public VariantBuilder(MultiVariantXtextBslModuleFix fix) + { + this.fix = fix; + } + + /** + * Static variant builder creator + * + * @param fix the reference to the model fix, cannot be {@code null} + * @return the instance of the variant builder, never {@code null} + */ + public static VariantBuilder create(MultiVariantXtextBslModuleFix fix) + { + return new VariantBuilder(fix); + } + + /** + * Creates code change delegate + * + * @param delegate change delegate, cannot be {@code null} + * @return the instance of the variant builder, never {@code null} + */ + public VariantBuilder change(IMultiVariantXtextModuleFixChangeDelegate delegate) + { + this.delegate = delegate; + return this; + } + + /** + * Sets the modification model type - either interactive (UI) or not + * + * @param isInteractive {@code true} if quick fix supports inbteractive (UI) model, {@code false} otherwise + * @return the instance of the variant builder, never {@code null} + */ + public VariantBuilder interactive(boolean isInteractive) + { + this.isInteractive = isInteractive; + return this; + } + + /** + * Creates variant description and details messages + * + * @param description the short description, cannot be {@code null} + * @param details the detailed message, can be {@code null} + * @return the instance of the variant builder, never {@code null} + */ + public VariantBuilder description(String description, String details) + { + this.description = description; + this.details = details; + return this; + } + + /** + * Finalizes the variant builder, registers the variant + */ + public void build() + { + IFixVariant variant = + new MultiVariantXtextBslModuleVariant<>(delegate, description, details, isInteractive); + fix.fixVariants.add(variant); + } + } + + private static class MultiVariantXtextBslModuleVariant + implements IFixVariant + { + private final IMultiVariantXtextModuleFixChangeDelegate delegate; + private final String description; + private final String details; + private final boolean isInteractive; + + /** + * Creates {@link MultiVariantXtextBslModuleVariant} instance + * + * @param delegate the delegate to be executed, cannot be {@code null} + * @param description the fix variant short description, cannot be {@code null} + * @param details the fix variant detailed description, can be {@code null} + * @param isInteractive {@code true} if quick fix supports interactive (UI) model, {@code false} otherwise + */ + MultiVariantXtextBslModuleVariant(IMultiVariantXtextModuleFixChangeDelegate delegate, String description, + String details, boolean isInteractive) + { + this.delegate = delegate; + this.description = description; + this.details = details; + this.isInteractive = true; + } + + @Override + public Collection prepareChanges(C context, IFixSession session) + { + if (context.getTargetModuleUri() == null) + { + return Collections.emptyList(); + } + + return Collections.singleton(new VariantXtextBslModuleFixChange(delegate, isInteractive)); + } + + @Override + public FixVariantDescriptor describeChanges(C context, IFixSession session) + { + return new FixVariantDescriptor(description, details); + } + } + + private static final class VariantXtextBslModuleFixChange + implements IFixChange + { + private final IMultiVariantXtextModuleFixChangeDelegate delegate; + private final boolean isInteractive; + + /** + * Creates {@link VariantXtextBslModuleFixChange} instance + * + * @param delegate the delegate to be executed, cannot be {@code null} + * @param isInteractive {@code true} if quick fix supports interactive (UI) model, {@code false} otherwise + */ + VariantXtextBslModuleFixChange(IMultiVariantXtextModuleFixChangeDelegate delegate, boolean isInteractive) + { + this.delegate = delegate; + this.isInteractive = isInteractive; + } + + /** + * Executes the quick fix resolution code + * + * @param context the quick fix context, cannot be {@code null} + * @param session the quick fix session, cannot be {@code null} + */ + public void applyFix(SingleVariantXtextBslModuleFixContext context, IFixSession session) + { + IXtextBslModuleFixModel fixModel = context.getModel(session, isInteractive); + if (fixModel instanceof IXtextInteractiveBslModuleFixModel) + { + ((IXtextDocument)fixModel.getDocument()).readOnly(new IUnitOfWork.Void() + { + @Override + public void process(XtextResource state) throws Exception + { + delegate.applyFix(context, session, state, fixModel); + } + }); + } + else + { + // Nothing at the moment + } + } + } + + /* + * Variant fix change processor + */ + private static final class VariantXtextBslModuleFixChangeProcessor + implements IFixChangeProcessor + { + @Override + public void applyFix(VariantXtextBslModuleFixChange fixChange, SingleVariantXtextBslModuleFixContext context, + IFixSession session) + { + fixChange.applyFix(context, session); + } + + @Override + public Class getProcessedFixType() + { + return VariantXtextBslModuleFixChange.class; + } + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFix.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFix.java new file mode 100644 index 00000000..9b9e75d4 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFix.java @@ -0,0 +1,285 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.function.BiFunction; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.text.edits.TextEdit; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.ui.editor.model.IXtextDocument; +import org.eclipse.xtext.ui.editor.model.edit.IModificationContext; +import org.eclipse.xtext.util.concurrent.IUnitOfWork; +import org.eclipse.xtext.validation.Issue; +import org.eclipse.xtext.validation.Issue.IssueImpl; + +import com._1c.g5.v8.dt.bsl.model.Module; +import com._1c.g5.v8.dt.common.Pair; +import com._1c.g5.v8.dt.common.StringUtils; +import com.e1c.g5.v8.dt.bsl.check.qfix.ExternalQuickfixModification; +import com.e1c.g5.v8.dt.check.qfix.FixDescriptor; +import com.e1c.g5.v8.dt.check.qfix.FixVariantDescriptor; +import com.e1c.g5.v8.dt.check.qfix.IFixChange; +import com.e1c.g5.v8.dt.check.qfix.IFixChangeProcessor; +import com.e1c.g5.v8.dt.check.qfix.IFixSession; +import com.e1c.g5.v8.dt.check.qfix.components.SingleVariantBasicFix; +import com.e1c.v8codestyle.internal.bsl.BslPlugin; + +/** + * Single variant xtext bsl module fix common class for multi-variant quick fixes + * + * @author Vadim Geraskin + */ +public abstract class SingleVariantXtextBslModuleFix + extends SingleVariantBasicFix +{ + private BiFunction> descriptionSupplier; + private boolean isInteractive; + + @Override + public Collection prepareChanges(SingleVariantXtextBslModuleFixContext context, IFixSession session) + { + Module module = session.getModule(context.getTargetModuleUri()); + if (module == null) + { + return Collections.emptyList(); + } + + return prepareChanges(this::applyChanges); + } + + @Override + public final FixVariantDescriptor describeChanges(SingleVariantXtextBslModuleFixContext context, + IFixSession session) + { + Pair description = descriptionSupplier.apply(context, session); + return new FixVariantDescriptor(description.first, description.second); + } + + @Override + public final void onRegistration(FixDescriptor registrationContext) + { + registrationContext.setChangeProcessor(new SingleVariantModuleFixChangeProcessor()); + + FixConfigurer configurer = new FixConfigurer(); + configureFix(configurer); + applyConfiguration(configurer); + } + + @Override + public Class getRequiredContextType() + { + return SingleVariantXtextBslModuleFixContext.class; + } + + /** + * Configures the fix. The developer could provide descreptive/filtering information for the fix here + * + * @param configurer The configurer of the fix. May not be {@code null} + */ + protected void configureFix(FixConfigurer configurer) + { + // Nothing by default + } + + /** + * Modification of code to be overriden by clients + * + * @param state the xtext resource, cannot be {@code null} + * @param model xtext bsl module fix model facade, cannot be {@code null} + * @return {@link TextEdit}, can be {@code null} + * @throws BadLocationException + */ + protected abstract TextEdit fixIssue(XtextResource state, IXtextBslModuleFixModel model) + throws BadLocationException; + + protected void applyChanges(SingleVariantXtextBslModuleFixContext context, IFixSession session) + { + IssueImpl issue = context.getIssue(); + + IXtextBslModuleFixModel fixModel = context.getModel(session, isInteractive); + if (fixModel instanceof IXtextInteractiveBslModuleFixModel) + { + IModificationContext modificationContext = + ((XtextInteractiveBslModuleFixModel)fixModel).getModificationContext(); + + ExternalQuickfixModification quickFixModification = new ExternalQuickfixModification<>(issue, + EObject.class, element -> fixIssue((IXtextInteractiveBslModuleFixModel)fixModel)); + + try + { + quickFixModification.apply(modificationContext); + } + catch (Exception e) + { + BslPlugin.log(BslPlugin.createErrorStatus("Error occured when applying quick fix", e)); //$NON-NLS-1$ + } + } + else + { + // Nothing at the moment + } + } + + private TextEdit fixIssue(IXtextInteractiveBslModuleFixModel fixModel) + { + Issue issue = fixModel.getIssue(); + if (issue.getOffset() == null) + { + return null; + } + + List textEdits = new ArrayList<>(); + IXtextDocument document = (IXtextDocument)fixModel.getDocument(); + document.readOnly(new IUnitOfWork.Void() + { + @Override + public void process(XtextResource state) throws Exception + { + TextEdit te = fixIssue(state, fixModel); + if (te != null) + { + textEdits.add(te); + } + } + }); + return !textEdits.isEmpty() ? textEdits.get(0) : null; + } + + private Collection prepareChanges(ISingleVariantXtextModuleFixChangeDelegate changeDelegate) + { + return Collections.singleton(new SingleVariantModuleFixChange(changeDelegate)); + } + + /* + * Applies configuration provided by the fix developer + */ + private void applyConfiguration(FixConfigurer configurer) + { + this.descriptionSupplier = configurer.descriptionSupplier; + if (this.descriptionSupplier == null) + { + // Description isn't specified - adding the safety loopback + this.descriptionSupplier = (context, session) -> Pair.newPair(StringUtils.EMPTY, StringUtils.EMPTY); + } + this.isInteractive = configurer.isInteractive; + } + + /* + * Single variant fix change unique for the SingleVariantModelBasicFix + */ + private static final class SingleVariantModuleFixChange + implements IFixChange + { + private final ISingleVariantXtextModuleFixChangeDelegate delegate; + + SingleVariantModuleFixChange(ISingleVariantXtextModuleFixChangeDelegate delegate) + { + this.delegate = delegate; + } + + public void applyFix(SingleVariantXtextBslModuleFixContext context, IFixSession session) + { + delegate.applyFix(context, session); + } + } + + /* + * Single variant fix change processor unique for the SingleVariantModelBasicFix + */ + private static final class SingleVariantModuleFixChangeProcessor + implements IFixChangeProcessor + { + @Override + public void applyFix(SingleVariantModuleFixChange fixChange, SingleVariantXtextBslModuleFixContext context, + IFixSession session) + { + fixChange.applyFix(context, session); + } + + @Override + public Class getProcessedFixType() + { + return SingleVariantModuleFixChange.class; + } + } + + /** + * Configuration container for the {@link SingleVariantXtextBslModuleFixContext} descendants allowing them to + * specify fix parameters via the pure Java API + * + * @author Alexander Tretyakevich + */ + protected static final class FixConfigurer + { + private BiFunction> + descriptionSupplier; + private boolean isInteractive = true; + private String description = StringUtils.EMPTY; + private String details = StringUtils.EMPTY; + + /** + * Sets the dynamic description supplier for the fix. The description may be formed using the data from + * the {@link SingleVariantXtextBslModuleFixContext} + * + * @param descriptionSupplier The supplier to set. May not be {@code null} + * @return the instance of the fix configurer, never {@code null} + */ + public FixConfigurer description( + BiFunction> descriptionSupplier) + { + this.descriptionSupplier = descriptionSupplier; + return this; + } + + /** + * Sets the static description for the fix + * + * @param description The description to set. May not be {@code null} + * @return the instance of the fix configurer, never {@code null} + */ + public FixConfigurer description(String description) + { + this.description = description; + descriptionSupplier = (context, session) -> Pair.newPair(description, details); + return this; + } + + /** + * Sets the static details for the fix + * + * @param description The description to set. May not be {@code null} + * @return the instance of the fix configurer, never {@code null} + */ + public FixConfigurer details(String details) + { + this.details = details; + descriptionSupplier = (context, session) -> Pair.newPair(description, details); + return this; + } + + /** + * Sets the modification model type - either interactive (UI) or not + * + * @param isInteractive {@code true} if quick fix supports inbteractive (UI) model, {@code false} otherwise + * @return the instance of the fix configurer, never {@code null} + */ + public FixConfigurer interactive(boolean isInteractive) + { + this.isInteractive = isInteractive; + return this; + } + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFixContext.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFixContext.java new file mode 100644 index 00000000..12c53f4d --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFixContext.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.xtext.validation.Issue.IssueImpl; + +import com._1c.g5.v8.dt.core.platform.IDtProject; +import com.e1c.g5.v8.dt.check.qfix.IFixSession; +import com.e1c.g5.v8.dt.check.qfix.components.BasicFixContext; + +/** + * Single-variant xtext module quick fix context + * + * @author Vadim Geraskin + */ +public class SingleVariantXtextBslModuleFixContext + extends BasicFixContext +{ + private final URI targetModuleUri; + private final IssueImpl issue; + private final IXtextBslModuleFixProvider provider; + + /** + * Creates quick fix context + * + * @param targetModuleUri the module {@code URI}, cannot be {@code null} + * @param issue the {@code IssueImpl} instance, cannot be {@code null} + * @param provider the {@code IXtextBslModuleFixProvider} instance, cannot be {@code null} + * @param dtProject the DT project, cannot be {@code null} + */ + public SingleVariantXtextBslModuleFixContext(URI targetModuleUri, IssueImpl issue, + IXtextBslModuleFixProvider provider, IDtProject dtProject) + { + super(dtProject); + this.targetModuleUri = targetModuleUri; + this.issue = issue; + this.provider = provider; + } + + /** + * Provides the target module URI + * + * @return the targetModuleUri, never {@code null} + */ + public URI getTargetModuleUri() + { + return targetModuleUri; + } + + /** + * Provides the {@code IssueImpl} for quick fix + * + * @return xtext issue, never {@code null} + */ + public IssueImpl getIssue() + { + return issue; + } + + /** + * Provides the model {@code IXtextBslModuleFixModel} for quick fix + * + * @param session {@link IFixSession}, cannot be {@code null} + * @param isInteractive {@code true} if quick fix supports inbteractive (UI) model, {@code false} otherwise + * @return model {@code IXtextBslModuleFixModel}, never {@code null} + */ + public IXtextBslModuleFixModel getModel(IFixSession session, boolean isInteractive) + { + return provider.getXtextFixModel(getDtProject(), issue, session, targetModuleUri, isInteractive); + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFixContextFactory.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFixContextFactory.java new file mode 100644 index 00000000..5594caa9 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/SingleVariantXtextBslModuleFixContextFactory.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.xtext.validation.CheckType; +import org.eclipse.xtext.validation.Issue.IssueImpl; + +import com._1c.g5.v8.dt.bsl.validation.BslValidationUtil; +import com._1c.g5.v8.dt.validation.marker.IMarkerWrapper; +import com._1c.g5.v8.dt.validation.marker.PlainEObjectMarker; +import com.e1c.g5.v8.dt.check.qfix.IFixContextFactory; +import com.e1c.g5.v8.dt.check.qfix.IFixSession; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +/** + * Context factory for {@link SingleVariantXtextBslModuleFixContext} + * + * @author Vadim Geraskin + */ +@Singleton +public class SingleVariantXtextBslModuleFixContextFactory + implements IFixContextFactory +{ + @Inject + private IXtextBslModuleFixProvider provider; + + @Override + public final SingleVariantXtextBslModuleFixContext createContext(IMarkerWrapper marker, IFixSession session) + { + if (marker.getMarker() instanceof PlainEObjectMarker) + { + PlainEObjectMarker plainObjectMarker = (PlainEObjectMarker)marker.getMarker(); + URI uri = plainObjectMarker.getURI(); + IssueImpl issue = BslValidationUtil.createIssue(plainObjectMarker, CheckType.EXPENSIVE); + return new SingleVariantXtextBslModuleFixContext(uri, issue, provider, session.getDtProject()); + } + return null; + } + + @Override + public final Class getProvidedContextType() + { + return SingleVariantXtextBslModuleFixContext.class; + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextBslModuleFixModel.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextBslModuleFixModel.java new file mode 100644 index 00000000..2c683588 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextBslModuleFixModel.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Locale; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.URIConverter; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.xtext.validation.Issue; + +import com._1c.g5.v8.dt.bsl.model.Module; +import com._1c.g5.v8.dt.bsl.services.BslGrammarAccess; +import com._1c.g5.v8.dt.common.PreferenceUtils; +import com._1c.g5.v8.dt.core.platform.IDtProject; +import com._1c.g5.v8.dt.core.platform.IResourceLookup; +import com._1c.g5.v8.dt.core.platform.IV8Project; +import com._1c.g5.v8.dt.core.platform.IV8ProjectManager; +import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant; +import com.e1c.v8codestyle.internal.bsl.BslPlugin; +import com.google.common.base.Preconditions; + +/** + * The xtext module quick fix model + * + * @author Vadim Geraskin + */ +public class XtextBslModuleFixModel + implements IXtextBslModuleFixModel +{ + protected final IV8Project v8project; + private final Supplier moduleSupp; + private final BslGrammarAccess bslGrammar; + private final IResourceLookup resourceLookup; + private final Issue issue; + private IDocument document; + + /** + * Creates module quick fix model + * + * @param moduleSupp supplier for {@link Module}, cannot be {@code null} + * @param v8projectManager V8 project manager, cannot be {@code null} + * @param bslGrammar BSL grammar, cannot be {@code null} + * @param resourceLookup resource lookup service, cannot be {@code null} + * @param issue issue, cannot be {@code null} + * @param dtProject {@code IDtProject}, cannot be {@code null} + */ + public XtextBslModuleFixModel(Supplier moduleSupp, IV8ProjectManager v8projectManager, + BslGrammarAccess bslGrammar, IResourceLookup resourceLookup, Issue issue, IDtProject dtProject) + { + this.moduleSupp = Preconditions.checkNotNull(moduleSupp); + this.bslGrammar = Preconditions.checkNotNull(bslGrammar); + this.resourceLookup = Preconditions.checkNotNull(resourceLookup); + this.issue = Preconditions.checkNotNull(issue); + this.v8project = v8projectManager.getProject(dtProject); + } + + @Override + public IDocument getDocument() + { + if (document == null) + { + Module module = moduleSupp.get(); + if (module != null) + { + URI uri = EcoreUtil.getURI(module).trimFragment(); + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(URIConverter.INSTANCE.createInputStream(uri), StandardCharsets.UTF_8))) + { + Stream lines = reader.lines(); + String content = lines.collect(Collectors.joining(System.lineSeparator())); + document = new Document(content); + } + catch (IOException e) + { + BslPlugin.log(BslPlugin.createErrorStatus("Unable to read bsl module file", e)); //$NON-NLS-1$ + } + } + } + return document; + } + + @Override + public IResourceLookup getResourceLookup() + { + return resourceLookup; + } + + @Override + public EObject getElement() + { + URI uriToProblem = issue.getUriToProblem(); + String fragment = uriToProblem != null ? uriToProblem.fragment() : null; + if (fragment != null) + { + Module module = moduleSupp.get(); + return module != null ? module.eResource().getEObject(fragment) : null; + } + return null; + } + + @Override + public Issue getIssue() + { + return issue; + } + + @Override + public String[] getIssueData() + { + return issue.getData(); + } + + @Override + public BslGrammarAccess getBslGrammar() + { + return bslGrammar; + } + + @Override + public ScriptVariant getScriptVariant() + { + return getScriptVariant(v8project); + } + + @Override + public String getLineSeparator() + { + return PreferenceUtils.getLineSeparator(v8project.getProject()); + } + + protected static ScriptVariant getScriptVariant(IV8Project v8project) + { + if (v8project != null) + { + return v8project.getScriptVariant(); + } + return Locale.getDefault().getLanguage().equals(new Locale("ru").getLanguage()) ? ScriptVariant.RUSSIAN //$NON-NLS-1$ + : ScriptVariant.ENGLISH; + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextBslModuleFixProvider.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextBslModuleFixProvider.java new file mode 100644 index 00000000..b3d13a66 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextBslModuleFixProvider.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import java.util.function.Supplier; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.xtext.ui.editor.IURIEditorOpener; +import org.eclipse.xtext.validation.Issue; + +import com._1c.g5.v8.dt.bsl.model.Module; +import com._1c.g5.v8.dt.bsl.services.BslGrammarAccess; +import com._1c.g5.v8.dt.bsl.ui.BslGeneratorMultiLangProposals; +import com._1c.g5.v8.dt.core.platform.IDtProject; +import com._1c.g5.v8.dt.core.platform.IResourceLookup; +import com._1c.g5.v8.dt.core.platform.IV8ProjectManager; +import com._1c.g5.v8.dt.lcore.ui.texteditor.IndentTextEditorProvider; +import com.e1c.g5.v8.dt.check.qfix.IFixSession; +import com.google.common.base.Preconditions; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +/** + * Xtext BSl module quick fix provider + * + * @author Vadim Geraskin + */ +@Singleton +public class XtextBslModuleFixProvider + implements IXtextBslModuleFixProvider +{ + private final IV8ProjectManager v8projectManager; + private final BslGrammarAccess bslGrammar; + private final IResourceLookup resourceLookup; + private final IndentTextEditorProvider indentProvider; + private final BslGeneratorMultiLangProposals bslGenProp; + private final IURIEditorOpener editorOpener; + + @Inject + /** + * @param v8projectManager V8 project manager, cannot be {@code null} + * @param bslGrammar BSl grammar, cannot be {@code null} + * @param resourceLookup resource lookup, cannot be {@code null} + * @param indentProvider indent provider, cannot be {@code null} + * @param bslGenProp BSL multi-language proposals generator, cannot be {@code null} + * @param editorOpener editor opener, cannot be {@code null} + */ + public XtextBslModuleFixProvider(IV8ProjectManager v8projectManager, BslGrammarAccess bslGrammar, + IResourceLookup resourceLookup, IndentTextEditorProvider indentProvider, + BslGeneratorMultiLangProposals bslGenProp, IURIEditorOpener editorOpener) + { + this.v8projectManager = Preconditions.checkNotNull(v8projectManager); + this.bslGrammar = Preconditions.checkNotNull(bslGrammar); + this.resourceLookup = Preconditions.checkNotNull(resourceLookup); + this.indentProvider = Preconditions.checkNotNull(indentProvider); + this.bslGenProp = Preconditions.checkNotNull(bslGenProp); + this.editorOpener = Preconditions.checkNotNull(editorOpener); + } + + @Override + public IXtextBslModuleFixModel getXtextFixModel(IDtProject dtProject, Issue issue, IFixSession session, + URI targetModuleUri, boolean isInteractive) + { + Supplier moduleSupp = () -> session.getModule(targetModuleUri); + if (isInteractive) + { + return new XtextInteractiveBslModuleFixModel(moduleSupp, v8projectManager, bslGrammar, resourceLookup, + indentProvider, bslGenProp, issue, dtProject, editorOpener); + } + return new XtextBslModuleFixModel(moduleSupp, v8projectManager, bslGrammar, resourceLookup, issue, dtProject); + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextInteractiveBslModuleFixModel.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextInteractiveBslModuleFixModel.java new file mode 100644 index 00000000..0f4b2ec7 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/qfix/external/XtextInteractiveBslModuleFixModel.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.qfix.external; + +import java.util.Optional; +import java.util.function.Supplier; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.link.LinkedModeModel; +import org.eclipse.jface.text.link.LinkedModeUI; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.xtext.nodemodel.INode; +import org.eclipse.xtext.nodemodel.util.NodeModelUtils; +import org.eclipse.xtext.ui.editor.IURIEditorOpener; +import org.eclipse.xtext.ui.editor.model.IXtextDocument; +import org.eclipse.xtext.ui.editor.model.edit.IModificationContext; +import org.eclipse.xtext.validation.Issue; + +import com._1c.g5.v8.dt.bsl.model.Module; +import com._1c.g5.v8.dt.bsl.services.BslGrammarAccess; +import com._1c.g5.v8.dt.bsl.ui.BslGeneratorMultiLangProposals; +import com._1c.g5.v8.dt.bsl.ui.quickfix.BslQuickFixUtil; +import com._1c.g5.v8.dt.common.PreferenceUtils; +import com._1c.g5.v8.dt.core.platform.IDtProject; +import com._1c.g5.v8.dt.core.platform.IResourceLookup; +import com._1c.g5.v8.dt.core.platform.IV8ProjectManager; +import com._1c.g5.v8.dt.lcore.ui.texteditor.IndentTextEditorProvider; +import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant; +import com.google.common.base.Preconditions; + +/** + * The xtext module quick fix model + * + * @author Vadim Geraskin + */ +public class XtextInteractiveBslModuleFixModel + extends XtextBslModuleFixModel + implements IXtextInteractiveBslModuleFixModel +{ + private final IndentTextEditorProvider indentProvider; + private final BslGeneratorMultiLangProposals bslGenProp; + private final IModificationContext modificationContext; + private final IXtextDocument document; + private final LinkedModeModel linkedModeModel; + + /** + /** + * Creates module quick fix model + * + * @param moduleSupp supplier for {@link Module}, cannot be {@code null} + * @param v8projectManager V8 project manager, cannot be {@code null} + * @param bslGrammar BSL grammar, cannot be {@code null} + * @param resourceLookup resource lookup service, cannot be {@code null} + * @param indentProvider indent provider, cannot be {@code null} + * @param bslGenProp Multi-lang BSL proposals generator, cannot be {@code null} + * @param issue issue, cannot be {@code null} + * @param dtProject {@code IDtProject}, cannot be {@code null} + * @param editorOpener {@code IURIEditorOpener}, cannot be {@code null} + */ + public XtextInteractiveBslModuleFixModel(Supplier moduleSupp, IV8ProjectManager v8projectManager, + BslGrammarAccess bslGrammar, IResourceLookup resourceLookup, IndentTextEditorProvider indentProvider, + BslGeneratorMultiLangProposals bslGenProp, Issue issue, IDtProject dtProject, IURIEditorOpener editorOpener) + { + super(moduleSupp, v8projectManager, bslGrammar, resourceLookup, issue, dtProject); + this.indentProvider = Preconditions.checkNotNull(indentProvider); + this.bslGenProp = Preconditions.checkNotNull(bslGenProp); + this.modificationContext = new BslIssueModificationContext(issue, Preconditions.checkNotNull(editorOpener)); + this.document = modificationContext.getXtextDocument(issue.getUriToProblem()); + + linkedModeModel = new LinkedModeModel(); + boolean isRussian = getScriptVariant(v8project) == ScriptVariant.RUSSIAN; + bslGenProp.setRussianLang(isRussian); + } + + @Override + public IXtextDocument getDocument() + { + return document; + } + + @Override + public IndentTextEditorProvider getIndentProvider() + { + return indentProvider; + } + + @Override + public BslGeneratorMultiLangProposals getBslGeneratorMultiLangProposals() + { + return bslGenProp; + } + + @Override + public IModificationContext getModificationContext() + { + return modificationContext; + } + + @Override + public IRegion getLineInformationOfOffset(int offset) throws BadLocationException + { + return document.getLineInformationOfOffset(offset); + } + + @Override + public String getLineSeparator() + { + return PreferenceUtils.getLineSeparator(getResourceLookup().getProject(document.getResourceURI())); + } + + @Override + public Optional getFormatString(EObject eObject) throws BadLocationException + { + INode node = NodeModelUtils.findActualNodeFor(eObject); + if (node == null) + { + return Optional.empty(); + } + IRegion lineInformation = getLineInformationOfOffset(node.getOffset()); + String indent = computeFormatLine(document, lineInformation).toString(); + return Optional.ofNullable(indent); + } + + @Override + public LinkedModeModel getLinkedModeModel() + { + return linkedModeModel; + } + + @Override + public void enterUiMode() + { + LinkedModeUI ui = new LinkedModeUI(linkedModeModel, BslQuickFixUtil.getTextViewer(modificationContext)); + ui.enter(); + } + + @Override + public void selectAndRevealForLinkedModeModel(int posStart, int length) + { + selectAndRevealForLinkedModeModel(BslQuickFixUtil.getTextViewer(modificationContext), posStart, length); + } + + private static StringBuilder computeFormatLine(IDocument doc, IRegion lineInformation) throws BadLocationException + { + String lineContent = doc.get(lineInformation.getOffset(), lineInformation.getLength()); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < lineContent.length(); ++i) + { + if (Character.isWhitespace(lineContent.charAt(i))) + { + builder.append(lineContent.charAt(i)); + } + else + { + break; + } + } + return builder; + } + + private static void selectAndRevealForLinkedModeModel(ITextViewer viewer, int posStart, int length) + { + viewer.getSelectionProvider().addSelectionChangedListener(new ISelectionChangedListener() + { + @Override + public void selectionChanged(SelectionChangedEvent event) + { + viewer.getSelectionProvider().removeSelectionChangedListener(this); + viewer.revealRange(posStart, length); + viewer.setSelectedRange(posStart, length); + } + }); + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java index 7269e4ed..23c8f609 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/BslPlugin.java @@ -15,14 +15,19 @@ package com.e1c.v8codestyle.internal.bsl; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; +import org.eclipse.xtext.ui.shared.SharedStateModule; +import org.eclipse.xtext.util.Modules2; import org.osgi.framework.BundleContext; +import com._1c.g5.v8.dt.bsl.BslRuntimeModule; import com._1c.g5.v8.dt.bsl.model.BslPackage; import com._1c.g5.wiring.InjectorAwareServiceRegistrator; import com._1c.g5.wiring.ServiceInitialization; import com.e1c.v8codestyle.bsl.IModuleStructureProvider; +import com.e1c.v8codestyle.bsl.qfix.external.BslCheckFixBoostrap; import com.google.inject.Guice; import com.google.inject.Injector; +import com.google.inject.Module; /** * The bundle activator to support plug-in life-cycle @@ -127,14 +132,12 @@ public class BslPlugin plugin = this; BslPackage.eINSTANCE.eClass(); - registrator = new InjectorAwareServiceRegistrator(bundleContext, this::getInjector); - ServiceInitialization.schedule(() -> { // register services from injector registrator.service(IModuleStructureProvider.class).registerInjected(); + registrator.managedService(BslCheckFixBoostrap.class).activateBeforeRegistration().registerInjected(); }); - } /* @@ -182,7 +185,15 @@ public class BslPlugin { try { - return Guice.createInjector(new ServiceModule(), new ExternalDependenciesModule(this)); + Module internalServiceModule = new ServiceModule(); + Module bslExternalServicesModule = new com._1c.g5.v8.dt.bsl.ExternalServicesModule(this); + Module sharedStateModule = new SharedStateModule(); + Module externalDepModule = new ExternalDependenciesModule(this); + Module bslRuntimeModule = new BslRuntimeModule(); + + Module mergedModule = Modules2.mixin(internalServiceModule, bslExternalServicesModule, sharedStateModule, + bslRuntimeModule, externalDepModule); + return Guice.createInjector(mergedModule); } catch (Exception e) { diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ExternalDependenciesModule.java b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ExternalDependenciesModule.java index 9cd3ec9e..f8e76743 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ExternalDependenciesModule.java +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/internal/bsl/ExternalDependenciesModule.java @@ -23,12 +23,15 @@ import com._1c.g5.v8.dt.core.platform.IResourceLookup; import com._1c.g5.v8.dt.core.platform.IV8ProjectManager; import com._1c.g5.v8.dt.platform.version.IRuntimeVersionSupport; import com._1c.g5.wiring.AbstractServiceAwareModule; +import com.e1c.g5.v8.dt.check.qfix.IFixRepository; +import com.e1c.g5.v8.dt.check.settings.ICheckRepository; +import com.e1c.v8codestyle.bsl.qfix.external.IXtextBslModuleFixProvider; +import com.e1c.v8codestyle.bsl.qfix.external.XtextBslModuleFixProvider; /** * The external dependencies for plugin * * @author Dmitriy Marmyshev - * */ class ExternalDependenciesModule extends AbstractServiceAwareModule @@ -49,6 +52,9 @@ class ExternalDependenciesModule bind(IQualifiedNameConverter.class).toService(); bind(IBslModuleContextDefService.class).toService(); bind(IQualifiedNameProvider.class).toService(); - } + bind(ICheckRepository.class).toService(); + bind(IFixRepository.class).toService(); + bind(IXtextBslModuleFixProvider.class).to(XtextBslModuleFixProvider.class); + } } diff --git a/checkstyle.xml b/checkstyle.xml index 2169cb62..7ce1f7c5 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -21,11 +21,13 @@ + + + + + + - - - -