/** * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package org.python.pydev.core.docutils; import org.eclipse.jface.text.IDocument; import org.python.pydev.core.ICodeCompletionASTManager.ImportInfo; public class ImportsSelection { /** * @param doc * @param documentOffset * @return the import info or null if none is available */ public static ImportInfo getImportsTipperStr(String trimmedLine, boolean returnEvenEmpty) { String importMsg = ""; if (!trimmedLine.startsWith("from") && !trimmedLine.startsWith("import")) { return new ImportInfo("", false, false); // it is not an import } int fromIndex = trimmedLine.indexOf("from"); int importIndex = trimmedLine.indexOf("import"); boolean foundImportOnArray = false; boolean foundFromOnArray = false; // check if we have a from or an import. if (fromIndex != -1 || importIndex != -1) { trimmedLine = trimmedLine.replaceAll("#.*", ""); // remove comments String[] strings = trimmedLine.split(" "); if (fromIndex != -1 && importIndex == -1) { if (strings.length > 2) { // user has spaces as in 'from xxx uuu' return new ImportInfo("", foundImportOnArray, foundFromOnArray); } } for (int i = 0; i < strings.length; i++) { if (strings[i].equals("import")) { foundImportOnArray = true; } if (strings[i].equals("from")) { foundFromOnArray = true; } if (strings[i].equals("from") == false && strings[i].equals("import") == false) { if (importMsg.length() != 0) { importMsg += '.'; } importMsg += strings[i]; } // now, if we have a from xxx import something, we'll always // want to return only the xxx if (fromIndex != -1 && importIndex == -1 && (foundImportOnArray || i == strings.length - 1)) { if (importMsg.length() == 0) { return ImportsSelection.doExistingOrEmptyReturn(returnEvenEmpty, importMsg, foundImportOnArray, foundFromOnArray); } if (importMsg.startsWith(".")) { return new ImportInfo(importMsg, foundImportOnArray, foundFromOnArray); } if (importMsg.indexOf(".") == -1) { return ImportsSelection.doExistingOrEmptyReturn(returnEvenEmpty, importMsg, foundImportOnArray, foundFromOnArray); } return new ImportInfo(importMsg.substring(0, importMsg.lastIndexOf(".") + 1), foundImportOnArray, foundFromOnArray); } } if (fromIndex != -1 && importIndex != -1) { if (strings.length == 3) { importMsg += '.'; } } } else { return new ImportInfo("", foundImportOnArray, foundFromOnArray); } if (importMsg.indexOf(".") == -1) { // we have only import fff or from iii (so, we're going for all // imports). return ImportsSelection.doExistingOrEmptyReturn(returnEvenEmpty, importMsg, foundImportOnArray, foundFromOnArray); } if (fromIndex == -1 && importMsg.indexOf(',') != -1) { // we have something like import xxx, yyy, ... importMsg = importMsg.substring(importMsg.lastIndexOf(',') + 1, importMsg.length()); if (importMsg.startsWith(".")) { importMsg = importMsg.substring(1); } int j = importMsg.lastIndexOf('.'); if (j != -1) { importMsg = importMsg.substring(0, j); return new ImportInfo(importMsg, foundImportOnArray, foundFromOnArray); } else { return ImportsSelection.doExistingOrEmptyReturn(returnEvenEmpty, importMsg, foundImportOnArray, foundFromOnArray); } } else { // now, we may still have something like 'unittest.test,' or // 'unittest.test.,' // so, we have to remove this comma (s). int i; boolean removed = false; while ((i = importMsg.indexOf(',')) != -1) { if (importMsg.charAt(i - 1) == '.') { int j = importMsg.lastIndexOf('.'); importMsg = importMsg.substring(0, j); } int j = importMsg.lastIndexOf('.'); importMsg = importMsg.substring(0, j); removed = true; } // if it is something like aaa.sss.bb : removes the bb because it is // the qualifier // if it is something like aaa.sss. : removes only the last point if (!removed && importMsg.length() > 0 && importMsg.indexOf('.') != -1) { importMsg = importMsg.substring(0, importMsg.lastIndexOf('.')); } return new ImportInfo(importMsg, foundImportOnArray, foundFromOnArray); } } public static ImportInfo getImportsTipperStr(IDocument doc, int documentOffset) { PySelection.DocIterator iterator = new PySelection.DocIterator(false, new PySelection(doc, documentOffset)); StringBuffer buffer = new StringBuffer(); //it may still be a multiline-import... to check that, we have to go backward in the document and see if the //lines keep ending with a \ from the import line or if the import line has a ( boolean expectContinue = false; boolean allEndingWithSlash = true; boolean found = false; while (iterator.hasNext()) { String line = ParsingUtils.removeComments(iterator.next()); String trimmedLine = line.trim(); if (PySelection.isImportLine(trimmedLine)) { if (expectContinue) { boolean correct = false; if (trimmedLine.indexOf('(') != -1) { correct = true; } if (trimmedLine.endsWith("\\")) { if (allEndingWithSlash) { correct = true; } } if (!correct) { break; } } //that's it, we found it! found = true; buffer.insert(0, trimmedLine); break; } else { if (expectContinue) { if (trimmedLine.indexOf(')') != -1) { break; } if (allEndingWithSlash && trimmedLine.length() > 0) { char c = trimmedLine.charAt(trimmedLine.length() - 1); if (c != '\\' && c != ',' && c != '(') { break; //let's keep the analysis to lines that end with , ( \ (because otherwise it can be time-consuming) } if (c != '\\') { allEndingWithSlash = false; } } else if (trimmedLine.length() == 0) { //if some empty line was found, stop the analysis. break; } } expectContinue = true; buffer.insert(0, line); } } if (!found) { return new ImportInfo("", false, false); // it is not an import } return getImportsTipperStr(buffer.toString(), true); } private static ImportInfo doExistingOrEmptyReturn(final boolean returnEvenEmpty, final String importMsg, final boolean foundImportOnArray, final boolean foundFromOnArray) { if (returnEvenEmpty || importMsg.trim().length() > 0) { return new ImportInfo(" ", foundImportOnArray, foundFromOnArray); } else { return new ImportInfo("", foundImportOnArray, foundFromOnArray); } } }