View | Details | Raw Unified | Return to bug 260011 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java (+350 lines)
Lines 3229-3234 Link Here
3229
}
3229
}
3230
3230
3231
/**
3231
/**
3232
 * @bug 260011: [formatter] Formatting of html in javadoc comments doesn't work with style attributes
3233
 * @test Ensure that the comment formatter understand <p> html tag with attributes
3234
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=260011"
3235
 */
3236
public void testBug260011() throws JavaModelException {
3237
	String source = 
3238
		"public class Test {\n" + 
3239
		"    /**\n" + 
3240
		"     * some comment text here\n" + 
3241
		"     * <p style=\"font-variant:small-caps;\">\n" + 
3242
		"     * some text to be styled a certain way\n" + 
3243
		"     * </p>\n" + 
3244
		"     */\n" + 
3245
		"    void foo() {}\n" + 
3246
		"\n" + 
3247
		"}\n";
3248
	formatSource(source,
3249
		"public class Test {\n" + 
3250
		"	/**\n" + 
3251
		"	 * some comment text here\n" + 
3252
		"	 * <p style=\"font-variant:small-caps;\">\n" + 
3253
		"	 * some text to be styled a certain way\n" + 
3254
		"	 * </p>\n" + 
3255
		"	 */\n" + 
3256
		"	void foo() {\n" + 
3257
		"	}\n" + 
3258
		"\n" + 
3259
		"}\n"
3260
	);
3261
}
3262
public void testBug260011_01() throws JavaModelException {
3263
	String source = 
3264
		"public class Test {\n" + 
3265
		"    /**\n" + 
3266
		"     * some comment text here\n" + 
3267
		"     * <ul style=\"font-variant:small-caps;\"><li style=\"font-variant:small-caps;\">\n" + 
3268
		"     * some text to be styled a certain way</li></ul>\n" + 
3269
		"     * end of comment\n" + 
3270
		"     */\n" + 
3271
		"    void foo() {}\n" + 
3272
		"\n" + 
3273
		"}\n";
3274
	formatSource(source,
3275
		"public class Test {\n" + 
3276
		"	/**\n" + 
3277
		"	 * some comment text here\n" + 
3278
		"	 * <ul style=\"font-variant:small-caps;\">\n" + 
3279
		"	 * <li style=\"font-variant:small-caps;\">\n" + 
3280
		"	 * some text to be styled a certain way</li>\n" + 
3281
		"	 * </ul>\n" + 
3282
		"	 * end of comment\n" + 
3283
		"	 */\n" + 
3284
		"	void foo() {\n" + 
3285
		"	}\n" + 
3286
		"\n" + 
3287
		"}\n"
3288
	);
3289
}
3290
public void testBug260011_02() throws JavaModelException {
3291
	String source = 
3292
		"public class Test {\n" + 
3293
		"    /**\n" + 
3294
		"     * some comment text here\n" + 
3295
		"     * <pre style=\"font-variant:small-caps;\">\n" + 
3296
		"     *      some text\n" + 
3297
		"     *           to be styled\n" + 
3298
		"     *                 a certain way\n" + 
3299
		"     *      \n" + 
3300
		"     * </pre>\n" + 
3301
		"     * end of comment\n" + 
3302
		"     */\n" + 
3303
		"    void foo() {}\n" + 
3304
		"\n" + 
3305
		"}\n";
3306
	formatSource(source,
3307
		"public class Test {\n" + 
3308
		"	/**\n" + 
3309
		"	 * some comment text here\n" + 
3310
		"	 * \n" + 
3311
		"	 * <pre style=\"font-variant:small-caps;\">\n" + 
3312
		"	 *      some text\n" + 
3313
		"	 *           to be styled\n" + 
3314
		"	 *                 a certain way\n" + 
3315
		"	 * \n" + 
3316
		"	 * </pre>\n" + 
3317
		"	 * \n" + 
3318
		"	 * end of comment\n" + 
3319
		"	 */\n" + 
3320
		"	void foo() {\n" + 
3321
		"	}\n" + 
3322
		"\n" + 
3323
		"}\n"
3324
	);
3325
}
3326
public void testBug260011_03() throws JavaModelException {
3327
	String source = 
3328
		"public class Test {\n" + 
3329
		"\n" + 
3330
		"	/**\n" + 
3331
		"	 * Indent char is a space char but not a line delimiters.\n" + 
3332
		"	 * <code>== Character.isWhitespace(ch) && ch != \'\\n\' && ch != \'\\r\'</code>\n" + 
3333
		"	 */\n" + 
3334
		"	public void foo() {\n" + 
3335
		"	}\n" + 
3336
		"}\n";
3337
	formatSource(source,
3338
		"public class Test {\n" + 
3339
		"\n" + 
3340
		"	/**\n" + 
3341
		"	 * Indent char is a space char but not a line delimiters.\n" + 
3342
		"	 * <code>== Character.isWhitespace(ch) && ch != \'\\n\' && ch != \'\\r\'</code>\n" + 
3343
		"	 */\n" + 
3344
		"	public void foo() {\n" + 
3345
		"	}\n" + 
3346
		"}\n"
3347
	);
3348
}
3349
public void testBug260011_04() throws JavaModelException {
3350
	String source = 
3351
		"public class Test {\n" + 
3352
		"\n" + 
3353
		"	/**\n" + 
3354
		"	 * The list of variable declaration fragments (element type: \n" + 
3355
		"	 * <code VariableDeclarationFragment</code>).  Defaults to an empty list.\n" + 
3356
		"	 */\n" + 
3357
		"	int field;\n" + 
3358
		"}\n";
3359
	formatSource(source,
3360
		"public class Test {\n" + 
3361
		"\n" + 
3362
		"	/**\n" + 
3363
		"	 * The list of variable declaration fragments (element type:\n" + 
3364
		"	 * <code VariableDeclarationFragment</code>). Defaults to an empty list.\n" + 
3365
		"	 */\n" + 
3366
		"	int field;\n" + 
3367
		"}\n"
3368
	);
3369
}
3370
public void testBug260011_05() throws JavaModelException {
3371
	String source = 
3372
		"public class Test {\n" + 
3373
		"\n" + 
3374
		"	/**\n" + 
3375
		"	 * Compares version strings.\n" + 
3376
		"	 * \n" + 
3377
		"	 * @return result of comparison, as integer;\n" + 
3378
		"	 * <code><0 if left is less than right </code>\n" + 
3379
		"	 * <code>0 if left is equals to right</code>\n" + 
3380
		"	 * <code>>0 if left is greater than right</code>\n" + 
3381
		"	 */\n" + 
3382
		"	int foo() {\n" + 
3383
		"		return 0;\n" + 
3384
		"	}\n" + 
3385
		"}\n";
3386
	formatSource(source,
3387
		"public class Test {\n" + 
3388
		"\n" + 
3389
		"	/**\n" + 
3390
		"	 * Compares version strings.\n" + 
3391
		"	 * \n" + 
3392
		"	 * @return result of comparison, as integer;\n" + 
3393
		"	 *         <code><0 if left is less than right </code>\n" + 
3394
		"	 *         <code>0 if left is equals to right</code>\n" + 
3395
		"	 *         <code>>0 if left is greater than right</code>\n" + 
3396
		"	 */\n" + 
3397
		"	int foo() {\n" + 
3398
		"		return 0;\n" + 
3399
		"	}\n" + 
3400
		"}\n"
3401
	);
3402
}
3403
public void testBug260011_06() throws JavaModelException {
3404
	String source = 
3405
		"public interface Test {\n" + 
3406
		"\n" + 
3407
		"	/**\n" + 
3408
		"	 * Returns the length of this array.\n" + 
3409
		"	 * \n" + 
3410
		"	 * @return the length of this array\n" + 
3411
		"	 * @exception DebugException if this method fails. Reasons include:<ul>\n" + 
3412
		"	 * <li>Failure communicating with the VM.  The DebugException\'s\n" + 
3413
		"	 * status code contains the underlying exception responsible for\n" + 
3414
		"	 * the failure.</li>\n" + 
3415
		"	 * </ul\n" + 
3416
		"	 */\n" + 
3417
		"	public int getLength();\n" + 
3418
		"}\n";
3419
	formatSource(source,
3420
		"public interface Test {\n" + 
3421
		"\n" + 
3422
		"	/**\n" + 
3423
		"	 * Returns the length of this array.\n" + 
3424
		"	 * \n" + 
3425
		"	 * @return the length of this array\n" + 
3426
		"	 * @exception DebugException\n" + 
3427
		"	 *                if this method fails. Reasons include:\n" + 
3428
		"	 *                <ul>\n" + 
3429
		"	 *                <li>Failure communicating with the VM. The\n" + 
3430
		"	 *                DebugException\'s status code contains the underlying\n" + 
3431
		"	 *                exception responsible for the failure.</li>\n" + 
3432
		"	 *                </ul\n" + 
3433
		"	 */\n" + 
3434
		"	public int getLength();\n" + 
3435
		"}\n"
3436
	);
3437
}
3438
public void testBug260011_07() throws JavaModelException {
3439
	String source = 
3440
		"public interface Test {\n" + 
3441
		"\n" + 
3442
		"	\n" + 
3443
		"	/**\n" + 
3444
		"	 * Returns the change directly associated with this change element or <code\n" + 
3445
		"	 * null</code> if the element isn\'t associated with a change.\n" + 
3446
		"	 * \n" + 
3447
		"	 * @return the change or <code>null</code>\n" + 
3448
		"	 */\n" + 
3449
		"	public String getChange();\n" + 
3450
		"}\n";
3451
	formatSource(source,
3452
		"public interface Test {\n" + 
3453
		"\n" + 
3454
		"	/**\n" + 
3455
		"	 * Returns the change directly associated with this change element or <code\n" + 
3456
		"	 * null</code>\n" + 
3457
		"	 * if the element isn\'t associated with a change.\n" + 
3458
		"	 * \n" + 
3459
		"	 * @return the change or <code>null</code>\n" + 
3460
		"	 */\n" + 
3461
		"	public String getChange();\n" + 
3462
		"}\n"
3463
	);
3464
}
3465
public void testBug260011_08() throws JavaModelException {
3466
	String source = 
3467
		"public interface Test {\n" + 
3468
		"\n" + 
3469
		"	/**\n" + 
3470
		"	 * Answer the element factory for an id, or <code>null</code. if not found.\n" + 
3471
		"	 * @param targetID\n" + 
3472
		"	 * @return\n" + 
3473
		"	 */\n" + 
3474
		"	public int foo(String targetID);\n" + 
3475
		"}\n";
3476
	formatSource(source,
3477
		"public interface Test {\n" + 
3478
		"\n" + 
3479
		"	/**\n" + 
3480
		"	 * Answer the element factory for an id, or <code>null</code. if not found.\n" + 
3481
		"	 * \n" + 
3482
		"	 * @param targetID\n" + 
3483
		"	 * @return\n" + 
3484
		"	 */\n" + 
3485
		"	public int foo(String targetID);\n" + 
3486
		"}\n"
3487
	);
3488
}
3489
public void testBug260011_09() throws JavaModelException {
3490
	String source = 
3491
		"public class Test {\n" + 
3492
		"\n" + 
3493
		"	/**\n" + 
3494
		"     * o   Example: baseCE < a << b <<< q << c < d < e * nextCE(X,1) \n" + 
3495
		"	 */\n" + 
3496
		"	int field;\n" + 
3497
		"}\n";
3498
	formatSource(source,
3499
		"public class Test {\n" + 
3500
		"\n" + 
3501
		"	/**\n" + 
3502
		"	 * o Example: baseCE < a << b <<< q << c < d < e * nextCE(X,1)\n" + 
3503
		"	 */\n" + 
3504
		"	int field;\n" + 
3505
		"}\n"
3506
	);
3507
}
3508
public void testBug260011_09b() throws JavaModelException {
3509
	String source = 
3510
		"public class Test {\n" + 
3511
		"\n" + 
3512
		"	/**\n" + 
3513
		"     * o   Example: baseCE < a < b < q < c < p < e * nextCE(X,1) \n" + 
3514
		"	 */\n" + 
3515
		"	int field;\n" + 
3516
		"}\n";
3517
	formatSource(source,
3518
		"public class Test {\n" + 
3519
		"\n" + 
3520
		"	/**\n" + 
3521
		"	 * o Example: baseCE < a < b < q < c < p < e * nextCE(X,1)\n" + 
3522
		"	 */\n" + 
3523
		"	int field;\n" + 
3524
		"}\n"
3525
	);
3526
}
3527
public void testBug260011_10() throws JavaModelException {
3528
	String source = 
3529
		"public interface Test {\n" + 
3530
		"\n" + 
3531
		"	/**\n" + 
3532
		"	 * Creates and opens a dialog to edit the given template.\n" + 
3533
		"	 * <p\n" + 
3534
		"	 * Subclasses may override this method to provide a custom dialog.</p>\n" + 
3535
		"	 */\n" + 
3536
		"	void foo();\n" + 
3537
		"}\n";
3538
	formatSource(source,
3539
		"public interface Test {\n" + 
3540
		"\n" + 
3541
		"	/**\n" + 
3542
		"	 * Creates and opens a dialog to edit the given template.\n" + 
3543
		"	 * <p\n" + 
3544
		"	 * Subclasses may override this method to provide a custom dialog.\n" + 
3545
		"	 * </p>\n" + 
3546
		"	 */\n" + 
3547
		"	void foo();\n" + 
3548
		"}\n"
3549
	);
3550
}
3551
public void testBug260011_11() throws JavaModelException {
3552
	String source = 
3553
		"public class Test {\n" + 
3554
		"\n" + 
3555
		"    /** \n" + 
3556
		"     * <p>Binary property IDS_Trinary_Operator (new).</p> \n" + 
3557
		"     * <p?For programmatic determination of Ideographic Description \n" + 
3558
		"     * Sequences.</p> \n" + 
3559
		"     * @stable ICU 2.6\n" + 
3560
		"     */ \n" + 
3561
		"    public static final int IDS_TRINARY_OPERATOR = 19; \n" + 
3562
		"}\n";
3563
	formatSource(source,
3564
		"public class Test {\n" + 
3565
		"\n" + 
3566
		"	/**\n" + 
3567
		"	 * <p>\n" + 
3568
		"	 * Binary property IDS_Trinary_Operator (new).\n" + 
3569
		"	 * </p>\n" + 
3570
		"	 * <p\n" + 
3571
		"	 * ?For programmatic determination of Ideographic Description Sequences.\n" + 
3572
		"	 * </p>\n" + 
3573
		"	 * \n" + 
3574
		"	 * @stable ICU 2.6\n" + 
3575
		"	 */\n" + 
3576
		"	public static final int IDS_TRINARY_OPERATOR = 19;\n" + 
3577
		"}\n"
3578
	);
3579
}
3580
3581
/**
3232
 * @bug 260274: [formatter] * character is removed while formatting block comments
3582
 * @bug 260274: [formatter] * character is removed while formatting block comments
3233
 * @test Ensure that the comment formatter keep '*' characters while formatting block comments
3583
 * @test Ensure that the comment formatter keep '*' characters while formatting block comments
3234
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=260274"
3584
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=260274"
(-)formatter/org/eclipse/jdt/internal/formatter/FormatterCommentParser.java (-20 / +53 lines)
Lines 142-154 Link Here
142
	int length = htmlTag == null ? 0 : htmlTag.length;
142
	int length = htmlTag == null ? 0 : htmlTag.length;
143
	int tagId = 0;
143
	int tagId = 0;
144
	if (length > 0) {
144
	if (length > 0) {
145
		for (int i=0, max=JAVADOC_SPECIAL_TAGS.length; i<max; i++) {
146
			char[] tag = JAVADOC_SPECIAL_TAGS[i];
147
			if (length == tag.length && CharOperation.equals(htmlTag, tag, false)) {
148
				tagId = JAVADOC_SPECIAL_TAGS_ID;
149
				break;
150
			}
151
		}
152
		for (int i=0, max=JAVADOC_SINGLE_BREAK_TAG.length; i<max; i++) {
145
		for (int i=0, max=JAVADOC_SINGLE_BREAK_TAG.length; i<max; i++) {
153
			char[] tag = JAVADOC_SINGLE_BREAK_TAG[i];
146
			char[] tag = JAVADOC_SINGLE_BREAK_TAG[i];
154
			if (length == tag.length && CharOperation.equals(htmlTag, tag, false)) {
147
			if (length == tag.length && CharOperation.equals(htmlTag, tag, false)) {
Lines 193-199 Link Here
193
    boolean valid = false;
186
    boolean valid = false;
194
    boolean incremented = false;
187
    boolean incremented = false;
195
    int start = this.scanner.currentPosition;
188
    int start = this.scanner.currentPosition;
189
    int currentPosition = start;
196
    int htmlPtr = this.htmlTagsPtr;
190
    int htmlPtr = this.htmlTagsPtr;
191
    char firstChar = peekChar();
192
    boolean hasWhitespaces = firstChar == ' ' || ScannerHelper.isWhitespace(firstChar);
197
	try {
193
	try {
198
	    int token = readTokenAndConsume();
194
	    int token = readTokenAndConsume();
199
	    char[] htmlTag;
195
	    char[] htmlTag;
Lines 240-245 Link Here
240
		    		}
236
		    		}
241
				}
237
				}
242
				// Accept xhtml syntax
238
				// Accept xhtml syntax
239
				currentPosition = this.scanner.currentPosition;
243
				if (readToken() == TerminalTokens.TokenNameDIVIDE) {
240
				if (readToken() == TerminalTokens.TokenNameDIVIDE) {
244
					consumeToken();
241
					consumeToken();
245
				}
242
				}
Lines 268-291 Link Here
268
				// set closing flag
265
				// set closing flag
269
				htmlIndex |= JAVADOC_CLOSED_TAG;
266
				htmlIndex |= JAVADOC_CLOSED_TAG;
270
				closing = true;
267
				closing = true;
268
				currentPosition = this.scanner.currentPosition;
271
	    		break;
269
	    		break;
272
	    	default:
270
	    	default:
273
    			return false;
271
    			return false;
274
	    }
272
	    }
275
	    if ((token = readTokenAndConsume()) != TerminalTokens.TokenNameGREATER) {
273
	    
276
	    	if ((htmlIndex & JAVADOC_SPECIAL_TAGS_ID) == JAVADOC_SPECIAL_TAGS_ID) {
274
	    // Looking for tag closing
277
	    		// Special tags may have attributes, so consume tokens until the greater token is encountered
275
	    switch (token = readTokenAndConsume()) {
278
	    		while (token != TerminalTokens.TokenNameGREATER) {
276
	    	case TerminalTokens.TokenNameLESS:
279
	    			token = readTokenAndConsume();
277
	    	case TerminalTokens.TokenNameLESS_EQUAL:
280
	    			if (token == TerminalTokens.TokenNameEOF) {
278
	    		// consider that the closing '>' is missing
281
	    				return false;
279
	    		return false;
282
	    			}
280
	    	case TerminalTokens.TokenNameGREATER:
281
	    		// simple tag without attributes
282
	    		break;
283
	    	case TerminalTokens.TokenNameGREATER_EQUAL:
284
	    	case TerminalTokens.TokenNameRIGHT_SHIFT:
285
	    	case TerminalTokens.TokenNameRIGHT_SHIFT_EQUAL:
286
	    		// simple tag without attributes, but the closing '>' is followed by an '=' or '>'
287
	    		break;
288
	    	default:
289
	    		this.index = currentPosition;
290
	    		loop: while (true) {
291
//	    			currentPosition = this.index;
292
				    switch (readChar()) {
293
				    	case '<':
294
				    		if (hasWhitespaces) {
295
				    			// not 100% sure this is a tag definition => give up
296
				    			return false;
297
				    		}
298
				    		// opening tag => consider the current one as closed
299
				    		this.index = currentPosition;
300
				    		this.scanner.startPosition = currentPosition;
301
				    		this.scanner.currentPosition = currentPosition;
302
				    		this.scanner.currentCharacter = '<';
303
				    		break loop;
304
				    	case '>':
305
				    		// simple tag without attributes
306
				    		this.scanner.startPosition = this.index;
307
				    		this.scanner.currentPosition = this.index;
308
				    		this.scanner.currentCharacter = peekChar();
309
				    		break loop;
310
			    		default:
311
			    			break;
312
				    }
313
				    if (this.index >= this.javadocTextEnd) {
314
		    			// the end of the comment is reached => consider current tag as closed
315
			    		this.index = currentPosition;
316
			    		this.scanner.startPosition = currentPosition;
317
			    		this.scanner.currentPosition = currentPosition;
318
			    		break;
319
				    }
283
	    		}
320
	    		}
284
	    	} else {
321
		}
285
		    	// invalid syntax
286
				return false;
287
	    	}
288
	    }
289
322
290
	    // Push texts
323
	    // Push texts
291
		if (this.lineStarted && this.textStart != -1 && this.textStart < endTextPosition) {
324
		if (this.lineStarted && this.textStart != -1 && this.textStart < endTextPosition) {
(-)formatter/org/eclipse/jdt/internal/formatter/comment/IJavaDocTagConstants.java (-13 / +2 lines)
Lines 67-74 Link Here
67
	};
67
	};
68
68
69
	/** Javadoc parameter tags */
