/*******************************************************************************
* Copyright (c) 2012 BMW Car IT 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
*******************************************************************************/
/*
* generated by Xtext
*/
package org.jnario.feature.ui.contentassist;
import static com.google.common.collect.Iterables.addAll;
import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptySet;
import static org.eclipse.emf.ecore.util.EcoreUtil.resolve;
import static org.eclipse.xtext.EcoreUtil2.getContainerOfType;
import static org.jnario.feature.jvmmodel.StepTypeProvider.GIVEN;
import static org.jnario.feature.jvmmodel.StepTypeProvider.THEN;
import static org.jnario.feature.jvmmodel.StepTypeProvider.WHEN;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.graphics.Image;
import org.eclipse.xtend.core.xtend.XtendField;
import org.eclipse.xtend.core.xtend.XtendPackage;
import org.eclipse.xtend.core.xtend.XtendParameter;
import org.eclipse.xtext.Assignment;
import org.eclipse.xtext.CrossReference;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.common.types.TypesPackage;
import org.eclipse.xtext.common.types.xtext.ui.JdtVariableCompletions;
import org.eclipse.xtext.common.types.xtext.ui.TypeMatchFilters;
import org.eclipse.xtext.common.types.xtext.ui.JdtVariableCompletions.VariableType;
import org.eclipse.xtext.conversion.IValueConverter;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.IContainer;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.resource.IResourceDescription;
import org.eclipse.xtext.resource.IResourceDescriptions;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.SimpleScope;
import org.eclipse.xtext.ui.editor.contentassist.ConfigurableCompletionProposal;
import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext;
import org.eclipse.xtext.ui.editor.contentassist.ICompletionProposalAcceptor;
import org.eclipse.xtext.xbase.XbaseQualifiedNameConverter;
import org.eclipse.xtext.xbase.annotations.xAnnotations.XAnnotationsPackage;
import org.eclipse.xtext.xbase.conversion.XbaseQualifiedNameValueConverter;
import org.eclipse.xtext.xbase.imports.IImportsConfiguration;
import org.eclipse.xtext.xbase.imports.ImportSectionRegionUtil;
import org.eclipse.xtext.xbase.imports.RewritableImportSection;
import org.eclipse.xtext.xbase.jvmmodel.IJvmModelAssociations;
import org.eclipse.xtext.xbase.ui.imports.ReplaceConverter;
import org.eclipse.xtext.xtype.XImportSection;
import org.jnario.feature.feature.Feature;
import org.jnario.feature.feature.FeaturePackage;
import org.jnario.feature.feature.Scenario;
import org.jnario.feature.feature.Step;
import org.jnario.feature.feature.StepReference;
import org.jnario.feature.jvmmodel.StepTypeProvider;
import org.jnario.feature.naming.StepNameProvider;
import org.jnario.ui.contentassist.ImportingTypesProposalProvider.FQNImporter;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
/**
* @author Birgit Engelmann - Initial contribution and API
*/
public class FeatureProposalProvider extends AbstractFeatureProposalProvider {
public static class FeatureRewritableImportSection extends RewritableImportSection{
public FeatureRewritableImportSection(XtextResource resource,
IImportsConfiguration importsConfiguration,
XImportSection originalImportSection, String lineSeparator,
ImportSectionRegionUtil regionUtil,
IValueConverter<String> nameConverter) {
super(resource, importsConfiguration, originalImportSection, lineSeparator,
regionUtil, nameConverter);
}
}
private static final Logger LOG = Logger.getLogger(FeatureProposalProvider.class);
@Inject private IResourceDescriptions resourceDescriptions;
@Inject private IContainer.Manager containerManager;
@Inject private StepNameProvider stepNameProvider;
@Inject private RewritableImportSection.Factory importSectionFactory;
@Inject private ReplaceConverter replaceConverter;
@Inject private StepTypeProvider stepTypeProvider;
@Inject private IJvmModelAssociations associations;
@Inject
private JdtVariableCompletions completions;
@Override
public void completeXAnnotation_AnnotationType(EObject model, Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
completeJavaTypes(context, XAnnotationsPackage.Literals.XANNOTATION__ANNOTATION_TYPE,
TypeMatchFilters.all(IJavaSearchConstants.ANNOTATION_TYPE), acceptor);
}
// @Override
// public void completeMockLiteral_Type(EObject model, Assignment assignment,
// ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
// completeJavaTypes(context, XbasePackage.Literals.XTYPE_LITERAL__TYPE,
// TypeMatchFilters.all(IJavaSearchConstants.CLASS_AND_INTERFACE), acceptor);
// }
@Override
public void completeAndReference_Reference(EObject model,
Assignment assignment, ContentAssistContext context,
final ICompletionProposalAcceptor acceptor) {
}
@Override
public void completeGivenReference_Reference(EObject model,
Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
}
@Override
public void completeWhenReference_Reference(EObject model,
Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
}
@Override
public void completeThenReference_Reference(EObject model,
Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
}
@Override
public void completeButReference_Reference(EObject model,
Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
}
protected IScope createStepScope(EObject model) {
List<IEObjectDescription> scopedElements = newArrayList();
for (IContainer container : visibleContainers(model)) {
Iterable<IEObjectDescription> descs = container.getExportedObjectsByType(FeaturePackage.Literals.STEP_REFERENCE);
addAll(scopedElements, descs);
}
IScope scope = new SimpleScope(scopedElements);
return scope;
}
public void createProposal(ContentAssistContext context,
ICompletionProposalAcceptor acceptor, String stepPrefix,
StepReference ref) {
String name = stepNameProvider.nameOf(ref);
name = stepNameProvider.removeKeywords(name);
name = stepNameProvider.removeArguments(name);
if(Strings.isNullOrEmpty(name)){
return;
}
String proposal = stepPrefix + " " + name;
acceptor.accept(createCompletionProposal(proposal, name, getLabelProvider().getImage(ref) , context));
}
public List<IContainer> visibleContainers(EObject model) {
IResourceDescription.Manager resourceDescManager = ((XtextResource)model.eResource()).getResourceServiceProvider().getResourceDescriptionManager();
IResourceDescription resourceDescription = resourceDescManager.getResourceDescription(model.eResource());
List<IContainer> visibleContainers = containerManager.getVisibleContainers(resourceDescription, resourceDescriptions);
return visibleContainers;
}
@Override
public void completeKeyword(Keyword keyword,
ContentAssistContext contentAssistContext,
ICompletionProposalAcceptor acceptor) {
if("import".equals(keyword.getValue()) && contentAssistContext.getPreviousModel() instanceof Feature){
return;
}
super.completeKeyword(keyword, contentAssistContext, acceptor);
}
@Override
public void complete_FEATURE_TEXT(EObject model, RuleCall ruleCall,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
String proposal = "Feature: ";
if (context.getPreviousModel() instanceof Feature) {
complete_BACKGROUND_TEXT(model, ruleCall, context, acceptor);
complete_SCENARIO_TEXT(model, ruleCall, context, acceptor);
}else{
acceptor.accept(createCompletionProposal(proposal, proposal, getLabelProvider().getImage(model), context));
}
}
@Override
public void complete_BACKGROUND_TEXT(EObject model, RuleCall ruleCall,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
String proposal = "Background: ";
acceptor.accept(createCompletionProposal(proposal, proposal, getLabelProvider().getImage(model), context));
}
@Override
public void complete_SCENARIO_TEXT(EObject model, RuleCall ruleCall,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
String proposal = "Scenario: ";
acceptor.accept(createCompletionProposal(proposal, proposal, getLabelProvider().getImage(model), context));
}
@Override
public void complete_GIVEN_TEXT(EObject model, RuleCall ruleCall,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
completeStepReference(acceptor, context, "Given", GIVEN);
}
@Override
public void complete_WHEN_TEXT(EObject model, RuleCall ruleCall,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
completeStepReference(acceptor, context, "When", WHEN);
}
@Override
public void complete_THEN_TEXT(EObject model, RuleCall ruleCall,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
completeStepReference(acceptor, context, "Then", THEN);
}
@Override
public void complete_BUT_TEXT(EObject model, RuleCall ruleCall,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
completeStepReference(acceptor, context, "But", getExpectedTypes(context));
}
@Override
public void complete_AND_TEXT(EObject model, RuleCall ruleCall,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
completeStepReference(acceptor, context, "And", getExpectedTypes(context));
}
public void completeStepReference(ICompletionProposalAcceptor acceptor, ContentAssistContext context, String prefix, Set<EClass> expected) {
prefix = prefix + " ";
acceptor.accept(createCompletionProposal(prefix, prefix, getLabelProvider().getImage("step.png"), context));
IScope scope = getScopeProvider().getScope(context.getCurrentModel(), FeaturePackage.Literals.STEP_REFERENCE__SYNTHETIC_STEP_REFERENCE);
for (IEObjectDescription desc : scope.getAllElements()) {
Step step = (Step) resolve(desc.getEObjectOrProxy(), context.getCurrentModel());
Scenario scenario = getContainerOfType(step, Scenario.class);
String proposal = getQualifiedNameConverter().toString(desc.getQualifiedName().skipLast(1)) + "." + prefix + desc.getName().getLastSegment();
if(expected.contains(stepTypeProvider.getActualType(step)) && context.getMatcher().isCandidateMatchingPrefix(proposal, context.getPrefix())){
acceptor = createStepFqnShorterner(context, acceptor, scope, desc.getQualifiedName(), scenario);
String displayString = proposal;
StyledString styledDisplayString = getStyledDisplayString(step, displayString, scenario.getName());
acceptor.accept(doCreateProposal(proposal, styledDisplayString, getLabelProvider().getImage(step), 1000, context));
}
}
}
public Set<EClass> getExpectedTypes(ContentAssistContext context) {
EObject model = context.getLastCompleteNode().getSemanticElement();
model = getContainerOfType(model, Step.class);
if(model == null){
return emptySet();
}
return stepTypeProvider.getExpectedTypes((Step) model);
}
@Override
protected void lookupCrossReference(CrossReference crossReference, ContentAssistContext contentAssistContext,
ICompletionProposalAcceptor acceptor) {
lookupCrossReference(crossReference, contentAssistContext, acceptor, getFeatureDescriptionPredicate(contentAssistContext));
}
protected StyledString getStyledDisplayString(EObject element, String qualifiedName, String shortName) {
return new StyledString(getDisplayString(element, qualifiedName, shortName));
}
public ICompletionProposalAcceptor createStepFqnShorterner(final ContentAssistContext context, ICompletionProposalAcceptor acceptor, final IScope scope, final QualifiedName qualifiedName, Scenario scenario) {
XbaseQualifiedNameValueConverter qualifiedNameValueConverter = new XbaseQualifiedNameValueConverter(){
@Override
public String toString(String value) {
int end = value.lastIndexOf('.');
String result = value.substring(0, end) + ".*";
return result;
}
};
final IQualifiedNameConverter qualifiedNameConverter = new XbaseQualifiedNameConverter(){
@Override
public QualifiedName toQualifiedName(String qualifiedNameAsString) {
return new QualifiedName(qualifiedNameAsString.split("\\.")){
public String getLastSegment() {
return super.getLastSegment();
};
};
}
};
final FQNImporter fqnImporter = new FQNImporter(context.getResource(), context.getViewer(), scope, qualifiedNameConverter, null, qualifiedNameValueConverter);
final ICompletionProposalAcceptor scopeAware = new ICompletionProposalAcceptor.Delegate(acceptor) {
@Override
public void accept(ICompletionProposal proposal) {
if (proposal instanceof ConfigurableCompletionProposal) {
ConfigurableCompletionProposal configurableCompletionProposal = (ConfigurableCompletionProposal) proposal;
configurableCompletionProposal.setTextApplier(fqnImporter);
}
super.accept(proposal);
}
};
return scopeAware;
}
@Override
public void complete_RICH_TEXT(EObject model, RuleCall ruleCall, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
completeInRichString(model, ruleCall, context, acceptor);
}
@Override
public void complete_RICH_TEXT_START(EObject model, RuleCall ruleCall, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
completeInRichString(model, ruleCall, context, acceptor);
}
@Override
public void complete_RICH_TEXT_END(EObject model, RuleCall ruleCall, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
completeInRichString(model, ruleCall, context, acceptor);
}
@Override
public void complete_RICH_TEXT_INBETWEEN(EObject model, RuleCall ruleCall, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
completeInRichString(model, ruleCall, context, acceptor);
}
@Override
public void complete_COMMENT_RICH_TEXT_END(EObject model, RuleCall ruleCall, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
completeInRichString(model, ruleCall, context, acceptor);
}
@Override
public void complete_COMMENT_RICH_TEXT_INBETWEEN(EObject model, RuleCall ruleCall, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
completeInRichString(model, ruleCall, context, acceptor);
}
@Override
public void completeParameter_Name(final EObject model, Assignment assignment, final ContentAssistContext context,
final ICompletionProposalAcceptor acceptor) {
if (model instanceof XtendParameter) {
final List<XtendParameter> siblings = EcoreUtil2.getSiblingsOfType(model, XtendParameter.class);
Set<String> alreadyTaken = Sets.newHashSet();
for(XtendParameter sibling: siblings) {
alreadyTaken.add(sibling.getName());
}
alreadyTaken.addAll(getAllKeywords());
completions.getVariableProposals(model, XtendPackage.Literals.XTEND_PARAMETER__PARAMETER_TYPE,
VariableType.PARAMETER, alreadyTaken, new JdtVariableCompletions.CompletionDataAcceptor() {
public void accept(String replaceText, StyledString label, Image img) {
acceptor.accept(createCompletionProposal(replaceText, label, img, context));
}
});
} else {
super.completeParameter_Name(model, assignment, context, acceptor);
}
}
@Override
public void completeMember_Type(EObject model, Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
if (model instanceof XtendField) {
// don't propose types everywhere but only if there's already an indicator for fields, e.g. static, extension, var, val
completeJavaTypes(context, TypesPackage.Literals.JVM_PARAMETERIZED_TYPE_REFERENCE__TYPE, true,
getQualifiedNameValueConverter(), new TypeMatchFilters.All(IJavaSearchConstants.TYPE), acceptor);
}
}
@Override
public void completeMember_ReturnType(EObject model, Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
completeJavaTypes(context, TypesPackage.Literals.JVM_PARAMETERIZED_TYPE_REFERENCE__TYPE, true,
getQualifiedNameValueConverter(), new TypeMatchFilters.All(IJavaSearchConstants.TYPE), acceptor);
}
@Override
public void completeMember_Name(final EObject model, Assignment assignment, final ContentAssistContext context,
final ICompletionProposalAcceptor acceptor) {
if (model instanceof XtendField) {
//TODO go up type hierarchy and collect all local fields
final List<XtendField> siblings = EcoreUtil2.getSiblingsOfType(model, XtendField.class);
Set<String> alreadyTaken = Sets.newHashSet();
for(XtendField sibling: siblings) {
alreadyTaken.add(sibling.getName());
}
alreadyTaken.addAll(getAllKeywords());
completions.getVariableProposals(model, XtendPackage.Literals.XTEND_FIELD__TYPE,
VariableType.INSTANCE_FIELD, alreadyTaken, new JdtVariableCompletions.CompletionDataAcceptor() {
public void accept(String replaceText, StyledString label, Image img) {
acceptor.accept(createCompletionProposal(replaceText, label, img, context));
}
});
} else {
super.completeMember_Name(model, assignment, context, acceptor);
}
}
}