diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml index 742db29c76fd..4e643e050592 100644 --- a/python/src/META-INF/python-core.xml +++ b/python/src/META-INF/python-core.xml @@ -76,7 +76,7 @@ - + diff --git a/python/src/com/jetbrains/python/codeInsight/KeywordTypedHandler.java b/python/src/com/jetbrains/python/codeInsight/PyKeywordTypedHandler.java similarity index 94% rename from python/src/com/jetbrains/python/codeInsight/KeywordTypedHandler.java rename to python/src/com/jetbrains/python/codeInsight/PyKeywordTypedHandler.java index 5e3e6ca68b1d..3bf094dcb2c8 100644 --- a/python/src/com/jetbrains/python/codeInsight/KeywordTypedHandler.java +++ b/python/src/com/jetbrains/python/codeInsight/PyKeywordTypedHandler.java @@ -30,7 +30,7 @@ import com.jetbrains.python.psi.PyStringLiteralExpression; * User: dcheryasov * Date: May 29, 2009 4:42:03 AM */ -public class KeywordTypedHandler extends TypedHandlerDelegate { +public class PyKeywordTypedHandler extends TypedHandlerDelegate { @Override public Result beforeCharTyped(char character, Project project, Editor editor, PsiFile file, FileType fileType) { if (!(fileType instanceof PythonFileType)) return Result.CONTINUE; // else we'd mess up with other file types! @@ -51,7 +51,7 @@ public class KeywordTypedHandler extends TypedHandlerDelegate { editor.getCaretModel().moveToOffset(offset + 1); // overtype, that is, jump over return Result.STOP; } - UnindentingInsertHandler.unindentAsNeeded(project, editor, file); + PyUnindentingInsertHandler.unindentAsNeeded(project, editor, file); } return Result.CONTINUE; // the default diff --git a/python/src/com/jetbrains/python/codeInsight/PyKeywords.java b/python/src/com/jetbrains/python/codeInsight/PyKeywords.java new file mode 100644 index 000000000000..458715fbf6c4 --- /dev/null +++ b/python/src/com/jetbrains/python/codeInsight/PyKeywords.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.codeInsight; + +/** + * @author traff + */ +public class PyKeywords { + public static final String DEF = "def"; + public static final String CLASS = "class"; + + public static final String IF = "if"; + public static final String ELSE = "else"; + public static final String ELIF = "elif"; + + public static final String TRY = "try"; + public static final String EXCEPT = "except"; + public static final String FINALLY = "finally"; + + public static final String WHILE = "while"; + + public static final String FOR = "for"; + public static final String WITH = "with"; + public static final String AS = "as"; + + public static final String ASSERT = "assert"; + public static final String DEL = "del"; + public static final String EXEC = "exec"; + public static final String FROM = "from"; + public static final String IMPORT = "import"; + public static final String RAISE = "raise"; + public static final String PRINT = "print"; + public static final String BREAK = "break"; + public static final String CONTINUE = "continue"; + public static final String GLOBAL = "global"; + public static final String RETURN = "return"; + public static final String YIELD = "yield"; + public static final String NONLOCAL = "nonlocal"; + + public static final String AND = "and"; + public static final String OR = "or"; + public static final String IS = "is"; + public static final String IN = "in"; + public static final String NOT = "not"; + + public static final String LAMBDA = "lambda"; + + public static final String TRUE = "True"; + public static final String FALSE = "False"; + public static final String NONE = "None"; +} diff --git a/python/src/com/jetbrains/python/codeInsight/UnindentingInsertHandler.java b/python/src/com/jetbrains/python/codeInsight/PyUnindentingInsertHandler.java similarity index 79% rename from python/src/com/jetbrains/python/codeInsight/UnindentingInsertHandler.java rename to python/src/com/jetbrains/python/codeInsight/PyUnindentingInsertHandler.java index cd2902666acb..c95a7aa4f203 100644 --- a/python/src/com/jetbrains/python/codeInsight/UnindentingInsertHandler.java +++ b/python/src/com/jetbrains/python/codeInsight/PyUnindentingInsertHandler.java @@ -34,10 +34,10 @@ import com.jetbrains.python.psi.PyTryExceptStatement; * User: dcheryasov * Date: Mar 2, 2010 6:48:40 PM */ -public class UnindentingInsertHandler implements InsertHandler { - public final static UnindentingInsertHandler INSTANCE = new UnindentingInsertHandler(); +public class PyUnindentingInsertHandler implements InsertHandler { + public final static PyUnindentingInsertHandler INSTANCE = new PyUnindentingInsertHandler(); - private UnindentingInsertHandler() { + private PyUnindentingInsertHandler() { } public void handleInsert(InsertionContext context, PythonLookupElement item) { @@ -56,7 +56,9 @@ public class UnindentingInsertHandler implements InsertHandler= text.length()) offset = text.length() - 1; + if (offset >= text.length()) { + offset = text.length() - 1; + } int line_start_offset = document.getLineStartOffset(document.getLineNumber(offset)); int nonspace_offset = findBeginning(line_start_offset, text); @@ -64,26 +66,26 @@ public class UnindentingInsertHandler implements InsertHandler parentClass = null; - int last_offset = nonspace_offset + "finally".length(); // the longest of all + int last_offset = nonspace_offset + PyKeywords.FINALLY.length(); // the longest of all if (last_offset > offset) last_offset = offset; int local_length = last_offset - nonspace_offset + 1; if (local_length > 0) { String piece = text.subSequence(nonspace_offset, last_offset+1).toString(); - final int else_len = "else".length(); + final int else_len = PyKeywords.ELSE.length(); if (local_length >= else_len) { - if ((piece.startsWith("else") || piece.startsWith("elif")) && (else_len == piece.length() || piece.charAt(else_len) < 'a' || piece.charAt(else_len) > 'z')) { + if ((piece.startsWith(PyKeywords.ELSE) || piece.startsWith(PyKeywords.ELIF)) && (else_len == piece.length() || piece.charAt(else_len) < 'a' || piece.charAt(else_len) > 'z')) { parentClass = PyStatementWithElse.class; } } - final int except_len = "except".length(); + final int except_len = PyKeywords.EXCEPT.length(); if (local_length >= except_len) { - if (piece.startsWith("except") && (except_len == piece.length() || piece.charAt(except_len) < 'a' || piece.charAt(except_len) > 'z')) { + if (piece.startsWith(PyKeywords.EXCEPT) && (except_len == piece.length() || piece.charAt(except_len) < 'a' || piece.charAt(except_len) > 'z')) { parentClass = PyTryExceptStatement.class; } } - final int finally_len = "finally".length(); + final int finally_len = PyKeywords.FINALLY.length(); if (local_length >= finally_len) { - if (piece.startsWith("finally") && (finally_len == piece.length() || piece.charAt(finally_len) < 'a' || piece.charAt(finally_len) > 'z')) { + if (piece.startsWith(PyKeywords.FINALLY) && (finally_len == piece.length() || piece.charAt(finally_len) < 'a' || piece.charAt(finally_len) > 'z')) { parentClass = PyTryExceptStatement.class; } } diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java index 44ef899aeff9..6d7202457e83 100644 --- a/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java +++ b/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java @@ -33,7 +33,8 @@ import com.intellij.util.ProcessingContext; import com.jetbrains.python.PyNames; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.PythonLanguage; -import com.jetbrains.python.codeInsight.UnindentingInsertHandler; +import com.jetbrains.python.codeInsight.PyKeywords; +import com.jetbrains.python.codeInsight.PyUnindentingInsertHandler; import com.jetbrains.python.documentation.doctest.PyDocstringFile; import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NonNls; @@ -286,9 +287,9 @@ public class PyKeywordCompletionContributor extends CompletionContributor { psiElement() .inside(PyConditionalStatementPart.class) .andOr( - psiElement().afterLeaf(psiElement().withText("if")), - psiElement().afterLeaf(psiElement().withText("elif")), - psiElement().afterLeaf(psiElement().withText("while")) + psiElement().afterLeaf(psiElement().withText(PyKeywords.IF)), + psiElement().afterLeaf(psiElement().withText(PyKeywords.ELIF)), + psiElement().afterLeaf(psiElement().withText(PyKeywords.WHILE)) ); private static final PsiElementPattern.Capture IN_IMPORT_STMT = @@ -378,8 +379,8 @@ public class PyKeywordCompletionContributor extends CompletionContributor { protected void addCompletions( @NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result ) { - putKeywords(result, TailType.NONE, "def", "class", "for", "if", "while", "with"); - putKeywords(result, TailType.CASE_COLON, "try"); + putKeywords(result, TailType.NONE, PyKeywords.DEF, PyKeywords.CLASS, PyKeywords.FOR, PyKeywords.IF, PyKeywords.WHILE, PyKeywords.WITH); + putKeywords(result, TailType.CASE_COLON, PyKeywords.TRY); } } ); @@ -402,13 +403,13 @@ public class PyKeywordCompletionContributor extends CompletionContributor { protected void addCompletions( @NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result ) { - putKeywords(result, TailType.SPACE, "assert", "del", "exec", "from", "import", "raise"); + putKeywords(result, TailType.SPACE, PyKeywords.ASSERT, PyKeywords.DEL, PyKeywords.EXEC, PyKeywords.FROM, PyKeywords.IMPORT, PyKeywords.RAISE); putKeywords(result, TailType.NONE, PyNames.PASS); } } ); - extend(CompletionType.BASIC, inStatement.andNot(PY3K), new PyKeywordCompletionProvider(TailType.SPACE, "print")); + extend(CompletionType.BASIC, inStatement.andNot(PY3K), new PyKeywordCompletionProvider(TailType.SPACE, PyKeywords.PRINT)); } private void addBreak() { @@ -421,7 +422,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .andNot(IN_ARG_LIST) .and(IN_LOOP) , - new PyKeywordCompletionProvider(TailType.NONE, "break") + new PyKeywordCompletionProvider(TailType.NONE, PyKeywords.BREAK) ); } @@ -436,7 +437,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .andNot(IN_FINALLY_NO_LOOP) .and(IN_LOOP) , - new PyKeywordCompletionProvider(TailType.NONE, "continue") + new PyKeywordCompletionProvider(TailType.NONE, PyKeywords.CONTINUE) ); } @@ -448,7 +449,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .and(IN_BEGIN_STMT) .andNot(AFTER_QUALIFIER) , - new PyKeywordCompletionProvider("global", "return", "yield") + new PyKeywordCompletionProvider(PyKeywords.GLOBAL, PyKeywords.RETURN, PyKeywords.YIELD) ); extend( @@ -459,7 +460,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .and(PY3K) .andNot(AFTER_QUALIFIER) , - new PyKeywordCompletionProvider("nonlocal") + new PyKeywordCompletionProvider(PyKeywords.NONLOCAL) ); } @@ -471,7 +472,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .andOr(IN_IF_BODY, AFTER_IF) .andNot(AFTER_QUALIFIER).andNot(IN_STRING_LITERAL) , - new PyKeywordCompletionProvider(TailType.NONE, UnindentingInsertHandler.INSTANCE, "elif")); + new PyKeywordCompletionProvider(TailType.NONE, PyUnindentingInsertHandler.INSTANCE, PyKeywords.ELIF)); } private void addWithinTry() { @@ -487,8 +488,8 @@ public class PyKeywordCompletionContributor extends CompletionContributor { protected void addCompletions( @NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result ) { - putKeyword("except", UnindentingInsertHandler.INSTANCE, TailType.NONE, result); - putKeyword("finally", UnindentingInsertHandler.INSTANCE, TailType.CASE_COLON, result); + putKeyword(PyKeywords.EXCEPT, PyUnindentingInsertHandler.INSTANCE, TailType.NONE, result); + putKeyword(PyKeywords.FINALLY, PyUnindentingInsertHandler.INSTANCE, TailType.CASE_COLON, result); } } ); @@ -502,7 +503,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .andOr(IN_COND_STMT, IN_EXCEPT_BODY, AFTER_COND_STMT_NO_ELSE, AFTER_LOOP_NO_ELSE, AFTER_EXCEPT) .andNot(AFTER_QUALIFIER).andNot(IN_STRING_LITERAL) , - new PyKeywordCompletionProvider(TailType.CASE_COLON, UnindentingInsertHandler.INSTANCE, "else")); + new PyKeywordCompletionProvider(TailType.CASE_COLON, PyUnindentingInsertHandler.INSTANCE, PyKeywords.ELSE)); } private void addInfixOperators() { @@ -516,7 +517,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .andNot(AFTER_QUALIFIER). andNot(IN_STRING_LITERAL).and(IN_BEGIN_STMT) , - new PyKeywordCompletionProvider("and", "or", "is", "in") + new PyKeywordCompletionProvider(PyKeywords.AND, PyKeywords.OR, PyKeywords.IS, PyKeywords.IN) ); } @@ -530,7 +531,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .andNot(IN_FUNCTION_HEADER) .andNot(AFTER_QUALIFIER).andNot(IN_STRING_LITERAL) , - new PyKeywordCompletionProvider("not", "lambda") + new PyKeywordCompletionProvider(PyKeywords.NOT, PyKeywords.LAMBDA) ); } @@ -545,7 +546,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .andNot(AFTER_QUALIFIER) .andNot(IN_FUNCTION_HEADER) , - new PyKeywordCompletionProvider(TailType.NONE, "True", "False", "None") + new PyKeywordCompletionProvider(TailType.NONE, PyKeywords.TRUE, PyKeywords.FALSE, PyKeywords.NONE) ); } @@ -556,7 +557,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .andOr(IN_IMPORT_AFTER_REF, IN_WITH_AFTER_REF, IN_EXCEPT_AFTER_REF) .andNot(AFTER_QUALIFIER) , - new PyKeywordCompletionProvider("as") + new PyKeywordCompletionProvider(PyKeywords.AS) ); } @@ -567,7 +568,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .and(IN_FROM_IMPORT_AFTER_REF) .andNot(AFTER_QUALIFIER) , - new PyKeywordCompletionProvider("import") + new PyKeywordCompletionProvider(PyKeywords.IMPORT) ); } @@ -603,9 +604,9 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .withLanguage(PythonLanguage.getInstance()) .afterLeafSkipping(psiElement().whitespace(), psiElement().inside(psiElement(PyConditionalExpression.class)) - .and(psiElement().afterLeaf("if"))) + .and(psiElement().afterLeaf(PyKeywords.IF))) , - new PyKeywordCompletionProvider(TailType.SPACE, "else")); + new PyKeywordCompletionProvider(TailType.SPACE, PyKeywords.ELSE)); } private void addRaiseFrom() { @@ -614,7 +615,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .withLanguage(PythonLanguage.getInstance()) .and(PY3K) .afterLeaf(psiElement().inside(PyRaiseStatement.class)), - new PyKeywordCompletionProvider("from")); + new PyKeywordCompletionProvider(PyKeywords.FROM)); } private void addYieldFrom() { @@ -623,7 +624,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .withLanguage(PythonLanguage.getInstance()) .and(PY3K) .afterLeaf(psiElement().withElementType(PyTokenTypes.YIELD_KEYWORD)), - new PyKeywordCompletionProvider("from")); + new PyKeywordCompletionProvider(PyKeywords.FROM)); } public PyKeywordCompletionContributor() { @@ -654,14 +655,14 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .withLanguage(PythonLanguage.getInstance()) .inside(psiElement(PySequenceExpression.class)) .andNot(psiElement().afterLeaf(or(psiElement(PyTokenTypes.LBRACE), psiElement(PyTokenTypes.LBRACKET), psiElement(PyTokenTypes.LPAR)))), - new PyKeywordCompletionProvider("for")); + new PyKeywordCompletionProvider(PyKeywords.FOR)); } private void addInToFor() { extend(CompletionType.BASIC, psiElement() .withLanguage(PythonLanguage.getInstance()) - .and(psiElement()).afterLeaf(psiElement().afterLeaf("for")), + .and(psiElement()).afterLeaf(psiElement().afterLeaf(PyKeywords.FOR)), new PyKeywordCompletionProvider("in")); }