/** * 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); }
private static void tryConvertEndOfLineComment(Document doc, PsiElement commentElement) { Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(commentElement.getLanguage()); if (commenter instanceof CodeDocumentationAwareCommenter) { CodeDocumentationAwareCommenter docCommenter = (CodeDocumentationAwareCommenter) commenter; String lineCommentPrefix = commenter.getLineCommentPrefix(); String blockCommentPrefix = commenter.getBlockCommentPrefix(); String blockCommentSuffix = commenter.getBlockCommentSuffix(); if (commentElement.getNode().getElementType() == docCommenter.getLineCommentTokenType() && blockCommentPrefix != null && blockCommentSuffix != null && lineCommentPrefix != null) { String commentText = StringUtil.trimStart(commentElement.getText(), lineCommentPrefix); try { Project project = commentElement.getProject(); PsiParserFacade parserFacade = PsiParserFacade.SERVICE.getInstance(project); PsiComment newComment = parserFacade.createBlockCommentFromText(commentElement.getLanguage(), commentText); commentElement.replace(newComment); PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(doc); } catch (IncorrectOperationException e) { LOG.info("Failed to replace line comment with block comment", e); } } } }
/** * 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(PsiUtilBase.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); }
static CommentContext tryParseCommentContext(@Nullable Commenter langCommenter, @Nonnull CharSequence chars, int offset, int lineStartOffset) { 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); }
public static void createTypeParamsListComment(final StringBuilder buffer, final Project project, final CodeDocumentationAwareCommenter commenter, final PsiTypeParameterList typeParameterList) { final PsiTypeParameter[] typeParameters = typeParameterList.getTypeParameters(); for (PsiTypeParameter typeParameter : typeParameters) { buffer.append(CodeDocumentationUtil.createDocCommentLine(PARAM_TAG, project, commenter)); buffer.append("<").append(typeParameter.getName()).append(">"); buffer.append(LINE_SEPARATOR); } }
@Override public boolean isOneLine() { final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(myHost.getLanguage()); if (commenter instanceof CodeDocumentationAwareCommenter) { return myHost.getTokenType() == ((CodeDocumentationAwareCommenter) commenter).getLineCommentTokenType(); } return false; }
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 + " "; } } }
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; }
@Override public boolean canSelect(PsiElement e) { if (e instanceof PsiComment) { final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(e.getLanguage()); if (!(commenter instanceof CodeDocumentationAwareCommenter)) return true; return !((CodeDocumentationAwareCommenter) commenter).isDocumentationComment((PsiComment)e); } return false; }
private static boolean hasAnyDocAwareCommenters() { final Collection<Language> languages = Language.getRegisteredLanguages(); for (Language language : languages) { final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(language); if (commenter instanceof CodeDocumentationAwareCommenter) { final CodeDocumentationAwareCommenter docCommenter = (CodeDocumentationAwareCommenter)commenter; if (docCommenter.getDocumentationCommentLinePrefix() != null) { return true; } } } return false; }
private static void createTypeParamsListComment(final StringBuilder buffer, final Project project, final CodeDocumentationAwareCommenter commenter, final PsiTypeParameterList typeParameterList) { final PsiTypeParameter[] typeParameters = typeParameterList.getTypeParameters(); for (PsiTypeParameter typeParameter : typeParameters) { buffer.append(CodeDocumentationUtil.createDocCommentLine(PARAM_TAG, project, commenter)); buffer.append("<").append(typeParameter.getName()).append(">"); buffer.append(LINE_SEPARATOR); } }
public boolean isOneLine() { final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(myHost.getLanguage()); if (commenter instanceof CodeDocumentationAwareCommenter) { return myHost.getTokenType() == ((CodeDocumentationAwareCommenter) commenter).getLineCommentTokenType(); } return false; }
private static String getLineCommentPrefix(IElementType token) { if (token == null) return null; Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(token.getLanguage()); return (commenter instanceof CodeDocumentationAwareCommenter) && token.equals(((CodeDocumentationAwareCommenter)commenter).getLineCommentTokenType()) ? commenter.getLineCommentPrefix() : null; }
public static void createTypeParamsListComment(final StringBuilder buffer, final Project project, final CodeDocumentationAwareCommenter commenter, final PsiTypeParameterList typeParameterList) { final PsiTypeParameter[] typeParameters = typeParameterList.getTypeParameters(); for(PsiTypeParameter typeParameter : typeParameters) { buffer.append(CodeDocumentationUtil.createDocCommentLine(PARAM_TAG, project, commenter)); buffer.append("<").append(typeParameter.getName()).append(">"); buffer.append(LINE_SEPARATOR); } }
public static void generateParametersTakingDocFromSuperMethods(Project project, StringBuilder builder, CodeDocumentationAwareCommenter commenter, PsiMethod psiMethod) { final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); final Map<String, String> param2Description = new HashMap<String, String>(); final PsiMethod[] superMethods = psiMethod.findSuperMethods(); for (PsiMethod superMethod : superMethods) { final PsiDocComment comment = superMethod.getDocComment(); if (comment != null) { final PsiDocTag[] params = comment.findTagsByName("param"); for (PsiDocTag param : params) { final PsiElement[] dataElements = param.getDataElements(); if (dataElements != null) { String paramName = null; for (PsiElement dataElement : dataElements) { if (dataElement instanceof PsiDocParamRef) { //noinspection ConstantConditions paramName = dataElement.getReference().getCanonicalText(); break; } } if (paramName != null) { param2Description.put(paramName, param.getText()); } } } } } for (PsiParameter parameter : parameters) { String description = param2Description.get(parameter.getName()); if (description != null) { builder.append(CodeDocumentationUtil.createDocCommentLine("", project, commenter)); if (description.indexOf('\n') > -1) description = description.substring(0, description.lastIndexOf('\n')); builder.append(description); } else { builder.append(CodeDocumentationUtil.createDocCommentLine(PARAM_TAG, project, commenter)); builder.append(parameter.getName()); } builder.append(LINE_SEPARATOR); } }
@Override public String generateDocumentationContentStub(PsiComment contextComment) { if (!(contextComment instanceof GrDocComment)) { return null; } final GrDocCommentOwner owner = GrDocCommentUtil.findDocOwner((GrDocComment)contextComment); if (owner == null) return null; Project project = contextComment.getProject(); final CodeDocumentationAwareCommenter commenter = (CodeDocumentationAwareCommenter)LanguageCommenters.INSTANCE.forLanguage(owner.getLanguage()); StringBuilder builder = StringBuilderSpinAllocator.alloc(); try { if (owner instanceof GrMethod) { final GrMethod method = (GrMethod)owner; JavaDocumentationProvider.generateParametersTakingDocFromSuperMethods(project, builder, commenter, method); final PsiType returnType = method.getInferredReturnType(); if ((returnType != null || method.getModifierList().hasModifierProperty(GrModifier.DEF)) && returnType != PsiType.VOID) { builder.append(CodeDocumentationUtil.createDocCommentLine(RETURN_TAG, project, commenter)); builder.append(LINE_SEPARATOR); } final PsiClassType[] references = method.getThrowsList().getReferencedTypes(); for (PsiClassType reference : references) { builder.append(CodeDocumentationUtil.createDocCommentLine(THROWS_TAG, project, commenter)); builder.append(reference.getClassName()); builder.append(LINE_SEPARATOR); } } else if (owner instanceof GrTypeDefinition) { final PsiTypeParameterList typeParameterList = ((PsiClass)owner).getTypeParameterList(); if (typeParameterList != null) { JavaDocumentationProvider.createTypeParamsListComment(builder, project, commenter, typeParameterList); } } return builder.length() > 0 ? builder.toString() : null; } finally { StringBuilderSpinAllocator.dispose(builder); } }
public static void generateParametersTakingDocFromSuperMethods(Project project, StringBuilder builder, CodeDocumentationAwareCommenter commenter, PsiMethod psiMethod) { final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); final Map<String, String> param2Description = new HashMap<>(); final PsiMethod[] superMethods = psiMethod.findSuperMethods(); for(PsiMethod superMethod : superMethods) { final PsiDocComment comment = superMethod.getDocComment(); if(comment != null) { final PsiDocTag[] params = comment.findTagsByName("param"); for(PsiDocTag param : params) { final PsiElement[] dataElements = param.getDataElements(); if(dataElements != null) { String paramName = null; for(PsiElement dataElement : dataElements) { if(dataElement instanceof PsiDocParamRef) { //noinspection ConstantConditions paramName = dataElement.getReference().getCanonicalText(); break; } } if(paramName != null) { param2Description.put(paramName, param.getText()); } } } } } for(PsiParameter parameter : parameters) { String description = param2Description.get(parameter.getName()); if(description != null) { builder.append(CodeDocumentationUtil.createDocCommentLine("", project, commenter)); if(description.indexOf('\n') > -1) { description = description.substring(0, description.lastIndexOf('\n')); } builder.append(description); } else { builder.append(CodeDocumentationUtil.createDocCommentLine(PARAM_TAG, project, commenter)); builder.append(parameter.getName()); } builder.append(LINE_SEPARATOR); } }
boolean isCommentComplete(PsiComment comment, CodeDocumentationAwareCommenter commenter, Editor editor);
boolean isApplicable(PsiComment comment, CodeDocumentationAwareCommenter commenter);