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:
@@ -90,10 +90,10 @@ target('default': "Build artifacts") {
|
||||
|
||||
loadProject()
|
||||
|
||||
project.stage("Cleaning up sandbox folder")
|
||||
projectBuilder.stage("Cleaning up sandbox folder")
|
||||
|
||||
project.targetFolder = "${paths.sandbox}/classes"
|
||||
project.dryRun = dryRun
|
||||
projectBuilder.targetFolder = "${paths.sandbox}/classes"
|
||||
projectBuilder.dryRun = dryRun
|
||||
|
||||
if (!dryRun) {
|
||||
forceDelete(paths.sandbox)
|
||||
@@ -131,12 +131,12 @@ target('default': "Build artifacts") {
|
||||
|
||||
def forbiddenJars = ["client-api", "ideaLicenseDecoder", "eawtstub.jar", "ui.jar", "exe4jlib.jar", "cglib", "jcip-annotations", "/y.jar", "ysvg.jar"]
|
||||
|
||||
project.clean()
|
||||
projectBuilder.cleanOutput()
|
||||
modules.each {
|
||||
Module module = project[it] as Module
|
||||
Module module = findModule(it)
|
||||
if (module != null) {
|
||||
project.info("Building $module.name")
|
||||
module.runtimeClasspath().each {
|
||||
projectBuilder.info("Building $module.name")
|
||||
projectBuilder.moduleRuntimeClasspath(module, false).each {
|
||||
File file = new File(it)
|
||||
if (file.exists()) {
|
||||
String path = file.canonicalPath.replace('\\', '/')
|
||||
@@ -155,15 +155,15 @@ target('default': "Build artifacts") {
|
||||
module.make()
|
||||
}
|
||||
else {
|
||||
project.warning("$it is not a module")
|
||||
projectBuilder.warning("$it is not a module")
|
||||
}
|
||||
}
|
||||
|
||||
usedJars.add("$home/community/lib/jgoodies-common-1.2.1.jar")
|
||||
usedJars.add("$home/community/lib/jgoodies-looks-2.4.2.jar")
|
||||
|
||||
buildSearchableOptions("${project["platform-resources"].output}/search", ["$home/build/idea.license", "$home/build/pycharm.license"], {
|
||||
project["python-ide"].runtimeClasspath().each {
|
||||
buildSearchableOptions("${findModule("platform-resources").output}/search", ["$home/build/idea.license", "$home/build/pycharm.license"], {
|
||||
projectBuilder.moduleRuntimeClasspath(findModule("python-ide"), false).each {
|
||||
pathelement(location: it)
|
||||
}
|
||||
}, "-Didea.platform.prefix=Python -Didea.no.jre.check=true")
|
||||
|
||||
@@ -161,6 +161,9 @@ public class PyRequirement {
|
||||
@NotNull
|
||||
private List<String> parse(@Nullable String s) {
|
||||
// Version parsing from pkg_resources ensures that all the "pre", "alpha", "rc", etc. are sorted correctly
|
||||
if (s == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final Pattern COMPONENT_RE = Pattern.compile("\\d+|[a-z]+|\\.|-|.+");
|
||||
final List<String> results = new ArrayList<String>();
|
||||
final Matcher matcher = COMPONENT_RE.matcher(s);
|
||||
|
||||
@@ -181,7 +181,10 @@ public class PyDynamicMember {
|
||||
if (myTypeCallback != null) {
|
||||
return myTypeCallback.fun(myContext);
|
||||
}
|
||||
return PyPsiFacade.getInstance(getProject()).createClassType(myClass, !myResolveToInstance);
|
||||
else if (myClass != null) {
|
||||
return PyPsiFacade.getInstance(getProject()).createClassType(myClass, !myResolveToInstance);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-7
@@ -8,35 +8,49 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.profile.codeInspection.InspectionProfileManager;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.jetbrains.python.inspections.PyUnresolvedReferencesInspection;
|
||||
import com.jetbrains.python.psi.impl.PyQualifiedName;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class AddIgnoredIdentifierFix implements LocalQuickFix, LowPriorityAction {
|
||||
private final String myIdentifier;
|
||||
public class AddIgnoredIdentifierQuickFix implements LocalQuickFix, LowPriorityAction {
|
||||
public static final String END_WILDCARD = ".*";
|
||||
|
||||
public AddIgnoredIdentifierFix(String identifier) {
|
||||
@NotNull private final PyQualifiedName myIdentifier;
|
||||
private final boolean myIgnoreAllAttributes;
|
||||
|
||||
public AddIgnoredIdentifierQuickFix(@NotNull PyQualifiedName identifier, boolean ignoreAllAttributes) {
|
||||
myIdentifier = identifier;
|
||||
myIgnoreAllAttributes = ignoreAllAttributes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Ignore unresolved identifier " + myIdentifier;
|
||||
if (myIgnoreAllAttributes) {
|
||||
return "Mark all unresolved attributes of '" + myIdentifier + "' as ignored";
|
||||
}
|
||||
else {
|
||||
return "Ignore unresolved reference '" + myIdentifier + "'";
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return "Ignore unresolved identifier";
|
||||
return "Ignore unresolved reference";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PyUnresolvedReferencesInspection instance = PyUnresolvedReferencesInspection.getInstance(descriptor.getPsiElement());
|
||||
if (!instance.ignoredIdentifiers.contains(myIdentifier)) {
|
||||
instance.ignoredIdentifiers.add(myIdentifier);
|
||||
String name = myIdentifier.toString();
|
||||
if (myIgnoreAllAttributes) {
|
||||
name = name + END_WILDCARD;
|
||||
}
|
||||
if (!instance.ignoredIdentifiers.contains(name)) {
|
||||
instance.ignoredIdentifiers.add(name);
|
||||
final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
|
||||
InspectionProfileManager.getInstance().fireProfileChanged(profile);
|
||||
}
|
||||
@@ -470,9 +470,12 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
|
||||
|
||||
@Nullable
|
||||
private static PyClass inferClassOfParameter(PsiElement context) {
|
||||
final PyType type = ((PyNamedParameter)context).getType(TypeEvalContext.fast());
|
||||
if (type instanceof PyClassType)
|
||||
return ((PyClassType)type).getPyClass();
|
||||
if (context instanceof PyNamedParameter) {
|
||||
final PyType type = ((PyNamedParameter)context).getType(TypeEvalContext.fast());
|
||||
if (type instanceof PyClassType) {
|
||||
return ((PyClassType)type).getPyClass();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+109
-13
@@ -49,7 +49,10 @@ import com.jetbrains.python.psi.impl.PyImportedModule;
|
||||
import com.jetbrains.python.psi.impl.PyQualifiedName;
|
||||
import com.jetbrains.python.psi.impl.references.PyImportReference;
|
||||
import com.jetbrains.python.psi.impl.references.PyOperatorReference;
|
||||
import com.jetbrains.python.psi.resolve.*;
|
||||
import com.jetbrains.python.psi.resolve.ImportedResolveResult;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import com.jetbrains.python.psi.types.*;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
@@ -59,6 +62,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
|
||||
import static com.jetbrains.python.actions.AddIgnoredIdentifierQuickFix.END_WILDCARD;
|
||||
|
||||
/**
|
||||
* Marks references that fail to resolve. Also tracks unused imports and provides "optimize imports" support.
|
||||
* User: dcheryasov
|
||||
@@ -108,7 +113,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
ListEditForm form = new ListEditForm("Ignore identifiers", ignoredIdentifiers);
|
||||
ListEditForm form = new ListEditForm("Ignore references", ignoredIdentifiers);
|
||||
return form.getContentPanel();
|
||||
}
|
||||
|
||||
@@ -366,7 +371,8 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
}
|
||||
}
|
||||
|
||||
private void registerUnresolvedReferenceProblem(final PyElement node, final PsiReference reference, HighlightSeverity severity) {
|
||||
private void registerUnresolvedReferenceProblem(@NotNull PyElement node, @NotNull PsiReference reference,
|
||||
@NotNull HighlightSeverity severity) {
|
||||
String description = null;
|
||||
final String text = reference.getElement().getText();
|
||||
TextRange rangeInElement = reference.getRangeInElement();
|
||||
@@ -378,9 +384,30 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
final List<LocalQuickFix> actions = new ArrayList<LocalQuickFix>(2);
|
||||
if (ref_text.length() <= 0) return; // empty text, nothing to highlight
|
||||
final String refname = (element instanceof PyQualifiedExpression) ? ((PyQualifiedExpression)element).getReferencedName() : ref_text;
|
||||
|
||||
final PyQualifiedName canonicalQName = getCanonicalName(reference, myTypeEvalContext);
|
||||
final String canonicalName = canonicalQName != null ? canonicalQName.toString() : null;
|
||||
if (canonicalName != null) {
|
||||
for (String ignored : myIgnoredIdentifiers) {
|
||||
if (ignored.endsWith(END_WILDCARD)) {
|
||||
final String prefix = ignored.substring(0, ignored.length() - END_WILDCARD.length());
|
||||
if (canonicalName.startsWith(prefix)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (canonicalName.equals(ignored)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Legacy non-qualified ignore patterns
|
||||
if (myIgnoredIdentifiers.contains(refname)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (element instanceof PyReferenceExpression) {
|
||||
PyReferenceExpression refex = (PyReferenceExpression)element;
|
||||
if (myIgnoredIdentifiers.contains(refname) || PyNames.COMPARISON_OPERATORS.contains(refname)) {
|
||||
if (PyNames.COMPARISON_OPERATORS.contains(refname)) {
|
||||
return;
|
||||
}
|
||||
if (CythonLanguageDialect.isInsideCythonFile(element) && CythonNames.BUILTINS.contains(text)) {
|
||||
@@ -419,11 +446,6 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
// TODO: mark the node so that future references pointing to it won't result in a error, but in a warning
|
||||
}
|
||||
}
|
||||
if (reference instanceof DocStringParameterReference) {
|
||||
if (myIgnoredIdentifiers.contains(reference.getCanonicalText())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (reference instanceof PsiReferenceEx && description == null) {
|
||||
description = ((PsiReferenceEx)reference).getUnresolvedDescription();
|
||||
}
|
||||
@@ -431,9 +453,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
boolean marked_qualified = false;
|
||||
if (element instanceof PyQualifiedExpression) {
|
||||
final PyQualifiedExpression qexpr = (PyQualifiedExpression)element;
|
||||
if (myIgnoredIdentifiers.contains(ref_text) ||
|
||||
PyNames.COMPARISON_OPERATORS.contains(qexpr.getReferencedName()) ||
|
||||
refname == null) {
|
||||
if (PyNames.COMPARISON_OPERATORS.contains(qexpr.getReferencedName()) || refname == null) {
|
||||
return;
|
||||
}
|
||||
final PyExpression qualifier = qexpr.getQualifier();
|
||||
@@ -487,7 +507,12 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
if (GenerateBinaryStubsFix.isApplicable(reference)) {
|
||||
actions.add(new GenerateBinaryStubsFix(reference));
|
||||
}
|
||||
actions.add(new AddIgnoredIdentifierFix(ref_text));
|
||||
if (canonicalQName != null) {
|
||||
actions.add(new AddIgnoredIdentifierQuickFix(canonicalQName, false));
|
||||
if (canonicalQName.getComponentCount() > 1) {
|
||||
actions.add(new AddIgnoredIdentifierQuickFix(canonicalQName.removeLastComponent(), true));
|
||||
}
|
||||
}
|
||||
addPluginQuickFixes(reference, actions);
|
||||
|
||||
PsiElement point = node.getLastChild(); // usually the identifier at the end of qual ref
|
||||
@@ -515,6 +540,77 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
registerProblem(point, description, hl_type, null, range, actions.toArray(new LocalQuickFix[actions.size()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the canonical qualified name for a reference (even for an unresolved one).
|
||||
*/
|
||||
@Nullable
|
||||
private static PyQualifiedName getCanonicalName(@NotNull PsiReference reference, @NotNull TypeEvalContext context) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (reference instanceof PyOperatorReference && element instanceof PyQualifiedExpression) {
|
||||
final PyExpression receiver = ((PyOperatorReference)reference).getReceiver();
|
||||
if (receiver != null) {
|
||||
final PyType type = receiver.getType(context);
|
||||
if (type instanceof PyClassType) {
|
||||
final String name = ((PyClassType)type).getClassQName();
|
||||
if (name != null) {
|
||||
return PyQualifiedName.fromDottedString(name).append(((PyQualifiedExpression)element).getReferencedName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element instanceof PyReferenceExpression) {
|
||||
final PyReferenceExpression expr = (PyReferenceExpression)element;
|
||||
final PyExpression qualifier = expr.getQualifier();
|
||||
final String exprName = expr.getName();
|
||||
if (exprName != null) {
|
||||
if (qualifier != null) {
|
||||
final PyType type = qualifier.getType(context);
|
||||
if (type instanceof PyClassType) {
|
||||
final String name = ((PyClassType)type).getClassQName();
|
||||
if (name != null) {
|
||||
return PyQualifiedName.fromDottedString(name).append(exprName);
|
||||
}
|
||||
}
|
||||
else if (type instanceof PyModuleType) {
|
||||
final PyFile file = ((PyModuleType)type).getModule();
|
||||
final PyQualifiedName name = QualifiedNameFinder.findCanonicalImportPath(file, element);
|
||||
if (name != null) {
|
||||
return name.append(exprName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
final PsiElement parent = element.getParent();
|
||||
if (parent instanceof PyImportElement) {
|
||||
final PyImportStatementBase importStmt = PsiTreeUtil.getParentOfType(parent, PyImportStatementBase.class);
|
||||
if (importStmt instanceof PyImportStatement) {
|
||||
return PyQualifiedName.fromComponents(exprName);
|
||||
}
|
||||
else if (importStmt instanceof PyFromImportStatement) {
|
||||
final PsiElement resolved = ((PyFromImportStatement)importStmt).resolveImportSource();
|
||||
if (resolved != null) {
|
||||
final PyQualifiedName path = QualifiedNameFinder.findCanonicalImportPath(resolved, element);
|
||||
if (path != null) {
|
||||
return path.append(exprName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
final PyQualifiedName path = QualifiedNameFinder.findCanonicalImportPath(element, element);
|
||||
if (path != null) {
|
||||
return path.append(exprName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (reference instanceof DocStringParameterReference) {
|
||||
return PyQualifiedName.fromDottedString(reference.getCanonicalText());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean ignoreUnresolvedMemberForType(@NotNull PyType qtype, PsiReference reference, String refText) {
|
||||
if (qtype instanceof PyNoneType || PyTypeChecker.isUnknown(qtype)) {
|
||||
// this almost always means that we don't know the type, so don't show an error in this case
|
||||
|
||||
@@ -76,6 +76,20 @@ public class PyOperatorReference extends PyReferenceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyExpression getReceiver() {
|
||||
if (myElement instanceof PyBinaryExpression) {
|
||||
return ((PyBinaryExpression)myElement).getLeftExpression();
|
||||
}
|
||||
else if (myElement instanceof PySubscriptionExpression) {
|
||||
return ((PySubscriptionExpression)myElement).getOperand();
|
||||
}
|
||||
else if (myElement instanceof PyPrefixExpression) {
|
||||
return ((PyPrefixExpression)myElement).getOperand();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String leftToRightOperatorName(String name) {
|
||||
return name.replaceFirst("__([a-z]+)__", "__r$1__");
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.jetbrains.python.inspections.PyInspection;
|
||||
import com.jetbrains.python.inspections.PyUnresolvedReferencesInspection;
|
||||
import com.jetbrains.python.inspections.PyUnusedLocalInspection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
@@ -39,8 +41,9 @@ public class PySuppressInspectionsTest extends PyTestCase {
|
||||
public void testSuppressForStatement() {
|
||||
myFixture.configureByFile("inspections/suppress/suppressForStatement.py");
|
||||
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
|
||||
final IntentionAction suppressAction = myFixture.findSingleIntention("Suppress for statement");
|
||||
assertNotNull(suppressAction);
|
||||
final List<IntentionAction> intentions = myFixture.filterAvailableIntentions("Suppress for statement");
|
||||
assertEquals(2, intentions.size());
|
||||
final IntentionAction suppressAction = intentions.get(0);
|
||||
myFixture.launchAction(suppressAction);
|
||||
myFixture.checkResultByFile("inspections/suppress/suppressForStatement.after.py");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user