2424import org .eclipse .core .runtime .IProgressMonitor ;
2525import org .eclipse .jdt .core .IBuffer ;
2626import org .eclipse .jdt .core .ICompilationUnit ;
27- import org .eclipse .jdt .core .IJavaElement ;
2827import org .eclipse .jdt .core .manipulation .ChangeCorrectionProposalCore ;
2928import org .eclipse .jdt .internal .corext .fix .LinkedProposalModelCore ;
3029import org .eclipse .jdt .internal .corext .fix .LinkedProposalPositionGroupCore ;
@@ -84,18 +83,31 @@ 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 {
88- Object modifiedElement = proposal .getChange ().getModifiedElement ();
89- ICompilationUnit compilationUnit = (ICompilationUnit ) ((IJavaElement ) modifiedElement ).getAncestor (IJavaElement .COMPILATION_UNIT );
100+ ICompilationUnit compilationUnit = proposal .getCompilationUnit ();
90101 IBuffer buffer = compilationUnit .getBuffer ();
91102 LinkedProposalModelCore linkedProposals = proposal .getLinkedProposalModel ();
92103 List <Triple > snippets = new ArrayList <>();
93104 Iterator <LinkedProposalPositionGroupCore > it = linkedProposals .getPositionGroupCoreIterator ();
94- int snippetNumber = 1 ;
105+
95106 while (it .hasNext ()) {
96107 LinkedProposalPositionGroupCore group = it .next ();
97108 ProposalCore [] proposalList = group .getProposals ();
98109 PositionInformation [] positionList = group .getPositions ();
110+ // Sorts in ascending order to ensure first position in list has the smallest offset
99111 Arrays .sort (positionList , new Comparator <PositionInformation >() {
100112 @ Override
101113 public int compare (PositionInformation p1 , PositionInformation p2 ) {
@@ -104,12 +116,16 @@ public int compare(PositionInformation p1, PositionInformation p2) {
104116 });
105117 StringBuilder snippet = new StringBuilder ();
106118 snippet .append (SNIPPET_CHOICE_INDICATOR );
119+
107120 for (int i = 0 ; i < positionList .length ; i ++) {
108121 int offset = positionList [i ].getOffset ();
109122 int length = positionList [i ].getLength ();
123+
110124 // Create snippet on first iteration
111125 if (i == 0 ) {
112126 LinkedPosition linkedPosition = new LinkedPosition (JsonRpcHelpers .toDocument (buffer ), positionList [i ].getOffset (), positionList [i ].getLength (), positionList [i ].getSequenceRank ());
127+
128+ // Groups with no proposals will have the snippet text added while amending the WorkspaceEdit
113129 for (int j = 0 ; j < proposalList .length ; j ++) {
114130 org .eclipse .text .edits .TextEdit editWithText = findReplaceOrInsertEdit (proposalList [j ].computeEdits (0 , linkedPosition , '\u0000' , 0 , new LinkedModeModel ()));
115131 if (editWithText != null ) {
@@ -119,39 +135,42 @@ public int compare(PositionInformation p1, PositionInformation p2) {
119135 snippet .append (((ReplaceEdit ) editWithText ).getText ());
120136 }
121137 }
122- // // If snippet is empty, ignore this group
123- // if (snippet.toString().equals(String.valueOf(SNIPPET_CHOICE_INDICATOR))) {
124- // break;
125- // }
138+
126139 snippet .append (SNIPPET_CHOICE_POSTFIX );
127140 // If snippet only has one choice, remove choice indicators
128141 if (snippet .indexOf (SNIPPET_CHOICE_DELIMITER ) == -1 ) {
129142 snippet .setCharAt (0 , ':' );
130143 snippet .deleteCharAt (snippet .length () - 2 );
131144 }
145+ // Snippet is added with smallest offset as 0th element
132146 snippets .add (new Triple (snippet .toString (), offset , length ));
133147 } else {
148+ // Add offset/length values from additional positions in group to previously created snippet
134149 Triple currentSnippet = snippets .get (snippets .size () - 1 );
135150 currentSnippet .offset .add (offset );
136151 currentSnippet .length .add (length );
137152 }
138153 }
139154 }
140155 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
156+ // Sort snippets based on offset of earliest occurrence to enable correct numbering
142157 snippets .sort (null );
143- // ListIterator<Triple> li = snippets.listIterator(snippets.size()) ;
158+ int snippetNumber = 1 ;
144159 for (int i = snippets .size () - 1 ; i >= 0 ; i --) {
145160 Triple element = snippets .get (i );
146161 element .snippet = SNIPPET_PREFIX + snippetNumber + element .snippet ;
147162 snippetNumber ++;
163+ // Separate snippets with multiple positions into individual instances in list
148164 for (int j = 1 ; j < element .offset .size (); j ++) {
149165 snippets .add (new Triple (element .snippet .toString (), element .offset .get (j ), element .length .get (j )));
150166 element .offset .remove (j );
151167 element .length .remove (j );
152168 }
153169 }
170+ // Re-sort snippets (with the added individual instances) by offset in descending order,
171+ // so that the amendments to the text edit are applied in an order that does not alter the offset of later amendments
154172 snippets .sort (null );
173+
155174 for (int i = 0 ; i < edit .getDocumentChanges ().size (); i ++) {
156175 if (edit .getDocumentChanges ().get (i ).isLeft ()) {
157176 List <TextEdit > edits = edit .getDocumentChanges ().get (i ).getLeft ().getEdits ();
@@ -160,20 +179,22 @@ public int compare(PositionInformation p1, PositionInformation p2) {
160179 StringBuilder replacementText = new StringBuilder (edits .get (j ).getNewText ());
161180 int rangeStart = JsonRpcHelpers .toOffset (buffer , editRange .getStart ().getLine (), editRange .getStart ().getCharacter ());
162181 int rangeEnd = rangeStart + replacementText .length ();
182+
163183 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 ));
184+ Triple currentSnippet = snippets .get (k );
185+ if (currentSnippet .offset .get (0 ) >= rangeStart && currentSnippet .offset .get (0 ) <= rangeEnd ) {
186+ int replaceStart = currentSnippet .offset .get (0 ) - rangeStart ;
187+ int replaceEnd = replaceStart + currentSnippet .length .get (0 );
188+ // 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
189+ if (currentSnippet .snippet .endsWith (":}" )) {
190+ currentSnippet .snippet = currentSnippet .snippet .replaceFirst (":" , ":" + replacementText .substring (replaceStart , replaceEnd ));
170191 }
171- replacementText .replace (replaceStart , replaceEnd , snippetHolder .snippet );
192+ replacementText .replace (replaceStart , replaceEnd , currentSnippet .snippet );
172193 }
173194 }
195+
174196 SnippetTextEdit newEdit = new SnippetTextEdit (editRange , replacementText .toString ());
175- edits .remove (j );
176- edits .add (j , newEdit );
197+ edits .set (j , newEdit );
177198 }
178199 }
179200 }
@@ -208,6 +229,7 @@ private static final class Triple implements Comparable<Triple> {
208229 this .length .add (length );
209230 }
210231
232+ // Sorts in descending order based on 0th (smallest) element of offset list
211233 @ Override
212234 public int compareTo (Triple other ) {
213235 return other .offset .get (0 ) - this .offset .get (0 );
0 commit comments