Merge branch 'master' of git.labs.intellij.net:idea/ultimate

This commit is contained in:
Dmitry Cheryasov
2010-06-16 20:18:23 +03:00
13 changed files with 171 additions and 189 deletions
+3
View File
@@ -40,6 +40,9 @@ class TeamcityTestResult(TestResult):
self.messages.testFailed(self.getTestName(test),
message='Failure', details=err)
def addSkip(self, test, reason):
self.messages.testIgnored(self.getTestName(test), message=reason)
def startTest(self, test):
setattr(test, "startTime", datetime.datetime.now())
self.messages.testStarted(self.getTestName(test), location="python_uttestid://" + str(test.id()))
+5 -20
View File
@@ -33,9 +33,6 @@
<completion.contributor language="Python" implementationClass="com.jetbrains.python.codeInsight.PySpecialMethodNamesCompletionContributor"/>
<lang.tokenSeparatorGenerator language="Python" implementationClass="com.jetbrains.python.PyTokenSeparatorGenerator"/>
<lang.elementManipulator forClass="com.jetbrains.python.psi.PyReferenceExpression" implementationClass="com.jetbrains.python.psi.impl.PyReferenceExpressionManipulator"/>
<!--
<com.intellij.inspectionToolsFactory implementation="com.jetbrains.python.inspections.PythonPyInspectionToolProvider"/>
-->
<projectService serviceInterface="com.jetbrains.python.psi.PyElementGenerator"
serviceImplementation="com.jetbrains.python.psi.impl.PyElementGeneratorImpl"/>
@@ -64,9 +61,6 @@
<configurationType implementation="com.jetbrains.python.testing.pytest.PyTestRunConfigurationType"/>
<configurationProducer implementation="com.jetbrains.python.testing.pytest.PyTestConfigurationProducer"/>
<applicationService serviceInterface="com.jetbrains.python.JythonManager"
serviceImplementation="com.jetbrains.python.JythonManager"/>
<referenceImporter implementation="com.jetbrains.python.validation.PythonReferenceImporter"/>
<codeInsight.lineMarkerProvider language="Python" implementationClass="com.jetbrains.python.codeInsight.PyLineMarkerProvider"/>
<definitionsSearch implementation="com.jetbrains.python.psi.search.PyDefinitionsSearch"/>
@@ -74,59 +68,50 @@
<typeHierarchyProvider language="Python" implementationClass="com.jetbrains.python.hierarchy.PyTypeHierachyProvider"/>
<highlightUsagesHandlerFactory implementation="com.jetbrains.python.codeInsight.highlighting.PyHighlightExitPointsHandlerFactory"/>
<intentionAction factoryClass="com.jetbrains.python.PyExtensionFactory"
factoryArgument="intentions/PyDemorganIntention.py">
<className>PyDemorganIntention</className>
<category>Python</category>
<descriptionDirectoryName>PyDemorganIntention</descriptionDirectoryName>
</intentionAction>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.ImportToImportFromIntention</className>
<category>Python</category>
<descriptionDirectoryName>ImportToImportFromIntention</descriptionDirectoryName>
</intentionAction>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.ImportFromToImportIntention</className>
<category>Python</category>
<descriptionDirectoryName>ImportFromToImportIntention</descriptionDirectoryName>
</intentionAction>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.ImportToggleAliasIntention</className>
<category>Python</category>
<descriptionDirectoryName>ImportToggleAliasIntention</descriptionDirectoryName>
</intentionAction>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.PySplitIfIntention</className>
<category>Python</category>
<descriptionDirectoryName>PySplitIfIntention</descriptionDirectoryName>
</intentionAction>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.PyNegateComparisonIntention</className>
<category>Python</category>
<descriptionDirectoryName>PyNegateComparisonIntention</descriptionDirectoryName>
</intentionAction>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.PyStringConcatenationToFormatIntention</className>
<category>Python</category>
<descriptionDirectoryName>PyStringConcatenationToFormatIntention</descriptionDirectoryName>
</intentionAction>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.ConvertFormatOperatorToMethodIntention</className>
<category>Python</category>
<descriptionDirectoryName>ConvertFormatOperatorToMethodIntention</descriptionDirectoryName>
</intentionAction>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.PyFlipComparisonIntention</className>
<category>Python</category>
<descriptionDirectoryName>PyFlipComparisonIntention</descriptionDirectoryName>
</intentionAction>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.PyDemorganIntention</className>
<category>Python</category>
</intentionAction>
<stubElementTypeHolder class="com.jetbrains.python.PyElementTypes"/>
@@ -1,68 +0,0 @@
package com.jetbrains.python;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.PathUtil;
import org.jetbrains.annotations.NonNls;
import org.python.core.*;
import org.python.util.PythonInterpreter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* @author yole
*/
public class JythonManager {
private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.JythonManager");
public static JythonManager getInstance() {
return ServiceManager.getService(JythonManager.class);
}
private final PythonInterpreter myInterpreter;
public JythonManager() {
@NonNls Properties postProperties = new Properties();
postProperties.put("python.cachedir.skip", "true");
String pythonScriptPath = findPythonScriptPath();
postProperties.put("python.path", pythonScriptPath);
LOG.info("Loading Python scripts from " + pythonScriptPath);
PySystemState.initialize(PySystemState.getBaseProperties(), postProperties, new String[] { "" });
myInterpreter = new PythonInterpreter();
}
private String findPythonScriptPath() {
@NonNls String classRoot = PathUtil.getJarPathForClass(getClass());
if (classRoot.endsWith(".jar")) {
return classRoot;
}
// compiled classes
File f = new File(new File(classRoot).getParent(), "python-py");
if (f.exists()) {
return f.getPath();
}
throw new RuntimeException("Can't figure out Python script path: " + classRoot);
}
public void execScriptFromResource(@NonNls String resourcePath) {
final InputStream stream = getClass().getClassLoader().getResourceAsStream(resourcePath);
try {
myInterpreter.execfile(stream);
}
finally {
try {
stream.close();
}
catch (IOException e) {
LOG.error(e);
}
}
}
public PyObject eval(@NonNls final String code) {
return myInterpreter.eval(code);
}
}
@@ -1,20 +0,0 @@
package com.jetbrains.python;
import com.intellij.openapi.extensions.ExtensionFactory;
import com.intellij.openapi.diagnostic.Logger;
import org.python.core.PyObject;
/**
* @author yole
*/
public class PyExtensionFactory implements ExtensionFactory {
private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.PyExtensionFactory");
public Object createInstance(final String factoryArgument, final String implementationClass) {
LOG.info("Instantiating Jython class " + implementationClass + " from script " + factoryArgument);
JythonManager jythonManager = JythonManager.getInstance();
jythonManager.execScriptFromResource(factoryArgument);
final PyObject object = jythonManager.eval(implementationClass + "()");
return object.__tojava__(Object.class);
}
}
@@ -92,9 +92,26 @@ public class PyCodeFragmentUtil {
}
// If we see more than 1 outer instruction, controlflow is interrupted
if (outerInstructions.size() > 1){
if (outerInstructions.size() > 2){
throw new CannotCreateCodeFragmentException(PyBundle.message("refactoring.extract.method.error.cannot.perform.refactoring.when.execution.flow.is.interrupted"));
}
if (outerInstructions.size() == 2){
boolean errorFound = true;
for (Instruction outerInstruction : outerInstructions) {
// Here we check control flow when for statement content is beeing extracted
if (outerInstruction instanceof ReadWriteInstruction &&
PyForStatementNavigator.getPyForStatementByIterable(outerInstruction.getElement())!=null) {
// In case when return instruction is inside
if (!returnInstructionInside){
errorFound = false;
break;
}
}
}
if (errorFound){
throw new CannotCreateCodeFragmentException(PyBundle.message("refactoring.extract.method.error.cannot.perform.refactoring.when.execution.flow.is.interrupted"));
}
}
// Building code fragment
final PyCodeFragmentBuilder builder = new PyCodeFragmentBuilder(owner, start, end);
@@ -0,0 +1,123 @@
package com.jetbrains.python.codeInsight.intentions;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class PyDemorganIntention extends BaseIntentionAction {
@NotNull
@Override
public String getText() {
return "DeMorgan Law";
}
@NotNull
@Override
public String getFamilyName() {
return "DeMorgan Law";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
PyBinaryExpression expression = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyBinaryExpression.class);
if (expression != null) {
PyElementType op = expression.getOperator();
if (op == PyTokenTypes.AND_KEYWORD || op == PyTokenTypes.OR_KEYWORD) {
return true;
}
}
return false;
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyBinaryExpression expression = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()),
PyBinaryExpression.class);
PyElementType op = expression.getOperator();
String converted = convertConjunctionExpression(expression, op);
replaceExpression(converted, expression);
}
private static void replaceExpression(String newExpression, PyBinaryExpression expression) {
PsiElement expressionToReplace = expression;
String expString = "not(" + newExpression + ')';
PsiElement parent = expression.getParent().getParent();
if (isNegation(parent)) {
expressionToReplace = parent;
expString = newExpression;
}
PyElementGenerator generator = PyElementGenerator.getInstance(expression.getProject());
PyExpression newCall = generator.createExpressionFromText(expString);
PsiElement insertedElement = expressionToReplace.replace(newCall);
// codeStyleManager = expression.getManager().getCodeStyleManager()
// TODO codeStyleManager.reformat(insertedElement)
}
private static String convertConjunctionExpression(PyBinaryExpression exp, PyElementType tokenType) {
PyExpression lhs = exp.getLeftExpression();
String lhsText, rhsText;
if (isConjunctionExpression(lhs, tokenType)) {
lhsText = convertConjunctionExpression((PyBinaryExpression)lhs, tokenType);
}
else {
lhsText = convertLeafExpression(lhs);
}
PyExpression rhs = exp.getRightExpression();
if (isConjunctionExpression(rhs, tokenType)) {
rhsText = convertConjunctionExpression((PyBinaryExpression)rhs, tokenType);
}
else {
rhsText = convertLeafExpression(rhs);
}
String flippedConjunction = (tokenType == PyTokenTypes.AND_KEYWORD) ? " or " : " and ";
return lhsText + flippedConjunction + rhsText;
}
private static String convertLeafExpression(PyExpression condition) {
if (isNegation(condition)) {
PyExpression negated = getNegated(condition);
if (negated == null) {
return "";
}
return negated.getText();
}
else {
return "not " + condition.getText();
}
}
private static PyExpression getNegated(PyExpression expression) {
PyExpression operand = ((PyPrefixExpression)expression).getOperand();
return operand; // TODO strip ()
}
private static boolean isConjunctionExpression(PyExpression expression, PyElementType tokenType) {
if (expression instanceof PyBinaryExpression) {
PyElementType operator = ((PyBinaryExpression) expression).getOperator();
return operator == tokenType;
}
return false;
}
private static boolean isNegation(PsiElement expression) {
if (!(expression instanceof PyPrefixExpression)) {
return false;
}
PyElementType op = ((PyPrefixExpression)expression).getOperationSign();
return op == PyTokenTypes.NOT_KEYWORD;
}
}
@@ -74,18 +74,18 @@ public class PyDebugValue extends XValue {
}
// todo: pass StringBuilder to recursive calls
public String getQualifiedExpression() {
public String getEvaluationExpression() {
if (myParent == null) {
return getTempName();
}
else if ("list".equals(myParent.getType()) || "tuple".equals(myParent.getType())) {
return new StringBuilder().append(myParent.getQualifiedExpression()).append('[').append(myName).append(']').toString();
return new StringBuilder().append(myParent.getEvaluationExpression()).append('[').append(myName).append(']').toString();
}
else if ("dict".equals(myParent.getType())) {
return new StringBuilder().append(myParent.getQualifiedExpression()).append("['").append(myName).append("']").toString();
return new StringBuilder().append(myParent.getEvaluationExpression()).append("['").append(myName).append("']").toString();
}
else {
return new StringBuilder().append(myParent.getQualifiedExpression()).append('.').append(myName).toString();
return new StringBuilder().append(myParent.getEvaluationExpression()).append('.').append(myName).toString();
}
}
@@ -1,71 +0,0 @@
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.InspectionToolsFactory;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.InspectionTool;
import com.intellij.codeInspection.ex.InspectionToolRegistrar;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.util.Function;
import com.jetbrains.python.JythonManager;
import org.jetbrains.annotations.Nullable;
import org.python.core.PyList;
import org.python.core.PyObject;
import java.util.HashSet;
import java.util.Set;
/**
* @author yole
*/
public class PythonPyInspectionToolProvider implements InspectionToolsFactory {
private final JythonManager myManager;
public static PythonPyInspectionToolProvider getInstance() {
return ApplicationManager.getApplication().getComponent(PythonPyInspectionToolProvider.class);
}
private final InspectionToolRegistrar myRegistrar;
private final Set<String> myShortNames = new HashSet<String>();
public PythonPyInspectionToolProvider(final InspectionToolRegistrar registrar, final JythonManager jythonManager) {
myRegistrar = registrar;
myManager = jythonManager;
}
@Nullable
public LocalInspectionTool createLocalInspectionTool(final String inspectionToolName) {
try {
final PyObject object = myManager.eval(inspectionToolName + "()");
final Object o = object.__tojava__(LocalInspectionTool.class);
return (LocalInspectionTool)o;
}
catch (Exception e) {
return null;
}
}
public InspectionProfileEntry[] createTools() {
myRegistrar.registerInspectionToolProvider(new Function<String, InspectionTool>() {
@Nullable
public InspectionTool fun(String shortName) {
final LocalInspectionTool tool = myShortNames.contains(shortName) ? createLocalInspectionTool(shortName) : null;
return tool != null ? new LocalInspectionToolWrapper(tool) : null;
}
});
myManager.execScriptFromResource("inspections/inspections.py");
final PyList pyList = (PyList) myManager.eval("getAllInspections()");
int len = pyList.__len__();
final InspectionProfileEntry[] profileEntries = new InspectionProfileEntry[len];
for(int i=0; i<len; i++) {
final String inspectionToolName = pyList.__getitem__(i).toString();
profileEntries[i] = createLocalInspectionTool(inspectionToolName);
myShortNames.add(inspectionToolName);
}
return profileEntries;
}
}
@@ -47,7 +47,7 @@ public class PyExtractMethodUtil {
final CodeFragment fragment,
final PsiElement statement1,
final PsiElement statement2) {
if (!fragment.getOutputVariables().isEmpty() && fragment.isReturnInstructonInside()) {
if (!fragment.getOutputVariables().isEmpty() && fragment.isReturnInstructionInside()) {
CommonRefactoringUtil.showErrorHint(project, editor,
"Cannot perform refactoring from expression with local variables modifications and return instructions inside code fragment",
RefactoringBundle.message("error.title"), "refactoring.extractMethod");
@@ -79,7 +79,7 @@ public class PyExtractMethodUtil {
// Generating call element
final StringBuilder builder = new StringBuilder();
if (fragment.isReturnInstructonInside()) {
if (fragment.isReturnInstructionInside()) {
builder.append("return ");
}
if (isMethod){
@@ -157,7 +157,7 @@ public class PyExtractMethodUtil {
return;
}
if (fragment.isReturnInstructonInside()){
if (fragment.isReturnInstructionInside()){
CommonRefactoringUtil.showErrorHint(project, editor,
"Cannot extract method with return instructions inside code fragment",
RefactoringBundle.message("error.title"), "refactoring.extractMethod");
@@ -186,7 +186,7 @@ public class PyExtractMethodUtil {
// Generating call element
final StringBuilder builder = new StringBuilder();
if (fragment.isReturnInstructonInside()) {
if (fragment.isReturnInstructionInside()) {
builder.append("return ");
}
if (isMethod){
@@ -352,6 +352,7 @@ public class PythonSdkType extends SdkType {
public void run(@NotNull final ProgressIndicator indicator) {
try {
final SdkModificator sdkModificator = sdk.getSdkModificator();
sdkModificator.removeAllRoots();
setupSdkPaths(sdkModificator, indicator);
//sdkModificator.commitChanges() must happen outside, in dispatch thread.
sdkModificatorRef.set(sdkModificator);
@@ -0,0 +1,7 @@
class Conference(object):
def __init__(self):
self.talks = []
def getTalkAt(self, hour):
for start, end, name in self.talks:
<selection>if hour >= start and hour < end: return name</selection>
@@ -70,7 +70,7 @@ public class PyCodeFragmentTest extends LightMarkedTestCase {
final StringBuffer buffer = new StringBuffer();
try {
final CodeFragment fragment = PyCodeFragmentUtil.createCodeFragment((ScopeOwner)context, startElement, endElement);
if (fragment.isReturnInstructonInside()) {
if (fragment.isReturnInstructionInside()) {
buffer.append("Return instruction inside found").append("\n");
}
buffer.append("In:\n");
@@ -126,4 +126,9 @@ public class PyExtractMethodTest extends LightMarkedTestCase {
public void testClass() throws Throwable {
doTest("context/class.before.py", "bar", "context/class.after.py");
}
public void testConditionalReturn() throws Throwable {
doTest("conditionalreturn.before.py", "bar", "Cannot perform refactoring when execution flow is interrupted");
}
}