External URL help added for PY-11855

This commit is contained in:
Ilya.Kazakevich
2015-03-24 19:52:09 +03:00
parent 80d3f386d1
commit dc8dd99468
16 changed files with 167 additions and 72 deletions
@@ -6,6 +6,7 @@ import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElement;
import com.jetbrains.commandInterface.commandLine.CommandLinePart;
import com.jetbrains.commandInterface.command.Argument;
import com.jetbrains.commandInterface.command.Help;
import com.jetbrains.commandInterface.command.Option;
public interface CommandLineArgument extends CommandLinePart {
@@ -23,6 +24,6 @@ public interface CommandLineArgument extends CommandLinePart {
Argument findRealArgument();
@Nullable
String findBestHelpText();
Help findBestHelp();
}
@@ -11,6 +11,7 @@ import static com.jetbrains.commandInterface.commandLine.CommandLineElementTypes
import com.jetbrains.commandInterface.commandLine.CommandLineElement;
import com.jetbrains.commandInterface.commandLine.psi.*;
import com.jetbrains.commandInterface.command.Argument;
import com.jetbrains.commandInterface.command.Help;
import com.jetbrains.commandInterface.command.Option;
public class CommandLineArgumentImpl extends CommandLineElement implements CommandLineArgument {
@@ -47,8 +48,8 @@ public class CommandLineArgumentImpl extends CommandLineElement implements Comma
}
@Nullable
public String findBestHelpText() {
return CommandLinePsiImplUtils.findBestHelpText(this);
public Help findBestHelp() {
return CommandLinePsiImplUtils.findBestHelp(this);
}
}
@@ -35,7 +35,7 @@ public final class Argument {
* Argument help user-readable text
*/
@NotNull
private final String myHelpText;
private final Help myHelpText;
/**
* List of values argument may have. Null if any value is possible.
*/
@@ -48,7 +48,7 @@ public final class Argument {
/**
* @param helpText Argument help user-readable text
*/
public Argument(@NotNull final String helpText) {
public Argument(@NotNull final Help helpText) {
this(helpText, null, null);
}
@@ -56,14 +56,14 @@ public final class Argument {
* @param type Argument value type. Null if any type is possible.
*/
public Argument(@NotNull final ArgumentType type) {
this("", type);
this(new Help(""), type);
}
/**
* @param helpText Argument help user-readable text
* @param type Argument value type. Null if any type is possible.
*/
public Argument(@NotNull final String helpText,
public Argument(@NotNull final Help helpText,
@Nullable final ArgumentType type) {
this(helpText, null, type);
}
@@ -72,14 +72,14 @@ public final class Argument {
* @param availableValues List of values argument may have. Null if any value is possible.
*/
public Argument(@Nullable final List<String> availableValues) {
this("", availableValues, null);
this(new Help(""), availableValues, null);
}
/**
* @param helpText Argument help user-readable text
* @param availableValues List of values argument may have. Null if any value is possible.
*/
public Argument(@NotNull final String helpText, @Nullable final List<String> availableValues) {
public Argument(@NotNull final Help helpText, @Nullable final List<String> availableValues) {
this(helpText, availableValues, null);
}
@@ -89,7 +89,7 @@ public final class Argument {
* @param availableValues List of values argument may have. Null if any value is possible.
* @param type Argument value type. Null if any type is possible.
*/
public Argument(@NotNull final String helpText,
public Argument(@NotNull final Help helpText,
@Nullable final List<String> availableValues,
@Nullable final ArgumentType type) {
myHelpText = helpText;
@@ -101,7 +101,7 @@ public final class Argument {
* @return Argument help user-readable text
*/
@NotNull
public String getHelpText() {
public Help getHelp() {
return myHelpText;
}
@@ -39,10 +39,10 @@ public interface Command {
* @param tryCutOutArguments Try to remove information about arguments from help text (i.e. "[file] removes file" -> "removes file").
* Command may or may not support it.
* It should ignore argument if it does not know how to cut out argument info.
* @return Command readable help text
* @return Command help
*/
@Nullable
String getHelp(boolean tryCutOutArguments);
Help getHelp(boolean tryCutOutArguments);
/**
@@ -0,0 +1,63 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.commandInterface.command;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Covers element help: text and external url (if exists)
*
* @author Ilya.Kazakevich
*/
public final class Help {
@NotNull
private final String myHelpString;
@Nullable
private final String myExternalHelpUrl;
/**
* @param helpString help text (no external url provided)
*/
public Help(@NotNull final String helpString) {
this(helpString, null);
}
/**
* @param helpString help text
* @param externalHelpUrl external help url (if any)
*/
public Help(@NotNull final String helpString, @Nullable final String externalHelpUrl) {
myHelpString = helpString;
myExternalHelpUrl = externalHelpUrl;
}
/**
* @return help text
*/
@NotNull
public String getHelpString() {
return myHelpString;
}
/**
* @return external help url (if any)
*/
@Nullable
public String getExternalHelpUrl() {
return myExternalHelpUrl;
}
}
@@ -39,7 +39,7 @@ public final class Option {
@Nullable
private final Pair<Integer, Argument> myArgumentAndQuantity;
@NotNull
private final String myHelp;
private final Help myHelp;
/**
* @param argumentAndQuantity if option accepts argument, there should be pair of [argument_quantity, its_type_info]
@@ -48,7 +48,7 @@ public final class Option {
* @param longNames option long names
*/
public Option(@Nullable final Pair<Integer, Argument> argumentAndQuantity,
@NotNull final String help,
@NotNull final Help help,
@NotNull final Collection<String> shortNames,
@NotNull final Collection<String> longNames) {
Preconditions
@@ -99,7 +99,7 @@ public final class Option {
* @return Option help
*/
@NotNull
public String getHelp() {
public Help getHelp() {
return myHelp;
}
}
@@ -30,12 +30,12 @@ public final class UnknownArgumentsInfo implements ArgumentsInfo {
* Argument help text
*/
@NotNull
private final String myHelp;
private final Help myHelp;
/**
* @param allArgumentsHelpText argument help text
*/
public UnknownArgumentsInfo(@NotNull final String allArgumentsHelpText) {
public UnknownArgumentsInfo(@NotNull final Help allArgumentsHelpText) {
myHelp = allArgumentsHelpText;
}
@@ -18,6 +18,7 @@ package com.jetbrains.commandInterface.commandLine;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.psi.PsiElement;
import com.jetbrains.commandInterface.command.Argument;
import com.jetbrains.commandInterface.command.Help;
import com.jetbrains.commandInterface.command.Option;
import com.jetbrains.commandInterface.commandLine.psi.CommandLineArgument;
import org.jetbrains.annotations.NotNull;
@@ -53,7 +54,9 @@ public final class CommandLineArgumentReference extends CommandLineElementRefere
// priority is used to display args before options
if (argumentValues != null) {
for (final String value : argumentValues) {
builder.addElement(LookupElementBuilder.create(value).withBoldness(true), getElement().findBestHelpText(), 1);
final Help help = getElement().findBestHelp();
final String helpText = (help != null ? help.getHelpString() : null);
builder.addElement(LookupElementBuilder.create(value).withBoldness(true), helpText, 1);
}
}
@@ -66,7 +69,7 @@ public final class CommandLineArgumentReference extends CommandLineElementRefere
if (argumentOption == null) { // If not option argument
for (final Option option : validationResult.getUnusedOptions()) {
for (final String value : option.getAllNames()) {
builder.addElement(LookupElementBuilder.create(value), option.getHelp(), 0);
builder.addElement(LookupElementBuilder.create(value), option.getHelp().getHelpString(), 0);
}
}
}
@@ -18,6 +18,7 @@ package com.jetbrains.commandInterface.commandLine;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.psi.PsiElement;
import com.jetbrains.commandInterface.command.Command;
import com.jetbrains.commandInterface.command.Help;
import com.jetbrains.commandInterface.commandLine.psi.CommandLineCommand;
import com.jetbrains.commandInterface.commandLine.psi.CommandLineFile;
import org.jetbrains.annotations.NotNull;
@@ -58,8 +59,8 @@ public final class CommandLineCommandReference extends CommandLineElementReferen
for (final Command command : commands) {
final LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(command.getName());
final String help = command.getHelp(true);
result.addElement(lookupElementBuilder, help);
final Help help = command.getHelp(true);
result.addElement(lookupElementBuilder, (help != null ? help.getHelpString(): null));
}
@@ -22,12 +22,16 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.commandInterface.command.Command;
import com.jetbrains.commandInterface.command.Help;
import com.jetbrains.commandInterface.command.Option;
import com.jetbrains.commandInterface.commandLine.psi.*;
import com.jetbrains.python.psi.PyUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
/**
* Provides quick help for arguments
*
@@ -37,34 +41,27 @@ public final class CommandLineDocumentationProvider extends DocumentationProvide
@Nullable
@Override
public String generateDoc(final PsiElement element, @Nullable final PsiElement originalElement) {
if (!(element instanceof CommandLinePart)) {
final Help help = findHelp(element);
if (help == null) {
return null;
}
final CommandLinePart commandLinePart = (CommandLinePart)element;
final Command realCommand = commandLinePart.findRealCommand();
if (realCommand == null) {
return null;
}
if (element instanceof CommandLineFile) {
return realCommand.getHelp(false); // We do not need arguments info in help text
}
final CommandLineElement commandLineElement = PyUtil.as(element, CommandLineElement.class);
if (commandLineElement == null) {
return null;
}
final MyCommandHelpObtainer helpObtainer = new MyCommandHelpObtainer(realCommand);
commandLineElement.accept(helpObtainer);
final String help = helpObtainer.myResultText;
// For some reason we can't return empty sting (leads to "fetchig doc" string)
return (StringUtil.isEmptyOrSpaces(help) ? null : help);
final String helpText = help.getHelpString();
// For some reason we can't return empty sting (leads to "fetching doc" string)
return (StringUtil.isEmptyOrSpaces(helpText) ? null : helpText);
}
@Override
public List<String> getUrlFor(final PsiElement element, final PsiElement originalElement) {
final Help help = findHelp(element);
if (help == null) {
return null;
}
final String externalHelpUrl = help.getExternalHelpUrl();
if (externalHelpUrl != null) {
return Collections.singletonList(externalHelpUrl);
}
return null;
}
@Nullable
@Override
@@ -78,27 +75,55 @@ public final class CommandLineDocumentationProvider extends DocumentationProvide
return PyUtil.as(file, CommandLineFile.class);
}
/**
* Searches for help text for certain element
* @param element element to search help for
* @return help or
*
*/
@Nullable
private static Help findHelp(@NotNull final PsiElement element) {
if (!(element instanceof CommandLinePart)) {
return null;
}
final CommandLinePart commandLinePart = (CommandLinePart)element;
final Command realCommand = commandLinePart.findRealCommand();
if (realCommand == null) {
return null;
}
final CommandLineElement commandLineElement = PyUtil.as(element, CommandLineElement.class);
if (commandLineElement == null) {
return null;
}
final MyCommandHelpObtainer helpObtainer = new MyCommandHelpObtainer();
commandLineElement.accept(helpObtainer);
return helpObtainer.myResultHelp;
}
/**
* Fetches text from command line part as visitor
*/
private static final class MyCommandHelpObtainer extends CommandLineVisitor {
private String myResultText;
private final Command myRealCommand;
private MyCommandHelpObtainer(@NotNull final Command realCommand) {
myRealCommand = realCommand;
}
private Help myResultHelp;
@Override
public void visitArgument(@NotNull final CommandLineArgument o) {
super.visitArgument(o);
myResultText = o.findBestHelpText();
myResultHelp = o.findBestHelp();
}
@Override
public void visitCommand(@NotNull final CommandLineCommand o) {
public void visitCommand(@NotNull CommandLineCommand o) {
super.visitCommand(o);
myResultText = myRealCommand.getHelp(false);
final Command realCommand = o.findRealCommand();
if (realCommand != null) {
myResultHelp = realCommand.getHelp(false); // Arguments are ok to display here;
}
}
@Override
@@ -108,7 +133,7 @@ public final class CommandLineDocumentationProvider extends DocumentationProvide
if (option == null) {
return;
}
myResultText = option.getHelp();
myResultHelp = option.getHelp();
}
}
}
}
@@ -55,7 +55,7 @@ public final class CommandLineOptionReference extends CommandLineElementReferenc
// Suggest long options for -- and short for -
final List<String> names = getElement().isLong() ? option.getLongNames() : option.getShortNames();
for (final String optionName : names) {
builder.addElement(LookupElementBuilder.create(optionName), option.getHelp());
builder.addElement(LookupElementBuilder.create(optionName), option.getHelp().getHelpString());
}
}
@@ -41,6 +41,6 @@ methods=[ getOptionName isLong findRealOption ]
private short_option_name ::= SHORT_OPTION_NAME_TOKEN
private long_option_name ::= LONG_OPTION_NAME_TOKEN
argument ::= LITERAL_STARTS_FROM_LETTER | LITERAL_STARTS_FROM_DIGIT {
methods=[ findOptionForOptionArgument findRealArgument findBestHelpText ]
methods=[ findOptionForOptionArgument findRealArgument findBestHelp ]
}
@@ -17,6 +17,7 @@ package com.jetbrains.commandInterface.commandLine.psi.impl;
import com.intellij.psi.PsiElement;
import com.jetbrains.commandInterface.command.Argument;
import com.jetbrains.commandInterface.command.Help;
import com.jetbrains.commandInterface.command.Option;
import com.jetbrains.commandInterface.commandLine.CommandLinePart;
import com.jetbrains.commandInterface.commandLine.ValidationResult;
@@ -66,20 +67,20 @@ final class CommandLinePsiImplUtils {
/**
* Tries to find appropriate help text for argument. It can be argument help string for positional argument or option help
* Tries to find appropriate help for argument. It can be argument help for positional argument or option help
* for option argument.
*
* @param argument argument to search help for
* @return help string for argument or null if not found
* @return help for argument or null if not found
*/
@Nullable
static String findBestHelpText(@NotNull final CommandLineArgument argument) {
static Help findBestHelp(@NotNull final CommandLineArgument argument) {
final Option option = argument.findOptionForOptionArgument();
if (option != null) {
return option.getHelp();
}
final Argument realArgument = argument.findRealArgument();
return (realArgument != null ? realArgument.getHelpText() : null);
return (realArgument != null ? realArgument.getHelp() : null);
}
@@ -166,7 +166,7 @@ final class ArgumentHintLayer extends JPanel implements Listener {
final int x = (myPromptWidthPx + (myCharWidthPx * myDocumentLengthInChars)) + spaceToRight;
final boolean required = nextArg.first;
final String argumentText = nextArg.second.getHelpText();
final String argumentText = nextArg.second.getHelp().getHelpString();
g.setColor(required ? myRequiredColor : myOptionalColor);
@@ -69,6 +69,6 @@ public final class CommandLineArgsTest extends PyTestCase {
final Pair<Boolean, Argument> arg = validationResult.getNextArg();
Assert.assertNotNull("No argument returned, but should", arg);
Assert.assertTrue("Required argument is not marked as required", arg.first);
Assert.assertEquals("Wrong argument text", expectedArgumentText, arg.second.getHelpText());
Assert.assertEquals("Wrong argument text", expectedArgumentText, arg.second.getHelp().getHelpString());
}
}
@@ -53,17 +53,17 @@ final class CommandTestTools {
//command positional_argument --available-option=available_argument
final Command command = EasyMock.createMock(Command.class);
EasyMock.expect(command.getName()).andReturn("command").anyTimes();
EasyMock.expect(command.getHelp(true)).andReturn("some_text").anyTimes();
EasyMock.expect(command.getHelp(false)).andReturn("some_text").anyTimes();
EasyMock.expect(command.getHelp(true)).andReturn(new Help("some_text")).anyTimes();
EasyMock.expect(command.getHelp(false)).andReturn(new Help("some_text")).anyTimes();
final List<Option> options = new ArrayList<Option>();
options.add(new Option(Pair.create(1, new Argument("option argument", Collections.singletonList("available_argument"))), "",
Collections.<String>emptyList(),
Collections.singletonList("--available-option")));
options.add(new Option(Pair.create(1, new Argument(new Help("option argument"), Collections.singletonList("available_argument"))), new Help(""),
Collections.<String>emptyList(),
Collections.singletonList("--available-option")));
options.add(new Option(null, "",
options.add(new Option(null, new Help(""),
Collections.<String>emptyList(),
Collections.singletonList("--option-no-argument")));
@@ -71,7 +71,7 @@ final class CommandTestTools {
final ArgumentsInfo argumentInfo = new KnownArgumentsInfo(Collections.singletonList(
new Argument("positional_argument",
new Argument(new Help("positional_argument"),
Collections.singletonList("positional_argument"))), 1, 1);
EasyMock.expect(command.getArgumentsInfo()).andReturn(argumentInfo)