mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+1
-1
@@ -62,7 +62,7 @@ public class VariableInplaceRenamer extends InplaceRefactoring {
|
||||
);
|
||||
private ResolveSnapshotProvider.ResolveSnapshot mySnapshot;
|
||||
private TextRange mySelectedRange;
|
||||
private Language myLanguage;
|
||||
protected Language myLanguage;
|
||||
|
||||
public VariableInplaceRenamer(@NotNull PsiNamedElement elementToRename, Editor editor) {
|
||||
this(elementToRename, editor, elementToRename.getProject());
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 com.intellij.ui.mac;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.ui.mac.foundation.Foundation;
|
||||
import com.intellij.ui.mac.foundation.ID;
|
||||
import com.sun.jna.Callback;
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static com.intellij.ui.mac.foundation.Foundation.invoke;
|
||||
|
||||
/**
|
||||
* @author Denis Fokin
|
||||
*/
|
||||
public class JDK7WindowReorderingWorkaround {
|
||||
|
||||
private static AtomicInteger requestorCount = new AtomicInteger();
|
||||
|
||||
private static final Callback windowDidBecomeMainCallback = new Callback() {
|
||||
@SuppressWarnings("UnusedDeclaration") // this is a native up-call
|
||||
public void callback(ID self,
|
||||
ID nsNotification)
|
||||
{
|
||||
if (requestorCount.intValue() == 0) {
|
||||
invoke(self, "oldWindowDidBecomeMain:", nsNotification);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static {
|
||||
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
|
||||
ID awtWindow = Foundation.getObjcClass("AWTWindow");
|
||||
|
||||
Pointer windowWillEnterFullScreenMethod = Foundation.createSelector("windowDidBecomeMain:");
|
||||
ID originalWindowWillEnterFullScreen = Foundation.class_replaceMethod(awtWindow, windowWillEnterFullScreenMethod,
|
||||
windowDidBecomeMainCallback, "v@::@");
|
||||
|
||||
Foundation.addMethodByID(awtWindow, Foundation.createSelector("oldWindowDidBecomeMain:"),
|
||||
originalWindowWillEnterFullScreen, "v@::@");
|
||||
}
|
||||
}
|
||||
|
||||
static void disableReordering() {
|
||||
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
|
||||
requestorCount.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
static void enableReordering () {
|
||||
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
|
||||
requestorCount.decrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -137,6 +137,7 @@ public class MacFileChooserDialogImpl implements PathChooserDialog {
|
||||
finally {
|
||||
Foundation.cfRelease(self);
|
||||
Foundation.cfRelease(contextInfo);
|
||||
JDK7WindowReorderingWorkaround.enableReordering();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -323,6 +324,7 @@ public class MacFileChooserDialogImpl implements PathChooserDialog {
|
||||
ourImplMap.put(delegate, impl);
|
||||
|
||||
final ID select = toSelect == null ? null : Foundation.nsString(toSelect);
|
||||
JDK7WindowReorderingWorkaround.disableReordering();
|
||||
invoke(delegate, "performSelectorOnMainThread:withObject:waitUntilDone:", Foundation.createSelector("showOpenPanel:"), select, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -72,6 +71,7 @@ public class MacMessagesImpl extends MacMessages {
|
||||
resultsFromDocumentRoot.put(documentRoot, new MessageResult(returnCode.intValue(), suppressState.intValue() == 1));
|
||||
queuesFromDocumentRoot.get(windowFromId.get(contextInfo.longValue())).runFromQueue();
|
||||
}
|
||||
JDK7WindowReorderingWorkaround.enableReordering();
|
||||
cfRelease(self);
|
||||
}
|
||||
};
|
||||
@@ -203,6 +203,7 @@ public class MacMessagesImpl extends MacMessages {
|
||||
private MacMessagesImpl() {}
|
||||
|
||||
private static final Callback windowDidBecomeMainCallback = new Callback() {
|
||||
@SuppressWarnings("UnusedDeclaration") // this is a native up-call
|
||||
public void callback(ID self,
|
||||
ID nsNotification)
|
||||
{
|
||||
@@ -357,6 +358,7 @@ public class MacMessagesImpl extends MacMessages {
|
||||
private static void startModal(final Window w, ID windowId) {
|
||||
long windowPtr = windowId.longValue();
|
||||
synchronized (lock) {
|
||||
JDK7WindowReorderingWorkaround.disableReordering();
|
||||
windowFromId.put(windowPtr, w);
|
||||
if (blockedDocumentRoots.keySet().contains(w)) {
|
||||
blockedDocumentRoots.put(w, blockedDocumentRoots.get(w) + 1);
|
||||
@@ -566,7 +568,7 @@ public class MacMessagesImpl extends MacMessages {
|
||||
|
||||
final Window documentRoot = getDocumentRootFromWindow(foremostWindow);
|
||||
|
||||
final ID nativeFocusedWindow = windowIdFromWindow(foremostWindow);
|
||||
final ID nativeFocusedWindow = MacUtil.findWindowFromJavaWindow(foremostWindow);
|
||||
|
||||
paramsWrapper.setNativeWindow(nativeFocusedWindow);
|
||||
|
||||
@@ -591,54 +593,10 @@ public class MacMessagesImpl extends MacMessages {
|
||||
return documentRoot;
|
||||
}
|
||||
|
||||
private static ID windowIdFromWindow (Window w) {
|
||||
|
||||
ID windowId = null;
|
||||
|
||||
if (SystemInfo.isJavaVersionAtLeast("1.7") && Registry.is("skip.untitled.windows.for.mac.messages")) {
|
||||
try {
|
||||
Class <?> cWindowPeerClass = w.getPeer().getClass();
|
||||
Method getPlatformWindowMethod = cWindowPeerClass.getDeclaredMethod("getPlatformWindow");
|
||||
Object cPlatformWindow = getPlatformWindowMethod.invoke(w.getPeer());
|
||||
Class <?> cPlatformWindowClass = cPlatformWindow.getClass();
|
||||
Method getNSWindowPtrMethod = cPlatformWindowClass.getDeclaredMethod("getNSWindowPtr");
|
||||
windowId = new ID((Long)getNSWindowPtrMethod.invoke(cPlatformWindow));
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
|
||||
} else {
|
||||
String foremostWindowTitle = getWindowTitle(w);
|
||||
windowId = MacUtil.findWindowForTitle(foremostWindowTitle);
|
||||
}
|
||||
|
||||
return windowId;
|
||||
|
||||
}
|
||||
|
||||
private static int convertReturnCodeFromNativeMessageDialog(int result) {
|
||||
return result - 1000;
|
||||
}
|
||||
|
||||
private static String getWindowTitle(Window documentRoot) {
|
||||
String windowTitle;
|
||||
if (documentRoot instanceof Frame) {
|
||||
windowTitle = ((Frame)documentRoot).getTitle();
|
||||
} else if (documentRoot instanceof Dialog) {
|
||||
windowTitle = ((Dialog)documentRoot).getTitle();
|
||||
} else {
|
||||
throw new RuntimeException("The window is not a frame and not a dialog!");
|
||||
}
|
||||
return windowTitle;
|
||||
}
|
||||
|
||||
@Messages.YesNoCancelResult
|
||||
private static int convertReturnCodeFromNativeAlertDialog(int returnCode, String alternateText) {
|
||||
// DEFAULT = 1
|
||||
@@ -744,8 +702,8 @@ public class MacMessagesImpl extends MacMessages {
|
||||
}
|
||||
|
||||
//Actually can, but not in this implementation. If you know a reasonable scenario, please ask Denis Fokin for the improvement.
|
||||
LOG.assertTrue(getWindowTitle(_window) != null, "A window without a title should not be used for showing MacMessages");
|
||||
while (_window != null && getWindowTitle(_window) == null) {
|
||||
LOG.assertTrue(MacUtil.getWindowTitle(_window) != null, "A window without a title should not be used for showing MacMessages");
|
||||
while (_window != null && MacUtil.getWindowTitle(_window) == null) {
|
||||
_window = _window.getOwner();
|
||||
//At least our frame should have a title
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.io.BaseDataReader;
|
||||
import com.intellij.util.io.BaseOutputReader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -28,7 +29,7 @@ import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static com.intellij.util.io.BaseOutputReader.AdaptiveSleepingPolicy;
|
||||
import static com.intellij.util.io.BaseDataReader.AdaptiveSleepingPolicy;
|
||||
|
||||
public class BaseOSProcessHandler extends ProcessHandler implements TaskExecutor {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.process.OSProcessHandlerBase");
|
||||
@@ -82,13 +83,10 @@ public class BaseOSProcessHandler extends ProcessHandler implements TaskExecutor
|
||||
@Override
|
||||
public void startNotified(final ProcessEvent event) {
|
||||
try {
|
||||
BaseOutputReader.SleepingPolicy sleepingPolicy =
|
||||
useAdaptiveSleepingPolicyWhenReadingOutput() ? new AdaptiveSleepingPolicy() : BaseOutputReader.SleepingPolicy.SIMPLE;
|
||||
final BaseOutputReader stdoutReader = new SimpleOutputReader(createProcessOutReader(), ProcessOutputTypes.STDOUT, sleepingPolicy);
|
||||
final BaseOutputReader stderrReader = processHasSeparateErrorStream()
|
||||
? new SimpleOutputReader(createProcessErrReader(), ProcessOutputTypes.STDERR,
|
||||
sleepingPolicy)
|
||||
: null;
|
||||
BaseDataReader.SleepingPolicy sleepingPolicy =
|
||||
useAdaptiveSleepingPolicyWhenReadingOutput() ? new AdaptiveSleepingPolicy() : BaseDataReader.SleepingPolicy.SIMPLE;
|
||||
final BaseDataReader stdoutReader = createOutputDataReader(sleepingPolicy);
|
||||
final BaseDataReader stderrReader = processHasSeparateErrorStream() ? createErrorDataReader(sleepingPolicy) : null;
|
||||
|
||||
myWaitFor.setTerminationCallback(new Consumer<Integer>() {
|
||||
@Override
|
||||
@@ -120,6 +118,17 @@ public class BaseOSProcessHandler extends ProcessHandler implements TaskExecutor
|
||||
super.startNotify();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected BaseDataReader createErrorDataReader(BaseDataReader.SleepingPolicy sleepingPolicy) {
|
||||
return new SimpleOutputReader(createProcessErrReader(), ProcessOutputTypes.STDERR,
|
||||
sleepingPolicy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected BaseDataReader createOutputDataReader(BaseDataReader.SleepingPolicy sleepingPolicy) {
|
||||
return new SimpleOutputReader(createProcessOutReader(), ProcessOutputTypes.STDOUT, sleepingPolicy);
|
||||
}
|
||||
|
||||
protected void onOSProcessTerminated(final int exitCode) {
|
||||
notifyProcessTerminated(exitCode);
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
package com.intellij.ui.mac.foundation;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -27,6 +29,8 @@ import javax.swing.text.JTextComponent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.AWTEventListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static com.intellij.ui.mac.foundation.Foundation.invoke;
|
||||
import static com.intellij.ui.mac.foundation.Foundation.toStringViaUTF8;
|
||||
@@ -35,6 +39,7 @@ import static com.intellij.ui.mac.foundation.Foundation.toStringViaUTF8;
|
||||
* @author pegov
|
||||
*/
|
||||
public class MacUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.mac.foundation.MacUtil");
|
||||
public static final String MAC_NATIVE_WINDOW_SHOWING = "MAC_NATIVE_WINDOW_SHOWING";
|
||||
|
||||
private MacUtil() {
|
||||
@@ -72,7 +77,7 @@ public class MacUtil {
|
||||
|
||||
return focusedWindow;
|
||||
}
|
||||
|
||||
|
||||
public static synchronized void startModal(JComponent component, String key) {
|
||||
try {
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
@@ -91,7 +96,7 @@ public class MacUtil {
|
||||
((MenuComponent)source).dispatchEvent(event);
|
||||
}
|
||||
else {
|
||||
System.err.println("Unable to dispatch: " + event);
|
||||
LOG.debug("Unable to dispatch: " + event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,4 +142,47 @@ public class MacUtil {
|
||||
});
|
||||
Toolkit.getDefaultToolkit().addAWTEventListener(listener, AWTEvent.KEY_EVENT_MASK);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static ID findWindowFromJavaWindow(final Window w) {
|
||||
ID windowId = null;
|
||||
if (SystemInfo.isJavaVersionAtLeast("1.7") && Registry.is("skip.untitled.windows.for.mac.messages")) {
|
||||
try {
|
||||
//noinspection deprecation
|
||||
Class <?> cWindowPeerClass = w.getPeer().getClass();
|
||||
Method getPlatformWindowMethod = cWindowPeerClass.getDeclaredMethod("getPlatformWindow");
|
||||
Object cPlatformWindow = getPlatformWindowMethod.invoke(w.getPeer());
|
||||
Class <?> cPlatformWindowClass = cPlatformWindow.getClass();
|
||||
Method getNSWindowPtrMethod = cPlatformWindowClass.getDeclaredMethod("getNSWindowPtr");
|
||||
windowId = new ID((Long)getNSWindowPtrMethod.invoke(cPlatformWindow));
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
|
||||
} else {
|
||||
String foremostWindowTitle = getWindowTitle(w);
|
||||
windowId = findWindowForTitle(foremostWindowTitle);
|
||||
}
|
||||
return windowId;
|
||||
}
|
||||
|
||||
|
||||
public static String getWindowTitle(Window documentRoot) {
|
||||
String windowTitle;
|
||||
if (documentRoot instanceof Frame) {
|
||||
windowTitle = ((Frame)documentRoot).getTitle();
|
||||
} else if (documentRoot instanceof Dialog) {
|
||||
windowTitle = ((Dialog)documentRoot).getTitle();
|
||||
} else {
|
||||
throw new RuntimeException("The window is not a frame and not a dialog!");
|
||||
}
|
||||
return windowTitle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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 com.intellij.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.TimeoutUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public abstract class BaseDataReader {
|
||||
private static final Logger LOG = Logger.getInstance(BaseDataReader.class);
|
||||
|
||||
protected volatile boolean isStopped = false;
|
||||
|
||||
private Future<?> myFinishedFuture = null;
|
||||
@NotNull protected final SleepingPolicy mySleepingPolicy;
|
||||
|
||||
public BaseDataReader(SleepingPolicy sleepingPolicy) {
|
||||
mySleepingPolicy = sleepingPolicy != null ? sleepingPolicy: SleepingPolicy.SIMPLE;
|
||||
}
|
||||
|
||||
protected void start() {
|
||||
if (myFinishedFuture == null) {
|
||||
myFinishedFuture = executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doRun();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Future<?> executeOnPooledThread(Runnable runnable);
|
||||
|
||||
public interface SleepingPolicy {
|
||||
int sleepTimeWhenWasActive = 1;
|
||||
int sleepTimeWhenIdle = 5;
|
||||
|
||||
SleepingPolicy SIMPLE = new SleepingPolicy() {
|
||||
@Override
|
||||
public int getTimeToSleep(boolean wasActive) {
|
||||
return wasActive ? sleepTimeWhenWasActive : sleepTimeWhenIdle;
|
||||
}
|
||||
};
|
||||
|
||||
int getTimeToSleep(boolean wasActive);
|
||||
}
|
||||
|
||||
public static class AdaptiveSleepingPolicy implements SleepingPolicy {
|
||||
private static final int maxSleepTimeWhenIdle = 200;
|
||||
private static final int maxIterationsWithCurrentSleepTime = 50;
|
||||
|
||||
private volatile int myIterationsWithCurrentTime;
|
||||
private volatile int myCurrentSleepTime = sleepTimeWhenIdle;
|
||||
|
||||
@Override
|
||||
public int getTimeToSleep(boolean wasActive) {
|
||||
int currentSleepTime = myCurrentSleepTime; // volatile read
|
||||
if (wasActive) currentSleepTime = sleepTimeWhenWasActive;
|
||||
else if (currentSleepTime == sleepTimeWhenWasActive) {
|
||||
currentSleepTime = sleepTimeWhenIdle;
|
||||
myIterationsWithCurrentTime = 0;
|
||||
}
|
||||
else {
|
||||
int iterationsWithCurrentTime = ++myIterationsWithCurrentTime;
|
||||
if (iterationsWithCurrentTime >= maxIterationsWithCurrentSleepTime) {
|
||||
myIterationsWithCurrentTime = 0;
|
||||
currentSleepTime = Math.min(2* currentSleepTime, maxSleepTimeWhenIdle);
|
||||
}
|
||||
}
|
||||
|
||||
myCurrentSleepTime = currentSleepTime; // volatile write
|
||||
return currentSleepTime;
|
||||
}
|
||||
}
|
||||
|
||||
protected void doRun() {
|
||||
try {
|
||||
while (true) {
|
||||
boolean read = readAvailable();
|
||||
|
||||
if (isStopped) {
|
||||
break;
|
||||
}
|
||||
|
||||
TimeoutUtil.sleep(mySleepingPolicy.getTimeToSleep(read));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("Can't close stream", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean readAvailable() throws IOException;
|
||||
protected abstract void close() throws IOException;
|
||||
|
||||
public void stop() {
|
||||
isStopped = true;
|
||||
}
|
||||
|
||||
public void waitFor() throws InterruptedException {
|
||||
try {
|
||||
myFinishedFuture.get();
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,121 +15,29 @@
|
||||
*/
|
||||
package com.intellij.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.TimeoutUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* @author traff
|
||||
*/
|
||||
public abstract class BaseOutputReader {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.BaseOutputReader");
|
||||
public abstract class BaseOutputReader extends BaseDataReader {
|
||||
|
||||
protected final Reader myReader;
|
||||
protected volatile boolean isStopped = false;
|
||||
|
||||
private final char[] myBuffer = new char[8192];
|
||||
private final StringBuilder myTextBuffer = new StringBuilder();
|
||||
private boolean skipLF = false;
|
||||
|
||||
private Future<?> myFinishedFuture = null;
|
||||
@NotNull protected final SleepingPolicy mySleepingPolicy;
|
||||
|
||||
public BaseOutputReader(@NotNull Reader reader) {
|
||||
this(reader, null);
|
||||
}
|
||||
|
||||
public BaseOutputReader(@NotNull Reader reader, SleepingPolicy sleepingPolicy) {
|
||||
super(sleepingPolicy);
|
||||
myReader = reader;
|
||||
mySleepingPolicy = sleepingPolicy != null ? sleepingPolicy: SleepingPolicy.SIMPLE;
|
||||
}
|
||||
|
||||
protected void start() {
|
||||
if (myFinishedFuture == null) {
|
||||
myFinishedFuture = executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doRun();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Future<?> executeOnPooledThread(Runnable runnable);
|
||||
|
||||
public interface SleepingPolicy {
|
||||
int sleepTimeWhenWasActive = 1;
|
||||
int sleepTimeWhenIdle = 5;
|
||||
|
||||
SleepingPolicy SIMPLE = new SleepingPolicy() {
|
||||
@Override
|
||||
public int getTimeToSleep(boolean wasActive) {
|
||||
return wasActive ? sleepTimeWhenWasActive : sleepTimeWhenIdle;
|
||||
}
|
||||
};
|
||||
|
||||
int getTimeToSleep(boolean wasActive);
|
||||
}
|
||||
|
||||
public static class AdaptiveSleepingPolicy implements SleepingPolicy {
|
||||
private static final int maxSleepTimeWhenIdle = 200;
|
||||
private static final int maxIterationsWithCurrentSleepTime = 50;
|
||||
|
||||
private volatile int myIterationsWithCurrentTime;
|
||||
private volatile int myCurrentSleepTime = sleepTimeWhenIdle;
|
||||
|
||||
@Override
|
||||
public int getTimeToSleep(boolean wasActive) {
|
||||
int currentSleepTime = myCurrentSleepTime; // volatile read
|
||||
if (wasActive) currentSleepTime = sleepTimeWhenWasActive;
|
||||
else if (currentSleepTime == sleepTimeWhenWasActive) {
|
||||
currentSleepTime = sleepTimeWhenIdle;
|
||||
myIterationsWithCurrentTime = 0;
|
||||
}
|
||||
else {
|
||||
int iterationsWithCurrentTime = ++myIterationsWithCurrentTime;
|
||||
if (iterationsWithCurrentTime >= maxIterationsWithCurrentSleepTime) {
|
||||
myIterationsWithCurrentTime = 0;
|
||||
currentSleepTime = Math.min(2* currentSleepTime, maxSleepTimeWhenIdle);
|
||||
}
|
||||
}
|
||||
|
||||
myCurrentSleepTime = currentSleepTime; // volatile write
|
||||
return currentSleepTime;
|
||||
}
|
||||
}
|
||||
|
||||
protected void doRun() {
|
||||
try {
|
||||
while (true) {
|
||||
boolean read = readAvailable();
|
||||
|
||||
if (isStopped) {
|
||||
break;
|
||||
}
|
||||
|
||||
TimeoutUtil.sleep(mySleepingPolicy.getTimeToSleep(read));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
myReader.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("Can't close stream", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,18 +84,10 @@ public abstract class BaseOutputReader {
|
||||
return read;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close() throws IOException {
|
||||
myReader.close();
|
||||
}
|
||||
|
||||
protected abstract void onTextAvailable(@NotNull String text);
|
||||
|
||||
public void stop() {
|
||||
isStopped = true;
|
||||
}
|
||||
|
||||
public void waitFor() throws InterruptedException {
|
||||
try {
|
||||
myFinishedFuture.get();
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 com.intellij.util.io;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public abstract class BinaryOutputReader extends BaseDataReader {
|
||||
|
||||
@NotNull private final InputStream myStream;
|
||||
@NotNull private final byte[] myBuffer = new byte[8192];
|
||||
|
||||
public BinaryOutputReader(@NotNull InputStream stream, SleepingPolicy sleepingPolicy) {
|
||||
super(sleepingPolicy);
|
||||
myStream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean readAvailable() throws IOException {
|
||||
byte[] buffer = myBuffer;
|
||||
|
||||
boolean read = false;
|
||||
while (myStream.available() > 0) {
|
||||
int n = myStream.read(buffer);
|
||||
if (n <= 0) break;
|
||||
read = true;
|
||||
|
||||
onBinaryAvailable(buffer, n);
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
protected abstract void onBinaryAvailable(@NotNull byte[] data, int size);
|
||||
|
||||
@Override
|
||||
protected void close() throws IOException {
|
||||
myStream.close();
|
||||
}
|
||||
}
|
||||
@@ -22,13 +22,18 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.io.BaseDataReader;
|
||||
import com.intellij.util.io.BinaryOutputReader;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.tmatesoft.svn.core.SVNCancelException;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -117,7 +122,13 @@ public class CommandExecutor {
|
||||
|
||||
@NotNull
|
||||
protected OSProcessHandler createProcessHandler() {
|
||||
return new OSProcessHandler(myProcess, myCommandLine.getCommandLineString());
|
||||
return needsBinaryOutput()
|
||||
? new BinaryOSProcessHandler(myProcess, myCommandLine.getCommandLineString())
|
||||
: new OSProcessHandler(myProcess, myCommandLine.getCommandLineString());
|
||||
}
|
||||
|
||||
private boolean needsBinaryOutput() {
|
||||
return SvnCommandName.cat.equals(myCommand.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -142,6 +153,11 @@ public class CommandExecutor {
|
||||
return outputAdapter.getOutput().getStderr();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ByteArrayOutputStream getBinaryOutput() {
|
||||
return myHandler instanceof BinaryOSProcessHandler ? ((BinaryOSProcessHandler)myHandler).myBinaryOutput : null;
|
||||
}
|
||||
|
||||
// TODO: Carefully here - do not modify command from threads other than the one started command execution
|
||||
@NotNull
|
||||
public Command getCommand() {
|
||||
@@ -344,4 +360,38 @@ public class CommandExecutor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class BinaryOSProcessHandler extends OSProcessHandler {
|
||||
|
||||
@NotNull private final ByteArrayOutputStream myBinaryOutput;
|
||||
|
||||
public BinaryOSProcessHandler(@NotNull final Process process, @Nullable final String commandLine) {
|
||||
super(process, commandLine);
|
||||
myBinaryOutput = new ByteArrayOutputStream();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected BaseDataReader createOutputDataReader(BaseDataReader.SleepingPolicy sleepingPolicy) {
|
||||
return new SimpleBinaryOutputReader(myProcess.getInputStream(), sleepingPolicy);
|
||||
}
|
||||
|
||||
private class SimpleBinaryOutputReader extends BinaryOutputReader {
|
||||
|
||||
public SimpleBinaryOutputReader(@NotNull InputStream stream, SleepingPolicy sleepingPolicy) {
|
||||
super(stream, sleepingPolicy);
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBinaryAvailable(@NotNull byte[] data, int size) {
|
||||
myBinaryOutput.write(data, 0, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Future<?> executeOnPooledThread(Runnable runnable) {
|
||||
return BinaryOSProcessHandler.this.executeOnPooledThread(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.idea.svn.commandLine.*;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -22,17 +23,17 @@ public class CmdContentClient extends BaseSvnClient implements ContentClient {
|
||||
public byte[] getContent(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable SVNRevision pegRevision)
|
||||
throws VcsException, FileTooBigRuntimeException {
|
||||
// TODO: rewrite this to provide output as Stream
|
||||
// TODO: rewrite without conversion from String to byte[]
|
||||
// TODO: Also implement max size constraint like in SvnKitContentClient
|
||||
// TODO: Could not use export to get content of scheduled for deletion file - use cat command, but write special binary handler
|
||||
// NOTE: Export could not be used to get content of scheduled for deletion file
|
||||
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
CommandUtil.put(parameters, target.getPathOrUrlString(), pegRevision);
|
||||
CommandUtil.put(parameters, revision);
|
||||
|
||||
CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.cat, parameters, null);
|
||||
|
||||
byte[] bytes = CharsetToolkit.getUtf8Bytes(command.getOutput());
|
||||
// TODO: currently binary output will be null for terminal mode - use text output in this case
|
||||
ByteArrayOutputStream output = command.getBinaryOutput();
|
||||
byte[] bytes = output != null ? output.toByteArray() : CharsetToolkit.getUtf8Bytes(command.getOutput());
|
||||
|
||||
ContentRevisionCache.checkContentsSize(target.getPathOrUrlString(), bytes.length);
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<patterns.patternClass className="com.jetbrains.python.patterns.PythonPatterns" alias="py"/>
|
||||
<multiHostInjector implementation="com.jetbrains.python.intelliLang.PyTemporaryInjector"/>
|
||||
<multiHostInjector implementation="com.jetbrains.python.intelliLang.PyCommentInjector"/>
|
||||
<multiHostInjector implementation="com.jetbrains.python.intelliLang.PyConfigurationInjector"/>
|
||||
<multiHostInjector implementation="com.jetbrains.python.intelliLang.PyTemporaryInjector"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.jetbrains.python.intelliLang;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.codeInsight.PyInjectorBase;
|
||||
import org.intellij.plugins.intelliLang.inject.InjectedLanguage;
|
||||
import org.intellij.plugins.intelliLang.inject.InjectorUtils;
|
||||
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author vlan
|
||||
*/
|
||||
public class PyCommentInjector extends PyInjectorBase {
|
||||
@Nullable
|
||||
@Override
|
||||
public Language getInjectedLanguage(@NotNull PsiElement context) {
|
||||
final BaseInjection injection = InjectorUtils.findCommentInjection(context, "comment", null);
|
||||
if (injection != null) {
|
||||
return InjectedLanguage.findLanguageById(injection.getInjectedLanguageId());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+9
@@ -15,10 +15,13 @@
|
||||
*/
|
||||
package com.jetbrains.python.intelliLang;
|
||||
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiLanguageInjectionHost;
|
||||
import com.jetbrains.python.patterns.PythonPatterns;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import org.intellij.plugins.intelliLang.inject.AbstractLanguageInjectionSupport;
|
||||
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -51,4 +54,10 @@ public class PyLanguageInjectionSupport extends AbstractLanguageInjectionSupport
|
||||
public String getHelpId() {
|
||||
return "reference.settings.language.injection.generic.python";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BaseInjection findCommentInjection(@NotNull PsiElement host, @Nullable Ref<PsiElement> commentRef) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user