Skip to content

Commit 2a1a4bb

Browse files
committed
additional edits + comments
1 parent 50516ee commit 2a1a4bb

File tree

1 file changed

+41
-18
lines changed

1 file changed

+41
-18
lines changed

org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CodeActionResolveHandler.java

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.eclipse.core.runtime.IProgressMonitor;
2525
import org.eclipse.jdt.core.IBuffer;
2626
import org.eclipse.jdt.core.ICompilationUnit;
27-
import org.eclipse.jdt.core.IJavaElement;
2827
import org.eclipse.jdt.core.manipulation.ChangeCorrectionProposalCore;
2928
import org.eclipse.jdt.internal.corext.fix.LinkedProposalModelCore;
3029
import org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroupCore;
@@ -84,18 +83,32 @@ public CodeAction resolve(CodeAction params, IProgressMonitor monitor) {
8483
return params;
8584
}
8685

86+
/***
87+
* Supports linked correction proposals by converting them to snippets.
88+
* Represents a
89+
* {@link org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroupCore}
90+
* with snippet choice syntax if the group has multiple proposals, otherwise
91+
* represents it as a placeholder.
92+
*
93+
* @param proposal
94+
* the proposal to add support for
95+
* @param edit
96+
* the current edit to be returned with the code action
97+
* @throws CoreException
98+
*/
8799
private static final void addSnippetsIfApplicable(LinkedCorrectionProposalCore proposal, WorkspaceEdit edit) throws CoreException {
88100
Object modifiedElement = proposal.getChange().getModifiedElement();
89-
ICompilationUnit compilationUnit = (ICompilationUnit) ((IJavaElement) modifiedElement).getAncestor(IJavaElement.COMPILATION_UNIT);
101+
ICompilationUnit compilationUnit = proposal.getCompilationUnit();
90102
IBuffer buffer = compilationUnit.getBuffer();
91103
LinkedProposalModelCore linkedProposals = proposal.getLinkedProposalModel();
92104
List<Triple> snippets = new ArrayList<>();
93105
Iterator<LinkedProposalPositionGroupCore> it = linkedProposals.getPositionGroupCoreIterator();
94-
int snippetNumber = 1;
106+
95107
while (it.hasNext()) {
96108
LinkedProposalPositionGroupCore group = it.next();
97109
ProposalCore[] proposalList = group.getProposals();
98110
PositionInformation[] positionList = group.getPositions();
111+
// Sorts in ascending order to ensure first position in list has the smallest offset
99112
Arrays.sort(positionList, new Comparator<PositionInformation>() {
100113
@Override
101114
public int compare(PositionInformation p1, PositionInformation p2) {
@@ -104,12 +117,16 @@ public int compare(PositionInformation p1, PositionInformation p2) {
104117
});
105118
StringBuilder snippet = new StringBuilder();
106119
snippet.append(SNIPPET_CHOICE_INDICATOR);
120+
107121
for (int i = 0; i < positionList.length; i++) {
108122
int offset = positionList[i].getOffset();
109123
int length = positionList[i].getLength();
124+
110125
// Create snippet on first iteration
111126
if (i == 0) {
112127
LinkedPosition linkedPosition = new LinkedPosition(JsonRpcHelpers.toDocument(buffer), positionList[i].getOffset(), positionList[i].getLength(), positionList[i].getSequenceRank());
128+
129+
// Groups with no proposals will have the snippet text added while amending the WorkspaceEdit
113130
for (int j = 0; j < proposalList.length; j++) {
114131
org.eclipse.text.edits.TextEdit editWithText = findReplaceOrInsertEdit(proposalList[j].computeEdits(0, linkedPosition, '\u0000', 0, new LinkedModeModel()));
115132
if (editWithText != null) {
@@ -119,39 +136,42 @@ public int compare(PositionInformation p1, PositionInformation p2) {
119136
snippet.append(((ReplaceEdit) editWithText).getText());
120137
}
121138
}
122-
// // If snippet is empty, ignore this group
123-
// if (snippet.toString().equals(String.valueOf(SNIPPET_CHOICE_INDICATOR))) {
124-
// break;
125-
// }
139+
126140
snippet.append(SNIPPET_CHOICE_POSTFIX);
127141
// If snippet only has one choice, remove choice indicators
128142
if (snippet.indexOf(SNIPPET_CHOICE_DELIMITER) == -1) {
129143
snippet.setCharAt(0, ':');
130144
snippet.deleteCharAt(snippet.length() - 2);
131145
}
146+
// Snippet is added with smallest offset as 0th element
132147
snippets.add(new Triple(snippet.toString(), offset, length));
133148
} else {
149+
// Add offset/length values from additional positions in group to previously created snippet
134150
Triple currentSnippet = snippets.get(snippets.size() - 1);
135151
currentSnippet.offset.add(offset);
136152
currentSnippet.length.add(length);
137153
}
138154
}
139155
}
140156
if (!snippets.isEmpty()) {
141-
// 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
157+
// Sort snippets based on offset of earliest occurrence to enable correct numbering
142158
snippets.sort(null);
143-
// ListIterator<Triple> li = snippets.listIterator(snippets.size());
159+
int snippetNumber = 1;
144160
for (int i = snippets.size() - 1; i >= 0; i--) {
145161
Triple element = snippets.get(i);
146162
element.snippet = SNIPPET_PREFIX + snippetNumber + element.snippet;
147163
snippetNumber++;
164+
// Separate snippets with multiple positions into individual instances in list
148165
for (int j = 1; j < element.offset.size(); j++) {
149166
snippets.add(new Triple(element.snippet.toString(), element.offset.get(j), element.length.get(j)));
150167
element.offset.remove(j);
151168
element.length.remove(j);
152169
}
153170
}
171+
// Re-sort snippets (with the added individual instances) by offset in descending order,
172+
// so that the amendments to the text edit are applied in an order that does not alter the offset of later amendments
154173
snippets.sort(null);
174+
155175
for (int i = 0; i < edit.getDocumentChanges().size(); i++) {
156176
if (edit.getDocumentChanges().get(i).isLeft()) {
157177
List<TextEdit> edits = edit.getDocumentChanges().get(i).getLeft().getEdits();
@@ -160,20 +180,22 @@ public int compare(PositionInformation p1, PositionInformation p2) {
160180
StringBuilder replacementText = new StringBuilder(edits.get(j).getNewText());
161181
int rangeStart = JsonRpcHelpers.toOffset(buffer, editRange.getStart().getLine(), editRange.getStart().getCharacter());
162182
int rangeEnd = rangeStart + replacementText.length();
183+
163184
for (int k = 0; k < snippets.size(); k++) {
164-
Triple snippetHolder = snippets.get(k);
165-
if (snippetHolder.offset.get(0) >= rangeStart && snippetHolder.offset.get(0) <= rangeEnd) {
166-
int replaceStart = snippetHolder.offset.get(0) - rangeStart;
167-
int replaceEnd = replaceStart + snippetHolder.length.get(0);
168-
if (snippetHolder.snippet.endsWith(":}")) {
169-
snippetHolder.snippet = snippetHolder.snippet.replaceFirst(":", ":" + replacementText.substring(replaceStart, replaceEnd));
185+
Triple currentSnippet = snippets.get(k);
186+
if (currentSnippet.offset.get(0) >= rangeStart && currentSnippet.offset.get(0) <= rangeEnd) {
187+
int replaceStart = currentSnippet.offset.get(0) - rangeStart;
188+
int replaceEnd = replaceStart + currentSnippet.length.get(0);
189+
// 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
190+
if (currentSnippet.snippet.endsWith(":}")) {
191+
currentSnippet.snippet = currentSnippet.snippet.replaceFirst(":", ":" + replacementText.substring(replaceStart, replaceEnd));
170192
}
171-
replacementText.replace(replaceStart, replaceEnd, snippetHolder.snippet);
193+
replacementText.replace(replaceStart, replaceEnd, currentSnippet.snippet);
172194
}
173195
}
196+
174197
SnippetTextEdit newEdit = new SnippetTextEdit(editRange, replacementText.toString());
175-
edits.remove(j);
176-
edits.add(j, newEdit);
198+
edits.set(j, newEdit);
177199
}
178200
}
179201
}
@@ -208,6 +230,7 @@ private static final class Triple implements Comparable<Triple> {
208230
this.length.add(length);
209231
}
210232

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

0 commit comments

Comments
 (0)