1 /*******************************************************************************
2  * Copyright (c) 2009, 2020 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.text.tests;
15 
16 import static org.junit.Assert.assertEquals;
17 import static org.junit.Assert.fail;
18 
19 import org.junit.After;
20 import org.junit.Before;
21 import org.junit.Test;
22 
23 import org.eclipse.core.runtime.ILogListener;
24 import org.eclipse.core.runtime.IStatus;
25 
26 import org.eclipse.text.tests.Accessor;
27 
28 import org.eclipse.jface.text.Document;
29 import org.eclipse.jface.text.DocumentCommand;
30 import org.eclipse.jface.text.IDocument;
31 import org.eclipse.jface.text.rules.FastPartitioner;
32 
33 import org.eclipse.jdt.ui.text.IJavaPartitions;
34 
35 import org.eclipse.jdt.internal.ui.JavaPlugin;
36 import org.eclipse.jdt.internal.ui.text.FastJavaPartitionScanner;
37 import org.eclipse.jdt.internal.ui.text.java.JavaAutoIndentStrategy;
38 
39 /**
40  * JavaAutoIndentStrategyTest.
41  *
42  * @since 3.6
43  */
44 public class JavaAutoIndentStrategyTest implements ILogListener {
45 	private FastPartitioner fPartitioner;
46 
47 	private Document fDocument;
48 
49 	private DocumentCommand fDocumentCommand;
50 
51 	private Accessor fAccessor;
52 
53 	private Accessor fCommandAccessor;
54 
55 	private JavaAutoIndentStrategy fJavaAutoIndentStrategy;
56 
JavaAutoIndentStrategyTest()57 	public JavaAutoIndentStrategyTest() {
58 		fDocument= new Document();
59 		String[] types= new String[] {
60 			IJavaPartitions.JAVA_DOC,
61 			IJavaPartitions.JAVA_MULTI_LINE_COMMENT,
62 			IJavaPartitions.JAVA_SINGLE_LINE_COMMENT,
63 			IJavaPartitions.JAVA_STRING,
64 			IJavaPartitions.JAVA_CHARACTER,
65 			IDocument.DEFAULT_CONTENT_TYPE
66 		};
67 		fPartitioner= new FastPartitioner(new FastJavaPartitionScanner(), types);
68 		fPartitioner.connect(fDocument);
69 		fDocument.setDocumentPartitioner(IJavaPartitions.JAVA_PARTITIONING, fPartitioner);
70 		fJavaAutoIndentStrategy= new JavaAutoIndentStrategy(IJavaPartitions.JAVA_PARTITIONING, null, null);
71 		fDocumentCommand= new DocumentCommand() {
72 		};
73 		fAccessor= new Accessor(fJavaAutoIndentStrategy, JavaAutoIndentStrategy.class);
74 		fCommandAccessor= new Accessor(fDocumentCommand, DocumentCommand.class);
75 	}
76 
performPaste()77 	private void performPaste() {
78 		fAccessor.invoke("smartPaste", new Class[] { IDocument.class, DocumentCommand.class }, new Object[] { fDocument, fDocumentCommand });
79 	}
80 
81 	@Test
testPasteDefaultAtEnd()82 	public void testPasteDefaultAtEnd() {
83 		fDocument.set("public class Test2 {\r\n\r\n}\r\n");
84 
85 		fDocumentCommand.doit= true;
86 		fDocumentCommand.offset= 27;
87 		fDocumentCommand.text= "default";
88 		performPaste();
89 		String result= "default";
90 		assertEquals(result, fDocumentCommand.text);
91 	}
92 
93 	@Test
testPasteFooAtEnd()94 	public void testPasteFooAtEnd() {
95 		fDocument.set("public class Test2 {\r\n\r\n}\r\n");
96 
97 		fDocumentCommand.doit= true;
98 		fDocumentCommand.offset= 27;
99 		fDocumentCommand.text= "foo";
100 		performPaste();
101 		String result= "foo";
102 		assertEquals(result, fDocumentCommand.text);
103 	}
104 
105 	@Test
testPasteAndIndentOfLongStringWithContinuations1()106 	public void testPasteAndIndentOfLongStringWithContinuations1() {
107 		//https://bugs.eclipse.org/bugs/show_bug.cgi?id=330556
108 		//https://bugs.eclipse.org/bugs/show_bug.cgi?id=65317
109 		fDocument.set("public class Test2 {\n}");
110 
111 		fDocumentCommand.doit= true;
112 		fDocumentCommand.offset= 21;
113 		fDocumentCommand.text= "String[]a=new String[] {\n" +
114 				"\"X.java\",\n" +
115 				"\"public class X extends B{\\n\"\n" +
116 				"\"    public static int field1;\\n\"\n" +
117 				"\"    public static X xfield;\\n\"\n" +
118 				"\"    public void bar1(int i) {\\n\"\n" +
119 				"\"        field1 = 1;\\n\"\n" +
120 				"\"    }\\n\"\n" +
121 				"\"    public void bar2(int i) {\\n\"\n" +
122 				"\"        this.field1 = 1;\\n\"\n" +
123 				"\"    }\\n\"\n" +
124 				"\"}\\n\"\n" +
125 				"\"class A{\\n\"\n" +
126 				"\"    public static X xA;\\n\"\n" +
127 				"\"}\\n\"\n" +
128 				"\"class B{\\n\"\n" +
129 				"\"    public static int b1;\\n\"\n" +
130 				"\"}\"\n" +
131 				"};";
132 		performPaste();
133 		String result= "\tString[]a=new String[] {\n" +
134 				"\t\t\t\"X.java\",\n" +
135 				"\t\t\t\"public class X extends B{\\n\"\n" +
136 				"\t\t\t\"    public static int field1;\\n\"\n" +
137 				"\t\t\t\"    public static X xfield;\\n\"\n" +
138 				"\t\t\t\"    public void bar1(int i) {\\n\"\n" +
139 				"\t\t\t\"        field1 = 1;\\n\"\n" +
140 				"\t\t\t\"    }\\n\"\n" +
141 				"\t\t\t\"    public void bar2(int i) {\\n\"\n" +
142 				"\t\t\t\"        this.field1 = 1;\\n\"\n" +
143 				"\t\t\t\"    }\\n\"\n" +
144 				"\t\t\t\"}\\n\"\n" +
145 				"\t\t\t\"class A{\\n\"\n" +
146 				"\t\t\t\"    public static X xA;\\n\"\n" +
147 				"\t\t\t\"}\\n\"\n" +
148 				"\t\t\t\"class B{\\n\"\n" +
149 				"\t\t\t\"    public static int b1;\\n\"\n" +
150 				"\t\t\t\"}\"\n" +
151 				"\t\t\t};";
152 		assertEquals(result, fDocumentCommand.text);
153 	}
154 
155 	@Test
testPasteAndIndentOfStringWithContinuations2()156 	public void testPasteAndIndentOfStringWithContinuations2() {
157 		//https://bugs.eclipse.org/bugs/show_bug.cgi?id=337150
158 		fDocument.set("public class Test2 {\n}");
159 
160 		fDocumentCommand.doit= true;
161 		fDocumentCommand.offset= 21;
162 		fDocumentCommand.text= "String array2= \"this is the 1st string\"\n" +
163 				"\t+ \"this is the 1st string\"\n" +
164 				"\t+ \"this is the 1st string\";\n";
165 		performPaste();
166 		String result= "\tString array2= \"this is the 1st string\"\n" +
167 				"\t\t\t+ \"this is the 1st string\"\n" +
168 				"\t\t\t+ \"this is the 1st string\";\n";
169 		assertEquals(result, fDocumentCommand.text);
170 	}
171 
172 	@Test
testPasteAndIndentOfStringWithContinuations3()173 	public void testPasteAndIndentOfStringWithContinuations3() {
174 		//https://bugs.eclipse.org/bugs/show_bug.cgi?id=337150
175 		fDocument.set("public class Test2 {\n}");
176 
177 		fDocumentCommand.doit= true;
178 		fDocumentCommand.offset= 21;
179 		fDocumentCommand.text= "\tString array2= \"this is the 1st string\"\n" +
180 				"+ \"this is the 1st string\"\n" +
181 				"\t+ \"this is the 1st string\";\n";
182 		performPaste();
183 		String result= "\tString array2= \"this is the 1st string\"\n" +
184 				"+ \"this is the 1st string\"\n" +
185 				"\t+ \"this is the 1st string\";\n";
186 		assertEquals(result, fDocumentCommand.text);
187 	}
188 
189 	@Test
testPasteAndIndentOfStringWithContinuations4()190 	public void testPasteAndIndentOfStringWithContinuations4() {
191 		//https://bugs.eclipse.org/bugs/show_bug.cgi?id=337150
192 		fDocument.set("public class Test2 {\n}");
193 
194 		fDocumentCommand.doit= true;
195 		fDocumentCommand.offset= 21;
196 		fDocumentCommand.text= "\tString array2= \"this is the 1st string\"\n" +
197 				"\t+ \"this is the 1st string\"\n" +
198 				"\t+ \"this is the 1st string\";\n";
199 		performPaste();
200 		String result= "\tString array2= \"this is the 1st string\"\n" +
201 				"\t+ \"this is the 1st string\"\n" +
202 				"\t+ \"this is the 1st string\";\n";
203 		assertEquals(result, fDocumentCommand.text);
204 	}
205 
206 	@Test
testPasteAndIndentOfStringWithContinuations5()207 	public void testPasteAndIndentOfStringWithContinuations5() {
208 		//https://bugs.eclipse.org/bugs/show_bug.cgi?id=337150
209 		fDocument.set("public class Test2 {\n}");
210 
211 		fDocumentCommand.doit= true;
212 		fDocumentCommand.offset= 21;
213 		fDocumentCommand.text= "\tString array2= \"this is the 1st string\"\n" +
214 				"\t\t\t\t\t+ \"this is the 1st string\"\n" +
215 				"\t\t\t\t\t\t\t+ \"this is the 1st string\";\n";
216 		performPaste();
217 		String result= "\tString array2= \"this is the 1st string\"\n" +
218 				"\t\t\t+ \"this is the 1st string\"\n" +
219 				"\t\t\t\t\t+ \"this is the 1st string\";\n";
220 		assertEquals(result, fDocumentCommand.text);
221 	}
222 
performSmartIndentAfterNewLine()223 	private void performSmartIndentAfterNewLine() {
224 		fAccessor.invoke("clearCachedValues", null, null);
225 		fAccessor.invoke("smartIndentAfterNewLine", new Class[] { IDocument.class, DocumentCommand.class }, new Object[] { fDocument, fDocumentCommand });
226 		fCommandAccessor.invoke("execute", new Class[] { IDocument.class }, new Object[] { fDocument });
227 	}
228 
229 	@Test
testSmartIndentAfterNewLine1()230 	public void testSmartIndentAfterNewLine1() {
231 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=29379
232 		fDocument.setInitialLineDelimiter("\r\n");
233 		fDocument.set("main (new String [] {);");
234 		fDocumentCommand.doit= true;
235 		fDocumentCommand.offset= 21;
236 		fDocumentCommand.text= "\r\n";
237 		performSmartIndentAfterNewLine();
238 		StringBuilder buf= new StringBuilder();
239 		buf.append("main (new String [] {\r\n");
240 		buf.append("\t\t\r\n");
241 		buf.append("});");
242 		assertEquals(buf.toString(), fDocument.get());
243 
244 		fDocument.set("main (new String [] {\"a\");");
245 		fDocumentCommand.doit= true;
246 		fDocumentCommand.offset= 24;
247 		fDocumentCommand.text= "\r\n";
248 		performSmartIndentAfterNewLine();
249 		StringBuilder buf1= new StringBuilder();
250 		buf1.append("main (new String [] {\"a\"\r\n");
251 		buf1.append("\t\t\r\n");
252 		buf1.append("});");
253 		assertEquals(buf1.toString(), fDocument.get());
254 	}
255 
256 	@Test
testSmartIndentAfterNewLine2()257 	public void testSmartIndentAfterNewLine2() {
258 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=395071
259 		fDocument.setInitialLineDelimiter("\r\n");
260 		fDocument.set("main (new String [] {\"a\",);");
261 		fDocumentCommand.doit= true;
262 		fDocumentCommand.offset= 25;
263 		fDocumentCommand.text= "\r\n";
264 		performSmartIndentAfterNewLine();
265 		StringBuilder buf= new StringBuilder();
266 		buf.append("main (new String [] {\"a\",\r\n");
267 		buf.append("\t\t\r\n");
268 		buf.append("});");
269 		assertEquals(buf.toString(), fDocument.get());
270 
271 		fDocument.set("main (new String [] {\"a\", );");
272 		fDocumentCommand.doit= true;
273 		fDocumentCommand.offset= 26;
274 		fDocumentCommand.text= "\r\n";
275 		performSmartIndentAfterNewLine();
276 		StringBuilder buf1= new StringBuilder();
277 		buf1.append("main (new String [] {\"a\", \r\n");
278 		buf1.append("\t\t\r\n");
279 		buf1.append("});");
280 		assertEquals(buf1.toString(), fDocument.get());
281 	}
282 
283 	@Test
testSmartIndentAfterNewLine3()284 	public void testSmartIndentAfterNewLine3() {
285 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=395071
286 		fDocument.setInitialLineDelimiter("\r\n");
287 		fDocument.set("main (new String [] {\"a\",\"b\",);");
288 		fDocumentCommand.doit= true;
289 		fDocumentCommand.offset= 29;
290 		fDocumentCommand.text= "\r\n";
291 		performSmartIndentAfterNewLine();
292 		StringBuilder buf= new StringBuilder();
293 		buf.append("main (new String [] {\"a\",\"b\",\r\n");
294 		buf.append("\t\t\r\n");
295 		buf.append("});");
296 		assertEquals(buf.toString(), fDocument.get());
297 	}
298 
299 	@Test
testSmartIndentAfterNewLine4()300 	public void testSmartIndentAfterNewLine4() {
301 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=254704
302 		fDocument.setInitialLineDelimiter("\r\n");
303 		fDocument.set("@NamedQueries({);");
304 		fDocumentCommand.doit= true;
305 		fDocumentCommand.offset= 15;
306 		fDocumentCommand.text= "\r\n";
307 		performSmartIndentAfterNewLine();
308 		StringBuilder buf= new StringBuilder();
309 		buf.append("@NamedQueries({\r\n");
310 		buf.append("\t\r\n");
311 		buf.append("});");
312 		assertEquals(buf.toString(), fDocument.get());
313 
314 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=394467
315 		fDocument.set("@MesageDriven( activationConfig ={)");
316 		fDocumentCommand.doit= true;
317 		fDocumentCommand.offset= 34;
318 		fDocumentCommand.text= "\r\n";
319 		performSmartIndentAfterNewLine();
320 		StringBuilder buf1= new StringBuilder();
321 		buf1.append("@MesageDriven( activationConfig ={\r\n");
322 		buf1.append("\t\t\r\n");
323 		buf1.append("})");
324 		assertEquals(buf1.toString(), fDocument.get());
325 	}
326 
327 	@Test
testSmartIndentAfterNewLine5()328 	public void testSmartIndentAfterNewLine5() {
329 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=256087
330 		fDocument.setInitialLineDelimiter("\r\n");
331 		fDocument.set("if (false) {return false;");
332 		fDocumentCommand.doit= true;
333 		fDocumentCommand.offset= 12;
334 		fDocumentCommand.text= "\r\n";
335 		performSmartIndentAfterNewLine();
336 		StringBuilder buf= new StringBuilder();
337 		buf.append("if (false) {\r\n");
338 		buf.append("\treturn false;\r\n");
339 		buf.append("}");
340 		assertEquals(buf.toString(), fDocument.get());
341 
342 		fDocument.set("if (false) { return false;");
343 		fDocumentCommand.doit= true;
344 		fDocumentCommand.offset= 13;
345 		fDocumentCommand.text= "\r\n";
346 		performSmartIndentAfterNewLine();
347 		StringBuilder buf1= new StringBuilder();
348 		buf1.append("if (false) { \r\n");
349 		buf1.append("\treturn false;\r\n");
350 		buf1.append("}");
351 		assertEquals(buf1.toString(), fDocument.get());
352 	}
353 
354 	@Test
testSmartIndentAfterNewLine6()355 	public void testSmartIndentAfterNewLine6() {
356 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=200015
357 		fDocument.setInitialLineDelimiter("\r\n");
358 		StringBuilder inBuf= new StringBuilder();
359 		inBuf.append("enum ReviewResult {\n");
360 		inBuf.append("    Good{, Bad\n");
361 		inBuf.append("}");
362 		fDocument.set(inBuf.toString());
363 		fDocumentCommand.doit= true;
364 		fDocumentCommand.offset= 29;
365 		fDocumentCommand.text= "\r\n";
366 		performSmartIndentAfterNewLine();
367 		StringBuilder buf= new StringBuilder();
368 		buf.append("enum ReviewResult {\n");
369 		buf.append("    Good{\r\n");
370 		buf.append("    \t\n");
371 		buf.append("    }, Bad\n");
372 		buf.append("}");
373 		assertEquals(buf.toString(), fDocument.get());
374 	}
375 
376 	@Test
testSmartIndentAfterNewLine7()377 	public void testSmartIndentAfterNewLine7() {
378 		fDocument.setInitialLineDelimiter("\r\n");
379 		fDocument.set("int[] a= new int[] { ;");
380 		fDocumentCommand.doit= true;
381 		fDocumentCommand.offset= 21;
382 		fDocumentCommand.text= "\r\n";
383 		performSmartIndentAfterNewLine();
384 		StringBuilder buf= new StringBuilder();
385 		buf.append("int[] a= new int[] { \r\n");
386 		buf.append("\t\t\r\n");
387 		buf.append("};");
388 		assertEquals(buf.toString(), fDocument.get());
389 	}
390 
391 	@Test
testSmartIndentAfterNewLine8()392 	public void testSmartIndentAfterNewLine8() {
393 		fDocument.setInitialLineDelimiter("\r\n");
394 		fDocument.set("String[] strs = {\"a\",\"b\",");
395 		fDocumentCommand.doit= true;
396 		fDocumentCommand.offset= 21;
397 		fDocumentCommand.text= "\r\n";
398 		performSmartIndentAfterNewLine();
399 		StringBuilder buf= new StringBuilder();
400 		buf.append("String[] strs = {\"a\",\r\n");
401 		buf.append("\t\t\"b\",\r\n");
402 		buf.append("}");
403 		assertEquals(buf.toString(), fDocument.get());
404 	}
405 
406 	@Test
testSmartIndentAfterNewLine9()407 	public void testSmartIndentAfterNewLine9() {
408 		fDocument.setInitialLineDelimiter("\r\n");
409 		fDocument.set("{ int a;");
410 		fDocumentCommand.doit= true;
411 		fDocumentCommand.offset= 1;
412 		fDocumentCommand.text= "\r\n";
413 		performSmartIndentAfterNewLine();
414 		StringBuilder buf= new StringBuilder();
415 		buf.append("{\r\n");
416 		buf.append("\tint a;\r\n");
417 		buf.append("}");
418 		assertEquals(buf.toString(), fDocument.get());
419 	}
420 
421 	@Test
testSmartIndentAfterNewLine10()422 	public void testSmartIndentAfterNewLine10() {
423 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=404879
424 		fDocument.setInitialLineDelimiter("\r\n");
425 		fDocument.set("{ foo();");
426 		fDocumentCommand.doit= true;
427 		fDocumentCommand.offset= 1;
428 		fDocumentCommand.text= "\r\n";
429 		performSmartIndentAfterNewLine();
430 		StringBuilder buf= new StringBuilder();
431 		buf.append("{\r\n");
432 		buf.append("\tfoo();\r\n");
433 		buf.append("}");
434 		assertEquals(buf.toString(), fDocument.get());
435 	}
436 
437 	/*
438 	 * @see junit.framework.TestCase#setUp()
439 	 */
440 	@Before
setUp()441 	public void setUp() throws Exception {
442 		JavaPlugin.getDefault().getLog().addLogListener(this);
443 	}
444 
445 	/*
446 	 * @see junit.framework.TestCase#tearDown()
447 	 */
448 	@After
tearDown()449 	public void tearDown() throws Exception {
450 		JavaPlugin.getDefault().getLog().removeLogListener(this);
451 	}
452 
453 	/*
454 	 * @see org.eclipse.core.runtime.ILogListener#logging(org.eclipse.core.runtime.IStatus, java.lang.String)
455 	 */
456 	@Override
logging(IStatus status, String plugin)457 	public void logging(IStatus status, String plugin) {
458 		fail();
459 	}
460 }
461