Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2015-05-18 15:54:11 +02:00
29 changed files with 783 additions and 380 deletions
+2 -2
View File
@@ -56,11 +56,11 @@
<orderEntry type="module" module-name="java-structure-view" exported="" />
<orderEntry type="module" module-name="spellchecker" />
<orderEntry type="library" name="nekohtml" level="project" />
<orderEntry type="module" module-name="built-in-server" />
</component>
<component name="copyright">
<Base>
<setting name="state" value="1" />
</Base>
</component>
</module>
</module>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* 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.
@@ -50,11 +50,14 @@ import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.SmartList;
import com.intellij.util.Url;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.builtInWebServer.BuiltInWebBrowserUrlProvider;
import java.util.LinkedHashSet;
import java.util.List;
@@ -684,7 +687,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext
}
@Nullable
public static List<String> findUrlForClass(PsiClass aClass) {
public static List<String> findUrlForClass(@NotNull PsiClass aClass) {
String qName = aClass.getQualifiedName();
if (qName == null) return null;
@@ -696,18 +699,18 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext
String packageName = ((PsiJavaFile)file).getPackageName();
String relPath;
if (packageName.length() > 0) {
relPath = packageName.replace('.', '/') + '/' + qName.substring(packageName.length() + 1) + HTML_EXTENSION;
if (packageName.isEmpty()) {
relPath = qName + HTML_EXTENSION;
}
else {
relPath = qName + HTML_EXTENSION;
relPath = packageName.replace('.', '/') + '/' + qName.substring(packageName.length() + 1) + HTML_EXTENSION;
}
return findUrlForVirtualFile(file.getProject(), virtualFile, relPath);
}
@Nullable
public static List<String> findUrlForVirtualFile(final Project project, final VirtualFile virtualFile, final String relPath) {
public static List<String> findUrlForVirtualFile(@NotNull Project project, @NotNull VirtualFile virtualFile, @NotNull String relPath) {
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
Module module = fileIndex.getModuleForFile(virtualFile);
if (module == null) {
@@ -728,11 +731,25 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext
}
}
final List<OrderEntry> orderEntries = fileIndex.getOrderEntriesForFile(virtualFile);
for (OrderEntry orderEntry : orderEntries) {
final String[] files = JavadocOrderRootType.getUrls(orderEntry);
final List<String> httpRoot = PlatformDocumentationUtil.getHttpRoots(files, relPath);
if (httpRoot != null) return httpRoot;
for (OrderEntry orderEntry : fileIndex.getOrderEntriesForFile(virtualFile)) {
for (VirtualFile root : orderEntry.getFiles(JavadocOrderRootType.getInstance())) {
if (root.getFileSystem() == JarFileSystem.getInstance()) {
VirtualFile file = root.findFileByRelativePath(relPath);
List<Url> urls = file == null ? null : BuiltInWebBrowserUrlProvider.getUrls(file, project, null);
if (!ContainerUtil.isEmpty(urls)) {
List<String> result = new SmartList<String>();
for (Url url : urls) {
result.add(url.toExternalForm());
}
return result;
}
}
}
List<String> httpRoot = PlatformDocumentationUtil.getHttpRoots(JavadocOrderRootType.getUrls(orderEntry), relPath);
if (httpRoot != null) {
return httpRoot;
}
}
return null;
}
@@ -33,6 +33,8 @@ import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.PairFunction;
import com.intellij.util.PlatformUtils;
@@ -207,7 +209,8 @@ final class DefaultWebServerRootsProvider extends WebServerRootsProvider {
DirectoryInfo info = directoryIndex.getInfoForFile(file);
// we serve excluded files
if (!info.isExcluded() && !info.isInProject()) {
return null;
// javadoc jars is "not under project", but actually is, so, let's check project library table
return file.getFileSystem() == JarFileSystem.getInstance() ? getInfoForDocJar(file, project) : null;
}
VirtualFile root = info.getSourceRoot();
@@ -245,6 +248,59 @@ final class DefaultWebServerRootsProvider extends WebServerRootsProvider {
}
}
@Nullable
private static PathInfo getInfoForDocJar(@NotNull final VirtualFile file, @NotNull Project project) {
final OrderRootType javaDocRootType = JavadocOrderRootType.getInstance();
if (javaDocRootType == null) {
return null;
}
class LibraryProcessor implements Processor<Library> {
PathInfo result;
String moduleName;
@Override
public boolean process(Library library) {
for (VirtualFile root : library.getFiles(javaDocRootType)) {
if (VfsUtilCore.isAncestor(root, file, false)) {
result = new PathInfo(file, root, moduleName, true);
return false;
}
}
return true;
}
}
LibraryProcessor processor = new LibraryProcessor();
AccessToken token = ReadAction.start();
try {
ModuleManager moduleManager = ModuleManager.getInstance(project);
for (Module module : moduleManager.getModules()) {
if (module.isDisposed()) {
continue;
}
processor.moduleName = module.getName();
ModuleRootManager.getInstance(module).orderEntries().forEachLibrary(processor);
if (processor.result != null) {
return processor.result;
}
}
processor.moduleName = null;
for (Library library : LibraryTablesRegistrar.getInstance().getLibraryTable(project).getLibraries()) {
if (!processor.process(library)) {
return processor.result;
}
}
}
finally {
token.finish();
}
return null;
}
@Nullable
private static String getModuleNameQualifier(@NotNull Project project, @Nullable Module module) {
if (module != null &&
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* 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.
@@ -19,10 +19,11 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.ex.http.HttpFileSystem;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
@@ -30,7 +31,6 @@ import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class PlatformDocumentationUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.documentation.PlatformDocumentationUtil");
private static final @NonNls Pattern ourLtFixupPattern = Pattern.compile("<([^/^\\w^!])");
@@ -38,19 +38,23 @@ public class PlatformDocumentationUtil {
private static final @NonNls String LT_ENTITY = "&lt;";
@Nullable
public static List<String> getHttpRoots(final String[] roots, String relPath) {
final ArrayList<String> result = new ArrayList<String>();
public static List<String> getHttpRoots(@NotNull String[] roots, String relPath) {
List<String> result = new SmartList<String>();
for (String root : roots) {
final VirtualFile virtualFile = VirtualFileManager.getInstance().findFileByUrl(root);
VirtualFile virtualFile = VirtualFileManager.getInstance().findFileByUrl(root);
if (virtualFile != null) {
if (virtualFile.getFileSystem() instanceof HttpFileSystem) {
String url = virtualFile.getUrl();
if (!url.endsWith("/")) url += "/";
if (!url.endsWith("/")) {
url += "/";
}
result.add(url + relPath);
}
else {
VirtualFile file = virtualFile.findFileByRelativePath(relPath);
if (file != null) result.add(file.getUrl());
if (file != null) {
result.add(file.getUrl());
}
}
}
}
@@ -705,33 +705,35 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
@Override
public void actionPerformed(AnActionEvent e) {
if (myElement != null) {
final PsiElement element = myElement.getElement();
final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element);
final PsiElement originalElement = DocumentationManager.getOriginalElement(element);
boolean processed = false;
if (provider instanceof CompositeDocumentationProvider) {
for (DocumentationProvider p : ((CompositeDocumentationProvider)provider).getAllProviders()) {
if (p instanceof ExternalDocumentationHandler && ((ExternalDocumentationHandler)p).handleExternal(element, originalElement)) {
processed = true;
break;
}
}
}
if (myElement == null) {
return;
}
if (!processed) {
final Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(e.getDataContext());
final List<String> urls;
if (!StringUtil.isEmptyOrSpaces(myEffectiveExternalUrl)) {
urls = Collections.singletonList(myEffectiveExternalUrl);
} else {
urls = provider.getUrlFor(element, originalElement);
assert urls != null : provider;
assert !urls.isEmpty() : provider;
final PsiElement element = myElement.getElement();
final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element);
final PsiElement originalElement = DocumentationManager.getOriginalElement(element);
boolean processed = false;
if (provider instanceof CompositeDocumentationProvider) {
for (DocumentationProvider p : ((CompositeDocumentationProvider)provider).getAllProviders()) {
if (p instanceof ExternalDocumentationHandler && ((ExternalDocumentationHandler)p).handleExternal(element, originalElement)) {
processed = true;
break;
}
ExternalJavaDocAction.showExternalJavadoc(urls, component);
}
}
if (!processed) {
List<String> urls;
if (!StringUtil.isEmptyOrSpaces(myEffectiveExternalUrl)) {
urls = Collections.singletonList(myEffectiveExternalUrl);
}
else {
urls = provider.getUrlFor(element, originalElement);
assert urls != null : provider;
assert !urls.isEmpty() : provider;
}
ExternalJavaDocAction.showExternalJavadoc(urls, PlatformDataKeys.CONTEXT_COMPONENT.getData(e.getDataContext()));
}
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -35,11 +35,13 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.util.ArrayUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ExternalJavaDocAction extends AnAction {
@@ -90,8 +92,8 @@ public class ExternalJavaDocAction extends AnAction {
}
}
public static void showExternalJavadoc(List<String> urls, Component component) {
final HashSet<String> set = new HashSet<String>(urls);
public static void showExternalJavadoc(@NotNull List<String> urls, Component component) {
Set<String> set = new THashSet<String>(urls);
if (set.size() > 1) {
JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<String>("Choose external documentation root", ArrayUtil.toStringArray(set)) {
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* 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.
@@ -137,10 +137,6 @@ public class BrowserLauncherAppless extends BrowserLauncher {
private void openOrBrowse(@NotNull String url, boolean browse, @Nullable Project project) {
url = url.trim();
if (url.startsWith("jar:")) {
return;
}
URI uri;
if (BrowserUtil.isAbsoluteURL(url)) {
uri = VfsUtil.toUri(url);
@@ -35,7 +35,7 @@ import java.util.Locale;
)
public class KeyboardSettingsExternalizable implements PersistentStateComponent<KeyboardSettingsExternalizable.OptionSet> {
private static final String [] supportedNonEnglishLanguages = {"de", "fr", "it"};
private static final String [] supportedNonEnglishLanguages = {"de", "fr", "it", "uk"};
public static boolean isSupportedKeyboardLayout(@NotNull Component component) {
if (SystemInfo.isMac) return false;
@@ -92,6 +92,10 @@ public class KeyboardSettingsExternalizable implements PersistentStateComponent<
myOptions = state;
}
public boolean isUkrainianKeyboard (Component c) {
return c!=null && "uk".equals(c.getInputContext().getLocale().getLanguage());
}
public boolean isNonEnglishKeyboardSupportEnabled () {
return myOptions.USE_NON_ENGLISH_KEYBOARD;
}
@@ -416,20 +416,8 @@ public class IdeEventQueue extends EventQueue {
if (e instanceof KeyEvent) {
KeyEvent ke = (KeyEvent)e;
// Alt,keyChar=Undefined keyChar,modifiers=Ctrl+Alt,extModifiers=Ctrl+Alt+Button5,keyLocation=KEY_LOCATION_RIGHT
//if (ke.getKeyCode() == KeyEvent.VK_ALT && ke.getID() == KeyEvent.KEY_PRESSED) {
//
// if (ke.getKeyLocation() == KeyEvent.KEY_LOCATION_RIGHT) {
// if ((ke.getModifiersEx() & (InputEvent.ALT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)) != (InputEvent.ALT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK))
// {
// altGrIsPressed = true;
// }
// }
//
//} else {
// altGrIsPressed = false;
//}
// Try to get it from editor
Component sourceComponent = WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow();
if (ke.getID() == KeyEvent.KEY_PRESSED) {
switch (ke.getKeyCode()) {
@@ -459,8 +447,15 @@ public class IdeEventQueue extends EventQueue {
}
}
if (!leftAltIsPressed && KeyboardSettingsExternalizable.getInstance().isUkrainianKeyboard(sourceComponent) ) {
if ('ґ' == ke.getKeyChar() || ke.getKeyCode() == KeyEvent.VK_U) {
ke = new KeyEvent(ke.getComponent(), ke.getID(), ke.getWhen(), 0,
KeyEvent.VK_UNDEFINED, 'ґ', ke.getKeyLocation());
ke.setKeyCode(KeyEvent.VK_U);
ke.setKeyChar('ґ');
return ke;
}
}
Integer keyCodeFromChar = CharToVKeyMap.get(ke.getKeyChar());
if (keyCodeFromChar != null) {
@@ -469,15 +464,12 @@ public class IdeEventQueue extends EventQueue {
ke.setKeyCode(keyCodeFromChar);
}
// Try to get it from editor
Component sourceComponent = WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow();
//for (int i = 0; sourceComponent == null && i < WindowManagerEx.getInstanceEx().getAllProjectFrames().length; i++) {
// sourceComponent = WindowManagerEx.getInstanceEx().getAllProjectFrames()[i].getComponent();
//}
if (sourceComponent != null) {
if (sourceComponent.getInputContext().getLocale().getLanguage().equals("de")) {
if (KeyboardSettingsExternalizable.isSupportedKeyboardLayout(sourceComponent)) {
if ((ke.getModifiersEx() & (InputEvent.ALT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)) != 0 /*&& ke.getKeyLocation() == KeyEvent.KEY_LOCATION_RIGHT*/) {
// On German keyboard layout on Windows we are getting on key press
// ctrl + alt instead of AltGr
@@ -18,7 +18,10 @@ package com.jetbrains.python.inspections.quickfix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
@@ -26,16 +29,15 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
/**
* For:
* class B(A):
* def __init__(self):
* A.__init__(self) # inserted
* print "Constructor B was called"
*
* def __init__(self):
* A.__init__(self) # inserted
* print "Constructor B was called"
* <p/>
* User: catherine
*/
public class AddCallSuperQuickFix implements LocalQuickFix {
@@ -52,7 +54,7 @@ public class AddCallSuperQuickFix implements LocalQuickFix {
}
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
PyFunction problemFunction = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PyFunction.class);
final PyFunction problemFunction = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PyFunction.class);
if (problemFunction == null) return;
final StringBuilder superCall = new StringBuilder();
final PyClass klass = problemFunction.getContainingClass();
@@ -63,35 +65,56 @@ public class AddCallSuperQuickFix implements LocalQuickFix {
final PyClass superClass = superClasses[0];
final PyFunction superInit = superClass.findMethodByName(PyNames.INIT, true);
if (superInit == null) return;
boolean addComma = true;
final boolean addComma;
if (klass.isNewStyleClass()) {
addComma = false;
if (LanguageLevel.forElement(klass).isPy3K())
if (LanguageLevel.forElement(klass).isPy3K()) {
superCall.append("super().__init__(");
else
}
else {
superCall.append("super(").append(klass.getName()).append(", self).__init__(");
}
}
else {
addComma = true;
superCall.append(superClass.getName());
superCall.append(".__init__(self");
}
StringBuilder newFunction = new StringBuilder("def __init__(self");
final StringBuilder newFunction = new StringBuilder("def __init__(self");
buildParameterList(problemFunction, superInit, superCall, newFunction, addComma);
final Couple<List<String>> couple = buildNewFunctionParamsAndSuperInitCallArgs(problemFunction, superInit);
final List<String> newParameters = couple.getFirst();
if (!newParameters.isEmpty()) {
newFunction.append(", ");
}
StringUtil.join(newParameters, ", ", newFunction);
newFunction.append(")");
if (problemFunction.getAnnotation() != null) {
newFunction.append(problemFunction.getAnnotation().getText());
}
newFunction.append(":\n\t");
final List<String> superCallArguments = couple.getSecond();
if (addComma && !superCallArguments.isEmpty()) {
superCall.append(", ");
}
StringUtil.join(superCallArguments, ", ", superCall);
superCall.append(")");
final PyStatementList statementList = problemFunction.getStatementList();
PyExpression docstring = null;
final PyStatement[] statements = statementList.getStatements();
if (statements.length != 0 && statements[0] instanceof PyExpressionStatement) {
PyExpressionStatement st = (PyExpressionStatement)statements[0];
if (st.getExpression() instanceof PyStringLiteralExpression)
final PyExpressionStatement st = (PyExpressionStatement)statements[0];
if (st.getExpression() instanceof PyStringLiteralExpression) {
docstring = st.getExpression();
}
}
newFunction.append("):\n\t");
if (docstring != null)
if (docstring != null) {
newFunction.append(docstring.getText()).append("\n\t");
}
newFunction.append(superCall).append("\n\t");
boolean first = true;
for (PyStatement statement : statements) {
@@ -102,89 +125,249 @@ public class AddCallSuperQuickFix implements LocalQuickFix {
newFunction.append(statement.getText()).append("\n\t");
}
problemFunction.replace(
PyElementGenerator.getInstance(project).createFromText(LanguageLevel.forElement(problemFunction), PyFunction.class,
newFunction.toString()));
final PyElementGenerator generator = PyElementGenerator.getInstance(project);
problemFunction.replace(generator.createFromText(LanguageLevel.forElement(problemFunction), PyFunction.class, newFunction.toString()));
}
private static void buildParameterList(@NotNull final PyFunction problemFunction,
@NotNull final PyFunction superInit,
@NotNull final StringBuilder superCall,
@NotNull final StringBuilder newFunction, boolean addComma) {
final PyParameter[] parameters = problemFunction.getParameterList().getParameters();
final List<String> problemParams = new ArrayList<String>();
final List<String> functionParams = new ArrayList<String>();
String starName = null;
String doubleStarName = null;
for (int i = 1; i != parameters.length; i++) {
PyParameter p = parameters[i];
functionParams.add(p.getName());
if (p.getText().startsWith("**")) {
doubleStarName = p.getText();
continue;
@NotNull
private static Couple<List<String>> buildNewFunctionParamsAndSuperInitCallArgs(@NotNull PyFunction origInit,
@NotNull PyFunction superInit) {
final List<String> newFunctionParams = new ArrayList<String>();
final List<String> superCallArgs = new ArrayList<String>();
final ParametersInfo origInfo = new ParametersInfo(origInit.getParameterList());
final ParametersInfo superInfo = new ParametersInfo(superInit.getParameterList());
// Required parameters (not-keyword)
for (PyParameter param : origInfo.getRequiredParameters()) {
newFunctionParams.add(param.getText());
}
for (PyParameter param : superInfo.getRequiredParameters()) {
// Special case as if base class has constructor __init__((a, b), c) and
// subclass has constructor __init__(a, (b, c))
final PyTupleParameter tupleParam = param.getAsTuple();
if (tupleParam != null) {
final List<String> uniqueNames = collectParameterNames(tupleParam);
final boolean hasDuplicates = uniqueNames.removeAll(origInfo.getAllParameterNames());
if (hasDuplicates) {
newFunctionParams.addAll(uniqueNames);
}
else {
newFunctionParams.add(param.getText());
}
// Retain original structure of tuple parameter.
// Note that tuple parameters cannot have annotations or nested default values, so it's syntactically safe
superCallArgs.add(param.getText());
}
if (p.getText().startsWith("*")) {
starName = p.getText();
continue;
else {
if (!origInfo.getAllParameterNames().contains(param.getName())) {
newFunctionParams.add(param.getText());
}
superCallArgs.add(param.getName());
}
if (p.getDefaultValue() != null) {
problemParams.add(p.getText());
continue;
}
newFunction.append(",").append(p.getText());
}
addParametersFromSuper(superInit, superCall, newFunction, addComma, problemParams, functionParams, starName, doubleStarName);
// Optional parameters (not-keyword)
for (PyParameter param : origInfo.getOptionalParameters()) {
newFunctionParams.add(param.getText());
}
// Positional vararg
PyParameter starredParam = null;
if (origInfo.getPositionalContainerParameter() != null) {
starredParam = origInfo.getPositionalContainerParameter();
}
else if (superInfo.getPositionalContainerParameter() != null) {
starredParam = superInfo.getPositionalContainerParameter();
}
else if (origInfo.getSingleStarParameter() != null) {
starredParam = origInfo.getSingleStarParameter();
}
else if (superInfo.getSingleStarParameter() != null) {
starredParam = superInfo.getSingleStarParameter();
}
if (starredParam != null) {
newFunctionParams.add(starredParam.getText());
if (superInfo.getPositionalContainerParameter() != null) {
superCallArgs.add("*" + starredParam.getName());
}
}
// Required keyword-only parameters
for (PyParameter param : origInfo.getRequiredKeywordOnlyParameters()) {
newFunctionParams.add(param.getText());
}
for (PyParameter param : superInfo.getRequiredKeywordOnlyParameters()) {
if (!origInfo.getAllParameterNames().contains(param.getName())) {
newFunctionParams.add(param.getText());
}
superCallArgs.add(param.getName() + "=" + param.getName());
}
// Optional keyword-only parameters
for (PyParameter param : origInfo.getOptionalKeywordOnlyParameters()) {
newFunctionParams.add(param.getText());
}
// Keyword vararg
PyParameter doubleStarredParam = null;
if (origInfo.getKeywordContainerParameter() != null) {
doubleStarredParam = origInfo.getKeywordContainerParameter();
}
else if (superInfo.getKeywordContainerParameter() != null) {
doubleStarredParam = superInfo.getKeywordContainerParameter();
}
if (doubleStarredParam != null) {
newFunctionParams.add(doubleStarredParam.getText());
if (superInfo.getKeywordContainerParameter() != null) {
superCallArgs.add("**" + doubleStarredParam.getName());
}
}
return Couple.of(newFunctionParams, superCallArgs);
}
private static void addParametersFromSuper(@NotNull final PyFunction superInit, @NotNull final StringBuilder superCall,
@NotNull final StringBuilder newFunction, boolean addComma,
@NotNull final List<String> problemParams, @NotNull final List<String> functionParams,
@Nullable String starName, @Nullable String doubleStarName) {
final PyParameterList paramList = superInit.getParameterList();
PyParameter[] parameters = paramList.getParameters();
boolean addDouble = false;
boolean addStar = false;
for (int i = 1; i != parameters.length; i++) {
PyParameter p = parameters[i];
if (p.getDefaultValue() != null) continue;
final String param = p.getName();
String paramText = p.getText();
if (paramText.startsWith("**")) {
addDouble = true;
if (doubleStarName == null)
doubleStarName = p.getText();
continue;
private static class ParametersInfo {
private final PyParameter mySelfParam;
/**
* Parameters without default value that come before first "*..." parameter.
*/
private final List<PyParameter> myRequiredParams = new ArrayList<PyParameter>();
/**
* Parameters with default value that come before first "*..." parameter.
*/
private final List<PyParameter> myOptionalParams = new ArrayList<PyParameter>();
/**
* Parameter of form "*args" (positional vararg), not the same as single "*".
*/
private final PyParameter myPositionalContainerParam;
/**
* Parameter "*", that is used to delimit normal and keyword-only parameters.
*/
private final PyParameter mySingleStarParam;
/**
* Parameters without default value that come after first "*..." parameter.
*/
private final List<PyParameter> myRequiredKwOnlyParams = new ArrayList<PyParameter>();
/**
* Parameters with default value that come after first "*..." parameter.
*/
private final List<PyParameter> myOptionalKwOnlyParams = new ArrayList<PyParameter>();
/**
* Parameter of form "**kwargs" (keyword vararg).
*/
private final PyParameter myKeywordContainerParam;
private final Set<String> myAllParameterNames = new LinkedHashSet<String>();
public ParametersInfo(@NotNull PyParameterList parameterList) {
PyParameter positionalContainer = null;
PyParameter singleStarParam = null;
PyParameter keywordContainer = null;
PyParameter selfParam = null;
for (PyParameter param : parameterList.getParameters()) {
myAllParameterNames.addAll(collectParameterNames(param));
if (param.isSelf()) {
selfParam = param;
}
else if (param.getText().equals("*")) {
singleStarParam = param;
}
else if (param.getText().startsWith("**")) {
keywordContainer = param;
}
else if (param.getText().startsWith("*")) {
positionalContainer = param;
}
else if (positionalContainer == null && singleStarParam == null) {
if (param.hasDefaultValue()) {
myOptionalParams.add(param);
}
else {
myRequiredParams.add(param);
}
}
else {
if (param.hasDefaultValue()) {
myOptionalKwOnlyParams.add(param);
}
else {
myRequiredKwOnlyParams.add(param);
}
}
}
if (paramText.startsWith("*")) {
addStar = true;
if (starName == null)
starName = p.getText();
continue;
}
if (addComma)
superCall.append(",");
superCall.append(param);
if (!functionParams.contains(param))
newFunction.append(",").append(param);
addComma = true;
mySelfParam = selfParam;
myPositionalContainerParam = positionalContainer;
mySingleStarParam = singleStarParam;
myKeywordContainerParam = keywordContainer;
}
for(String p : problemParams)
newFunction.append(",").append(p);
if (starName != null) {
newFunction.append(",").append(starName);
if (addStar) {
if (addComma) superCall.append(",");
superCall.append(starName);
addComma = true;
@Nullable
public PyParameter getSelfParameter() {
return mySelfParam;
}
@NotNull
public List<PyParameter> getRequiredParameters() {
return Collections.unmodifiableList(myRequiredParams);
}
@NotNull
public List<PyParameter> getOptionalParameters() {
return Collections.unmodifiableList(myOptionalParams);
}
@Nullable
public PyParameter getPositionalContainerParameter() {
return myPositionalContainerParam;
}
@Nullable
public PyParameter getSingleStarParameter() {
return mySingleStarParam;
}
@NotNull
public List<PyParameter> getRequiredKeywordOnlyParameters() {
return Collections.unmodifiableList(myRequiredKwOnlyParams);
}
@NotNull
public List<PyParameter> getOptionalKeywordOnlyParameters() {
return Collections.unmodifiableList(myOptionalKwOnlyParams);
}
@Nullable
public PyParameter getKeywordContainerParameter() {
return myKeywordContainerParam;
}
@NotNull
public Set<String> getAllParameterNames() {
return Collections.unmodifiableSet(myAllParameterNames);
}
}
@NotNull
private static List<String> collectParameterNames(@NotNull PyParameter param) {
final List<String> result = new ArrayList<String>();
collectParameterNames(param, result);
return result;
}
private static void collectParameterNames(@NotNull PyParameter param, @NotNull Collection<String> acc) {
final PyTupleParameter tupleParam = param.getAsTuple();
if (tupleParam != null) {
for (PyParameter subParam : tupleParam.getContents()) {
collectParameterNames(subParam, acc);
}
}
if (doubleStarName != null) {
newFunction.append(",").append(doubleStarName);
if (addDouble) {
if (addComma) superCall.append(",");
superCall.append(doubleStarName);
}
else {
ContainerUtil.addIfNotNull(acc, param.getName());
}
}
}
@@ -1,8 +0,0 @@
class Example1:
def __init__(self, field1: str):
self.field1 = field1
class Example2(Example1):
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self): ## Missed call to __init__ of super class
pass
@@ -1,8 +0,0 @@
class Example1:
def __init__(self, field1: str):
self.field1 = field1
class Example2(Example1):
def __init__(self, field1):
super().__init__(field1)
@@ -0,0 +1,7 @@
class A:
def __init__(self, (a, (b, c)), (d, e)):
pass
class B(A):
def <warning descr="Call to __init__ of super class is missed">__init_<caret>_</warning>(self, (a, b), c, e):
pass
@@ -0,0 +1,7 @@
class A:
def __init__(self, (a, (b, c)), (d, e)):
pass
class B(A):
def __init__(self, (a, b), c, e, d):
A.__init__(self, (a, (b, c)), (d, e))
@@ -0,0 +1,7 @@
class A:
def __init__(self, a):
pass
class B(A):
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self, b, c=1, *args, kw_only):
pass
@@ -0,0 +1,7 @@
class A:
def __init__(self, a):
pass
class B(A):
def __init__(self, b, a, c=1, *args, kw_only):
super().__init__(a)
@@ -0,0 +1,8 @@
class A:
def __init__(self, a, b=1, *args, kw_only):
pass
class B(A):
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self, c):
pass
@@ -0,0 +1,8 @@
class A:
def __init__(self, a, b=1, *args, kw_only):
pass
class B(A):
def __init__(self, c, a, *args, kw_only):
super().__init__(a, *args, kw_only=kw_only)
@@ -0,0 +1,8 @@
class A:
def __init__(self, a):
pass
class B(A):
def <warning descr="Call to __init__ of super class is missed">__init_<caret>_</warning>(self, a=1):
pass
@@ -0,0 +1,8 @@
class A:
def __init__(self, a):
pass
class B(A):
def __init__(self, a=1):
A.__init__(self, a)
@@ -0,0 +1,7 @@
class A:
def __init__(self, *, kw_only, optional_kw_only=None):
pass
class B(A):
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self):
pass
@@ -0,0 +1,7 @@
class A:
def __init__(self, *, kw_only):
pass
class B(A):
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self, *args, another_kw_only):
pass
@@ -0,0 +1,7 @@
class A:
def __init__(self, *, kw_only):
pass
class B(A):
def __init__(self, *args, another_kw_only, kw_only):
super().__init__(kw_only=kw_only)
@@ -0,0 +1,7 @@
class A:
def __init__(self, *, kw_only, optional_kw_only=None):
pass
class B(A):
def __init__(self, *, kw_only):
super().__init__(kw_only=kw_only)
@@ -0,0 +1,7 @@
class A:
def __init__(self, a:int, b:float, *args:tuple, c:complex, **kwargs:dict) -> None:
pass
class B(A):
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self, d:str, *, e:bytes) -> list:
pass
@@ -0,0 +1,7 @@
class A:
def __init__(self, a:int, b:float, *args:tuple, c:complex, **kwargs:dict) -> None:
pass
class B(A):
def __init__(self, d:str, a:int, b:float, *args:tuple, e:bytes, c:complex, **kwargs:dict) -> list:
super().__init__(a, b, *args, c=c, **kwargs)
@@ -24,6 +24,7 @@ import com.jetbrains.python.inspections.PyMissingConstructorInspection;
import com.jetbrains.python.inspections.PyStatementEffectInspection;
import com.jetbrains.python.psi.LanguageLevel;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@TestDataPath("$CONTENT_ROOT/../testData/inspections/")
public class Py3QuickFixTest extends PyTestCase {
@@ -32,39 +33,107 @@ public class Py3QuickFixTest extends PyTestCase {
return PyTestCase.ourPy3Descriptor;
}
// PY-13685
public void testReplacePrintEnd() {
runWithLanguageLevel(LanguageLevel.PYTHON34, new Runnable() {
@Override
public void run() {
doInspectionTest("ReplacePrintEnd.py", PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
}});
doInspectionTest(PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
}
});
}
// PY-13685
public void testReplacePrintComment() {
runWithLanguageLevel(LanguageLevel.PYTHON34, new Runnable() {
@Override
public void run() {
doInspectionTest("ReplacePrintComment.py", PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true,
true);
}});
doInspectionTest(PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
}
});
}
// PY-13685
public void testReplaceExecComment() {
runWithLanguageLevel(LanguageLevel.PYTHON34, new Runnable() {
@Override
public void run() {
doInspectionTest("ReplaceExecComment.py", PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true,
true);
}});
doInspectionTest(PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
}
});
}
public void testAddCallSuperAnnotations() {
runWithLanguageLevel(LanguageLevel.PYTHON33, new Runnable() {
// PY-15867
public void testAddCallSuperKeywordOnlyParamInSuperInit() {
runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
public void run() {
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
}
});
}
// PY-15867
public void testAddCallSuperKeywordOnlyParamInInit() {
runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
public void run() {
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
}
});
}
// PY-15867
public void testAddCallSuperSingleStarParamInSuperInit() {
runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
public void run() {
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
}
});
}
// PY-15867
public void testAddCallSuperSingleStarParamInSuperInitAndVarargInInit() {
runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
@Override
public void run() {
doInspectionTest("AddCallSuperAnnotations.py",
PyMissingConstructorInspection.class,
PyBundle.message("QFIX.add.super"), true, true);
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
}
});
}
// PY-11561
public void testAddCallSuperTypeAnnotationsPreserved() {
runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
@Override
public void run() {
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
}
});
}
// PY-8991
public void testRemoveUnicodePrefixFromGluedStringNodesWithSlash() {
runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() {
public void run() {
myFixture.configureByFile(getTestName(false) + ".py");
myFixture.checkHighlighting(true, false, false);
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("INTN.remove.leading.$0", "U"));
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(getTestName(false) + "_after.py");
}
});
}
// PY-8990
public void testRemoveUnicodePrefixFromGluedStringNodesInParenthesis() {
runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() {
public void run() {
myFixture.configureByFile(getTestName(false) + ".py");
myFixture.checkHighlighting(true, false, false);
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("INTN.remove.leading.$0", "U"));
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(getTestName(false) + "_after.py");
}
});
}
@@ -75,9 +144,16 @@ public class Py3QuickFixTest extends PyTestCase {
return PythonTestUtil.getTestDataPath() + "/inspections/";
}
protected void doInspectionTest(@TestDataFile @NonNls String testFileName,
final Class inspectionClass,
@NonNls String quickFixName,
private void doInspectionTest(@NotNull Class inspectionClass,
@NotNull String quickFixName,
boolean applyFix,
boolean available) {
doInspectionTest(getTestName(false) + ".py", inspectionClass, quickFixName, applyFix, available);
}
protected void doInspectionTest(@TestDataFile @NonNls @NotNull String testFileName,
@NotNull Class inspectionClass,
@NonNls @NotNull String quickFixName,
boolean applyFix,
boolean available) {
doInspectionTest(new String[]{testFileName}, inspectionClass, quickFixName, applyFix, available);
@@ -93,9 +169,9 @@ public class Py3QuickFixTest extends PyTestCase {
* @param available true if the fix should be available, false if it should be explicitly not available.
* @throws Exception
*/
protected void doInspectionTest(@NonNls String[] testFiles,
final Class inspectionClass,
@NonNls String quickFixName,
protected void doInspectionTest(@NonNls @NotNull String[] testFiles,
@NotNull Class inspectionClass,
@NonNls @NotNull String quickFixName,
boolean applyFix,
boolean available) {
myFixture.enableInspections(inspectionClass);
@@ -27,6 +27,7 @@ import com.jetbrains.python.inspections.*;
import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection;
import com.jetbrains.python.psi.LanguageLevel;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* @author dcheryasov
@@ -47,15 +48,19 @@ public class PyQuickFixTest extends PyTestCase {
}
public void testAddImport() {
doInspectionTest(new String[] { "AddImport.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, "Import 'ImportTarget'", true, true);
doInspectionTest(new String[]{"AddImport.py", "ImportTarget.py"}, PyUnresolvedReferencesInspection.class,
"Import 'ImportTarget'", true, true);
}
public void testAddImportDoc() {
doInspectionTest(new String[] { "AddImportDoc.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, "Import 'ImportTarget'", true, true);
doInspectionTest(new String[]{"AddImportDoc.py", "ImportTarget.py"}, PyUnresolvedReferencesInspection.class,
"Import 'ImportTarget'", true, true);
}
public void testAddImportDocComment() { // PY-728
doInspectionTest(new String[] { "AddImportDocComment.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, "Import 'ImportTarget'", true, true);
// PY-728
public void testAddImportDocComment() {
doInspectionTest(new String[]{"AddImportDocComment.py", "ImportTarget.py"}, PyUnresolvedReferencesInspection.class,
"Import 'ImportTarget'", true, true);
}
public void testImportFromModule() {
@@ -73,7 +78,8 @@ public class PyQuickFixTest extends PyTestCase {
assertEquals("Import 'module.MyOldStyleClass'", intention.getText());
}
public void testImportFromModuleStar() { // PY-6302
// PY-6302
public void testImportFromModuleStar() {
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
myFixture.copyDirectoryToProject("importFromModuleStar", "");
myFixture.configureFromTempProjectFile("source.py");
@@ -91,7 +97,8 @@ public class PyQuickFixTest extends PyTestCase {
settings.PREFER_FROM_IMPORT = false;
settings.HIGHLIGHT_UNUSED_IMPORTS = false;
try {
doInspectionTest(new String[]{"QualifyByImport.py", "QualifyByImportFoo.py"}, PyUnresolvedReferencesInspection.class, PyBundle.message("ACT.qualify.with.module"), true, true);
doInspectionTest(new String[]{"QualifyByImport.py", "QualifyByImportFoo.py"}, PyUnresolvedReferencesInspection.class,
PyBundle.message("ACT.qualify.with.module"), true, true);
}
finally {
settings.PREFER_FROM_IMPORT = oldPreferFrom;
@@ -104,7 +111,8 @@ public class PyQuickFixTest extends PyTestCase {
boolean oldHighlightUnused = settings.HIGHLIGHT_UNUSED_IMPORTS;
settings.HIGHLIGHT_UNUSED_IMPORTS = false;
try {
doInspectionTest(new String[]{"AddToImportFromList.py", "AddToImportFromFoo.py"}, PyUnresolvedReferencesInspection.class, "Import 'foo(a) from AddToImportFromFoo'", true, true);
doInspectionTest(new String[]{"AddToImportFromList.py", "AddToImportFromFoo.py"}, PyUnresolvedReferencesInspection.class,
"Import 'foo(a) from AddToImportFromFoo'", true, true);
}
finally {
settings.HIGHLIGHT_UNUSED_IMPORTS = oldHighlightUnused;
@@ -115,90 +123,86 @@ public class PyQuickFixTest extends PyTestCase {
// TODO: add tests for stub indexes-based autoimport of unimported somehow.
public void testAddSelf() {
doInspectionTest("AddSelf.py", PyMethodParametersInspection.class, PyBundle.message("QFIX.add.parameter.self", "self"), true, true);
doInspectionTest(PyMethodParametersInspection.class, PyBundle.message("QFIX.add.parameter.self", "self"), true, true);
}
public void testReplacePrint() {
doInspectionTest("ReplacePrint.py", PyCompatibilityInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
doInspectionTest(PyCompatibilityInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
}
public void testAddSelfFunction() { //PY-4556
doInspectionTest("AddSelfFunction.py",
PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.unresolved.reference", "get_a", "self"), true, true);
// PY-4556
public void testAddSelfFunction() {
doInspectionTest("AddSelfFunction.py", PyUnresolvedReferencesInspection.class,
PyBundle.message("QFIX.unresolved.reference", "get_a", "self"), true, true);
}
public void testAddSelfToClassmethod() { //PY-9721
doInspectionTest("AddSelfToClassmethod.py",
PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.unresolved.reference", "foo", "cls"), true, true);
// PY-9721
public void testAddSelfToClassmethod() {
doInspectionTest("AddSelfToClassmethod.py", PyUnresolvedReferencesInspection.class,
PyBundle.message("QFIX.unresolved.reference", "foo", "cls"), true, true);
}
public void testAddCls() {
doInspectionTest("AddCls.py", PyMethodParametersInspection.class, PyBundle.message("QFIX.add.parameter.self", "cls"), true, true);
doInspectionTest(PyMethodParametersInspection.class, PyBundle.message("QFIX.add.parameter.self", "cls"), true, true);
}
public void testRenameToSelf() {
doInspectionTest("RenameToSelf.py", PyMethodParametersInspection.class, PyBundle.message("QFIX.rename.parameter.to.$0", "self"), true,
true);
doInspectionTest(PyMethodParametersInspection.class, PyBundle.message("QFIX.rename.parameter.to.$0", "self"), true, true);
}
public void testRemoveTrailingSemicolon() {
doInspectionTest("RemoveTrailingSemicolon.py", PyTrailingSemicolonInspection.class, PyBundle.message("QFIX.remove.trailing.semicolon"),
true, true);
doInspectionTest(PyTrailingSemicolonInspection.class, PyBundle.message("QFIX.remove.trailing.semicolon"), true, true);
}
public void testDictCreation() {
doInspectionTest("DictCreation.py", PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
doInspectionTest(PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
}
public void testDictCreationTuple() { //PY-6283
doInspectionTest("DictCreationTuple.py", PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
// PY-6283
public void testDictCreationTuple() {
doInspectionTest(PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
}
public void testDictCreationDuplicate() { //PY-7318
doInspectionTest("DictCreationDuplicate.py", PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
// PY-7318
public void testDictCreationDuplicate() {
doInspectionTest(PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
}
public void testTransformClassicClass() {
doInspectionTest("TransformClassicClass.py", PyClassicStyleClassInspection.class,
PyBundle.message("QFIX.classic.class.transform"), true, true);
doInspectionTest(PyClassicStyleClassInspection.class, PyBundle.message("QFIX.classic.class.transform"), true, true);
}
public void testAddGlobalQuickFix() {
doInspectionTest("AddGlobalStatement.py", PyUnboundLocalVariableInspection.class,
PyBundle.message("QFIX.add.global"), true, true);
public void testAddGlobalStatement() {
doInspectionTest(PyUnboundLocalVariableInspection.class, PyBundle.message("QFIX.add.global"), true, true);
}
public void testAddGlobalExistingQuickFix() {
doInspectionTest("AddGlobalExistingStatement.py", PyUnboundLocalVariableInspection.class,
PyBundle.message("QFIX.add.global"), true, true);
public void testAddGlobalExistingStatement() {
doInspectionTest(PyUnboundLocalVariableInspection.class, PyBundle.message("QFIX.add.global"), true, true);
}
public void testSimplifyBooleanCheckQuickFix() {
doInspectionTest("SimplifyBooleanCheck.py", PySimplifyBooleanCheckInspection.class,
PyBundle.message("QFIX.simplify.$0", "b"), true, true);
public void testSimplifyBooleanCheck() {
doInspectionTest(PySimplifyBooleanCheckInspection.class, PyBundle.message("QFIX.simplify.$0", "b"), true, true);
}
public void testFromFutureImportQuickFix() {
doInspectionTest("MoveFromFutureImport.py", PyFromFutureImportInspection.class,
PyBundle.message("QFIX.move.from.future.import"), true, true);
public void testMoveFromFutureImport() {
doInspectionTest(PyFromFutureImportInspection.class, PyBundle.message("QFIX.move.from.future.import"), true, true);
}
public void testFromFutureImportQuickFixDocString() { // PY-10080
doInspectionTest("MoveFromFutureImportDocString.py", PyFromFutureImportInspection.class,
PyBundle.message("QFIX.move.from.future.import"), true, true);
// PY-10080
public void testMoveFromFutureImportDocString() {
doInspectionTest(PyFromFutureImportInspection.class, PyBundle.message("QFIX.move.from.future.import"), true, true);
}
public void testComparisonWithNoneQuickFix() {
doInspectionTest("ComparisonWithNone.py", PyComparisonWithNoneInspection.class,
PyBundle.message("QFIX.replace.equality"), true, true);
public void testComparisonWithNone() {
doInspectionTest(PyComparisonWithNoneInspection.class, PyBundle.message("QFIX.replace.equality"), true, true);
}
public void testAddClassFix() {
doInspectionTest("AddClass.py", PyUnresolvedReferencesInspection.class, "Create class 'Xyzzy'", true, true);
}
public void testAddFunctionToModule() { // PY-1602
// PY-1602
public void testAddFunctionToModule() {
doInspectionTest(
"AddFunctionToModule.py",
PyUnresolvedReferencesInspection.class,
@@ -207,7 +211,8 @@ public class PyQuickFixTest extends PyTestCase {
);
}
public void testRedundantParentheses() { // PY-1470
// PY-1470
public void testRedundantParentheses() {
String[] testFiles = new String[]{"RedundantParentheses.py"};
myFixture.enableInspections(PyRedundantParenthesesInspection.class);
myFixture.configureByFiles(testFiles);
@@ -216,88 +221,86 @@ public class PyQuickFixTest extends PyTestCase {
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"));
}
public void testRedundantParenthesesBoolean() { // PY-3095
doInspectionTest("RedundantParenthesesBoolean.py", PyRedundantParenthesesInspection.class,
PyBundle.message("QFIX.redundant.parentheses"), true, true);
// PY-3095
public void testRedundantParenthesesBoolean() {
doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true);
}
public void testRedundantParenthesesMore() { // PY-3239
doInspectionTest("RedundantParenthesesMore.py", PyRedundantParenthesesInspection.class,
PyBundle.message("QFIX.redundant.parentheses"), true, true);
// PY-3239
public void testRedundantParenthesesMore() {
doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true);
}
public void testRedundantParenthesesParenthesizedExpression() { // PY-12679
doInspectionTest("RedundantParenthesesParenthesizedExpression.py", PyRedundantParenthesesInspection.class,
PyBundle.message("QFIX.redundant.parentheses"), true, true);
// PY-12679
public void testRedundantParenthesesParenthesizedExpression() {
doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true);
}
// PY-15506
public void testEmptyListOfBaseClasses() {
doInspectionTest("EmptyListOfBaseClasses.py", PyRedundantParenthesesInspection.class,
PyBundle.message("QFIX.redundant.parentheses"), true, true);
doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true);
}
public void testChainedComparisons() { // PY-1020
doInspectionTest("ChainedComparisons.py", PyChainedComparisonsInspection.class,
PyBundle.message("QFIX.chained.comparison"), true, true);
// PY-1020
public void testChainedComparisons() {
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
}
public void testChainedComparison1() { // PY-3126
doInspectionTest("ChainedComparison1.py", PyChainedComparisonsInspection.class,
PyBundle.message("QFIX.chained.comparison"), true, true);
// PY-3126
public void testChainedComparison1() {
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
}
public void testChainedComparison2() { // PY-3126
doInspectionTest("ChainedComparison2.py", PyChainedComparisonsInspection.class,
PyBundle.message("QFIX.chained.comparison"), true, true);
// PY-3126
public void testChainedComparison2() {
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
}
public void testChainedComparison3() { // PY-3126
doInspectionTest("ChainedComparison3.py", PyChainedComparisonsInspection.class,
PyBundle.message("QFIX.chained.comparison"), true, true);
// PY-3126
public void testChainedComparison3() {
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
}
public void testChainedComparison4() { // PY-5623
doInspectionTest("ChainedComparison4.py", PyChainedComparisonsInspection.class,
PyBundle.message("QFIX.chained.comparison"), true, true);
// PY-5623
public void testChainedComparison4() {
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
}
public void testChainedComparison5() { // PY-6467
doInspectionTest("ChainedComparison5.py", PyChainedComparisonsInspection.class,
PyBundle.message("QFIX.chained.comparison"), true, true);
// PY-6467
public void testChainedComparison5() {
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
}
// PY-14002
public void testChainedComparisonWithCommonBinaryExpression() {
doInspectionTest("ChainedComparisonWithCommonBinaryExpression.py", PyChainedComparisonsInspection.class,
PyBundle.message("QFIX.chained.comparison"), true, true);
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
}
public void testStatementEffect() { // PY-1362, PY-2585
doInspectionTest("StatementEffect.py", PyStatementEffectInspection.class,
PyBundle.message("QFIX.statement.effect"), true, true);
// PY-1362, PY-2585
public void testStatementEffect() {
doInspectionTest(PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
}
public void testStatementEffectIntroduceVariable() { // PY-1265
doInspectionTest("StatementEffectIntroduceVariable.py", PyStatementEffectInspection.class,
PyBundle.message("QFIX.statement.effect.introduce.variable"), true, true);
// PY-1265
public void testStatementEffectIntroduceVariable() {
doInspectionTest(PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect.introduce.variable"), true, true);
}
public void testUnresolvedWith() { // PY-2083
// PY-2083
public void testUnresolvedWith() {
runWithLanguageLevel(LanguageLevel.PYTHON25, new Runnable() {
@Override
public void run() {
doInspectionTest("UnresolvedWith.py", PyUnresolvedReferencesInspection.class,
PyBundle.message("QFIX.unresolved.reference.add.future"), true, true);
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.unresolved.reference.add.future"), true, true);
}
});
}
public void testUnresolvedRefCreateFunction() { // PY-2092
doInspectionTest("UnresolvedRefCreateFunction.py", PyUnresolvedReferencesInspection.class,
// PY-2092
public void testUnresolvedRefCreateFunction() {
doInspectionTest(PyUnresolvedReferencesInspection.class,
PyBundle.message("QFIX.unresolved.reference.create.function.$0", "ref"), true, true);
}
@@ -305,109 +308,113 @@ public class PyQuickFixTest extends PyTestCase {
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
myFixture.configureByFile("UnresolvedRefNoCreateFunction.py");
myFixture.checkHighlighting(true, false, false);
final IntentionAction intentionAction = myFixture.getAvailableIntention(
PyBundle.message("QFIX.unresolved.reference.create.function.$0", "ref"));
final IntentionAction intentionAction = myFixture.getAvailableIntention(PyBundle.message("QFIX.unresolved.reference.create.function.$0", "ref"));
assertNull(intentionAction);
}
public void testReplaceNotEqOperator() {
doInspectionTest("ReplaceNotEqOperator.py", PyCompatibilityInspection.class,
PyBundle.message("INTN.replace.noteq.operator"), true, true);
doInspectionTest(PyCompatibilityInspection.class, PyBundle.message("INTN.replace.noteq.operator"), true, true);
}
public void testListCreation() {
doInspectionTest("ListCreation.py", PyListCreationInspection.class,
PyBundle.message("QFIX.list.creation"), true, true);
doInspectionTest(PyListCreationInspection.class, PyBundle.message("QFIX.list.creation"), true, true);
}
public void testConvertSingleQuotedDocstring() { //PY-1445
doInspectionTest("ConvertSingleQuotedDocstring.py", PySingleQuotedDocstringInspection.class,
PyBundle.message("QFIX.convert.single.quoted.docstring"), true, true);
// PY-1445
public void testConvertSingleQuotedDocstring() {
doInspectionTest(PySingleQuotedDocstringInspection.class, PyBundle.message("QFIX.convert.single.quoted.docstring"), true, true);
}
public void testConvertSingleQuotedDocstringEscape() { //PY-8926
doInspectionTest("ConvertSingleQuotedDocstringEscape.py", PySingleQuotedDocstringInspection.class,
PyBundle.message("QFIX.convert.single.quoted.docstring"), true, true);
// PY-8926
public void testConvertSingleQuotedDocstringEscape() {
doInspectionTest(PySingleQuotedDocstringInspection.class, PyBundle.message("QFIX.convert.single.quoted.docstring"), true, true);
}
public void testDefaultArgument() { //PY-3127
doInspectionTest("DefaultArgument.py", PyDefaultArgumentInspection.class,
PyBundle.message("QFIX.default.argument"), true, true);
// PY-3127
public void testDefaultArgument() {
doInspectionTest(PyDefaultArgumentInspection.class, PyBundle.message("QFIX.default.argument"), true, true);
}
public void testDefaultArgumentEmptyList() {
doInspectionTest("DefaultArgumentEmptyList.py", PyDefaultArgumentInspection.class,
PyBundle.message("QFIX.default.argument"), true, true);
doInspectionTest(PyDefaultArgumentInspection.class, PyBundle.message("QFIX.default.argument"), true, true);
}
public void testPyArgumentEqualDefault() { //PY-3125
doInspectionTest("ArgumentEqualDefault.py", PyArgumentEqualDefaultInspection.class,
PyBundle.message("QFIX.remove.argument.equal.default"), true, true);
// PY-3125
public void testArgumentEqualDefault() {
doInspectionTest(PyArgumentEqualDefaultInspection.class, PyBundle.message("QFIX.remove.argument.equal.default"), true, true);
}
public void testAddCallSuper() { //PY-3315
doInspectionTest("AddCallSuper.py", PyMissingConstructorInspection.class,
PyBundle.message("QFIX.add.super"), true, true);
// PY-3315
public void testAddCallSuper() {
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
}
public void testAddCallSuper1() { //PY-4017
doInspectionTest("AddCallSuper1.py", PyMissingConstructorInspection.class,
PyBundle.message("QFIX.add.super"), true, true);
// PY-4017
public void testAddCallSuper1() {
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
}
public void testAddCallSuperPass() { //PY-8654
doInspectionTest("AddCallSuperPass.py", PyMissingConstructorInspection.class,
PyBundle.message("QFIX.add.super"), true, true);
// PY-8654
public void testAddCallSuperPass() {
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
}
//PY-491, PY-13297
// PY-15867
public void testAddCallSuperOptionalAndRequiredParamsNameCollision() {
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
}
// PY-15927
public void testAddCallSuperConflictingTupleParam() {
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
}
// PY-491, PY-13297
public void testAddEncoding() {
doInspectionTest("AddEncoding.py", PyMandatoryEncodingInspection.class,
PyBundle.message("QFIX.add.encoding"), true, true);
doInspectionTest(PyMandatoryEncodingInspection.class, PyBundle.message("QFIX.add.encoding"), true, true);
}
// PY-13297
public void testAddEncodingAtLastLine() {
doInspectionTest("AddEncodingAtLastLine.py", PyMandatoryEncodingInspection.class,
PyBundle.message("QFIX.add.encoding"), true, true);
doInspectionTest(PyMandatoryEncodingInspection.class, PyBundle.message("QFIX.add.encoding"), true, true);
}
public void testRemoveDecorator() { //PY-3348
doInspectionTest("RemoveDecorator.py", PyDecoratorInspection.class,
PyBundle.message("QFIX.remove.decorator"), true, true);
// PY-3348
public void testRemoveDecorator() {
doInspectionTest(PyDecoratorInspection.class, PyBundle.message("QFIX.remove.decorator"), true, true);
}
public void testAddParameter() {
doInspectionTest("AddParameter.py", PyUnresolvedReferencesInspection.class,
doInspectionTest(PyUnresolvedReferencesInspection.class,
PyBundle.message("QFIX.unresolved.reference.add.param.$0", "test"), true, true);
}
public void testRenameUnresolvedReference() { //PY-6595
doInspectionTest("RenameUnresolvedReference.py", PyUnresolvedReferencesInspection.class,
PyBundle.message("QFIX.rename.unresolved.reference"), true, true);
// PY-6595
public void testRenameUnresolvedReference() {
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.rename.unresolved.reference"), true, true);
}
public void testSetFunctionToLiteral() { //PY-3120
// PY-3120
public void testSetFunctionToLiteral() {
runWithLanguageLevel(LanguageLevel.PYTHON27, new Runnable() {
@Override
public void run() {
doInspectionTest("SetFunctionToLiteral.py", PySetFunctionToLiteralInspection.class,
PyBundle.message("QFIX.replace.function.set.with.literal"), true, true);
doInspectionTest(PySetFunctionToLiteralInspection.class, PyBundle.message("QFIX.replace.function.set.with.literal"), true, true);
}
});
}
public void testDictComprehensionToCall() {
doInspectionTest("DictComprehensionToCall.py", PyCompatibilityInspection.class,
PyBundle.message("INTN.convert.dict.comp.to"), true, true);
doInspectionTest(PyCompatibilityInspection.class, PyBundle.message("INTN.convert.dict.comp.to"), true, true);
}
public void testDocstringParams() { //PY-3394
// PY-3394
public void testDocstringParams() {
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
try {
doInspectionTest("DocstringParams.py", PyDocstringInspection.class,
PyBundle.message("QFIX.docstring.add.$0", "b"), true, true);
doInspectionTest(PyDocstringInspection.class,
PyBundle.message("QFIX.docstring.add.$0", "b"), true, true);
}
finally {
documentationSettings.setFormat(DocStringFormat.PLAIN);
@@ -418,20 +425,19 @@ public class PyQuickFixTest extends PyTestCase {
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
try {
doInspectionTest("DocstringParams1.py", PyDocstringInspection.class,
PyBundle.message("QFIX.docstring.remove.$0", "c"), true, true);
doInspectionTest(PyDocstringInspection.class, PyBundle.message("QFIX.docstring.remove.$0", "c"), true, true);
}
finally {
documentationSettings.setFormat(DocStringFormat.PLAIN);
}
}
public void testDocstringParams2() { //PY-4964
// PY-4964
public void testDocstringParams2() {
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
try {
doInspectionTest("DocstringParams2.py", PyDocstringInspection.class,
PyBundle.message("QFIX.docstring.add.$0", "ham"), true, true);
doInspectionTest(PyDocstringInspection.class, PyBundle.message("QFIX.docstring.add.$0", "ham"), true, true);
}
finally {
documentationSettings.setFormat(DocStringFormat.PLAIN);
@@ -449,9 +455,9 @@ public class PyQuickFixTest extends PyTestCase {
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"));
}
public void testUnresolvedRefTrueFalse() { //PY-3051
doInspectionTest("UnresolvedRefTrueFalse.py", PyUnresolvedReferencesInspection.class,
PyBundle.message("QFIX.unresolved.reference.replace.$0", "True"), true, true);
// PY-3051
public void testUnresolvedRefTrueFalse() {
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.unresolved.reference.replace.$0", "True"), true, true);
}
public void testUnnecessaryBackslashInArgumentList() {
@@ -498,43 +504,22 @@ public class PyQuickFixTest extends PyTestCase {
myFixture.checkHighlighting(true, false, true);
}
// PY-8991
public void testRemoveUnicodePrefixFromGluedStringNodesWithSlash() {
runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() {
public void run() {
myFixture.configureByFile(getTestName(false) + ".py");
myFixture.checkHighlighting(true, false, false);
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("INTN.remove.leading.$0", "U"));
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(getTestName(false) + "_after.py");
}
});
}
// PY-8990
public void testRemoveUnicodePrefixFromGluedStringNodesInParenthesis() {
runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() {
public void run() {
myFixture.configureByFile(getTestName(false) + ".py");
myFixture.checkHighlighting(true, false, false);
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("INTN.remove.leading.$0", "U"));
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(getTestName(false) + "_after.py");
}
});
}
@Override
@NonNls
protected String getTestDataPath() {
return PythonTestUtil.getTestDataPath() + "/inspections/";
}
protected void doInspectionTest(@TestDataFile @NonNls String testFileName,
final Class inspectionClass,
@NonNls String quickFixName,
private void doInspectionTest(@NotNull Class inspectionClass,
@NotNull String quickFixName,
boolean applyFix,
boolean available) {
doInspectionTest(getTestName(false) + ".py", inspectionClass, quickFixName, applyFix, available);
}
protected void doInspectionTest(@TestDataFile @NonNls @NotNull String testFileName,
@NotNull Class inspectionClass,
@NonNls @NotNull String quickFixName,
boolean applyFix,
boolean available) {
doInspectionTest(new String[]{testFileName}, inspectionClass, quickFixName, applyFix, available);
@@ -550,9 +535,9 @@ public class PyQuickFixTest extends PyTestCase {
* @param available true if the fix should be available, false if it should be explicitly not available.
* @throws Exception
*/
protected void doInspectionTest(@NonNls String[] testFiles,
final Class inspectionClass,
@NonNls String quickFixName,
protected void doInspectionTest(@NonNls @NotNull String[] testFiles,
@NotNull Class inspectionClass,
@NonNls @NotNull String quickFixName,
boolean applyFix,
boolean available) {
myFixture.enableInspections(inspectionClass);
@@ -48,7 +48,7 @@ public class WebBrowserServiceImpl extends WebBrowserService {
VirtualFile file = request.getVirtualFile();
return file instanceof LightVirtualFile || !request.getFile().getViewProvider().isPhysical()
? Collections.<Url>emptyList()
: Collections.singleton(Urls.newFromVirtualFile(file));
: Collections.singletonList(Urls.newFromVirtualFile(file));
}
@NotNull