From aeb04c019d56851f03ea1bc2b24da0228940436b Mon Sep 17 00:00:00 2001 From: Graham Pearson Date: Thu, 1 Feb 2018 18:52:41 +0000 Subject: [PATCH] #51: Autocorrect to add check to configuration does not put string params in quotes Autocorrect to add check to configuration now does put string params in quotes. It also now handles default string parameters containing whitespace; previously it did not. Issue-Id: #51 --- .../ddk/checkcfg/ui/CheckCfgUiModule.java | 12 +++++ .../CheckCfgTemplateContextType.java | 29 ++++++++++++ .../CheckCfgTemplateProposalProvider.java | 45 ++++++++++--------- .../SimpleEnumTemplateVariableResolver.java | 25 +++++++++++ 4 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/templates/CheckCfgTemplateContextType.java create mode 100644 com.avaloq.tools.ddk.xtext.ui/src/com/avaloq/tools/ddk/xtext/ui/templates/SimpleEnumTemplateVariableResolver.java diff --git a/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/CheckCfgUiModule.java b/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/CheckCfgUiModule.java index 6df8cb665..b3721f481 100644 --- a/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/CheckCfgUiModule.java +++ b/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/CheckCfgUiModule.java @@ -15,12 +15,15 @@ import org.eclipse.xtext.ui.editor.IXtextEditorCallback; import org.eclipse.xtext.ui.editor.contentassist.ITemplateProposalProvider; import org.eclipse.xtext.ui.editor.templates.CrossReferenceTemplateVariableResolver; +import org.eclipse.xtext.ui.editor.templates.XtextTemplateContextType; import org.eclipse.xtext.xbase.compiler.GeneratorConfigProvider; import org.eclipse.xtext.xbase.compiler.IGeneratorConfigProvider; +import com.avaloq.tools.ddk.checkcfg.ui.templates.CheckCfgTemplateContextType; import com.avaloq.tools.ddk.checkcfg.ui.templates.CheckCfgTemplateProposalProvider; import com.avaloq.tools.ddk.xtext.ui.editor.FixedDirtyStateEditorSupport; import com.avaloq.tools.ddk.xtext.ui.templates.KeywordAwareCrossReferenceTemplateVariableResolver; +import com.avaloq.tools.ddk.xtext.ui.templates.SimpleEnumTemplateVariableResolver; /** @@ -31,6 +34,15 @@ public CheckCfgUiModule(final AbstractUIPlugin plugin) { super(plugin); } + /** + * Binds a {@link XtextTemplateContextType} which adds {@link SimpleEnumTemplateVariableResolver}. + * + * @return {@link CheckCfgTemplateContextType} + */ + public Class bindXtextTemplateContextType() { + return CheckCfgTemplateContextType.class; + } + /** Binds a proposal provider for check configuration templates. {@inheritDoc} */ @Override public Class bindITemplateProposalProvider() { diff --git a/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/templates/CheckCfgTemplateContextType.java b/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/templates/CheckCfgTemplateContextType.java new file mode 100644 index 000000000..4663e2203 --- /dev/null +++ b/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/templates/CheckCfgTemplateContextType.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2016 Avaloq Evolution AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Avaloq Evolution AG - initial API and implementation + *******************************************************************************/ +package com.avaloq.tools.ddk.checkcfg.ui.templates; + +import org.eclipse.xtext.ui.editor.templates.XtextTemplateContextType; + +import com.avaloq.tools.ddk.xtext.ui.templates.SimpleEnumTemplateVariableResolver; + + +/** + * Used for adding custom template variable resolvers. + */ +public class CheckCfgTemplateContextType extends XtextTemplateContextType { + + @Override + protected void addDefaultTemplateVariables() { + super.addDefaultTemplateVariables(); + addResolver(new SimpleEnumTemplateVariableResolver()); + } + +} diff --git a/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/templates/CheckCfgTemplateProposalProvider.java b/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/templates/CheckCfgTemplateProposalProvider.java index fbac863b5..7ae894586 100644 --- a/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/templates/CheckCfgTemplateProposalProvider.java +++ b/com.avaloq.tools.ddk.checkcfg.ui/src/com/avaloq/tools/ddk/checkcfg/ui/templates/CheckCfgTemplateProposalProvider.java @@ -12,6 +12,8 @@ import java.util.List; import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.StringJoiner; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jface.text.templates.ContextTypeRegistry; @@ -22,6 +24,7 @@ import org.eclipse.jface.text.templates.persistence.TemplateStore; import org.eclipse.swt.graphics.Image; import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.xtext.common.types.JvmType; import org.eclipse.xtext.conversion.impl.QualifiedNameValueConverter; import org.eclipse.xtext.resource.IEObjectDescription; import org.eclipse.xtext.scoping.IScopeProvider; @@ -31,6 +34,7 @@ import org.eclipse.xtext.ui.editor.templates.DefaultTemplateProposalProvider; import org.eclipse.xtext.util.Strings; import org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter; +import org.eclipse.xtext.xbase.jvmmodel.JvmTypeReferenceBuilder; import com.avaloq.tools.ddk.check.check.Check; import com.avaloq.tools.ddk.check.check.CheckCatalog; @@ -70,6 +74,9 @@ public class CheckCfgTemplateProposalProvider extends DefaultTemplateProposalPro private final TemplateStore templateStore; + @Inject + private JvmTypeReferenceBuilder.Factory typeRefBuilderFactory; + @Inject public CheckCfgTemplateProposalProvider(final TemplateStore templateStore, final ContextTypeRegistry registry, final ContextTypeIdHelper helper) { super(templateStore, registry, helper); @@ -125,8 +132,8 @@ protected void createTemplates(final TemplateContext templateContext, final Cont */ @SuppressWarnings("all") private void addCatalogConfigurations(final TemplateContext templateContext, final ContentAssistContext context, final ITemplateAcceptor acceptor) { - final String templateName = "Add all registered catalogs"; - final String templateDescription = "configures all missing catalogs"; + final String templateName = "Add all registered catalogs"; //$NON-NLS-1$ + final String templateDescription = "configures all missing catalogs"; //$NON-NLS-1$ final String contextTypeId = templateContext.getContextType().getId(); if (context.getRootModel() instanceof CheckConfiguration) { @@ -145,12 +152,12 @@ private void addCatalogConfigurations(final TemplateContext templateContext, fin } else if (allElements.indexOf(description) > 0) { builder.append(Strings.newLine()); } - builder.append("catalog ").append(qualifiedNameValueConverter.toString(description.getQualifiedName().toString())).append(" {").append(Strings.newLine()); + builder.append("catalog ").append(qualifiedNameValueConverter.toString(description.getQualifiedName().toString())).append(" {").append(Strings.newLine()); //$NON-NLS-1$ //$NON-NLS-2$ for (Check check : catalog.getAllChecks()) { - builder.append(" default ").append(qualifiedNameValueConverter.toString(check.getName())).append(Strings.newLine()); + builder.append(" default ").append(qualifiedNameValueConverter.toString(check.getName())).append(Strings.newLine()); //$NON-NLS-1$ } // CHECKSTYLE:OFF - builder.append("}"); + builder.append("}"); //$NON-NLS-1$ builder.append(Strings.newLine()); // CHECKSTYLE:ON } @@ -158,7 +165,7 @@ private void addCatalogConfigurations(final TemplateContext templateContext, fin } if (builder.length() > 0) { - builder.append("${cursor}"); + builder.append("${cursor}"); //$NON-NLS-1$ Template t = new Template(templateName, templateDescription, contextTypeId, builder.toString(), true); TemplateProposal tp = createProposal(t, templateContext, context, images.forConfiguredCatalog(), getRelevance(t)); acceptor.accept(tp); @@ -216,31 +223,29 @@ public String apply(final ConfiguredCheck from) { } }), Predicates.notNull()); final CheckCatalog catalog = configuredCatalog.getCatalog(); + final JvmType stringType = typeRefBuilderFactory.create(context.getResource().getResourceSet()).typeRef(String.class).getType(); for (final Check check : catalog.getAllChecks()) { // create a template on the fly final String checkName = check.getName(); if (!Iterables.contains(alreadyConfiguredCheckNames, checkName)) { // check if referenced check has configurable parameters - String paramString = ""; //$NON-NLS-1$ - if (!check.getFormalParameters().isEmpty()) { - StringBuilder params = new StringBuilder("("); //$NON-NLS-1$ - for (final FormalParameter p : check.getFormalParameters()) { - final String paramName = p.getName(); - final String defaultValue = String.valueOf(interpreter.evaluate(p.getRight()).getResult()); - params.append(paramName).append(" = ").append("${").append(defaultValue).append('}'); //$NON-NLS-1$ //$NON-NLS-2$ - params.append(", "); //$NON-NLS-1$ - } - if (params.length() > 2) { - paramString = params.substring(0, params.length() - 2) + ')'; - } + final StringJoiner paramsJoiner = new StringJoiner(", ", " ( ", ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + paramsJoiner.setEmptyValue(""); //$NON-NLS-1$ + for (final FormalParameter param : check.getFormalParameters()) { + final JvmType paramType = param.getType().getType(); + final String paramName = param.getName(); + final String defaultValue = String.valueOf(interpreter.evaluate(param.getRight()).getResult()); + + // Use SimpleEnumTemplateVariableResolver with strings because otherwise TemplateTranslator can't cope with whitespace + paramsJoiner.add(paramName + " = " + (Objects.equals(stringType, paramType) ? "\"${defaultValue:SimpleEnum('" + defaultValue + "')}\"" //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + : "${" + defaultValue + '}')); //$NON-NLS-1$ } final String severity = (catalog.isFinal() || check.isFinal()) ? "default " : "${default:Enum('SeverityKind')} "; //$NON-NLS-1$ //$NON-NLS-2$ final String description = "Configures the check \"" + check.getLabel() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ final String contextTypeId = "com.avaloq.tools.ddk.checkcfg.CheckCfg.ConfiguredCheck." + checkName; //$NON-NLS-1$ - final String pattern = severity + qualifiedNameValueConverter.toString(checkName) - + (paramString.length() == 0 ? "${cursor}" : " " + paramString + "${cursor}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + final String pattern = severity + qualifiedNameValueConverter.toString(checkName) + paramsJoiner + "${cursor}"; //$NON-NLS-1$ Template t = new Template(checkName, description, contextTypeId, pattern, true); TemplateProposal tp = createProposal(t, templateContext, context, images.forConfiguredCheck(check.getDefaultSeverity()), getRelevance(t)); diff --git a/com.avaloq.tools.ddk.xtext.ui/src/com/avaloq/tools/ddk/xtext/ui/templates/SimpleEnumTemplateVariableResolver.java b/com.avaloq.tools.ddk.xtext.ui/src/com/avaloq/tools/ddk/xtext/ui/templates/SimpleEnumTemplateVariableResolver.java new file mode 100644 index 000000000..7b36ae9aa --- /dev/null +++ b/com.avaloq.tools.ddk.xtext.ui/src/com/avaloq/tools/ddk/xtext/ui/templates/SimpleEnumTemplateVariableResolver.java @@ -0,0 +1,25 @@ +package com.avaloq.tools.ddk.xtext.ui.templates; + +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.jface.text.templates.TemplateVariable; +import org.eclipse.xtext.ui.editor.templates.AbstractTemplateVariableResolver; +import org.eclipse.xtext.ui.editor.templates.XtextTemplateContext; + + +/** + * Simple enumeration template where enumeration is passed as string arguments to the template. + */ +public class SimpleEnumTemplateVariableResolver extends AbstractTemplateVariableResolver { + + public SimpleEnumTemplateVariableResolver() { + super("SimpleEnum", ""); //$NON-NLS-1$ //$NON-NLS-2$ + } + + @Override + public List resolveValues(final TemplateVariable variable, final XtextTemplateContext castedContext) { + return variable.getVariableType().getParams().stream().filter(param -> param instanceof String).collect(Collectors.toList()); + } + +}