Index: src/org/eclipse/jdt/core/tests/model/JavadocBugsCompletionModelTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavadocBugsCompletionModelTest.java,v --- src/org/eclipse/jdt/core/tests/model/JavadocBugsCompletionModelTest.java 19 Nov 2006 19:47:39 -0000 1.17 +++ src/org/eclipse/jdt/core/tests/model/JavadocBugsCompletionModelTest.java 21 Nov 2006 11:50:52 -0000 @@ -807,7 +807,7 @@ "package bugs.b139621;\n" + "public class BasicTestBugs {\n" + " /**\n" + - " * This method returns an object\n" + + " * Test with only an orphan comment in type declaration\n" + " * @see Obj\n" + " */\n" + "}\n"; @@ -820,10 +820,100 @@ String source = "package bugs.b139621;\n" + "/**\n" + - " * This method returns an object\n" + + " * Test with an existing javadoc type declaration\n" + + " * @see Test\n" + + " */\n" + + "public class BasicTestBugs {\n" + + " /**\n" + + " * Test with only an orphan comment in type declaration\n" + + " * @see Obj\n" + + " */\n" + + "}\n"; + completeInJavadoc("/Completion/src/bugs/b139621/BasicTestBugs.java", source, true, "Obj"); + assertSortedResults( + "Object[TYPE_REF]{Object, java.lang, Ljava.lang.Object;, null, null, "+this.positions+R_DICUNR+"}" + ); +} +public void testBug139621c() throws JavaModelException { + String source = + "package bugs.b139621;\n" + + "public class BasicTestBugs {\n" + + " /**\n" + + " * Test with only an orphan comment in type declaration\n" + + " * (completion for tags)\n" + + " * @\n" + + " */\n" + + "}\n"; + completeInJavadoc("/Completion/src/bugs/b139621/BasicTestBugs.java", source, true, "@"); + assertSortedResults( + "author[JAVADOC_BLOCK_TAG]{@author, null, null, author, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "category[JAVADOC_BLOCK_TAG]{@category, null, null, category, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "deprecated[JAVADOC_BLOCK_TAG]{@deprecated, null, null, deprecated, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "docRoot[JAVADOC_INLINE_TAG]{{@docRoot}, null, null, docRoot, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "exception[JAVADOC_BLOCK_TAG]{@exception, null, null, exception, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "inheritDoc[JAVADOC_INLINE_TAG]{{@inheritDoc}, null, null, inheritDoc, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "link[JAVADOC_INLINE_TAG]{{@link}, null, null, link, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "linkplain[JAVADOC_INLINE_TAG]{{@linkplain}, null, null, linkplain, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "param[JAVADOC_BLOCK_TAG]{@param, null, null, param, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "return[JAVADOC_BLOCK_TAG]{@return, null, null, return, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "see[JAVADOC_BLOCK_TAG]{@see, null, null, see, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "serial[JAVADOC_BLOCK_TAG]{@serial, null, null, serial, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "serialData[JAVADOC_BLOCK_TAG]{@serialData, null, null, serialData, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "serialField[JAVADOC_BLOCK_TAG]{@serialField, null, null, serialField, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "since[JAVADOC_BLOCK_TAG]{@since, null, null, since, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "throws[JAVADOC_BLOCK_TAG]{@throws, null, null, throws, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "value[JAVADOC_INLINE_TAG]{{@value}, null, null, value, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "version[JAVADOC_BLOCK_TAG]{@version, null, null, version, null, "+this.positions+JAVADOC_RELEVANCE+"}" + ); +} +public void testBug139621d() throws JavaModelException { + String source = + "package bugs.b139621;\n" + + "public class BasicTestBugs {\n" + + " /**\n" + + " * Test with only an orphan comment in type declaration\n" + + " * (variation of completion for tags but considered in text as it's in fact tag start character is after a reference )\n" + + " * @see Object" + // missing \n + " * @\n" + + " */\n" + + "}\n"; + completeInJavadoc("/Completion/src/bugs/b139621/BasicTestBugs.java", source, true, "@", 2); + assertSortedResults( + "docRoot[JAVADOC_INLINE_TAG]{{@docRoot}, null, null, docRoot, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "inheritDoc[JAVADOC_INLINE_TAG]{{@inheritDoc}, null, null, inheritDoc, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "link[JAVADOC_INLINE_TAG]{{@link}, null, null, link, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "linkplain[JAVADOC_INLINE_TAG]{{@linkplain}, null, null, linkplain, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "value[JAVADOC_INLINE_TAG]{{@value}, null, null, value, null, "+this.positions+JAVADOC_RELEVANCE+"}" + ); +} +public void testBug139621e() throws JavaModelException { + String source = + "package bugs.b139621;\n" + + "/**\n" + + " * Test with orphan comment after a method declaration\n" + + " * @see Test\n" + + " */\n" + + "public class BasicTestBugs {\n" + + " public void foo() {}\n" + + " /**\n" + + " * This method returns an object\n" + + " * @see Obj\n" + + " */\n" + + "}\n"; + completeInJavadoc("/Completion/src/bugs/b139621/BasicTestBugs.java", source, true, "Obj"); + assertSortedResults( + "Object[TYPE_REF]{Object, java.lang, Ljava.lang.Object;, null, null, "+this.positions+R_DICUNR+"}" + ); +} +public void testBug139621f() throws JavaModelException { + String source = + "package bugs.b139621;\n" + + "/**\n" + + " * Test with orphan comment after a field declaration\n" + " * @see Test\n" + " */\n" + "public class BasicTestBugs {\n" + + " public int x;\n" + " /**\n" + " * This method returns an object\n" + " * @see Obj\n" + @@ -834,6 +924,58 @@ "Object[TYPE_REF]{Object, java.lang, Ljava.lang.Object;, null, null, "+this.positions+R_DICUNR+"}" ); } +public void testBug139621g() throws JavaModelException { + String source = + "package bugs.b139621;\n" + + "/**\n" + + " * Compilation unit without any type\n" + + " * @see Obj\n" + + " */\n"; + completeInJavadoc("/Completion/src/bugs/b139621/BasicTestBugs.java", source, true, "Obj"); + assertSortedResults( + "Object[TYPE_REF]{Object, java.lang, Ljava.lang.Object;, null, null, "+this.positions+R_DICUNR+"}" + ); +} +public void testBug139621h() throws JavaModelException { + String source = + "package bugs.b139621;\n" + + "/**\n" + + " * Compilation unit without any type\n" + + " * (completion for tags)\n" + + " * @\n" + + " */\n"; + completeInJavadoc("/Completion/src/bugs/b139621/BasicTestBugs.java", source, true, "@"); + assertSortedResults( + "author[JAVADOC_BLOCK_TAG]{@author, null, null, author, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "category[JAVADOC_BLOCK_TAG]{@category, null, null, category, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "deprecated[JAVADOC_BLOCK_TAG]{@deprecated, null, null, deprecated, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "docRoot[JAVADOC_INLINE_TAG]{{@docRoot}, null, null, docRoot, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "link[JAVADOC_INLINE_TAG]{{@link}, null, null, link, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "linkplain[JAVADOC_INLINE_TAG]{{@linkplain}, null, null, linkplain, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "see[JAVADOC_BLOCK_TAG]{@see, null, null, see, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "serial[JAVADOC_BLOCK_TAG]{@serial, null, null, serial, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "since[JAVADOC_BLOCK_TAG]{@since, null, null, since, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "value[JAVADOC_INLINE_TAG]{{@value}, null, null, value, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "version[JAVADOC_BLOCK_TAG]{@version, null, null, version, null, "+this.positions+JAVADOC_RELEVANCE+"}" + ); +} +public void testBug139621i() throws JavaModelException { + String source = + "package bugs.b139621;\n" + + "/**\n" + + " * Compilation unit without any type\n" + + " * (variation of completion for tags but considered in text as it's in fact tag start character is after a reference )\n" + + " * @see Object The root class" + // missing \n + " * @\n" + + " */\n"; + completeInJavadoc("/Completion/src/bugs/b139621/BasicTestBugs.java", source, true, "@", 2); + assertSortedResults( + "docRoot[JAVADOC_INLINE_TAG]{{@docRoot}, null, null, docRoot, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "link[JAVADOC_INLINE_TAG]{{@link}, null, null, link, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "linkplain[JAVADOC_INLINE_TAG]{{@linkplain}, null, null, linkplain, null, "+this.positions+JAVADOC_RELEVANCE+"}\n" + + "value[JAVADOC_INLINE_TAG]{{@value}, null, null, value, null, "+this.positions+JAVADOC_RELEVANCE+"}" + ); +} /** * Bug 144866: [assist][javadoc] Wrong completion inside @value tag Index: compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java,v --- compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java 17 Nov 2006 16:11:30 -0000 1.49 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java 21 Nov 2006 11:50:55 -0000 @@ -180,7 +180,7 @@ } /* - * Resolve type javadoc while a class scope + * Resolve type javadoc */ public void resolve(ClassScope scope) { @@ -229,9 +229,16 @@ scope.problemReporter().javadocUnexpectedTag((int)(this.valuePositions>>>32), (int) this.valuePositions); } } - + + /* + * Resolve compilation unit javadoc + */ + public void resolve(CompilationUnitScope unitScope) { + // do nothing + } + /* - * Resolve method javadoc while a method scope + * Resolve method javadoc */ public void resolve(MethodScope methScope) { Index: compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java,v --- compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java 28 Oct 2006 04:11:27 -0000 1.64 +++ compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java 21 Nov 2006 11:50:55 -0000 @@ -344,6 +344,11 @@ this.javadoc.resolve(syntheticTypeDeclaration.staticInitializerScope); } startingTypeIndex = 1; + } else { + // resolve compilation unit javadoc package if any + if (this.javadoc != null) { + this.javadoc.resolve(this.scope); + } } if (this.currentPackage != null && this.currentPackage.annotations != null && !isPackageInfo) { scope.problemReporter().invalidFileNameForPackageAnnotations(this.currentPackage.annotations[0]); Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java,v --- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java 20 Nov 2006 10:49:56 -0000 1.166 +++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java 21 Nov 2006 11:50:54 -0000 @@ -1774,14 +1774,18 @@ * @see org.eclipse.jdt.internal.compiler.parser.Parser#consumeClassDeclaration() */ protected void consumeClassDeclaration() { - if (this.astPtr >= 0 && this.astStack[this.astPtr] instanceof TypeDeclaration) { - TypeDeclaration typeDeclaration = (TypeDeclaration) this.astStack[this.astPtr]; + if (this.astPtr >= 0) { + int length = this.astLengthStack[this.astLengthPtr]; + TypeDeclaration typeDeclaration = (TypeDeclaration) this.astStack[this.astPtr-length]; this.javadoc = null; + CompletionJavadocParser completionJavadocParser = (CompletionJavadocParser)this.javadocParser; + completionJavadocParser.allPossibleTags = true; checkComment(); if (this.javadoc != null && this.cursorLocation > this.javadoc.sourceStart && this.cursorLocation < this.javadoc.sourceEnd) { - // completion is in an orphan javadoc comment => replace type declaration one with it to allow completion resolution + // completion is in an orphan javadoc comment => replace in last read declaration to allow completion resolution typeDeclaration.javadoc = this.javadoc; } + completionJavadocParser.allPossibleTags = false; } super.consumeClassDeclaration(); } @@ -1829,6 +1833,27 @@ super.consumeClassTypeElt(); popElement(K_NEXT_TYPEREF_IS_EXCEPTION); } + +/* (non-Javadoc) + * @see org.eclipse.jdt.internal.compiler.parser.Parser#consumeCompilationUnit() + */ +protected void consumeCompilationUnit() { + this.javadoc = null; + checkComment(); + if (this.javadoc != null && this.cursorLocation > this.javadoc.sourceStart && this.cursorLocation < this.javadoc.sourceEnd) { + // completion is in an orphan javadoc comment => replace compilation unit one to allow completion resolution + compilationUnit.javadoc = this.javadoc; + // create a fake interface declaration to allow resolution + if (this.compilationUnit.types == null) { + this.compilationUnit.types = new TypeDeclaration[1]; + TypeDeclaration declaration = new TypeDeclaration(compilationUnit.compilationResult); + declaration.name = FAKE_TYPE_NAME; + declaration.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccInterface; + this.compilationUnit.types[0] = declaration; + } + } + super.consumeCompilationUnit(); +} protected void consumeConditionalExpression(int op) { popElement(K_CONDITIONAL_OPERATOR); super.consumeConditionalExpression(op); Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadoc.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadoc.java,v --- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadoc.java 21 Oct 2005 22:33:36 -0000 1.2 +++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadoc.java 21 Nov 2006 11:50:53 -0000 @@ -20,6 +20,7 @@ int ONLY_INLINE_TAG = 0x0010; int REPLACE_TAG = 0x0020; int FORMAL_REFERENCE = 0x0040; + int ALL_POSSIBLE_TAGS = 0x0080; /** * Get completion node flags. Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTag.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTag.java,v --- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTag.java 28 Mar 2006 20:29:57 -0000 1.4 +++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTag.java 21 Nov 2006 11:50:53 -0000 @@ -12,6 +12,7 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.JavadocSingleNameReference; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.Scope; @@ -22,9 +23,10 @@ public final static char[][][] NO_CHAR_CHAR_CHAR = new char[0][][]; private char[][][] possibleTags = NO_CHAR_CHAR_CHAR; - public CompletionOnJavadocTag(char[] source, long pos, int tagStart, int tagEnd, char[][][] possibleTags) { + public CompletionOnJavadocTag(char[] source, long pos, int tagStart, int tagEnd, char[][][] possibleTags, boolean orphan) { super(source, pos, tagStart, tagEnd); this.possibleTags = possibleTags; + if (orphan) this.completionFlags |= ALL_POSSIBLE_TAGS; } /** @@ -80,12 +82,13 @@ } public void filterPossibleTags(Scope scope) { - if (this.possibleTags == null || this.possibleTags.length == 0) { + if (this.possibleTags == null || this.possibleTags.length == 0 || (this.completionFlags & ALL_POSSIBLE_TAGS) != 0) { return; } int kind = scope.kind; char[][] specifiedTags = null; switch (kind) { + case Scope.COMPILATION_UNIT_SCOPE: case Scope.CLASS_SCOPE: specifiedTags = CLASS_TAGS; break; @@ -114,9 +117,23 @@ char[] possibleTag = this.possibleTags[k][i]; for (int j=0; j= ClassFileConstants.JDK1_5) { + if (((ClassScope)scope).referenceContext.binding.isGenericType()) { + filteredTags[size++] = possibleTag; + } + } + break; + case Scope.COMPILATION_UNIT_SCOPE: + if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { + filteredTags[size++] = possibleTag; + } + break; + default: + filteredTags[size++] = possibleTag; + break; } } else { filteredTags[size++] = possibleTag; Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java,v --- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java 23 Jun 2006 07:57:55 -0000 1.24 +++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java 21 Nov 2006 11:50:53 -0000 @@ -51,6 +51,7 @@ int cursorLocation; CompletionOnJavadoc completionNode = null; boolean pushText = false; + boolean allPossibleTags = false; public CompletionJavadocParser(CompletionParser sourceParser) { super(sourceParser); @@ -557,7 +558,7 @@ System.arraycopy(this.source, this.tagSourceStart, tag, 0, length); char[][][] tags = possibleTags(tag, newLine); if (tags != null) { - this.completionNode = new CompletionOnJavadocTag(tag, position, startPosition, end, tags); + this.completionNode = new CompletionOnJavadocTag(tag, position, startPosition, end, tags, this.allPossibleTags); } } return valid; Index: compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java,v --- compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java 23 Oct 2006 16:45:42 -0000 1.64 +++ compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java 21 Nov 2006 11:50:55 -0000 @@ -221,9 +221,9 @@ // for DOM AST node, store tag as text in case of invalid syntax if (isDomParser) { createTag(); - this.textStart = this.tagSourceEnd+1; - invalidTagLineEnd = this.lineEnd; } + this.textStart = this.tagSourceEnd+1; + invalidTagLineEnd = this.lineEnd; } } catch (InvalidInputException e) { consumeToken();