Lines 38-43
Link Here
|
38 |
// returns whether this JavadocParser should report errors or not (overrides reportProblems) |
38 |
// returns whether this JavadocParser should report errors or not (overrides reportProblems) |
39 |
// see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=192449" |
39 |
// see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=192449" |
40 |
public boolean shouldReportProblems = true; |
40 |
public boolean shouldReportProblems = true; |
|
|
41 |
|
42 |
// flag to let the parser know that the current tag is waiting for a description |
43 |
// see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=222900" |
44 |
private int tagWaitingForDescription; |
41 |
|
45 |
|
42 |
public JavadocParser(Parser sourceParser) { |
46 |
public JavadocParser(Parser sourceParser) { |
43 |
super(sourceParser); |
47 |
super(sourceParser); |
Lines 58-63
Link Here
|
58 |
this.firstTagPosition = this.sourceParser.scanner.commentTagStarts[commentPtr]; |
62 |
this.firstTagPosition = this.sourceParser.scanner.commentTagStarts[commentPtr]; |
59 |
this.validValuePositions = -1; |
63 |
this.validValuePositions = -1; |
60 |
this.invalidValuePositions = -1; |
64 |
this.invalidValuePositions = -1; |
|
|
65 |
this.tagWaitingForDescription = NO_TAG_VALUE; |
61 |
|
66 |
|
62 |
// Init javadoc if necessary |
67 |
// Init javadoc if necessary |
63 |
if (this.checkDocComment) { |
68 |
if (this.checkDocComment) { |
Lines 339-351
Link Here
|
339 |
*/ |
344 |
*/ |
340 |
protected boolean parseThrows() { |
345 |
protected boolean parseThrows() { |
341 |
boolean valid = super.parseThrows(); |
346 |
boolean valid = super.parseThrows(); |
342 |
if (valid && this.reportProblems && verifyEndLine(this.scanner.currentPosition)) { |
347 |
this.tagWaitingForDescription = valid && this.reportProblems ? TAG_THROWS_VALUE : NO_TAG_VALUE; |
343 |
// retrieve last identifier position (valid as, in the super method, we already parsed an identifier) |
|
|
344 |
int start = (int) (this.identifierPositionStack[0] >>> 32); |
345 |
int end = (int) this.identifierPositionStack[this.identifierPtr]; |
346 |
this.sourceParser.problemReporter().javadocMissingTagDescriptionAfterReference(start, end, this.sourceParser.modifiers); |
347 |
return false; |
348 |
} |
349 |
return valid; |
348 |
return valid; |
350 |
} |
349 |
} |
351 |
|
350 |
|
Lines 408-413
Link Here
|
408 |
|
407 |
|
409 |
protected boolean parseTag(int previousPosition) throws InvalidInputException { |
408 |
protected boolean parseTag(int previousPosition) throws InvalidInputException { |
410 |
|
409 |
|
|
|
410 |
// Signal tag missing description if necessary |
411 |
switch (this.tagWaitingForDescription) { |
412 |
case TAG_PARAM_VALUE: |
413 |
case TAG_THROWS_VALUE: |
414 |
int start = (int) (this.identifierPositionStack[0] >>> 32); |
415 |
int end = (int) this.identifierPositionStack[this.identifierPtr]; |
416 |
this.sourceParser.problemReporter().javadocMissingTagDescriptionAfterReference(start, end, this.sourceParser.modifiers); |
417 |
break; |
418 |
case NO_TAG_VALUE: |
419 |
break; |
420 |
default: |
421 |
this.sourceParser.problemReporter().javadocMissingTagDescription(TAG_NAMES[this.tagWaitingForDescription], this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers); |
422 |
break; |
423 |
} |
424 |
this.tagWaitingForDescription = NO_TAG_VALUE; |
425 |
|
411 |
// Read tag name |
426 |
// Read tag name |
412 |
int currentPosition = this.index; |
427 |
int currentPosition = this.index; |
413 |
int token = readTokenAndConsume(); |
428 |
int token = readTokenAndConsume(); |
Lines 486-492
Link Here
|
486 |
|
501 |
|
487 |
// Decide which parse to perform depending on tag name |
502 |
// Decide which parse to perform depending on tag name |
488 |
this.tagValue = TAG_OTHERS_VALUE; |
503 |
this.tagValue = TAG_OTHERS_VALUE; |
489 |
boolean alreadyParsedTag = false; |
|
|
490 |
boolean valid = false; |
504 |
boolean valid = false; |
491 |
switch (token) { |
505 |
switch (token) { |
492 |
case TerminalTokens.TokenNameIdentifier : |
506 |
case TerminalTokens.TokenNameIdentifier : |
Lines 494-499
Link Here
|
494 |
case 'a': |
508 |
case 'a': |
495 |
if (length == TAG_AUTHOR_LENGTH && CharOperation.equals(TAG_AUTHOR, tagName)) { |
509 |
if (length == TAG_AUTHOR_LENGTH && CharOperation.equals(TAG_AUTHOR, tagName)) { |
496 |
this.tagValue = TAG_AUTHOR_VALUE; |
510 |
this.tagValue = TAG_AUTHOR_VALUE; |
|
|
511 |
this.tagWaitingForDescription = this.tagValue; |
497 |
} |
512 |
} |
498 |
break; |
513 |
break; |
499 |
case 'c': |
514 |
case 'c': |
Lines 502-507
Link Here
|
502 |
valid = parseIdentifierTag(false); // TODO (frederic) reconsider parameter value when @category will be significant in spec |
517 |
valid = parseIdentifierTag(false); // TODO (frederic) reconsider parameter value when @category will be significant in spec |
503 |
} else if (length == TAG_CODE_LENGTH && this.inlineTagStarted && CharOperation.equals(TAG_CODE, tagName)) { |
518 |
} else if (length == TAG_CODE_LENGTH && this.inlineTagStarted && CharOperation.equals(TAG_CODE, tagName)) { |
504 |
this.tagValue = TAG_CODE_VALUE; |
519 |
this.tagValue = TAG_CODE_VALUE; |
|
|
520 |
this.tagWaitingForDescription = this.tagValue; |
505 |
} |
521 |
} |
506 |
break; |
522 |
break; |
507 |
case 'd': |
523 |
case 'd': |
Lines 509-527
Link Here
|
509 |
this.deprecated = true; |
525 |
this.deprecated = true; |
510 |
valid = true; |
526 |
valid = true; |
511 |
this.tagValue = TAG_DEPRECATED_VALUE; |
527 |
this.tagValue = TAG_DEPRECATED_VALUE; |
|
|
528 |
this.tagWaitingForDescription = this.tagValue; |
512 |
} else if (length == TAG_DOC_ROOT_LENGTH && CharOperation.equals(TAG_DOC_ROOT, tagName)) { |
529 |
} else if (length == TAG_DOC_ROOT_LENGTH && CharOperation.equals(TAG_DOC_ROOT, tagName)) { |
513 |
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=227730 |
530 |
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=227730 |
514 |
// identify @docRoot tag as a base tag that does not expect any argument |
531 |
// identify @docRoot tag as a base tag that does not expect any argument |
515 |
valid = true; |
532 |
valid = true; |
516 |
this.tagValue = TAG_DOC_ROOT_VALUE; |
533 |
this.tagValue = TAG_DOC_ROOT_VALUE; |
517 |
alreadyParsedTag = true; |
|
|
518 |
} |
534 |
} |
519 |
break; |
535 |
break; |
520 |
case 'e': |
536 |
case 'e': |
521 |
if (length == TAG_EXCEPTION_LENGTH && CharOperation.equals(TAG_EXCEPTION, tagName)) { |
537 |
if (length == TAG_EXCEPTION_LENGTH && CharOperation.equals(TAG_EXCEPTION, tagName)) { |
522 |
this.tagValue = TAG_EXCEPTION_VALUE; |
538 |
this.tagValue = TAG_EXCEPTION_VALUE; |
523 |
valid = parseThrows(); |
539 |
valid = parseThrows(); |
524 |
alreadyParsedTag = true; |
|
|
525 |
} |
540 |
} |
526 |
break; |
541 |
break; |
527 |
case 'i': |
542 |
case 'i': |
Lines 536-544
Link Here
|
536 |
} |
551 |
} |
537 |
valid = true; |
552 |
valid = true; |
538 |
this.tagValue = TAG_INHERITDOC_VALUE; |
553 |
this.tagValue = TAG_INHERITDOC_VALUE; |
539 |
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=227730 |
|
|
540 |
// no argument expected for @inheritedDoc tag |
541 |
alreadyParsedTag = true; |
542 |
} |
554 |
} |
543 |
break; |
555 |
break; |
544 |
case 'l': |
556 |
case 'l': |
Lines 554-560
Link Here
|
554 |
this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); |
566 |
this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); |
555 |
} |
567 |
} |
556 |
} |
568 |
} |
557 |
alreadyParsedTag = true; |
|
|
558 |
} else if (length == TAG_LINKPLAIN_LENGTH && CharOperation.equals(TAG_LINKPLAIN, tagName)) { |
569 |
} else if (length == TAG_LINKPLAIN_LENGTH && CharOperation.equals(TAG_LINKPLAIN, tagName)) { |
559 |
this.tagValue = TAG_LINKPLAIN_VALUE; |
570 |
this.tagValue = TAG_LINKPLAIN_VALUE; |
560 |
if (this.inlineTagStarted) { |
571 |
if (this.inlineTagStarted) { |
Lines 565-580
Link Here
|
565 |
this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); |
576 |
this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); |
566 |
} |
577 |
} |
567 |
} |
578 |
} |
568 |
alreadyParsedTag = true; |
|
|
569 |
} else if (length == TAG_LITERAL_LENGTH && this.inlineTagStarted && CharOperation.equals(TAG_LITERAL, tagName)) { |
579 |
} else if (length == TAG_LITERAL_LENGTH && this.inlineTagStarted && CharOperation.equals(TAG_LITERAL, tagName)) { |
570 |
this.tagValue = TAG_LITERAL_VALUE; |
580 |
this.tagValue = TAG_LITERAL_VALUE; |
|
|
581 |
this.tagWaitingForDescription = this.tagValue; |
571 |
} |
582 |
} |
572 |
break; |
583 |
break; |
573 |
case 'p': |
584 |
case 'p': |
574 |
if (length == TAG_PARAM_LENGTH && CharOperation.equals(TAG_PARAM, tagName)) { |
585 |
if (length == TAG_PARAM_LENGTH && CharOperation.equals(TAG_PARAM, tagName)) { |
575 |
this.tagValue = TAG_PARAM_VALUE; |
586 |
this.tagValue = TAG_PARAM_VALUE; |
576 |
valid = parseParam(); |
587 |
valid = parseParam(); |
577 |
alreadyParsedTag = true; |
|
|
578 |
} |
588 |
} |
579 |
break; |
589 |
break; |
580 |
case 's': |
590 |
case 's': |
Lines 590-604
Link Here
|
590 |
this.tagValue = TAG_SEE_VALUE; |
600 |
this.tagValue = TAG_SEE_VALUE; |
591 |
valid = parseReference(); |
601 |
valid = parseReference(); |
592 |
} |
602 |
} |
593 |
alreadyParsedTag = true; |
|
|
594 |
} else if (length == TAG_SERIAL_LENGTH && CharOperation.equals(TAG_SERIAL, tagName)) { |
603 |
} else if (length == TAG_SERIAL_LENGTH && CharOperation.equals(TAG_SERIAL, tagName)) { |
595 |
this.tagValue = TAG_SERIAL_VALUE; |
604 |
this.tagValue = TAG_SERIAL_VALUE; |
|
|
605 |
this.tagWaitingForDescription = this.tagValue; |
596 |
} else if (length == TAG_SERIAL_DATA_LENGTH && CharOperation.equals(TAG_SERIAL_DATA, tagName)) { |
606 |
} else if (length == TAG_SERIAL_DATA_LENGTH && CharOperation.equals(TAG_SERIAL_DATA, tagName)) { |
597 |
this.tagValue = TAG_SERIAL_DATA_VALUE; |
607 |
this.tagValue = TAG_SERIAL_DATA_VALUE; |
|
|
608 |
this.tagWaitingForDescription = this.tagValue; |
598 |
} else if (length == TAG_SERIAL_FIELD_LENGTH && CharOperation.equals(TAG_SERIAL_FIELD, tagName)) { |
609 |
} else if (length == TAG_SERIAL_FIELD_LENGTH && CharOperation.equals(TAG_SERIAL_FIELD, tagName)) { |
599 |
this.tagValue = TAG_SERIAL_FIELD_VALUE; |
610 |
this.tagValue = TAG_SERIAL_FIELD_VALUE; |
|
|
611 |
this.tagWaitingForDescription = this.tagValue; |
600 |
} else if (length == TAG_SINCE_LENGTH && CharOperation.equals(TAG_SINCE, tagName)) { |
612 |
} else if (length == TAG_SINCE_LENGTH && CharOperation.equals(TAG_SINCE, tagName)) { |
601 |
this.tagValue = TAG_SINCE_VALUE; |
613 |
this.tagValue = TAG_SINCE_VALUE; |
|
|
614 |
this.tagWaitingForDescription = this.tagValue; |
602 |
} |
615 |
} |
603 |
break; |
616 |
break; |
604 |
case 'v': |
617 |
case 'v': |
Lines 626-634
Link Here
|
626 |
if (this.reportProblems) this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); |
639 |
if (this.reportProblems) this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); |
627 |
} |
640 |
} |
628 |
} |
641 |
} |
629 |
alreadyParsedTag = true; |
|
|
630 |
} else if (length == TAG_VERSION_LENGTH && CharOperation.equals(TAG_VERSION, tagName)) { |
642 |
} else if (length == TAG_VERSION_LENGTH && CharOperation.equals(TAG_VERSION, tagName)) { |
631 |
this.tagValue = TAG_VERSION_VALUE; |
643 |
this.tagValue = TAG_VERSION_VALUE; |
|
|
644 |
this.tagWaitingForDescription = this.tagValue; |
632 |
} else { |
645 |
} else { |
633 |
createTag(); |
646 |
createTag(); |
634 |
} |
647 |
} |
Lines 641-667
Link Here
|
641 |
case TerminalTokens.TokenNamereturn : |
654 |
case TerminalTokens.TokenNamereturn : |
642 |
this.tagValue = TAG_RETURN_VALUE; |
655 |
this.tagValue = TAG_RETURN_VALUE; |
643 |
valid = parseReturn(); |
656 |
valid = parseReturn(); |
644 |
alreadyParsedTag = true; |
|
|
645 |
/* verify characters after return tag (we're expecting text description) |
646 |
if(!verifyCharsAfterReturnTag(this.index)) { |
647 |
if (this.sourceParser != null) { |
648 |
int end = this.starPosition == -1 || this.lineEnd<this.starPosition ? this.lineEnd : this.starPosition; |
649 |
this.sourceParser.problemReporter().javadocEmptyReturnTag(this.tagSourceStart, end); |
650 |
} |
651 |
} |
652 |
*/ |
653 |
break; |
657 |
break; |
654 |
case TerminalTokens.TokenNamethrows : |
658 |
case TerminalTokens.TokenNamethrows : |
655 |
this.tagValue = TAG_THROWS_VALUE; |
659 |
this.tagValue = TAG_THROWS_VALUE; |
656 |
valid = parseThrows(); |
660 |
valid = parseThrows(); |
657 |
alreadyParsedTag = true; |
|
|
658 |
break; |
661 |
break; |
659 |
} |
662 |
} |
660 |
this.textStart = this.index; |
663 |
this.textStart = this.index; |
661 |
if (this.tagValue != TAG_OTHERS_VALUE && ! alreadyParsedTag && this.reportProblems && verifyEndLine(this.scanner.currentPosition)) { |
|
|
662 |
this.sourceParser.problemReporter().javadocMissingTagDescription(tagName, this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers); |
663 |
return false; |
664 |
} |
665 |
return valid; |
664 |
return valid; |
666 |
} |
665 |
} |
667 |
|
666 |
|
Lines 670-682
Link Here
|
670 |
*/ |
669 |
*/ |
671 |
protected boolean parseParam() throws InvalidInputException { |
670 |
protected boolean parseParam() throws InvalidInputException { |
672 |
boolean valid = super.parseParam(); |
671 |
boolean valid = super.parseParam(); |
673 |
if (valid && this.reportProblems && verifyEndLine(this.scanner.currentPosition)) { |
672 |
this.tagWaitingForDescription = valid && this.reportProblems ? TAG_PARAM_VALUE : NO_TAG_VALUE; |
674 |
// retrieve last identifier position (valid as, in the super method, we already parsed an identifier) |
|
|
675 |
int start = (int) (this.identifierPositionStack[0] >>> 32); |
676 |
int end = (int) this.identifierPositionStack[this.identifierPtr]; |
677 |
this.sourceParser.problemReporter().javadocMissingTagDescriptionAfterReference(start, end, this.sourceParser.modifiers); |
678 |
return false; |
679 |
} |
680 |
return valid; |
673 |
return valid; |
681 |
} |
674 |
} |
682 |
|
675 |
|
Lines 771-776
Link Here
|
771 |
return true; |
764 |
return true; |
772 |
} |
765 |
} |
773 |
|
766 |
|
|
|
767 |
/* (non-Javadoc) |
768 |
* @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushText(int, int) |
769 |
*/ |
770 |
protected void pushText(int start, int end) { |
771 |
// The tag gets its description => clear the flag |
772 |
this.tagWaitingForDescription = NO_TAG_VALUE; |
773 |
} |
774 |
|
774 |
/* |
775 |
/* |
775 |
* Push a throws type ref in ast node stack. |
776 |
* Push a throws type ref in ast node stack. |
776 |
*/ |
777 |
*/ |
Lines 800-805
Link Here
|
800 |
return true; |
801 |
return true; |
801 |
} |
802 |
} |
802 |
|
803 |
|
|
|
804 |
/* (non-Javadoc) |
805 |
* @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#refreshInlineTagPosition(int) |
806 |
*/ |
807 |
protected void refreshInlineTagPosition(int previousPosition) { |
808 |
|
809 |
// Signal tag missing description if necessary |
810 |
if (this.tagWaitingForDescription!= NO_TAG_VALUE) { |
811 |
this.sourceParser.problemReporter().javadocMissingTagDescription(TAG_NAMES[this.tagWaitingForDescription], this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers); |
812 |
this.tagWaitingForDescription = NO_TAG_VALUE; |
813 |
} |
814 |
} |
815 |
|
803 |
/* |
816 |
/* |
804 |
* Refresh return statement |
817 |
* Refresh return statement |
805 |
*/ |
818 |
*/ |
Lines 820-825
Link Here
|
820 |
*/ |
833 |
*/ |
821 |
protected void updateDocComment() { |
834 |
protected void updateDocComment() { |
822 |
|
835 |
|
|
|
836 |
// Signal tag missing description if necessary |
837 |
switch (this.tagWaitingForDescription) { |
838 |
case TAG_PARAM_VALUE: |
839 |
case TAG_THROWS_VALUE: |
840 |
int start = (int) (this.identifierPositionStack[0] >>> 32); |
841 |
int end = (int) this.identifierPositionStack[this.identifierPtr]; |
842 |
this.sourceParser.problemReporter().javadocMissingTagDescriptionAfterReference(start, end, this.sourceParser.modifiers); |
843 |
break; |
844 |
case NO_TAG_VALUE: |
845 |
break; |
846 |
default: |
847 |
this.sourceParser.problemReporter().javadocMissingTagDescription(TAG_NAMES[this.tagWaitingForDescription], this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers); |
848 |
break; |
849 |
} |
850 |
this.tagWaitingForDescription = NO_TAG_VALUE; |
851 |
|
823 |
// Set positions |
852 |
// Set positions |
824 |
this.docComment.inheritedPositions = this.inheritedPositions; |
853 |
this.docComment.inheritedPositions = this.inheritedPositions; |
825 |
this.docComment.valuePositions = this.validValuePositions != -1 ? this.validValuePositions : this.invalidValuePositions; |
854 |
this.docComment.valuePositions = this.validValuePositions != -1 ? this.validValuePositions : this.invalidValuePositions; |