├── .gitignore
├── LICENSE
├── META-INF
└── plugin.xml
├── README.md
├── intellibot.jar
├── resources
├── images
│ ├── robot_icon.png
│ └── robot_icon@2x.png
└── inspectionDescriptions
│ ├── RobotGherkinInspection.html
│ ├── RobotImportNotFound.html
│ ├── RobotImportNotUsed.html
│ ├── RobotKeywordDefinitionStartingWithGherkin.html
│ ├── RobotKeywordNotFound.html
│ ├── RobotNestedVariable.html
│ ├── RobotNestedVariableDefinition.html
│ └── RobotVariableNotFound.html
├── src
└── com
│ └── millennialmedia
│ └── intellibot
│ ├── RobotBundle.java
│ ├── RobotBundle.properties
│ ├── ide
│ ├── RobotCommenter.java
│ ├── RobotCompletionContributor.java
│ ├── RobotFoldingBuilder.java
│ ├── config
│ │ ├── RobotColorsPage.java
│ │ ├── RobotConfiguration.form
│ │ ├── RobotConfiguration.java
│ │ └── RobotOptionsProvider.java
│ ├── icons
│ │ └── RobotIcons.java
│ ├── inspections
│ │ ├── SimpleInspection.java
│ │ ├── SimpleInspectionVisitor.java
│ │ ├── SimpleRobotInspection.java
│ │ ├── cleanup
│ │ │ └── RobotImportNotUsed.java
│ │ ├── compilation
│ │ │ ├── RobotImportNotFound.java
│ │ │ ├── RobotKeywordNotFound.java
│ │ │ └── RobotVariableNotFound.java
│ │ ├── complexity
│ │ │ ├── RobotNestedVariable.java
│ │ │ └── RobotNestedVariableDefinition.java
│ │ └── readability
│ │ │ ├── RobotGherkinInspection.java
│ │ │ └── RobotKeywordDefinitionStartingWithGherkin.java
│ ├── search
│ │ └── RobotPythonReferenceSearch.java
│ ├── structure
│ │ ├── RobotStructureViewElement.java
│ │ ├── RobotStructureViewFactory.java
│ │ ├── RobotStructureViewModel.java
│ │ ├── RobotTypeFilter.java
│ │ ├── RobotTypeSorter.java
│ │ └── RobotViewElementType.java
│ └── usage
│ │ ├── RobotFindUsagesProvider.java
│ │ ├── RobotKeywordGroupingRuleProvider.java
│ │ └── RobotWordScanner.java
│ └── psi
│ ├── RecommendationWord.java
│ ├── RobotElementType.java
│ ├── RobotFeatureFileType.java
│ ├── RobotFileTypeHandler.java
│ ├── RobotHighlighter.java
│ ├── RobotKeywordProvider.java
│ ├── RobotKeywordTable.java
│ ├── RobotLanguage.java
│ ├── RobotLexer.java
│ ├── RobotParser.java
│ ├── RobotParserDefinition.java
│ ├── RobotPsiManager.java
│ ├── RobotSyntaxHighlightingFactory.java
│ ├── RobotTokenTypes.java
│ ├── dto
│ ├── ImportType.java
│ ├── KeywordDto.java
│ └── VariableDto.java
│ ├── element
│ ├── Argument.java
│ ├── ArgumentImpl.java
│ ├── BracketSetting.java
│ ├── BracketSettingImpl.java
│ ├── DefinedKeyword.java
│ ├── DefinedVariable.java
│ ├── Heading.java
│ ├── HeadingImpl.java
│ ├── Import.java
│ ├── ImportImpl.java
│ ├── KeywordDefinition.java
│ ├── KeywordDefinitionId.java
│ ├── KeywordDefinitionIdImpl.java
│ ├── KeywordDefinitionImpl.java
│ ├── KeywordFile.java
│ ├── KeywordInvokable.java
│ ├── KeywordInvokableImpl.java
│ ├── KeywordStatement.java
│ ├── KeywordStatementImpl.java
│ ├── RobotFile.java
│ ├── RobotFileImpl.java
│ ├── RobotPsiElementBase.java
│ ├── RobotStatement.java
│ ├── Setting.java
│ ├── SettingImpl.java
│ ├── Variable.java
│ ├── VariableDefinition.java
│ ├── VariableDefinitionId.java
│ ├── VariableDefinitionIdImpl.java
│ ├── VariableDefinitionImpl.java
│ └── VariableImpl.java
│ ├── manip
│ ├── ArgumentManipulator.java
│ ├── KeywordInvokableManipulator.java
│ └── VariableManipulator.java
│ ├── ref
│ ├── PythonResolver.java
│ ├── ResolverUtils.java
│ ├── RobotArgumentReference.java
│ ├── RobotFileManager.java
│ ├── RobotKeywordReference.java
│ ├── RobotPythonClass.java
│ ├── RobotPythonFile.java
│ ├── RobotPythonWrapper.java
│ └── RobotVariableReference.java
│ └── util
│ ├── PatternBuilder.java
│ ├── PatternUtil.java
│ ├── PerformanceCollector.java
│ ├── PerformanceEntity.java
│ ├── ReservedVariable.java
│ └── ReservedVariableScope.java
├── test
└── com
│ └── millennialmedia
│ └── intellibot
│ ├── ResourceLoader.java
│ ├── ide
│ ├── AbstractRobotIdeTest.java
│ ├── RobotFindUsagesTest.java
│ ├── RobotFoldingTest.java
│ └── RobotHighlightTest.java
│ └── psi
│ ├── RobotLexerTest.java
│ ├── RobotParserTest.java
│ ├── element
│ └── KeywordDefinitionTest.java
│ ├── ref
│ └── RobotFileManagerTest.java
│ └── util
│ ├── KeywordParserTest.java
│ ├── PatternUtilBuildPatternTest.java
│ └── PatternUtilGetPresentableTextTest.java
├── testData
├── ide
│ ├── folding
│ │ └── keywordFolding.robot
│ └── usages
│ │ ├── findInlineKeywordByDefinition.robot
│ │ ├── findInlineKeywordByUsage.robot
│ │ ├── findInlineVariableByDefinition.robot
│ │ ├── findInlineVariableByUsage.robot
│ │ ├── findKeywordByDefinition.robot
│ │ ├── findKeywordByUsage.robot
│ │ ├── findVariableByDefinition.robot
│ │ └── findVariableByUsage.robot
└── samples
│ ├── Demo.lexer.txt
│ ├── Demo.robot
│ ├── Demo.txt
│ ├── EmptyHeaders.lexer.txt
│ ├── EmptyHeaders.robot
│ ├── EmptyHeaders.txt
│ ├── Junk.lexer.txt
│ ├── Junk.robot
│ ├── Junk.txt
│ ├── ParsingTestData.lexer.txt
│ ├── ParsingTestData.robot
│ ├── ParsingTestData.txt
│ ├── TrimmedVariables.robot
│ ├── TrimmedVariables.txt
│ ├── Variables.lexer.txt
│ ├── Variables.robot
│ └── Variables.txt
└── wiki
├── dev_setup
├── intellij_sdk.png
├── plugin_config.png
└── python_library.png
├── features
├── code_folding.png
├── demo_complete.png
├── find_usages.png
├── jump_to_source.png
├── keyword_recommendation.png
├── structure.png
└── undefined_keyword.png
├── python_interpreter
├── intellij
│ ├── module_interpreter.png
│ ├── project_sdk.png
│ └── python_plugin.png
└── pycharm
│ ├── console_interpreter.png
│ └── project_interpreter.png
├── robot_options
├── event_log.png
└── options.png
├── test_debugging
└── debug_settings.png
└── using_txt_files
└── txt_file_type.png
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | out/
3 | target/
4 | *.iml
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 millenialmedia
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## IntelliJ/PyCharm Plugin for Robot Automation Framework
2 |
3 | This is a work in progress (the product of a 24 hour hack match), though at this point I have devoted far more time than that.
4 | Related feature request to JetBrains: [IDEA-97678](http://youtrack.jetbrains.com/issue/IDEA-97678).
5 | **Here is a growing list of [features](https://github.com/millennialmedia/intellibot/wiki/Features).**
6 |
7 | 
8 |
9 | ### Installation & Usage
10 |
11 | Note that this plugin should work in either IntelliJ or PyCharm, but that PyCharm is far less used (and thus tested) personally.
12 |
13 | **The plugin is now hosted in the JetBrains [repositories](http://plugins.jetbrains.com/plugin/7386?pr=github).**
14 | This means you can install it directly form your IDE.
15 | Just search for 'Intellibot' under 'Browse Repositories...'.
16 |
17 | You can also install the plugin manually.
18 | To do so you can either download and [compile](https://github.com/millennialmedia/intellibot/wiki/Development-Setup) the project yourself.
19 | Or download the [intellibot.jar](https://github.com/millennialmedia/intellibot/raw/master/intellibot.jar) file in the project.
20 | You can then install this plugin to your IDE by using the 'Install plugin from disk...' option.
21 | This version may be slightly ahead of the JetBrains repository though potentially slightly less stable.
22 |
23 | The plugin will, by default, operate against any ".robot" file in the project.
24 | **You can add ".txt" support by following these [instructions](https://github.com/millennialmedia/intellibot/wiki/Supporting-.txt-Files).**
25 | If you are using PyCharm then any Python libraries should be detected when you setup your interpreter.
26 | If you are using IntelliJ then you can install the Python plugin.
27 | Both instructions can be found in this [wiki page](https://github.com/millennialmedia/intellibot/wiki/Python-Interpreter).
28 |
--------------------------------------------------------------------------------
/intellibot.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/intellibot.jar
--------------------------------------------------------------------------------
/resources/images/robot_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/resources/images/robot_icon.png
--------------------------------------------------------------------------------
/resources/images/robot_icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/resources/images/robot_icon@2x.png
--------------------------------------------------------------------------------
/resources/inspectionDescriptions/RobotGherkinInspection.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | This inspection triggers when the format of the gherkin text is off (GIVEN, when, tHeN).
5 | Scenarios will generally read better if you keep your structure sentence-like.
6 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/inspectionDescriptions/RobotImportNotFound.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | This inspection triggers when the library or resource is not defined.
5 |
6 |
7 |
--------------------------------------------------------------------------------
/resources/inspectionDescriptions/RobotImportNotUsed.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | This inspection triggers when the resource is not used.
5 | Note that this does not currently cover libraries.
6 |
7 | Note that this can be a false positive regarding keywords that take keywords as an argument.
8 |
9 |
10 |
--------------------------------------------------------------------------------
/resources/inspectionDescriptions/RobotKeywordDefinitionStartingWithGherkin.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | This inspection triggers when a keyword definition starts with gherkin.
5 | This is often redundant and so can be removed.
6 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/inspectionDescriptions/RobotKeywordNotFound.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | This inspection triggers when the keyword is not defined.
5 | This includes imports of the current file; including python if configured.
6 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/inspectionDescriptions/RobotNestedVariable.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | This inspection triggers when nested variables are used (${variable${nested}}).
5 | This generally makes the code much harder to read and debug.
6 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/inspectionDescriptions/RobotNestedVariableDefinition.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | This inspection triggers when nested variable definitions are used (${variable${nested}}).
5 | This generally makes the code much harder to read and debug.
6 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/inspectionDescriptions/RobotVariableNotFound.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | This inspection triggers when the variable is not defined.
5 | This includes imports of the current file; including python if configured.
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/RobotBundle.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot;
2 |
3 | import com.intellij.CommonBundle;
4 | import com.intellij.reference.SoftReference;
5 | import org.jetbrains.annotations.NonNls;
6 | import org.jetbrains.annotations.PropertyKey;
7 |
8 | import java.lang.ref.Reference;
9 | import java.util.ResourceBundle;
10 |
11 | /**
12 | * @author mrubino
13 | */
14 | public class RobotBundle {
15 |
16 | // based off python's
17 |
18 | @NonNls
19 | private static final String BUNDLE = "com.millennialmedia.intellibot.RobotBundle";
20 |
21 | private static Reference instance;
22 |
23 | private RobotBundle() {
24 | }
25 |
26 | public static String message(@NonNls @PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
27 | return CommonBundle.message(getBundle(), key, params);
28 | }
29 |
30 | // Cached loading
31 | private static ResourceBundle getBundle() {
32 | ResourceBundle bundle = SoftReference.dereference(instance);
33 | if (bundle == null) {
34 | bundle = ResourceBundle.getBundle(BUNDLE);
35 | instance = new SoftReference(bundle);
36 | }
37 | return bundle;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/RobotBundle.properties:
--------------------------------------------------------------------------------
1 | color.settings.argument=Argument
2 | color.settings.bracketSetting=Bracket Setting
3 | color.settings.comment=Comment
4 | color.settings.error=Error
5 | color.settings.gherkin=Gherkin
6 | color.settings.heading=Heading
7 | color.settings.import=Import
8 | color.settings.keyword=Keyword
9 | color.settings.keywordDefinition=Keyword Definition
10 | color.settings.setting=Setting
11 | color.settings.variable=Variable
12 | color.settings.variableDefinition=Variable Definition
13 |
14 | # Python Support Warning
15 | plugin.python.missing=If you configure a python interpreter you will be able to get code completion around imported libraries in your robot files.
16 | plugin.python.missing.title=Intellibot: No Python Support for Robot
17 |
18 | # Structure
19 | action.structureView.show.files=Shows Files
20 | action.structureView.show.headings=Show Headings
21 | action.structureView.show.testCases=Show Test Cases
22 | action.structureView.show.keywords=Show Keywords
23 | action.structureView.show.variables=Show Variables
24 | action.structureView.sort.type=Sort by Type
25 |
26 | # Find Usages
27 | usage.declaration=Declaration
28 | usage.descriptive.argument=argument
29 | usage.descriptive.import=resource
30 | usage.descriptive.keyword=keyword
31 | usage.descriptive.variable=variable
32 |
33 | # Inspections
34 | # Inspection Groups
35 | INSP.GROUP.complexity=Complexity
36 | INSP.GROUP.readability=Readability
37 | INSP.GROUP.compilation=Compilation
38 | INSP.GROUP.cleanup=Clean Up
39 | # RobotGherkinInspection
40 | INSP.NAME.gherkin.format=Gherkin format
41 | INSP.gherkin.format=Incorrect gherkin format
42 | INSP.OPT.gherkin.format.upper=Allow all uppercase gherkin
43 | # RobotKeywordDefinitionStartingWithGherkin
44 | INSP.NAME.define.keyword.gherkin.start=Keyword starting with gherkin
45 | INSP.define.keyword.gherkin.start=Keyword starting with gherkin
46 | # RobotKeywordNotFound
47 | INSP.NAME.keyword.undefined=Undefined keyword
48 | INSP.keyword.undefined=Keyword definition not found
49 | # RobotVariableNotFound
50 | INSP.NAME.variable.undefined=Undefined variable
51 | INSP.variable.undefined=Variable definition not found
52 | # RobotImportNotFound
53 | INSP.NAME.import.undefined=Import not found
54 | INSP.import.undefined=Import file not found
55 | # RobotImportNotUsed
56 | INSP.NAME.import.unused=Import not used
57 | INSP.import.unused=Unused import statement
58 | # RobotNestedVariable
59 | INSP.NAME.variable.nested=Nested variable
60 | INSP.variable.nested=Usage of a nested variable
61 | # RobotNestedVariableDefinition
62 | INSP.NAME.variableDefinition.nested=Nested variable definition
63 | INSP.variableDefinition.nested=Usage of a nested variable definition
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/RobotCommenter.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide;
2 |
3 | import com.intellij.lang.Commenter;
4 | import org.jetbrains.annotations.Nullable;
5 |
6 | /**
7 | * @author mrubino
8 | */
9 | public class RobotCommenter implements Commenter {
10 |
11 | private static final String LINE_COMMENT_PREFIX = "#";
12 |
13 | @Nullable
14 | public String getLineCommentPrefix() {
15 | return LINE_COMMENT_PREFIX;
16 | }
17 |
18 | @Nullable
19 | public String getBlockCommentPrefix() {
20 | return null;
21 | }
22 |
23 | @Nullable
24 | public String getBlockCommentSuffix() {
25 | return null;
26 | }
27 |
28 | @Nullable
29 | public String getCommentedBlockCommentPrefix() {
30 | return null;
31 | }
32 |
33 | @Nullable
34 | public String getCommentedBlockCommentSuffix() {
35 | return null;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/RobotFoldingBuilder.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.lang.folding.FoldingBuilder;
5 | import com.intellij.lang.folding.FoldingDescriptor;
6 | import com.intellij.navigation.ItemPresentation;
7 | import com.intellij.navigation.NavigationItem;
8 | import com.intellij.openapi.editor.Document;
9 | import com.intellij.openapi.project.DumbAware;
10 | import com.intellij.psi.tree.TokenSet;
11 | import com.millennialmedia.intellibot.psi.RobotTokenTypes;
12 | import com.millennialmedia.intellibot.psi.element.Heading;
13 | import com.millennialmedia.intellibot.psi.element.KeywordDefinition;
14 | import com.millennialmedia.intellibot.psi.element.RobotStatement;
15 | import org.jetbrains.annotations.NotNull;
16 | import org.jetbrains.annotations.Nullable;
17 |
18 | import java.util.ArrayList;
19 | import java.util.Collection;
20 |
21 | /**
22 | * @author mrubino
23 | */
24 | public class RobotFoldingBuilder implements FoldingBuilder, DumbAware {
25 |
26 | private static final String ELLIPSIS = "...";
27 |
28 | private static final TokenSet BLOCKS_TO_FOLD = TokenSet.create(RobotTokenTypes.KEYWORD_DEFINITION, RobotTokenTypes.HEADING);
29 |
30 | @NotNull
31 | public FoldingDescriptor[] buildFoldRegions(@NotNull ASTNode node, @NotNull Document document) {
32 | Collection descriptors = new ArrayList();
33 | appendDescriptors(node, descriptors);
34 | return descriptors.toArray(new FoldingDescriptor[descriptors.size()]);
35 | }
36 |
37 | private void appendDescriptors(ASTNode node, Collection descriptors) {
38 | if (BLOCKS_TO_FOLD.contains(node.getElementType()) &&
39 | node.getTextRange().getLength() >= 2 &&
40 | node.getPsi() instanceof RobotStatement) {
41 | descriptors.add(new FoldingDescriptor(node, node.getTextRange()));
42 | }
43 | ASTNode child = node.getFirstChildNode();
44 | while (child != null) {
45 | appendDescriptors(child, descriptors);
46 | child = child.getTreeNext();
47 | }
48 | }
49 |
50 | @Nullable
51 | public String getPlaceholderText(@NotNull ASTNode node) {
52 | if (node.getPsi() instanceof Heading ||
53 | node.getPsi() instanceof KeywordDefinition) {
54 | ItemPresentation presentation = ((NavigationItem) node.getPsi()).getPresentation();
55 | if (presentation != null) {
56 | return presentation.getPresentableText();
57 | }
58 | }
59 | return ELLIPSIS;
60 | }
61 |
62 | public boolean isCollapsedByDefault(@NotNull ASTNode node) {
63 | return node.getPsi() instanceof Heading && ((Heading) node.getPsi()).isSettings();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/config/RobotColorsPage.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.config;
2 |
3 | import com.intellij.openapi.editor.colors.TextAttributesKey;
4 | import com.intellij.openapi.fileTypes.SyntaxHighlighter;
5 | import com.intellij.openapi.options.colors.AttributesDescriptor;
6 | import com.intellij.openapi.options.colors.ColorDescriptor;
7 | import com.intellij.openapi.options.colors.ColorSettingsPage;
8 | import com.millennialmedia.intellibot.RobotBundle;
9 | import com.millennialmedia.intellibot.psi.RobotFeatureFileType;
10 | import com.millennialmedia.intellibot.psi.RobotHighlighter;
11 | import com.millennialmedia.intellibot.psi.RobotKeywordProvider;
12 | import org.jetbrains.annotations.NotNull;
13 | import org.jetbrains.annotations.Nullable;
14 |
15 | import javax.swing.*;
16 | import java.util.Map;
17 |
18 | /**
19 | * @author mrubino
20 | */
21 | public class RobotColorsPage implements ColorSettingsPage {
22 |
23 | private static final String DEMO_TEXT = "invalid\n" +
24 | "*** Settings ***\n" +
25 | "Documentation This is some demo text\n" +
26 | "Library CalculatorLibrary\n" +
27 | "\n" +
28 | "*** Variables ***\n" +
29 | "${var1} 12345\n" +
30 | "${var2} another variable\n" +
31 | "\n" +
32 | "*** Test Cases ***\n" +
33 | "Addition\n" +
34 | " [Tags] Calculator\n" +
35 | " Given calculator has been cleared\n" +
36 | " When user types \"1 + 1\"\n" +
37 | " And user pushes equals\n" +
38 | " Then result is \"2\"\n" +
39 | "\n" +
40 | "#Subtraction\n" +
41 | "# [Tags] Calculator\n" +
42 | "# TODO: implement me\n" +
43 | "\n" +
44 | "*** Keywords ***\n" +
45 | "Calculator has been cleared\n" +
46 | " Push button C\n" +
47 | "\n" +
48 | "User types \"${expression}\"\n" +
49 | " Push buttons ${expression}\n" +
50 | "\n" +
51 | "User pushes equals\n" +
52 | " Push button =\n" +
53 | "\n" +
54 | "Result is \"${result}\"\n" +
55 | " Result should be ${result}";
56 |
57 | private static final String NAME = "Robot";
58 | private static final ColorDescriptor[] COLORS = new ColorDescriptor[0];
59 |
60 | private static final AttributesDescriptor[] ATTRIBUTES = new AttributesDescriptor[]{
61 | new AttributesDescriptor(RobotBundle.message("color.settings.heading"), RobotHighlighter.HEADING),
62 | new AttributesDescriptor(RobotBundle.message("color.settings.comment"), RobotHighlighter.COMMENT),
63 | new AttributesDescriptor(RobotBundle.message("color.settings.argument"), RobotHighlighter.ARGUMENT),
64 | new AttributesDescriptor(RobotBundle.message("color.settings.error"), RobotHighlighter.ERROR),
65 | new AttributesDescriptor(RobotBundle.message("color.settings.gherkin"), RobotHighlighter.GHERKIN),
66 | new AttributesDescriptor(RobotBundle.message("color.settings.variable"), RobotHighlighter.VARIABLE),
67 | new AttributesDescriptor(RobotBundle.message("color.settings.variableDefinition"), RobotHighlighter.VARIABLE_DEFINITION),
68 | new AttributesDescriptor(RobotBundle.message("color.settings.keyword"), RobotHighlighter.KEYWORD),
69 | new AttributesDescriptor(RobotBundle.message("color.settings.keywordDefinition"), RobotHighlighter.KEYWORD_DEFINITION),
70 | new AttributesDescriptor(RobotBundle.message("color.settings.bracketSetting"), RobotHighlighter.BRACKET_SETTING),
71 | new AttributesDescriptor(RobotBundle.message("color.settings.setting"), RobotHighlighter.SETTING),
72 | new AttributesDescriptor(RobotBundle.message("color.settings.import"), RobotHighlighter.IMPORT)
73 | };
74 |
75 | @Nullable
76 | @Override
77 | public Icon getIcon() {
78 | return RobotFeatureFileType.getInstance().getIcon();
79 | }
80 |
81 | @NotNull
82 | @Override
83 | public SyntaxHighlighter getHighlighter() {
84 | return new RobotHighlighter(RobotKeywordProvider.getInstance());
85 | }
86 |
87 | @NotNull
88 | @Override
89 | public String getDemoText() {
90 | return DEMO_TEXT;
91 | }
92 |
93 | @Nullable
94 | @Override
95 | public Map getAdditionalHighlightingTagToDescriptorMap() {
96 | return null;
97 | }
98 |
99 | @NotNull
100 | @Override
101 | public AttributesDescriptor[] getAttributeDescriptors() {
102 | return ATTRIBUTES;
103 | }
104 |
105 | @NotNull
106 | @Override
107 | public ColorDescriptor[] getColorDescriptors() {
108 | return COLORS;
109 | }
110 |
111 | @NotNull
112 | @Override
113 | public String getDisplayName() {
114 | return NAME;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/config/RobotConfiguration.form:
--------------------------------------------------------------------------------
1 |
2 |
69 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/config/RobotConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.config;
2 |
3 | import com.intellij.openapi.options.Configurable;
4 | import com.intellij.openapi.options.ConfigurationException;
5 | import com.intellij.openapi.options.SearchableConfigurable;
6 | import org.jetbrains.annotations.Nls;
7 | import org.jetbrains.annotations.NotNull;
8 | import org.jetbrains.annotations.Nullable;
9 |
10 | import javax.swing.*;
11 |
12 | /**
13 | * @author mrubino
14 | * @since 2014-06-26
15 | */
16 | public class RobotConfiguration implements SearchableConfigurable, Configurable.NoScroll {
17 |
18 | private RobotOptionsProvider provider;
19 |
20 | private JPanel panel;
21 | private JCheckBox enableDebug;
22 | private JCheckBox allowTransitiveImports;
23 | private JCheckBox allowGlobalVariables;
24 | private JCheckBox capitalizeKeywords;
25 | private JCheckBox inlineVariableSearch;
26 |
27 | public RobotConfiguration(@NotNull RobotOptionsProvider provider) {
28 | this.provider = provider;
29 | }
30 |
31 | @NotNull
32 | @Override
33 | public String getId() {
34 | return getHelpTopic();
35 | }
36 |
37 | @Nullable
38 | @Override
39 | public Runnable enableSearch(String s) {
40 | return null;
41 | }
42 |
43 | @Nls
44 | @Override
45 | public String getDisplayName() {
46 | return "Robot Options";
47 | }
48 |
49 | @NotNull
50 | @Override
51 | public String getHelpTopic() {
52 | return "reference.idesettings.robot";
53 | }
54 |
55 | @Nullable
56 | @Override
57 | public JComponent createComponent() {
58 | return this.panel;
59 | }
60 |
61 | @Override
62 | public boolean isModified() {
63 | return this.provider.isDebug() != this.enableDebug.isSelected() ||
64 | this.provider.allowTransitiveImports() != this.allowTransitiveImports.isSelected() ||
65 | this.provider.allowGlobalVariables() != this.allowGlobalVariables.isSelected() ||
66 | this.provider.capitalizeKeywords() != this.capitalizeKeywords.isSelected() ||
67 | this.provider.inlineVariableSearch() != this.inlineVariableSearch.isSelected();
68 | }
69 |
70 | @Override
71 | public void apply() throws ConfigurationException {
72 | this.provider.setDebug(this.enableDebug.isSelected());
73 | this.provider.setTransitiveImports(this.allowTransitiveImports.isSelected());
74 | this.provider.setGlobalVariables(this.allowGlobalVariables.isSelected());
75 | this.provider.setCapitalizeKeywords(this.capitalizeKeywords.isSelected());
76 | this.provider.setInlineVariableSearch(this.inlineVariableSearch.isSelected());
77 | }
78 |
79 | @Override
80 | public void reset() {
81 | this.enableDebug.setSelected(this.provider.isDebug());
82 | this.allowTransitiveImports.setSelected(this.provider.allowTransitiveImports());
83 | this.allowGlobalVariables.setSelected(this.provider.allowGlobalVariables());
84 | this.capitalizeKeywords.setSelected(this.provider.capitalizeKeywords());
85 | this.inlineVariableSearch.setSelected(this.provider.inlineVariableSearch());
86 | }
87 |
88 | @Override
89 | public void disposeUIResources() {
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/config/RobotOptionsProvider.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.config;
2 |
3 | import com.intellij.openapi.components.*;
4 | import com.intellij.openapi.project.Project;
5 | import org.jetbrains.annotations.Nullable;
6 |
7 | /**
8 | * @author mrubino
9 | * @since 2014-06-26
10 | */
11 | @State(
12 | name = "RobotOptionsProvider",
13 | storages = {
14 | @Storage(file = StoragePathMacros.WORKSPACE_FILE)
15 | }
16 | )
17 | public class RobotOptionsProvider implements PersistentStateComponent {
18 |
19 | public static class State {
20 | public boolean transitiveImports = true;
21 | public boolean globalVariables = true;
22 | public boolean debug = false;
23 | public boolean capitalizeKeywords = false;
24 | public boolean inlineVariableSearch = false;
25 | }
26 |
27 | private State state = new State();
28 |
29 | public static RobotOptionsProvider getInstance(Project project) {
30 | return ServiceManager.getService(project, RobotOptionsProvider.class);
31 | }
32 |
33 | @Nullable
34 | @Override
35 | public State getState() {
36 | return this.state;
37 | }
38 |
39 | @Override
40 | public void loadState(State state) {
41 | this.state.debug = state.debug;
42 | this.state.transitiveImports = state.transitiveImports;
43 | this.state.globalVariables = state.globalVariables;
44 | this.state.capitalizeKeywords = state.capitalizeKeywords;
45 | this.state.inlineVariableSearch = state.inlineVariableSearch;
46 | }
47 |
48 | public boolean isDebug() {
49 | return this.state.debug;
50 | }
51 |
52 | public void setDebug(boolean debug) {
53 | this.state.debug = debug;
54 | }
55 |
56 | public boolean allowTransitiveImports() {
57 | return this.state.transitiveImports;
58 | }
59 |
60 | public void setTransitiveImports(boolean transitiveImports) {
61 | this.state.transitiveImports = transitiveImports;
62 | }
63 |
64 | public boolean allowGlobalVariables() {
65 | return this.state.globalVariables;
66 | }
67 |
68 | public void setGlobalVariables(boolean globalVariables) {
69 | this.state.globalVariables = globalVariables;
70 | }
71 |
72 | public boolean capitalizeKeywords() {
73 | return this.state.capitalizeKeywords;
74 | }
75 |
76 | public void setCapitalizeKeywords(boolean capitalizeKeywords) {
77 | this.state.capitalizeKeywords = capitalizeKeywords;
78 | }
79 |
80 | public boolean inlineVariableSearch() {
81 | return this.state.inlineVariableSearch;
82 | }
83 |
84 | public void setInlineVariableSearch(boolean inlineVariableSearch) {
85 | this.state.inlineVariableSearch = inlineVariableSearch;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/icons/RobotIcons.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.icons;
2 |
3 | import com.intellij.icons.AllIcons;
4 | import com.intellij.openapi.util.IconLoader;
5 |
6 | import javax.swing.*;
7 |
8 | /**
9 | * @author mrubino
10 | * @since 2016-01-28
11 | */
12 | public class RobotIcons {
13 |
14 | public static final Icon FILE = IconLoader.findIcon("/images/robot_icon.png");
15 | public static final Icon HEADING = AllIcons.Nodes.Tag;
16 | public static final Icon KEYWORD_DEFINITION = AllIcons.Nodes.Method;
17 | public static final Icon TEST_CASE = AllIcons.RunConfigurations.Junit;
18 | public static final Icon VARIABLE_DEFINITION = AllIcons.Nodes.Variable;
19 |
20 | private RobotIcons() {
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/SimpleInspection.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections;
2 |
3 | import com.intellij.psi.PsiElement;
4 |
5 | /**
6 | * @author mrubino
7 | * @since 2014-06-07
8 | */
9 | public interface SimpleInspection {
10 |
11 | /**
12 | * Determines if the element is valid for this inspection.
13 | *
14 | * @param element the element in question.
15 | * @return true if this element is valid; false if it is not.
16 | */
17 | boolean skip(PsiElement element);
18 |
19 | /**
20 | * The inspection message to be show in this inspection matches.
21 | *
22 | * @return the inspection message.
23 | */
24 | String getMessage();
25 | }
26 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/SimpleInspectionVisitor.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections;
2 |
3 | import com.intellij.codeInspection.ProblemsHolder;
4 | import com.intellij.psi.PsiElement;
5 | import com.intellij.psi.PsiElementVisitor;
6 |
7 | /**
8 | * @author mrubino
9 | * @since 2014-06-07
10 | */
11 | public class SimpleInspectionVisitor extends PsiElementVisitor {
12 |
13 | private final ProblemsHolder holder;
14 | private final SimpleInspection context;
15 |
16 | public SimpleInspectionVisitor(ProblemsHolder holder, SimpleInspection context) {
17 | this.holder = holder;
18 | this.context = context;
19 | }
20 |
21 | @Override
22 | public void visitElement(PsiElement element) {
23 | if (this.context.skip(element)) {
24 | return;
25 | }
26 |
27 | // TODO: the refactor
28 | this.holder.registerProblem(element, this.context.getMessage());
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/SimpleRobotInspection.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections;
2 |
3 | import com.intellij.codeInspection.LocalInspectionTool;
4 | import com.intellij.codeInspection.LocalInspectionToolSession;
5 | import com.intellij.codeInspection.ProblemsHolder;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.millennialmedia.intellibot.RobotBundle;
8 | import org.jetbrains.annotations.Nls;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | /**
12 | * @author mrubino
13 | * @since 2014-06-07
14 | */
15 | public abstract class SimpleRobotInspection extends LocalInspectionTool implements SimpleInspection {
16 |
17 | @Nls
18 | @NotNull
19 | @Override
20 | public String getGroupDisplayName() {
21 | return RobotBundle.message(getGroupNameKey());
22 | }
23 |
24 | @NotNull
25 | protected abstract String getGroupNameKey();
26 |
27 | @NotNull
28 | @Override
29 | public String getShortName() {
30 | return getClass().getSimpleName();
31 | }
32 |
33 | @Override
34 | public boolean isEnabledByDefault() {
35 | return true;
36 | }
37 |
38 | @NotNull
39 | @Override
40 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
41 | boolean isOnTheFly,
42 | @NotNull LocalInspectionToolSession session) {
43 | return new SimpleInspectionVisitor(holder, this);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/cleanup/RobotImportNotUsed.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections.cleanup;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiFile;
5 | import com.intellij.psi.PsiReference;
6 | import com.millennialmedia.intellibot.RobotBundle;
7 | import com.millennialmedia.intellibot.ide.inspections.SimpleRobotInspection;
8 | import com.millennialmedia.intellibot.psi.RobotTokenTypes;
9 | import com.millennialmedia.intellibot.psi.element.Argument;
10 | import com.millennialmedia.intellibot.psi.element.Import;
11 | import com.millennialmedia.intellibot.psi.element.RobotFile;
12 | import org.jetbrains.annotations.Nls;
13 | import org.jetbrains.annotations.NotNull;
14 |
15 | import java.util.Collection;
16 |
17 | /**
18 | * @author mrubino
19 | * @since 2014-06-07
20 | */
21 | public class RobotImportNotUsed extends SimpleRobotInspection {
22 |
23 | @Nls
24 | @NotNull
25 | @Override
26 | public String getDisplayName() {
27 | return RobotBundle.message("INSP.NAME.import.unused");
28 | }
29 |
30 | @Override
31 | public boolean skip(PsiElement element) {
32 | if (element.getNode().getElementType() != RobotTokenTypes.ARGUMENT) {
33 | return true;
34 | } else if (!(element instanceof Argument)) {
35 | return true;
36 | }
37 | PsiFile file = element.getContainingFile();
38 | if (!(file instanceof RobotFile)) {
39 | return true;
40 | }
41 |
42 | PsiElement parent = element.getParent();
43 |
44 | if (parent instanceof Import) {
45 | if (!((Import) parent).isResource()) {
46 | // TODO: python libraries
47 | // TODO: variables
48 | return true;
49 | }
50 | PsiElement[] children = parent.getChildren();
51 | // first child seems to be different than this
52 | if (children.length > 0 && children[0] == element) {
53 | PsiReference reference = element.getReference();
54 | if (reference == null) {
55 | return true;
56 | }
57 | PsiElement importFile = reference.resolve();
58 | if (importFile == null) {
59 | return true; // we cannot find the file thus we do not know if we use it
60 | }
61 |
62 | Collection referenced = ((RobotFile) file).getFilesFromInvokedKeywordsAndVariables();
63 | return referenced.contains(importFile.getContainingFile());
64 | } else {
65 | return true;
66 | }
67 | } else {
68 | return true;
69 | }
70 | }
71 |
72 | @Override
73 | public String getMessage() {
74 | return RobotBundle.message("INSP.import.unused");
75 | }
76 |
77 | @NotNull
78 | @Override
79 | protected String getGroupNameKey() {
80 | return "INSP.GROUP.cleanup";
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/compilation/RobotImportNotFound.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections.compilation;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiReference;
5 | import com.millennialmedia.intellibot.RobotBundle;
6 | import com.millennialmedia.intellibot.ide.inspections.SimpleRobotInspection;
7 | import com.millennialmedia.intellibot.psi.RobotTokenTypes;
8 | import com.millennialmedia.intellibot.psi.element.Import;
9 | import org.jetbrains.annotations.Nls;
10 | import org.jetbrains.annotations.NotNull;
11 |
12 | /**
13 | * @author mrubino
14 | * @since 2014-06-07
15 | */
16 | public class RobotImportNotFound extends SimpleRobotInspection {
17 |
18 | @Nls
19 | @NotNull
20 | @Override
21 | public String getDisplayName() {
22 | return RobotBundle.message("INSP.NAME.import.undefined");
23 | }
24 |
25 | @Override
26 | public boolean skip(PsiElement element) {
27 | if (element.getNode().getElementType() != RobotTokenTypes.ARGUMENT) {
28 | return true;
29 | }
30 | PsiElement parent = element.getParent();
31 | if (parent instanceof Import) {
32 | PsiElement[] children = parent.getChildren();
33 | // first child seems to be different than this
34 | if (children.length > 0 && children[0] == element) {
35 | PsiReference reference = element.getReference();
36 | return reference != null && reference.resolve() != null;
37 | } else {
38 | return true;
39 | }
40 |
41 | } else {
42 | return true;
43 | }
44 | }
45 |
46 | @Override
47 | public String getMessage() {
48 | return RobotBundle.message("INSP.import.undefined");
49 | }
50 |
51 | @NotNull
52 | @Override
53 | protected String getGroupNameKey() {
54 | return "INSP.GROUP.compilation";
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/compilation/RobotKeywordNotFound.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections.compilation;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiReference;
5 | import com.millennialmedia.intellibot.RobotBundle;
6 | import com.millennialmedia.intellibot.ide.inspections.SimpleRobotInspection;
7 | import com.millennialmedia.intellibot.psi.element.KeywordInvokable;
8 | import org.jetbrains.annotations.Nls;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | /**
12 | * @author mrubino
13 | * @since 2014-06-07
14 | */
15 | public class RobotKeywordNotFound extends SimpleRobotInspection {
16 |
17 | @Nls
18 | @NotNull
19 | @Override
20 | public String getDisplayName() {
21 | return RobotBundle.message("INSP.NAME.keyword.undefined");
22 | }
23 |
24 | @Override
25 | public boolean skip(PsiElement element) {
26 | if (element instanceof KeywordInvokable) {
27 | PsiReference reference = element.getReference();
28 | if (reference != null && reference.resolve() != null) {
29 | return true;
30 | }
31 |
32 | String text = ((KeywordInvokable) element).getPresentableText();
33 | if (text.startsWith(":")) {
34 | // TODO: for loops
35 | return true;
36 | } else if (text.startsWith("\\")) {
37 | // TODO: for loops
38 | return true;
39 | }
40 | return false;
41 | } else {
42 | return true;
43 | }
44 | }
45 |
46 | @Override
47 | public String getMessage() {
48 | return RobotBundle.message("INSP.keyword.undefined");
49 | }
50 |
51 | @NotNull
52 | @Override
53 | protected String getGroupNameKey() {
54 | return "INSP.GROUP.compilation";
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/compilation/RobotVariableNotFound.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections.compilation;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiReference;
5 | import com.millennialmedia.intellibot.RobotBundle;
6 | import com.millennialmedia.intellibot.ide.inspections.SimpleRobotInspection;
7 | import com.millennialmedia.intellibot.psi.element.Argument;
8 | import com.millennialmedia.intellibot.psi.element.KeywordInvokable;
9 | import com.millennialmedia.intellibot.psi.element.KeywordStatement;
10 | import com.millennialmedia.intellibot.psi.element.Variable;
11 | import org.jetbrains.annotations.Nls;
12 | import org.jetbrains.annotations.NotNull;
13 |
14 | import java.util.List;
15 |
16 | /**
17 | * @author mrubino
18 | * @since 2014-06-18
19 | */
20 | public class RobotVariableNotFound extends SimpleRobotInspection {
21 |
22 | @Nls
23 | @NotNull
24 | @Override
25 | public String getDisplayName() {
26 | return RobotBundle.message("INSP.NAME.variable.undefined");
27 | }
28 |
29 | @Override
30 | public boolean skip(PsiElement element) {
31 | if (element instanceof Variable) {
32 | PsiReference reference = element.getReference();
33 | if (reference != null && reference.resolve() != null) {
34 | return true;
35 | }
36 | if (((Variable) element).isNested()) {
37 | // TODO: nested variables
38 | return true;
39 | }
40 |
41 | // TODO: what is needed below this point...
42 | PsiElement container = element.getParent();
43 | element = container;
44 | if (container instanceof Argument) {
45 | container = container.getParent();
46 | }
47 | if (container instanceof KeywordStatement) {
48 | KeywordInvokable invokable = ((KeywordStatement) container).getInvokable();
49 | String text = invokable == null ? null : invokable.getPresentableText();
50 | if (text != null) {
51 | if (text.startsWith(":")) {
52 | // TODO: for loops
53 | return true;
54 | } else if (text.startsWith("\\")) {
55 | // TODO: for loops
56 | return true;
57 | }
58 | }
59 | // this is the case where we have a 'set test variable' call with more than one arg
60 | // the first is the variable name, the second is the value
61 | // if there is only one argument then we might want to see where it was created
62 | if (((KeywordStatement) container).getGlobalVariable() != null) {
63 | List arguments = ((KeywordStatement) container).getArguments();
64 | if (arguments.size() > 1 && element == arguments.get(0)) {
65 | return true;
66 | }
67 | }
68 | }
69 | return false;
70 | } else {
71 | return true;
72 | }
73 | }
74 |
75 | @Override
76 | public String getMessage() {
77 | return RobotBundle.message("INSP.variable.undefined");
78 | }
79 |
80 | @NotNull
81 | @Override
82 | protected String getGroupNameKey() {
83 | return "INSP.GROUP.compilation";
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/complexity/RobotNestedVariable.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections.complexity;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.millennialmedia.intellibot.RobotBundle;
5 | import com.millennialmedia.intellibot.ide.inspections.SimpleRobotInspection;
6 | import com.millennialmedia.intellibot.psi.RobotTokenTypes;
7 | import com.millennialmedia.intellibot.psi.element.Variable;
8 | import org.jetbrains.annotations.Nls;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | /**
12 | * @author mrubino
13 | * @since 2015-08-24
14 | */
15 | public class RobotNestedVariable extends SimpleRobotInspection {
16 |
17 | @Nls
18 | @NotNull
19 | @Override
20 | public String getDisplayName() {
21 | return RobotBundle.message("INSP.NAME.variable.nested");
22 | }
23 |
24 | @Override
25 | public boolean skip(PsiElement element) {
26 | if (element.getNode().getElementType() != RobotTokenTypes.VARIABLE) {
27 | return true;
28 | }
29 | PsiElement parent = element.getParent();
30 | return !(parent instanceof Variable) || !((Variable) parent).isNested();
31 | }
32 |
33 | @Override
34 | public String getMessage() {
35 | return RobotBundle.message("INSP.variable.nested");
36 | }
37 |
38 | @NotNull
39 | @Override
40 | protected String getGroupNameKey() {
41 | return "INSP.GROUP.complexity";
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/complexity/RobotNestedVariableDefinition.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections.complexity;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.millennialmedia.intellibot.RobotBundle;
5 | import com.millennialmedia.intellibot.ide.inspections.SimpleRobotInspection;
6 | import com.millennialmedia.intellibot.psi.RobotTokenTypes;
7 | import com.millennialmedia.intellibot.psi.element.VariableDefinition;
8 | import org.jetbrains.annotations.Nls;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | /**
12 | * @author mrubino
13 | * @since 2015-08-24
14 | * TODO: this should go away once we identify the nesting correctly
15 | */
16 | public class RobotNestedVariableDefinition extends SimpleRobotInspection {
17 |
18 | @Nls
19 | @NotNull
20 | @Override
21 | public String getDisplayName() {
22 | return RobotBundle.message("INSP.NAME.variableDefinition.nested");
23 | }
24 |
25 | @Override
26 | public boolean skip(PsiElement element) {
27 | if (element.getNode().getElementType() != RobotTokenTypes.VARIABLE_DEFINITION) {
28 | return true;
29 | }
30 | PsiElement parent = element.getParent();
31 | return !(parent instanceof VariableDefinition) || !((VariableDefinition) parent).isNested();
32 | }
33 |
34 | @Override
35 | public String getMessage() {
36 | return RobotBundle.message("INSP.variableDefinition.nested");
37 | }
38 |
39 | @NotNull
40 | @Override
41 | protected String getGroupNameKey() {
42 | return "INSP.GROUP.complexity";
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/readability/RobotGherkinInspection.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections.readability;
2 |
3 | import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
4 | import com.intellij.psi.PsiElement;
5 | import com.millennialmedia.intellibot.RobotBundle;
6 | import com.millennialmedia.intellibot.ide.inspections.SimpleInspection;
7 | import com.millennialmedia.intellibot.ide.inspections.SimpleRobotInspection;
8 | import com.millennialmedia.intellibot.psi.RobotKeywordProvider;
9 | import com.millennialmedia.intellibot.psi.RobotTokenTypes;
10 | import org.jetbrains.annotations.Nls;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | import javax.swing.*;
14 | import java.util.Collection;
15 | import java.util.HashSet;
16 |
17 | /**
18 | * @author mrubino
19 | * @since 2014-06-07
20 | */
21 | public class RobotGherkinInspection extends SimpleRobotInspection implements SimpleInspection {
22 |
23 | private static final Collection NORMAL;
24 | private static final Collection UPPER;
25 |
26 | static {
27 | NORMAL = new HashSet();
28 | UPPER = new HashSet();
29 | for (String gherkin : RobotKeywordProvider.getInstance().getSyntaxOfType(RobotTokenTypes.GHERKIN)) {
30 | NORMAL.add(gherkin);
31 | UPPER.add(gherkin.toUpperCase());
32 | }
33 | }
34 |
35 | public boolean allowUppercase = false;
36 |
37 | @Nls
38 | @NotNull
39 | @Override
40 | public String getDisplayName() {
41 | return RobotBundle.message("INSP.NAME.gherkin.format");
42 | }
43 |
44 | @Override
45 | public JComponent createOptionsPanel() {
46 | MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
47 | panel.addCheckbox(RobotBundle.message("INSP.OPT.gherkin.format.upper"), "allowUppercase");
48 | return panel;
49 | }
50 |
51 | @Override
52 | public boolean skip(PsiElement element) {
53 | // this should be getPresentableText if we ever formalize the Gherkin type
54 | return element.getNode().getElementType() != RobotTokenTypes.GHERKIN ||
55 | valid(element.getText());
56 | }
57 |
58 | @Override
59 | public String getMessage() {
60 | return RobotBundle.message("INSP.gherkin.format");
61 | }
62 |
63 | private boolean valid(String text) {
64 | return NORMAL.contains(text) || (this.allowUppercase && UPPER.contains(text));
65 | }
66 |
67 | @NotNull
68 | @Override
69 | protected String getGroupNameKey() {
70 | return "INSP.GROUP.readability";
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/inspections/readability/RobotKeywordDefinitionStartingWithGherkin.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.inspections.readability;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.millennialmedia.intellibot.RobotBundle;
5 | import com.millennialmedia.intellibot.ide.inspections.SimpleRobotInspection;
6 | import com.millennialmedia.intellibot.psi.RobotKeywordProvider;
7 | import com.millennialmedia.intellibot.psi.RobotTokenTypes;
8 | import com.millennialmedia.intellibot.psi.element.KeywordDefinition;
9 | import org.jetbrains.annotations.Nls;
10 | import org.jetbrains.annotations.NotNull;
11 |
12 | import java.util.Collection;
13 |
14 | /**
15 | * @author mrubino
16 | * @since 2014-06-07
17 | */
18 | public class RobotKeywordDefinitionStartingWithGherkin extends SimpleRobotInspection {
19 |
20 | @Nls
21 | @NotNull
22 | @Override
23 | public String getDisplayName() {
24 | return RobotBundle.message("INSP.NAME.define.keyword.gherkin.start");
25 | }
26 |
27 | @Override
28 | public boolean skip(PsiElement element) {
29 | return !(element instanceof KeywordDefinition) || valid(((KeywordDefinition) element).getPresentableText());
30 | }
31 |
32 | private boolean valid(String text) {
33 | Collection gherkin = RobotKeywordProvider.getInstance().getSyntaxOfType(RobotTokenTypes.GHERKIN);
34 | int firstSpace = text.indexOf(" ");
35 |
36 | String word;
37 | if (firstSpace < 0) {
38 | word = text;
39 | } else {
40 | word = text.substring(0, firstSpace);
41 | }
42 | return !gherkin.contains(word);
43 | }
44 |
45 | @Override
46 | public String getMessage() {
47 | return RobotBundle.message("INSP.define.keyword.gherkin.start");
48 | }
49 |
50 | @NotNull
51 | @Override
52 | protected String getGroupNameKey() {
53 | return "INSP.GROUP.readability";
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/structure/RobotStructureViewFactory.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.structure;
2 |
3 | import com.intellij.ide.structureView.StructureViewBuilder;
4 | import com.intellij.ide.structureView.StructureViewModel;
5 | import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
6 | import com.intellij.lang.PsiStructureViewFactory;
7 | import com.intellij.openapi.editor.Editor;
8 | import com.intellij.psi.PsiFile;
9 | import org.jetbrains.annotations.NotNull;
10 | import org.jetbrains.annotations.Nullable;
11 |
12 | /**
13 | * @author mrubino
14 | * @since 2015-11-23
15 | */
16 | public class RobotStructureViewFactory implements PsiStructureViewFactory {
17 |
18 | @Nullable
19 | @Override
20 | public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) {
21 | return new TreeBasedStructureViewBuilder() {
22 | @NotNull
23 | @Override
24 | public StructureViewModel createStructureViewModel(@Nullable Editor editor) {
25 | return new RobotStructureViewModel(psiFile, editor);
26 | }
27 | };
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/structure/RobotStructureViewModel.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.structure;
2 |
3 | import com.intellij.ide.structureView.StructureViewModel;
4 | import com.intellij.ide.structureView.StructureViewModelBase;
5 | import com.intellij.ide.structureView.StructureViewTreeElement;
6 | import com.intellij.ide.util.treeView.smartTree.Filter;
7 | import com.intellij.ide.util.treeView.smartTree.Sorter;
8 | import com.intellij.openapi.editor.Editor;
9 | import com.intellij.psi.PsiFile;
10 | import com.millennialmedia.intellibot.psi.element.KeywordDefinition;
11 | import com.millennialmedia.intellibot.psi.element.RobotFile;
12 | import com.millennialmedia.intellibot.psi.element.VariableDefinition;
13 | import org.jetbrains.annotations.NotNull;
14 | import org.jetbrains.annotations.Nullable;
15 |
16 | /**
17 | * @author mrubino
18 | * @since 2015-11-23
19 | */
20 | public class RobotStructureViewModel extends StructureViewModelBase implements StructureViewModel.ElementInfoProvider, StructureViewModel.ExpandInfoProvider {
21 |
22 | private static final Filter[] FILTERS = new Filter[]{
23 | new RobotTypeFilter("SHOW_TEST_CASES", RobotViewElementType.TestCase),
24 | new RobotTypeFilter("SHOW_KEYWORDS", RobotViewElementType.Keyword),
25 | new RobotTypeFilter("SHOW_VARIABLES", RobotViewElementType.Variable),
26 | new RobotTypeFilter("SHOW_HEADINGS", RobotViewElementType.Heading)
27 | };
28 |
29 | public RobotStructureViewModel(@NotNull PsiFile psiFile, @Nullable Editor editor) {
30 | this(psiFile, editor, new RobotStructureViewElement(psiFile));
31 | withSorters(
32 | Sorter.ALPHA_SORTER,
33 | RobotTypeSorter.getInstance()
34 | );
35 | }
36 |
37 | public RobotStructureViewModel(@NotNull PsiFile psiFile, @Nullable Editor editor, @NotNull StructureViewTreeElement element) {
38 | super(psiFile, editor, element);
39 | }
40 |
41 |
42 | @Override
43 | public boolean isAlwaysShowsPlus(StructureViewTreeElement element) {
44 | return element.getValue() instanceof RobotFile;
45 | }
46 |
47 | @Override
48 | public boolean isAlwaysLeaf(StructureViewTreeElement element) {
49 | final Object value = element.getValue();
50 | return value instanceof KeywordDefinition || value instanceof VariableDefinition;
51 | }
52 |
53 | @Override
54 | public boolean shouldEnterElement(Object element) {
55 | return false;
56 | }
57 |
58 | @NotNull
59 | @Override
60 | public Filter[] getFilters() {
61 | return FILTERS;
62 | }
63 |
64 | @Override
65 | public boolean isAutoExpand(@NotNull StructureViewTreeElement element) {
66 | return element.getValue() instanceof RobotFile;
67 | }
68 |
69 | @Override
70 | public boolean isSmartExpand() {
71 | return false;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/structure/RobotTypeFilter.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.structure;
2 |
3 | import com.intellij.ide.util.treeView.smartTree.ActionPresentation;
4 | import com.intellij.ide.util.treeView.smartTree.ActionPresentationData;
5 | import com.intellij.ide.util.treeView.smartTree.Filter;
6 | import com.intellij.ide.util.treeView.smartTree.TreeElement;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | /**
10 | * @author mrubino
11 | * @since 2015-12-15
12 | */
13 | class RobotTypeFilter implements Filter {
14 |
15 | @NotNull
16 | private final String name;
17 | @NotNull
18 | private final RobotViewElementType type;
19 |
20 | RobotTypeFilter(@NotNull String name, @NotNull RobotViewElementType type) {
21 | this.name = name;
22 | this.type = type;
23 | }
24 |
25 | @Override
26 | public boolean isVisible(TreeElement treeElement) {
27 | if (treeElement instanceof RobotStructureViewElement) {
28 | RobotViewElementType type = ((RobotStructureViewElement) treeElement).getType();
29 | return this.type != type;
30 | }
31 | return false;
32 | }
33 |
34 | @Override
35 | public boolean isReverted() {
36 | return true;
37 | }
38 |
39 | @NotNull
40 | @Override
41 | public ActionPresentation getPresentation() {
42 | return new ActionPresentationData(
43 | this.type.getMessage(),
44 | null,
45 | this.type.getIcon(null)
46 | );
47 | }
48 |
49 | @NotNull
50 | @Override
51 | public String getName() {
52 | return this.name;
53 | }
54 |
55 | @Override
56 | public String toString() {
57 | return this.getName();
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/structure/RobotTypeSorter.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.structure;
2 |
3 | import com.intellij.icons.AllIcons;
4 | import com.intellij.ide.util.treeView.smartTree.ActionPresentation;
5 | import com.intellij.ide.util.treeView.smartTree.ActionPresentationData;
6 | import com.intellij.ide.util.treeView.smartTree.Sorter;
7 | import com.millennialmedia.intellibot.RobotBundle;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import java.util.Comparator;
11 |
12 | /**
13 | * @author mrubino
14 | * @since 2015-12-15
15 | */
16 | public class RobotTypeSorter implements Sorter {
17 |
18 | private static final RobotTypeSorter INSTANCE = new RobotTypeSorter();
19 |
20 | public static Sorter getInstance() {
21 | return INSTANCE;
22 | }
23 |
24 | @Override
25 | public Comparator getComparator() {
26 | return new Comparator() {
27 | public int compare(Object o1, Object o2) {
28 | if (o1 instanceof RobotStructureViewElement && o2 instanceof RobotStructureViewElement) {
29 | return Integer.compare(
30 | ((RobotStructureViewElement) o1).getType().ordinal(),
31 | ((RobotStructureViewElement) o2).getType().ordinal()
32 | );
33 |
34 | }
35 | return 0;
36 | }
37 | };
38 | }
39 |
40 | @Override
41 | public boolean isVisible() {
42 | return true;
43 | }
44 |
45 | @Override
46 | public String toString() {
47 | return this.getName();
48 | }
49 |
50 | @NotNull
51 | @Override
52 | public ActionPresentation getPresentation() {
53 | return new ActionPresentationData(RobotBundle.message("action.structureView.sort.type"),
54 | null, AllIcons.ObjectBrowser.SortByType);
55 | }
56 |
57 | @NotNull
58 | @Override
59 | public String getName() {
60 | return "ROBOT_TYPE_COMPARATOR";
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/structure/RobotViewElementType.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.structure;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.millennialmedia.intellibot.RobotBundle;
5 | import com.millennialmedia.intellibot.ide.icons.RobotIcons;
6 | import org.jetbrains.annotations.NotNull;
7 | import org.jetbrains.annotations.Nullable;
8 |
9 | import javax.swing.*;
10 |
11 | /**
12 | * @author mrubino
13 | * @since 2015-12-15
14 | */
15 | enum RobotViewElementType {
16 | File {
17 | @Nullable
18 | @Override
19 | protected Icon getIcon(@Nullable PsiElement element) {
20 | return element == null ? null : element.getIcon(0);
21 | }
22 |
23 | @NotNull
24 | @Override
25 | protected String getMessage() {
26 | return RobotBundle.message("action.structureView.show.files");
27 | }
28 | },
29 | Heading {
30 | @Nullable
31 | @Override
32 | protected Icon getIcon(@Nullable PsiElement element) {
33 | return RobotIcons.HEADING;
34 | }
35 |
36 | @NotNull
37 | @Override
38 | protected String getMessage() {
39 | return RobotBundle.message("action.structureView.show.headings");
40 | }
41 | },
42 | TestCase {
43 | @Nullable
44 | @Override
45 | protected Icon getIcon(@Nullable PsiElement element) {
46 | return RobotIcons.TEST_CASE;
47 | }
48 |
49 | @NotNull
50 | @Override
51 | protected String getMessage() {
52 | return RobotBundle.message("action.structureView.show.testCases");
53 | }
54 | },
55 | Keyword {
56 | @Nullable
57 | @Override
58 | protected Icon getIcon(@Nullable PsiElement element) {
59 | return RobotIcons.KEYWORD_DEFINITION;
60 | }
61 |
62 | @NotNull
63 | @Override
64 | protected String getMessage() {
65 | return RobotBundle.message("action.structureView.show.keywords");
66 | }
67 | },
68 | Variable {
69 | @Nullable
70 | @Override
71 | protected Icon getIcon(@Nullable PsiElement element) {
72 | return RobotIcons.VARIABLE_DEFINITION;
73 | }
74 |
75 | @NotNull
76 | @Override
77 | protected String getMessage() {
78 | return RobotBundle.message("action.structureView.show.variables");
79 | }
80 | };
81 |
82 | @Nullable
83 | protected abstract Icon getIcon(@Nullable PsiElement element);
84 |
85 | @NotNull
86 | protected abstract String getMessage();
87 | }
88 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/usage/RobotFindUsagesProvider.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.usage;
2 |
3 | import com.intellij.lang.cacheBuilder.WordsScanner;
4 | import com.intellij.lang.findUsages.FindUsagesProvider;
5 | import com.intellij.psi.PsiElement;
6 | import com.intellij.psi.PsiNamedElement;
7 | import com.millennialmedia.intellibot.RobotBundle;
8 | import com.millennialmedia.intellibot.psi.element.*;
9 | import org.jetbrains.annotations.NotNull;
10 | import org.jetbrains.annotations.Nullable;
11 |
12 | /**
13 | * @author Stephen Abrams
14 | */
15 | public class RobotFindUsagesProvider implements FindUsagesProvider {
16 |
17 | @Nullable
18 | @Override
19 | public WordsScanner getWordsScanner() {
20 | return new RobotWordScanner();
21 | }
22 |
23 | @Override
24 | public boolean canFindUsagesFor(@NotNull PsiElement element) {
25 | if (element instanceof Argument && element.getParent() instanceof Import) {
26 | // if the Argument is the first child of Import, then it is the file reference
27 | // everything else will be covered by Variables
28 | return element == element.getParent().getFirstChild();
29 | }
30 | return element instanceof PsiNamedElement;
31 | }
32 |
33 | @Nullable
34 | @Override
35 | public String getHelpId(@NotNull PsiElement element) {
36 | return null;
37 | }
38 |
39 | @NotNull
40 | @Override
41 | public String getType(@NotNull PsiElement element) {
42 | return RobotBundle.message("usage.declaration");
43 | }
44 |
45 | @NotNull
46 | @Override
47 | public String getDescriptiveName(@NotNull PsiElement element) {
48 | // this is what appears in the find usages dialog
49 | if (element instanceof KeywordDefinition) {
50 | return RobotBundle.message("usage.descriptive.keyword");
51 | } else if (element instanceof VariableDefinition) {
52 | return RobotBundle.message("usage.descriptive.variable");
53 | } else if (element instanceof RobotFile) {
54 | return RobotBundle.message("usage.descriptive.import");
55 | } else if (element instanceof Argument) {
56 | return RobotBundle.message("usage.descriptive.argument");
57 | }
58 | return "";
59 | }
60 |
61 | @NotNull
62 | @Override
63 | public String getNodeText(@NotNull PsiElement element, boolean useFullName) {
64 | // TODO: if variable definition get value set to variable
65 | return "";
66 | // if (element instanceof SimpleProperty) {
67 | // return ((SimpleProperty) element).getKey() + ":" + ((SimpleProperty) element).getValue();
68 | // } else {
69 | // return "";
70 | // }
71 | }
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/usage/RobotKeywordGroupingRuleProvider.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.usage;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.psi.PsiElement;
5 | import com.intellij.psi.util.PsiTreeUtil;
6 | import com.intellij.usages.PsiNamedElementUsageGroupBase;
7 | import com.intellij.usages.Usage;
8 | import com.intellij.usages.UsageGroup;
9 | import com.intellij.usages.impl.FileStructureGroupRuleProvider;
10 | import com.intellij.usages.rules.PsiElementUsage;
11 | import com.intellij.usages.rules.UsageGroupingRule;
12 | import com.millennialmedia.intellibot.psi.element.KeywordDefinitionImpl;
13 | import org.jetbrains.annotations.NotNull;
14 | import org.jetbrains.annotations.Nullable;
15 |
16 | /**
17 | * @author mrubino
18 | * @since 2016-01-28
19 | */
20 | public class RobotKeywordGroupingRuleProvider implements FileStructureGroupRuleProvider {
21 |
22 | @Nullable
23 | @Override
24 | public UsageGroupingRule getUsageGroupingRule(Project project) {
25 | return new RobotKeywordGroupingRule();
26 | }
27 |
28 | private static class RobotKeywordGroupingRule implements UsageGroupingRule {
29 |
30 | private RobotKeywordGroupingRule() {
31 | }
32 |
33 | public UsageGroup groupUsage(@NotNull Usage usage) {
34 | if (!(usage instanceof PsiElementUsage)) {
35 | return null;
36 | } else {
37 | PsiElement psiElement = ((PsiElementUsage) usage).getElement();
38 | KeywordDefinitionImpl definition = PsiTreeUtil.getParentOfType(psiElement, KeywordDefinitionImpl.class, false);
39 | return definition == null ? null : new PsiNamedElementUsageGroupBase(definition);
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/ide/usage/RobotWordScanner.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide.usage;
2 |
3 | import com.intellij.lang.cacheBuilder.DefaultWordsScanner;
4 | import com.intellij.psi.tree.TokenSet;
5 | import com.millennialmedia.intellibot.psi.RobotKeywordProvider;
6 | import com.millennialmedia.intellibot.psi.RobotLexer;
7 | import com.millennialmedia.intellibot.psi.RobotTokenTypes;
8 |
9 | /**
10 | * @author mrubino
11 | * @since 2015-12-22
12 | */
13 | public class RobotWordScanner extends DefaultWordsScanner {
14 |
15 | private static final TokenSet IDENTIFIERS = TokenSet.create(RobotTokenTypes.KEYWORD_DEFINITION, RobotTokenTypes.VARIABLE_DEFINITION);
16 | private static final TokenSet COMMENTS = TokenSet.create(RobotTokenTypes.COMMENT);
17 | private static final TokenSet LITERALS = TokenSet.create(RobotTokenTypes.ARGUMENT);
18 |
19 | public RobotWordScanner() {
20 | super(new RobotLexer(RobotKeywordProvider.getInstance()), IDENTIFIERS, COMMENTS, LITERALS);
21 | setMayHaveFileRefsInLiterals(true);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RecommendationWord.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | /**
6 | * @author mrubino
7 | * @since 2014-02-16
8 | */
9 | public class RecommendationWord {
10 |
11 | private final String presentation;
12 | private final String lookup;
13 |
14 | public RecommendationWord(@NotNull String presentation, @NotNull String lookup) {
15 | this.presentation = presentation;
16 | this.lookup = lookup;
17 | }
18 |
19 | @NotNull
20 | public String getPresentation() {
21 | return this.presentation;
22 | }
23 |
24 | @NotNull
25 | public String getLookup() {
26 | return this.lookup;
27 | }
28 |
29 | @Override
30 | public boolean equals(Object o) {
31 | if (this == o) return true;
32 | if (o == null || getClass() != o.getClass()) return false;
33 |
34 | RecommendationWord that = (RecommendationWord) o;
35 |
36 | if (!this.lookup.equals(that.lookup)) return false;
37 | //noinspection RedundantIfStatement
38 | if (!this.presentation.equals(that.presentation)) return false;
39 |
40 | return true;
41 | }
42 |
43 | @Override
44 | public int hashCode() {
45 | int result = this.presentation.hashCode();
46 | result = 31 * result + this.lookup.hashCode();
47 | return result;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RobotElementType.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import com.intellij.psi.tree.IElementType;
4 | import org.jetbrains.annotations.NonNls;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | public class RobotElementType extends IElementType {
8 | public RobotElementType(@NotNull @NonNls String debugName) {
9 | super(debugName, com.millennialmedia.intellibot.psi.RobotLanguage.INSTANCE);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RobotFeatureFileType.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import com.intellij.openapi.fileTypes.LanguageFileType;
4 | import com.millennialmedia.intellibot.ide.icons.RobotIcons;
5 | import org.jetbrains.annotations.NotNull;
6 | import org.jetbrains.annotations.Nullable;
7 |
8 | import javax.swing.*;
9 |
10 | /**
11 | * @author mrubino
12 | */
13 | public class RobotFeatureFileType extends LanguageFileType {
14 |
15 | private static final RobotFeatureFileType INSTANCE = new RobotFeatureFileType();
16 |
17 | private RobotFeatureFileType() {
18 | super(RobotLanguage.INSTANCE);
19 | }
20 |
21 | public static RobotFeatureFileType getInstance() {
22 | return INSTANCE;
23 | }
24 |
25 | @NotNull
26 | public String getName() {
27 | return "Robot Feature";
28 | }
29 |
30 | @NotNull
31 | public String getDescription() {
32 | return "Robot Feature Files";
33 | }
34 |
35 | @NotNull
36 | public String getDefaultExtension() {
37 | return "robot";
38 | }
39 |
40 | @Nullable
41 | public Icon getIcon() {
42 | return RobotIcons.FILE;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RobotFileTypeHandler.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import com.intellij.openapi.fileTypes.FileTypeConsumer;
4 | import com.intellij.openapi.fileTypes.FileTypeFactory;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | /**
8 | * @author mrubino
9 | */
10 | public class RobotFileTypeHandler extends FileTypeFactory {
11 |
12 | @Override
13 | public void createFileTypes(@NotNull FileTypeConsumer consumer) {
14 | consumer.consume(RobotFeatureFileType.getInstance());
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RobotHighlighter.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import com.intellij.lexer.Lexer;
4 | import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
5 | import com.intellij.openapi.editor.colors.TextAttributesKey;
6 | import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
7 | import com.intellij.psi.tree.IElementType;
8 | import gnu.trove.THashMap;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | import java.util.Map;
12 |
13 | /**
14 | * @author Stephen Abrams
15 | */
16 | public class RobotHighlighter extends SyntaxHighlighterBase {
17 | private static final Map keys1;
18 | private static final Map keys2;
19 |
20 | private final RobotKeywordProvider myKeywordProvider;
21 |
22 | public RobotHighlighter(RobotKeywordProvider keywordProvider) {
23 | this.myKeywordProvider = keywordProvider;
24 | }
25 |
26 | @NotNull
27 | public Lexer getHighlightingLexer() {
28 | return new RobotLexer(this.myKeywordProvider);
29 | }
30 |
31 | public static final TextAttributesKey HEADING = TextAttributesKey.createTextAttributesKey(
32 | RobotTokenTypes.HEADING.toString(),
33 | DefaultLanguageHighlighterColors.STRING
34 | );
35 |
36 | public static final TextAttributesKey SETTING = TextAttributesKey.createTextAttributesKey(
37 | RobotTokenTypes.SETTING.toString(),
38 | DefaultLanguageHighlighterColors.KEYWORD
39 | );
40 |
41 | public static final TextAttributesKey BRACKET_SETTING = TextAttributesKey.createTextAttributesKey(
42 | RobotTokenTypes.BRACKET_SETTING.toString(),
43 | DefaultLanguageHighlighterColors.DOC_COMMENT_TAG
44 | );
45 |
46 | public static final TextAttributesKey IMPORT = TextAttributesKey.createTextAttributesKey(
47 | RobotTokenTypes.IMPORT.toString(),
48 | DefaultLanguageHighlighterColors.DOC_COMMENT_TAG_VALUE
49 | );
50 |
51 | public static final TextAttributesKey KEYWORD_DEFINITION = TextAttributesKey.createTextAttributesKey(
52 | RobotTokenTypes.KEYWORD_DEFINITION.toString(),
53 | DefaultLanguageHighlighterColors.KEYWORD
54 | );
55 |
56 | public static final TextAttributesKey KEYWORD = TextAttributesKey.createTextAttributesKey(
57 | RobotTokenTypes.KEYWORD.toString(),
58 | DefaultLanguageHighlighterColors.FUNCTION_DECLARATION
59 | );
60 |
61 | public static final TextAttributesKey ARGUMENT = TextAttributesKey.createTextAttributesKey(
62 | RobotTokenTypes.ARGUMENT.toString(),
63 | DefaultLanguageHighlighterColors.STATIC_FIELD
64 | );
65 |
66 | public static final TextAttributesKey VARIABLE_DEFINITION = TextAttributesKey.createTextAttributesKey(
67 | RobotTokenTypes.VARIABLE_DEFINITION.toString(),
68 | DefaultLanguageHighlighterColors.MARKUP_ATTRIBUTE
69 | );
70 |
71 | public static final TextAttributesKey VARIABLE = TextAttributesKey.createTextAttributesKey(
72 | RobotTokenTypes.VARIABLE.toString(),
73 | DefaultLanguageHighlighterColors.DOC_COMMENT_MARKUP
74 | );
75 |
76 | public static final TextAttributesKey COMMENT = TextAttributesKey.createTextAttributesKey(
77 | RobotTokenTypes.COMMENT.toString(),
78 | DefaultLanguageHighlighterColors.LINE_COMMENT
79 | );
80 |
81 | public static final TextAttributesKey GHERKIN = TextAttributesKey.createTextAttributesKey(
82 | RobotTokenTypes.GHERKIN.toString(),
83 | DefaultLanguageHighlighterColors.METADATA
84 | );
85 |
86 | public static final TextAttributesKey ERROR = TextAttributesKey.createTextAttributesKey(
87 | RobotTokenTypes.ERROR.toString(),
88 | DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE
89 | );
90 |
91 | static {
92 | keys1 = new THashMap();
93 | keys2 = new THashMap();
94 |
95 | keys1.put(RobotTokenTypes.HEADING, HEADING);
96 | keys1.put(RobotTokenTypes.COMMENT, COMMENT);
97 | keys1.put(RobotTokenTypes.ARGUMENT, ARGUMENT);
98 | keys1.put(RobotTokenTypes.ERROR, ERROR);
99 | keys1.put(RobotTokenTypes.GHERKIN, GHERKIN);
100 | keys1.put(RobotTokenTypes.VARIABLE, VARIABLE);
101 | keys1.put(RobotTokenTypes.VARIABLE_DEFINITION, VARIABLE_DEFINITION);
102 | keys1.put(RobotTokenTypes.KEYWORD, KEYWORD);
103 | keys1.put(RobotTokenTypes.KEYWORD_DEFINITION, KEYWORD_DEFINITION);
104 | keys1.put(RobotTokenTypes.BRACKET_SETTING, BRACKET_SETTING);
105 | keys1.put(RobotTokenTypes.SETTING, SETTING);
106 | keys1.put(RobotTokenTypes.IMPORT, IMPORT);
107 | }
108 |
109 | @NotNull
110 | public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
111 | return pack(keys1.get(tokenType), keys2.get(tokenType));
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RobotKeywordTable.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | import java.util.*;
6 |
7 | public class RobotKeywordTable {
8 |
9 | private final Map> syntaxByType = new HashMap>();
10 | private final Map> recommendationsByType = new HashMap>();
11 |
12 | public void addSyntax(RobotElementType type, String keyword) {
13 | Set keywords = this.syntaxByType.get(type);
14 | if (keywords == null) {
15 | if (type == RobotTokenTypes.GHERKIN) {
16 | // this allows syntax for WHEN vs When vs when
17 | keywords = new TreeSet(String.CASE_INSENSITIVE_ORDER);
18 | } else {
19 | keywords = new HashSet();
20 | }
21 | this.syntaxByType.put(type, keywords);
22 | }
23 | keywords.add(keyword);
24 | }
25 |
26 | public void addRecommendation(@NotNull RobotElementType type, @NotNull String keyword, @NotNull String lookup) {
27 | Set keywords = this.recommendationsByType.get(type);
28 | if (keywords == null) {
29 | keywords = new HashSet();
30 | this.recommendationsByType.put(type, keywords);
31 | }
32 | keywords.add(new RecommendationWord(keyword, lookup));
33 | }
34 |
35 | @NotNull
36 | public Set getSyntaxOfType(RobotElementType type) {
37 | Set results = this.syntaxByType.get(type);
38 | return results == null ? Collections.emptySet() : results;
39 | }
40 |
41 | @NotNull
42 | public Set getRecommendationsForType(RobotElementType type) {
43 | Set results = this.recommendationsByType.get(type);
44 | return results == null ? Collections.emptySet() : results;
45 | }
46 | }
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RobotLanguage.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import com.intellij.lang.Language;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | /**
7 | * @author mrubino
8 | */
9 | public class RobotLanguage extends Language {
10 |
11 | public static final RobotLanguage INSTANCE = new RobotLanguage();
12 |
13 | private RobotLanguage() {
14 | super("Robot", "");
15 | }
16 |
17 | @NotNull
18 | @Override
19 | public String getDisplayName() {
20 | return "Robot";
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RobotParserDefinition.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.lang.ParserDefinition;
5 | import com.intellij.lang.PsiParser;
6 | import com.intellij.lexer.Lexer;
7 | import com.intellij.openapi.project.Project;
8 | import com.intellij.psi.FileViewProvider;
9 | import com.intellij.psi.PsiElement;
10 | import com.intellij.psi.PsiFile;
11 | import com.intellij.psi.tree.IFileElementType;
12 | import com.intellij.psi.tree.TokenSet;
13 | import com.intellij.psi.util.PsiUtilCore;
14 | import com.millennialmedia.intellibot.psi.element.*;
15 | import org.jetbrains.annotations.NotNull;
16 |
17 | /**
18 | * @author Stephen Abrams
19 | */
20 | public class RobotParserDefinition implements ParserDefinition {
21 |
22 | private static final TokenSet WHITESPACE_SET = TokenSet.create(RobotTokenTypes.WHITESPACE);
23 | private static final TokenSet COMMENTS_SET = TokenSet.create(RobotTokenTypes.COMMENT);
24 | private static final TokenSet STRING_SET = TokenSet.create(RobotTokenTypes.GHERKIN);
25 |
26 | @NotNull
27 | @Override
28 | public Lexer createLexer(Project project) {
29 | return new RobotLexer(RobotKeywordProvider.getInstance());
30 | }
31 |
32 | @Override
33 | public PsiParser createParser(Project project) {
34 | return new RobotParser();
35 | }
36 |
37 | @Override
38 | public IFileElementType getFileNodeType() {
39 | return RobotTokenTypes.FILE;
40 | }
41 |
42 | @NotNull
43 | @Override
44 | public TokenSet getWhitespaceTokens() {
45 | return WHITESPACE_SET;
46 | }
47 |
48 | @NotNull
49 | @Override
50 | public TokenSet getCommentTokens() {
51 | return COMMENTS_SET;
52 | }
53 |
54 | @NotNull
55 | @Override
56 | public TokenSet getStringLiteralElements() {
57 | return STRING_SET;
58 | }
59 |
60 | @NotNull
61 | @Override
62 | public PsiElement createElement(ASTNode node) {
63 | if (node.getElementType() == RobotTokenTypes.KEYWORD_DEFINITION) return new KeywordDefinitionImpl(node);
64 | if (node.getElementType() == RobotTokenTypes.KEYWORD_DEFINITION_ID) return new KeywordDefinitionIdImpl(node);
65 | if (node.getElementType() == RobotTokenTypes.KEYWORD_STATEMENT) return new KeywordStatementImpl(node);
66 | if (node.getElementType() == RobotTokenTypes.KEYWORD) return new KeywordInvokableImpl(node);
67 | if (node.getElementType() == RobotTokenTypes.VARIABLE_DEFINITION) return new VariableDefinitionImpl(node);
68 | if (node.getElementType() == RobotTokenTypes.VARIABLE_DEFINITION_ID) return new VariableDefinitionIdImpl(node);
69 | if (node.getElementType() == RobotTokenTypes.HEADING) return new HeadingImpl(node);
70 | if (node.getElementType() == RobotTokenTypes.ARGUMENT) return new ArgumentImpl(node);
71 | if (node.getElementType() == RobotTokenTypes.VARIABLE) return new VariableImpl(node);
72 | if (node.getElementType() == RobotTokenTypes.IMPORT) return new ImportImpl(node);
73 | if (node.getElementType() == RobotTokenTypes.SETTING) return new SettingImpl(node);
74 | if (node.getElementType() == RobotTokenTypes.BRACKET_SETTING) return new BracketSettingImpl(node);
75 |
76 | return PsiUtilCore.NULL_PSI_ELEMENT;
77 |
78 | }
79 |
80 | @Override
81 | public PsiFile createFile(FileViewProvider viewProvider) {
82 | return new RobotFileImpl(viewProvider);
83 | }
84 |
85 | @Override
86 | public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
87 | // TODO: guessing this is for code cleanup
88 | return null;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RobotPsiManager.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import com.intellij.openapi.components.ProjectComponent;
4 | import com.intellij.psi.PsiElement;
5 | import com.intellij.psi.impl.AbstractModificationTracker;
6 | import com.intellij.psi.impl.PsiManagerImpl;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | /**
10 | * @author mrubino
11 | */
12 | public class RobotPsiManager extends AbstractModificationTracker implements ProjectComponent {
13 |
14 | public RobotPsiManager(PsiManagerImpl psiManager) {
15 | super(psiManager);
16 | }
17 |
18 | @Override
19 | protected boolean isInsideCodeBlock(PsiElement element) {
20 | // TODO: usage?
21 | return false;
22 | }
23 |
24 | public void projectOpened() {
25 | // nothing
26 | }
27 |
28 | public void projectClosed() {
29 | // nothing
30 | }
31 |
32 | public void initComponent() {
33 | // nothing
34 | }
35 |
36 | public void disposeComponent() {
37 | // nothing
38 | }
39 |
40 | @NotNull
41 | public String getComponentName() {
42 | return "RobotPsiManager";
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RobotSyntaxHighlightingFactory.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import com.intellij.openapi.fileTypes.SyntaxHighlighter;
4 | import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
5 | import com.intellij.openapi.project.Project;
6 | import com.intellij.openapi.vfs.VirtualFile;
7 | import org.jetbrains.annotations.NotNull;
8 | import org.jetbrains.annotations.Nullable;
9 |
10 | /**
11 | * @author mrubino
12 | */
13 | public class RobotSyntaxHighlightingFactory extends SyntaxHighlighterFactory {
14 |
15 | @NotNull
16 | @Override
17 | public SyntaxHighlighter getSyntaxHighlighter(@Nullable Project project, @Nullable VirtualFile virtualFile) {
18 | return new RobotHighlighter(RobotKeywordProvider.getInstance());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/RobotTokenTypes.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import com.intellij.psi.tree.IFileElementType;
4 | import com.intellij.psi.tree.IStubFileElementType;
5 |
6 | public interface RobotTokenTypes {
7 |
8 | IFileElementType FILE = new IStubFileElementType(RobotLanguage.INSTANCE);
9 | RobotElementType HEADING = new RobotElementType("HEADING");
10 | RobotElementType SETTING = new RobotElementType("SETTING");
11 | RobotElementType BRACKET_SETTING = new RobotElementType("BRACKET_SETTING");
12 | RobotElementType IMPORT = new RobotElementType("IMPORT");
13 | RobotElementType KEYWORD_DEFINITION = new RobotElementType("KEYWORD_DEFINITION");
14 | RobotElementType KEYWORD_DEFINITION_ID = new RobotElementType("KEYWORD_DEFINITION_ID");
15 | RobotElementType KEYWORD = new RobotElementType("KEYWORD");
16 | RobotElementType ARGUMENT = new RobotElementType("ARGUMENT");
17 | RobotElementType VARIABLE_DEFINITION = new RobotElementType("VARIABLE_DEFINITION");
18 | RobotElementType VARIABLE_DEFINITION_ID = new RobotElementType("VARIABLE_DEFINITION_ID");
19 | RobotElementType VARIABLE = new RobotElementType("VARIABLE");
20 | RobotElementType COMMENT = new RobotElementType("COMMENT");
21 | RobotElementType GHERKIN = new RobotElementType("GHERKIN");
22 | RobotElementType KEYWORD_STATEMENT = new RobotElementType("KEYWORD_STATEMENT");
23 |
24 | RobotElementType ERROR = new RobotElementType("ERROR");
25 | RobotElementType WHITESPACE = new RobotElementType("WHITESPACE");
26 | }
27 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/dto/ImportType.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.dto;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 | import org.jetbrains.annotations.Nullable;
5 |
6 | import java.util.Map;
7 | import java.util.TreeMap;
8 |
9 | /**
10 | * @author mrubino
11 | * @since 2014-06-19
12 | */
13 | public enum ImportType {
14 |
15 | RESOURCE,
16 | LIBRARY,
17 | VARIABLES,
18 | UNKNOWN;
19 |
20 | private static final Map MAP;
21 |
22 | static {
23 | MAP = new TreeMap(String.CASE_INSENSITIVE_ORDER);
24 | MAP.put("resource", RESOURCE);
25 | MAP.put("resources", RESOURCE);
26 | MAP.put("library", LIBRARY);
27 | MAP.put("libraries", LIBRARY);
28 | MAP.put("variable", VARIABLES);
29 | MAP.put("variables", VARIABLES);
30 | }
31 |
32 | @NotNull
33 | public static ImportType getType(@Nullable String text) {
34 | ImportType result = MAP.get(text == null ? null : text.trim());
35 | return result == null ? UNKNOWN : result;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/dto/KeywordDto.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.dto;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.millennialmedia.intellibot.psi.element.DefinedKeyword;
5 | import com.millennialmedia.intellibot.psi.util.PatternBuilder;
6 | import com.millennialmedia.intellibot.psi.util.PatternUtil;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | import java.util.regex.Pattern;
10 |
11 | /**
12 | * This acts as a wrapper for python definitions.
13 | *
14 | * @author mrubino
15 | * @since 2014-06-06
16 | */
17 | public class KeywordDto implements DefinedKeyword {
18 |
19 |
20 |
21 | private final PsiElement reference;
22 | private final String name;
23 | private final boolean args;
24 | private final Pattern namePattern;
25 |
26 | public KeywordDto(@NotNull PsiElement reference, @NotNull String namespace, @NotNull String name, boolean args) {
27 | this.reference = reference;
28 | this.name = PatternUtil.functionToKeyword(name).trim();
29 | this.namePattern = Pattern.compile(PatternBuilder.parseNamespaceKeyword(namespace, this.name), Pattern.CASE_INSENSITIVE);
30 | this.args = args;
31 | }
32 |
33 | @Override
34 | public String getKeywordName() {
35 | return this.name;
36 | }
37 |
38 | @Override
39 | public boolean hasArguments() {
40 | return this.args;
41 | }
42 |
43 | @Override
44 | public boolean matches(String text) {
45 | return text != null &&
46 | this.namePattern.matcher(PatternUtil.functionToKeyword(text).trim()).matches();
47 | }
48 |
49 | @Override
50 | public PsiElement reference() {
51 | return this.reference;
52 | }
53 |
54 | @Override
55 | public boolean equals(Object o) {
56 | if (this == o) return true;
57 | if (o == null || getClass() != o.getClass()) return false;
58 |
59 | KeywordDto that = (KeywordDto) o;
60 |
61 | // I am not sure if we care about arguments in terms of uniqueness here
62 | return this.name.equals(that.name);
63 | }
64 |
65 | @Override
66 | public int hashCode() {
67 | return this.name.hashCode();
68 | }
69 |
70 | @Override
71 | public String toString() {
72 | return this.name;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/dto/VariableDto.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.dto;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.millennialmedia.intellibot.psi.element.DefinedVariable;
5 | import com.millennialmedia.intellibot.psi.util.PatternUtil;
6 | import com.millennialmedia.intellibot.psi.util.ReservedVariableScope;
7 | import org.jetbrains.annotations.NotNull;
8 | import org.jetbrains.annotations.Nullable;
9 |
10 | import java.util.regex.Pattern;
11 |
12 | /**
13 | * @author mrubino
14 | * @since 2014-06-18
15 | */
16 | public class VariableDto implements DefinedVariable {
17 |
18 | private final PsiElement reference;
19 | private final String name;
20 | private final ReservedVariableScope scope;
21 | private Pattern pattern;
22 |
23 | public VariableDto(@NotNull PsiElement reference, @NotNull String name, @Nullable ReservedVariableScope scope) {
24 | this.reference = reference;
25 | this.name = name.trim();
26 | this.scope = scope;
27 | }
28 |
29 | @Override
30 | public boolean matches(@Nullable String text) {
31 | if (text == null) {
32 | return false;
33 | }
34 | Pattern pattern = this.pattern;
35 | if (pattern == null) {
36 | pattern = Pattern.compile(PatternUtil.getVariablePattern(this.name), Pattern.CASE_INSENSITIVE);
37 | this.pattern = pattern;
38 | }
39 | return pattern.matcher(text).matches();
40 | }
41 |
42 | @Override
43 | public boolean isInScope(@Nullable PsiElement position) {
44 | return this.scope == null || position == null || this.scope.isInScope(position);
45 | }
46 |
47 | @Nullable
48 | @Override
49 | public PsiElement reference() {
50 | return this.reference;
51 | }
52 |
53 | @Nullable
54 | @Override
55 | public String getLookup() {
56 | return this.scope == null ? this.reference.getText() : this.name;
57 | }
58 |
59 | @Override
60 | public boolean equals(Object o) {
61 | if (this == o) return true;
62 | if (o == null || getClass() != o.getClass()) return false;
63 |
64 | VariableDto that = (VariableDto) o;
65 | return this.name.equals(that.name);
66 | }
67 |
68 | @Override
69 | public int hashCode() {
70 | return this.name.hashCode();
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/Argument.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.psi.PsiNamedElement;
4 |
5 | /**
6 | * @author Stephen Abrams
7 | */
8 | public interface Argument extends RobotStatement, PsiNamedElement {
9 | }
10 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/ArgumentImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.psi.PsiReference;
5 | import com.millennialmedia.intellibot.psi.ref.RobotArgumentReference;
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | /**
9 | * @author Stephen Abrams
10 | */
11 | public class ArgumentImpl extends RobotPsiElementBase implements Argument {
12 |
13 | public ArgumentImpl(@NotNull final ASTNode node) {
14 | super(node);
15 | }
16 |
17 | @Override
18 | public PsiReference getReference() {
19 | return new RobotArgumentReference(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/BracketSetting.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | /**
4 | * @author mrubino
5 | */
6 | public interface BracketSetting extends RobotStatement {
7 |
8 | /**
9 | * Determines if the current element is an '[Arguments]' element.
10 | *
11 | * @return true if this is an argument element; false otherwise.
12 | */
13 | boolean isArguments();
14 |
15 | /**
16 | * Determines if the current element is a '[Teardown]' element.
17 | *
18 | * @return true if this is a teardown element; false otherwise.
19 | */
20 | boolean isTeardown();
21 | }
22 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/BracketSettingImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | /**
7 | * @author mrubino
8 | */
9 | public class BracketSettingImpl extends RobotPsiElementBase implements BracketSetting {
10 |
11 | private static final String ARGUMENTS = "[Arguments]";
12 | private static final String TEARDOWN = "[Teardown]";
13 |
14 | public BracketSettingImpl(@NotNull final ASTNode node) {
15 | super(node);
16 | }
17 |
18 | @Override
19 | public boolean isArguments() {
20 | // TODO: better OO
21 | return ARGUMENTS.equalsIgnoreCase(getPresentableText());
22 | }
23 |
24 | @Override
25 | public boolean isTeardown() {
26 | // TODO: better OO
27 | return TEARDOWN.equalsIgnoreCase(getPresentableText());
28 | }
29 | }
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/DefinedKeyword.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.psi.PsiElement;
4 |
5 | /**
6 | * @author mrubino
7 | * @since 2014-06-06
8 | */
9 | public interface DefinedKeyword {
10 |
11 | String getKeywordName();
12 |
13 | /**
14 | * @return true if this keyword definition has the [Arguments] setting.
15 | */
16 | boolean hasArguments();
17 |
18 | boolean matches(String text);
19 |
20 | PsiElement reference();
21 | }
22 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/DefinedVariable.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import org.jetbrains.annotations.Nullable;
5 |
6 | /**
7 | * @author mrubino
8 | * @since 2014-06-18
9 | */
10 | public interface DefinedVariable {
11 |
12 | boolean matches(@Nullable String text);
13 |
14 | boolean isInScope(@Nullable PsiElement position);
15 |
16 | @Nullable
17 | PsiElement reference();
18 |
19 | @Nullable
20 | String getLookup();
21 | }
22 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/Heading.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.psi.PsiFile;
4 | import org.jetbrains.annotations.NotNull;
5 | import org.jetbrains.annotations.Nullable;
6 |
7 | import java.util.Collection;
8 |
9 | /**
10 | * @author Stephen Abrams
11 | */
12 | public interface Heading extends RobotStatement {
13 |
14 | boolean isSettings();
15 |
16 | boolean containsTestCases();
17 |
18 | boolean containsKeywordDefinitions();
19 |
20 | @NotNull
21 | Collection getImportedFiles();
22 |
23 | @NotNull
24 | Collection getDefinedKeywords();
25 |
26 | @NotNull
27 | Collection getTestCases();
28 |
29 | @NotNull
30 | Collection getFilesFromInvokedKeywordsAndVariables();
31 |
32 | @NotNull
33 | Collection getDefinedVariables();
34 |
35 | void importsChanged();
36 |
37 | @NotNull
38 | Collection getInvokedKeywords();
39 |
40 | @NotNull
41 | Collection getKeywordReferences(@Nullable KeywordDefinition definition);
42 | }
43 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/Import.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | /**
4 | * @author mrubino
5 | */
6 | public interface Import extends RobotStatement {
7 |
8 | boolean isResource();
9 |
10 | boolean isLibrary();
11 |
12 | boolean isVariables();
13 | }
14 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/ImportImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | /**
7 | * @author mrubino
8 | */
9 | public class ImportImpl extends RobotPsiElementBase implements Import {
10 |
11 | public ImportImpl(@NotNull final ASTNode node) {
12 | super(node);
13 | }
14 |
15 | public boolean isResource() {
16 | // TODO: better OO
17 | String text = getPresentableText();
18 | return text.equals("Resource");
19 | }
20 |
21 | public boolean isVariables() {
22 | // TODO: better OO
23 | String text = getPresentableText();
24 | return text.equals("Variables");
25 | }
26 |
27 | public boolean isLibrary() {
28 | // TODO: better OO
29 | String text = getPresentableText();
30 | return text.equals("Library");
31 | }
32 | }
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/KeywordDefinition.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.psi.PsiNamedElement;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import java.util.Collection;
7 | import java.util.List;
8 |
9 | /**
10 | * @author Stephen Abrams
11 | */
12 | public interface KeywordDefinition extends RobotStatement, PsiNamedElement {
13 |
14 | @NotNull
15 | List getInvokedKeywords();
16 |
17 | /**
18 | * This does not include variables that are saved globally as a result of calling this keyword.
19 | *
20 | * @return a list of variables as defined in the arguments of this keyword
21 | */
22 | @NotNull
23 | Collection getDeclaredVariables();
24 |
25 | /**
26 | * Determines if this keyword definition has inline variables defined within its name.
27 | *
28 | * @return true if there are inline variables defined, false otherwise.
29 | */
30 | boolean hasInlineVariables();
31 | }
32 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/KeywordDefinitionId.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | /**
4 | * @author mrubino
5 | * @since 2016-01-07
6 | */
7 | public interface KeywordDefinitionId extends RobotStatement {
8 | }
9 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/KeywordDefinitionIdImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | /**
7 | * @author mrubino
8 | * @since 2016-01-06
9 | */
10 | public class KeywordDefinitionIdImpl extends RobotPsiElementBase implements KeywordDefinitionId {
11 |
12 | public KeywordDefinitionIdImpl(@NotNull ASTNode node) {
13 | super(node);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/KeywordFile.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.millennialmedia.intellibot.psi.dto.ImportType;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import java.util.Collection;
7 |
8 | /**
9 | * Created with IntelliJ IDEA.
10 | * User: mrubino
11 | * Date: 1/28/14
12 | * Time: 8:01 PM
13 | */
14 | public interface KeywordFile {
15 |
16 | @NotNull
17 | Collection getDefinedKeywords();
18 |
19 | @NotNull
20 | Collection getDefinedVariables();
21 |
22 | @NotNull
23 | ImportType getImportType();
24 |
25 | @NotNull
26 | Collection getImportedFiles(boolean includeTransitive);
27 | }
28 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/KeywordInvokable.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.psi.PsiNamedElement;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | import java.util.Collection;
7 |
8 | /**
9 | * @author Stephen Abrams
10 | */
11 | public interface KeywordInvokable extends RobotStatement, PsiNamedElement {
12 |
13 | @NotNull
14 | Collection getArguments();
15 | }
16 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/KeywordInvokableImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.psi.PsiElement;
5 | import com.intellij.psi.PsiReference;
6 | import com.millennialmedia.intellibot.psi.ref.RobotKeywordReference;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | import java.util.Collection;
10 | import java.util.Collections;
11 |
12 | /**
13 | * @author Stephen Abrams
14 | */
15 | public class KeywordInvokableImpl extends RobotPsiElementBase implements KeywordInvokable {
16 |
17 | public KeywordInvokableImpl(@NotNull final ASTNode node) {
18 | super(node);
19 | }
20 |
21 | @NotNull
22 | @Override
23 | public Collection getArguments() {
24 | PsiElement parent = getParent();
25 | if (parent instanceof KeywordStatement) {
26 | return ((KeywordStatement) parent).getArguments();
27 | }
28 | return Collections.emptySet();
29 | }
30 |
31 | @Override
32 | public PsiReference getReference() {
33 | return new RobotKeywordReference(this);
34 | }
35 | }
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/KeywordStatement.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 | import org.jetbrains.annotations.Nullable;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @author mrubino
10 | */
11 | public interface KeywordStatement extends RobotStatement {
12 |
13 | @Nullable
14 | KeywordInvokable getInvokable();
15 |
16 | @NotNull
17 | List getArguments();
18 |
19 | @Nullable
20 | DefinedVariable getGlobalVariable();
21 | }
22 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/KeywordStatementImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.psi.PsiElement;
5 | import com.millennialmedia.intellibot.psi.dto.VariableDto;
6 | import com.millennialmedia.intellibot.psi.util.PatternUtil;
7 | import com.millennialmedia.intellibot.psi.util.PerformanceCollector;
8 | import com.millennialmedia.intellibot.psi.util.PerformanceEntity;
9 | import org.jetbrains.annotations.NotNull;
10 | import org.jetbrains.annotations.Nullable;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | /**
16 | * @author mrubino
17 | */
18 | public class KeywordStatementImpl extends RobotPsiElementBase implements KeywordStatement, PerformanceEntity {
19 |
20 | private List arguments;
21 | private DefinedVariable variable;
22 | private KeywordInvokable invokable;
23 |
24 | public KeywordStatementImpl(@NotNull ASTNode node) {
25 | super(node);
26 | }
27 |
28 | @Nullable
29 | @Override
30 | public KeywordInvokable getInvokable() {
31 | KeywordInvokable result = this.invokable;
32 | if (result == null) {
33 | PerformanceCollector debug = new PerformanceCollector(this, "invokable");
34 | result = collectInvokable();
35 | this.invokable = result;
36 | debug.complete();
37 | }
38 | return result;
39 | }
40 |
41 | @Nullable
42 | private KeywordInvokable collectInvokable() {
43 | for (PsiElement child : getChildren()) {
44 | if (child instanceof KeywordInvokable) {
45 | return (KeywordInvokable) child;
46 | }
47 | }
48 | return null;
49 | }
50 |
51 | @NotNull
52 | @Override
53 | public List getArguments() {
54 | List results = this.arguments;
55 | if (results == null) {
56 | PerformanceCollector debug = new PerformanceCollector(this, "arguments");
57 | results = collectArguments();
58 | this.arguments = results;
59 | debug.complete();
60 | }
61 | return results;
62 | }
63 |
64 | @NotNull
65 | private List collectArguments() {
66 | List results = new ArrayList();
67 | for (PsiElement element : getChildren()) {
68 | if (element instanceof Argument) {
69 | results.add((Argument) element);
70 | }
71 | }
72 | return results;
73 | }
74 |
75 | @Nullable
76 | @Override
77 | public DefinedVariable getGlobalVariable() {
78 | DefinedVariable result = this.variable;
79 | if (result == null) {
80 | PerformanceCollector debug = new PerformanceCollector(this, "global variable");
81 | result = collectGlobalVariable();
82 | this.variable = result;
83 | debug.complete();
84 | }
85 | return result;
86 | }
87 |
88 | @Nullable
89 | private DefinedVariable collectGlobalVariable() {
90 | KeywordInvokable invokable = getInvokable();
91 | if (invokable != null) {
92 | String text = invokable.getPresentableText();
93 | if (PatternUtil.isVariableSettingKeyword(text)) {
94 | List arguments = getArguments();
95 | if (arguments.size() > 0) {
96 | Argument variable = arguments.get(0);
97 | // already formatted ${X}
98 | return new VariableDto(variable, variable.getPresentableText(), null);
99 | }
100 | }
101 | }
102 | return null;
103 | }
104 |
105 | @Override
106 | public void subtreeChanged() {
107 | super.subtreeChanged();
108 | this.arguments = null;
109 | this.invokable = null;
110 | this.variable = null;
111 | }
112 |
113 | @NotNull
114 | @Override
115 | public String getDebugText() {
116 | KeywordInvokable invokable = getInvokable();
117 | String text = invokable == null ? null : getInvokable().getPresentableText();
118 | return text == null ? "EMPTY" : text;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/RobotFile.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.psi.PsiFile;
4 | import org.jetbrains.annotations.NotNull;
5 | import org.jetbrains.annotations.Nullable;
6 |
7 | import java.util.Collection;
8 |
9 | /**
10 | * @author Stephen Abrams
11 | */
12 | public interface RobotFile extends PsiFile {
13 |
14 | /**
15 | * @return locally defined keywords.
16 | */
17 | @NotNull
18 | Collection getDefinedKeywords();
19 |
20 | /**
21 | * @return all files that contain references to invoked keywords and used variables.
22 | */
23 | @NotNull
24 | Collection getFilesFromInvokedKeywordsAndVariables();
25 |
26 | /**
27 | * Gets all the imported keyword files that are considered in scope for this file. This
28 | * includes python libraries and robot resource files.
29 | *
30 | * @return a collection of keyword files that this files knows about.
31 | */
32 | @NotNull
33 | Collection getImportedFiles(boolean includeTransitive);
34 |
35 | @NotNull
36 | Collection getDefinedVariables();
37 |
38 | void importsChanged();
39 |
40 | @NotNull
41 | Collection getKeywordReferences(@Nullable KeywordDefinition definition);
42 | }
43 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/RobotFileImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.extapi.psi.PsiFileBase;
4 | import com.intellij.openapi.fileTypes.FileType;
5 | import com.intellij.psi.FileViewProvider;
6 | import com.intellij.psi.PsiElement;
7 | import com.intellij.psi.PsiFile;
8 | import com.millennialmedia.intellibot.psi.RobotFeatureFileType;
9 | import com.millennialmedia.intellibot.psi.RobotLanguage;
10 | import com.millennialmedia.intellibot.psi.dto.ImportType;
11 | import com.millennialmedia.intellibot.psi.util.PerformanceCollector;
12 | import com.millennialmedia.intellibot.psi.util.PerformanceEntity;
13 | import org.jetbrains.annotations.NotNull;
14 | import org.jetbrains.annotations.Nullable;
15 |
16 | import java.util.Collection;
17 | import java.util.HashSet;
18 | import java.util.LinkedHashSet;
19 |
20 | /**
21 | * @author Stephen Abrams
22 | */
23 | public class RobotFileImpl extends PsiFileBase implements RobotFile, KeywordFile, PerformanceEntity {
24 |
25 | private Collection headings;
26 |
27 | public RobotFileImpl(FileViewProvider viewProvider) {
28 | super(viewProvider, RobotLanguage.INSTANCE);
29 | }
30 |
31 | @NotNull
32 | @Override
33 | public FileType getFileType() {
34 | return RobotFeatureFileType.getInstance();
35 | }
36 |
37 | @Override
38 | public void subtreeChanged() {
39 | super.subtreeChanged();
40 | this.headings = null;
41 | }
42 |
43 | @NotNull
44 | @Override
45 | public Collection getDefinedVariables() {
46 | Collection results = new LinkedHashSet();
47 | for (Heading heading : getHeadings()) {
48 | results.addAll(heading.getDefinedVariables());
49 | }
50 | return results;
51 | }
52 |
53 | @NotNull
54 | @Override
55 | public ImportType getImportType() {
56 | return ImportType.RESOURCE;
57 | }
58 |
59 | @NotNull
60 | @Override
61 | public Collection getDefinedKeywords() {
62 | Collection results = new LinkedHashSet();
63 | for (Heading heading : getHeadings()) {
64 | results.addAll(heading.getDefinedKeywords());
65 | }
66 | return results;
67 | }
68 |
69 | @NotNull
70 | @Override
71 | public Collection getFilesFromInvokedKeywordsAndVariables() {
72 | Collection results = new HashSet();
73 | for (Heading heading : getHeadings()) {
74 | results.addAll(heading.getFilesFromInvokedKeywordsAndVariables());
75 | }
76 | return results;
77 | }
78 |
79 | @NotNull
80 | @Override
81 | public Collection getImportedFiles(boolean includeTransitive) {
82 | Collection results = new LinkedHashSet();
83 | for (Heading heading : getHeadings()) {
84 | for (KeywordFile file : heading.getImportedFiles()) {
85 | addKeywordFiles(results, file, includeTransitive);
86 | }
87 | }
88 | return results;
89 | }
90 |
91 | private void addKeywordFiles(Collection files, KeywordFile current, boolean includeTransitive) {
92 | if (files.add(current)) {
93 | if (includeTransitive) {
94 | for (KeywordFile file : current.getImportedFiles(false)) {
95 | addKeywordFiles(files, file, true);
96 | }
97 | }
98 | }
99 | }
100 |
101 | @Override
102 | public void importsChanged() {
103 | for (Heading heading : getHeadings()) {
104 | heading.importsChanged();
105 | }
106 | }
107 |
108 | @NotNull
109 | @Override
110 | public Collection getKeywordReferences(@Nullable KeywordDefinition definition) {
111 | Collection results = new LinkedHashSet();
112 | for (Heading heading : getHeadings()) {
113 | results.addAll(heading.getKeywordReferences(definition));
114 | }
115 | return results;
116 | }
117 |
118 | @NotNull
119 | private Collection getHeadings() {
120 | Collection results = this.headings;
121 | if (results == null) {
122 | PerformanceCollector debug = new PerformanceCollector(this, "headings");
123 | results = collectHeadings();
124 | this.headings = results;
125 | debug.complete();
126 | }
127 | return results;
128 | }
129 |
130 | @NotNull
131 | private Collection collectHeadings() {
132 | Collection results = new LinkedHashSet();
133 | for (PsiElement child : getChildren()) {
134 | if (child instanceof Heading) {
135 | results.add((Heading) child);
136 | }
137 | }
138 | return results;
139 | }
140 |
141 | @NotNull
142 | @Override
143 | public String getDebugFileName() {
144 | return getVirtualFile().getName();
145 | }
146 |
147 | @NotNull
148 | @Override
149 | public String getDebugText() {
150 | return ".";
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/RobotPsiElementBase.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.extapi.psi.ASTWrapperPsiElement;
4 | import com.intellij.lang.ASTNode;
5 | import com.intellij.navigation.ItemPresentation;
6 | import com.intellij.openapi.util.Iconable;
7 | import com.intellij.psi.PsiElement;
8 | import com.intellij.util.IncorrectOperationException;
9 | import com.millennialmedia.intellibot.psi.util.PatternUtil;
10 | import com.millennialmedia.intellibot.psi.util.PerformanceEntity;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | import javax.swing.*;
14 |
15 | /**
16 | * @author Stephen Abrams
17 | */
18 | public abstract class RobotPsiElementBase extends ASTWrapperPsiElement implements PerformanceEntity, RobotStatement {
19 |
20 | public RobotPsiElementBase(@NotNull final ASTNode node) {
21 | super(node);
22 | }
23 |
24 | @NotNull
25 | private static String toPresentableText(ASTNode node) {
26 | return PatternUtil.getPresentableText(node.getText());
27 | }
28 |
29 | @Override
30 | public ItemPresentation getPresentation() {
31 | return new ItemPresentation() {
32 | public String getPresentableText() {
33 | return RobotPsiElementBase.this.getPresentableText();
34 | }
35 |
36 | public String getLocationString() {
37 | return null;
38 | }
39 |
40 | public Icon getIcon(final boolean open) {
41 | return RobotPsiElementBase.this.getIcon(Iconable.ICON_FLAG_VISIBILITY);
42 | }
43 | };
44 | }
45 |
46 | @NotNull
47 | @Override
48 | public String getPresentableText() {
49 | return toPresentableText(getNode());
50 | }
51 |
52 | @NotNull
53 | @Override
54 | public String getDebugFileName() {
55 | return getContainingFile().getVirtualFile().getName();
56 | }
57 |
58 | @NotNull
59 | @Override
60 | public String getDebugText() {
61 | return getPresentableText();
62 | }
63 |
64 | @NotNull
65 | public String getName() {
66 | return getPresentableText();
67 | }
68 |
69 | public PsiElement setName(@NotNull String var1) throws IncorrectOperationException {
70 | // TODO: for renaming an element
71 | return this;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/RobotStatement.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | /**
7 | * @author mrubino
8 | * @since 2015-07-23
9 | */
10 | public interface RobotStatement extends PsiElement {
11 |
12 | @NotNull
13 | String getPresentableText();
14 | }
15 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/Setting.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | /**
4 | * @author mrubino
5 | */
6 | public interface Setting extends RobotStatement {
7 |
8 | /**
9 | * Determines if the current element is a 'Suite Teardown' element.
10 | *
11 | * @return true if this is a suite teardown element; false otherwise.
12 | */
13 | boolean isSuiteTeardown();
14 |
15 | /**
16 | * Determines if the current element is a 'Test Teardown' element.
17 | *
18 | * @return true if this is a test teardown element; false otherwise.
19 | */
20 | boolean isTestTeardown();
21 | }
22 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/SettingImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | /**
7 | * @author mrubino
8 | */
9 | public class SettingImpl extends RobotPsiElementBase implements Setting {
10 |
11 | private static final String SUITE_TEARDOWN = "Suite Teardown";
12 | private static final String TEST_TEARDOWN = "Test Teardown";
13 |
14 | public SettingImpl(@NotNull final ASTNode node) {
15 | super(node);
16 | }
17 |
18 | @Override
19 | public boolean isSuiteTeardown() {
20 | // TODO: better OO
21 | return SUITE_TEARDOWN.equalsIgnoreCase(getPresentableText());
22 | }
23 |
24 | @Override
25 | public boolean isTestTeardown() {
26 | // TODO: better OO
27 | return TEST_TEARDOWN.equalsIgnoreCase(getPresentableText());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/Variable.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | /**
4 | * @author mrubino
5 | * @since 2015-07-21
6 | */
7 | public interface Variable extends RobotStatement {
8 |
9 | boolean isNested();
10 | }
11 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/VariableDefinition.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.psi.PsiNamedElement;
4 |
5 | /**
6 | * @author mrubino
7 | */
8 | public interface VariableDefinition extends RobotStatement, PsiNamedElement {
9 |
10 | // TODO: this should go away once we identify the nesting correctly
11 | boolean isNested();
12 | }
13 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/VariableDefinitionId.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | /**
4 | * @author mrubino
5 | * @since 2016-04-01
6 | */
7 | public interface VariableDefinitionId extends RobotStatement {
8 | }
9 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/VariableDefinitionIdImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | /**
7 | * @author mrubino
8 | * @since 2016-04-01
9 | */
10 | public class VariableDefinitionIdImpl extends RobotPsiElementBase implements VariableDefinitionId {
11 |
12 | public VariableDefinitionIdImpl(@NotNull ASTNode node) {
13 | super(node);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/VariableDefinitionImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.openapi.util.text.StringUtil;
5 | import com.intellij.psi.PsiElement;
6 | import com.intellij.psi.PsiNameIdentifierOwner;
7 | import com.intellij.psi.util.PsiTreeUtil;
8 | import com.millennialmedia.intellibot.ide.icons.RobotIcons;
9 | import com.millennialmedia.intellibot.psi.util.PatternUtil;
10 | import org.jetbrains.annotations.NotNull;
11 | import org.jetbrains.annotations.Nullable;
12 |
13 | import javax.swing.*;
14 | import java.util.regex.Pattern;
15 |
16 | /**
17 | * @author mrubino
18 | */
19 | public class VariableDefinitionImpl extends RobotPsiElementBase implements VariableDefinition, DefinedVariable, PsiNameIdentifierOwner {
20 |
21 | private Pattern pattern;
22 |
23 | public VariableDefinitionImpl(@NotNull final ASTNode node) {
24 | super(node);
25 | }
26 |
27 | @Override
28 | public void subtreeChanged() {
29 | super.subtreeChanged();
30 | this.pattern = null;
31 | }
32 |
33 | @Override
34 | public boolean matches(String text) {
35 | if (text == null) {
36 | return false;
37 | }
38 | String myText = getPresentableText();
39 | Pattern pattern = this.pattern;
40 | if (pattern == null) {
41 | pattern = Pattern.compile(PatternUtil.getVariablePattern(myText), Pattern.CASE_INSENSITIVE);
42 | this.pattern = pattern;
43 | }
44 | return pattern.matcher(text).matches();
45 | }
46 |
47 | @Override
48 | public boolean isInScope(@Nullable PsiElement position) {
49 | return true;
50 | }
51 |
52 | @Nullable
53 | @Override
54 | public PsiElement reference() {
55 | return this;
56 | }
57 |
58 | @Nullable
59 | @Override
60 | public String getLookup() {
61 | return getText();
62 | }
63 |
64 | @Override
65 | public boolean isNested() {
66 | String text = getPresentableText();
67 | return StringUtil.getOccurrenceCount(text, "}") > 1 &&
68 | (StringUtil.getOccurrenceCount(text, "${") + StringUtil.getOccurrenceCount(text, "@{") + StringUtil.getOccurrenceCount(text, "%{") > 1);
69 | }
70 |
71 | @Override
72 | @NotNull
73 | public Icon getIcon(int flags) {
74 | return RobotIcons.VARIABLE_DEFINITION;
75 | }
76 |
77 | @Nullable
78 | @Override
79 | public PsiElement getNameIdentifier() {
80 | return PsiTreeUtil.findChildOfType(this, VariableDefinitionId.class);
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/element/VariableImpl.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.lang.ASTNode;
4 | import com.intellij.openapi.util.text.StringUtil;
5 | import com.intellij.psi.PsiReference;
6 | import com.millennialmedia.intellibot.psi.ref.RobotVariableReference;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | /**
10 | * @author mrubino
11 | * @since 2015-07-15
12 | */
13 | public class VariableImpl extends RobotPsiElementBase implements Variable {
14 |
15 | public VariableImpl(@NotNull final ASTNode node) {
16 | super(node);
17 | }
18 |
19 | @Override
20 | public PsiReference getReference() {
21 | return new RobotVariableReference(this);
22 | }
23 |
24 | @Override
25 | public boolean isNested() {
26 | // TODO: this should become a check if the parent is a variable or a variable definition once we identify the nesting correctly
27 | String text = getPresentableText();
28 | return StringUtil.getOccurrenceCount(text, "}") > 1 &&
29 | (StringUtil.getOccurrenceCount(text, "${") + StringUtil.getOccurrenceCount(text, "@{") + StringUtil.getOccurrenceCount(text, "%{") > 1);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/manip/ArgumentManipulator.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.manip;
2 |
3 | import com.intellij.openapi.util.TextRange;
4 | import com.intellij.psi.AbstractElementManipulator;
5 | import com.intellij.util.IncorrectOperationException;
6 | import com.millennialmedia.intellibot.psi.element.Argument;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | /**
10 | * we seem to need this but it is not really used at this time. it prevents NPEs for the jump to source.
11 | * we likely need it to do intelligent refactoring.
12 | *
13 | * @author Scott Albertine
14 | */
15 | public class ArgumentManipulator extends AbstractElementManipulator {
16 |
17 | @Override
18 | public Argument handleContentChange(@NotNull Argument element, @NotNull TextRange range,
19 | String newContent) throws IncorrectOperationException {
20 | return null;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/manip/KeywordInvokableManipulator.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.manip;
2 |
3 | import com.intellij.openapi.util.TextRange;
4 | import com.intellij.psi.AbstractElementManipulator;
5 | import com.intellij.util.IncorrectOperationException;
6 | import com.millennialmedia.intellibot.psi.element.KeywordInvokable;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | /**
10 | * we seem to need this but it is not really used at this time. it prevents NPEs for the jump to source.
11 | * we likely need it to do intelligent refactoring.
12 | *
13 | * @author mrubino
14 | */
15 | public class KeywordInvokableManipulator extends AbstractElementManipulator {
16 |
17 | @Override
18 | public KeywordInvokable handleContentChange(@NotNull KeywordInvokable element, @NotNull TextRange range,
19 | String newContent) throws IncorrectOperationException {
20 | return null;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/manip/VariableManipulator.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.manip;
2 |
3 | import com.intellij.openapi.util.TextRange;
4 | import com.intellij.psi.AbstractElementManipulator;
5 | import com.intellij.util.IncorrectOperationException;
6 | import com.millennialmedia.intellibot.psi.element.Argument;
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | /**
10 | * we seem to need this but it is not really used at this time. it prevents NPEs for the jump to source.
11 | * we likely need it to do intelligent refactoring.
12 | *
13 | * @author mrubino
14 | * @since 2015-07-21
15 | */
16 | public class VariableManipulator extends AbstractElementManipulator {
17 |
18 | @Override
19 | public Argument handleContentChange(@NotNull Argument element, @NotNull TextRange range,
20 | String newContent) throws IncorrectOperationException {
21 | return null;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/ref/RobotArgumentReference.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.ref;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiReferenceBase;
5 | import com.millennialmedia.intellibot.psi.element.Argument;
6 | import com.millennialmedia.intellibot.psi.element.Import;
7 | import com.millennialmedia.intellibot.psi.element.KeywordStatement;
8 | import com.millennialmedia.intellibot.psi.util.PerformanceCollector;
9 | import com.millennialmedia.intellibot.psi.util.PerformanceEntity;
10 | import org.jetbrains.annotations.NotNull;
11 | import org.jetbrains.annotations.Nullable;
12 |
13 | /**
14 | * @author Scott Albertine
15 | */
16 | public class RobotArgumentReference extends PsiReferenceBase {
17 |
18 | public RobotArgumentReference(@NotNull Argument element) {
19 | super(element, false);
20 | }
21 |
22 | @Nullable
23 | @Override
24 | public PsiElement resolve() {
25 | PsiElement parent = getElement().getParent();
26 | // TODO: potentially unsafe cast
27 | PerformanceCollector debug = new PerformanceCollector((PerformanceEntity) getElement(), "resolve");
28 | PsiElement result = null;
29 | // we only want to attempt to resolve a resource/library for the first argument
30 | if (parent instanceof Import) {
31 | PsiElement secondChild = getSecondChild(parent);
32 | if (secondChild == getElement()) {
33 | Import importElement = (Import) parent;
34 | if (importElement.isResource()) {
35 | result = resolveResource();
36 | } else if (importElement.isLibrary() || importElement.isVariables()) {
37 | result = resolveLibrary();
38 | }
39 | }
40 | } else if (parent instanceof KeywordStatement) {
41 | result = resolveKeyword();
42 | }
43 | debug.complete();
44 | return result;
45 | }
46 |
47 | private static PsiElement getSecondChild(PsiElement element) {
48 | if (element == null) {
49 | return null;
50 | }
51 | PsiElement[] children = element.getChildren();
52 | return children.length > 0 ? children[0] : null;
53 | }
54 |
55 | private PsiElement resolveKeyword() {
56 | Argument element = getElement();
57 | String keyword = element.getPresentableText();
58 | // all files we import are based off the file we are currently in
59 | return ResolverUtils.resolveKeywordFromFile(keyword, element.getContainingFile());
60 | }
61 |
62 | @Nullable
63 | private PsiElement resolveLibrary() {
64 | return RobotFileManager.findPython(getElement().getPresentableText(),
65 | getElement().getProject(), getElement());
66 | }
67 |
68 | private PsiElement resolveResource() {
69 | return RobotFileManager.findRobot(getElement().getPresentableText(),
70 | getElement().getProject(), getElement());
71 | }
72 |
73 | @NotNull
74 | @Override
75 | public Object[] getVariants() {
76 | return EMPTY_ARRAY;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/ref/RobotKeywordReference.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.ref;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiReferenceBase;
5 | import com.millennialmedia.intellibot.psi.element.KeywordInvokable;
6 | import com.millennialmedia.intellibot.psi.util.PerformanceCollector;
7 | import com.millennialmedia.intellibot.psi.util.PerformanceEntity;
8 | import org.jetbrains.annotations.NotNull;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | /**
12 | * @author mrubino
13 | */
14 | public class RobotKeywordReference extends PsiReferenceBase {
15 |
16 | public RobotKeywordReference(@NotNull KeywordInvokable element) {
17 | super(element, false);
18 | }
19 |
20 | @Nullable
21 | @Override
22 | public PsiElement resolve() {
23 | KeywordInvokable element = getElement();
24 | String keyword = element.getPresentableText();
25 | // all files we import are based off the file we are currently in
26 | // TODO: potentially unsafe cast
27 | PerformanceCollector debug = new PerformanceCollector((PerformanceEntity) element, "resolve");
28 | PsiElement results = ResolverUtils.resolveKeywordFromFile(keyword, element.getContainingFile());
29 | debug.complete();
30 | return results;
31 | }
32 |
33 | @NotNull
34 | @Override
35 | public Object[] getVariants() {
36 | return EMPTY_ARRAY;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/ref/RobotPythonClass.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.ref;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.jetbrains.python.psi.PyClass;
5 | import com.millennialmedia.intellibot.psi.dto.ImportType;
6 | import com.millennialmedia.intellibot.psi.element.DefinedKeyword;
7 | import com.millennialmedia.intellibot.psi.element.DefinedVariable;
8 | import com.millennialmedia.intellibot.psi.element.KeywordFile;
9 | import com.millennialmedia.intellibot.psi.util.PerformanceCollector;
10 | import com.millennialmedia.intellibot.psi.util.PerformanceEntity;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | import java.util.Collection;
14 | import java.util.Collections;
15 | import java.util.HashSet;
16 |
17 | /**
18 | * @author mrubino
19 | */
20 | public class RobotPythonClass extends RobotPythonWrapper implements KeywordFile, PerformanceEntity {
21 |
22 | private final String library;
23 | private final PyClass pythonClass;
24 | private final ImportType importType;
25 |
26 | public RobotPythonClass(@NotNull String library, @NotNull PyClass pythonClass, @NotNull ImportType importType) {
27 | this.library = library;
28 | this.pythonClass = pythonClass;
29 | this.importType = importType;
30 | }
31 |
32 | @NotNull
33 | @Override
34 | public Collection getDefinedKeywords() {
35 | final Collection results = new HashSet();
36 | PerformanceCollector debug = new PerformanceCollector(this, "get defined keywords");
37 | addDefinedKeywords(this.pythonClass, this.library, results);
38 | debug.complete();
39 | return results;
40 | }
41 |
42 | @NotNull
43 | @Override
44 | public Collection getDefinedVariables() {
45 | final Collection results = new HashSet();
46 | PerformanceCollector debug = new PerformanceCollector(this, "get defined variables");
47 | addDefinedVariables(this.pythonClass, results);
48 | debug.complete();
49 | return results;
50 | }
51 |
52 | @NotNull
53 | @Override
54 | public ImportType getImportType() {
55 | return this.importType;
56 | }
57 |
58 | @NotNull
59 | @Override
60 | public Collection getImportedFiles(boolean includeTransitive) {
61 | return Collections.emptyList();
62 | }
63 |
64 | @Override
65 | public boolean equals(Object o) {
66 | if (this == o) return true;
67 | if (o == null || getClass() != o.getClass()) return false;
68 |
69 | RobotPythonClass that = (RobotPythonClass) o;
70 | return this.library.equals(that.library) && this.pythonClass.equals(that.pythonClass);
71 | }
72 |
73 | @Override
74 | public int hashCode() {
75 | int result = this.library.hashCode();
76 | result = 31 * result + this.pythonClass.hashCode();
77 | return result;
78 | }
79 |
80 | @Override
81 | public String toString() {
82 | return this.library;
83 | }
84 |
85 | @NotNull
86 | @Override
87 | public String getDebugFileName() {
88 | return this.library;
89 | }
90 |
91 | @NotNull
92 | @Override
93 | public String getDebugText() {
94 | return this.pythonClass.getContainingFile().getVirtualFile().getName();
95 | }
96 |
97 | @NotNull
98 | @Override
99 | public Project getProject() {
100 | return this.pythonClass.getProject();
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/ref/RobotPythonFile.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.ref;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.jetbrains.python.psi.PyClass;
5 | import com.jetbrains.python.psi.PyFile;
6 | import com.jetbrains.python.psi.PyFunction;
7 | import com.jetbrains.python.psi.PyTargetExpression;
8 | import com.millennialmedia.intellibot.psi.dto.ImportType;
9 | import com.millennialmedia.intellibot.psi.dto.KeywordDto;
10 | import com.millennialmedia.intellibot.psi.dto.VariableDto;
11 | import com.millennialmedia.intellibot.psi.element.DefinedKeyword;
12 | import com.millennialmedia.intellibot.psi.element.DefinedVariable;
13 | import com.millennialmedia.intellibot.psi.element.KeywordFile;
14 | import com.millennialmedia.intellibot.psi.util.PerformanceCollector;
15 | import com.millennialmedia.intellibot.psi.util.PerformanceEntity;
16 | import com.millennialmedia.intellibot.psi.util.ReservedVariable;
17 | import org.jetbrains.annotations.NotNull;
18 |
19 | import java.util.Collection;
20 | import java.util.Collections;
21 | import java.util.HashSet;
22 |
23 | /**
24 | * @author mrubino
25 | * @since 2014-06-17
26 | */
27 | public class RobotPythonFile extends RobotPythonWrapper implements KeywordFile, PerformanceEntity {
28 |
29 | private static final String EMPTY = "";
30 |
31 | private final String library;
32 | private final PyFile pythonFile;
33 | private final ImportType importType;
34 |
35 | public RobotPythonFile(@NotNull String library, @NotNull PyFile pythonFile, @NotNull ImportType importType) {
36 | this.library = library;
37 | this.pythonFile = pythonFile;
38 | this.importType = importType;
39 | }
40 |
41 | @NotNull
42 | @Override
43 | public Collection getDefinedKeywords() {
44 | PerformanceCollector debug = new PerformanceCollector(this, "get defined keywords");
45 | Collection results = new HashSet();
46 | for (PyFunction function : this.pythonFile.getTopLevelFunctions()) {
47 | String keyword = functionToKeyword(function.getName());
48 | if (keyword != null) {
49 | results.add(new KeywordDto(function, this.library, keyword, hasArguments(function.getParameterList().getParameters())));
50 | }
51 | }
52 | for (PyTargetExpression expression : this.pythonFile.getTopLevelAttributes()) {
53 | String keyword = functionToKeyword(expression.getName());
54 | if (keyword != null) {
55 | results.add(new KeywordDto(expression, this.library, keyword, false));
56 | }
57 | }
58 | for (PyClass subClass : this.pythonFile.getTopLevelClasses()) {
59 | String namespace = subClass.getQualifiedName() == null ? EMPTY : subClass.getQualifiedName();
60 | addDefinedKeywords(subClass, namespace, results);
61 | }
62 | debug.complete();
63 | return results;
64 | }
65 |
66 | @NotNull
67 | @Override
68 | public Collection getDefinedVariables() {
69 | PerformanceCollector debug = new PerformanceCollector(this, "get defined variables");
70 | final Collection results = new HashSet();
71 | for (PyTargetExpression expression : this.pythonFile.getTopLevelAttributes()) {
72 | String keyword = expression.getName();
73 | if (keyword != null) {
74 | // not formatted ${X}, assume scalar
75 | results.add(new VariableDto(expression, ReservedVariable.wrapToScalar(keyword), null));
76 | }
77 | }
78 | for (PyClass subClass : this.pythonFile.getTopLevelClasses()) {
79 | addDefinedVariables(subClass, results);
80 | }
81 | debug.complete();
82 | return results;
83 | }
84 |
85 | @NotNull
86 | @Override
87 | public ImportType getImportType() {
88 | return this.importType;
89 | }
90 |
91 | @NotNull
92 | @Override
93 | public Collection getImportedFiles(boolean includeTransitive) {
94 | return Collections.emptyList();
95 | }
96 |
97 | @Override
98 | public boolean equals(Object o) {
99 | if (this == o) return true;
100 | if (o == null || getClass() != o.getClass()) return false;
101 |
102 | RobotPythonFile that = (RobotPythonFile) o;
103 | return this.library.equals(that.library) && this.pythonFile.equals(that.pythonFile);
104 | }
105 |
106 | @Override
107 | public int hashCode() {
108 | int result = this.library.hashCode();
109 | result = 31 * result + this.pythonFile.hashCode();
110 | return result;
111 | }
112 |
113 | @Override
114 | public String toString() {
115 | return this.library;
116 | }
117 |
118 | @NotNull
119 | @Override
120 | public String getDebugFileName() {
121 | return toString();
122 | }
123 |
124 | @NotNull
125 | @Override
126 | public String getDebugText() {
127 | return this.pythonFile.getContainingFile().getVirtualFile().getName();
128 | }
129 |
130 | @NotNull
131 | @Override
132 | public Project getProject() {
133 | return this.pythonFile.getProject();
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/ref/RobotPythonWrapper.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.ref;
2 |
3 | import com.intellij.util.Processor;
4 | import com.jetbrains.python.psi.*;
5 | import com.millennialmedia.intellibot.psi.dto.KeywordDto;
6 | import com.millennialmedia.intellibot.psi.dto.VariableDto;
7 | import com.millennialmedia.intellibot.psi.element.DefinedKeyword;
8 | import com.millennialmedia.intellibot.psi.element.DefinedVariable;
9 | import com.millennialmedia.intellibot.psi.util.ReservedVariable;
10 | import org.jetbrains.annotations.NotNull;
11 | import org.jetbrains.annotations.Nullable;
12 |
13 | import java.util.Collection;
14 |
15 | /**
16 | * @author mrubino
17 | * @since 2014-06-17
18 | */
19 | public abstract class RobotPythonWrapper {
20 |
21 | private static final String UNDERSCORE = "_";
22 | private static final String SELF = "self";
23 |
24 | protected static boolean hasArguments(@Nullable PyParameter[] parameters) {
25 | if (parameters == null || parameters.length == 0) {
26 | return false;
27 | }
28 |
29 | for (PyParameter parameter : parameters) {
30 | String name = parameter.getName();
31 | if (name != null && !SELF.equalsIgnoreCase(name)) {
32 | return true;
33 | }
34 | }
35 | return false;
36 | }
37 |
38 | protected static String functionToKeyword(@Nullable String function) {
39 | if (function == null || isPrivate(function)) {
40 | return null;
41 | } else {
42 | return function;
43 | }
44 | }
45 |
46 | protected static void addDefinedVariables(@NotNull PyClass pythonClass, @NotNull final Collection results) {
47 | pythonClass.visitClassAttributes(
48 | new Processor() {
49 | @Override
50 | public boolean process(PyTargetExpression expression) {
51 | String keyword = expression.getName();
52 | if (keyword != null && !isPrivate(keyword)) {
53 | // not formatted ${X}, assume scalar
54 | results.add(new VariableDto(expression, ReservedVariable.wrapToScalar(keyword), null));
55 | }
56 | return true;
57 | }
58 | },
59 | true,
60 | null
61 | );
62 | }
63 |
64 | private static boolean isPrivate(@NotNull String keyword) {
65 | // these keeps out intended private functions
66 | return keyword.startsWith(UNDERSCORE) || keyword.startsWith("ROBOT_LIBRARY_");
67 | }
68 |
69 | protected static void addDefinedKeywords(@NotNull PyClass pythonClass, @NotNull final String namespace, @NotNull final Collection results) {
70 | pythonClass.visitMethods(
71 | new Processor() {
72 |
73 | @Override
74 | public boolean process(PyFunction function) {
75 | String keyword = functionToKeyword(function.getName());
76 | if (keyword != null) {
77 | // Get info from @keyword
78 | PyDecoratorList decorators = function.getDecoratorList();
79 | if (decorators != null) {
80 | PyDecorator keyword_decorator = decorators.findDecorator("keyword");
81 | if (keyword_decorator != null) {
82 | if (keyword_decorator.hasArgumentList()) {
83 | // Get case 'name =' argument
84 | PyExpression kwa = keyword_decorator.getKeywordArgument("name");
85 | if (kwa != null) {
86 | keyword = kwa.getText().replaceAll("^\"|\"$", "");
87 | }
88 | else {
89 | // Otherwise, check if first argument is unnamed
90 | PyExpression[] kda = keyword_decorator.getArguments();
91 |
92 | // Argument exists and is unnamed
93 | if (kda.length > 0 && kda[0].getName() == null) {
94 | keyword = kda[0].getText().replaceAll("^\"|\"$", "");
95 | }
96 | }
97 | }
98 | }
99 | }
100 | results.add(new KeywordDto(function, namespace, keyword, hasArguments(function.getParameterList().getParameters())));
101 | }
102 | return true;
103 | }
104 | },
105 | true,
106 | null
107 | );
108 | pythonClass.visitClassAttributes(
109 | new Processor() {
110 |
111 | @Override
112 | public boolean process(PyTargetExpression expression) {
113 | String keyword = functionToKeyword(expression.getName());
114 | if (keyword != null) {
115 | results.add(new KeywordDto(expression, namespace, keyword, false));
116 | }
117 | return true;
118 | }
119 | },
120 | true,
121 | null
122 | );
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/ref/RobotVariableReference.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.ref;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.psi.PsiFile;
5 | import com.intellij.psi.PsiReferenceBase;
6 | import com.millennialmedia.intellibot.ide.config.RobotOptionsProvider;
7 | import com.millennialmedia.intellibot.psi.element.Variable;
8 | import org.jetbrains.annotations.NotNull;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | /**
12 | * @author Scott Albertine
13 | */
14 | public class RobotVariableReference extends PsiReferenceBase {
15 |
16 | public RobotVariableReference(@NotNull Variable element) {
17 | super(element, false);
18 | }
19 |
20 | @Nullable
21 | @Override
22 | public PsiElement resolve() {
23 | String text = getElement().getPresentableText();
24 | PsiElement parent = getElement().getParent();
25 | PsiElement results = ResolverUtils.resolveVariableFromStatement(text, parent,
26 | RobotOptionsProvider.getInstance(getElement().getProject()).allowGlobalVariables());
27 | if (results != null) {
28 | return results;
29 | }
30 | PsiFile file = getElement().getContainingFile();
31 | return ResolverUtils.resolveVariableFromFile(text, file);
32 | }
33 |
34 | @NotNull
35 | @Override
36 | public Object[] getVariants() {
37 | return EMPTY_ARRAY;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/util/PatternBuilder.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.util;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | import java.util.regex.Matcher;
6 | import java.util.regex.Pattern;
7 |
8 | public class PatternBuilder {
9 | private static final Pattern PATTERN = Pattern.compile("(.*?)(\\$\\{.*?\\})(.*)");
10 | private static final String ANY = ".*?";
11 | private static final String DOT = ".";
12 |
13 | @NotNull
14 | static private String parseFunction(@NotNull String keyword) {
15 | Matcher matcher = PATTERN.matcher(keyword);
16 | String result = "";
17 | if (matcher.matches()) {
18 | String start = matcher.group(1);
19 | String end = parseFunction(matcher.group(3));
20 |
21 | if (start.length() > 0) {
22 | result = Pattern.quote(start);
23 | }
24 | result += ANY;
25 | if (end.length() > 0) {
26 | result += end;
27 | }
28 | } else {
29 | result = !keyword.isEmpty() ? Pattern.quote(keyword) : keyword;
30 | }
31 | return result;
32 | }
33 |
34 | @NotNull
35 | static private String parseNamespace(@NotNull String namespace) {
36 | String result = "";
37 | if (!namespace.isEmpty()) {
38 | result = "(" + Pattern.quote(namespace + DOT) + ")?";
39 | }
40 | return result;
41 | }
42 |
43 |
44 | @NotNull
45 | static public String parseNamespaceKeyword(@NotNull String namespace, @NotNull String keyword) {
46 | return parseNamespace(namespace) + parseFunction(keyword);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/util/PatternUtil.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.util;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 | import org.jetbrains.annotations.Nullable;
5 |
6 | import java.util.Collection;
7 | import java.util.TreeSet;
8 | import java.util.regex.Pattern;
9 |
10 | /**
11 | * @author mrubino
12 | * @since 2014-06-19
13 | */
14 | public class PatternUtil {
15 |
16 | private static final Collection VARIABLE_SETTERS;
17 | private static final String EMPTY = "";
18 | private static final String SPACE = " ";
19 | private static final String SUPER_SPACE = " ";
20 | private static final String TAB = "\t";
21 | private static final String NEWLINE = "\n";
22 | private static final String UNDERSCORE = "_";
23 | private static final String EQUAL = "=";
24 | private static final String SCALAR_START = "${";
25 | private static final String LIST_START = "@{";
26 | private static final String ENVIRONMENT_START = "%{";
27 | private static final String DICTIONARY_START = "&{";
28 | private static final String VARIABLE_CLOSE = "}";
29 | private static final String VARIABLE_START_PATTERN = "[\\$\\@\\%\\&]\\{";
30 | private static final String VARIABLE_END_PATTERN = "((\\..*?)*?(\\[.*?\\])*?)*?\\}(\\[\\d+\\])?";
31 | private static final String VARIABLE_SEPARATOR = "[ _]*?";
32 |
33 | static {
34 | VARIABLE_SETTERS = new TreeSet(String.CASE_INSENSITIVE_ORDER);
35 | VARIABLE_SETTERS.add("set test variable");
36 | VARIABLE_SETTERS.add("set suite variable");
37 | VARIABLE_SETTERS.add("set global variable");
38 | }
39 |
40 | private PatternUtil() {
41 | }
42 |
43 | @NotNull
44 | public static String getVariablePattern(@NotNull String original) {
45 | String text = original.trim();
46 | if (text.length() == 0) {
47 | return text;
48 | }
49 | // strip any equals
50 | if (text.endsWith(EQUAL)) {
51 | text = text.substring(0, text.length() - 1);
52 | }
53 | text = text.trim();
54 | // strip the starting marker
55 | if (text.startsWith(SCALAR_START) || text.startsWith(LIST_START) ||
56 | text.startsWith(DICTIONARY_START) || text.startsWith(ENVIRONMENT_START)) {
57 | text = text.substring(2);
58 | }
59 | // strip the ending marker
60 | if (text.endsWith(VARIABLE_CLOSE)) {
61 | text = text.substring(0, text.length() - 1);
62 | }
63 | if (text.isEmpty()) {
64 | return original;
65 | }
66 | // put it all back together allowing for ' ' or '_' optionally anywhere
67 | StringBuilder pattern = new StringBuilder();
68 | pattern.append(VARIABLE_START_PATTERN);
69 | for (char c : text.toCharArray()) {
70 | if (c == '_' || c == ' ') {
71 | continue;
72 | }
73 | pattern.append(VARIABLE_SEPARATOR);
74 | pattern.append(Pattern.quote(Character.toString(c)));
75 | }
76 | pattern.append(VARIABLE_SEPARATOR);
77 | pattern.append(VARIABLE_END_PATTERN);
78 |
79 | return pattern.toString();
80 | }
81 |
82 | public static boolean isVariableSettingKeyword(String keyword) {
83 | return VARIABLE_SETTERS.contains(functionToKeyword(keyword));
84 | }
85 |
86 | @Nullable
87 | public static String functionToKeyword(@Nullable String function) {
88 | return function == null ? null : function.replaceAll(UNDERSCORE, SPACE).trim();
89 | }
90 |
91 | @NotNull
92 | public static String getPresentableText(@Nullable String text) {
93 | if (text == null) {
94 | return EMPTY;
95 | }
96 | int newLine = indexOf(text, NEWLINE);
97 | int tab = indexOf(text, TAB);
98 | int superSpace = indexOf(text, SUPER_SPACE);
99 |
100 | int index = Math.min(newLine, tab);
101 | index = Math.min(index, superSpace);
102 |
103 | return text.substring(0, index).trim();
104 | }
105 |
106 | private static int indexOf(@NotNull String text, @NotNull String string) {
107 | int index = text.indexOf(string);
108 | return index < 0 ? text.length() : index;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/util/PerformanceCollector.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.util;
2 |
3 | import com.intellij.notification.*;
4 | import com.millennialmedia.intellibot.ide.config.RobotOptionsProvider;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | /**
8 | * @author mrubino
9 | * @since 2014-06-26
10 | */
11 | public class PerformanceCollector {
12 |
13 | private static final String MILLISECONDS = "ms";
14 | private static final long MINIMUM = 500;
15 |
16 | private final String context;
17 | private final PerformanceEntity entity;
18 | private final long start;
19 |
20 | public PerformanceCollector(@NotNull PerformanceEntity entity, @NotNull String context) {
21 | this.entity = entity;
22 | this.context = context;
23 | this.start = System.currentTimeMillis();
24 | NotificationsConfiguration.getNotificationsConfiguration().register(
25 | "intellibot.debug", NotificationDisplayType.NONE);
26 | }
27 |
28 | public void complete() {
29 | if (RobotOptionsProvider.getInstance(this.entity.getProject()).isDebug()) {
30 | long duration = System.currentTimeMillis() - this.start;
31 | if (duration > MINIMUM) {
32 | String message = String.format("[%s][%s][%s] %d%s",
33 | this.entity.getDebugFileName(), this.context, this.entity.getDebugText(), duration, MILLISECONDS);
34 | Notifications.Bus.notify(new Notification("intellibot.debug", "Debug", message, NotificationType.INFORMATION));
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/com/millennialmedia/intellibot/psi/util/PerformanceEntity.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.util;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | /**
7 | * @author mrubino
8 | * @since 2014-06-27
9 | */
10 | public interface PerformanceEntity {
11 |
12 | @NotNull
13 | String getDebugFileName();
14 |
15 | @NotNull
16 | String getDebugText();
17 |
18 | @NotNull
19 | Project getProject();
20 | }
21 |
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/ResourceLoader.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot;
2 |
3 | import java.net.URL;
4 |
5 | /**
6 | * @author mrubino
7 | * @since 2014-06-19
8 | */
9 | public class ResourceLoader {
10 |
11 | private ResourceLoader() {
12 | }
13 |
14 | public static String getResourcePath(String path) {
15 | URL resource = ResourceLoader.class.getClassLoader().getResource(path);
16 | return resource == null ? null : resource.getFile();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/ide/AbstractRobotIdeTest.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide;
2 |
3 | import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
4 | import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
5 | import com.millennialmedia.intellibot.ResourceLoader;
6 |
7 | /**
8 | * @author mrubino
9 | * @since 2016-06-01
10 | */
11 | public abstract class AbstractRobotIdeTest extends LightPlatformCodeInsightFixtureTestCase {
12 |
13 | protected final String getTestFile() {
14 | return String.format("%s%s.robot", getTestDataPath(), getTestName(true));
15 | }
16 |
17 | @Override
18 | protected abstract String getBasePath();
19 |
20 | @Override
21 | protected final String getTestDataPath() {
22 | return ResourceLoader.getResourcePath(getBasePath());
23 | }
24 |
25 | protected final CodeInsightTestFixture getFixture() {
26 | return this.myFixture;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/ide/RobotFindUsagesTest.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide;
2 |
3 | import com.intellij.psi.PsiElement;
4 | import com.intellij.usageView.UsageInfo;
5 | import com.millennialmedia.intellibot.ide.config.RobotOptionsProvider;
6 |
7 | import java.util.*;
8 |
9 | /**
10 | * @author mrubino
11 | * @since 2016-06-01
12 | */
13 | public class RobotFindUsagesTest extends AbstractRobotIdeTest {
14 |
15 | public void testFindKeywordByDefinition() {
16 | assertUsages(
17 | doTest(getTestFile()),
18 | "calculator has been cleared",
19 | "calculator has been cleared"
20 | );
21 | }
22 |
23 | public void testFindKeywordByUsage() {
24 | assertUsages(
25 | doTest(getTestFile()),
26 | "calculator has been cleared",
27 | "calculator has been cleared"
28 | );
29 | }
30 |
31 | public void testFindInlineKeywordByDefinition() {
32 | assertUsages(
33 | doTest(getTestFile()),
34 | "user types \"1 + 1\"",
35 | "user types \"2 - 1\""
36 | );
37 | }
38 |
39 | public void testFindInlineKeywordByUsage() {
40 | assertUsages(
41 | doTest(getTestFile()),
42 | "user types \"1 + 1\"",
43 | "user types \"2 - 1\""
44 | );
45 | }
46 |
47 | public void testFindVariableByDefinition() {
48 | assertUsages(
49 | doTest(getTestFile()),
50 | "${var2}"
51 | );
52 | }
53 |
54 | public void testFindVariableByUsage() {
55 | assertUsages(
56 | doTest(getTestFile()),
57 | "${var2}"
58 | );
59 | }
60 |
61 | public void testFindInlineVariableByDefinition() {
62 | assertUsages(
63 | doTest(getTestFile()),
64 | "${expression}"
65 | );
66 | }
67 |
68 | public void testFindInlineVariableByUsage() {
69 | assertUsages(
70 | doTest(getTestFile()),
71 | "${expression}"
72 | );
73 | }
74 |
75 | private Collection doTest(String... files) {
76 | // TODO: seems bit hacky
77 | RobotOptionsProvider.getInstance(getFixture().getProject()).setInlineVariableSearch(true);
78 | return getFixture().testFindUsages(files);
79 | }
80 |
81 | /**
82 | * Checks that the usage info that we get for the test file matches our expectations. This
83 | * will sort the given usages based on appearance in file to ensure consistency.
84 | *
85 | * @param usages the results to check.
86 | * @param expected the expectations.
87 | */
88 | private void assertUsages(Collection usages, String... expected) {
89 | assertNotNull(usages);
90 | assertEquals(expected.length, usages.size());
91 | List sorted = sortUsages(usages);
92 | for (int i = 0; i < expected.length; i++) {
93 | assertEquals(expected[i], getUsageText(sorted.get(i)));
94 | }
95 | }
96 |
97 | private List sortUsages(Collection usages) {
98 | List sorted = new ArrayList(usages);
99 | Collections.sort(sorted, new Comparator() {
100 | @Override
101 | public int compare(UsageInfo o1, UsageInfo o2) {
102 | PsiElement e1 = o1.getElement();
103 | PsiElement e2 = o2.getElement();
104 | assertNotNull(e1);
105 | assertNotNull(e2);
106 | return Integer.compare(e1.getTextOffset(), e2.getTextOffset());
107 | }
108 | });
109 | return sorted;
110 | }
111 |
112 | private String getUsageText(UsageInfo usage) {
113 | PsiElement element = usage.getElement();
114 | assertNotNull(element);
115 | int start = element.getTextOffset();
116 | return getFixture().getFile().getText().substring(start, start + element.getTextLength());
117 | }
118 |
119 | @Override
120 | protected String getBasePath() {
121 | return "ide/usages/";
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/ide/RobotFoldingTest.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide;
2 |
3 | /**
4 | * @author mrubino
5 | * @since 2016-06-01
6 | */
7 | public class RobotFoldingTest extends AbstractRobotIdeTest {
8 |
9 | public void testKeywordFolding() {
10 | doTest();
11 | }
12 |
13 | private void doTest() {
14 | getFixture().testFoldingWithCollapseStatus(getTestFile());
15 | }
16 |
17 | @Override
18 | protected String getBasePath() {
19 | return "ide/folding/";
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/ide/RobotHighlightTest.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.ide;
2 |
3 | import com.intellij.openapi.editor.markup.RangeHighlighter;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 | import java.util.Comparator;
8 | import java.util.List;
9 |
10 | /**
11 | * @author mrubino
12 | * @since 2016-06-01
13 | */
14 | public class RobotHighlightTest extends AbstractRobotIdeTest {
15 |
16 | public void testFindKeywordByDefinition() {
17 | assertHighlights(
18 | doTest(getTestFile()),
19 | "calculator has been cleared",
20 | "calculator has been cleared",
21 | "Calculator has been cleared"
22 | );
23 | }
24 |
25 | public void testFindKeywordByUsage() {
26 | assertHighlights(
27 | doTest(getTestFile()),
28 | "calculator has been cleared",
29 | "calculator has been cleared",
30 | "Calculator has been cleared"
31 | );
32 | }
33 |
34 | public void testFindInlineKeywordByDefinition() {
35 | assertHighlights(
36 | doTest(getTestFile()),
37 | "user types \"1 + 1\"",
38 | "user types \"2 - 1\"",
39 | "User types \"${expression}\""
40 | );
41 | }
42 |
43 | public void testFindInlineKeywordByUsage() {
44 | assertHighlights(
45 | doTest(getTestFile()),
46 | "user types \"1 + 1\"",
47 | "user types \"2 - 1\"",
48 | "User types \"${expression}\""
49 | );
50 | }
51 |
52 | public void testFindVariableByDefinition() {
53 | assertHighlights(
54 | doTest(getTestFile()),
55 | "${var2}",
56 | "${var2}"
57 | );
58 | }
59 |
60 | public void testFindVariableByUsage() {
61 | assertHighlights(
62 | doTest(getTestFile()),
63 | "${var2}",
64 | "${var2}"
65 | );
66 | }
67 |
68 | public void testFindInlineVariableByDefinition() {
69 | assertHighlights(
70 | doTest(getTestFile()),
71 | "${expression}",
72 | "${expression}"
73 | );
74 | }
75 |
76 | public void testFindInlineVariableByUsage() {
77 | assertHighlights(
78 | doTest(getTestFile()),
79 | "${expression}",
80 | "${expression}"
81 | );
82 | }
83 |
84 | private RangeHighlighter[] doTest(String... files) {
85 | return getFixture().testHighlightUsages(files);
86 | }
87 |
88 |
89 | /**
90 | * Checks that the highlights that we get for the test file matches our expectations. This
91 | * will sort the given highlights based on appearance in file to ensure consistency.
92 | *
93 | * @param highlights the results to check.
94 | * @param expected the expectations.
95 | */
96 | private void assertHighlights(RangeHighlighter[] highlights, String... expected) {
97 | assertNotNull(highlights);
98 | assertEquals(expected.length, highlights.length);
99 | List sorted = sortHighlights(highlights);
100 | for (int i = 0; i < expected.length; i++) {
101 | assertEquals(expected[i], getHighlightText(sorted.get(i)));
102 | }
103 | }
104 |
105 | private List sortHighlights(RangeHighlighter[] highlights) {
106 | List sorted = new ArrayList(highlights.length);
107 | Collections.addAll(sorted, highlights);
108 | Collections.sort(sorted, new Comparator() {
109 | @Override
110 | public int compare(RangeHighlighter o1, RangeHighlighter o2) {
111 | return Integer.compare(o1.getStartOffset(), o2.getStartOffset());
112 | }
113 | });
114 | return sorted;
115 | }
116 |
117 | private String getHighlightText(RangeHighlighter highlight) {
118 | return getFixture().getFile().getText().substring(highlight.getStartOffset(), highlight.getEndOffset());
119 | }
120 |
121 | @Override
122 | protected String getBasePath() {
123 | return "ide/usages/";
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/psi/RobotParserTest.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi;
2 |
3 | import com.intellij.testFramework.ParsingTestCase;
4 | import com.millennialmedia.intellibot.ResourceLoader;
5 | import org.junit.Test;
6 |
7 | @SuppressWarnings("JUnit4AnnotatedMethodInJUnit3TestCase")
8 | public class RobotParserTest extends ParsingTestCase {
9 |
10 | public RobotParserTest() {
11 | super("", "robot", new RobotParserDefinition());
12 | }
13 |
14 | @Test
15 | public void testParsingTestData() {
16 | doTest(true);
17 | }
18 |
19 | @Test
20 | public void testJunk() {
21 | doTest(true);
22 | }
23 |
24 | @Test
25 | public void testVariables() {
26 | doTest(true);
27 | }
28 |
29 | @Test
30 | public void testTrimmedVariables() {
31 | doTest(true);
32 | }
33 |
34 | @Test
35 | public void testEmptyHeaders() {
36 | doTest(true);
37 | }
38 |
39 | @Test
40 | public void testDemo() {
41 | doTest(true);
42 | }
43 |
44 | @Override
45 | protected String getTestDataPath() {
46 | return ResourceLoader.getResourcePath("samples");
47 | }
48 |
49 | @Override
50 | protected boolean skipSpaces() {
51 | return true;
52 | }
53 |
54 | @Override
55 | protected boolean includeRanges() {
56 | return true;
57 | }
58 | }
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/psi/element/KeywordDefinitionTest.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.element;
2 |
3 | import com.intellij.psi.impl.source.DummyHolderElement;
4 | import org.junit.Test;
5 | import org.junit.runner.RunWith;
6 | import org.junit.runners.Parameterized;
7 |
8 | import java.lang.reflect.InvocationTargetException;
9 | import java.lang.reflect.Method;
10 | import java.util.Arrays;
11 | import java.util.Collection;
12 | import java.util.regex.Pattern;
13 |
14 | import static org.junit.Assert.assertEquals;
15 | import static org.junit.Assert.assertTrue;
16 |
17 | /**
18 | * @author mrubino
19 | * @since 2014-06-08
20 | */
21 | @RunWith(Parameterized.class)
22 | public class KeywordDefinitionTest {
23 |
24 | private String namespace;
25 | private String keyword;
26 | private String pattern;
27 |
28 | public KeywordDefinitionTest(String namespace, String keyword, String pattern) {
29 | this.namespace = namespace;
30 | this.keyword = keyword;
31 | this.pattern = pattern;
32 | }
33 |
34 | @Test
35 | public void testBuildPattern() {
36 | try {
37 | Method method = KeywordDefinitionImpl.class.getDeclaredMethod("buildPattern", String.class, String.class);
38 | method.setAccessible(true);
39 | String actual = (String) method.invoke(new KeywordDefinitionImpl(new DummyHolderElement("dummy")), this.namespace, this.keyword);
40 | assertEquals(this.pattern, actual);
41 |
42 | assertTrue(Pattern.compile(actual).matcher(this.keyword).matches());
43 | String temp = this.keyword.replace("${variable1}", "junk")
44 | .replace("${variable2}", "junk2")
45 | .replace("${date_range}", "Yesterday");
46 | assertTrue(Pattern.compile(actual).matcher(temp).matches());
47 | assertTrue(Pattern.compile(actual).matcher(this.namespace + "." + temp).matches());
48 | } catch (InvocationTargetException e) {
49 | throw new RuntimeException(e);
50 | } catch (NoSuchMethodException e) {
51 | throw new RuntimeException(e);
52 | } catch (IllegalAccessException e) {
53 | throw new RuntimeException(e);
54 | }
55 | }
56 |
57 | @Parameterized.Parameters
58 | public static Collection patterns() {
59 | return Arrays.asList(new Object[][]{
60 | {"my_file", "This is a test keyword", "(\\Qmy_file.\\E)?\\QThis is a test keyword\\E"},
61 | {"my_file", "This is a test keyword with some ${crap in it", "(\\Qmy_file.\\E)?\\QThis is a test keyword with some ${crap in it\\E"},
62 | {"my_file", "This is a ${variable1} keyword", "(\\Qmy_file.\\E)?\\QThis is a \\E.*?\\Q keyword\\E"},
63 | {"my_file", "Set the date range to \"${date_range}\"", "(\\Qmy_file.\\E)?\\QSet the date range to \"\\E.*?\\Q\"\\E"},
64 | {"my_file", "This is a keyword with a ${variable1}", "(\\Qmy_file.\\E)?\\QThis is a keyword with a \\E.*?"},
65 | {"my_file", "${variable1} keyword am I", "(\\Qmy_file.\\E)?.*?\\Q keyword am I\\E"},
66 | {"my_file", "This is a ${variable1} keyword times ${variable2}", "(\\Qmy_file.\\E)?\\QThis is a \\E.*?\\Q keyword times \\E.*?"}
67 | });
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/psi/ref/RobotFileManagerTest.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.ref;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.junit.runners.Parameterized;
6 |
7 | import java.lang.reflect.InvocationTargetException;
8 | import java.lang.reflect.Method;
9 | import java.util.Arrays;
10 | import java.util.Collection;
11 |
12 | import static junit.framework.TestCase.assertNotNull;
13 | import static org.junit.Assert.assertEquals;
14 |
15 | /**
16 | * @author mrubino
17 | * @since 2014-06-18
18 | */
19 | @RunWith(Parameterized.class)
20 | public class RobotFileManagerTest {
21 |
22 | private String path;
23 | private String suffix;
24 | private String[] expected;
25 |
26 | public RobotFileManagerTest(String path, String suffix, String[] expected) {
27 | this.path = path;
28 | this.suffix = suffix;
29 | this.expected = expected;
30 | }
31 |
32 |
33 | @Test
34 | public void testGetFilename() {
35 | try {
36 | Method method = RobotFileManager.class.getDeclaredMethod("getFilename", String.class, String.class);
37 | method.setAccessible(true);
38 | String[] actual = (String[]) method.invoke(null, this.path, this.suffix);
39 | assertNotNull(actual);
40 | assertEquals(2, actual.length);
41 | assertEquals(this.expected[0], actual[0]);
42 | assertEquals(this.expected[1], actual[1]);
43 | } catch (InvocationTargetException e) {
44 | throw new RuntimeException(e);
45 | } catch (NoSuchMethodException e) {
46 | throw new RuntimeException(e);
47 | } catch (IllegalAccessException e) {
48 | throw new RuntimeException(e);
49 | }
50 | }
51 |
52 | @Parameterized.Parameters
53 | public static Collection files() {
54 | return Arrays.asList(new Object[][]{
55 | {"google_response_files_utils.robot", "", new String[]{"", "google_response_files_utils.robot"}},
56 | {"kyle/web/ui_login_page.robot", "", new String[]{"kyle/web/", "ui_login_page.robot"}},
57 | {"utils", ".py", new String[] {"", "utils.py"}},
58 | {"utils.py", ".py", new String[] {"", "utils.py"}},
59 | {"kyle/data/archive/users", ".py", new String[] {"kyle/data/archive/", "users.py"}},
60 | {"kyle/data/archive/users.py", ".py", new String[] {"kyle/data/archive/", "users.py"}}
61 | });
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/psi/util/KeywordParserTest.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.util;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.junit.runners.Parameterized;
6 |
7 | import java.util.Arrays;
8 | import java.util.Collection;
9 | import java.util.regex.Pattern;
10 |
11 | import static org.junit.Assert.assertEquals;
12 | import static org.junit.Assert.assertTrue;
13 |
14 | @RunWith(Parameterized.class)
15 | public class KeywordParserTest {
16 |
17 | private String namespace;
18 | private String keyword;
19 | private String pattern;
20 |
21 | public KeywordParserTest(String namespace, String keyword, String pattern) {
22 | this.namespace = namespace;
23 | this.keyword = keyword;
24 | this.pattern = pattern;
25 | }
26 |
27 | @Test
28 | public void testBuildPattern() throws Throwable {
29 | String actual = PatternBuilder.parseNamespaceKeyword(namespace, keyword);
30 | assertEquals(pattern, actual);
31 |
32 | assertTrue(Pattern.compile(actual).matcher(keyword).matches());
33 | String temp = keyword.replace("${variable1}", "junk")
34 | .replace("${variable2}", "junk2")
35 | .replace("${date_range}", "Yesterday");
36 | assertTrue(Pattern.compile(actual).matcher(temp).matches());
37 | assertTrue(Pattern.compile(actual).matcher(namespace + "." + temp).matches());
38 | }
39 |
40 | @Parameterized.Parameters
41 | public static Collection patterns() {
42 | return Arrays.asList(new Object[][]{
43 | {"my_file", "This is a test keyword", "(\\Qmy_file.\\E)?\\QThis is a test keyword\\E"},
44 | {"my_file", "This is a test keyword with some ${crap in it", "(\\Qmy_file.\\E)?\\QThis is a test keyword with some ${crap in it\\E"},
45 | {"my_file", "This is a ${variable1} keyword", "(\\Qmy_file.\\E)?\\QThis is a \\E.*?\\Q keyword\\E"},
46 | {"my_file", "Set the date range to \"${date_range}\"", "(\\Qmy_file.\\E)?\\QSet the date range to \"\\E.*?\\Q\"\\E"},
47 | {"my_file", "This is a keyword with a ${variable1}", "(\\Qmy_file.\\E)?\\QThis is a keyword with a \\E.*?"},
48 | {"my_file", "${variable1} keyword am I", "(\\Qmy_file.\\E)?.*?\\Q keyword am I\\E"},
49 | {"my_file", "This is a ${variable1} keyword times ${variable2}", "(\\Qmy_file.\\E)?\\QThis is a \\E.*?\\Q keyword times \\E.*?"}
50 | });
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/psi/util/PatternUtilBuildPatternTest.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.util;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.junit.runners.Parameterized;
6 |
7 | import java.util.Arrays;
8 | import java.util.Collection;
9 | import java.util.regex.Pattern;
10 |
11 | import static org.junit.Assert.assertEquals;
12 | import static org.junit.Assert.assertTrue;
13 |
14 | /**
15 | * @author mrubino
16 | * @since 2014-06-19
17 | */
18 | @RunWith(Parameterized.class)
19 | public class PatternUtilBuildPatternTest {
20 |
21 | private static final String EXPECTED = "[\\$\\@\\%\\&]\\{[ _]*?\\Qv\\E[ _]*?\\Qa\\E[ _]*?\\Qr\\E[ _]*?\\Qi\\E[ _]*?\\Qa\\E[ _]*?\\Qb\\E[ _]*?\\Ql\\E[ _]*?\\Qe\\E[ _]*?((\\..*?)*?(\\[.*?\\])*?)*?\\}(\\[\\d+\\])?";
22 | private String name;
23 | private String expected;
24 |
25 | public PatternUtilBuildPatternTest(String name, String expected) {
26 | this.name = name;
27 | this.expected = expected;
28 | }
29 |
30 | @Parameterized.Parameters
31 | public static Collection patterns() {
32 | return Arrays.asList(new Object[][]{
33 | {"variable", EXPECTED},
34 | {"${variable}", EXPECTED},
35 | {"${var_i able}", EXPECTED},
36 | {"${variable}=", EXPECTED},
37 | {"${variable} =", EXPECTED},
38 | {" ${variable} = ", EXPECTED},
39 | {"@{variable}", EXPECTED},
40 | {"@{var_i able}", EXPECTED},
41 | {"@{variable}=", EXPECTED},
42 | {"@{variable} =", EXPECTED},
43 | {" @{variable} = ", EXPECTED},
44 | {"%{variable}", EXPECTED},
45 | {"%{var_i able}", EXPECTED},
46 | {"%{variable}=", EXPECTED},
47 | {"%{variable} =", EXPECTED},
48 | {" %{variable} = ", EXPECTED},
49 | {"&{variable}", EXPECTED},
50 | {"&{var_i able}", EXPECTED},
51 | {"&{variable}=", EXPECTED},
52 | {"&{variable} =", EXPECTED},
53 | {" &{variable} = ", EXPECTED},
54 | });
55 | }
56 |
57 | @Test
58 | public void testBuildPattern() {
59 | String actual = PatternUtil.getVariablePattern(this.name);
60 | assertEquals(this.expected, actual);
61 | Pattern pattern = Pattern.compile(actual);
62 | // TODO: asserts that either [@,$,%,&] are interchangeable in terms of variable matching/linking; acceptable?
63 | assertTrue(pattern.matcher("${variable}").matches());
64 | assertTrue(pattern.matcher("${var i_able}").matches());
65 | assertTrue(pattern.matcher("${var i__able}").matches());
66 | assertTrue(pattern.matcher("${variable['a']['b']}").matches());
67 | assertTrue(pattern.matcher("${variable['a'].name}").matches());
68 | assertTrue(pattern.matcher("${variable.name}").matches());
69 | assertTrue(pattern.matcher("${variable.name['a']}").matches());
70 |
71 | assertTrue(pattern.matcher("@{variable}").matches());
72 | assertTrue(pattern.matcher("@{var i_able}").matches());
73 | assertTrue(pattern.matcher("@{var i__able}").matches());
74 | assertTrue(pattern.matcher("@{variable['a']['b']}").matches());
75 | assertTrue(pattern.matcher("@{variable['a'].name}").matches());
76 | assertTrue(pattern.matcher("@{variable.name}").matches());
77 | assertTrue(pattern.matcher("@{variable.name['a']}").matches());
78 |
79 | assertTrue(pattern.matcher("%{variable}").matches());
80 | assertTrue(pattern.matcher("%{var i_able}").matches());
81 | assertTrue(pattern.matcher("%{var i__able}").matches());
82 | assertTrue(pattern.matcher("%{variable['a']['b']}").matches());
83 | assertTrue(pattern.matcher("%{variable['a'].name}").matches());
84 | assertTrue(pattern.matcher("%{variable.name}").matches());
85 | assertTrue(pattern.matcher("%{variable.name['a']}").matches());
86 |
87 | assertTrue(pattern.matcher("&{variable}").matches());
88 | assertTrue(pattern.matcher("&{var i_able}").matches());
89 | assertTrue(pattern.matcher("&{var i__able}").matches());
90 | assertTrue(pattern.matcher("&{variable['a']['b']}").matches());
91 | assertTrue(pattern.matcher("&{variable['a'].name}").matches());
92 | assertTrue(pattern.matcher("&{variable.name}").matches());
93 | assertTrue(pattern.matcher("&{variable.name['a']}").matches());
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/test/com/millennialmedia/intellibot/psi/util/PatternUtilGetPresentableTextTest.java:
--------------------------------------------------------------------------------
1 | package com.millennialmedia.intellibot.psi.util;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.junit.runners.Parameterized;
6 |
7 | import java.util.Arrays;
8 | import java.util.Collection;
9 |
10 | import static org.junit.Assert.assertEquals;
11 |
12 | /**
13 | * @author mrubino
14 | * @since 2014-06-19
15 | */
16 | @RunWith(Parameterized.class)
17 | public class PatternUtilGetPresentableTextTest {
18 |
19 | private String text;
20 | private String expected;
21 |
22 | public PatternUtilGetPresentableTextTest(String text, String expected) {
23 | this.text = text;
24 | this.expected = expected;
25 | }
26 |
27 | @Test
28 | public void testPresentableTest() {
29 | String actual = PatternUtil.getPresentableText(this.text);
30 | assertEquals(this.expected, actual);
31 | }
32 |
33 | @Parameterized.Parameters
34 | public static Collection patterns() {
35 | return Arrays.asList(new Object[][]{
36 | {null, ""},
37 | {"", ""},
38 | {" ", ""},
39 | {" ", ""},
40 | {" ", ""},
41 | {"\t", ""},
42 | {"\n", ""},
43 | {"word", "word"},
44 | {"this is a sentence", "this is a sentence"},
45 | {"this is a sentence with an argument", "this is a sentence"},
46 | {"this is a sentence with an argument", "this is a sentence"},
47 | {"this is a sentence\twith an argument", "this is a sentence"},
48 | {"this is a sentence\nwith another sentence", "this is a sentence"},
49 | {" this is a sentence \nwith another sentence", "this is a sentence"},
50 | });
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/testData/ide/folding/keywordFolding.robot:
--------------------------------------------------------------------------------
1 | invalid
2 | *** Settings ***
3 | Documentation This is some demo text
4 | Library CalculatorLibrary
5 |
6 | *** Variables ***
7 | ${var1} 12345
8 | ${var2} another variable
9 |
10 | *** Test Cases ***
11 | Addition
12 | [Tags] Calculator
13 | Given calculator has been cleared
14 | When user types "1 + 1"
15 | And user pushes equals
16 | Then result is "2"
17 |
18 | #Subtraction
19 | # [Tags] Calculator
20 | # TODO: implement me
21 |
22 | *** Keywords ***
23 | Calculator has been cleared
24 | Push button C
25 |
26 | User types "${expression}"
27 | Push buttons ${expression}
28 |
29 | User pushes equals
30 | Push button =
31 |
32 | Result is "${result}"
33 | Result should be ${result}
--------------------------------------------------------------------------------
/testData/ide/usages/findInlineKeywordByDefinition.robot:
--------------------------------------------------------------------------------
1 | invalid
2 | *** Settings ***
3 | Documentation This is some demo text
4 | Library CalculatorLibrary
5 |
6 | *** Variables ***
7 | ${var1} 12345
8 | ${var2} another variable
9 |
10 | *** Test Cases ***
11 | Addition
12 | [Tags] Calculator
13 | Given calculator has been cleared
14 | When user types "1 + 1"
15 | And user pushes equals
16 | Then result is "2"
17 |
18 | Subtraction
19 | [Tags] Calculator
20 | Given calculator has been cleared
21 | When user types "2 - 1"
22 | And user pushes equals
23 | Then result is "1"
24 |
25 | *** Keywords ***
26 | Calculator has been cleared
27 | Push button C
28 |
29 | User types "${expression}"
30 | Push buttons ${expression}
31 |
32 | User pushes equals
33 | Push button =
34 |
35 | Result is "${result}"
36 | Result should be ${result}
--------------------------------------------------------------------------------
/testData/ide/usages/findInlineKeywordByUsage.robot:
--------------------------------------------------------------------------------
1 | invalid
2 | *** Settings ***
3 | Documentation This is some demo text
4 | Library CalculatorLibrary
5 |
6 | *** Variables ***
7 | ${var1} 12345
8 | ${var2} another variable
9 |
10 | *** Test Cases ***
11 | Addition
12 | [Tags] Calculator
13 | Given calculator has been cleared
14 | When user types "1 + 1"
15 | And user pushes equals
16 | Then result is "2"
17 |
18 | Subtraction
19 | [Tags] Calculator
20 | Given calculator has been cleared
21 | When user types "2 - 1"
22 | And user pushes equals
23 | Then result is "1"
24 |
25 | *** Keywords ***
26 | Calculator has been cleared
27 | Push button C
28 |
29 | User types "${expression}"
30 | Push buttons ${expression}
31 |
32 | User pushes equals
33 | Push button =
34 |
35 | Result is "${result}"
36 | Result should be ${result}
--------------------------------------------------------------------------------
/testData/ide/usages/findInlineVariableByDefinition.robot:
--------------------------------------------------------------------------------
1 | invalid
2 | *** Settings ***
3 | Documentation This is some demo text
4 | Library CalculatorLibrary
5 |
6 | *** Variables ***
7 | ${var1} 12345
8 | ${var2} another variable
9 |
10 | *** Test Cases ***
11 | Addition
12 | [Tags] Calculator
13 | Given calculator has been cleared
14 | When user types "1 + 1"
15 | And user pushes equals
16 | Then result is "2"
17 |
18 | Subtraction
19 | [Tags] Calculator
20 | Given calculator has been cleared
21 | When user types "2 - 1"
22 | And user pushes equals
23 | Then result is "1"
24 |
25 | *** Keywords ***
26 | Calculator has been cleared
27 | Push button C
28 | Log ${var2}
29 |
30 | User types "${expression}"
31 | Push buttons ${expression}
32 |
33 | User pushes equals
34 | Push button =
35 |
36 | Result is "${result}"
37 | Result should be ${result}
--------------------------------------------------------------------------------
/testData/ide/usages/findInlineVariableByUsage.robot:
--------------------------------------------------------------------------------
1 | invalid
2 | *** Settings ***
3 | Documentation This is some demo text
4 | Library CalculatorLibrary
5 |
6 | *** Variables ***
7 | ${var1} 12345
8 | ${var2} another variable
9 |
10 | *** Test Cases ***
11 | Addition
12 | [Tags] Calculator
13 | Given calculator has been cleared
14 | When user types "1 + 1"
15 | And user pushes equals
16 | Then result is "2"
17 |
18 | Subtraction
19 | [Tags] Calculator
20 | Given calculator has been cleared
21 | When user types "2 - 1"
22 | And user pushes equals
23 | Then result is "1"
24 |
25 | *** Keywords ***
26 | Calculator has been cleared
27 | Push button C
28 | Log ${var2}
29 |
30 | User types "${expression}"
31 | Push buttons ${expression}
32 |
33 | User pushes equals
34 | Push button =
35 |
36 | Result is "${result}"
37 | Result should be ${result}
--------------------------------------------------------------------------------
/testData/ide/usages/findKeywordByDefinition.robot:
--------------------------------------------------------------------------------
1 | invalid
2 | *** Settings ***
3 | Documentation This is some demo text
4 | Library CalculatorLibrary
5 |
6 | *** Variables ***
7 | ${var1} 12345
8 | ${var2} another variable
9 |
10 | *** Test Cases ***
11 | Addition
12 | [Tags] Calculator
13 | Given calculator has been cleared
14 | When user types "1 + 1"
15 | And user pushes equals
16 | Then result is "2"
17 |
18 | Subtraction
19 | [Tags] Calculator
20 | Given calculator has been cleared
21 | When user types "2 - 1"
22 | And user pushes equals
23 | Then result is "1"
24 |
25 | *** Keywords ***
26 | Calculator has been cleared
27 | Push button C
28 |
29 | User types "${expression}"
30 | Push buttons ${expression}
31 |
32 | User pushes equals
33 | Push button =
34 |
35 | Result is "${result}"
36 | Result should be ${result}
--------------------------------------------------------------------------------
/testData/ide/usages/findKeywordByUsage.robot:
--------------------------------------------------------------------------------
1 | invalid
2 | *** Settings ***
3 | Documentation This is some demo text
4 | Library CalculatorLibrary
5 |
6 | *** Variables ***
7 | ${var1} 12345
8 | ${var2} another variable
9 |
10 | *** Test Cases ***
11 | Addition
12 | [Tags] Calculator
13 | Given calculator has been cleared
14 | When user types "1 + 1"
15 | And user pushes equals
16 | Then result is "2"
17 |
18 | Subtraction
19 | [Tags] Calculator
20 | Given calculator has been cleared
21 | When user types "2 - 1"
22 | And user pushes equals
23 | Then result is "1"
24 |
25 | *** Keywords ***
26 | Calculator has been cleared
27 | Push button C
28 |
29 | User types "${expression}"
30 | Push buttons ${expression}
31 |
32 | User pushes equals
33 | Push button =
34 |
35 | Result is "${result}"
36 | Result should be ${result}
--------------------------------------------------------------------------------
/testData/ide/usages/findVariableByDefinition.robot:
--------------------------------------------------------------------------------
1 | invalid
2 | *** Settings ***
3 | Documentation This is some demo text
4 | Library CalculatorLibrary
5 |
6 | *** Variables ***
7 | ${var1} 12345
8 | ${var2} another variable
9 |
10 | *** Test Cases ***
11 | Addition
12 | [Tags] Calculator
13 | Given calculator has been cleared
14 | When user types "1 + 1"
15 | And user pushes equals
16 | Then result is "2"
17 |
18 | Subtraction
19 | [Tags] Calculator
20 | Given calculator has been cleared
21 | When user types "2 - 1"
22 | And user pushes equals
23 | Then result is "1"
24 |
25 | *** Keywords ***
26 | Calculator has been cleared
27 | Push button C
28 | Log ${var2}
29 |
30 | User types "${expression}"
31 | Push buttons ${expression}
32 |
33 | User pushes equals
34 | Push button =
35 |
36 | Result is "${result}"
37 | Result should be ${result}
--------------------------------------------------------------------------------
/testData/ide/usages/findVariableByUsage.robot:
--------------------------------------------------------------------------------
1 | invalid
2 | *** Settings ***
3 | Documentation This is some demo text
4 | Library CalculatorLibrary
5 |
6 | *** Variables ***
7 | ${var1} 12345
8 | ${var2} another variable
9 |
10 | *** Test Cases ***
11 | Addition
12 | [Tags] Calculator
13 | Given calculator has been cleared
14 | When user types "1 + 1"
15 | And user pushes equals
16 | Then result is "2"
17 |
18 | Subtraction
19 | [Tags] Calculator
20 | Given calculator has been cleared
21 | When user types "2 - 1"
22 | And user pushes equals
23 | Then result is "1"
24 |
25 | *** Keywords ***
26 | Calculator has been cleared
27 | Push button C
28 | Log ${var2}
29 |
30 | User types "${expression}"
31 | Push buttons ${expression}
32 |
33 | User pushes equals
34 | Push button =
35 |
36 | Result is "${result}"
37 | Result should be ${result}
--------------------------------------------------------------------------------
/testData/samples/Demo.lexer.txt:
--------------------------------------------------------------------------------
1 | "invalid", RobotTokenTypes.COMMENT, 0
2 | "\n", RobotTokenTypes.WHITESPACE, 0
3 | "*** Settings ***", RobotTokenTypes.HEADING, 1
4 | "\n", RobotTokenTypes.WHITESPACE, 1
5 | "Documentation", RobotTokenTypes.SETTING, 5
6 | " ", RobotTokenTypes.WHITESPACE, 5
7 | "This is some demo text", RobotTokenTypes.ARGUMENT, 5
8 | "\n", RobotTokenTypes.WHITESPACE, 1
9 | "Library", RobotTokenTypes.IMPORT, 5
10 | " ", RobotTokenTypes.WHITESPACE, 5
11 | "CalculatorLibrary", RobotTokenTypes.ARGUMENT, 5
12 | "\n", RobotTokenTypes.WHITESPACE, 1
13 | "\n", RobotTokenTypes.WHITESPACE, 1
14 | "*** Variables ***", RobotTokenTypes.HEADING, 4
15 | "\n", RobotTokenTypes.WHITESPACE, 4
16 | "${var1}", RobotTokenTypes.VARIABLE_DEFINITION, 9
17 | " ", RobotTokenTypes.WHITESPACE, 9
18 | "12345", RobotTokenTypes.ARGUMENT, 9
19 | "\n", RobotTokenTypes.WHITESPACE, 4
20 | "${var2}", RobotTokenTypes.VARIABLE_DEFINITION, 9
21 | " ", RobotTokenTypes.WHITESPACE, 9
22 | "another variable", RobotTokenTypes.ARGUMENT, 9
23 | "\n", RobotTokenTypes.WHITESPACE, 4
24 | "\n", RobotTokenTypes.WHITESPACE, 4
25 | "*** Test Cases ***", RobotTokenTypes.HEADING, 2
26 | "\n", RobotTokenTypes.WHITESPACE, 2
27 | "Addition", RobotTokenTypes.KEYWORD_DEFINITION, 8
28 | "\n", RobotTokenTypes.WHITESPACE, 8
29 | " ", RobotTokenTypes.WHITESPACE, 8
30 | "[Tags]", RobotTokenTypes.BRACKET_SETTING, 5
31 | " ", RobotTokenTypes.WHITESPACE, 5
32 | "Calculator", RobotTokenTypes.ARGUMENT, 5
33 | "\n", RobotTokenTypes.WHITESPACE, 8
34 | " ", RobotTokenTypes.WHITESPACE, 8
35 | "Given", RobotTokenTypes.GHERKIN, 11
36 | " ", RobotTokenTypes.WHITESPACE, 8
37 | "calculator has been cleared", RobotTokenTypes.KEYWORD, 6
38 | "\n", RobotTokenTypes.WHITESPACE, 8
39 | " ", RobotTokenTypes.WHITESPACE, 8
40 | "When", RobotTokenTypes.GHERKIN, 11
41 | " ", RobotTokenTypes.WHITESPACE, 8
42 | "user types "1 + 1"", RobotTokenTypes.KEYWORD, 6
43 | "\n", RobotTokenTypes.WHITESPACE, 8
44 | " ", RobotTokenTypes.WHITESPACE, 8
45 | "And", RobotTokenTypes.GHERKIN, 11
46 | " ", RobotTokenTypes.WHITESPACE, 8
47 | "user pushes equals", RobotTokenTypes.KEYWORD, 6
48 | "\n", RobotTokenTypes.WHITESPACE, 8
49 | " ", RobotTokenTypes.WHITESPACE, 8
50 | "Then", RobotTokenTypes.GHERKIN, 11
51 | " ", RobotTokenTypes.WHITESPACE, 8
52 | "result is "2"", RobotTokenTypes.KEYWORD, 6
53 | "\n", RobotTokenTypes.WHITESPACE, 6
54 | "\n", RobotTokenTypes.WHITESPACE, 6
55 | "#Subtraction", RobotTokenTypes.COMMENT, 6
56 | "\n", RobotTokenTypes.WHITESPACE, 6
57 | "# [Tags] Calculator", RobotTokenTypes.COMMENT, 6
58 | "\n", RobotTokenTypes.WHITESPACE, 6
59 | "# TODO: implement me", RobotTokenTypes.COMMENT, 6
60 | "\n", RobotTokenTypes.WHITESPACE, 8
61 | "\n", RobotTokenTypes.WHITESPACE, 2
62 | "*** Keywords ***", RobotTokenTypes.HEADING, 3
63 | "\n", RobotTokenTypes.WHITESPACE, 3
64 | "Calculator has been cleared", RobotTokenTypes.KEYWORD_DEFINITION, 8
65 | "\n", RobotTokenTypes.WHITESPACE, 8
66 | " ", RobotTokenTypes.WHITESPACE, 8
67 | "Push button", RobotTokenTypes.KEYWORD, 6
68 | " ", RobotTokenTypes.WHITESPACE, 6
69 | "C", RobotTokenTypes.ARGUMENT, 6
70 | "\n", RobotTokenTypes.WHITESPACE, 8
71 | "\n", RobotTokenTypes.WHITESPACE, 3
72 | "User types "", RobotTokenTypes.KEYWORD_DEFINITION, 3
73 | "${expression}", RobotTokenTypes.VARIABLE_DEFINITION, 3
74 | """, RobotTokenTypes.KEYWORD_DEFINITION, 8
75 | "\n", RobotTokenTypes.WHITESPACE, 8
76 | " ", RobotTokenTypes.WHITESPACE, 8
77 | "Push buttons", RobotTokenTypes.KEYWORD, 6
78 | " ", RobotTokenTypes.WHITESPACE, 6
79 | "${expression}", RobotTokenTypes.VARIABLE, 6
80 | "\n", RobotTokenTypes.WHITESPACE, 8
81 | "\n", RobotTokenTypes.WHITESPACE, 3
82 | "User pushes equals", RobotTokenTypes.KEYWORD_DEFINITION, 8
83 | "\n", RobotTokenTypes.WHITESPACE, 8
84 | " ", RobotTokenTypes.WHITESPACE, 8
85 | "Push button", RobotTokenTypes.KEYWORD, 6
86 | " ", RobotTokenTypes.WHITESPACE, 6
87 | "=", RobotTokenTypes.ARGUMENT, 6
88 | "\n", RobotTokenTypes.WHITESPACE, 8
89 | "\n", RobotTokenTypes.WHITESPACE, 3
90 | "Result is "", RobotTokenTypes.KEYWORD_DEFINITION, 3
91 | "${result}", RobotTokenTypes.VARIABLE_DEFINITION, 3
92 | """, RobotTokenTypes.KEYWORD_DEFINITION, 8
93 | "\n", RobotTokenTypes.WHITESPACE, 8
94 | " ", RobotTokenTypes.WHITESPACE, 8
95 | "Result should be", RobotTokenTypes.KEYWORD, 6
96 | " ", RobotTokenTypes.WHITESPACE, 6
97 | "${result}", RobotTokenTypes.VARIABLE, 6
98 | "\n", RobotTokenTypes.WHITESPACE, 3
99 | "\n", RobotTokenTypes.null, 3
100 |
--------------------------------------------------------------------------------
/testData/samples/Demo.robot:
--------------------------------------------------------------------------------
1 | invalid
2 | *** Settings ***
3 | Documentation This is some demo text
4 | Library CalculatorLibrary
5 |
6 | *** Variables ***
7 | ${var1} 12345
8 | ${var2} another variable
9 |
10 | *** Test Cases ***
11 | Addition
12 | [Tags] Calculator
13 | Given calculator has been cleared
14 | When user types "1 + 1"
15 | And user pushes equals
16 | Then result is "2"
17 |
18 | #Subtraction
19 | # [Tags] Calculator
20 | # TODO: implement me
21 |
22 | *** Keywords ***
23 | Calculator has been cleared
24 | Push button C
25 |
26 | User types "${expression}"
27 | Push buttons ${expression}
28 |
29 | User pushes equals
30 | Push button =
31 |
32 | Result is "${result}"
33 | Result should be ${result}
--------------------------------------------------------------------------------
/testData/samples/Demo.txt:
--------------------------------------------------------------------------------
1 | FILE(0,614)
2 | PsiComment(COMMENT)('invalid')(0,7)
3 | HeadingImpl(HEADING)(8,101)
4 | PsiElement(HEADING)('*** Settings ***')(8,24)
5 | SettingImpl(SETTING)(25,65)
6 | PsiElement(SETTING)('Documentation')(25,38)
7 | ArgumentImpl(ARGUMENT)(43,65)
8 | PsiElement(ARGUMENT)('This is some demo text')(43,65)
9 | ImportImpl(IMPORT)(66,101)
10 | PsiElement(IMPORT)('Library')(66,73)
11 | ArgumentImpl(ARGUMENT)(84,101)
12 | PsiElement(ARGUMENT)('CalculatorLibrary')(84,101)
13 | HeadingImpl(HEADING)(103,161)
14 | PsiElement(HEADING)('*** Variables ***')(103,120)
15 | VariableDefinitionImpl(VARIABLE_DEFINITION)(121,135)
16 | VariableDefinitionIdImpl(VARIABLE_DEFINITION_ID)(121,128)
17 | PsiElement(VARIABLE_DEFINITION)('${var1}')(121,128)
18 | ArgumentImpl(ARGUMENT)(130,135)
19 | PsiElement(ARGUMENT)('12345')(130,135)
20 | VariableDefinitionImpl(VARIABLE_DEFINITION)(136,161)
21 | VariableDefinitionIdImpl(VARIABLE_DEFINITION_ID)(136,143)
22 | PsiElement(VARIABLE_DEFINITION)('${var2}')(136,143)
23 | ArgumentImpl(ARGUMENT)(145,161)
24 | PsiElement(ARGUMENT)('another variable')(145,161)
25 | HeadingImpl(HEADING)(163,327)
26 | PsiElement(HEADING)('*** Test Cases ***')(163,181)
27 | KeywordDefinitionImpl(KEYWORD_DEFINITION)(182,327)
28 | KeywordDefinitionIdImpl(KEYWORD_DEFINITION_ID)(182,190)
29 | PsiElement(KEYWORD_DEFINITION)('Addition')(182,190)
30 | BracketSettingImpl(BRACKET_SETTING)(193,211)
31 | PsiElement(BRACKET_SETTING)('[Tags]')(193,199)
32 | ArgumentImpl(ARGUMENT)(201,211)
33 | PsiElement(ARGUMENT)('Calculator')(201,211)
34 | KeywordStatementImpl(KEYWORD_STATEMENT)(216,249)
35 | PsiElement(GHERKIN)('Given')(216,221)
36 | KeywordInvokableImpl(KEYWORD)(222,249)
37 | PsiElement(KEYWORD)('calculator has been cleared')(222,249)
38 | KeywordStatementImpl(KEYWORD_STATEMENT)(254,277)
39 | PsiElement(GHERKIN)('When')(254,258)
40 | KeywordInvokableImpl(KEYWORD)(259,277)
41 | PsiElement(KEYWORD)('user types "1 + 1"')(259,277)
42 | KeywordStatementImpl(KEYWORD_STATEMENT)(282,304)
43 | PsiElement(GHERKIN)('And')(282,285)
44 | KeywordInvokableImpl(KEYWORD)(286,304)
45 | PsiElement(KEYWORD)('user pushes equals')(286,304)
46 | KeywordStatementImpl(KEYWORD_STATEMENT)(309,327)
47 | PsiElement(GHERKIN)('Then')(309,313)
48 | KeywordInvokableImpl(KEYWORD)(314,327)
49 | PsiElement(KEYWORD)('result is "2"')(314,327)
50 | PsiComment(COMMENT)('#Subtraction')(329,341)
51 | PsiComment(COMMENT)('# [Tags] Calculator')(342,363)
52 | PsiComment(COMMENT)('# TODO: implement me')(364,387)
53 | HeadingImpl(HEADING)(389,614)
54 | PsiElement(HEADING)('*** Keywords ***')(389,405)
55 | KeywordDefinitionImpl(KEYWORD_DEFINITION)(406,454)
56 | KeywordDefinitionIdImpl(KEYWORD_DEFINITION_ID)(406,433)
57 | PsiElement(KEYWORD_DEFINITION)('Calculator has been cleared')(406,433)
58 | KeywordStatementImpl(KEYWORD_STATEMENT)(438,454)
59 | KeywordInvokableImpl(KEYWORD)(438,449)
60 | PsiElement(KEYWORD)('Push button')(438,449)
61 | ArgumentImpl(ARGUMENT)(453,454)
62 | PsiElement(ARGUMENT)('C')(453,454)
63 | KeywordDefinitionImpl(KEYWORD_DEFINITION)(456,516)
64 | KeywordDefinitionIdImpl(KEYWORD_DEFINITION_ID)(456,482)
65 | PsiElement(KEYWORD_DEFINITION)('User types "')(456,468)
66 | VariableDefinitionImpl(VARIABLE_DEFINITION)(468,481)
67 | VariableDefinitionIdImpl(VARIABLE_DEFINITION_ID)(468,481)
68 | PsiElement(VARIABLE_DEFINITION)('${expression}')(468,481)
69 | PsiElement(KEYWORD_DEFINITION)('"')(481,482)
70 | KeywordStatementImpl(KEYWORD_STATEMENT)(487,516)
71 | KeywordInvokableImpl(KEYWORD)(487,499)
72 | PsiElement(KEYWORD)('Push buttons')(487,499)
73 | ArgumentImpl(ARGUMENT)(503,516)
74 | VariableImpl(VARIABLE)(503,516)
75 | PsiElement(VARIABLE)('${expression}')(503,516)
76 | KeywordDefinitionImpl(KEYWORD_DEFINITION)(518,557)
77 | KeywordDefinitionIdImpl(KEYWORD_DEFINITION_ID)(518,536)
78 | PsiElement(KEYWORD_DEFINITION)('User pushes equals')(518,536)
79 | KeywordStatementImpl(KEYWORD_STATEMENT)(541,557)
80 | KeywordInvokableImpl(KEYWORD)(541,552)
81 | PsiElement(KEYWORD)('Push button')(541,552)
82 | ArgumentImpl(ARGUMENT)(556,557)
83 | PsiElement(ARGUMENT)('=')(556,557)
84 | KeywordDefinitionImpl(KEYWORD_DEFINITION)(559,614)
85 | KeywordDefinitionIdImpl(KEYWORD_DEFINITION_ID)(559,580)
86 | PsiElement(KEYWORD_DEFINITION)('Result is "')(559,570)
87 | VariableDefinitionImpl(VARIABLE_DEFINITION)(570,579)
88 | VariableDefinitionIdImpl(VARIABLE_DEFINITION_ID)(570,579)
89 | PsiElement(VARIABLE_DEFINITION)('${result}')(570,579)
90 | PsiElement(KEYWORD_DEFINITION)('"')(579,580)
91 | KeywordStatementImpl(KEYWORD_STATEMENT)(585,614)
92 | KeywordInvokableImpl(KEYWORD)(585,601)
93 | PsiElement(KEYWORD)('Result should be')(585,601)
94 | ArgumentImpl(ARGUMENT)(605,614)
95 | VariableImpl(VARIABLE)(605,614)
96 | PsiElement(VARIABLE)('${result}')(605,614)
--------------------------------------------------------------------------------
/testData/samples/EmptyHeaders.lexer.txt:
--------------------------------------------------------------------------------
1 | "*** Settings ***", RobotTokenTypes.HEADING, 1
2 | "\n", RobotTokenTypes.WHITESPACE, 1
3 | "\n", RobotTokenTypes.WHITESPACE, 1
4 | "*** Variables ***", RobotTokenTypes.HEADING, 4
5 | "\n", RobotTokenTypes.WHITESPACE, 4
6 | "\n", RobotTokenTypes.WHITESPACE, 4
7 | "*** Test Cases ***", RobotTokenTypes.HEADING, 2
8 | "\n", RobotTokenTypes.WHITESPACE, 2
9 | "\n", RobotTokenTypes.WHITESPACE, 2
10 | "*** Keywords ***", RobotTokenTypes.HEADING, 3
11 | "\n", RobotTokenTypes.WHITESPACE, 3
12 | "\n", RobotTokenTypes.WHITESPACE, 3
13 | "Clean Database", RobotTokenTypes.KEYWORD_DEFINITION, 8
14 | "\n", RobotTokenTypes.WHITESPACE, 8
15 | " ", RobotTokenTypes.WHITESPACE, 8
16 | "This works", RobotTokenTypes.KEYWORD, 6
17 | "\n", RobotTokenTypes.WHITESPACE, 8
18 | " ", RobotTokenTypes.WHITESPACE, 8
19 | "I will be happy", RobotTokenTypes.KEYWORD, 6
20 | "\n", RobotTokenTypes.WHITESPACE, 8
21 | "\n", RobotTokenTypes.WHITESPACE, 3
22 | "This works", RobotTokenTypes.KEYWORD_DEFINITION, 8
23 | "\n", RobotTokenTypes.WHITESPACE, 8
24 | " ", RobotTokenTypes.WHITESPACE, 8
25 | "log", RobotTokenTypes.KEYWORD, 6
26 | " ", RobotTokenTypes.WHITESPACE, 6
27 | "a", RobotTokenTypes.ARGUMENT, 6
28 | "\n", RobotTokenTypes.WHITESPACE, 8
29 | "\n", RobotTokenTypes.WHITESPACE, 3
30 | "I will be happy", RobotTokenTypes.KEYWORD_DEFINITION, 8
31 | "\n", RobotTokenTypes.WHITESPACE, 8
32 | " ", RobotTokenTypes.WHITESPACE, 8
33 | "log", RobotTokenTypes.KEYWORD, 6
34 | " ", RobotTokenTypes.WHITESPACE, 6
35 | "b", RobotTokenTypes.ARGUMENT, 6
36 | "\n", RobotTokenTypes.WHITESPACE, 3
37 | "\n", RobotTokenTypes.null, 3
38 |
--------------------------------------------------------------------------------
/testData/samples/EmptyHeaders.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 |
3 | *** Variables ***
4 |
5 | *** Test Cases ***
6 |
7 | *** Keywords ***
8 |
9 | Clean Database
10 | This works
11 | I will be happy
12 |
13 | This works
14 | log a
15 |
16 | I will be happy
17 | log b
--------------------------------------------------------------------------------
/testData/samples/EmptyHeaders.txt:
--------------------------------------------------------------------------------
1 | FILE(0,175)
2 | HeadingImpl(HEADING)(0,16)
3 | PsiElement(HEADING)('*** Settings ***')(0,16)
4 | HeadingImpl(HEADING)(18,35)
5 | PsiElement(HEADING)('*** Variables ***')(18,35)
6 | HeadingImpl(HEADING)(37,55)
7 | PsiElement(HEADING)('*** Test Cases ***')(37,55)
8 | HeadingImpl(HEADING)(57,175)
9 | PsiElement(HEADING)('*** Keywords ***')(57,73)
10 | KeywordDefinitionImpl(KEYWORD_DEFINITION)(75,124)
11 | KeywordDefinitionIdImpl(KEYWORD_DEFINITION_ID)(75,89)
12 | PsiElement(KEYWORD_DEFINITION)('Clean Database')(75,89)
13 | KeywordStatementImpl(KEYWORD_STATEMENT)(94,104)
14 | KeywordInvokableImpl(KEYWORD)(94,104)
15 | PsiElement(KEYWORD)('This works')(94,104)
16 | KeywordStatementImpl(KEYWORD_STATEMENT)(109,124)
17 | KeywordInvokableImpl(KEYWORD)(109,124)
18 | PsiElement(KEYWORD)('I will be happy')(109,124)
19 | KeywordDefinitionImpl(KEYWORD_DEFINITION)(126,147)
20 | KeywordDefinitionIdImpl(KEYWORD_DEFINITION_ID)(126,136)
21 | PsiElement(KEYWORD_DEFINITION)('This works')(126,136)
22 | KeywordStatementImpl(KEYWORD_STATEMENT)(141,147)
23 | KeywordInvokableImpl(KEYWORD)(141,144)
24 | PsiElement(KEYWORD)('log')(141,144)
25 | ArgumentImpl(ARGUMENT)(146,147)
26 | PsiElement(ARGUMENT)('a')(146,147)
27 | KeywordDefinitionImpl(KEYWORD_DEFINITION)(149,175)
28 | KeywordDefinitionIdImpl(KEYWORD_DEFINITION_ID)(149,164)
29 | PsiElement(KEYWORD_DEFINITION)('I will be happy')(149,164)
30 | KeywordStatementImpl(KEYWORD_STATEMENT)(169,175)
31 | KeywordInvokableImpl(KEYWORD)(169,172)
32 | PsiElement(KEYWORD)('log')(169,172)
33 | ArgumentImpl(ARGUMENT)(174,175)
34 | PsiElement(ARGUMENT)('b')(174,175)
--------------------------------------------------------------------------------
/testData/samples/Junk.lexer.txt:
--------------------------------------------------------------------------------
1 | "some junk", RobotTokenTypes.COMMENT, 0
2 | "\n", RobotTokenTypes.WHITESPACE, 0
3 | "\n", RobotTokenTypes.null, 0
4 |
--------------------------------------------------------------------------------
/testData/samples/Junk.robot:
--------------------------------------------------------------------------------
1 | some junk
--------------------------------------------------------------------------------
/testData/samples/Junk.txt:
--------------------------------------------------------------------------------
1 | FILE(0,9)
2 | PsiComment(COMMENT)('some junk')(0,9)
--------------------------------------------------------------------------------
/testData/samples/ParsingTestData.robot:
--------------------------------------------------------------------------------
1 | documentation
2 | this is a sample file
3 |
4 | *** Settings ***
5 | # fun things going on here
6 | Documentation Test the account dashboard
7 | ...
8 | ... and this goes to the next line
9 | Documentation
10 | ... all new line
11 |
12 | Resource kyle/web/db_advertiser_actions.robot
13 | Resource kyle/web/db_campaign_actions.robot
14 | Resource kyle/web/db_staff_actions.robot
15 | Resource kyle/web/ui_login_page.robot
16 | Resource kyle/web/ui_manage_accounts_page.robot
17 | Resource kyle_db_cleanup/kyle_cleanup.robot
18 | Library Selenium2Library timeout=${ENV['selenium']['timeout']} implicit_wait=${ENV['selenium']['implicit_wait']}
19 | Library db.orm.Orm
20 | Library OperatingSystem
21 | Library Collections
22 |
23 | Force Tags Kyle Advertiser Dashboard Component #Other Tag
24 | Suite Teardown This works
25 |
26 | *** Variables ***
27 |
28 | ${Total_Requests} 97,000
29 | ${kw_timeout} 20 sec
30 | ${kw_retry_interval} 0.5 sec
31 | @{some_letters} A B C
32 |
33 | *** Test Cases ***
34 |
35 | Scenario: An admin can see the conversion trend
36 | [Tags] Was Flickering
37 | [Setup] Prepare advertiser "Robot_Company"
38 | Given Advertiser has performance data
39 | And I have an Account Manager MANAGER
40 |
41 | When I login to Tapmatch as Staff ${ACCOUNT_MANAGER.user.name} ${ACCOUNT_MANAGER.user.password}
42 | Then The 7-day average should be $0.09
43 | [Teardown] Run Keywords Close All Browsers Clean Database
44 |
45 | Scenario: This is also a keyword definition
46 | [Documentation] adding another
47 | # just for fun
48 | ... keyword will be classified correctly
49 | Given this sometimes works
50 | Then I will be happy
51 | And I will be happy 12 123
52 |
53 | *** Keywords ***
54 |
55 | Clean Database
56 | [Documentation] Cleans the database
57 | [Arguments] ${defined}=${Total_Requests}
58 | ${var1} = This works 1
59 | Clean Kyle
60 | ${var2} ${var3} = This should work 2
61 | ${defined} Clean Ike
62 | # Clean Other Stuff
63 | Close All Browsers
64 |
65 |
66 | This ${rate} works
67 | its a new ${rate} keyword
68 | run keyword if ${a}=${b} equal not equal
69 | [Return] ${Total_Requests}
70 |
71 | I will be happy
72 | there is a smile on my face ...
--------------------------------------------------------------------------------
/testData/samples/TrimmedVariables.robot:
--------------------------------------------------------------------------------
1 | *** Variables ***
2 | ${VAR_1} variable 1
3 | ${VAR_2} variable 2
4 | ${VAR_3} variable 3
--------------------------------------------------------------------------------
/testData/samples/TrimmedVariables.txt:
--------------------------------------------------------------------------------
1 | FILE(0,79)
2 | HeadingImpl(HEADING)(0,68)
3 | PsiElement(HEADING)('*** Variables ***')(0,17)
4 | VariableDefinitionImpl(VARIABLE_DEFINITION)(18,38)
5 | VariableDefinitionIdImpl(VARIABLE_DEFINITION_ID)(18,26)
6 | PsiElement(VARIABLE_DEFINITION)('${VAR_1}')(18,26)
7 | ArgumentImpl(ARGUMENT)(28,38)
8 | PsiElement(ARGUMENT)('variable 1')(28,38)
9 | VariableDefinitionImpl(VARIABLE_DEFINITION)(39,59)
10 | VariableDefinitionIdImpl(VARIABLE_DEFINITION_ID)(39,47)
11 | PsiElement(VARIABLE_DEFINITION)('${VAR_2}')(39,47)
12 | ArgumentImpl(ARGUMENT)(49,59)
13 | PsiElement(ARGUMENT)('variable 2')(49,59)
14 | VariableDefinitionImpl(VARIABLE_DEFINITION)(60,68)
15 | VariableDefinitionIdImpl(VARIABLE_DEFINITION_ID)(60,68)
16 | PsiElement(VARIABLE_DEFINITION)('${VAR_3}')(60,68)
--------------------------------------------------------------------------------
/testData/samples/Variables.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 |
3 | Library Selenium2Library ${variable} ${${variable}.length}
4 |
5 | *** Variables ***
6 |
7 | ${variable} 1234
8 |
9 | *** Test Cases ***
10 | Do It Up
11 | User types "water"
12 | User then types falls
13 | "are" is then entered by user
14 | pretty is entered by user
15 |
16 | Do It Up Again
17 | User types "${variable}"
18 | User then types ${variable}
19 | "${variable}" is then entered by user
20 | ${variable} is entered by user
21 | User types "${variable}" and "${variable}"
22 |
23 | *** Keywords ***
24 |
25 | ${a} is entered by user
26 | Enter ${a}
27 |
28 | User types "${b}" and "${c}"
29 | ${b} is entered by user
30 | ${c} is entered by user
31 |
32 | "${d}" is then entered by user
33 | Enter ${d}
34 |
35 | User then types ${e}
36 | Enter ${e}
37 | log ${${e}[0]}
38 |
39 | User types "${f}"
40 | Enter ${f}
41 | [Return] ${${f}}
42 |
43 | Enter
44 | [Arguments] ${g}
45 | ${h}= log ${g}
46 | ${${h}} ${${g}}= log stuff
47 | [Return] ${h}
48 |
49 | Leave
50 | [Arguments] ${i}=1
51 | ... ${j}=2
52 | Log ${i} ${j}
--------------------------------------------------------------------------------
/wiki/dev_setup/intellij_sdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/dev_setup/intellij_sdk.png
--------------------------------------------------------------------------------
/wiki/dev_setup/plugin_config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/dev_setup/plugin_config.png
--------------------------------------------------------------------------------
/wiki/dev_setup/python_library.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/dev_setup/python_library.png
--------------------------------------------------------------------------------
/wiki/features/code_folding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/features/code_folding.png
--------------------------------------------------------------------------------
/wiki/features/demo_complete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/features/demo_complete.png
--------------------------------------------------------------------------------
/wiki/features/find_usages.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/features/find_usages.png
--------------------------------------------------------------------------------
/wiki/features/jump_to_source.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/features/jump_to_source.png
--------------------------------------------------------------------------------
/wiki/features/keyword_recommendation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/features/keyword_recommendation.png
--------------------------------------------------------------------------------
/wiki/features/structure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/features/structure.png
--------------------------------------------------------------------------------
/wiki/features/undefined_keyword.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/features/undefined_keyword.png
--------------------------------------------------------------------------------
/wiki/python_interpreter/intellij/module_interpreter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/python_interpreter/intellij/module_interpreter.png
--------------------------------------------------------------------------------
/wiki/python_interpreter/intellij/project_sdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/python_interpreter/intellij/project_sdk.png
--------------------------------------------------------------------------------
/wiki/python_interpreter/intellij/python_plugin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/python_interpreter/intellij/python_plugin.png
--------------------------------------------------------------------------------
/wiki/python_interpreter/pycharm/console_interpreter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/python_interpreter/pycharm/console_interpreter.png
--------------------------------------------------------------------------------
/wiki/python_interpreter/pycharm/project_interpreter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/python_interpreter/pycharm/project_interpreter.png
--------------------------------------------------------------------------------
/wiki/robot_options/event_log.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/robot_options/event_log.png
--------------------------------------------------------------------------------
/wiki/robot_options/options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/robot_options/options.png
--------------------------------------------------------------------------------
/wiki/test_debugging/debug_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/test_debugging/debug_settings.png
--------------------------------------------------------------------------------
/wiki/using_txt_files/txt_file_type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mtrubs/intellibot/a0e24156fb6bc5302f9d15737f7ada5836780f7f/wiki/using_txt_files/txt_file_type.png
--------------------------------------------------------------------------------