Skip to content

Commit

Permalink
Support creating record accessor for completion
Browse files Browse the repository at this point in the history
  • Loading branch information
jjohnstn committed Mar 7, 2024
1 parent 33a8fa9 commit ec3cecd
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ private JavaTextMessages() {
public static String GetterSetterCompletionProposal_setter_label;
public static String MethodCompletionProposal_constructor_label;
public static String MethodCompletionProposal_method_label;
public static String RecordAccessorCompletionProposal_accessor_label;

static {
NLS.initializeMessages(BUNDLE_NAME, JavaTextMessages.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ GetterSetterCompletionProposal_getter_label=Getter for ''{0}''
GetterSetterCompletionProposal_setter_label=Setter for ''{0}''
MethodCompletionProposal_constructor_label=Constructor
MethodCompletionProposal_method_label=Method stub
RecordAccessorCompletionProposal_accessor_label=Record accessor stub

ContentAssistProcessor_computing_proposals=Computing completion proposals
ContentAssistProcessor_collecting_proposals=Collecting proposals
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2018 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -28,6 +28,7 @@
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextUtilities;

import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.Signature;
Expand Down Expand Up @@ -58,16 +59,18 @@ public class MethodDeclarationCompletionProposal extends JavaTypeCompletionPropo

public static void evaluateProposals(IType type, String prefix, int offset, int length, int relevance, Set<String> suggestedMethods, Collection<IJavaCompletionProposal> result) throws CoreException {
IMethod[] methods= type.getMethods();
IField[] components= type.getRecordComponents();
if (!type.isInterface()) {
String constructorName= type.getElementName();
if (constructorName.length() > 0 && constructorName.startsWith(prefix) && !hasMethod(methods, constructorName) && suggestedMethods.add(constructorName)) {
result.add(new MethodDeclarationCompletionProposal(type, constructorName, null, offset, length, relevance + 500));
}
}

if (prefix.length() > 0 && !"main".equals(prefix) && !hasMethod(methods, prefix) && suggestedMethods.add(prefix)) { //$NON-NLS-1$
if (!JavaConventionsUtil.validateMethodName(prefix, type).matches(IStatus.ERROR))
if (prefix.length() > 0 && !"main".equals(prefix) && !hasMethod(methods, prefix) && !hasRecordComponent(components, prefix) && suggestedMethods.add(prefix)) { //$NON-NLS-1$
if (!JavaConventionsUtil.validateMethodName(prefix, type).matches(IStatus.ERROR)) {
result.add(new MethodDeclarationCompletionProposal(type, prefix, Signature.SIG_VOID, offset, length, relevance));
}
}
}

Expand All @@ -80,6 +83,15 @@ private static boolean hasMethod(IMethod[] methods, String name) {
return false;
}

private static boolean hasRecordComponent(IField[] components, String name) {
for (IField curr : components) {
if (curr.getElementName().equals(name)) {
return true;
}
}
return false;
}

private final IType fType;
private final String fReturnTypeSig;
private final String fMethodName;
Expand Down Expand Up @@ -140,7 +152,9 @@ protected boolean updateReplacementString(IDocument document, char trigger, int
}
}
if (fReturnTypeSig != null) {
if (!isInterface) {
if (fType.isRecord()) {
buf.append("public "); //$NON-NLS-1$
} else if (!isInterface) {
buf.append("private "); //$NON-NLS-1$
}
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/*******************************************************************************
* Copyright (c) 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.ui.text.java;

import java.util.Collection;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;

import org.eclipse.jface.viewers.StyledString;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextUtilities;

import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.manipulation.CodeGeneration;

import org.eclipse.jdt.internal.core.manipulation.util.Strings;
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.jdt.internal.corext.util.JavaConventionsUtil;

import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;

import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
import org.eclipse.jdt.internal.ui.preferences.formatter.FormatterProfileManager;


/**
* Record accessor declaration proposal.
*/
public class RecordAccessorCompletionProposal extends JavaTypeCompletionProposal {


public static void evaluateProposals(IType type, String prefix, int offset, int length, int relevance, Set<String> suggestedMethods, Collection<IJavaCompletionProposal> result) throws CoreException {
IMethod[] methods= type.getMethods();
if (!type.isRecord()) {
return;
}
if (prefix.length() > 0 && !hasMethod(methods, prefix)) {
if (!JavaConventionsUtil.validateMethodName(prefix, type).matches(IStatus.ERROR)) {
IField[] fields= type.getRecordComponents();
for (IField field : fields) {
if (field.getElementName().startsWith(prefix)) {
if (suggestedMethods.add(field.getElementName())) {
result.add(new RecordAccessorCompletionProposal(type, field.getElementName(), field.getTypeSignature(), offset, length, relevance + 1));
}
}
}
}
}
}

private static boolean hasMethod(IMethod[] methods, String name) {
for (IMethod curr : methods) {
if (curr.getElementName().equals(name) && curr.getParameterTypes().length == 0) {
return true;
}
}
return false;
}

private final IType fType;
private final String fReturnTypeSig;
private final String fMethodName;

public RecordAccessorCompletionProposal(IType type, String methodName, String returnTypeSig, int start, int length, int relevance) {
super("", type.getCompilationUnit(), start, length, null, getDisplayName(methodName, returnTypeSig), relevance); //$NON-NLS-1$
Assert.isNotNull(type);
Assert.isNotNull(methodName);
Assert.isNotNull(returnTypeSig);

fType= type;
fMethodName= methodName;
fReturnTypeSig= returnTypeSig;

setImage(JavaPluginImages.get(JavaPluginImages.IMG_MISC_PUBLIC));
}

private static StyledString getDisplayName(String methodName, String returnTypeSig) {
StyledString buf= new StyledString();
buf.append(methodName);
buf.append('(');
buf.append(')');
buf.append(" : "); //$NON-NLS-1$
buf.append(Signature.toString(returnTypeSig));
buf.append(" - ", StyledString.QUALIFIER_STYLER); //$NON-NLS-1$
buf.append(JavaTextMessages.RecordAccessorCompletionProposal_accessor_label, StyledString.QUALIFIER_STYLER);
return buf;
}

@Override
protected boolean updateReplacementString(IDocument document, char trigger, int offset, ImportRewrite impRewrite) throws CoreException, BadLocationException {

CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(fType.getJavaProject());
boolean addComments= settings.createComments;

String[] empty= new String[0];
String lineDelim= TextUtilities.getDefaultLineDelimiter(document);
String declTypeName= fType.getTypeQualifiedName('.');

StringBuilder buf= new StringBuilder();
if (addComments) {
String comment= CodeGeneration.getMethodComment(fType.getCompilationUnit(), declTypeName, fMethodName, empty, empty, fReturnTypeSig, empty, null, lineDelim);
if (comment != null) {
buf.append(comment);
buf.append(lineDelim);
}
}
buf.append("public "); //$NON-NLS-1$

if (fReturnTypeSig != null) {
buf.append(Signature.toString(fReturnTypeSig));
}
buf.append(' ');
buf.append(fMethodName);
buf.append("() {"); //$NON-NLS-1$
buf.append(lineDelim);

String body= CodeGeneration.getMethodBodyContent(fType.getCompilationUnit(), declTypeName, fMethodName, fReturnTypeSig == null, "", lineDelim); //$NON-NLS-1$
if (body != null) {
buf.append(body);
buf.append(lineDelim);
}
buf.append("}"); //$NON-NLS-1$
buf.append(lineDelim);
String stub= buf.toString();

// use the code formatter
IRegion region= document.getLineInformationOfOffset(getReplacementOffset());
int lineStart= region.getOffset();
int indent= Strings.computeIndentUnits(document.get(lineStart, getReplacementOffset() - lineStart), settings.tabWidth, settings.indentWidth);

String replacement= CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, stub, indent, lineDelim, FormatterProfileManager.getProjectSettings(fType.getJavaProject()));

if (replacement.endsWith(lineDelim)) {
replacement= replacement.substring(0, replacement.length() - lineDelim.length());
}

setReplacementString(Strings.trimLeadingTabsAndSpaces(replacement));
return true;
}

@Override
public CharSequence getPrefixCompletionText(IDocument document, int completionOffset) {
return ""; // don't let method stub proposals complete incrementally //$NON-NLS-1$
}

/*
* @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension4#isAutoInsertable()
*/
@Override
public boolean isAutoInsertable() {
return false;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2023 IBM Corporation and others.
* Copyright (c) 2000, 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -18,11 +18,19 @@
import java.util.List;
import java.util.Set;

import org.eclipse.swt.graphics.Image;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.StyledString;

import org.eclipse.jface.text.contentassist.IContextInformation;

import org.eclipse.jdt.core.CompletionContext;
import org.eclipse.jdt.core.CompletionProposal;
import org.eclipse.jdt.core.CompletionRequestor;
Expand All @@ -35,9 +43,11 @@
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.formatter.CodeFormatter;

import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.jdt.internal.corext.util.CollectionsUtil;
import org.eclipse.jdt.internal.corext.util.TypeFilter;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.preferences.formatter.FormatterProfileManager;
import org.eclipse.jdt.internal.ui.text.java.AnnotationAtttributeProposalInfo;
Expand All @@ -57,14 +67,11 @@
import org.eclipse.jdt.internal.ui.text.java.MethodProposalInfo;
import org.eclipse.jdt.internal.ui.text.java.OverrideCompletionProposal;
import org.eclipse.jdt.internal.ui.text.java.ProposalContextInformation;
import org.eclipse.jdt.internal.ui.text.java.RecordAccessorCompletionProposal;
import org.eclipse.jdt.internal.ui.text.java.RelevanceComputer;
import org.eclipse.jdt.internal.ui.text.javadoc.JavadocInlineTagCompletionProposal;
import org.eclipse.jdt.internal.ui.text.javadoc.JavadocLinkTypeCompletionProposal;
import org.eclipse.jdt.internal.ui.viewsupport.ImageDescriptorRegistry;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.graphics.Image;

/**
* Java UI implementation of <code>CompletionRequestor</code>. Produces
Expand Down Expand Up @@ -677,6 +684,7 @@ private void acceptPotentialMethodDeclaration(CompletionProposal proposal) {
int relevance= computeRelevance(proposal);

GetterSetterCompletionProposal.evaluateProposals(type, prefix, completionStart, completionEnd - completionStart, relevance + 2, fSuggestedMethodNames, fJavaProposals);
RecordAccessorCompletionProposal.evaluateProposals(type, prefix, completionStart, completionEnd - completionStart, relevance + 1, fSuggestedMethodNames, fJavaProposals);
MethodDeclarationCompletionProposal.evaluateProposals(type, prefix, completionStart, completionEnd - completionStart, relevance, fSuggestedMethodNames, fJavaProposals);
}
} catch (CoreException e) {
Expand Down

0 comments on commit ec3cecd

Please sign in to comment.