blob: bcb6196c9434e85984195ba51e38fd9b1c9cd993 [file] [log] [blame]
/*
* Copyright 2000-2013 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.codeInsight.editorActions;
import com.intellij.lang.CodeDocumentationAwareCommenter;
import com.intellij.lang.Commenter;
import com.intellij.lang.LanguageCommenters;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public class CodeDocumentationUtil {
private CodeDocumentationUtil() {
}
public static String createDocCommentLine(String lineData, Project project, CodeDocumentationAwareCommenter commenter) {
if (!CodeStyleSettingsManager.getSettings(project).JD_LEADING_ASTERISKS_ARE_ENABLED) {
return " " + lineData + " ";
}
else {
if (lineData.length() == 0) {
return commenter.getDocumentationCommentLinePrefix() + " ";
}
else {
return commenter.getDocumentationCommentLinePrefix() + " " + lineData + " ";
}
}
}
/**
* Utility method that does the following:
* <pre>
* <ol>
* <li>Checks if target document line that contains given offset starts with '*';</li>
* <li>Returns document text located between the '*' and first non-white space symbols after it if the check above is successful;</li>
* </ol>
</pre>
*
* @param document target document
* @param offset target offset that identifies line to check and max offset to use during scanning
* @return
*/
@Nullable
public static String getIndentInsideJavadoc(@NotNull Document document, int offset) {
CharSequence text = document.getCharsSequence();
if (offset >= text.length()) {
return null;
}
int line = document.getLineNumber(offset);
int lineStartOffset = document.getLineStartOffset(line);
int lineEndOffset = document.getLineEndOffset(line);
int i = CharArrayUtil.shiftForward(text, lineStartOffset, " \t");
if (i > lineEndOffset || text.charAt(i) != '*') {
return null;
}
int start = i + 1;
int end = CharArrayUtil.shiftForward(text, start, " \t");
end = Math.min(end, lineEndOffset);
return end > start ? text.subSequence(start, end).toString() : "";
}
/**
* Analyzes position at the given offset at the given text and returns information about comments presence and kind there if any.
*
* @param file target file being edited (necessary for language recognition at target offset. Language is necessary
* to get information about specific comment syntax)
* @param chars target text
* @param offset target offset at the given text
* @param lineStartOffset start offset of the line that contains given offset
* @return object that encapsulates information about comments at the given offset at the given text
*/
@NotNull
public static CommentContext tryParseCommentContext(@NotNull PsiFile file, @NotNull CharSequence chars, int offset, int lineStartOffset) {
Commenter langCommenter = LanguageCommenters.INSTANCE.forLanguage(PsiUtilCore.getLanguageAtOffset(file, offset));
final boolean isInsideCommentLikeCode = langCommenter instanceof CodeDocumentationAwareCommenter;
if (!isInsideCommentLikeCode) {
return new CommentContext();
}
final CodeDocumentationAwareCommenter commenter = (CodeDocumentationAwareCommenter)langCommenter;
int commentStartOffset = CharArrayUtil.shiftForward(chars, lineStartOffset, " \t");
boolean docStart = commenter.getDocumentationCommentPrefix() != null
&& CharArrayUtil.regionMatches(chars, commentStartOffset, commenter.getDocumentationCommentPrefix());
boolean cStyleStart = commenter.getBlockCommentPrefix() != null
&& CharArrayUtil.regionMatches(chars, commentStartOffset, commenter.getBlockCommentPrefix());
boolean docAsterisk = commenter.getDocumentationCommentLinePrefix() != null
&& CharArrayUtil.regionMatches(chars, commentStartOffset, commenter.getDocumentationCommentLinePrefix());
final int firstNonSpaceInLine = CharArrayUtil.shiftForward(chars, offset, " \t");
boolean slashSlash = commenter.getLineCommentPrefix() != null
&& CharArrayUtil.regionMatches(chars, commentStartOffset, commenter.getLineCommentPrefix())
&& firstNonSpaceInLine < chars.length() && chars.charAt(firstNonSpaceInLine) != '\n';
return new CommentContext(commenter, docStart, cStyleStart, docAsterisk, slashSlash, commentStartOffset);
}
/**
* Utility class that contains information about current comment context.
*/
public static class CommentContext {
public final CodeDocumentationAwareCommenter commenter;
public final int lineStart;
/** Indicates position at the line that starts from {@code '/**'} (in java language). */
public boolean docStart;
/** Indicates position at the line that starts from {@code '/*'} (in java language). */
public boolean cStyleStart;
/** Indicates position at the line that starts from {@code '*'} (non-first and non-last javadoc line in java language). */
public boolean docAsterisk;
/** Indicates position at the line that starts from {@code '//'} (in java language). */
public boolean slashSlash;
public CommentContext() {
commenter = null;
lineStart = 0;
}
public CommentContext(CodeDocumentationAwareCommenter commenter, boolean docStart, boolean cStyleStart, boolean docAsterisk,
boolean slashSlash, int lineStart)
{
this.docStart = docStart;
this.cStyleStart = cStyleStart;
this.docAsterisk = docAsterisk;
this.slashSlash = slashSlash;
this.commenter = commenter;
this.lineStart = lineStart;
}
}
}