mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -11,3 +11,9 @@ tasks-core
|
||||
tasks-api
|
||||
github
|
||||
terminal
|
||||
IntelliLang
|
||||
IntelliLang-xml
|
||||
IntelliLang-js
|
||||
IntelliLang-python
|
||||
rest
|
||||
python-rest
|
||||
|
||||
@@ -60,8 +60,8 @@ setProperty("buildName", "PY-$buildNumber")
|
||||
|
||||
target('default': "Build artifacts") {
|
||||
def modules = [
|
||||
"python-pydev", "colorSchemes", pycharmPlatformApiModules(), platformUltimateImplementationModules, pycharmImplementationModules(), pluginFilter
|
||||
].flatten()
|
||||
"python-pydev", "colorSchemes", pycharmPlatformApiModules(), platformUltimateImplementationModules,
|
||||
pycharmImplementationModules(), pluginFilter, "platform-main"].flatten()
|
||||
|
||||
loadProject()
|
||||
|
||||
@@ -156,8 +156,26 @@ target('default': "Build artifacts") {
|
||||
buildMacZip(macAppRoot, "${paths.artifacts}/pycharm${buildName}.sit", [paths.distAll], paths.distMac)
|
||||
signMacZip("pycharm")
|
||||
buildDmg("pycharm", "${home}/python/build/DMG_background.png")
|
||||
|
||||
communityEdition(usedJars)
|
||||
}
|
||||
|
||||
private communityEdition(Set usedJars) {
|
||||
Script s = groovyShell.parse(new File("$pythonCommunityHome/build/pycharm_community_build.gant"))
|
||||
s.setBinding(binding)
|
||||
|
||||
s.layoutCommunity(usedJars)
|
||||
|
||||
// todo: get rid of copying
|
||||
//ant.copy(file: "$paths.artifacts/ideaIC-${buildNumber}.mac.zip", tofile: "$paths.artifacts/ideaIC-${buildNumber}.sit")
|
||||
//def extraArgs = ["build.number": "IC-$buildNumber"]
|
||||
//signMacZip("idea", extraArgs)
|
||||
//notifyArtifactBuilt("$paths.artifacts/ideaIC-${buildNumber}.sit")
|
||||
//buildDmg("idea", getDmgImage(true), extraArgs)
|
||||
//ant.delete(file: "$paths.artifacts/ideaIC-${buildNumber}.sit")
|
||||
}
|
||||
|
||||
|
||||
private layoutPlugins(layouts) {
|
||||
dir("plugins") {
|
||||
layouts.layoutPlugin("django-db-config")
|
||||
|
||||
@@ -107,9 +107,9 @@ target('default': "Build artifacts") {
|
||||
def normalizedHome = ch.replace('\\', '/')
|
||||
def normalizedPythonHome = pythonCommunityHome.replace('\\', '/')
|
||||
def approvedJars = ["$normalizedHome/lib/", "$normalizedPythonHome/lib/", "$normalizedHome/xml/relaxng/lib/"]
|
||||
def usedJars = buildModulesAndCollectUsedJars(modules, approvedJars, [])
|
||||
def usedJars = buildModulesAndCollectUsedJars(modules, approvedJars, ["/ant/"])
|
||||
|
||||
layoutCommunity(paths, usedJars)
|
||||
layoutCommunity(usedJars)
|
||||
|
||||
|
||||
buildWinZip("${paths.artifacts}/pycharm${buildName}.zip", [paths.distAll, paths.distWin])
|
||||
@@ -119,18 +119,14 @@ target('default': "Build artifacts") {
|
||||
"pycharm", false, true, system_selector)
|
||||
*/
|
||||
|
||||
String tarRoot = isEap() ? "pycharm-community-$buildNumber" : "pycharm-community-${p("component.version.major")}.${p("component.version.minor")}"
|
||||
buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}.tar", [paths.distAll, paths.distUnix])
|
||||
|
||||
/*
|
||||
String macAppRoot = isEap() ? "PyCharm ${p("component.version.major")}.${p("component.version.minor")} EAP.app" : "PyCharm.app"
|
||||
buildMacZip(macAppRoot, "${paths.artifacts}/pycharm${buildName}.sit", [paths.distAll], paths.distMac)
|
||||
signMacZip("pycharm")
|
||||
buildDmg("pycharm", "${home}/python/build/DMG_background.png")
|
||||
*/
|
||||
}
|
||||
|
||||
public layoutCommunity(Paths paths, Set usedJars) {
|
||||
public layoutCommunity(Set usedJars) {
|
||||
def paths = new Paths(home)
|
||||
buildSearchableOptions("${projectBuilder.moduleOutput(findModule("platform-resources"))}/search", [], {
|
||||
projectBuilder.moduleRuntimeClasspath(findModule("main_pycharm_ce"), false).each {
|
||||
ant.pathelement(location: it)
|
||||
@@ -166,6 +162,12 @@ public layoutCommunity(Paths paths, Set usedJars) {
|
||||
"$pythonCommunityHome/resources"]
|
||||
buildWinLauncher("$ch", "$ch/bin/WinLauncher/WinLauncher.exe", launcher,
|
||||
appInfoFile(), "$pythonCommunityHome/build/pycharm_community_launcher.properties", system_selector, resourcePaths)
|
||||
|
||||
String tarRoot = isEap() ? "pycharm-community-$buildNumber" : "pycharm-community-${p("component.version.major")}.${p("component.version.minor")}"
|
||||
buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}.tar", [paths.distAll, paths.distUnix])
|
||||
|
||||
String macAppRoot = isEap() ? "PyCharm Community Edition ${p("component.version.major")}.${p("component.version.minor")} EAP.app" : "PyCharm Community Edition.app"
|
||||
buildMacZip(macAppRoot, "${paths.artifacts}/pycharm${buildName}.sit", [paths.distAll], paths.distMac)
|
||||
}
|
||||
|
||||
private layoutPlugins(layouts) {
|
||||
@@ -187,8 +189,10 @@ private layoutPlugins(layouts) {
|
||||
layouts.layoutPlugin("python-uml")
|
||||
layouts.layoutPlugin("localization")
|
||||
layouts.layoutPlugin("python-localization")
|
||||
*/
|
||||
layouts.layoutPlugin("rest")
|
||||
layouts.layoutPlugin("python-rest")
|
||||
/*
|
||||
layouts.layoutPlugin("pycharm-flask")
|
||||
layouts.layoutPlugin("pycharm-numpy")
|
||||
layouts.layoutPlugin("textmate") {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
IDS_JDK_ENV_VAR=PYCHARM_JDK
|
||||
IDS_JDK_ONLY=false
|
||||
IDS_VM_OPTIONS=-Didea.platform.prefix=PythonCore -Didea.no.jre.check=true -Didea.paths.selector=__PRODUCT_PATHS_SELECTOR__
|
||||
IDS_VM_OPTIONS=-Didea.platform.prefix=PyCharmCore -Didea.no.jre.check=true -Didea.paths.selector=__PRODUCT_PATHS_SELECTOR__
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="lang-impl" />
|
||||
<orderEntry type="module" module-name="rest" />
|
||||
<orderEntry type="module" module-name="python" />
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="module" module-name="testFramework" scope="TEST" />
|
||||
<orderEntry type="module" module-name="python-tests" scope="TEST" />
|
||||
<orderEntry type="module" module-name="python-community" />
|
||||
<orderEntry type="module" module-name="python-community-tests" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -4,11 +4,12 @@ import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.ex.util.LayerDescriptor;
|
||||
import com.intellij.openapi.editor.ex.util.LayeredLexerEditorHighlighter;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.django.lang.template.DjangoTemplateFileType;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -26,9 +27,12 @@ public class RestEditorHighlighter extends LayeredLexerEditorHighlighter {
|
||||
registerLayer(RestTokenTypes.PYTHON_LINE, new LayerDescriptor(
|
||||
SyntaxHighlighterFactory.getSyntaxHighlighter(PythonFileType.INSTANCE, project, file), "", EditorColors.INJECTED_LANGUAGE_FRAGMENT));
|
||||
|
||||
registerLayer(RestTokenTypes.DJANGO_LINE, new LayerDescriptor(
|
||||
SyntaxHighlighterFactory.getSyntaxHighlighter(DjangoTemplateFileType.INSTANCE, project, file), "", EditorColors.INJECTED_LANGUAGE_FRAGMENT));
|
||||
|
||||
FileType djangoTemplateFileType = FileTypeManager.getInstance().findFileTypeByName("DjangoTemplate");
|
||||
if (djangoTemplateFileType != null) {
|
||||
registerLayer(RestTokenTypes.DJANGO_LINE, new LayerDescriptor(
|
||||
SyntaxHighlighterFactory.getSyntaxHighlighter(djangoTemplateFileType, project, file), "",
|
||||
EditorColors.INJECTED_LANGUAGE_FRAGMENT));
|
||||
}
|
||||
|
||||
registerLayer(RestTokenTypes.JAVASCRIPT_LINE, new LayerDescriptor(
|
||||
SyntaxHighlighterFactory.getSyntaxHighlighter(StdFileTypes.JS, project, file), "", EditorColors.INJECTED_LANGUAGE_FRAGMENT));
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||
import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
|
||||
import com.jetbrains.django.lang.template.DjangoTemplateLanguage;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -51,7 +50,10 @@ public class RestFileViewProvider extends MultiplePsiFilesPerDocumentFileViewPro
|
||||
if (myLanguages == null) {
|
||||
myLanguages = Sets.newLinkedHashSet();
|
||||
myLanguages.add(getBaseLanguage());
|
||||
myLanguages.add(DjangoTemplateLanguage.INSTANCE);
|
||||
Language djangoTemplateLanguage = Language.findLanguageByID("DjangoTemplate");
|
||||
if (djangoTemplateLanguage != null) {
|
||||
myLanguages.add(djangoTemplateLanguage);
|
||||
}
|
||||
myLanguages.add(getTemplateDataLanguage());
|
||||
}
|
||||
return myLanguages;
|
||||
@@ -66,7 +68,7 @@ public class RestFileViewProvider extends MultiplePsiFilesPerDocumentFileViewPro
|
||||
file.setContentElementType(RestPythonElementTypes.PYTHON_BLOCK_DATA);
|
||||
return file;
|
||||
}
|
||||
else if (lang == DjangoTemplateLanguage.INSTANCE) {
|
||||
else if (lang.getID().equals("DjangoTemplate")) {
|
||||
PsiFileImpl file = (PsiFileImpl)def.createFile(this);
|
||||
file.setContentElementType(RestPythonElementTypes.DJANGO_BLOCK_DATA);
|
||||
return file;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
<orderEntry type="module" module-name="duplicates" scope="TEST" />
|
||||
<orderEntry type="module" module-name="duplicates-xml" scope="TEST" />
|
||||
<orderEntry type="module" module-name="IntelliLang-js" scope="TEST" />
|
||||
<orderEntry type="module" module-name="python-community-tests" exported="" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 347 KiB |
@@ -4,7 +4,7 @@
|
||||
<build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
|
||||
<logo url="/pycharm_core_logo.png" textcolor="ffffff" progressColor="ffaa16" progressY="230" progressTailIcon="/community_progress_tail.png"/>
|
||||
<about url="/pycharm_core_about.png" logoX="300" logoY="265" logoW="75" logoH="30" foreground="ffffff" linkColor="fca11a"/>
|
||||
<icon size32="/PyCharm_32.png" size16="/PyCharm_16.png" size32opaque="/PyCharm_32.png" size12="/PyCharm_13.png" ico="PyCharm.ico"/>
|
||||
<icon size32="/PyCharm_32.png" size16="/PyCharm_16.png" size32opaque="/PyCharm_32.png" size12="/PyCharm_13.png" ico="PyCharmCore.ico"/>
|
||||
<package code="__PACKAGE_CODE__"/>
|
||||
<names product="PyCharm Core" fullname="PyCharm Core" script="charm"/>
|
||||
<install-over minbuild="0" maxbuild="0" version="1.x"/>
|
||||
|
||||
@@ -236,6 +236,30 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor {
|
||||
return head.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyConditionalExpression(PyConditionalExpression node) {
|
||||
myBuilder.startNode(node);
|
||||
final PyExpression condition = node.getCondition();
|
||||
final PyTypeAssertionEvaluator assertionEvaluator = new PyTypeAssertionEvaluator();
|
||||
if (condition != null) {
|
||||
condition.accept(this);
|
||||
condition.accept(assertionEvaluator);
|
||||
}
|
||||
final Instruction branchingPoint = myBuilder.prevInstruction;
|
||||
final PyExpression truePart = node.getTruePart();
|
||||
final PyExpression falsePart = node.getFalsePart();
|
||||
if (truePart != null) {
|
||||
InstructionBuilder.addAssertInstructions(myBuilder, assertionEvaluator);
|
||||
truePart.accept(this);
|
||||
myBuilder.addPendingEdge(node, myBuilder.prevInstruction);
|
||||
}
|
||||
if (falsePart != null) {
|
||||
myBuilder.prevInstruction = branchingPoint;
|
||||
falsePart.accept(this);
|
||||
myBuilder.addPendingEdge(node, myBuilder.prevInstruction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyIfStatement(final PyIfStatement node) {
|
||||
myBuilder.startNode(node);
|
||||
|
||||
+26
-34
@@ -50,16 +50,14 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
|
||||
final PyReferenceExpression target = (PyReferenceExpression)args[0];
|
||||
final PyExpression typeElement = args[1];
|
||||
final boolean positive = myPositive;
|
||||
if (!processTuple(target, typeElement)) {
|
||||
pushAssertion(target, new InstructionTypeCallback() {
|
||||
@Override
|
||||
public PyType getType(TypeEvalContext context, PsiElement anchor) {
|
||||
final List<PyType> types = new ArrayList<PyType>();
|
||||
types.add(context.getType(typeElement));
|
||||
return createAssertionType(context.getType(target), types, positive, context);
|
||||
}
|
||||
});
|
||||
}
|
||||
pushAssertion(target, new InstructionTypeCallback() {
|
||||
@Override
|
||||
public PyType getType(TypeEvalContext context, PsiElement anchor) {
|
||||
final List<PyType> types = new ArrayList<PyType>();
|
||||
types.add(context.getType(typeElement));
|
||||
return createAssertionType(context.getType(target), types, positive, context);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (node.isCalleeText(PyNames.CALLABLE_BUILTIN)) {
|
||||
@@ -120,34 +118,11 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
|
||||
super.visitPyBinaryExpression(node);
|
||||
}
|
||||
|
||||
private boolean processTuple(final PyReferenceExpression target, PyExpression typeElement) {
|
||||
boolean pushed = false;
|
||||
if (typeElement instanceof PyParenthesizedExpression) {
|
||||
final PyExpression contained = ((PyParenthesizedExpression)typeElement).getContainedExpression();
|
||||
if (contained instanceof PyTupleExpression) {
|
||||
final PyTupleExpression tuple = (PyTupleExpression)contained;
|
||||
final boolean positive = myPositive;
|
||||
pushAssertion(target, new InstructionTypeCallback() {
|
||||
@Override
|
||||
public PyType getType(TypeEvalContext context, @Nullable PsiElement anchor) {
|
||||
final List<PyType> types = new ArrayList<PyType>();
|
||||
for (PyExpression e : tuple.getElements()) {
|
||||
types.add(context.getType(e));
|
||||
}
|
||||
return createAssertionType(context.getType(target), types, positive, context);
|
||||
}
|
||||
});
|
||||
pushed = true;
|
||||
}
|
||||
}
|
||||
return pushed;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyType createAssertionType(PyType initial, List<PyType> types, boolean positive, TypeEvalContext context) {
|
||||
final List<PyType> members = new ArrayList<PyType>();
|
||||
for (PyType t : types) {
|
||||
members.add(t instanceof PyClassType ? ((PyClassType)t).toInstance() : t);
|
||||
members.add(transformTypeFromAssertion(t));
|
||||
}
|
||||
final PyType union = PyUnionType.union(members);
|
||||
if (positive) {
|
||||
@@ -162,6 +137,23 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
|
||||
return initial;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyType transformTypeFromAssertion(@Nullable PyType type) {
|
||||
if (type instanceof PyTupleType) {
|
||||
final List<PyType> members = new ArrayList<PyType>();
|
||||
final PyTupleType tupleType = (PyTupleType)type;
|
||||
final int count = tupleType.getElementCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
members.add(transformTypeFromAssertion(tupleType.getElementType(i)));
|
||||
}
|
||||
return PyUnionType.union(members);
|
||||
}
|
||||
else if (type instanceof PyClassType) {
|
||||
return ((PyClassType)type).toInstance();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private void pushAssertion(PyReferenceExpression element, InstructionTypeCallback getType) {
|
||||
myStack.push(new Assertion(element, getType));
|
||||
}
|
||||
|
||||
@@ -684,26 +684,10 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
|
||||
mySelected = state;
|
||||
|
||||
if (mySelected) {
|
||||
final XStandaloneVariablesView view = new XStandaloneVariablesView(getProject(), new PyDebuggerEditorsProvider());
|
||||
PyStackFrame stackFrame = new PyStackFrame(getProject(), myPydevConsoleCommunication, new PyStackFrameInfo("", "", "", null), null);
|
||||
view.showVariables(stackFrame);
|
||||
|
||||
getConsoleView().showVariables(view);
|
||||
|
||||
myPydevConsoleCommunication.addCommunicationListener(new ConsoleCommunicationListener() {
|
||||
@Override
|
||||
public void commandExecuted() {
|
||||
view.showMessage("Execution finished");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inputRequested() {
|
||||
|
||||
}
|
||||
});
|
||||
getConsoleView().showVariables(myPydevConsoleCommunication);
|
||||
}
|
||||
else {
|
||||
getConsoleView().hideVariables();
|
||||
getConsoleView().restoreWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,10 @@ import com.intellij.xdebugger.impl.frame.XStandaloneVariablesView;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.console.completion.PythonConsoleAutopopupBlockingHandler;
|
||||
import com.jetbrains.python.console.pydev.ConsoleCommunication;
|
||||
import com.jetbrains.python.console.pydev.ConsoleCommunicationListener;
|
||||
import com.jetbrains.python.debugger.PyDebuggerEditorsProvider;
|
||||
import com.jetbrains.python.debugger.PyStackFrame;
|
||||
import com.jetbrains.python.debugger.PyStackFrameInfo;
|
||||
import com.jetbrains.python.highlighting.PyHighlighter;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
@@ -59,7 +63,8 @@ public class PythonConsoleView extends JPanel implements LanguageConsoleView, Ob
|
||||
private boolean myHyperlink;
|
||||
|
||||
private final MyLanguageConsoleViewImpl myLanguageConsoleView;
|
||||
private XStandaloneVariablesView myVariablesView;
|
||||
|
||||
private Disposable mySplittedDisposable;
|
||||
|
||||
public PythonConsoleView(final Project project, final String title, Sdk sdk) {
|
||||
super(new BorderLayout());
|
||||
@@ -361,27 +366,43 @@ public class PythonConsoleView extends JPanel implements LanguageConsoleView, Ob
|
||||
return myProject;
|
||||
}
|
||||
|
||||
public void showVariables(XStandaloneVariablesView view) {
|
||||
public void showVariables(PydevConsoleCommunication consoleCommunication) {
|
||||
PyStackFrame stackFrame = new PyStackFrame(myProject, consoleCommunication, new PyStackFrameInfo("", "", "", null), null);
|
||||
final XStandaloneVariablesView view = new XStandaloneVariablesView(myProject, new PyDebuggerEditorsProvider(), stackFrame);
|
||||
consoleCommunication.addCommunicationListener(new ConsoleCommunicationListener() {
|
||||
@Override
|
||||
public void commandExecuted() {
|
||||
view.rebuildView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inputRequested() {
|
||||
}
|
||||
});
|
||||
splitWindow(view.getPanel(), view);
|
||||
}
|
||||
|
||||
private void splitWindow(JComponent component, Disposable componentDisposable) {
|
||||
removeAll();
|
||||
JSplitPane p = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||
p.add(myLanguageConsoleView.getComponent(), JSplitPane.LEFT);
|
||||
myVariablesView = view;
|
||||
p.add(myVariablesView.getPanel(), JSplitPane.RIGHT);
|
||||
mySplittedDisposable = componentDisposable;
|
||||
p.add(component, JSplitPane.RIGHT);
|
||||
p.setDividerLocation((int)getSize().getWidth()*2/3);
|
||||
add(p, BorderLayout.CENTER);
|
||||
|
||||
|
||||
validate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void hideVariables() {
|
||||
public void restoreWindow() {
|
||||
removeAll();
|
||||
add(myLanguageConsoleView.getComponent(), BorderLayout.CENTER);
|
||||
validate();
|
||||
repaint();
|
||||
if (myVariablesView != null) {
|
||||
Disposer.dispose(myVariablesView);
|
||||
myVariablesView = null;
|
||||
if (mySplittedDisposable != null) {
|
||||
Disposer.dispose(mySplittedDisposable);
|
||||
mySplittedDisposable = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiPolyVariantReference;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
@@ -111,13 +112,20 @@ public class PyUnboundLocalVariableInspection extends PyInspection {
|
||||
if (!isFirstUnboundRead(node, owner)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement resolved = node.getReference(resolveWithoutImplicits()).resolve();
|
||||
final PsiPolyVariantReference ref = node.getReference(resolveWithoutImplicits());
|
||||
if (ref == null) {
|
||||
return;
|
||||
}
|
||||
final PsiElement resolved = ref.resolve();
|
||||
final boolean isBuiltin = PyBuiltinCache.getInstance(node).hasInBuiltins(resolved);
|
||||
if (owner instanceof PyClass) {
|
||||
if (isBuiltin || ScopeUtil.getDeclarationScopeOwner(owner, name) != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (PyUnreachableCodeInspection.hasAnyInterruptedControlFlowPaths(node)) {
|
||||
return;
|
||||
}
|
||||
if (owner instanceof PyFile) {
|
||||
if (isBuiltin) {
|
||||
return;
|
||||
@@ -192,5 +200,5 @@ public class PyUnboundLocalVariableInspection extends PyInspection {
|
||||
PyBundle.message("INSP.unbound.function.too.large", owner.getName()),
|
||||
ProblemHighlightType.WEAK_WARNING);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ import com.intellij.codeInsight.controlflow.ControlFlowUtil;
|
||||
import com.intellij.codeInsight.controlflow.Instruction;
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.util.Function;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -50,7 +52,7 @@ public class PyUnreachableCodeInspection extends PyInspection {
|
||||
ControlFlowUtil.iteratePrev(instructions.length - 1, instructions, new Function<Instruction, ControlFlowUtil.Operation>() {
|
||||
@Override
|
||||
public ControlFlowUtil.Operation fun(Instruction instruction) {
|
||||
if (instruction.allPred().isEmpty() && instruction.num() != 0) {
|
||||
if (instruction.allPred().isEmpty() && !isFirstInstruction(instruction)) {
|
||||
unreachable.add(instruction.getElement());
|
||||
}
|
||||
return ControlFlowUtil.Operation.NEXT;
|
||||
@@ -63,4 +65,32 @@ public class PyUnreachableCodeInspection extends PyInspection {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasAnyInterruptedControlFlowPaths(@NotNull PsiElement element) {
|
||||
final ScopeOwner owner = ScopeUtil.getScopeOwner(element);
|
||||
if (owner != null) {
|
||||
final ControlFlow flow = ControlFlowCache.getControlFlow(owner);
|
||||
final Instruction[] instructions = flow.getInstructions();
|
||||
final int start = ControlFlowUtil.findInstructionNumberByElement(instructions, element);
|
||||
if (start >= 0) {
|
||||
final Ref<Boolean> resultRef = Ref.create(false);
|
||||
ControlFlowUtil.iteratePrev(start, instructions, new Function<Instruction, ControlFlowUtil.Operation>() {
|
||||
@Override
|
||||
public ControlFlowUtil.Operation fun(Instruction instruction) {
|
||||
if (instruction.allPred().isEmpty() && !isFirstInstruction(instruction)) {
|
||||
resultRef.set(true);
|
||||
return ControlFlowUtil.Operation.BREAK;
|
||||
}
|
||||
return ControlFlowUtil.Operation.NEXT;
|
||||
}
|
||||
});
|
||||
return resultRef.get();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isFirstInstruction(Instruction instruction) {
|
||||
return instruction.num() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,6 +426,9 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
if ((object_type != null) && object_type.getPossibleInstanceMembers().contains(refname)) return;
|
||||
}
|
||||
else {
|
||||
if (PyUnreachableCodeInspection.hasAnyInterruptedControlFlowPaths(refex)) {
|
||||
return;
|
||||
}
|
||||
if (LanguageLevel.forElement(node).isOlderThan(LanguageLevel.PYTHON26)) {
|
||||
if ("with".equals(refname)) {
|
||||
actions.add(new UnresolvedRefAddFutureImportQuickFix());
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
x = 1
|
||||
y = 2
|
||||
c = True
|
||||
z = x if c else y
|
||||
@@ -0,0 +1,16 @@
|
||||
0(1) element: null
|
||||
1(2) element: PyAssignmentStatement
|
||||
2(3) WRITE ACCESS: x
|
||||
3(4) element: PyAssignmentStatement
|
||||
4(5) WRITE ACCESS: y
|
||||
5(6) element: PyAssignmentStatement
|
||||
6(7) READ ACCESS: True
|
||||
7(8) WRITE ACCESS: c
|
||||
8(9) element: PyAssignmentStatement
|
||||
9(10) element: PyConditionalExpression
|
||||
10(11,12) READ ACCESS: c
|
||||
11(13) READ ACCESS: x
|
||||
12(13) READ ACCESS: y
|
||||
13(14) WRITE ACCESS: z
|
||||
14() element: null
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
def test1(c, xs):
|
||||
if c:
|
||||
y = 1
|
||||
print(<warning descr="Local variable 'y' might be referenced before assignment">y</warning>)
|
||||
for x in xs:
|
||||
continue
|
||||
z = 1
|
||||
@@ -0,0 +1,5 @@
|
||||
def f():
|
||||
x = 1
|
||||
print(<error descr="Unresolved reference 'z'">z</error>)
|
||||
return x
|
||||
print(x)
|
||||
@@ -218,6 +218,10 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testConditionalExpression() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTestFirstStatement() {
|
||||
final String testName = getTestName(false).toLowerCase();
|
||||
configureByFile(testName + ".py");
|
||||
|
||||
@@ -737,6 +737,21 @@ public class PyTypeTest extends PyTestCase {
|
||||
" expr = x\n");
|
||||
}
|
||||
|
||||
public void testIsInstanceExpressionResolvedToTuple() {
|
||||
doTest("str | unicode",
|
||||
"string_types = str, unicode\n" +
|
||||
"\n" +
|
||||
"def f(x):\n" +
|
||||
" if isinstance(x, string_types):\n" +
|
||||
" expr = x\n");
|
||||
}
|
||||
|
||||
public void testIsInstanceInConditionalExpression() {
|
||||
doTest("str | int",
|
||||
"def f(x):\n" +
|
||||
" expr = x if isinstance(x, str) else 10\n");
|
||||
}
|
||||
|
||||
private static TypeEvalContext getTypeEvalContext(@NotNull PyExpression element) {
|
||||
return TypeEvalContext.userInitiated(element.getContainingFile()).withTracing();
|
||||
}
|
||||
|
||||
@@ -147,6 +147,6 @@ public abstract class PyTestCase extends UsefulTestCase {
|
||||
}
|
||||
|
||||
public static void initPlatformPrefix() {
|
||||
PlatformTestCase.initPlatformPrefix(IDEA_MARKER_CLASS, PlatformUtils.PYCHARM_PREFIX);
|
||||
PlatformTestCase.initPlatformPrefix(UsefulTestCase.IDEA_MARKER_CLASS, PlatformUtils.PYCHARM_PREFIX);
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -173,6 +173,11 @@ public class PyUnboundLocalVariableInspectionTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-6114
|
||||
public void testUnboundUnreachable() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
myFixture.configureByFile(TEST_DIRECTORY + getTestName(false) + ".py");
|
||||
myFixture.enableInspections(PyUnboundLocalVariableInspection.class);
|
||||
|
||||
+5
@@ -289,6 +289,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-10006
|
||||
public void testUnresolvedUnreachable() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py");
|
||||
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="testFramework" />
|
||||
<orderEntry type="module" module-name="python-psi-api" scope="TEST" />
|
||||
<orderEntry type="module" module-name="python-community" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
Reference in New Issue
Block a user