Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 200207 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java (-104 / +108 lines)
Lines 1364-1473 Link Here
1364
					}
1364
					}
1365
					throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
1365
					throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
1366
				case '"' :
1366
				case '"' :
1367
					try {
1367
					return scanStringLiteral();
1368
						// consume next character
1369
						this.unicodeAsBackSlash = false;
1370
						boolean isUnicode = false;
1371
						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
1372
							&& (this.source[this.currentPosition] == 'u')) {
1373
							getNextUnicodeChar();
1374
							isUnicode = true;
1375
						} else {
1376
							if (this.withoutUnicodePtr != 0) {
1377
								unicodeStore();
1378
							}
1379
						}
1380
1381
						while (this.currentCharacter != '"') {
1382
							/**** \r and \n are not valid in string literals ****/
1383
							if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
1384
								// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
1385
								if (isUnicode) {
1386
									int start = this.currentPosition;
1387
									for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
1388
										if (this.currentPosition >= this.eofPosition) {
1389
											this.currentPosition = start;
1390
											break;
1391
										}
1392
										if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
1393
											isUnicode = true;
1394
											getNextUnicodeChar();
1395
										} else {
1396
											isUnicode = false;
1397
										}
1398
										if (!isUnicode && this.currentCharacter == '\n') {
1399
											this.currentPosition--; // set current position on new line character
1400
											break;
1401
										}
1402
										if (this.currentCharacter == '\"') {
1403
											throw new InvalidInputException(INVALID_CHAR_IN_STRING);
1404
										}
1405
									}
1406
								} else {
1407
									this.currentPosition--; // set current position on new line character
1408
								}
1409
								throw new InvalidInputException(INVALID_CHAR_IN_STRING);
1410
							}
1411
							if (this.currentCharacter == '\\') {
1412
								if (this.unicodeAsBackSlash) {
1413
									this.withoutUnicodePtr--;
1414
									// consume next character
1415
									this.unicodeAsBackSlash = false;
1416
									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
1417
										getNextUnicodeChar();
1418
										isUnicode = true;
1419
										this.withoutUnicodePtr--;
1420
									} else {
1421
										isUnicode = false;
1422
									}
1423
								} else {
1424
									if (this.withoutUnicodePtr == 0) {
1425
										unicodeInitializeBuffer(this.currentPosition - this.startPosition);
1426
									}
1427
									this.withoutUnicodePtr --;
1428
									this.currentCharacter = this.source[this.currentPosition++];
1429
								}
1430
								// we need to compute the escape character in a separate buffer
1431
								scanEscapeCharacter();
1432
								if (this.withoutUnicodePtr != 0) {
1433
									unicodeStore();
1434
								}
1435
							}
1436
							// consume next character
1437
							this.unicodeAsBackSlash = false;
1438
							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
1439
								&& (this.source[this.currentPosition] == 'u')) {
1440
								getNextUnicodeChar();
1441
								isUnicode = true;
1442
							} else {
1443
								isUnicode = false;
1444
								if (this.withoutUnicodePtr != 0) {
1445
									unicodeStore();
1446
								}
1447
							}
1448
1449
						}
1450
					} catch (IndexOutOfBoundsException e) {
1451
						this.currentPosition--;
1452
						throw new InvalidInputException(UNTERMINATED_STRING);
1453
					} catch (InvalidInputException e) {
1454
						if (e.getMessage().equals(INVALID_ESCAPE)) {
1455
							// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
1456
							for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
1457
								if (this.currentPosition + lookAhead == this.eofPosition)
1458
									break;
1459
								if (this.source[this.currentPosition + lookAhead] == '\n')
1460
									break;
1461
								if (this.source[this.currentPosition + lookAhead] == '\"') {
1462
									this.currentPosition += lookAhead + 1;
1463
									break;
1464
								}
1465
							}
1466
1467
						}
1468
						throw e; // rethrow
1469
					}
1470
					return TokenNameStringLiteral;
1471
				case '/' :
1368
				case '/' :
1472
					if (!this.skipComments) {
1369
					if (!this.skipComments) {
1473
						int test = getNextChar('/', '*');
1370
						int test = getNextChar('/', '*');
Lines 1717-1722 Link Here
1717
	}
1614
	}
1718
	return TokenNameEOF;