69
	/** Javadoc parameter tags */
70
	// TODO (eric) should have another name than 'param' for the following tags
70
	// TODO (frederic) should have another name than 'param' for the following tags
71
	// TODO (eric) investigate how and why this list was created
71
	// TODO (frederic) investigate how and why this list was created
72
	public static final char[][] JAVADOC_PARAM_TAGS= new char[][] {
72
	public static final char[][] JAVADOC_PARAM_TAGS= new char[][] {
73
			"@exception".toCharArray(), //$NON-NLS-1$
73
			"@exception".toCharArray(), //$NON-NLS-1$
74
			"@param".toCharArray(), //$NON-NLS-1$
74
			"@param".toCharArray(), //$NON-NLS-1$
Lines 89-104 Link Here
89
			"tr".toCharArray(), //$NON-NLS-1$
89
			"tr".toCharArray(), //$NON-NLS-1$
90
	};
90
	};
91
91
92
	/**
93
	 * Following table is used to identify special tags which may have more complex
94
	 * opening than just &lt;name&gt;
95
	 */
96
	public static final char[][] JAVADOC_SPECIAL_TAGS= new char[][] {
97
			"table".toCharArray(), //$NON-NLS-1$
98
			"tr".toCharArray(), //$NON-NLS-1$
99
			"td".toCharArray(), //$NON-NLS-1$
100
	};
101
102
	/** Javadoc tag prefix */
92
	/** Javadoc tag prefix */
103
	public static final char JAVADOC_TAG_PREFIX= '@';
93
	public static final char JAVADOC_TAG_PREFIX= '@';
104
94
Lines 151-155 Link Here
151
	static final int JAVADOC_SEPARATOR_TAGS_ID = 0x1000;
141
	static final int JAVADOC_SEPARATOR_TAGS_ID = 0x1000;
152
	static final int JAVADOC_SINGLE_TAGS_ID = JAVADOC_SINGLE_BREAK_TAG_ID; // ID max for tags ID with no opening/closing (e.g. <bla>....</bla>)
142
	static final int JAVADOC_SINGLE_TAGS_ID = JAVADOC_SINGLE_BREAK_TAG_ID; // ID max for tags ID with no opening/closing (e.g. <bla>....</bla>)
153
	static final int JAVADOC_CLOSED_TAG = 0x10000;
143
	static final int JAVADOC_CLOSED_TAG = 0x10000;
154
	static final int JAVADOC_SPECIAL_TAGS_ID = 0x20000;
155
}
144
}

Return to bug 260011