Merge remote-tracking branch 'origin/master'

This commit is contained in:
Alexander Lobas
2012-04-10 21:59:31 +04:00
19 changed files with 683 additions and 223 deletions
Binary file not shown.
Binary file not shown.
@@ -343,11 +343,12 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool {
final RefElementImpl refElement = (RefElementImpl)refEntity;
if (!refElement.isSuspicious()) return;
final PsiElement element = refElement.getElement();
if (element == null) return;
PsiFile file = refElement.getContainingFile();
if (file == null) return;
final boolean isSuppressed = refElement.isSuppressed(getShortName());
if (!getContext().isToCheckMember(element, UnusedDeclarationInspection.this) || isSuppressed) {
if (isSuppressed || !scope.contains(element)) {
if (!getContext().isToCheckFile(file, UnusedDeclarationInspection.this) || isSuppressed) {
if (isSuppressed || !scope.contains(file)) {
getEntryPointsManager().addEntryPoint(refElement, false);
}
return;
+4 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -24,6 +24,8 @@
// logging
void userlog(int priority, const char* format, ...);
#define CHECK_NULL(p, r) if (p == NULL) { userlog(LOG_ERR, "out of memory"); return r; }
// variable-length array
typedef struct __array array;
@@ -38,7 +40,7 @@ void array_delete(array* a);
void array_delete_vs_data(array* a);
// key/value pairs table
// poor man's hash table
typedef struct __table table;
table* table_create(int capacity);
+31 -21
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -32,8 +32,6 @@
#define DEFAULT_SUBDIR_COUNT 5
#define CHECK_NULL(p) if (p == NULL) { userlog(LOG_ERR, "out of memory"); return ERR_ABORT; }
typedef struct __watch_node {
char* name;
int wd;
@@ -153,9 +151,9 @@ static int add_watch(const char* path, watch_node* parent) {
node = malloc(sizeof(watch_node));
CHECK_NULL(node);
CHECK_NULL(node, ERR_ABORT);
node->name = strdup(path);
CHECK_NULL(node->name);
CHECK_NULL(node->name, ERR_ABORT);
node->wd = wd;
node->parent = parent;
node->kids = NULL;
@@ -163,9 +161,9 @@ static int add_watch(const char* path, watch_node* parent) {
if (parent != NULL) {
if (parent->kids == NULL) {
parent->kids = array_create(DEFAULT_SUBDIR_COUNT);
CHECK_NULL(parent->kids);
CHECK_NULL(parent->kids, ERR_ABORT);
}
CHECK_NULL(array_push(parent->kids, node));
CHECK_NULL(array_push(parent->kids, node), ERR_ABORT);
}
if (table_put(watches, wd, node) == NULL) {
@@ -238,25 +236,31 @@ static bool is_ignored(const char* path, array* ignores) {
return false;
}
static int walk_tree(const char* path, watch_node* parent, array* ignores) {
static int walk_tree(const char* path, watch_node* parent, array* ignores, bool recursive) {
if (is_ignored(path, ignores)) {
return ERR_IGNORE;
}
DIR* dir = opendir(path);
if (dir == NULL) {
if (errno == EACCES) {
return ERR_IGNORE;
DIR* dir;
if (recursive) {
dir = opendir(path);
if (dir == NULL) {
if (errno == EACCES) {
return ERR_IGNORE;
}
else if (errno == ENOTDIR) { // "future" root
return add_watch(path, parent);
}
userlog(LOG_ERR, "opendir(%s): %s", path, strerror(errno));
return ERR_CONTINUE;
}
else if (errno == ENOTDIR) { // flat root
return add_watch(path, parent);
}
userlog(LOG_ERR, "opendir(%s): %s", path, strerror(errno));
return ERR_CONTINUE;
}
int id = add_watch(path, parent);
if (id < 0) {
if (!recursive) {
return id;
}
else if (id < 0) {
closedir(dir);
return id;
}
@@ -279,7 +283,7 @@ static int walk_tree(const char* path, watch_node* parent, array* ignores) {
continue;
}
int subdir_id = walk_tree(subdir, table_get(watches, id), ignores);
int subdir_id = walk_tree(subdir, table_get(watches, id), ignores, recursive);
if (subdir_id < 0 && subdir_id != ERR_IGNORE) {
rm_watch(id, true);
id = subdir_id;
@@ -293,9 +297,15 @@ static int walk_tree(const char* path, watch_node* parent, array* ignores) {
int watch(const char* root, array* ignores) {
bool recursive = true;
if (root[0] == '|') {
root++;
recursive = false;
}
char buf[PATH_MAX];
const char* normalized = realpath(root, buf);
return walk_tree((normalized != NULL ? normalized : root), NULL, ignores);
return walk_tree((normalized != NULL ? normalized : root), NULL, ignores, recursive);
}
@@ -323,7 +333,7 @@ static bool process_inotify_event(struct inotify_event* event) {
}
if ((event->mask & IN_CREATE || event->mask & IN_MOVED_TO) && event->mask & IN_ISDIR) {
int result = walk_tree(path, node, NULL);
int result = walk_tree(path, node, NULL, true);
if (result < 0 && result != ERR_IGNORE) {
return false;
}
+9 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -33,7 +33,7 @@
#define LOG_ENV_ERROR "error"
#define LOG_ENV_OFF "off"
#define VERSION "1.0"
#define VERSION "1.1"
#define VERSION_MSG "fsnotifier " VERSION "\n"
#define USAGE_MSG \
@@ -58,11 +58,8 @@ typedef struct {
static array* roots = NULL;
static bool show_warning = true;
static bool self_test = false;
#define CHECK_NULL(p) if (p == NULL) { userlog(LOG_ERR, "out of memory"); return false; }
static void init_log();
static void run_self_test();
static void main_loop();
@@ -223,7 +220,7 @@ static bool read_input() {
if (strcmp(line, "ROOTS") == 0) {
array* new_roots = array_create(20);
CHECK_NULL(new_roots);
CHECK_NULL(new_roots, false);
while (1) {
line = read_line(stdin);
@@ -235,12 +232,9 @@ static bool read_input() {
break;
}
else {
if (line[0] == '|') line++; // flat roots will be differentiated later
int l = strlen(line);
if (l > 1 && line[l-1] == '/') line[l-1] = '\0';
CHECK_NULL(array_push(new_roots, strdup(line)));
CHECK_NULL(array_push(new_roots, strdup(line)), false);
}
}
@@ -266,7 +260,7 @@ static bool update_roots(array* new_roots) {
}
array* unwatchable = array_create(20);
CHECK_NULL(unwatchable);
CHECK_NULL(unwatchable, false);
if (!unwatchable_mounts(unwatchable)) {
return false;
}
@@ -312,10 +306,10 @@ static bool register_roots(array* new_roots, array* unwatchable) {
}
else if (id >= 0) {
watch_root* root = malloc(sizeof(watch_root));
CHECK_NULL(root);
CHECK_NULL(root, false);
root->id = id;
root->name = new_root;
CHECK_NULL(array_push(roots, root));
CHECK_NULL(array_push(roots, root), false);
}
else {
if (show_warning && watch_limit_reached()) {
@@ -324,7 +318,7 @@ static bool register_roots(array* new_roots, array* unwatchable) {
output("MESSAGE\n" INOTIFY_LIMIT_MSG, limit);
show_warning = false; // warn only once
}
CHECK_NULL(array_push(unwatchable, new_root));
CHECK_NULL(array_push(unwatchable, new_root), false);
}
}
@@ -362,7 +356,7 @@ static bool unwatchable_mounts(array* mounts) {
}
if (!is_watchable(dev, point, fs)) {
CHECK_NULL(array_push(mounts, strdup(point)));
CHECK_NULL(array_push(mounts, strdup(point)), false);
}
}
@@ -19,6 +19,7 @@ package com.intellij.codeInspection.ex;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.LocalDummyInspectionTool;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.search.scope.packageSet.NamedScope;
@@ -43,6 +44,7 @@ public class Descriptor {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.Descriptor");
private final ScopeToolState myState;
private final InspectionProfileImpl myInspectionProfile;
private boolean myShouldBeShown = true;
public Descriptor(ScopeToolState pair, InspectionProfileImpl inspectionProfile) {
myState = pair;
@@ -56,6 +58,14 @@ public class Descriptor {
myEnabled = ((InspectionProfileImpl)inspectionProfile).isToolEnabled(myKey, pair.getScope());
myTool = tool;
myScope = pair.getScope();
if (tool instanceof InspectionToolWrapper) {
InspectionProfileEntry inspection = ((InspectionToolWrapper)tool).getTool();
if (inspection instanceof LocalDummyInspectionTool) {
myShouldBeShown = ((LocalDummyInspectionTool)inspection).shouldBeShownInInspectionProfile();
}
}
}
public boolean equals(Object obj) {
@@ -80,6 +90,10 @@ public class Descriptor {
myEnabled = enabled;
}
public boolean shouldBeShown() {
return myShouldBeShown;
}
public String getText() {
return myText;
}
@@ -71,7 +71,10 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class GlobalInspectionContextImpl extends UserDataHolderBase implements GlobalInspectionContext {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.GlobalInspectionContextImpl");
@@ -346,16 +349,15 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G
public boolean isToCheckMember(@NotNull RefElement owner, InspectionProfileEntry tool) {
final PsiElement element = owner.getElement();
return isToCheckMember(element, tool) && !((RefElementImpl)owner).isSuppressed(tool.getShortName());
return isToCheckFile(((RefElementImpl)owner).getContainingFile(), tool) && !((RefElementImpl)owner).isSuppressed(tool.getShortName());
}
public boolean isToCheckMember(final PsiElement element, final InspectionProfileEntry tool) {
public boolean isToCheckFile(PsiFile file, final InspectionProfileEntry tool) {
final Tools tools = myTools.get(tool.getShortName());
if (tools != null) {
for (ScopeToolState state : tools.getTools()) {
final NamedScope namedScope = state.getScope(element.getProject());
if (namedScope == null || namedScope.getValue().contains(element.getContainingFile(), getCurrentProfile().getProfileManager().getScopesManager())) {
final NamedScope namedScope = state.getScope(file.getProject());
if (namedScope == null || namedScope.getValue().contains(file, getCurrentProfile().getProfileManager().getScopesManager())) {
if (state.isEnabled()) {
final InspectionProfileEntry entry = state.getTool();
if (entry instanceof InspectionToolWrapper && ((InspectionToolWrapper)entry).getTool() == tool) return true;
@@ -444,10 +444,6 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
return false;
}
for (InspectionToolWrapper tool : tools) {
if (tool.getTool() instanceof LocalDummyInspectionTool && !((LocalDummyInspectionTool)tool.getTool()).shouldBeShownInInspectionProfile()) {
continue;
}
final String shortName = tool.getShortName();
HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
if (key == null) {
@@ -21,14 +21,8 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.SeverityRegistrar;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ModifiableModel;
import com.intellij.codeInspection.ex.Descriptor;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.codeInspection.ex.InspectionToolRegistrar;
import com.intellij.codeInspection.ex.ScopeToolState;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.*;
import com.intellij.ide.CommonActionsManager;
import com.intellij.ide.DefaultTreeExpander;
import com.intellij.ide.IdeTooltipManager;
@@ -685,7 +679,7 @@ public class SingleInspectionProfilePanel extends JPanel {
keySetList.addAll(SearchUtil.findKeys(filter, quated));
}
for (Descriptor descriptor : myDescriptors.keySet()) {
if (filter != null && filter.length() > 0 && !isDescriptorAccepted(descriptor, filter, forceInclude, keySetList, quated)) {
if (!descriptor.shouldBeShown() || filter != null && filter.length() > 0 && !isDescriptorAccepted(descriptor, filter, forceInclude, keySetList, quated)) {
continue;
}
final List<ScopeToolState> nonDefaultTools = mySelectedProfile.getNonDefaultTools(descriptor.getKey().toString());
@@ -173,6 +173,9 @@ public abstract class BaseRefactoringProcessor {
}
catch (Throwable e) {
anyException.set(Boolean.TRUE);
if (ApplicationManager.getApplication().isUnitTestMode()) {
LOG.error(e);
}
}
}
};
@@ -20,34 +20,32 @@ import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.watcher.ChangeKind;
import com.intellij.util.PairFunction;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.event.HyperlinkEvent;
import java.io.*;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author max
*/
public class FileWatcher {
@NonNls public static final String PROPERTY_WATCHER_DISABLED = "filewatcher.disabled";
@NonNls private static final String PROPERTY_WATCHER_EXECUTABLE_PATH = "idea.filewatcher.executable.path";
@NonNls public static final String PROPERTY_WATCHER_DISABLED = "idea.filewatcher.disabled";
@NonNls public static final String PROPERTY_WATCHER_EXECUTABLE_PATH = "idea.filewatcher.executable.path";
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.local.FileWatcher");
@@ -59,15 +57,7 @@ public class FileWatcher {
@NonNls private static final String EXIT_COMMAND = "EXIT";
@NonNls private static final String MESSAGE_COMMAND = "MESSAGE";
private static final PairFunction<String,String,Boolean> PATH_COMPARATOR = new PairFunction<String, String, Boolean>() {
@Override
public Boolean fun(final String s1, final String s2) {
return SystemInfo.isFileSystemCaseSensitive ? s1.equals(s2) : s1.equalsIgnoreCase(s2);
}
};
private final Object LOCK = new Object();
private final Lock SET_ROOTS_LOCK = new ReentrantLock(true);
private List<String> myDirtyPaths = new ArrayList<String>();
private List<String> myDirtyRecursivePaths = new ArrayList<String>();
@@ -75,21 +65,23 @@ public class FileWatcher {
private List<String> myManualWatchRoots = new ArrayList<String>();
private final List<Pair<String, String>> myMapping = new ArrayList<Pair<String, String>>();
private List<Pair<String, String>> myCanonicalMapping = new ArrayList<Pair<String, String>>();
private List<String> myRecursiveWatchRoots = new ArrayList<String>();
private List<String> myFlatWatchRoots = new ArrayList<String>();
private final Collection<String> myAllPaths = new ArrayList<String>(2);
private final Collection<String> myWatchedPaths = new ArrayList<String>(2);
private File executable;
private volatile Process notifierProcess;
private volatile BufferedReader notifierReader;
private volatile BufferedWriter notifierWriter;
private volatile BufferedWriter notifierWriter;
private boolean myFailureShownToTheUser = false;
private int attemptCount = 0;
private static final int MAX_PROCESS_LAUNCH_ATTEMPT_COUNT = 10;
private boolean isShuttingDown = false;
private final ManagingFS myManagingFS;
private final ManagingFS myManagingFS;
private static final FileWatcher ourInstance = new FileWatcher();
public static FileWatcher getInstance() {
@@ -140,7 +132,6 @@ public class FileWatcher {
myDirtyRecursivePaths = new ArrayList<String>();
return result;
}
}
public List<String> getDirtyDirs() {
@@ -158,26 +149,16 @@ public class FileWatcher {
}
public void setWatchRoots(final List<String> recursive, final List<String> flat) {
SET_ROOTS_LOCK.lock();
try {
synchronized (LOCK) {
if (myRecursiveWatchRoots.equals(recursive) && myFlatWatchRoots.equals(flat)) return;
}
final List<Pair<String, String>> mapping = new ArrayList<Pair<String, String>>();
long t = System.nanoTime();
final List<String> checkedRecursive = checkPaths(recursive, mapping);
final List<String> checkedFlat = checkPaths(flat, mapping);
t = (System.nanoTime() - t) / 1000;
LOG.info((recursive.size() + flat.size()) + " paths checked, " + mapping.size() + " mapped, " + t + " mks");
synchronized (LOCK) {
if (myRecursiveWatchRoots.equals(recursive) && myFlatWatchRoots.equals(flat)) return;
if (isAlive()) {
try {
writeLine(ROOTS_COMMAND);
for (String path : checkedRecursive) {
for (String path : recursive) {
writeLine(path);
}
for (String path : checkedFlat) {
for (String path : flat) {
writeLine("|" + path);
}
writeLine("#");
@@ -187,37 +168,10 @@ public class FileWatcher {
}
}
synchronized (LOCK) {
myRecursiveWatchRoots = recursive;
myFlatWatchRoots = flat;
myMapping.clear();
myCanonicalMapping = mapping;
}
myRecursiveWatchRoots = recursive;
myFlatWatchRoots = flat;
myMapping.clear();
}
finally {
SET_ROOTS_LOCK.unlock();
}
}
private static List<String> checkPaths(final List<String> paths, final List<Pair<String, String>> mapping) {
if (!SystemInfo.areSymLinksSupported) return paths;
final List<String> checkedPaths = new ArrayList<String>(paths.size());
for (String path : paths) {
String watched = path;
final String canonical = getCanonicalPath(path);
//noinspection ConstantConditions
if (!PATH_COMPARATOR.fun(path, canonical)) {
mapping.add(Pair.create((watched = canonical), path));
}
checkedPaths.add(watched);
}
return checkedPaths;
}
private static String getCanonicalPath(final String path) {
final String realPath = FileSystemUtil.resolveSymLink(path);
return realPath != null ? realPath : path;
}
private boolean isAlive() {
@@ -247,43 +201,34 @@ public class FileWatcher {
shutdownProcess();
String execPath = null;
if (executable == null) {
executable = getExecutable();
final String altExecPath = System.getProperty(PROPERTY_WATCHER_EXECUTABLE_PATH);
if (altExecPath != null && new File(altExecPath).isFile()) {
execPath = FileUtil.toSystemDependentName(altExecPath);
}
if (execPath == null) {
final String execName;
execName = getExecutableName();
if (execName == null) {
if (executable == null) {
myFailureShownToTheUser = true; // ignore unsupported platforms
return;
}
execPath = PathManager.getBinPath() + File.separatorChar + execName;
if (!executable.exists()) {
notifyOnFailure("File watcher is not found at path: " + executable, null);
return;
}
if (!executable.canExecute()) {
final String message = "File watcher is not executable: <a href=\"" + executable + "\">" + executable + "</a>";
final File exec = executable;
notifyOnFailure(message, new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
ShowFilePathAction.openFile(exec);
}
});
return;
}
}
final File exec = new File(execPath);
if (!exec.exists()) {
notifyOnFailure("File watcher is not found at path: " + execPath, null);
return;
}
if (!exec.canExecute()) {
notifyOnFailure("File watcher is not executable: <a href=\"" + execPath + "\">" + execPath +"</a>", new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
ShowFilePathAction.openFile(exec);
}
});
return;
}
LOG.info("Starting file watcher: " + execPath);
notifierProcess = Runtime.getRuntime().exec(new String[]{execPath});
LOG.info("Starting file watcher: " + executable);
notifierProcess = Runtime.getRuntime().exec(executable.getAbsolutePath());
notifierReader = new BufferedReader(new InputStreamReader(notifierProcess.getInputStream()));
notifierWriter = new BufferedWriter(new OutputStreamWriter(notifierProcess.getOutputStream()));
@@ -299,15 +244,43 @@ public class FileWatcher {
}
@Nullable
private static String getExecutableName() {
private static File getExecutable() {
String execPath = null;
final String altExecPath = System.getProperty(PROPERTY_WATCHER_EXECUTABLE_PATH);
if (altExecPath != null && new File(altExecPath).isFile()) {
execPath = FileUtil.toSystemDependentName(altExecPath);
}
if (execPath == null) {
final String execName = getExecutableName(false);
if (execName == null) {
return null;
}
execPath = FileUtil.join(PathManager.getBinPath(), execName);
}
File exec = new File(execPath);
if (!exec.exists()) {
String homePath = PathManager.getHomePath();
if (new File(homePath, "community").exists()) {
homePath += File.separator + "community";
}
exec = new File(FileUtil.join(homePath, "bin", getExecutableName(true)));
}
return exec;
}
@Nullable
private static String getExecutableName(final boolean withSubDir) {
if (SystemInfo.isWindows) {
return "fsnotifier.exe";
return (withSubDir ? "win" + File.separator : "") + "fsnotifier.exe";
}
else if (SystemInfo.isMac) {
return "fsnotifier";
return (withSubDir ? "mac" + File.separator : "") + "fsnotifier";
}
else if (SystemInfo.isLinux) {
return SystemInfo.isAMD64 ? "fsnotifier64" : "fsnotifier";
return (withSubDir ? "linux" + File.separator : "") + (SystemInfo.isAMD64 ? "fsnotifier64" : "fsnotifier");
}
return null;
@@ -316,7 +289,8 @@ public class FileWatcher {
private void notifyOnFailure(String cause, @Nullable NotificationListener listener) {
if (!myFailureShownToTheUser) {
myFailureShownToTheUser = true;
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, "External file sync may be slow", cause, NotificationType.WARNING, listener));
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, "External file sync may be slow",
cause, NotificationType.WARNING, listener));
}
}
@@ -339,6 +313,32 @@ public class FileWatcher {
return notifierProcess != null;
}
@TestOnly
public void startup() throws IOException {
final Application app = ApplicationManager.getApplication();
assert app != null && app.isUnitTestMode() : app;
myFailureShownToTheUser = true;
attemptCount = 0;
startupProcess(false);
attemptCount = 2 * MAX_PROCESS_LAUNCH_ATTEMPT_COUNT;
if (notifierProcess != null) {
new WatchForChangesThread().start();
}
}
@TestOnly
public void shutdown() throws InterruptedException {
final Application app = ApplicationManager.getApplication();
assert app != null && app.isUnitTestMode() : app;
final Process process = notifierProcess;
if (process != null) {
shutdownProcess();
process.waitFor();
}
}
private class WatchForChangesThread extends Thread {
public WatchForChangesThread() {
//noinspection HardCodedStringLiteral
@@ -396,7 +396,7 @@ public class FileWatcher {
final String pathB = readLine();
if (pathB == null || "#".equals(pathB)) break;
pairs.add(new Pair<String, String>(ensureEndsWithSlash(pathA), ensureEndsWithSlash(pathB)));
pairs.add(Pair.create(preparePathForMapping(pathA), preparePathForMapping(pathB)));
}
while (true);
@@ -414,10 +414,10 @@ public class FileWatcher {
}
synchronized (LOCK) {
final String watchedPath = checkWatchable(path);
if (watchedPath != null) {
final Collection<String> watchedPaths = checkWatchable(path);
if (!watchedPaths.isEmpty()) {
try {
onPathChange(ChangeKind.valueOf(command), watchedPath);
onPathChange(ChangeKind.valueOf(command), watchedPaths);
}
catch (IllegalArgumentException e) {
LOG.error("Illegal watcher command: " + command);
@@ -438,9 +438,9 @@ public class FileWatcher {
}
}
private static String ensureEndsWithSlash(String path) {
if (path.endsWith("/") || path.endsWith(File.separator)) return path;
return path + '/';
private static String preparePathForMapping(final String path) {
final String localPath = FileUtil.toSystemDependentName(path);
return localPath.endsWith(File.separator) ? localPath : localPath + File.separator;
}
private void writeLine(String line) throws IOException {
@@ -486,64 +486,76 @@ public class FileWatcher {
return line;
}
public boolean isWatched(VirtualFile file) {
return isOperational() && checkWatchable(file.getPresentableUrl()) != null;
public boolean isWatched(@NotNull final VirtualFile file) {
if (isOperational()) {
synchronized (LOCK) {
return !checkWatchable(file.getPresentableUrl()).isEmpty();
}
}
return false;
}
@Nullable
private String checkWatchable(String path) {
if (path == null) return null;
@NotNull
private Collection<String> checkWatchable(final String reportedPath) {
if (reportedPath == null) return Collections.emptyList();
for (Pair<String, String> mapping : myCanonicalMapping) {
if (path.startsWith(mapping.first)) {
path = mapping.second + path.substring(mapping.first.length());
break;
myAllPaths.clear();
myAllPaths.add(reportedPath);
for (Pair<String, String> map : myMapping) {
if (FileUtil.startsWith(reportedPath, map.first)) {
myAllPaths.add(map.second + reportedPath.substring(map.first.length()));
}
else if (FileUtil.startsWith(reportedPath, map.second)) {
myAllPaths.add(map.first + reportedPath.substring(map.second.length()));
}
}
for (String root : myRecursiveWatchRoots) {
if (FileUtil.startsWith(path, root)) {
return path;
myWatchedPaths.clear();
ext:
for (String path : myAllPaths) {
for (String root : myRecursiveWatchRoots) {
if (FileUtil.startsWith(path, root)) {
myWatchedPaths.add(path);
continue ext;
}
}
for (String root : myFlatWatchRoots) {
if (FileUtil.pathsEqual(path, root)) {
myWatchedPaths.add(path);
continue ext;
}
final File parentFile = new File(path).getParentFile();
if (parentFile != null && FileUtil.pathsEqual(parentFile.getPath(), root)) {
myWatchedPaths.add(path);
continue ext;
}
}
}
for (String root : myFlatWatchRoots) {
if (FileUtil.pathsEqual(path, root)) {
return path;
}
final File parentFile = new File(path).getParentFile();
if (parentFile != null && FileUtil.pathsEqual(parentFile.getPath(), root)) {
return path;
}
}
return null;
return myWatchedPaths;
}
private void onPathChange(final ChangeKind changeKind, final String path) {
private void onPathChange(final ChangeKind changeKind, final Collection<String> paths) {
switch (changeKind) {
case STATS:
case CHANGE:
addPath(path, myDirtyPaths);
myDirtyPaths.addAll(paths);
break;
case CREATE:
case DELETE:
final File parentFile = new File(path).getParentFile();
if (parentFile != null) {
addPath(parentFile.getPath(), myDirtyPaths);
}
else {
addPath(path, myDirtyPaths);
for (String path : paths) {
final File parent = new File(path).getParentFile();
myDirtyPaths.add(parent != null ? parent.getPath() : path);
}
break;
case DIRTY:
addPath(path, myDirtyDirs);
myDirtyDirs.addAll(paths);
break;
case RECDIRTY:
addPath(path, myDirtyRecursivePaths);
myDirtyRecursivePaths.addAll(paths);
break;
case RESET:
@@ -552,19 +564,6 @@ public class FileWatcher {
}
}
private void addPath(String path, List<String> list) {
list.add(path);
for (Pair<String, String> map : myMapping) {
if (FileUtil.startsWith(path, map.getFirst())) {
list.add(map.getSecond() + path.substring(map.getFirst().length()));
}
else if (FileUtil.startsWith(path, map.getSecond())) {
list.add(map.getFirst() + path.substring(map.getSecond().length()));
}
}
}
private void reset() {
synchronized (LOCK) {
myDirtyPaths.clear();
@@ -0,0 +1,438 @@
/*
* Copyright 2000-2012 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.openapi.vfs.local;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.idea.Bombed;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.impl.local.FileWatcher;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.testFramework.PlatformLangTestCase;
import com.intellij.util.Function;
import com.intellij.util.TimeoutUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.*;
public class FileWatcherTest extends PlatformLangTestCase {
private static final int NATIVE_PROCESS_DELAY = 500; // time to event to be caught by native watcher and passed to watcher thread
private FileWatcher myWatcher;
private LocalFileSystem myFileSystem;
private MessageBusConnection myConnection;
private final List<VFileEvent> myEvents = new ArrayList<VFileEvent>();
@Override
protected void setUp() throws Exception {
super.setUp();
myWatcher = FileWatcher.getInstance();
assertNotNull(myWatcher);
assertFalse(myWatcher.isOperational());
myWatcher.startup();
assertTrue(myWatcher.isOperational());
myFileSystem = LocalFileSystem.getInstance();
assertNotNull(myFileSystem);
myConnection = ApplicationManager.getApplication().getMessageBus().connect();
myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
@Override
public void before(@NotNull List<? extends VFileEvent> events) {
}
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
synchronized (myEvents) {
myEvents.addAll(events);
myEvents.notifyAll();
}
}
});
}
@Override
protected void tearDown() throws Exception {
try {
myConnection.disconnect();
myWatcher.shutdown();
}
finally {
myFileSystem = null;
myWatcher = null;
super.tearDown();
}
}
public void testFileRoot() throws Exception {
final File file = FileUtil.createTempFile("test.", ".txt");
refresh(file);
final LocalFileSystem.WatchRequest request = watch(file);
try {
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, file.getAbsolutePath());
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, file.getAbsolutePath());
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(file);
}
}
public void testNonCanonicallyNamedFileRoot() throws Exception {
if (SystemInfo.isFileSystemCaseSensitive) {
System.out.println("Ignored: case-insensitive FS required");
return;
}
final File file = FileUtil.createTempFile("test.", ".txt");
refresh(file);
final String watchRoot = file.getAbsolutePath().toUpperCase(Locale.US);
final LocalFileSystem.WatchRequest request = watch(new File(watchRoot));
try {
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, file.getAbsolutePath());
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, file.getAbsolutePath());
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(file);
}
}
public void testDirectoryRecursive() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
refresh(topDir);
final LocalFileSystem.WatchRequest request = watch(topDir);
try {
final File subDir = FileUtil.createTempDirectory(topDir, "sub.", null);
assertEvent(VFileCreateEvent.class, subDir.getAbsolutePath());
refresh(subDir);
final File file = FileUtil.createTempFile(subDir, "test.", ".txt", true, false);
assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, file.getAbsolutePath());
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, file.getAbsolutePath());
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(topDir);
}
}
public void testDirectoryFlat() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
final File watchedFile = FileUtil.createTempFile(topDir, "test.", ".txt", true, false);
final File subDir = FileUtil.createTempDirectory(topDir, "sub.", null);
final File unwatchedFile = FileUtil.createTempFile(subDir, "test.", ".txt", true, false);
refresh(topDir);
final LocalFileSystem.WatchRequest request = watch(topDir, false);
try {
FileUtil.writeToFile(watchedFile, "new content");
assertEvent(VFileContentChangeEvent.class, watchedFile.getAbsolutePath());
FileUtil.writeToFile(unwatchedFile, "new content");
assertEvent(VFileEvent.class);
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(topDir);
}
}
public void testDirectoryNonExisting() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
final File subDir = new File(topDir, "subDir");
final File file = new File(subDir, "file.txt");
refresh(topDir);
final LocalFileSystem.WatchRequest request = watch(subDir);
try {
assertTrue(subDir.toString(), subDir.mkdir());
assertEvent(VFileCreateEvent.class, subDir.getAbsolutePath());
refresh(subDir);
FileUtil.writeToFile(file, "new content");
assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(topDir);
}
}
public void testDirectoryOverlapping() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
final File file1 = FileUtil.createTempFile(topDir, "file1.", ".txt", true, false);
final File subDir = FileUtil.createTempDirectory(topDir, "sub.", null);
final File file2 = FileUtil.createTempFile(subDir, "file2.", ".txt", true, false);
final File sideDir = FileUtil.createTempDirectory("side.", null);
final File file3 = FileUtil.createTempFile(sideDir, "file3.", ".txt", true, false);
refresh(topDir);
refresh(sideDir);
final LocalFileSystem.WatchRequest request1 = watch(subDir);
final LocalFileSystem.WatchRequest request2 = watch(sideDir);
try {
FileUtil.writeToFile(file1, "new content");
FileUtil.writeToFile(file2, "new content");
FileUtil.writeToFile(file3, "new content");
assertEvent(VFileContentChangeEvent.class, file2.getAbsolutePath(), file3.getAbsolutePath());
final LocalFileSystem.WatchRequest request3 = watch(topDir);
try {
FileUtil.writeToFile(file1, "newer content");
FileUtil.writeToFile(file2, "newer content");
FileUtil.writeToFile(file3, "newer content");
assertEvent(VFileContentChangeEvent.class, file1.getAbsolutePath(), file2.getAbsolutePath(), file3.getAbsolutePath());
}
finally {
unwatch(request3);
}
FileUtil.writeToFile(file1, "newest content");
FileUtil.writeToFile(file2, "newest content");
FileUtil.writeToFile(file3, "newest content");
assertEvent(VFileContentChangeEvent.class, file2.getAbsolutePath(), file3.getAbsolutePath());
FileUtil.delete(file1);
FileUtil.delete(file2);
FileUtil.delete(file3);
assertEvent(VFileDeleteEvent.class, file1.getAbsolutePath(), file2.getAbsolutePath(), file3.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoots(Arrays.asList(request1, request2));
FileUtil.delete(topDir);
}
}
@Bombed(user = "roman.shevchenko", year = 2012, month = Calendar.MAY, day = 1)
public void testSymlinkAboveWatchRoot() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
final File topLink = SymlinkHandlingTest.createTempLink(topDir.getAbsolutePath(), "link");
final File subDir = FileUtil.createTempDirectory(topDir, "sub.", null);
final File file = FileUtil.createTempFile(subDir, "test.", ".txt", true, false);
final File fileLink = new File(new File(topLink, subDir.getName()), file.getName());
refresh(topDir);
refresh(topLink);
final LocalFileSystem.WatchRequest request = watch(topLink);
try {
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, fileLink.getAbsolutePath());
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, fileLink.getAbsolutePath());
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, fileLink.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(topLink);
FileUtil.delete(topDir);
}
}
@Bombed(user = "roman.shevchenko", year = 2012, month = Calendar.MAY, day = 1)
public void testSymlinkBelowWatchRoot() throws Exception {
final File targetDir = FileUtil.createTempDirectory("top.", null);
final File file = FileUtil.createTempFile(targetDir, "test.", ".txt", true, false);
final File linkDir = FileUtil.createTempDirectory("link.", null);
final File link = new File(linkDir, "link");
SymlinkHandlingTest.createTempLink(targetDir.getAbsolutePath(), link.getAbsolutePath());
final File fileLink = new File(link, file.getName());
refresh(targetDir);
refresh(linkDir);
final LocalFileSystem.WatchRequest request = watch(linkDir);
try {
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, fileLink.getAbsolutePath());
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, fileLink.getAbsolutePath());
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, fileLink.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
FileUtil.delete(linkDir);
FileUtil.delete(targetDir);
}
}
public void testSubst() throws Exception {
if (!SystemInfo.isWindows) {
System.out.println("Ignored: Windows required");
return;
}
final Set<Character> roots = ContainerUtil.map2Set(File.listRoots(), new Function<File, Character>() {
@Override
public Character fun(File root) {
return root.getPath().toLowerCase(Locale.US).charAt(0);
}
});
char subst = 0;
for (char c = 'e'; c <= 'z'; c++) {
if (!roots.contains(c)) {
subst = c;
break;
}
}
assertFalse("Occupied: " + roots.toString(), subst == 0);
final File targetDir = FileUtil.createTempDirectory("top.", null);
final File subDir = FileUtil.createTempDirectory(targetDir, "sub.", null);
final File file = FileUtil.createTempFile(subDir, "test.", ".txt", true, false);
final int rv = new GeneralCommandLine("subst", subst + ":", targetDir.getAbsolutePath()).createProcess().waitFor();
assertEquals(0, rv);
final File substDir = new File((subst + ":\\").toUpperCase(Locale.US), subDir.getName());
final File substFile = new File(substDir, file.getName());
refresh(targetDir);
refresh(substDir);
final LocalFileSystem.WatchRequest request = watch(substDir);
try {
FileUtil.writeToFile(file, "new content");
assertEvent(VFileContentChangeEvent.class, substFile.getAbsolutePath());
final LocalFileSystem.WatchRequest request2 = watch(targetDir);
try {
FileUtil.delete(file);
assertEvent(VFileDeleteEvent.class, file.getAbsolutePath(), substFile.getAbsolutePath());
}
finally {
unwatch(request2);
}
FileUtil.writeToFile(file, "re-creation");
assertEvent(VFileCreateEvent.class, substFile.getAbsolutePath());
}
finally {
myFileSystem.removeWatchedRoot(request);
new GeneralCommandLine("subst", subst + ":", "/d").createProcess().waitFor();
FileUtil.delete(targetDir);
}
}
private List<VFileEvent> getEvents() throws InterruptedException {
TimeoutUtil.sleep(NATIVE_PROCESS_DELAY);
myFileSystem.refresh(false);
synchronized (myEvents) {
final ArrayList<VFileEvent> result = new ArrayList<VFileEvent>(myEvents);
myEvents.clear();
return result;
}
}
private void clearEvents() {
myFileSystem.refresh(false);
synchronized (myEvents) {
myEvents.clear();
}
}
@NotNull
private LocalFileSystem.WatchRequest watch(final File watchFile) throws InterruptedException {
return watch(watchFile, true);
}
@NotNull
private LocalFileSystem.WatchRequest watch(final File watchFile, final boolean recursive) throws InterruptedException {
final LocalFileSystem.WatchRequest request = myFileSystem.addRootToWatch(watchFile.getAbsolutePath(), recursive);
assertNotNull(request);
TimeoutUtil.sleep(NATIVE_PROCESS_DELAY);
clearEvents();
return request;
}
private void unwatch(final LocalFileSystem.WatchRequest request) throws InterruptedException {
myFileSystem.removeWatchedRoot(request);
TimeoutUtil.sleep(NATIVE_PROCESS_DELAY);
clearEvents();
}
private VirtualFile refresh(final File file) {
final VirtualFile vFile = myFileSystem.refreshAndFindFileByIoFile(file);
assertNotNull(file.toString(), vFile);
VfsUtilCore.visitChildrenRecursively(vFile, new VirtualFileVisitor() {
@Override
public boolean visitFile(@NotNull VirtualFile file) {
file.getChildren();
return true;
}
});
return vFile;
}
private void assertEvent(final Class<? extends VFileEvent> type, final String... paths) throws InterruptedException {
final List<VFileEvent> events = getEvents();
assertEquals(events.toString(), paths.length, events.size());
final Set<String> pathSet = ContainerUtil.map2Set(paths, new Function<String, String>() {
@Override
public String fun(final String path) {
return FileUtil.toSystemIndependentName(path);
}
});
for (final VFileEvent event : events) {
assertTrue(event.toString(), type.isInstance(event));
final VirtualFile eventFile = event.getFile();
assertNotNull(event.toString(), eventFile);
assertTrue(eventFile + " not in " + Arrays.toString(paths), pathSet.remove(eventFile.getPath()));
}
}
}
@@ -266,7 +266,7 @@ public class SymlinkHandlingTest extends LightPlatformLangTestCase {
}
// todo[r.sh] use NIO2 API after migration to JDK 7
private static File createTempLink(final String target, final String link) throws InterruptedException, ExecutionException {
public static File createTempLink(final String target, final String link) throws InterruptedException, ExecutionException {
final boolean isAbsolute = SystemInfo.isUnix && StringUtil.startsWithChar(link, '/') ||
SystemInfo.isWindows && link.matches("^[c-zC-Z]:[/\\\\].*$");
final File linkFile = isAbsolute ? new File(link) : new File(FileUtil.getTempDirectory(), link);
@@ -52,7 +52,9 @@ public class AndroidCommonUtils {
private static final Pattern WARNING_PATTERN = Pattern.compile(".*warning.*");
private static final Pattern ERROR_PATTERN = Pattern.compile(".*error.*");
private static final Pattern EXCEPTION_PATTERN = Pattern.compile(".*exception.*");
private static Pattern R_PATTERN = Pattern.compile("R(\\$.*)?\\.class");
private static Pattern MANIFEST_PATTERN = Pattern.compile("Manifest(\\$.*)?\\.class");
public static final Pattern COMPILER_MESSAGE_PATTERN = Pattern.compile("(.+):(\\d+):.+");
@@ -204,7 +206,7 @@ public class AndroidCommonUtils {
private static void addFileToJar(@NotNull File file,
@NotNull File rootDirectory,
boolean packRClasses,
boolean packRAndManifestClasses,
@NotNull List<Pair<File, String>> files)
throws IOException {
@@ -213,7 +215,7 @@ public class AndroidCommonUtils {
if (children != null) {
for (File child : children) {
addFileToJar(child, rootDirectory, packRClasses, files);
addFileToJar(child, rootDirectory, packRAndManifestClasses, files);
}
}
}
@@ -222,7 +224,9 @@ public class AndroidCommonUtils {
return;
}
if (!packRClasses && R_PATTERN.matcher(file.getName()).matches()) {
if (!packRAndManifestClasses &&
(R_PATTERN.matcher(file.getName()).matches() ||
MANIFEST_PATTERN.matcher(file.getName()).matches())) {
return;
}
@@ -77,7 +77,7 @@ public class GitBranchUiUtil {
*/
@Nullable
public static String getNewBranchNameFromUser(@NotNull Project project, @NotNull Collection<GitRepository> repositories, @NotNull String dialogTitle) {
return Messages.showInputDialog(project, "Enter the name of new branch", dialogTitle, Messages.getQuestionIcon(), "",
return Messages.showInputDialog(project, "Enter the name of new branch:", dialogTitle, Messages.getQuestionIcon(), "",
GitNewBranchNameValidator.newInstance(repositories));
}
@@ -95,8 +95,10 @@ public class MavenRepositoriesConfigurable extends BaseConfigurable implements S
final String value = (String)myServiceList.getSelectedValue();
final String text = Messages.showInputDialog("Artifactory or Nexus Service URL", "Add Service URL", Messages.getQuestionIcon(),
value == null ? "http://" : value, new URLInputVaslidator());
myModel.add(text);
myServiceList.setSelectedValue(text, true);
if (StringUtil.isNotEmpty(text)) {
myModel.add(text);
myServiceList.setSelectedValue(text, true);
}
}
});
myEditButton.addActionListener(new ActionListener() {
@@ -105,7 +107,7 @@ public class MavenRepositoriesConfigurable extends BaseConfigurable implements S
final int index = myServiceList.getSelectedIndex();
final String text = Messages.showInputDialog("Artifactory or Nexus Service URL", "Edit Service URL", Messages.getQuestionIcon(),
myModel.getElementAt(index), new URLInputVaslidator());
if (text != null) {
if (StringUtil.isNotEmpty(text)) {
myModel.setElementAt(text, index);
}
}
@@ -145,7 +145,7 @@ public class DuplicatePropertyInspection extends GlobalSimpleInspectionTool {
private void checkFile(final PsiFile file, final InspectionManager manager, GlobalInspectionContextImpl context, final RefManager refManager, final ProblemDescriptionsProcessor processor) {
if (!(file instanceof PropertiesFile)) return;
if (!context.isToCheckMember(file, this)) return;
if (!context.isToCheckFile(file, this)) return;
final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(file.getProject());
final PropertiesFile propertiesFile = (PropertiesFile)file;
final List<IProperty> properties = propertiesFile.getProperties();
@@ -133140,6 +133140,7 @@ unwarrantably
unwarranted
unwary
unwashed
unwatch
unwatchable
unwatched
unwavering