下面列出了怎么用com.intellij.psi.PsiComment的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Adds comment to the given method "// An event handler ContextClassName.methodName(c,
* parameterName)
*/
public static void addComment(PsiClass contextClass, PsiMethod method) {
final Project project = contextClass.getProject();
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final StringBuilder builder =
new StringBuilder("// An event handler ")
.append(LithoPluginUtils.getLithoComponentNameFromSpec(contextClass.getName()))
.append(".")
.append(method.getName())
.append("(")
.append(CONTEXT_PARAMETER_NAME);
for (PsiParameter parameter : method.getParameterList().getParameters()) {
if (LithoPluginUtils.isParam(parameter)) {
builder.append(", ").append(parameter.getName());
}
}
builder.append(")");
final PsiComment comment = factory.createCommentFromText(builder.toString(), method);
method.addBefore(comment, method.getModifierList());
}
@Override
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder annotationHolder) {
if (element instanceof PsiComment) {
IElementType commentTokenType = ((PsiComment) element).getTokenType();
if (commentTokenType != SoyTypes.DOC_COMMENT_BLOCK
&& commentTokenType != SoyTypes.COMMENT_BLOCK) {
return;
}
if (!element.getText().endsWith("*/")) {
int start = element.getTextRange().getEndOffset() - 1;
int end = start + 1;
annotationHolder
.createErrorAnnotation(TextRange.create(start, end), "Unterminated comment");
}
}
}
@Override
public Result postProcessEnter(
@NotNull PsiFile file, @NotNull Editor editor, @NotNull DataContext dataContext) {
if (file.getFileType() != SoyFileType.INSTANCE) {
return Result.Continue;
}
int caretOffset = editor.getCaretModel().getOffset();
PsiElement element = file.findElementAt(caretOffset);
Document document = editor.getDocument();
int lineNumber = document.getLineNumber(caretOffset) - 1;
int lineStartOffset = document.getLineStartOffset(lineNumber);
String lineTextBeforeCaret = document.getText(new TextRange(lineStartOffset, caretOffset));
if (element instanceof PsiComment && element.getTextOffset() < caretOffset) {
handleEnterInComment(element, file, editor);
} else if (lineTextBeforeCaret.startsWith("/*")) {
insertText(file, editor, " * \n ", 3);
}
return Result.Continue;
}
/**
* Used for debugging. Will return the statement the given element is contained in.
* If the element is a PsiComment, <PsiComment> will be returned. Otherwise, the element's ancestor statement
* text will be returned with all newlines replaced with spaces.
* <p>
* If the element has no parent or no {@link SQFStatement} parent, <No Statement Parent> will be returned
*
* @return the text, or <PsiComment> if element is a PsiComment
*/
@NotNull
public static String debug_getStatementTextForElement(@NotNull PsiElement element) {
if (element instanceof PsiComment) {
return "<PsiComment>";
}
if (element.getContainingFile() == null || !(element.getContainingFile() instanceof SQFFile)) {
throw new IllegalArgumentException("element isn't in an SQFFile");
}
while (!(element instanceof SQFStatement)) {
element = element.getParent();
if (element == null) {
return "<No Statement Parent>";
}
}
return element.getText().replaceAll("\n", " ");
}
private static FuncallExpression getRuleFuncallExpression(PsiElement element) {
PsiFile parentFile = element.getContainingFile();
if (!(parentFile instanceof BuildFile)
|| ((BuildFile) parentFile).getBlazeFileType() != BlazeFileType.BuildPackage) {
return null;
}
if (!(element instanceof LeafElement)
|| element instanceof PsiWhiteSpace
|| element instanceof PsiComment) {
return null;
}
if (!(element.getParent() instanceof ReferenceExpression)) {
return null;
}
PsiElement grandParent = element.getParent().getParent();
return grandParent instanceof FuncallExpression
&& ((FuncallExpression) grandParent).isTopLevel()
? (FuncallExpression) grandParent
: null;
}
/** Get all non-WS, non-Comment children of t */
@NotNull
public static PsiElement[] getChildren(PsiElement t) {
if ( t==null ) return PsiElement.EMPTY_ARRAY;
PsiElement psiChild = t.getFirstChild();
if (psiChild == null) return PsiElement.EMPTY_ARRAY;
List<PsiElement> result = new ArrayList<>();
while (psiChild != null) {
if ( !(psiChild instanceof PsiComment) &&
!(psiChild instanceof PsiWhiteSpace) )
{
result.add(psiChild);
}
psiChild = psiChild.getNextSibling();
}
return PsiUtilCore.toPsiElementArray(result);
}
@NotNull
@Override
public Tokenizer getTokenizer(PsiElement element) {
if (element instanceof PsiWhiteSpace) {
return EMPTY_TOKENIZER;
}
if (element instanceof PsiNameIdentifierOwner) {
return new PsiIdentifierOwnerTokenizer();
}
if (element.getParent() instanceof PsiNameIdentifierOwner) {
return EMPTY_TOKENIZER;
}
if (element.getNode().getElementType() == JSGraphQLEndpointTokenTypes.IDENTIFIER) {
return IDENTIFIER_TOKENIZER;
}
if (element instanceof PsiComment) {
if (SuppressionUtil.isSuppressionComment(element)) {
return EMPTY_TOKENIZER;
}
return myCommentTokenizer;
}
return EMPTY_TOKENIZER;
}
@Nullable
protected SimpleMatch isDuplicateFragment(@Nonnull final PsiElement candidate) {
if (!canReplace(myReplacement, candidate)) return null;
for (PsiElement pattern : myPattern) {
if (PsiTreeUtil.isAncestor(pattern, candidate, false)) return null;
}
PsiElement sibling = candidate;
final ArrayList<PsiElement> candidates = new ArrayList<>();
for (int i = 0; i != myPattern.size(); ++i) {
if (sibling == null) return null;
candidates.add(sibling);
sibling = PsiTreeUtil.skipSiblingsForward(sibling, PsiWhiteSpace.class, PsiComment.class);
}
if (myPattern.size() != candidates.size()) return null;
if (candidates.size() <= 0) return null;
final SimpleMatch match = new SimpleMatch(candidates.get(0), candidates.get(candidates.size() - 1));
for (int i = 0; i < myPattern.size(); i++) {
if (!matchPattern(myPattern.get(i), candidates.get(i), match)) return null;
}
return match;
}
/**
* Gets whether the specified comment is considered documentation, i.e. that it's placed directly above a type or field definition
*/
public static boolean isDocumentationComment(PsiElement element) {
if (element instanceof PsiComment) {
PsiElement next = element.getNextSibling();
while (next != null) {
final boolean isWhiteSpace = next instanceof PsiWhiteSpace;
if (next instanceof PsiComment || isWhiteSpace) {
if (isWhiteSpace && StringUtils.countMatches(next.getText(), "\n") > 1) {
// a blank line before the next element, so this comment is not directly above it
break;
}
next = next.getNextSibling();
} else {
break;
}
}
if (next instanceof JSGraphQLEndpointFieldDefinition || next instanceof JSGraphQLEndpointNamedTypeDefinition) {
return true;
}
}
return false;
}
/**
* Gets the text of the continuous comments placed directly above the specified element
* @param element element whose previous siblings are enumerated and included if they're documentation comments
* @return the combined text of the documentation comments, preserving line breaks, or <code>null</code> if no documentation is available
*/
public static String getDocumentation(PsiElement element) {
final PsiComment comment = PsiTreeUtil.getPrevSiblingOfType(element, PsiComment.class);
final PsiElement previousElement =PsiTreeUtil.getPrevSiblingOfType(element, element.getClass());
if(isDocumentationComment(comment)) {
if(previousElement != null && previousElement.getTextOffset() > comment.getTextOffset()) {
// the comment is for another element of same type so no docs for this element
return null;
}
final List<PsiComment> siblings = Lists.newArrayList(comment);
getDocumentationCommentSiblings(comment, siblings, PsiElement::getPrevSibling);
Collections.reverse(siblings);
return siblings.stream().map(c -> StringUtils.stripStart(c.getText(), "# ")).collect(Collectors.joining("\n"));
}
return null;
}
/**
* @return the nearest ancestor {@link SQFStatement} that contains the given element, or null if not in a {@link SQFStatement}
* @throws IllegalArgumentException when element is a PsiComment or when it is not in an SQFFile
*/
@Nullable
public static SQFStatement getStatementForElement(@NotNull PsiElement element) {
if (element instanceof PsiComment) {
throw new IllegalArgumentException("element is a comment");
}
if (element.getContainingFile() == null || !(element.getContainingFile() instanceof SQFFile)) {
throw new IllegalArgumentException("element isn't in an SQFFile");
}
while (!(element instanceof SQFStatement)) {
element = element.getParent();
if (element == null) {
return null;
}
}
return (SQFStatement) element;
}
/**
* Used for debugging. Will return the statement the given element is contained in.
* If the element is a PsiComment, <PsiComment> will be returned. Otherwise, the element's ancestor statement
* text will be returned with all newlines replaced with spaces.
* <p>
* If the element has no parent or no {@link SQFStatement} parent, <No Statement Parent> will be returned
*
* @return the text, or <PsiComment> if element is a PsiComment
*/
@NotNull
public static String debug_getStatementTextForElement(@NotNull PsiElement element) {
if (element instanceof PsiComment) {
return "<PsiComment>";
}
if (element.getContainingFile() == null || !(element.getContainingFile() instanceof SQFFile)) {
throw new IllegalArgumentException("element isn't in an SQFFile");
}
while (!(element instanceof SQFStatement)) {
element = element.getParent();
if (element == null) {
return "<No Statement Parent>";
}
}
return element.getText().replaceAll("\n", " ");
}
@Nonnull
private List<Block> getBlocksStartingNewLine() {
NewLineBlocksIterator newLineBlocksIterator = new NewLineBlocksIterator(myRootBlock, myDocument);
List<Block> newLineBlocks = new ArrayList<Block>();
int currentLine = 0;
while (newLineBlocksIterator.hasNext() && currentLine < MAX_NEW_LINE_BLOCKS_TO_PROCESS) {
Block next = newLineBlocksIterator.next();
if (next instanceof ASTBlock && ((ASTBlock)next).getNode() instanceof PsiComment) {
continue;
}
newLineBlocks.add(next);
currentLine++;
}
return newLineBlocks;
}
@Nullable
@Override
public PsiElement[] getGotoDeclarationTargets(PsiElement sourceElement, int offset, Editor editor) {
if(!ShopwareProjectComponent.isValidForProject(sourceElement)) {
return new PsiElement[0];
}
final List<PsiElement> targets = new ArrayList<>();
if(ExtJsUtil.getStringLiteralPattern().accepts(sourceElement)) {
// {link file='frontend/_resources/styles/framework.css'}
attachControllerActionNameGoto(sourceElement, targets);
// {s name='foobar' namespace='foobar/ns'}
attachSnippets(sourceElement, targets);
}
if(PlatformPatterns.psiElement(PsiComment.class).accepts(sourceElement)) {
attachSnippetAsComment(sourceElement, targets);
}
return targets.toArray(new PsiElement[0]);
}
@Nullable
private PsiElement findAboveComment(@Nullable PsiElement element) {
if (element == null) {
return null;
}
PsiElement prevSibling = element.getPrevSibling();
PsiElement prevPrevSibling = prevSibling == null ? null : prevSibling.getPrevSibling();
if (prevPrevSibling instanceof PsiComment && prevSibling instanceof PsiWhiteSpace && prevSibling.getText().replaceAll("[ \t]", "").length() == 1) {
return prevPrevSibling;
}
return null;
}
@Nullable
private PsiElement findBelowComment(@Nullable PsiElement element) {
if (element == null) {
return null;
}
PsiElement nextSibling = element.getNextSibling();
PsiElement nextNextSibling = nextSibling == null ? null : nextSibling.getNextSibling();
if (nextNextSibling instanceof PsiComment && nextSibling instanceof PsiWhiteSpace && nextSibling.getText().replaceAll("[ \t]", "").length() == 1) {
return nextNextSibling;
}
return null;
}
public static void createSuppression(@Nonnull Project project,
@Nonnull PsiElement container,
@Nonnull String id, @Nonnull Language commentLanguage) {
final String text = SUPPRESS_INSPECTIONS_TAG_NAME + " " + id;
PsiComment comment = createComment(project, text, commentLanguage);
container.getParent().addBefore(comment, container);
}
private void highlightWordIfTag(PsiComment comment, AnnotationHolder holder, Pair<String, Integer> pair) {
Integer offset = pair.second;
String word = pair.first;
if (XQ_DOC_TAGS.contains(word)) {
int absoluteOffset = comment.getTextOffset() + offset;
highlightTextRange(holder, absoluteOffset, word.length());
}
}
@Nullable
default PsiComment getDocComment() {
PsiElement firstChild = getFirstChild();
return firstChild instanceof PsiComment
&& firstChild.getNode().getElementType() == SoyTypes.DOC_COMMENT_BLOCK
? (PsiComment) firstChild
: null;
}
@Nullable
public static PsiElement searchNonSpaceNonCommentBack(PsiElement element, final boolean strict) {
if(element == null || element.getNode() == null) return null;
ASTNode leftNeibour = TreeUtil.prevLeaf(element.getNode());
if (!strict) {
while (leftNeibour != null && (leftNeibour.getElementType() == TokenType.WHITE_SPACE || leftNeibour.getPsi() instanceof PsiComment)){
leftNeibour = TreeUtil.prevLeaf(leftNeibour);
}
}
return leftNeibour != null ? leftNeibour.getPsi() : null;
}
@Nullable
public static PsiElement getLastMeaningChild(PsiElement element) {
PsiElement last = element.getLastChild();
return last instanceof PsiWhiteSpace || last instanceof PsiComment
? getPrevMeaningSibling(last)
: last;
}
public static PsiElement[] getFilteredChildren(@Nonnull final PsiElement element,
@Nullable Condition<PsiElement> isElementSignificantCondition,
boolean areCommentsSignificant) {
ASTNode[] children1 = element.getNode().getChildren(null);
ArrayList<PsiElement> array = new ArrayList<PsiElement>();
for (ASTNode node : children1) {
final PsiElement child = node.getPsi();
if (!(child instanceof PsiWhiteSpace) && (areCommentsSignificant || !(child instanceof PsiComment)) &&
(isElementSignificantCondition == null || isElementSignificantCondition.value(child))) {
array.add(child);
}
}
return PsiUtilCore.toPsiElementArray(array);
}
public SortItem(PsiElement define, PsiElement parameter, boolean inactive, PsiComment ignoreComment, PsiElement regularComment)
{
this.define = define;
this.parameter = parameter;
if(ignoreComment != null)
{
this.ignoreComment = (PsiComment) ignoreComment.copy();
}
if(regularComment != null)
{
this.regularComment = (PsiComment) regularComment.copy();
}
}
@Override
public PsiComment handleContentChange(@Nonnull PsiComment psiComment, @Nonnull TextRange range, String newContent) throws IncorrectOperationException {
String oldText = psiComment.getText();
String newText = oldText.substring(0, range.getStartOffset()) + newContent + oldText.substring(range.getEndOffset());
FileType type = psiComment.getContainingFile().getFileType();
PsiFile fromText = PsiFileFactory.getInstance(psiComment.getProject()).createFileFromText("__." + type.getDefaultExtension(), type, newText);
PsiComment newElement = PsiTreeUtil.getParentOfType(fromText.findElementAt(0), psiComment.getClass(), false);
assert newElement != null;
return (PsiComment)psiComment.replace(newElement);
}
@Override
protected String getLanguagePlaceholderText(@NotNull ASTNode node, @NotNull TextRange range) {
PsiElement element = node.getPsi();
if (element instanceof TagBlockElement) {
TagBlockElement block = (TagBlockElement) element;
String openingTagText = block.getOpeningTag().getText();
PsiElement firstMeaningfulChild = WhitespaceUtils.getFirstMeaningChild(block.getOpeningTag());
if (firstMeaningfulChild == null) {
return "...";
}
int tagStart = firstMeaningfulChild.getStartOffsetInParent();
if (tagStart != 0) {
// Strip leading doc comment.
openingTagText = openingTagText.substring(tagStart);
}
return normalizePlaceHolderText(openingTagText)
+ "..."
+ normalizePlaceHolderText(getClosingTagText(element));
}
if (element instanceof PsiComment) {
String placeholderText = buildCommentPlaceholderText(element);
if (placeholderText != null) {
return placeholderText;
}
}
return "{...}";
}
@Override
protected boolean isRegionCollapsedByDefault(@Nonnull ASTNode node)
{
PsiElement psi = node.getPsi();
if(psi instanceof CSharpUsingListChild)
{
return true;
}
else if(psi instanceof PsiComment)
{
return CodeFoldingSettings.getInstance().COLLAPSE_FILE_HEADER;
}
return false;
}
@Nonnull
public static PsiComment createComment(@Nonnull Project project,
@Nonnull String commentText,
@Nonnull Language language) {
final PsiParserFacade parserFacade = PsiParserFacade.SERVICE.getInstance(project);
return parserFacade.createLineOrBlockCommentFromText(language, commentText);
}
private static boolean isAcceptableComment(PsiElement nextSibling, IElementType elementType)
{
if(nextSibling == null)
{
return false;
}
return nextSibling instanceof PsiWhiteSpace || (nextSibling instanceof PsiComment && ((PsiComment) nextSibling).getTokenType() == elementType);
}
private static PsiElement skipOverDocComments(PsiElement startElement) {
PsiElement elt = startElement.getNextSibling();
if (elt == null) {
return startElement;
} else if (elt instanceof PsiComment) {
IElementType commentType = ((PsiComment) elt).getTokenType();
if (commentType == START_DOC_COMMENT) {
return PsiTreeUtil.skipSiblingsForward(elt, PsiComment.class);
}
}
return elt;
}
@Override
public boolean isMyContext(PsiElement element) {
if (element instanceof PsiComment) {
return true;
}
if (element instanceof StringLiteral) {
// as a rough heuristic, only spell-check triple-quoted strings, which are more likely to be
// english sentences rather than keywords
QuoteType q = ((StringLiteral) element).getQuoteType();
return q == QuoteType.TripleDouble || q == QuoteType.TripleSingle;
}
return false;
}