Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2016-02-15 13:27:18 +01:00
27 changed files with 313 additions and 389 deletions
@@ -672,12 +672,13 @@ public class BuildManager implements Disposable {
return null;
}
final DelegateFuture<?> _future = new DelegateFuture<>();
final DelegateFuture<BuilderMessageHandler> _future = new DelegateFuture<>();
// by using the same queue that processes events we ensure that
// the build will be aware of all events that have happened before this request
runCommand(new Runnable() {
@Override
public void run() {
final Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> preloaded = takePreloadedProcess(projectPath);
final RequestFuture<PreloadedProcessMessageHandler> preloadedFuture = preloaded != null? preloaded.first : null;
final boolean usingPreloadedProcess = preloadedFuture != null;
@@ -692,7 +693,8 @@ public class BuildManager implements Disposable {
sessionId = UUID.randomUUID();
}
final RequestFuture<? extends BuilderMessageHandler> future = usingPreloadedProcess? preloadedFuture : new RequestFuture<BuilderMessageHandler>(handler, sessionId, new CancelBuildSessionAction<BuilderMessageHandler>());
final RequestFuture<? extends BuilderMessageHandler> future = usingPreloadedProcess? preloadedFuture : new RequestFuture<>(handler, sessionId, new CancelBuildSessionAction<BuilderMessageHandler>());
_future.setDelegate(future);
if (!usingPreloadedProcess && (future.isCancelled() || project.isDisposed())) {
// in case of preloaded process the process was already running, so the handler will be notified upon process termination
@@ -739,7 +741,7 @@ public class BuildManager implements Disposable {
}
try {
Future<?> buildFuture = projectTaskQueue.submit(new Runnable() {
projectTaskQueue.submit(new Runnable() {
@Override
public void run() {
Throwable execFailure = null;
@@ -776,7 +778,7 @@ public class BuildManager implements Disposable {
}
});
}
catch (Throwable e) {
catch(Throwable e) {
LOG.info(e);
}
}
@@ -841,9 +843,6 @@ public class BuildManager implements Disposable {
}
}
});
TaskFutureAdapter adapter = new TaskFutureAdapter<>(buildFuture);
boolean set = _future.setDelegate(adapter);
assert set;
}
catch (Throwable e) {
handleProcessExecutionFailure(sessionId, e);
@@ -1,90 +0,0 @@
/*
* Copyright 2000-2016 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 org.jetbrains.jps.api;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.*;
/**
* Makes TaskFuture from the supplied Future
*/
public class TaskFutureAdapter<T> implements TaskFuture<T> {
@NotNull private final Future<T> myFuture;
public TaskFutureAdapter(@NotNull Future<T> future) {
myFuture = future;
}
@Override
public void waitFor() {
try {
get();
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
catch (ExecutionException e) {
throw new RuntimeException(e);
}
catch (CancellationException ignored) {
}
}
@Override
public boolean waitFor(long timeout, TimeUnit unit) {
try {
get(timeout, unit);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
catch (ExecutionException e) {
throw new RuntimeException(e);
}
catch (TimeoutException ignored) {
}
catch (CancellationException ignored) {
}
return isDone();
}
// delegates
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return myFuture.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return myFuture.isCancelled();
}
@Override
public boolean isDone() {
return myFuture.isDone();
}
@Override
public T get() throws InterruptedException, ExecutionException {
return myFuture.get();
}
@Override
public T get(long timeout, @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return myFuture.get(timeout, unit);
}
}
@@ -25,7 +25,6 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.Restarter;
import com.intellij.util.SystemProperties;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
@@ -81,9 +80,7 @@ public class Main {
System.exit(NO_GRAPHICS);
}
//this property is temporary and will be removed when IntelliJ platform really migrates to Java 8
boolean checkVersion = !SystemProperties.getBooleanProperty("idea.no.java.version.check", false);
if (checkVersion && !SystemInfo.isJavaVersionAtLeast("1.8")) {
if (!SystemInfo.isJavaVersionAtLeast("1.8")) {
showMessage("Unsupported Java Version",
"Cannot start under Java " + SystemInfo.JAVA_RUNTIME_VERSION + ": Java 1.8 or later is required.", true);
System.exit(UNSUPPORTED_JAVA_VERSION);
@@ -883,6 +883,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
isReleased = true;
clearSettingsCache();
mySizeAdjustmentStrategy.cancelAllRequests();
myFoldingModel.dispose();
mySoftWrapModel.release();
@@ -103,6 +103,10 @@ class EditorSizeAdjustmentStrategy {
scheduleSizeUpdate(editor);
return result;
}
void cancelAllRequests() {
myAlarm.cancelAllRequests();
}
/**
* Removes old timings.
@@ -252,6 +252,16 @@ public class ContainerUtilTest extends TestCase {
assertSame(EmptyIterator.getInstance(), iterator);
}
public void testIdenticalItemsInLockFreeCOW() {
List<String> list = ContainerUtil.createLockFreeCopyOnWriteList(Arrays.asList("a", "b"));
list.add("a");
assertEquals(3, list.size());
list.remove("a");
assertEquals(2, list.size());
list.remove("a");
assertEquals(1, list.size());
}
public void testLockFreeCOWIteratorRemove() {
List<String> seq = Arrays.asList("0", "1", "2", "3", "4");
LockFreeCopyOnWriteArrayList<String> my = (LockFreeCopyOnWriteArrayList<String>)ContainerUtil.createLockFreeCopyOnWriteList(seq);
Binary file not shown.
@@ -3,6 +3,7 @@ package org.jetbrains.plugins.terminal;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.impl.IdeBackgroundUtil;
import com.intellij.ui.SearchTextField;
import com.intellij.ui.components.JBScrollBar;
import com.jediterm.terminal.TerminalStarter;
import com.jediterm.terminal.TtyConnector;
@@ -14,7 +15,9 @@ import com.jediterm.terminal.ui.settings.SettingsProvider;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.KeyListener;
public class JBTerminalWidget extends JediTermWidget implements Disposable{
@@ -53,4 +56,31 @@ public class JBTerminalWidget extends JediTermWidget implements Disposable{
@Override
public void dispose() {
}
@Override
protected SearchComponent createSearchComponent() {
return new SearchComponent() {
private final SearchTextField myTextField = new SearchTextField(false);
@Override
public String getText() {
return myTextField.getText();
}
@Override
public JComponent getComponent() {
myTextField.setOpaque(false);
return myTextField;
}
@Override
public void addDocumentChangeListener(DocumentListener listener) {
myTextField.addDocumentListener(listener);
}
@Override
public void addKeyListener(KeyListener listener) {
myTextField.addKeyboardListener(listener);
}
};
}
}
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.generation.PsiGenerationInfo;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
@@ -129,7 +130,10 @@ public class GenerateMainAction extends AnAction {
@Override
public void update(AnActionEvent e) {
e.getPresentation().setVisible(isActionEnabled(e));
boolean enabled = isActionEnabled(e);
Presentation presentation = e.getPresentation();
presentation.setEnabled(enabled);
presentation.setVisible(enabled);
}
private static boolean isActionEnabled(final AnActionEvent e) {
@@ -281,7 +281,7 @@ public final class PropertyInspectorTable extends Table implements DataProvider{
return myEditor;
}
else if (PlatformDataKeys.FILE_EDITOR.is(dataId)) {
GuiEditor designer = DesignerToolWindowManager.getInstance(myProject).getActiveFormEditor();
GuiEditor designer = myProject.isDisposed() ? null : DesignerToolWindowManager.getInstance(myProject).getActiveFormEditor();
return designer == null ? null : designer.getEditor();
}
else if (PlatformDataKeys.HELP_ID.is(dataId)) {
@@ -1,54 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.uiDesigner.propertyInspector.editors.string.NewKeyDialog">
<grid id="1eff1" binding="myPanel" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<grid id="49180" binding="myPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<xy x="59" y="38" width="219" height="49"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0"/>
<xy x="59" y="38" width="232" height="65"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="9981" class="javax.swing.JLabel">
<constraints>
<xy x="2" y="5" width="55" height="14"/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0"/>
</constraints>
<properties>
<labelFor value="89f45"/>
<text resource-bundle="messages/UIDesignerBundle" key="key.chooser.new.property.name"/>
</properties>
</component>
<component id="89f45" class="javax.swing.JTextField" binding="myKeyNameEdit">
<constraints>
<xy x="67" y="2" width="150" height="20"/>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<grid id="772be" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints border-constraint="North"/>
<properties/>
</component>
<component id="f12ed" class="javax.swing.JTextField" binding="myKeyValueEdit">
<constraints>
<xy x="67" y="27" width="150" height="20"/>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<columns value="50"/>
</properties>
</component>
<component id="23f8d" class="javax.swing.JLabel">
<constraints>
<xy x="2" y="30" width="55" height="14"/>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0"/>
</constraints>
<properties>
<labelFor value="f12ed"/>
<text resource-bundle="messages/UIDesignerBundle" key="key.chooser.new.property.value"/>
</properties>
</component>
<border type="none"/>
<children>
<component id="ab054" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="89f45"/>
<text resource-bundle="messages/UIDesignerBundle" key="key.chooser.new.property.name"/>
</properties>
</component>
<component id="5ff32" class="javax.swing.JTextField" binding="myKeyNameEdit">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="19be8" class="javax.swing.JTextField" binding="myKeyValueEdit">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<columns value="50"/>
</properties>
</component>
<component id="49d01" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="f12ed"/>
<text resource-bundle="messages/UIDesignerBundle" key="key.chooser.new.property.value"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
</form>
@@ -17,6 +17,7 @@ package com.intellij.uiDesigner.propertyInspector.editors.string;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.uiDesigner.UIDesignerBundle;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.DocumentListener;
@@ -63,6 +64,11 @@ public class NewKeyDialog extends DialogWrapper {
return myPanel;
}
@NotNull
protected String getDimensionServiceKey() {
return getClass().getName();
}
public String getName() {
return myKeyNameEdit.getText();
}
@@ -235,10 +235,17 @@ public class StudyUtils {
if (course == null) {
return null;
}
final VirtualFile taskDir = file.getParent();
VirtualFile taskDir = file.getParent();
if (taskDir == null) {
return null;
}
//need this because of multi-module generation
if ("src".equals(taskDir.getName())) {
taskDir = taskDir.getParent();
if (taskDir == null) {
return null;
}
}
final String taskDirName = taskDir.getName();
if (taskDirName.contains(EduNames.TASK)) {
final VirtualFile lessonDir = taskDir.getParent();
@@ -392,6 +399,12 @@ public class StudyUtils {
}
if (taskDirectory != null) {
VirtualFile taskTextFile = taskDirectory.findChild(EduNames.TASK_HTML);
if (taskTextFile == null) {
VirtualFile srcDir = taskDirectory.findChild("src");
if (srcDir != null) {
taskTextFile = srcDir.findChild(EduNames.TASK_HTML);
}
}
if (taskTextFile != null) {
try {
return FileUtil.loadTextAndClose(taskTextFile.getInputStream());
@@ -92,7 +92,8 @@ abstract public class StudyTaskNavigationAction extends DumbAwareAction {
for (Map.Entry<String, TaskFile> entry : nextTaskFiles.entrySet()) {
String name = entry.getKey();
TaskFile taskFile = entry.getValue();
VirtualFile vf = taskDir.findChild(name);
VirtualFile srcDir = taskDir.findChild("src");
VirtualFile vf = srcDir == null ? taskDir.findChild(name) : srcDir.findChild(name);
if (vf != null) {
FileEditorManager.getInstance(project).openFile(vf, true);
if (!taskFile.getAnswerPlaceholders().isEmpty()) {
@@ -46,10 +46,10 @@ import java.util.Map;
public class StudyProjectGenerator {
private static final Logger LOG = Logger.getInstance(StudyProjectGenerator.class.getName());
private final List<SettingsListener> myListeners = ContainerUtil.newArrayList();
private static final File ourCoursesDir = new File(PathManager.getConfigPath(), "courses");
protected static final File ourCoursesDir = new File(PathManager.getConfigPath(), "courses");
private static final String CACHE_NAME = "courseNames.txt";
private List<CourseInfo> myCourses = new ArrayList<>();
private CourseInfo mySelectedCourseInfo;
protected CourseInfo mySelectedCourseInfo;
private static final String COURSE_NAME_ATTRIBUTE = "name";
private static final String COURSE_DESCRIPTION = "description";
public static final String AUTHOR_ATTRIBUTE = "authors";
@@ -82,7 +82,7 @@ public class StudyProjectGenerator {
})));
}
private Course getCourse() {
protected Course getCourse() {
Reader reader = null;
try {
final File courseFile = new File(new File(ourCoursesDir, mySelectedCourseInfo.getName()), EduNames.COURSE_META_FILE);
@@ -41,7 +41,7 @@ public class StudyDirectoryNode extends PsiDirectoryNode {
String valueName = myValue.getName();
StudyTaskManager studyTaskManager = StudyTaskManager.getInstance(myProject);
Course course = studyTaskManager.getCourse();
if (course == null || valueName == null) {
if (course == null) {
return;
}
if (valueName.equals(myProject.getName())) {
@@ -50,19 +50,17 @@ public class StudyDirectoryNode extends PsiDirectoryNode {
data.addText(course.getName(), new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, JBColor.BLACK));
}
else if (valueName.contains(EduNames.TASK)) {
TaskFile file = null;
for (PsiElement child : myValue.getChildren()) {
VirtualFile virtualFile = child instanceof PsiDirectory ? ((PsiDirectory)child).getVirtualFile() :
child.getContainingFile().getVirtualFile();
file = StudyUtils.getTaskFile(myProject, virtualFile);
if (file != null) {
break;
VirtualFile taskVirtualFile = myValue.getVirtualFile();
VirtualFile lessonVirtualFile = taskVirtualFile.getParent();
if (lessonVirtualFile != null) {
Lesson lesson = course.getLesson(lessonVirtualFile.getName());
if (lesson != null) {
Task task = lesson.getTask(taskVirtualFile.getName());
if (task != null) {
setStudyAttributes(task, data, task.getName());
}
}
}
if (file != null) {
Task task = file.getTask();
setStudyAttributes(task, data, task.getName());
}
}
else if (valueName.contains(EduNames.LESSON)) {
int lessonIndex = Integer.parseInt(valueName.substring(EduNames.LESSON.length())) - 1;
@@ -73,7 +71,7 @@ public class StudyDirectoryNode extends PsiDirectoryNode {
else if (valueName.contains(EduNames.SANDBOX_DIR)) {
if (myValue.getParent() != null) {
final String parentName = myValue.getParent().getName();
if (parentName!= null && !parentName.contains(EduNames.SANDBOX_DIR)) {
if (!parentName.contains(EduNames.SANDBOX_DIR)) {
data.setPresentableText(EduNames.SANDBOX_DIR);
data.setIcon(InteractiveLearningIcons.Sandbox);
}
+4 -214
View File
@@ -4,61 +4,19 @@
<variable name="method" expression="pyFunctionName()" defaultValue="" alwaysStopAt="false" />
<variable name="end" 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" />
<option name="Python_Class" value="true" />
</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" />
<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="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">
@@ -66,21 +24,7 @@
<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">
@@ -88,21 +32,7 @@
<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">
@@ -111,21 +41,7 @@
<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">
@@ -133,21 +49,7 @@
<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">
@@ -156,21 +58,7 @@
<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">
@@ -178,21 +66,7 @@
<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">
@@ -201,21 +75,7 @@
<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="Dict comprehension" toReformat="false" toShortenFQNames="true">
@@ -224,21 +84,7 @@
<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="Dict comprehension with 'if'" toReformat="false" toShortenFQNames="true">
@@ -248,81 +94,25 @@
<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" />
<option name="Python_Class" value="true" />
</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" />
<option name="Python_Class" value="true" />
</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" />
<option name="Python_Class" value="true" />
</context>
</template>
</templateSet>
+3 -3
View File
@@ -374,7 +374,9 @@
<localInspection language="Python" shortName="PyPep8NamingInspection" suppressId="PyPep8Naming" displayName="PEP 8 naming convention violation" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyPep8NamingInspection"/>
<localInspection language="Python" shortName="PyAssignmentToLoopOrWithParameterInspection" suppressId="PyAssignmentToLoopOrWithParameter" displayName="Assignment to 'for' loop or 'with' statement parameter" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyAssignmentToLoopOrWithParameterInspection"/>
<liveTemplateContext implementation="com.jetbrains.python.codeInsight.liveTemplates.PythonTemplateContextType"/>
<defaultLiveTemplatesProvider implementation="com.jetbrains.python.codeInsight.liveTemplates.PyDefaultLiveTemplatesProvider"/>
<liveTemplateContext implementation="com.jetbrains.python.codeInsight.liveTemplates.PythonTemplateContextType$General"/>
<liveTemplateContext implementation="com.jetbrains.python.codeInsight.liveTemplates.PythonTemplateContextType$Class"/>
<liveTemplateMacro implementation="com.jetbrains.python.codeInsight.liveTemplates.CollectionElementNameMacro"/>
<liveTemplateMacro implementation="com.jetbrains.python.codeInsight.liveTemplates.PyClassNameMacro"/>
<liveTemplateMacro implementation="com.jetbrains.python.codeInsight.liveTemplates.PyFunctionNameMacro"/>
@@ -418,8 +420,6 @@
serviceImplementation="com.jetbrains.python.sdk.PySdkService"/>
<autoImportOptionsProvider instance="com.jetbrains.python.codeInsight.imports.PyAutoImportOptions"/>
<defaultLiveTemplatesProvider implementation="com.jetbrains.python.codeInsight.liveTemplates.PyDefaultLiveTemplatesProvider"/>
<completion.contributor language="Python"
implementationClass="com.jetbrains.python.codeInsight.completion.PyClassNameCompletionContributor"/>
<weigher key="completion" implementationClass="com.jetbrains.python.codeInsight.completion.PythonCompletionWeigher" order="first"/>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -15,15 +15,18 @@
*/
package com.jetbrains.python.codeInsight.liveTemplates;
import com.intellij.codeInsight.template.FileTypeBasedContextType;
import com.intellij.codeInsight.template.EverywhereContextType;
import com.intellij.codeInsight.template.TemplateContextType;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.jetbrains.annotations.NotNull;
@@ -33,22 +36,37 @@ import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author yole
*/
public class PythonTemplateContextType extends FileTypeBasedContextType {
public PythonTemplateContextType() {
super("Python", "Python", PythonFileType.INSTANCE);
public abstract class PythonTemplateContextType extends TemplateContextType {
public PythonTemplateContextType(@NotNull String id,
@NotNull String presentableName,
@NotNull java.lang.Class<? extends TemplateContextType> baseContextType) {
super(id, presentableName, baseContextType);
}
@Override
public boolean isInContext(@NotNull PsiFile file, int offset) {
if (super.isInContext(file, offset)) {
if (isPythonLanguage(file, offset)) {
final PsiElement element = file.findElementAt(offset);
if (element != null) {
return !(isAfterDot(element) || element instanceof PsiComment || isInsideStringLiteral(element) || isInsideParameterList(element));
if (isAfterDot(element) || element instanceof PsiComment || isInsideStringLiteral(element) || isInsideParameterList(element)) {
return false;
}
return isInContext(element);
}
}
return false;
}
protected abstract boolean isInContext(@NotNull PsiElement element);
private static boolean isPythonLanguage(@NotNull PsiFile file, int offset) {
return PsiUtilCore.getLanguageAtOffset(file, offset).isKindOf(PythonLanguage.getInstance());
}
private static boolean isInsideStringLiteral(@NotNull PsiElement element) {
return PsiTreeUtil.getParentOfType(element, PyStringLiteralExpression.class, false) != null;
}
@@ -62,4 +80,28 @@ public class PythonTemplateContextType extends FileTypeBasedContextType {
psiElement().withElementType(PyTokenTypes.DOT));
return capture.accepts(element, new ProcessingContext());
}
public static class General extends PythonTemplateContextType {
public General() {
super("Python", "Python", EverywhereContextType.class);
}
@Override
protected boolean isInContext(@NotNull PsiElement element) {
return true;
}
}
public static class Class extends PythonTemplateContextType {
public Class() {
super("Python_Class", "Class", General.class);
}
@Override
protected boolean isInContext(@NotNull PsiElement element) {
return PsiTreeUtil.getParentOfType(element, PyClass.class) != null;
}
}
}
@@ -0,0 +1 @@
foo.<caret>
@@ -0,0 +1,3 @@
class C(object):
p<caret>
pass
@@ -0,0 +1,2 @@
p<caret>
pass
@@ -0,0 +1 @@
# <caret>
@@ -0,0 +1,2 @@
def foo(a, <caret>):
pass
@@ -0,0 +1 @@
"abc<caret>"
@@ -0,0 +1,3 @@
<html>
<caret>
</html>
@@ -0,0 +1,104 @@
/*
* Copyright 2000-2016 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.template.TemplateContextType;
import com.intellij.testFramework.UsefulTestCase;
import com.jetbrains.python.fixtures.PyTestCase;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class PyLiveTemplatesTest extends PyTestCase {
@Override
protected String getTestDataPath() {
return super.getTestDataPath() + "/codeInsight/liveTemplates/context/";
}
public void testNotPython() {
doTest(Collections.emptyList(), "html");
}
// PY-12212
public void testAfterDot() {
doTest(Collections.emptyList());
}
// PY-13076
public void testInComment() {
doTest(Collections.emptyList());
}
// PY-12349
public void testInStringLiteral() {
doTest(Collections.emptyList());
}
// PY-12395
public void testInParameterList() {
doTest(Collections.emptyList());
}
public void testGeneral() {
doTest(
Collections.singletonList(PythonTemplateContextType.General.class)
);
}
// PY-12396
public void testClass() {
doTest(
Arrays.asList(PythonTemplateContextType.Class.class, PythonTemplateContextType.General.class)
);
}
private void doTest(@NotNull List<Class<? extends PythonTemplateContextType>> expectedContextTypes) {
doTest(expectedContextTypes, "py");
}
private void doTest(@NotNull List<Class<? extends PythonTemplateContextType>> expectedContextTypes, @NotNull String extension) {
myFixture.configureByFile(getTestName(true) + "." + extension);
UsefulTestCase.assertSameElements(
calculateEnabledContextTypes(getRegisteredContextTypes()),
expectedContextTypes
);
}
@NotNull
private List<Class<? extends PythonTemplateContextType>> calculateEnabledContextTypes(@NotNull List<PythonTemplateContextType> registeredContextTypes) {
//noinspection Convert2MethodRef
return registeredContextTypes
.stream()
.filter(type -> type.isInContext(myFixture.getFile(), myFixture.getCaretOffset()))
.map(type -> type.getClass())
.sorted((o1, o2) -> o1.getSimpleName().compareTo(o2.getSimpleName()))
.collect(Collectors.toList());
}
@NotNull
private static List<PythonTemplateContextType> getRegisteredContextTypes() {
return Arrays
.stream(TemplateContextType.EP_NAME.getExtensions())
.filter(type -> type instanceof PythonTemplateContextType)
.map(type -> (PythonTemplateContextType)type)
.collect(Collectors.toList());
}
}