Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Field Name Recommendation Based on Program-Specific Naming Conventions #825

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ private CorrectionMessages() {
public static String QuickAssistProcessor_name_extension_from_interface;
public static String QuickAssistProcessor_convert_constant_name;
public static String QuickAssistProcessor_convert_constant_name_description;
public static String QuickAssistProcessor_convert_project_name;
public static String QuickAssistProcessor_convert_project_name_description;
public static String SerialVersionHashOperation_computing_id;
public static String SerialVersionHashOperation_error_classnotfound;
public static String SerialVersionHashOperation_save_caption;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,8 @@ QuickAssistProcessor_name_extension_from_interface={0}Extension

QuickAssistProcessor_convert_constant_name=Rename to follow constant naming convention
QuickAssistProcessor_convert_constant_name_description=Rename the field {0} to {1}
QuickAssistProcessor_convert_project_name=Rename to follow project naming convention
QuickAssistProcessor_convert_project_name_description=Rename the field {0} to {1}
QuickAssistProcessor_unwrap_ifstatement=Remove surrounding 'if' statement
QuickAssistProcessor_unwrap_whilestatement=Remove surrounding 'while' statement
QuickAssistProcessor_unwrap_forstatement=Remove surrounding 'for' statement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ public interface IProposalRelevance {
int CONVERT_TO_ANONYMOUS_CLASS_CREATION= 2;
int CONVERT_TO_SWITCH_EXPRESSION= 2;
int FIELD_NAMING_CONVENTION= 2;
int PROJECT_NAMING_CONVENTION= 1;
int JOIN_VARIABLE_DECLARATION= 1;
int INVERT_EQUALS= 1;
int CONVERT_TO_ITERATOR_FOR_LOOP= 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@
import org.eclipse.jdt.internal.ui.text.correction.proposals.AddStaticFavoriteProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.AssignToVariableAssistProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ConvertFieldNamingConventionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ConvertProjectNamingConventionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.FixCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.GenerateForLoopAssistProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedCorrectionProposal;
Expand Down Expand Up @@ -283,8 +284,12 @@ public class QuickAssistProcessor implements IQuickAssistProcessor {

public static final String FIELD_NAMING_CONVENTION_ID= "org.eclipse.jdt.ui.correction.convertToConstantNamingConvention.assist"; //$NON-NLS-1$

public static final String CONVERT_To_PROJECT_NAMING_CONVENTION_ID= "org.eclipse.jdt.ui.correction.convertToProjectNamingConvention.assist"; //$NON-NLS-1$

public static final Pattern FIELD_NAMING_PATTERN= Pattern.compile("^[A-Z0-9]+(_[A-Z0-9]+)*$"); //$NON-NLS-1$

public static final Pattern PROJECT_NAMING_PATTERN= Pattern.compile("([a-z]+|[A-Z][a-z]*|\\d+|_+)"); //$NON-NLS-1$

public QuickAssistProcessor() {
super();
}
Expand Down Expand Up @@ -323,6 +328,7 @@ public boolean hasAssists(IInvocationContext context) throws CoreException {
|| getExtractMethodFromLambdaProposal(context, coveringNode, false, null)
|| getInlineLocalProposal(context, coveringNode, null)
|| getConvertFieldNamingConventionProposal(context, coveringNode, null)
|| getConvertProjectNamingConvention(context, coveringNode, null)
|| getConvertLocalToFieldProposal(context, coveringNode, null)
|| getConvertAnonymousToNestedProposal(context, coveringNode, null)
|| getConvertAnonymousClassCreationsToLambdaProposals(context, coveringNode, null)
Expand Down Expand Up @@ -399,6 +405,7 @@ public IJavaCompletionProposal[] getAssists(IInvocationContext context, IProblem
getExtractMethodFromLambdaProposal(context, coveringNode, problemsAtLocation, resultingCollections);
getInlineLocalProposal(context, coveringNode, resultingCollections);
getConvertFieldNamingConventionProposal(context, coveringNode, resultingCollections);
getConvertProjectNamingConvention(context, coveringNode, resultingCollections);
getConvertLocalToFieldProposal(context, coveringNode, resultingCollections);
getConvertAnonymousToNestedProposal(context, coveringNode, resultingCollections);
getConvertAnonymousClassCreationsToLambdaProposals(context, coveringNode, resultingCollections);
Expand Down Expand Up @@ -4660,6 +4667,131 @@ public static String convertToConstantName(String identifier) {
}
return constantNaming.toString().replaceAll("_{2,}", "_"); //$NON-NLS-1$ //$NON-NLS-2$
}
private boolean getConvertProjectNamingConvention(IInvocationContext context, ASTNode coveringNode, ArrayList<ICommandAccess> resultingCollections) {
if (!(coveringNode instanceof SimpleName)) {
return false;
}
SimpleName simpleName= (SimpleName) coveringNode;
String selectedField= simpleName.toString();
int offset= coveringNode.getStartPosition();
if (simpleName.getAST().apiLevel() >= ASTHelper.JLS10 && simpleName.isVar()) {
return false;
}
IEditorPart editor= ((AssistContext) context).getEditor();
if (!(editor instanceof JavaEditor))
return false;

if (!(simpleName.resolveBinding() instanceof IVariableBinding binding) || !binding.isField()) {
return false;
}

CompilationUnit cu= context.getASTRoot();
VariableDeclarationFragment vdf= (VariableDeclarationFragment) ASTNodes.findDeclaration(binding, cu);
if (vdf == null) {
return false;
}

FieldDeclaration fd= (FieldDeclaration) vdf.getParent();
if (fd == null) {
return false;
}

AbstractTypeDeclaration typeDecl= (AbstractTypeDeclaration) fd.getParent();
if (typeDecl == null) {
return false;
}

FieldDeclarationChecker fdChecker= new FieldDeclarationChecker();
typeDecl.accept(fdChecker);

List<String> fieldNames= fdChecker.getFieldDeclarationList();
if (fieldNames.size() < 3) {
return false;
}

List<String> namePrefix= new ArrayList<>();
for (int i= 0; i < fieldNames.size(); i++) {
namePrefix.add(splitField(fieldNames.get(i)).get(0));
}

String firstField= findMostFrequentElement(namePrefix);
List<String> selectField= splitField(selectedField);
if (firstField == null || selectField.contains(firstField)) {
return false;
}

selectField.add(0, firstField);
String newName= joinToCamelCase(selectField);
if (fdChecker.getFieldDeclarationList().contains(newName)) {
return false;
}

if (resultingCollections == null) {
return true;
}

IField iField= (IField) binding.getJavaElement();
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_RENAME);
ConvertProjectNamingConventionProposal proposal= new ConvertProjectNamingConventionProposal(newName, offset, offset, image, iField);
proposal.setCommandId(CONVERT_To_PROJECT_NAMING_CONVENTION_ID);
resultingCollections.add(proposal);

return true;
}

public static List<String> splitField(String input) {
List<String> words= new ArrayList<>();
Pattern pattern= PROJECT_NAMING_PATTERN;
Matcher matcher= pattern.matcher(input);
while (matcher.find()) {
String word= matcher.group();
words.add(word);
}
return words;
}

public static String joinToCamelCase(List<String> elements) {
if (elements == null || elements.isEmpty()) {
return null;
}
StringBuilder result= new StringBuilder();
result.append(elements.get(0));
String camelCaseElement= null;
for (int i= 1; i < elements.size(); i++) {
String element= elements.get(i);
if (i - 1 >= 0 && elements.get(i - 1).equals("_")) { //$NON-NLS-1$
camelCaseElement= element;
} else {
camelCaseElement= element.substring(0, 1).toUpperCase() + element.substring(1).toLowerCase();
}
result.append(camelCaseElement);
}
return result.toString();
}

@SuppressWarnings("boxing")
public static String findMostFrequentElement(List<String> list) {
if (list.isEmpty()) {
return null;
}
Map<String, Integer> elementCountMap= new HashMap<>();
for (String element : list) {
elementCountMap.put(element, elementCountMap.getOrDefault(element, 0) + 1);
}
String mostFrequentElement= null;
int maxCount= 0;
for (Map.Entry<String, Integer> entry : elementCountMap.entrySet()) {
if (entry.getValue() > maxCount) {
mostFrequentElement= entry.getKey();
maxCount= entry.getValue();
}
}
if (maxCount >= (list.size()/2 -1)) {
return mostFrequentElement;
} else {
return null;
}
}
}

final class FieldDeclarationChecker extends ASTVisitor {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package org.eclipse.jdt.internal.ui.text.correction.proposals;

import java.text.MessageFormat;

import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;

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

import org.eclipse.ltk.core.refactoring.CheckConditionsOperation;
import org.eclipse.ltk.core.refactoring.PerformRefactoringOperation;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring;

import org.eclipse.jdt.core.IField;

import org.eclipse.jdt.internal.corext.refactoring.rename.RenameFieldProcessor;

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

import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages;
import org.eclipse.jdt.internal.ui.text.correction.IProposalRelevance;

public class ConvertProjectNamingConventionProposal implements IJavaCompletionProposal, ICommandAccess {
private String replacement;

private int offset;

private int cursorPosition;

private int fRelevance;

private String fCommandId;

private Image image;

private IField fSelectedField;

public ConvertProjectNamingConventionProposal(String replacement, int offset, int cursorPosition, Image image, IField selectedField) {
this.replacement= replacement;
this.offset= offset;
this.cursorPosition= cursorPosition;
this.fRelevance= IProposalRelevance.PROJECT_NAMING_CONVENTION;
this.image= image;
this.fSelectedField= selectedField;
}

@Override
public void apply(IDocument document) {
try {
RenameFieldProcessor processor= new RenameFieldProcessor(fSelectedField);
processor.setNewElementName(replacement);
processor.setUpdateReferences(true);
processor.setRenameSetter(true);
processor.setRenameGetter(true);
processor.setUpdateTextualMatches(true);
RenameRefactoring refactoring= new RenameRefactoring(processor);
RefactoringStatus status;
status= refactoring.checkAllConditions(new NullProgressMonitor());
if (status.isOK()) {
PerformRefactoringOperation operation= new PerformRefactoringOperation(refactoring, CheckConditionsOperation.ALL_CONDITIONS);
operation.run(new NullProgressMonitor());
}
} catch (OperationCanceledException e) {
e.printStackTrace();
} catch (CoreException e) {
e.printStackTrace();
}
}

@Override
public Point getSelection(IDocument document) {
return new Point(offset + cursorPosition, 0);
}

@Override
public String getAdditionalProposalInfo() {
return MessageFormat.format(CorrectionMessages.QuickAssistProcessor_convert_project_name_description, fSelectedField.getElementName(), replacement);
}

@Override
public String getDisplayString() {
return CorrectionMessages.QuickAssistProcessor_convert_project_name;
}

@Override
public Image getImage() {
return image;
}

@Override
public IContextInformation getContextInformation() {
return null;
}

@Override
public int getRelevance() {
return fRelevance;
}

public void setRelevance(int relevance) {
fRelevance= relevance;
}

@Override
public String getCommandId() {
return fCommandId;
}

public void setCommandId(String commandId) {
fCommandId= commandId;
}
}
Loading