blob: d9b061483567db01ebdfb85a17658dd66d47ff74 [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.jetbrains.python.documentation;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: catherine
*/
public class DocStringUtil {
private DocStringUtil() {
}
@Nullable
public static String getDocStringValue(@NotNull PyDocStringOwner owner) {
return PyPsiUtils.strValue(owner.getDocStringExpression());
}
@Nullable
public static StructuredDocString parse(@Nullable String text) {
if (text == null) {
return null;
}
if (isSphinxDocString(text)) {
return new SphinxDocString(text);
}
return new EpydocString(text);
}
public static boolean isSphinxDocString(@NotNull String text) {
return text.contains(":param ") || text.contains(":rtype") || text.contains(":type");
}
public static boolean isEpydocDocString(@NotNull String text) {
return text.contains("@param ") || text.contains("@rtype") || text.contains("@type");
}
/**
* Looks for a doc string under given parent.
* @param parent where to look. For classes and functions, this would be PyStatementList, for modules, PyFile.
* @return the defining expression, or null.
*/
@Nullable
public static PyStringLiteralExpression findDocStringExpression(@Nullable PyElement parent) {
if (parent != null) {
PsiElement seeker = PyUtil.getFirstNonCommentAfter(parent.getFirstChild());
if (seeker instanceof PyExpressionStatement) seeker = PyUtil.getFirstNonCommentAfter(seeker.getFirstChild());
if (seeker instanceof PyStringLiteralExpression) return (PyStringLiteralExpression)seeker;
}
return null;
}
public static StructuredDocString getStructuredDocString(PyDocStringOwner owner) {
return parse(owner.getDocStringValue());
}
public static boolean isDocStringExpression(@Nullable PyExpression expression) {
final PyDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(expression, PyDocStringOwner.class);
if (docStringOwner != null) {
if (docStringOwner.getDocStringExpression() == expression) {
return true;
}
}
if (expression instanceof PyStringLiteralExpression) {
return isVariableDocString((PyStringLiteralExpression)expression);
}
return false;
}
@Nullable
public static String getAttributeDocComment(@NotNull PyTargetExpression attr) {
if (attr.getParent() instanceof PyAssignmentStatement) {
final PyAssignmentStatement assignment = (PyAssignmentStatement)attr.getParent();
PsiElement prevSibling = assignment.getPrevSibling();
while (prevSibling != null && (prevSibling instanceof PsiWhiteSpace)) {
prevSibling = prevSibling.getPrevSibling();
}
if (prevSibling instanceof PsiComment && prevSibling.getText().startsWith("#:")) {
return prevSibling.getText().substring(2);
}
}
return null;
}
public static boolean isVariableDocString(@NotNull PyStringLiteralExpression expr) {
final PsiElement parent = expr.getParent();
if (!(parent instanceof PyExpressionStatement)) {
return false;
}
PsiElement prevElement = parent.getPrevSibling();
while (prevElement instanceof PsiWhiteSpace || prevElement instanceof PsiComment) {
prevElement = prevElement.getPrevSibling();
}
if (prevElement instanceof PyAssignmentStatement) {
if (expr.getText().contains("type:")) return true;
final PyAssignmentStatement assignmentStatement = (PyAssignmentStatement)prevElement;
final ScopeOwner scope = PsiTreeUtil.getParentOfType(prevElement, ScopeOwner.class);
if (scope instanceof PyClass || scope instanceof PyFile) {
return true;
}
if (scope instanceof PyFunction) {
for (PyExpression target : assignmentStatement.getTargets()) {
if (PyUtil.isInstanceAttribute(target)) {
return true;
}
}
}
}
return false;
}
}