1615
	return TokenNameEOF;
1719
}
1616
}
1617
1618
protected int scanStringLiteral() throws InvalidInputException {
1619
	try {
1620
		// consume next character
1621
		this.unicodeAsBackSlash = false;
1622
		boolean isUnicode = false;
1623
		if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
1624
			&& (this.source[this.currentPosition] == 'u')) {
1625
			getNextUnicodeChar();
1626
			isUnicode = true;
1627
		} else {
1628
			if (this.withoutUnicodePtr != 0) {
1629
				unicodeStore();
1630
			}
1631
		}
1632
1633
		while (this.currentCharacter != '"') {
1634
			/**** \r and \n are not valid in string literals ****/
1635
			if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
1636
				// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
1637
				if (isUnicode) {
1638
					int start = this.currentPosition;
1639
					for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
1640
						if (this.currentPosition >= this.eofPosition) {
1641
							this.currentPosition = start;
1642
							break;
1643
						}
1644
						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
1645
							isUnicode = true;
1646
							getNextUnicodeChar();
1647
						} else {
1648
							isUnicode = false;
1649
						}
1650
						if (!isUnicode && this.currentCharacter == '\n') {
1651
							this.currentPosition--; // set current position on new line character
1652
							break;
1653
						}
1654
						if (this.currentCharacter == '\"') {
1655
							throw new InvalidInputException(INVALID_CHAR_IN_STRING);
1656
						}
1657
					}
1658
				} else {
1659
					this.currentPosition--; // set current position on new line character
1660
				}
1661
				throw new InvalidInputException(INVALID_CHAR_IN_STRING);
1662
			}
1663
			if (this.currentCharacter == '\\') {
1664
				if (this.unicodeAsBackSlash) {
1665
					this.withoutUnicodePtr--;
1666
					// consume next character
1667
					this.unicodeAsBackSlash = false;
1668
					if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
1669
						getNextUnicodeChar();
1670
						isUnicode = true;
1671
						this.withoutUnicodePtr--;
1672
					} else {
1673
						isUnicode = false;
1674
					}
1675
				} else {
1676
					if (this.withoutUnicodePtr == 0) {
1677
						unicodeInitializeBuffer(this.currentPosition - this.startPosition);
1678
					}
1679
					this.withoutUnicodePtr --;
1680
					this.currentCharacter = this.source[this.currentPosition++];
1681
				}
1682
				// we need to compute the escape character in a separate buffer
1683
				scanEscapeCharacter();
1684
				if (this.withoutUnicodePtr != 0) {
1685
					unicodeStore();
1686
				}
1687
			}
1688
			// consume next character
1689
			this.unicodeAsBackSlash = false;
1690
			if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
1691
				&& (this.source[this.currentPosition] == 'u')) {
1692
				getNextUnicodeChar();
1693
				isUnicode = true;
1694
			} else {
1695
				isUnicode = false;
1696
				if (this.withoutUnicodePtr != 0) {
1697
					unicodeStore();
1698
				}
1699
			}
1700
1701
		}
1702
	} catch (IndexOutOfBoundsException e) {
1703
		this.currentPosition--;
1704
		throw new InvalidInputException(UNTERMINATED_STRING);
1705
	} catch (InvalidInputException e) {
1706
		if (e.getMessage().equals(INVALID_ESCAPE)) {
1707
			// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
1708
			for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
1709
				if (this.currentPosition + lookAhead == this.eofPosition)
1710
					break;
1711
				if (this.source[this.currentPosition + lookAhead] == '\n')
1712
					break;
1713
				if (this.source[this.currentPosition + lookAhead] == '\"') {
1714
					this.currentPosition += lookAhead + 1;
1715
					break;
1716
				}
1717
			}
1718
1719
		}
1720
		throw e; // rethrow
1721
	}
1722
	return TokenNameStringLiteral;
