diff --git a/colorSchemes/src/colorSchemes/Darcula.xml b/colorSchemes/src/colorSchemes/Darcula.xml
index 8356b0f6137a..bd7b3ac8efd0 100644
--- a/colorSchemes/src/colorSchemes/Darcula.xml
+++ b/colorSchemes/src/colorSchemes/Darcula.xml
@@ -1113,6 +1113,11 @@
+
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java b/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java
index bf0569b4755b..7347b430cacd 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java
@@ -155,13 +155,14 @@ public class HotSwapManager extends AbstractProjectComponent {
}
private void reloadClasses(DebuggerSession session, Map classesToReload, HotSwapProgress progress) {
- if (progress.isCancelled()) {
- session.setModifiedClassesScanRequired(true);
- return;
- }
final long newSwapTime = System.currentTimeMillis();
new ReloadClassesWorker(session, progress).reloadClasses(classesToReload);
- setTimeStamp(session, newSwapTime);
+ if (progress.isCancelled()) {
+ session.setModifiedClassesScanRequired(true);
+ }
+ else {
+ setTimeStamp(session, newSwapTime);
+ }
}
public static Map> findModifiedClasses(List sessions, Map> generatedPaths) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java
index 9a43bfbcc881..2898e3f10dd9 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java
@@ -114,32 +114,44 @@ class ReloadClassesWorker {
try {
RedefineProcessor redefineProcessor = new RedefineProcessor(virtualMachineProxy);
- int processedClassesCount = 0;
- for (final String qualifiedName : modifiedClasses.keySet()) {
- processedClassesCount++;
+ int processedEntriesCount = 0;
+ for (final Map.Entry entry : modifiedClasses.entrySet()) {
+ if (redefineProcessor.getProcessedClassesCount() == 0 && myProgress.isCancelled()) {
+ // once at least one class has been actually reloaded, do not interrupt the whole process
+ break;
+ }
+ processedEntriesCount++;
+ final String qualifiedName = entry.getKey();
if (qualifiedName != null) {
myProgress.setText(qualifiedName);
- myProgress.setFraction(processedClassesCount / (double)modifiedClasses.size());
+ myProgress.setFraction(processedEntriesCount / (double)modifiedClasses.size());
}
- final HotSwapFile fileDescr = modifiedClasses.get(qualifiedName);
try {
- redefineProcessor.processClass(qualifiedName, fileDescr.file);
+ redefineProcessor.processClass(qualifiedName, entry.getValue().file);
}
catch (IOException e) {
reportProblem(qualifiedName, e);
}
}
+
+ if (redefineProcessor.getProcessedClassesCount() == 0 && myProgress.isCancelled()) {
+ // once at least one class has been actually reloaded, do not interrupt the whole process
+ return;
+ }
+
redefineProcessor.processPending();
myProgress.setFraction(1);
final int partiallyRedefinedClassesCount = redefineProcessor.getPartiallyRedefinedClassesCount();
if (partiallyRedefinedClassesCount == 0) {
- myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION,
- DebuggerBundle.message("status.classes.reloaded", redefineProcessor.getProcessedClassesCount()));
+ myProgress.addMessage(
+ myDebuggerSession, MessageCategory.INFORMATION, DebuggerBundle.message("status.classes.reloaded", redefineProcessor.getProcessedClassesCount())
+ );
}
else {
- final String message = DebuggerBundle.message("status.classes.not.all.versions.reloaded", partiallyRedefinedClassesCount,
- redefineProcessor.getProcessedClassesCount());
+ final String message = DebuggerBundle.message(
+ "status.classes.not.all.versions.reloaded", partiallyRedefinedClassesCount, redefineProcessor.getProcessedClassesCount()
+ );
myProgress.addMessage(myDebuggerSession, MessageCategory.WARNING, message);
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java
index 9c61c8c73fe5..19f94cbe8658 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java
@@ -269,8 +269,7 @@ public class HotSwapUIImpl extends HotSwapUI implements ProjectComponent {
return result.get();
}
- private static void reloadModifiedClasses(final Map> modifiedClasses,
- final HotSwapProgressImpl progress) {
+ private static void reloadModifiedClasses(final Map> modifiedClasses, final HotSwapProgressImpl progress) {
ProgressManager.getInstance().runProcess(new Runnable() {
public void run() {
HotSwapManager.reloadModifiedClasses(modifiedClasses, progress);
diff --git a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java
index b342e2b8bde9..4fe378ce9076 100644
--- a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java
+++ b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java
@@ -259,13 +259,13 @@ public class PsiTreeUtil {
}
@NotNull
- public static Collection findChildrenOfType(@Nullable PsiElement element, @NotNull Class aClass) {
+ public static Collection findChildrenOfType(@Nullable PsiElement element, @NotNull Class extends T> aClass) {
return findChildrenOfAnyType(element, aClass);
}
@NotNull
public static Collection findChildrenOfAnyType(@Nullable final PsiElement element,
- @NotNull final Class... classes) {
+ @NotNull final Class extends T>... classes) {
if (element == null) {
return ContainerUtil.emptyList();
}
diff --git a/platform/icons/src/javaee/web_xml.png b/platform/icons/src/javaee/web_xml.png
index 760533d662db..ac51ed31cff8 100644
Binary files a/platform/icons/src/javaee/web_xml.png and b/platform/icons/src/javaee/web_xml.png differ
diff --git a/platform/icons/src/javaee/web_xml@2x.png b/platform/icons/src/javaee/web_xml@2x.png
new file mode 100644
index 000000000000..a849ced5c3f4
Binary files /dev/null and b/platform/icons/src/javaee/web_xml@2x.png differ
diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java
index c627dd91682c..b66eef0c68bd 100644
--- a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java
+++ b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java
@@ -140,22 +140,12 @@ public class FontOptions extends JPanel implements OptionsPanel{
@Override
public void textChanged(DocumentEvent event) {
if (myIsInSchemeChange || !SwingUtilities.isEventDispatchThread()) return;
- try {
- int fontSize = Integer.parseInt(myEditorFontSizeField.getText());
- if (fontSize < 1) fontSize = 1;
- if (fontSize > OptionsConstants.MAX_EDITOR_FONT_SIZE) fontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE;
- Object selectedFont = myPrimaryCombo.getSelectedItem();
- if (selectedFont instanceof String) {
- FontPreferences fontPreferences = getFontPreferences();
- fontPreferences.register((String)selectedFont, fontSize);
- }
- }
- catch (NumberFormatException e) {
- // OK, ignore
- }
- finally {
- updateDescription(true);
+ Object selectedFont = myPrimaryCombo.getSelectedItem();
+ if (selectedFont instanceof String) {
+ FontPreferences fontPreferences = getFontPreferences();
+ fontPreferences.register((String)selectedFont, getFontSizeFromField());
}
+ updateDescription(true);
}
});
@@ -163,25 +153,32 @@ public class FontOptions extends JPanel implements OptionsPanel{
@Override
public void textChanged(DocumentEvent event) {
if (myIsInSchemeChange) return;
- float lineSpacing = 1;
- try {
- lineSpacing = Float.parseFloat(myLineSpacingField.getText());
- }
- catch (NumberFormatException e) {
- // OK, ignore
- }
- finally {
- if (lineSpacing <= 0) lineSpacing = 1;
- if (lineSpacing > 30) lineSpacing = 30;
- if (getLineSpacing() != lineSpacing) {
- setCurrentLineSpacing(lineSpacing);
- }
- updateDescription(true);
+ float lineSpacing = getLineSpacingFromField();
+ if (getLineSpacing() != lineSpacing) {
+ setCurrentLineSpacing(lineSpacing);
}
+ updateDescription(true);
}
});
-
}
+
+ private int getFontSizeFromField() {
+ try {
+ return Math.min(OptionsConstants.MAX_EDITOR_FONT_SIZE, Math.max(1, Integer.parseInt(myEditorFontSizeField.getText())));
+ }
+ catch (NumberFormatException e) {
+ return OptionsConstants.DEFAULT_EDITOR_FONT_SIZE;
+ }
+ }
+
+ private float getLineSpacingFromField() {
+ try {
+ return Math.min(30, Math.max(1, Float.parseFloat(myLineSpacingField.getText())));
+ } catch (NumberFormatException e){
+ return 1;
+ }
+ }
+
private void syncFontFamilies() {
if (myIsInSchemeChange) {
return;
@@ -190,11 +187,18 @@ public class FontOptions extends JPanel implements OptionsPanel{
fontPreferences.clearFonts();
String primaryFontFamily = (String)myPrimaryCombo.getSelectedItem();
String secondaryFontFamily = mySecondaryCombo.isEnabled() ? (String)mySecondaryCombo.getSelectedItem() : null;
- if (primaryFontFamily != null && !FontPreferences.DEFAULT_FONT_NAME.equals(primaryFontFamily)) {
- fontPreferences.addFontFamily(primaryFontFamily);
+ int fontSize = getFontSizeFromField();
+ if (primaryFontFamily != null ) {
+ if (!FontPreferences.DEFAULT_FONT_NAME.equals(primaryFontFamily)) {
+ fontPreferences.addFontFamily(primaryFontFamily);
+ }
+ fontPreferences.register(primaryFontFamily, fontSize);
}
- if (secondaryFontFamily != null && !FontPreferences.DEFAULT_FONT_NAME.equals(secondaryFontFamily)) {
- fontPreferences.addFontFamily(secondaryFontFamily);
+ if (secondaryFontFamily != null) {
+ if (!FontPreferences.DEFAULT_FONT_NAME.equals(secondaryFontFamily)){
+ fontPreferences.addFontFamily(secondaryFontFamily);
+ }
+ fontPreferences.register(secondaryFontFamily, fontSize);
}
updateDescription(true);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CapitalizeAndUnderscoreMacro.java b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CapitalizeAndUnderscoreMacro.java
index 8ae675bf464e..f7e134f41f0a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CapitalizeAndUnderscoreMacro.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CapitalizeAndUnderscoreMacro.java
@@ -32,23 +32,31 @@ public class CapitalizeAndUnderscoreMacro extends MacroBase {
super("capitalizeAndUnderscore", CodeInsightBundle.message("macro.capitalizeAndUnderscore.string"));
}
+ protected CapitalizeAndUnderscoreMacro(String name, String description) {
+ super(name, description);
+ }
+
@Override
protected Result calculateResult(@NotNull Expression[] params, ExpressionContext context, boolean quick) {
String text = getTextResult(params, context, true);
if (text != null && text.length() > 0) {
final String[] words = NameUtil.nameToWords(text);
boolean insertUnderscore = false;
- final StringBuffer buf = new StringBuffer();
+ final StringBuilder buf = new StringBuilder();
for (String word : words) {
if (insertUnderscore) {
buf.append("_");
} else {
insertUnderscore = true;
}
- buf.append(StringUtil.toUpperCase(word));
+ buf.append(convertCase(word));
}
return new TextResult(buf.toString());
}
return null;
}
+
+ protected String convertCase(String word) {
+ return StringUtil.toUpperCase(word);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/SnakeCaseMacro.java b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/SnakeCaseMacro.java
new file mode 100644
index 000000000000..9e5d8ac25106
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/SnakeCaseMacro.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.macro;
+
+/**
+ * @author yole
+ */
+public class SnakeCaseMacro extends CapitalizeAndUnderscoreMacro {
+ public SnakeCaseMacro() {
+ super("snakeCase", "snakeCase(String)");
+ }
+
+ @Override
+ protected String convertCase(String word) {
+ return word.toLowerCase();
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/LocalFsFinder.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/LocalFsFinder.java
index ec12a86d2667..c02c77b83469 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/LocalFsFinder.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/LocalFsFinder.java
@@ -64,7 +64,8 @@ public class LocalFsFinder implements FileLookup.Finder, FileLookup {
return null;
}
- public String normalize(@NotNull final String path) {
+ public String normalize(@NotNull String path) {
+ path = FileUtil.expandUserHome(path);
final File file = new File(path);
if (file.isAbsolute()) return file.getAbsolutePath();
diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml
index 737fc16383aa..99595f0058b8 100644
--- a/platform/platform-resources/src/META-INF/LangExtensions.xml
+++ b/platform/platform-resources/src/META-INF/LangExtensions.xml
@@ -432,6 +432,7 @@
+
diff --git a/platform/projectModel-impl/src/com/intellij/application/options/PathMacrosImpl.java b/platform/projectModel-impl/src/com/intellij/application/options/PathMacrosImpl.java
index 715834f27595..493b21d85306 100644
--- a/platform/projectModel-impl/src/com/intellij/application/options/PathMacrosImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/application/options/PathMacrosImpl.java
@@ -129,7 +129,8 @@ public class PathMacrosImpl extends PathMacros implements ApplicationComponent,
"SelectionStartLine",
"SelectionEndLine",
"SelectionStartColumn",
- "SelectionEndColumn"
+ "SelectionEndColumn",
+ "PyInterpreterDirectory"
);
public PathMacrosImpl() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
index 6e147414b669..a9c3182ff9d5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
@@ -21,6 +21,7 @@ import com.intellij.lang.LanguageRefactoringSupport;
import com.intellij.lang.refactoring.RefactoringSupportProvider;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -365,12 +366,18 @@ public abstract class GrIntroduceHandlerBase
+
+
@@ -504,7 +506,6 @@
-
@@ -547,6 +548,7 @@
+
diff --git a/python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java b/python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java
index fee8c8518ce7..6d5e3c850de2 100644
--- a/python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java
+++ b/python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java
@@ -85,6 +85,9 @@ public class PyImportOptimizer implements ImportOptimizer {
}
LanguageLevel langLevel = LanguageLevel.forElement(myFile);
for (PyImportStatementBase importStatement : myImportBlock) {
+ if (importStatement instanceof PyFromImportStatement && ((PyFromImportStatement)importStatement).isFromFuture()) {
+ continue;
+ }
if (importStatement instanceof PyImportStatement && importStatement.getImportElements().length > 1) {
for (PyImportElement importElement : importStatement.getImportElements()) {
myMissorted = true;
@@ -96,7 +99,7 @@ public class PyImportOptimizer implements ImportOptimizer {
else {
PsiElement toImport;
if (importStatement instanceof PyFromImportStatement) {
- toImport = ((PyFromImportStatement) importStatement).resolveImportSource();
+ toImport = ((PyFromImportStatement)importStatement).resolveImportSource();
}
else {
toImport = importStatement.getImportElements()[0].resolve();
@@ -140,12 +143,21 @@ public class PyImportOptimizer implements ImportOptimizer {
addImports(myThirdPartyImports);
addImports(myProjectImports);
PsiElement lastElement = myImportBlock.get(myImportBlock.size()-1);
- myFile.deleteChildRange(myImportBlock.get(0), lastElement);
+ myFile.deleteChildRange(findFirstNonFutureImport(), lastElement);
for (PyImportStatementBase anImport : myBuiltinImports) {
anImport.putCopyableUserData(PyBlock.IMPORT_GROUP_BEGIN, null);
}
}
+ private PyImportStatementBase findFirstNonFutureImport() {
+ for (PyImportStatementBase importStatement: myImportBlock) {
+ if (!(importStatement instanceof PyFromImportStatement && ((PyFromImportStatement)importStatement).isFromFuture())) {
+ return importStatement;
+ }
+ }
+ return myImportBlock.get(0);
+ }
+
private static void markGroupBegin(List imports) {
if (imports.size() > 0) {
imports.get(0).putCopyableUserData(PyBlock.IMPORT_GROUP_BEGIN, true);
@@ -154,7 +166,7 @@ public class PyImportOptimizer implements ImportOptimizer {
private void addImports(final List imports) {
for (PyImportStatementBase newImport: imports) {
- myFile.addBefore(newImport, myImportBlock.get(0));
+ myFile.addBefore(newImport, findFirstNonFutureImport());
}
}
}
diff --git a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
index eecb8e03a0d3..97a5a365f2ea 100644
--- a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
@@ -16,6 +16,7 @@
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
+import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
@@ -138,7 +139,7 @@ public class PyArgumentListInspection extends PyInspection {
holder.registerProblem(arg, PyBundle.message("INSP.duplicate.star.arg"));
}
if (flags.contains(CallArgumentsMapping.ArgFlag.IS_POS_PAST_KWD)) {
- holder.registerProblem(arg, PyBundle.message("INSP.cannot.appear.past.keyword.arg"));
+ holder.registerProblem(arg, PyBundle.message("INSP.cannot.appear.past.keyword.arg"), ProblemHighlightType.ERROR);
}
if (flags.contains(CallArgumentsMapping.ArgFlag.IS_UNMAPPED)) {
holder.registerProblem(arg, PyBundle.message("INSP.unexpected.arg"));
diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
index cd8241015855..514bc9d563ce 100644
--- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
@@ -835,7 +835,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
}
private void addCreateClassFix(String refText, PsiElement element, List actions) {
- if (refText.length() > 2 && Character.isUpperCase(refText.charAt(0)) && !Character.isUpperCase(refText.charAt(1)) &&
+ if (refText.length() > 2 && Character.isUpperCase(refText.charAt(0)) && !refText.toUpperCase().equals(refText) &&
PsiTreeUtil.getParentOfType(element, PyImportStatementBase.class) == null) {
PsiElement anchor = element;
if (element instanceof PyQualifiedExpression) {
diff --git a/python/src/com/jetbrains/python/inspections/quickfix/MoveFromFutureImportQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/MoveFromFutureImportQuickFix.java
index 74b54e245fc3..7b3b235ffd73 100644
--- a/python/src/com/jetbrains/python/inspections/quickfix/MoveFromFutureImportQuickFix.java
+++ b/python/src/com/jetbrains/python/inspections/quickfix/MoveFromFutureImportQuickFix.java
@@ -21,14 +21,13 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.documentation.DocStringUtil;
import com.jetbrains.python.psi.PyFile;
+import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.jetbrains.annotations.NotNull;
/**
- * Created by IntelliJ IDEA.
- * Author: Alexey.Ivanov
- * Date: 24.03.2010
- * Time: 20:15:23
+ * @author Alexey.Ivanov
*/
public class MoveFromFutureImportQuickFix implements LocalQuickFix {
@NotNull
@@ -46,7 +45,13 @@ public class MoveFromFutureImportQuickFix implements LocalQuickFix {
PsiFile psiFile = problemElement.getContainingFile();
if (psiFile instanceof PyFile) {
PyFile file = (PyFile)psiFile;
- file.addBefore(problemElement, file.getStatements().get(0));
+ PyStringLiteralExpression docString = DocStringUtil.findDocStringExpression(file);
+ if (docString != null) {
+ file.addAfter(problemElement, docString.getParent() /* PyExpressionStatement */);
+ }
+ else {
+ file.addBefore(problemElement, file.getStatements().get(0));
+ }
problemElement.delete();
}
}
diff --git a/python/src/com/jetbrains/python/lexer/PyStringLiteralLexer.java b/python/src/com/jetbrains/python/lexer/PyStringLiteralLexer.java
index 6cfeac5af1cb..10c8c9be41cb 100644
--- a/python/src/com/jetbrains/python/lexer/PyStringLiteralLexer.java
+++ b/python/src/com/jetbrains/python/lexer/PyStringLiteralLexer.java
@@ -221,6 +221,7 @@ public class PyStringLiteralLexer extends LexerBase {
if (myBuffer.charAt(i) == '\\') {
LOG.assertTrue(myState == AFTER_FIRST_QUOTE);
i++;
+ if (myIsRaw) return i;
if (i == myBufferEnd) {
myState = AFTER_LAST_QUOTE;
return i;
@@ -282,7 +283,7 @@ public class PyStringLiteralLexer extends LexerBase {
final int quote_limit = myIsTriple ? 3 : 1;
int qcnt = 0; // count consequent quotes
while (i < myBufferEnd) { // scan to next \something
- if (myBuffer.charAt(i) == '\\') {
+ if (myBuffer.charAt(i) == '\\' && !myIsRaw) {
return i;
}
if (myState == BEFORE_FIRST_QUOTE && myBuffer.charAt(i) == myQuoteChar) {
@@ -292,7 +293,7 @@ public class PyStringLiteralLexer extends LexerBase {
qcnt = 0; // for last quote detection in the same pass
}
}
- else if (myState == AFTER_FIRST_QUOTE && myBuffer.charAt(i) == myQuoteChar) { // done?
+ else if (myState == AFTER_FIRST_QUOTE && myBuffer.charAt(i) == myQuoteChar && (!myIsRaw || myBuffer.charAt(i-1) != '\\')) { // done?
qcnt += 1;
if (qcnt == quote_limit) {
myState = AFTER_LAST_QUOTE;
diff --git a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java
index 9181d02dc593..65c791a33aed 100644
--- a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java
+++ b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java
@@ -772,6 +772,7 @@ public class ExpressionParsing extends Parsing {
PsiBuilder.Marker starExpr = myBuilder.mark();
nextToken();
if (!parseBitwiseORExpression(isTargetExpression)) {
+ myBuilder.error(message("PARSE.expected.expression"));
starExpr.drop();
return false;
}
diff --git a/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java b/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java
index 432a9ceb1099..692ff0052b10 100644
--- a/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java
@@ -65,29 +65,9 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
public void mapArguments(PyCallExpression.PyMarkedCallee resolved_callee, @NotNull TypeEvalContext context) {
PyExpression[] arguments = myArgumentList.getArguments();
myMarkedCallee = resolved_callee;
- List unmatched_args = new LinkedList();
- Collections.addAll(unmatched_args, arguments);
final List unmatched_subargs = new LinkedList(); // unmatched nested arguments will go here
- // detect starred args
- for (PyExpression arg : arguments) {
- if (arg instanceof PyStarArgument) {
- PyStarArgument star_arg = (PyStarArgument)arg;
- if (star_arg.isKeyword()) {
- if (myKwdArg == null) myKwdArg = star_arg;
- else {
- markArgument(arg, ArgFlag.IS_DUP_KWD);
- unmatched_args.remove(arg);
- }
- }
- else {
- if (myTupleArg == null) myTupleArg = star_arg;
- else {
- markArgument(arg, ArgFlag.IS_DUP_TUPLE);
- unmatched_args.remove(arg);
- }
- }
- }
- }
+ List unmatched_args = verifyArguments();
+
final List parameters = PyUtil.getParameters(myMarkedCallee.getCallable(), context);
// prepare parameter slots
Map slots = new LinkedHashMap();
@@ -180,15 +160,8 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
for (PyExpression arg : unmatched_subargs) {
markArgument(arg, ArgFlag.IS_UNMAPPED);
}
- // mark past-bound positional args
- i = positional_bound;
- while (i parameter_by_name = new LinkedHashMap();
@@ -352,6 +325,57 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
}
}
+ public List verifyArguments() {
+ List unmatched_args = new LinkedList();
+ Collections.addAll(unmatched_args, myArgumentList.getArguments());
+ // detect starred args
+ for (PyExpression arg : myArgumentList.getArguments()) {
+ if (arg instanceof PyStarArgument) {
+ PyStarArgument star_arg = (PyStarArgument)arg;
+ if (star_arg.isKeyword()) {
+ if (myKwdArg == null) myKwdArg = star_arg;
+ else {
+ markArgument(arg, ArgFlag.IS_DUP_KWD);
+ unmatched_args.remove(arg);
+ }
+ }
+ else {
+ if (myTupleArg == null) myTupleArg = star_arg;
+ else {
+ markArgument(arg, ArgFlag.IS_DUP_TUPLE);
+ unmatched_args.remove(arg);
+ }
+ }
+ }
+ }
+
+ markPastBoundPositionalArguments(myArgumentList.getArguments());
+ return unmatched_args;
+ }
+
+ private void markPastBoundPositionalArguments(PyExpression[] arguments) {
+ boolean seenKwArg = false;
+ boolean seenKeyword = false;
+ boolean seenStar = false;
+ for (PyExpression arg : arguments) {
+ if (arg == myKwdArg) {
+ seenKwArg = true;
+ }
+ else if (arg instanceof PyKeywordArgument) {
+ seenKeyword = true;
+ }
+ else if (arg instanceof PyStarArgument) {
+ seenStar = true;
+ }
+
+ if (seenKeyword || seenKwArg || seenStar) {
+ if (!(arg instanceof PyStarArgument) && (seenKwArg || !(arg instanceof PyKeywordArgument))) {
+ markArgument(arg, ArgFlag.IS_POS_PAST_KWD);
+ }
+ }
+ }
+ }
+
private static boolean isPositionalArg(PyExpression arg) {
return !(arg instanceof PyKeywordArgument) && !(arg instanceof PyStarArgument);
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
index 49a52944c431..50ba5419070f 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
@@ -269,8 +269,13 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList
// following the spec: http://docs.python.org/ref/calls.html
PyCallExpression call = getCallExpression();
if (call != null) {
- PyCallExpression.PyMarkedCallee resolved_callee = call.resolveCallee(resolveContext, offset);
- if (resolved_callee != null) ret.mapArguments(resolved_callee, resolveContext.getTypeEvalContext());
+ PyCallExpression.PyMarkedCallee resolvedCallee = call.resolveCallee(resolveContext, offset);
+ if (resolvedCallee != null) {
+ ret.mapArguments(resolvedCallee, resolveContext.getTypeEvalContext());
+ }
+ else {
+ ret.verifyArguments();
+ }
}
return ret;
}
diff --git a/python/src/com/jetbrains/python/sdk/InterpreterDirectoryMacro.java b/python/src/com/jetbrains/python/sdk/InterpreterDirectoryMacro.java
new file mode 100644
index 000000000000..a601aeb8dc6a
--- /dev/null
+++ b/python/src/com/jetbrains/python/sdk/InterpreterDirectoryMacro.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.sdk;
+
+import com.intellij.ide.macro.Macro;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.PathUtil;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author yole
+ */
+public class InterpreterDirectoryMacro extends Macro {
+ @Override
+ public String getName() {
+ return "PyInterpreterDirectory";
+ }
+
+ @Override
+ public String getDescription() {
+ return "The directory containing the Python interpreter selected for the project";
+ }
+
+ @Nullable
+ @Override
+ public String expand(DataContext dataContext) throws ExecutionCancelledException {
+ Module module = LangDataKeys.MODULE.getData(dataContext);
+ if (module == null) {
+ Project project = CommonDataKeys.PROJECT.getData(dataContext);
+ if (project == null) {
+ return null;
+ }
+ Module[] modules = ModuleManager.getInstance(project).getModules();
+ if (modules.length == 0) {
+ return null;
+ }
+ module = modules[0];
+ }
+ Sdk sdk = PythonSdkType.findPythonSdk(module);
+ if (sdk != null) {
+ VirtualFile homeDir = sdk.getHomeDirectory();
+ if (homeDir == null) {
+ return null;
+ }
+ String path = PathUtil.getLocalPath(homeDir.getParent());
+ if (path != null) {
+ return FileUtil.toSystemDependentName(path);
+ }
+ }
+ return null;
+ }
+}
diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java
index 9b65dca3c70b..0e64b29b374d 100644
--- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java
+++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java
@@ -25,7 +25,6 @@ import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
@@ -556,16 +555,22 @@ public class PythonSdkType extends SdkType {
@NotNull
public static Notification createInvalidSdkNotification(@Nullable final Project project) {
+ String message = "Cannot run the project interpreter.";
+ if (project != null && !project.isDisposed()) {
+ message += " Configure...";
+ }
return new Notification("xxx",
"Invalid Project Interpreter",
- "Cannot run the project interpreter. Configure...",
+ message,
NotificationType.ERROR,
new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification,
@NotNull HyperlinkEvent event) {
- final ShowSettingsUtil settings = ShowSettingsUtil.getInstance();
- settings.showSettingsDialog(project, "Project Interpreter");
+ if (project != null && !project.isDisposed()) {
+ final ShowSettingsUtil settings = ShowSettingsUtil.getInstance();
+ settings.showSettingsDialog(project, "Project Interpreter");
+ }
notification.expire();
}
});
diff --git a/python/src/com/jetbrains/python/validation/StarAnnotator.java b/python/src/com/jetbrains/python/validation/StarAnnotator.java
new file mode 100644
index 000000000000..b801343494e1
--- /dev/null
+++ b/python/src/com/jetbrains/python/validation/StarAnnotator.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.validation;
+
+import com.jetbrains.python.psi.PyStarExpression;
+import com.jetbrains.python.psi.PyTargetExpression;
+
+/**
+ * @author yole
+ */
+public class StarAnnotator extends PyAnnotator {
+ @Override
+ public void visitPyStarExpression(PyStarExpression node) {
+ super.visitPyStarExpression(node);
+ if (!(node.getExpression() instanceof PyTargetExpression)) {
+ getHolder().createErrorAnnotation(node, "can use starred expression only as assignment target");
+ }
+ }
+}
diff --git a/python/testData/highlighting/starInGenerator.py b/python/testData/highlighting/starInGenerator.py
new file mode 100644
index 000000000000..a5f9979baaa9
--- /dev/null
+++ b/python/testData/highlighting/starInGenerator.py
@@ -0,0 +1 @@
+y = (*() for _ in ())
\ No newline at end of file
diff --git a/python/testData/inspections/MoveFromFutureImportDocString.py b/python/testData/inspections/MoveFromFutureImportDocString.py
new file mode 100644
index 000000000000..8d7212411954
--- /dev/null
+++ b/python/testData/inspections/MoveFromFutureImportDocString.py
@@ -0,0 +1,10 @@
+"""This is a docstring."""
+
+from __future__ import print_function
+#comment
+from __future__ import absolute_import
+
+class A:
+ pass
+
+from __future__ import with_statement
diff --git a/python/testData/inspections/MoveFromFutureImportDocString_after.py b/python/testData/inspections/MoveFromFutureImportDocString_after.py
new file mode 100644
index 000000000000..86ac79b6053e
--- /dev/null
+++ b/python/testData/inspections/MoveFromFutureImportDocString_after.py
@@ -0,0 +1,10 @@
+"""This is a docstring."""
+from __future__ import with_statement
+
+from __future__ import print_function
+#comment
+from __future__ import absolute_import
+
+class A:
+ pass
+
diff --git a/python/testData/inspections/PyArgumentListInspection/badarglist.py b/python/testData/inspections/PyArgumentListInspection/badarglist.py
index ee17bcadcdef..627e2ee79ed3 100644
--- a/python/testData/inspections/PyArgumentListInspection/badarglist.py
+++ b/python/testData/inspections/PyArgumentListInspection/badarglist.py
@@ -42,7 +42,7 @@ f3(1, 2, 3)
f3(b=2, a=1)
f3(b=1, b=2, a=1)
f3(1, b=2)
-f3(a=1, 2)
+f3(a=1, 2)
def f4(a, *b):
pass
@@ -52,4 +52,4 @@ f4(1, 2)
f4(1, 2, 3)
f4(1, *(2, 3))
f4(*(1,2,3))
-f4(a=1, 2, 3)
+f4(a=1, 2, 3)
diff --git a/python/testData/inspections/PyArgumentListInspection/parameterWithDefaultAfterKeywordContainer.py b/python/testData/inspections/PyArgumentListInspection/parameterWithDefaultAfterKeywordContainer.py
new file mode 100644
index 000000000000..6601fc76d18c
--- /dev/null
+++ b/python/testData/inspections/PyArgumentListInspection/parameterWithDefaultAfterKeywordContainer.py
@@ -0,0 +1,5 @@
+def foo(**kwargs): pass
+
+two = 0
+kw = {}
+foo(**kw, two=1)
diff --git a/python/testData/inspections/PyArgumentListInspection/parameterWithDefaultAfterKeywordContainer2.py b/python/testData/inspections/PyArgumentListInspection/parameterWithDefaultAfterKeywordContainer2.py
new file mode 100644
index 000000000000..c4233c6004ee
--- /dev/null
+++ b/python/testData/inspections/PyArgumentListInspection/parameterWithDefaultAfterKeywordContainer2.py
@@ -0,0 +1,8 @@
+kwargs = {'foo': 'bar'}
+
+
+class Foo(object):
+
+ @classmethod
+ def test(cls):
+ cls(**kwargs, foo=1)
\ No newline at end of file
diff --git a/python/testData/inspections/PyArgumentListInspection/py1268.py b/python/testData/inspections/PyArgumentListInspection/py1268.py
index e6c578134dba..4e33321bb520 100644
--- a/python/testData/inspections/PyArgumentListInspection/py1268.py
+++ b/python/testData/inspections/PyArgumentListInspection/py1268.py
@@ -19,7 +19,7 @@ def f2(a, b, c=1, *d):
f2(c=3, *(1,2))
f2(1,2,3, *(1,2))
f2(*(1,2), c=20)
-f2(*(1,2), 20) # fail: positional past *
+f2(*(1,2), 20) # fail: positional past *
def f3(a=1, b=2, c=3, *d):
return a,b,c,d
diff --git a/python/testData/inspections/PyArgumentListInspection/py3k.py b/python/testData/inspections/PyArgumentListInspection/py3k.py
index bb85744ba8bb..a43c848f77d3 100644
--- a/python/testData/inspections/PyArgumentListInspection/py3k.py
+++ b/python/testData/inspections/PyArgumentListInspection/py3k.py
@@ -13,7 +13,7 @@ namedpast(1,2,3, foo='a') # pass
namedpast(*args, foo='b') # pass
namedpast(foo='c') # pass
namedpast() # pass
-namedpast(foo='1', 2) # fail
+namedpast(foo='1', 2) # fail
def a23(a, *b, c=1):
pass
@@ -21,7 +21,7 @@ def a23(a, *b, c=1):
a23(1,2,3, c=10) # pass
a23(1,2,3, c=10, a=1) # fail
a23(c=10, a=1) # pass
-a23(c=10, 1) # fail
+a23(c=10, 1) # fail
a23(*args, a=1) # fail
a23(*args, c=1) # pass
diff --git a/python/testData/optimizeImports/order.after.py b/python/testData/optimizeImports/order.after.py
index e89fc2619475..e3719e04dcc0 100644
--- a/python/testData/optimizeImports/order.after.py
+++ b/python/testData/optimizeImports/order.after.py
@@ -1,3 +1,4 @@
+from __future__ import with_statement
import sys
import datetime
diff --git a/python/testData/optimizeImports/order.py b/python/testData/optimizeImports/order.py
index 4232fbd83ed6..ad3147aef522 100644
--- a/python/testData/optimizeImports/order.py
+++ b/python/testData/optimizeImports/order.py
@@ -1,3 +1,4 @@
+from __future__ import with_statement
import foo
import sys
from bar import *
diff --git a/python/testData/psi/LoneStar.py b/python/testData/psi/LoneStar.py
new file mode 100644
index 000000000000..b54e94ecac2c
--- /dev/null
+++ b/python/testData/psi/LoneStar.py
@@ -0,0 +1 @@
+x = (*)
diff --git a/python/testData/psi/LoneStar.txt b/python/testData/psi/LoneStar.txt
new file mode 100644
index 000000000000..8dc1b17e3d36
--- /dev/null
+++ b/python/testData/psi/LoneStar.txt
@@ -0,0 +1,13 @@
+PyFile:LoneStar.py
+ PyAssignmentStatement
+ PyTargetExpression: x
+ PsiElement(Py:IDENTIFIER)('x')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyParenthesizedExpression
+ PsiElement(Py:LPAR)('(')
+ PsiElement(Py:MULT)('*')
+ PsiErrorElement:expression expected
+
+ PsiElement(Py:RPAR)(')')
\ No newline at end of file
diff --git a/python/testData/selectWord/escapeSequenceRaw/after1.py b/python/testData/selectWord/escapeSequenceRaw/after1.py
new file mode 100644
index 000000000000..cc34c2e72f4e
--- /dev/null
+++ b/python/testData/selectWord/escapeSequenceRaw/after1.py
@@ -0,0 +1 @@
+s = r'Hello\nWorld!'
\ No newline at end of file
diff --git a/python/testData/selectWord/escapeSequenceRaw/before.py b/python/testData/selectWord/escapeSequenceRaw/before.py
new file mode 100644
index 000000000000..7de388ad5996
--- /dev/null
+++ b/python/testData/selectWord/escapeSequenceRaw/before.py
@@ -0,0 +1 @@
+s = r'Hello\nWorld!'
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
index a4ef43bbf8d4..9f5dcccf4b8c 100644
--- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
+++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
@@ -27,9 +27,7 @@ import com.jetbrains.python.psi.LanguageLevel;
import org.jetbrains.annotations.NonNls;
/**
- * Test actions that various inspections add.
- * User: dcheryasov
- * Date: Nov 29, 2008 12:47:08 AM
+ * @author dcheryasov
*/
@TestDataPath("$CONTENT_ROOT/../testData/inspections/")
public class PyQuickFixTest extends PyTestCase {
@@ -161,6 +159,11 @@ public class PyQuickFixTest extends PyTestCase {
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);
+ }
+
public void testComparisonWithNoneQuickFix() {
doInspectionTest("ComparisonWithNone.py", PyComparisonWithNoneInspection.class,
PyBundle.message("QFIX.replace.equality"), true, true);
diff --git a/python/testSrc/com/jetbrains/python/PySelectWordTest.java b/python/testSrc/com/jetbrains/python/PySelectWordTest.java
index 9321d576a925..0d043332488b 100644
--- a/python/testSrc/com/jetbrains/python/PySelectWordTest.java
+++ b/python/testSrc/com/jetbrains/python/PySelectWordTest.java
@@ -46,6 +46,10 @@ public class PySelectWordTest extends PyTestCase {
doTest();
}
+ public void testEscapeSequenceRaw() { // PY-10322
+ doTest();
+ }
+
private void doTest() {
CodeInsightTestUtil.doWordSelectionTestOnDirectory(myFixture, "selectWord/" + getTestName(true), "py");
}
diff --git a/python/testSrc/com/jetbrains/python/PyStringLiteralLexerTest.java b/python/testSrc/com/jetbrains/python/PyStringLiteralLexerTest.java
index 037eef11427e..100f84988709 100644
--- a/python/testSrc/com/jetbrains/python/PyStringLiteralLexerTest.java
+++ b/python/testSrc/com/jetbrains/python/PyStringLiteralLexerTest.java
@@ -26,4 +26,9 @@ public class PyStringLiteralLexerTest extends PyLexerTestCase {
PyLexerTestCase.doLexerTest("u\"\\N{LATIN SMALL LETTER B}\"", new PyStringLiteralLexer(PyTokenTypes.SINGLE_QUOTED_UNICODE),
"Py:SINGLE_QUOTED_UNICODE", "VALID_STRING_ESCAPE_TOKEN", "Py:SINGLE_QUOTED_UNICODE");
}
+
+ public void testRawBackslashN() {
+ PyLexerTestCase.doLexerTest("r'[\\w\\']'", new PyStringLiteralLexer(PyTokenTypes.SINGLE_QUOTED_STRING), true,
+ "r'[\\w\\']'");
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java b/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java
index 9e62c7f18074..7ac138765b00 100644
--- a/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java
@@ -183,6 +183,10 @@ public class PythonHighlightingTest extends PyTestCase {
doTest(false, false);
}
+ public void testStarInGenerator() { // PY-10177
+ doTest(LanguageLevel.PYTHON33, false, false);
+ }
+
public void testStarArgs() { // PY-6456
doTest(LanguageLevel.PYTHON32, true, false);
}
diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java
index 34119cf248ef..87f9e535ade2 100644
--- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java
@@ -398,6 +398,10 @@ public class PythonParsingTest extends ParsingTestCase {
doTest();
}
+ public void testLoneStar() { // PY-10177
+ doTest();
+ }
+
public void doTest(LanguageLevel languageLevel) {
LanguageLevel prev = myLanguageLevel;
myLanguageLevel = languageLevel;
diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyLexerTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyLexerTestCase.java
index 4ce5e3516364..aa6fc8af0ab4 100644
--- a/python/testSrc/com/jetbrains/python/fixtures/PyLexerTestCase.java
+++ b/python/testSrc/com/jetbrains/python/fixtures/PyLexerTestCase.java
@@ -35,6 +35,13 @@ public abstract class PyLexerTestCase extends PlatformLiteFixture {
}
public static void doLexerTest(String text, Lexer lexer, String... expectedTokens) {
+ doLexerTest(text, lexer, false, expectedTokens);
+ }
+
+ public static void doLexerTest(String text,
+ Lexer lexer,
+ boolean checkTokenText,
+ String... expectedTokens) {
lexer.start(text);
int idx = 0;
int tokenPos = 0;
@@ -44,13 +51,13 @@ public abstract class PyLexerTestCase extends PlatformLiteFixture {
lexer.advance();
while (lexer.getTokenType() != null) {
remainingTokens.append(",");
- remainingTokens.append(" \"").append(lexer.getTokenType().toString()).append("\"");
+ remainingTokens.append(" \"").append(checkTokenText ? lexer.getTokenText() : lexer.getTokenType().toString()).append("\"");
lexer.advance();
}
fail("Too many tokens. Following tokens: " + remainingTokens.toString());
}
assertEquals("Token offset mismatch at position " + idx, tokenPos, lexer.getTokenStart());
- String tokenName = lexer.getTokenType().toString();
+ String tokenName = checkTokenText ? lexer.getTokenText() : lexer.getTokenType().toString();
assertEquals("Token mismatch at position " + idx, expectedTokens[idx], tokenName);
idx++;
tokenPos = lexer.getTokenEnd();
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java
index affc095d1c3a..fabba0c2458f 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java
@@ -168,4 +168,12 @@ public class PyArgumentListInspectionTest extends PyTestCase {
public void testDictFromKeys() {
doTest();
}
+
+ public void testParameterWithDefaultAfterKeywordContainer() { // PY-9934
+ doTest();
+ }
+
+ public void testParameterWithDefaultAfterKeywordContainer2() { // PY-10351
+ doTest();
+ }
}