add before-after preview for postfix templates

This commit is contained in:
Andrey Starovoyt
2014-04-28 15:33:46 +04:00
parent c4084ffc9e
commit 4d43dab9e9
109 changed files with 1264 additions and 337 deletions
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.codeInsight.template.postfix.settings.PostfixDescriptionPanel">
<grid id="d0bf1" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="26" y="23" width="498" height="354"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="3853d" layout-manager="GridLayoutManager" row-count="6" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<xy id="a6fdd" binding="myAfterPanel" layout-manager="XYLayout" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</xy>
<xy id="fa495" binding="myBeforePanel" layout-manager="XYLayout" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</xy>
<component id="e4723" class="com.intellij.ui.TitledSeparator">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Before"/>
</properties>
</component>
<component id="967ce" class="com.intellij.ui.TitledSeparator">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<alignmentY value="0.2"/>
<text value="After"/>
</properties>
</component>
<scrollpane id="93a5c" class="com.intellij.ui.components.JBScrollPane">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="2f94a" class="javax.swing.JEditorPane" binding="myDescriptionBrowser">
<constraints/>
<properties>
<contentType value="text/html" noi18n="true"/>
<editable value="false"/>
</properties>
</component>
</children>
</scrollpane>
<component id="36ea" class="com.intellij.ui.TitledSeparator">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Description"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
</form>
@@ -0,0 +1,114 @@
/*
* 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.intellij.codeInsight.template.postfix.settings;
import com.intellij.codeInsight.intention.impl.config.ActionUsagePanel;
import com.intellij.codeInsight.intention.impl.config.TextDescriptor;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.TitledSeparator;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
class PostfixDescriptionPanel implements Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.config.IntentionDescriptionPanel");
private JPanel myPanel;
private JPanel myAfterPanel;
private JPanel myBeforePanel;
private JEditorPane myDescriptionBrowser;
public void reset(PostfixTemplateMetaData actionMetaData) {
try {
final TextDescriptor url = actionMetaData.getDescription();
final String description = url == null ? "" : url.getText();
myDescriptionBrowser.setText(description);
showUsages(myBeforePanel, ArrayUtil.getFirstElement(actionMetaData.getExampleUsagesBefore()));
showUsages(myAfterPanel, ArrayUtil.getFirstElement(actionMetaData.getExampleUsagesAfter()));
}
catch (IOException e) {
LOG.error(e);
}
}
private void showUsages(final JPanel panel, @Nullable final TextDescriptor exampleUsage) throws IOException {
boolean createMode = exampleUsage == null || panel.getComponents().length == 0;
if (createMode) {
panel.setLayout(new BorderLayout());
panel.removeAll();
}
if (exampleUsage != null) {
final String name = exampleUsage.getFileName();
final FileTypeManagerEx fileTypeManager = FileTypeManagerEx.getInstanceEx();
final String extension = fileTypeManager.getExtension(name);
final FileType fileType = fileTypeManager.getFileTypeByExtension(extension);
ActionUsagePanel actionUsagePanel;
if (createMode) {
actionUsagePanel = new ActionUsagePanel();
Disposer.register(this, actionUsagePanel);
}
else {
actionUsagePanel = (ActionUsagePanel)panel.getComponent(0);
}
actionUsagePanel.reset(exampleUsage.getText(), fileType);
if (createMode) {
panel.add(actionUsagePanel);
}
}
panel.repaint();
}
JPanel getComponent() {
return myPanel;
}
@Override
public void dispose() {
}
public void init(final int preferredWidth) {
double height =
(myDescriptionBrowser.getSize().getHeight() + myBeforePanel.getSize().getHeight() + myAfterPanel.getSize().getHeight()) / 3;
Dimension newd = new Dimension(preferredWidth, (int)height);
myDescriptionBrowser.setSize(newd);
myDescriptionBrowser.setPreferredSize(newd);
myDescriptionBrowser.setMaximumSize(newd);
myDescriptionBrowser.setMinimumSize(newd);
myBeforePanel.setSize(newd);
myBeforePanel.setPreferredSize(newd);
myBeforePanel.setMaximumSize(newd);
myBeforePanel.setMinimumSize(newd);
myAfterPanel.setSize(newd);
myAfterPanel.setPreferredSize(newd);
myAfterPanel.setMaximumSize(newd);
myAfterPanel.setMinimumSize(newd);
}
}
@@ -0,0 +1,101 @@
/*
* 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.intellij.codeInsight.template.postfix.settings;
import com.intellij.codeInsight.intention.impl.config.BeforeAfterActionMetaData;
import com.intellij.codeInsight.intention.impl.config.TextDescriptor;
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.lang.UrlClassLoader;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
public final class PostfixTemplateMetaData extends BeforeAfterActionMetaData {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.template.postfix.settings.PostfixTemplateMetaData");
private static final String DESCRIPTION_FOLDER = "postfixTemplates";
public static final String KEY = "$key";
private URL urlDir = null;
private PostfixTemplate myTemplate;
public PostfixTemplateMetaData(PostfixTemplate template) {
super(template.getClass().getClassLoader(), template.getClass().getSimpleName());
myTemplate = template;
}
@NotNull
@Override
public TextDescriptor[] getExampleUsagesBefore() {
return decorateTextDescription(super.getExampleUsagesBefore());
}
private TextDescriptor[] decorateTextDescription(TextDescriptor[] before) {
List<TextDescriptor> list = ContainerUtil.newArrayList();
for (final TextDescriptor descriptor : before) {
list.add(new TextDescriptor() {
@Override
public String getText() throws IOException {
return StringUtil.replace(descriptor.getText(), KEY, myTemplate.getKey());
}
@Override
public String getFileName() {
return descriptor.getFileName();
}
});
}
return list.toArray(new TextDescriptor[list.size()]);
}
@NotNull
@Override
public TextDescriptor[] getExampleUsagesAfter() {
return decorateTextDescription(super.getExampleUsagesAfter());
}
@Override
protected URL getDirURL() {
if (urlDir != null) {
return urlDir;
}
final URL pageURL = myLoader.getResource(DESCRIPTION_FOLDER + "/" + myDescriptionDirectoryName + "/" + DESCRIPTION_FILE_NAME);
if (LOG.isDebugEnabled()) {
LOG.debug("Path:" + DESCRIPTION_FOLDER + "/" + myDescriptionDirectoryName);
LOG.debug("URL:" + pageURL);
}
if (pageURL != null) {
try {
final String url = pageURL.toExternalForm();
urlDir = UrlClassLoader.internProtocol(new URL(url.substring(0, url.lastIndexOf('/'))));
return urlDir;
}
catch (MalformedURLException e) {
LOG.error(e);
}
}
return null;
}
}
@@ -16,15 +16,6 @@
<text value="&amp;Enable postfix templates"/>
</properties>
</component>
<grid id="a9fc9" binding="myTemplatesListPanelContainer" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<component id="9f784" class="com.intellij.ui.components.JBCheckBox" binding="myCompletionEnabledCheckbox">
<constraints>
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="1" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
@@ -49,6 +40,34 @@
<model/>
</properties>
</component>
<grid id="1b5f1" layout-manager="GridLayoutManager" row-count="1" 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>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="a9fc9" binding="myTemplatesListPanelContainer" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
<grid id="560dc" binding="myDescriptionPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
</children>
</grid>
</children>
</grid>
</form>
@@ -28,6 +28,7 @@ import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nls;
@@ -37,6 +38,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.util.Comparator;
import java.util.List;
@@ -48,11 +51,14 @@ public class PostfixTemplatesConfigurable implements SearchableConfigurable, Edi
@NotNull
private final PostfixTemplatesSettings myTemplatesSettings;
private final PostfixDescriptionPanel myInnerPostfixDescriptionPanel = new PostfixDescriptionPanel();
private JComponent myPanel;
private JBCheckBox myCompletionEnabledCheckbox;
private JBCheckBox myPostfixTemplatesEnabled;
private JPanel myTemplatesListPanelContainer;
private ComboBox myShortcutComboBox;
private JPanel myDescriptionPanel;
private static final String SPACE = CodeInsightBundle.message("template.shortcut.space");
private static final String TAB = CodeInsightBundle.message("template.shortcut.tab");
@@ -82,7 +88,7 @@ public class PostfixTemplatesConfigurable implements SearchableConfigurable, Edi
});
myTemplatesListPanel = new PostfixTemplatesListPanel(templates);
myTemplatesListPanelContainer.setLayout(new BorderLayout());
myTemplatesListPanelContainer.add(myTemplatesListPanel.getComponent(), BorderLayout.CENTER);
myTemplatesListPanelContainer.add(myTemplatesListPanel.getComponent());
myPostfixTemplatesEnabled.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
@@ -92,6 +98,30 @@ public class PostfixTemplatesConfigurable implements SearchableConfigurable, Edi
myShortcutComboBox.addItem(TAB);
myShortcutComboBox.addItem(SPACE);
myShortcutComboBox.addItem(ENTER);
myDescriptionPanel.setLayout(new BorderLayout());
myDescriptionPanel.add(myInnerPostfixDescriptionPanel.getComponent());
myTemplatesListPanel.addSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
resetDescriptionPanel();
}
});
myDescriptionPanel.setVisible(false);
}
private void resetDescriptionPanel() {
assert myTemplatesListPanel != null;
PostfixTemplate template = myTemplatesListPanel.getTemplate();
if (null != template) {
myDescriptionPanel.setVisible(true);
myInnerPostfixDescriptionPanel.reset(new PostfixTemplateMetaData(template));
}
else {
myDescriptionPanel.setVisible(false);
}
}
@NotNull
@@ -147,6 +177,7 @@ public class PostfixTemplatesConfigurable implements SearchableConfigurable, Edi
myPostfixTemplatesEnabled.setSelected(myTemplatesSettings.isPostfixTemplatesEnabled());
myCompletionEnabledCheckbox.setSelected(myTemplatesSettings.isTemplatesCompletionEnabled());
myShortcutComboBox.setSelectedItem(shortcutToString((char)myTemplatesSettings.getShortcut()));
resetDescriptionPanel();
updateComponents();
}
}
@@ -164,6 +195,7 @@ public class PostfixTemplatesConfigurable implements SearchableConfigurable, Edi
@Override
public void disposeUIResources() {
Disposer.dispose(myInnerPostfixDescriptionPanel);
myTemplatesListPanel = null;
}
@@ -32,6 +32,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.util.Arrays;
@@ -48,24 +49,6 @@ public class PostfixTemplatesListPanel {
}
};
private static final NotNullFunction<PostfixTemplate, String> GET_DESCRIPTION_FUNCTION =
new NotNullFunction<PostfixTemplate, String>() {
@NotNull
@Override
public String fun(@NotNull PostfixTemplate template) {
return template.getDescription();
}
};
private static final NotNullFunction<PostfixTemplate, String> GET_EXAMPLE_FUNCTION =
new NotNullFunction<PostfixTemplate, String>() {
@NotNull
@Override
public String fun(@NotNull PostfixTemplate template) {
return template.getExample();
}
};
@NotNull private final Map<String, Boolean> myTemplatesState = ContainerUtil.newHashMap();
@NotNull private final JPanel myPanelWithTableView;
private final TableView<PostfixTemplate> myTemplatesTableView;
@@ -79,7 +62,7 @@ public class PostfixTemplatesListPanel {
myTemplatesTableView.setAutoCreateRowSorter(true);
myTemplatesTableView.setShowGrid(false);
myTemplatesTableView.setBorder(null);
myTemplatesTableView.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
new TableViewSpeedSearch<PostfixTemplate>(myTemplatesTableView) {
@Override
protected String getItemText(@NotNull PostfixTemplate template) {
@@ -94,21 +77,19 @@ public class PostfixTemplatesListPanel {
.disableUpDownActions().createPanel();
}
public PostfixTemplate getTemplate() {
return ContainerUtil.getFirstItem(myTemplatesTableView.getSelection());
}
@NotNull
private ColumnInfo[] generateColumns(@NotNull List<PostfixTemplate> templates) {
String longestTemplateName = "";
String longestDescription = "";
String longestExample = "";
for (PostfixTemplate template : templates) {
longestTemplateName = longestString(longestTemplateName, GET_SHORTCUT_FUNCTION.fun(template));
longestDescription = longestString(longestDescription, GET_DESCRIPTION_FUNCTION.fun(template));
longestExample = longestString(longestExample, GET_EXAMPLE_FUNCTION.fun(template));
}
return new ColumnInfo[]{
new BooleanColumnInfo(),
new StringColumnInfo("Shortcut", GET_SHORTCUT_FUNCTION, longestTemplateName),
new StringColumnInfo("Description", GET_DESCRIPTION_FUNCTION, longestDescription),
new StringColumnInfo("Example", GET_EXAMPLE_FUNCTION, longestExample),
new StringColumnInfo("Shortcut", GET_SHORTCUT_FUNCTION, longestTemplateName)
};
}
@@ -228,4 +209,8 @@ public class PostfixTemplatesListPanel {
return myValueOfFunction.fun(template);
}
}
public void addSelectionListener(ListSelectionListener listener) {
myTemplatesTableView.getSelectionModel().addListSelectionListener(listener);
}
}
@@ -1,3 +1,18 @@
/*
* 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.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
@@ -7,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
public class AssertStatementPostfixTemplate extends BooleanPostfixTemplate {
public AssertStatementPostfixTemplate() {
super("assert", "Creates assertion from boolean expression", "assert expr;");
super("assert", "assert expr;");
}
@Override
@@ -22,8 +22,8 @@ import com.intellij.psi.PsiExpression;
import org.jetbrains.annotations.NotNull;
abstract public class BooleanPostfixTemplate extends PostfixTemplate {
protected BooleanPostfixTemplate(@NotNull String name, @NotNull String description, @NotNull String example) {
super(name, description, example);
protected BooleanPostfixTemplate(@NotNull String name, @NotNull String example) {
super(name, example);
}
@Override
@@ -1,3 +1,18 @@
/*
* 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.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.generation.surroundWith.JavaWithCastSurrounder;
@@ -8,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
public class CastExpressionPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
public CastExpressionPostfixTemplate() {
super("cast", "Surrounds expression with cast", "((SomeType) expr)");
super("cast", "((SomeType) expr)");
}
@Override
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.NotNull;
public class ElseStatementPostfixTemplate extends BooleanPostfixTemplate {
public ElseStatementPostfixTemplate() {
super("else", "Checks boolean expression to be 'false'", "if (!expr)");
super("else", "if (!expr)");
}
@Override
@@ -38,15 +38,14 @@ import java.util.List;
* @author ignatov
*/
public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTemplate {
protected ExpressionPostfixTemplateWithChooser(@NotNull String name, @NotNull String description, @NotNull String example) {
super(name, description, example);
protected ExpressionPostfixTemplateWithChooser(@NotNull String name, @NotNull String example) {
super(name, example);
}
protected ExpressionPostfixTemplateWithChooser(@NotNull String name,
@NotNull String key,
@NotNull String description,
@NotNull String example) {
super(name, key, description, example);
super(name, key, example);
}
@Override
@@ -1,3 +1,18 @@
/*
* 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.intellij.codeInsight.template.postfix.templates;
import com.intellij.openapi.util.Pair;
@@ -7,7 +22,7 @@ import org.jetbrains.annotations.Nullable;
public class ForAscendingPostfixTemplate extends ForIndexedPostfixTemplate {
public ForAscendingPostfixTemplate() {
super("fori", "Iterates with index over collection", "for (int i = 0; i < expr.length; i++)");
super("fori", "for (int i = 0; i < expr.length; i++)");
}
@Override
@@ -1,3 +1,18 @@
/*
* 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.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
@@ -8,7 +23,7 @@ import org.jetbrains.annotations.Nullable;
public class ForDescendingPostfixTemplate extends ForIndexedPostfixTemplate {
public ForDescendingPostfixTemplate() {
super("forr", "Iterates with index in reverse order", "for (int i = expr.length-1; i >= 0; i--)");
super("forr", "for (int i = expr.length-1; i >= 0; i--)");
}
@Override
@@ -31,8 +31,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class ForIndexedPostfixTemplate extends PostfixTemplate {
protected ForIndexedPostfixTemplate(@NotNull String key, @NotNull String description, @NotNull String example) {
super(key, description, example);
protected ForIndexedPostfixTemplate(@NotNull String key, @NotNull String example) {
super(key, example);
}
@Override
@@ -32,7 +32,7 @@ import org.jetbrains.annotations.NotNull;
public class ForeachPostfixTemplate extends PostfixTemplate {
public ForeachPostfixTemplate() {
super("for", "Iterates over enumerable collection", "for (T item : collection)");
super("for", "for (T item : collection)");
}
@Override
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
public class FormatPostfixTemplate extends PostfixTemplate {
public FormatPostfixTemplate() {
super("format", "Creates String.format call", "String.format(expr);");
super("format", "String.format(expr);");
}
@Override
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
public class IfStatementPostfixTemplate extends BooleanPostfixTemplate {
public IfStatementPostfixTemplate() {
super("if", "Checks boolean expression to be 'true'", "if (expr)");
super("if", "if (expr)");
}
@Override
@@ -41,7 +41,7 @@ public class InstanceofExpressionPostfixTemplate extends PostfixTemplate {
}
public InstanceofExpressionPostfixTemplate(String alias) {
super(alias, "Surrounds expression with instanceof", "expr instanceof SomeType ? ((SomeType) expr). : null");
super(alias, "expr instanceof Type ? ((Type) expr). : null");
}
@Override
@@ -1,3 +1,18 @@
/*
* 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.intellij.codeInsight.template.postfix.templates;
import com.intellij.openapi.application.ApplicationManager;
@@ -10,7 +25,7 @@ import org.jetbrains.annotations.NotNull;
public class IntroduceFieldPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
public IntroduceFieldPostfixTemplate() {
super("field", "Introduces field for expression", "myField = expr;");
super("field", "myField = expr;");
}
@Override
@@ -1,3 +1,18 @@
/*
* 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.intellij.codeInsight.template.postfix.templates;
import com.intellij.openapi.application.ApplicationManager;
@@ -16,7 +31,7 @@ import org.jetbrains.annotations.NotNull;
// todo: support for int[].var (parses as .class access!)
public class IntroduceVariablePostfixTemplate extends ExpressionPostfixTemplateWithChooser {
public IntroduceVariablePostfixTemplate() {
super("var", "Introduces variable for expression", "T name = expr;");
super("var", "T name = expr;");
}
@Override
@@ -1,10 +1,25 @@
/*
* 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.intellij.codeInsight.template.postfix.templates;
import org.jetbrains.annotations.NotNull;
public class IsNullCheckPostfixTemplate extends NullCheckPostfixTemplate {
public IsNullCheckPostfixTemplate() {
super("null", "Checks expression to be null", "if (expr == null)");
super("null", "if (expr == null)");
}
@NotNull
@@ -22,8 +22,8 @@ import com.intellij.psi.PsiExpression;
import org.jetbrains.annotations.NotNull;
abstract public class NonVoidPostfixTemplate extends PostfixTemplate {
protected NonVoidPostfixTemplate(@NotNull String name, @NotNull String description, @NotNull String example) {
super(name, description, example);
protected NonVoidPostfixTemplate(@NotNull String name, @NotNull String example) {
super(name, example);
}
@Override
@@ -31,11 +31,11 @@ public class NotExpressionPostfixTemplate extends ExpressionPostfixTemplateWithC
};
public NotExpressionPostfixTemplate() {
super("not", "Negates boolean expression", "!expr");
super("not", "!expr");
}
public NotExpressionPostfixTemplate(String alias) {
super(alias, alias, "Negates boolean expression", "!expr");
super(alias, alias, "!expr");
}
@Override
@@ -24,7 +24,7 @@ public class NotNullCheckPostfixTemplate extends NullCheckPostfixTemplate {
}
public NotNullCheckPostfixTemplate(String alias) {
super(alias, "Checks expression to be not-null", "if (expr != null)");
super(alias, "if (expr != null)");
}
@NotNull
@@ -30,8 +30,8 @@ import org.jetbrains.annotations.NotNull;
* @author ignatov
*/
public abstract class NullCheckPostfixTemplate extends PostfixTemplate {
protected NullCheckPostfixTemplate(@NotNull String name, @NotNull String description, @NotNull String example) {
super(name, description, example);
protected NullCheckPostfixTemplate(@NotNull String name, @NotNull String example) {
super(name, example);
}
@NotNull
@@ -1,3 +1,18 @@
/*
* 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.intellij.codeInsight.template.postfix.templates;
import com.intellij.openapi.editor.Editor;
@@ -9,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
public class ParenthesizedExpressionPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
public ParenthesizedExpressionPostfixTemplate() {
super("par", "Parenthesizes expression", "(expression)");
super("par", "(expression)");
}
@Override
@@ -15,27 +15,36 @@
*/
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.settings.PostfixTemplateMetaData;
import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public abstract class PostfixTemplate {
@NotNull private final String myPresentableName;
@NotNull private final String myKey;
@NotNull private final String myDescription;
@NotNull private final String myExample;
protected PostfixTemplate(@NotNull String name, @NotNull String description, @NotNull String example) {
this(name, "." + name, description, example);
protected PostfixTemplate(@NotNull String name, @NotNull String example) {
this(name, "." + name, example);
}
protected PostfixTemplate(@NotNull String name, @NotNull String key, @NotNull String description, @NotNull String example) {
protected PostfixTemplate(@NotNull String name, @NotNull String key, @NotNull String example) {
myPresentableName = name;
myKey = key;
myDescription = description;
myExample = example;
try {
myDescription = new PostfixTemplateMetaData(this).getDescription().getText();
}
catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@NotNull
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
public class ReturnStatementPostfixTemplate extends NonVoidPostfixTemplate {
public ReturnStatementPostfixTemplate() {
super("return", "Returns value from containing method", "return expr;");
super("return", "return expr;");
}
@Override
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
public class SoutPostfixTemplate extends NonVoidPostfixTemplate {
public SoutPostfixTemplate() {
super("sout", "Creates System.out.println call", "System.out.println(expr);");
super("sout", "System.out.println(expr);");
}
@Override
@@ -28,8 +28,8 @@ import com.intellij.psi.util.PsiTreeUtil;
* @author ignatov
*/
public abstract class StatementPostfixTemplateBase extends PostfixTemplate {
protected StatementPostfixTemplateBase(String name, String description, String example) {
super(name, description, example);
protected StatementPostfixTemplateBase(String name, String example) {
super(name, example);
}
protected void surroundWith(PsiElement context, Editor editor, String text) {
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable;
public class SwitchStatementPostfixTemplate extends StatementPostfixTemplateBase {
public SwitchStatementPostfixTemplate() {
super("switch", "Produces switch over integral/enum/string values", "switch (expr)");
super("switch", "switch (expr)");
}
private static boolean isSwitchCompatibleType(@Nullable PsiType type, @NotNull PsiElement context) {
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
public class SynchronizedStatementPostfixTemplate extends StatementPostfixTemplateBase {
public SynchronizedStatementPostfixTemplate() {
super("synchronized", "Produces synchronization statement", "synchronized (expr)");
super("synchronized", "synchronized (expr)");
}
@Override
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
public class ThrowExceptionPostfixTemplate extends PostfixTemplate {
public ThrowExceptionPostfixTemplate() {
super("throw", "Throws expression of 'Throwable' type", "throw expr;");
super("throw", "throw expr;");
}
@Override
@@ -29,7 +29,7 @@ import org.jetbrains.annotations.NotNull;
public class TryStatementPostfixTemplate extends PostfixTemplate {
protected TryStatementPostfixTemplate() {
super("try", "Insert statement in try-catch block", "try { exp } catch (Exception e) { e.printStackTrace(); }");
super("try", "try { exp } catch(Ex e) { e.printStackTrace(); }");
}
@Override
@@ -38,7 +38,7 @@ import java.util.Collections;
public class TryWithResourcesPostfixTemplate extends PostfixTemplate {
protected TryWithResourcesPostfixTemplate() {
super("twr", "Description", "Example");
super("twr", "try(Type f = new Type()) {} catch (Ex e) {}");
}
@Override
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
public class WhileStatementPostfixTemplate extends BooleanPostfixTemplate {
public WhileStatementPostfixTemplate() {
super("while", "Iterating while boolean statement is 'true'", "while (expr)");
super("while", "while (expr)");
}
@Override
@@ -0,0 +1,146 @@
/*
* 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.intellij.codeInsight.intention.impl.config;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.DocumentUtil;
import com.intellij.util.ui.RangeBlinker;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class ActionUsagePanel extends JPanel implements Disposable {
@NonNls private static final String SPOT_MARKER = "spot";
protected final EditorEx myEditor;
protected final RangeBlinker myRangeBlinker;
public ActionUsagePanel() {
myEditor = (EditorEx)createEditor("", 10, 3, -1);
setLayout(new BorderLayout());
add(myEditor.getComponent(), BorderLayout.CENTER);
TextAttributes blinkAttributes =
EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.BLINKING_HIGHLIGHTS_ATTRIBUTES);
myRangeBlinker = new RangeBlinker(myEditor, blinkAttributes, Integer.MAX_VALUE);
}
protected static Editor createEditor(String text, int column, int line, int selectedLine) {
EditorFactory editorFactory = EditorFactory.getInstance();
Document editorDocument = editorFactory.createDocument(text);
EditorEx editor = (EditorEx)editorFactory.createViewer(editorDocument);
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
editor.setColorsScheme(scheme);
EditorSettings settings = editor.getSettings();
settings.setWhitespacesShown(true);
settings.setLineMarkerAreaShown(false);
settings.setIndentGuidesShown(false);
settings.setFoldingOutlineShown(false);
settings.setAdditionalColumnsCount(0);
settings.setAdditionalLinesCount(0);
settings.setRightMarginShown(true);
settings.setRightMargin(60);
LogicalPosition pos = new LogicalPosition(line, column);
editor.getCaretModel().moveToLogicalPosition(pos);
if (selectedLine >= 0) {
editor.getSelectionModel().setSelection(editorDocument.getLineStartOffset(selectedLine),
editorDocument.getLineEndOffset(selectedLine));
}
return editor;
}
public void reset(final String usageText, final FileType fileType) {
reinitViews();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (myEditor.isDisposed()) return;
DocumentUtil.writeInRunUndoTransparentAction(new Runnable() {
@Override
public void run() {
configureByText(usageText, fileType);
}
});
}
});
}
private void configureByText(final String usageText, FileType fileType) {
Document document = myEditor.getDocument();
String text = StringUtil.convertLineSeparators(usageText);
document.replaceString(0, document.getTextLength(), text);
final EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
myEditor.setHighlighter(EditorHighlighterFactory.getInstance().createEditorHighlighter(fileType, scheme, null));
setupSpots(document);
}
private void setupSpots(Document document) {
List<Segment> markers = new ArrayList<Segment>();
while (true) {
String text = document.getText();
final int spotStart = text.indexOf("<" + SPOT_MARKER + ">");
if (spotStart < 0) break;
final int spotEnd = text.indexOf("</" + SPOT_MARKER + ">", spotStart);
if (spotEnd < 0) break;
document.deleteString(spotEnd, spotEnd + SPOT_MARKER.length() + 3);
document.deleteString(spotStart, spotStart + SPOT_MARKER.length() + 2);
Segment spotMarker = new Segment() {
@Override
public int getStartOffset() {
return spotStart;
}
@Override
public int getEndOffset() {
return spotEnd - SPOT_MARKER.length() - 2;
}
};
markers.add(spotMarker);
}
myRangeBlinker.resetMarkers(markers);
if (!markers.isEmpty()) {
myRangeBlinker.startBlinking();
}
}
@Override
public void dispose() {
myRangeBlinker.stopBlinking();
EditorFactory editorFactory = EditorFactory.getInstance();
editorFactory.releaseEditor(myEditor);
}
private void reinitViews() {
myEditor.reinitSettings();
myEditor.getMarkupModel().removeAllHighlighters();
}
}
@@ -0,0 +1,163 @@
/*
* 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.intellij.codeInsight.intention.impl.config;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public abstract class BeforeAfterActionMetaData {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.config.BeforeAfterActionMetaData");
@NonNls protected static final String DESCRIPTION_FILE_NAME = "description.html";
@NonNls static final String EXAMPLE_USAGE_URL_SUFFIX = ".template";
@NonNls private static final String BEFORE_TEMPLATE_PREFIX = "before";
@NonNls private static final String AFTER_TEMPLATE_PREFIX = "after";
protected final ClassLoader myLoader;
protected final String myDescriptionDirectoryName;
protected TextDescriptor[] myExampleUsagesBefore = null;
protected TextDescriptor[] myExampleUsagesAfter = null;
protected TextDescriptor myDescription = null;
public BeforeAfterActionMetaData(ClassLoader loader, String descriptionDirectoryName) {
myLoader = loader;
myDescriptionDirectoryName = descriptionDirectoryName;
}
public BeforeAfterActionMetaData(final TextDescriptor description,
final TextDescriptor[] exampleUsagesBefore,
final TextDescriptor[] exampleUsagesAfter) {
myLoader = null;
myDescriptionDirectoryName = null;
myExampleUsagesBefore = exampleUsagesBefore;
myExampleUsagesAfter = exampleUsagesAfter;
myDescription = description;
}
@NotNull
private static TextDescriptor[] retrieveURLs(@NotNull URL descriptionDirectory, @NotNull String prefix, @NotNull String suffix)
throws MalformedURLException {
List<TextDescriptor> urls = new ArrayList<TextDescriptor>();
final FileType[] fileTypes = FileTypeManager.getInstance().getRegisteredFileTypes();
for (FileType fileType : fileTypes) {
final String[] extensions = FileTypeManager.getInstance().getAssociatedExtensions(fileType);
for (String extension : extensions) {
for (int i = 0; ; i++) {
URL url = new URL(descriptionDirectory.toExternalForm() + "/" +
prefix + "." + extension + (i == 0 ? "" : Integer.toString(i)) +
suffix);
try {
InputStream inputStream = url.openStream();
inputStream.close();
urls.add(new ResourceTextDescriptor(url));
}
catch (IOException ioe) {
break;
}
}
}
}
if (urls.isEmpty()) {
String[] children;
Exception cause = null;
try {
URI uri = descriptionDirectory.toURI();
children = uri.isOpaque() ? null : ObjectUtils.notNull(new File(uri).list(), ArrayUtil.EMPTY_STRING_ARRAY);
}
catch (URISyntaxException e) {
cause = e;
children = null;
}
catch (IllegalArgumentException e) {
cause = e;
children = null;
}
LOG.error("URLs not found for available file types and prefix: '" +
prefix +
"', suffix: '" +
suffix +
"';" +
" in directory: '" +
descriptionDirectory +
"'" +
(children == null ? "" : "; directory contents: " + Arrays.asList(children)), cause);
return new TextDescriptor[0];
}
return urls.toArray(new TextDescriptor[urls.size()]);
}
@NotNull
public TextDescriptor[] getExampleUsagesBefore() {
if (myExampleUsagesBefore == null) {
try {
myExampleUsagesBefore = retrieveURLs(getDirURL(), BEFORE_TEMPLATE_PREFIX, EXAMPLE_USAGE_URL_SUFFIX);
}
catch (MalformedURLException e) {
LOG.error(e);
}
}
return myExampleUsagesBefore;
}
@NotNull
public TextDescriptor[] getExampleUsagesAfter() {
if (myExampleUsagesAfter == null) {
try {
myExampleUsagesAfter = retrieveURLs(getDirURL(), AFTER_TEMPLATE_PREFIX, EXAMPLE_USAGE_URL_SUFFIX);
}
catch (MalformedURLException e) {
LOG.error(e);
}
}
return myExampleUsagesAfter;
}
@NotNull
public TextDescriptor getDescription() {
if (myDescription == null) {
try {
final URL dirURL = getDirURL();
URL descriptionURL = new URL(dirURL.toExternalForm() + "/" + DESCRIPTION_FILE_NAME);
myDescription = new ResourceTextDescriptor(descriptionURL);
}
catch (MalformedURLException e) {
LOG.error(e);
}
}
return myDescription;
}
protected abstract URL getDirURL();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -23,54 +23,30 @@ import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.ide.plugins.cl.PluginClassLoader;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.lang.UrlClassLoader;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public final class IntentionActionMetaData {
public final class IntentionActionMetaData extends BeforeAfterActionMetaData {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.config.IntentionActionMetaData");
@NotNull private final IntentionAction myAction;
private final ClassLoader myIntentionLoader;
private final String myDescriptionDirectoryName;
@NotNull public final String[] myCategory;
private TextDescriptor[] myExampleUsagesBefore = null;
private TextDescriptor[] myExampleUsagesAfter = null;
private TextDescriptor myDescription = null;
private URL myDirURL = null;
@NonNls private static final String BEFORE_TEMPLATE_PREFIX = "before";
@NonNls private static final String AFTER_TEMPLATE_PREFIX = "after";
@NonNls static final String EXAMPLE_USAGE_URL_SUFFIX = ".template";
@NonNls private static final String DESCRIPTION_FILE_NAME = "description.html";
@NonNls private static final String INTENTION_DESCRIPTION_FOLDER = "intentionDescriptions";
public IntentionActionMetaData(@NotNull IntentionAction action,
@Nullable ClassLoader loader,
@NotNull String[] category,
@NotNull String descriptionDirectoryName) {
super(loader, descriptionDirectoryName);
myAction = action;
myIntentionLoader = loader;
myCategory = category;
myDescriptionDirectoryName = descriptionDirectoryName;
}
public IntentionActionMetaData(@NotNull final IntentionAction action,
@@ -78,110 +54,22 @@ public final class IntentionActionMetaData {
final TextDescriptor description,
final TextDescriptor[] exampleUsagesBefore,
final TextDescriptor[] exampleUsagesAfter) {
super(description, exampleUsagesBefore, exampleUsagesAfter);
myAction = action;
myCategory = category;
myExampleUsagesBefore = exampleUsagesBefore;
myExampleUsagesAfter = exampleUsagesAfter;
myDescription = description;
myIntentionLoader = null;
myDescriptionDirectoryName = null;
}
public String toString() {
return getFamily();
}
@NotNull
public TextDescriptor[] getExampleUsagesBefore() {
if(myExampleUsagesBefore == null){
try {
myExampleUsagesBefore = retrieveURLs(getDirURL(), BEFORE_TEMPLATE_PREFIX, EXAMPLE_USAGE_URL_SUFFIX);
}
catch (MalformedURLException e) {
LOG.error(e);
}
}
return myExampleUsagesBefore;
}
@NotNull
public TextDescriptor[] getExampleUsagesAfter() {
if(myExampleUsagesAfter == null){
try {
myExampleUsagesAfter = retrieveURLs(getDirURL(), AFTER_TEMPLATE_PREFIX, EXAMPLE_USAGE_URL_SUFFIX);
}
catch (MalformedURLException e) {
LOG.error(e);
}
}
return myExampleUsagesAfter;
}
@NotNull
public TextDescriptor getDescription() {
if(myDescription == null){
try {
final URL dirURL = getDirURL();
URL descriptionURL = new URL(dirURL.toExternalForm() + "/" + DESCRIPTION_FILE_NAME);
myDescription = new ResourceTextDescriptor(descriptionURL);
}
catch (MalformedURLException e) {
LOG.error(e);
}
}
return myDescription;
}
@NotNull
private static TextDescriptor[] retrieveURLs(@NotNull URL descriptionDirectory, @NotNull String prefix, @NotNull String suffix) throws MalformedURLException {
List<TextDescriptor> urls = new ArrayList<TextDescriptor>();
final FileType[] fileTypes = FileTypeManager.getInstance().getRegisteredFileTypes();
for (FileType fileType : fileTypes) {
final String[] extensions = FileTypeManager.getInstance().getAssociatedExtensions(fileType);
for (String extension : extensions) {
for (int i = 0; ; i++) {
URL url = new URL(descriptionDirectory.toExternalForm() + "/" +
prefix + "." + extension + (i == 0 ? "" : Integer.toString(i)) +
suffix);
try {
InputStream inputStream = url.openStream();
inputStream.close();
urls.add(new ResourceTextDescriptor(url));
}
catch (IOException ioe) {
break;
}
}
}
}
if (urls.isEmpty()) {
String[] children;
Exception cause = null;
try {
URI uri = descriptionDirectory.toURI();
children = uri.isOpaque()? null : ObjectUtils.notNull(new File(uri).list(), ArrayUtil.EMPTY_STRING_ARRAY);
}
catch (URISyntaxException e) {
cause = e;
children = null;
}
catch (IllegalArgumentException e) {
cause = e;
children = null;
}
LOG.error("URLs not found for available file types and prefix: '"+prefix+"', suffix: '"+suffix+"';" +
" in directory: '"+descriptionDirectory+ "'" + (children == null? "" : "; directory contents: "+ Arrays.asList(children)), cause);
return new TextDescriptor[0];
}
return urls.toArray(new TextDescriptor[urls.size()]);
}
@Nullable
private static URL getIntentionDescriptionDirURL(ClassLoader aClassLoader, String intentionFolderName) {
final URL pageURL = aClassLoader.getResource(INTENTION_DESCRIPTION_FOLDER + "/" + intentionFolderName+"/"+ DESCRIPTION_FILE_NAME);
final URL pageURL = aClassLoader.getResource(INTENTION_DESCRIPTION_FOLDER + "/" + intentionFolderName + "/" + DESCRIPTION_FILE_NAME);
if (LOG.isDebugEnabled()) {
LOG.debug("Path:"+"intentionDescriptions/" + intentionFolderName);
LOG.debug("URL:"+pageURL);
LOG.debug("Path:" + "intentionDescriptions/" + intentionFolderName);
LOG.debug("URL:" + pageURL);
}
if (pageURL != null) {
try {
@@ -195,21 +83,10 @@ public final class IntentionActionMetaData {
return null;
}
private URL getDirURL() {
if (myDirURL == null) {
myDirURL = getIntentionDescriptionDirURL(myIntentionLoader, myDescriptionDirectoryName);
}
if (myDirURL == null) { //plugin compatibility
myDirURL = getIntentionDescriptionDirURL(myIntentionLoader, getFamily());
}
LOG.assertTrue(myDirURL != null, "Intention Description Dir URL is null: " +
getFamily() +"; "+myDescriptionDirectoryName + ", " + myIntentionLoader);
return myDirURL;
}
@Nullable public PluginId getPluginId() {
if (myIntentionLoader instanceof PluginClassLoader) {
return ((PluginClassLoader)myIntentionLoader).getPluginId();
@Nullable
public PluginId getPluginId() {
if (myLoader instanceof PluginClassLoader) {
return ((PluginClassLoader)myLoader).getPluginId();
}
return null;
}
@@ -223,4 +100,16 @@ public final class IntentionActionMetaData {
public IntentionAction getAction() {
return myAction;
}
protected URL getDirURL() {
if (myDirURL == null) {
myDirURL = getIntentionDescriptionDirURL(myLoader, myDescriptionDirectoryName);
}
if (myDirURL == null) { //plugin compatibility
myDirURL = getIntentionDescriptionDirURL(myLoader, getFamily());
}
LOG.assertTrue(myDirURL != null, "Intention Description Dir URL is null: " +
getFamily() + "; " + myDescriptionDirectoryName + ", " + myLoader);
return myDirURL;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -19,128 +19,7 @@
*/
package com.intellij.codeInsight.intention.impl.config;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.DocumentUtil;
import com.intellij.util.ui.RangeBlinker;
import org.jetbrains.annotations.NonNls;
class IntentionUsagePanel extends ActionUsagePanel {
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
class IntentionUsagePanel extends JPanel{
private final EditorEx myEditor;
@NonNls private static final String SPOT_MARKER = "spot";
private final RangeBlinker myRangeBlinker;
public IntentionUsagePanel() {
myEditor = (EditorEx)createEditor("", 10, 3, -1);
setLayout(new BorderLayout());
add(myEditor.getComponent(), BorderLayout.CENTER);
TextAttributes blinkAttributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.BLINKING_HIGHLIGHTS_ATTRIBUTES);
myRangeBlinker = new RangeBlinker(myEditor, blinkAttributes, Integer.MAX_VALUE);
}
public void reset(final String usageText, final FileType fileType) {
reinitViews();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (myEditor.isDisposed()) return;
DocumentUtil.writeInRunUndoTransparentAction(new Runnable() {
@Override
public void run() {
configureByText(usageText, fileType);
}
});
}
});
}
private void configureByText(final String usageText, FileType fileType) {
Document document = myEditor.getDocument();
String text = StringUtil.convertLineSeparators(usageText);
document.replaceString(0, document.getTextLength(), text);
final EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
myEditor.setHighlighter(EditorHighlighterFactory.getInstance().createEditorHighlighter(fileType, scheme, null));
setupSpots(document);
}
private void setupSpots(Document document) {
List<Segment> markers = new ArrayList<Segment>();
while (true) {
String text = document.getText();
final int spotStart = text.indexOf("<" + SPOT_MARKER + ">");
if (spotStart < 0) break;
final int spotEnd = text.indexOf("</" + SPOT_MARKER + ">", spotStart);
if (spotEnd < 0) break;
document.deleteString(spotEnd, spotEnd + SPOT_MARKER.length() + 3);
document.deleteString(spotStart, spotStart + SPOT_MARKER.length() + 2);
Segment spotMarker = new Segment() {
@Override
public int getStartOffset() {
return spotStart;
}
@Override
public int getEndOffset() {
return spotEnd - SPOT_MARKER.length() - 2;
}
};
markers.add(spotMarker);
}
myRangeBlinker.resetMarkers(markers);
if (!markers.isEmpty()) {
myRangeBlinker.startBlinking();
}
}
public void dispose() {
myRangeBlinker.stopBlinking();
EditorFactory editorFactory = EditorFactory.getInstance();
editorFactory.releaseEditor(myEditor);
}
private void reinitViews() {
myEditor.reinitSettings();
myEditor.getMarkupModel().removeAllHighlighters();
}
private static Editor createEditor(String text, int column, int line, int selectedLine) {
EditorFactory editorFactory = EditorFactory.getInstance();
Document editorDocument = editorFactory.createDocument(text);
EditorEx editor = (EditorEx)editorFactory.createViewer(editorDocument);
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
editor.setColorsScheme(scheme);
EditorSettings settings = editor.getSettings();
settings.setWhitespacesShown(true);
settings.setLineMarkerAreaShown(false);
settings.setIndentGuidesShown(false);
settings.setFoldingOutlineShown(false);
settings.setAdditionalColumnsCount(0);
settings.setAdditionalLinesCount(0);
settings.setRightMarginShown(true);
settings.setRightMargin(60);
LogicalPosition pos = new LogicalPosition(line, column);
editor.getCaretModel().moveToLogicalPosition(pos);
if (selectedLine >= 0) {
editor.getSelectionModel().setSelection(editorDocument.getLineStartOffset(selectedLine),
editorDocument.getLineEndOffset(selectedLine));
}
return editor;
}
}
@@ -0,0 +1,3 @@
public void m(boolean value) {
assert value;
}
@@ -0,0 +1,3 @@
public void m(boolean value) {
<spot>value</spot>$key
}
@@ -0,0 +1,5 @@
<html>
<body>
Creates assertion from boolean expression.
</body>
</html>
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
((<spot></spot>) o)
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
<spot>o</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Surrounds expression with cast.
</body>
</html>
@@ -0,0 +1,7 @@
public class Foo {
void m(boolean b) {
if (!b) {
}
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(boolean b) {
<spot>b</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Checks boolean expression to be 'false'.
</body>
</html>
@@ -0,0 +1,8 @@
public class Foo {
void m() {
int foo = 100;
for (int i = 0; i < foo; i++) {
}
}
}
@@ -0,0 +1,6 @@
public class Foo {
void m() {
int foo = 100;
<spot>foo</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Iterates with index over collection.
</body>
</html>
@@ -0,0 +1,8 @@
public class Foo {
void m() {
int foo = 100;
for (int i = foo; i > 0; i--) {
}
}
}
@@ -0,0 +1,6 @@
public class Foo {
void m() {
int foo = 100;
<spot>foo</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Iterates with index in reverse order.
</body>
</html>
@@ -0,0 +1,8 @@
public class Foo {
void m() {
int[] values = {1, 2, 3};
for (int value : values) {
}
}
}
@@ -0,0 +1,6 @@
public class Foo {
void m() {
int[] values = {1, 2, 3};
<spot>values</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Iterates over enumerable collection.
</body>
</html>
@@ -0,0 +1,3 @@
public void m(String value) {
String.format(value, <spot></spot>);
}
@@ -0,0 +1,6 @@
public class Foo {
void m() {
int foo = 100;
<spot>foo</spot>.fori
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Creates String.format call.
</body>
</html>
@@ -0,0 +1,7 @@
public class Foo {
void m(boolean b) {
if (b) {
}
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(boolean b) {
<spot>b</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Checks boolean expression to be 'true'.
</body>
</html>
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
o instanceof <spot></spot> ? ((<spot></spot>) o) : null;
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
<spot>o</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Surrounds expression with instanceof.
</body>
</html>
@@ -0,0 +1,7 @@
public class Foo {
private int foo;
public Foo(int arg) {
foo = arg;
}
}
@@ -0,0 +1,5 @@
public class Foo {
public Foo(int arg) {
<spot>arg</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Introduces field for expression.
</body>
</html>
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
boolean foo = o instanceof String;
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
<spot>o instanceof String</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Introduces variable for expression.
</body>
</html>
@@ -0,0 +1,7 @@
public class Foo {
void m(Object o) {
if (o == null){
}
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
<spot>o</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Checks expression to be null.
</body>
</html>
@@ -0,0 +1,5 @@
public class Foo {
void m(boolean b) {
m(!b);
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(boolean b) {
m(<spot>b</spot>$key);
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Negates boolean expression.
</body>
</html>
@@ -0,0 +1,7 @@
public class Foo {
void m(Object o) {
if (o != null){
}
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
<spot>o</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Checks expression to be not-null.
</body>
</html>
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
(o)
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
<spot>o</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Parenthesizes expression.
</body>
</html>
@@ -0,0 +1,5 @@
public class Foo {
String m() {
return "result";
}
}
@@ -0,0 +1,5 @@
public class Foo {
String m() {
<spot>"result"</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Returns value from containing method.
</body>
</html>
@@ -0,0 +1,5 @@
public class Foo {
void m(boolean b) {
System.out.println(b);
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(boolean b) {
<spot>b</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Creates System.out.println call.
</body>
</html>
@@ -0,0 +1,9 @@
public enum Foo {
A, B, C;
void f(Foo foo) {
switch (foo) {
}
}
}
@@ -0,0 +1,7 @@
public enum Foo {
A, B, C;
void f(Foo foo) {
<spot>foo</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Produces switch over integral/enum/string values.
</body>
</html>
@@ -0,0 +1,7 @@
public class Foo {
void m(Object o) {
synchronized (o) {
}
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m(Object o) {
<spot>o</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Produces synchronization statement.
</body>
</html>
@@ -0,0 +1,5 @@
public class Foo {
void m() {
throw new RuntimeException("error");
}
}
@@ -0,0 +1,5 @@
public class Foo {
void m() {
<spot>new RuntimeException("error")</spot>$key
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Throws expression of 'Throwable' type.
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More