Javadoc refactoring

This commit is contained in:
Denis.Zhdanov
2013-07-23 12:49:09 +04:00
parent 7c69dfcd9c
commit 718c577bae
4 changed files with 88 additions and 70 deletions
@@ -16,9 +16,11 @@
package com.intellij.psi.impl.source.codeStyle;
import com.intellij.lang.ASTNode;
import com.intellij.lang.StdLanguages;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
@@ -31,57 +33,51 @@ public class FormatCommentsProcessor implements PreFormatProcessor {
@NotNull
@Override
public TextRange process(@NotNull final ASTNode element, @NotNull final TextRange range) {
final Project project = SourceTreeToPsiMap.treeElementToPsi(element).getProject();
PsiElement e = SourceTreeToPsiMap.treeElementToPsi(element);
assert e != null;
final Project project = e.getProject();
if (!CodeStyleSettingsManager.getSettings(project).ENABLE_JAVADOC_FORMATTING ||
element.getPsi().getContainingFile().getLanguage() != StdLanguages.JAVA) {
element.getPsi().getContainingFile().getLanguage() != JavaLanguage.INSTANCE)
{
return range;
}
return formatCommentsInner(project, element, range);
}
private static TextRange formatCommentsInner(Project project, ASTNode element, final TextRange range) {
TextRange result = range;
/**
* Formats PsiDocComments of current ASTNode element and all his children PsiDocComments
*/
@NotNull
private static TextRange formatCommentsInner(@NotNull Project project, @NotNull ASTNode element, @NotNull final TextRange markedRange) {
TextRange resultTextRange = markedRange;
boolean shouldFormat = markedRange.contains(element.getTextRange());
if (shouldFormat) {
TextRange before = element.getTextRange();
new CommentFormatter(project).processComment(element);
int deltaRange = element.getTextRange().getLength() - before.getLength();
resultTextRange = new TextRange(markedRange.getStartOffset(), markedRange.getEndOffset() + deltaRange);
}
// check for RepositoryTreeElement is optimization
if (shouldProcess(element)) {
final TextRange elementRange = element.getTextRange();
if (range.contains(elementRange)) {
new CommentFormatter(project).process(element);
final TextRange newRange = element.getTextRange();
result = new TextRange(range.getStartOffset(), range.getEndOffset() + newRange.getLength() - elementRange.getLength());
}
// optimization, does not seek PsiDocComment inside fields / methods or out of range
if (element.getPsi() instanceof PsiField ||
element.getPsi() instanceof PsiMethod ||
element instanceof PsiDocComment ||
range.getEndOffset() < elementRange.getStartOffset()
) {
return result;
}
final PsiElement elementPsi = element.getPsi();
// If element is Psi{Method, Field, DocComment} and was formatted there is no reason to continue - we formatted all possible javadocs.
// If element is out of range its children are also out of range. So in both cases formatting is finished. It's just for optimization.
if ((shouldFormat && (elementPsi instanceof PsiMethod || elementPsi instanceof PsiField || elementPsi instanceof PsiDocComment))
|| markedRange.getEndOffset() < element.getStartOffset())
{
return resultTextRange;
}
ASTNode current = element.getFirstChildNode();
while (current != null) {
// we expand the chameleons here for effectiveness
current.getFirstChildNode();
result = formatCommentsInner(project, current, result);
//When element is PsiClass his PsiDocComment is formatted up to this moment, so we didn't need to format it again.
if (!(shouldFormat && current.getPsi() instanceof PsiDocComment && elementPsi instanceof PsiClass)) {
resultTextRange = formatCommentsInner(project, current, resultTextRange);
}
current = current.getTreeNext();
}
return result;
}
private static boolean shouldProcess(final ASTNode element) {
if (element instanceof PsiDocComment) {
return true;
}
else {
return true;//element.getElementType() instanceof JavaStubElementType &&
//(element.getPsi()) instanceof PsiDocCommentOwner;
}
return resultTextRange;
}
}
@@ -43,7 +43,7 @@ public class CommentFormatter {
private final JDParser myParser;
private final Project myProject;
public CommentFormatter(Project project) {
public CommentFormatter(@NotNull Project project) {
mySettings = CodeStyleSettingsManager.getSettings(project);
myParser = new JDParser(mySettings);
myProject = project;
@@ -57,7 +57,7 @@ public class CommentFormatter {
return myParser;
}
public void process(ASTNode element) {
public void processComment(@Nullable ASTNode element) {
if (!getSettings().ENABLE_JAVADOC_FORMATTING) return;
PsiElement psiElement = SourceTreeToPsiMap.treeElementToPsi(element);
@@ -320,18 +320,20 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
}
public void testClassComment() throws Exception {
doTextTest("/**\n" +
"* @author smbd\n" +
"* @param <T> some param\n" +
"* @since 1.9\n" +
"*/\n" +
"class Test<T>{}",
"/**\n" +
" * @param <T> some param\n" +
" * @author smbd\n" +
" * @since 1.9\n" +
" */\n" +
"class Test<T> {\n}");
String before = "/**\n" +
"* @author smbd\n" +
"* @param <T> some param\n" +
"* @since 1.9\n" +
"*/\n" +
"class Test<T>{}";
String after = "/**\n" +
" * @param <T> some param\n" +
" * @author smbd\n" +
" * @since 1.9\n" +
" */\n" +
"class Test<T> {\n" +
"}";
doTextTest(before,after);
}
public void testStringBinaryOperation() throws Exception {
@@ -1166,23 +1168,27 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
}
public void testNewLineAfterJavaDocs() throws Exception {
doTextTest("/** @noinspection InstanceVariableNamingConvention*/class Foo{\n" +
"/** @noinspection InstanceVariableNamingConvention*/int myFoo;\n" +
"/** @noinspection InstanceVariableNamingConvention*/ void foo(){}}", "/**\n" +
" * @noinspection InstanceVariableNamingConvention\n" +
" */\n" +
"class Foo {\n" +
" /**\n" +
" * @noinspection InstanceVariableNamingConvention\n" +
" */\n" +
" int myFoo;\n" +
"\n" +
" /**\n" +
" * @noinspection InstanceVariableNamingConvention\n" +
" */\n" +
" void foo() {\n" +
" }\n" +
"}");
String before = "/** @noinspection InstanceVariableNamingConvention*/class Foo{\n" +
"/** @noinspection InstanceVariableNamingConvention*/int myFoo;\n" +
"/** @noinspection InstanceVariableNamingConvention*/ void foo(){}}";
String after = "/**\n" +
" * @noinspection InstanceVariableNamingConvention\n" +
" */\n" +
"class Foo {\n" +
" /**\n" +
" * @noinspection InstanceVariableNamingConvention\n" +
" */\n" +
" int myFoo;\n" +
"\n" +
" /**\n" +
" * @noinspection InstanceVariableNamingConvention\n" +
" */\n" +
" void foo() {\n" +
" }\n" +
"}";
doTextTest(before, after);
}
public void testArrayInitializerWrapping() throws Exception {
@@ -41,6 +41,23 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
}
public void testOneLineCommentWrappedByRightMarginIntoMultiLine() throws Exception {
getSettings().getRootSettings().WRAP_COMMENTS = true;
getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
getSettings().getRootSettings().JD_DO_NOT_WRAP_ONE_LINE_COMMENTS = true;
getSettings().getRootSettings().RIGHT_MARGIN = 35;
doTextTest(
"/** Here is one-line java-doc comment */" +
"class Foo {\n" +
"}",
"/**\n" +
" * Here is one-line java-doc\n" +
" * comment\n" +
" */\n" +
"class Foo {\n" +
"}");
}
public void testLineFeedsArePreservedDuringWrap() {
// Inspired by IDEA-61895
getSettings().getRootSettings().WRAP_COMMENTS = true;
@@ -587,6 +604,5 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
"}";
doTextTest(before, after);
}
}
}