diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml
index af758032d20b..3f2e779478a8 100644
--- a/.idea/inspectionProfiles/idea_default.xml
+++ b/.idea/inspectionProfiles/idea_default.xml
@@ -151,6 +151,7 @@
+
diff --git a/bin/scripts/unix/idea.sh b/bin/scripts/unix/idea.sh
index 6245a0620128..195cbfa0139e 100755
--- a/bin/scripts/unix/idea.sh
+++ b/bin/scripts/unix/idea.sh
@@ -199,9 +199,13 @@ LD_LIBRARY_PATH="$IDE_BIN_HOME:$LD_LIBRARY_PATH" "$JAVA_BIN" \
com.intellij.idea.Main \
"$@"
EC=$?
+
test $EC -ne 88 && exit $EC
-if [ -x "$HOME/.@@system_selector@@/restart/restarter.sh" ]; then
- "$HOME/.@@system_selector@@/restart/restarter.sh"
- "$RM" -f "$HOME/.@@system_selector@@/restart/restarter.sh"
+
+RESTARTER="$HOME/.@@system_selector@@/restart/restarter.sh"
+if [ -x "$RESTARTER" ]; then
+ "$RESTARTER"
+ "$RM" -f "$RESTARTER"
fi
+
exec "$0" "$@"
diff --git a/java/execution/impl/src/com/intellij/execution/scratch/JavaScratchConfigurable.java b/java/execution/impl/src/com/intellij/execution/scratch/JavaScratchConfigurable.java
index ea2eaca3da5c..55df9b8851ad 100644
--- a/java/execution/impl/src/com/intellij/execution/scratch/JavaScratchConfigurable.java
+++ b/java/execution/impl/src/com/intellij/execution/scratch/JavaScratchConfigurable.java
@@ -15,22 +15,27 @@
*/
package com.intellij.execution.scratch;
-import com.intellij.execution.application.ApplicationConfigurable;
-import com.intellij.execution.application.ApplicationConfiguration;
+import com.intellij.application.options.ModulesComboBox;
+import com.intellij.execution.ui.CommonJavaParametersPanel;
+import com.intellij.execution.ui.ConfigurationModuleSelector;
+import com.intellij.execution.ui.DefaultJreSelector;
+import com.intellij.execution.ui.JrePathEditor;
import com.intellij.ide.scratch.ScratchFileService;
import com.intellij.ide.scratch.ScratchRootType;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithId;
-import com.intellij.ui.components.JBLabel;
-import com.intellij.util.ui.components.BorderLayoutPanel;
+import com.intellij.ui.PanelWithAnchor;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,13 +48,28 @@ import java.awt.event.ActionListener;
* @author Eugene Zhuravlev
* Date: 30-Sep-15
*/
-public class JavaScratchConfigurable extends ApplicationConfigurable{
+public class JavaScratchConfigurable extends SettingsEditor implements PanelWithAnchor {
- private final TextFieldWithBrowseButton myScratchPathField;
+ private final CommonJavaParametersPanel myCommonProgramParameters;
+ private final LabeledComponent myMainClass;
+ private final LabeledComponent myScratchPathField;
+ private final LabeledComponent myModule;
+ private JPanel myWholePanel;
+
+ private final ConfigurationModuleSelector myModuleSelector;
+ private JrePathEditor myJrePathEditor;
+ private JComponent myAnchor;
public JavaScratchConfigurable(final Project project) {
- super(project);
- myScratchPathField = new TextFieldWithBrowseButton(new ActionListener() {
+ myMainClass = new LabeledComponent();
+ myMainClass.setLabelLocation(BorderLayout.WEST);
+ myMainClass.setText("Main &class:");
+ myMainClass.setComponent(new JTextField());
+
+ myScratchPathField = new LabeledComponent();
+ myScratchPathField.setLabelLocation(BorderLayout.WEST);
+ myScratchPathField.setText("&Path to scratch file:");
+ myScratchPathField.setComponent(new TextFieldWithBrowseButton(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
VirtualFile toSelect = getVFileFromEditor();
@@ -63,33 +83,64 @@ public class JavaScratchConfigurable extends ApplicationConfigurable{
setVFileToEditor(file);
}
}
- }, this);
+ }, this));
+
+ myModule = new LabeledComponent();
+ myModule.setLabelLocation(BorderLayout.WEST);
+ myModule.setComponent(new ModulesComboBox());
+ myModule.setText("Use classpath of &module:");
+ myModuleSelector = new ConfigurationModuleSelector(project, myModule.getComponent());
+
+ myCommonProgramParameters = new CommonJavaParametersPanel();
+ myCommonProgramParameters.setModuleContext(myModuleSelector.getModule());
+ myModule.getComponent().addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ myCommonProgramParameters.setModuleContext(myModuleSelector.getModule());
+ }
+ });
+ myJrePathEditor = new JrePathEditor();
+ myJrePathEditor.setDefaultJreSelector(DefaultJreSelector.projectSdk(project));
+
+ myWholePanel = new JPanel(new GridBagLayout());
+ myWholePanel.add(myMainClass, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(6, 0, 0, 0),0, 0 ));
+ myWholePanel.add(myScratchPathField, new GridBagConstraints(GridBagConstraints.RELATIVE, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(6, 0, 0, 0),0, 0 ));
+ myWholePanel.add(myCommonProgramParameters, new GridBagConstraints(GridBagConstraints.RELATIVE, 2, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(12, 0, 12, 0),0, 0 ));
+ myWholePanel.add(myModule, new GridBagConstraints(GridBagConstraints.RELATIVE, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0),0, 0 ));
+ myWholePanel.add(myJrePathEditor, new GridBagConstraints(GridBagConstraints.RELATIVE, 4, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(6, 0, 0, 0),0, 0 ));
+
+ myAnchor = UIUtil.mergeComponentsWithAnchor(myMainClass, myScratchPathField, myCommonProgramParameters, myJrePathEditor, myModule);
}
@Override
- public void applyEditorTo(ApplicationConfiguration configuration) throws ConfigurationException {
- super.applyEditorTo(configuration);
+ public void applyEditorTo(JavaScratchConfiguration configuration) throws ConfigurationException {
+ myCommonProgramParameters.applyTo(configuration);
+ myModuleSelector.applyTo(configuration);
+ configuration.MAIN_CLASS_NAME = myMainClass.getComponent().getText().trim();
+ configuration.ALTERNATIVE_JRE_PATH = myJrePathEditor.getJrePathOrName();
+ configuration.ALTERNATIVE_JRE_PATH_ENABLED = myJrePathEditor.isAlternativeJreSelected();
+
final VirtualFile vFile = getVFileFromEditor();
- ((JavaScratchConfiguration)configuration).SCRATCH_FILE_ID = vFile instanceof VirtualFileWithId ? ((VirtualFileWithId)vFile).getId() : 0;
+ configuration.SCRATCH_FILE_ID = vFile instanceof VirtualFileWithId ? ((VirtualFileWithId)vFile).getId() : 0;
}
@Nullable
private VirtualFile getVFileFromEditor() {
- final String path = FileUtil.toSystemIndependentName(myScratchPathField.getText());
+ final String path = FileUtil.toSystemIndependentName(myScratchPathField.getComponent().getText().trim());
return !StringUtil.isEmpty(path) ? LocalFileSystem.getInstance().findFileByPath(path) : null;
}
@Override
- public void resetEditorFrom(ApplicationConfiguration configuration) {
- super.resetEditorFrom(configuration);
- final JavaScratchConfiguration scratchConfig = (JavaScratchConfiguration)configuration;
- final VirtualFile file = scratchConfig.getScratchVirtualFile();
- setVFileToEditor(file);
+ public void resetEditorFrom(JavaScratchConfiguration configuration) {
+ myCommonProgramParameters.reset(configuration);
+ myModuleSelector.reset(configuration);
+ myMainClass.getComponent().setText(configuration.MAIN_CLASS_NAME != null ? configuration.MAIN_CLASS_NAME.replaceAll("\\$", "\\.") : "");
+ myJrePathEditor.setPathOrName(configuration.ALTERNATIVE_JRE_PATH, configuration.ALTERNATIVE_JRE_PATH_ENABLED);
+ setVFileToEditor(configuration.getScratchVirtualFile());
}
private void setVFileToEditor(VirtualFile file) {
if (file != null) {
- myScratchPathField.setText(FileUtil.toSystemDependentName(file.getPath()));
+ myScratchPathField.getComponent().setText(FileUtil.toSystemDependentName(file.getPath()));
}
else {
myScratchPathField.setText("");
@@ -99,9 +150,21 @@ public class JavaScratchConfigurable extends ApplicationConfigurable{
@NotNull
@Override
public JComponent createEditor() {
- final JPanel panel = new JPanel(new GridBagLayout());
- panel.add(new JBLabel("Path to scratch file: "), new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(20,0,0,10), 0, 0));
- panel.add(myScratchPathField, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(20, 0, 0, 0), 0, 0));
- return new BorderLayoutPanel().addToCenter(super.createEditor()).addToBottom(panel);
+ return myWholePanel;
+ }
+
+ @Override
+ public JComponent getAnchor() {
+ return myAnchor;
+ }
+
+ @Override
+ public void setAnchor(@Nullable JComponent anchor) {
+ myAnchor = anchor;
+ myMainClass.setAnchor(anchor);
+ myScratchPathField.setAnchor(anchor);
+ myCommonProgramParameters.setAnchor(anchor);
+ myJrePathEditor.setAnchor(anchor);
+ myModule.setAnchor(anchor);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
index 12b91dc196ea..51adfb34bf76 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
@@ -84,9 +84,8 @@ public class JavaResolveCache {
PsiType type = isOverloadCheck ? null : myCalculatedTypes.get(expr);
if (type == null) {
final RecursionGuard.StackStamp dStackStamp = PsiDiamondType.ourDiamondGuard.markStack();
- final RecursionGuard.StackStamp gStackStamp = PsiResolveHelper.ourGraphGuard.markStack();
type = f.fun(expr);
- if (!dStackStamp.mayCacheNow() || !gStackStamp.mayCacheNow() || isOverloadCheck) {
+ if (!dStackStamp.mayCacheNow() || isOverloadCheck) {
return type;
}
if (type == null) type = TypeConversionUtil.NULL_TYPE;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
index 20d18262f9d9..6121d6530c8b 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
@@ -1195,7 +1195,9 @@ public class InferenceSession {
}
}
finally {
- LambdaUtil.ourFunctionTypes.set(null);
+ if (formula instanceof InputOutputConstraintFormula) {
+ LambdaUtil.getFunctionalTypeMap().remove(((InputOutputConstraintFormula)formula).getExpression());
+ }
}
return true;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java
index f03a796350d8..bd7549957c7b 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java
@@ -157,7 +157,7 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai
}
@Override
- protected PsiExpression getExpression() {
+ public PsiExpression getExpression() {
return myExpression;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java
index 8efff6b10f71..0fb9e7f41d52 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java
@@ -30,7 +30,7 @@ import java.util.*;
*/
public abstract class InputOutputConstraintFormula implements ConstraintFormula {
- protected abstract PsiExpression getExpression();
+ public abstract PsiExpression getExpression();
protected abstract PsiType getT();
protected abstract void setT(PsiType t);
protected abstract InputOutputConstraintFormula createSelfConstraint(PsiType type, PsiExpression expression);
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/IDEA140686.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/IDEA140686.java
new file mode 100644
index 000000000000..eae6d376024f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/IDEA140686.java
@@ -0,0 +1,50 @@
+package nise;
+
+import java.util.function.BiFunction;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+
+
+class TypeTest {
+ public static void main(String[] args) {
+ assertThat(id(new Combiner<>(echo("A"), echo("B"), (str1, str2) ->
+ new StringBuilder(str1.length() + str2.length())
+ .append(str1)
+ .append(str2))).get(),
+ hasSameContentAs("AB"));
+ }
+
+ private static Supplier id(Supplier s) {
+ return s;
+ }
+
+ private static Supplier echo(T s) {
+ return () -> s;
+ }
+
+ private static Predicate hasSameContentAs(CharSequence seq) {
+ return charSequence -> charSequence.toString().equals(seq.toString());
+ }
+
+ private static void assertThat(T actual, Predicate super T> matcher) {
+ if (!matcher.test(actual)) throw new AssertionError();
+ }
+
+ private static class Combiner implements Supplier {
+ private final Supplier s1;
+ private final Supplier s2;
+ private final BiFunction f;
+
+ public Combiner(Supplier s1, Supplier s2, BiFunction f) {
+ this.s1 = s1;
+ this.s2 = s2;
+ this.f = f;
+ }
+
+ @Override
+ public R get() {
+ return f.apply(s1.get(), s2.get());
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/expressions/ProoveThatInferenceInsideLambdaBodyDontInfluenceOuterCallInference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/expressions/ProoveThatInferenceInsideLambdaBodyDontInfluenceOuterCallInference.java
new file mode 100644
index 000000000000..c34eae729fbb
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/expressions/ProoveThatInferenceInsideLambdaBodyDontInfluenceOuterCallInference.java
@@ -0,0 +1,25 @@
+
+import java.util.List;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+class Test {
+ void f(Stream stream1) {
+ final Supplier> revisionDiffItemDTOs = () -> stream1.map(record -> {
+ foo(null);
+ final Object stream = record.getAllNodes().stream();
+ return "";
+ }).collect(Collectors.toList());
+ }
+
+
+ private void foo(T t) throws RuntimeException {}
+
+ private class ReviewDiffRecord {
+ List getAllNodes() {
+ return null;
+ }
+ }
+
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Diamond8HighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Diamond8HighlightingTest.java
index 1990221b5e5f..fb31edf8d404 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Diamond8HighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Diamond8HighlightingTest.java
@@ -46,6 +46,10 @@ public class Diamond8HighlightingTest extends LightDaemonAnalyzerTestCase {
public void testWithConstructorRefInside() throws Exception {
doTest();
}
+
+ public void testIDEA140686() throws Exception {
+ doTest();
+ }
private void doTest() throws Exception {
doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java
index 99b4a647fe11..a325f0e32552 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java
@@ -16,17 +16,13 @@
package com.intellij.codeInsight.daemon.lambda;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NonNls;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/expressions";
@@ -47,6 +43,10 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
doTestAllMethodCallExpressions();
}
+ public void testProoveThatInferenceInsideLambdaBodyDontInfluenceOuterCallInference() throws Exception {
+ doTestAllMethodCallExpressions();
+ }
+
public void testCachedUnresolvedMethods() throws Exception {
doTestCachedUnresolved();
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewController.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewController.java
index 00346aeb29bd..4ea787e5a498 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewController.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewController.java
@@ -274,7 +274,6 @@ public class LivePreviewController implements LivePreview.Delegate, FindUtil.Rep
public void dispose() {
if (myDisposed) return;
- myLivePreview.cleanUp();
off();
mySearchResults.dispose();
diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java
index ab518d001af7..f81ed3fbf2ea 100644
--- a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java
+++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java
@@ -46,4 +46,8 @@ public abstract class ScratchFileService {
@NotNull
public abstract PerFileMappings getScratchesMapping();
+
+ public static boolean isInScratchRoot(@Nullable VirtualFile file) {
+ return getInstance().getRootType(file) != null;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesHandler.java b/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesHandler.java
index 2aa855f52711..5ede26109afd 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesHandler.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesHandler.java
@@ -22,9 +22,9 @@ import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.move.MoveCallback;
import com.intellij.refactoring.move.MoveHandlerDelegate;
import org.jetbrains.annotations.Nullable;
@@ -62,13 +62,7 @@ public class MoveFilesOrDirectoriesHandler extends MoveHandlerDelegate {
public static boolean isValidTarget(PsiElement psiElement) {
if (!(psiElement instanceof PsiDirectory || psiElement instanceof PsiDirectoryContainer)) return false;
- return psiElement.getManager().isInProject(psiElement) || isInScratches(psiElement);
- }
-
- protected static boolean isInScratches(PsiElement psiElement) {
- VirtualFile virtualFile = psiElement instanceof PsiFileSystemItem ? ((PsiFileSystemItem)psiElement).getVirtualFile() : null;
- if (virtualFile != null && ScratchFileService.getInstance().getRootType(virtualFile) != null) return true;
- return false;
+ return psiElement.getManager().isInProject(psiElement) || ScratchFileService.isInScratchRoot(PsiUtilCore.getVirtualFile(psiElement));
}
public void doMove(final PsiElement[] elements, final PsiElement targetContainer) {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java
index 06d812127d6f..ef76ae11eabb 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java
@@ -300,7 +300,10 @@ public class RenameProcessor extends BaseRefactoringProcessor {
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < elements.size(); i++) {
PsiElement element = elements.get(i);
- LOG.assertTrue(element != null);
+ if (element == null) {
+ LOG.error("primary: " + myPrimaryElement + "; renamers: " + myRenamers);
+ continue;
+ }
final String newName = myAllRenames.get(element);
final UsageInfo[] usages = RenameUtil.findUsages(element, newName, mySearchInComments, mySearchTextOccurrences, myAllRenames);
final List usagesList = Arrays.asList(usages);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/LineLayout.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/LineLayout.java
index 0d691ab2e388..9c54b2b9851f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/LineLayout.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/LineLayout.java
@@ -107,7 +107,7 @@ class LineLayout {
List runs = createRuns(editor, chars, -1);
for (BidiRun run : runs) {
for (Chunk chunk : run.getChunks()) {
- addFragments(chunk, run.isRtl(), chars, chunk.startOffset, chunk.endOffset, fontStyle, fontPreferences, fontRenderContext, null);
+ addFragments(run, chunk, chars, chunk.startOffset, chunk.endOffset, fontStyle, fontPreferences, fontRenderContext, null);
}
}
return runs;
@@ -150,6 +150,18 @@ class LineLayout {
}
private static void addRuns(List runs, char[] text, int start, int end) {
+ int afterLastTabPosition = start;
+ for (int i = start; i < end; i++) {
+ if (text[i] == '\t') {
+ addRunsNoTabs(runs, text, afterLastTabPosition, i);
+ afterLastTabPosition = i + 1;
+ addOrMergeRun(runs, new BidiRun((byte)0, i, i + 1));
+ }
+ }
+ addRunsNoTabs(runs, text, afterLastTabPosition, end);
+ }
+
+ private static void addRunsNoTabs(List runs, char[] text, int start, int end) {
if (start >= end) return;
Bidi bidi = new Bidi(text, start, null, 0, end - start, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
int runCount = bidi.getRunCount();
@@ -170,7 +182,7 @@ class LineLayout {
}
}
- private static void addFragments(Chunk chunk, boolean isRtl, char[] text, int start, int end, int fontStyle,
+ private static void addFragments(BidiRun run, Chunk chunk, char[] text, int start, int end, int fontStyle,
FontPreferences fontPreferences, FontRenderContext fontRenderContext,
@Nullable TabFragment tabFragment) {
assert start < end;
@@ -179,7 +191,7 @@ class LineLayout {
for(int i = start; i < end; i++) {
char c = text[i];
if (c == '\t' && tabFragment != null) {
- assert !isRtl;
+ assert run.level == 0;
addTextFragmentIfNeeded(chunk, text, currentIndex, i, currentFont, fontRenderContext, false);
chunk.fragments.add(tabFragment);
currentFont = null;
@@ -188,13 +200,13 @@ class LineLayout {
else {
Font font = ComplementaryFontsRegistry.getFontAbleToDisplay(c, fontStyle, fontPreferences).getFont();
if (!font.equals(currentFont)) {
- addTextFragmentIfNeeded(chunk, text, currentIndex, i, currentFont, fontRenderContext, isRtl);
+ addTextFragmentIfNeeded(chunk, text, currentIndex, i, currentFont, fontRenderContext, run.isRtl());
currentFont = font;
currentIndex = i;
}
}
}
- addTextFragmentIfNeeded(chunk, text, currentIndex, end, currentFont, fontRenderContext, isRtl);
+ addTextFragmentIfNeeded(chunk, text, currentIndex, end, currentFont, fontRenderContext, run.isRtl());
assert !chunk.fragments.isEmpty();
}
@@ -342,7 +354,7 @@ class LineLayout {
for (Chunk chunk : getChunks()) {
if (chunk.endOffset <= start) continue;
if (chunk.startOffset >= end) break;
- subChunks.add(chunk.subChunk(view, lineStartOffset, isRtl(), start, end, quick));
+ subChunks.add(chunk.subChunk(view, this, lineStartOffset, start, end, quick));
}
subRun.chunks = subChunks.toArray(new Chunk[subChunks.size()]);
return subRun;
@@ -359,7 +371,7 @@ class LineLayout {
this.endOffset = endOffset;
}
- private void ensureLayout(@NotNull EditorView view, int lineStartOffset, boolean isRtl) {
+ private void ensureLayout(@NotNull EditorView view, BidiRun run, int lineStartOffset) {
if (!fragments.isEmpty()) return;
int start = lineStartOffset + startOffset;
int end = lineStartOffset + endOffset;
@@ -367,7 +379,7 @@ class LineLayout {
FontPreferences fontPreferences = view.getEditor().getColorsScheme().getFontPreferences();
char[] chars = CharArrayUtil.fromSequence(view.getEditor().getDocument().getImmutableCharSequence(), start, end);
while (!it.atEnd()) {
- addFragments(this, isRtl, chars, it.getStartOffset() - start, it.getEndOffset() - start,
+ addFragments(run, this, chars, it.getStartOffset() - start, it.getEndOffset() - start,
it.getMergedAttributes().getFontType(), fontPreferences, view.getFontRenderContext(), view.getTabFragment());
it.advance();
}
@@ -375,7 +387,7 @@ class LineLayout {
assert !fragments.isEmpty();
}
- private Chunk subChunk(EditorView view, int lineStartOffset, boolean isRtl, int targetStartOffset, int targetEndOffset, boolean quick) {
+ private Chunk subChunk(EditorView view, BidiRun run, int lineStartOffset, int targetStartOffset, int targetEndOffset, boolean quick) {
assert targetStartOffset < endOffset;
assert targetEndOffset > startOffset;
int start = Math.max(startOffset, targetStartOffset);
@@ -390,7 +402,7 @@ class LineLayout {
if (start == startOffset && end == this.endOffset) {
return this;
}
- ensureLayout(view, lineStartOffset, isRtl);
+ ensureLayout(view, run, lineStartOffset);
Chunk chunk = new Chunk(start, end);
int offset = startOffset;
for (LineFragment fragment : fragments) {
@@ -434,7 +446,7 @@ class LineLayout {
if (myChunkIndex >= chunks.length) return false;
Chunk chunk = chunks[run.isRtl() ? chunks.length - 1 - myChunkIndex : myChunkIndex];
if (myView != null) {
- chunk.ensureLayout(myView, myLineStartOffset, run.isRtl());
+ chunk.ensureLayout(myView, run, myLineStartOffset);
}
return myFragmentIndex < chunk.fragments.size();
}
diff --git a/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java b/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
index 7881b8a7c96a..bf9e8a783adc 100644
--- a/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
+++ b/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
@@ -32,6 +32,7 @@ import com.intellij.ui.HyperlinkLabel;
import com.intellij.ui.TextFieldWithHistory;
import com.intellij.ui.TextFieldWithHistoryWithBrowseButton;
import com.intellij.util.NotNullProducer;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.ComparatorUtil;
import com.intellij.util.containers.ContainerUtil;
@@ -295,7 +296,7 @@ public class SwingHelper {
boolean mergeWithPrevHistory) {
Set newHistorySet = ContainerUtil.newHashSet(history);
List prevHistory = textFieldWithHistory.getHistory();
- List mergedHistory = ContainerUtil.newArrayList();
+ List mergedHistory = ContainerUtil.newArrayListWithCapacity(history.size());
if (mergeWithPrevHistory) {
for (String item : prevHistory) {
if (!newHistorySet.contains(item)) {
@@ -303,15 +304,20 @@ public class SwingHelper {
}
}
}
- else {
- String currentText = textFieldWithHistory.getText();
- if (StringUtil.isNotEmpty(currentText) && !newHistorySet.contains(currentText)) {
- mergedHistory.add(currentText);
- }
- }
mergedHistory.addAll(history);
+ String oldText = StringUtil.notNullize(textFieldWithHistory.getText());
+ String oldSelectedItem = ObjectUtils.tryCast(textFieldWithHistory.getSelectedItem(), String.class);
+ if (!mergedHistory.contains(oldSelectedItem)) {
+ oldSelectedItem = null;
+ }
textFieldWithHistory.setHistory(mergedHistory);
setLongestAsPrototype(textFieldWithHistory, mergedHistory);
+ if (oldSelectedItem != null) {
+ textFieldWithHistory.setSelectedItem(oldSelectedItem);
+ }
+ if (!oldText.equals(oldSelectedItem)) {
+ textFieldWithHistory.setText(oldText);
+ }
}
private static void setLongestAsPrototype(@NotNull JComboBox comboBox, @NotNull List variants) {
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorRtlTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorRtlTest.java
index d55f36c1e9a6..302710ea536a 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorRtlTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorRtlTest.java
@@ -563,6 +563,26 @@ public class EditorRtlTest extends AbstractEditorTest {
checkResult("RLR");
}
+ public void testTabInsideRtlText() throws Exception {
+ prepareText("R\tRR");
+ right();
+ checkResult("R\tRR");
+ right();
+ checkResult("R\tRR");
+ right();
+ checkResult("R\tRR");
+ right();
+ checkResult("R\tRR");
+ right();
+ checkResult("R\tRR");
+ right();
+ checkResult("R\tRR");
+ right();
+ checkResult("R\tRR");
+ right();
+ checkResult("R\tRR");
+ }
+
private void prepareText(String text) throws IOException {
prepare(text, TestFileType.TEXT);
}
diff --git a/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java
index 9528ff5df6b8..c1d524bb8f77 100644
--- a/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java
@@ -23,7 +23,6 @@ import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyExpressionCodeFragmentImpl;
@@ -221,7 +220,8 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
if (expr instanceof PySubscriptionExpression) {
final PyExpression indexExpr = ((PySubscriptionExpression)expr).getIndexExpression();
if (indexExpr != null) {
- final PyGenericType genericType = getGenericType(indexExpr, context);
+ final PsiElement resolved = tryResolving(indexExpr, context);
+ final PyGenericType genericType = getGenericType(resolved, context);
if (genericType != null) {
results.add(genericType);
}
@@ -235,35 +235,36 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
@Nullable
private static PyType getType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- final PyType unionType = getUnionType(expression, context);
+ final PsiElement resolved = tryResolving(expression, context);
+ final PyType unionType = getUnionType(resolved, context);
if (unionType != null) {
return unionType;
}
- final Ref optionalType = getOptionalTypeFromDefaultNone(expression, context);
+ final Ref optionalType = getOptionalTypeFromDefaultNone(resolved, context);
if (optionalType != null) {
return optionalType.get();
}
- final PyType callableType = getCallableType(expression, context);
+ final PyType callableType = getCallableType(resolved, context);
if (callableType != null) {
return callableType;
}
- final PyType parameterizedType = getParameterizedType(expression, context);
+ final PyType parameterizedType = getParameterizedType(resolved, context);
if (parameterizedType != null) {
return parameterizedType;
}
- final PyType builtinCollection = getBuiltinCollection(expression, context);
+ final PyType builtinCollection = getBuiltinCollection(resolved);
if (builtinCollection != null) {
return builtinCollection;
}
- final PyType genericType = getGenericType(expression, context);
+ final PyType genericType = getGenericType(resolved, context);
if (genericType != null) {
return genericType;
}
- final Ref classType = getClassType(expression, context);
+ final Ref classType = getClassType(resolved, context);
if (classType != null) {
return classType.get();
}
- final PyType stringBasedType = getStringBasedType(expression, context);
+ final PyType stringBasedType = getStringBasedType(resolved, context);
if (stringBasedType != null) {
return stringBasedType;
}
@@ -271,28 +272,30 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static Ref getClassType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- final PyType type = context.getType(expression);
- if (type != null && isAny(type)) {
- return Ref.create();
- }
- if (type instanceof PyClassLikeType) {
- final PyClassLikeType classType = (PyClassLikeType)type;
- if (classType.isDefinition()) {
- final PyType instanceType = classType.toInstance();
- return Ref.create(instanceType);
+ private static Ref getClassType(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ if (element instanceof PyTypedElement) {
+ final PyType type = context.getType((PyTypedElement)element);
+ if (type != null && isAny(type)) {
+ return Ref.create();
+ }
+ if (type instanceof PyClassLikeType) {
+ final PyClassLikeType classType = (PyClassLikeType)type;
+ if (classType.isDefinition()) {
+ final PyType instanceType = classType.toInstance();
+ return Ref.create(instanceType);
+ }
+ }
+ else if (type instanceof PyNoneType) {
+ return Ref.create(type);
}
- }
- else if (type instanceof PyNoneType) {
- return Ref.create(type);
}
return null;
}
@Nullable
- private static Ref getOptionalTypeFromDefaultNone(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- if (expression instanceof PySubscriptionExpression) {
- final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)expression;
+ private static Ref getOptionalTypeFromDefaultNone(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ if (element instanceof PySubscriptionExpression) {
+ final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)element;
final PyExpression operand = subscriptionExpr.getOperand();
final String operandName = resolveToQualifiedName(operand, context);
if ("typing.Optional".equals(operandName)) {
@@ -310,11 +313,11 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getStringBasedType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- if (expression instanceof PyStringLiteralExpression) {
+ private static PyType getStringBasedType(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ if (element instanceof PyStringLiteralExpression) {
// XXX: Requires switching from stub to AST
- final String contents = ((PyStringLiteralExpression)expression).getStringValue();
- return getStringBasedType(contents, expression, context);
+ final String contents = ((PyStringLiteralExpression)element).getStringValue();
+ return getStringBasedType(contents, element, context);
}
return null;
}
@@ -341,9 +344,9 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getCallableType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- if (expression instanceof PySubscriptionExpression) {
- final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)expression;
+ private static PyType getCallableType(@NotNull PsiElement resolved, @NotNull TypeEvalContext context) {
+ if (resolved instanceof PySubscriptionExpression) {
+ final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)resolved;
final PyExpression operand = subscriptionExpr.getOperand();
final String operandName = resolveToQualifiedName(operand, context);
if ("typing.Callable".equals(operandName)) {
@@ -371,9 +374,9 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getUnionType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- if (expression instanceof PySubscriptionExpression) {
- final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)expression;
+ private static PyType getUnionType(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ if (element instanceof PySubscriptionExpression) {
+ final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)element;
final PyExpression operand = subscriptionExpr.getOperand();
final String operandName = resolveToQualifiedName(operand, context);
if ("typing.Union".equals(operandName)) {
@@ -384,32 +387,22 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyGenericType getGenericType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- final PsiElement resolved = resolve(expression, context);
- if (resolved instanceof PyTargetExpression) {
- final PyTargetExpression targetExpr = (PyTargetExpression)resolved;
- final QualifiedName calleeName = targetExpr.getCalleeName();
- if (calleeName != null && "TypeVar".equals(calleeName.toString())) {
- // XXX: Requires switching from stub to AST
- final PyExpression assigned = targetExpr.findAssignedValue();
- if (assigned instanceof PyCallExpression) {
- final PyCallExpression assignedCall = (PyCallExpression)assigned;
- final PyExpression callee = assignedCall.getCallee();
- if (callee != null) {
- final String calleeQName = resolveToQualifiedName(callee, context);
- if ("typing.TypeVar".equals(calleeQName)) {
- final PyExpression[] arguments = assignedCall.getArguments();
- if (arguments.length > 0) {
- final PyExpression firstArgument = arguments[0];
- if (firstArgument instanceof PyStringLiteralExpression) {
- final String name = ((PyStringLiteralExpression)firstArgument).getStringValue();
- if (name != null) {
- return new PyGenericType(name, getGenericTypeBound(arguments, context));
- }
- }
+ private static PyGenericType getGenericType(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ if (element instanceof PyCallExpression) {
+ final PyCallExpression assignedCall = (PyCallExpression)element;
+ final PyExpression callee = assignedCall.getCallee();
+ if (callee != null) {
+ final String calleeQName = resolveToQualifiedName(callee, context);
+ if ("typing.TypeVar".equals(calleeQName)) {
+ final PyExpression[] arguments = assignedCall.getArguments();
+ if (arguments.length > 0) {
+ final PyExpression firstArgument = arguments[0];
+ if (firstArgument instanceof PyStringLiteralExpression) {
+ final String name = ((PyStringLiteralExpression)firstArgument).getStringValue();
+ if (name != null) {
+ return new PyGenericType(name, getGenericTypeBound(arguments, context));
}
}
-
}
}
}
@@ -443,9 +436,9 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getParameterizedType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- if (expression instanceof PySubscriptionExpression) {
- final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)expression;
+ private static PyType getParameterizedType(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ if (element instanceof PySubscriptionExpression) {
+ final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)element;
final PyExpression operand = subscriptionExpr.getOperand();
final PyExpression indexExpr = subscriptionExpr.getIndexExpression();
final PyType operandType = getType(operand, context);
@@ -453,7 +446,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
final PyClass cls = ((PyClassType)operandType).getPyClass();
final List indexTypes = getIndexTypes(subscriptionExpr, context);
if (PyNames.TUPLE.equals(cls.getQualifiedName())) {
- return PyTupleType.create(expression, indexTypes.toArray(new PyType[indexTypes.size()]));
+ return PyTupleType.create(element, indexTypes.toArray(new PyType[indexTypes.size()]));
}
else if (indexExpr != null) {
return new PyCollectionTypeImpl(cls, false, indexTypes);
@@ -464,18 +457,18 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getBuiltinCollection(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- final String collectionName = resolveToQualifiedName(expression, context);
+ private static PyType getBuiltinCollection(@NotNull PsiElement element) {
+ final String collectionName = getQualifiedName(element);
final String builtinName = COLLECTION_CLASSES.get(collectionName);
- return builtinName != null ? PyTypeParser.getTypeByName(expression, builtinName) : null;
+ return builtinName != null ? PyTypeParser.getTypeByName(element, builtinName) : null;
}
- @Nullable
- private static PsiElement resolve(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- if (expression instanceof PyReferenceOwner) {
- final PyReferenceOwner referenceOwner = (PyReferenceOwner)expression;
+ @NotNull
+ private static PsiElement tryResolving(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ if (expression instanceof PyReferenceExpression) {
+ final PyReferenceExpression referenceExpr = (PyReferenceExpression)expression;
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
- final PsiPolyVariantReference reference = referenceOwner.getReference(resolveContext);
+ final PsiPolyVariantReference reference = referenceExpr.getReference(resolveContext);
final PsiElement element = reference.resolve();
if (element instanceof PyFunction) {
final PyFunction function = (PyFunction)element;
@@ -486,14 +479,28 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
}
}
- return element;
+ else if (element instanceof PyTargetExpression) {
+ final PyTargetExpression targetExpr = (PyTargetExpression)element;
+ // XXX: Requires switching from stub to AST
+ final PyExpression assignedValue = targetExpr.findAssignedValue();
+ if (assignedValue != null) {
+ return assignedValue;
+ }
+ }
+ if (element != null) {
+ return element;
+ }
}
- return null;
+ return expression;
}
@Nullable
private static String resolveToQualifiedName(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
- final PsiElement element = resolve(expression, context);
+ return getQualifiedName(tryResolving(expression, context));
+ }
+
+ @Nullable
+ private static String getQualifiedName(@NotNull PsiElement element) {
if (element instanceof PyQualifiedNameOwner) {
final PyQualifiedNameOwner qualifiedNameOwner = (PyQualifiedNameOwner)element;
return qualifiedNameOwner.getQualifiedName();
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index 31bdabd31f6d..87d9be86fe81 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.java
@@ -23,7 +23,7 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
-import com.intellij.ide.scratch.ScratchRootType;
+import com.intellij.ide.scratch.ScratchFileService;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.lang.ASTFactory;
import com.intellij.lang.ASTNode;
@@ -55,6 +55,7 @@ import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.util.QualifiedName;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.*;
@@ -1832,8 +1833,7 @@ public class PyUtil {
}
public static boolean isInScratchFile(@NotNull PsiElement element) {
- PsiFile file = element.getContainingFile();
- return file != null && ScratchRootType.getInstance().isScratchFile(file.getVirtualFile());
+ return ScratchFileService.isInScratchRoot(PsiUtilCore.getVirtualFile(element));
}
/**
diff --git a/python/src/com/jetbrains/python/psi/types/PyGenericType.java b/python/src/com/jetbrains/python/psi/types/PyGenericType.java
index 0bccf762dff2..c43f14235ab5 100644
--- a/python/src/com/jetbrains/python/psi/types/PyGenericType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyGenericType.java
@@ -15,8 +15,11 @@
*/
package com.jetbrains.python.psi.types;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
+import com.intellij.util.Function;
import com.intellij.util.ProcessingContext;
+import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.AccessDirection;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.resolve.PyResolveContext;
@@ -55,7 +58,19 @@ public class PyGenericType implements PyType {
@NotNull
@Override
public String getName() {
- return myBound != null ? myName + " <= " + myBound.getName() : myName;
+ if (myBound instanceof PyUnionType) {
+ final PyUnionType bounds = (PyUnionType)myBound;
+ final String boundsString = StringUtil.join(bounds.getMembers(), new Function() {
+ @Override
+ public String fun(PyType type) {
+ return type != null ? type.getName() : PyNames.UNKNOWN_TYPE;
+ }
+ }, ", ");
+ return "TypeVar('" + myName + "', " + boundsString + ")";
+ }
+ else {
+ return "TypeVar('" + myName + "')";
+ }
}
@Override
diff --git a/python/testData/inspections/PyTypeCheckerInspection/BoundedGeneric.py b/python/testData/inspections/PyTypeCheckerInspection/BoundedGeneric.py
index 7c626d093b1b..8de1106ee540 100644
--- a/python/testData/inspections/PyTypeCheckerInspection/BoundedGeneric.py
+++ b/python/testData/inspections/PyTypeCheckerInspection/BoundedGeneric.py
@@ -8,5 +8,5 @@ def test():
x = f(10)
y = f('foo')
- z = f([])
+ z = f([])
return x + y
diff --git a/python/testData/inspections/PyTypeCheckerInspection/GenericUserClasses.py b/python/testData/inspections/PyTypeCheckerInspection/GenericUserClasses.py
index e652dcf92fc6..fdef2e5afb96 100644
--- a/python/testData/inspections/PyTypeCheckerInspection/GenericUserClasses.py
+++ b/python/testData/inspections/PyTypeCheckerInspection/GenericUserClasses.py
@@ -21,4 +21,4 @@ class User1(object):
c = User1(10)
print(c.get() + 'foo')
c.put(14)
-c.put('foo')
+c.put('foo')
diff --git a/python/testData/inspections/PyTypeCheckerInspection/GenericUserFunctions.py b/python/testData/inspections/PyTypeCheckerInspection/GenericUserFunctions.py
index 937bffc0fb05..2fd5ffb4c22f 100644
--- a/python/testData/inspections/PyTypeCheckerInspection/GenericUserFunctions.py
+++ b/python/testData/inspections/PyTypeCheckerInspection/GenericUserFunctions.py
@@ -40,7 +40,7 @@ def test():
print(result)
print(result + 'foo')
- f2(1, ['foo'], 'bar')
+ f2(1, ['foo'], 'bar')
result = f3(1, 'foo', True)
f4(result)
diff --git a/python/testData/inspections/PyTypeCheckerInspection/SecondFormIter.py b/python/testData/inspections/PyTypeCheckerInspection/SecondFormIter.py
index 4d2cbf6a7a6b..b44e1d22d31f 100644
--- a/python/testData/inspections/PyTypeCheckerInspection/SecondFormIter.py
+++ b/python/testData/inspections/PyTypeCheckerInspection/SecondFormIter.py
@@ -7,7 +7,7 @@ def test_second_form():
def test_second_form_fail():
- for chunk in iter(10, ''):
+ for chunk in iter(10, ''):
pass
diff --git a/python/testData/inspections/PyTypeCheckerInspection/TypingTypeVarWithUnresolvedBound.py b/python/testData/inspections/PyTypeCheckerInspection/TypingTypeVarWithUnresolvedBound.py
new file mode 100644
index 000000000000..5953fb4baf5a
--- /dev/null
+++ b/python/testData/inspections/PyTypeCheckerInspection/TypingTypeVarWithUnresolvedBound.py
@@ -0,0 +1,11 @@
+from typing import TypeVar
+
+
+T = TypeVar('T', int, unresolved)
+
+
+def calc(a: T, b: T):
+ pass
+
+
+calc('a', 0)
diff --git a/python/testData/pyi/inspections/overloads/Overloads.py b/python/testData/pyi/inspections/overloads/Overloads.py
index af7473a12ab9..954390000ab9 100644
--- a/python/testData/pyi/inspections/overloads/Overloads.py
+++ b/python/testData/pyi/inspections/overloads/Overloads.py
@@ -31,6 +31,6 @@ def test_stub_only_function(x):
def tset_overloaded_generics(x):
g(Gen(10).get(10, 10))
- g(Gen(10).get(10, 'foo'))
- g(Gen('foo').get(10, 10))
+ g(Gen(10).get(10, 'foo'))
+ g(Gen('foo').get(10, 10))
g(Gen('foo').get(10, 'foo'))
diff --git a/python/testSrc/com/jetbrains/python/PyTypeParserTest.java b/python/testSrc/com/jetbrains/python/PyTypeParserTest.java
index 91fa46fbe2ed..b0f3b6aa1eeb 100644
--- a/python/testSrc/com/jetbrains/python/PyTypeParserTest.java
+++ b/python/testSrc/com/jetbrains/python/PyTypeParserTest.java
@@ -137,7 +137,7 @@ public class PyTypeParserTest extends PyTestCase {
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "T");
assertNotNull(type);
assertInstanceOf(type, PyGenericType.class);
- assertEquals("T", type.getName());
+ assertEquals("TypeVar('T')", type.getName());
}
// PY-4223
@@ -251,7 +251,7 @@ public class PyTypeParserTest extends PyTestCase {
assertEquals("int", type0.getName());
final PyType type1 = parameterTypes.get(1).getType(context);
assertNotNull(type1);
- assertEquals("T", type1.getName());
+ assertEquals("TypeVar('T')", type1.getName());
}
public void testCallableWithoutArgs() {
diff --git a/python/testSrc/com/jetbrains/python/PyTypingTest.java b/python/testSrc/com/jetbrains/python/PyTypingTest.java
index 7409f24faeb3..2d767ae01891 100644
--- a/python/testSrc/com/jetbrains/python/PyTypingTest.java
+++ b/python/testSrc/com/jetbrains/python/PyTypingTest.java
@@ -151,7 +151,7 @@ public class PyTypingTest extends PyTestCase {
}
public void testGenericType() {
- doTest("A",
+ doTest("TypeVar('A')",
"from typing import TypeVar\n" +
"\n" +
"T = TypeVar('A')\n" +
@@ -161,7 +161,7 @@ public class PyTypingTest extends PyTestCase {
}
public void testGenericBoundedType() {
- doTest("T <= int | str",
+ doTest("TypeVar('T', int, str)",
"from typing import TypeVar\n" +
"\n" +
"T = TypeVar('T', int, str)\n" +
@@ -346,12 +346,25 @@ public class PyTypingTest extends PyTestCase {
"from typing import Iterable\n" +
"\n" +
"def foo() -> Iterable[int]:\n" +
- " passs\n" +
+ " pass\n" +
"\n" +
"for expr in foo():\n" +
" pass\n");
}
+ // PY-16353
+ public void testAssignedType() {
+ doTest("Iterable[int]",
+ "from typing import Iterable\n" +
+ "\n" +
+ "IntIterable = Iterable[int]\n" +
+ "\n" +
+ "def foo() -> IntIterable:\n" +
+ " pass\n" +
+ "\n" +
+ "expr = foo()\n");
+ }
+
private void doTestNoInjectedText(@NotNull String text) {
myFixture.configureByText(PythonFileType.INSTANCE, text);
final InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(myFixture.getProject());
diff --git a/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java
index b3fc9efa0b0e..84f2290e8a4a 100644
--- a/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java
@@ -78,4 +78,9 @@ public class Py3TypeCheckerInspectionTest extends PyTestCase {
public void testTypingListSubscriptionExpression() {
doTest();
}
+
+ // PY-16855
+ public void testTypingTypeVarWithUnresolvedBound() {
+ doTest();
+ }
}