mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
fixed PY-6947 Separate RST into plugin suitable for inclusion into PhpStorm/WebStorm
This commit is contained in:
@@ -42,7 +42,8 @@ setProperty("pluginFilter", [
|
||||
"coffeescript",
|
||||
"python-remote-interpreter",
|
||||
"diagram-api", "uml",
|
||||
"python-uml", "localization"
|
||||
"python-uml", "localization",
|
||||
"rest"
|
||||
])
|
||||
|
||||
private List<String> pycharmPlatformApiModules() {
|
||||
@@ -357,6 +358,13 @@ private layoutFull(Map args, String target, Set usedJars) {
|
||||
}
|
||||
}
|
||||
}
|
||||
dir("rest") {
|
||||
dir("lib") {
|
||||
jar("rest.jar") {
|
||||
module("rest")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def layouts = includeFile("$home/build/scripts/layouts.gant")
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
<orderEntry type="module" module-name="uml" />
|
||||
<orderEntry type="module" module-name="python-uml" />
|
||||
<orderEntry type="module" module-name="localization" />
|
||||
<orderEntry type="module" module-name="rest" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
<orderEntry type="module" module-name="FirefoxConnector" />
|
||||
<orderEntry type="library" name="Velocity" level="project" />
|
||||
<orderEntry type="module" module-name="localization" />
|
||||
<orderEntry type="module" module-name="rest" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<idea-plugin version="2" xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<name>ReStructuredText Support</name>
|
||||
<id>org.jetbrains.plugins.rest</id>
|
||||
<version>VERSION</version>
|
||||
<description>This plugin enables support for ReStructuredText files (*.rst)</description>
|
||||
<vendor logo="/general/ijLogo.png">JetBrains</vendor>
|
||||
<depends>com.intellij.modules.ultimate</depends>
|
||||
|
||||
<xi:include href="/META-INF/rest.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,27 @@
|
||||
<idea-plugin version="2">
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
|
||||
<fileTypeFactory implementation="com.jetbrains.rest.RestFileTypeFactory"/>
|
||||
<lang.syntaxHighlighterFactory key="ReST"
|
||||
implementationClass="com.jetbrains.rest.RestHighlighterFactory"/>
|
||||
<lang.parserDefinition language="ReST" implementationClass="com.jetbrains.rest.parsing.RestParserDefinition"/>
|
||||
<colorSettingsPage implementation="com.jetbrains.rest.RestColorsPage"/>
|
||||
|
||||
<projectService serviceInterface="com.jetbrains.rest.ReSTService"
|
||||
serviceImplementation="com.jetbrains.rest.ReSTService"/>
|
||||
<completion.contributor language="ReST" implementationClass="com.jetbrains.rest.completion.DirectiveCompletionContributor"/>
|
||||
<completion.contributor language="ReST" implementationClass="com.jetbrains.rest.completion.OptionCompletionContributor"/>
|
||||
<completion.contributor language="ReST" implementationClass="com.jetbrains.rest.completion.ReferenceCompletionContributor"/>
|
||||
<gotoDeclarationHandler implementation="com.jetbrains.rest.RestGotoProvider" order="FIRST"/>
|
||||
<lang.psiStructureViewFactory language="ReST"
|
||||
implementationClass="com.jetbrains.rest.structureView.RestStructureViewFactory"/>
|
||||
<annotator language="ReST" implementationClass="com.jetbrains.rest.validation.RestAnnotatingVisitor"/>
|
||||
|
||||
<lang.substitutor language="TEXT" implementationClass="com.jetbrains.rest.RestLanguageSubstitutor"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij.spellchecker">
|
||||
<support language="ReST" implementationClass="com.jetbrains.rest.spellchecker.RestSpellcheckerStrategy"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="platform-api" />
|
||||
<orderEntry type="module" module-name="lang-impl" />
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="module" module-name="spellchecker" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
|
||||
/**
|
||||
* User: catherine
|
||||
*/
|
||||
@State(name = "ReSTService",
|
||||
storages = {
|
||||
@Storage( file = StoragePathMacros.PROJECT_FILE),
|
||||
@Storage( file = StoragePathMacros.PROJECT_CONFIG_DIR + "/rest.xml", scheme = StorageScheme.DIRECTORY_BASED)
|
||||
}
|
||||
)
|
||||
public class ReSTService implements PersistentStateComponent<ReSTService> {
|
||||
public String DOC_DIR = "";
|
||||
public boolean TXT_IS_RST = false;
|
||||
|
||||
public ReSTService() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReSTService getState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(ReSTService state) {
|
||||
XmlSerializerUtil.copyBean(state, this);
|
||||
}
|
||||
|
||||
public void setWorkdir(String workDir) {
|
||||
DOC_DIR = workDir;
|
||||
}
|
||||
|
||||
public static ReSTService getInstance(Project project) {
|
||||
return ServiceManager.getService(project, ReSTService.class);
|
||||
}
|
||||
|
||||
public String getWorkdir() {
|
||||
return DOC_DIR;
|
||||
}
|
||||
|
||||
public boolean txtIsRst() {
|
||||
return TXT_IS_RST;
|
||||
}
|
||||
|
||||
public void setTxtIsRst(boolean isRst) {
|
||||
TXT_IS_RST = isRst;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
// A copy of Ruby's.
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestBundle {
|
||||
private static Reference<ResourceBundle> ourBundle;
|
||||
|
||||
@NonNls
|
||||
private static final String BUNDLE = "com.jetbrains.rest.RestBundle";
|
||||
|
||||
private RestBundle() {
|
||||
}
|
||||
|
||||
public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
|
||||
return CommonBundle.message(getBundle(), key, params);
|
||||
}
|
||||
|
||||
// Cached loading
|
||||
private static ResourceBundle getBundle() {
|
||||
ResourceBundle bundle = null;
|
||||
if (ourBundle != null) bundle = ourBundle.get();
|
||||
if (bundle == null) {
|
||||
bundle = ResourceBundle.getBundle(BUNDLE);
|
||||
ourBundle = new SoftReference<ResourceBundle>(bundle);
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
### Inspections: INSP ###
|
||||
INSP.GROUP.rest=ReST
|
||||
|
||||
INSP.role.not.defined=Role is not defined
|
||||
|
||||
### Quick fixes ###
|
||||
QFIX.ignore.role=Ignore undefined role ''{0}''
|
||||
|
||||
### Annotators ###
|
||||
ANN.unknown.target=Unknown target name ''{0}''
|
||||
ANN.duplicate.target=Duplicate explicit target name ''{0}''
|
||||
ANN.unusable.anonymous.target=Anonymous hyperlink target has no reference
|
||||
ANN.inline.block=Blank line is required after a literal block
|
||||
|
||||
### Run configurations ###
|
||||
runcfg.docutils.display_name=Python docs
|
||||
runcfg.docutils.description=Python documentation run configuration
|
||||
runcfg.docutils.input=Input:
|
||||
runcfg.docutils.output=Output:
|
||||
runcfg.docutils.command=Command:
|
||||
runcfg.docutils.options=Options:
|
||||
runcfg.dlg.select.script.path=Select path:
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
|
||||
import com.intellij.openapi.options.colors.AttributesDescriptor;
|
||||
import com.intellij.openapi.options.colors.ColorDescriptor;
|
||||
import com.intellij.openapi.options.colors.ColorSettingsPage;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestColorsPage implements ColorSettingsPage {
|
||||
private static final AttributesDescriptor[] ATTRS = new AttributesDescriptor[]{
|
||||
new AttributesDescriptor("Comment", RestSyntaxHighlighter.REST_COMMENT),
|
||||
new AttributesDescriptor("Title", RestSyntaxHighlighter.REST_SECTION_HEADER),
|
||||
new AttributesDescriptor("Explicit markup", RestSyntaxHighlighter.REST_EXPLICIT),
|
||||
new AttributesDescriptor("Fields", RestSyntaxHighlighter.REST_FIELD),
|
||||
new AttributesDescriptor("Reference name", RestSyntaxHighlighter.REST_REF_NAME),
|
||||
new AttributesDescriptor("Inline literals", RestSyntaxHighlighter.REST_FIXED),
|
||||
new AttributesDescriptor("Bold text", RestSyntaxHighlighter.REST_BOLD),
|
||||
new AttributesDescriptor("Italic text", RestSyntaxHighlighter.REST_ITALIC),
|
||||
new AttributesDescriptor("Interpreted text", RestSyntaxHighlighter.REST_INTERPRETED),
|
||||
new AttributesDescriptor("Literal and line blocks", RestSyntaxHighlighter.REST_INLINE),
|
||||
};
|
||||
|
||||
@NonNls private static final HashMap<String, TextAttributesKey> ourTagToDescriptorMap = new HashMap<String, TextAttributesKey>();
|
||||
|
||||
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return "ReST file";
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
return RestFileType.INSTANCE.getIcon();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public AttributesDescriptor[] getAttributeDescriptors() {
|
||||
return ATTRS;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ColorDescriptor[] getColorDescriptors() {
|
||||
return ColorDescriptor.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SyntaxHighlighter getHighlighter() {
|
||||
final SyntaxHighlighter highlighter = SyntaxHighlighter.PROVIDER.create(RestFileType.INSTANCE, null, null);
|
||||
assert highlighter != null;
|
||||
return highlighter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDemoText() {
|
||||
return
|
||||
".. comment for documentation master file\n\n" +
|
||||
"===============\n" +
|
||||
" Section Title\n" +
|
||||
"===============\n\n" +
|
||||
".. toctree::\n" +
|
||||
" :maxdepth: 2\n\n" +
|
||||
"There is *some italics text*\n" +
|
||||
"and **bold one** " +
|
||||
"and ``inline literals``\n\n" +
|
||||
"A link_ in citation style.\n" +
|
||||
"\n" +
|
||||
".. _link: http://www.google.com\n\n" +
|
||||
".. rubric:: Footnotes\n" +
|
||||
".. [*] footnote.\n" +
|
||||
".. [REL09] Citation\n\n" +
|
||||
":ref:`builders`\n\n" +
|
||||
"\n" +
|
||||
"::\n" +
|
||||
"\n" +
|
||||
" Whitespace, newlines, blank lines, and\n" +
|
||||
" all kinds of markup (like *this* or\n" +
|
||||
" \\this) is preserved by literal blocks.\n\n" +
|
||||
"It was literal block.";
|
||||
}
|
||||
|
||||
public Map<String, TextAttributesKey> getAdditionalHighlightingTagToDescriptorMap() {
|
||||
return ourTagToDescriptorMap;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestElementType extends IElementType {
|
||||
public RestElementType(@NotNull @NonNls String s) {
|
||||
super(s, RestLanguage.INSTANCE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.psi.tree.IFileElementType;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public interface RestElementTypes {
|
||||
IFileElementType REST_FILE = new IFileElementType("REST_FILE", RestLanguage.INSTANCE);
|
||||
RestElementType REFERENCE_TARGET = new RestElementType("REFERENCE");
|
||||
RestElementType DIRECTIVE_BLOCK = new RestElementType("DIRECTIVE_BLOCK");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestFile extends PsiFileImpl {
|
||||
public RestFile(FileViewProvider viewProvider) {
|
||||
super(RestElementTypes.REST_FILE, RestElementTypes.REST_FILE, viewProvider);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FileType getFileType() {
|
||||
return RestFileType.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
visitor.visitFile(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "rest file";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*
|
||||
* file type for restructured text files
|
||||
*/
|
||||
public class RestFileType extends LanguageFileType {
|
||||
public static final RestFileType INSTANCE = new RestFileType();
|
||||
@NonNls public static final String DEFAULT_EXTENSION = "rst";
|
||||
@NonNls private static final String NAME = "ReST";
|
||||
@NonNls private static final String DESCRIPTION = "reStructuredText files";
|
||||
|
||||
private RestFileType() {
|
||||
super(RestLanguage.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDescription() {
|
||||
return DESCRIPTION;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDefaultExtension() {
|
||||
return DEFAULT_EXTENSION;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Icon getIcon() {
|
||||
return IconLoader.getIcon("/com/jetbrains/rest/res/rst.png", RestFileType.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileTypeConsumer;
|
||||
import com.intellij.openapi.fileTypes.FileTypeFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestFileTypeFactory extends FileTypeFactory {
|
||||
@Override
|
||||
public void createFileTypes(final @NotNull FileTypeConsumer consumer) {
|
||||
consumer.consume(RestFileType.INSTANCE, RestFileType.DEFAULT_EXTENSION);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandlerBase;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.rest.psi.RestReference;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestGotoProvider extends GotoDeclarationHandlerBase {
|
||||
|
||||
public PsiElement getGotoDeclarationTarget(PsiElement source, Editor editor) {
|
||||
if (source != null && source.getLanguage() instanceof RestLanguage) {
|
||||
RestReference ref = PsiTreeUtil.getParentOfType(source, RestReference.class);
|
||||
if (ref != null) {
|
||||
return ref.resolve();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestHighlighterFactory extends SyntaxHighlighterFactory {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SyntaxHighlighter getSyntaxHighlighter(Project project, VirtualFile virtualFile) {
|
||||
return new RestSyntaxHighlighter();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.psi.templateLanguages.TemplateLanguage;
|
||||
import com.jetbrains.rest.validation.RestAnnotator;
|
||||
import com.jetbrains.rest.validation.RestHyperlinksAnnotator;
|
||||
import com.jetbrains.rest.validation.RestInlineBlockAnnotator;
|
||||
import com.jetbrains.rest.validation.RestReferenceTargetAnnotator;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestLanguage extends Language implements TemplateLanguage {
|
||||
public static final RestLanguage INSTANCE = new RestLanguage();
|
||||
private final Set<Class<? extends RestAnnotator>> _annotators = new CopyOnWriteArraySet<Class<? extends RestAnnotator>>();
|
||||
private RestLanguage() {
|
||||
super("ReST");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Rest language";
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestFileType getAssociatedFileType() {
|
||||
return RestFileType.INSTANCE;
|
||||
}
|
||||
{
|
||||
_annotators.add(RestHyperlinksAnnotator.class);
|
||||
_annotators.add(RestReferenceTargetAnnotator.class);
|
||||
_annotators.add(RestInlineBlockAnnotator.class);
|
||||
}
|
||||
|
||||
public Set<Class<? extends RestAnnotator>> getAnnotators() {
|
||||
return _annotators;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.LanguageSubstitutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestLanguageSubstitutor extends LanguageSubstitutor {
|
||||
@Override
|
||||
public Language getLanguage(@NotNull final VirtualFile vFile, @NotNull final Project project) {
|
||||
boolean txtIsRst = ReSTService.getInstance(project).txtIsRst();
|
||||
if (txtIsRst)
|
||||
return RestLanguage.INSTANCE;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2000-2008 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.lexer.Lexer;
|
||||
import com.intellij.openapi.editor.SyntaxHighlighterColors;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.jetbrains.rest.lexer.RestFlexLexer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestSyntaxHighlighter extends SyntaxHighlighterBase implements RestTokenTypes {
|
||||
public static final TextAttributesKey REST_COMMENT = TextAttributesKey.createTextAttributesKey(
|
||||
"REST.LINE_COMMENT",
|
||||
SyntaxHighlighterColors.LINE_COMMENT.getDefaultAttributes()
|
||||
);
|
||||
|
||||
public static final TextAttributesKey REST_SECTION_HEADER = TextAttributesKey.createTextAttributesKey(
|
||||
"REST.SECTION.HEADER",
|
||||
SyntaxHighlighterColors.NUMBER.getDefaultAttributes()
|
||||
);
|
||||
|
||||
public static final TextAttributesKey REST_BOLD = TextAttributesKey.createTextAttributesKey(
|
||||
"REST.BOLD",
|
||||
new TextAttributes(Color.black, null, null, null, Font.BOLD)
|
||||
);
|
||||
public static final TextAttributesKey REST_ITALIC = TextAttributesKey.createTextAttributesKey(
|
||||
"REST.ITALIC",
|
||||
new TextAttributes(Color.black, null, null, null, Font.ITALIC)
|
||||
);
|
||||
public static final TextAttributesKey REST_FIXED = TextAttributesKey.createTextAttributesKey(
|
||||
"REST.FIXED",
|
||||
new TextAttributes(Color.black, new Color(217, 217, 240), null, null, Font.PLAIN)
|
||||
);
|
||||
|
||||
public static final TextAttributesKey REST_INTERPRETED = TextAttributesKey.createTextAttributesKey(
|
||||
"REST.INTERPRETED",
|
||||
new TextAttributes(Color.black, new Color(202, 218, 186), null, null, Font.PLAIN)
|
||||
);
|
||||
|
||||
public static final TextAttributesKey REST_REF_NAME = TextAttributesKey.createTextAttributesKey(
|
||||
"REST.REF.NAME",
|
||||
SyntaxHighlighterColors.STRING.getDefaultAttributes()
|
||||
);
|
||||
|
||||
public static final TextAttributesKey REST_EXPLICIT= TextAttributesKey.createTextAttributesKey(
|
||||
"REST.EXPLICIT",
|
||||
SyntaxHighlighterColors.KEYWORD.getDefaultAttributes()
|
||||
);
|
||||
public static final TextAttributesKey REST_FIELD = TextAttributesKey.createTextAttributesKey(
|
||||
"REST.FIELD",
|
||||
SyntaxHighlighterColors.KEYWORD.getDefaultAttributes()
|
||||
);
|
||||
|
||||
public static final TextAttributesKey REST_INLINE = TextAttributesKey.createTextAttributesKey(
|
||||
"REST.INLINE",
|
||||
new TextAttributes(null, new Color(237, 252, 237), null, null, Font.PLAIN)
|
||||
);
|
||||
private static final Map<IElementType, TextAttributesKey> ATTRIBUTES = Maps.newHashMap();
|
||||
|
||||
static {
|
||||
ATTRIBUTES.put(REFERENCE_NAME, REST_REF_NAME);
|
||||
ATTRIBUTES.put(DIRECT_HYPERLINK, REST_REF_NAME);
|
||||
ATTRIBUTES.put(TITLE, REST_SECTION_HEADER);
|
||||
ATTRIBUTES.put(TITLE_TEXT, REST_SECTION_HEADER);
|
||||
ATTRIBUTES.put(FOOTNOTE, REST_EXPLICIT);
|
||||
ATTRIBUTES.put(CITATION, REST_EXPLICIT);
|
||||
ATTRIBUTES.put(HYPERLINK, REST_REF_NAME);
|
||||
ATTRIBUTES.put(ANONYMOUS_HYPERLINK, REST_REF_NAME);
|
||||
ATTRIBUTES.put(DIRECTIVE, REST_EXPLICIT);
|
||||
ATTRIBUTES.put(CUSTOM_DIRECTIVE, REST_EXPLICIT);
|
||||
ATTRIBUTES.put(SUBSTITUTION, REST_EXPLICIT);
|
||||
ATTRIBUTES.put(COMMENT, REST_COMMENT);
|
||||
ATTRIBUTES.put(FIELD, REST_FIELD);
|
||||
ATTRIBUTES.put(BOLD, REST_BOLD);
|
||||
ATTRIBUTES.put(ITALIC, REST_ITALIC);
|
||||
ATTRIBUTES.put(FIXED, REST_FIXED);
|
||||
ATTRIBUTES.put(INTERPRETED, REST_INTERPRETED);
|
||||
ATTRIBUTES.put(INLINE_LINE, REST_INLINE);
|
||||
ATTRIBUTES.put(PYTHON_LINE, REST_INLINE);
|
||||
ATTRIBUTES.put(DJANGO_LINE, REST_INLINE);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
|
||||
return SyntaxHighlighterBase.pack(ATTRIBUTES.get(tokenType));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Lexer getHighlightingLexer() {
|
||||
return new RestFlexLexer();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public interface RestTokenTypes {
|
||||
RestElementType WHITESPACE = new RestElementType("WHITESPACE");
|
||||
|
||||
RestElementType TITLE = new RestElementType("TITLE");
|
||||
RestElementType TITLE_TEXT = new RestElementType("TITLETEXT");
|
||||
RestElementType EXPLISIT_MARKUP_START = new RestElementType("EXPLISIT_MARKUP_START");
|
||||
RestElementType FOOTNOTE = new RestElementType("FOOTNOTE");
|
||||
RestElementType CITATION = new RestElementType("CITATION");
|
||||
RestElementType HYPERLINK = new RestElementType("HYPERLINK");
|
||||
RestElementType ANONYMOUS_HYPERLINK = new RestElementType("ANONYMOUS_HYPERLINK");
|
||||
RestElementType DIRECTIVE = new RestElementType("DIRECTIVE");
|
||||
RestElementType CUSTOM_DIRECTIVE = new RestElementType("CUSTOM_DIRECTIVE");
|
||||
RestElementType SUBSTITUTION = new RestElementType("SUBSTITUTION");
|
||||
|
||||
RestElementType LINE = new RestElementType("LINE");
|
||||
RestElementType INLINE_LINE = new RestElementType("INLINE_LINE");
|
||||
RestElementType SPEC_SYMBOL = new RestElementType("SPEC_SYMBOL");
|
||||
|
||||
RestElementType COMMENT = new RestElementType("COMMENT");
|
||||
RestElementType REFERENCE_NAME = new RestElementType("REFERENCE_NAME");
|
||||
|
||||
RestElementType FIELD = new RestElementType("FIELD");
|
||||
|
||||
RestElementType BOLD = new RestElementType("BOLD");
|
||||
RestElementType ITALIC = new RestElementType("ITALIC");
|
||||
RestElementType FIXED = new RestElementType("FIXED");
|
||||
RestElementType LITERAL_BLOCK_START = new RestElementType("LITERAL_BLOCK_START");
|
||||
RestElementType INTERPRETED = new RestElementType("INTERPRETED");
|
||||
|
||||
RestElementType ERROR = new RestElementType("ERROR");
|
||||
|
||||
RestElementType REST_INJECTION = new RestElementType("REST_INJECTION");
|
||||
RestElementType REST_DJANGO_INJECTION = new RestElementType("REST_DJANGO_INJECTION");
|
||||
RestElementType DJANGO_LINE = new RestElementType("DJANGO_LINE");
|
||||
RestElementType PYTHON_LINE = new RestElementType("PYTHON_LINE");
|
||||
RestElementType JAVASCRIPT_LINE = new RestElementType("JAVASCRIPT_LINE");
|
||||
RestElementType DIRECT_HYPERLINK = new RestElementType("DIRECT_HYPERLINK");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package com.jetbrains.rest;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestUtil {
|
||||
private RestUtil() {}
|
||||
|
||||
@Nullable
|
||||
public static String findRunner(final String sdkHome, String runnerName) {
|
||||
String shortRunner = null;
|
||||
if (runnerName.endsWith(".py")) shortRunner = runnerName.substring(0, runnerName.length()-3);
|
||||
File bin_path = new File(sdkHome);
|
||||
File bin_dir = bin_path.getParentFile();
|
||||
if (bin_dir == null) return null;
|
||||
File runner = new File(bin_dir, runnerName);
|
||||
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
|
||||
runner = new File(new File(bin_dir, "scripts"), runnerName);
|
||||
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
|
||||
runner = new File(new File(bin_dir.getParentFile(), "scripts"), runnerName);
|
||||
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
|
||||
runner = new File(new File(bin_dir.getParentFile(), "local"), runnerName);
|
||||
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
|
||||
runner = new File(new File (new File(bin_dir.getParentFile(), "local"), "bin"), runnerName);
|
||||
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
|
||||
|
||||
if (shortRunner != null) return findRunner(sdkHome, shortRunner);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String[] SPHINX_DIRECTIVES = new String[] {
|
||||
"module::" , "automodule::" , "autoclass::" , "toctree::" , "glossary::" , "code-block::", "versionadded::",
|
||||
"versionchanged::", "deprecated::", "seealso::", "centered::", "hlist::", "index::", "productionlist::", "highlight::",
|
||||
"literalinclude::", "sectionauthor::", "codeauthor::", "only::", "tabularcolumns::", "py:function::", "default-domain::",
|
||||
"py:module::", "py:currentmodule::", "py:data::", "py:exception::", "py:function::", "py:class::", "py:attribute::",
|
||||
"py:method::", "py:staticmethod::", "py:classmethod::", "c:function::", "c:member::", "c:macro::", "c:type::", "c:var::",
|
||||
"cpp:class::", "cpp:function::", "cpp:member::", "cpp:type::", "option::", "envvar::", "program::", "describe::", "object::",
|
||||
"js:function::", "js:class::", "js:data::", "js:attribute::", "rst:directive::", "rst:role::"
|
||||
};
|
||||
|
||||
|
||||
public static final Set<String> PREDEFINED_ROLES = Sets.newHashSet();
|
||||
public static final Set<String> SPHINX_ROLES = Sets.newHashSet();
|
||||
private static final Map<String, String[]> DIRECTIVES = Maps.newHashMap();
|
||||
|
||||
static {
|
||||
PREDEFINED_ROLES.add(":emphasis:");
|
||||
PREDEFINED_ROLES.add(":literal:");
|
||||
PREDEFINED_ROLES.add(":pep-reference:");
|
||||
PREDEFINED_ROLES.add(":PEP:");
|
||||
PREDEFINED_ROLES.add(":rfc-reference:");
|
||||
PREDEFINED_ROLES.add(":RFC:");
|
||||
PREDEFINED_ROLES.add(":strong:");
|
||||
PREDEFINED_ROLES.add(":subscript:");
|
||||
PREDEFINED_ROLES.add(":sub:");
|
||||
PREDEFINED_ROLES.add(":superscript:");
|
||||
PREDEFINED_ROLES.add(":sup:");
|
||||
PREDEFINED_ROLES.add(":title-reference:");
|
||||
PREDEFINED_ROLES.add(":title:");
|
||||
PREDEFINED_ROLES.add(":t:");
|
||||
PREDEFINED_ROLES.add(":raw:");
|
||||
|
||||
SPHINX_ROLES.add(":py:mod:");
|
||||
SPHINX_ROLES.add(":py:func:");
|
||||
SPHINX_ROLES.add(":py:data:");
|
||||
SPHINX_ROLES.add(":py:const:");
|
||||
SPHINX_ROLES.add(":py:class:");
|
||||
SPHINX_ROLES.add(":py:meth:");
|
||||
SPHINX_ROLES.add(":py:attr:");
|
||||
SPHINX_ROLES.add(":py:exc:");
|
||||
SPHINX_ROLES.add(":py:obj:");
|
||||
SPHINX_ROLES.add(":ref:");
|
||||
SPHINX_ROLES.add(":doc:");
|
||||
SPHINX_ROLES.add(":download:");
|
||||
SPHINX_ROLES.add(":envvar:");
|
||||
SPHINX_ROLES.add(":token:");
|
||||
SPHINX_ROLES.add(":keyword:");
|
||||
SPHINX_ROLES.add(":option:");
|
||||
SPHINX_ROLES.add(":term:");
|
||||
SPHINX_ROLES.add(":abbr:");
|
||||
SPHINX_ROLES.add(":command:");
|
||||
SPHINX_ROLES.add(":dfn:");
|
||||
SPHINX_ROLES.add(":file:");
|
||||
SPHINX_ROLES.add(":guilabel:");
|
||||
SPHINX_ROLES.add(":kbd:");
|
||||
SPHINX_ROLES.add(":mailheader:");
|
||||
SPHINX_ROLES.add(":makevar:");
|
||||
SPHINX_ROLES.add(":manpage:");
|
||||
SPHINX_ROLES.add(":menuselection:");
|
||||
SPHINX_ROLES.add(":mimetype:");
|
||||
SPHINX_ROLES.add(":newsgroup:");
|
||||
SPHINX_ROLES.add(":program:");
|
||||
SPHINX_ROLES.add(":regexp:");
|
||||
SPHINX_ROLES.add(":samp:");
|
||||
SPHINX_ROLES.add(":pep:");
|
||||
SPHINX_ROLES.add(":rfc:");
|
||||
|
||||
DIRECTIVES.put("attention::", new String[] {});
|
||||
DIRECTIVES.put("caution::", new String[] {});
|
||||
DIRECTIVES.put("danger::", new String[] {});
|
||||
DIRECTIVES.put("error::", new String[] {});
|
||||
DIRECTIVES.put("hint::", new String[] {});
|
||||
DIRECTIVES.put("important::", new String[] {});
|
||||
DIRECTIVES.put("note::", new String[] {});
|
||||
DIRECTIVES.put("tip::", new String[] {});
|
||||
DIRECTIVES.put("warning::", new String[] {});
|
||||
DIRECTIVES.put("admonition::", new String[] {":class:"});
|
||||
DIRECTIVES.put("image::", new String[] {":alt:", ":height:", ":width:", ":scale:", ":align:", ":target:", ":class:"});
|
||||
DIRECTIVES.put("figure::", new String[] {":alt:", ":height:", ":width:", ":scale:", ":align:", ":target:", ":class:", ":figwidth:", ":figclass:"});
|
||||
DIRECTIVES.put("topic::", new String[] {":class:"});
|
||||
DIRECTIVES.put("sidebar::", new String[] {":subtitle:", ":class:"});
|
||||
DIRECTIVES.put("line-block::", new String[] {":class:"});
|
||||
DIRECTIVES.put("parsed-literal::", new String[] {":class:"});
|
||||
DIRECTIVES.put("rubric::", new String[] {":class:"});
|
||||
DIRECTIVES.put("epigraph::", new String[] {});
|
||||
DIRECTIVES.put("highlights::", new String[] {});
|
||||
DIRECTIVES.put("pull-quote::", new String[] {});
|
||||
DIRECTIVES.put("compound::", new String[] {":class:"});
|
||||
DIRECTIVES.put("container::", new String[] {});
|
||||
DIRECTIVES.put("table::", new String[] {":class:"});
|
||||
DIRECTIVES.put("csv-table::", new String[] {":class:", ":widths:", ":header-rows:", ":stub-columns:", ":header:", ":file:", ":url:", ":encoding:",
|
||||
":delim:", ":quote:", ":keepspace:", ":escape:"});
|
||||
DIRECTIVES.put("list-table::", new String[] {":class:", ":widths:", ":header-rows:", ":stub-columns:"});
|
||||
DIRECTIVES.put("contents::", new String[] {":class:", ":depth:", ":local:", ":backlinks:"});
|
||||
DIRECTIVES.put("sectnum::", new String[] {":depth:", ":prefix:", ":suffix:", ":start:"});
|
||||
DIRECTIVES.put("section-autonumbering::", new String[] {":depth:", ":prefix:", ":suffix:", ":start:"});
|
||||
DIRECTIVES.put("header::", new String[] {});
|
||||
DIRECTIVES.put("footer::", new String[] {});
|
||||
DIRECTIVES.put("target-notes::", new String[] {"class"});
|
||||
|
||||
DIRECTIVES.put("footnotes::", new String[] {});
|
||||
DIRECTIVES.put("citations::", new String[] {});
|
||||
DIRECTIVES.put("meta::", new String[] {});
|
||||
|
||||
DIRECTIVES.put("replace::", new String[] {});
|
||||
DIRECTIVES.put("unicode::", new String[] {":ltrim:", ":rtrim:", ":trim:"});
|
||||
DIRECTIVES.put("date::", new String[] {});
|
||||
DIRECTIVES.put("include::", new String[] {":start-line:", ":end-line:", ":start-after:", ":end-before:", ":literal:", ":encoding:", ":tab-width:"});
|
||||
DIRECTIVES.put("raw::", new String[] {":file:", ":url:", ":encoding:"});
|
||||
DIRECTIVES.put("class::", new String[] {});
|
||||
DIRECTIVES.put("role::", new String[] {":class:", ":format:"});
|
||||
DIRECTIVES.put("default-role::", new String[] {});
|
||||
DIRECTIVES.put("title::", new String[] {});
|
||||
DIRECTIVES.put("restructuredtext-test-directive::", new String[] {});
|
||||
}
|
||||
|
||||
static public String[] getDirectiveOptions(String directive) {
|
||||
if (DIRECTIVES.containsKey(directive))
|
||||
return DIRECTIVES.get(directive);
|
||||
return new String[]{};
|
||||
}
|
||||
|
||||
static public Set<String> getDirectives() {
|
||||
return DIRECTIVES.keySet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.jetbrains.rest.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.patterns.PsiElementPattern;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.jetbrains.rest.RestTokenTypes;
|
||||
import com.jetbrains.rest.RestUtil;
|
||||
import com.jetbrains.rest.psi.RestReferenceTarget;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
import static com.intellij.patterns.StandardPatterns.or;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class DirectiveCompletionContributor extends CompletionContributor {
|
||||
public static final PsiElementPattern.Capture<PsiElement> DIRECTIVE_PATTERN = psiElement().afterSibling(or(psiElement().
|
||||
withElementType(RestTokenTypes.WHITESPACE).afterSibling(psiElement(RestReferenceTarget.class)),
|
||||
psiElement().withElementType(RestTokenTypes.EXPLISIT_MARKUP_START)));
|
||||
|
||||
public DirectiveCompletionContributor() {
|
||||
extend(CompletionType.BASIC, DIRECTIVE_PATTERN,
|
||||
new CompletionProvider<CompletionParameters>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
ProcessingContext context,
|
||||
@NotNull CompletionResultSet result) {
|
||||
for (String tag : RestUtil.getDirectives()) {
|
||||
result.addElement(LookupElementBuilder.create(tag));
|
||||
}
|
||||
Sdk sdk = ProjectRootManager.getInstance(parameters.getPosition().getProject()).getProjectSdk();
|
||||
if (sdk != null) {
|
||||
String sphinx = RestUtil.findRunner(sdk.getHomePath(), "sphinx-quickstart"+ (SystemInfo.isWindows ? ".exe" : ""));
|
||||
if (sphinx != null && !sphinx.isEmpty()) {
|
||||
for (String tag : RestUtil.SPHINX_DIRECTIVES) {
|
||||
result.addElement(LookupElementBuilder.create(tag));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.jetbrains.rest.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.patterns.PsiElementPattern;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.jetbrains.rest.RestUtil;
|
||||
import com.jetbrains.rest.psi.RestDirectiveBlock;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class OptionCompletionContributor extends CompletionContributor {
|
||||
public static final PsiElementPattern.Capture<PsiElement> OPTION_PATTERN = psiElement().withParent(RestDirectiveBlock.class);
|
||||
|
||||
public OptionCompletionContributor() {
|
||||
extend(CompletionType.BASIC, OPTION_PATTERN,
|
||||
new CompletionProvider<CompletionParameters>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
ProcessingContext context,
|
||||
@NotNull CompletionResultSet result) {
|
||||
|
||||
RestDirectiveBlock original = PsiTreeUtil.getParentOfType(parameters.getOriginalPosition(), RestDirectiveBlock.class);
|
||||
if (original != null) {
|
||||
|
||||
int offset = parameters.getOffset();
|
||||
final PsiFile file = parameters.getOriginalFile();
|
||||
String prefix = getPrefix(offset, file);
|
||||
|
||||
if (prefix.length() > 0) {
|
||||
result = result.withPrefixMatcher(prefix);
|
||||
}
|
||||
for (String tag : RestUtil.getDirectiveOptions(original.getDirectiveName())) {
|
||||
result.addElement(LookupElementBuilder.create(tag + " "));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String getPrefix(int offset, PsiFile file) {
|
||||
if (offset > 0) {
|
||||
offset--;
|
||||
}
|
||||
final String text = file.getText();
|
||||
StringBuilder prefixBuilder = new StringBuilder();
|
||||
while(offset > 0 && (Character.isLetterOrDigit(text.charAt(offset)) || text.charAt(offset) == ':')) {
|
||||
prefixBuilder.insert(0, text.charAt(offset));
|
||||
if (text.charAt(offset) == ':') {
|
||||
break;
|
||||
}
|
||||
offset--;
|
||||
}
|
||||
return prefixBuilder.toString();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.jetbrains.rest.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.patterns.PsiElementPattern;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.jetbrains.rest.RestTokenTypes;
|
||||
import com.jetbrains.rest.psi.RestReference;
|
||||
import com.jetbrains.rest.psi.RestReferenceTarget;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class ReferenceCompletionContributor extends CompletionContributor {
|
||||
public static final PsiElementPattern.Capture<PsiElement> REFERENCE_PATTERN =
|
||||
psiElement().afterSibling(psiElement().withElementType(RestTokenTypes.EXPLISIT_MARKUP_START));
|
||||
|
||||
public static final PsiElementPattern.Capture<PsiElement> PATTERN =
|
||||
psiElement().andOr(psiElement().withParent(REFERENCE_PATTERN), REFERENCE_PATTERN);
|
||||
|
||||
public ReferenceCompletionContributor() {
|
||||
extend(CompletionType.BASIC, PATTERN,
|
||||
new CompletionProvider<CompletionParameters>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
ProcessingContext context,
|
||||
@NotNull CompletionResultSet result) {
|
||||
PsiElement original = parameters.getPosition();
|
||||
PsiFile file = original.getContainingFile();
|
||||
int offset = parameters.getOffset();
|
||||
String prefix = getPrefix(offset, file);
|
||||
|
||||
if (prefix.length() > 0) {
|
||||
result = result.withPrefixMatcher(prefix);
|
||||
}
|
||||
RestReference[] elements = PsiTreeUtil.getChildrenOfType(file, RestReference.class);
|
||||
RestReferenceTarget[] targets = PsiTreeUtil.getChildrenOfType(file, RestReferenceTarget.class);
|
||||
Set<String> names = new HashSet<String>();
|
||||
if (targets != null) {
|
||||
for (RestReferenceTarget t : targets) {
|
||||
names.add(t.getReferenceName());
|
||||
}
|
||||
}
|
||||
|
||||
if (elements != null) {
|
||||
for (RestReference e : elements) {
|
||||
String name = e.getReferenceText();
|
||||
if (! names.contains(name)) {
|
||||
if ((name.startsWith("[") && name.endsWith("]")) ||
|
||||
(name.startsWith("|") && name.endsWith("|")))
|
||||
result.addElement(LookupElementBuilder.create(name));
|
||||
else if (name.equals("__"))
|
||||
result.addElement(LookupElementBuilder.create(name + ":"));
|
||||
else {
|
||||
if (name.startsWith("_")) name = "\\"+name;
|
||||
result.addElement(LookupElementBuilder.create("_" + name + ":"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getPrefix(int offset, PsiFile file) {
|
||||
if (offset > 0) {
|
||||
offset--;
|
||||
}
|
||||
final String text = file.getText();
|
||||
StringBuilder prefixBuilder = new StringBuilder();
|
||||
while(offset > 0 && (Character.isLetterOrDigit(text.charAt(offset)) || text.charAt(offset) == '_'
|
||||
|| text.charAt(offset) == '[') || text.charAt(offset) == '|') {
|
||||
prefixBuilder.insert(0, text.charAt(offset));
|
||||
if (text.charAt(offset) == '_' || text.charAt(offset) == '[' || text.charAt(offset) == '|') {
|
||||
break;
|
||||
}
|
||||
offset--;
|
||||
}
|
||||
return prefixBuilder.toString();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.jetbrains.rest.lexer;
|
||||
|
||||
import com.intellij.lexer.FlexAdapter;
|
||||
import com.intellij.lexer.MergingLexerAdapter;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.jetbrains.rest.RestTokenTypes;
|
||||
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestFlexLexer extends MergingLexerAdapter {
|
||||
public static final TokenSet TOKENS_TO_MERGE = TokenSet.create(RestTokenTypes.ITALIC, RestTokenTypes.BOLD, RestTokenTypes.FIXED,
|
||||
RestTokenTypes.LINE, RestTokenTypes.PYTHON_LINE,
|
||||
RestTokenTypes.COMMENT);
|
||||
public RestFlexLexer() {
|
||||
super(new FlexAdapter(new _RestFlexLexer((Reader) null)), TOKENS_TO_MERGE);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,219 @@
|
||||
package com.jetbrains.rest.lexer;
|
||||
|
||||
import com.intellij.lexer.FlexLexer;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.jetbrains.rest.RestTokenTypes;
|
||||
|
||||
/* Auto generated File */
|
||||
%%
|
||||
|
||||
%class _RestFlexLexer
|
||||
%implements FlexLexer, RestTokenTypes
|
||||
%unicode
|
||||
%public
|
||||
%ignorecase
|
||||
%function advance
|
||||
%type IElementType
|
||||
|
||||
|
||||
%eof{ return;
|
||||
%eof}
|
||||
|
||||
CRLF= \n|\r|\r\n
|
||||
SPACE=[\ \t]
|
||||
|
||||
ADORNMENT_SYMBOL="="|"-"|"`"|":"|"."|"'"|\"|"~"|"^"|"_"|"*"|"+"|"#"|">"
|
||||
ADORNMENT=("="{4, 80}|"-"{4, 80}|"`"{4, 80}|":"{4, 80}|"."{4, 80}|"'"{4, 80}|\"{4, 80}|"~"{4, 80}|"^"{4, 80}|"_"{4, 80}|"*"{4, 80}|"+"{4, 80}|"#"{4, 80}){CRLF}
|
||||
SEPARATOR=[\n .:,()\{\}\[\]\-]
|
||||
USUAL_TYPES="attention"|"caution"|"danger"|"error"|"hint"|"important"|"note"|"tip"|"warning"|"admonition"|"image"|"figure"|"topic"|"sidebar"|"parsed-literal"|"rubric"|"epigraph"|"highlights"|"pull-quote"|"compound"|"container"|"table"|"csv-table"|"list-table"|"contents"|"sectnum"|"section-autonumbering"|"header"|"footer"|"target-notes"|"footnotes"|"citations"|"meta"|"replace"|"unicode"|"date"|"include"|"raw"|"class"|"role"|"default-role"|"title"|"restructuredtext-test-directive"
|
||||
HIGHLIGHT_TYPES= "highlight" | "sourcecode" | "code-block"
|
||||
ANY_CHAR = [^\t`\ \n]
|
||||
NOT_BACKQUOTE = [^`]
|
||||
ANY= .|\n
|
||||
|
||||
%state IN_EXPLISIT_MARKUP
|
||||
%state IN_COMMENT
|
||||
%state IN_TITLE_TEXT
|
||||
%state IN_BODY
|
||||
%state IN_INLINE
|
||||
%state HYPERLINK_TEXT
|
||||
%state INDENTED
|
||||
%state PRE_INDENTED
|
||||
%state QUOTED
|
||||
%state PRE_QUOTED
|
||||
%state IN_LINE
|
||||
%state IN_HIGHLIGHT
|
||||
%state IN_VALUE
|
||||
%state IN_FOOTNOTE
|
||||
%state IN_LINEBEGIN
|
||||
%state INIT
|
||||
|
||||
%{
|
||||
int myState = 0; //python=1;django=2;initial=0;
|
||||
int myIndent = 0;
|
||||
private IElementType chooseType () {if (myState == 2)
|
||||
return DJANGO_LINE;
|
||||
else if (myState == 3)
|
||||
return JAVASCRIPT_LINE;
|
||||
else if (myState == 1)
|
||||
return PYTHON_LINE;
|
||||
else
|
||||
return INLINE_LINE;
|
||||
}
|
||||
%}
|
||||
|
||||
%%
|
||||
<YYINITIAL> {
|
||||
":"[^:\n\r ]([^:\n\r] | "\\:")*[^:\n\r ]":"[ `\n] { yypushback(1); return FIELD;}
|
||||
. { yypushback(1); yybegin(INIT); }
|
||||
}
|
||||
|
||||
<INIT> {
|
||||
//TITLES
|
||||
^{ADORNMENT}?.*{CRLF}{ADORNMENT} { return TITLE;}
|
||||
{CRLF}{2,5}{ADORNMENT}{CRLF}+ { return TITLE;}
|
||||
|
||||
//EXPLICIT MARKUP
|
||||
".."" "+ { yybegin(IN_EXPLISIT_MARKUP); return EXPLISIT_MARKUP_START;}
|
||||
"::"{CRLF}{CRLF} { yybegin(IN_INLINE);return LITERAL_BLOCK_START;}
|
||||
|
||||
// ESCAPING
|
||||
"\\" { yybegin(IN_LINE); return SPEC_SYMBOL;}
|
||||
|
||||
// IMPLICIT MARKUP
|
||||
|
||||
"``"[^`\n\r ][^`\n\r]*[^`\n\r ]"``" { return FIXED;}
|
||||
"**"[^*\n\r ][^*\n\r]*[^*\n\r ]"**" { return BOLD;}
|
||||
"*"[^*\n\r ][^*\n\r]*[^*\n\r ]"*" { return ITALIC;}
|
||||
"|"[^*|\n\r ][^*|\n\r]*[^*|\n\r ]"|" { return SUBSTITUTION;}
|
||||
|
||||
"http://"[^\n\r ]+ {return DIRECT_HYPERLINK;}
|
||||
|
||||
"`"[^`\n\r ][^`\n\r]*[^`\n\r ]"`" { return INTERPRETED;}
|
||||
"`"{NOT_BACKQUOTE}+"`_""_"?{SEPARATOR} {yypushback(1); return REFERENCE_NAME;}
|
||||
[0-9A-Za-z][0-9A-Za-z\-:+_]*"_""_"?{SEPARATOR} {yypushback(1); return REFERENCE_NAME;}
|
||||
//"["([0-9]* | #?[0-9A-Za-z]* | "*")"]_"{SEPARATOR} {yypushback(1); return REFERENCE_NAME;}
|
||||
|
||||
":"[^:\n\r ]([^:\n\r] | "\\:")*[^:\n\r ]":"[`] { yypushback(1); yybegin(INIT); return FIELD;}
|
||||
{CRLF} { yybegin(IN_LINEBEGIN); return WHITESPACE;}
|
||||
. { yypushback(1); yybegin(IN_LINE); }
|
||||
{SPACE}+ { yybegin(IN_LINEBEGIN); return WHITESPACE;}
|
||||
}
|
||||
|
||||
<IN_LINEBEGIN> {
|
||||
"["([0-9]* | #?[0-9A-Za-z]* | "*")"]_"{SEPARATOR} { yypushback(1); yybegin(INIT); return REFERENCE_NAME;}
|
||||
{SPACE} { return LINE;}
|
||||
{CRLF} { return WHITESPACE;}
|
||||
"__" { yybegin(IN_VALUE); return ANONYMOUS_HYPERLINK;}
|
||||
":"[^:\n\r ]([^:\n\r] | "\\:")*[^:\n\r ]":"[ `\n] { yypushback(1); yybegin(INIT); return FIELD;}
|
||||
. { yypushback(1); yybegin(INIT);}
|
||||
}
|
||||
|
||||
<IN_FOOTNOTE> {
|
||||
"["([0-9]* | #?[0-9A-Za-z]* | "*")"]_"{SEPARATOR} { yypushback(1); yybegin(INIT); return REFERENCE_NAME;}
|
||||
{SPACE} { return LINE;}
|
||||
{CRLF} { return WHITESPACE;}
|
||||
. { yypushback(1); yybegin(INIT);}
|
||||
}
|
||||
|
||||
<IN_LINE> {
|
||||
{CRLF} { return WHITESPACE;}
|
||||
[^`*:\n\r\[ |({]* { yybegin(INIT); return LINE;}
|
||||
{SPACE} { yybegin(IN_FOOTNOTE); return LINE;}
|
||||
"(" | "[" | "{" { yybegin(IN_FOOTNOTE); return LINE;}
|
||||
"`" | "_" | ":" | "*" | "[" | "|" { yybegin(INIT); return LINE;}
|
||||
}
|
||||
|
||||
<IN_INLINE> {
|
||||
//Two posibilities -- quoted-block, indented block
|
||||
|
||||
{CRLF} { return WHITESPACE;}
|
||||
{SPACE}+ { yybegin(PRE_INDENTED); myIndent = yylength(); return chooseType();}
|
||||
{ADORNMENT_SYMBOL} { yybegin(PRE_QUOTED); return SPEC_SYMBOL;}
|
||||
|
||||
//{CRLF}{2}~{CRLF}{2} { yybegin(INIT); return LINE;}
|
||||
}
|
||||
|
||||
<PRE_QUOTED> {
|
||||
.* { return chooseType();}
|
||||
{CRLF} { yybegin(QUOTED); return chooseType();}
|
||||
}
|
||||
|
||||
<QUOTED> {
|
||||
{ADORNMENT_SYMBOL} { yybegin(PRE_QUOTED); return chooseType();}
|
||||
. { yypushback(1); myState = 0; yybegin(INIT);}
|
||||
}
|
||||
|
||||
<PRE_INDENTED> {
|
||||
.* { yybegin(INDENTED); return chooseType();}
|
||||
{CRLF} { return chooseType();}
|
||||
}
|
||||
|
||||
<INDENTED> {
|
||||
{SPACE}+ { if (yylength() >= myIndent) {
|
||||
yybegin(PRE_INDENTED); return chooseType();}
|
||||
else {
|
||||
myIndent = 0; yypushback(yylength()); yybegin(INIT);
|
||||
} }
|
||||
{SPACE}*{CRLF}+ { return chooseType();}
|
||||
{CRLF}+ { return chooseType();}
|
||||
. { yypushback(1); myIndent = 0; myState = 0; yybegin(INIT);}
|
||||
}
|
||||
|
||||
<IN_EXPLISIT_MARKUP> {
|
||||
"["([0-9]* | #[0-9A-Za-z]* | "*")"]" { yybegin(INIT); return FOOTNOTE;}
|
||||
"["[0-9A-Za-z]*"]" { yybegin(INIT); return CITATION;}
|
||||
|
||||
"__" { yybegin(IN_VALUE); return ANONYMOUS_HYPERLINK;}
|
||||
"_"[^_\n\r:][^\n\r:]+":" { yybegin(INIT); return HYPERLINK;}
|
||||
|
||||
{USUAL_TYPES}"::" { yybegin(IN_VALUE); return DIRECTIVE;}
|
||||
{HIGHLIGHT_TYPES}"::" { yybegin(IN_HIGHLIGHT); return CUSTOM_DIRECTIVE;}
|
||||
[0-9A-Za-z\-:]*"::" { yybegin(IN_VALUE); return CUSTOM_DIRECTIVE;}
|
||||
"|"[0-9A-Za-z]*"|" { return SUBSTITUTION;}
|
||||
[0-9A-Za-z_\[|.]* { yybegin(IN_COMMENT); return COMMENT;}
|
||||
{CRLF}{2} { yybegin(INIT); return COMMENT;}
|
||||
{SPACE}*{CRLF}+ { return WHITESPACE; }
|
||||
{SPACE}+ { return WHITESPACE;}
|
||||
}
|
||||
|
||||
<IN_VALUE> {
|
||||
[^\n\r]+ { return LINE;}
|
||||
{CRLF} { yybegin(INIT); return WHITESPACE; }
|
||||
}
|
||||
|
||||
<IN_HIGHLIGHT> {
|
||||
{SPACE}+ { return WHITESPACE;}
|
||||
{CRLF} { yybegin(INIT); return WHITESPACE; }
|
||||
[A-Za-z+]+{CRLF}{CRLF} { String value = yytext().toString().trim();
|
||||
if ("python".equalsIgnoreCase(value)) {
|
||||
myState = 1;
|
||||
yybegin(IN_INLINE);
|
||||
}
|
||||
else if ("django".equalsIgnoreCase(value) ||
|
||||
"html+django".equalsIgnoreCase(value)) {
|
||||
myState = 2;
|
||||
yybegin(IN_INLINE);
|
||||
}
|
||||
else if ("javascript".equalsIgnoreCase(value)) {
|
||||
myState = 3;
|
||||
yybegin(IN_INLINE);
|
||||
}
|
||||
else {
|
||||
yybegin(INIT);
|
||||
}
|
||||
return LINE;
|
||||
}
|
||||
. { yypushback(1); yybegin(INIT);}
|
||||
}
|
||||
|
||||
<IN_COMMENT> {
|
||||
{CRLF}".. " { yybegin(IN_EXPLISIT_MARKUP); return EXPLISIT_MARKUP_START;}
|
||||
{SPACE}+ { return WHITESPACE;}
|
||||
{CRLF}{2} { yybegin(INIT); return COMMENT;}
|
||||
. { return COMMENT;}
|
||||
{CRLF} { return WHITESPACE;}
|
||||
}
|
||||
|
||||
{CRLF} { yybegin(INIT); return WHITESPACE; }
|
||||
. { yybegin(INIT); return ERROR;}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.rest.parsing;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.PsiParser;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.jetbrains.rest.RestElementTypes;
|
||||
import com.jetbrains.rest.RestTokenTypes;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestParser implements PsiParser {
|
||||
@NotNull
|
||||
public ASTNode parse(IElementType root, PsiBuilder builder) {
|
||||
final PsiBuilder.Marker rootMarker = builder.mark();
|
||||
while (!builder.eof()) {
|
||||
IElementType type = builder.getTokenType();
|
||||
if (type == RestTokenTypes.EXPLISIT_MARKUP_START) {
|
||||
builder.advanceLexer();
|
||||
parseMarkup(builder);
|
||||
}
|
||||
else if (type == RestTokenTypes.REFERENCE_NAME || type == RestTokenTypes.SUBSTITUTION) {
|
||||
PsiBuilder.Marker marker = builder.mark();
|
||||
builder.advanceLexer();
|
||||
marker.done(RestTokenTypes.REFERENCE_NAME);
|
||||
}
|
||||
else if (type == RestTokenTypes.TITLE) {
|
||||
PsiBuilder.Marker marker = builder.mark();
|
||||
builder.advanceLexer();
|
||||
marker.done(RestTokenTypes.TITLE);
|
||||
}
|
||||
else if (type == RestTokenTypes.FIELD) {
|
||||
PsiBuilder.Marker marker = builder.mark();
|
||||
builder.advanceLexer();
|
||||
marker.done(RestTokenTypes.FIELD);
|
||||
}
|
||||
else if (type == RestTokenTypes.INLINE_LINE) {
|
||||
PsiBuilder.Marker marker = builder.mark();
|
||||
builder.advanceLexer();
|
||||
type = builder.getTokenType();
|
||||
while (type == RestTokenTypes.INLINE_LINE) {
|
||||
builder.advanceLexer();
|
||||
type = builder.getTokenType();
|
||||
}
|
||||
marker.done(RestTokenTypes.INLINE_LINE);
|
||||
}
|
||||
else if (type == RestTokenTypes.ANONYMOUS_HYPERLINK) {
|
||||
PsiBuilder.Marker marker = builder.mark();
|
||||
builder.advanceLexer();
|
||||
marker.done(RestElementTypes.REFERENCE_TARGET);
|
||||
}
|
||||
else
|
||||
builder.advanceLexer();
|
||||
}
|
||||
rootMarker.done(root);
|
||||
return builder.getTreeBuilt();
|
||||
}
|
||||
|
||||
private void parseMarkup(PsiBuilder builder) {
|
||||
PsiBuilder.Marker marker = builder.mark();
|
||||
IElementType type = builder.getTokenType();
|
||||
if (type == RestTokenTypes.SUBSTITUTION) {
|
||||
builder.advanceLexer();
|
||||
marker.done(RestElementTypes.REFERENCE_TARGET);
|
||||
builder.advanceLexer();
|
||||
marker = builder.mark();
|
||||
type = builder.getTokenType();
|
||||
}
|
||||
if (type == RestTokenTypes.DIRECTIVE) {
|
||||
gotoNextWhiteSpaces(builder);
|
||||
if (builder.getTokenType() != RestTokenTypes.WHITESPACE) {
|
||||
builder.advanceLexer();
|
||||
marker.done(RestElementTypes.DIRECTIVE_BLOCK);
|
||||
return;
|
||||
}
|
||||
skipBlankLines(builder);
|
||||
if (builder.getTokenType() != RestTokenTypes.WHITESPACE || "\n".equals(builder.getTokenText())) {
|
||||
marker.done(RestElementTypes.DIRECTIVE_BLOCK);
|
||||
return;
|
||||
}
|
||||
String white = builder.getTokenText();
|
||||
parseDirective(builder, white, marker);
|
||||
}
|
||||
else if (type == RestTokenTypes.FOOTNOTE || type == RestTokenTypes.CITATION ||
|
||||
type == RestTokenTypes.HYPERLINK || type == RestTokenTypes.ANONYMOUS_HYPERLINK) {
|
||||
builder.advanceLexer();
|
||||
marker.done(RestElementTypes.REFERENCE_TARGET);
|
||||
}
|
||||
else {
|
||||
builder.advanceLexer();
|
||||
marker.drop();
|
||||
}
|
||||
}
|
||||
|
||||
private void gotoNextWhiteSpaces(PsiBuilder builder) {
|
||||
while(!"\n".equals(builder.getTokenText()) && !(builder.getTokenType() == RestTokenTypes.TITLE) && !builder.eof() && (builder.getTokenType() != null)) {
|
||||
builder.advanceLexer();
|
||||
}
|
||||
}
|
||||
|
||||
private void skipBlankLines(PsiBuilder builder) {
|
||||
while("\n".equals(builder.getTokenText()) && !builder.eof() && (builder.getTokenType() != null)) {
|
||||
builder.advanceLexer();
|
||||
}
|
||||
}
|
||||
|
||||
private void parseDirective(PsiBuilder builder, String white, PsiBuilder.Marker marker) {
|
||||
gotoNextWhiteSpaces(builder);
|
||||
if (builder.getTokenType() != RestTokenTypes.WHITESPACE) {
|
||||
builder.advanceLexer();
|
||||
marker.done(RestElementTypes.DIRECTIVE_BLOCK);
|
||||
return;
|
||||
}
|
||||
skipBlankLines(builder);
|
||||
if (white.equals(builder.getTokenText())) {
|
||||
builder.advanceLexer();
|
||||
parseDirective(builder, white, marker);
|
||||
}
|
||||
else {
|
||||
marker.done(RestElementTypes.DIRECTIVE_BLOCK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.jetbrains.rest.parsing;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.ParserDefinition;
|
||||
import com.intellij.lang.PsiParser;
|
||||
import com.intellij.lexer.Lexer;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.IFileElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.jetbrains.rest.RestFile;
|
||||
import com.jetbrains.rest.RestLanguage;
|
||||
import com.jetbrains.rest.RestTokenTypes;
|
||||
import com.jetbrains.rest.lexer.RestFlexLexer;
|
||||
import com.jetbrains.rest.psi.RestASTFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestParserDefinition implements ParserDefinition, RestTokenTypes {
|
||||
private static final IFileElementType FILE_ELEMENT_TYPE = new IFileElementType(RestLanguage.INSTANCE);
|
||||
|
||||
private final RestASTFactory astFactory = new RestASTFactory();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Lexer createLexer(Project project) {
|
||||
return new RestFlexLexer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiParser createParser(Project project) {
|
||||
return new RestParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFileElementType getFileNodeType() {
|
||||
return FILE_ELEMENT_TYPE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TokenSet getWhitespaceTokens() {
|
||||
return TokenSet.EMPTY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TokenSet getCommentTokens() {
|
||||
return TokenSet.EMPTY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TokenSet getStringLiteralElements() {
|
||||
return TokenSet.EMPTY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement createElement(ASTNode node) {
|
||||
return astFactory.create(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiFile createFile(FileViewProvider viewProvider) {
|
||||
return new RestFile(viewProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
|
||||
return SpaceRequirements.MAY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.jetbrains.rest.psi;
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.jetbrains.rest.RestElementTypes;
|
||||
import com.jetbrains.rest.RestTokenTypes;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestASTFactory implements RestTokenTypes, RestElementTypes {
|
||||
|
||||
public PsiElement create(ASTNode node) {
|
||||
IElementType type = node.getElementType();
|
||||
|
||||
if (type == DIRECTIVE_BLOCK) {
|
||||
return new RestDirectiveBlock(node);
|
||||
}
|
||||
if (type == REFERENCE_NAME) {
|
||||
return new RestReference(node);
|
||||
}
|
||||
if (type == REFERENCE_TARGET) {
|
||||
return new RestReferenceTarget(node);
|
||||
}
|
||||
if (type == TITLE) {
|
||||
return new RestTitle(node);
|
||||
}
|
||||
if (type == FIELD) {
|
||||
return new RestRole(node);
|
||||
}
|
||||
if (type == INLINE_LINE) {
|
||||
return new RestInlineBlock(node);
|
||||
}
|
||||
return new ASTWrapperPsiElement(node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.jetbrains.rest.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestDirectiveBlock extends RestElement {
|
||||
public RestDirectiveBlock(@NotNull final ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestDirective:" + getNode().getElementType().toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDirectiveName() {
|
||||
PsiElement child = this.getFirstChild();
|
||||
if (child != null)
|
||||
return child.getText();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.jetbrains.rest.psi;
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.NavigatablePsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.jetbrains.rest.validation.RestElementVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class RestElement extends ASTWrapperPsiElement implements NavigatablePsiElement {
|
||||
|
||||
public RestElement(@NotNull final ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestElement:" + getNode().getElementType().toString();
|
||||
}
|
||||
|
||||
protected void acceptRestVisitor(RestElementVisitor visitor) {
|
||||
visitor.visitRestElement(this);
|
||||
}
|
||||
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof RestElementVisitor) {
|
||||
acceptRestVisitor(((RestElementVisitor)visitor));
|
||||
}
|
||||
else {
|
||||
super.accept(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.jetbrains.rest.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.jetbrains.rest.validation.RestElementVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestInlineBlock extends RestElement {
|
||||
public RestInlineBlock(@NotNull final ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestInlineBlock";
|
||||
}
|
||||
public boolean isValid() {
|
||||
return getText().matches("(.|\n)*\n *\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void acceptRestVisitor(RestElementVisitor visitor) {
|
||||
visitor.visitInlineBlock(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.jetbrains.rest.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.rest.validation.RestElementVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestReference extends RestElement {
|
||||
public RestReference(@NotNull final ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestReference:" + getNode().getElementType().toString();
|
||||
}
|
||||
|
||||
public String getReferenceText() {
|
||||
String text = getNode().getText();
|
||||
text = StringUtil.replace(text, "\n", " ");
|
||||
text = text.replaceAll("\\\\([^\\\\]+)", "$1");
|
||||
if (text.startsWith("`") && text.endsWith("`_"))
|
||||
return text.substring(1, text.length()-2);
|
||||
if (text.endsWith("__"))
|
||||
return "__";
|
||||
if (text.startsWith("|") && text.endsWith("|"))
|
||||
return text;
|
||||
return text.substring(0, text.length()-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void acceptRestVisitor(RestElementVisitor visitor) {
|
||||
visitor.visitReference(this);
|
||||
}
|
||||
|
||||
public RestElement resolve() {
|
||||
String name = getReferenceText();
|
||||
PsiFile file = getContainingFile();
|
||||
RestReferenceTarget[] elements = PsiTreeUtil.getChildrenOfType(file, RestReferenceTarget.class);
|
||||
if (elements != null) {
|
||||
if (name.equals("__") || name.equals("[*]") || name.equals("[#]"))
|
||||
return findAnonimousTarget(file, elements);
|
||||
|
||||
for (RestReferenceTarget element : elements) {
|
||||
if (element.getReferenceName().equalsIgnoreCase(name) || element.getReferenceName(false).equalsIgnoreCase(name)) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
//TODO[catherine]: targets are not better than titles for resolving
|
||||
// they should have the same ancestor
|
||||
RestTitle[] titles = PsiTreeUtil.getChildrenOfType(file, RestTitle.class);
|
||||
if (titles != null) {
|
||||
for (RestTitle element : titles) {
|
||||
if (name.equalsIgnoreCase(element.getName())) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private RestReferenceTarget findAnonimousTarget(PsiFile file, RestReferenceTarget[] targets) {
|
||||
String name = getReferenceText();
|
||||
RestReference[] references = PsiTreeUtil.getChildrenOfType(file, RestReference.class);
|
||||
int refIndex = 1;
|
||||
int i = 0;
|
||||
while (!references[i].equals(this)) {
|
||||
if (references[i].getReferenceText().equals(name))
|
||||
++refIndex;
|
||||
++i;
|
||||
}
|
||||
|
||||
int targetIndex = 0;
|
||||
for (int j = 0; j != targets.length; ++j) {
|
||||
if (targets[j].getReferenceName().equals(name))
|
||||
++targetIndex;
|
||||
if (targetIndex == refIndex)
|
||||
return targets[j];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.jetbrains.rest.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.rest.validation.RestElementVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestReferenceTarget extends RestElement {
|
||||
public RestReferenceTarget(@NotNull final ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestReferenceTarget:" + getNode().getElementType().toString();
|
||||
}
|
||||
|
||||
public String getReferenceName(boolean quoted) {
|
||||
String text = getNode().getText();
|
||||
if ("__".equals(text))
|
||||
return text;
|
||||
|
||||
text = text.replaceAll("\\\\([^\\\\]+)", "$1");
|
||||
if (text.startsWith("_`") && !quoted)
|
||||
return text.substring(2, text.length()-2);
|
||||
|
||||
if (text.startsWith("_"))
|
||||
return text.substring(1, text.length()-1);
|
||||
|
||||
if (text.startsWith("[#") && !quoted && text.length()>3)
|
||||
return text.substring(2, text.length()-1);
|
||||
|
||||
if (text.startsWith("[") && !quoted)
|
||||
return text.substring(1, text.length()-1);
|
||||
|
||||
return text;
|
||||
}
|
||||
public String getReferenceName() {
|
||||
return getReferenceName(true);
|
||||
}
|
||||
|
||||
public boolean hasReference() {
|
||||
String text = getNode().getText();
|
||||
PsiFile file = getContainingFile();
|
||||
if ("__".equals(text)) {
|
||||
RestReference[] references = PsiTreeUtil.getChildrenOfType(file, RestReference.class);
|
||||
if (references != null) {
|
||||
for (RestReference ref : references) {
|
||||
if (ref.resolve() == this)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void acceptRestVisitor(RestElementVisitor visitor) {
|
||||
visitor.visitReferenceTarget(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.jetbrains.rest.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.jetbrains.rest.validation.RestElementVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestRole extends RestElement {
|
||||
public RestRole(@NotNull final ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestRole:" + getNode().getElementType().toString();
|
||||
}
|
||||
|
||||
public String getRoleName() {
|
||||
String text = getNode().getText();
|
||||
return text.substring(1, text.length()-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void acceptRestVisitor(RestElementVisitor visitor) {
|
||||
visitor.visitRole(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.jetbrains.rest.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.CharacterIterator;
|
||||
import java.text.StringCharacterIterator;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestTitle extends RestElement {
|
||||
public RestTitle(@NotNull final ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestTitle:" + getNode().getElementType().toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getName() {
|
||||
final String text = getNode().getText();
|
||||
if (text.length() == 0) return null;
|
||||
final char adorn = text.charAt(text.length()-2);
|
||||
final CharacterIterator it = new StringCharacterIterator(text);
|
||||
int finish = 0;
|
||||
for (char ch = it.last(); ch != CharacterIterator.DONE; ch = it.previous()) {
|
||||
if (finish == 0)
|
||||
finish++;
|
||||
else if (ch != adorn) {
|
||||
finish = it.getIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
int start = 0;
|
||||
if (text.charAt(0) == adorn) {
|
||||
for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) {
|
||||
if (ch != adorn) {
|
||||
start = it.getIndex() + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (finish <= 0 || start < 0)
|
||||
return null;
|
||||
return text.substring(start, finish).trim();
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package com.jetbrains.python.spellchecker;
|
||||
package com.jetbrains.rest.spellchecker;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.jetbrains.rest.structureView;
|
||||
|
||||
import com.intellij.ide.structureView.StructureViewTreeElement;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.psi.NavigatablePsiElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.jetbrains.rest.psi.RestElement;
|
||||
import com.jetbrains.rest.psi.RestTitle;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Handles nodes in ReST Structure View.
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestStructureViewElement implements StructureViewTreeElement {
|
||||
|
||||
private NavigatablePsiElement myElement;
|
||||
|
||||
public RestStructureViewElement(NavigatablePsiElement element) {
|
||||
myElement = element;
|
||||
}
|
||||
|
||||
public NavigatablePsiElement getValue() {
|
||||
return myElement;
|
||||
}
|
||||
|
||||
public void navigate(boolean requestFocus) {
|
||||
myElement.navigate(requestFocus);
|
||||
}
|
||||
|
||||
public boolean canNavigate() {
|
||||
return myElement.canNavigate();
|
||||
}
|
||||
|
||||
public boolean canNavigateToSource() {
|
||||
return myElement.canNavigateToSource();
|
||||
}
|
||||
|
||||
public StructureViewTreeElement[] getChildren() {
|
||||
final Set<RestElement> childrenElements = new LinkedHashSet<RestElement>();
|
||||
myElement.acceptChildren(new PsiElementVisitor() {
|
||||
@Override
|
||||
public void visitElement(PsiElement element) {
|
||||
if (element instanceof RestTitle && ((RestTitle)element).getName() != null)
|
||||
childrenElements.add((RestElement)element);
|
||||
else
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
});
|
||||
StructureViewTreeElement[] children = new StructureViewTreeElement[childrenElements.size()];
|
||||
int i = 0;
|
||||
for (RestElement element : childrenElements) {
|
||||
children[i] = new RestStructureViewElement(element);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
public ItemPresentation getPresentation() {
|
||||
return new ItemPresentation() {
|
||||
public String getPresentableText() {
|
||||
return myElement.getName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getLocationString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Icon getIcon(boolean open) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.jetbrains.rest.structureView;
|
||||
|
||||
import com.intellij.ide.structureView.StructureViewBuilder;
|
||||
import com.intellij.ide.structureView.StructureViewModel;
|
||||
import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
|
||||
import com.intellij.lang.PsiStructureViewFactory;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestStructureViewFactory implements PsiStructureViewFactory {
|
||||
public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) {
|
||||
return new TreeBasedStructureViewBuilder() {
|
||||
|
||||
@NotNull
|
||||
public StructureViewModel createStructureViewModel() {
|
||||
return new RestStructureViewModel(psiFile);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.jetbrains.rest.structureView;
|
||||
|
||||
import com.intellij.ide.structureView.StructureViewModel;
|
||||
import com.intellij.ide.structureView.StructureViewModelBase;
|
||||
import com.intellij.ide.structureView.StructureViewTreeElement;
|
||||
import com.intellij.ide.util.treeView.smartTree.Sorter;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.rest.RestFile;
|
||||
import com.jetbrains.rest.psi.RestTitle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestStructureViewModel extends StructureViewModelBase implements StructureViewModel.ElementInfoProvider, StructureViewModel.ExpandInfoProvider {
|
||||
public RestStructureViewModel(@NotNull PsiFile psiFile) {
|
||||
super(psiFile, new RestStructureViewElement(psiFile));
|
||||
withSorters(Sorter.ALPHA_SORTER);
|
||||
withSuitableClasses(RestTitle.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlwaysShowsPlus(StructureViewTreeElement element) {
|
||||
final Object value = element.getValue();
|
||||
return value instanceof RestFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlwaysLeaf(StructureViewTreeElement element) {
|
||||
return element.getValue() instanceof RestTitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoExpand(StructureViewTreeElement element) {
|
||||
return element.getValue() instanceof PsiFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSmartExpand() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.jetbrains.rest.validation;
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.rest.RestFileType;
|
||||
import com.jetbrains.rest.RestLanguage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestAnnotatingVisitor implements Annotator {
|
||||
private static final Logger LOGGER = Logger.getInstance(RestAnnotatingVisitor.class.getName());
|
||||
private final List<RestAnnotator> myAnnotators = new ArrayList<RestAnnotator>();
|
||||
|
||||
public RestAnnotatingVisitor() {
|
||||
for (Class<? extends RestAnnotator> cls : ((RestLanguage)RestFileType.INSTANCE.getLanguage()).getAnnotators()) {
|
||||
RestAnnotator annotator;
|
||||
try {
|
||||
annotator = cls.newInstance();
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
LOGGER.error(e);
|
||||
continue;
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
LOGGER.error(e);
|
||||
continue;
|
||||
}
|
||||
myAnnotators.add(annotator);
|
||||
}
|
||||
}
|
||||
|
||||
public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) {
|
||||
for(RestAnnotator annotator: myAnnotators) {
|
||||
annotator.annotateElement(psiElement, holder);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.jetbrains.rest.validation;
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.psi.PsiElement;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
*/
|
||||
public abstract class RestAnnotator extends RestElementVisitor {
|
||||
private AnnotationHolder _holder;
|
||||
|
||||
public AnnotationHolder getHolder() {
|
||||
return _holder;
|
||||
}
|
||||
|
||||
public void setHolder(AnnotationHolder holder) {
|
||||
_holder = holder;
|
||||
}
|
||||
|
||||
public synchronized void annotateElement(final PsiElement psiElement, final AnnotationHolder holder) {
|
||||
setHolder(holder);
|
||||
try {
|
||||
psiElement.accept(this);
|
||||
}
|
||||
finally {
|
||||
setHolder(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void markError(PsiElement element, String message) {
|
||||
getHolder().createErrorAnnotation(element, message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.jetbrains.rest.validation;
|
||||
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.jetbrains.rest.psi.*;
|
||||
|
||||
/**
|
||||
* User : catherine
|
||||
* Visitor for rest-specific nodes.
|
||||
*/
|
||||
public class RestElementVisitor extends PsiElementVisitor {
|
||||
public void visitRestElement(final RestElement node) {
|
||||
visitElement(node);
|
||||
}
|
||||
|
||||
public void visitReference(final RestReference node) {
|
||||
visitRestElement(node);
|
||||
}
|
||||
|
||||
public void visitReferenceTarget(final RestReferenceTarget node) {
|
||||
visitRestElement(node);
|
||||
}
|
||||
|
||||
public void visitRole(final RestRole node) {
|
||||
visitRestElement(node);
|
||||
}
|
||||
|
||||
public void visitTitle(final RestTitle node) {
|
||||
visitRestElement(node);
|
||||
}
|
||||
|
||||
public void visitDirectiveBlock(final RestDirectiveBlock node) {
|
||||
visitRestElement(node);
|
||||
}
|
||||
|
||||
public void visitInlineBlock(final RestInlineBlock node) {
|
||||
visitRestElement(node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.jetbrains.rest.validation;
|
||||
|
||||
import com.jetbrains.rest.RestBundle;
|
||||
import com.jetbrains.rest.psi.RestReference;
|
||||
|
||||
/**
|
||||
* Looks for not defined hyperlinks
|
||||
*
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestHyperlinksAnnotator extends RestAnnotator {
|
||||
|
||||
@Override
|
||||
public void visitReference(final RestReference node) {
|
||||
if (node.getText().matches("`[^`]*<[^`]+>`_(_)?"))
|
||||
return;
|
||||
|
||||
if (node.resolve() == null)
|
||||
getHolder().createWarningAnnotation(node, RestBundle.message("ANN.unknown.target", node.getReferenceText()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.jetbrains.rest.validation;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.rest.RestBundle;
|
||||
import com.jetbrains.rest.psi.RestInlineBlock;
|
||||
|
||||
/**
|
||||
* Looks for invalid inline block
|
||||
*
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestInlineBlockAnnotator extends RestAnnotator {
|
||||
|
||||
@Override
|
||||
public void visitInlineBlock(final RestInlineBlock node) {
|
||||
if (!node.isValid()) {
|
||||
PsiElement el = node.getLastChild();
|
||||
if (el != null) {
|
||||
if (el.getText().equals("\n") && el.getPrevSibling() != null)
|
||||
el = el.getPrevSibling();
|
||||
markError(el, RestBundle.message("ANN.inline.block"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.jetbrains.rest.validation;
|
||||
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.rest.RestBundle;
|
||||
import com.jetbrains.rest.RestFile;
|
||||
import com.jetbrains.rest.psi.RestReferenceTarget;
|
||||
|
||||
/**
|
||||
* Looks for double defined hyperlinks
|
||||
*
|
||||
* User : catherine
|
||||
*/
|
||||
public class RestReferenceTargetAnnotator extends RestAnnotator {
|
||||
|
||||
@Override
|
||||
public void visitReferenceTarget(final RestReferenceTarget node) {
|
||||
RestFile file = (RestFile)node.getContainingFile();
|
||||
RestReferenceTarget[] targets = PsiTreeUtil.getChildrenOfType(file, RestReferenceTarget.class);
|
||||
String quotedName = node.getReferenceName();
|
||||
String name = node.getReferenceName(false);
|
||||
if (targets != null) {
|
||||
if ("__".equals(name) && !node.hasReference()) {
|
||||
getHolder().createWarningAnnotation(node, RestBundle.message("ANN.unusable.anonymous.target"));
|
||||
}
|
||||
for (RestReferenceTarget element : targets) {
|
||||
if ((element.getReferenceName().equalsIgnoreCase(name) || element.getReferenceName(false).equalsIgnoreCase(name) ||
|
||||
element.getReferenceName().equalsIgnoreCase(quotedName) || element.getReferenceName(false).equalsIgnoreCase(quotedName)) &&
|
||||
!element.equals(node) && ! "__".equals(name) && !"[#]".equals(quotedName) && !"[*]".equals(quotedName)) {
|
||||
getHolder().createWarningAnnotation(element, RestBundle.message("ANN.duplicate.target", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -652,29 +652,14 @@
|
||||
|
||||
<!-- ReST files -->
|
||||
|
||||
<fileTypeFactory implementation="com.jetbrains.rest.RestFileTypeFactory"/>
|
||||
<lang.syntaxHighlighterFactory key="ReST"
|
||||
implementationClass="com.jetbrains.rest.RestHighlighterFactory"/>
|
||||
<lang.parserDefinition language="ReST" implementationClass="com.jetbrains.rest.parsing.RestParserDefinition"/>
|
||||
<colorSettingsPage implementation="com.jetbrains.rest.RestColorsPage"/>
|
||||
|
||||
<projectService serviceInterface="com.jetbrains.rest.ReSTService"
|
||||
serviceImplementation="com.jetbrains.rest.ReSTService"/>
|
||||
<completion.contributor language="ReST" implementationClass="com.jetbrains.rest.completion.DirectiveCompletionContributor"/>
|
||||
<completion.contributor language="ReST" implementationClass="com.jetbrains.rest.completion.OptionCompletionContributor"/>
|
||||
<completion.contributor language="ReST" implementationClass="com.jetbrains.rest.completion.ReferenceCompletionContributor"/>
|
||||
<gotoDeclarationHandler implementation="com.jetbrains.rest.RestGotoProvider" order="FIRST"/>
|
||||
<lang.fileViewProviderFactory language="ReST"
|
||||
implementationClass="com.jetbrains.rest.RestFileProviderFactory"/>
|
||||
<lang.psiStructureViewFactory language="ReST"
|
||||
implementationClass="com.jetbrains.rest.structureView.RestStructureViewFactory"/>
|
||||
<annotator language="ReST" implementationClass="com.jetbrains.rest.validation.RestAnnotatingVisitor"/>
|
||||
<editorHighlighterProvider filetype="ReST" implementationClass="com.jetbrains.rest.RestEditorHighlighterProvider"/>
|
||||
|
||||
<localInspection language="ReST" shortName="RestRoleInspection" bundle="com.jetbrains.rest.RestBundle" key="INSP.role.not.defined"
|
||||
groupKey="INSP.GROUP.rest" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.jetbrains.rest.inspections.RestRoleInspection"/>
|
||||
|
||||
<lang.substitutor language="TEXT" implementationClass="com.jetbrains.rest.RestLanguageSubstitutor"/>
|
||||
<configurationType implementation="com.jetbrains.rest.run.RestRunConfigurationType"/>
|
||||
<configurationProducer implementation="com.jetbrains.rest.run.docutils.DocutilsConfigurationProducer"/>
|
||||
<configurationProducer implementation="com.jetbrains.rest.run.sphinx.SphinxConfigurationProducer"/>
|
||||
@@ -965,7 +950,6 @@
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij.spellchecker">
|
||||
<support language="Python" implementationClass="com.jetbrains.python.spellchecker.PythonSpellcheckerStrategy"/>
|
||||
<support language="ReST" implementationClass="com.jetbrains.python.spellchecker.RestSpellcheckerStrategy"/>
|
||||
<bundledDictionaryProvider implementation="com.jetbrains.python.spellchecker.PythonBundledDictionaryProvider"/>
|
||||
</extensions>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user