Skip to content

Commit

Permalink
additional edits + comments
Browse files Browse the repository at this point in the history
  • Loading branch information
hopehadfield committed Aug 22, 2024
1 parent 50516ee commit 2a1a4bb
Showing 1 changed file with 41 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.manipulation.ChangeCorrectionProposalCore;
import org.eclipse.jdt.internal.corext.fix.LinkedProposalModelCore;
import org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroupCore;
Expand Down Expand Up @@ -84,18 +83,32 @@ public CodeAction resolve(CodeAction params, IProgressMonitor monitor) {
return params;
}

/***
* Supports linked correction proposals by converting them to snippets.
* Represents a
* {@link org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroupCore}
* with snippet choice syntax if the group has multiple proposals, otherwise
* represents it as a placeholder.
*
* @param proposal
* the proposal to add support for
* @param edit
* the current edit to be returned with the code action
* @throws CoreException
*/
private static final void addSnippetsIfApplicable(LinkedCorrectionProposalCore proposal, WorkspaceEdit edit) throws CoreException {
Object modifiedElement = proposal.getChange().getModifiedElement();
ICompilationUnit compilationUnit = (ICompilationUnit) ((IJavaElement) modifiedElement).getAncestor(IJavaElement.COMPILATION_UNIT);
ICompilationUnit compilationUnit = proposal.getCompilationUnit();
IBuffer buffer = compilationUnit.getBuffer();
LinkedProposalModelCore linkedProposals = proposal.getLinkedProposalModel();
List<Triple> snippets = new ArrayList<>();
Iterator<LinkedProposalPositionGroupCore> it = linkedProposals.getPositionGroupCoreIterator();
int snippetNumber = 1;

while (it.hasNext()) {
LinkedProposalPositionGroupCore group = it.next();
ProposalCore[] proposalList = group.getProposals();
PositionInformation[] positionList = group.getPositions();
// Sorts in ascending order to ensure first position in list has the smallest offset
Arrays.sort(positionList, new Comparator<PositionInformation>() {
@Override
public int compare(PositionInformation p1, PositionInformation p2) {
Expand All @@ -104,12 +117,16 @@ public int compare(PositionInformation p1, PositionInformation p2) {
});
StringBuilder snippet = new StringBuilder();
snippet.append(SNIPPET_CHOICE_INDICATOR);

for (int i = 0; i < positionList.length; i++) {
int offset = positionList[i].getOffset();
int length = positionList[i].getLength();

// Create snippet on first iteration
if (i == 0) {
LinkedPosition linkedPosition = new LinkedPosition(JsonRpcHelpers.toDocument(buffer), positionList[i].getOffset(), positionList[i].getLength(), positionList[i].getSequenceRank());

// Groups with no proposals will have the snippet text added while amending the WorkspaceEdit
for (int j = 0; j < proposalList.length; j++) {
org.eclipse.text.edits.TextEdit editWithText = findReplaceOrInsertEdit(proposalList[j].computeEdits(0, linkedPosition, '\u0000', 0, new LinkedModeModel()));
if (editWithText != null) {
Expand All @@ -119,39 +136,42 @@ public int compare(PositionInformation p1, PositionInformation p2) {
snippet.append(((ReplaceEdit) editWithText).getText());
}
}
// // If snippet is empty, ignore this group
// if (snippet.toString().equals(String.valueOf(SNIPPET_CHOICE_INDICATOR))) {
// break;
// }

snippet.append(SNIPPET_CHOICE_POSTFIX);
// If snippet only has one choice, remove choice indicators
if (snippet.indexOf(SNIPPET_CHOICE_DELIMITER) == -1) {
snippet.setCharAt(0, ':');
snippet.deleteCharAt(snippet.length() - 2);
}
// Snippet is added with smallest offset as 0th element
snippets.add(new Triple(snippet.toString(), offset, length));
} else {
// Add offset/length values from additional positions in group to previously created snippet
Triple currentSnippet = snippets.get(snippets.size() - 1);
currentSnippet.offset.add(offset);
currentSnippet.length.add(length);
}
}
}
if (!snippets.isEmpty()) {
// Sort snippets in descending order based on offset, so that the edits are applied in an order that does not alter the offset of later edits
// Sort snippets based on offset of earliest occurrence to enable correct numbering
snippets.sort(null);
// ListIterator<Triple> li = snippets.listIterator(snippets.size());
int snippetNumber = 1;
for (int i = snippets.size() - 1; i >= 0; i--) {
Triple element = snippets.get(i);
element.snippet = SNIPPET_PREFIX + snippetNumber + element.snippet;
snippetNumber++;
// Separate snippets with multiple positions into individual instances in list
for (int j = 1; j < element.offset.size(); j++) {
snippets.add(new Triple(element.snippet.toString(), element.offset.get(j), element.length.get(j)));
element.offset.remove(j);
element.length.remove(j);
}
}
// Re-sort snippets (with the added individual instances) by offset in descending order,
// so that the amendments to the text edit are applied in an order that does not alter the offset of later amendments
snippets.sort(null);

for (int i = 0; i < edit.getDocumentChanges().size(); i++) {
if (edit.getDocumentChanges().get(i).isLeft()) {
List<TextEdit> edits = edit.getDocumentChanges().get(i).getLeft().getEdits();
Expand All @@ -160,20 +180,22 @@ public int compare(PositionInformation p1, PositionInformation p2) {
StringBuilder replacementText = new StringBuilder(edits.get(j).getNewText());
int rangeStart = JsonRpcHelpers.toOffset(buffer, editRange.getStart().getLine(), editRange.getStart().getCharacter());
int rangeEnd = rangeStart + replacementText.length();

for (int k = 0; k < snippets.size(); k++) {
Triple snippetHolder = snippets.get(k);
if (snippetHolder.offset.get(0) >= rangeStart && snippetHolder.offset.get(0) <= rangeEnd) {
int replaceStart = snippetHolder.offset.get(0) - rangeStart;
int replaceEnd = replaceStart + snippetHolder.length.get(0);
if (snippetHolder.snippet.endsWith(":}")) {
snippetHolder.snippet = snippetHolder.snippet.replaceFirst(":", ":" + replacementText.substring(replaceStart, replaceEnd));
Triple currentSnippet = snippets.get(k);
if (currentSnippet.offset.get(0) >= rangeStart && currentSnippet.offset.get(0) <= rangeEnd) {
int replaceStart = currentSnippet.offset.get(0) - rangeStart;
int replaceEnd = replaceStart + currentSnippet.length.get(0);
// If snippet text has not been added due to no elements in the proposal list, create snippet based on the text in the given position range
if (currentSnippet.snippet.endsWith(":}")) {
currentSnippet.snippet = currentSnippet.snippet.replaceFirst(":", ":" + replacementText.substring(replaceStart, replaceEnd));
}
replacementText.replace(replaceStart, replaceEnd, snippetHolder.snippet);
replacementText.replace(replaceStart, replaceEnd, currentSnippet.snippet);
}
}

SnippetTextEdit newEdit = new SnippetTextEdit(editRange, replacementText.toString());
edits.remove(j);
edits.add(j, newEdit);
edits.set(j, newEdit);
}
}
}
Expand Down Expand Up @@ -208,6 +230,7 @@ private static final class Triple implements Comparable<Triple> {
this.length.add(length);
}

// Sorts in descending order based on 0th (smallest) element of offset list
@Override
public int compareTo(Triple other) {
return other.offset.get(0) - this.offset.get(0);
Expand Down

0 comments on commit 2a1a4bb

Please sign in to comment.