Merge branch 'python-live-templates'

This commit is contained in:
Andrey Vlasovskikh
2014-02-25 19:14:48 +04:00
3 changed files with 411 additions and 2 deletions
+294 -2
View File
@@ -1,9 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<templateSet group="Python">
<template name="super" value="super($class$, self).$method$($end$)" description="Generates a 'super' call" toReformat="false" toShortenFQNames="true">
<template name="super" value="super($class$, self).$method$($end$)" description="'super(...)' call" toReformat="false" toShortenFQNames="true">
<variable name="class" expression="pyClassName()" defaultValue="" alwaysStopAt="false" />
<variable name="method" expression="pyFunctionName()" defaultValue="" alwaysStopAt="false" />
<variable name="end" expression="" defaultValue="" alwaysStopAt="true" />
<context>
<option name="TypeScript" value="false" />
<option name="CoffeeScript" value="false" />
</context>
</template>
<template name="main" value="if __name__ == '__main__':&#10; $END$" description="if __name__ == '__main__'" toReformat="false" toShortenFQNames="true">
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
@@ -16,7 +21,294 @@
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="iter" value="for $VAR$ in $ITERABLE$:&#10; $END$" description="Iterate (for ... in ...)" toReformat="false" toShortenFQNames="true">
<variable name="ITERABLE" expression="pyIterableVariable()" defaultValue="" alwaysStopAt="true" />
<variable name="VAR" expression="collectionElementName(ITERABLE)" defaultValue="" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="itere" value="for $INDEX$, $VAR$ in enumerate($ITERABLE$):&#10; $END$" description="Iterate (for ... in enumerate)" toReformat="false" toShortenFQNames="true">
<variable name="ITERABLE" expression="pyIterableVariable()" defaultValue="" alwaysStopAt="true" />
<variable name="VAR" expression="collectionElementName(ITERABLE)" defaultValue="" alwaysStopAt="true" />
<variable name="INDEX" expression="" defaultValue="&quot;i&quot;" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="compl" value="[$VAR_EXPR$ for $VAR$ in $ITERABLE$]" description="List comprehension" toReformat="false" toShortenFQNames="true">
<variable name="ITERABLE" expression="pyIterableVariable()" defaultValue="" alwaysStopAt="true" />
<variable name="VAR" expression="collectionElementName(ITERABLE)" defaultValue="" alwaysStopAt="true" />
<variable name="VAR_EXPR" expression="" defaultValue="VAR" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="compli" value="[$VAR_EXPR$ for $VAR$ in $ITERABLE$ if $VAR_EXPR_IF$]" description="List comprehension with 'if'" toReformat="false" toShortenFQNames="true">
<variable name="ITERABLE" expression="pyIterableVariable()" defaultValue="" alwaysStopAt="true" />
<variable name="VAR" expression="collectionElementName(ITERABLE)" defaultValue="" alwaysStopAt="true" />
<variable name="VAR_EXPR" expression="" defaultValue="VAR" alwaysStopAt="true" />
<variable name="VAR_EXPR_IF" expression="" defaultValue="VAR" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="compg" value="($VAR_EXPR$ for $VAR$ in $ITERABLE$)" description="Generator comprehension" toReformat="false" toShortenFQNames="true">
<variable name="ITERABLE" expression="pyIterableVariable()" defaultValue="" alwaysStopAt="true" />
<variable name="VAR" expression="collectionElementName(ITERABLE)" defaultValue="" alwaysStopAt="true" />
<variable name="VAR_EXPR" expression="" defaultValue="VAR" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="compgi" value="($VAR_EXPR$ for $VAR$ in $ITERABLE$ if $VAR_EXPR_IF$)" description="Generator comprehension with 'if'" toReformat="false" toShortenFQNames="true">
<variable name="ITERABLE" expression="pyIterableVariable()" defaultValue="" alwaysStopAt="true" />
<variable name="VAR" expression="collectionElementName(ITERABLE)" defaultValue="" alwaysStopAt="true" />
<variable name="VAR_EXPR" expression="" defaultValue="VAR" alwaysStopAt="true" />
<variable name="VAR_EXPR_IF" expression="" defaultValue="VAR" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="comps" value="{$VAR_EXPR$ for $VAR$ in $ITERABLE$}" description="Set comprehension" toReformat="false" toShortenFQNames="true">
<variable name="ITERABLE" expression="pyIterableVariable()" defaultValue="" alwaysStopAt="true" />
<variable name="VAR" expression="collectionElementName(ITERABLE)" defaultValue="" alwaysStopAt="true" />
<variable name="VAR_EXPR" expression="" defaultValue="VAR" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="compsi" value="{$VAR_EXPR$ for $VAR$ in $ITERABLE$ if $VAR_EXPR_IF$}" description="Set comprehension with 'if'" toReformat="false" toShortenFQNames="true">
<variable name="ITERABLE" expression="pyIterableVariable()" defaultValue="" alwaysStopAt="true" />
<variable name="VAR" expression="collectionElementName(ITERABLE)" defaultValue="" alwaysStopAt="true" />
<variable name="VAR_EXPR" expression="" defaultValue="VAR" alwaysStopAt="true" />
<variable name="VAR_EXPR_IF" expression="" defaultValue="VAR" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="compd" value="{$KEY_EXPR$: $VAL_EXPR$ for $VAR$ in $ITERABLE$}" description="Generator comprehension" toReformat="false" toShortenFQNames="true">
<variable name="ITERABLE" expression="pyIterableVariable()" defaultValue="" alwaysStopAt="true" />
<variable name="VAR" expression="collectionElementName(ITERABLE)" defaultValue="" alwaysStopAt="true" />
<variable name="KEY_EXPR" expression="" defaultValue="VAR" alwaysStopAt="true" />
<variable name="VAL_EXPR" expression="" defaultValue="VAR" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="compdi" value="{$KEY_EXPR$: $VAL_EXPR$ for $VAR$ in $ITERABLE$ if $VAR_EXPR_IF$}" description="Generator comprehension with 'if'" toReformat="false" toShortenFQNames="true">
<variable name="ITERABLE" expression="pyIterableVariable()" defaultValue="" alwaysStopAt="true" />
<variable name="VAR" expression="collectionElementName(ITERABLE)" defaultValue="" alwaysStopAt="true" />
<variable name="KEY_EXPR" expression="" defaultValue="VAR" alwaysStopAt="true" />
<variable name="VAL_EXPR" expression="" defaultValue="VAR" alwaysStopAt="true" />
<variable name="VAR_EXPR_IF" expression="" defaultValue="VAR" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="prop" value="@property&#10;def $NAME$(self):&#10; return $END$" description="Property getter" toReformat="false" toShortenFQNames="true">
<variable name="NAME" expression="" defaultValue="" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="props" value="@property&#10;def $NAME$(self):&#10; return $END$&#10;&#10;@$NAME$.setter&#10;def $NAME$(self, value):&#10; pass" description="Property getter/setter" toReformat="false" toShortenFQNames="true">
<variable name="NAME" expression="" defaultValue="" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
<template name="propsd" value="@property&#10;def $NAME$(self):&#10; return $END$&#10;&#10;@$NAME$.setter&#10;def $NAME$(self, value):&#10; pass&#10;&#10;@$NAME$.deleter&#10;def $NAME$(self):&#10; pass" description="Property getter/setter/deleter" toReformat="false" toShortenFQNames="true">
<variable name="NAME" expression="" defaultValue="" alwaysStopAt="true" />
<context>
<option name="HTML_TEXT" value="false" />
<option name="HTML" value="false" />
<option name="XSL_TEXT" value="false" />
<option name="XML" value="false" />
<option name="Python" value="true" />
<option name="Django" value="false" />
<option name="CSS_PROPERTY_VALUE" value="false" />
<option name="CSS_DECLARATION_BLOCK" value="false" />
<option name="CSS_RULESET_LIST" value="false" />
<option name="CSS" value="false" />
<option name="JAVA_SCRIPT" value="false" />
<option name="TypeScript" value="false" />
<option name="SQL" value="false" />
<option name="CoffeeScript" value="false" />
<option name="OTHER" value="false" />
</context>
</template>
+1
View File
@@ -339,6 +339,7 @@
<liveTemplateMacro implementation="com.jetbrains.python.codeInsight.liveTemplates.CollectionElementNameMacro"/>
<liveTemplateMacro implementation="com.jetbrains.python.codeInsight.liveTemplates.PyClassNameMacro"/>
<liveTemplateMacro implementation="com.jetbrains.python.codeInsight.liveTemplates.PyFunctionNameMacro"/>
<liveTemplateMacro implementation="com.jetbrains.python.codeInsight.liveTemplates.PyIterableVariableMacro"/>
<codeInsight.overrideMethod language="Python" implementationClass="com.jetbrains.python.codeInsight.override.PyOverrideMethodsHandler"/>
<lang.refactoringSupport language="Python" implementationClass="com.jetbrains.python.refactoring.PyRefactoringProvider"/>
@@ -0,0 +1,116 @@
/*
* 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.liveTemplates;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.template.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.psi.PyElement;
import com.jetbrains.python.psi.PyImportedNameDefiner;
import com.jetbrains.python.psi.PyTypedElement;
import com.jetbrains.python.psi.types.PyABCUtil;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* @author vlan
*/
public class PyIterableVariableMacro extends Macro {
@Override
public String getName() {
return "pyIterableVariable";
}
@Override
public String getPresentableName() {
return "pyIterableVariable()";
}
@Nullable
@Override
public Result calculateResult(@NotNull Expression[] params, @NotNull ExpressionContext context) {
final PsiElement element = context.getPsiElementAtStartOffset();
if (element != null) {
final List<PsiNamedElement> components = getIterableElements(element);
if (!components.isEmpty()) {
return new PsiElementResult(components.get(0));
}
}
return null;
}
@Nullable
@Override
public LookupElement[] calculateLookupItems(@NotNull Expression[] params, ExpressionContext context) {
final List<LookupElement> results = new ArrayList<LookupElement>();
final PsiElement element = context.getPsiElementAtStartOffset();
if (element != null) {
for (PsiNamedElement iterableElement : getIterableElements(element)) {
results.add(LookupElementBuilder.create(iterableElement));
}
}
return results.toArray(new LookupElement[results.size()]);
}
@Override
public boolean isAcceptableInContext(TemplateContextType context) {
return context instanceof PythonTemplateContextType;
}
@NotNull
protected List<PsiNamedElement> getIterableElements(@NotNull PsiElement element) {
final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(element.getContainingFile());
final List<PsiNamedElement> components = new ArrayList<PsiNamedElement>();
for (PsiNamedElement namedElement : getVisibleNamedElements(element)) {
if (namedElement instanceof PyTypedElement) {
final PyType type = typeEvalContext.getType((PyTypedElement)namedElement);
if (type != null && PyABCUtil.isSubtype(type, PyNames.ITERABLE, typeEvalContext)) {
components.add(namedElement);
}
}
}
return components;
}
@NotNull
private static List<PsiNamedElement> getVisibleNamedElements(@NotNull PsiElement anchor) {
final List<PsiNamedElement> results = new ArrayList<PsiNamedElement>();
for (ScopeOwner owner = ScopeUtil.getScopeOwner(anchor); owner != null; owner = ScopeUtil.getScopeOwner(owner)) {
final Scope scope = ControlFlowCache.getScope(owner);
results.addAll(scope.getNamedElements());
for (PyImportedNameDefiner importedNameDefiner : scope.getImportedNameDefiners()) {
for (PyElement importedElement : importedNameDefiner.iterateNames()) {
if (importedElement instanceof PsiNamedElement) {
results.add((PsiNamedElement)importedElement);
}
}
}
}
return results;
}
}