mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-11074 Clean up in ImportToImportFromIntention
* Reformat sources * Add missing @Nullable/@NotNull annotations * Add missing final modifiers * Change occasional snake_case identifiers to conventional camelCase
This commit is contained in:
+65
-51
@@ -57,10 +57,11 @@ public class ImportToImportFromIntention implements IntentionAction {
|
||||
private PsiElement myReferee = null;
|
||||
private PyImportElement myImportElement = null;
|
||||
private Collection<PsiReference> myReferences = null;
|
||||
private boolean myHasModuleReference = false; // is anything that resolves to our imported module is just an exact reference to that module
|
||||
private boolean myHasModuleReference = false;
|
||||
// is anything that resolves to our imported module is just an exact reference to that module
|
||||
private int myRelativeLevel; // true if "from ... import"
|
||||
|
||||
public IntentionState(Editor editor, PsiFile file) {
|
||||
public IntentionState(@NotNull Editor editor, @NotNull PsiFile file) {
|
||||
boolean available = false;
|
||||
myImportElement = findImportElement(editor, file);
|
||||
if (myImportElement != null) {
|
||||
@@ -70,10 +71,10 @@ public class ImportToImportFromIntention implements IntentionAction {
|
||||
available = true;
|
||||
}
|
||||
else if (parent instanceof PyFromImportStatement) {
|
||||
PyFromImportStatement from_import = (PyFromImportStatement)parent;
|
||||
final int relative_level = from_import.getRelativeLevel();
|
||||
if (from_import.isValid() && relative_level > 0 && from_import.getImportSource() == null) {
|
||||
myRelativeLevel = relative_level;
|
||||
final PyFromImportStatement fromImport = (PyFromImportStatement)parent;
|
||||
final int relativeLevel = fromImport.getRelativeLevel();
|
||||
if (fromImport.isValid() && relativeLevel > 0 && fromImport.getImportSource() == null) {
|
||||
myRelativeLevel = relativeLevel;
|
||||
available = true;
|
||||
}
|
||||
}
|
||||
@@ -92,25 +93,27 @@ public class ImportToImportFromIntention implements IntentionAction {
|
||||
assert myImportElement != null : "isAvailable() must have returned true, but myImportElement is null";
|
||||
|
||||
// usages of imported name are qualifiers; what they refer to?
|
||||
PyReferenceExpression reference = myImportElement.getImportReferenceExpression();
|
||||
if (reference != null) {
|
||||
myModuleName = PyPsiUtils.toPath(reference);
|
||||
final PyReferenceExpression importReference = myImportElement.getImportReferenceExpression();
|
||||
if (importReference != null) {
|
||||
myModuleName = PyPsiUtils.toPath(importReference);
|
||||
myQualifierName = myImportElement.getVisibleName();
|
||||
myReferee = reference.getReference().resolve();
|
||||
myReferee = importReference.getReference().resolve();
|
||||
myHasModuleReference = false;
|
||||
if (myReferee != null && myModuleName != null && myQualifierName != null) {
|
||||
final Collection<PsiReference> references = new ArrayList<PsiReference>();
|
||||
PsiTreeUtil.processElements(file, new PsiElementProcessor() {
|
||||
public boolean execute(@NotNull PsiElement element) {
|
||||
if (element instanceof PyReferenceExpression && PsiTreeUtil.getParentOfType(element, PyImportElement.class) == null) {
|
||||
PyReferenceExpression ref = (PyReferenceExpression)element;
|
||||
final PyReferenceExpression ref = (PyReferenceExpression)element;
|
||||
if (myQualifierName.equals(PyPsiUtils.toPath(ref))) { // filter out other names that might resolve to our target
|
||||
PsiElement parent_elt = ref.getParent();
|
||||
if (parent_elt instanceof PyQualifiedExpression) { // really qualified by us, not just referencing?
|
||||
PsiElement resolved = ref.getReference().resolve();
|
||||
final PsiElement parentElt = ref.getParent();
|
||||
if (parentElt instanceof PyQualifiedExpression) { // really qualified by us, not just referencing?
|
||||
final PsiElement resolved = ref.getReference().resolve();
|
||||
if (resolved == myReferee) references.add(ref.getReference());
|
||||
}
|
||||
else myHasModuleReference = true;
|
||||
else {
|
||||
myHasModuleReference = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -123,68 +126,68 @@ public class ImportToImportFromIntention implements IntentionAction {
|
||||
|
||||
public void invoke() {
|
||||
assert myImportElement != null : "isAvailable() must have returned true, but myImportElement is null";
|
||||
PyUtil.sure(myImportElement.getImportReferenceExpression());
|
||||
Project project = myImportElement.getProject();
|
||||
sure(myImportElement.getImportReferenceExpression());
|
||||
final Project project = myImportElement.getProject();
|
||||
|
||||
// usages of imported name are qualifiers; what they refer to?
|
||||
try {
|
||||
// remember names and make them drop qualifiers
|
||||
Set<String> used_names = new HashSet<String>();
|
||||
final Set<String> usedNames = new HashSet<String>();
|
||||
for (PsiReference ref : myReferences) {
|
||||
PsiElement elt = ref.getElement();
|
||||
PsiElement parent_elt = elt.getParent();
|
||||
used_names.add(sure(PyUtil.sure(parent_elt).getLastChild()).getText()); // TODO: find ident node more properly
|
||||
final PsiElement elt = ref.getElement();
|
||||
final PsiElement parentElt = elt.getParent();
|
||||
usedNames.add(sure(sure(parentElt).getLastChild()).getText()); // TODO: find ident node more properly
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(elt)) {
|
||||
return;
|
||||
}
|
||||
PsiElement next_elt = elt.getNextSibling();
|
||||
if (next_elt != null && ".".equals(next_elt.getText())) next_elt.delete();
|
||||
final PsiElement nextElt = elt.getNextSibling();
|
||||
if (nextElt != null && ".".equals(nextElt.getText())) nextElt.delete();
|
||||
elt.delete();
|
||||
}
|
||||
|
||||
// create a separate import stmt for the module
|
||||
PsiElement importer = myImportElement.getParent();
|
||||
PyStatement import_statement;
|
||||
PyImportElement[] import_elements;
|
||||
final PsiElement importer = myImportElement.getParent();
|
||||
final PyStatement importStatement;
|
||||
final PyImportElement[] importElements;
|
||||
if (importer instanceof PyImportStatement) {
|
||||
import_statement = (PyImportStatement)importer;
|
||||
import_elements = ((PyImportStatement)import_statement).getImportElements();
|
||||
importStatement = (PyImportStatement)importer;
|
||||
importElements = ((PyImportStatement)importStatement).getImportElements();
|
||||
}
|
||||
else if (importer instanceof PyFromImportStatement) {
|
||||
import_statement = (PyFromImportStatement)importer;
|
||||
import_elements = ((PyFromImportStatement)import_statement).getImportElements();
|
||||
importStatement = (PyFromImportStatement)importer;
|
||||
importElements = ((PyFromImportStatement)importStatement).getImportElements();
|
||||
}
|
||||
else {
|
||||
throw new IncorrectOperationException("Not an import at all");
|
||||
}
|
||||
PyElementGenerator generator = PyElementGenerator.getInstance(project);
|
||||
StringBuilder builder = new StringBuilder("from ").append(getDots()).append(myModuleName).append(" import ");
|
||||
builder.append(StringUtil.join(used_names, ", "));
|
||||
PyFromImportStatement from_import_stmt =
|
||||
final PyElementGenerator generator = PyElementGenerator.getInstance(project);
|
||||
final StringBuilder builder = new StringBuilder("from ").append(getDots()).append(myModuleName).append(" import ");
|
||||
builder.append(StringUtil.join(usedNames, ", "));
|
||||
final PyFromImportStatement fromImportStatement =
|
||||
generator.createFromText(LanguageLevel.getDefault(), PyFromImportStatement.class, builder.toString());
|
||||
PsiElement parent = import_statement.getParent();
|
||||
final PsiElement parent = importStatement.getParent();
|
||||
sure(parent);
|
||||
sure(parent.isValid());
|
||||
if (import_elements.length == 1) {
|
||||
if (importElements.length == 1) {
|
||||
if (myHasModuleReference) {
|
||||
parent.addAfter(from_import_stmt, import_statement); // add 'import from': we need the module imported as is
|
||||
parent.addAfter(fromImportStatement, importStatement); // add 'import from': we need the module imported as is
|
||||
}
|
||||
else { // replace entire existing import
|
||||
sure(parent.getNode()).replaceChild(sure(import_statement.getNode()), sure(from_import_stmt.getNode()));
|
||||
sure(parent.getNode()).replaceChild(sure(importStatement.getNode()), sure(fromImportStatement.getNode()));
|
||||
// import_statement.replace(from_import_stmt);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!myHasModuleReference) {
|
||||
// cut the module out of import, add a from-import.
|
||||
for (PyImportElement pie : import_elements) {
|
||||
for (PyImportElement pie : importElements) {
|
||||
if (pie == myImportElement) {
|
||||
PyUtil.removeListNode(pie);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
parent.addAfter(from_import_stmt, import_statement);
|
||||
parent.addAfter(fromImportStatement, importStatement);
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException ignored) {
|
||||
@@ -193,18 +196,24 @@ public class ImportToImportFromIntention implements IntentionAction {
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public String getText() {
|
||||
String module_name = "?";
|
||||
String moduleName = "?";
|
||||
if (myImportElement != null) {
|
||||
PyReferenceExpression reference = myImportElement.getImportReferenceExpression();
|
||||
if (reference != null) module_name = PyPsiUtils.toPath(reference);
|
||||
final PyReferenceExpression reference = myImportElement.getImportReferenceExpression();
|
||||
if (reference != null) {
|
||||
moduleName = PyPsiUtils.toPath(reference);
|
||||
}
|
||||
}
|
||||
return PyBundle.message("INTN.convert.to.from.$0.import.$1", getDots()+module_name, "...");
|
||||
return PyBundle.message("INTN.convert.to.from.$0.import.$1", getDots() + moduleName, "...");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getDots() {
|
||||
String dots = "";
|
||||
for (int i=0; i<myRelativeLevel; i+=1) dots += "."; // this generally runs 1-2 times, so it's cheaper than allocating a StringBuilder
|
||||
for (int i = 0; i < myRelativeLevel; i += 1) {
|
||||
dots += "."; // this generally runs 1-2 times, so it's cheaper than allocating a StringBuilder
|
||||
}
|
||||
return dots;
|
||||
}
|
||||
}
|
||||
@@ -222,10 +231,15 @@ public class ImportToImportFromIntention implements IntentionAction {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyImportElement findImportElement(Editor editor, PsiFile file) {
|
||||
PyImportElement import_elt = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyImportElement.class);
|
||||
if (import_elt != null && import_elt.isValid()) return import_elt;
|
||||
else return null;
|
||||
private static PyImportElement findImportElement(@NotNull Editor editor, @NotNull PsiFile file) {
|
||||
final PsiElement elementAtCaret = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
final PyImportElement importElement = PsiTreeUtil.getParentOfType(elementAtCaret, PyImportElement.class);
|
||||
if (importElement != null && importElement.isValid()) {
|
||||
return importElement;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
@@ -233,7 +247,7 @@ public class ImportToImportFromIntention implements IntentionAction {
|
||||
return false;
|
||||
}
|
||||
|
||||
IntentionState state = new IntentionState(editor, file);
|
||||
final IntentionState state = new IntentionState(editor, file);
|
||||
if (state.isAvailable()) {
|
||||
myText = state.getText();
|
||||
return true;
|
||||
@@ -242,7 +256,7 @@ public class ImportToImportFromIntention implements IntentionAction {
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
IntentionState state = new IntentionState(editor, file);
|
||||
final IntentionState state = new IntentionState(editor, file);
|
||||
state.invoke();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user