From 7fc78a853e16b8b14e294433d3313352fb75b6d7 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 21 Sep 2011 11:52:54 +0200 Subject: [PATCH] Javadoc parser migrated to PsiBuilder --- .../lang/java/parser/JavaParserUtil.java | 5 +- .../lang/java/parser/JavadocParser.java | 269 ++++++++++++++++++ .../impl/source/tree/JavaDocElementType.java | 81 +++--- .../parser-full/javadocParsing/ParamTag0.java | 8 + .../parser-full/javadocParsing/ParamTag0.txt | 63 ++++ .../lang/java/parser/JavadocParsingTest.java | 3 +- .../lang/impl/PsiBuilderFactoryImpl.java | 11 +- .../intellij/lang/impl/PsiBuilderImpl.java | 31 +- 8 files changed, 419 insertions(+), 52 deletions(-) create mode 100644 java/java-impl/src/com/intellij/lang/java/parser/JavadocParser.java create mode 100644 java/java-tests/testData/psi/parser-full/javadocParsing/ParamTag0.java create mode 100644 java/java-tests/testData/psi/parser-full/javadocParsing/ParamTag0.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java b/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java index 0a9d06b7fe23..12e5fcd99bf4 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.daemon.JavaErrorMessages; import com.intellij.lang.*; import com.intellij.lang.impl.PsiBuilderAdapter; import com.intellij.lang.java.JavaParserDefinition; +import com.intellij.lexer.JavaDocLexer; import com.intellij.lexer.Lexer; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; @@ -225,7 +226,9 @@ public class JavaParserUtil { final Project project = psi.getProject(); final PsiBuilderFactory factory = PsiBuilderFactory.getInstance(); - final Lexer lexer = JavaParserDefinition.createLexer(level); + final Lexer lexer = chameleon.getElementType() == JavaDocElementType.DOC_COMMENT + ? new JavaDocLexer(level.isAtLeast(LanguageLevel.JDK_1_5)) + : JavaParserDefinition.createLexer(level); final PsiBuilder builder = factory.createBuilder(project, chameleon, lexer, chameleon.getElementType().getLanguage(), chameleon.getChars()); setLanguageLevel(builder, level); diff --git a/java/java-impl/src/com/intellij/lang/java/parser/JavadocParser.java b/java/java-impl/src/com/intellij/lang/java/parser/JavadocParser.java new file mode 100644 index 000000000000..36c9a842c889 --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/parser/JavadocParser.java @@ -0,0 +1,269 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.lang.java.parser; + +import com.intellij.lang.PsiBuilder; +import com.intellij.openapi.util.Key; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.JavaDocTokenType; +import com.intellij.psi.TokenType; +import com.intellij.psi.impl.source.tree.JavaDocElementType; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class JavadocParser { + private static final TokenSet TAG_VALUES_SET = TokenSet.create( + JavaDocTokenType.DOC_TAG_VALUE_TOKEN, JavaDocTokenType.DOC_TAG_VALUE_COMMA, JavaDocTokenType.DOC_TAG_VALUE_DOT, + JavaDocTokenType.DOC_TAG_VALUE_LPAREN, JavaDocTokenType.DOC_TAG_VALUE_RPAREN, JavaDocTokenType.DOC_TAG_VALUE_SHARP_TOKEN, + JavaDocTokenType.DOC_TAG_VALUE_LT, JavaDocTokenType.DOC_TAG_VALUE_GT); + + private static final TokenSet INLINE_TAG_BORDERS_SET = TokenSet.create( + JavaDocTokenType.DOC_INLINE_TAG_START, JavaDocTokenType.DOC_INLINE_TAG_END); + + public static final TokenSet SKIP_TOKENS = TokenSet.create(JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS); + + @NonNls private static final String SEE_TAG = "@see"; + @NonNls private static final String LINK_TAG = "@link"; + @NonNls private static final String LINK_PLAIN_TAG = "@linkplain"; + @NonNls private static final String THROWS_TAG = "@throws"; + @NonNls private static final String EXCEPTION_TAG = "@exception"; + @NonNls private static final String PARAM_TAG = "@param"; + @NonNls private static final String VALUE_TAG = "@value"; + + private static final Key BRACE_SCOPE_KEY = Key.create("Javadoc.Parser.Brace.Scope"); + + private JavadocParser() { } + + public static void parseJavadocReference(@NotNull final PsiBuilder builder) { + ReferenceParser.parseJavaCodeReference(builder, true, true, false, false, false); + swallowTokens(builder); + } + + public static void parseJavadocType(@NotNull final PsiBuilder builder) { + ReferenceParser.parseType(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.ELLIPSIS | ReferenceParser.WILDCARD); + swallowTokens(builder); + } + + private static void swallowTokens(PsiBuilder builder) { + while (!builder.eof()) builder.advanceLexer(); + } + + public static void parseDocCommentText(@NotNull final PsiBuilder builder) { + builder.enforceCommentTokens(SKIP_TOKENS); + + while (!builder.eof()) { + final IElementType tokenType = getTokenType(builder); + if (tokenType == JavaDocTokenType.DOC_TAG_NAME) { + parseTag(builder); + } + else { + parseDataItem(builder, null, false); + } + } + } + + private static void parseTag(@NotNull final PsiBuilder builder) { + final String tagName = builder.getTokenText(); + final PsiBuilder.Marker tag = builder.mark(); + builder.advanceLexer(); + while (true) { + final IElementType tokenType = getTokenType(builder); + if (tokenType == null || tokenType == JavaDocTokenType.DOC_TAG_NAME || tokenType == JavaDocTokenType.DOC_COMMENT_END) break; + parseDataItem(builder, tagName, false); + } + tag.done(JavaDocElementType.DOC_TAG); + } + + private static void parseDataItem(@NotNull final PsiBuilder builder, @Nullable final String tagName, final boolean isInline) { + IElementType tokenType = getTokenType(builder); + if (tokenType == JavaDocTokenType.DOC_INLINE_TAG_START) { + int braceScope = getBraceScope(builder); + if (braceScope > 0) { + setBraceScope(builder, braceScope + 1); + builder.remapCurrentToken(JavaDocTokenType.DOC_COMMENT_DATA); + builder.advanceLexer(); + return; + } + + final PsiBuilder.Marker tag = builder.mark(); + builder.advanceLexer(); + + tokenType = getTokenType(builder); + if (tokenType != JavaDocTokenType.DOC_TAG_NAME && tokenType != JavaDocTokenType.DOC_COMMENT_BAD_CHARACTER) { + tag.rollbackTo(); + builder.remapCurrentToken(JavaDocTokenType.DOC_COMMENT_DATA); + builder.advanceLexer(); + return; + } + + setBraceScope(builder, braceScope + 1); + String inlineTagName = ""; + + while (true) { + tokenType = getTokenType(builder); + if (tokenType == JavaDocTokenType.DOC_TAG_NAME) { + inlineTagName = builder.getTokenText(); + } + else if (tokenType == null || tokenType == JavaDocTokenType.DOC_COMMENT_END) { + break; + } + + parseDataItem(builder, inlineTagName, true); + if (tokenType == JavaDocTokenType.DOC_INLINE_TAG_END) { + braceScope = getBraceScope(builder); + if (braceScope > 0) setBraceScope(builder, --braceScope); + if (braceScope == 0) break; + } + } + + tag.done(JavaDocElementType.DOC_INLINE_TAG); + } + else if (TAG_VALUES_SET.contains(tokenType)) { + if (SEE_TAG.equals(tagName) && !isInline || + LINK_TAG.equals(tagName) && isInline) { + parseSeeTagValue(builder); + } + else { + if (JavaParserUtil.getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_1_4) && LINK_PLAIN_TAG.equals(tagName) && isInline) { + parseSeeTagValue(builder); + } + else if (!isInline && (THROWS_TAG.equals(tagName) || EXCEPTION_TAG.equals(tagName))) { + final PsiBuilder.Marker tagValue = builder.mark(); + builder.remapCurrentToken(JavaDocElementType.DOC_REFERENCE_HOLDER); + builder.advanceLexer(); + tagValue.done(JavaDocTokenType.DOC_TAG_VALUE_TOKEN); + } + else if (!isInline && tagName != null && tagName.equals(PARAM_TAG)) { + parseSimpleTagValue(builder, true); + } + else { + if (JavaParserUtil.getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_1_5) && VALUE_TAG.equals(tagName) && isInline) { + parseSeeTagValue(builder); + } + else { + parseSimpleTagValue(builder, false); + } + } + } + } + else { + remapAndAdvance(builder); + } + } + + private static void parseSeeTagValue(@NotNull final PsiBuilder builder) { + final IElementType tokenType = getTokenType(builder); + if (tokenType == JavaDocTokenType.DOC_TAG_VALUE_SHARP_TOKEN) { + parseMethodRef(builder, builder.mark()); + } + else if (tokenType == JavaDocTokenType.DOC_TAG_VALUE_TOKEN) { + final PsiBuilder.Marker refStart = builder.mark(); + builder.remapCurrentToken(JavaDocElementType.DOC_REFERENCE_HOLDER); + builder.advanceLexer(); + + if (getTokenType(builder) == JavaDocTokenType.DOC_TAG_VALUE_SHARP_TOKEN) { + parseMethodRef(builder, refStart); + } + else { + refStart.drop(); + } + } + else { + final PsiBuilder.Marker tagValue = builder.mark(); + builder.advanceLexer(); + tagValue.done(JavaDocTokenType.DOC_TAG_VALUE_TOKEN); + } + } + + private static void parseMethodRef(@NotNull final PsiBuilder builder, @NotNull final PsiBuilder.Marker refStart) { + builder.advanceLexer(); + + if (getTokenType(builder) != JavaDocTokenType.DOC_TAG_VALUE_TOKEN) { + refStart.done(JavaDocElementType.DOC_METHOD_OR_FIELD_REF); + return; + } + builder.advanceLexer(); + + if (getTokenType(builder) == JavaDocTokenType.DOC_TAG_VALUE_LPAREN) { + builder.advanceLexer(); + + final PsiBuilder.Marker subValue = builder.mark(); + + IElementType tokenType; + while (TAG_VALUES_SET.contains(tokenType = getTokenType(builder))) { + if (tokenType == JavaDocTokenType.DOC_TAG_VALUE_TOKEN) { + builder.remapCurrentToken(JavaDocElementType.DOC_TYPE_HOLDER); + builder.advanceLexer(); + + while (TAG_VALUES_SET.contains(tokenType = getTokenType(builder)) && + tokenType != JavaDocTokenType.DOC_TAG_VALUE_COMMA && tokenType != JavaDocTokenType.DOC_TAG_VALUE_RPAREN) { + builder.advanceLexer(); + } + } + else if (tokenType == JavaDocTokenType.DOC_TAG_VALUE_RPAREN) { + subValue.done(JavaDocTokenType.DOC_TAG_VALUE_TOKEN); + builder.advanceLexer(); + refStart.done(JavaDocElementType.DOC_METHOD_OR_FIELD_REF); + return; + } + else { + builder.advanceLexer(); + } + } + + subValue.done(JavaDocTokenType.DOC_TAG_VALUE_TOKEN); + } + + refStart.done(JavaDocElementType.DOC_METHOD_OR_FIELD_REF); + } + + private static void parseSimpleTagValue(@NotNull final PsiBuilder builder, final boolean parameter) { + final PsiBuilder.Marker tagValue = builder.mark(); + while (TAG_VALUES_SET.contains(getTokenType(builder))) { + builder.advanceLexer(); + } + tagValue.done(parameter ? JavaDocElementType.DOC_PARAMETER_REF : JavaDocTokenType.DOC_TAG_VALUE_TOKEN); + } + + @Nullable + private static IElementType getTokenType(@NotNull final PsiBuilder builder) { + IElementType tokenType; + while ((tokenType = builder.getTokenType()) == JavaDocTokenType.DOC_SPACE) { + builder.remapCurrentToken(TokenType.WHITE_SPACE); + builder.advanceLexer(); + } + return tokenType; + } + + private static int getBraceScope(@NotNull final PsiBuilder builder) { + final Integer braceScope = builder.getUserDataUnprotected(BRACE_SCOPE_KEY); + return braceScope != null ? braceScope : 0; + } + + private static void setBraceScope(@NotNull final PsiBuilder builder, final int braceScope) { + builder.putUserDataUnprotected(BRACE_SCOPE_KEY, braceScope); + } + + private static void remapAndAdvance(@NotNull final PsiBuilder builder) { + if (INLINE_TAG_BORDERS_SET.contains(builder.getTokenType()) && getBraceScope(builder) != 1) { + builder.remapCurrentToken(JavaDocTokenType.DOC_COMMENT_DATA); + } + builder.advanceLexer(); + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java index 0064b280ddd0..e4bd50ef6e9e 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,24 +16,25 @@ package com.intellij.psi.impl.source.tree; import com.intellij.lang.ASTNode; +import com.intellij.lang.PsiBuilder; import com.intellij.lang.java.JavaLanguage; +import com.intellij.lang.java.parser.JavaParserUtil; +import com.intellij.lang.java.parser.JavadocParser; import com.intellij.lexer.JavaLexer; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.pom.java.LanguageLevel; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiManager; import com.intellij.psi.impl.source.javadoc.PsiDocCommentImpl; import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef; import com.intellij.psi.impl.source.javadoc.PsiDocParamRef; import com.intellij.psi.impl.source.javadoc.PsiDocTagImpl; -import com.intellij.psi.impl.source.parsing.JavaParsingContext; import com.intellij.psi.impl.source.tree.java.PsiInlineDocTagImpl; import com.intellij.psi.tree.*; import com.intellij.psi.tree.java.IJavaDocElementType; -import com.intellij.util.CharTable; import com.intellij.util.ReflectionUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.lang.reflect.Constructor; @@ -70,58 +71,68 @@ public interface JavaDocElementType { IElementType DOC_PARAMETER_REF = new JavaDocCompositeElementType("DOC_PARAMETER_REF", PsiDocParamRef.class); ILazyParseableElementType DOC_REFERENCE_HOLDER = new JavaDocLazyElementType("DOC_REFERENCE_HOLDER") { + private final JavaParserUtil.ParserWrapper myParser = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + JavadocParser.parseJavadocReference(builder); + } + }; + + @Nullable + @Override public ASTNode parseContents(final ASTNode chameleon) { - final CharSequence chars = chameleon.getChars(); - final PsiElement psi = chameleon.getTreeParent().getPsi(); - assert psi != null : chameleon; - final PsiManager manager = psi.getManager(); - final CharTable table = SharedImplUtil.findCharTableByTree(chameleon); - //no language features from higher java language versions are present in javadoc - final JavaParsingContext context = new JavaParsingContext(table, LanguageLevel.JDK_1_3); - return context.getJavadocParsing().parseJavaDocReference(chars, new JavaLexer(LanguageLevel.JDK_1_3), false, manager); + return JavaParserUtil.parseFragment(chameleon, myParser, false, LanguageLevel.JDK_1_3); } }; ILazyParseableElementType DOC_TYPE_HOLDER = new JavaDocLazyElementType("DOC_TYPE_HOLDER") { + private final JavaParserUtil.ParserWrapper myParser = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + JavadocParser.parseJavadocType(builder); + } + }; + + @Nullable + @Override public ASTNode parseContents(final ASTNode chameleon) { - final CharSequence chars = chameleon.getChars(); - final PsiElement psi = chameleon.getTreeParent().getPsi(); - assert psi != null : chameleon; - final PsiManager manager = psi.getManager(); - final CharTable table = SharedImplUtil.findCharTableByTree(chameleon); - //no language features from higher java language versions are present in javadoc - final JavaParsingContext context = new JavaParsingContext(table, LanguageLevel.JDK_1_3); - return context.getJavadocParsing().parseJavaDocReference(chars, new JavaLexer(LanguageLevel.JDK_1_3), true, manager); + return JavaParserUtil.parseFragment(chameleon, myParser, false, LanguageLevel.JDK_1_3); } }; ILazyParseableElementType DOC_COMMENT = new IReparseableElementType("DOC_COMMENT", JavaLanguage.INSTANCE) { + private final JavaParserUtil.ParserWrapper myParser = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + JavadocParser.parseDocCommentText(builder); + } + }; + @Override public ASTNode createNode(final CharSequence text) { return new PsiDocCommentImpl(text); } + @Nullable + @Override public ASTNode parseContents(final ASTNode chameleon) { - final CharSequence chars = chameleon.getChars(); - final PsiElement psi = chameleon.getTreeParent().getPsi(); - assert psi != null : chameleon; - final PsiManager manager = psi.getManager(); - //no higher java language level features are allowed in javadoc - final JavaParsingContext context = new JavaParsingContext(SharedImplUtil.findCharTableByTree(chameleon), LanguageLevel.JDK_1_3); - return context.getJavadocParsing().parseDocCommentText(manager, chars, 0, chars.length()); + return JavaParserUtil.parseFragment(chameleon, myParser); } public boolean isParsable(final CharSequence buffer, final Project project) { - final JavaLexer lexer = new JavaLexer(LanguageLevel.JDK_1_5); + final JavaLexer lexer = new JavaLexer(LanguageLevelProjectExtension.getInstance(project).getLanguageLevel()); lexer.start(buffer); - if (lexer.getTokenType() != DOC_COMMENT) return false; - lexer.advance(); - if (lexer.getTokenType() != null) return false; - return true; + if (lexer.getTokenType() == DOC_COMMENT) { + lexer.advance(); + if (lexer.getTokenType() == null) { + return true; + } + } + return false; } }; - + TokenSet ALL_JAVADOC_ELEMENTS = TokenSet.create( - DOC_TAG, DOC_INLINE_TAG, DOC_METHOD_OR_FIELD_REF, DOC_PARAMETER_REF, DOC_REFERENCE_HOLDER, DOC_TYPE_HOLDER, DOC_COMMENT + DOC_TAG, DOC_INLINE_TAG, DOC_METHOD_OR_FIELD_REF, DOC_PARAMETER_REF, DOC_REFERENCE_HOLDER, DOC_TYPE_HOLDER, DOC_COMMENT ); } diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/ParamTag0.java b/java/java-tests/testData/psi/parser-full/javadocParsing/ParamTag0.java new file mode 100644 index 000000000000..de3eeb32721d --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/javadocParsing/ParamTag0.java @@ -0,0 +1,8 @@ +class C { + /** + * Javadoc + * @param p1 + * @param p2 + */ + void m() { } +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/ParamTag0.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/ParamTag0.txt new file mode 100644 index 000000000000..6042867ec644 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/javadocParsing/ParamTag0.txt @@ -0,0 +1,63 @@ +PsiJavaFile:ParamTag0.java + PsiImportList + + PsiClass:C + PsiModifierList: + + PsiKeyword:class('class') + PsiWhiteSpace(' ') + PsiIdentifier:C('C') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiWhiteSpace('\n ') + PsiMethod:m + PsiDocComment + PsiDocToken:DOC_COMMENT_START('/**') + PsiWhiteSpace('\n ') + PsiDocToken:DOC_COMMENT_LEADING_ASTERISKS('*') + PsiDocToken:DOC_COMMENT_DATA(' Javadoc') + PsiWhiteSpace('\n ') + PsiDocToken:DOC_COMMENT_LEADING_ASTERISKS('*') + PsiDocToken:DOC_COMMENT_DATA(' ') + PsiDocTag:@param + PsiDocToken:DOC_TAG_NAME('@param') + PsiWhiteSpace(' ') + PsiElement(DOC_PARAMETER_REF) + PsiDocToken:DOC_TAG_VALUE_TOKEN('p1') + PsiWhiteSpace('\n ') + PsiDocToken:DOC_COMMENT_LEADING_ASTERISKS('*') + PsiDocToken:DOC_COMMENT_DATA(' ') + PsiDocTag:@param + PsiDocToken:DOC_TAG_NAME('@param') + PsiWhiteSpace(' ') + PsiElement(DOC_PARAMETER_REF) + PsiDocToken:DOC_TAG_VALUE_TOKEN('p2') + PsiWhiteSpace('\n ') + PsiDocToken:DOC_COMMENT_END('*/') + PsiWhiteSpace('\n ') + PsiModifierList: + + PsiTypeParameterList + + PsiTypeElement:void + PsiKeyword:void('void') + PsiWhiteSpace(' ') + PsiIdentifier:m('m') + PsiParameterList:() + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') + PsiReferenceList + + PsiWhiteSpace(' ') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') + PsiWhiteSpace('\n') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/JavadocParsingTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/JavadocParsingTest.java index 8ce2a4835d66..2d0432b198f9 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/JavadocParsingTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/JavadocParsingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,6 +60,7 @@ public class JavadocParsingTest extends JavaParsingTestCase { public void testLinkTag5() { doTest(true); } public void testLinkTag6() { doTest(true); } + public void testParamTag0() { doTest(true); } public void testParamTag1() { doTest(true); } public void testLinkPlainTag0() { doTest(true); } diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderFactoryImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderFactoryImpl.java index 1fafb26c2700..4c9d2d3df332 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderFactoryImpl.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,7 +48,8 @@ public class PsiBuilderFactoryImpl extends PsiBuilderFactory { @Nullable final Lexer lexer, @NotNull final Language lang, @NotNull final CharSequence seq) { - return new PsiBuilderImpl(project, LanguageParserDefinitions.INSTANCE.forLanguage(lang), lexer != null ? lexer : createLexer(project, lang), chameleon, seq); + final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(lang); + return new PsiBuilderImpl(project, parserDefinition, lexer != null ? lexer : createLexer(project, lang), chameleon, seq); } @NotNull @@ -59,8 +60,7 @@ public class PsiBuilderFactoryImpl extends PsiBuilderFactory { @NotNull final Language lang, @NotNull final CharSequence seq) { final Language language = chameleon.getTokenType().getLanguage(); - ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(language); - + final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(language); return new PsiBuilderImpl(project, parserDefinition, lexer != null ? lexer : createLexer(project, lang), chameleon, seq); } @@ -72,7 +72,8 @@ public class PsiBuilderFactoryImpl extends PsiBuilderFactory { @NotNull @Override - public PsiBuilder createBuilder(@NotNull ParserDefinition parserDefinition, @NotNull final Lexer lexer, + public PsiBuilder createBuilder(@NotNull final ParserDefinition parserDefinition, + @NotNull final Lexer lexer, @NotNull final CharSequence seq) { return new PsiBuilderImpl(null, null, parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer, null, seq, null, null); } diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index 8be80c5d4892..4d3a96f24b1b 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ package com.intellij.lang.impl; import com.intellij.lang.*; import com.intellij.lexer.Lexer; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; @@ -56,7 +57,7 @@ import java.util.List; import java.util.Map; /** - * User: max + * @author max */ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { private static final Logger LOG = Logger.getInstance("#com.intellij.lang.impl.PsiBuilderImpl"); @@ -135,16 +136,22 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { @NotNull ParserDefinition parserDefinition, @NotNull Lexer lexer, CharTable charTable, - @NotNull final CharSequence text, ASTNode originalTree, MyTreeStructure parentLightTree) { - this(project, containingFile, parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer, charTable, text, originalTree, parentLightTree); + @NotNull final CharSequence text, + @Nullable ASTNode originalTree, + @Nullable MyTreeStructure parentLightTree) { + this(project, containingFile, parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer, charTable, text, + originalTree, parentLightTree); } + public PsiBuilderImpl(Project project, PsiFile containingFile, @NotNull TokenSet whiteSpaces, @NotNull TokenSet comments, @NotNull Lexer lexer, CharTable charTable, - @NotNull final CharSequence text, ASTNode originalTree, MyTreeStructure parentLightTree) { + @NotNull final CharSequence text, + @Nullable ASTNode originalTree, + @Nullable MyTreeStructure parentLightTree) { myProject = project; myFile = containingFile; @@ -152,7 +159,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { myTextArray = CharArrayUtil.fromSequenceWithoutCopying(text); myLexer = lexer; - myWhitespaces=whiteSpaces; + myWhitespaces = whiteSpaces; myComments = comments; myCharTable = charTable; myOriginalTree = originalTree; @@ -166,7 +173,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { @NotNull final Lexer lexer, @NotNull final ASTNode chameleon, @NotNull final CharSequence text) { - this(project, SharedImplUtil.getContainingFile(chameleon), parserDefinition, lexer, SharedImplUtil.findCharTableByTree(chameleon), text, chameleon.getUserData(BlockSupport.TREE_TO_BE_REPARSED), null); + this(project, SharedImplUtil.getContainingFile(chameleon), parserDefinition, lexer, SharedImplUtil.findCharTableByTree(chameleon), text, + chameleon.getUserData(BlockSupport.TREE_TO_BE_REPARSED), null); } public PsiBuilderImpl(@NotNull final Project project, @@ -174,7 +182,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { @NotNull final Lexer lexer, @NotNull final LighterLazyParseableNode chameleon, @NotNull final CharSequence text) { - this(project, chameleon.getContainingFile(), parserDefinition, lexer, chameleon.getCharTable(), text, null, ((LazyParseableToken)chameleon).myParent); + this(project, chameleon.getContainingFile(), parserDefinition, lexer, chameleon.getCharTable(), text, + null, ((LazyParseableToken)chameleon).myParent); } private void cacheLexemes() { @@ -949,7 +958,9 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { final MyTreeStructure treeStructure = new MyTreeStructure(newRoot, null); final MyComparator comparator = new MyComparator(getUserDataUnprotected(CUSTOM_COMPARATOR), treeStructure); - BlockSupportImpl.diffTrees(oldRoot, builder, comparator, treeStructure, ProgressIndicatorProvider.getInstance().getProgressIndicator()); + final ProgressIndicatorProvider provider = ProgressIndicatorProvider.getInstance(); + final ProgressIndicator indicator = provider != null ? provider.getProgressIndicator() : null; + BlockSupportImpl.diffTrees(oldRoot, builder, comparator, treeStructure, indicator); return diffLog; } @@ -1512,10 +1523,10 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } } + @SuppressWarnings("unchecked") @Override public T getUserDataUnprotected(@NotNull final Key key) { if (key == FileContextUtil.CONTAINING_FILE_KEY) return (T)myFile; - //noinspection unchecked return myUserData != null ? (T)myUserData.get(key) : null; }