mirror of
https://github.com/JetBrains/intellij-sdk-code-samples.git
synced 2025-07-30 02:07:50 +08:00
179 lines
14 KiB
HTML
179 lines
14 KiB
HTML
|
||
|
||
|
||
<!doctype html>
|
||
<html lang="en-US">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>References and Resolve / IntelliJ Platform SDK DevGuide</title>
|
||
<link rel="stylesheet" href="/intellij/sdk/docs/app/css/styles.min.css">
|
||
|
||
<!-- non-retina iPad pre iOS 7 -->
|
||
<link rel="apple-touch-icon" href="/intellij/sdk/docs/apple-touch-icon-72x72.png" sizes="72x72">
|
||
|
||
<!-- retina iPhone pre iOS 7 -->
|
||
<link rel="apple-touch-icon" href="/intellij/sdk/docs/apple-touch-icon-114x114.png" sizes="114x114">
|
||
|
||
<!-- retina iPad pre iOS 7 -->
|
||
<link rel="apple-touch-icon" href="/intellij/sdk/docs/apple-touch-icon-144x144.png" sizes="144x144">
|
||
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/intellij/sdk/docs/apple-touch-icon-precomposed.png">
|
||
|
||
<!-- normal favicon -->
|
||
<link rel="shortcut icon" type="image/x-icon" href="/intellij/sdk/docs/favicon.ico">
|
||
<link rel="icon" type="image/png" href="/intellij/sdk/docs/favicon.png">
|
||
<link rel="stylesheet" href="/intellij/sdk/docs/styles/styles.css"></head>
|
||
<body data-id="reference_guide/custom_language_support/references_and_resolve">
|
||
<div class="wrapper">
|
||
<section class="panel _nav">
|
||
<header class="panel__header">
|
||
<div class="container">
|
||
<form class="search-box">
|
||
<label for="search-box__input" class="search-box__label">
|
||
<input type="text" class="search-box__input" id="search-box__input" placeholder="Search IntelliJ Platform SDK DevGuide">
|
||
</label>
|
||
<div class="search-box__clear" title="Clear"></div>
|
||
</form>
|
||
</div>
|
||
</header>
|
||
<nav class="panel__content">
|
||
<div class="container _nav">
|
||
<menu class="nav-tree"></menu>
|
||
</div>
|
||
<div class="container _footer panel__footer">
|
||
<p><a href="https://youtrack.jetbrains.com/issues/IJSDK">Send feedback</a></p>
|
||
<p>© 2000–2016 <a href="//www.jetbrains.com">JetBrains</a> s.r.o.<br>
|
||
All rights reserved.</p>
|
||
</div>
|
||
</nav>
|
||
</section>
|
||
|
||
<main class="panel _main" role="main">
|
||
<header class="panel__header">
|
||
<div class="container">
|
||
<h3>IntelliJ Platform SDK DevGuide</h3>
|
||
|
||
<div class="shortcuts-switcher"><label for="switch-shortcuts">Keymap:</label><select id="switch-shortcuts" class="select _shortcuts" height="1">
|
||
<option data-group="primary" value="default" selected>Default</option>
|
||
<option data-group="primary" value="default_for_gnome">GNOME</option>
|
||
<option data-group="primary" value="default_for_kde">KDE</option>
|
||
<option data-group="primary" value="default_for_xwin">XWindow</option>
|
||
<option data-group="primary" value="emacs">Emacs</option>
|
||
<option data-group="primary" value="jbuilder">JBuilder</option>
|
||
<option data-group="primary" value="visual_studio">Visual Studio</option>
|
||
<option data-group="primary" value="netbeans_6.5">NetBeans 6.5</option>
|
||
<option data-group="primary" value="eclipse">Eclipse</option>
|
||
<option data-group="secondary" value="mac_os_x_10.5_">OS X 10.5+</option>
|
||
<option data-group="secondary" value="mac_os_x">OS X</option>
|
||
<option data-group="secondary" value="eclipse_mac_os_x">OS X Eclipse</option></select>
|
||
</div>
|
||
|
||
<div class="panel-trigger"></div>
|
||
</div>
|
||
</header>
|
||
<section class="panel__content">
|
||
<div class="container">
|
||
<article class="article" data-shortcut-switcher="false">
|
||
|
||
<h1>References and Resolve</h1>
|
||
<p>One of the most important and tricky parts in implementing a custom language PSI is resolving references.
|
||
Resolving references gives users the ability to navigate from a PSI element usage (accessing a variable, calling a method and so on) to the declaration of that element (the variable’s definition, a method declaration and so on).
|
||
This feature is needed in order to support the <code class="code highlight language-text">Go to Declaration</code> action invoked by <strong>Ctrl-B</strong> and <strong>Ctrl-Click</strong>, and it is a prerequisite for implementing the <code class="code highlight language-text">Find Usages</code> action, the <code class="code highlight language-text">Rename</code> refactoring and code completion.</p>
|
||
|
||
<p>All PSI elements which work as references (for which the <code class="code highlight language-text">Go to Declaration</code> action applies) need to implement the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/PsiElement.java" data-bypass="yes" target="_blank"><span>PsiElement.getReference()</span></a>
|
||
method and to return a
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/PsiReference.java" data-bypass="yes" target="_blank"><span>PsiReference</span></a>
|
||
implementation from that method.
|
||
The
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/PsiReference.java" data-bypass="yes" target="_blank"><span>PsiReference</span></a>
|
||
interface can be implemented by the same class as
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/PsiElement.java" data-bypass="yes" target="_blank"><span>PsiElement</span></a>,
|
||
or by a different class. An element can also contain multiple references (for example, a string literal can contain multiple substrings which are valid full-qualified class names), in which case it can implement
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/PsiElement.java" data-bypass="yes" target="_blank"><span>PsiElement.getReferences()</span></a>
|
||
and return the references as an array.</p>
|
||
|
||
<p>The main method of the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/PsiReference.java" data-bypass="yes" target="_blank"><span>PsiReference</span></a>
|
||
interface is <code class="code highlight language-text">resolve()</code>, which returns the element to which the reference points, or <code class="code highlight language-text">null</code> if it was not possible to resolve the reference to a valid element (for example, should it point to an undefined class).
|
||
A counterpart to this method is <code class="code highlight language-text">isReferenceTo()</code>, which checks if the reference resolves to the specified element.
|
||
The latter method can be implemented by calling <code class="code highlight language-text">resolve()</code> and comparing the result with the passed PSI element, but additional optimizations are possible (for example, performing the tree walk only if the element text is equal to the text of the reference).</p>
|
||
|
||
<p><strong>Example</strong>:
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java" data-bypass="yes" target="_blank"><span>Reference</span></a>
|
||
to a ResourceBundle in the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/plugins/properties" data-bypass="yes" target="_blank"><span>Properties language plugin</span></a></p>
|
||
|
||
<p>There’s a set of interfaces which can be used as a base for implementing resolve support, namely the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java" data-bypass="yes" target="_blank"><span>PsiScopeProcessor</span></a> interface and the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/PsiElement.java" data-bypass="yes" target="_blank"><span>PsiElement.processDeclarations()</span></a>
|
||
method.
|
||
These interfaces have a number of extra complexities which are not necessary for most custom languages (like support for substituting Java generics types), but they are required if the custom language can have references to Java code.
|
||
If Java interoperability is not required, the plugin can forgo the standard interfaces and provide its own, different implementation of resolve.</p>
|
||
|
||
<p>The implementation of resolve based on the standard helper classes contains of the following components:</p>
|
||
|
||
<ul>
|
||
<li>
|
||
<p>A class implementing the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java" data-bypass="yes" target="_blank"><span>PsiScopeProcessor</span></a>
|
||
interface which gathers the possible declarations for the reference and stops the resolve process when it has successfully completed.
|
||
The main method which needs to be implemented is <code class="code highlight language-text">execute()</code>, which is called to process every declaration encountered during the resolve, and returns <code class="code highlight language-text">true</code> if the resolve needs to be continued or <code class="code highlight language-text">false</code> if the declaration has been found.
|
||
The methods <code class="code highlight language-text">getHint()</code> and <code class="code highlight language-text">handleEvent()</code> are used for internal optimizations and can be left empty in the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java" data-bypass="yes" target="_blank"><span>PsiScopeProcessor</span></a>
|
||
implementations for custom languages.</p>
|
||
</li>
|
||
<li>
|
||
<p>A function which walks the PSI tree up from the reference location until the resolve has successfully completed or until the end of the resolve scope has been reached.
|
||
If the target of the reference is located in a different file, the file can be located, for example, using
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java" data-bypass="yes" target="_blank"><span>FilenameIndex.getFilesByName()</span></a>
|
||
(if the file name is known) or by iterating through all custom language files in the project (<code class="code highlight language-text">iterateContent()</code> in the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java" data-bypass="yes" target="_blank"><span>FileIndex</span></a>
|
||
interface obtained from
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectRootManager.java" data-bypass="yes" target="_blank"><span>ProjectRootManager.getFileIndex()</span></a>
|
||
).</p>
|
||
</li>
|
||
<li>
|
||
<p>The individual PSI elements, on which the <code class="code highlight language-text">processDeclarations()</code> method is called during the PSI tree walk.
|
||
If a PSI element is a declaration, it passes itself to the <code class="code highlight language-text">execute()</code> method of the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java" data-bypass="yes" target="_blank"><span>PsiScopeProcessor</span></a>
|
||
passed to it.
|
||
Also, if necessary according to the language scoping rules, a PSI element can pass the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java" data-bypass="yes" target="_blank"><span>PsiScopeProcessor</span></a>
|
||
to its child elements.</p>
|
||
</li>
|
||
</ul>
|
||
|
||
<p>An extension of the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/PsiReference.java" data-bypass="yes" target="_blank"><span>PsiReference</span></a>
|
||
interface, which allows a reference to resolve to multiple targets, is the
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/PsiPolyVariantReference.java" data-bypass="yes" target="_blank"><span>PsiPolyVariantReference</span></a>
|
||
interface.
|
||
The targets to which the reference resolves are returned from the <code class="code highlight language-text">multiResolve()</code> method.
|
||
The <code class="code highlight language-text">Go to Declaration</code> action for such references allows the user to choose a navigation target.
|
||
The implementation of <code class="code highlight language-text">multiResolve()</code> can be also based on
|
||
<a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-1731d054af4ca27aa827c03929e27eeb0e6a8366/platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java" data-bypass="yes" target="_blank"><span>PsiScopeProcessor</span></a>,
|
||
and can collect all valid targets for the reference instead of stopping when the first valid target is found.</p>
|
||
|
||
<p>The <code class="code highlight language-text">Quick Definition Lookup</code> action is based on the same mechanism as <code class="code highlight language-text">Go to Declaration</code>, so it becomes automatically available for all references that can be resolved by the language plugin.</p>
|
||
|
||
|
||
<div class="last-modified">
|
||
Last modified: 21 December 2015
|
||
</div>
|
||
</article>
|
||
|
||
<section class="disqus">
|
||
<div id="disqus_thread"></div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
|
||
|
||
<script data-main="/intellij/sdk/docs/app/js/main.build" data-baseurl="/intellij/sdk/docs/" src="/intellij/sdk/docs/app/js/vendor/requirejs/require.js"></script>
|
||
|
||
</body>
|
||
</html>
|
||
|