{"id":330422,"date":"2022-03-09T09:01:00","date_gmt":"2022-03-09T09:01:00","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=330422"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=330422","title":{"rendered":"<span>\u041f\u0438\u0448\u0435\u043c \u0441\u0432\u043e\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f IDEA \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 (\u0447\u0430\u0441\u0442\u044c 2)<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><em>\u0414\u0438\u0441\u043a\u043b\u0430\u0439\u043c\u0435\u0440: \u044f \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0441\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u0438\u0437 JetBrains, \u0430 \u0436\u0430\u043b\u044c, \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u0438 \u0432 \u043a\u043e\u0434\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u0438 \u043e\u0448\u0438\u0431\u043a\u0438.<\/em><\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/653183\/\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0441\u0442\u044c 1<\/a><\/p>\n<ul>\n<li>\n<p>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u044b \u044f\u0437\u044b\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 PSI-\u0434\u0435\u0440\u0435\u0432\u0430<\/p>\n<\/li>\n<li>\n<p>&#8212; \u041b\u0435\u043a\u0441\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>&#8212; \u041f\u0430\u0440\u0441\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>\u0410\u043d\u043d\u043e\u0442\u0430\u0442\u043e\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0430 \u0441\u043a\u043e\u0431\u043e\u043a<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0430\u0441\u0442\u044c 2<\/p>\n<ul>\n<li>\n<p><a href=\"#format\" rel=\"noopener noreferrer nofollow\">\u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#structureview\" rel=\"noopener noreferrer nofollow\">Structure view<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#cache\" rel=\"noopener noreferrer nofollow\">\u041a\u044d\u0448\u0438, \u0438\u043d\u0434\u0435\u043a\u0441\u044b, stub \u0438 goto<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#reference\" rel=\"noopener noreferrer nofollow\">\u0421\u0441\u044b\u043b\u043a\u0438 (Reference)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#usages\" rel=\"noopener noreferrer nofollow\">Find Usages<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#rename\" rel=\"noopener noreferrer nofollow\">Rename \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#notes\" rel=\"noopener noreferrer nofollow\">\u041c\u0430\u0440\u043a\u0435\u0440\u044b (Markers)<\/a>  <\/p>\n<\/li>\n<li>\n<p><a href=\"#completion\" rel=\"noopener noreferrer nofollow\">\u0410\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#test\" rel=\"noopener noreferrer nofollow\">\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 <a href=\"https:\/\/habr.com\/ru\/publication\/edit\/653183\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u0431\u044b\u043b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u0430\u0440\u043a\u0430\u0441\u0430 \u044f\u0437\u044b\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0434\u043b\u044f <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\" rel=\"noopener noreferrer nofollow\">Java<\/a>, <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\" rel=\"noopener noreferrer nofollow\">go<\/a>, <a href=\"https:\/\/github.com\/IntelliJ-Frege\" rel=\"noopener noreferrer nofollow\">Frege<\/a>. \u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0437 <a href=\"https:\/\/github.com\/pyltsin\/monkey-plugin\" rel=\"noopener noreferrer nofollow\">\u043f\u043b\u0430\u0433\u0438\u043d\u0430<\/a> \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u0430 <a href=\"https:\/\/monkeylang.org\/\" rel=\"noopener noreferrer nofollow\">Monkey<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043f\u043e\u043a\u0430 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0441\u044f, \u043a\u0430\u043a \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0422\u0430\u043a \u043a\u0430\u043a \u0443 \u043c\u0435\u043d\u044f \u043d\u0435 \u0431\u044b\u043b\u043e \u0446\u0435\u043b\u044c\u044e \u043e\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u0432\u0441\u0451, \u0442\u043e \u043f\u043b\u0430\u0433\u0438\u043d \u043e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0435 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u044f\u0437\u044b\u043a\u0430. \u0421\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/pyltsin\/monkey-source\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>.<\/p>\n<p><a class=\"anchor\" name=\"format\" id=\"format\"><\/a><\/p>\n<h2>\u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h2>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/code-formatting.html\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>, \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0432 <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/tree\/master\/src\/com\/goide\/formatter\" rel=\"noopener noreferrer nofollow\">go-plugin<\/a>, <a href=\"https:\/\/github.com\/pyltsin\/monkey-plugin\/blob\/main\/src\/main\/kotlin\/com\/github\/pyltsin\/monkeyplugin\/formatter\/MonkeyFormattingModelBuilder.kt\" rel=\"noopener noreferrer nofollow\">monkey<\/a>.<\/p>\n<p>\u0412\u0441\u0435 \u043a\u0430\u043a \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0442\u043e\u0447\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"xml\">&lt;lang.formatter language=\"Monkey\" implementationClass=\"com.github.pyltsin.monkeyplugin.formatter.MonkeyFormattingModelBuilder\"\/> <\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <\/p>\n<pre><code class=\"java\">public interface FormattingModelBuilder { @NotNull  FormattingModel createModel(@NotNull FormattingContext formattingContext);  @Nullable  TextRange getRangeAffectingIndent(PsiFile file, int offset,                                   ASTNode elementAtOffset) ; }<\/code><\/pre>\n<p>\u041d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0432\u0430\u0436\u043d\u044b\u0439 &#8212; \u043f\u0435\u0440\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434. \u041e\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043c\u043e\u0434\u0435\u043b\u044c \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043d\u0430 \u0431\u043b\u043e\u043a\u0430\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c <code>FormattingModelProvider.createFormattingModelForPsiFile<\/code> <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0431\u043b\u043e\u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 IDEA \u0431\u043b\u043e\u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u0430\u043a \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>com.intellij.formatting.Block<\/code> &#8212;  \u044d\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0442\u0435\u043a\u0441\u0442\u0430 (\u0447\u0430\u0441\u0442\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043a\u0430\u043a\u043e\u043c\u0443-\u0442\u043e PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443), \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0411\u043b\u043e\u043a\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0440\u0443\u0433 \u0432 \u0434\u0440\u0443\u0433\u0430 \u0438 \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442 \u0434\u0435\u0440\u0435\u0432\u043e.<\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 Block<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">public interface Block {  @NotNull   TextRange getTextRange();    @NotNull   List&lt;Block> getSubBlocks();    @Nullable   Wrap getWrap();    @Nullable   Indent getIndent();    @Nullable   Alignment getAlignment();    @Nullable   Spacing getSpacing(@Nullable Block child1, @NotNull Block child2);    @NotNull   ChildAttributes getChildAttributes(final int newChildIndex);    boolean isIncomplete();    boolean isLeaf();    @Nullable   default String getDebugName() {     return null;   } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u0442\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430, \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c PSI-Viewer (Tools->View PSI  Structure, \u0440\u0430\u0437\u0434\u0435\u043b Block Sructure)<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fe9\/9c7\/9ca\/fe99c79ca82669da2188395308344249.png\" width=\"894\" height=\"717\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fe9\/9c7\/9ca\/fe99c79ca82669da2188395308344249.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u043c <code>AbstractBlock<\/code>. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432\u043c\u0435\u0441\u0442\u043e \u043c\u0435\u0442\u043e\u0434\u0430 <code>getSubBlocks<\/code>\u043e\u043d \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>buildChildren<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430.<\/p>\n<p><code>getSpacing<\/code>  &#8212; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0441\u0442\u0440\u043e\u043a \u043c\u0435\u0436\u0434\u0443 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438. \u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u043c <code>com.intellij.formatting.SpacingBuilder<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u043e\u0435 API \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u0430\u0432\u0438\u043b.<\/p>\n<pre><code class=\"java\">\/\/\u0441\u0438\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 plugin-go public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { return new SpacingBuilder(settings, GoLanguage.INSTANCE)       .before(COMMA).spaceIf(false)       .after(COMMA).spaceIf(true)       .betweenInside(SEMICOLON, SEMICOLON, FOR_CLAUSE).spaces(1)       .before(SEMICOLON).spaceIf(false)       .after(SEMICOLON).spaceIf(true)       .beforeInside(DOT, IMPORT_SPEC).none()       .afterInside(DOT, IMPORT_SPEC).spaces(1)       \/\/\u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435       .getSpacing(this, child1, child2); }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 builder, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 <code>com.intellij.formatting.Spacing#createSpacing<\/code><\/p>\n<p><code>getIndent<\/code> &#8212;  \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043e\u0442\u0441\u0442\u0443\u043f\u0430 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430<\/p>\n<p><code>getWrap<\/code>  &#8212; \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u0441\u0442\u0440\u043e\u0447\u043a\u0443 \u043a\u043e\u043d\u0442\u0435\u043d\u0442<\/p>\n<p><code>getAlignment<\/code> &#8212; \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u043e\u0432 \u0434\u0440\u0443\u0433 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u0440\u0443\u0433\u0430<\/p>\n<p><code>getChildIndent<\/code> &#8212; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <code>AbstractBlock<\/code> \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f <code>getChildAttributes<\/code> , \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0434\u043b\u044f \u0431\u043b\u043e\u043a\u0430, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0448\u0438 Enter.<\/p>\n<p><a class=\"anchor\" name=\"structureview\" id=\"structureview\"><\/a><\/p>\n<h2>Structure view<\/h2>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043f\u043e\u0439\u0434\u0435\u0442 \u0440\u0435\u0447\u044c \u043e\u0431 \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0432\u043e\u0442 \u044d\u0442\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/352\/c1f\/84b\/352c1f84b38255ff3f9f70f97883372d.png\" width=\"362\" height=\"290\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/352\/c1f\/84b\/352c1f84b38255ff3f9f70f97883372d.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0442\u043e\u0447\u043a\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/p>\n<pre><code class=\"xml\">&lt;lang.psiStructureViewFactory language=\"Monkey\" implementationClass=\"com.github.pyltsin.monkeyplugin.editor.MonkeyStructureViewFactory\"\/> <\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<pre><code class=\"java\">@FunctionalInterface public interface PsiStructureViewFactory {   @Nullable   StructureViewBuilder getStructureViewBuilder(@NotNull PsiFile psiFile); }<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>StructureViewBuilder<\/code> \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u0433\u043e\u0442\u043e\u0432\u043a\u0438 <code>com.intellij.ide.structureView.TreeBasedStructureViewBuilder<\/code>, <code>com.intellij.ide.structureView.StructureViewModelBase<\/code> \u0438 <code>com.intellij.ide.structureView.impl.common.PsiTreeElementBase<\/code>.<\/p>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 <code>PsiTreeElementBase<\/code>  \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0431\u043b\u043e\u043a\u0430\u043c\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/structure-view.html\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/tree\/GoStructureViewFactory.java\" rel=\"noopener noreferrer nofollow\">plugin-go<\/a>, <a href=\"https:\/\/github.com\/pyltsin\/monkey-plugin\/blob\/main\/src\/main\/kotlin\/com\/github\/pyltsin\/monkeyplugin\/editor\/MonkeyStructureViewFactory.kt\" rel=\"noopener noreferrer nofollow\">Monkey<\/a>. <\/p>\n<p><a class=\"anchor\" name=\"cache\" id=\"cache\"><\/a><\/p>\n<h2>\u041a\u044d\u0448\u0438, \u0438\u043d\u0434\u0435\u043a\u0441\u044b, stub \u0438 goto<\/h2>\n<h4>\u041a\u044d\u0448\u0438<\/h4>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043a\u044d\u0448\u0435\u0439. IDEA \u043e\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u043c\u043d\u043e\u0433\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0440\u0430\u0437. \u0415\u0441\u043b\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0442\u044f\u0436\u0435\u043b\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443, \u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u043b\u0443\u0447\u0448\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 &#8212; \u044d\u0442\u043e \u0437\u0430\u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u044d\u0442\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b. IDEA \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043e\u0431\u0435\u0440\u0442\u043e\u043a \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0438\u043f  Go \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u043f\u043b\u0430\u0433\u0438\u043d\u0435 plugin-go:<\/p>\n<pre><code class=\"java\">  @Nullable   public static GoType getGoType(@NotNull GoExpression o, @Nullable ResolveState context) {     return RecursionManager.doPreventingRecursion(o, true, () -> {       if (context != null) return unwrapParType(o, context);       return CachedValuesManager.getCachedValue(o, () -> CachedValueProvider.Result         .create(unwrapParType(o, createContextOnElement(o)), PsiModificationTracker.MODIFICATION_COUNT));     });   } <\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f 2 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430. \u041f\u0435\u0440\u0432\u044b\u0439 &#8212; <code>CachedValuesManager<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u044d\u0448\u0438\u0440\u0443\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u043b\u044f psi-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0438 \u0432\u0442\u043e\u0440\u043e\u0439 &#8212; <code>RecursionManager<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438 <code>StackOverflowError<\/code>. \u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u044d\u0448 <code>com.intellij.psi.impl.source.resolve.ResolveCache<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0438 (resolving) \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 (\u043f\u0440\u043e \u044d\u0442\u043e \u043d\u0438\u0436\u0435).<\/p>\n<h4>\u0418\u043d\u0434\u0435\u043a\u0441\u044b<\/h4>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/376\/994\/015\/376994015a015a57227686e95574b9df.jpg\" alt=\"\u0412\u0437\u044f\u0442\u043e \u0438\u0437 reddit\" title=\"\u0412\u0437\u044f\u0442\u043e \u0438\u0437 reddit\" width=\"500\" height=\"502\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/376\/994\/015\/376994015a015a57227686e95574b9df.jpg\" data-blurred=\"true\"\/><figcaption>\u0412\u0437\u044f\u0442\u043e \u0438\u0437 reddit<\/figcaption><\/figure>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/indexing-and-psi-stubs.html#indexes\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>. \u0412\u0441\u0435 \u043c\u044b \u0437\u043d\u0430\u0435\u043c \u043a\u0430\u043a IDEA \u043b\u044e\u0431\u0438\u0442 \u0432\u0441\u0451 \u0438\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0438 \u043a\u0430\u043a \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. <\/p>\n<p>\u0418\u043d\u0434\u0435\u043a\u0441\u044b \u0432 IDEA \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u0441 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u0438\u043b\u0438 psi-\u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u0435 \u043c\u0435\u0441\u0442\u0430, \u0433\u0434\u0435 \u043e\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f).<\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043c\u043e\u0436\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/13029-index-viewer\" rel=\"noopener noreferrer nofollow\">Index viewer<\/a>. \u041e \u0442\u043e\u043c, \u043a\u0430\u043a \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e <a href=\"https:\/\/habr.com\/ru\/company\/hsespb\/blog\/574692\/\" rel=\"noopener noreferrer nofollow\">Frege<\/a>.<\/p>\n<p>IDEA \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0430 \u0432\u0438\u0434\u0430 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 &#8212; File-based \u0438 Stub. File-based \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c \u0444\u0430\u0439\u043b\u0430, Stub \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 Stub-\u0434\u0435\u0440\u0435\u0432\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 Psi-\u0434\u0435\u0440\u0435\u0432\u0430. <\/p>\n<h4>File-based \u0438\u043d\u0434\u0435\u043a\u0441\u044b.<\/h4>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043f\u043b\u0430\u0433\u0438\u043d\u0435 <a href=\"https:\/\/github.com\/carymrobbins\/intellij-haskforce\" rel=\"noopener noreferrer nofollow\">haskforce<\/a><\/p>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u0435 \u043a\u0430\u043a \u0432\u0441\u0435\u0433\u0434\u0430 \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u0447\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/p>\n<pre><code class=\"xml\">&lt;fileBasedIndex implementation=\"com.haskforce.index.HaskellModuleIndex\"\/><\/code><\/pre>\n<p>\u0424\u0430\u0439\u043b \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c <code>FileBasedIndexExtension<\/code>. \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0438\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437 <\/p>\n<pre><code class=\"java\">FileBasedIndex.getInstance()<\/code><\/pre>\n<p>\u041f\u043b\u0430\u0433\u0438\u043d <a href=\"https:\/\/github.com\/carymrobbins\/intellij-haskforce\" rel=\"noopener noreferrer nofollow\">haskforce<\/a>, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044d\u0442\u043e\u0442 \u0442\u0438\u043f \u0438\u043d\u0434\u0435\u043a\u0441\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043c\u043e\u0434\u0443\u043b\u044f:<\/p>\n<pre><code class=\"java\">@NotNull public static Collection&lt;VirtualFile> getVirtualFilesByModuleName(@NotNull String moduleName, @NotNull GlobalSearchScope searchScope) {   return FileBasedIndex.getInstance()     .getContainingFiles(HASKELL_MODULE_INDEX, moduleName, searchScope); } <\/code><\/pre>\n<h4>Stub \u0438\u043d\u0434\u0435\u043a\u0441\u044b<\/h4>\n<p>\u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432, \u043a\u0430\u043a \u043c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0447\u0430\u0449\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c \u043f\u043e PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c (\u0430 \u0442\u043e\u0447\u043d\u0435\u0435 \u043f\u043e stub, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u0443\u044e \u0447\u0430\u0441\u0442\u044c psi-\u0434\u0435\u0440\u0435\u0432\u0430). Stub \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0438\u043c\u0435\u043d\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0445 psi-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 (\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 PsiNamedElement). \u041e \u043d\u0438\u0445 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 Reference<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;stubIndex implementation= \"com.github.pyltsin.monkeyplugin.stubs.MonkeyVarNameIndex\"\/><\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>StubIndexExtension<\/code>(\u0438\u043b\u0438 \u0435\u0433\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>StringStubIndexExtension<\/code>). <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f Monkey:<\/p>\n<pre><code class=\"java\">class MonkeyVarNameIndex : StringStubIndexExtension&lt;MonkeyNamedElement>() {     override fun getVersion(): Int {         return super.getVersion() + VERSION     }      override fun getKey(): StubIndexKey&lt;String, MonkeyNamedElement> {         return KEY     }      companion object {         val KEY: StubIndexKey&lt;String, MonkeyNamedElement> =             StubIndexKey.createIndexKey(\"monkey.var.name\")         const val VERSION = 0     } }<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0432 <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/stubs\/index\/GoAllPublicNamesIndex.java\" rel=\"noopener noreferrer nofollow\">go-plugin<\/a>, <a href=\"https:\/\/github.com\/IntelliJ-Frege\/intellij-frege\/tree\/master\/src\/main\/kotlin\/com\/plugin\/frege\/stubs\/index\" rel=\"noopener noreferrer nofollow\">frege<\/a>.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0443\u0447\u0438\u0442\u044c IDEA \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0435\u0440\u0435\u0432\u043e Stub-\u043e\u0432 \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043f\u043e\u0434 \u043d\u0443\u0436\u043d\u044b\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u043c. <\/p>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a Stub, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 Stub. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043a\u043e\u0440\u043d\u0435\u043c \u0432\u0441\u0435\u0445 Stub-\u043e\u0432 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c FileStub. <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f Monkey:<\/p>\n<pre><code class=\"kotlin\">class MonkeyFileStub(file: MonkeyFile?) : PsiFileStubImpl&lt;MonkeyFile>(file)  class MonkeyVarDefinitionStub : NamedStubBase&lt;MonkeyVarDefinition> {     constructor(parent: StubElement&lt;*>?, elementType: IStubElementType&lt;*, *>, name: StringRef?) : super(         parent,         elementType,         name     )      constructor(parent: StubElement&lt;*>?, elementType: IStubElementType&lt;*, *>, name: String?) : super(         parent,         elementType,         name     ) } <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0437 go-plugin (<a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/stubs\/GoFileStub.java\" rel=\"noopener noreferrer nofollow\">\u0444\u0430\u0439\u043b<\/a>, <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/stubs\/GoFieldDefinitionStub.java\" rel=\"noopener noreferrer nofollow\">\u044d\u043b\u0435\u043c\u0435\u043d\u0442<\/a>), Frege (<a href=\"https:\/\/github.com\/IntelliJ-Frege\/intellij-frege\/blob\/master\/src\/main\/kotlin\/com\/plugin\/frege\/stubs\/FregeFileStub.kt\" rel=\"noopener noreferrer nofollow\">\u0444\u0430\u0439\u043b<\/a>, <a href=\"https:\/\/github.com\/IntelliJ-Frege\/intellij-frege\/blob\/master\/src\/main\/kotlin\/com\/plugin\/frege\/stubs\/FregeClassStub.kt\" rel=\"noopener noreferrer nofollow\">\u044d\u043b\u0435\u043c\u0435\u043d\u0442<\/a>)<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433 &#8212; \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e Stub \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u044d\u0442\u043e\u0433\u043e Stub. (\u0414\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0445 PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c Grammar-Kit \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 <code>elementTypeHolderClass<\/code> \u0438 <code>elementTypeClass<\/code>). ElementType \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c <code>IStubFileElementType<\/code>,  \u0434\u043b\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 &#8212; <code>IStubElementType<\/code>.<\/p>\n<p><code>IStubElementType<\/code> \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432:<\/p>\n<pre><code class=\"java\">@NotNull String getExternalId();  void serialize(@NotNull T stub, @NotNull StubOutputStream dataStream) throws IOException;  @NotNull T deserialize(@NotNull StubInputStream dataStream, P parentStub) throws IOException;  void indexStub(@NotNull T stub, @NotNull IndexSink sink);  PsiT createPsi(@NotNull StubT stub);  @NotNull StubT createStub(@NotNull PsiT psi, StubElement&lt;?> parentStub);  shouldCreateStub(ASTNode node)  <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0438\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c Stub \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>indexStub<\/code> . \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 Monkey \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0442\u0430\u043a\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e:<\/p>\n<pre><code class=\"kotlin\">    override fun indexStub(stub: S, sink: IndexSink) {         val name = stub.name         if (name != null) {             sink.occurrence(MonkeyVarNameIndex.KEY, name)         }     }<\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 &#8212; <a href=\"https:\/\/github.com\/pyltsin\/monkey-plugin\/blob\/main\/src\/main\/kotlin\/com\/github\/pyltsin\/monkeyplugin\/stubs\/types\/MonkeyVarDefinitionStubElementType.kt\" rel=\"noopener noreferrer nofollow\">\u043f\u043b\u0430\u0433\u0438\u043d<\/a> \u0434\u043b\u044f Monkey, <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/stubs\/types\/GoMethodDeclarationStubElementType.java\" rel=\"noopener noreferrer nofollow\">go-plugin<\/a>, <a href=\"https:\/\/github.com\/IntelliJ-Frege\/intellij-frege\/blob\/master\/src\/main\/kotlin\/com\/plugin\/frege\/stubs\/types\/FregeMethodElementType.kt\" rel=\"noopener noreferrer nofollow\">Frege<\/a><\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448\u0438 stub-\u044b \u043d\u0430\u0434\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a \u043f\u0430\u0440\u0441\u0435\u0440\u0443. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432 2 \u0448\u0430\u0433\u0430.<\/p>\n<ul>\n<li>\n<p>1 \u0448\u0430\u0433: \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u0444\u0430\u0431\u0440\u0438\u043a\u0443 \u0442\u0438\u043f\u043e\u0432 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 <code>IStubElementType<\/code>, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u0430\u043a<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">object MonkeyElementTypeFactory {     @JvmStatic     fun factory(name: String): IElementType {         if (name == \"VAR_DEFINITION\") return MonkeyVarDefinitionStubElementType(name)         throw RuntimeException(\"Unknown element type: $name\")     } } <\/code><\/pre>\n<p>\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 bnf \u0444\u0430\u0439\u043b\u0435, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0435 \u043d\u0430\u0434\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432:<\/p>\n<pre><code class=\"java\">elementTypeFactory(\"var_definition\")= \"com.github.pyltsin.monkeyplugin.psi.impl.MonkeyElementTypeFactory.factory\"<\/code><\/pre>\n<ul>\n<li>\n<p>2 \u0448\u0430\u0433. \u0423\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u0438 PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c <code>StubBasedPsiElementBase<\/code> <\/p>\n<\/li>\n<\/ul>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432\u0441\u0435 \u0432\u043c\u0435\u0441\u0442\u0435. \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0446\u0438\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f <code>StubBasedPsiElementBase<\/code> , \u0437\u0430\u0442\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e IStubElementType.createStub \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f Stub, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f (<code>serialize<\/code>) \u0438 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043d\u0435\u0433\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0438\u043d\u0434\u0435\u043a\u0441(<code>indexStub<\/code>). <\/p>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e Stub, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432, \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 stub \u043d\u0430\u0434\u043e \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043f\u0440\u0438 \u0430\u043d\u0430\u043b\u0438\u0437\u0435. \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 getNode(), \u043d\u043e \u043e\u043d \u0434\u043e\u0440\u043e\u0433\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u0444\u0430\u0439\u043b\u0430.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <code>com.intellij.psi.impl.java.stubs.impl.PsiAnnotationStubImpl#getPsiElement<\/code> , \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u0435\u043a\u0441\u0442 \u0438\u0437 ASTNode.<\/p>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 stub \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432<\/h4>\n<p>\u0418\u043d\u0434\u0435\u043a\u0441\u044b \u0448\u0438\u0440\u043e\u043a\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f go-to \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e79\/d56\/abb\/e79d56abb456585c5ebccf542adbe1bf.png\" width=\"619\" height=\"249\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e79\/d56\/abb\/e79d56abb456585c5ebccf542adbe1bf.png\"\/><figcaption><\/figcaption><\/figure>\n<details class=\"spoiler\">\n<summary>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f go-to \u0434\u043b\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 (Symbols) \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0430<\/summary>\n<div class=\"spoiler__content\">\n<p>plugin.xml:<\/p>\n<pre><code class=\"xml\">&lt;gotoSymbolContributor implementation= \"com.github.pyltsin.monkeyplugin.usages.MonkeySymbolContributor\"\/><\/code><\/pre>\n<p>MonkeySymbolContributor:<\/p>\n<pre><code class=\"kotlin\">class MonkeySymbolContributor : ChooseByNameContributorEx {     private val myIndexKeys = listOf(MonkeyVarNameIndex.KEY)     override fun processNames(         processor: Processor&lt;in String>,         scope: GlobalSearchScope,         filter: IdFilter?     ) {         for (key in myIndexKeys) {             ProgressManager.checkCanceled()             StubIndex.getInstance().processAllKeys(                 key,                 processor,                 scope,                 filter             )         }     }      override fun processElementsWithName(         name: String,         processor: Processor&lt;in NavigationItem>,         parameters: FindSymbolParameters     ) {         for (key in myIndexKeys) {             ProgressManager.checkCanceled()             StubIndex.getInstance().processElements(                 key,                 name,                 parameters.project,                 parameters.searchScope,                 parameters.idFilter,                 MonkeyNamedElement::class.java,                 processor             )         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041c\u043d\u043e\u0433\u0438\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0438\u043d\u0434\u0435\u043a\u0441\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/9567-request-mapper\" rel=\"noopener noreferrer nofollow\">Request mapper<\/a> (\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0430\u043a\u0430\u044f \u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0432 IDEA), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c \u0442\u043e\u0447\u043a\u0438 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f REST-\u043c\u0435\u0442\u043e\u0434\u043e\u0432<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c18\/446\/e42\/c18446e42656a46309df5db8c462bb44.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b Request Mapper\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b Request Mapper\" width=\"719\" height=\"403\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c18\/446\/e42\/c18446e42656a46309df5db8c462bb44.png\"\/><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b Request Mapper<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d9d\/395\/ef7\/d9d395ef7e0e25fa8d6873f685d57111.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b \u0432 IDEA (\u043c\u043e\u0436\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043d\u0430\u0431\u0440\u0430\u0432 \/url)\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b \u0432 IDEA (\u043c\u043e\u0436\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043d\u0430\u0431\u0440\u0430\u0432 \/url)\" width=\"622\" height=\"226\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d9d\/395\/ef7\/d9d395ef7e0e25fa8d6873f685d57111.png\"\/><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b \u0432 IDEA (\u043c\u043e\u0436\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043d\u0430\u0431\u0440\u0430\u0432 \/url)<\/figcaption><\/figure>\n<p>\u041f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c RequestMapper \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"java\">\/\/JavaAnnotationIndex - \u043e\u0431\u044b\u0447\u043d\u044b\u0439 Stub index \u0434\u043b\u044f Java \u0434\u043b\u044f \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 JavaAnnotationIndex             .getInstance()             .get(annotationName, project, GlobalSearchScope.projectScope(project))             .asSequence()      <\/code><\/pre>\n<p><a class=\"anchor\" name=\"reference\" id=\"reference\"><\/a><\/p>\n<h3>\u0421\u0441\u044b\u043b\u043a\u0438 (References)<\/h3>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/declarations-and-references.html\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a><\/p>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u0434\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 API \u0432 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5c2\/015\/6db\/5c20156dbe80e9bcddb3f39726ddea2d.gif\" width=\"905\" height=\"229\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5c2\/015\/6db\/5c20156dbe80e9bcddb3f39726ddea2d.gif\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0421\u0441\u044b\u043b\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442 \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438, \u0442\u0430\u043a, \u043d\u0430\u0436\u0430\u0432 Ctrl+B, \u0432\u044b \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u0442\u0435 \u043d\u0430 \u0442\u043e\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044d\u0442\u0430 \u0441\u0441\u044b\u043b\u043a\u0430 \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f. \u041d\u0430\u0436\u0430\u0432 Ctrl+B \u0435\u0449\u0435 \u0440\u0430\u0437, \u0432\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0432\u0441\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u044d\u0442\u043e\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442. <\/p>\n<p>\u042d\u043b\u0435\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f, \u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f, \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u043c\u0435\u0442\u044c \u0438\u043c\u044f. \u0422\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u044d\u0442\u043e \u0438\u043c\u044f, \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c <code>PsiNamedElement<\/code> (\u0430 \u043b\u0443\u0447\u0448\u0435 <code>PsiNameIdentifierOwner<\/code>, \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 Rename)<\/p>\n<pre><code class=\"kotlin\">@JvmStatic fun setName(expr: MonkeySimpleRefExpr, name: String): PsiElement { val e: PsiElement = MonkeyElementTextFactory.createStatementFromText(expr.project, \"$name + 1\") \/\/newLetExpr \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c PsiNamedElement   val newLetExpr = PsiTreeUtil.findChildOfType(e, MonkeySimpleRefExpr::class.java) if (newLetExpr != null) { expr.replace(newLetExpr) \/\/newLetExpr \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 } return expr }<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043c\u043e\u0433 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443, \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b<\/p>\n<pre><code class=\"java\">PsiReference getReference();  \/\/\u0435\u0441\u043b\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u0442\u043e PsiReference @NotNull [] getReferences();  \/\/\u0438\u043b\u0438 \u043d\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 @Experimental default @NotNull Iterable&lt;? extends @NotNull PsiSymbolReference> getOwnReferences() { return Collections.emptyList(); }<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 PsiReference \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u0433\u043e\u0442\u043e\u0432\u043a\u043e\u0439 PsiReferenceBase. \u041e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>PsiElement resolve()<\/code> \u0438\u043b\u0438<code>ResolveResult [] multiResolve(boolean incompleteCode)<\/code> , \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f. \u041f\u0440\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0438\u043c\u0435\u0435\u0442 \u0441\u043c\u044b\u0441\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u044d\u0448:<\/p>\n<pre><code class=\"kotlin\">override fun multiResolve(incompleteCode: Boolean): Array&lt;ResolveResult> {     return ResolveCache.getInstance(psiElement.project).resolveWithCaching(         this, { referenceBase, _ ->             referenceBase.resolveInner(false)                 .map { PsiElementResolveResult(it) }                 .toTypedArray()         },         true, false     ) }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 IDEA \u0443\u0436\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e.<\/p>\n<p><a class=\"anchor\" name=\"usages\" id=\"usages\"><\/a><\/p>\n<h3>Find Usages<\/h3>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/find-usages.html\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>. \u041f\u0440\u0438\u043c\u0435\u0440\u044b <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/usages\/GoFindUsagesProvider.java\" rel=\"noopener noreferrer nofollow\">go-plugin<\/a>, <a href=\"https:\/\/github.com\/pyltsin\/monkey-plugin\/blob\/main\/src\/main\/kotlin\/com\/github\/pyltsin\/monkeyplugin\/usages\/MonkeyFindUsagesProvider.kt\" rel=\"noopener noreferrer nofollow\">monkey<\/a>.<\/p>\n<p>\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u043d\u044e:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/902\/b82\/109\/902b82109a9adf3a5af95dc0825158b4.gif\" width=\"998\" height=\"489\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/902\/b82\/109\/902b82109a9adf3a5af95dc0825158b4.gif\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u043e\u0447\u043a\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;lang.findUsagesProvider language=\"Monkey\" implementationClass=\"com.github.pyltsin.monkeyplugin.usages.MonkeyFindUsagesProvider\"\/> <\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>FindUsagesProvider<\/code>.<\/p>\n<p><a class=\"anchor\" name=\"rename\" id=\"rename\"><\/a><\/p>\n<h2>Rename \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0438<\/h2>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/rename-refactoring.html\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a><\/p>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u043e\u0432 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 (Shift+F6)<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0ae\/cc5\/1c6\/0aecc51c684b541c8b54a2f978d1f19b.gif\" width=\"589\" height=\"313\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0ae\/cc5\/1c6\/0aecc51c684b541c8b54a2f978d1f19b.gif\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0434\u0432\u0435 \u0442\u043e\u0447\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;lang.refactoringSupport language=\"Monkey\"                          implementationClass=\"com.github.pyltsin.monkeyplugin.refactor.MonkeyRefactoringSupportProvider\"\/> &lt;renameInputValidator implementation=\"com.github.pyltsin.monkeyplugin.refactor.MonkeyRenameInputValidator\"\/> <\/code><\/pre>\n<p><code>renameInputValidator<\/code> \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>RenameInputValidator<\/code> <\/p>\n<p><code>refactoringSupport<\/code> \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>RefactoringSupportProvider<\/code>. \u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u0438\u0434\u043e\u0432 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u043e\u0432. \u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043b\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435.<\/p>\n<pre><code class=\"java\">  public boolean isMemberInplaceRenameAvailable(@NotNull PsiElement element, @Nullable PsiElement context) {     return false;   }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f. \u041a\u0430\u043a \u0443\u0436\u0435 \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0434\u043e \u044d\u0442\u043e\u0433\u043e, PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0438\u043c\u044f, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441  <code>PsiNamedElement<\/code>.<\/p>\n<pre><code class=\"java\">public interface PsiNamedElement extends PsiElement {   String getName();   PsiElement setName(@NlsSafe @NotNull String name)   throws IncorrectOperationException; }<\/code><\/pre>\n<p>\u041d\u0430\u0441 \u0437\u0434\u0435\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u043c\u0435\u0442\u043e\u0434 <code>setName<\/code>. \u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 &#8212; \u044d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0430\u043a<\/p>\n<pre><code class=\"kotlin\">private fun createFileFromText(project: Project, text: String): MonkeyFile { return PsiFileFactory.getInstance(project) .createFileFromText(\"A.monkey\", MonkeyLanguage.INSTANCE, text) as MonkeyFile } <\/code><\/pre>\n<p>\u0418 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 <\/p>\n<pre><code class=\"kotlin\">expr.replace(newLetExpr)<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043d\u0430\u0448 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0438\u0437 <code>PsiReference<\/code><\/p>\n<pre><code class=\"java\">PsiElement handleElementRename(@NotNull String newElementName)  throws IncorrectOperationException;<\/code><\/pre>\n<p>\u0438\u043b\u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0433\u043e\u0442\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438\u0437 <code>com.intellij.psi.PsiReferenceBase<\/code>, \u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p><a class=\"anchor\" name=\"notes\" id=\"notes\"><\/a><\/p>\n<h3>\u041c\u0430\u0440\u043a\u0435\u0440\u044b (Markers)<\/h3>\n<p> IDEA \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0438 \u0432 \u0432\u0438\u0434\u0435 \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9f8\/933\/097\/9f8933097a6115a24ba9da0d11c39739.png\" width=\"183\" height=\"24\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9f8\/933\/097\/9f8933097a6115a24ba9da0d11c39739.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/marker\/GoRecursiveCallMarkerProvider.java\" rel=\"noopener noreferrer nofollow\">go-plugin<\/a>, <a href=\"https:\/\/github.com\/IntelliJ-Frege\/intellij-frege\/blob\/master\/src\/main\/kotlin\/com\/plugin\/frege\/linemarker\/related\/FregeRelatedItemLineMarkerProvider.kt\" rel=\"noopener noreferrer nofollow\">Frege<\/a>, <a href=\"https:\/\/github.com\/pyltsin\/monkey-plugin\/blob\/main\/src\/main\/kotlin\/com\/github\/pyltsin\/monkeyplugin\/editor\/MonkeyFunctionLineMarkerProvider.kt\" rel=\"noopener noreferrer nofollow\">monkey<\/a><\/p>\n<p>\u0422\u043e\u0447\u043a\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;codeInsight.lineMarkerProvider language=\"Monkey\" implementationClass=\"com.github.pyltsin.monkeyplugin.editor.MonkeyFunctionLineMarkerProvider\"\/> <\/code><\/pre>\n<p>\u0424\u0430\u0439\u043b \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>LineMarkerProvider<\/code>, \u043c\u0435\u0442\u043e\u0434\u044b \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 <code>LineMarkerInfo<\/code> . \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043c\u0430\u0440\u043a\u0435\u0440\u044b \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u043b\u0438\u0441\u0442\u044c\u044f\u043c PSI-\u0434\u0435\u0440\u0435\u0432\u0430<\/p>\n<p><a class=\"anchor\" name=\"completion\" id=\"completion\"><\/a><\/p>\n<h3>\u0410\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0414\u0443\u043c\u0430\u044e, \u0432\u0441\u0435 \u043a\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 IDEA \u043b\u044e\u0431\u0438\u0442, \u043a\u0430\u043a \u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430\u043c\u0438 (\u0445\u043e\u0442\u044f, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0435\u0441\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0438, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0430 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0443\u043f\u0438\u0442). \u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u0447\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u043e. \u0411\u044b\u043b \u0434\u0430\u0436\u0435 \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e <a href=\"https:\/\/habr.com\/ru\/company\/JetBrains\/blog\/568884\/\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e<\/a>. \u041d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043e\u0442 \u0442\u0430\u043a\u0438\u0435:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fa4\/d88\/827\/fa4d88827fbfd81c5a8a9c7bce62a21e.gif\" width=\"589\" height=\"130\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fa4\/d88\/827\/fa4d88827fbfd81c5a8a9c7bce62a21e.gif\"\/><figcaption><\/figcaption><\/figure>\n<p>\u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>PsiReference.getVariants<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u0438\u0434\u0438\u043c\u044b\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e \u043f\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u0430\u043c\u0430 IDEA.<\/p>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043a\u0435\u0439\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u0447\u043a\u043e\u0439 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;completion.contributor language=\"Monkey\"                         implementationClass=\"com.github.pyltsin.monkeyplugin.completion.MonkeyKeywordCompletionContributor\"\/> <\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>CompletionContributor<\/code>. <\/p>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/code-completion.html\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/completion\/GoKeywordCompletionContributor.java\" rel=\"noopener noreferrer nofollow\">go-plugin<\/a>, <a href=\"https:\/\/github.com\/IntelliJ-Frege\/intellij-frege\/blob\/master\/src\/main\/kotlin\/com\/plugin\/frege\/completion\/FregeKeywordCompletionContributor.kt\" rel=\"noopener noreferrer nofollow\">frege<\/a>, <a href=\"https:\/\/github.com\/pyltsin\/monkey-plugin\/blob\/main\/src\/main\/kotlin\/com\/github\/pyltsin\/monkeyplugin\/completion\/MonkeyKeywordCompletionContributor.kt\" rel=\"noopener noreferrer nofollow\">monkey<\/a> (\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0441\u043b\u043e\u0432)<\/p>\n<p><a class=\"anchor\" name=\"test\" id=\"test\"><\/a><\/p>\n<h3>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/writing-tests-for-plugins.html\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>.<a href=\"https:\/\/habr.com\/ru\/company\/hsespb\/blog\/575566\/\" rel=\"noopener noreferrer nofollow\"> \u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 frege<\/a><\/p>\n<p>\u0412 IDEA \u0442\u0435\u0441\u0442\u044b \u0447\u0430\u0441\u0442\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u0431\u043e\u0439 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u044f\u0437\u044b\u043a\u0430,  \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0414\u041e \u0438 \u041f\u041e\u0421\u041b\u0415 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0414\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 <code>BasePlatformTestCase<\/code> , \u0430 \u0441\u0430\u043c\u0438 \u0442\u0435\u0441\u0442\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"kotlin\">myFixture.configureByFiles(\"RenameTestData.monkey\") myFixture.renameElementAtCaret(\"test\") myFixture.checkResultByFile(\"RenameTestData.monkey\", \"RenameTestDataAfter.monkey\", false)<\/code><\/pre>\n<p>\u0433\u0434\u0435 RenameTestData.monkey \u0438 RenameTestDataAfter.monkey &#8212; \u0444\u0430\u0439\u043b\u044b \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0434\u043e \u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0437 \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u044f\u0437\u044b\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f IDEA \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d. \u0423\u0434\u0430\u0447\u0438 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0441\u0432\u043e\u0435\u0433\u043e IDE \u043f\u043e\u0434 \u0441\u0435\u0431\u044f!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/653667\/\"> https:\/\/habr.com\/ru\/post\/653667\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><em>\u0414\u0438\u0441\u043a\u043b\u0430\u0439\u043c\u0435\u0440: \u044f \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0441\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u0438\u0437 JetBrains, \u0430 \u0436\u0430\u043b\u044c, \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u0438 \u0432 \u043a\u043e\u0434\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u0438 \u043e\u0448\u0438\u0431\u043a\u0438.<\/em><\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/653183\/\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0441\u0442\u044c 1<\/a><\/p>\n<ul>\n<li>\n<p>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u044b \u044f\u0437\u044b\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 PSI-\u0434\u0435\u0440\u0435\u0432\u0430<\/p>\n<\/li>\n<li>\n<p>&#8212; \u041b\u0435\u043a\u0441\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>&#8212; \u041f\u0430\u0440\u0441\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>\u0410\u043d\u043d\u043e\u0442\u0430\u0442\u043e\u0440\u044b<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0430 \u0441\u043a\u043e\u0431\u043e\u043a<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0430\u0441\u0442\u044c 2<\/p>\n<ul>\n<li>\n<p><a href=\"#format\" rel=\"noopener noreferrer nofollow\">\u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#structureview\" rel=\"noopener noreferrer nofollow\">Structure view<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#cache\" rel=\"noopener noreferrer nofollow\">\u041a\u044d\u0448\u0438, \u0438\u043d\u0434\u0435\u043a\u0441\u044b, stub \u0438 goto<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#reference\" rel=\"noopener noreferrer nofollow\">\u0421\u0441\u044b\u043b\u043a\u0438 (Reference)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#usages\" rel=\"noopener noreferrer nofollow\">Find Usages<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#rename\" rel=\"noopener noreferrer nofollow\">Rename \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#notes\" rel=\"noopener noreferrer nofollow\">\u041c\u0430\u0440\u043a\u0435\u0440\u044b (Markers)<\/a>  <\/p>\n<\/li>\n<li>\n<p><a href=\"#completion\" rel=\"noopener noreferrer nofollow\">\u0410\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#test\" rel=\"noopener noreferrer nofollow\">\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 <a href=\"https:\/\/habr.com\/ru\/publication\/edit\/653183\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u0431\u044b\u043b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u0430\u0440\u043a\u0430\u0441\u0430 \u044f\u0437\u044b\u043a\u043e\u0432\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0434\u043b\u044f <a href=\"https:\/\/github.com\/JetBrains\/intellij-community\" rel=\"noopener noreferrer nofollow\">Java<\/a>, <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\" rel=\"noopener noreferrer nofollow\">go<\/a>, <a href=\"https:\/\/github.com\/IntelliJ-Frege\" rel=\"noopener noreferrer nofollow\">Frege<\/a>. \u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0437 <a href=\"https:\/\/github.com\/pyltsin\/monkey-plugin\" rel=\"noopener noreferrer nofollow\">\u043f\u043b\u0430\u0433\u0438\u043d\u0430<\/a> \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u0430 <a href=\"https:\/\/monkeylang.org\/\" rel=\"noopener noreferrer nofollow\">Monkey<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043f\u043e\u043a\u0430 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0441\u044f, \u043a\u0430\u043a \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0422\u0430\u043a \u043a\u0430\u043a \u0443 \u043c\u0435\u043d\u044f \u043d\u0435 \u0431\u044b\u043b\u043e \u0446\u0435\u043b\u044c\u044e \u043e\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u0432\u0441\u0451, \u0442\u043e \u043f\u043b\u0430\u0433\u0438\u043d \u043e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0435 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u044f\u0437\u044b\u043a\u0430. \u0421\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/pyltsin\/monkey-source\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>.<\/p>\n<p><a class=\"anchor\" name=\"format\" id=\"format\"><\/a><\/p>\n<h2>\u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h2>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/code-formatting.html\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>, \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0432 <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/tree\/master\/src\/com\/goide\/formatter\" rel=\"noopener noreferrer nofollow\">go-plugin<\/a>, <a href=\"https:\/\/github.com\/pyltsin\/monkey-plugin\/blob\/main\/src\/main\/kotlin\/com\/github\/pyltsin\/monkeyplugin\/formatter\/MonkeyFormattingModelBuilder.kt\" rel=\"noopener noreferrer nofollow\">monkey<\/a>.<\/p>\n<p>\u0412\u0441\u0435 \u043a\u0430\u043a \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0442\u043e\u0447\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"xml\">&lt;lang.formatter language=\"Monkey\" implementationClass=\"com.github.pyltsin.monkeyplugin.formatter.MonkeyFormattingModelBuilder\"\/> <\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <\/p>\n<pre><code class=\"java\">public interface FormattingModelBuilder { @NotNull  FormattingModel createModel(@NotNull FormattingContext formattingContext);  @Nullable  TextRange getRangeAffectingIndent(PsiFile file, int offset,                                   ASTNode elementAtOffset) ; }<\/code><\/pre>\n<p>\u041d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0432\u0430\u0436\u043d\u044b\u0439 &#8212; \u043f\u0435\u0440\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434. \u041e\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043c\u043e\u0434\u0435\u043b\u044c \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043d\u0430 \u0431\u043b\u043e\u043a\u0430\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c <code>FormattingModelProvider.createFormattingModelForPsiFile<\/code> <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0431\u043b\u043e\u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 IDEA \u0431\u043b\u043e\u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u0430\u043a \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>com.intellij.formatting.Block<\/code> &#8212;  \u044d\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0442\u0435\u043a\u0441\u0442\u0430 (\u0447\u0430\u0441\u0442\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043a\u0430\u043a\u043e\u043c\u0443-\u0442\u043e PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443), \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0411\u043b\u043e\u043a\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0440\u0443\u0433 \u0432 \u0434\u0440\u0443\u0433\u0430 \u0438 \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442 \u0434\u0435\u0440\u0435\u0432\u043e.<\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 Block<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">public interface Block {  @NotNull   TextRange getTextRange();    @NotNull   List&lt;Block> getSubBlocks();    @Nullable   Wrap getWrap();    @Nullable   Indent getIndent();    @Nullable   Alignment getAlignment();    @Nullable   Spacing getSpacing(@Nullable Block child1, @NotNull Block child2);    @NotNull   ChildAttributes getChildAttributes(final int newChildIndex);    boolean isIncomplete();    boolean isLeaf();    @Nullable   default String getDebugName() {     return null;   } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u0442\u043e\u0433\u043e \u0434\u0435\u0440\u0435\u0432\u0430, \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c PSI-Viewer (Tools->View PSI  Structure, \u0440\u0430\u0437\u0434\u0435\u043b Block Sructure)<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u043c <code>AbstractBlock<\/code>. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432\u043c\u0435\u0441\u0442\u043e \u043c\u0435\u0442\u043e\u0434\u0430 <code>getSubBlocks<\/code>\u043e\u043d \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>buildChildren<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430.<\/p>\n<p><code>getSpacing<\/code>  &#8212; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0441\u0442\u0440\u043e\u043a \u043c\u0435\u0436\u0434\u0443 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438. \u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u043c <code>com.intellij.formatting.SpacingBuilder<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u043e\u0435 API \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u0430\u0432\u0438\u043b.<\/p>\n<pre><code class=\"java\">\/\/\u0441\u0438\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 plugin-go public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { return new SpacingBuilder(settings, GoLanguage.INSTANCE)       .before(COMMA).spaceIf(false)       .after(COMMA).spaceIf(true)       .betweenInside(SEMICOLON, SEMICOLON, FOR_CLAUSE).spaces(1)       .before(SEMICOLON).spaceIf(false)       .after(SEMICOLON).spaceIf(true)       .beforeInside(DOT, IMPORT_SPEC).none()       .afterInside(DOT, IMPORT_SPEC).spaces(1)       \/\/\u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435       .getSpacing(this, child1, child2); }<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 builder, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 <code>com.intellij.formatting.Spacing#createSpacing<\/code><\/p>\n<p><code>getIndent<\/code> &#8212;  \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043e\u0442\u0441\u0442\u0443\u043f\u0430 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430<\/p>\n<p><code>getWrap<\/code>  &#8212; \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u0441\u0442\u0440\u043e\u0447\u043a\u0443 \u043a\u043e\u043d\u0442\u0435\u043d\u0442<\/p>\n<p><code>getAlignment<\/code> &#8212; \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u043e\u0432 \u0434\u0440\u0443\u0433 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u0440\u0443\u0433\u0430<\/p>\n<p><code>getChildIndent<\/code> &#8212; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <code>AbstractBlock<\/code> \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f <code>getChildAttributes<\/code> , \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0434\u043b\u044f \u0431\u043b\u043e\u043a\u0430, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0448\u0438 Enter.<\/p>\n<p><a class=\"anchor\" name=\"structureview\" id=\"structureview\"><\/a><\/p>\n<h2>Structure view<\/h2>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043f\u043e\u0439\u0434\u0435\u0442 \u0440\u0435\u0447\u044c \u043e\u0431 \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0432\u043e\u0442 \u044d\u0442\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438:<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0442\u043e\u0447\u043a\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/p>\n<pre><code class=\"xml\">&lt;lang.psiStructureViewFactory language=\"Monkey\" implementationClass=\"com.github.pyltsin.monkeyplugin.editor.MonkeyStructureViewFactory\"\/> <\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<pre><code class=\"java\">@FunctionalInterface public interface PsiStructureViewFactory {   @Nullable   StructureViewBuilder getStructureViewBuilder(@NotNull PsiFile psiFile); }<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>StructureViewBuilder<\/code> \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u0433\u043e\u0442\u043e\u0432\u043a\u0438 <code>com.intellij.ide.structureView.TreeBasedStructureViewBuilder<\/code>, <code>com.intellij.ide.structureView.StructureViewModelBase<\/code> \u0438 <code>com.intellij.ide.structureView.impl.common.PsiTreeElementBase<\/code>.<\/p>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 <code>PsiTreeElementBase<\/code>  \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0431\u043b\u043e\u043a\u0430\u043c\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/structure-view.html\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/tree\/GoStructureViewFactory.java\" rel=\"noopener noreferrer nofollow\">plugin-go<\/a>, <a href=\"https:\/\/github.com\/pyltsin\/monkey-plugin\/blob\/main\/src\/main\/kotlin\/com\/github\/pyltsin\/monkeyplugin\/editor\/MonkeyStructureViewFactory.kt\" rel=\"noopener noreferrer nofollow\">Monkey<\/a>. <\/p>\n<p><a class=\"anchor\" name=\"cache\" id=\"cache\"><\/a><\/p>\n<h2>\u041a\u044d\u0448\u0438, \u0438\u043d\u0434\u0435\u043a\u0441\u044b, stub \u0438 goto<\/h2>\n<h4>\u041a\u044d\u0448\u0438<\/h4>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043a\u044d\u0448\u0435\u0439. IDEA \u043e\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u043c\u043d\u043e\u0433\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0440\u0430\u0437. \u0415\u0441\u043b\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0442\u044f\u0436\u0435\u043b\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443, \u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u043b\u0443\u0447\u0448\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 &#8212; \u044d\u0442\u043e \u0437\u0430\u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u044d\u0442\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b. IDEA \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043e\u0431\u0435\u0440\u0442\u043e\u043a \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0438\u043f  Go \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u043f\u043b\u0430\u0433\u0438\u043d\u0435 plugin-go:<\/p>\n<pre><code class=\"java\">  @Nullable   public static GoType getGoType(@NotNull GoExpression o, @Nullable ResolveState context) {     return RecursionManager.doPreventingRecursion(o, true, () -> {       if (context != null) return unwrapParType(o, context);       return CachedValuesManager.getCachedValue(o, () -> CachedValueProvider.Result         .create(unwrapParType(o, createContextOnElement(o)), PsiModificationTracker.MODIFICATION_COUNT));     });   } <\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f 2 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430. \u041f\u0435\u0440\u0432\u044b\u0439 &#8212; <code>CachedValuesManager<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u044d\u0448\u0438\u0440\u0443\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u043b\u044f psi-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0438 \u0432\u0442\u043e\u0440\u043e\u0439 &#8212; <code>RecursionManager<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u0438 <code>StackOverflowError<\/code>. \u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u044d\u0448 <code>com.intellij.psi.impl.source.resolve.ResolveCache<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0438 (resolving) \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 (\u043f\u0440\u043e \u044d\u0442\u043e \u043d\u0438\u0436\u0435).<\/p>\n<h4>\u0418\u043d\u0434\u0435\u043a\u0441\u044b<\/h4>\n<figure class=\"\"><figcaption>\u0412\u0437\u044f\u0442\u043e \u0438\u0437 reddit<\/figcaption><\/figure>\n<p><a href=\"https:\/\/plugins.jetbrains.com\/docs\/intellij\/indexing-and-psi-stubs.html#indexes\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/a>. \u0412\u0441\u0435 \u043c\u044b \u0437\u043d\u0430\u0435\u043c \u043a\u0430\u043a IDEA \u043b\u044e\u0431\u0438\u0442 \u0432\u0441\u0451 \u0438\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0438 \u043a\u0430\u043a \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. <\/p>\n<p>\u0418\u043d\u0434\u0435\u043a\u0441\u044b \u0432 IDEA \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u0441 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u0438\u043b\u0438 psi-\u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432\u0441\u0435 \u043c\u0435\u0441\u0442\u0430, \u0433\u0434\u0435 \u043e\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f).<\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043c\u043e\u0436\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/13029-index-viewer\" rel=\"noopener noreferrer nofollow\">Index viewer<\/a>. \u041e \u0442\u043e\u043c, \u043a\u0430\u043a \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e <a href=\"https:\/\/habr.com\/ru\/company\/hsespb\/blog\/574692\/\" rel=\"noopener noreferrer nofollow\">Frege<\/a>.<\/p>\n<p>IDEA \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0430 \u0432\u0438\u0434\u0430 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 &#8212; File-based \u0438 Stub. File-based \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c \u0444\u0430\u0439\u043b\u0430, Stub \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 Stub-\u0434\u0435\u0440\u0435\u0432\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 Psi-\u0434\u0435\u0440\u0435\u0432\u0430. <\/p>\n<h4>File-based \u0438\u043d\u0434\u0435\u043a\u0441\u044b.<\/h4>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043f\u043b\u0430\u0433\u0438\u043d\u0435 <a href=\"https:\/\/github.com\/carymrobbins\/intellij-haskforce\" rel=\"noopener noreferrer nofollow\">haskforce<\/a><\/p>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u0435 \u043a\u0430\u043a \u0432\u0441\u0435\u0433\u0434\u0430 \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u0447\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/p>\n<pre><code class=\"xml\">&lt;fileBasedIndex implementation=\"com.haskforce.index.HaskellModuleIndex\"\/><\/code><\/pre>\n<p>\u0424\u0430\u0439\u043b \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c <code>FileBasedIndexExtension<\/code>. \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0438\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437 <\/p>\n<pre><code class=\"java\">FileBasedIndex.getInstance()<\/code><\/pre>\n<p>\u041f\u043b\u0430\u0433\u0438\u043d <a href=\"https:\/\/github.com\/carymrobbins\/intellij-haskforce\" rel=\"noopener noreferrer nofollow\">haskforce<\/a>, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044d\u0442\u043e\u0442 \u0442\u0438\u043f \u0438\u043d\u0434\u0435\u043a\u0441\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043c\u043e\u0434\u0443\u043b\u044f:<\/p>\n<pre><code class=\"java\">@NotNull public static Collection&lt;VirtualFile> getVirtualFilesByModuleName(@NotNull String moduleName, @NotNull GlobalSearchScope searchScope) {   return FileBasedIndex.getInstance()     .getContainingFiles(HASKELL_MODULE_INDEX, moduleName, searchScope); } <\/code><\/pre>\n<h4>Stub \u0438\u043d\u0434\u0435\u043a\u0441\u044b<\/h4>\n<p>\u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432, \u043a\u0430\u043a \u043c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0447\u0430\u0449\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c \u043f\u043e PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c (\u0430 \u0442\u043e\u0447\u043d\u0435\u0435 \u043f\u043e stub, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u0443\u044e \u0447\u0430\u0441\u0442\u044c psi-\u0434\u0435\u0440\u0435\u0432\u0430). Stub \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0438\u043c\u0435\u043d\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0445 psi-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 (\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 PsiNamedElement). \u041e \u043d\u0438\u0445 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 Reference<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;stubIndex implementation= \"com.github.pyltsin.monkeyplugin.stubs.MonkeyVarNameIndex\"\/><\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>StubIndexExtension<\/code>(\u0438\u043b\u0438 \u0435\u0433\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>StringStubIndexExtension<\/code>). <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f Monkey:<\/p>\n<pre><code class=\"java\">class MonkeyVarNameIndex : StringStubIndexExtension&lt;MonkeyNamedElement>() {     override fun getVersion(): Int {         return super.getVersion() + VERSION     }      override fun getKey(): StubIndexKey&lt;String, MonkeyNamedElement> {         return KEY     }      companion object {         val KEY: StubIndexKey&lt;String, MonkeyNamedElement> =             StubIndexKey.createIndexKey(\"monkey.var.name\")         const val VERSION = 0     } }<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0432 <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/stubs\/index\/GoAllPublicNamesIndex.java\" rel=\"noopener noreferrer nofollow\">go-plugin<\/a>, <a href=\"https:\/\/github.com\/IntelliJ-Frege\/intellij-frege\/tree\/master\/src\/main\/kotlin\/com\/plugin\/frege\/stubs\/index\" rel=\"noopener noreferrer nofollow\">frege<\/a>.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0443\u0447\u0438\u0442\u044c IDEA \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0435\u0440\u0435\u0432\u043e Stub-\u043e\u0432 \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043f\u043e\u0434 \u043d\u0443\u0436\u043d\u044b\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u043c. <\/p>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a Stub, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 Stub. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043a\u043e\u0440\u043d\u0435\u043c \u0432\u0441\u0435\u0445 Stub-\u043e\u0432 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c FileStub. <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f Monkey:<\/p>\n<pre><code class=\"kotlin\">class MonkeyFileStub(file: MonkeyFile?) : PsiFileStubImpl&lt;MonkeyFile>(file)  class MonkeyVarDefinitionStub : NamedStubBase&lt;MonkeyVarDefinition> {     constructor(parent: StubElement&lt;*>?, elementType: IStubElementType&lt;*, *>, name: StringRef?) : super(         parent,         elementType,         name     )      constructor(parent: StubElement&lt;*>?, elementType: IStubElementType&lt;*, *>, name: String?) : super(         parent,         elementType,         name     ) } <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0437 go-plugin (<a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/stubs\/GoFileStub.java\" rel=\"noopener noreferrer nofollow\">\u0444\u0430\u0439\u043b<\/a>, <a href=\"https:\/\/github.com\/go-lang-plugin-org\/go-lang-idea-plugin\/blob\/master\/src\/com\/goide\/stubs\/GoFieldDefinitionStub.java\" rel=\"noopener noreferrer nofollow\">\u044d\u043b\u0435\u043c\u0435\u043d\u0442<\/a>), Frege (<a href=\"https:\/\/github.com\/IntelliJ-Frege\/intellij-frege\/blob\/master\/src\/main\/kotlin\/com\/plugin\/frege\/stubs\/FregeFileStub.kt\" rel=\"noopener noreferrer nofollow\">\u0444\u0430\u0439\u043b<\/a>, <a href=\"https:\/\/github.com\/IntelliJ-Frege\/intellij-frege\/blob\/master\/src\/main\/kotlin\/com\/plugin\/frege\/stubs\/FregeClassStub.kt\" rel=\"noopener noreferrer nofollow\">\u044d\u043b\u0435\u043c\u0435\u043d\u0442<\/a>)<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433 &#8212; \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e Stub \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u044d\u0442\u043e\u0433\u043e Stub. (\u0414\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0445 PSI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c Grammar-Kit \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 <code>elementTypeHolderClass<\/code> \u0438 <code>elementTypeClass<\/code>). ElementType \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c <code>IStubFileElementType<\/code>,  \u0434\u043b\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 &#8212; <code>IStubElementType<\/code>.<\/p>\n<p><code>IStubElementType<\/code> \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432:<\/p>\n<pre><code class=\"java\">@NotNull String getExternalId();  void serialize(@NotNull T stub, @NotNull StubOutputStream dataStream) throws IOException;  @NotNull T deserialize(@NotNull StubInputStream dataStream, P parentStub) throws IOException;  void indexStub(@NotNull T stub, @NotNull IndexSink sink);  PsiT createPsi(@NotNull StubT stub);  @NotNull<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-330422","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330422","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=330422"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330422\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=330422"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=330422"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=330422"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}