This commit is contained in:
Alexey Kudravtsev
2017-04-25 17:19:19 +03:00
parent 526d4f0c2c
commit 06156396fa
7 changed files with 134 additions and 122 deletions
@@ -104,17 +104,15 @@ public class CompilerManagerImpl extends CompilerManager {
projectGeneratedSrcRoot.mkdirs();
final LocalFileSystem lfs = LocalFileSystem.getInstance();
myWatchRoots = lfs.addRootsToWatch(Collections.singletonList(FileUtil.toCanonicalPath(projectGeneratedSrcRoot.getPath())), true);
Disposer.register(project, new Disposable() {
public void dispose() {
final ExternalJavacManager manager = myExternalJavacManager;
myExternalJavacManager = null;
if (manager != null) {
manager.stop();
}
lfs.removeWatchedRoots(myWatchRoots);
if (ApplicationManager.getApplication().isUnitTestMode()) { // force cleanup for created compiler system directory with generated sources
FileUtil.delete(CompilerPaths.getCompilerSystemDirectory(project));
}
Disposer.register(project, () -> {
final ExternalJavacManager manager = myExternalJavacManager;
myExternalJavacManager = null;
if (manager != null) {
manager.stop();
}
lfs.removeWatchedRoots(myWatchRoots);
if (ApplicationManager.getApplication().isUnitTestMode()) { // force cleanup for created compiler system directory with generated sources
FileUtil.delete(CompilerPaths.getCompilerSystemDirectory(project));
}
});
}
@@ -123,10 +121,12 @@ public class CompilerManagerImpl extends CompilerManager {
return myCompilationSemaphore;
}
@Override
public boolean isCompilationActive() {
return myCompilationSemaphore.availablePermits() == 0;
}
@Override
public final void addCompiler(@NotNull Compiler compiler) {
myCompilers.add(compiler);
// supporting file instrumenting compilers and validators for external build
@@ -139,27 +139,27 @@ public class CompilerManagerImpl extends CompilerManager {
}
}
@Override
@Deprecated
public void addTranslatingCompiler(@NotNull TranslatingCompiler compiler, Set<FileType> inputTypes, Set<FileType> outputTypes) {
// empty
}
@Override
public final void removeCompiler(@NotNull Compiler compiler) {
for (List<CompileTask> tasks : Arrays.asList(myBeforeTasks, myAfterTasks)) {
for (Iterator<CompileTask> iterator = tasks.iterator(); iterator.hasNext(); ) {
CompileTask task = iterator.next();
if (task instanceof FileProcessingCompilerAdapterTask && ((FileProcessingCompilerAdapterTask)task).getCompiler() == compiler) {
iterator.remove();
}
}
tasks.removeIf(
task -> task instanceof FileProcessingCompilerAdapterTask && ((FileProcessingCompilerAdapterTask)task).getCompiler() == compiler);
}
}
@Override
@NotNull
public <T extends Compiler> T[] getCompilers(@NotNull Class<T> compilerClass) {
return getCompilers(compilerClass, CompilerFilter.ALL);
}
@Override
@NotNull
public <T extends Compiler> T[] getCompilers(@NotNull Class<T> compilerClass, CompilerFilter filter) {
final List<T> compilers = new ArrayList<>(myCompilers.size());
@@ -172,26 +172,32 @@ public class CompilerManagerImpl extends CompilerManager {
return compilers.toArray(array);
}
@Override
public void addCompilableFileType(@NotNull FileType type) {
myCompilableTypes.add(type);
}
@Override
public void removeCompilableFileType(@NotNull FileType type) {
myCompilableTypes.remove(type);
}
@Override
public boolean isCompilableFileType(@NotNull FileType type) {
return myCompilableTypes.contains(type);
}
@Override
public final void addBeforeTask(@NotNull CompileTask task) {
myBeforeTasks.add(task);
}
@Override
public final void addAfterTask(@NotNull CompileTask task) {
myAfterTasks.add(task);
}
@Override
@NotNull
public CompileTask[] getBeforeTasks() {
return getCompileTasks(myBeforeTasks, CompileTaskBean.CompileTaskExecutionPhase.BEFORE);
@@ -207,53 +213,65 @@ public class CompilerManagerImpl extends CompilerManager {
return beforeTasks.toArray(new CompileTask[beforeTasks.size()]);
}
@Override
@NotNull
public CompileTask[] getAfterTasks() {
return getCompileTasks(myAfterTasks, CompileTaskBean.CompileTaskExecutionPhase.AFTER);
}
@Override
public void compile(@NotNull VirtualFile[] files, CompileStatusNotification callback) {
compile(createFilesCompileScope(files), callback);
}
@Override
public void compile(@NotNull Module module, CompileStatusNotification callback) {
new CompileDriver(myProject).compile(createModuleCompileScope(module, false), new ListenerNotificator(callback));
}
@Override
public void compile(@NotNull CompileScope scope, CompileStatusNotification callback) {
new CompileDriver(myProject).compile(scope, new ListenerNotificator(callback));
}
@Override
public void make(CompileStatusNotification callback) {
new CompileDriver(myProject).make(createProjectCompileScope(myProject), new ListenerNotificator(callback));
}
@Override
public void make(@NotNull Module module, CompileStatusNotification callback) {
new CompileDriver(myProject).make(createModuleCompileScope(module, true), new ListenerNotificator(callback));
}
@Override
public void make(@NotNull Project project, @NotNull Module[] modules, CompileStatusNotification callback) {
new CompileDriver(myProject).make(createModuleGroupCompileScope(project, modules, true), new ListenerNotificator(callback));
}
@Override
public void make(@NotNull CompileScope scope, CompileStatusNotification callback) {
new CompileDriver(myProject).make(scope, new ListenerNotificator(callback));
}
@Override
public void make(@NotNull CompileScope scope, CompilerFilter filter, @Nullable CompileStatusNotification callback) {
final CompileDriver compileDriver = new CompileDriver(myProject);
compileDriver.setCompilerFilter(filter);
compileDriver.make(scope, new ListenerNotificator(callback));
}
@Override
public boolean isUpToDate(@NotNull final CompileScope scope) {
return new CompileDriver(myProject).isUpToDate(scope);
}
@Override
public void rebuild(CompileStatusNotification callback) {
new CompileDriver(myProject).rebuild(new ListenerNotificator(callback));
}
@Override
public void executeTask(@NotNull CompileTask task, @NotNull CompileScope scope, String contentName, Runnable onTaskFinished) {
final CompileDriver compileDriver = new CompileDriver(myProject);
compileDriver.executeCompileTask(task, scope, contentName, onTaskFinished);
@@ -261,6 +279,7 @@ public class CompilerManagerImpl extends CompilerManager {
private final Map<CompilationStatusListener, MessageBusConnection> myListenerAdapters = new HashMap<>();
@Override
public void addCompilationStatusListener(@NotNull final CompilationStatusListener listener) {
final MessageBusConnection connection = myProject.getMessageBus().connect();
myListenerAdapters.put(listener, connection);
@@ -273,6 +292,7 @@ public class CompilerManagerImpl extends CompilerManager {
connection.subscribe(CompilerTopics.COMPILATION_STATUS, listener);
}
@Override
public void removeCompilationStatusListener(@NotNull final CompilationStatusListener listener) {
final MessageBusConnection connection = myListenerAdapters.remove(listener);
if (connection != null) {
@@ -280,10 +300,12 @@ public class CompilerManagerImpl extends CompilerManager {
}
}
@Override
public boolean isExcludedFromCompilation(@NotNull VirtualFile file) {
return CompilerConfiguration.getInstance(myProject).isExcludedFromCompilation(file);
}
@Override
@NotNull
public CompileScope createFilesCompileScope(@NotNull final VirtualFile[] files) {
CompileScope[] scopes = new CompileScope[files.length];
@@ -293,26 +315,31 @@ public class CompilerManagerImpl extends CompilerManager {
return new CompositeScope(scopes);
}
@Override
@NotNull
public CompileScope createModuleCompileScope(@NotNull final Module module, final boolean includeDependentModules) {
return createModulesCompileScope(new Module[] {module}, includeDependentModules);
}
@Override
@NotNull
public CompileScope createModulesCompileScope(@NotNull final Module[] modules, final boolean includeDependentModules) {
return createModulesCompileScope(modules, includeDependentModules, false);
}
@NotNull
@Override
@NotNull
public CompileScope createModulesCompileScope(@NotNull Module[] modules, boolean includeDependentModules, boolean includeRuntimeDependencies) {
return new ModuleCompileScope(myProject, modules, includeDependentModules, includeRuntimeDependencies);
}
@Override
@NotNull
public CompileScope createModuleGroupCompileScope(@NotNull final Project project, @NotNull final Module[] modules, final boolean includeDependentModules) {
return new ModuleCompileScope(project, modules, includeDependentModules);
}
@Override
@NotNull
public CompileScope createProjectCompileScope(@NotNull final Project project) {
return new ProjectCompileScope(project);
@@ -371,9 +398,7 @@ public class CompilerManagerImpl extends CompilerManager {
final Set<File> sourceRoots = new THashSet<>(FileUtil.FILE_HASHING_STRATEGY);
if (!sourcePath.isEmpty()) {
for (File file : sourcePath) {
sourceRoots.add(file);
}
sourceRoots.addAll(sourcePath);
}
else {
for (File file : files) {
@@ -464,7 +489,7 @@ public class CompilerManagerImpl extends CompilerManager {
private final String myClassName;
private final byte[] myBytes;
public CompiledClass(String path, String className, byte[] bytes) {
CompiledClass(String path, String className, byte[] bytes) {
myPath = path;
myClassName = className;
myBytes = bytes;
@@ -493,12 +518,13 @@ public class CompilerManagerImpl extends CompilerManager {
}
private class ListenerNotificator implements CompileStatusNotification {
private final @Nullable CompileStatusNotification myDelegate;
@Nullable private final CompileStatusNotification myDelegate;
private ListenerNotificator(@Nullable CompileStatusNotification delegate) {
myDelegate = delegate;
}
@Override
public void finished(boolean aborted, int errors, int warnings, final CompileContext compileContext) {
if (!myProject.isDisposed()) {
myEventPublisher.compilationFinished(aborted, errors, warnings, compileContext);
@@ -511,6 +537,7 @@ public class CompilerManagerImpl extends CompilerManager {
private static class DiagnosticCollector implements DiagnosticOutputConsumer {
private final List<Diagnostic<? extends JavaFileObject>> myDiagnostics = new ArrayList<>();
@Override
public void outputLineAvailable(String line) {
// for debugging purposes uncomment this line
//System.out.println(line);
@@ -519,17 +546,21 @@ public class CompilerManagerImpl extends CompilerManager {
}
}
@Override
public void registerImports(String className, Collection<String> imports, Collection<String> staticImports) {
// ignore
}
@Override
public void javaFileLoaded(File file) {
// ignore
}
@Override
public void customOutputData(String pluginId, String dataName, byte[] data) {
}
@Override
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
myDiagnostics.add(diagnostic);
}
@@ -541,13 +572,14 @@ public class CompilerManagerImpl extends CompilerManager {
private static class OutputCollector implements OutputFileConsumer {
private List<OutputFileObject> myClasses = new ArrayList<>();
private final List<OutputFileObject> myClasses = new ArrayList<>();
@Override
public void save(@NotNull OutputFileObject fileObject) {
myClasses.add(fileObject);
}
public List<OutputFileObject> getCompiledClasses() {
List<OutputFileObject> getCompiledClasses() {
return myClasses;
}
}
@@ -78,6 +78,7 @@ import com.intellij.util.*;
import com.intellij.util.concurrency.SequentialTaskExecutor;
import com.intellij.util.containers.IntArrayList;
import com.intellij.util.io.BaseOutputReader;
import com.intellij.util.io.NettyKt;
import com.intellij.util.io.storage.HeavyProcessLatch;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.net.NetUtils;
@@ -121,7 +122,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.intellij.util.io.NettyKt.serverBootstrap;
import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
/**
@@ -160,7 +160,7 @@ public class BuildManager implements Disposable {
private final BuildProcessClasspathManager myClasspathManager = new BuildProcessClasspathManager();
private final ExecutorService myRequestsProcessor = SequentialTaskExecutor.createSequentialApplicationPoolExecutor("BuildManager requestProcessor pool");
private final Map<String, ProjectData> myProjectDataMap = Collections.synchronizedMap(new HashMap<String, ProjectData>());
private volatile int myFileChangeCounter = 0;
private volatile int myFileChangeCounter;
private final BuildManagerPeriodicTask myAutoMakeTask = new BuildManagerPeriodicTask() {
@Override
@@ -509,7 +509,7 @@ public class BuildManager implements Disposable {
final StackTraceElement[] trace = thread.getStackTrace();
for (int i = 0; i < depth && i < trace.length; i++) {
final StackTraceElement element = trace[i];
buf.append("\tat ").append(element.toString()).append("\n");
buf.append("\tat ").append(element).append("\n");
}
return buf.toString();
}
@@ -556,10 +556,7 @@ public class BuildManager implements Disposable {
if (!config.MAKE_PROJECT_ON_SAVE) {
return false;
}
if (!config.allowAutoMakeWhileRunningApplication() && hasRunningProcess(project)) {
return false;
}
return true;
return config.allowAutoMakeWhileRunningApplication() || !hasRunningProcess(project);
}
@Nullable
@@ -725,7 +722,7 @@ public class BuildManager implements Disposable {
if (!usingPreloadedProcess && (future.isCancelled() || project.isDisposed())) {
// in case of preloaded process the process was already running, so the handler will be notified upon process termination
handler.sessionTerminated(sessionId);
((BasicFuture)future).setDone();
future.setDone();
}
else {
final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals =
@@ -915,12 +912,8 @@ public class BuildManager implements Disposable {
@NotNull
private ProjectData getProjectData(String projectPath) {
synchronized (myProjectDataMap) {
ProjectData data = myProjectDataMap.get(projectPath);
if (data == null) {
data = new ProjectData(SequentialTaskExecutor.createSequentialApplicationPoolExecutor("BuildManager pool"));
myProjectDataMap.put(projectPath, data);
}
return data;
return myProjectDataMap.computeIfAbsent(projectPath, k -> new ProjectData(
SequentialTaskExecutor.createSequentialApplicationPoolExecutor("BuildManager pool")));
}
}
@@ -991,7 +984,7 @@ public class BuildManager implements Disposable {
}
}
if (projectJdk == null || sdkVersion == null || !sdkVersion.isAtLeast(oldestPossibleVersion)) {
if (projectJdk == null || !sdkVersion.isAtLeast(oldestPossibleVersion)) {
final Sdk internalJdk = JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();
projectJdk = internalJdk;
sdkVersion = javaSdkType.getVersion(internalJdk);
@@ -1286,11 +1279,11 @@ public class BuildManager implements Disposable {
if (!StringUtil.isEmptyOrSpaces(text)) {
if (ProcessOutputTypes.SYSTEM.equals(outputType)) {
if (LOG.isDebugEnabled()) {
LOG.debug("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim());
LOG.debug("BUILDER_PROCESS [" + outputType + "]: " + text.trim());
}
}
else {
LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim());
LOG.info("BUILDER_PROCESS [" + outputType + "]: " + text.trim());
}
}
}
@@ -1302,7 +1295,7 @@ public class BuildManager implements Disposable {
return processHandler;
}
private boolean shouldIncludeEclipseCompiler(CompilerConfiguration config) {
private static boolean shouldIncludeEclipseCompiler(CompilerConfiguration config) {
if (config instanceof CompilerConfigurationImpl) {
final BackendCompiler javaCompiler = ((CompilerConfigurationImpl)config).getDefaultCompiler();
final String compilerId = javaCompiler != null? javaCompiler.getId() : null;
@@ -1399,16 +1392,12 @@ public class BuildManager implements Disposable {
}
private int startListening() throws Exception {
EventLoopGroup group;
BuiltInServer mainServer = StartupUtil.getServer();
boolean isOwnEventLoopGroup = !Registry.is("compiler.shared.event.group", true) || mainServer == null || mainServer.getEventLoopGroup() instanceof OioEventLoopGroup;
if (isOwnEventLoopGroup) {
group = new NioEventLoopGroup(1, ConcurrencyUtil.newNamedThreadFactory("External compiler"));
}
else {
group = mainServer.getEventLoopGroup();
}
final ServerBootstrap bootstrap = serverBootstrap(group);
EventLoopGroup group = isOwnEventLoopGroup
? new NioEventLoopGroup(1, ConcurrencyUtil.newNamedThreadFactory("External compiler"))
: mainServer.getEventLoopGroup();
final ServerBootstrap bootstrap = NettyKt.serverBootstrap(group);
bootstrap.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(@NotNull Channel channel) throws Exception {
@@ -1459,17 +1448,17 @@ public class BuildManager implements Disposable {
}
};
protected BuildManagerPeriodicTask() {
BuildManagerPeriodicTask() {
myAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, BuildManager.this);
}
public final void schedule() {
final void schedule() {
cancelPendingExecution();
final int delay = Math.max(100, getDelay());
myAlarm.addRequest(this, delay);
}
public void cancelPendingExecution() {
void cancelPendingExecution() {
myAlarm.cancelAllRequests();
}
@@ -1503,7 +1492,7 @@ public class BuildManager implements Disposable {
private final BuilderMessageHandler myDelegateHandler;
private final boolean myIsAutomake;
public NotifyingMessageHandler(@NotNull Project project, @NotNull BuilderMessageHandler delegateHandler, final boolean isAutomake) {
NotifyingMessageHandler(@NotNull Project project, @NotNull BuilderMessageHandler delegateHandler, final boolean isAutomake) {
myProject = project;
myDelegateHandler = delegateHandler;
myIsAutomake = isAutomake;
@@ -1667,12 +1656,10 @@ public class BuildManager implements Disposable {
if (project.isDisposed()) {
return Collections.emptySet();
}
else {
return candidates.stream()
.map(lfs::findFileByPath)
.filter(root -> root != null && fileIndex.isInSourceContent(root))
.collect(Collectors.toSet());
}
return candidates.stream()
.map(lfs::findFileByPath)
.filter(root -> root != null && fileIndex.isInSourceContent(root))
.collect(Collectors.toSet());
});
if (!toRefresh.isEmpty()) {
@@ -1690,12 +1677,9 @@ public class BuildManager implements Disposable {
}
});
final String projectPath = getProjectPath(project);
Disposer.register(project, new Disposable() {
@Override
public void dispose() {
cancelPreloadedBuilds(projectPath);
myProjectDataMap.remove(projectPath);
}
Disposer.register(project, () -> {
cancelPreloadedBuilds(projectPath);
myProjectDataMap.remove(projectPath);
});
StartupManager.getInstance(project).registerPostStartupActivity(() -> {
runCommand(() -> {
@@ -1744,7 +1728,7 @@ public class BuildManager implements Disposable {
this.taskQueue = taskQueue;
}
public void addChanged(Collection<String> paths) {
void addChanged(Collection<String> paths) {
if (!myNeedRescan) {
for (String path : paths) {
final InternedPath _path = InternedPath.create(path);
@@ -1754,7 +1738,7 @@ public class BuildManager implements Disposable {
}
}
public void addDeleted(Collection<String> paths) {
void addDeleted(Collection<String> paths) {
if (!myNeedRescan) {
for (String path : paths) {
final InternedPath _path = InternedPath.create(path);
@@ -1764,7 +1748,7 @@ public class BuildManager implements Disposable {
}
}
public CmdlineRemoteProto.Message.ControllerMessage.FSEvent createNextEvent() {
CmdlineRemoteProto.Message.ControllerMessage.FSEvent createNextEvent() {
final CmdlineRemoteProto.Message.ControllerMessage.FSEvent.Builder builder =
CmdlineRemoteProto.Message.ControllerMessage.FSEvent.newBuilder();
builder.setOrdinal(++myNextEventOrdinal);
@@ -1782,13 +1766,13 @@ public class BuildManager implements Disposable {
return builder.build();
}
public boolean getAndResetRescanFlag() {
boolean getAndResetRescanFlag() {
final boolean rescan = myNeedRescan;
myNeedRescan = false;
return rescan;
}
public void dropChanges() {
void dropChanges() {
myNeedRescan = true;
myNextEventOrdinal = 0L;
myChanged.clear();
@@ -1802,7 +1786,7 @@ public class BuildManager implements Disposable {
/**
* @param path assuming system-independent path with forward slashes
*/
protected InternedPath(String path) {
InternedPath(String path) {
final IntArrayList list = new IntArrayList();
final StringTokenizer tokenizer = new StringTokenizer(path, "/", false);
while(tokenizer.hasMoreTokens()) {
@@ -1821,9 +1805,7 @@ public class BuildManager implements Disposable {
InternedPath path = (InternedPath)o;
if (!Arrays.equals(myPath, path.myPath)) return false;
return true;
return Arrays.equals(myPath, path.myPath);
}
@Override
@@ -618,11 +618,11 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
StartMarker parent,
int start,
int end) {
this.myParentNode = parent;
this.myBuilder = builder;
this.myTokenType = type;
this.myTokenStart = start;
this.myTokenEnd = end;
myParentNode = parent;
myBuilder = builder;
myTokenType = type;
myTokenStart = start;
myTokenEnd = end;
}
}
@@ -681,11 +681,11 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
private StartMarker myStart;
private boolean myCollapse;
public DoneMarker() {
DoneMarker() {
myEdgeTokenBinder = WhitespacesBinders.DEFAULT_RIGHT_BINDER;
}
public DoneMarker(final StartMarker marker, final int currentLexeme) {
DoneMarker(final StartMarker marker, final int currentLexeme) {
this();
myLexemeIndex = currentLexeme;
myStart = marker;
@@ -739,7 +739,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
private final PsiBuilderImpl myBuilder;
private String myMessage;
public ErrorItem(final PsiBuilderImpl builder, final String message, final int idx) {
ErrorItem(final PsiBuilderImpl builder, final String message, final int idx) {
myBuilder = builder;
myMessage = message;
myLexemeIndex = idx;
@@ -1921,7 +1921,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
final int[] myLexStarts;
final IElementType[] myLexTypes;
public LazyParseableTokensCache(int[] lexStarts, IElementType[] lexTypes) {
LazyParseableTokensCache(int[] lexStarts, IElementType[] lexTypes) {
myLexStarts = lexStarts;
myLexTypes = lexTypes;
}
@@ -42,12 +42,7 @@ public class UnknownSdkType extends SdkType{
@NotNull
public static UnknownSdkType getInstance(@NotNull String typeName) {
UnknownSdkType instance = ourTypeNameToInstanceMap.get(typeName);
if (instance == null) {
instance = new UnknownSdkType(typeName);
ourTypeNameToInstanceMap.put(typeName, instance);
}
return instance;
return ourTypeNameToInstanceMap.computeIfAbsent(typeName, UnknownSdkType::new);
}
@Override
@@ -29,7 +29,9 @@ import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.VolatileNotNullLazyValue;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.IconDeferrer;
@@ -48,12 +50,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
public abstract class ChooseFileEncodingAction extends ComboBoxAction {
private final VirtualFile myVirtualFile;
public ChooseFileEncodingAction(@Nullable VirtualFile virtualFile) {
protected ChooseFileEncodingAction(@Nullable VirtualFile virtualFile) {
myVirtualFile = virtualFile;
}
@@ -75,33 +76,35 @@ public abstract class ChooseFileEncodingAction extends ComboBoxAction {
public void update(AnActionEvent e) {
super.update(e);
String description = charsetFilter.fun(charset);
AtomicReference<CharSequence> myText = new AtomicReference<>();
AtomicReference<byte[]> myBytes = new AtomicReference<>();
Icon defer = virtualFile == null || virtualFile.isDirectory() ? null : IconDeferrer.getInstance().defer(null, Pair.create(virtualFile, charset), pair -> {
VirtualFile myFile = pair.getFirst();
Charset charset = pair.getSecond();
CharSequence text = myText.get();
if (text == null) {
myText.set(text = LoadTextUtil.loadText(myFile));
}
byte[] bytes = myBytes.get();
if (bytes == null) {
Icon defer;
if (virtualFile == null || virtualFile.isDirectory()) {
defer = null;
}
else {
NotNullLazyValue<CharSequence> myText = VolatileNotNullLazyValue.createValue(()->LoadTextUtil.loadText(virtualFile));
NotNullLazyValue<byte[]> myBytes = VolatileNotNullLazyValue.createValue(() -> {
try {
myBytes.set(bytes = myFile.contentsToByteArray());
return virtualFile.contentsToByteArray();
}
catch (IOException io) {
bytes = ArrayUtil.EMPTY_BYTE_ARRAY;
catch (IOException e1) {
return ArrayUtil.EMPTY_BYTE_ARRAY;
}
}
EncodingUtil.Magic8 safeToReload = EncodingUtil.isSafeToReloadIn(myFile, text, bytes, charset);
EncodingUtil.Magic8 safeToConvert = EncodingUtil.Magic8.ABSOLUTELY;
if (safeToReload != EncodingUtil.Magic8.ABSOLUTELY) {
safeToConvert = EncodingUtil.isSafeToConvertTo(myFile, text, bytes, charset);
}
return safeToReload == EncodingUtil.Magic8.ABSOLUTELY || safeToConvert == EncodingUtil.Magic8.ABSOLUTELY ? null :
safeToReload == EncodingUtil.Magic8.WELL_IF_YOU_INSIST || safeToConvert == EncodingUtil.Magic8.WELL_IF_YOU_INSIST ?
AllIcons.General.Warning : AllIcons.General.Error;
});
});
defer = IconDeferrer.getInstance().defer(null, Pair.create(virtualFile, charset), pair -> {
VirtualFile myFile = pair.getFirst();
Charset charset = pair.getSecond();
CharSequence text = myText.getValue();
byte[] bytes = myBytes.getValue();
EncodingUtil.Magic8 safeToReload = EncodingUtil.isSafeToReloadIn(myFile, text, bytes, charset);
EncodingUtil.Magic8 safeToConvert = EncodingUtil.Magic8.ABSOLUTELY;
if (safeToReload != EncodingUtil.Magic8.ABSOLUTELY) {
safeToConvert = EncodingUtil.isSafeToConvertTo(myFile, text, bytes, charset);
}
return safeToReload == EncodingUtil.Magic8.ABSOLUTELY || safeToConvert == EncodingUtil.Magic8.ABSOLUTELY ? null :
safeToReload == EncodingUtil.Magic8.WELL_IF_YOU_INSIST || safeToConvert == EncodingUtil.Magic8.WELL_IF_YOU_INSIST ?
AllIcons.General.Warning : AllIcons.General.Error;
});
}
e.getPresentation().setIcon(defer);
e.getPresentation().setDescription(description);
}
@@ -110,7 +113,7 @@ public abstract class ChooseFileEncodingAction extends ComboBoxAction {
}
}
public static final Charset NO_ENCODING = new Charset("NO_ENCODING", null) {
protected static final Charset NO_ENCODING = new Charset("NO_ENCODING", null) {
@Override
public boolean contains(final Charset cs) {
return false;
@@ -50,7 +50,6 @@ class FilePointerPartNode {
int pointersUnder; // number of alive pointers in this node plus all nodes beneath
private static final VirtualFileManager ourFileManager = VirtualFileManager.getInstance();
private static final ManagingFS ourManagingFS = ManagingFS.getInstance();
FilePointerPartNode(@NotNull String part, FilePointerPartNode parent, Pair<VirtualFile,String> fileAndUrl) {
this.part = part;
@@ -254,7 +253,7 @@ class FilePointerPartNode {
final long lastUpdated = myLastUpdated;
final Pair<VirtualFile, String> fileAndUrl = myFileAndUrl;
if (fileAndUrl == null) return null;
final long fsModCount = ourManagingFS.getStructureModificationCount();
final long fsModCount = ManagingFS.getInstance().getStructureModificationCount();
if (lastUpdated == fsModCount) return fileAndUrl;
VirtualFile file = fileAndUrl.first;
String url = fileAndUrl.second;
@@ -30,7 +30,8 @@ public abstract class CompilerModuleExtension extends ModuleExtension {
@NonNls public static final String PRODUCTION = "production";
@NonNls public static final String TEST = "test";
public static @Nullable CompilerModuleExtension getInstance(final Module module) {
@Nullable
public static CompilerModuleExtension getInstance(final Module module) {
return ModuleRootManager.getInstance(module).getModuleExtension(CompilerModuleExtension.class);
}
@@ -85,7 +86,7 @@ public abstract class CompilerModuleExtension extends ModuleExtension {
public abstract void inheritCompilerOutputPath(boolean inherit);
/**
* Returns <code>true</code> if compiler output for this module is inherited from a project
* Returns {@code true} if compiler output for this module is inherited from a project
* @return true if compiler output path is inherited, false otherwise
*/
public abstract boolean isCompilerOutputPathInherited();