1723
}
1720
public void getNextUnicodeChar()
1724
public void getNextUnicodeChar()
1721
	throws InvalidInputException {
1725
	throws InvalidInputException {
1722
	//VOID
1726
	//VOID
(-)compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java (-2 / +2 lines)
Lines 95-101 Link Here
95
95
96
	protected AbstractCommentParser(Parser sourceParser) {
96
	protected AbstractCommentParser(Parser sourceParser) {
97
		this.sourceParser = sourceParser;
97
		this.sourceParser = sourceParser;
98
		this.scanner = new Scanner(false, false, false, ClassFileConstants.JDK1_3, null, null, true/*taskCaseSensitive*/);
98
		this.scanner = new CommentScanner(false, false, false, ClassFileConstants.JDK1_3, null, null, true/*taskCaseSensitive*/, this);
99
		this.identifierStack = new char[20][];
99
		this.identifierStack = new char[20][];
100
		this.identifierPositionStack = new long[20];
100
		this.identifierPositionStack = new long[20];
101
		this.identifierLengthStack = new int[10];
101
		this.identifierLengthStack = new int[10];
Lines 1152-1158 Link Here
1152
						if (currentError.length>0 && currentError[0] == '"') {
1152
						if (currentError.length>0 && currentError[0] == '"') {
1153
							if (this.reportProblems) {
1153
							if (this.reportProblems) {
1154
								boolean isUrlRef = false;
1154
								boolean isUrlRef = false;
1155
								if (this.tagValue == TAG_SEE_VALUE) {
1155
								if (this.tagValue == TAG_SEE_VALUE || this.tagValue == TAG_LINK_VALUE) {
1156
									int length=currentError.length, i=1 /* first char is " */;
1156
									int length=currentError.length, i=1 /* first char is " */;
1157
									while (i<length && ScannerHelper.isLetter(currentError[i])) {
1157
									while (i<length && ScannerHelper.isLetter(currentError[i])) {
1158
										i++;
1158
										i++;
(-)compiler/org/eclipse/jdt/internal/compiler/parser/CommentScanner.java (+175 lines)
Added Link Here
1
package org.eclipse.jdt.internal.compiler.parser;
2
3
import org.eclipse.jdt.core.compiler.InvalidInputException;
4
5
public class CommentScanner extends Scanner {
6
7
	protected AbstractCommentParser parser;
8
	
9
	public CommentScanner(
10
			boolean tokenizeComments,
11
			boolean tokenizeWhiteSpace,
12
			boolean checkNonExternalizedStringLiterals,
13
			long sourceLevel,
14
			char[][] taskTags,
15
			char[][] taskPriorities,
16
			boolean isTaskCaseSensitive,
17
			AbstractCommentParser parser) {
18
19
		super(
20
			tokenizeComments,
21
			tokenizeWhiteSpace,
22
			checkNonExternalizedStringLiterals,
23
			sourceLevel,
24
			taskTags,
25
			taskPriorities,
26
			isTaskCaseSensitive);
27
		this.parser = parser; 
28
	}	
29
	
30
	protected int scanStringLiteral() throws InvalidInputException {
31
		try {
32
			// consume next character
33
			boolean isUnicode = consumeNextCharacter();
34
			boolean possibleNextTag = true;
35
			int lastClosingBrace = -1;
36
			int endOfToken = this.currentPosition;
37
			while (this.currentCharacter != '"') {
38
					// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
39
				if (isUnicode) {
40
					int start = this.currentPosition;
41
					for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
42
						if (this.currentPosition >= this.eofPosition) {
43
							this.currentPosition = start;
44
							break;
45
						}
46
						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
47
							isUnicode = true;
48
							getNextUnicodeChar();
49
						} else {
50
							isUnicode = false;
51
						}
52
						if (!isUnicode && this.currentCharacter == '\n') {
53
							this.currentPosition--; // set current position on new line character
54
							break;
55
						}
56
						if (this.currentCharacter == '\"') {
57
							throw new InvalidInputException(INVALID_CHAR_IN_STRING);
58
						}
59
					}
60
				}
61
				else {
62
					switch(this.currentCharacter) {
63
						case '@':
64
							if (possibleNextTag) {
65
								if (lastClosingBrace != -1) {
66
									this.currentPosition = lastClosingBrace;
67
								}
68
								else {
69
									this.currentPosition = endOfToken;
70
								}
71
								throw new InvalidInputException(UNTERMINATED_STRING);
72
							}
73
							break;
74
						case '}':
75
							lastClosingBrace = this.currentPosition;
76
							if (this.parser.inlineTagStarted) {
77
								throw new InvalidInputException(UNTERMINATED_STRING);
78
							}
79
							break;
80
						case '*':
81
							break;
82
						case '\n':
83
						case '\r':
84
							if (!possibleNextTag) {
85
								if (lastClosingBrace != -1) {
86
									endOfToken = this.currentPosition -1;
87
								}
88
								else {
89
									endOfToken = this.currentPosition -1;
90
								}
91
							}
92
							possibleNextTag = true;
93
							break;
94
						case '\\':
95
							lastClosingBrace = -1;
96
							if (this.unicodeAsBackSlash) {
97
								this.withoutUnicodePtr--;
98
								// consume next character
99
								this.unicodeAsBackSlash = false;
100
								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
101
									getNextUnicodeChar();
102
									isUnicode = true;
103
									this.withoutUnicodePtr--;
104
								} else {
105
									isUnicode = false;
106
								}
107
							} else {
108
								if (this.withoutUnicodePtr == 0) {
109
									unicodeInitializeBuffer(this.currentPosition - this.startPosition);
110
								}
111
								this.withoutUnicodePtr --;
112
								this.currentCharacter = this.source[this.currentPosition++];
113
							}
114
							// we need to compute the escape character in a separate buffer
115
							scanEscapeCharacter();
116
							if (this.withoutUnicodePtr != 0) {
117
								unicodeStore();
118
							}
119
							break;
120
						default:
121
							if ( possibleNextTag && this.currentCharacter == '{') {
122
								possibleNextTag = true;
123
							}
124
							else if (!ScannerHelper.isWhitespace(this.currentCharacter)) {
125
								lastClosingBrace = -1;
126
								possibleNextTag = false;
127
							}
128
							break;
129
					}						
130
				}
131
132
				// consume next character
133
				isUnicode = consumeNextCharacter();
134
135
			}
136
		} catch (IndexOutOfBoundsException e) {
137
			this.currentPosition--;
138
			throw new InvalidInputException(UNTERMINATED_STRING);
139
		} catch (InvalidInputException e) {
140
			if (e.getMessage().equals(INVALID_ESCAPE)) {
141
				// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
142
				for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
143
					if (this.currentPosition + lookAhead == this.eofPosition)
144
						break;
145
					if (this.source[this.currentPosition + lookAhead] == '\n')
146
						break;
147
					if (this.source[this.currentPosition + lookAhead] == '\"') {
148
						this.currentPosition += lookAhead + 1;
149
						break;
150
					}
151
				}
152
153
			}
154
			throw e; // rethrow
155
		}
156
		return TokenNameStringLiteral;
157
	}
158
159
	private boolean consumeNextCharacter() throws InvalidInputException {
160
		this.unicodeAsBackSlash = false;
161
		boolean isUnicode = false;
162
		if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
163
			&& (this.source[this.currentPosition] == 'u')) {
164
			getNextUnicodeChar();
165
			isUnicode = true;
166
		} else {
167
			if (this.withoutUnicodePtr != 0) {
168
				unicodeStore();
169
			}
170
		}
171
		return isUnicode;
172
		
173
		
174
	}	
175
}
(-)src/org/eclipse/jdt/core/tests/compiler/regression/JavadocBugsTest.java (-2 / +104 lines)
Lines 7529-7535 Link Here
7529
		"1. ERROR in pkg\\X.java (at line 5)\n" + 
7529
		"1. ERROR in pkg\\X.java (at line 5)\n" + 
7530
		"	* {@link \"http://www.eclipse.org/}\n" + 
7530
		"	* {@link \"http://www.eclipse.org/}\n" + 
7531
		"	         ^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
7531
		"	         ^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
7532
		"Javadoc: Invalid reference\n" + 
7532
		"Javadoc: Invalid URL reference. Double quote the reference or use the href syntax\n" + 
7533
		"----------\n" + 
7533
		"----------\n" + 
7534
		"2. ERROR in pkg\\X.java (at line 6)\n" + 
7534
		"2. ERROR in pkg\\X.java (at line 6)\n" + 
7535
		"	* @see \"http://www.eclipse.org/\n" + 
7535
		"	* @see \"http://www.eclipse.org/\n" + 
Lines 8321-8324 Link Here
8321
	}
8321
	}
8322
}
8322
}
8323
8323
8324
}
8324
public void testBug200207() {
8325
	runNegativeTest(
8326
		new String[] {
8327
				"XYZ.java", 
8328
				"/** \n" +
8329
				"* " +
8330
				"* @see \"Unterminated\n" +
8331
				"* @see String\"\n" +
8332
				"*/ \n" + 
8333
				"public class XYZ { \n"+
8334
				"}\n"
8335
				},
8336
				"----------\n" + 
8337
				"1. ERROR in XYZ.java (at line 2)\n" + 
8338
				"	* * @see \"Unterminated\n" + 
8339
				"	         ^^^^^^^^^^^^^\n" + 
8340
				"Javadoc: Invalid reference\n" + 
8341
				"----------\n" + 
8342
				"2. ERROR in XYZ.java (at line 3)\n" + 
8343
				"	* @see String\"\n" + 
8344
				"	       ^^^^^^^\n" + 
8345
				"Javadoc: Malformed reference (missing end space separator)\n" + 
8346
				"----------\n");
8347
}	
8348
8349
public void testBug200207_2() {
8350
	runConformTest(
8351
		new String[] {
8352
				"XYZ.java", 
8353
				"/** \n" +
8354
				"* " +
8355
				"* @see \"Unterminated\n" +
8356
				"* String\"\n" +
8357
				"* @author jay\n" +
8358
				"* @see \"Alice in \n" +
8359
				"* still ** @@ not closed @\n" +
8360
				"* wonder*land@\"\n" +
8361
				"*/ \n" + 
8362
				"public class XYZ { \n"+
8363
				"}\n"
8364
				});
8365
}
8366
8367
public void testBug200207_3() {
8368
	runConformTest(
8369
		new String[] {
8370
				"XYZ.java", 
8371
				"/** \n" +
8372
				"* " +
8373
				"* @see <a href=\"http://www.eclipse.org" +
8374
				"* \">Eclipse</a>" +
8375
				"*/ \n" + 
8376
				"public class XYZ { \n"+
8377
				"}\n"
8378
				},
8379
				"");
8380
}
8381
8382
public void testBug200207_4() {
8383
	runNegativeTest(
8384
		new String[] {
8385
				"XYZ.java", 
8386
				"/** \n" +
8387
				"* This test includes valid {@link \"http://www.eclipse.org\"}, {@author jay} \n" +
8388
				"* invalid {@link \"http://eclipse.org} inline tags \n" +
8389
				"* " +
8390
				"*/ \n" + 
8391
				"public class XYZ { \n"+
8392
				"}\n"
8393
				},
8394
				"----------\n" + 
8395
				"1. ERROR in XYZ.java (at line 3)\n" + 
8396
				"	* invalid {@link \"http://eclipse.org} inline tags \n" + 
8397
				"	                 ^^^^^^^^^^^^^^^^^^^^\n" + 
8398
				"Javadoc: Invalid URL reference. Double quote the reference or use the href syntax\n" + 
8399
				"----------\n");
8400
}
8401
8402
public void testBug200207_5() {
8403
	runNegativeTest(
8404
		new String[] {
8405
				"XYZ.java", 
8406
				"/** \n" +
8407
				"* This test checks for two invalid {@link \"http://www.eclipse.org} inline {@link http://eclipse.org\"} tags \n" +
8408
				"* " +
8409
				"*/ \n" + 
8410
				"public class XYZ { \n"+
8411
				"}\n"
8412
				},
8413
				"----------\n" + 
8414
				"1. ERROR in XYZ.java (at line 2)\n" + 
8415
				"	* This test checks for two invalid {@link \"http://www.eclipse.org} inline {@link http://eclipse.org\"} tags \n" + 
8416
				"	                                          ^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
8417
				"Javadoc: Invalid URL reference. Double quote the reference or use the href syntax\n" + 
8418
				"----------\n" + 
8419
				"2. ERROR in XYZ.java (at line 2)\n" + 
8420
				"	* This test checks for two invalid {@link \"http://www.eclipse.org} inline {@link http://eclipse.org\"} tags \n" + 
8421
				"	                                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
8422
				"Javadoc: Invalid URL reference. Double quote the reference or use the href syntax\n" + 
8423
				"----------\n");
8424
}
8425
8426
}

Return to bug 200207