Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2013-01-21 14:04:16 +04:00
52 changed files with 514 additions and 371 deletions
Binary file not shown.
Binary file not shown.
@@ -263,6 +263,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
else {
profile.enableTool(id);
}
assertEquals(0, countInitializedTools(profile));
profile.writeExternal(new Element("profile"));
List<InspectionProfileEntry> initializedTools = getInitializedTools(profile);
if (initializedTools.size() != 1) {
+6 -3
View File
@@ -104,7 +104,6 @@ int main(int argc, char** argv) {
}
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
roots = array_create(20);
if (init_inotify() && roots != NULL) {
@@ -120,7 +119,7 @@ int main(int argc, char** argv) {
unregister_roots();
}
else {
printf("GIVEUP\n");
output("GIVEUP\n");
}
close_inotify();
array_delete(roots);
@@ -430,7 +429,7 @@ static void report_event(char* event, char* path) {
userlog(LOG_DEBUG, "%s: %s", event, path);
int len = strlen(path);
for (char* p = path; *p != '\0'; p++){
for (char* p = path; *p != '\0'; p++) {
if (*p == '\n') {
*p = '\0';
}
@@ -440,6 +439,8 @@ static void report_event(char* event, char* path) {
fputc('\n', stdout);
fwrite(path, len, 1, stdout);
fputc('\n', stdout);
fflush(stdout);
}
@@ -452,4 +453,6 @@ static void output(const char* format, ...) {
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
fflush(stdout);
}
+1 -1
View File
@@ -24,7 +24,7 @@ static void reportEvent(char *event, char *path) {
int len = 0;
if (path != NULL) {
len = strlen(path);
for (char* p = path; *p != '\0'; p++){
for (char* p = path; *p != '\0'; p++) {
if (*p == '\n') {
*p = '\0';
}
@@ -51,7 +51,7 @@ public abstract class ProgressIndicatorProvider {
};
}
public static boolean ourNeedToCheckCancel = false;
public static volatile boolean ourNeedToCheckCancel = false;
public static void checkCanceled() throws ProcessCanceledException {
// smart optimization! There's a thread started in ProgressManagerImpl, that set's this flag up once in 10 milliseconds
if (ourNeedToCheckCancel && ourInstance != null) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -124,23 +124,22 @@ public class LookupCellRenderer implements ListCellRenderer {
myIsSelected = isSelected;
final LookupElement item = (LookupElement)value;
final boolean dark = UIUtil.isUnderDarcula();
final Color foreground = getForegroundColor(isSelected);
final Color background = isSelected ? SELECTED_BACKGROUND_COLOR : dark ? BACKGROUND_COLOR_DARK_VARIANT : BACKGROUND_COLOR;
final Color background = isSelected ? SELECTED_BACKGROUND_COLOR : new JBColor(BACKGROUND_COLOR, BACKGROUND_COLOR_DARK_VARIANT);
int allowedWidth = list.getWidth() - AFTER_TAIL - AFTER_TYPE - getIconIndent();
final LookupElementPresentation presentation = new RealLookupElementPresentation(isSelected ? getMaxWidth() : allowedWidth, myNormalMetrics, myBoldMetrics, myLookup);
if (item.isValid()) {
item.renderElement(presentation);
} else {
presentation.setItemTextForeground(Color.RED);
presentation.setItemTextForeground(JBColor.RED);
presentation.setItemText("Invalid");
}
myNameComponent.clear();
myNameComponent.setIcon(augmentIcon(presentation.getIcon(), myEmptyIcon));
myNameComponent.setBackground(background);
allowedWidth -= setItemTextLabel(item, dark ? foreground : isSelected ? SELECTED_FOREGROUND_COLOR : presentation.getItemTextForeground(), isSelected, presentation, allowedWidth);
allowedWidth -= setItemTextLabel(item, new JBColor(isSelected ? SELECTED_FOREGROUND_COLOR : presentation.getItemTextForeground(), foreground), isSelected, presentation, allowedWidth);
myTypeLabel.clear();
if (allowedWidth > 0) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -35,10 +35,15 @@ import com.intellij.openapi.command.undo.DocumentReferenceManager;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.editor.markup.HighlighterLayer;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
@@ -59,9 +64,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.*;
import java.util.List;
public class TemplateState implements Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.template.impl.TemplateState");
@@ -969,7 +972,8 @@ public class TemplateState implements Disposable {
}
private RangeHighlighter getSegmentHighlighter(int segmentNumber, boolean isSelected, boolean isEnd) {
TextAttributes attributes = isSelected ? new TextAttributes(null, null, Color.red, EffectType.BOXED, Font.PLAIN) : new TextAttributes();
final TextAttributes lvAttr = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.LIVE_TEMPLATE_ATTRIBUTES);
TextAttributes attributes = isSelected ? lvAttr : new TextAttributes();
TextAttributes endAttributes = new TextAttributes();
int start = mySegments.getSegmentStart(segmentNumber);
@@ -22,6 +22,7 @@ import com.intellij.ide.structureView.impl.StructureViewFactoryImpl;
import com.intellij.ide.structureView.impl.StructureViewState;
import com.intellij.ide.structureView.impl.common.PsiTreeElementBase;
import com.intellij.ide.ui.customization.CustomizationUtil;
import com.intellij.ide.util.FileStructurePopup;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.AbstractTreeStructure;
import com.intellij.ide.util.treeView.NodeDescriptorProvidingKey;
@@ -52,6 +53,7 @@ import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
import com.intellij.util.EditSourceOnDoubleClickHandler;
import com.intellij.util.OpenSourceUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.tree.TreeUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
@@ -182,7 +184,17 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre
myAutoScrollFromSourceHandler.install();
TreeUtil.installActions(getTree());
new TreeSpeedSearch(getTree());
new TreeSpeedSearch(getTree(), new Convertor<TreePath, String>() {
public String convert(final TreePath treePath) {
final DefaultMutableTreeNode node = (DefaultMutableTreeNode)treePath.getLastPathComponent();
final Object userObject = node.getUserObject();
if (userObject != null) {
return FileStructurePopup.getSpeedSearchText(userObject);
}
return null;
}
});
addTreeKeyListener();
addTreeMouseListeners();
@@ -626,7 +638,7 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre
return myAbstractTreeBuilder.getTreeStructure();
}
public JTree getTree() {
public Tree getTree() {
return myTree;
}
@@ -29,6 +29,7 @@ import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.NodeRenderer;
import com.intellij.ide.util.treeView.smartTree.*;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.LocationPresentation;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.MnemonicHelper;
import com.intellij.openapi.actionSystem.*;
@@ -771,27 +772,38 @@ public class FileStructurePopup implements Disposable {
}
@Nullable
private static String getText(final Object node) {
String text = String.valueOf(node);
public static String getSpeedSearchText(final Object userObject) {
String text = String.valueOf(userObject);
if (text != null) {
if (node instanceof StructureViewComponent.StructureViewTreeElementWrapper) {
final TreeElement value = ((StructureViewComponent.StructureViewTreeElementWrapper)node).getValue();
if (userObject instanceof StructureViewComponent.StructureViewTreeElementWrapper) {
final TreeElement value = ((StructureViewComponent.StructureViewTreeElementWrapper)userObject).getValue();
if (value instanceof PsiTreeElementBase && ((PsiTreeElementBase)value).isSearchInLocationString()) {
final String string = ((PsiTreeElementBase)value).getLocationString();
if (!StringUtil.isEmpty(string)) {
return text + " (" + string + ")";
final String locationString = ((PsiTreeElementBase)value).getLocationString();
if (!StringUtil.isEmpty(locationString)) {
String locationPrefix = null;
String locationSuffix = null;
if (value instanceof LocationPresentation) {
locationPrefix = ((LocationPresentation)value).getLocationPrefix();
locationSuffix = ((LocationPresentation)value).getLocationSuffix();
}
return text +
StringUtil.notNullize(locationPrefix, LocationPresentation.DEFAULT_LOCATION_PREFIX) +
locationString +
StringUtil.notNullize(locationSuffix, LocationPresentation.DEFAULT_LOCATION_SUFFIX);
}
}
}
return text;
}
if (node instanceof StructureViewComponent.StructureViewTreeElementWrapper) {
if (userObject instanceof StructureViewComponent.StructureViewTreeElementWrapper) {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Nullable
@Override
public String compute() {
final ItemPresentation presentation = ((StructureViewComponent.StructureViewTreeElementWrapper)node).getValue().getPresentation();
final ItemPresentation presentation =
((StructureViewComponent.StructureViewTreeElementWrapper)userObject).getValue().getPresentation();
return presentation.getPresentableText();
}
});
@@ -819,7 +831,7 @@ public class FileStructurePopup implements Disposable {
return true;
}
final String text = getText(value);
final String text = getSpeedSearchText(value);
if (text == null) return false;
if (matches(text)) {
@@ -863,7 +875,7 @@ public class FileStructurePopup implements Disposable {
final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
final Object userObject = node.getUserObject();
if (userObject instanceof FilteringTreeStructure.FilteringNode) {
return getText(((FilteringTreeStructure.FilteringNode)userObject).getDelegate());
return getSpeedSearchText(((FilteringTreeStructure.FilteringNode)userObject).getDelegate());
}
return "";
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -80,6 +80,7 @@ public class GeneralColorsPage implements ColorSettingsPage, InspectionColorSett
new AttributesDescriptor(OptionsBundle.message("options.general.attribute.descriptior.identifier.under.caret.write"), EditorColors.WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES),
new AttributesDescriptor(OptionsBundle.message("options.general.attribute.descriptor.text.search.result"), EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES),
new AttributesDescriptor(OptionsBundle.message("options.general.attribute.descriptor.live.template"), EditorColors.LIVE_TEMPLATE_ATTRIBUTES),
new AttributesDescriptor(OptionsBundle.message("options.general.attribute.descriptor.template.variable"), TemplateColors.TEMPLATE_VARIABLE_ATTRIBUTES),
new AttributesDescriptor(OptionsBundle.message("options.general.color.descriptor.injected.language.fragment"), EditorColors.INJECTED_LANGUAGE_FRAGMENT),
@@ -181,6 +181,14 @@ public class FormatterUtil {
return expectedTypes.contains(prevNode.getElementType());
}
public static boolean hasPrecedingSiblingOfType(@Nullable ASTNode node, IElementType expectedSiblingType, IElementType... skipTypes) {
for (ASTNode prevNode = node == null ? null : node.getTreePrev(); prevNode != null; prevNode = prevNode.getTreePrev()) {
if (isWhitespaceOrEmpty(prevNode) || isOneOf(prevNode, skipTypes)) continue;
if (prevNode.getElementType() == expectedSiblingType) return true;
}
return false;
}
public static boolean isFollowedBy(@Nullable ASTNode node, IElementType expectedType) {
return isFollowedBy(node, expectedType, IElementType.EMPTY_ARRAY);
}
@@ -47,10 +47,7 @@ public class ParametersList implements Cloneable {
}
public boolean hasProperty(@NonNls final String name) {
for (@NonNls String parameter : myParameters) {
if (parameter.startsWith("-D" + name + '=')) return true;
}
return false;
return getPropertyValue(name) != null;
}
@Nullable
@@ -17,6 +17,7 @@ package com.intellij.openapi.application;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.PlatformUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -94,7 +95,7 @@ public class ApplicationNamesInfo {
}
public static String getComponentName() {
final String prefix = System.getProperty("idea.platform.prefix");
final String prefix = System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY);
if (prefix != null) {
return prefix + COMPONENT_NAME;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -38,6 +38,7 @@ public interface EditorColors {
TextAttributesKey REFERENCE_HYPERLINK_COLOR = TextAttributesKey.createTextAttributesKey("CTRL_CLICKABLE", new TextAttributes(JBColor.blue, null, JBColor.blue, EffectType.LINE_UNDERSCORE, 0));
TextAttributesKey SEARCH_RESULT_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("SEARCH_RESULT_ATTRIBUTES");
TextAttributesKey LIVE_TEMPLATE_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("LIVE_TEMPLATE_ATTRIBUTES");
TextAttributesKey WRITE_SEARCH_RESULT_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("WRITE_SEARCH_RESULT_ATTRIBUTES");
TextAttributesKey IDENTIFIER_UNDER_CARET_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("IDENTIFIER_UNDER_CARET_ATTRIBUTES");
TextAttributesKey WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES =
@@ -60,7 +60,7 @@ public abstract class ProgressManager {
public abstract ProgressIndicator getProgressIndicator();
protected static boolean ourNeedToCheckCancel = false;
protected static volatile boolean ourNeedToCheckCancel = false;
public static void checkCanceled() throws ProcessCanceledException {
// smart optimization! There's a thread started in ProgressManagerImpl, that set's this flag up once in 10 milliseconds
if (ourNeedToCheckCancel) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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,6 +15,7 @@
*/
package com.intellij.ui.components.panels;
import com.intellij.ui.JBColor;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
@@ -74,7 +75,7 @@ public abstract class ValidatingComponent<T extends JComponent> extends NonOpaqu
protected JLabel createErrorLabel() {
final JLabel label = new JLabel(" ");
label.setForeground(Color.red);
label.setForeground(JBColor.red);
label.setFont(ERROR_FONT);
return label;
}
@@ -23,6 +23,8 @@ import org.jetbrains.annotations.Nullable;
* @author Konstantin Bulenkov
*/
public class PlatformUtils {
public static final String PLATFORM_PREFIX_KEY = "idea.platform.prefix";
public static final String IDEA_PREFIX = "idea";
public static final String COMMUNITY_PREFIX = "Idea";
public static final String APPCODE_PREFIX = "AppCode";
@@ -40,7 +42,7 @@ public class PlatformUtils {
}
public static String getPlatformPrefix(String defaultPrefix) {
return System.getProperty("idea.platform.prefix", defaultPrefix);
return System.getProperty(PLATFORM_PREFIX_KEY, defaultPrefix);
}
public static boolean isIdea() {
@@ -162,6 +162,7 @@ public class JobImpl<T> implements Job<T> {
}
catch (CancellationException ignore) {
// already cancelled
cancel();
}
catch (ExecutionException e) {
cancel();
@@ -21,6 +21,7 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.util.PlatformUtils;
/**
* @author yole
@@ -35,6 +36,6 @@ public class NewDummyProjectAction extends AnAction implements DumbAware {
@Override
public void update(final AnActionEvent e) {
e.getPresentation().setVisible("Platform".equals(System.getProperty("idea.platform.prefix")));
e.getPresentation().setVisible("Platform".equals(System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY)));
}
}
@@ -33,6 +33,8 @@ import com.intellij.openapi.vfs.VirtualFile;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author spleaner
@@ -58,7 +60,8 @@ public class SaveAsDirectoryBasedFormatAction extends AnAction implements DumbAw
final StateStorageManager storageManager = projectStore.getStateStorageManager();
for (String file : storageManager.getStorageFileNames()) {
final Collection<String> storageFileNames = new ArrayList<String>(storageManager.getStorageFileNames());
for (String file : storageFileNames) {
storageManager.clearStateStorage(file);
}
@@ -45,6 +45,7 @@ import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.PlatformUtils;
import com.intellij.util.graph.CachingSemiGraph;
import com.intellij.util.graph.DFSTBuilder;
import com.intellij.util.graph.Graph;
@@ -231,7 +232,7 @@ public class PluginManager {
}
final IdeaPluginDescriptor corePluginDescriptor = idToDescriptorMap.get(PluginId.getId(CORE_PLUGIN_ID));
assert corePluginDescriptor != null : CORE_PLUGIN_ID + " not found; platform prefix is " + System.getProperty("idea.platform.prefix");
assert corePluginDescriptor != null : CORE_PLUGIN_ID + " not found; platform prefix is " + System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY);
for (IdeaPluginDescriptorImpl descriptor : result) {
if (descriptor != corePluginDescriptor) {
descriptor.insertDependency(corePluginDescriptor);
@@ -631,7 +632,7 @@ public class PluginManager {
private static void loadDescriptorsFromClassPath(final List<IdeaPluginDescriptorImpl> result, @Nullable StartupProgress progress) {
try {
final Collection<URL> urls = getClassLoaderUrls();
final String platformPrefix = System.getProperty("idea.platform.prefix");
final String platformPrefix = System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY);
int i = 0;
for (URL url : urls) {
i++;
@@ -527,12 +527,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
((ProgressManagerImpl)getInstance()).dispose();
}
@TestOnly
public static void setNeedToCheckCancel(boolean needToCheckCancel) {
ourNeedToCheckCancel = needToCheckCancel;
ProgressIndicatorProvider.ourNeedToCheckCancel = true;
}
@TestOnly
@SuppressWarnings({"UnusedDeclaration"})
public static String isCanceledThread(Thread thread) {
@@ -176,9 +176,9 @@ public class FileWatcher {
private static boolean isUpToDate(File executable) {
long length = SystemInfo.isWindows ? 70216 :
SystemInfo.isMac ? 13924 :
SystemInfo.isLinux ? SystemInfo.isAMD64 ? 29296 : 22793 :
SystemInfo.isLinux ? SystemInfo.isAMD64 ? 29308 : 22809 :
-1;
return length > 0 && length == executable.length();
return length < 0 || length == executable.length();
}
private void notifyOnFailure(final String cause, @Nullable final NotificationListener listener) {
@@ -474,7 +474,8 @@ public class FileWatcher {
}
}
else {
processChange(line.replace('\0', '\n'), myLastOp);
String path = line.replace('\0', '\n'); // unescape
processChange(path, myLastOp);
myLastOp = null;
}
}
@@ -22,6 +22,7 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.ui.AppUIUtil;
import com.intellij.util.PlatformUtils;
import com.intellij.util.text.DateFormatUtilRt;
import com.intellij.util.ui.UIUtil;
@@ -37,9 +38,7 @@ public class MainImpl {
* Called from PluginManager via reflection.
*/
protected static void start(final String[] args) {
if (System.getProperty("idea.platform.prefix") == null) {
System.setProperty("idea.platform.prefix", "Idea");
}
System.setProperty(PlatformUtils.PLATFORM_PREFIX_KEY, PlatformUtils.getPlatformPrefix(PlatformUtils.COMMUNITY_PREFIX));
StartupUtil.isHeadless = Main.isHeadless(args);
if (!StartupUtil.isHeadless) {
@@ -229,4 +229,5 @@ color.settings.console.yellow=ANSI Yellow
color.settings.console.blue=ANSI Blue
color.settings.console.magenta=ANSI Magenta
color.settings.console.cyan=ANSI Cyan
color.settings.console.gray=ANSI Gray
color.settings.console.gray=ANSI Gray
options.general.attribute.descriptor.live.template=Live Template
@@ -734,6 +734,14 @@
<option name="EFFECT_COLOR"/>
</value>
</option>
<option name="LIVE_TEMPLATE_ATTRIBUTES">
<value>
<option name="FOREGROUND"/>
<option name="BACKGROUND"/>
<option name="EFFECT_COLOR" value="ff0000"/>
<option name="EFFECT_TYPE" value="0"/>
</value>
</option>
<option name="WRITE_SEARCH_RESULT_ATTRIBUTES">
<value>
@@ -86,7 +86,7 @@ public class ProjectFileIndexImpl implements ProjectFileIndex {
}
@Nullable
public static DirectoryInfo getInfoForFileOrDirectory(@NotNull VirtualFile file, DirectoryIndex directoryIndex) {
static DirectoryInfo getInfoForFileOrDirectory(@NotNull VirtualFile file, DirectoryIndex directoryIndex) {
if (!file.isDirectory() && file.getParent() == null) return null; // e.g. LightVirtualFile in test
DirectoryInfo info = directoryIndex.getInfoForDirectory(file);
if (info != null) {
@@ -68,6 +68,7 @@ import com.intellij.psi.impl.DocumentCommitThread;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
import com.intellij.util.PatchedWeakReference;
import com.intellij.util.PlatformUtils;
import com.intellij.util.indexing.IndexableSetContributor;
import com.intellij.util.indexing.IndexedRootsProvider;
import com.intellij.util.ui.UIUtil;
@@ -813,7 +814,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
}
private static void setPlatformPrefix(String prefix) {
System.setProperty("idea.platform.prefix", prefix);
System.setProperty(PlatformUtils.PLATFORM_PREFIX_KEY, prefix);
}
@Retention(RetentionPolicy.RUNTIME)
@@ -1,68 +0,0 @@
/*
* Copyright 2003-2005 Dave Griffith
*
* 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.siyeh.ig;
import com.intellij.codeInspection.InspectionProfileEntry;
import java.util.Comparator;
class InspectionComparator
implements Comparator<Class<? extends InspectionProfileEntry>> {
public int compare(Class<? extends InspectionProfileEntry> class1,
Class<? extends InspectionProfileEntry> class2) {
final InspectionProfileEntry inspection1;
final InspectionProfileEntry inspection2;
try {
inspection1 = class1.newInstance();
inspection2 = class2.newInstance();
}
catch (InstantiationException ignore) {
return -1;
}
catch (IllegalAccessException ignore) {
return -1;
}
final String groupName1 = inspection1.getGroupDisplayName();
final String groupName2 = inspection2.getGroupDisplayName();
final int groupNameComparison = groupName1.compareTo(groupName2);
if (groupNameComparison != 0) {
return groupNameComparison;
}
String displayName1 = inspection1.getDisplayName();
String displayName2 = inspection2.getDisplayName();
displayName1 = displayName1.toUpperCase();
displayName2 = displayName2.toUpperCase();
displayName1 = stripQuotes(displayName1);
displayName2 = stripQuotes(displayName2);
return displayName1.compareTo(displayName2);
}
private static String stripQuotes(String str) {
if (str.indexOf((int)'\'') < 0 && str.indexOf((int)'"') < 0) {
return str;
}
final int length = str.length();
final StringBuffer buffer = new StringBuffer(length);
for (int i = 0; i < length; i++) {
final char ch = str.charAt(i);
if (ch != '"' && ch != '\'') {
buffer.append(ch);
}
}
return buffer.toString();
}
}
@@ -3,7 +3,7 @@
<table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
<tr>
<td colspan="3"><font face="verdana" size="-1">This is a built-in template used each time you create
a new <b>IntelliJ IDEA</b> action.</font>
a new <b>IntelliJ Platform</b> action.</font>
</td>
</tr>
</table>
@@ -3,7 +3,7 @@
<table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
<tr>
<td colspan="3"><font face="verdana" size="-1">This is a built-in template used each time you create
a new <b>IntelliJ IDEA</b> application component.</font>
a new <b>IntelliJ Platform</b> application component.</font>
</td>
</tr>
</table>
@@ -3,7 +3,7 @@
<table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
<tr>
<td colspan="3"><font face="verdana" size="-1">This is a built-in template used each time you create
a new <b>IntelliJ IDEA</b> module component.</font>
a new <b>IntelliJ Platform</b> module component.</font>
</td>
</tr>
</table>
@@ -3,7 +3,7 @@
<table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
<tr>
<td colspan="3"><font face="verdana" size="-1">This is a built-in template used each time you create
a new <b>IntelliJ IDEA</b> project component.</font>
a new <b>IntelliJ Platform</b> project component.</font>
</td>
</tr>
</table>
@@ -3,7 +3,7 @@
<table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111">
<tr>
<td colspan="3"><font face="verdana" size="-1">This is a built-in template used each time you create
a new <b>IntelliJ IDEA</b> plugin module.</font>
a new <b>IntelliJ Platform</b> plugin module.</font>
</td>
</tr>
</table>
+5 -7
View File
@@ -1,8 +1,8 @@
#module type
module.title=IntelliJ IDEA Plugin
module.description=Plugin modules are used for development of <b>IntelliJ IDEA Plugins</b>. They support <b>IntelliJ IDEA Plugin SDK</b> configuration and \
<b>Run Configuration</b> for running a dedicated <b>IntelliJ IDEA</b> instance for plugin debugging.
plugin.descriptor=IntelliJ IDEA Plugin Descriptor
module.title=IntelliJ Platform Plugin
module.description=Plugin modules are used for developing plugins for <b>IntelliJ Platform</b>-based IDEs.<br>\
They provide <b>IntelliJ Platform Plugin SDK</b> and <b>Run Configuration</b> for running and debugging plugins inside an IDE.
plugin.descriptor=IntelliJ Platform Plugin Descriptor
#Module Editor - Deployment
deployment.title=Plugin Deployment
@@ -30,7 +30,7 @@ success.deployment.message=Plugin Module ''{0}'' Successfully Prepared For Deplo
success.deployment.message.all=All Plugins Successfully Prepared For Deployment
##Idea Sdk
sdk.title=IntelliJ IDEA Plugin SDK
sdk.title=IntelliJ Platform Plugin SDK
sandbox.specification=Please configure the sandbox
sandbox.home=Sandbox Home
sandbox.home.label=Sandbox Home:
@@ -64,8 +64,6 @@ presentable.plugin.module.name=Plugin Module ''{0}''
action.MakeJarAction.text=Prepare To Deploy
action.MakeAllJarsAction.text=Prepare All Plugins To Deploy
plugin.DevKit.description=IntelliJ IDEA plugins development kit. Adds dedicated Plugin module type to IntelliJ IDEA project.\
Allows running/debugging IDEA plugins through Plugin-oriented Run/Debug Configuration
dont.add.idea.libs.to.classpath=IDEA-related libraries ({0}) must not be added to the module classpath. Please add them to the IDEA-JDK instead.
new.action.id=&Action ID:
@@ -33,6 +33,7 @@ import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.PlatformUtils;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -144,25 +145,30 @@ public class PluginRunConfiguration extends RunConfigurationBase implements Modu
}
}
String buildNumber = IdeaJdk.getBuildNumber(usedIdeaJdk.getHomePath());
if (buildNumber != null) {
if (buildNumber.startsWith("IC")) {
vm.defineProperty("idea.platform.prefix", "Idea");
}
else if (buildNumber.startsWith("PY")) {
vm.defineProperty("idea.platform.prefix", "Python");
}
else if (buildNumber.startsWith("RM")) {
vm.defineProperty("idea.platform.prefix", "Ruby");
}
else if (buildNumber.startsWith("PS")) {
vm.defineProperty("idea.platform.prefix", "PhpStorm");
}
else if (buildNumber.startsWith("WS")) {
vm.defineProperty("idea.platform.prefix", "WebStorm");
}
else if (buildNumber.startsWith("OC")) {
vm.defineProperty("idea.platform.prefix", "AppCode");
if (!vm.hasProperty(PlatformUtils.PLATFORM_PREFIX_KEY)) {
String buildNumber = IdeaJdk.getBuildNumber(usedIdeaJdk.getHomePath());
if (buildNumber != null) {
String prefix = null;
if (buildNumber.startsWith("IC")) {
prefix = PlatformUtils.COMMUNITY_PREFIX;
}
else if (buildNumber.startsWith("PY")) {
prefix = PlatformUtils.PYCHARM_PREFIX;
}
else if (buildNumber.startsWith("RM")) {
prefix = PlatformUtils.RUBY_PREFIX;
}
else if (buildNumber.startsWith("PS")) {
prefix = PlatformUtils.PHP_PREFIX;
}
else if (buildNumber.startsWith("WS")) {
prefix = PlatformUtils.WEB_PREFIX;
}
else if (buildNumber.startsWith("OC")) {
prefix = buildNumber.contains("121") ? "CIDR" : PlatformUtils.APPCODE_PREFIX;
}
if (prefix != null) vm.defineProperty(PlatformUtils.PLATFORM_PREFIX_KEY, prefix);
}
}
@@ -5,6 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
@@ -15,6 +16,7 @@
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="RegExpSupport" />
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
</component>
</module>
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2012 the original author or authors.
* Copyright 2001-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,8 @@
package org.jetbrains.generate.tostring.inspection;
import com.intellij.codeInsight.TestFrameworks;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.util.ui.CheckBox;
@@ -44,8 +42,6 @@ import java.awt.*;
*/
public class ClassHasNoToStringMethodInspection extends AbstractToStringInspection {
private final LocalQuickFix fix = new GenerateToStringQuickFix();
/** User options for classes to exclude. Must be a regexp pattern */
public String excludeClassNames = ""; // must be public for JDOMSerialization
/** User options for excluded exception classes */
@@ -161,7 +157,8 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
}
if (log.isDebugEnabled()) log.debug("Class does not override toString() method: " + clazz.getQualifiedName());
holder.registerProblem(nameIdentifier, "Class '" + clazz.getName() + "' does not override 'toString()' method", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix);
holder.registerProblem(nameIdentifier, "Class '" + clazz.getName() + "' does not override 'toString()' method",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, GenerateToStringQuickFix.getInstance());
}
};
}
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2012 the original author or authors.
* Copyright 2001-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,217 +15,163 @@
*/
package org.jetbrains.generate.tostring.inspection;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PropertyUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.generate.tostring.GenerateToStringContext;
import org.jetbrains.generate.tostring.GenerateToStringUtils;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
import java.util.Collections;
/**
* Intention to check if the current class toString() method is out of
* sync with the fields defined.
* <p/>
* This inspection will use filter information from the settings to exclude certain fields (eg. constants etc.).
* <p/>
* This inspection will only perform inspection if the class has a toString() method.
* Inspection to check if the current class toString() method is out of
* sync with the fields defined. It uses filter information from the settings
* to exclude certain fields (eg. constants etc.). Will only warn if the
* class has a toString() method.
*/
public class FieldNotUsedInToStringInspection extends AbstractToStringInspection {
private final LocalQuickFix fix = new GenerateToStringQuickFix();
@NotNull
public String getDisplayName() {
return "Field not used in 'toString()' method";
}
@NotNull
public String getDisplayName() {
return "Field not used in 'toString()' method";
}
@NotNull
public String getShortName() {
return "FieldNotUsedInToString";
}
@NotNull
public String getShortName() {
return "FieldNotUsedInToString";
@Override
public boolean runForWholeFile() {
return true;
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new FieldNotUsedInToStringVisitor(holder);
}
private static class FieldNotUsedInToStringVisitor extends JavaElementVisitor{
private final ProblemsHolder myHolder;
public FieldNotUsedInToStringVisitor(ProblemsHolder holder) {
myHolder = holder;
}
@Override
public boolean runForWholeFile() {
return true;
public void visitField(PsiField field) {
super.visitField(field);
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new JavaElementVisitor() {
@Override
public void visitClass(PsiClass clazz) {
checkFields(holder, clazz);
checkMethods(holder, clazz);
}
};
public void visitMethod(PsiMethod method) {
super.visitMethod(method);
@NonNls final String methodName = method.getName();
if (!"toString".equals(methodName)) {
return;
}
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() != 0) {
return;
}
final PsiType returnType = method.getReturnType();
final PsiClassType javaLangString = PsiType.getJavaLangString(method.getManager(), method.getResolveScope());
if (!javaLangString.equals(returnType)) {
return;
}
final PsiClass aClass = method.getContainingClass();
if (aClass == null) {
return;
}
final PsiField[] fields =
GenerateToStringUtils.filterAvailableFields(aClass, GenerateToStringContext.getConfig().getFilterPattern());
final PsiMethod[] methods;
if (GenerateToStringContext.getConfig().isEnableMethods()) {
methods = GenerateToStringUtils.filterAvailableMethods(aClass, GenerateToStringContext.getConfig().getFilterPattern());
}
else {
methods = PsiMethod.EMPTY_ARRAY;
}
final FieldUsedVisitor visitor = new FieldUsedVisitor(fields, methods);
method.accept(visitor);
for (PsiField field : visitor.getUnusedFields()) {
final String fieldName = field.getName();
myHolder.registerProblem(field.getNameIdentifier(), "Field '" + fieldName + "' is not used in 'toString()' method",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, GenerateToStringQuickFix.getInstance());
}
for (PsiMethod unusedMethod : visitor.getUnusedMethods()) {
final PsiIdentifier identifier = unusedMethod.getNameIdentifier();
final PsiElement target = identifier == null ? unusedMethod : identifier;
myHolder.registerProblem(target, "Method '" + unusedMethod.getName() + "' is not used in 'toString()' method",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, GenerateToStringQuickFix.getInstance());
}
}
}
private static class FieldUsedVisitor extends JavaRecursiveElementVisitor {
private final THashSet<PsiField> myUnusedFields = new THashSet<PsiField>();
private final THashSet<PsiMethod> myUnusedMethods = new THashSet<PsiMethod>();
public FieldUsedVisitor(PsiField[] fields, PsiMethod[] methods) {
Collections.addAll(myUnusedFields, fields);
Collections.addAll(myUnusedMethods, methods);
}
/**
* Checking for problems with fields.
*
* @param clazz the class to check
* @param holder a sink to feed the problem to
*/
private void checkFields(ProblemsHolder holder, PsiClass clazz) {
if (log.isDebugEnabled()) log.debug("checkFields: clazz=" + clazz);
// must be a class
if (clazz == null || clazz.getName() == null) {
return;
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
if (myUnusedFields.isEmpty() && myUnusedMethods.isEmpty()) {
return;
}
super.visitReferenceExpression(expression);
final PsiElement target = expression.resolve();
if (target instanceof PsiField) {
final PsiField field = (PsiField)target;
myUnusedFields.remove(field);
}
else if (target instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)target;
if (usesReflection(method)) {
myUnusedFields.clear();
myUnusedMethods.clear();
}
// must have fields
PsiField[] fields = clazz.getFields();
if (fields.length == 0) {
log.debug("Class does not have any fields");
return;
else {
myUnusedMethods.remove(method);
final PsiField field = PropertyUtil.findPropertyFieldByMember(method);
myUnusedFields.remove(field);
}
// a toString method must exist
PsiMethod toStringMethod = PsiAdapter.findMethodByName(clazz, "toString");
if (toStringMethod == null) {
log.debug("No toString() method");
return;
}
// a toString code block must exist
PsiCodeBlock code = toStringMethod.getBody();
if (code == null) {
log.debug("No toString() code");
return;
}
// check if toString uses reflection if so exit
String body = code.getText();
if (body.indexOf("getDeclaredFields()") != -1) {
log.debug("Using reflection");
return;
} else if (body.indexOf("ReflectionToStringBuilder(this).toString()") != -1) {
log.debug("Using reflection (ReflectionToStringBuilder)");
return;
}
// get list of fields supposed to be dumped in the toString method
Project project = clazz.getProject();
fields = GenerateToStringUtils.filterAvailableFields(clazz, GenerateToStringContext.getConfig().getFilterPattern());
if (fields.length == 0) {
log.debug("No fields to be dumped as all fields was excluded (exclude field by XXX from Settings)");
return;
}
// toString exists and fields are supposed to be dumped
// check if any fields are missing (out of sync)
for (PsiField field : fields) {
final String fieldName = field.getName();
if (log.isDebugEnabled()) log.debug("Evaluating if field " + fieldName + " is in toString() method");
// field must be enclosed with non words before and after the field to ensure the fieldname are dumped
String pattern = "(?s).*\\W" + StringUtil.escapeToRegexp(fieldName) + "[\\W&&[^=]].*";
if (log.isDebugEnabled()) log.debug("Match pattern = " + pattern);
// use regexp to match if field is used in code
if (!body.matches(pattern)) {
if (log.isDebugEnabled()) log.debug("Field is not used in toString() method (out-of-sync): " + field);
holder.registerProblem(field.getNameIdentifier(), "Field '" + fieldName + "' is not used in 'toString()' method",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix);
}
}
}
}
/**
* Checking for problems with fields.
*
* @param clazz the class to check
* @param holder a sink to feed the problem to
*/
private void checkMethods(ProblemsHolder holder, PsiClass clazz) {
if (log.isDebugEnabled()) log.debug("checkMethods: clazz=" + clazz);
// must be a class
if (clazz == null || clazz.getName() == null) {
return;
}
// must have 'Enable getters in code generation' set to true
if (! GenerateToStringContext.getConfig().isEnableMethods()) {
return;
}
// a toString method must exist
PsiMethod toStringMethod = PsiAdapter.findMethodByName(clazz, "toString");
if (toStringMethod == null) {
log.debug("No toString() method");
return;
}
// a toString code block must exist
PsiCodeBlock code = toStringMethod.getBody();
if (code == null) {
log.debug("No toString() code");
return;
}
// check if toString uses reflection if so exit
String body = code.getText();
if (body.contains("getDeclaredFields()")) {
log.debug("Using reflection");
return;
}
// must have methods
PsiMethod[] methods = clazz.getMethods();
if (methods.length == 0) {
log.debug("Class does not have any methods");
return;
}
// get list of methods supposed to be dumped in the toString method
methods = GenerateToStringUtils.filterAvailableMethods(clazz, GenerateToStringContext.getConfig().getFilterPattern());
if (methods.length == 0) {
log.debug("No getter methods to be dumped as all methods was excluded or a field existed for the getter method (exclude method by XXX from Settings)");
return;
}
// toString exists and methods are supposed to be dumped
// check if any methods are missing (out of sync)
for (PsiMethod method : methods) {
final String methodName = method.getName();
if (log.isDebugEnabled()) log.debug("Evaluating if method " + methodName + " is in toString() method");
// method must be enclosed with non words before and after the method to ensure the fieldname are dumped
String pattern = "(?s).*\\W" + StringUtil.escapeToRegexp(methodName) + "[\\W&&[^=]].*";
if (log.isDebugEnabled()) log.debug("Match pattern = " + pattern);
// use regexp to match if method is used in code
if (!body.matches(pattern)) {
// method is not in toString
if (log.isDebugEnabled()) log.debug("Getter method is not used in toString() method (out-of-sync): " + method);
final PsiIdentifier identifier = method.getNameIdentifier();
final PsiElement target = identifier == null ? method : identifier;
holder.registerProblem(target, "Method '" + methodName + "' is not used in 'toString()' method",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix);
}
}
private boolean usesReflection(PsiMethod method) {
@NonNls final String name = method.getName();
final PsiClass containingClass = method.getContainingClass();
if (containingClass == null) {
return false;
}
@NonNls final String qualifiedName = containingClass.getQualifiedName();
if ("getDeclaredFields".equals(name)) {
return "java.lang.Class".equals(qualifiedName);
}
else if ("toString".equals(name)) {
return "org.apache.commons.lang.builder.ReflectionToStringBuilder".equals(qualifiedName) ||
"java.util.Objects".equals(qualifiedName);
}
return false;
}
/*
public static void main(String[] args) {
// for testing regexp pattern
String me = "return \"DummyTestBean{\" +\n" +
" \", myNewString ='\" + myNewString + \"'\" +\n" +
" \"}\";";
System.out.println("me = " + me);
System.out.println( me.matches("(?s).*\\WmyNewString[\\W*&&[^\\s*=]].*") );
public THashSet<PsiField> getUnusedFields() {
return myUnusedFields;
}
*/
public THashSet<PsiMethod> getUnusedMethods() {
return myUnusedMethods;
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2012 the original author or authors.
* Copyright 2001-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,16 @@ import org.jetbrains.generate.tostring.GenerateToStringActionHandlerImpl;
*/
public class GenerateToStringQuickFix implements LocalQuickFix {
public static final GenerateToStringQuickFix INSTANCE = new GenerateToStringQuickFix();
private final GenerateToStringActionHandler myHandler = new GenerateToStringActionHandlerImpl();
private GenerateToStringQuickFix() {}
public static GenerateToStringQuickFix getInstance() {
return INSTANCE;
}
@NotNull
public String getName() {
return "Generate toString()";
@@ -40,15 +50,10 @@ public class GenerateToStringQuickFix implements LocalQuickFix {
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor desc) {
// find the class
PsiClass clazz = PsiTreeUtil.getParentOfType(desc.getPsiElement(), PsiClass.class);
final PsiClass clazz = PsiTreeUtil.getParentOfType(desc.getPsiElement(), PsiClass.class);
if (clazz == null) {
return; // no class to fix, so return
return; // no class to fix
}
// execute the action
GenerateToStringActionHandler handler = new GenerateToStringActionHandlerImpl();
handler.executeActionQuickFix(project, clazz);
myHandler.executeActionQuickFix(project, clazz);
}
}
@@ -0,0 +1,77 @@
/*
* Copyright 2000-2013 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.generate.tostring.inspection;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NonNls;
/**
* @author Bas Leijdekkers
*/
public class FieldNotUsedInToStringInspectionTest extends LightCodeInsightFixtureTestCase {
public void testBasic() {
doTest("class X {" +
" private int <warning descr=\"Field 'i' is not used in 'toString()' method\">i</warning> = 0;" +
" public String toString() {" +
" return null;" +
" }" +
"}");
}
public void testGetterUsed() {
doTest("public class ToStringTest3 {" +
"" +
" int number;" +
"" +
" public int getNumber() {" +
" return number;" +
" }" +
"" +
" @Override" +
" public String toString() {" +
" final StringBuilder sb = new StringBuilder();" +
" sb.append(\"ToStringTest3\");" +
" sb.append(\"{number=\").append(getNumber());" +
" sb.append('}');" +
" return sb.toString();" +
" }" +
"}");
}
public void testReflectionUsed() {
myFixture.addClass("package java.util;" +
"public class Objects {" +
" public static String toString(Object object) {" +
" return null;" +
" }" +
"}");
doTest("import java.util.Objects;" +
"class X {" +
" private int i = 0;" +
" " +
" public String toString() {" +
" return Objects.toString(this);" +
" }" +
"}");
}
private void doTest(@NonNls String text) {
myFixture.configureByText("X.java", text);
myFixture.enableInspections(new FieldNotUsedInToStringInspection());
myFixture.testHighlighting(true, false, false);
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.javaFX.fxml;
import com.intellij.patterns.PatternCondition;
import com.intellij.patterns.XmlAttributeValuePattern;
import com.intellij.patterns.XmlPatterns;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
@@ -34,17 +35,21 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
final XmlAttributeValuePattern attributeValueInFxml = XmlPatterns.xmlAttributeValue().with(inFxmlCondition());
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.FX_CONTROLLER))
.and(XmlPatterns.xmlAttributeValue().with(inFxmlCondition())),
.and(attributeValueInFxml),
CLASS_REFERENCE_PROVIDER);
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.FX_ID))
.and(XmlPatterns.xmlAttributeValue().with(inFxmlCondition())),
.and(attributeValueInFxml),
new JavaFxFieldIdReferenceProvider());
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withValue(string().startsWith("#"))
.and(XmlPatterns.xmlAttributeValue().with(inFxmlCondition())),
.and(attributeValueInFxml),
new JavaFxEventHandlerReferenceProvider());
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withValue(string().startsWith("@")).and(attributeValueInFxml),
new JavaFxLocationReferenceProvider());
}
private static PatternCondition<XmlAttributeValue> inFxmlCondition() {
@@ -121,7 +121,8 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
if (field.hasModifierProperty(PsiModifier.STATIC)) continue;
final PsiType fieldType = field.getType();
if (PropertyUtil.findPropertyGetter(myPsiClass, field.getName(), false, true) != null &&
InheritanceUtil.isInheritor(fieldType, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY_PROPERTY)) {
InheritanceUtil.isInheritor(fieldType, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY_PROPERTY) ||
fieldType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
simpleAttrs.add(new JavaFxPropertyAttributeDescriptor(field.getName(), myPsiClass));
}
}
@@ -28,4 +28,5 @@ public class JavaFxCommonClassNames {
@NonNls public static final String JAVAFX_BEANS_DEFAULT_PROPERTY = "javafx.beans.DefaultProperty";
@NonNls public static final String JAVAFX_FXML_FXML = "javafx.fxml.FXML";
@NonNls public static final String JAVAFX_BEANS_PROPERTY_OBJECT_PROPERTY = "javafx.beans.property.ObjectProperty";
@NonNls public static final String JAVAFX_EVENT_EVENT_HANDLER = "javafx.event.EventHandler";
}
@@ -16,11 +16,13 @@
package org.jetbrains.plugins.javaFX.fxml;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiReference;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ProcessingContext;
import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.NotNull;
/**
@@ -36,6 +38,23 @@ class JavaFxEventHandlerReferenceProvider extends JavaFxControllerBasedReference
ProcessingContext context) {
final String attValueString = xmlAttributeValue.getValue();
LOG.assertTrue(attValueString.startsWith("#"));
final XmlAttribute attribute = (XmlAttribute)xmlAttributeValue.getContext();
if (attribute == null) return PsiReference.EMPTY_ARRAY;
final String attributeName = attribute.getName();
final XmlTag xmlTag = attribute.getParent();
final XmlElementDescriptor descriptor = xmlTag.getDescriptor();
if (descriptor == null) return PsiReference.EMPTY_ARRAY;
final PsiElement currentTagClass = descriptor.getDeclaration();
if (!(currentTagClass instanceof PsiClass)) return PsiReference.EMPTY_ARRAY;
final PsiField handlerField = ((PsiClass)currentTagClass).findFieldByName(attributeName, true);
if (handlerField == null) {
return PsiReference.EMPTY_ARRAY;
}
final PsiClass objectPropertyClass = JavaFxPropertyAttributeDescriptor.getPropertyClass(handlerField);
if (objectPropertyClass == null || !InheritanceUtil.isInheritor(objectPropertyClass, JavaFxCommonClassNames.JAVAFX_EVENT_EVENT_HANDLER)) {
return PsiReference.EMPTY_ARRAY;
}
final String eventHandlerName = attValueString.substring(1);
final PsiMethod[] methods = controllerClass.findMethodsByName(eventHandlerName, true);
@@ -0,0 +1,72 @@
/*
* Copyright 2000-2013 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.plugins.javaFX.fxml;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* User: anna
*/
class JavaFxLocationReferenceProvider extends PsiReferenceProvider {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull final PsiElement element,
@NotNull ProcessingContext context) {
final String value = ((XmlAttributeValue)element).getValue();
final String relativePathToResource = value.substring(1);
final VirtualFile virtualFile = element.getContainingFile().getOriginalFile().getVirtualFile();
if (virtualFile != null) {
final VirtualFile parent = virtualFile.getParent();
final VirtualFile resourceFile = parent != null ? parent.findFileByRelativePath(relativePathToResource) : null;
final PsiReferenceBase.Immediate<XmlAttributeValue> ref =
new PsiReferenceBase.Immediate<XmlAttributeValue>((XmlAttributeValue)element, resourceFile != null ? element.getManager().findFile(resourceFile) : null) {
@NotNull
@Override
public Object[] getVariants() {
if (parent != null) { //todo multilevel completion, filter by resources
final PsiDirectory psiDirectory = element.getManager().findDirectory(parent);
if (psiDirectory != null) {
final PsiElement[] children = psiDirectory.getChildren();
final List<String> paths = new ArrayList<String>();
for (PsiElement child : children) {
if (child instanceof PsiFileSystemItem) {
paths.add("@" + ((PsiFileSystemItem)child).getName());
}
}
return ArrayUtil.toStringArray(paths);
}
}
return super.getVariants();
}
};
return new PsiReference[]{ref};
}
return PsiReference.EMPTY_ARRAY;
}
}
@@ -73,7 +73,11 @@ public class JavaFxPropertyAttributeDescriptor implements XmlAttributeDescriptor
}
protected PsiClass getEnum() {
final PsiElement field = getDeclaration();
final PsiClass aClass = getPropertyClass(getDeclaration());
return aClass != null && aClass.isEnum() ? aClass : null;
}
public static PsiClass getPropertyClass(PsiElement field) {
if (field instanceof PsiField) {
final PsiType type = ((PsiField)field).getType();
if (type instanceof PsiClassType) {
@@ -83,14 +87,12 @@ public class JavaFxPropertyAttributeDescriptor implements XmlAttributeDescriptor
final PsiClass objectProperty = JavaPsiFacade.getInstance(attributeClass.getProject())
.findClass(JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY_OBJECT_PROPERTY, attributeClass.getResolveScope());
if (objectProperty != null) {
final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getClassSubstitutor(objectProperty, attributeClass, resolveResult.getSubstitutor());
final PsiSubstitutor superClassSubstitutor = TypeConversionUtil
.getClassSubstitutor(objectProperty, attributeClass, resolveResult.getSubstitutor());
if (superClassSubstitutor != null) {
final PsiType propertyType = superClassSubstitutor.substitute(objectProperty.getTypeParameters()[0]);
if (propertyType instanceof PsiClassType) {
final PsiClass psiClass = ((PsiClassType)propertyType).resolve();
if (psiClass != null && psiClass.isEnum()) {
return psiClass;
}
return ((PsiClassType)propertyType).resolve();
}
}
}
@@ -99,7 +101,7 @@ public class JavaFxPropertyAttributeDescriptor implements XmlAttributeDescriptor
}
return null;
}
@Nullable
@Override
public String validateValue(XmlElement context, String value) {
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.image.*?>
<AnchorPane xmlns:fx="http://javafx.com/fxml">
<children>
<ImageView>
<image>
<Image url="@appIcon.png"/>
</image>
</ImageView>
<ImageView>
<image>
<Image url="<error descr="Cannot resolve symbol '@unknownIcon.png'">@unknownIcon.png</error>"/>
</image>
</ImageView>
</children>
</AnchorPane>
@@ -41,6 +41,11 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
public void testEnumValues() throws Exception {
doTest();
}
public void testImageIcon() throws Exception {
configureByFiles(null, getTestName(true) + ".fxml", "appIcon.png");
doDoTest(false, false);
}
private void doTest() throws Exception {
doTest(false, false, getTestName(true) + ".fxml");
@@ -60,6 +60,10 @@ public class HtmlStructureViewElementProvider implements XmlStructureViewElement
return text.isEmpty() ? null : shortenTextIfLong(text);
}
public boolean isSearchInLocationString() {
return true;
}
private static String normalizeSpaces(final String text) {
final StringBuilder buf = new StringBuilder();