Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Alexey Pegov
2010-08-09 20:17:59 +04:00
79 changed files with 1329 additions and 431 deletions
+1
View File
@@ -31,6 +31,7 @@
<orderEntry type="module" module-name="jsp-openapi" />
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="idea-ui" />
<orderEntry type="library" name="Guava" level="project" />
</component>
<component name="copyright">
<Base>
@@ -44,7 +44,7 @@ import java.util.Map;
public class CompilerCacheManager implements ProjectComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.CompilerCacheManager");
private final Map<Compiler, Object> myCompilerToCacheMap = new HashMap<Compiler, Object>();
private final Map<NewCompiler<?,?>, NewCompilerCache<?,?>> myNewCachesMap = new HashMap<NewCompiler<?,?>, NewCompilerCache<?,?>>();
private final Map<NewCompiler<?,?,?>, NewCompilerCache<?,?,?>> myNewCachesMap = new HashMap<NewCompiler<?,?,?>, NewCompilerCache<?,?,?>>();
private final List<Disposable> myCacheDisposables = new ArrayList<Disposable>();
private final File myCachesRoot;
private final Runnable myShutdownTask = new Runnable() {
@@ -90,10 +90,11 @@ public class CompilerCacheManager implements ProjectComponent {
return dir;
}
public synchronized <Key, State> NewCompilerCache<Key, State> getNewCompilerCache(NewCompiler<Key, State> compiler) throws IOException {
NewCompilerCache<?, ?> cache = myNewCachesMap.get(compiler);
public synchronized <Key, SourceState, OutputState> NewCompilerCache<Key, SourceState, OutputState>
getNewCompilerCache(NewCompiler<Key, SourceState, OutputState> compiler) throws IOException {
NewCompilerCache<?,?,?> cache = myNewCachesMap.get(compiler);
if (cache == null) {
final NewCompilerCache<?, ?> newCache = new NewCompilerCache<Key, State>(compiler, NewCompilerRunner.getNewCompilerCacheDir(myProject, compiler));
final NewCompilerCache<?,?,?> newCache = new NewCompilerCache<Key, SourceState, OutputState>(compiler, NewCompilerRunner.getNewCompilerCacheDir(myProject, compiler));
myNewCachesMap.put(compiler, newCache);
myCacheDisposables.add(new Disposable() {
@Override
@@ -104,7 +105,7 @@ public class CompilerCacheManager implements ProjectComponent {
cache = newCache;
}
//noinspection unchecked
return (NewCompilerCache<Key, State>)cache;
return (NewCompilerCache<Key, SourceState, OutputState>)cache;
}
public synchronized FileProcessingCompilerStateCache getFileProcessingCompilerCache(FileProcessingCompiler compiler) throws IOException {
@@ -15,14 +15,17 @@
*/
package com.intellij.compiler.impl;
import com.google.common.base.Throwables;
import com.intellij.compiler.impl.newApi.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.RunResult;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
@@ -43,7 +46,7 @@ public class NewCompilerRunner {
private CompileContext myContext;
private final boolean myForceCompile;
private final boolean myOnlyCheckStatus;
private final NewCompiler<?,?>[] myCompilers;
private final NewCompiler<?,?,?>[] myCompilers;
private final Project myProject;
public NewCompilerRunner(CompileContext context, CompilerManager compilerManager, boolean forceCompile, boolean onlyCheckStatus) {
@@ -57,7 +60,7 @@ public class NewCompilerRunner {
public boolean invokeCompilers(NewCompiler.CompileOrderPlace place) throws CompileDriver.ExitException {
boolean didSomething = false;
try {
for (NewCompiler<?, ?> compiler : myCompilers) {
for (NewCompiler<?,?,?> compiler : myCompilers) {
if (compiler.getOrderPlace().equals(place)) {
didSomething = invokeCompiler(compiler);
}
@@ -81,13 +84,13 @@ public class NewCompilerRunner {
return didSomething;
}
private <T extends BuildTarget, Key, State> boolean invokeCompiler(NewCompiler<Key, State> compiler) throws IOException, CompileDriver.ExitException {
private <Key, SourceState, OutputState> boolean invokeCompiler(NewCompiler<Key, SourceState, OutputState> compiler) throws IOException, CompileDriver.ExitException {
return invokeCompiler(compiler, compiler.createInstance(myContext));
}
private <T extends BuildTarget, Item extends CompileItem<Key, State>, Key, State>
boolean invokeCompiler(NewCompiler<Key, State> compiler, CompilerInstance<T, Item, Key, State> instance) throws IOException, CompileDriver.ExitException {
NewCompilerCache<Key, State> cache = CompilerCacheManager.getInstance(myProject).getNewCompilerCache(compiler);
private <T extends BuildTarget, Item extends CompileItem<Key, SourceState, OutputState>, Key, SourceState, OutputState>
boolean invokeCompiler(NewCompiler<Key, SourceState, OutputState> compiler, CompilerInstance<T, Item, Key, SourceState, OutputState> instance) throws IOException, CompileDriver.ExitException {
NewCompilerCache<Key, SourceState, OutputState> cache = CompilerCacheManager.getInstance(myProject).getNewCompilerCache(compiler);
NewCompilerPersistentData data = new NewCompilerPersistentData(getNewCompilerCacheDir(myProject, compiler), compiler.getVersion());
if (data.isVersionChanged()) {
LOG.info("Clearing cache for " + compiler.getDescription());
@@ -106,10 +109,10 @@ public class NewCompilerRunner {
}
List<Key> keys = new ArrayList<Key>();
cache.processSources(id, new CommonProcessors.CollectProcessor<Key>(keys));
List<Pair<Key, State>> obsoleteSources = new ArrayList<Pair<Key, State>>();
List<NewCompilerItemState<Key, SourceState, OutputState>> obsoleteSources = new ArrayList<NewCompilerItemState<Key,SourceState,OutputState>>();
for (Key key : keys) {
final State state = cache.getState(id, key);
obsoleteSources.add(Pair.create(key, state));
final NewCompilerCache.PersistentStateData<SourceState, OutputState> state = cache.getState(id, key);
obsoleteSources.add(new NewCompilerItemState<Key,SourceState,OutputState>(key, state.mySourceState, state.myOutputState));
}
instance.processObsoleteTarget(target, obsoleteSources);
if (myContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
@@ -131,23 +134,24 @@ public class NewCompilerRunner {
return didSomething;
}
public static File getNewCompilerCacheDir(Project project, NewCompiler<?, ?> compiler) {
public static File getNewCompilerCacheDir(Project project, NewCompiler<?,?,?> compiler) {
return new File(CompilerPaths.getCacheStoreDirectory(project), compiler.getId());
}
private <T extends BuildTarget, Item extends CompileItem<Key, State>, Key, State>
boolean processTarget(T target, final int targetId, final NewCompiler<Key, State> compiler, final CompilerInstance<T, Item, Key, State> instance,
final NewCompilerCache<Key, State> cache) throws IOException, CompileDriver.ExitException {
private <T extends BuildTarget, Item extends CompileItem<Key, SourceState, OutputState>, Key, SourceState, OutputState>
boolean processTarget(T target, final int targetId, final NewCompiler<Key, SourceState, OutputState> compiler, final CompilerInstance<T, Item, Key, SourceState, OutputState> instance,
final NewCompilerCache<Key, SourceState, OutputState> cache) throws IOException, CompileDriver.ExitException {
if (LOG.isDebugEnabled()) {
LOG.debug("Processing target '" + target + "' (id=" + targetId + ")");
}
final List<Item> items = instance.getItems(target);
if (myContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) return true;
final List<Pair<Item, State>> toProcess = new ArrayList<Pair<Item, State>>();
final List<NewCompilerItemState<Item, SourceState, OutputState>> toProcess = new ArrayList<NewCompilerItemState<Item,SourceState,OutputState>>();
final THashSet<Key> keySet = new THashSet<Key>(new SourceItemHashingStrategy<Key>(compiler));
final Ref<IOException> exception = Ref.create(null);
DumbService.getInstance(myProject).waitForSmartMode();
final Map<Item, SourceState> sourceStates = new HashMap<Item,SourceState>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
@@ -155,9 +159,13 @@ public class NewCompilerRunner {
for (Item item : items) {
final Key key = item.getKey();
keySet.add(key);
State output = cache.getState(targetId, key);
if (myForceCompile || output == null || !item.isUpToDate(output)) {
toProcess.add(Pair.create(item, output));
final NewCompilerCache.PersistentStateData<SourceState, OutputState> data = cache.getState(targetId, key);
SourceState sourceState = data != null ? data.mySourceState : null;
final OutputState outputState = data != null ? data.myOutputState : null;
if (myForceCompile || sourceState == null || !item.isSourceUpToDate(sourceState)
|| outputState == null || !item.isOutputUpToDate(outputState)) {
sourceStates.put(item, item.computeSourceState());
toProcess.add(new NewCompilerItemState<Item, SourceState, OutputState>(item, sourceState, outputState));
}
}
}
@@ -193,9 +201,10 @@ public class NewCompilerRunner {
throw new CompileDriver.ExitException(CompileDriver.ExitStatus.CANCELLED);
}
List<Pair<Key, State>> obsoleteItems = new ArrayList<Pair<Key, State>>();
List<NewCompilerItemState<Key, SourceState, OutputState>> obsoleteItems = new ArrayList<NewCompilerItemState<Key,SourceState,OutputState>>();
for (Key key : toRemove) {
obsoleteItems.add(Pair.create(key, cache.getState(targetId, key)));
final NewCompilerCache.PersistentStateData<SourceState, OutputState> data = cache.getState(targetId, key);
obsoleteItems.add(new NewCompilerItemState<Key,SourceState,OutputState>(key, data.mySourceState, data.myOutputState));
}
final List<Item> processedItems = new ArrayList<Item>();
@@ -218,9 +227,19 @@ public class NewCompilerRunner {
cache.remove(targetId, key);
}
CompilerUtil.refreshIOFiles(toRefresh);
for (Item item : processedItems) {
cache.putOutput(targetId, item.getKey(), item.computeState());
}
final RunResult runResult = new ReadAction() {
protected void run(final Result result) throws Throwable {
for (Item item : processedItems) {
SourceState sourceState = sourceStates.get(item);
if (sourceState == null) {
sourceState = item.computeSourceState();
}
cache.putState(targetId, item.getKey(), sourceState, item.computeOutputState());
}
}
}.executeSilently();
Throwables.propagateIfPossible(runResult.getThrowable(), IOException.class);
return true;
@@ -229,7 +248,7 @@ public class NewCompilerRunner {
private class SourceItemHashingStrategy<S> implements TObjectHashingStrategy<S> {
private KeyDescriptor<S> myKeyDescriptor;
public SourceItemHashingStrategy(NewCompiler<S, ?> compiler) {
public SourceItemHashingStrategy(NewCompiler<S, ?, ?> compiler) {
myKeyDescriptor = compiler.getItemKeyDescriptor();
}
@@ -20,12 +20,18 @@ import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class CompileItem<Key, State> {
public abstract class CompileItem<Key, SourceState, OutputState> {
@NotNull
public abstract Key getKey();
public abstract boolean isUpToDate(@NotNull State state);
public abstract boolean isSourceUpToDate(@NotNull SourceState state);
@NotNull
public abstract State computeState();
public abstract SourceState computeSourceState();
public abstract boolean isOutputUpToDate(@NotNull OutputState state);
@NotNull
public abstract OutputState computeOutputState();
}
@@ -17,7 +17,6 @@ package com.intellij.compiler.impl.newApi;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -26,7 +25,7 @@ import java.util.List;
/**
* @author nik
*/
public abstract class CompilerInstance<T extends BuildTarget, Item extends CompileItem<Key, State>, Key, State> {
public abstract class CompilerInstance<T extends BuildTarget, Item extends CompileItem<Key, SourceState, OutputState>, Key, SourceState, OutputState> {
protected final CompileContext myContext;
protected CompilerInstance(CompileContext context) {
@@ -43,16 +42,16 @@ public abstract class CompilerInstance<T extends BuildTarget, Item extends Compi
@NotNull
public abstract List<T> getSelectedTargets();
public abstract void processObsoleteTarget(@NotNull String targetId, @NotNull List<Pair<Key, State>> obsoleteItems);
public abstract void processObsoleteTarget(@NotNull String targetId, @NotNull List<NewCompilerItemState<Key, SourceState, OutputState>> obsoleteItems);
@NotNull
public abstract List<Item> getItems(@NotNull T target);
public abstract void processItems(@NotNull T target, @NotNull List<Pair<Item, State>> changedItems, @NotNull List<Pair<Key, State>> obsoleteItems,
public abstract void processItems(@NotNull T target, @NotNull List<NewCompilerItemState<Item, SourceState, OutputState>> changedItems, @NotNull List<NewCompilerItemState<Key, SourceState, OutputState>> obsoleteItems,
@NotNull OutputConsumer<Item> consumer);
public interface OutputConsumer<Item extends CompileItem<?,?>> {
public interface OutputConsumer<Item extends CompileItem<?,?,?>> {
void addFileToRefresh(@NotNull File file);
void addProcessedItem(@NotNull Item sourceItem);
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class NewCompiler<Key, State> implements Compiler {
public abstract class NewCompiler<Key, SourceState, OutputState> implements Compiler {
private final String myId;
private final int myVersion;
private final CompileOrderPlace myOrderPlace;
@@ -38,10 +38,12 @@ public abstract class NewCompiler<Key, State> implements Compiler {
@NotNull
public abstract KeyDescriptor<Key> getItemKeyDescriptor();
@NotNull
public abstract DataExternalizer<State> getItemStateExternalizer();
public abstract DataExternalizer<SourceState> getSourceStateExternalizer();
@NotNull
public abstract DataExternalizer<OutputState> getOutputStateExternalizer();
@NotNull
public abstract CompilerInstance<?, ? extends CompileItem<Key, State>, Key, State> createInstance(@NotNull CompileContext context);
public abstract CompilerInstance<?, ? extends CompileItem<Key, SourceState, OutputState>, Key, SourceState, OutputState> createInstance(@NotNull CompileContext context);
public final String getId() {
return myId;
@@ -17,6 +17,7 @@ package com.intellij.compiler.impl.newApi;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Processor;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.io.PersistentHashMap;
@@ -28,28 +29,25 @@ import java.io.IOException;
/**
* @author nik
*/
public class NewCompilerCache<Key, State> {
public class NewCompilerCache<Key, SourceState, OutputState> {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.newApi.NewCompilerCache");
private PersistentHashMap<KeyAndTargetData<Key>, State> myPersistentMap;
private PersistentHashMap<KeyAndTargetData<Key>, PersistentStateData<SourceState, OutputState>> myPersistentMap;
private File myCacheFile;
private final NewCompiler<Key, State> myCompiler;
private final NewCompiler<Key, SourceState, OutputState> myCompiler;
public NewCompilerCache(NewCompiler<Key, State> compiler, final File compilerCacheDir) throws IOException {
public NewCompilerCache(NewCompiler<Key, SourceState, OutputState> compiler, final File compilerCacheDir) throws IOException {
myCompiler = compiler;
myCacheFile = new File(compilerCacheDir, "timestamps");
createMap();
}
private void createMap() throws IOException {
myPersistentMap = new PersistentHashMap<KeyAndTargetData<Key>, State>(myCacheFile, new SourceItemDataDescriptor(myCompiler.getItemKeyDescriptor()),
myCompiler.getItemStateExternalizer());
myPersistentMap = new PersistentHashMap<KeyAndTargetData<Key>, PersistentStateData<SourceState,OutputState>>(myCacheFile, new SourceItemDataDescriptor(myCompiler.getItemKeyDescriptor()),
new PersistentStateDataExternalizer(myCompiler));
}
private KeyAndTargetData<Key> getKeyAndTargetData(Key key, int target) {
KeyAndTargetData<Key> data = new KeyAndTargetData<Key>();
data.myTarget = target;
data.myKey = key;
return data;
return new KeyAndTargetData<Key>(target, key);
}
public void wipe() throws IOException {
@@ -75,7 +73,7 @@ public class NewCompilerCache<Key, State> {
myPersistentMap.remove(getKeyAndTargetData(key, targetId));
}
public State getState(int targetId, Key key) throws IOException {
public PersistentStateData<SourceState, OutputState> getState(int targetId, Key key) throws IOException {
return myPersistentMap.get(getKeyAndTargetData(key, targetId));
}
@@ -88,16 +86,31 @@ public class NewCompilerCache<Key, State> {
});
}
public void putOutput(int targetId, Key key, State outputItem) throws IOException {
myPersistentMap.put(getKeyAndTargetData(key, targetId), outputItem);
public void putState(int targetId, Key key, SourceState sourceState, OutputState outputState) throws IOException {
myPersistentMap.put(getKeyAndTargetData(key, targetId), new PersistentStateData<SourceState,OutputState>(sourceState, outputState));
}
private static class KeyAndTargetData<Key> {
public int myTarget;
public Key myKey;
public final int myTarget;
public final Key myKey;
private KeyAndTargetData(int target, Key key) {
myTarget = target;
myKey = key;
}
}
public static class PersistentStateData<SourceState, OutputState> {
public final SourceState mySourceState;
public final OutputState myOutputState;
private PersistentStateData(SourceState sourceState, OutputState outputState) {
mySourceState = sourceState;
myOutputState = outputState;
}
}
private class SourceItemDataDescriptor implements KeyDescriptor<KeyAndTargetData<Key>> {
private final KeyDescriptor<Key> myKeyDescriptor;
@@ -129,4 +142,27 @@ public class NewCompilerCache<Key, State> {
return getKeyAndTargetData(item, target);
}
}
private class PersistentStateDataExternalizer implements DataExternalizer<PersistentStateData<SourceState, OutputState>> {
private DataExternalizer<SourceState> mySourceStateExternalizer;
private DataExternalizer<OutputState> myOutputStateExternalizer;
public PersistentStateDataExternalizer(NewCompiler<Key,SourceState,OutputState> compiler) {
mySourceStateExternalizer = compiler.getSourceStateExternalizer();
myOutputStateExternalizer = compiler.getOutputStateExternalizer();
}
@Override
public void save(DataOutput out, PersistentStateData<SourceState, OutputState> value) throws IOException {
mySourceStateExternalizer.save(out, value.mySourceState);
myOutputStateExternalizer.save(out, value.myOutputState);
}
@Override
public PersistentStateData<SourceState, OutputState> read(DataInput in) throws IOException {
SourceState sourceState = mySourceStateExternalizer.read(in);
OutputState outputState = myOutputStateExternalizer.read(in);
return new PersistentStateData<SourceState,OutputState>(sourceState, outputState);
}
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
/**
* @author nik
*/
public class NewCompilerItemState<Item, SourceState, OutputState> {
private final Item myItem;
private final SourceState mySourceState;
private final OutputState myOutputState;
public NewCompilerItemState(Item item, SourceState sourceState, OutputState outputState) {
myItem = item;
mySourceState = sourceState;
myOutputState = outputState;
}
public Item getItem() {
return myItem;
}
public SourceState getSourceState() {
return mySourceState;
}
public OutputState getOutputState() {
return myOutputState;
}
}
@@ -30,7 +30,7 @@ import java.util.Set;
*/
public class NewCompilerPersistentData {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.newApi.NewCompilerPersistentData");
private static final int VERSION = 0;
private static final int VERSION = 1;
private File myFile;
private Map<String, Integer> myTarget2Id = new HashMap<String, Integer>();
private TIntHashSet myUsedIds = new TIntHashSet();
@@ -16,7 +16,6 @@
package com.intellij.compiler.impl.newApi;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
@@ -25,7 +24,7 @@ import java.util.List;
/**
* @author nik
*/
public abstract class SingleTargetCompilerInstance<Item extends CompileItem<S,O>, S, O> extends CompilerInstance<BuildTarget, Item, S, O> {
public abstract class SingleTargetCompilerInstance<Item extends CompileItem<K,S,O>, K,S, O> extends CompilerInstance<BuildTarget, Item, K, S, O> {
protected SingleTargetCompilerInstance(CompileContext context) {
super(context);
}
@@ -43,6 +42,6 @@ public abstract class SingleTargetCompilerInstance<Item extends CompileItem<S,O>
}
@Override
public void processObsoleteTarget(@NotNull String targetId, @NotNull List<Pair<S, O>> obsoleteItems) {
public void processObsoleteTarget(@NotNull String targetId, @NotNull List<NewCompilerItemState<K, S, O>> obsoleteItems) {
}
}
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class VirtualFileCompileItem<State extends VirtualFilePersistentState> extends CompileItem<String, State> {
public abstract class VirtualFileCompileItem<OutputState> extends CompileItem<String, VirtualFilePersistentState, OutputState> {
public static final KeyDescriptor<String> KEY_DESCRIPTOR = new EnumeratorStringDescriptor();
protected final VirtualFile myFile;
@@ -36,15 +36,16 @@ public abstract class VirtualFileCompileItem<State extends VirtualFilePersistent
return myFile;
}
@NotNull
@Override
public final boolean isUpToDate(@NotNull State state) {
if (myFile.getTimeStamp() != state.getSourceTimestamp()) {
return false;
}
return isStateUpToDate(state);
public VirtualFilePersistentState computeSourceState() {
return new VirtualFilePersistentState(myFile.getTimeStamp());
}
protected abstract boolean isStateUpToDate(State state);
@Override
public boolean isSourceUpToDate(@NotNull VirtualFilePersistentState state) {
return myFile.getTimeStamp() == state.getSourceTimestamp();
}
@NotNull
@Override
@@ -24,21 +24,17 @@ import java.io.IOException;
/**
* @author nik
*/
public abstract class VirtualFileStateExternalizer<State extends VirtualFilePersistentState> implements DataExternalizer<State> {
protected abstract void doSave(DataOutput out, State value) throws IOException;
protected abstract State doRead(DataInput in, long sourceTimestamp) throws IOException;
public class VirtualFileStateExternalizer implements DataExternalizer<VirtualFilePersistentState> {
public static VirtualFileStateExternalizer INSTANCE = new VirtualFileStateExternalizer();
@Override
public final void save(DataOutput out, State value) throws IOException {
public void save(DataOutput out, VirtualFilePersistentState value) throws IOException {
out.writeLong(value.getSourceTimestamp());
doSave(out, value);
}
@Override
public final State read(DataInput in) throws IOException {
final long sourceTimestamp = in.readLong();
return doRead(in, sourceTimestamp);
public VirtualFilePersistentState read(DataInput in) throws IOException {
return new VirtualFilePersistentState(in.readLong());
}
}
@@ -46,7 +46,7 @@ public class ArtifactCompilerCompileItem extends VirtualFileCompileItem<Artifact
@NotNull
@Override
public ArtifactPackagingItemOutputState computeState() {
public ArtifactPackagingItemOutputState computeOutputState() {
final SmartList<Pair<String, Long>> pairs = new SmartList<Pair<String, Long>>();
for (DestinationInfo destination : myDestinations) {
destination.update();
@@ -54,11 +54,11 @@ public class ArtifactCompilerCompileItem extends VirtualFileCompileItem<Artifact
long timestamp = outputFile != null ? outputFile.getTimeStamp() : -1;
pairs.add(Pair.create(destination.getOutputPath(), timestamp));
}
return new ArtifactPackagingItemOutputState(myFile.getTimeStamp(), pairs);
return new ArtifactPackagingItemOutputState(pairs);
}
@Override
public boolean isStateUpToDate(ArtifactPackagingItemOutputState state) {
public boolean isOutputUpToDate(@NotNull ArtifactPackagingItemOutputState state) {
final SmartList<Pair<String, Long>> cachedDestinations = state.myDestinations;
if (cachedDestinations.size() != myDestinations.size()) {
return false;
@@ -15,9 +15,9 @@
*/
package com.intellij.packaging.impl.compiler;
import com.intellij.compiler.impl.newApi.VirtualFileStateExternalizer;
import com.intellij.openapi.util.Pair;
import com.intellij.util.SmartList;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.IOUtil;
import java.io.DataInput;
@@ -27,12 +27,11 @@ import java.io.IOException;
/**
* @author nik
*/
public class ArtifactPackagingItemExternalizer
extends VirtualFileStateExternalizer<ArtifactPackagingItemOutputState> {
public class ArtifactPackagingItemExternalizer implements DataExternalizer<ArtifactPackagingItemOutputState> {
private byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
@Override
protected void doSave(DataOutput out, ArtifactPackagingItemOutputState value) throws IOException {
public void save(DataOutput out, ArtifactPackagingItemOutputState value) throws IOException {
out.writeInt(value.myDestinations.size());
for (Pair<String, Long> pair : value.myDestinations) {
IOUtil.writeUTFFast(myBuffer, out, pair.getFirst());
@@ -41,7 +40,7 @@ public class ArtifactPackagingItemExternalizer
}
@Override
protected ArtifactPackagingItemOutputState doRead(DataInput in, long sourceTimestamp) throws IOException {
public ArtifactPackagingItemOutputState read(DataInput in) throws IOException {
int size = in.readInt();
SmartList<Pair<String, Long>> destinations = new SmartList<Pair<String, Long>>();
while (size-- > 0) {
@@ -49,6 +48,6 @@ public class ArtifactPackagingItemExternalizer
long outputTimestamp = in.readLong();
destinations.add(Pair.create(path, outputTimestamp));
}
return new ArtifactPackagingItemOutputState(sourceTimestamp, destinations);
return new ArtifactPackagingItemOutputState(destinations);
}
}
@@ -15,18 +15,16 @@
*/
package com.intellij.packaging.impl.compiler;
import com.intellij.compiler.impl.newApi.VirtualFilePersistentState;
import com.intellij.openapi.util.Pair;
import com.intellij.util.SmartList;
/**
* @author nik
*/
public class ArtifactPackagingItemOutputState extends VirtualFilePersistentState {
public class ArtifactPackagingItemOutputState {
public final SmartList<Pair<String, Long>> myDestinations;
public ArtifactPackagingItemOutputState(long timestamp, SmartList<Pair<String, Long>> destinations) {
super(timestamp);
public ArtifactPackagingItemOutputState(SmartList<Pair<String, Long>> destinations) {
myDestinations = destinations;
}
}
@@ -15,10 +15,7 @@
*/
package com.intellij.packaging.impl.compiler;
import com.intellij.compiler.impl.newApi.CompileItem;
import com.intellij.compiler.impl.newApi.CompilerInstance;
import com.intellij.compiler.impl.newApi.NewCompiler;
import com.intellij.compiler.impl.newApi.VirtualFileCompileItem;
import com.intellij.compiler.impl.newApi.*;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerManager;
@@ -35,7 +32,7 @@ import java.util.Set;
/**
* @author nik
*/
public class ArtifactsCompiler extends NewCompiler<String, ArtifactPackagingItemOutputState> {
public class ArtifactsCompiler extends NewCompiler<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState> {
static final Key<Set<String>> WRITTEN_PATHS_KEY = Key.create("artifacts_written_paths");
static final Key<Set<Artifact>> AFFECTED_ARTIFACTS = Key.create("affected_artifacts");
@@ -57,13 +54,19 @@ public class ArtifactsCompiler extends NewCompiler<String, ArtifactPackagingItem
@NotNull
@Override
public DataExternalizer<ArtifactPackagingItemOutputState> getItemStateExternalizer() {
return ArtifactCompilerCompileItem.OUTPUT_EXTERNALIZER;
public DataExternalizer<VirtualFilePersistentState> getSourceStateExternalizer() {
return VirtualFileStateExternalizer.INSTANCE;
}
@NotNull
@Override
public CompilerInstance<ArtifactBuildTarget, ? extends CompileItem<String, ArtifactPackagingItemOutputState>, String, ArtifactPackagingItemOutputState> createInstance(
public DataExternalizer<ArtifactPackagingItemOutputState> getOutputStateExternalizer() {
return new ArtifactPackagingItemExternalizer();
}
@NotNull
@Override
public CompilerInstance<ArtifactBuildTarget, ? extends CompileItem<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState>, String, VirtualFilePersistentState, ArtifactPackagingItemOutputState> createInstance(
@NotNull CompileContext context) {
return new ArtifactsCompilerInstance(context);
}
@@ -18,6 +18,8 @@ package com.intellij.packaging.impl.compiler;
import com.intellij.compiler.CompilerManagerImpl;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.impl.newApi.CompilerInstance;
import com.intellij.compiler.impl.newApi.NewCompilerItemState;
import com.intellij.compiler.impl.newApi.VirtualFilePersistentState;
import com.intellij.compiler.impl.packagingCompiler.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
@@ -31,7 +33,7 @@ import com.intellij.openapi.deployment.DeploymentUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
@@ -60,7 +62,7 @@ import java.util.*;
* @author nik
*/
public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTarget, ArtifactCompilerCompileItem,
String, ArtifactPackagingItemOutputState> {
String, VirtualFilePersistentState, ArtifactPackagingItemOutputState> {
private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.compiler.ArtifactsCompilerInstance");
private ArtifactsProcessingItemsBuilderContext myBuilderContext;
@@ -117,8 +119,9 @@ public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTar
}
@Override
public void processObsoleteTarget(@NotNull String targetId, @NotNull List<Pair<String, ArtifactPackagingItemOutputState>> obsoleteItems) {
deleteFiles(obsoleteItems, Collections.<Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState>>emptyList());
public void processObsoleteTarget(@NotNull String targetId,
@NotNull List<NewCompilerItemState<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState>> obsoleteItems) {
deleteFiles(obsoleteItems, Collections.<NewCompilerItemState<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState>>emptyList());
}
@NotNull
@@ -160,7 +163,7 @@ public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTar
rootElement.computeIncrementalCompilerInstructions(instructionCreator, resolvingContext, myBuilderContext, artifact.getArtifactType());
}
private boolean doBuild(final List<Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState>> changedItems,
private boolean doBuild(final List<NewCompilerItemState<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState>> changedItems,
final Set<ArtifactCompilerCompileItem> processedItems,
final @NotNull Set<String> writtenPaths, final Set<String> deletedJars) {
final boolean testMode = ApplicationManager.getApplication().isUnitTestMode();
@@ -179,8 +182,8 @@ public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTar
}
int i = 0;
for (final Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState> item : changedItems) {
final ArtifactCompilerCompileItem sourceItem = item.getFirst();
for (final NewCompilerItemState<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState> item : changedItems) {
final ArtifactCompilerCompileItem sourceItem = item.getItem();
myContext.getProgressIndicator().checkCanceled();
final Ref<IOException> exception = Ref.create(null);
@@ -304,9 +307,10 @@ public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTar
}
@Override
public void processItems(@NotNull ArtifactBuildTarget target, @NotNull final List<Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState>> changedItems,
@NotNull List<Pair<String, ArtifactPackagingItemOutputState>> obsoleteItems,
@NotNull final OutputConsumer<ArtifactCompilerCompileItem> consumer) {
public void processItems(@NotNull ArtifactBuildTarget target,
@NotNull final List<NewCompilerItemState<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState>> changedItems,
@NotNull List<NewCompilerItemState<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState>> obsoleteItems,
@NotNull OutputConsumer<ArtifactCompilerCompileItem> consumer) {
final THashSet<String> deletedJars = deleteFiles(obsoleteItems, changedItems);
@@ -333,8 +337,8 @@ public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTar
myContext.putUserData(ArtifactsCompiler.WRITTEN_PATHS_KEY, writtenPaths);
}
private THashSet<String> deleteFiles(List<Pair<String, ArtifactPackagingItemOutputState>> obsoleteItems,
List<Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState>> changedItems) {
private THashSet<String> deleteFiles(List<NewCompilerItemState<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState>> obsoleteItems,
List<NewCompilerItemState<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState>> changedItems) {
myContext.getProgressIndicator().setText(CompilerBundle.message("packaging.compiler.message.deleting.outdated.files"));
final boolean testMode = ApplicationManager.getApplication().isUnitTestMode();
@@ -345,21 +349,21 @@ public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTar
}
Set<String> pathToDelete = new THashSet<String>();
for (Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState> item : changedItems) {
final ArtifactPackagingItemOutputState cached = item.getSecond();
for (NewCompilerItemState<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState> item : changedItems) {
final ArtifactPackagingItemOutputState cached = item.getOutputState();
if (cached != null) {
for (Pair<String, Long> destination : cached.myDestinations) {
pathToDelete.add(destination.getFirst());
}
}
}
for (Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState> item : changedItems) {
for (DestinationInfo destination : item.getFirst().getDestinations()) {
for (NewCompilerItemState<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState> item : changedItems) {
for (DestinationInfo destination : item.getItem().getDestinations()) {
pathToDelete.remove(destination.getOutputPath());
}
}
for (Pair<String, ArtifactPackagingItemOutputState> item : obsoleteItems) {
for (Pair<String, Long> destination : item.getSecond().myDestinations) {
for (NewCompilerItemState<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState> item : obsoleteItems) {
for (Pair<String, Long> destination : item.getOutputState().myDestinations) {
pathToDelete.add(destination.getFirst());
}
}
@@ -366,7 +366,7 @@ public class JavaDocUtil {
String s = fixupMatcher.group(1);
//[db] that's workaround to avoid internal bug
if (!s.equals("\\")) {
if (!s.equals("\\") && !secondSymbols.contains(s)) {
secondSymbols.addFirst(s);
}
}
@@ -31,11 +31,14 @@ import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatement;
import com.intellij.psi.impl.source.resolve.ResolveClassUtil;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReference;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.jsp.JspFile;
import com.intellij.psi.jsp.JspSpiUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
@@ -59,8 +62,14 @@ public class ImportHelper{
}
public PsiImportList prepareOptimizeImportsResult(@NotNull final PsiJavaFile file) {
// Java parser works in a way that comments may be included to the import list, e.g.:
// import a;
// /* comment */
// import b;
// We want to preserve those comments then.
List<String> comments = new ArrayList<String>();
// Note: this array may contain "<packageOrClassName>.*" for unresolved imports!
List<Pair<String, Boolean>> names = new ArrayList<Pair<String, Boolean>>(collectNamesToImport(file));
List<Pair<String, Boolean>> names = new ArrayList<Pair<String, Boolean>>(collectNamesToImport(file, comments));
Collections.sort(names, new Comparator<Pair<String, Boolean>>() {
public int compare(Pair<String, Boolean> o1, Pair<String, Boolean> o2) {
return o1.getFirst().compareTo(o2.getFirst());
@@ -131,15 +140,29 @@ public class ImportHelper{
try {
StringBuilder text = buildImportListText(resultList, classesOrPackagesToImportOnDemand, classesToUseSingle);
for (String comment : comments) {
text.append("\n").append(comment);
}
String ext = StdFileTypes.JAVA.getDefaultExtension();
PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject());
final PsiJavaFile dummyFile = (PsiJavaFile)factory.createFileFromText("_Dummy_." + ext, StdFileTypes.JAVA, text);
CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(file.getProject());
codeStyleManager.reformat(dummyFile);
PsiImportList result = dummyFile.getImportList();
PsiImportList newImportList = dummyFile.getImportList();
PsiImportList result = (PsiImportList)newImportList.copy();
PsiImportList oldList = file.getImportList();
if (oldList.isReplaceEquivalent(result)) return null;
PsiElement firstPrevious = newImportList.getPrevSibling();
while (firstPrevious != null && firstPrevious.getPrevSibling() != null) {
firstPrevious = firstPrevious.getPrevSibling();
}
for (PsiElement element = firstPrevious; element != null && element != newImportList; element = element.getNextSibling()) {
result.add(element.copy());
}
for (PsiElement element = newImportList.getNextSibling(); element != null; element = element.getNextSibling()) {
result.add(element.copy());
}
return result;
}
catch(IncorrectOperationException e) {
@@ -603,17 +626,17 @@ public class ImportHelper{
@NotNull
// returns list of (name, isImportStatic) pairs
private static Collection<Pair<String,Boolean>> collectNamesToImport(@NotNull PsiJavaFile file){
private static Collection<Pair<String,Boolean>> collectNamesToImport(@NotNull PsiJavaFile file, List<String> comments){
Set<Pair<String,Boolean>> names = new THashSet<Pair<String,Boolean>>();
final JspFile jspFile = JspPsiUtil.getJspFile(file);
collectNamesToImport(names, file, jspFile);
collectNamesToImport(names, comments, file, jspFile);
if (jspFile != null) {
PsiFile[] files = ArrayUtil.mergeArrays(JspSpiUtil.getIncludingFiles(jspFile), JspSpiUtil.getIncludedFiles(jspFile), PsiFile.class);
for (PsiFile includingFile : files) {
final PsiFile javaRoot = includingFile.getViewProvider().getPsi(StdLanguages.JAVA);
if (javaRoot instanceof PsiJavaFile && file != javaRoot) {
collectNamesToImport(names, (PsiJavaFile)javaRoot, jspFile);
collectNamesToImport(names, comments, (PsiJavaFile)javaRoot, jspFile);
}
}
}
@@ -624,17 +647,19 @@ public class ImportHelper{
}
private static void collectNamesToImport(@NotNull final Set<Pair<String, Boolean>> names,
@NotNull List<String> comments,
@NotNull final PsiJavaFile file,
PsiFile context) {
String packageName = file.getPackageName();
final PsiElement[] roots = file.getPsiRoots();
for (PsiElement root : roots) {
addNamesToImport(names, root, packageName, context);
addNamesToImport(names, comments, root, packageName, context);
}
}
private static void addNamesToImport(@NotNull Set<Pair<String, Boolean>> names,
@NotNull List<String> comments,
@NotNull PsiElement scope,
@NotNull String thisPackageName,
PsiFile context){
@@ -644,7 +669,15 @@ public class ImportHelper{
stack.add(scope);
while (!stack.isEmpty()) {
final PsiElement child = stack.removeFirst();
if (child instanceof PsiImportList) continue;
if (child instanceof PsiImportList) {
for (PsiElement element : child.getChildren()) {
IElementType elementType = element.getNode().getElementType();
if (!JavaElementType.IMPORT_STATEMENT.equals(elementType) && !ElementType.WHITE_SPACE_BIT_SET.contains(elementType)) {
comments.add(element.getText());
}
}
continue;
}
if (child instanceof PsiLiteralExpression) continue;
ContainerUtil.addAll(stack, child.getChildren());
@@ -38,7 +38,6 @@ import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NonNls;
@@ -589,7 +588,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
String[] names = getSuggestionsByName(propertyName, variableKind, false);
final PsiExpression qualifierExpression = methodExpr.getQualifierExpression();
if (qualifierExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifierExpression).resolve() instanceof PsiVariable) {
names = ArrayUtil.append(names, changeIfNotIdentifier(qualifierExpression.getText() + StringUtil.capitalize(propertyName)));
names = ArrayUtil.append(names, StringUtil.sanitizeJavaIdentifier(changeIfNotIdentifier(qualifierExpression.getText() + StringUtil.capitalize(propertyName))));
}
return new NamesByExprInfo(propertyName, names);
}
@@ -945,7 +944,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
@NotNull
public SuggestedNameInfo suggestUniqueVariableName(@NotNull final SuggestedNameInfo baseNameInfo, PsiElement place, boolean lookForward) {
final String[] names = baseNameInfo.names;
Set<String> uniqueNames = new HashSet<String>(names.length);
final LinkedHashSet<String> uniqueNames = new LinkedHashSet<String>(names.length);
for (String name : names) {
uniqueNames.add(suggestUniqueVariableName(name, place, lookForward));
}
@@ -36,6 +36,7 @@ public class OptimizeImportsRefactoringHelper implements RefactoringHelper<Set<P
public Set<PsiJavaFile> prepareOperation(final UsageInfo[] usages) {
Set<PsiJavaFile> javaFiles = new HashSet<PsiJavaFile>();
for (UsageInfo usage : usages) {
if (usage.isNonCodeUsage) continue;
final PsiElement element = usage.getElement();
if (element != null) {
final PsiFile file = element.getContainingFile();
@@ -400,7 +400,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
return RefactoringUtil.getTypeByExpressionWithExpectedType(expr);
}
public PsiClass getParentClass(PsiExpression initializerExpression) {
public PsiClass getParentClass(@NotNull PsiExpression initializerExpression) {
PsiElement element = initializerExpression.getUserData(ElementToWorkOn.PARENT);
if (element == null) element = initializerExpression.getParent();
PsiElement parent = element;
@@ -71,7 +71,7 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler {
PsiLocalVariable local,
PsiExpression[] occurences,
boolean isStatic) {
return IntroduceConstantHandler.this.showRefactoringDialog(project, editor, aClass, local.getInitializer(), local.getType(), occurences, null, null);
return IntroduceConstantHandler.this.showRefactoringDialog(project, editor, aClass, local.getInitializer(), local.getType(), occurences, local, null);
}
};
return localToFieldHandler.convertLocalToField(localVariable, editor);
@@ -86,6 +86,7 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler {
PsiExpression[] occurences,
PsiElement anchorElement,
PsiElement anchorElementIfAll) {
final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(expr != null ? expr : anchorElement, PsiMethod.class);
for (PsiExpression occurrence : occurences) {
if (RefactoringUtil.isAssignmentLHS(occurrence)) {
String message =
@@ -133,7 +134,7 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler {
final IntroduceConstantDialog dialog =
new IntroduceConstantDialog(project, parentClass, expr, localVariable, false, occurences, getParentClass(),
new TypeSelectorManagerImpl(project, type, expr, occurences));
new TypeSelectorManagerImpl(project, type, containingMethod, expr, occurences));
dialog.show();
if (!dialog.isOK()) {
if (occurences.length > 1) {
@@ -161,7 +162,7 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler {
@Nullable
private PsiElement isStaticFinalInitializer(PsiExpression expr) {
PsiClass parentClass = getParentClass(expr);
PsiClass parentClass = expr != null ? getParentClass(expr) : null;
if (parentClass == null) return null;
IsStaticFinalInitializerExpression visitor = new IsStaticFinalInitializerExpression(parentClass, expr);
expr.accept(visitor);
@@ -212,7 +213,7 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler {
}
}
public PsiClass getParentClass(PsiExpression initializerExpression) {
public PsiClass getParentClass(@NotNull PsiExpression initializerExpression) {
final PsiType type = initializerExpression.getType();
if (type != null && PsiUtil.isConstantExpression(initializerExpression)) {
@@ -20,7 +20,6 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.HelpID;
@@ -28,7 +27,6 @@ import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.occurences.*;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
public class IntroduceFieldHandler extends BaseExpressionToFieldHandler {
@@ -96,13 +94,12 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler {
final boolean currentMethodConstructor = containingMethod != null && containingMethod.isConstructor();
final boolean allowInitInMethod = (!currentMethodConstructor || !isInSuperOrThis) && anchorElement instanceof PsiStatement;
final boolean allowInitInMethodIfAll = (!currentMethodConstructor || !isInSuperOrThis) && anchorElementIfAll instanceof PsiStatement;
type = checkIfTypeAccessible(type, project, parentClass, containingMethod);
IntroduceFieldDialog dialog = new IntroduceFieldDialog(
project, parentClass, expr, localVariable,
currentMethodConstructor,
false, declareStatic, occurencesNumber,
allowInitInMethod, allowInitInMethodIfAll,
new TypeSelectorManagerImpl(project, type, expr, occurences)
new TypeSelectorManagerImpl(project, type, containingMethod, expr, occurences)
);
dialog.show();
@@ -125,23 +122,6 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler {
dialog.getFieldType(), localVariable != null, (TargetDestination)null, false, false);
}
private static PsiType checkIfTypeAccessible(PsiType type, Project project, PsiClass parentClass, PsiMethod containingMethod) {
final PsiClass typeClass = PsiUtil.resolveClassInType(type);
if (typeClass != null) {
if (typeClass instanceof PsiTypeParameter) {
if (ArrayUtil.find(parentClass.getTypeParameters(), typeClass) == -1) { //unknown type parameter
type = PsiType.getJavaLangObject(PsiManager.getInstance(project), GlobalSearchScope.allScope(project));
}
} else if (PsiTreeUtil.isAncestor(containingMethod, typeClass, true)) { //local class type
final PsiClassType[] superTypes = typeClass.getSuperTypes();
if (superTypes.length > 0) {
return checkIfTypeAccessible(superTypes[0], project, parentClass, containingMethod);
}
}
}
return type;
}
private static boolean isInSuperOrThis(PsiExpression occurence) {
return !NotInSuperCallOccurenceFilter.INSTANCE.isOK(occurence) || !NotInThisCallFilter.INSTANCE.isOK(occurence);
}
@@ -21,11 +21,14 @@ import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.TailType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.statistics.StatisticsInfo;
import com.intellij.psi.statistics.StatisticsManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.util.RefactoringHierarchyUtil;
import com.intellij.util.ArrayUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
@@ -35,7 +38,7 @@ import java.util.*;
* @author dsl
*/
public class TypeSelectorManagerImpl implements TypeSelectorManager {
private final PsiType myDefaultType;
private PsiType myDefaultType;
private final PsiExpression myMainOccurence;
private final PsiExpression[] myOccurrences;
private final PsiType[] myTypesForMain;
@@ -47,27 +50,7 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
private ExpectedTypesProvider myExpectedTypesProvider;
public TypeSelectorManagerImpl(Project project, PsiType type, PsiExpression mainOccurence, PsiExpression[] occurrences) {
myFactory = JavaPsiFacade.getInstance(project).getElementFactory();
myDefaultType = type;
myMainOccurence = mainOccurence;
myOccurrences = occurrences;
myExpectedTypesProvider = ExpectedTypesProvider.getInstance(project);
myOccurrenceClassProvider = createOccurrenceClassProvider();
myTypesForMain = getTypesForMain();
myTypesForAll = getTypesForAll(true);
myIsOneSuggestion =
myTypesForMain.length == 1 && myTypesForAll.length == 1 &&
myTypesForAll[0].equals(myTypesForMain[0]);
if (myIsOneSuggestion) {
myTypeSelector = new TypeSelector(myTypesForAll[0]);
}
else {
myTypeSelector = new TypeSelector();
}
this(project, type, null, mainOccurence, occurrences);
}
public TypeSelectorManagerImpl(Project project, PsiType type, PsiExpression[] occurrences) {
@@ -94,10 +77,64 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
}
}
public TypeSelectorManagerImpl(Project project,
PsiType type,
PsiMethod containingMethod,
PsiExpression mainOccurence,
PsiExpression[] occurrences) {
myFactory = JavaPsiFacade.getInstance(project).getElementFactory();
myDefaultType = type;
myMainOccurence = mainOccurence;
myOccurrences = occurrences;
myExpectedTypesProvider = ExpectedTypesProvider.getInstance(project);
myOccurrenceClassProvider = createOccurrenceClassProvider();
myTypesForMain = getTypesForMain();
myTypesForAll = getTypesForAll(true);
if (containingMethod != null) {
if (PsiUtil.resolveClassInType(type) != null) {
myDefaultType = checkIfTypeAccessible(type, project, containingMethod);
}
}
myIsOneSuggestion =
myTypesForMain.length == 1 && myTypesForAll.length == 1 &&
myTypesForAll[0].equals(myTypesForMain[0]);
if (myIsOneSuggestion) {
myTypeSelector = new TypeSelector(myTypesForAll[0]);
}
else {
myTypeSelector = new TypeSelector();
}
}
private PsiType checkIfTypeAccessible(PsiType type, Project project, PsiMethod containingMethod) {
PsiClass parentClass = containingMethod.getContainingClass();
final PsiClass typeClass = PsiUtil.resolveClassInType(type);
if (typeClass != null) {
if (typeClass instanceof PsiTypeParameter) {
if (ArrayUtil.find(parentClass.getTypeParameters(), typeClass) == -1) { //unknown type parameter
return PsiType.getJavaLangObject(PsiManager.getInstance(project), GlobalSearchScope.allScope(project));
}
} else if (PsiTreeUtil.isAncestor(containingMethod, typeClass, true)) { //local class type
final int nextTypeIdx = ArrayUtil.find(myTypesForAll, type) + 1;
if (nextTypeIdx < myTypesForAll.length) {
return checkIfTypeAccessible(myTypesForAll[nextTypeIdx], project, containingMethod);
}
}
}
return type;
}
public PsiType[] getTypesForAll() {
return myTypesForAll;
}
public PsiType getDefaultType() {
return myDefaultType;
}
private ExpectedTypesProvider.ExpectedClassProvider createOccurrenceClassProvider() {
final Set<PsiClass> occurrenceClasses = new HashSet<PsiClass>();
for (final PsiExpression occurence : myOccurrences) {
@@ -15,14 +15,26 @@
*/
package com.intellij.testIntegration;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.testIntegration.createTest.CreateTestAction;
import com.intellij.util.IncorrectOperationException;
public class JavaTestCreator implements TestCreator {
private static final Logger LOG = Logger.getInstance("com.intellij.testIntegration.JavaTestCreator");
@Override
public boolean isAvailable(Project project, Editor editor, PsiFile file) {
CreateTestAction action = new CreateTestAction();
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
return action.isAvailableForElement(element);
}
public void createTest(Project project, Editor editor, PsiFile file) {
try {
CreateTestAction action = new CreateTestAction();
@@ -32,7 +44,7 @@ public class JavaTestCreator implements TestCreator {
}
}
catch (IncorrectOperationException e) {
throw new RuntimeException(e);
LOG.warn(e);
}
}
}
@@ -0,0 +1,6 @@
class Test {
void foo() {
class C {}
C c<caret>c;
}
}
@@ -0,0 +1,7 @@
class Test {
class C {}
void foo() {
C c<caret>c;
}
}
@@ -1,12 +1,13 @@
package com.intellij.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiLocalVariable;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.testFramework.TestDataPath;
import com.intellij.util.VisibilityUtil;
@@ -87,6 +88,37 @@ public class IntroduceConstantTest extends LightCodeInsightTestCase {
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
public void testResultedType() throws Exception {
checkDefaultType("java.lang.Object");
}
public void testResultedTypeWhenNonLocal() throws Exception {
checkDefaultType("Test.C");
}
private void checkDefaultType(final String expectedType) throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
new MockIntroduceConstantHandler(null){
@Override
protected Settings showRefactoringDialog(Project project,
Editor editor,
PsiClass parentClass,
PsiExpression expr,
PsiType type,
PsiExpression[] occurences,
PsiElement anchorElement,
PsiElement anchorElementIfAll) {
final TypeSelectorManagerImpl selectorManager =
new TypeSelectorManagerImpl(project, type, PsiTreeUtil.getParentOfType(anchorElement, PsiMethod.class), expr, occurences);
final PsiType psiType = selectorManager.getDefaultType();
Assert.assertEquals(psiType.getCanonicalText(), expectedType);
return new Settings("xxx", true, true, true,
InitializationPlace.IN_FIELD_DECLARATION, getVisibility(), null, psiType, false,
parentClass, false, false);
}
}.invoke(getProject(), getEditor(), getFile(), null);
}
protected Sdk getProjectJDK() {
return JavaSdkImpl.getMockJdk17("java 1.5");
}
@@ -43,10 +43,19 @@ public class JarVersionDetectionUtil {
@Nullable
public static String detectJarVersion(@NotNull final String detectionClass, @NotNull Module module) {
try {
final ZipFile zipFile = getDetectionJar(detectionClass, module);
if (zipFile == null) {
return null;
}
return detectJarVersion(getDetectionJar(detectionClass, module));
}
catch (IOException e) {
return null;
}
}
@Nullable
public static String detectJarVersion(ZipFile zipFile) {
if (zipFile == null) {
return null;
}
try {
final ZipEntry zipEntry = zipFile.getEntry(JarFile.MANIFEST_NAME);
if (zipEntry == null) {
return null;
@@ -21,5 +21,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
public interface TestCreator {
boolean isAvailable(Project project, Editor editor, PsiFile file);
void createTest(Project project, Editor editor, PsiFile file);
}
@@ -16,15 +16,12 @@
package com.intellij.refactoring.rename;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiNamedElement;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.rename.naming.AutomaticRenamer;
@@ -250,7 +247,7 @@ public class AutomaticRenamingDialog extends DialogWrapper {
case CHECK_COLUMN:
return Boolean.valueOf(myShouldRename[rowIndex]);
case OLD_NAME_COLUMN:
return "<html>" + RefactoringUIUtil.getDescription(myRenames[rowIndex], true) + "</html>";
return "<html><nobr>" + RefactoringUIUtil.getDescription(myRenames[rowIndex], true) + "</nobr></html>";
case NEW_NAME_COLUMN:
return myNewNames[rowIndex];
default:
@@ -53,23 +53,25 @@ public class GotoTestOrCodeHandler extends GotoTargetHandler {
}
else {
candidates = TestFinderHelper.findTestsForClass(selectedElement);
actions.add(new AdditionalAction() {
@Override
public String getText() {
return "Create New Test...";
}
final TestCreator creator = LanguageTestCreators.INSTANCE.forLanguage(file.getLanguage());
if (creator != null && creator.isAvailable(file.getProject(), editor, file)) {
actions.add(new AdditionalAction() {
@Override
public String getText() {
return "Create New Test...";
}
@Override
public Icon getIcon() {
return IconLoader.getIcon("/actions/intentionBulb.png");
}
@Override
public Icon getIcon() {
return IconLoader.getIcon("/actions/intentionBulb.png");
}
@Override
public void execute() {
final TestCreator creator = LanguageTestCreators.INSTANCE.forLanguage(file.getLanguage());
if (creator != null) creator.createTest(file.getProject(), editor, file);
}
});
@Override
public void execute() {
creator.createTest(file.getProject(), editor, file);
}
});
}
}
return new GotoData(sourceElement, candidates.toArray(new PsiElement[candidates.size()]), actions);
@@ -65,7 +65,7 @@ public interface TextAnnotationGutterProvider {
/***
* enables annotation view modifications
*/
List<AnAction> getPopupActions(final Editor editor);
List<AnAction> getPopupActions(final int line, final Editor editor);
/**
* Called when the annotations are removed from the editor gutter.
@@ -1191,8 +1191,12 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
DefaultActionGroup actionGroup = new DefaultActionGroup(EditorBundle.message("editor.annotations.action.group.name"), true);
actionGroup.add(new CloseAnnotationsAction());
final List<AnAction> addActions = new ArrayList<AnAction>();
final Point p = e.getPoint();
int line = myEditor.xyToLogicalPosition(new Point(0, (int)p.getY())).line;
if (line >= myEditor.getDocument().getLineCount()) return;
for (TextAnnotationGutterProvider gutterProvider : myTextAnnotationGutters) {
final List<AnAction> list = gutterProvider.getPopupActions(myEditor);
final List<AnAction> list = gutterProvider.getPopupActions(line, myEditor);
if (list != null) {
for (AnAction action : list) {
if (! addActions.contains(action)) {
@@ -59,7 +59,6 @@ import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.GuiUtils;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.LightweightHint;
import com.intellij.ui.components.JBScrollBar;
import com.intellij.ui.components.JBScrollPane;
@@ -72,6 +71,7 @@ import com.intellij.util.ui.EmptyClipboardOwner;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.update.UiNotifyConnector;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntHashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -1203,12 +1203,18 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myGutterComponent.repaint(0, yStartLine, myGutterComponent.getWidth(), yEndLine - yStartLine);
}
/**
* Asks to repaint all logical lines from the given <code>[start; end]</code> range.
*
* @param startLine start logical line to repaint (inclusive)
* @param endLine end logical line to repaint (inclusive)
*/
public void repaintLines(int startLine, int endLine) {
if (!isShowing()) return;
Rectangle visibleArea = getScrollingModel().getVisibleArea();
int yStartLine = logicalLineToY(startLine);
int yEndLine = logicalLineToY(endLine) + getLineHeight() + WAVE_HEIGHT;
int yEndLine = logicalPositionToXY(new LogicalPosition(endLine + 1, 0)).y + WAVE_HEIGHT;
myEditorComponent.repaintEditorComponent(visibleArea.x, yStartLine, visibleArea.x + visibleArea.width, yEndLine - yStartLine);
myGutterComponent.repaint(0, yStartLine, myGutterComponent.getWidth(), yEndLine - yStartLine);
@@ -1578,20 +1584,31 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
int visibleLineNumber = clip.y / lineHeight;
int startLineNumber = xyToLogicalPosition(new Point(0, clip.y)).line;
VisualPosition visualPosition = xyToVisualPosition(new Point(0, clip.y));
LogicalPosition logicalPosition = visualToLogicalPosition(visualPosition);
Point position = new Point(0, visibleLineNumber * lineHeight);
if (startLineNumber == 0 && myPrefixText != null) {
if (visualPosition.line == 0 && myPrefixText != null) {
position.x = drawBackground(g, myPrefixAttributes.getBackgroundColor(), new String(myPrefixText), position, myPrefixAttributes.getFontType(),
defaultBackground, clip);
}
if (startLineNumber >= myDocument.getLineCount() || startLineNumber < 0) {
if (logicalPosition.line >= myDocument.getLineCount() || logicalPosition.line < 0) {
if (position.x > 0) flushBackground(g, clip);
return;
}
int start = myDocument.getLineStartOffset(startLineNumber);
int start = logicalPositionToOffset(logicalPosition);
// There is a possible case that we need to draw background from the start of soft wrap-introduced visual line. Given position
// has valid 'y' coordinate then at it shouldn't be affected by soft wrap that corresponds to the visual line start offset.
// Hence, we store information about soft wrap to be skipped for further processing and adjust 'x' coordinate value if necessary.
TIntHashSet softWrapsToSkip = new TIntHashSet();
TextChange softWrap = getSoftWrapModel().getSoftWrap(start);
if (softWrap != null) {
position.x = getSoftWrapModel().getSoftWrapIndentWidthInPixels(softWrap);
softWrapsToSkip.add(softWrap.getStart());
}
IterationState iterationState = new IterationState(this, start, paintSelection());
@@ -1620,7 +1637,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start);
if (collapsedFolderAt == null) {
position.x = drawSoftWrapAwareBackground(g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType,
defaultBackground, clip);
defaultBackground, clip, softWrapsToSkip);
if (lIterator.getLineNumber() < lastLineIndex) {
if (backColor != null && !backColor.equals(defaultBackground)) {
@@ -1653,11 +1670,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (hEnd > lEnd - lIterator.getSeparatorLength()) {
position.x = drawSoftWrapAwareBackground(
g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType,
defaultBackground, clip
defaultBackground, clip, softWrapsToSkip
);
}
else {
position.x = drawSoftWrapAwareBackground(g, backColor, text, start, hEnd, position, fontType, defaultBackground, clip);
position.x = drawSoftWrapAwareBackground(
g, backColor, text, start, hEnd, position, fontType, defaultBackground, clip, softWrapsToSkip
);
}
}
@@ -1716,12 +1735,15 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
private int drawSoftWrapAwareBackground(Graphics g, Color backColor, CharSequence text, int start, int end, Point position,
int fontType, Color defaultBackground, Rectangle clip)
int fontType, Color defaultBackground, Rectangle clip, TIntHashSet processSoftWrap)
{
int startToUse = start;
List<? extends TextChange> softWraps = getSoftWrapModel().getSoftWrapsForRange(start, end);
for (TextChange softWrap : softWraps) {
int softWrapStart = softWrap.getStart();
if (processSoftWrap.contains(softWrapStart)) {
continue;
}
if (startToUse < softWrapStart) {
position.x = drawBackground(g, backColor, text.subSequence(startToUse, softWrapStart), position, fontType, defaultBackground, clip);
}
@@ -1739,7 +1761,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
int fontType, Color defaultBackground, Rectangle clip)
{
position.x = drawBackground(
g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED), position, fontType,
g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED), position,
defaultBackground, clip
);
@@ -1763,7 +1785,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
position.x = drawBackground(
g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP), position, fontType,
g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP), position,
defaultBackground, clip
);
}
@@ -1772,14 +1794,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
Rectangle clip)
{
int width = getTextSegmentWidth(text, position.x, fontType, clip);
return drawBackground(g, backColor, width, position, fontType, defaultBackground, clip);
return drawBackground(g, backColor, width, position, defaultBackground, clip);
}
private int drawBackground(Graphics g,
Color backColor,
int width,
Point position,
int fontType,
Color defaultBackground,
Rectangle clip) {
if (backColor != null && !backColor.equals(defaultBackground) && clip.intersects(position.x, position.y, width, getLineHeight())) {
@@ -3400,7 +3421,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myCommandProcessor.executeCommand(myProject, new DocumentRunnable(myDocument, myProject) {
public void run() {
int oldSelectionStart = mySelectionModel.getLeadSelectionOffset();
LogicalPosition caretPosition = getCaretModel().getLogicalPosition();
VisualPosition caretPosition = getCaretModel().getVisualPosition();
int columnNumber = caretPosition.column;
xPassedCycles++;
if (xPassedCycles >= myXCycles) {
@@ -3415,8 +3436,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
lineNumber += myDy;
}
LogicalPosition pos = new LogicalPosition(lineNumber, columnNumber);
getCaretModel().moveToLogicalPosition(pos);
VisualPosition pos = new VisualPosition(lineNumber, columnNumber);
getCaretModel().moveToVisualPosition(pos);
getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
int newCaretOffset = getCaretModel().getOffset();
@@ -4886,13 +4907,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
int maxWidth = 0;
for (int i = startToUse; i < endToUse; i++) {
// TODO den unwrap
try {
maxWidth = Math.max(maxWidth, myLineWidths.getQuick(i));
}
catch (Exception e) {
e.printStackTrace();
}
maxWidth = Math.max(maxWidth, myLineWidths.getQuick(i));
}
mySize = new Dimension(maxWidth, getLineHeight() * getVisibleLineCount());
@@ -21,7 +21,6 @@
package com.intellij.execution.testframework;
import com.intellij.execution.Location;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
@@ -91,4 +90,30 @@ public abstract class AbstractTestProxy extends CompositePrintable {
Disposer.dispose(proxy);
}
}
public static void flushOutput(AbstractTestProxy testProxy) {
testProxy.flush();
AbstractTestProxy parent = testProxy.getParent();
while (parent != null) {
final List<? extends AbstractTestProxy> children = parent.getChildren();
if (!testProxy.isInProgress() && testProxy.equals(children.get(children.size() - 1))) {
parent.flush();
} else {
break;
}
testProxy = parent;
parent = parent.getParent();
}
}
@Override
public int getExceptionMark() {
if (myExceptionMark == 0 && getChildren().size() > 0) {
return getChildren().get(0).getExceptionMark();
}
return myExceptionMark;
}
}
@@ -15,42 +15,211 @@
*/
package com.intellij.execution.testframework;
import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.testframework.stacktrace.DiffHyperlink;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.io.IOUtil;
import org.jetbrains.annotations.NonNls;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class CompositePrintable implements Printable, Disposable {
public static final String NEW_LINE = "\n";
protected final ArrayList<Printable> myNestedPrintables = new ArrayList<Printable>();
protected final List<Printable> myNestedPrintables = new ArrayList<Printable>();
private PrintablesWrapper myWrapper;
protected int myExceptionMark;
public void flush() {
if (myWrapper == null) {
try {
myWrapper = new PrintablesWrapper(File.createTempFile("frst", "scd"));
}
catch (IOException ignored) {
}
}
if (myWrapper != null) {
synchronized (myNestedPrintables) {
myWrapper.flash(myNestedPrintables);
clear();
}
}
}
public void printOn(final Printer printer) {
printAllOn(myNestedPrintables, printer);
if (myWrapper != null) {
myWrapper.printOn(printer);
}
synchronized (myNestedPrintables) {
for (int i = 0; i < myNestedPrintables.size(); i++) {
if (i == getExceptionMark() && i > 0) printer.mark();
myNestedPrintables.get(i).printOn(printer);
}
}
}
public void addLast(final Printable printable) {
myNestedPrintables.add(printable);
synchronized (myNestedPrintables) {
myNestedPrintables.add(printable);
}
}
protected void clear() {
myNestedPrintables.clear();
synchronized (myNestedPrintables) {
myNestedPrintables.clear();
}
}
public int getCurrentSize() {
return myNestedPrintables.size();
}
public static <T extends Printable> void printAllOn(final List<T> printables, final Printer console) {
for (final T printable : printables) {
printable.printOn(console);
}
}
@Override
public void dispose() {
clear();
if (myWrapper != null) {
myWrapper.dispose();
}
}
public int getExceptionMark() {
return myExceptionMark;
}
public void setExceptionMark(int exceptionMark) {
myExceptionMark = exceptionMark;
}
private static final Logger LOG = Logger.getInstance("#" + PrintablesWrapper.class.getName());
private class PrintablesWrapper {
@NonNls private static final String HYPERLINK = "hyperlink";
private DataInputStream myReader;
private ConsoleViewContentType myLastSelected;
private final File myFile;
PrintablesWrapper(File file) {
myFile = file;
}
public void flash(List<Printable> printables) {
final DataOutputStream fileWriter;
try {
fileWriter = new DataOutputStream(new FileOutputStream(myFile, true));
}
catch (FileNotFoundException e) {
LOG.error(e);
return;
}
try {
for (final Printable printable : printables) {
printable.printOn(new Printer() {
@Override
public void print(String text, ConsoleViewContentType contentType) {
try {
IOUtil.writeString(contentType.toString() + text, fileWriter);
}
catch (IOException e) {
LOG.error(e);
}
}
@Override
public void onNewAvailable(Printable printable11) {
}
@Override
public void printHyperlink(String text, HyperlinkInfo info) {
if (info instanceof DiffHyperlink.DiffHyperlinkInfo) {
final DiffHyperlink diffHyperlink = ((DiffHyperlink.DiffHyperlinkInfo)info).getPrintable();
try {
IOUtil.writeString(HYPERLINK, fileWriter);
IOUtil.writeString(diffHyperlink.getLeft(), fileWriter);
IOUtil.writeString(diffHyperlink.getRight(), fileWriter);
IOUtil.writeString(diffHyperlink.getFilePath(), fileWriter);
}
catch (IOException e) {
LOG.error(e);
}
}
else {
print(text, ConsoleViewContentType.NORMAL_OUTPUT);
}
}
@Override
public void mark() {
}
});
}
}
finally {
try {
fileWriter.close();
}
catch (IOException e) {
LOG.error(e);
}
}
}
public void printOn(Printer console) {
try {
myReader = new DataInputStream(new FileInputStream(myFile));
int lineNum = 0;
while (myReader.available() > 0) {
if (lineNum == CompositePrintable.this.getExceptionMark() && lineNum > 0) console.mark();
final String line = IOUtil.readString(myReader);
if (!isApplicable(console, line, ConsoleViewContentType.ERROR_OUTPUT)) {
if (!isApplicable(console, line, ConsoleViewContentType.SYSTEM_OUTPUT)) {
if (!isApplicable(console, line, ConsoleViewContentType.NORMAL_OUTPUT)) {
if (line.startsWith(HYPERLINK)) {
new DiffHyperlink(IOUtil.readString(myReader), IOUtil.readString(myReader), IOUtil.readString(myReader)).printOn(console);
}
else {
console.print(line, myLastSelected != null ? myLastSelected : ConsoleViewContentType.NORMAL_OUTPUT);
}
}
}
}
lineNum++;
}
}
catch (IOException e) {
LOG.error(e);
}
finally {
try {
if (myReader != null) {
myReader.close();
}
}
catch (IOException e) {
LOG.error(e);
}
}
}
private boolean isApplicable(Printer console, String line, ConsoleViewContentType contentType) {
final String prefix = contentType.toString();
if (line.startsWith(prefix)) {
console.print(line.substring(prefix.length()), contentType);
myLastSelected = contentType;
return true;
}
return false;
}
public void dispose() {
FileUtil.delete(myFile);
}
}
}
@@ -38,11 +38,7 @@ public class DiffHyperlink implements Printable {
protected final String myExpected;
protected final String myActual;
protected final String myFilePath;
private final HyperlinkInfo myDiffHyperlink = new HyperlinkInfo() {
public void navigate(final Project project) {
openDiff(project);
}
};
private final HyperlinkInfo myDiffHyperlink = new DiffHyperlinkInfo();
public DiffHyperlink(final String expected, final String actual, final String filePath) {
@@ -80,6 +76,10 @@ public class DiffHyperlink implements Printable {
return myActual;
}
public String getFilePath() {
return myFilePath;
}
public void printOn(final Printer printer) {
if (hasMoreThanOneLine(myActual) || hasMoreThanOneLine(myExpected)) {
printer.print(" ", ConsoleViewContentType.ERROR_OUTPUT);
@@ -98,4 +98,14 @@ public class DiffHyperlink implements Printable {
private static boolean hasMoreThanOneLine(final String string) {
return string.indexOf('\n') != -1 || string.indexOf('\r') != -1;
}
public class DiffHyperlinkInfo implements HyperlinkInfo {
public void navigate(final Project project) {
openDiff(project);
}
public DiffHyperlink getPrintable() {
return DiffHyperlink.this;
}
}
}
@@ -31,11 +31,8 @@ import org.jetbrains.annotations.Nullable;
import java.beans.Introspector;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.DateFormat;
import java.util.*;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -1608,6 +1605,19 @@ public class StringUtil {
return "a" + Character.toUpperCase(c) + name.substring(1);
}
public static String sanitizeJavaIdentifier(String name) {
final StringBuilder result = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
final char ch = name.charAt(i);
if (Character.isLetterOrDigit(ch)) {
result.append(ch);
}
}
return result.toString();
}
public static void assertValidSeparators(@NotNull CharSequence s) {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '\r') {
@@ -72,7 +72,7 @@ public abstract class AbstractVcsHelper {
showErrors(Arrays.asList(e), s);
}
public abstract void showAnnotation(FileAnnotation annotation, VirtualFile file);
public abstract void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs);
public abstract void showDifferences(final VcsFileRevision cvsVersionOn, final VcsFileRevision cvsVersionOn1, final File file);
@@ -19,6 +19,7 @@ package com.intellij.openapi.vcs;
import com.intellij.openapi.vcs.changes.committed.DecoratorManager;
import com.intellij.openapi.vcs.changes.committed.VcsCommittedListsZipper;
import com.intellij.openapi.vcs.changes.committed.VcsCommittedViewAuxiliary;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
@@ -55,4 +56,7 @@ public interface CommittedChangesProvider<T extends CommittedChangeList, U exten
* since may be different for different VCSs
*/
int getUnlimitedCountValue();
@Nullable
T getOneList(final RepositoryLocation location, final VcsRevisionNumber number) throws VcsException;
}
@@ -15,9 +15,7 @@
*/
package com.intellij.openapi.vcs.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.ColorKey;
@@ -36,23 +34,32 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.annotate.*;
import com.intellij.openapi.vcs.changes.BackgroundFromStartOption;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.actions.ShowDiffAction;
import com.intellij.openapi.vcs.changes.ui.ChangesComparator;
import com.intellij.openapi.vcs.changes.ui.ChangesViewBalloonProblemNotifier;
import com.intellij.openapi.vcs.history.VcsFileRevision;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.impl.BackgroundableActionEnabledHandler;
import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl;
import com.intellij.openapi.vcs.impl.UpToDateLineNumberProviderImpl;
import com.intellij.openapi.vcs.impl.VcsBackgroundableActions;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.io.File;
import java.util.*;
import java.util.List;
@@ -152,7 +159,7 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware {
final VirtualFile file = FileDocumentManager.getInstance().getFile(editor.getDocument());
if (project == null) return;
final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstance(project);
AbstractVcs vcs = plVcsManager.getVcsFor(file);
final AbstractVcs vcs = plVcsManager.getVcsFor(file);
if (vcs == null) return;
final AnnotationProvider annotationProvider = vcs.getAnnotationProvider();
@@ -188,12 +195,16 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware {
}
if (fileAnnotationRef.isNull()) return;
doAnnotate(editor, project, file, fileAnnotationRef.get());
doAnnotate(editor, project, file, fileAnnotationRef.get(), vcs);
}
});
}
public static void doAnnotate(final Editor editor, final Project project, final VirtualFile file, final FileAnnotation fileAnnotation) {
public static void doAnnotate(final Editor editor,
final Project project,
final VirtualFile file,
final FileAnnotation fileAnnotation,
final AbstractVcs vcs) {
String upToDateContent = fileAnnotation.getAnnotatedContent();
final UpToDateLineNumberProvider getUpToDateLineNumber = new UpToDateLineNumberProviderImpl(
@@ -214,7 +225,14 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware {
final HighlightAnnotationsActions highlighting = new HighlightAnnotationsActions(project, file, fileAnnotation, editorGutterComponentEx);
final List<AnnotationFieldGutter> gutters = new ArrayList<AnnotationFieldGutter>();
final AnnotationSourceSwitcher switcher = fileAnnotation.getAnnotationSourceSwitcher();
final MyAnnotationPresentation presentation = new MyAnnotationPresentation(highlighting, switcher, editorGutterComponentEx, gutters);
final MyAnnotationPresentation presentation;
if (vcs.getCommittedChangesProvider() != null) {
final ShowDiffFromAnnotation showDiff = new ShowDiffFromAnnotation(getUpToDateLineNumber, fileAnnotation, vcs, file);
presentation = new MyAnnotationPresentation(highlighting, switcher, editorGutterComponentEx, gutters, showDiff);
presentation.addLineNumberListener(showDiff);
} else {
presentation = new MyAnnotationPresentation(highlighting, switcher, editorGutterComponentEx, gutters);
}
if (switcher != null) {
@@ -375,15 +393,25 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware {
private final List<AnnotationFieldGutter> myGutters;
private final List<AnAction> myActions;
private MySwitchAnnotationSourceAction mySwitchAction;
private final List<Consumer<Integer>> myPopupLineNumberListeners;
public MyAnnotationPresentation(@NotNull final HighlightAnnotationsActions highlighting, @Nullable final AnnotationSourceSwitcher switcher,
final EditorGutterComponentEx gutter,
List<AnnotationFieldGutter> gutters) {
final EditorGutterComponentEx gutter, final List<AnnotationFieldGutter> gutters, final AnAction... actions) {
myHighlighting = highlighting;
mySwitcher = switcher;
myGutters = gutters;
myPopupLineNumberListeners = new LinkedList<Consumer<Integer>>();
myActions = new ArrayList<AnAction>(myHighlighting.getList());
myActions = new ArrayList<AnAction>();
myActions.add(Separator.getInstance());
if (actions != null) {
final List<AnAction> actionsList = Arrays.<AnAction>asList(actions);
if (! actionsList.isEmpty()) {
myActions.addAll(actionsList);
myActions.add(new Separator());
}
}
myActions.addAll(myHighlighting.getList());
if (mySwitcher != null) {
mySwitchAction = new MySwitchAnnotationSourceAction(mySwitcher, gutter);
myActions.add(mySwitchAction);
@@ -391,6 +419,10 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware {
myActions.add(new ShowHideColorsAction(myGutters, gutter));
}
public void addLineNumberListener(final Consumer<Integer> listener) {
myPopupLineNumberListeners.add(listener);
}
public EditorFontType getFontType(final int line) {
return myHighlighting.isLineBold(line) ? EditorFontType.BOLD : EditorFontType.PLAIN;
}
@@ -400,7 +432,10 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware {
return mySwitcher.getAnnotationSource(line).getColor();
}
public List<AnAction> getActions() {
public List<AnAction> getActions(int line) {
for (Consumer<Integer> listener : myPopupLineNumberListeners) {
listener.consume(line);
}
return myActions;
}
@@ -443,4 +478,108 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware {
myGutter.revalidateMarkup();
}
}
private static class ShowDiffFromAnnotation extends AnAction implements Consumer<Integer> {
private final UpToDateLineNumberProvider myLineNumberProvider;
private final FileAnnotation myFileAnnotation;
private final AbstractVcs myVcs;
private final VirtualFile myFile;
private RepositoryLocation myLocationFor;
private int currentLine;
private ShowDiffFromAnnotation(final UpToDateLineNumberProvider lineNumberProvider,
final FileAnnotation fileAnnotation, final AbstractVcs vcs, final VirtualFile file) {
super(VcsBundle.message("updated.info.tree.show.diff.text"), VcsBundle.message("updated.info.tree.show.diff.text"), IconLoader.getIcon("/actions/diff.png"));
myLineNumberProvider = lineNumberProvider;
myFileAnnotation = fileAnnotation;
myVcs = vcs;
myFile = file;
final CommittedChangesProvider provider = myVcs.getCommittedChangesProvider();
final VirtualFile root = ProjectLevelVcsManager.getInstance(vcs.getProject()).getVcsRootFor(file);
myLocationFor = provider.getLocationFor(new FilePathImpl(root));
currentLine = -1;
}
@Override
public void consume(Integer integer) {
currentLine = integer;
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setVisible(getActualLineNumber(e) >= 0);
}
private int getActualLineNumber(final AnActionEvent e) {
final DataContext dc = e.getDataContext();
if (currentLine < 0) return -1;
return myLineNumberProvider.getLineNumber(currentLine);
}
@Override
public void actionPerformed(AnActionEvent e) {
final int actualNumber = getActualLineNumber(e);
if (actualNumber < 0) return;
final VcsRevisionNumber revisionNumber = myFileAnnotation.getLineRevisionNumber(actualNumber);
if (revisionNumber != null) {
final VcsException[] exc = new VcsException[1];
final List<Change> changes = new LinkedList<Change>();
ProgressManager.getInstance().run(new Task.Backgroundable(myVcs.getProject(),
"Loading revision " + revisionNumber.asString() + " contents", true, BackgroundFromStartOption.getInstance()) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
final CommittedChangesProvider provider = myVcs.getCommittedChangesProvider();
try {
final CommittedChangeList cl = provider.getOneList(myLocationFor, revisionNumber);
if (cl == null) {
ChangesViewBalloonProblemNotifier.showMe(myVcs.getProject(), "Can not load data for show diff", MessageType.ERROR);
return;
}
changes.addAll(cl.getChanges());
Collections.sort(changes, ChangesComparator.getInstance());
}
catch (VcsException e1) {
exc[0] = e1;
}
}
@Override
public void onSuccess() {
if (exc[0] != null) {
ChangesViewBalloonProblemNotifier.showMe(myVcs.getProject(), "Can not show diff: " + exc[0].getMessage(), MessageType.ERROR);
} else if (! changes.isEmpty()) {
int idx = findSelfInList(changes);
ShowDiffAction.showDiffForChange(changes.toArray(new Change[changes.size()]), idx, myVcs.getProject());
}
}
});
}
}
private int findSelfInList(List<Change> changes) {
int idx = -1;
final File ioFile = new File(myFile.getPath());
for (int i = 0; i < changes.size(); i++) {
final Change change = changes.get(i);
if ((change.getAfterRevision() != null) && (change.getAfterRevision().getFile().getIOFile().equals(ioFile))) {
idx = i;
break;
}
}
if (idx >= 0) return idx;
idx = 0;
// try to use name only
final String name = ioFile.getName();
for (int i = 0; i < changes.size(); i++) {
final Change change = changes.get(i);
if ((change.getAfterRevision() != null) && (change.getAfterRevision().getFile().getName().equals(name))) {
idx = i;
break;
}
}
return idx;
}
}
}
@@ -99,8 +99,8 @@ class AnnotationFieldGutter implements ActiveAnnotationGutter {
return myPresentation.getColor(line);
}
public List<AnAction> getPopupActions(final Editor editor) {
return myPresentation.getActions();
public List<AnAction> getPopupActions(int line, final Editor editor) {
return myPresentation.getActions(line);
}
public void gutterClosed() {
@@ -68,8 +68,8 @@ public class AnnotationGutterLineConvertorProxy implements ActiveAnnotationGutte
return myDelegate.getBgColor(currentLine, editor);
}
public List<AnAction> getPopupActions(Editor editor) {
return myDelegate.getPopupActions(editor);
public List<AnAction> getPopupActions(int line, Editor editor) {
return myDelegate.getPopupActions(line, editor);
}
public void gutterClosed() {
@@ -1,51 +0,0 @@
/*
* Copyright 2000-2009 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.vcs.annotate;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.actions.AnnotateToggleAction;
import com.intellij.openapi.vfs.VirtualFile;
public class Annotater {
private final Project myProject;
private final VirtualFile myVirtualFile;
private final FileAnnotation myFileAnnotation;
public Annotater(FileAnnotation fileAnnotation, Project project, VirtualFile virtualFile) {
myFileAnnotation = fileAnnotation;
myProject = project;
myVirtualFile = virtualFile;
}
public void showAnnotation() {
OpenFileDescriptor openFileDescriptor = new OpenFileDescriptor(myProject, myVirtualFile);
Editor editor = FileEditorManager.getInstance(myProject).openTextEditor(openFileDescriptor, true);
if (editor == null) {
Messages.showMessageDialog(VcsBundle.message("message.text.cannot.open.editor", myVirtualFile.getPresentableUrl()),
VcsBundle.message("message.title.cannot.open.editor"), Messages.getInformationIcon());
return;
}
AnnotateToggleAction.doAnnotate(editor, myProject, myVirtualFile, myFileAnnotation);
}
}
@@ -18,10 +18,11 @@ package com.intellij.openapi.vcs.annotate;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.editor.colors.ColorKey;
import com.intellij.openapi.editor.colors.EditorFontType;
import java.util.List;
public interface TextAnnotationPresentation {
EditorFontType getFontType(int line);
ColorKey getColor(int line);
List<AnAction> getActions();
List<AnAction> getActions(int line);
}
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes.committed;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsType;
import com.intellij.util.NotNullFunction;
import org.jetbrains.annotations.NotNull;
@@ -29,10 +30,10 @@ public class CommittedChangesVisibilityPredicate implements NotNullFunction<Proj
public Boolean fun(final Project project) {
final AbstractVcs[] abstractVcses = ProjectLevelVcsManager.getInstance(project).getAllActiveVcss();
for(AbstractVcs vcs: abstractVcses) {
if (vcs.getCommittedChangesProvider() != null) {
if (vcs.getCommittedChangesProvider() != null && VcsType.centralized.equals(vcs.getType())) {
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}
}
}
@@ -19,6 +19,7 @@ package com.intellij.openapi.vcs.changes.committed;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
@@ -151,6 +152,11 @@ public class CompositeCommittedChangesProvider implements CommittedChangesProvid
throw new UnsupportedOperationException();
}
@Override
public CommittedChangeList getOneList(RepositoryLocation location, VcsRevisionNumber number) {
throw new UnsupportedOperationException();
}
public static class CompositeChangeBrowserSettings extends ChangeBrowserSettings {
private final Map<AbstractVcs, ChangeBrowserSettings> myMap;
private final Set<AbstractVcs> myEnabledVcs = new HashSet<AbstractVcs>();
@@ -16,9 +16,10 @@
package com.intellij.openapi.vcs.changes.committed;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.CachingCommittedChangesProvider;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsType;
import com.intellij.util.NotNullFunction;
import org.jetbrains.annotations.NotNull;
@@ -30,7 +31,7 @@ public class IncomingChangesVisibilityPredicate implements NotNullFunction<Proje
public Boolean fun(final Project project) {
final AbstractVcs[] abstractVcses = ProjectLevelVcsManager.getInstance(project).getAllActiveVcss();
for(AbstractVcs vcs: abstractVcses) {
if (vcs.getCommittedChangesProvider() instanceof CachingCommittedChangesProvider) {
if (vcs.getCommittedChangesProvider() instanceof CachingCommittedChangesProvider && VcsType.centralized.equals(vcs.getType())) {
return Boolean.TRUE;
}
}
@@ -36,6 +36,7 @@ public class TableLinkMouseListener extends AbstractBaseTagMouseListener {
JTable table = (JTable)e.getSource();
int row = table.rowAtPoint(e.getPoint());
int column = table.columnAtPoint(e.getPoint());
if (row == -1 || column == -1) return null;
TableCellRenderer cellRenderer = table.getCellRenderer(row, column);
if (cellRenderer instanceof DualView.TableCellRendererWrapper) {
cellRenderer = ((DualView.TableCellRendererWrapper) cellRenderer).getRenderer();
@@ -111,7 +111,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
private String myOriginalComment = "";
private final DefaultActionGroup myPopupActions;
private final Project myProject;
private final AbstractVcs myVcs;
private final VcsHistoryProvider myProvider;
private final AnnotationProvider myAnnotationProvider;
private VcsHistorySession myHistorySession;
@@ -265,20 +265,20 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
private static final DateFormat DATE_FORMAT = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT);
private final Map<VcsFileRevision, VirtualFile> myRevisionToVirtualFile = new HashMap<VcsFileRevision, VirtualFile>();
public FileHistoryPanelImpl(Project project,
FilePath filePath, final String repositoryPath, VcsHistorySession session,
public FileHistoryPanelImpl(AbstractVcs vcs,
FilePath filePath, VcsHistorySession session,
VcsHistoryProvider provider,
AnnotationProvider annotationProvider,
ContentManager contentManager, final Runnable refresher) {
super(contentManager, provider.getHelpId() != null ? provider.getHelpId() : "reference.versionControl.toolwindow.history");
myVcs = vcs;
myProvider = provider;
myAnnotationProvider = annotationProvider;
myProject = project;
myRefresher = refresher;
myHistorySession = session;
myFilePath = filePath;
COLUMNS = createColumnList(project, provider, session);
COLUMNS = createColumnList(myVcs.getProject(), provider, session);
myComments = new JEditorPane(UIUtil.HTML_MIME, "");
myComments.setPreferredSize(new Dimension(150, 100));
@@ -298,11 +298,11 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
@NonNls String storageKey = "FileHistory." + provider.getClass().getName();
if (treeHistoryProvider != null) {
myDualView = new DualView(new TreeNodeOnVcsRevision(null, treeHistoryProvider.createTreeOn(myHistorySession.getRevisionList())),
COLUMNS, storageKey, project);
COLUMNS, storageKey, myVcs.getProject());
}
else {
myDualView = new DualView(new TreeNodeOnVcsRevision(null, wrapWithTreeElements(myHistorySession.getRevisionList())), COLUMNS,
storageKey, project);
storageKey, myVcs.getProject());
myDualView.switchToTheFlatMode();
}
final TableLinkMouseListener listener = new TableLinkMouseListener();
@@ -330,7 +330,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
// todo react to event?
myUpdateAlarm.addRequest(new Runnable() {
public void run() {
if (myProject.isDisposed()) {
if (myVcs.getProject().isDisposed()) {
return;
}
final boolean refresh = (! myInRefresh) && myHistorySession.shouldBeRefreshed();
@@ -556,7 +556,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
revision = getFirstSelectedRevision();
final String message = revision.getCommitMessage();
myOriginalComment = message;
@NonNls final String text = IssueLinkHtmlRenderer.formatTextIntoHtml(myProject, message);
@NonNls final String text = IssueLinkHtmlRenderer.formatTextIntoHtml(myVcs.getProject(), message);
myComments.setText(text);
myComments.setCaretPosition(0);
}
@@ -584,7 +584,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
if (content2 == null) throw new VcsException("Failed to load content for revision " + right.getRevisionNumber().asString());
SimpleDiffRequest diffData = new SimpleDiffRequest(myProject, myFilePath.getPresentableUrl());
SimpleDiffRequest diffData = new SimpleDiffRequest(myVcs.getProject(), myFilePath.getPresentableUrl());
diffData.addHint(DiffTool.HINT_SHOW_FRAME);
@@ -693,7 +693,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
}
private VcsConfiguration getConfiguration() {
return VcsConfiguration.getInstance(myProject);
return VcsConfiguration.getInstance(myVcs.getProject());
}
private DefaultActionGroup createPopupActions() {
@@ -757,7 +757,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
}
private void refreshImpl() {
new AbstractCalledLater(myProject, ModalityState.NON_MODAL) {
new AbstractCalledLater(myVcs.getProject(), ModalityState.NON_MODAL) {
public void run() {
if (myInRefresh) return;
myInRefresh = true;
@@ -806,12 +806,12 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
int selectionSize = sel.size();
if (selectionSize > 1) {
showDifferences(myProject, sel.get(0), sel.get(sel.size() - 1));
showDifferences(myVcs.getProject(), sel.get(0), sel.get(sel.size() - 1));
}
else if (selectionSize == 1) {
final VcsRevisionNumber currentRevisionNumber = myHistorySession.getCurrentRevisionNumber();
if (currentRevisionNumber != null) {
showDifferences(myProject, getFirstSelectedRevision(), new CurrentRevision(myFilePath.getVirtualFile(), currentRevisionNumber));
showDifferences(myVcs.getProject(), getFirstSelectedRevision(), new CurrentRevision(myFilePath.getVirtualFile(), currentRevisionNumber));
}
}
}
@@ -880,7 +880,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
protected void actionPerformed() {
final VcsFileRevision revision = getFirstSelectedRevision();
if (getVirtualFile() != null) {
if (!new ReplaceFileConfirmationDialog(myProject, VcsBundle.message("acton.name.get.revision"))
if (!new ReplaceFileConfirmationDialog(myVcs.getProject(), VcsBundle.message("acton.name.get.revision"))
.confirmFor(new VirtualFile[]{getVirtualFile()})) {
return;
}
@@ -926,14 +926,14 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
};
}
if (refresh != null) {
ProgressManager.getInstance().runProcessWithProgressSynchronously(refresh, "Refreshing files...", false, myProject);
ProgressManager.getInstance().runProcessWithProgressSynchronously(refresh, "Refreshing files...", false, myVcs.getProject());
}
}
private void getVersion(final VcsFileRevision revision) {
final VirtualFile file = getVirtualFile();
if ((file != null) && !file.isWritable()) {
if (ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(file).hasReadonlyFiles()) {
if (ReadonlyStatusHandler.getInstance(myVcs.getProject()).ensureFilesWritable(file).hasReadonlyFiles()) {
return;
}
}
@@ -961,7 +961,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
try {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
CommandProcessor.getInstance().executeCommand(myVcs.getProject(), new Runnable() {
public void run() {
try {
write(finalRevisionContent);
@@ -975,7 +975,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
}
});
if (file != null) {
VcsDirtyScopeManager.getInstance(myProject).fileDirty(file);
VcsDirtyScopeManager.getInstance(myVcs.getProject()).fileDirty(file);
}
}
finally {
@@ -1027,7 +1027,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
private void writeContentToDocument(final Document document, byte[] revisionContent) throws IOException {
final String content = StringUtil.convertLineSeparators(new String(revisionContent, myFilePath.getCharset().name()));
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
CommandProcessor.getInstance().executeCommand(myVcs.getProject(), new Runnable() {
public void run() {
document.replaceString(0, document.getTextLength(), content);
}
@@ -1053,7 +1053,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
boolean enabled = revision != null && revVFile != null && !fileType.isBinary();
if (enabled) {
final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstance(myProject);
final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstance(myVcs.getProject());
enabled &= (! (((ProjectLevelVcsManagerImpl) plVcsManager).getBackgroundableActionHandler(
VcsBackgroundableActions.ANNOTATE).isInProgress(key(revVFile, revision))));
}
@@ -1070,14 +1070,14 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
final VirtualFile revisionVirtualFile = e.getData(VcsDataKeys.VCS_VIRTUAL_FILE);
if ((revision == null) || (revisionVirtualFile == null)) return;
final BackgroundableActionEnabledHandler handler = ((ProjectLevelVcsManagerImpl) ProjectLevelVcsManager.getInstance(myProject)).
final BackgroundableActionEnabledHandler handler = ((ProjectLevelVcsManagerImpl) ProjectLevelVcsManager.getInstance(myVcs.getProject())).
getBackgroundableActionHandler(VcsBackgroundableActions.ANNOTATE);
handler.register(key(revisionVirtualFile, revision));
final Ref<FileAnnotation> fileAnnotationRef = new Ref<FileAnnotation>();
final Ref<VcsException> exceptionRef = new Ref<VcsException>();
ProgressManager.getInstance().run(new Task.Backgroundable(myProject, VcsBundle.message("retrieving.annotations"), true,
ProgressManager.getInstance().run(new Task.Backgroundable(myVcs.getProject(), VcsBundle.message("retrieving.annotations"), true,
BackgroundFromStartOption.getInstance()) {
public void run(@NotNull ProgressIndicator indicator) {
try {
@@ -1102,7 +1102,7 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
}
if (fileAnnotationRef.isNull()) return;
AbstractVcsHelper.getInstance(myProject).showAnnotation(fileAnnotationRef.get(), revisionVirtualFile);
AbstractVcsHelper.getInstance(myProject).showAnnotation(fileAnnotationRef.get(), revisionVirtualFile, myVcs);
}
});
}
@@ -1118,14 +1118,14 @@ public class FileHistoryPanelImpl<S extends CommittedChangeList, U extends Chang
}
VirtualFile virtualFileForRevision = createVirtualFileForRevision(firstSelectedRevision);
if (virtualFileForRevision != null) {
return new OpenFileDescriptor(myProject, virtualFileForRevision);
return new OpenFileDescriptor(myVcs.getProject(), virtualFileForRevision);
}
else {
return null;
}
}
else if (PlatformDataKeys.PROJECT.is(dataId)) {
return myProject;
return myVcs.getProject();
}
else if (VcsDataKeys.VCS_FILE_REVISION.is(dataId)) {
return firstSelectedRevision;
@@ -27,7 +27,10 @@ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.*;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -41,7 +44,7 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.annotate.Annotater;
import com.intellij.openapi.vcs.actions.AnnotateToggleAction;
import com.intellij.openapi.vcs.annotate.AnnotationProvider;
import com.intellij.openapi.vcs.annotate.FileAnnotation;
import com.intellij.openapi.vcs.changes.BackgroundFromStartOption;
@@ -160,7 +163,7 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper {
private FileHistoryPanelImpl ensureHistoryPanelCreated() {
if (myFileHistoryPanel == null) {
ContentManager contentManager = ProjectLevelVcsManagerEx.getInstanceEx(myVcs.getProject()).getContentManager();
myFileHistoryPanel = new FileHistoryPanelImpl(myVcs.getProject(), myPath, myRepositoryPath, mySession, myVcsHistoryProvider,
myFileHistoryPanel = new FileHistoryPanelImpl(myVcs, myPath, mySession, myVcsHistoryProvider,
myAnnotationProvider, contentManager, myRefresher);
}
return myFileHistoryPanel;
@@ -436,8 +439,16 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper {
return exceptions;
}
public void showAnnotation(FileAnnotation annotation, VirtualFile file) {
new Annotater(annotation, myProject, file).showAnnotation();
public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs) {
OpenFileDescriptor openFileDescriptor = new OpenFileDescriptor(myProject, file);
Editor editor = FileEditorManager.getInstance(myProject).openTextEditor(openFileDescriptor, true);
if (editor == null) {
Messages.showMessageDialog(VcsBundle.message("message.text.cannot.open.editor", file.getPresentableUrl()),
VcsBundle.message("message.title.cannot.open.editor"), Messages.getInformationIcon());
return;
}
AnnotateToggleAction.doAnnotate(editor, myProject, file, annotation, vcs);
}
public void showDifferences(final VcsFileRevision version1, final VcsFileRevision version2, final File file) {
@@ -130,6 +130,41 @@ public class CvsCommittedChangesProvider implements CachingCommittedChangesProvi
return 0;
}
@Nullable
@Override
public CvsChangeList getOneList(RepositoryLocation location, final VcsRevisionNumber number) throws VcsException {
CvsRepositoryLocation cvsLocation = (CvsRepositoryLocation) location;
final String module = cvsLocation.getModuleName();
final CvsEnvironment connectionSettings = cvsLocation.getEnvironment();
if (connectionSettings.isOffline()) {
return null;
}
final CvsChangeListsBuilder builder = new CvsChangeListsBuilder(module, connectionSettings, myProject, cvsLocation.getRootFile());
final CvsChangeList[] result = new CvsChangeList[1];
final CvsResult executionResult = runRLogOperation(connectionSettings, module, new Date(1000), null, new Consumer<LogInformationWrapper>() {
public void consume(LogInformationWrapper wrapper) {
if (result[0] != null) return;
final List<RevisionWrapper> wrappers = builder.revisionWrappersFromLog(wrapper);
if (wrappers != null) {
for (RevisionWrapper revisionWrapper : wrappers) {
if (Comparing.equal(revisionWrapper.getRevision().getNumber(), number.asString())) {
result[0] = builder.addRevision(revisionWrapper);
}
}
}
}
});
if (executionResult.isCanceled()) {
throw new ProcessCanceledException();
}
else if (! executionResult.hasNoErrors()) {
throw executionResult.composeError();
}
return result[0];
}
public List<CvsChangeList> getCommittedChanges(ChangeBrowserSettings settings, RepositoryLocation location, final int maxCount) throws VcsException {
CvsRepositoryLocation cvsLocation = (CvsRepositoryLocation) location;
return loadCommittedChanges(settings, cvsLocation.getModuleName(), cvsLocation.getEnvironment(), cvsLocation.getRootFile());
@@ -172,9 +172,10 @@ public class BrowserPanel extends JPanel implements DataProvider, CvsTabbedWindo
public void actionPerformed(AnActionEvent e) {
VcsVirtualFile vcsVirtualFile = (VcsVirtualFile)getCvsVirtualFile();
try {
final FileAnnotation annotation = CvsVcs2.getInstance(myProject)
final CvsVcs2 vcs = CvsVcs2.getInstance(myProject);
final FileAnnotation annotation = vcs
.createAnnotation(vcsVirtualFile, vcsVirtualFile.getRevision(), myCvsRootConfiguration);
AbstractVcsHelper.getInstance(myProject).showAnnotation(annotation, vcsVirtualFile);
AbstractVcsHelper.getInstance(myProject).showAnnotation(annotation, vcsVirtualFile, vcs);
}
catch (VcsException e1) {
AbstractVcsHelper.getInstance(myProject).showError(e1, CvsBundle.message("operation.name.annotate"));
@@ -171,7 +171,7 @@ public class CvsHistoryProvider implements VcsHistoryProvider {
@Nullable
public VcsRevisionNumber calcCurrentRevisionNumber() {
return getCurrentRevision(myFilePath);
return myFilePath == null ? null : getCurrentRevision(myFilePath);
}
@Override
+1 -2
View File
@@ -338,8 +338,7 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
*/
@Override
public CommittedChangesProvider getCommittedChangesProvider() {
// TODO Temporary disabled: return myCommittedChangeListProvider;
return null;
return myCommittedChangeListProvider;
}
/**
@@ -49,7 +49,7 @@ import java.util.List;
/**
* The provider for committed change lists
*/
public class GitCommittedChangeListProvider implements CachingCommittedChangesProvider<CommittedChangeList, ChangeBrowserSettings> {
public class GitCommittedChangeListProvider implements CommittedChangesProvider<CommittedChangeList, ChangeBrowserSettings> {
/**
* the logger
*/
@@ -224,6 +224,29 @@ public class GitCommittedChangeListProvider implements CachingCommittedChangesPr
return -1;
}
@Override
public CommittedChangeList getOneList(RepositoryLocation location, final VcsRevisionNumber number) throws VcsException {
final GitRepositoryLocation l = (GitRepositoryLocation)location;
VirtualFile root = LocalFileSystem.getInstance().findFileByIoFile(l.getRoot());
if (root == null) {
throw new VcsException("The repository does not exists anymore: " + l.getRoot());
}
final CommittedChangeList[] result = new CommittedChangeList[1];
GitUtil.getLocalCommittedChanges(myProject, root, new Consumer<GitSimpleHandler>() {
public void consume(GitSimpleHandler h) {
h.addParameters("-n1");
h.addParameters(number.asString());
}
}, new Consumer<CommittedChangeList>() {
@Override
public void consume(CommittedChangeList committedChangeList) {
result[0] = committedChangeList;
}
}, false);
return result[0];
}
public int getFormatVersion() {
return 0;
}
@@ -155,20 +155,25 @@ public class GitProjectLogManager {
content.setCloseable(false);
cvcm.addContent(content);
newKeys.put(root, content);
new CalculateContinuation<String>().calculateAndContinue(new ThrowableComputable<String, Exception>() {
public String compute() throws Exception {
return getCaption(baseDir, root);
new AbstractCalledLater(myProject, ModalityState.NON_MODAL) {
@Override
public void run() {
new CalculateContinuation<String>().calculateAndContinue(new ThrowableComputable<String, Exception>() {
public String compute() throws Exception {
return getCaption(baseDir, root);
}
}, new CatchingConsumer<String, Exception>() {
public void consume(Exception e) {
//should not
LOG.info(e);
}
public void consume(final String caption) {
content.setDisplayName(caption);
}
});
}
}, new CatchingConsumer<String, Exception>() {
public void consume(Exception e) {
//should not
LOG.info(e);
}
public void consume(final String caption) {
content.setDisplayName(caption);
}
});
}.callMe();
}
}
@@ -44,6 +44,7 @@ public class GroovyImportOptimizerRefactoringHelper implements RefactoringHelper
public Set<GroovyFile> prepareOperation(UsageInfo[] usages) {
Set<GroovyFile> files = new HashSet<GroovyFile>();
for (UsageInfo usage : usages) {
if (usage.isNonCodeUsage) continue;
final PsiElement element = usage.getElement();
if (element != null) {
final PsiFile file = element.getContainingFile();
@@ -268,4 +268,18 @@ public class HgCachingCommitedChangesProvider
public int getUnlimitedCountValue() {
return -1;
}
@Override
public CommittedChangeList getOneList(RepositoryLocation location, VcsRevisionNumber number) throws VcsException {
final ChangeBrowserSettings settings = createDefaultSettings();
settings.USE_CHANGE_AFTER_FILTER = true;
settings.USE_CHANGE_BEFORE_FILTER = true;
settings.CHANGE_AFTER = number.asString();
settings.CHANGE_BEFORE = number.asString();
final List<CommittedChangeList> list = getCommittedChanges(settings, location, 1);
if (list.size() == 1) {
return list.get(0);
}
return null;
}
}
@@ -265,7 +265,7 @@ public abstract class TestObject implements JavaCommandLine {
consoleView.initUI();
consoleView.attachToProcess(handler);
unboundOutputRoot.setPrinter(consoleView.getPrinter());
Disposer.register(consoleView, unboundOutputRoot);
final TestsPacketsReceiver packetsReceiver = new TestsPacketsReceiver(consoleView) {
@Override
public void notifyStart(TestProxy root) {
@@ -232,6 +232,7 @@ public class TestsPacketsReceiver implements PacketProcessor, Disposable {
}
static void complete(TestProxy testProxy) {
testProxy.flush();
final int magnitude = testProxy.getState().getMagnitude();
TestProxy parent = testProxy.getParent();
@@ -240,8 +241,9 @@ public class TestsPacketsReceiver implements PacketProcessor, Disposable {
final List<TestProxy> children = parent.getChildren();
final TestState parentState = parent.getState();
LOG.assertTrue(parentState instanceof SuiteState);
if (child.equals(children.get(children.size() - 1))) {
if (!child.isInProgress() && child.equals(children.get(children.size() - 1))) {
((SuiteState)parentState).setRunning(false);
parent.flush();
}
((SuiteState)parentState).updateMagnitude(magnitude);
child = parent;
@@ -24,4 +24,6 @@ public interface MavenFacadeLogger extends Remote {
void warn(Throwable e) throws RemoteException;
void error(Throwable e) throws RemoteException;
void print(String s) throws RemoteException;
}
@@ -0,0 +1,57 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.maven.facade.embedder;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.metadata.*;
import org.jetbrains.idea.maven.model.MavenId;
import java.io.File;
import java.util.List;
import java.util.Map;
public class CustomRepositoryMetadataManager extends DefaultRepositoryMetadataManager {
private Map<MavenId, File> myProjectIdToFileMap;
public void customize(Map<MavenId, File> projectIdToFileMap) {
myProjectIdToFileMap = projectIdToFileMap;
}
public void reset() {
myProjectIdToFileMap = null;
}
@Override
public void resolve(RepositoryMetadata metadata, List remoteRepositories, ArtifactRepository localRepository)
throws RepositoryMetadataResolutionException {
super.resolve(metadata, remoteRepositories, localRepository);
Map<MavenId, File> map = myProjectIdToFileMap;
if (map == null) return;
Metadata data = metadata.getMetadata();
Versioning versioning = data.getVersioning();
if (versioning == null) {
data.setVersioning(versioning = new Versioning());
}
for (MavenId each : map.keySet()) {
if (each.equals(data.getGroupId(), data.getArtifactId())) {
versioning.addVersion(each.getVersion());
}
}
}
}
@@ -24,8 +24,10 @@ import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.InvalidRepositoryException;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.manager.WagonManager;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolver;
@@ -554,6 +556,7 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade
MavenEmbedder.setImplementation(c, ArtifactFactory.class, CustomArtifactFactory.class);
MavenEmbedder.setImplementation(c, ProjectArtifactFactory.class, CustomArtifactFactory.class);
MavenEmbedder.setImplementation(c, ArtifactResolver.class, CustomArtifactResolver.class);
MavenEmbedder.setImplementation(c, RepositoryMetadataManager.class, CustomRepositoryMetadataManager.class);
MavenEmbedder.setImplementation(c, WagonManager.class, CustomWagonManager.class);
MavenEmbedder.setImplementation(c, ModelInterpolator.class, CustomModelInterpolator.class);
}
@@ -580,6 +583,7 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade
((CustomArtifactFactory)getComponent(ArtifactFactory.class)).customize();
((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).customize();
((CustomArtifactResolver)getComponent(ArtifactResolver.class)).customize(projectIdToFileMap, strict);
((CustomRepositoryMetadataManager)getComponent(RepositoryMetadataManager.class)).customize(projectIdToFileMap);
((CustomWagonManager)getComponent(WagonManager.class)).customize(strict);
setConsoleAndLogger(logger, process);
@@ -604,6 +608,7 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade
((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).reset();
((CustomArtifactFactory)getComponent(ArtifactFactory.class)).reset();
((CustomArtifactResolver)getComponent(ArtifactResolver.class)).reset();
((CustomRepositoryMetadataManager)getComponent(RepositoryMetadataManager.class)).reset();
((CustomWagonManager)getComponent(WagonManager.class)).reset();
}
catch (Exception e) {
@@ -53,4 +53,13 @@ public class MavenFacadeLoggerWrapper {
throw new RuntimeException(e1);
}
}
public void print(String o) {
try {
myWrappee.print(o);
}
catch (RemoteException e1) {
throw new RuntimeException(e1);
}
}
}
@@ -168,6 +168,7 @@ public class MavenFacadeManager {
}
}
params.getVMParametersList().addParametersString("-Djava.awt.headless=true -Xmx512m");
//params.getVMParametersList().addParametersString("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5009");
return params;
}
@@ -346,6 +347,10 @@ public class MavenFacadeManager {
public void error(Throwable e) {
MavenLog.LOG.error(e);
}
public void print(String s) {
System.out.println(s);
}
}
private static class RemoteMavenFacadeDownloadListener extends RemoteObject implements MavenFacadeDownloadListener {
@@ -187,7 +187,7 @@ public class DependenciesImportingTest extends MavenImportingTestCase {
assertModuleLibDeps("project", "Maven: group:lib:1");
}
public void testIntermoduleDependencies() throws Exception {
public void testInterModuleDependencies() throws Exception {
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
"<packaging>pom</packaging>" +
@@ -196,7 +196,6 @@ public class DependenciesImportingTest extends MavenImportingTestCase {
"<modules>" +
" <module>m1</module>" +
" <module>m2</module>" +
" <module>m3</module>" +
"</modules>");
createModulePom("m1", "<groupId>test</groupId>" +
@@ -259,6 +258,72 @@ public class DependenciesImportingTest extends MavenImportingTestCase {
assertModuleModuleDeps("m1", "m2");
}
public void testInterModuleDependenciesWithVersionRanges() throws Exception {
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
"<packaging>pom</packaging>" +
"<version>1</version>" +
"<modules>" +
" <module>m1</module>" +
" <module>m2</module>" +
"</modules>");
createModulePom("m1", "<groupId>test</groupId>" +
"<artifactId>m1</artifactId>" +
"<version>1</version>" +
"<dependencies>" +
" <dependency>" +
" <groupId>test</groupId>" +
" <artifactId>m2</artifactId>" +
" <version>[1, 2]</version>" +
" </dependency>" +
"</dependencies>");
createModulePom("m2", "<groupId>test</groupId>" +
"<artifactId>m2</artifactId>" +
"<version>1</version>");
importProject();
assertModules("project", "m1", "m2");
assertModuleModuleDeps("m1", "m2");
}
public void testInterSnapshotModuleDependenciesWithVersionRanges() throws Exception {
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
"<packaging>pom</packaging>" +
"<version>1</version>" +
"<modules>" +
" <module>m1</module>" +
" <module>m2</module>" +
"</modules>");
createModulePom("m1", "<groupId>test</groupId>" +
"<artifactId>m1</artifactId>" +
"<version>1</version>" +
"<dependencies>" +
" <dependency>" +
" <groupId>test</groupId>" +
" <artifactId>m2</artifactId>" +
" <version>[, 1-SNAPSHOT]</version>" +
" </dependency>" +
"</dependencies>");
createModulePom("m2", "<groupId>test</groupId>" +
"<artifactId>m2</artifactId>" +
"<version>1-SNAPSHOT</version>");
importProject();
assertModules("project", "m1", "m2");
assertModuleModuleDeps("m1", "m2");
}
public void testInterModuleDependenciesWithoutModuleGroup() throws Exception {
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
@@ -39,17 +39,17 @@ import com.intellij.util.ThrowableConsumer;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnAuthenticationNotifier;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.actions.ConfigureBranchesAction;
import org.tmatesoft.svn.core.ISVNLogEntryHandler;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNInfo;
import org.tmatesoft.svn.core.wc.SVNLogClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNWCClient;
import java.io.DataInput;
import java.io.DataOutput;
@@ -490,6 +490,106 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi
return 0;
}
@Override
public SvnChangeList getOneList(final RepositoryLocation location, VcsRevisionNumber number) throws VcsException {
final String url = ((SvnRepositoryLocation)location).getURL();
final long revision;
try {
revision = Long.parseLong(number.asString());
} catch (NumberFormatException e) {
throw new VcsException(e);
}
final SvnChangeList[] result = new SvnChangeList[1];
final SVNLogClient logger;
final SVNRevision revisionBefore;
final SVNURL repositoryUrl;
final SVNURL svnurl;
try {
logger = myVcs.createLogClient();
revisionBefore = SVNRevision.create(revision);
svnurl = SVNURL.parseURIEncoded(url);
final SVNWCClient client = myVcs.createWCClient();
SVNInfo info = client.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
if (info == null) {
throw new VcsException("Can not get repository URL");
}
repositoryUrl = info.getRepositoryRootURL();
}
catch (SVNException e) {
throw new VcsException(e);
}
tryExactHit((SvnRepositoryLocation)location, result, logger, revisionBefore, repositoryUrl, svnurl);
if (result[0] == null) {
tryByRoot(result, logger, revisionBefore, repositoryUrl);
if (result[0] == null) {
tryStepByStep((SvnRepositoryLocation)location, result, logger, revisionBefore, repositoryUrl, svnurl);
}
}
return result[0];
}
private void tryByRoot(SvnChangeList[] result, SVNLogClient logger, SVNRevision revisionBefore, SVNURL repositoryUrl) throws VcsException {
final boolean authorized = SvnAuthenticationNotifier.passiveValidation(myProject, repositoryUrl);
if (! authorized) return;
tryExactHit(new SvnRepositoryLocation(repositoryUrl.toString()), result, logger, revisionBefore, repositoryUrl, repositoryUrl);
}
private void tryStepByStep(final SvnRepositoryLocation svnRepositoryLocation,
final SvnChangeList[] result,
SVNLogClient logger,
final SVNRevision revisionBefore, final SVNURL repositoryUrl, SVNURL svnurl) throws VcsException {
try {
logger.doLog(svnurl, null, SVNRevision.UNDEFINED, SVNRevision.HEAD, revisionBefore,
false, true, true, 0, null,
new ISVNLogEntryHandler() {
public void handleLogEntry(SVNLogEntry logEntry) {
if (myProject.isDisposed()) throw new ProcessCanceledException();
if (logEntry.getDate() == null) {
// do not add lists without info - this situation is possible for lists where there are paths that user has no rights to observe
return;
}
if (logEntry.getRevision() == revisionBefore.getNumber()) {
result[0] = new SvnChangeList(myVcs, svnRepositoryLocation, logEntry, repositoryUrl.toString());
}
}
});
}
catch (SVNException e) {
throw new VcsException(e);
}
}
private void tryExactHit(final SvnRepositoryLocation location,
final SvnChangeList[] result,
SVNLogClient logger,
SVNRevision revisionBefore,
final SVNURL repositoryUrl, SVNURL svnurl) throws VcsException {
try {
logger.doLog(svnurl, null, SVNRevision.UNDEFINED, revisionBefore, revisionBefore,
false, true, false, 1, null,
new ISVNLogEntryHandler() {
public void handleLogEntry(SVNLogEntry logEntry) {
if (myProject.isDisposed()) throw new ProcessCanceledException();
if (logEntry.getDate() == null) {
// do not add lists without info - this situation is possible for lists where there are paths that user has no rights to observe
return;
}
result[0] = new SvnChangeList(myVcs, (SvnRepositoryLocation) location, logEntry, repositoryUrl.toString());
}
});
}
catch (SVNException e) {
if (SVNErrorCode.FS_CATEGORY == e.getErrorMessage().getErrorCode().getCategory()) {
// pass to step by step looking for revision
return;
}
throw new VcsException(e);
}
}
public int getFormatVersion() {
return VERSION_WITH_REPLACED_PATHS;
}
Binary file not shown.
Binary file not shown.
@@ -49,6 +49,7 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
@@ -131,6 +132,7 @@ public class TestNGRunnableState extends JavaCommandLineState {
executor);
console.initUI();
unboundOutputRoot.setPrinter(console.getPrinter());
Disposer.register(console, unboundOutputRoot);
for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
ext.handleStartProcess(config, processHandler);
}
@@ -46,6 +46,7 @@ public class TestNGRemoteListener implements IRemoteSuiteListener, IRemoteTestLi
}
public void onFinish(SuiteMessage suiteMessage) {
unboundOutputRoot.flush();
console.finish();
final TestNGResults view = console.getResultsView();
if (view != null) {
@@ -17,26 +17,18 @@ package com.theoryinpractice.testng.model;
import com.intellij.execution.Location;
import com.intellij.execution.PsiLocation;
import com.intellij.execution.stacktrace.StackTraceLine;
import com.intellij.execution.testframework.AbstractTestProxy;
import com.intellij.execution.testframework.Filter;
import com.intellij.execution.testframework.Printable;
import com.intellij.execution.testframework.Printer;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.ide.util.EditSourceUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diff.LineTokenizer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.pom.Navigatable;
import com.intellij.psi.*;
import com.theoryinpractice.testng.ui.TestNGConsoleView;
import org.jetbrains.annotations.Nullable;
import org.testng.remote.strprotocol.MessageHelper;
import org.testng.remote.strprotocol.TestResultMessage;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
@@ -49,7 +41,6 @@ public class TestProxy extends AbstractTestProxy {
private TestProxy parent;
private SmartPsiElementPointer psiElement;
private boolean inProgress;
private int myExceptionMark;
private boolean myTearDownFailure;
public TestProxy() {}
@@ -220,24 +211,6 @@ public class TestProxy extends AbstractTestProxy {
return null;
}
public int getExceptionMark() {//todo
if (myExceptionMark == 0 && getChildCount() > 0) {
return getChildAt(0).getExceptionMark();
}
return myExceptionMark;
}
public void setExceptionMark(int exceptionMark) {
myExceptionMark = exceptionMark;
}
@Override
public void printOn(Printer printer) {
for (int i = 0; i < myNestedPrintables.size(); i++) {
if (i == myExceptionMark && i > 0) printer.mark();
myNestedPrintables.get(i).printOn(printer);
}
}
public boolean isInterrupted() {
return !isInProgress() && inProgress;
@@ -109,19 +109,20 @@ public class TestNGConsoleView extends BaseTestsOutputConsoleView {
if (testNGResults != null) {
int exceptionMark = myExceptionalMark == -1 ? 0 : myExceptionalMark;
final String stackTrace = result.getStackTrace();
if (stackTrace != null && stackTrace.length() > 10) {
exceptionMark = currentTest.getCurrentSize();
//trim useless crud from stacktrace
String trimmed = trimStackTrace(stackTrace);
List<Printable> printables = getPrintables(result, trimmed);
for (Printable printable : printables) {
currentTest.addLast(printable);
if (currentTest != null) {
final String stackTrace = result.getStackTrace();
if (stackTrace != null && stackTrace.length() > 10) {
exceptionMark = currentTest.getCurrentSize();
//trim useless crud from stacktrace
List<Printable> printables = getPrintables(result);
for (Printable printable : printables) {
currentTest.addLast(printable);
}
}
final TestProxy failedToStart = testNGResults.getFailedToStart();
if (failedToStart != null) {
currentTest.addChild(failedToStart);
}
}
final TestProxy failedToStart = testNGResults.getFailedToStart();
if (failedToStart != null) {
currentTest.addChild(failedToStart);
}
testNGResults.addTestResult(result, exceptionMark);
myExceptionalMark = -1;
@@ -166,7 +167,8 @@ public class TestNGConsoleView extends BaseTestsOutputConsoleView {
return builder.toString();
}
private List<Printable> getPrintables(final TestResultMessage result, String s) {
static List<Printable> getPrintables(final TestResultMessage result) {
String s = trimStackTrace(result.getStackTrace());
List<Printable> printables = new ArrayList<Printable>();
//figure out if we have a diff we need to hyperlink
Matcher matcher = COMPARISION_PATTERN.matcher(s);
@@ -56,7 +56,6 @@ import java.awt.event.MouseEvent;
import java.text.NumberFormat;
import java.util.*;
import java.util.List;
import java.util.regex.Pattern;
public class TestNGResults extends TestResultsPanel implements TestFrameworkRunningModel {
@NonNls private static final String TESTNG_SPLITTER_PROPERTY = "TestNG.Splitter.Proportion";
@@ -242,10 +241,18 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn
else {
//do not remember testresultmessage: test hierarchy is not set
testCase = new TestProxy(result.toDisplayString());
final String stackTrace = result.getStackTrace();
if (stackTrace != null) {
final List<Printable> printables = TestNGConsoleView.getPrintables(result);
for (Printable printable : printables) {
testCase.addLast(printable);
}
}
failedToStart = testCase;
}
testCase.setExceptionMark(exceptionMark);
AbstractTestProxy.flushOutput(testCase);
if (result.getResult() == MessageHelper.FAILED_TEST) {
myStatusLine.setStatusColor(ColorProgressBar.RED);
@@ -26,20 +26,17 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.JarVersionDetectionUtil;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.*;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.TextOccurenceProcessor;
import com.intellij.psi.search.UsageSearchContext;
import com.intellij.psi.search.searches.AllClassesSearch;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiElementFilter;
@@ -56,9 +53,11 @@ import org.testng.TestNG;
import org.testng.annotations.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipFile;
/**
* @author Hani Suleiman Date: Jul 20, 2005 Time: 1:37:36 PM
@@ -68,6 +67,31 @@ public class TestNGUtil
private static final Logger LOGGER = Logger.getInstance("TestNG Runner");
public static final String TESTNG_GROUP_NAME = "TestNG";
public static boolean hasDocTagsSupport = hasDocTagsSupport();
private static boolean hasDocTagsSupport() {
final String testngJarPath = PathUtil.getJarPathForClass(Test.class);
if (testngJarPath != null) {
final VirtualFile testngjar = LocalFileSystem.getInstance().findFileByPath(testngJarPath);
if (testngjar != null ) {
try {
final VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(testngjar);
if (jarRoot != null) {
final ZipFile zipFile = JarFileSystem.getInstance().getJarFile(jarRoot);
final String version = JarVersionDetectionUtil.detectJarVersion(zipFile);
if (version != null && version.compareTo("5.12") > 0) {
return false;
}
}
}
catch (IOException e) {
return true;
}
}
}
return true;
}
public static final String TEST_ANNOTATION_FQN = Test.class.getName();
public static final String[] CONFIG_ANNOTATIONS_FQN = {
Configuration.class.getName(),
@@ -145,12 +169,7 @@ public class TestNGUtil
}
public static boolean hasTest(PsiModifierListOwner element, boolean checkDisabled) {
return hasTest(element, checkDisabled, !element.getManager().getSearchHelper().processElementsWithWord(new TextOccurenceProcessor() {
@Override
public boolean execute(PsiElement element, int offsetInElement) {
return false;
}
}, GlobalSearchScope.projectScope(element.getProject()), "testng.test", UsageSearchContext.IN_COMMENTS , true));
return hasTest(element, checkDisabled, hasDocTagsSupport);
}
public static boolean hasTest(PsiModifierListOwner element, boolean checkDisabled, boolean checkJavadoc) {
@@ -24,7 +24,6 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
@@ -492,8 +491,10 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag {
ChangeUtil.copyElement((TreeElement)XmlChildRole.START_TAG_NAME_FINDER.findChild(dummyTag), charTableByTree));
final ASTNode childByRole = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(tag);
if (childByRole != null) {
tag.replaceChild(childByRole,
ChangeUtil.copyElement((TreeElement)XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(dummyTag), charTableByTree));
final TreeElement treeElement = (TreeElement)XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(dummyTag);
if (treeElement != null) {
tag.replaceChild(childByRole, ChangeUtil.copyElement(treeElement, charTableByTree));
}
}
return XmlTagNameChangedImpl.createXmlTagNameChanged(model, tag, oldName);