diff --git a/java/java-impl/java-impl.iml b/java/java-impl/java-impl.iml index cf601bbd0f76..ee71056b6734 100644 --- a/java/java-impl/java-impl.iml +++ b/java/java-impl/java-impl.iml @@ -56,11 +56,11 @@ + - - + \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java index cb215d06380d..0a61a7c94c06 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -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 findUrlForClass(PsiClass aClass) { + public static List 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 findUrlForVirtualFile(final Project project, final VirtualFile virtualFile, final String relPath) { + public static List 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 orderEntries = fileIndex.getOrderEntriesForFile(virtualFile); - for (OrderEntry orderEntry : orderEntries) { - final String[] files = JavadocOrderRootType.getUrls(orderEntry); - final List 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 urls = file == null ? null : BuiltInWebBrowserUrlProvider.getUrls(file, project, null); + if (!ContainerUtil.isEmpty(urls)) { + List result = new SmartList(); + for (Url url : urls) { + result.add(url.toExternalForm()); + } + return result; + } + } + } + + List httpRoot = PlatformDocumentationUtil.getHttpRoots(JavadocOrderRootType.getUrls(orderEntry), relPath); + if (httpRoot != null) { + return httpRoot; + } } return null; } diff --git a/platform/built-in-server/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java b/platform/built-in-server/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java index fa09f74d71ea..70ed18f5f98b 100644 --- a/platform/built-in-server/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java +++ b/platform/built-in-server/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java @@ -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 { + 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 && diff --git a/platform/core-impl/src/com/intellij/codeInsight/documentation/PlatformDocumentationUtil.java b/platform/core-impl/src/com/intellij/codeInsight/documentation/PlatformDocumentationUtil.java index 966d8173c150..fa519f0249bb 100644 --- a/platform/core-impl/src/com/intellij/codeInsight/documentation/PlatformDocumentationUtil.java +++ b/platform/core-impl/src/com/intellij/codeInsight/documentation/PlatformDocumentationUtil.java @@ -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 = "<"; @Nullable - public static List getHttpRoots(final String[] roots, String relPath) { - final ArrayList result = new ArrayList(); + public static List getHttpRoots(@NotNull String[] roots, String relPath) { + List result = new SmartList(); 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()); + } } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index d687848a4949..36e8f4005070 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -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 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 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 diff --git a/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java b/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java index 9d73cd569c40..f974d35afd8d 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java @@ -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 urls, Component component) { - final HashSet set = new HashSet(urls); + public static void showExternalJavadoc(@NotNull List urls, Component component) { + Set set = new THashSet(urls); if (set.size() > 1) { JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep("Choose external documentation root", ArrayUtil.toStringArray(set)) { @Override diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java index 2385d0000bee..c7f3989c8b7c 100644 --- a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java +++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java @@ -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); diff --git a/platform/platform-api/src/com/intellij/openapi/keymap/KeyboardSettingsExternalizable.java b/platform/platform-api/src/com/intellij/openapi/keymap/KeyboardSettingsExternalizable.java index 8f4c6f6b4329..e96abb6fd18f 100644 --- a/platform/platform-api/src/com/intellij/openapi/keymap/KeyboardSettingsExternalizable.java +++ b/platform/platform-api/src/com/intellij/openapi/keymap/KeyboardSettingsExternalizable.java @@ -35,7 +35,7 @@ import java.util.Locale; ) public class KeyboardSettingsExternalizable implements PersistentStateComponent { - 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; } diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java index f6a0b2d9e7fb..ad541c2675dc 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java @@ -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 diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java index c8ac88af9da1..d6568240ecf4 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AddCallSuperQuickFix.java @@ -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" + *

* 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> couple = buildNewFunctionParamsAndSuperInitCallArgs(problemFunction, superInit); + final List 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 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 problemParams = new ArrayList(); - final List functionParams = new ArrayList(); - 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> buildNewFunctionParamsAndSuperInitCallArgs(@NotNull PyFunction origInit, + @NotNull PyFunction superInit) { + final List newFunctionParams = new ArrayList(); + final List superCallArgs = new ArrayList(); + + 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 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 problemParams, @NotNull final List 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 myRequiredParams = new ArrayList(); + /** + * Parameters with default value that come before first "*..." parameter. + */ + private final List myOptionalParams = new ArrayList(); + /** + * 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 myRequiredKwOnlyParams = new ArrayList(); + /** + * Parameters with default value that come after first "*..." parameter. + */ + private final List myOptionalKwOnlyParams = new ArrayList(); + /** + * Parameter of form "**kwargs" (keyword vararg). + */ + private final PyParameter myKeywordContainerParam; + + private final Set myAllParameterNames = new LinkedHashSet(); + + 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 getRequiredParameters() { + return Collections.unmodifiableList(myRequiredParams); + } + + @NotNull + public List getOptionalParameters() { + return Collections.unmodifiableList(myOptionalParams); + } + + @Nullable + public PyParameter getPositionalContainerParameter() { + return myPositionalContainerParam; + } + + @Nullable + public PyParameter getSingleStarParameter() { + return mySingleStarParam; + } + + @NotNull + public List getRequiredKeywordOnlyParameters() { + return Collections.unmodifiableList(myRequiredKwOnlyParams); + } + + @NotNull + public List getOptionalKeywordOnlyParameters() { + return Collections.unmodifiableList(myOptionalKwOnlyParams); + } + + @Nullable + public PyParameter getKeywordContainerParameter() { + return myKeywordContainerParam; + } + + @NotNull + public Set getAllParameterNames() { + return Collections.unmodifiableSet(myAllParameterNames); + } + } + + @NotNull + private static List collectParameterNames(@NotNull PyParameter param) { + final List result = new ArrayList(); + collectParameterNames(param, result); + return result; + } + + + private static void collectParameterNames(@NotNull PyParameter param, @NotNull Collection 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()); } } } diff --git a/python/testData/inspections/AddCallSuperAnnotations.py b/python/testData/inspections/AddCallSuperAnnotations.py deleted file mode 100644 index b50ae1b4fb72..000000000000 --- a/python/testData/inspections/AddCallSuperAnnotations.py +++ /dev/null @@ -1,8 +0,0 @@ -class Example1: - def __init__(self, field1: str): - self.field1 = field1 - - -class Example2(Example1): - def __init__(self): ## Missed call to __init__ of super class - pass \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperAnnotations_after.py b/python/testData/inspections/AddCallSuperAnnotations_after.py deleted file mode 100644 index 4bfd08c375e3..000000000000 --- a/python/testData/inspections/AddCallSuperAnnotations_after.py +++ /dev/null @@ -1,8 +0,0 @@ -class Example1: - def __init__(self, field1: str): - self.field1 = field1 - - -class Example2(Example1): - def __init__(self, field1): - super().__init__(field1) \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperConflictingTupleParam.py b/python/testData/inspections/AddCallSuperConflictingTupleParam.py new file mode 100644 index 000000000000..276e16dc2e73 --- /dev/null +++ b/python/testData/inspections/AddCallSuperConflictingTupleParam.py @@ -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): + pass \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperConflictingTupleParam_after.py b/python/testData/inspections/AddCallSuperConflictingTupleParam_after.py new file mode 100644 index 000000000000..5a41d4a81d09 --- /dev/null +++ b/python/testData/inspections/AddCallSuperConflictingTupleParam_after.py @@ -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)) \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperKeywordOnlyParamInInit.py b/python/testData/inspections/AddCallSuperKeywordOnlyParamInInit.py new file mode 100644 index 000000000000..e1da8962d217 --- /dev/null +++ b/python/testData/inspections/AddCallSuperKeywordOnlyParamInInit.py @@ -0,0 +1,7 @@ +class A: + def __init__(self, a): + pass + +class B(A): + def __init__(self, b, c=1, *args, kw_only): + pass \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperKeywordOnlyParamInInit_after.py b/python/testData/inspections/AddCallSuperKeywordOnlyParamInInit_after.py new file mode 100644 index 000000000000..925cac6746a3 --- /dev/null +++ b/python/testData/inspections/AddCallSuperKeywordOnlyParamInInit_after.py @@ -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) \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperKeywordOnlyParamInSuperInit.py b/python/testData/inspections/AddCallSuperKeywordOnlyParamInSuperInit.py new file mode 100644 index 000000000000..5248dd92742a --- /dev/null +++ b/python/testData/inspections/AddCallSuperKeywordOnlyParamInSuperInit.py @@ -0,0 +1,8 @@ +class A: + def __init__(self, a, b=1, *args, kw_only): + pass + + +class B(A): + def __init__(self, c): + pass \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperKeywordOnlyParamInSuperInit_after.py b/python/testData/inspections/AddCallSuperKeywordOnlyParamInSuperInit_after.py new file mode 100644 index 000000000000..0ee340e47d36 --- /dev/null +++ b/python/testData/inspections/AddCallSuperKeywordOnlyParamInSuperInit_after.py @@ -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) \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperOptionalAndRequiredParamsNameCollision.py b/python/testData/inspections/AddCallSuperOptionalAndRequiredParamsNameCollision.py new file mode 100644 index 000000000000..3d3bb7d4b64e --- /dev/null +++ b/python/testData/inspections/AddCallSuperOptionalAndRequiredParamsNameCollision.py @@ -0,0 +1,8 @@ +class A: + def __init__(self, a): + pass + + +class B(A): + def __init__(self, a=1): + pass \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperOptionalAndRequiredParamsNameCollision_after.py b/python/testData/inspections/AddCallSuperOptionalAndRequiredParamsNameCollision_after.py new file mode 100644 index 000000000000..1693904e6b58 --- /dev/null +++ b/python/testData/inspections/AddCallSuperOptionalAndRequiredParamsNameCollision_after.py @@ -0,0 +1,8 @@ +class A: + def __init__(self, a): + pass + + +class B(A): + def __init__(self, a=1): + A.__init__(self, a) \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperSingleStarParamInSuperInit.py b/python/testData/inspections/AddCallSuperSingleStarParamInSuperInit.py new file mode 100644 index 000000000000..7ff489252191 --- /dev/null +++ b/python/testData/inspections/AddCallSuperSingleStarParamInSuperInit.py @@ -0,0 +1,7 @@ +class A: + def __init__(self, *, kw_only, optional_kw_only=None): + pass + +class B(A): + def __init__(self): + pass \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperSingleStarParamInSuperInitAndVarargInInit.py b/python/testData/inspections/AddCallSuperSingleStarParamInSuperInitAndVarargInInit.py new file mode 100644 index 000000000000..afca366ff1e3 --- /dev/null +++ b/python/testData/inspections/AddCallSuperSingleStarParamInSuperInitAndVarargInInit.py @@ -0,0 +1,7 @@ +class A: + def __init__(self, *, kw_only): + pass + +class B(A): + def __init__(self, *args, another_kw_only): + pass \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperSingleStarParamInSuperInitAndVarargInInit_after.py b/python/testData/inspections/AddCallSuperSingleStarParamInSuperInitAndVarargInInit_after.py new file mode 100644 index 000000000000..01cf279b21fc --- /dev/null +++ b/python/testData/inspections/AddCallSuperSingleStarParamInSuperInitAndVarargInInit_after.py @@ -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) \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperSingleStarParamInSuperInit_after.py b/python/testData/inspections/AddCallSuperSingleStarParamInSuperInit_after.py new file mode 100644 index 000000000000..1eb8c4228300 --- /dev/null +++ b/python/testData/inspections/AddCallSuperSingleStarParamInSuperInit_after.py @@ -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) \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperTypeAnnotationsPreserved.py b/python/testData/inspections/AddCallSuperTypeAnnotationsPreserved.py new file mode 100644 index 000000000000..76b33e20063e --- /dev/null +++ b/python/testData/inspections/AddCallSuperTypeAnnotationsPreserved.py @@ -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, *, e:bytes) -> list: + pass \ No newline at end of file diff --git a/python/testData/inspections/AddCallSuperTypeAnnotationsPreserved_after.py b/python/testData/inspections/AddCallSuperTypeAnnotationsPreserved_after.py new file mode 100644 index 000000000000..c8b5b3e67c00 --- /dev/null +++ b/python/testData/inspections/AddCallSuperTypeAnnotationsPreserved_after.py @@ -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) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/Py3QuickFixTest.java b/python/testSrc/com/jetbrains/python/Py3QuickFixTest.java index f757da9f3fac..10ed5fa597b4 100644 --- a/python/testSrc/com/jetbrains/python/Py3QuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/Py3QuickFixTest.java @@ -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); diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java index 9a55254d8287..1fc8572ae262 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java @@ -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); diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java index 6cd24659c003..097a1d1859fc 100644 --- a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java +++ b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java @@ -48,7 +48,7 @@ public class WebBrowserServiceImpl extends WebBrowserService { VirtualFile file = request.getVirtualFile(); return file instanceof LightVirtualFile || !request.getFile().getViewProvider().isPhysical() ? Collections.emptyList() - : Collections.singleton(Urls.newFromVirtualFile(file)); + : Collections.singletonList(Urls.newFromVirtualFile(file)); } @NotNull