/* * Copyright (c) 2005, 2010 committers of openArchitectureWare 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: * committers of openArchitectureWare - initial API and implementation */ package org.eclipse.gmf.internal.xpand.codeassist; import java.util.List; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.ETypedElement; import org.eclipse.gmf.internal.xpand.editor.EditorImages; import org.eclipse.gmf.internal.xpand.expression.codeassist.ProposalFactory; import org.eclipse.gmf.internal.xpand.xtend.ast.GenericExtension; import org.eclipse.jface.text.contentassist.CompletionProposal; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.ocl.ecore.CollectionType; import org.eclipse.ocl.ecore.EcoreEnvironment; import org.eclipse.ocl.ecore.EcoreEnvironmentFactory; import org.eclipse.ocl.lpg.AbstractFormattingHelper; import org.eclipse.ocl.util.ObjectUtil; import org.eclipse.swt.graphics.Image; public class ProposalFactoryImpl implements ProposalFactory { protected final int offset; private final EditorImages editorImages; private final int selectionLen; private final EcoreEnvironment ecoreEnvironment; public ProposalFactoryImpl(int offset, int selectionLen, EditorImages images) { this.offset = offset; assert selectionLen >= 0; this.selectionLen = selectionLen; this.editorImages = images; this.ecoreEnvironment = (EcoreEnvironment) EcoreEnvironmentFactory.INSTANCE.createEnvironment(); } public ICompletionProposal createCollectionSpecificOperationProposal(String insertString, String displayString, String prefix, int cursor, int marked) { return new CompletionProposal(insertString, offset - prefix.length(), prefix.length() + selectionLen, cursor, editorImages.getOperation(), displayString, null, null); } public ICompletionProposal createPropertyProposal(final EStructuralFeature p, final String prefix, final boolean onCollection) { final String returnType = computeReturnType(p, onCollection); final String displayStr = p.getName() + " " + returnType + " - " + p.getEContainingClass().getName(); final String insertStr = p.getName(); return new CompletionProposal(insertStr, offset - prefix.length(), prefix.length() + selectionLen, insertStr.length(), editorImages.getProperty(), displayStr, null, null); } private String computeReturnType(ETypedElement returnType, final boolean onCollection) { EClassifier t = ecoreEnvironment.getUMLReflection().getOCLType(returnType); if (onCollection) { // FIXME [artem] not sure why for properties that return list but invoked on collection // I need to use inner type - sort of implicit collect ("a.b.c", where all properties are lists still // gives a flat result list). Need to check if this holds true with OCL/QVT if (t instanceof CollectionType) { EClassifier temp = t; t = ((CollectionType) t).getElementType(); // @see EcoreEvaluationEnvironment#getCollectionKind() ObjectUtil.dispose(temp); } t = (EClassifier) ecoreEnvironment.getOCLFactory().createSequenceType(t); } return getTypeName(t); } public ICompletionProposal createOperationProposal(final EOperation p, final String prefix, final boolean onCollection) { final StringBuilder displayStr = new StringBuilder(); displayStr.append(p.getName()); displayStr.append(toParamString(p)); displayStr.append(" "); displayStr.append(computeReturnType(p, onCollection)); if (p.getEContainingClass() != null) { // == null for EDataType operations displayStr.append(" - "); displayStr.append(getTypeName(p.getEContainingClass())); } final String insertStr = p.getName() + "()"; int x = insertStr.length(); if (p.getEParameters().size() > 0) { x--; } final Image img = editorImages.getOperation(); return new CompletionProposal(insertStr, offset - prefix.length(), prefix.length() + selectionLen, x, img, displayStr.toString(), null, null); } public ICompletionProposal createExtensionProposal(final GenericExtension p, final String prefix) { final String displayStr = p.getName() + toParamString(p, false) + " - " + p.getFileName(); final String insertStr = p.getName() + "()"; int x = insertStr.length(); if (p.getParameterNames().size() > 0) { x--; } return new CompletionProposal(insertStr, offset - prefix.length(), prefix.length() + selectionLen, x, editorImages.getExtension(), displayStr, null, null); } public ICompletionProposal createExtensionOnMemberPositionProposal(GenericExtension p, String prefix, boolean onOperation) { final String displayStr = p.getName() + toParamString(p, true) + " - " + getTypeName(p.getParameterTypes().get(0)); final String insertStr = p.getName() + "()"; int x = insertStr.length(); if (p.getParameterNames().size() > 1) { x--; } final Image img = editorImages.getExtension(); return new CompletionProposal(insertStr, offset - prefix.length(), prefix.length() + selectionLen, x, img, displayStr, null, null); } private static String toParamString(final EOperation op) { final StringBuilder b = new StringBuilder("("); EList<EParameter> params = op.getEParameters(); for (int i = 0, x = params.size(); i < x; i++) { b.append(getTypeName(params.get(i).getEType())); if (i + 1 < x) { b.append(","); } } b.append(")"); return b.toString(); } private static String toParamString(final GenericExtension p, final boolean member) { final StringBuilder b = new StringBuilder("("); int i = member ? 1 : 0; List<String> parameterNames = p.getParameterNames(); // TODO: check if getParameterTypes() return proper collection in all situations List<EClassifier> parameterTypes = p.getParameterTypes(); for (final int x = parameterNames.size(); i < x; i++) { b.append(parameterTypes.size() < x ? getTypeName(parameterTypes.get(x)) : "?"); b.append(" "); b.append(parameterNames.get(x)); if (i + 1 < x) { b.append(","); } } b.append(")"); return b.toString(); } // TODO: revisit this method and check correct type name processing for QVT types private static String getTypeName(EClassifier classifier) { return AbstractFormattingHelper.INSTANCE.formatType(classifier); } public ICompletionProposal createVariableProposal(String varName, String typeName, String prefix) { final String displayStr = varName + " " + typeName; final String insertStr = varName; return new CompletionProposal(insertStr, offset - prefix.length(), prefix.length() + selectionLen, insertStr.length(), editorImages.getVariable(), displayStr, null, null); } public ICompletionProposal createTypeProposal(final String insertStr, String displayStr, final String prefix) { return new CompletionProposal(insertStr, offset - prefix.length(), prefix.length() + selectionLen, insertStr.length(), editorImages.getType(), displayStr, null, null); } public ICompletionProposal createStatementProposal(String insertString, String displayString, String prefix, int cursor, int marked) { return new CompletionProposal(insertString, offset - prefix.length(), prefix.length() + selectionLen, cursor, editorImages.getStatement(), displayString, null, null); } public ICompletionProposal createStatementProposal(String insertString, String displayString, String prefix) { return createStatementProposal(insertString, displayString, prefix, insertString.length(), 0); } public ICompletionProposal createKeywordProposal(String insertString, String displayString, String prefix) { return new CompletionProposal(insertString, offset - prefix.length(), prefix.length() + selectionLen, insertString.length()); } }