summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Benz2012-12-24 07:25:08 (EST)
committer Jan Koehnlein2013-01-15 09:32:59 (EST)
commita75dd02f0dfd81e061ae0f8352a54a0264bcfc46 (patch)
tree3e65d117b8173e775a36e7bb41b8bb91ed0146d5
parent23601d976ab4e4898fe140b4971784a3e1250c2d (diff)
downloadorg.eclipse.xtext-a75dd02f0dfd81e061ae0f8352a54a0264bcfc46.zip
org.eclipse.xtext-a75dd02f0dfd81e061ae0f8352a54a0264bcfc46.tar.gz
org.eclipse.xtext-a75dd02f0dfd81e061ae0f8352a54a0264bcfc46.tar.bz2
[quickfix] add create missing method & type quickfix
merged patch https://bugs.eclipse.org/bugs/attachment.cgi?id=225038
-rw-r--r--plugins/org.eclipse.xtend.ide/icons/java_file.gifbin0 -> 598 bytes
-rw-r--r--plugins/org.eclipse.xtend.ide/icons/java_interface.gifbin0 -> 588 bytes
-rw-r--r--plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/CallsReadOnlyType.xtend27
-rw-r--r--plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/ExpectedTypeResolver.java81
-rw-r--r--plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/FeatureCallTargetTypeProvider.xtend29
-rw-r--r--plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/IsUndefinedMethod.xtend52
-rw-r--r--plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/MethodBuilder.xtend200
-rw-r--r--plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/NewTypePageConfigurer.java38
-rw-r--r--plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/ProjectProvider.java33
-rw-r--r--plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/UndefinedMethodFix.xtend170
-rw-r--r--plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/XtendQuickfixProvider.java202
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CallsReadOnlyType.java32
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CreateJavaMethod.java132
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CreateXtendMethod.java179
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/FeatureCallTargetTypeProvider.java44
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/IsUndefinedMethod.java93
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/JavaMethodBuilder.java22
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/MethodBuilderProvider.java37
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/NewMethodModificationProvider.java93
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/UndefinedMethodFix.java58
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/VariableNameAcceptor.java69
-rw-r--r--plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/XtendMethodBuilder.java255
22 files changed, 1845 insertions, 1 deletions
diff --git a/plugins/org.eclipse.xtend.ide/icons/java_file.gif b/plugins/org.eclipse.xtend.ide/icons/java_file.gif
new file mode 100644
index 0000000..a1c6545
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/icons/java_file.gif
Binary files differ
diff --git a/plugins/org.eclipse.xtend.ide/icons/java_interface.gif b/plugins/org.eclipse.xtend.ide/icons/java_interface.gif
new file mode 100644
index 0000000..0c198ef
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/icons/java_interface.gif
Binary files differ
diff --git a/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/CallsReadOnlyType.xtend b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/CallsReadOnlyType.xtend
new file mode 100644
index 0000000..00c193b
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/CallsReadOnlyType.xtend
@@ -0,0 +1,27 @@
+package org.eclipse.xtend.ide.quickfix
+
+import org.eclipse.xtext.common.types.JvmType
+import com.google.inject.Inject
+import org.eclipse.xtext.common.types.util.jdt.IJavaElementFinder
+import org.eclipse.xtext.xbase.XMemberFeatureCall
+
+class CallsReadOnlyType {
+
+ extension IJavaElementFinder elementFinder
+ extension FeatureCallTargetTypeProvider targetTypeProvider
+
+ @Inject
+ new(IJavaElementFinder elementFinder, FeatureCallTargetTypeProvider targetTypeProvider){
+ this.elementFinder = elementFinder
+ this.targetTypeProvider = targetTypeProvider
+ }
+
+ def receiverIsReadOnly(XMemberFeatureCall featureCall) {
+ return featureCall.targetType?.targetJavaElement?.isReadOnly
+ }
+
+ def private targetJavaElement(JvmType type){
+ findElementFor(type)
+ }
+
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/ExpectedTypeResolver.java b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/ExpectedTypeResolver.java
new file mode 100644
index 0000000..6be346c
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/ExpectedTypeResolver.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2012 itemis AG (http://www.itemis.eu) 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
+ *******************************************************************************/
+package org.eclipse.xtend.ide.quickfix;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.xtext.common.types.JvmTypeParameter;
+import org.eclipse.xtext.common.types.JvmTypeReference;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.xbase.XAbstractFeatureCall;
+import org.eclipse.xtext.xbase.XExpression;
+import org.eclipse.xtext.xbase.typesystem.references.ITypeReferenceOwner;
+import org.eclipse.xtext.xbase.typesystem.references.LightweightBoundTypeArgument;
+import org.eclipse.xtext.xbase.typesystem.references.LightweightMergedBoundTypeArgument;
+import org.eclipse.xtext.xbase.typesystem.references.OwnedConverter;
+import org.eclipse.xtext.xbase.typesystem.util.CommonTypeComputationServices;
+import org.eclipse.xtext.xbase.typesystem.util.TypeParameterByConstraintSubstitutor;
+import org.eclipse.xtext.xbase.typing.ITypeProvider;
+
+import com.google.inject.Inject;
+
+/**
+ * @author Sebastian Benz - Initial contribution and API
+ */
+public class ExpectedTypeResolver {
+
+ @Inject
+ private CommonTypeComputationServices computationServices;
+
+ @Inject
+ private ITypeProvider typeProvider;
+
+ public JvmTypeReference resolveExpectedType(final EObject context, JvmTypeReference expectedType) {
+ ITypeReferenceOwner owner = new ITypeReferenceOwner() {
+
+ @NonNull
+ public CommonTypeComputationServices getServices() {
+ return computationServices;
+ }
+
+ @NonNull
+ public List<LightweightBoundTypeArgument> getAllHints(@NonNull Object handle) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void acceptHint(@NonNull Object handle,
+ @NonNull LightweightBoundTypeArgument boundTypeArgument) {
+ throw new UnsupportedOperationException();
+ }
+
+ @NonNull
+ public ResourceSet getContextResourceSet() {
+ return context.eResource().getResourceSet();
+ }
+
+ public boolean isResolved(@NonNull Object handle) {
+ throw new UnsupportedOperationException();
+ }
+
+ @NonNull
+ public List<JvmTypeParameter> getDeclaredTypeParameters() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ TypeParameterByConstraintSubstitutor substitutor = new TypeParameterByConstraintSubstitutor(
+ Collections.<JvmTypeParameter, LightweightMergedBoundTypeArgument> emptyMap(),
+ owner);
+ JvmTypeReference resolvedExpectedType = substitutor.substitute(
+ new OwnedConverter(owner).toLightweightReference(expectedType)).toTypeReference();
+ return resolvedExpectedType;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/FeatureCallTargetTypeProvider.xtend b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/FeatureCallTargetTypeProvider.xtend
new file mode 100644
index 0000000..a1da42b
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/FeatureCallTargetTypeProvider.xtend
@@ -0,0 +1,29 @@
+package org.eclipse.xtend.ide.quickfix
+
+import com.google.inject.Inject
+import org.eclipse.xtext.common.types.JvmIdentifiableElement
+import org.eclipse.xtext.xbase.XAbstractFeatureCall
+import org.eclipse.xtext.xbase.XConstructorCall
+import org.eclipse.xtext.xbase.XMemberFeatureCall
+import org.eclipse.xtext.xbase.typing.ITypeProvider
+
+class FeatureCallTargetTypeProvider {
+
+ @Inject extension ITypeProvider
+
+ def targetType(XMemberFeatureCall featureCall){
+ featureCall.targetFeature?.typeForIdentifiable?.type
+ }
+
+ def private JvmIdentifiableElement targetFeature(XMemberFeatureCall featureCall){
+ val memberCallTarget = featureCall.memberCallTarget
+ if(memberCallTarget instanceof XConstructorCall){
+ return (memberCallTarget as XConstructorCall).constructor?.declaringType
+ }
+ if(!(memberCallTarget instanceof XAbstractFeatureCall)){
+ return null
+ }
+ (memberCallTarget as XAbstractFeatureCall).feature
+ }
+
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/IsUndefinedMethod.xtend b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/IsUndefinedMethod.xtend
new file mode 100644
index 0000000..c3b0bd0
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/IsUndefinedMethod.xtend
@@ -0,0 +1,52 @@
+package org.eclipse.xtend.ide.quickfix
+
+import org.eclipse.xtext.xbase.XMemberFeatureCall
+import com.google.inject.Inject
+import org.eclipse.xtext.common.types.JvmOperation
+import org.eclipse.xtext.xbase.typing.ITypeProvider
+import org.eclipse.emf.ecore.EObject
+
+class IsUndefinedMethod {
+
+ @Inject extension FeatureCallTargetTypeProvider
+ @Inject extension ITypeProvider
+
+ def callsUndefinedMethod(XMemberFeatureCall featureCall){
+ if(featureCall.targetType.isUnknown){
+ return false
+ }
+ val method = featureCall.feature
+ if(method == null){
+ return false
+ }
+ if(method.eIsProxy){
+ return true
+ }
+ if(!(method instanceof JvmOperation)){
+ return false
+ }
+ return featureCall.calls(method as JvmOperation)
+ }
+
+ def private calls(XMemberFeatureCall featureCall, JvmOperation operation){
+ val left = operation.parameters
+ val right = featureCall.memberCallArguments
+ if(left.size != right.size){
+ return true
+ }
+ var i = 0
+
+ while(i < operation.parameters.size){
+ if(left.get(i).parameterType != right.get(i).type){
+ return true
+ }
+ i = i + 1
+ }
+ return false
+ }
+
+ def private isUnknown(EObject obj){
+ obj == null || obj.eIsProxy
+ }
+
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/MethodBuilder.xtend b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/MethodBuilder.xtend
new file mode 100644
index 0000000..edc00a5
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/MethodBuilder.xtend
@@ -0,0 +1,200 @@
+package org.eclipse.xtend.ide.quickfix
+
+import com.google.common.collect.Lists
+import com.google.inject.Inject
+import com.google.inject.Provider
+import java.util.Collections
+import java.util.Set
+import org.eclipse.jface.viewers.StyledString
+import org.eclipse.swt.graphics.Image
+import org.eclipse.xtend.lib.Property
+import org.eclipse.xtext.common.types.JvmPrimitiveType
+import org.eclipse.xtext.common.types.JvmTypeReference
+import org.eclipse.xtext.common.types.util.Primitives
+import org.eclipse.xtext.common.types.xtext.ui.JdtVariableCompletions
+import org.eclipse.xtext.common.types.xtext.ui.JdtVariableCompletions$CompletionDataAcceptor
+import org.eclipse.xtext.xbase.XAbstractFeatureCall
+import org.eclipse.xtext.xbase.XMemberFeatureCall
+import org.eclipse.xtext.xbase.compiler.IAppendable
+import org.eclipse.xtext.xbase.typing.ITypeProvider
+
+import static org.eclipse.xtext.common.types.util.Primitives$Primitive.*
+import static org.eclipse.xtext.common.types.xtext.ui.JdtVariableCompletions$VariableType.*
+import org.eclipse.xtext.xbase.compiler.TypeReferenceSerializer
+
+class MethodBuilderProvider{
+
+ @Inject Provider<XtendMethodBuilder> xtendMethodBuilderProvider
+ @Inject Provider<JavaMethodBuilder> javaMethodBuilderProvider
+
+ def newXtendMethodBuilder(String methodName, XAbstractFeatureCall call){
+ xtendMethodBuilderProvider.invoke(methodName, call)
+ }
+
+ def newJavaMethodBuilder(String methodName, XAbstractFeatureCall call){
+ javaMethodBuilderProvider.invoke(methodName, call)
+ }
+
+ def private invoke(Provider<?extends XtendMethodBuilder> provider, String methodName, XAbstractFeatureCall call){
+ val builder = provider.get
+ builder.methodName = methodName
+ builder.featureCall = call
+ builder
+ }
+}
+
+class XtendMethodBuilder {
+
+ @Inject extension ITypeProvider
+ @Inject extension JdtVariableCompletions
+ @Inject extension Primitives
+ @Inject extension ExpectedTypeResolver
+ @Inject extension TypeReferenceSerializer
+
+ @Property String methodName
+ @Property boolean isInterface
+ @Property XAbstractFeatureCall featureCall
+
+ def build(IAppendable appendable){
+ appendable => [
+ addPrefix
+ addName
+ addArguments
+ addBody
+ ]
+ }
+
+ def protected addName(IAppendable appendable){
+ appendable.append(methodName)
+ }
+
+ def protected addPrefix(IAppendable appendable){
+ appendable.append("def ")
+ }
+
+ def protected addBody(IAppendable appendable){
+ if(isInterface) return appendable.append(";");
+ appendable.append('''
+ {
+ «returnStatement»
+ }
+ ''')
+ }
+
+ def protected returnStatement(){
+ if(featureCall == null || featureCall.isVoid){
+ return ""
+ }else{
+ return defaultReturnStatement
+ }
+ }
+
+ def protected defaultReturnStatement(){
+ val expectedType = returnType
+ val result = new StringBuilder("return ")
+ if(isPrimitive(expectedType)){
+ val primitiveKind = primitiveKind(expectedType.type as JvmPrimitiveType)
+ switch (primitiveKind) {
+ case Boolean:
+ result.append("false")
+ default:
+ result.append("0")
+ }
+ }else{
+ return result.append("null")
+ }
+ return result
+ }
+
+ def private isVoid(XAbstractFeatureCall featureCall){
+ val returnType = returnType()
+ return returnType == null || returnType.simpleName == "void"
+ }
+
+ def protected returnType(){
+ featureCall.expectedType
+ }
+
+ def protected addArguments(IAppendable appendable) {
+ if(featureCall == null){
+ return appendable.append("()")
+ }
+ var iterator = if(featureCall instanceof XMemberFeatureCall){
+ (featureCall as XMemberFeatureCall).memberCallArguments.iterator
+ }else{
+ featureCall.explicitArguments.iterator
+ }
+ val notallowed = <String>newHashSet()
+ appendable.append("(")
+
+ while(iterator.hasNext()){
+ val expression = iterator.next()
+ val typeRef = expression.type
+ if(typeRef != null){
+ appendable.append(typeRef)
+ appendable.append(" ")
+ val acceptor = new VariableNameAcceptor(notallowed)
+ getVariableProposals(typeRef.getIdentifier(), featureCall, PARAMETER, notallowed, acceptor)
+ appendable.append(acceptor.getVariableName())
+ }
+ if(iterator.hasNext())
+ appendable.append(", ")
+ }
+ appendable.append(")")
+ }
+
+ def protected append(IAppendable appendable, JvmTypeReference typeRef){
+ if(typeRef == null){
+ appendable.append("void")
+ }else{
+ val resolvedExpectedType = featureCall.resolveExpectedType(typeRef)
+ resolvedExpectedType.serialize(featureCall, appendable)
+ }
+ appendable
+ }
+
+}
+
+class JavaMethodBuilder extends XtendMethodBuilder{
+
+ override protected defaultReturnStatement() {
+ super.defaultReturnStatement().append(";")
+ }
+
+ override protected addPrefix(IAppendable appendable) {
+ appendable.append("public ").append(returnType).append(" ")
+ }
+
+}
+
+
+class VariableNameAcceptor implements JdtVariableCompletions$CompletionDataAcceptor {
+
+ val Set<String> notallowed
+ val Set<String> variableNames = newHashSet()
+
+ new(Set<String> notallowed) {
+ this.notallowed = notallowed;
+ }
+
+ override accept(String replaceText, StyledString label, Image img) {
+ variableNames.add(replaceText);
+ notallowed.add(replaceText);
+ }
+
+ def getVariableName(){
+ val candidates = Lists::newArrayList(variableNames);
+ Collections::sort(candidates, [left, right|
+ if (left.length() < right.length()) {
+ return -1;
+ } else if (left.length() > right.length()) {
+ return 1;
+ } else {
+ return 0;
+ }
+ ])
+ if(candidates.size > 0)
+ return candidates.get(0)
+ return ""
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/NewTypePageConfigurer.java b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/NewTypePageConfigurer.java
new file mode 100644
index 0000000..559d891
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/NewTypePageConfigurer.java
@@ -0,0 +1,38 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import org.apache.log4j.Logger;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.ui.wizards.NewTypeWizardPage;
+
+import com.google.inject.Inject;
+
+public class NewTypePageConfigurer {
+
+ private static final Logger LOG = Logger.getLogger(NewTypePageConfigurer.class);
+ @Inject private ProjectProvider projectProvider;
+
+ public void configure(NewTypeWizardPage page, URI contextUri, String typeName){
+ setPackageName(page, contextUri);
+ page.setTypeName(typeName, true);
+ }
+
+ public void setPackageName(NewTypeWizardPage page, URI contextUri) {
+ IJavaProject javaProject = projectProvider.getJavaProject(contextUri);
+ String path = contextUri.trimSegments(1).toPlatformString(true);
+ try {
+ IPackageFragment packageFragment = javaProject.findPackageFragment(new Path(path));
+ IPackageFragmentRoot root = (IPackageFragmentRoot) packageFragment.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+ page.setPackageFragment(packageFragment, true);
+ page.setPackageFragmentRoot(root, true);
+ } catch (JavaModelException e) {
+ LOG.error("Could not find package for " + path, e);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/ProjectProvider.java b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/ProjectProvider.java
new file mode 100644
index 0000000..0edc759
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/ProjectProvider.java
@@ -0,0 +1,33 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+
+import com.google.inject.Inject;
+
+public class ProjectProvider {
+
+ @Inject IWorkspaceRoot workspaceRoot;
+
+ public IJavaProject getJavaProject(URI uri){
+ IProject project = getProject(uri);
+ if(project == null){
+ return null;
+ }
+ return JavaCore.create(project);
+ }
+
+ public IProject getProject(URI uri){
+ IFile file = workspaceRoot.getFile(new Path(uri.toPlatformString(true)));
+ if(file == null){
+ return null;
+ }
+ return file.getProject();
+ }
+
+}
diff --git a/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/UndefinedMethodFix.xtend b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/UndefinedMethodFix.xtend
new file mode 100644
index 0000000..66404b0
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/UndefinedMethodFix.xtend
@@ -0,0 +1,170 @@
+package org.eclipse.xtend.ide.quickfix
+
+import com.google.inject.Inject
+import org.eclipse.core.runtime.NullProgressMonitor
+import org.eclipse.emf.ecore.util.EcoreUtil
+import org.eclipse.jdt.core.IJavaElement
+import org.eclipse.jdt.core.IType
+import org.eclipse.xtend.core.xtend.XtendClass
+import org.eclipse.xtend.lib.Data
+import org.eclipse.xtext.Keyword
+import org.eclipse.xtext.common.types.JvmType
+import org.eclipse.xtext.common.types.util.jdt.IJavaElementFinder
+import org.eclipse.xtext.common.types.xtext.ui.JdtHyperlink
+import org.eclipse.xtext.nodemodel.util.NodeModelUtils
+import org.eclipse.xtext.ui.editor.IURIEditorOpener
+import org.eclipse.xtext.ui.editor.XtextEditor
+import org.eclipse.xtext.ui.editor.model.edit.IModification
+import org.eclipse.xtext.ui.editor.model.edit.IModificationContext
+import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor
+import org.eclipse.xtext.validation.Issue
+import org.eclipse.xtext.xbase.XMemberFeatureCall
+import org.eclipse.xtext.xbase.compiler.ImportManager
+import org.eclipse.xtext.xbase.compiler.StringBuilderBasedAppendable
+
+import static org.eclipse.xtext.xbase.XbasePackage$Literals.*
+import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.*
+import org.eclipse.xtext.common.types.JvmGenericType
+import org.eclipse.xtext.xbase.ui.contentassist.ReplacingAppendable
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.emf.ecore.EStructuralFeature
+import org.eclipse.xtext.nodemodel.INode
+
+class UndefinedMethodFix {
+
+ @Inject extension NewMethodModificationProvider
+ @Inject extension IsUndefinedMethod
+ @Inject extension CallsReadOnlyType
+
+ def apply(Issue issue, IssueResolutionAcceptor issueResolutionAcceptor, XMemberFeatureCall featureCall){
+ val issueString = textForFeature(featureCall, XABSTRACT_FEATURE_CALL__FEATURE);
+ if(!featureCall.callsUndefinedMethod){
+ return
+ }
+ if(featureCall.receiverIsReadOnly){
+ return
+ }
+ issueResolutionAcceptor.accept(
+ issue,
+ "create method '" + issueString + "'", "",
+ "fix_public_function.png",
+ createModification(featureCall, issueString)
+ )
+ }
+
+ def private textForFeature(EObject eObject, EStructuralFeature feature){
+ val nodes = findNodesForFeature(eObject, feature);
+ val sb = new StringBuilder();
+ for (INode node : nodes) {
+ sb.append(node.getText());
+ }
+ return sb.toString().trim();
+ }
+}
+
+
+class NewMethodModificationProvider{
+
+ @Inject IURIEditorOpener editorOpener
+ @Inject ReplacingAppendable$Factory apendableFactory
+ @Inject extension MethodBuilderProvider methodBuilderProvider
+ @Inject extension IJavaElementFinder elementProvider
+ @Inject extension FeatureCallTargetTypeProvider
+
+ def IModification createModification(XMemberFeatureCall call, String methodName) {
+ val targetType = call.targetType
+ val xtendClass = targetType.xtendClass
+ if(xtendClass != null){
+ val methodBuilder = newXtendMethodBuilder(methodName, call)
+ return new CreateXtendMethod(methodBuilder, targetType.xtendClass, editorOpener, apendableFactory)
+ }else{
+ val methodBuilder = newJavaMethodBuilder(methodName, call)
+ methodBuilder.isInterface = (targetType instanceof JvmGenericType) && (targetType as JvmGenericType).interface
+ val javaElement = findElementFor(targetType)
+ return new CreateJavaMethod(methodBuilder, javaElement as IType)
+ }
+ }
+
+ def private xtendClass(JvmType type){
+ if(type == null){
+ return null
+ }
+ type.eResource.allContents.filter(typeof(XtendClass)).findFirst[it.name == type.simpleName]
+ }
+
+}
+
+@Data
+class CreateJavaMethod implements IModification{
+
+ XtendMethodBuilder methodBuilder
+ IType type
+
+ override apply(IModificationContext context) throws Exception {
+ generateMethod.openInEditor
+ }
+
+ def private generateMethod(){
+ val importManager = new ImportManager(true, ".".charAt(0))
+ val content = new StringBuilderBasedAppendable(importManager)
+ methodBuilder.build(content)
+ importManager.imports.forEach[
+ type.compilationUnit.createImport(it, null, monitor)
+ ]
+ type.createMethod(content.toString, null, true, monitor)
+ }
+
+ def monitor(){
+ new NullProgressMonitor
+ }
+
+ def private openInEditor(IJavaElement element){
+ val link = new JdtHyperlink()
+ link.javaElement = element
+ link.open
+ }
+}
+
+@Data
+class CreateXtendMethod implements IModification{
+
+ XtendMethodBuilder methodBuilder
+ XtendClass xtendClass
+ IURIEditorOpener editorOpener
+ ReplacingAppendable$Factory appendableFactory
+
+ override apply(IModificationContext context) throws Exception {
+ val editor = editorOpener.open(EcoreUtil::getURI(xtendClass), false);
+ if (!(editor instanceof XtextEditor)) {
+ return
+ }
+ val xtextEditor = editor as XtextEditor;
+ val document = xtextEditor.getDocument();
+ var offset = getFunctionInsertOffset(xtendClass)
+
+ val appendable = appendableFactory.get(document, xtendClass, offset-1, 0, 1, false)
+ appendable.newLine()
+ methodBuilder.build(appendable)
+ appendable.decreaseIndentation().newLine()
+ appendable.commitChanges
+ xtextEditor.setHighlightRange(offset + 1, appendable.length, true)
+ }
+
+ def getFunctionInsertOffset(XtendClass clazz) {
+ val clazzNode = NodeModelUtils::findActualNodeFor(clazz)
+ if (clazzNode == null)
+ throw new IllegalStateException("Cannot determine node for clazz " + clazz.getName())
+ var lastClosingBraceOffset = -1
+ for (leafNode : clazzNode.getLeafNodes()) {
+ if ((leafNode.getGrammarElement() instanceof Keyword)
+ && "}" == (leafNode.getGrammarElement() as Keyword).getValue()) {
+ lastClosingBraceOffset = leafNode.getOffset();
+ }
+ }
+ if(lastClosingBraceOffset == -1)
+ clazzNode.getTotalEndOffset()
+ else lastClosingBraceOffset
+ }
+
+}
+
diff --git a/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/XtendQuickfixProvider.java b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/XtendQuickfixProvider.java
index 19587d9..845c4ac 100644
--- a/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/XtendQuickfixProvider.java
+++ b/plugins/org.eclipse.xtend.ide/src/org/eclipse/xtend/ide/quickfix/XtendQuickfixProvider.java
@@ -7,6 +7,7 @@
*******************************************************************************/
package org.eclipse.xtend.ide.quickfix;
+import static org.eclipse.xtext.ui.util.DisplayRunHelper.*;
import static org.eclipse.xtext.util.Strings.*;
import java.util.ArrayList;
@@ -26,9 +27,19 @@ import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.internal.ui.wizards.NewClassCreationWizard;
+import org.eclipse.jdt.internal.ui.wizards.NewElementWizard;
+import org.eclipse.jdt.internal.ui.wizards.NewInterfaceCreationWizard;
+import org.eclipse.jdt.ui.wizards.NewClassWizardPage;
+import org.eclipse.jdt.ui.wizards.NewInterfaceWizardPage;
import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
import org.eclipse.xtend.core.formatting.MemberFromSuperImplementor;
import org.eclipse.xtend.core.jvmmodel.IXtendJvmAssociations;
import org.eclipse.xtend.core.services.XtendGrammarAccess;
@@ -37,7 +48,8 @@ import org.eclipse.xtend.core.xtend.XtendClass;
import org.eclipse.xtend.core.xtend.XtendFunction;
import org.eclipse.xtend.core.xtend.XtendMember;
import org.eclipse.xtend.ide.buildpath.XtendLibClasspathAdder;
-import org.eclipse.xtend.ide.validator.XtendUIValidator;
+import org.eclipse.xtend.ide.wizards.NewXtendClassWizard;
+import org.eclipse.xtend.ide.wizards.NewXtendClassWizardPage;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.common.types.JvmConstructor;
@@ -75,6 +87,7 @@ import org.eclipse.xtext.xbase.XAssignment;
import org.eclipse.xtext.xbase.XBlockExpression;
import org.eclipse.xtext.xbase.XExpression;
import org.eclipse.xtext.xbase.XMemberFeatureCall;
+import org.eclipse.xtext.xbase.XbasePackage;
import org.eclipse.xtext.xbase.compiler.IAppendable;
import org.eclipse.xtext.xbase.compiler.ImportManager;
import org.eclipse.xtext.xbase.compiler.ScopeFakeReference;
@@ -134,6 +147,10 @@ public class XtendQuickfixProvider extends XbaseQuickfixProvider {
private CommonTypeComputationServices computationServices;
@Inject
private JdtTypeRelevance jdtTypeRelevance;
+ @Inject
+ private NewTypePageConfigurer newTypePageConfigurer;
+ @Inject Provider<NewXtendClassWizard> newXtendClassWizardProvider;
+ @Inject UndefinedMethodFix createMissingMethod;
@Override
public boolean hasResolutionFor(String issueCode) {
@@ -164,16 +181,128 @@ public class XtendQuickfixProvider extends XbaseQuickfixProvider {
}
}
+ @Override
+ public void createLinkingIssueResolutions(final Issue issue,
+ final IssueResolutionAcceptor issueResolutionAcceptor) {
+ final IModificationContext modificationContext = getModificationContextFactory().createModificationContext(
+ issue);
+ final IXtextDocument xtextDocument = modificationContext.getXtextDocument();
+ if (xtextDocument != null) {
+ xtextDocument.readOnly(new IUnitOfWork.Void<XtextResource>() {
+ @Override
+ public void process(XtextResource state) throws Exception {
+ EObject target = state.getEObject(issue.getUriToProblem().fragment());
+ EReference reference = getUnresolvedEReference(issue, target);
+ if (reference == null)
+ return;
+
+ if( reference == XbasePackage.Literals.XCONSTRUCTOR_CALL__CONSTRUCTOR ||
+ reference == XbasePackage.Literals.XTYPE_LITERAL__TYPE ||
+ reference == TypesPackage.Literals.JVM_PARAMETERIZED_TYPE_REFERENCE__TYPE){
+ URI context = state.getURI();
+ String issueString = getIssueString(issue, xtextDocument);
+ issueResolutionAcceptor.accept(
+ issue,
+ "Create Xtend class",
+ "Opens the new Xtend class wizard to create the type '" + issueString + "'",
+ "xtend_file.png", openNewXtendClassWizardFor(context, issueString));
+ issueResolutionAcceptor.accept(issue,
+ "Create Java class",
+ "Opens the new Java class wizard to create the type '" + issueString + "'",
+ "java_file.gif",
+ openNewJavaClassWizardFor(context, issueString));
+ issueResolutionAcceptor.accept(issue,
+ "Create Java Interface",
+ "Opens the new Java interface wizard to create the type '" + issueString + "'",
+ "java_interface.gif",
+ openNewJavaInterfaceWizardFor(context, issueString));
+ }
+ }
+
+
+ });
+ super.createLinkingIssueResolutions(issue, issueResolutionAcceptor);
+ }
+ }
+
+ protected String getIssueString(Issue issue, IXtextDocument xtextDocument)
+ throws BadLocationException {
+ return xtextDocument.get(issue.getOffset(), issue.getLength());
+ }
+
+ private IModification openNewJavaInterfaceWizardFor(final URI contextUri, final String typeName) {
+ return new IModification() {
+ public void apply(IModificationContext context) throws Exception {
+ runAsyncInDisplayThread(new Runnable(){
+
+ public void run() {
+ NewInterfaceWizardPage classWizardPage = new NewInterfaceWizardPage();
+ NewInterfaceCreationWizard wizard = new NewInterfaceCreationWizard(classWizardPage, false);
+ WizardDialog dialog = createWizardDialog(wizard);
+ newTypePageConfigurer.configure(classWizardPage, contextUri, typeName);
+ dialog.open();
+ }
+ });
+ }
+ };
+ }
+
+ private IModification openNewJavaClassWizardFor(final URI contextUri, final String typeName) {
+ return new IModification() {
+ public void apply(IModificationContext context) throws Exception {
+ runAsyncInDisplayThread(new Runnable(){
+
+ public void run() {
+ NewClassWizardPage classWizardPage = new NewClassWizardPage();
+ NewClassCreationWizard wizard = new NewClassCreationWizard(classWizardPage, false);
+ WizardDialog dialog = createWizardDialog(wizard);
+ newTypePageConfigurer.configure(classWizardPage, contextUri, typeName);
+ dialog.open();
+ }
+ });
+ }
+ };
+ }
+
+ private IModification openNewXtendClassWizardFor(final URI contextUri, final String typeName) {
+ return new IModification() {
+ public void apply(IModificationContext context) throws Exception {
+ runAsyncInDisplayThread(new Runnable(){
+
+ public void run() {
+ NewElementWizard newXtendClassWizard = newXtendClassWizardProvider.get();
+ WizardDialog dialog = createWizardDialog(newXtendClassWizard);
+ NewXtendClassWizardPage page = (NewXtendClassWizardPage) newXtendClassWizard.getStartingPage();
+ newTypePageConfigurer.configure(page, contextUri, typeName);
+ dialog.open();
+ }
+ });
+ }
+ };
+ }
+
+ private WizardDialog createWizardDialog(
+ NewElementWizard newXtendClassWizard) {
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ Shell shell = workbench.getActiveWorkbenchWindow().getShell();
+ newXtendClassWizard.init(workbench, new StructuredSelection());
+ WizardDialog dialog = new WizardDialog(shell, newXtendClassWizard);
+ dialog.create();
+ return dialog;
+ }
+
/**
* @since 2.3
*/
protected void createXtendLinkingIssueResolutions(final Issue issue, final IssueResolutionAcceptor issueResolutionAcceptor) {
+ fixUndefinedMethod(issue, issueResolutionAcceptor);
final IModificationContext modificationContext = getModificationContextFactory().createModificationContext(issue);
IXtextDocument xtextDocument = modificationContext.getXtextDocument();
if(issue.getData() != null && xtextDocument != null){
final String elementName = issue.getData()[0];
if(elementName != null)
xtextDocument.modify(new IUnitOfWork.Void<XtextResource>(){
+
@Override
public void process(final XtextResource state) throws Exception {
EObject eObject = state.getEObject(issue.getUriToProblem().fragment());
@@ -183,6 +312,10 @@ public class XtendQuickfixProvider extends XbaseQuickfixProvider {
if(target != null && isExpressionWithName(target, XbaseScopeProvider.SUPER))
return;
}
+ XMemberFeatureCall memberFeatureCall = EcoreUtil2.getContainerOfType(eObject, XMemberFeatureCall.class);
+ if(memberFeatureCall == null){
+ return;
+ }
if(eObject instanceof XAbstractFeatureCall){
XAbstractFeatureCall call = (XAbstractFeatureCall) eObject;
StringBuilderBasedAppendable appendable = new StringBuilderBasedAppendable(new ImportManager(true));
@@ -262,6 +395,49 @@ public class XtendQuickfixProvider extends XbaseQuickfixProvider {
}
}
}
+
+ private JvmTypeReference resolveExpectedType(final XtextResource state, XAbstractFeatureCall call) {
+ JvmTypeReference expectedType = typeProvider.getExpectedType(call);
+ ITypeReferenceOwner owner = new ITypeReferenceOwner() {
+
+ @NonNull
+ public CommonTypeComputationServices getServices() {
+ return computationServices;
+ }
+
+ @NonNull
+ public List<LightweightBoundTypeArgument> getAllHints(@NonNull Object handle) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void acceptHint(@NonNull Object handle,
+ @NonNull LightweightBoundTypeArgument boundTypeArgument) {
+ throw new UnsupportedOperationException();
+ }
+
+ @NonNull
+ public ResourceSet getContextResourceSet() {
+ return state.getResourceSet();
+ }
+
+ public boolean isResolved(@NonNull Object handle) {
+ throw new UnsupportedOperationException();
+ }
+
+ public @NonNull List<JvmTypeParameter> getDeclaredTypeParameters() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ TypeParameterByConstraintSubstitutor substitutor = new TypeParameterByConstraintSubstitutor(
+ Collections.<JvmTypeParameter, LightweightMergedBoundTypeArgument> emptyMap(),
+ owner);
+ if(expectedType == null){
+ return null;
+ }
+ JvmTypeReference resolvedExpectedType = substitutor.substitute(
+ new OwnedConverter(owner).toLightweightReference(expectedType)).toTypeReference();
+ return resolvedExpectedType;
+ }
});
}
}
@@ -730,6 +906,30 @@ public class XtendQuickfixProvider extends XbaseQuickfixProvider {
return findContainerExpressionInBlockExpression(container);
}
+ @Fix(org.eclipse.xtext.xbase.validation.IssueCodes.INVALID_NUMBER_OF_ARGUMENTS)
+ public void fixInvalidNumberOfArguments(final Issue issue, IssueResolutionAcceptor acceptor) {
+ fixUndefinedMethod(issue, acceptor);
+ }
+
+ protected void fixUndefinedMethod(final Issue issue,
+ final IssueResolutionAcceptor issueResolutionAcceptor) {
+ final IModificationContext modificationContext = getModificationContextFactory().createModificationContext(issue);
+ final IXtextDocument xtextDocument = modificationContext.getXtextDocument();
+ if(xtextDocument != null){
+ xtextDocument.modify(new IUnitOfWork.Void<XtextResource>(){
+ @Override
+ public void process(XtextResource state) throws Exception {
+ EObject eObject = state.getEObject(issue.getUriToProblem().fragment());
+ XMemberFeatureCall memberFeatureCall = EcoreUtil2.getContainerOfType(eObject, XMemberFeatureCall.class);
+ if(memberFeatureCall == null){
+ return;
+ }
+ createMissingMethod.apply(issue, issueResolutionAcceptor, memberFeatureCall);
+ }
+ });
+ }
+ }
+
@Fix(IssueCodes.XBASE_LIB_NOT_ON_CLASSPATH)
public void putXtendOnClasspath(final Issue issue, IssueResolutionAcceptor acceptor) {
acceptor.accept(issue, "Add Xtend libs to classpath", "Add Xtend libs to classpath", "fix_indent.gif", new ISemanticModification() {
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CallsReadOnlyType.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CallsReadOnlyType.java
new file mode 100644
index 0000000..e674b8b
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CallsReadOnlyType.java
@@ -0,0 +1,32 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import com.google.inject.Inject;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.xtend.ide.quickfix.FeatureCallTargetTypeProvider;
+import org.eclipse.xtext.common.types.JvmType;
+import org.eclipse.xtext.common.types.util.jdt.IJavaElementFinder;
+import org.eclipse.xtext.xbase.XMemberFeatureCall;
+
+@SuppressWarnings("all")
+public class CallsReadOnlyType {
+ private IJavaElementFinder elementFinder;
+
+ private FeatureCallTargetTypeProvider targetTypeProvider;
+
+ @Inject
+ public CallsReadOnlyType(final IJavaElementFinder elementFinder, final FeatureCallTargetTypeProvider targetTypeProvider) {
+ this.elementFinder = elementFinder;
+ this.targetTypeProvider = targetTypeProvider;
+ }
+
+ public boolean receiverIsReadOnly(final XMemberFeatureCall featureCall) {
+ JvmType _targetType = this.targetTypeProvider.targetType(featureCall);
+ IJavaElement _targetJavaElement = _targetType==null?(IJavaElement)null:this.targetJavaElement(_targetType);
+ return _targetJavaElement==null?false:_targetJavaElement.isReadOnly();
+ }
+
+ private IJavaElement targetJavaElement(final JvmType type) {
+ IJavaElement _findElementFor = this.elementFinder.findElementFor(type);
+ return _findElementFor;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CreateJavaMethod.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CreateJavaMethod.java
new file mode 100644
index 0000000..9f30fbd
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CreateJavaMethod.java
@@ -0,0 +1,132 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import java.util.List;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.xtend.ide.quickfix.XtendMethodBuilder;
+import org.eclipse.xtend.lib.Data;
+import org.eclipse.xtext.common.types.xtext.ui.JdtHyperlink;
+import org.eclipse.xtext.ui.editor.model.edit.IModification;
+import org.eclipse.xtext.ui.editor.model.edit.IModificationContext;
+import org.eclipse.xtext.xbase.compiler.ImportManager;
+import org.eclipse.xtext.xbase.compiler.StringBuilderBasedAppendable;
+import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.eclipse.xtext.xbase.lib.util.ToStringHelper;
+
+@Data
+@SuppressWarnings("all")
+public class CreateJavaMethod implements IModification {
+ private final XtendMethodBuilder _methodBuilder;
+
+ public XtendMethodBuilder getMethodBuilder() {
+ return this._methodBuilder;
+ }
+
+ private final IType _type;
+
+ public IType getType() {
+ return this._type;
+ }
+
+ public void apply(final IModificationContext context) throws Exception {
+ IMethod _generateMethod = this.generateMethod();
+ this.openInEditor(_generateMethod);
+ }
+
+ private IMethod generateMethod() {
+ try {
+ IMethod _xblockexpression = null;
+ {
+ char _charAt = ".".charAt(0);
+ ImportManager _importManager = new ImportManager(true, _charAt);
+ final ImportManager importManager = _importManager;
+ StringBuilderBasedAppendable _stringBuilderBasedAppendable = new StringBuilderBasedAppendable(importManager);
+ final StringBuilderBasedAppendable content = _stringBuilderBasedAppendable;
+ XtendMethodBuilder _methodBuilder = this.getMethodBuilder();
+ _methodBuilder.build(content);
+ List<String> _imports = importManager.getImports();
+ final Procedure1<String> _function = new Procedure1<String>() {
+ public void apply(final String it) {
+ try {
+ IType _type = CreateJavaMethod.this.getType();
+ ICompilationUnit _compilationUnit = _type.getCompilationUnit();
+ NullProgressMonitor _monitor = CreateJavaMethod.this.monitor();
+ _compilationUnit.createImport(it, null, _monitor);
+ } catch (Exception _e) {
+ throw Exceptions.sneakyThrow(_e);
+ }
+ }
+ };
+ IterableExtensions.<String>forEach(_imports, _function);
+ IType _type = this.getType();
+ String _string = content.toString();
+ NullProgressMonitor _monitor = this.monitor();
+ IMethod _createMethod = _type.createMethod(_string, null, true, _monitor);
+ _xblockexpression = (_createMethod);
+ }
+ return _xblockexpression;
+ } catch (Exception _e) {
+ throw Exceptions.sneakyThrow(_e);
+ }
+ }
+
+ public NullProgressMonitor monitor() {
+ NullProgressMonitor _nullProgressMonitor = new NullProgressMonitor();
+ return _nullProgressMonitor;
+ }
+
+ private void openInEditor(final IJavaElement element) {
+ JdtHyperlink _jdtHyperlink = new JdtHyperlink();
+ final JdtHyperlink link = _jdtHyperlink;
+ link.setJavaElement(element);
+ link.open();
+ }
+
+ public CreateJavaMethod(final XtendMethodBuilder methodBuilder, final IType type) {
+ super();
+ this._methodBuilder = methodBuilder;
+ this._type = type;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_methodBuilder== null) ? 0 : _methodBuilder.hashCode());
+ result = prime * result + ((_type== null) ? 0 : _type.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CreateJavaMethod other = (CreateJavaMethod) obj;
+ if (_methodBuilder == null) {
+ if (other._methodBuilder != null)
+ return false;
+ } else if (!_methodBuilder.equals(other._methodBuilder))
+ return false;
+ if (_type == null) {
+ if (other._type != null)
+ return false;
+ } else if (!_type.equals(other._type))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ String result = new ToStringHelper().toString(this);
+ return result;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CreateXtendMethod.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CreateXtendMethod.java
new file mode 100644
index 0000000..1e94e75
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/CreateXtendMethod.java
@@ -0,0 +1,179 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.xtend.core.xtend.XtendClass;
+import org.eclipse.xtend.ide.quickfix.XtendMethodBuilder;
+import org.eclipse.xtend.lib.Data;
+import org.eclipse.xtext.Keyword;
+import org.eclipse.xtext.nodemodel.ICompositeNode;
+import org.eclipse.xtext.nodemodel.ILeafNode;
+import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
+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.IModification;
+import org.eclipse.xtext.ui.editor.model.edit.IModificationContext;
+import org.eclipse.xtext.xbase.compiler.IAppendable;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.util.ToStringHelper;
+import org.eclipse.xtext.xbase.ui.contentassist.ReplacingAppendable;
+import org.eclipse.xtext.xbase.ui.contentassist.ReplacingAppendable.Factory;
+
+@Data
+@SuppressWarnings("all")
+public class CreateXtendMethod implements IModification {
+ private final XtendMethodBuilder _methodBuilder;
+
+ public XtendMethodBuilder getMethodBuilder() {
+ return this._methodBuilder;
+ }
+
+ private final XtendClass _xtendClass;
+
+ public XtendClass getXtendClass() {
+ return this._xtendClass;
+ }
+
+ private final IURIEditorOpener _editorOpener;
+
+ public IURIEditorOpener getEditorOpener() {
+ return this._editorOpener;
+ }
+
+ private final Factory _appendableFactory;
+
+ public Factory getAppendableFactory() {
+ return this._appendableFactory;
+ }
+
+ public void apply(final IModificationContext context) throws Exception {
+ IURIEditorOpener _editorOpener = this.getEditorOpener();
+ XtendClass _xtendClass = this.getXtendClass();
+ URI _uRI = EcoreUtil.getURI(_xtendClass);
+ final IEditorPart editor = _editorOpener.open(_uRI, false);
+ boolean _not = (!(editor instanceof XtextEditor));
+ if (_not) {
+ return;
+ }
+ final XtextEditor xtextEditor = ((XtextEditor) editor);
+ final IXtextDocument document = xtextEditor.getDocument();
+ XtendClass _xtendClass_1 = this.getXtendClass();
+ int offset = this.getFunctionInsertOffset(_xtendClass_1);
+ Factory _appendableFactory = this.getAppendableFactory();
+ XtendClass _xtendClass_2 = this.getXtendClass();
+ int _minus = (offset - 1);
+ final ReplacingAppendable appendable = _appendableFactory.get(document, _xtendClass_2, _minus, 0, 1, false);
+ appendable.newLine();
+ XtendMethodBuilder _methodBuilder = this.getMethodBuilder();
+ _methodBuilder.build(appendable);
+ IAppendable _decreaseIndentation = appendable.decreaseIndentation();
+ _decreaseIndentation.newLine();
+ appendable.commitChanges();
+ int _plus = (offset + 1);
+ int _length = appendable.length();
+ xtextEditor.setHighlightRange(_plus, _length, true);
+ }
+
+ public int getFunctionInsertOffset(final XtendClass clazz) {
+ int _xblockexpression = (int) 0;
+ {
+ final ICompositeNode clazzNode = NodeModelUtils.findActualNodeFor(clazz);
+ boolean _equals = ObjectExtensions.operator_equals(clazzNode, null);
+ if (_equals) {
+ String _name = clazz.getName();
+ String _plus = ("Cannot determine node for clazz " + _name);
+ IllegalStateException _illegalStateException = new IllegalStateException(_plus);
+ throw _illegalStateException;
+ }
+ int lastClosingBraceOffset = (-1);
+ Iterable<ILeafNode> _leafNodes = clazzNode.getLeafNodes();
+ for (final ILeafNode leafNode : _leafNodes) {
+ boolean _and = false;
+ EObject _grammarElement = leafNode.getGrammarElement();
+ if (!(_grammarElement instanceof Keyword)) {
+ _and = false;
+ } else {
+ EObject _grammarElement_1 = leafNode.getGrammarElement();
+ String _value = ((Keyword) _grammarElement_1).getValue();
+ boolean _equals_1 = ObjectExtensions.operator_equals("}", _value);
+ _and = ((_grammarElement instanceof Keyword) && _equals_1);
+ }
+ if (_and) {
+ int _offset = leafNode.getOffset();
+ lastClosingBraceOffset = _offset;
+ }
+ }
+ int _xifexpression = (int) 0;
+ int _minus = (-1);
+ boolean _equals_2 = (lastClosingBraceOffset == _minus);
+ if (_equals_2) {
+ int _totalEndOffset = clazzNode.getTotalEndOffset();
+ _xifexpression = _totalEndOffset;
+ } else {
+ _xifexpression = lastClosingBraceOffset;
+ }
+ _xblockexpression = (_xifexpression);
+ }
+ return _xblockexpression;
+ }
+
+ public CreateXtendMethod(final XtendMethodBuilder methodBuilder, final XtendClass xtendClass, final IURIEditorOpener editorOpener, final Factory appendableFactory) {
+ super();
+ this._methodBuilder = methodBuilder;
+ this._xtendClass = xtendClass;
+ this._editorOpener = editorOpener;
+ this._appendableFactory = appendableFactory;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_methodBuilder== null) ? 0 : _methodBuilder.hashCode());
+ result = prime * result + ((_xtendClass== null) ? 0 : _xtendClass.hashCode());
+ result = prime * result + ((_editorOpener== null) ? 0 : _editorOpener.hashCode());
+ result = prime * result + ((_appendableFactory== null) ? 0 : _appendableFactory.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CreateXtendMethod other = (CreateXtendMethod) obj;
+ if (_methodBuilder == null) {
+ if (other._methodBuilder != null)
+ return false;
+ } else if (!_methodBuilder.equals(other._methodBuilder))
+ return false;
+ if (_xtendClass == null) {
+ if (other._xtendClass != null)
+ return false;
+ } else if (!_xtendClass.equals(other._xtendClass))
+ return false;
+ if (_editorOpener == null) {
+ if (other._editorOpener != null)
+ return false;
+ } else if (!_editorOpener.equals(other._editorOpener))
+ return false;
+ if (_appendableFactory == null) {
+ if (other._appendableFactory != null)
+ return false;
+ } else if (!_appendableFactory.equals(other._appendableFactory))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ String result = new ToStringHelper().toString(this);
+ return result;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/FeatureCallTargetTypeProvider.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/FeatureCallTargetTypeProvider.java
new file mode 100644
index 0000000..5c17f00
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/FeatureCallTargetTypeProvider.java
@@ -0,0 +1,44 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import com.google.inject.Inject;
+import org.eclipse.xtext.common.types.JvmConstructor;
+import org.eclipse.xtext.common.types.JvmDeclaredType;
+import org.eclipse.xtext.common.types.JvmIdentifiableElement;
+import org.eclipse.xtext.common.types.JvmType;
+import org.eclipse.xtext.common.types.JvmTypeReference;
+import org.eclipse.xtext.xbase.XAbstractFeatureCall;
+import org.eclipse.xtext.xbase.XConstructorCall;
+import org.eclipse.xtext.xbase.XExpression;
+import org.eclipse.xtext.xbase.XMemberFeatureCall;
+import org.eclipse.xtext.xbase.typing.ITypeProvider;
+
+@SuppressWarnings("all")
+public class FeatureCallTargetTypeProvider {
+ @Inject
+ private ITypeProvider _iTypeProvider;
+
+ public JvmType targetType(final XMemberFeatureCall featureCall) {
+ JvmIdentifiableElement _targetFeature = this.targetFeature(featureCall);
+ JvmTypeReference _typeForIdentifiable = _targetFeature==null?(JvmTypeReference)null:this._iTypeProvider.getTypeForIdentifiable(_targetFeature);
+ JvmType _type = _typeForIdentifiable==null?(JvmType)null:_typeForIdentifiable.getType();
+ return _type;
+ }
+
+ private JvmIdentifiableElement targetFeature(final XMemberFeatureCall featureCall) {
+ JvmIdentifiableElement _xblockexpression = null;
+ {
+ final XExpression memberCallTarget = featureCall.getMemberCallTarget();
+ if ((memberCallTarget instanceof XConstructorCall)) {
+ JvmConstructor _constructor = ((XConstructorCall) memberCallTarget).getConstructor();
+ return _constructor==null?(JvmDeclaredType)null:_constructor.getDeclaringType();
+ }
+ boolean _not = (!(memberCallTarget instanceof XAbstractFeatureCall));
+ if (_not) {
+ return null;
+ }
+ JvmIdentifiableElement _feature = ((XAbstractFeatureCall) memberCallTarget).getFeature();
+ _xblockexpression = (_feature);
+ }
+ return _xblockexpression;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/IsUndefinedMethod.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/IsUndefinedMethod.java
new file mode 100644
index 0000000..93b3c49
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/IsUndefinedMethod.java
@@ -0,0 +1,93 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import com.google.inject.Inject;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtend.ide.quickfix.FeatureCallTargetTypeProvider;
+import org.eclipse.xtext.common.types.JvmFormalParameter;
+import org.eclipse.xtext.common.types.JvmIdentifiableElement;
+import org.eclipse.xtext.common.types.JvmOperation;
+import org.eclipse.xtext.common.types.JvmType;
+import org.eclipse.xtext.common.types.JvmTypeReference;
+import org.eclipse.xtext.xbase.XExpression;
+import org.eclipse.xtext.xbase.XMemberFeatureCall;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.typing.ITypeProvider;
+
+@SuppressWarnings("all")
+public class IsUndefinedMethod {
+ @Inject
+ private FeatureCallTargetTypeProvider _featureCallTargetTypeProvider;
+
+ @Inject
+ private ITypeProvider _iTypeProvider;
+
+ public boolean callsUndefinedMethod(final XMemberFeatureCall featureCall) {
+ JvmType _targetType = this._featureCallTargetTypeProvider.targetType(featureCall);
+ boolean _isUnknown = this.isUnknown(_targetType);
+ if (_isUnknown) {
+ return false;
+ }
+ final JvmIdentifiableElement method = featureCall.getFeature();
+ boolean _equals = ObjectExtensions.operator_equals(method, null);
+ if (_equals) {
+ return false;
+ }
+ boolean _eIsProxy = method.eIsProxy();
+ if (_eIsProxy) {
+ return true;
+ }
+ boolean _not = (!(method instanceof JvmOperation));
+ if (_not) {
+ return false;
+ }
+ return this.calls(featureCall, ((JvmOperation) method));
+ }
+
+ private boolean calls(final XMemberFeatureCall featureCall, final JvmOperation operation) {
+ final EList<JvmFormalParameter> left = operation.getParameters();
+ final EList<XExpression> right = featureCall.getMemberCallArguments();
+ int _size = left.size();
+ int _size_1 = right.size();
+ boolean _notEquals = (_size != _size_1);
+ if (_notEquals) {
+ return true;
+ }
+ int i = 0;
+ EList<JvmFormalParameter> _parameters = operation.getParameters();
+ int _size_2 = _parameters.size();
+ boolean _lessThan = (i < _size_2);
+ boolean _while = _lessThan;
+ while (_while) {
+ {
+ JvmFormalParameter _get = left.get(i);
+ JvmTypeReference _parameterType = _get.getParameterType();
+ XExpression _get_1 = right.get(i);
+ JvmTypeReference _type = this._iTypeProvider.getType(_get_1);
+ boolean _notEquals_1 = ObjectExtensions.operator_notEquals(_parameterType, _type);
+ if (_notEquals_1) {
+ return true;
+ }
+ int _plus = (i + 1);
+ i = _plus;
+ }
+ EList<JvmFormalParameter> _parameters_1 = operation.getParameters();
+ int _size_3 = _parameters_1.size();
+ boolean _lessThan_1 = (i < _size_3);
+ _while = _lessThan_1;
+ }
+ return false;
+ }
+
+ private boolean isUnknown(final EObject obj) {
+ boolean _or = false;
+ boolean _equals = ObjectExtensions.operator_equals(obj, null);
+ if (_equals) {
+ _or = true;
+ } else {
+ boolean _eIsProxy = obj.eIsProxy();
+ _or = (_equals || _eIsProxy);
+ }
+ return _or;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/JavaMethodBuilder.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/JavaMethodBuilder.java
new file mode 100644
index 0000000..dbd150d
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/JavaMethodBuilder.java
@@ -0,0 +1,22 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import org.eclipse.xtend.ide.quickfix.XtendMethodBuilder;
+import org.eclipse.xtext.common.types.JvmTypeReference;
+import org.eclipse.xtext.xbase.compiler.IAppendable;
+
+@SuppressWarnings("all")
+public class JavaMethodBuilder extends XtendMethodBuilder {
+ protected StringBuilder defaultReturnStatement() {
+ StringBuilder _defaultReturnStatement = super.defaultReturnStatement();
+ StringBuilder _append = _defaultReturnStatement.append(";");
+ return _append;
+ }
+
+ protected IAppendable addPrefix(final IAppendable appendable) {
+ IAppendable _append = appendable.append("public ");
+ JvmTypeReference _returnType = this.returnType();
+ IAppendable _append_1 = this.append(_append, _returnType);
+ IAppendable _append_2 = _append_1.append(" ");
+ return _append_2;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/MethodBuilderProvider.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/MethodBuilderProvider.java
new file mode 100644
index 0000000..98da77b
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/MethodBuilderProvider.java
@@ -0,0 +1,37 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import org.eclipse.xtend.ide.quickfix.JavaMethodBuilder;
+import org.eclipse.xtend.ide.quickfix.XtendMethodBuilder;
+import org.eclipse.xtext.xbase.XAbstractFeatureCall;
+
+@SuppressWarnings("all")
+public class MethodBuilderProvider {
+ @Inject
+ private Provider<XtendMethodBuilder> xtendMethodBuilderProvider;
+
+ @Inject
+ private Provider<JavaMethodBuilder> javaMethodBuilderProvider;
+
+ public XtendMethodBuilder newXtendMethodBuilder(final String methodName, final XAbstractFeatureCall call) {
+ XtendMethodBuilder _invoke = this.invoke(this.xtendMethodBuilderProvider, methodName, call);
+ return _invoke;
+ }
+
+ public XtendMethodBuilder newJavaMethodBuilder(final String methodName, final XAbstractFeatureCall call) {
+ XtendMethodBuilder _invoke = this.invoke(this.javaMethodBuilderProvider, methodName, call);
+ return _invoke;
+ }
+
+ private XtendMethodBuilder invoke(final Provider<? extends XtendMethodBuilder> provider, final String methodName, final XAbstractFeatureCall call) {
+ XtendMethodBuilder _xblockexpression = null;
+ {
+ final XtendMethodBuilder builder = provider.get();
+ builder.setMethodName(methodName);
+ builder.setFeatureCall(call);
+ _xblockexpression = (builder);
+ }
+ return _xblockexpression;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/NewMethodModificationProvider.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/NewMethodModificationProvider.java
new file mode 100644
index 0000000..7c34d93
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/NewMethodModificationProvider.java
@@ -0,0 +1,93 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import com.google.common.collect.Iterators;
+import com.google.inject.Inject;
+import java.util.Iterator;
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.xtend.core.xtend.XtendClass;
+import org.eclipse.xtend.ide.quickfix.CreateJavaMethod;
+import org.eclipse.xtend.ide.quickfix.CreateXtendMethod;
+import org.eclipse.xtend.ide.quickfix.FeatureCallTargetTypeProvider;
+import org.eclipse.xtend.ide.quickfix.MethodBuilderProvider;
+import org.eclipse.xtend.ide.quickfix.XtendMethodBuilder;
+import org.eclipse.xtext.common.types.JvmGenericType;
+import org.eclipse.xtext.common.types.JvmType;
+import org.eclipse.xtext.common.types.util.jdt.IJavaElementFinder;
+import org.eclipse.xtext.ui.editor.IURIEditorOpener;
+import org.eclipse.xtext.ui.editor.model.edit.IModification;
+import org.eclipse.xtext.xbase.XMemberFeatureCall;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.IteratorExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.ui.contentassist.ReplacingAppendable.Factory;
+
+@SuppressWarnings("all")
+public class NewMethodModificationProvider {
+ @Inject
+ private IURIEditorOpener editorOpener;
+
+ @Inject
+ private Factory apendableFactory;
+
+ @Inject
+ private MethodBuilderProvider methodBuilderProvider;
+
+ @Inject
+ private IJavaElementFinder elementProvider;
+
+ @Inject
+ private FeatureCallTargetTypeProvider _featureCallTargetTypeProvider;
+
+ public IModification createModification(final XMemberFeatureCall call, final String methodName) {
+ final JvmType targetType = this._featureCallTargetTypeProvider.targetType(call);
+ final XtendClass xtendClass = this.xtendClass(targetType);
+ boolean _notEquals = ObjectExtensions.operator_notEquals(xtendClass, null);
+ if (_notEquals) {
+ final XtendMethodBuilder methodBuilder = this.methodBuilderProvider.newXtendMethodBuilder(methodName, call);
+ XtendClass _xtendClass = this.xtendClass(targetType);
+ CreateXtendMethod _createXtendMethod = new CreateXtendMethod(methodBuilder, _xtendClass, this.editorOpener, this.apendableFactory);
+ return _createXtendMethod;
+ } else {
+ final XtendMethodBuilder methodBuilder_1 = this.methodBuilderProvider.newJavaMethodBuilder(methodName, call);
+ boolean _and = false;
+ if (!(targetType instanceof JvmGenericType)) {
+ _and = false;
+ } else {
+ boolean _isInterface = ((JvmGenericType) targetType).isInterface();
+ _and = ((targetType instanceof JvmGenericType) && _isInterface);
+ }
+ methodBuilder_1.setIsInterface(_and);
+ final IJavaElement javaElement = this.elementProvider.findElementFor(targetType);
+ CreateJavaMethod _createJavaMethod = new CreateJavaMethod(methodBuilder_1, ((IType) javaElement));
+ return _createJavaMethod;
+ }
+ }
+
+ private XtendClass xtendClass(final JvmType type) {
+ XtendClass _xblockexpression = null;
+ {
+ boolean _equals = ObjectExtensions.operator_equals(type, null);
+ if (_equals) {
+ return null;
+ }
+ Resource _eResource = type.eResource();
+ TreeIterator<EObject> _allContents = _eResource.getAllContents();
+ Iterator<XtendClass> _filter = Iterators.<XtendClass>filter(_allContents, XtendClass.class);
+ final Function1<XtendClass,Boolean> _function = new Function1<XtendClass,Boolean>() {
+ public Boolean apply(final XtendClass it) {
+ String _name = it.getName();
+ String _simpleName = type.getSimpleName();
+ boolean _equals = ObjectExtensions.operator_equals(_name, _simpleName);
+ return Boolean.valueOf(_equals);
+ }
+ };
+ XtendClass _findFirst = IteratorExtensions.<XtendClass>findFirst(_filter, _function);
+ _xblockexpression = (_findFirst);
+ }
+ return _xblockexpression;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/UndefinedMethodFix.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/UndefinedMethodFix.java
new file mode 100644
index 0000000..e18d69c
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/UndefinedMethodFix.java
@@ -0,0 +1,58 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import com.google.inject.Inject;
+import java.util.List;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.xtend.ide.quickfix.CallsReadOnlyType;
+import org.eclipse.xtend.ide.quickfix.IsUndefinedMethod;
+import org.eclipse.xtend.ide.quickfix.NewMethodModificationProvider;
+import org.eclipse.xtext.nodemodel.INode;
+import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
+import org.eclipse.xtext.ui.editor.model.edit.IModification;
+import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor;
+import org.eclipse.xtext.validation.Issue;
+import org.eclipse.xtext.xbase.XMemberFeatureCall;
+import org.eclipse.xtext.xbase.XbasePackage.Literals;
+
+@SuppressWarnings("all")
+public class UndefinedMethodFix {
+ @Inject
+ private NewMethodModificationProvider _newMethodModificationProvider;
+
+ @Inject
+ private IsUndefinedMethod _isUndefinedMethod;
+
+ @Inject
+ private CallsReadOnlyType _callsReadOnlyType;
+
+ public void apply(final Issue issue, final IssueResolutionAcceptor issueResolutionAcceptor, final XMemberFeatureCall featureCall) {
+ final String issueString = this.textForFeature(featureCall, Literals.XABSTRACT_FEATURE_CALL__FEATURE);
+ boolean _callsUndefinedMethod = this._isUndefinedMethod.callsUndefinedMethod(featureCall);
+ boolean _not = (!_callsUndefinedMethod);
+ if (_not) {
+ return;
+ }
+ boolean _receiverIsReadOnly = this._callsReadOnlyType.receiverIsReadOnly(featureCall);
+ if (_receiverIsReadOnly) {
+ return;
+ }
+ String _plus = ("create method \'" + issueString);
+ String _plus_1 = (_plus + "\'");
+ IModification _createModification = this._newMethodModificationProvider.createModification(featureCall, issueString);
+ issueResolutionAcceptor.accept(issue, _plus_1, "",
+ "fix_public_function.png", _createModification);
+ }
+
+ private String textForFeature(final EObject eObject, final EStructuralFeature feature) {
+ final List<INode> nodes = NodeModelUtils.findNodesForFeature(eObject, feature);
+ StringBuilder _stringBuilder = new StringBuilder();
+ final StringBuilder sb = _stringBuilder;
+ for (final INode node : nodes) {
+ String _text = node.getText();
+ sb.append(_text);
+ }
+ String _string = sb.toString();
+ return _string.trim();
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/VariableNameAcceptor.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/VariableNameAcceptor.java
new file mode 100644
index 0000000..f5f562f
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/VariableNameAcceptor.java
@@ -0,0 +1,69 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Set;
+import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.xtext.common.types.xtext.ui.JdtVariableCompletions.CompletionDataAcceptor;
+import org.eclipse.xtext.xbase.lib.CollectionLiterals;
+import org.eclipse.xtext.xbase.lib.Functions.Function0;
+import org.eclipse.xtext.xbase.lib.Functions.Function2;
+
+@SuppressWarnings("all")
+public class VariableNameAcceptor implements CompletionDataAcceptor {
+ private final Set<String> notallowed;
+
+ private final Set<String> variableNames = new Function0<Set<String>>() {
+ public Set<String> apply() {
+ HashSet<String> _newHashSet = CollectionLiterals.<String>newHashSet();
+ return _newHashSet;
+ }
+ }.apply();
+
+ public VariableNameAcceptor(final Set<String> notallowed) {
+ this.notallowed = notallowed;
+ }
+
+ public void accept(final String replaceText, final StyledString label, final Image img) {
+ this.variableNames.add(replaceText);
+ this.notallowed.add(replaceText);
+ }
+
+ public String getVariableName() {
+ final ArrayList<String> candidates = Lists.<String>newArrayList(this.variableNames);
+ final Function2<String,String,Integer> _function = new Function2<String,String,Integer>() {
+ public Integer apply(final String left, final String right) {
+ int _length = left.length();
+ int _length_1 = right.length();
+ boolean _lessThan = (_length < _length_1);
+ if (_lessThan) {
+ return (-1);
+ } else {
+ int _length_2 = left.length();
+ int _length_3 = right.length();
+ boolean _greaterThan = (_length_2 > _length_3);
+ if (_greaterThan) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ }
+ };
+ Collections.<String>sort(candidates, new Comparator<String>() {
+ public int compare(String o1,String o2) {
+ return _function.apply(o1,o2);
+ }
+ });
+ int _size = candidates.size();
+ boolean _greaterThan = (_size > 0);
+ if (_greaterThan) {
+ return candidates.get(0);
+ }
+ return "";
+ }
+}
diff --git a/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/XtendMethodBuilder.java b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/XtendMethodBuilder.java
new file mode 100644
index 0000000..c852873
--- /dev/null
+++ b/plugins/org.eclipse.xtend.ide/xtend-gen/org/eclipse/xtend/ide/quickfix/XtendMethodBuilder.java
@@ -0,0 +1,255 @@
+package org.eclipse.xtend.ide.quickfix;
+
+import com.google.common.base.Objects;
+import com.google.inject.Inject;
+import java.util.HashSet;
+import java.util.Iterator;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.xtend.ide.quickfix.ExpectedTypeResolver;
+import org.eclipse.xtend.ide.quickfix.VariableNameAcceptor;
+import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtext.common.types.JvmPrimitiveType;
+import org.eclipse.xtext.common.types.JvmType;
+import org.eclipse.xtext.common.types.JvmTypeReference;
+import org.eclipse.xtext.common.types.util.Primitives;
+import org.eclipse.xtext.common.types.util.Primitives.Primitive;
+import org.eclipse.xtext.common.types.xtext.ui.JdtVariableCompletions;
+import org.eclipse.xtext.common.types.xtext.ui.JdtVariableCompletions.VariableType;
+import org.eclipse.xtext.xbase.XAbstractFeatureCall;
+import org.eclipse.xtext.xbase.XExpression;
+import org.eclipse.xtext.xbase.XMemberFeatureCall;
+import org.eclipse.xtext.xbase.compiler.IAppendable;
+import org.eclipse.xtext.xbase.compiler.TypeReferenceSerializer;
+import org.eclipse.xtext.xbase.lib.CollectionLiterals;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.eclipse.xtext.xbase.typing.ITypeProvider;
+
+@SuppressWarnings("all")
+public class XtendMethodBuilder {
+ @Inject
+ private ITypeProvider _iTypeProvider;
+
+ @Inject
+ private JdtVariableCompletions _jdtVariableCompletions;
+
+ @Inject
+ private Primitives _primitives;
+
+ @Inject
+ private ExpectedTypeResolver _expectedTypeResolver;
+
+ @Inject
+ private TypeReferenceSerializer _typeReferenceSerializer;
+
+ private String _methodName;
+
+ public String getMethodName() {
+ return this._methodName;
+ }
+
+ public void setMethodName(final String methodName) {
+ this._methodName = methodName;
+ }
+
+ private boolean _isInterface;
+
+ public boolean isIsInterface() {
+ return this._isInterface;
+ }
+
+ public void setIsInterface(final boolean isInterface) {
+ this._isInterface = isInterface;
+ }
+
+ private XAbstractFeatureCall _featureCall;
+
+ public XAbstractFeatureCall getFeatureCall() {
+ return this._featureCall;
+ }
+
+ public void setFeatureCall(final XAbstractFeatureCall featureCall) {
+ this._featureCall = featureCall;
+ }
+
+ public IAppendable build(final IAppendable appendable) {
+ final Procedure1<IAppendable> _function = new Procedure1<IAppendable>() {
+ public void apply(final IAppendable it) {
+ XtendMethodBuilder.this.addPrefix(it);
+ XtendMethodBuilder.this.addName(it);
+ XtendMethodBuilder.this.addArguments(it);
+ XtendMethodBuilder.this.addBody(it);
+ }
+ };
+ IAppendable _doubleArrow = ObjectExtensions.<IAppendable>operator_doubleArrow(appendable, _function);
+ return _doubleArrow;
+ }
+
+ protected IAppendable addName(final IAppendable appendable) {
+ String _methodName = this.getMethodName();
+ IAppendable _append = appendable.append(_methodName);
+ return _append;
+ }
+
+ protected IAppendable addPrefix(final IAppendable appendable) {
+ IAppendable _append = appendable.append("def ");
+ return _append;
+ }
+
+ protected IAppendable addBody(final IAppendable appendable) {
+ IAppendable _xblockexpression = null;
+ {
+ boolean _isIsInterface = this.isIsInterface();
+ if (_isIsInterface) {
+ return appendable.append(";");
+ }
+ StringConcatenation _builder = new StringConcatenation();
+ _builder.append("{");
+ _builder.newLine();
+ _builder.append("\t");
+ Object _returnStatement = this.returnStatement();
+ _builder.append(_returnStatement, " ");
+ _builder.newLineIfNotEmpty();
+ _builder.append("}");
+ _builder.newLine();
+ IAppendable _append = appendable.append(_builder);
+ _xblockexpression = (_append);
+ }
+ return _xblockexpression;
+ }
+
+ protected Object returnStatement() {
+ boolean _or = false;
+ XAbstractFeatureCall _featureCall = this.getFeatureCall();
+ boolean _equals = ObjectExtensions.operator_equals(_featureCall, null);
+ if (_equals) {
+ _or = true;
+ } else {
+ XAbstractFeatureCall _featureCall_1 = this.getFeatureCall();
+ boolean _isVoid = this.isVoid(_featureCall_1);
+ _or = (_equals || _isVoid);
+ }
+ if (_or) {
+ return "";
+ } else {
+ return this.defaultReturnStatement();
+ }
+ }
+
+ protected StringBuilder defaultReturnStatement() {
+ final JvmTypeReference expectedType = this.returnType();
+ StringBuilder _stringBuilder = new StringBuilder("return ");
+ final StringBuilder result = _stringBuilder;
+ boolean _isPrimitive = this._primitives.isPrimitive(expectedType);
+ if (_isPrimitive) {
+ JvmType _type = expectedType.getType();
+ final Primitive primitiveKind = this._primitives.primitiveKind(((JvmPrimitiveType) _type));
+ boolean _matched = false;
+ if (!_matched) {
+ if (Objects.equal(primitiveKind,Primitive.Boolean)) {
+ _matched=true;
+ result.append("false");
+ }
+ }
+ if (!_matched) {
+ result.append("0");
+ }
+ } else {
+ return result.append("null");
+ }
+ return result;
+ }
+
+ private boolean isVoid(final XAbstractFeatureCall featureCall) {
+ final JvmTypeReference returnType = this.returnType();
+ boolean _or = false;
+ boolean _equals = ObjectExtensions.operator_equals(returnType, null);
+ if (_equals) {
+ _or = true;
+ } else {
+ String _simpleName = returnType.getSimpleName();
+ boolean _equals_1 = ObjectExtensions.operator_equals(_simpleName, "void");
+ _or = (_equals || _equals_1);
+ }
+ return _or;
+ }
+
+ protected JvmTypeReference returnType() {
+ XAbstractFeatureCall _featureCall = this.getFeatureCall();
+ JvmTypeReference _expectedType = this._iTypeProvider.getExpectedType(_featureCall);
+ return _expectedType;
+ }
+
+ protected IAppendable addArguments(final IAppendable appendable) {
+ IAppendable _xblockexpression = null;
+ {
+ XAbstractFeatureCall _featureCall = this.getFeatureCall();
+ boolean _equals = ObjectExtensions.operator_equals(_featureCall, null);
+ if (_equals) {
+ return appendable.append("()");
+ }
+ Iterator<XExpression> _xifexpression = null;
+ XAbstractFeatureCall _featureCall_1 = this.getFeatureCall();
+ if ((_featureCall_1 instanceof XMemberFeatureCall)) {
+ XAbstractFeatureCall _featureCall_2 = this.getFeatureCall();
+ EList<XExpression> _memberCallArguments = ((XMemberFeatureCall) _featureCall_2).getMemberCallArguments();
+ Iterator<XExpression> _iterator = _memberCallArguments.iterator();
+ _xifexpression = _iterator;
+ } else {
+ XAbstractFeatureCall _featureCall_3 = this.getFeatureCall();
+ EList<XExpression> _explicitArguments = _featureCall_3.getExplicitArguments();
+ Iterator<XExpression> _iterator_1 = _explicitArguments.iterator();
+ _xifexpression = _iterator_1;
+ }
+ Iterator<XExpression> iterator = _xifexpression;
+ final HashSet<String> notallowed = CollectionLiterals.<String>newHashSet();
+ appendable.append("(");
+ boolean _hasNext = iterator.hasNext();
+ boolean _while = _hasNext;
+ while (_while) {
+ {
+ final XExpression expression = iterator.next();
+ final JvmTypeReference typeRef = this._iTypeProvider.getType(expression);
+ boolean _notEquals = ObjectExtensions.operator_notEquals(typeRef, null);
+ if (_notEquals) {
+ this.append(appendable, typeRef);
+ appendable.append(" ");
+ VariableNameAcceptor _variableNameAcceptor = new VariableNameAcceptor(notallowed);
+ final VariableNameAcceptor acceptor = _variableNameAcceptor;
+ String _identifier = typeRef.getIdentifier();
+ XAbstractFeatureCall _featureCall_4 = this.getFeatureCall();
+ this._jdtVariableCompletions.getVariableProposals(_identifier, _featureCall_4, VariableType.PARAMETER, notallowed, acceptor);
+ String _variableName = acceptor.getVariableName();
+ appendable.append(_variableName);
+ }
+ boolean _hasNext_1 = iterator.hasNext();
+ if (_hasNext_1) {
+ appendable.append(", ");
+ }
+ }
+ boolean _hasNext_1 = iterator.hasNext();
+ _while = _hasNext_1;
+ }
+ IAppendable _append = appendable.append(")");
+ _xblockexpression = (_append);
+ }
+ return _xblockexpression;
+ }
+
+ protected IAppendable append(final IAppendable appendable, final JvmTypeReference typeRef) {
+ IAppendable _xblockexpression = null;
+ {
+ boolean _equals = ObjectExtensions.operator_equals(typeRef, null);
+ if (_equals) {
+ appendable.append("void");
+ } else {
+ XAbstractFeatureCall _featureCall = this.getFeatureCall();
+ final JvmTypeReference resolvedExpectedType = this._expectedTypeResolver.resolveExpectedType(_featureCall, typeRef);
+ XAbstractFeatureCall _featureCall_1 = this.getFeatureCall();
+ this._typeReferenceSerializer.serialize(resolvedExpectedType, _featureCall_1, appendable);
+ }
+ _xblockexpression = (appendable);
+ }
+ return _xblockexpression;
+ }
+}