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

This commit is contained in:
Kirill Likhodedov
2010-08-11 13:01:33 +04:00
1227 changed files with 282875 additions and 5051 deletions
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -67,7 +67,7 @@ def wire_build_date(String buildNumber) {
target('default': 'The default target') {
depends(compile)
layoutAll(
buildNumber: "IC-X.SNAPSHOT",
buildNumber: "IC-96.SNAPSHOT",
version: "IdeaX",
system_selector: "IntelliJIdeaCE10",
jdk_req: "1.6*",
+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>
@@ -24,7 +24,7 @@ package com.intellij.compiler.impl;
import com.intellij.CommonBundle;
import com.intellij.analysis.AnalysisScope;
import com.intellij.compiler.*;
import com.intellij.compiler.impl.newApi.NewCompiler;
import com.intellij.openapi.compiler.generic.GenericCompiler;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.compiler.make.CacheUtils;
import com.intellij.compiler.make.DependencyCache;
@@ -725,7 +725,7 @@ public class CompileDriver {
boolean didSomething = false;
final CompilerManager compilerManager = CompilerManager.getInstance(myProject);
NewCompilerRunner runner = new NewCompilerRunner(context, compilerManager, forceCompile, onlyCheckStatus);
GenericCompilerRunner runner = new GenericCompilerRunner(context, compilerManager, forceCompile, onlyCheckStatus);
try {
didSomething |= generateSources(compilerManager, context, forceCompile, onlyCheckStatus);
@@ -747,23 +747,23 @@ public class CompileDriver {
didSomething |= invokeFileProcessingCompilers(compilerManager, context, ClassInstrumentingCompiler.class,
FILE_PROCESSING_COMPILER_ADAPTER_FACTORY, isRebuild, false, onlyCheckStatus);
didSomething |= runner.invokeCompilers(NewCompiler.CompileOrderPlace.CLASS_INSTRUMENTING);
didSomething |= runner.invokeCompilers(GenericCompiler.CompileOrderPlace.CLASS_INSTRUMENTING);
// explicitly passing forceCompile = false because in scopes that is narrower than ProjectScope it is impossible
// to understand whether the class to be processed is in scope or not. Otherwise compiler may process its items even if
// there were changes in completely independent files.
didSomething |= invokeFileProcessingCompilers(compilerManager, context, ClassPostProcessingCompiler.class,
FILE_PROCESSING_COMPILER_ADAPTER_FACTORY, isRebuild, false, onlyCheckStatus);
didSomething |= runner.invokeCompilers(NewCompiler.CompileOrderPlace.CLASS_POST_PROCESSING);
didSomething |= runner.invokeCompilers(GenericCompiler.CompileOrderPlace.CLASS_POST_PROCESSING);
didSomething |= invokeFileProcessingCompilers(compilerManager, context, PackagingCompiler.class,
FILE_PACKAGING_COMPILER_ADAPTER_FACTORY,
isRebuild, false, onlyCheckStatus);
didSomething |= runner.invokeCompilers(NewCompiler.CompileOrderPlace.PACKAGING);
didSomething |= runner.invokeCompilers(GenericCompiler.CompileOrderPlace.PACKAGING);
didSomething |= invokeFileProcessingCompilers(compilerManager, context, Validator.class, FILE_PROCESSING_COMPILER_ADAPTER_FACTORY,
forceCompile, true, onlyCheckStatus);
didSomething |= runner.invokeCompilers(NewCompiler.CompileOrderPlace.VALIDATING);
didSomething |= runner.invokeCompilers(GenericCompiler.CompileOrderPlace.VALIDATING);
}
catch (ExitException e) {
if (LOG.isDebugEnabled()) {
@@ -15,8 +15,8 @@
*/
package com.intellij.compiler.impl;
import com.intellij.compiler.impl.newApi.NewCompiler;
import com.intellij.compiler.impl.newApi.NewCompilerCache;
import com.intellij.compiler.impl.generic.GenericCompilerCache;
import com.intellij.openapi.compiler.generic.GenericCompiler;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.Compiler;
@@ -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<GenericCompiler<?,?,?>, GenericCompilerCache<?,?,?>> myGenericCachesMap = new HashMap<GenericCompiler<?,?,?>, GenericCompilerCache<?,?,?>>();
private final List<Disposable> myCacheDisposables = new ArrayList<Disposable>();
private final File myCachesRoot;
private final Runnable myShutdownTask = new Runnable() {
@@ -90,21 +90,23 @@ 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> GenericCompilerCache<Key, SourceState, OutputState>
getGenericCompilerCache(GenericCompiler<Key, SourceState, OutputState> compiler) throws IOException {
GenericCompilerCache<?,?,?> cache = myGenericCachesMap.get(compiler);
if (cache == null) {
final NewCompilerCache<?, ?> newCache = new NewCompilerCache<Key, State>(compiler, NewCompilerRunner.getNewCompilerCacheDir(myProject, compiler));
myNewCachesMap.put(compiler, newCache);
final GenericCompilerCache<?,?,?> genericCache = new GenericCompilerCache<Key, SourceState, OutputState>(compiler, GenericCompilerRunner
.getGenericCompilerCacheDir(myProject, compiler));
myGenericCachesMap.put(compiler, genericCache);
myCacheDisposables.add(new Disposable() {
@Override
public void dispose() {
newCache.close();
genericCache.close();
}
});
cache = newCache;
cache = genericCache;
}
//noinspection unchecked
return (NewCompilerCache<Key, State>)cache;
return (GenericCompilerCache<Key, SourceState, OutputState>)cache;
}
public synchronized FileProcessingCompilerStateCache getFileProcessingCompilerCache(FileProcessingCompiler compiler) throws IOException {
@@ -171,7 +173,7 @@ public class CompilerCacheManager implements ProjectComponent {
}
}
myCacheDisposables.clear();
myNewCachesMap.clear();
myGenericCachesMap.clear();
myCompilerToCacheMap.clear();
}
@@ -0,0 +1,305 @@
/*
* 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;
import com.google.common.base.Throwables;
import com.intellij.compiler.impl.generic.GenericCompilerCache;
import com.intellij.compiler.impl.generic.GenericCompilerPersistentData;
import com.intellij.openapi.compiler.generic.*;
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.Ref;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.io.KeyDescriptor;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author nik
*/
public class GenericCompilerRunner {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.GenericCompilerRunner");
private CompileContext myContext;
private final boolean myForceCompile;
private final boolean myOnlyCheckStatus;
private final GenericCompiler<?,?,?>[] myCompilers;
private final Project myProject;
public GenericCompilerRunner(CompileContext context, CompilerManager compilerManager, boolean forceCompile, boolean onlyCheckStatus) {
myContext = context;
myForceCompile = forceCompile;
myOnlyCheckStatus = onlyCheckStatus;
myCompilers = compilerManager.getCompilers(GenericCompiler.class);
myProject = myContext.getProject();
}
public boolean invokeCompilers(GenericCompiler.CompileOrderPlace place) throws CompileDriver.ExitException {
boolean didSomething = false;
try {
for (GenericCompiler<?,?,?> compiler : myCompilers) {
if (compiler.getOrderPlace().equals(place)) {
didSomething = invokeCompiler(compiler);
}
}
}
catch (IOException e) {
LOG.info(e);
myContext.requestRebuildNextTime(e.getMessage());
throw new CompileDriver.ExitException(CompileDriver.ExitStatus.ERRORS);
}
catch (CompileDriver.ExitException e) {
throw e;
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Exception e) {
LOG.info(e);
myContext.addMessage(CompilerMessageCategory.ERROR, CompilerBundle.message("compiler.error.exception", e.getMessage()), null, -1, -1);
}
return didSomething;
}
private <Key, SourceState, OutputState> boolean invokeCompiler(GenericCompiler<Key, SourceState, OutputState> compiler) throws IOException, CompileDriver.ExitException {
return invokeCompiler(compiler, compiler.createInstance(myContext));
}
private <T extends BuildTarget, Item extends CompileItem<Key, SourceState, OutputState>, Key, SourceState, OutputState>
boolean invokeCompiler(GenericCompiler<Key, SourceState, OutputState> compiler, final GenericCompilerInstance<T, Item, Key, SourceState, OutputState> instance) throws IOException, CompileDriver.ExitException {
final GenericCompilerCache<Key, SourceState, OutputState> cache = CompilerCacheManager.getInstance(myProject).getGenericCompilerCache(compiler);
GenericCompilerPersistentData
data = new GenericCompilerPersistentData(getGenericCompilerCacheDir(myProject, compiler), compiler.getVersion());
if (data.isVersionChanged()) {
LOG.info("Clearing cache for " + compiler.getDescription());
cache.wipe();
data.save();
}
final Set<String> targetsToRemove = new HashSet<String>(data.getAllTargets());
new ReadAction() {
protected void run(final Result result) {
for (T target : instance.getAllTargets()) {
targetsToRemove.remove(target.getId());
}
}
}.execute();
if (!myOnlyCheckStatus) {
for (final String target : targetsToRemove) {
final int id = data.removeId(target);
if (LOG.isDebugEnabled()) {
LOG.debug("Removing obsolete target '" + target + "' (id=" + id + ")");
}
final List<Key> keys = new ArrayList<Key>();
CompilerUtil.runInContext(myContext, "Processing obsolete targets...", new ThrowableRunnable<IOException>() {
@Override
public void run() throws IOException {
cache.processSources(id, new CommonProcessors.CollectProcessor<Key>(keys));
List<GenericCompilerCacheState<Key, SourceState, OutputState>> obsoleteSources = new ArrayList<GenericCompilerCacheState<Key,SourceState,OutputState>>();
for (Key key : keys) {
final GenericCompilerCache.PersistentStateData<SourceState, OutputState> state = cache.getState(id, key);
obsoleteSources.add(new GenericCompilerCacheState<Key,SourceState,OutputState>(key, state.mySourceState, state.myOutputState));
}
instance.processObsoleteTarget(target, obsoleteSources);
}
});
checkForErrorsOrCanceled();
for (Key key : keys) {
cache.remove(id, key);
}
}
}
final List<T> selectedTargets = new ReadAction<List<T>>() {
protected void run(final Result<List<T>> result) {
result.setResult(instance.getSelectedTargets());
}
}.execute().getResultObject();
boolean didSomething = false;
for (T target : selectedTargets) {
int id = data.getId(target.getId());
didSomething |= processTarget(target, id, compiler, instance, cache);
}
data.save();
return didSomething;
}
private void checkForErrorsOrCanceled() throws CompileDriver.ExitException {
if (myContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
throw new CompileDriver.ExitException(CompileDriver.ExitStatus.ERRORS);
}
if (myContext.getProgressIndicator().isCanceled()) {
throw new CompileDriver.ExitException(CompileDriver.ExitStatus.CANCELLED);
}
}
public static File getGenericCompilerCacheDir(Project project, GenericCompiler<?,?,?> compiler) {
return new File(CompilerPaths.getCacheStoreDirectory(project), compiler.getId());
}
private <T extends BuildTarget, Item extends CompileItem<Key, SourceState, OutputState>, Key, SourceState, OutputState>
boolean processTarget(T target, final int targetId, final GenericCompiler<Key, SourceState, OutputState> compiler, final GenericCompilerInstance<T, Item, Key, SourceState, OutputState> instance,
final GenericCompilerCache<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);
checkForErrorsOrCanceled();
final List<GenericCompilerProcessingItem<Item, SourceState, OutputState>> toProcess = new ArrayList<GenericCompilerProcessingItem<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() {
try {
for (Item item : items) {
final Key key = item.getKey();
keySet.add(key);
final GenericCompilerCache.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 GenericCompilerProcessingItem<Item,SourceState,OutputState>(item, sourceState, outputState));
}
}
}
catch (IOException e) {
exception.set(e);
}
}
});
if (!exception.isNull()) {
throw exception.get();
}
final List<Key> toRemove = new ArrayList<Key>();
cache.processSources(targetId, new Processor<Key>() {
@Override
public boolean process(Key key) {
if (!keySet.contains(key)) {
toRemove.add(key);
}
return true;
}
});
if (LOG.isDebugEnabled()) {
LOG.debug(toProcess.size() + " items will be processed, " + toRemove.size() + " items will be removed");
}
if (toProcess.isEmpty() && toRemove.isEmpty()) {
return false;
}
if (myOnlyCheckStatus) {
throw new CompileDriver.ExitException(CompileDriver.ExitStatus.CANCELLED);
}
List<GenericCompilerCacheState<Key, SourceState, OutputState>> obsoleteItems = new ArrayList<GenericCompilerCacheState<Key,SourceState,OutputState>>();
for (Key key : toRemove) {
final GenericCompilerCache.PersistentStateData<SourceState, OutputState> data = cache.getState(targetId, key);
obsoleteItems.add(new GenericCompilerCacheState<Key,SourceState,OutputState>(key, data.mySourceState, data.myOutputState));
}
final List<Item> processedItems = new ArrayList<Item>();
final List<File> filesToRefresh = new ArrayList<File>();
final List<File> dirsToRefresh = new ArrayList<File>();
instance.processItems(target, toProcess, obsoleteItems, new GenericCompilerInstance.OutputConsumer<Item>() {
@Override
public void addFileToRefresh(@NotNull File file) {
filesToRefresh.add(file);
}
@Override
public void addDirectoryToRefresh(@NotNull File dir) {
dirsToRefresh.add(dir);
}
@Override
public void addProcessedItem(@NotNull Item sourceItem) {
processedItems.add(sourceItem);
}
});
checkForErrorsOrCanceled();
CompilerUtil.runInContext(myContext, CompilerBundle.message("progress.updating.caches"), new ThrowableRunnable<IOException>() {
@Override
public void run() throws IOException {
for (Key key : toRemove) {
cache.remove(targetId, key);
}
CompilerUtil.refreshIOFiles(filesToRefresh);
CompilerUtil.refreshIODirectories(dirsToRefresh);
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;
}
private class SourceItemHashingStrategy<S> implements TObjectHashingStrategy<S> {
private KeyDescriptor<S> myKeyDescriptor;
public SourceItemHashingStrategy(GenericCompiler<S, ?, ?> compiler) {
myKeyDescriptor = compiler.getItemKeyDescriptor();
}
@Override
public int computeHashCode(S object) {
return myKeyDescriptor.getHashCode(object);
}
@Override
public boolean equals(S o1, S o2) {
return myKeyDescriptor.isEqual(o1, o2);
}
}
}
@@ -1,246 +0,0 @@
/*
* 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;
import com.intellij.compiler.impl.newApi.*;
import com.intellij.openapi.application.ApplicationManager;
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;
import com.intellij.util.io.KeyDescriptor;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author nik
*/
public class NewCompilerRunner {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.NewCompilerRunner");
private CompileContext myContext;
private final boolean myForceCompile;
private final boolean myOnlyCheckStatus;
private final NewCompiler<?,?>[] myCompilers;
private final Project myProject;
public NewCompilerRunner(CompileContext context, CompilerManager compilerManager, boolean forceCompile, boolean onlyCheckStatus) {
myContext = context;
myForceCompile = forceCompile;
myOnlyCheckStatus = onlyCheckStatus;
myCompilers = compilerManager.getCompilers(NewCompiler.class);
myProject = myContext.getProject();
}
public boolean invokeCompilers(NewCompiler.CompileOrderPlace place) throws CompileDriver.ExitException {
boolean didSomething = false;
try {
for (NewCompiler<?, ?> compiler : myCompilers) {
if (compiler.getOrderPlace().equals(place)) {
didSomething = invokeCompiler(compiler);
}
}
}
catch (IOException e) {
LOG.info(e);
myContext.requestRebuildNextTime(e.getMessage());
throw new CompileDriver.ExitException(CompileDriver.ExitStatus.ERRORS);
}
catch (CompileDriver.ExitException e) {
throw e;
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Exception e) {
LOG.info(e);
myContext.addMessage(CompilerMessageCategory.ERROR, CompilerBundle.message("compiler.error.exception", e.getMessage()), null, -1, -1);
}
return didSomething;
}
private <T extends BuildTarget, Key, State> boolean invokeCompiler(NewCompiler<Key, State> 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);
NewCompilerPersistentData data = new NewCompilerPersistentData(getNewCompilerCacheDir(myProject, compiler), compiler.getVersion());
if (data.isVersionChanged()) {
LOG.info("Clearing cache for " + compiler.getDescription());
cache.wipe();
}
Set<String> targetsToRemove = new HashSet<String>(data.getAllTargets());
for (T target : instance.getAllTargets()) {
targetsToRemove.remove(target.getId());
}
if (!myOnlyCheckStatus) {
for (String target : targetsToRemove) {
int id = data.removeId(target);
if (LOG.isDebugEnabled()) {
LOG.debug("Removing obsolete target '" + target + "' (id=" + id + ")");
}
List<Key> keys = new ArrayList<Key>();
cache.processSources(id, new CommonProcessors.CollectProcessor<Key>(keys));
List<Pair<Key, State>> obsoleteSources = new ArrayList<Pair<Key, State>>();
for (Key key : keys) {
final State state = cache.getState(id, key);
obsoleteSources.add(Pair.create(key, state));
}
instance.processObsoleteTarget(target, obsoleteSources);
if (myContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
return true;
}
for (Key key : keys) {
cache.remove(id, key);
}
}
}
boolean didSomething = false;
for (T target : instance.getSelectedTargets()) {
int id = data.getId(target.getId());
didSomething |= processTarget(target, id, compiler, instance, cache);
}
data.save();
return didSomething;
}
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 {
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 THashSet<Key> keySet = new THashSet<Key>(new SourceItemHashingStrategy<Key>(compiler));
final Ref<IOException> exception = Ref.create(null);
DumbService.getInstance(myProject).waitForSmartMode();
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
try {
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));
}
}
}
catch (IOException e) {
exception.set(e);
}
}
});
if (!exception.isNull()) {
throw exception.get();
}
final List<Key> toRemove = new ArrayList<Key>();
cache.processSources(targetId, new Processor<Key>() {
@Override
public boolean process(Key key) {
if (!keySet.contains(key)) {
toRemove.add(key);
}
return true;
}
});
if (LOG.isDebugEnabled()) {
LOG.debug(toProcess.size() + " items will be processed, " + toRemove.size() + " items will be removed");
}
if (toProcess.isEmpty() && toRemove.isEmpty()) {
return false;
}
if (myOnlyCheckStatus) {
throw new CompileDriver.ExitException(CompileDriver.ExitStatus.CANCELLED);
}
List<Pair<Key, State>> obsoleteItems = new ArrayList<Pair<Key, State>>();
for (Key key : toRemove) {
obsoleteItems.add(Pair.create(key, cache.getState(targetId, key)));
}
final List<Item> processedItems = new ArrayList<Item>();
final List<File> toRefresh = new ArrayList<File>();
instance.processItems(target, toProcess, obsoleteItems, new CompilerInstance.OutputConsumer<Item>() {
@Override
public void addFileToRefresh(@NotNull File file) {
toRefresh.add(file);
}
@Override
public void addProcessedItem(@NotNull Item sourceItem) {
processedItems.add(sourceItem);
}
});
if (myContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
return true;
}
for (Key key : toRemove) {
cache.remove(targetId, key);
}
CompilerUtil.refreshIOFiles(toRefresh);
for (Item item : processedItems) {
cache.putOutput(targetId, item.getKey(), item.computeState());
}
return true;
}
private class SourceItemHashingStrategy<S> implements TObjectHashingStrategy<S> {
private KeyDescriptor<S> myKeyDescriptor;
public SourceItemHashingStrategy(NewCompiler<S, ?> compiler) {
myKeyDescriptor = compiler.getItemKeyDescriptor();
}
@Override
public int computeHashCode(S object) {
return myKeyDescriptor.getHashCode(object);
}
@Override
public boolean equals(S o1, S o2) {
return myKeyDescriptor.isEqual(o1, o2);
}
}
}
@@ -13,12 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.newApi;
package com.intellij.compiler.impl.generic;
import com.intellij.openapi.compiler.generic.GenericCompiler;
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;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
@@ -28,28 +31,25 @@ import java.io.IOException;
/**
* @author nik
*/
public class NewCompilerCache<Key, State> {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.newApi.NewCompilerCache");
private PersistentHashMap<KeyAndTargetData<Key>, State> myPersistentMap;
public class GenericCompilerCache<Key, SourceState, OutputState> {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.generic.GenericCompilerCache");
private PersistentHashMap<KeyAndTargetData<Key>, PersistentStateData<SourceState, OutputState>> myPersistentMap;
private File myCacheFile;
private final NewCompiler<Key, State> myCompiler;
private final GenericCompiler<Key, SourceState, OutputState> myCompiler;
public NewCompilerCache(NewCompiler<Key, State> compiler, final File compilerCacheDir) throws IOException {
public GenericCompilerCache(GenericCompiler<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,12 +75,12 @@ 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));
}
public void processSources(final int targetId, final Processor<Key> processor) throws IOException {
myPersistentMap.processKeys(new Processor<KeyAndTargetData<Key>>() {
myPersistentMap.processKeysWithExistingMapping(new Processor<KeyAndTargetData<Key>>() {
@Override
public boolean process(KeyAndTargetData<Key> data) {
return targetId == data.myTarget ? processor.process(data.myKey) : true;
@@ -88,16 +88,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, @NotNull Key key, @NotNull SourceState sourceState, @NotNull 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(@NotNull SourceState sourceState, @NotNull OutputState outputState) {
mySourceState = sourceState;
myOutputState = outputState;
}
}
private class SourceItemDataDescriptor implements KeyDescriptor<KeyAndTargetData<Key>> {
private final KeyDescriptor<Key> myKeyDescriptor;
@@ -129,4 +144,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(GenericCompiler<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);
}
}
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.newApi;
package com.intellij.compiler.impl.generic;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.io.IOUtil;
@@ -28,16 +28,16 @@ import java.util.Set;
/**
* @author nik
*/
public class NewCompilerPersistentData {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.newApi.NewCompilerPersistentData");
private static final int VERSION = 0;
public class GenericCompilerPersistentData {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.generic.GenericCompilerPersistentData");
private static final int VERSION = 1;
private File myFile;
private Map<String, Integer> myTarget2Id = new HashMap<String, Integer>();
private TIntHashSet myUsedIds = new TIntHashSet();
private boolean myVersionChanged;
private final int myCompilerVersion;
public NewCompilerPersistentData(File cacheStoreDirectory, int compilerVersion) throws IOException {
public GenericCompilerPersistentData(File cacheStoreDirectory, int compilerVersion) throws IOException {
myCompilerVersion = compilerVersion;
myFile = new File(cacheStoreDirectory, "info");
if (!myFile.exists()) {
@@ -176,7 +176,7 @@ public class BackendCompilerWrapper {
}
}
finally {
if (fileToDelete != null) {
if (fileToDelete != null && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
FileUtil.asyncDelete(fileToDelete);
}
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.newApi;
package com.intellij.openapi.compiler.generic;
import org.jetbrains.annotations.NotNull;
@@ -0,0 +1,37 @@
/*
* 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.openapi.compiler.generic;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class CompileItem<Key, SourceState, OutputState> {
@NotNull
public abstract Key getKey();
public abstract boolean isSourceUpToDate(@NotNull SourceState state);
@NotNull
public abstract SourceState computeSourceState();
public abstract boolean isOutputUpToDate(@NotNull OutputState state);
@NotNull
public abstract OutputState computeOutputState();
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.newApi;
package com.intellij.openapi.compiler.generic;
import com.intellij.util.io.DataExternalizer;
@@ -22,23 +22,23 @@ import java.io.DataOutput;
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;
* @author nik
*/
public class DummyPersistentState {
public static final DummyPersistentState INSTANCE = new DummyPersistentState();
public static final DataExternalizer<DummyPersistentState> EXTERNALIZER = new DummyPersistentStateExternalizer();
protected abstract State doRead(DataInput in, long sourceTimestamp) throws IOException;
@Override
public final void save(DataOutput out, State value) throws IOException {
out.writeLong(value.getSourceTimestamp());
doSave(out, value);
private DummyPersistentState() {
}
@Override
public final State read(DataInput in) throws IOException {
final long sourceTimestamp = in.readLong();
return doRead(in, sourceTimestamp);
}
private static class DummyPersistentStateExternalizer implements DataExternalizer<DummyPersistentState> {
@Override
public void save(DataOutput out, DummyPersistentState value) throws IOException {
}
@Override
public DummyPersistentState read(DataInput in) throws IOException {
return INSTANCE;
}
}
}
@@ -13,23 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.newApi;
package com.intellij.openapi.compiler.generic;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.Compiler;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class NewCompiler<Key, State> implements Compiler {
public abstract class GenericCompiler<Key, SourceState, OutputState> implements Compiler {
protected static final KeyDescriptor<String> STRING_KEY_DESCRIPTOR = new EnumeratorStringDescriptor();
private final String myId;
private final int myVersion;
private final CompileOrderPlace myOrderPlace;
protected NewCompiler(@NotNull String id, int version, @NotNull CompileOrderPlace orderPlace) {
protected GenericCompiler(@NotNull String id, int version, @NotNull CompileOrderPlace orderPlace) {
myId = id;
myVersion = version;
myOrderPlace = orderPlace;
@@ -38,10 +41,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 GenericCompilerInstance<?, ? extends CompileItem<Key, SourceState, OutputState>, Key, SourceState, OutputState> createInstance(@NotNull CompileContext context);
public final String getId() {
return myId;
@@ -51,6 +56,11 @@ public abstract class NewCompiler<Key, State> implements Compiler {
return myVersion;
}
@Override
public boolean validateConfiguration(CompileScope scope) {
return true;
}
public CompileOrderPlace getOrderPlace() {
return myOrderPlace;
}
@@ -0,0 +1,48 @@
/*
* 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.openapi.compiler.generic;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public class GenericCompilerCacheState<Key, SourceState, OutputState> {
private final Key myKey;
private final SourceState mySourceState;
private final OutputState myOutputState;
public GenericCompilerCacheState(@NotNull Key key, @NotNull SourceState sourceState, @NotNull OutputState outputState) {
myKey = key;
mySourceState = sourceState;
myOutputState = outputState;
}
@NotNull
public Key getKey() {
return myKey;
}
@NotNull
public SourceState getSourceState() {
return mySourceState;
}
@NotNull
public OutputState getOutputState() {
return myOutputState;
}
}
@@ -13,11 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.newApi;
package com.intellij.openapi.compiler.generic;
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,10 +25,10 @@ import java.util.List;
/**
* @author nik
*/
public abstract class CompilerInstance<T extends BuildTarget, Item extends CompileItem<Key, State>, Key, State> {
public abstract class GenericCompilerInstance<T extends BuildTarget, Item extends CompileItem<Key, SourceState, OutputState>, Key, SourceState, OutputState> {
protected final CompileContext myContext;
protected CompilerInstance(CompileContext context) {
protected GenericCompilerInstance(CompileContext context) {
myContext = context;
}
@@ -43,18 +42,20 @@ 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<GenericCompilerCacheState<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<GenericCompilerProcessingItem<Item, SourceState, OutputState>> changedItems, @NotNull List<GenericCompilerCacheState<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 addDirectoryToRefresh(@NotNull File dir);
void addProcessedItem(@NotNull Item sourceItem);
}
}
@@ -0,0 +1,49 @@
/*
* 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.openapi.compiler.generic;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author nik
*/
public class GenericCompilerProcessingItem<Item extends CompileItem<?, SourceState, OutputState>, SourceState, OutputState> {
private final Item myItem;
private final SourceState myCachedSourceState;
private final OutputState myCachedOutputState;
public GenericCompilerProcessingItem(@NotNull Item item, @Nullable SourceState cachedSourceState, @Nullable OutputState cachedOutputState) {
myItem = item;
myCachedSourceState = cachedSourceState;
myCachedOutputState = cachedOutputState;
}
@NotNull
public Item getItem() {
return myItem;
}
@Nullable
public SourceState getCachedSourceState() {
return myCachedSourceState;
}
@Nullable
public OutputState getCachedOutputState() {
return myCachedOutputState;
}
}
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.newApi;
package com.intellij.openapi.compiler.generic;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
@@ -25,7 +24,8 @@ 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
GenericCompilerInstance<BuildTarget, Item, K, S, O> {
protected SingleTargetCompilerInstance(CompileContext context) {
super(context);
}
@@ -43,6 +43,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<GenericCompilerCacheState<K, S, O>> obsoleteItems) {
}
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.impl.newApi;
package com.intellij.openapi.compiler.generic;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.io.EnumeratorStringDescriptor;
@@ -23,8 +23,7 @@ import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class VirtualFileCompileItem<State extends VirtualFilePersistentState> extends CompileItem<String, State> {
public static final KeyDescriptor<String> KEY_DESCRIPTOR = new EnumeratorStringDescriptor();
public abstract class VirtualFileCompileItem<OutputState> extends CompileItem<String, VirtualFilePersistentState, OutputState> {
protected final VirtualFile myFile;
public VirtualFileCompileItem(@NotNull VirtualFile file) {
@@ -36,15 +35,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
@@ -0,0 +1,51 @@
/*
* 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.openapi.compiler.generic;
import com.intellij.util.io.DataExternalizer;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* @author nik
*/
public class VirtualFilePersistentState {
public static DataExternalizer<VirtualFilePersistentState> EXTERNALIZER = new VirtualFileStateExternalizer();
private final long mySourceTimestamp;
public VirtualFilePersistentState(long sourceTimestamp) {
mySourceTimestamp = sourceTimestamp;
}
public final long getSourceTimestamp() {
return mySourceTimestamp;
}
private static class VirtualFileStateExternalizer implements DataExternalizer<VirtualFilePersistentState> {
@Override
public void save(DataOutput out, VirtualFilePersistentState value) throws IOException {
out.writeLong(value.getSourceTimestamp());
}
@Override
public VirtualFilePersistentState read(DataInput in) throws IOException {
return new VirtualFilePersistentState(in.readLong());
}
}
}
@@ -0,0 +1,91 @@
/*
* 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.openapi.compiler.generic;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.IOUtil;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author nik
*/
public class VirtualFileSetState {
public static final DataExternalizer<VirtualFileSetState> EXTERNALIZER = new VirtualFileWithDependenciesExternalizer();
private Map<String, Long> myTimestamps = new HashMap<String, Long>();
public VirtualFileSetState() {
}
public VirtualFileSetState(Collection<? extends VirtualFile> files) {
for (VirtualFile file : files) {
addFile(file);
}
}
public void addFile(@NotNull VirtualFile file) {
myTimestamps.put(file.getUrl(), file.getTimeStamp());
}
public boolean isUpToDate(Set<? extends VirtualFile> files) {
if (files.size() != myTimestamps.size()) {
return false;
}
for (VirtualFile file : files) {
final Long timestamp = myTimestamps.get(file.getUrl());
if (timestamp == null || timestamp != file.getTimeStamp()) {
return false;
}
}
return true;
}
private static class VirtualFileWithDependenciesExternalizer implements DataExternalizer<VirtualFileSetState> {
private byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
@Override
public void save(DataOutput out, VirtualFileSetState value) throws IOException {
final Map<String, Long> dependencies = value.myTimestamps;
out.writeInt(dependencies.size());
for (Map.Entry<String, Long> entry : dependencies.entrySet()) {
IOUtil.writeUTFFast(myBuffer, out, entry.getKey());
out.writeLong(entry.getValue());
}
}
@Override
public VirtualFileSetState read(DataInput in) throws IOException {
final VirtualFileSetState state = new VirtualFileSetState();
int size = in.readInt();
while (size-- > 0) {
final String url = IOUtil.readUTFFast(myBuffer, in);
final long timestamp = in.readLong();
state.myTimestamps.put(url, timestamp);
}
return state;
}
}
}
@@ -0,0 +1,88 @@
/*
* 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.openapi.compiler.generic;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.IOUtil;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author nik
*/
public class VirtualFileWithDependenciesState {
public static final DataExternalizer<VirtualFileWithDependenciesState> EXTERNALIZER = new VirtualFileWithDependenciesExternalizer();
private long mySourceTimestamp;
private Map<String, Long> myDependencies = new HashMap<String, Long>();
public VirtualFileWithDependenciesState(long sourceTimestamp) {
mySourceTimestamp = sourceTimestamp;
}
public void addDependency(@NotNull VirtualFile file) {
myDependencies.put(file.getUrl(), file.getTimeStamp());
}
public boolean isUpToDate(@NotNull VirtualFile sourceFile) {
if (sourceFile.getTimeStamp() != mySourceTimestamp) {
return false;
}
VirtualFileManager manager = VirtualFileManager.getInstance();
for (Map.Entry<String, Long> entry : myDependencies.entrySet()) {
final VirtualFile file = manager.findFileByUrl(entry.getKey());
if (file == null || file.getTimeStamp() != entry.getValue()) {
return false;
}
}
return true;
}
private static class VirtualFileWithDependenciesExternalizer implements DataExternalizer<VirtualFileWithDependenciesState> {
private byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
@Override
public void save(DataOutput out, VirtualFileWithDependenciesState value) throws IOException {
out.writeLong(value.mySourceTimestamp);
final Map<String, Long> dependencies = value.myDependencies;
out.writeInt(dependencies.size());
for (Map.Entry<String, Long> entry : dependencies.entrySet()) {
IOUtil.writeUTFFast(myBuffer, out, entry.getKey());
out.writeLong(entry.getValue());
}
}
@Override
public VirtualFileWithDependenciesState read(DataInput in) throws IOException {
final VirtualFileWithDependenciesState state = new VirtualFileWithDependenciesState(in.readLong());
int size = in.readInt();
while (size-- > 0) {
final String url = IOUtil.readUTFFast(myBuffer, in);
final long timestamp = in.readLong();
state.myDependencies.put(url, timestamp);
}
return state;
}
}
}
@@ -17,9 +17,7 @@ package com.intellij.packaging.impl.artifacts;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.openapi.vfs.VirtualFile;
@@ -90,13 +88,8 @@ public class ArtifactBySourceFileFinderImpl extends ArtifactBySourceFileFinder {
final Module module = ((ModuleOutputPackagingElement)element).findModule(context);
if (module != null) {
final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module);
for (ContentEntry contentEntry : rootModel.getContentEntries()) {
for (SourceFolder sourceFolder : contentEntry.getSourceFolders()) {
final VirtualFile sourceRoot = sourceFolder.getFile();
if (sourceRoot != null && !sourceFolder.isTestSource()) {
result.put(sourceRoot, artifact);
}
}
for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) {
result.put(sourceRoot, artifact);
}
}
}
@@ -19,9 +19,7 @@ import com.intellij.compiler.CompilerConfiguration;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.CompilerProjectExtension;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Trinity;
@@ -365,12 +363,9 @@ public class ArtifactUtil {
final Module module = moduleElement.findModule(context);
if (module != null) {
final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module);
for (ContentEntry entry : rootModel.getContentEntries()) {
for (SourceFolder folder : entry.getSourceFolders()) {
final VirtualFile sourceRoot = folder.getFile();
if (!folder.isTestSource() && sourceRoot != null && VfsUtil.isAncestor(sourceRoot, file, true)) {
return VfsUtil.getRelativePath(file, sourceRoot, '/');
}
for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) {
if (VfsUtil.isAncestor(sourceRoot, file, true)) {
return VfsUtil.getRelativePath(file, sourceRoot, '/');
}
}
}
@@ -428,16 +423,11 @@ public class ArtifactUtil {
final Module module = ((ModuleOutputPackagingElement)element).findModule(context);
if (module != null) {
final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(context.getProject());
final ContentEntry[] contentEntries = context.getModulesProvider().getRootModel(module).getContentEntries();
for (ContentEntry contentEntry : contentEntries) {
for (SourceFolder sourceFolder : contentEntry.getSourceFolders()) {
final VirtualFile sourceRoot = sourceFolder.getFile();
if (!sourceFolder.isTestSource() && sourceRoot != null) {
final VirtualFile sourceFile = sourceRoot.findFileByRelativePath(path);
if (sourceFile != null && compilerConfiguration.isResourceFile(sourceFile)) {
result.add(sourceFile);
}
}
final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module);
for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) {
final VirtualFile sourceFile = sourceRoot.findFileByRelativePath(path);
if (sourceFile != null && compilerConfiguration.isResourceFile(sourceFile)) {
result.add(sourceFile);
}
}
}
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.packaging.impl.artifacts.JarArtifactFromModulesDialog">
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="c89c9" class="javax.swing.JLabel" binding="myMainClassLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Main &amp;Class:"/>
</properties>
</component>
<vspacer id="8cb38">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="535a8" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myMainClassField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="2fb86" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="4853e"/>
<text value="&amp;Module:"/>
</properties>
</component>
<component id="4853e" class="javax.swing.JComboBox" binding="myModuleComboBox">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="400" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="8e551" class="javax.swing.JLabel" binding="myManifestDirLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Directory for META-INF/MANIFEST.MF:"/>
</properties>
</component>
<component id="1ea2d" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myManifestDirField">
<constraints>
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="2" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<grid id="53c3f" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none" title="Jar files from libraries:"/>
<children>
<component id="f9a17" class="javax.swing.JRadioButton" binding="myExtractJarsRadioButton">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="true"/>
<text value="&amp;extract to the target jar"/>
</properties>
</component>
<hspacer id="90c4f">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<component id="b3972" class="javax.swing.JRadioButton" binding="myCopyJarsRadioButton">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="copy &amp;to the output directory and link via manifest"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
<buttonGroups>
<group name="jarFiles">
<member id="f9a17"/>
<member id="b3972"/>
</group>
</buttonGroups>
</form>
@@ -0,0 +1,152 @@
/*
* 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.packaging.impl.artifacts;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.elements.PackagingElementResolvingContext;
import com.intellij.packaging.impl.elements.ManifestFileUtil;
import com.intellij.ui.DocumentAdapter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* @author nik
*/
public class JarArtifactFromModulesDialog extends DialogWrapper {
private JPanel myMainPanel;
private TextFieldWithBrowseButton myMainClassField;
private JComboBox myModuleComboBox;
private JLabel myMainClassLabel;
private TextFieldWithBrowseButton myManifestDirField;
private JLabel myManifestDirLabel;
private JRadioButton myExtractJarsRadioButton;
private JRadioButton myCopyJarsRadioButton;
private PackagingElementResolvingContext myContext;
public JarArtifactFromModulesDialog(PackagingElementResolvingContext context) {
super(context.getProject());
myContext = context;
setTitle("Create Jar from Modules");
myMainClassLabel.setLabelFor(myMainClassField.getTextField());
myManifestDirLabel.setLabelFor(myManifestDirField.getTextField());
final Project project = myContext.getProject();
ManifestFileUtil.setupMainClassField(project, myMainClassField);
myMainClassField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
updateManifestDirField();
}
});
final ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateManifestDirField();
}
};
myExtractJarsRadioButton.addActionListener(actionListener);
myCopyJarsRadioButton.addActionListener(actionListener);
updateManifestDirField();
myManifestDirField.addBrowseFolderListener(null, null, project, ManifestFileUtil.createDescriptorForManifestDirectory());
final Module[] modules = context.getModulesProvider().getModules();
if (modules.length > 1) {
myModuleComboBox.addItem(null);
}
for (Module module : modules) {
myModuleComboBox.addItem(module);
}
myModuleComboBox.setRenderer(new ModuleListRenderer());
init();
}
private void updateManifestDirField() {
final boolean enable = !myMainClassField.getText().isEmpty() || !myExtractJarsRadioButton.isSelected();
setManifestDirFieldEnabled(enable);
if (enable && myManifestDirField.getText().isEmpty()) {
final VirtualFile file = ManifestFileUtil.suggestManifestFileDirectory(myContext.getProject(), getSelectedModule());
if (file != null) {
myManifestDirField.setText(FileUtil.toSystemDependentName(file.getPath()));
}
}
}
@Nullable
private Module getSelectedModule() {
return (Module)myModuleComboBox.getSelectedItem();
}
@NotNull
public Module[] getSelectedModules() {
final Module module = getSelectedModule();
if (module != null) {
return new Module[]{module};
}
return myContext.getModulesProvider().getModules();
}
@NotNull
public String getDirectoryForManifest() {
return FileUtil.toSystemIndependentName(myManifestDirField.getText());
}
public boolean isExtractLibrariesToJar() {
return myExtractJarsRadioButton.isSelected();
}
public String getMainClassName() {
return myMainClassField.getText();
}
private void setManifestDirFieldEnabled(boolean enabled) {
myManifestDirLabel.setEnabled(enabled);
myManifestDirField.setEnabled(enabled);
}
@Override
protected JComponent createCenterPanel() {
return myMainPanel;
}
private static class ModuleListRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
final Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Module) {
final Module module = (Module)value;
setIcon(module.getModuleType().getNodeIcon(false));
setText(module.getName());
}
else {
setText("<All Modules>");
setIcon(null);
}
return component;
}
}
}
@@ -16,13 +16,17 @@
package com.intellij.packaging.impl.artifacts;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.packaging.artifacts.ArtifactTemplate;
import com.intellij.packaging.artifacts.ArtifactType;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElementOutputKind;
import com.intellij.packaging.elements.PackagingElementResolvingContext;
import com.intellij.packaging.impl.elements.ArchivePackagingElement;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Collections;
import java.util.List;
/**
* @author nik
@@ -32,6 +36,10 @@ public class JarArtifactType extends ArtifactType {
super("jar", "Jar");
}
public static JarArtifactType getInstance() {
return EP_NAME.findExtension(JarArtifactType.class);
}
@NotNull
@Override
public Icon getIcon() {
@@ -48,4 +56,10 @@ public class JarArtifactType extends ArtifactType {
public CompositePackagingElement<?> createRootElement(@NotNull String artifactName) {
return new ArchivePackagingElement(FileUtil.sanitizeFileName(artifactName) + ".jar");
}
@NotNull
@Override
public List<? extends ArtifactTemplate> getNewArtifactTemplates(@NotNull PackagingElementResolvingContext context) {
return Collections.singletonList(new JarFromModulesTemplate(context));
}
}
@@ -0,0 +1,179 @@
/*
* 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.packaging.impl.artifacts;
import com.intellij.CommonBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.ArtifactTemplate;
import com.intellij.packaging.elements.*;
import com.intellij.packaging.impl.elements.LibraryPackagingElement;
import com.intellij.packaging.impl.elements.ManifestFileUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.*;
/**
* @author nik
*/
public class JarFromModulesTemplate extends ArtifactTemplate {
private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.artifacts.JarFromModulesTemplate");
private PackagingElementResolvingContext myContext;
public JarFromModulesTemplate(PackagingElementResolvingContext context) {
myContext = context;
}
@Override
public NewArtifactConfiguration createArtifact() {
JarArtifactFromModulesDialog dialog = new JarArtifactFromModulesDialog(myContext);
dialog.show();
if (!dialog.isOK()) {
return null;
}
return doCreateArtifact(dialog.getSelectedModules(), dialog.getMainClassName(), dialog.getDirectoryForManifest(),
dialog.isExtractLibrariesToJar());
}
@Nullable
public NewArtifactConfiguration doCreateArtifact(final Module[] modules, final String mainClassName,
final String directoryForManifest, final boolean extractLibrariesToJar) {
VirtualFile manifestFile = null;
final Project project = myContext.getProject();
if (mainClassName != null && !mainClassName.isEmpty() || !extractLibrariesToJar) {
final VirtualFile directory;
try {
directory = VfsUtil.createDirectoryIfMissing(directoryForManifest);
}
catch (IOException e) {
LOG.info(e);
Messages.showErrorDialog(project, "Cannot create directory '" + directoryForManifest + "': " + e.getMessage(),
CommonBundle.getErrorTitle());
return null;
}
if (directory == null) return null;
manifestFile = ManifestFileUtil.createManifestFile(directory, project);
if (manifestFile == null) {
return null;
}
ManifestFileUtil.updateManifest(manifestFile, mainClassName, null, true);
}
String name = modules.length == 1 ? modules[0].getName() : project.getName();
final PackagingElementFactory factory = PackagingElementFactory.getInstance();
final CompositePackagingElement<?> archive = factory.createArchive(FileUtil.sanitizeFileName(name) + ".jar");
final OrderEnumerator orderEnumerator = ProjectRootManager.getInstance(project).orderEntries(Arrays.asList(modules));
final Set<Library> libraries = new THashSet<Library>();
orderEnumerator.using(myContext.getModulesProvider()).withoutSdk().productionOnly().runtimeOnly().recursively().forEach(new Processor<OrderEntry>() {
@Override
public boolean process(OrderEntry orderEntry) {
if (orderEntry instanceof ModuleSourceOrderEntry) {
archive.addOrFindChild(factory.createModuleOutput(orderEntry.getOwnerModule()));
}
else if (orderEntry instanceof LibraryOrderEntry) {
ContainerUtil.addIfNotNull(((LibraryOrderEntry)orderEntry).getLibrary(), libraries);
}
return true;
}
});
final JarArtifactType jarArtifactType = JarArtifactType.getInstance();
if (manifestFile != null && !manifestFile.equals(ManifestFileUtil.findManifestFile(archive, myContext, jarArtifactType))) {
archive.addFirstChild(factory.createFileCopyWithParentDirectories(manifestFile.getPath(), ManifestFileUtil.MANIFEST_DIR_NAME));
}
final String artifactName = name + ":jar";
if (extractLibrariesToJar) {
addExtractedLibrariesToJar(archive, factory, libraries);
return new NewArtifactConfiguration(archive, artifactName, jarArtifactType);
}
else {
final ArtifactRootElement<?> root = factory.createArtifactRootElement();
List<String> classpath = new ArrayList<String>();
root.addOrFindChild(archive);
addLibraries(libraries, root, archive, classpath);
ManifestFileUtil.updateManifest(manifestFile, mainClassName, classpath, true);
return new NewArtifactConfiguration(root, artifactName, PlainArtifactType.getInstance());
}
}
private void addLibraries(Set<Library> libraries, ArtifactRootElement<?> root, CompositePackagingElement<?> archive,
List<String> classpath) {
PackagingElementFactory factory = PackagingElementFactory.getInstance();
for (Library library : libraries) {
if (LibraryPackagingElement.getKindForLibrary(library).containsDirectoriesWithClasses()) {
for (VirtualFile classesRoot : library.getFiles(OrderRootType.CLASSES)) {
if (classesRoot.isInLocalFileSystem()) {
archive.addOrFindChild(factory.createDirectoryCopyWithParentDirectories(classesRoot.getPath(), "/"));
}
else {
final PackagingElement<?> child = factory.createFileCopyWithParentDirectories(PathUtil.getLocalFile(classesRoot).getPath(), "/");
root.addOrFindChild(child);
classpath.addAll(ManifestFileUtil.getClasspathForElements(Collections.singletonList(child), myContext, PlainArtifactType.getInstance()));
}
}
}
else {
final List<? extends PackagingElement<?>> children = factory.createLibraryElements(library);
classpath.addAll(ManifestFileUtil.getClasspathForElements(children, myContext, PlainArtifactType.getInstance()));
root.addOrFindChildren(children);
}
}
}
private static void addExtractedLibrariesToJar(CompositePackagingElement<?> archive, PackagingElementFactory factory, Set<Library> libraries) {
for (Library library : libraries) {
if (LibraryPackagingElement.getKindForLibrary(library).containsJarFiles()) {
for (VirtualFile classesRoot : library.getFiles(OrderRootType.CLASSES)) {
if (classesRoot.isInLocalFileSystem()) {
archive.addOrFindChild(factory.createDirectoryCopyWithParentDirectories(classesRoot.getPath(), "/"));
}
else {
archive.addOrFindChild(factory.createExtractedDirectory(classesRoot));
}
}
}
else {
archive.addOrFindChildren(factory.createLibraryElements(library));
}
}
}
@Override
public String getPresentableName() {
return "From modules with dependencies...";
}
}
@@ -21,7 +21,6 @@ import com.intellij.packaging.artifacts.ArtifactType;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElementOutputKind;
import com.intellij.packaging.impl.elements.ArtifactRootElementImpl;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -35,7 +34,7 @@ public class PlainArtifactType extends ArtifactType {
@NonNls public static final String ID = "plain";
public static PlainArtifactType getInstance() {
return ContainerUtil.findInstance(getAllTypes(), PlainArtifactType.class);
return EP_NAME.findExtension(PlainArtifactType.class);
}
public PlainArtifactType() {
@@ -15,7 +15,7 @@
*/
package com.intellij.packaging.impl.compiler;
import com.intellij.compiler.impl.newApi.BuildTarget;
import com.intellij.openapi.compiler.generic.BuildTarget;
import com.intellij.packaging.artifacts.Artifact;
import org.jetbrains.annotations.NotNull;
@@ -15,7 +15,7 @@
*/
package com.intellij.packaging.impl.compiler;
import com.intellij.compiler.impl.newApi.VirtualFileCompileItem;
import com.intellij.openapi.compiler.generic.VirtualFileCompileItem;
import com.intellij.compiler.impl.packagingCompiler.DestinationInfo;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
@@ -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,12 +15,8 @@
*/
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.openapi.compiler.generic.*;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
@@ -35,12 +31,12 @@ import java.util.Set;
/**
* @author nik
*/
public class ArtifactsCompiler extends NewCompiler<String, ArtifactPackagingItemOutputState> {
public class ArtifactsCompiler extends GenericCompiler<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");
public ArtifactsCompiler() {
super("artifacts_compiler", 0, NewCompiler.CompileOrderPlace.PACKAGING);
super("artifacts_compiler", 0, GenericCompiler.CompileOrderPlace.PACKAGING);
}
@Nullable
@@ -52,26 +48,28 @@ public class ArtifactsCompiler extends NewCompiler<String, ArtifactPackagingItem
@NotNull
@Override
public KeyDescriptor<String> getItemKeyDescriptor() {
return VirtualFileCompileItem.KEY_DESCRIPTOR;
return STRING_KEY_DESCRIPTOR;
}
@NotNull
@Override
public DataExternalizer<ArtifactPackagingItemOutputState> getItemStateExternalizer() {
return ArtifactCompilerCompileItem.OUTPUT_EXTERNALIZER;
public DataExternalizer<VirtualFilePersistentState> getSourceStateExternalizer() {
return VirtualFilePersistentState.EXTERNALIZER;
}
@NotNull
@Override
public CompilerInstance<ArtifactBuildTarget, ? extends CompileItem<String, ArtifactPackagingItemOutputState>, String, ArtifactPackagingItemOutputState> createInstance(
public DataExternalizer<ArtifactPackagingItemOutputState> getOutputStateExternalizer() {
return new ArtifactPackagingItemExternalizer();
}
@NotNull
@Override
public GenericCompilerInstance<ArtifactBuildTarget, ? extends CompileItem<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState>, String, VirtualFilePersistentState, ArtifactPackagingItemOutputState> createInstance(
@NotNull CompileContext context) {
return new ArtifactsCompilerInstance(context);
}
public boolean validateConfiguration(final CompileScope scope) {
return true;
}
@NotNull
public String getDescription() {
return "Artifacts Packaging Compiler";
@@ -17,7 +17,10 @@ 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.openapi.compiler.generic.GenericCompilerCacheState;
import com.intellij.openapi.compiler.generic.GenericCompilerInstance;
import com.intellij.openapi.compiler.generic.GenericCompilerProcessingItem;
import com.intellij.openapi.compiler.generic.VirtualFilePersistentState;
import com.intellij.compiler.impl.packagingCompiler.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
@@ -31,7 +34,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;
@@ -59,8 +62,8 @@ import java.util.*;
/**
* @author nik
*/
public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTarget, ArtifactCompilerCompileItem,
String, ArtifactPackagingItemOutputState> {
public class ArtifactsCompilerInstance extends GenericCompilerInstance<ArtifactBuildTarget, ArtifactCompilerCompileItem,
String, VirtualFilePersistentState, ArtifactPackagingItemOutputState> {
private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.compiler.ArtifactsCompilerInstance");
private ArtifactsProcessingItemsBuilderContext myBuilderContext;
@@ -117,8 +120,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<GenericCompilerCacheState<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState>> obsoleteItems) {
deleteFiles(obsoleteItems, Collections.<GenericCompilerProcessingItem<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState>>emptyList());
}
@NotNull
@@ -160,7 +164,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<GenericCompilerProcessingItem<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 +183,8 @@ public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTar
}
int i = 0;
for (final Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState> item : changedItems) {
final ArtifactCompilerCompileItem sourceItem = item.getFirst();
for (final GenericCompilerProcessingItem<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState> item : changedItems) {
final ArtifactCompilerCompileItem sourceItem = item.getItem();
myContext.getProgressIndicator().checkCanceled();
final Ref<IOException> exception = Ref.create(null);
@@ -304,9 +308,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<GenericCompilerProcessingItem<ArtifactCompilerCompileItem,VirtualFilePersistentState,ArtifactPackagingItemOutputState>> changedItems,
@NotNull List<GenericCompilerCacheState<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState>> obsoleteItems,
@NotNull OutputConsumer<ArtifactCompilerCompileItem> consumer) {
final THashSet<String> deletedJars = deleteFiles(obsoleteItems, changedItems);
@@ -333,8 +338,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<GenericCompilerCacheState<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState>> obsoleteItems,
List<GenericCompilerProcessingItem<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState>> changedItems) {
myContext.getProgressIndicator().setText(CompilerBundle.message("packaging.compiler.message.deleting.outdated.files"));
final boolean testMode = ApplicationManager.getApplication().isUnitTestMode();
@@ -345,21 +350,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 (GenericCompilerProcessingItem<ArtifactCompilerCompileItem, VirtualFilePersistentState, ArtifactPackagingItemOutputState> item : changedItems) {
final ArtifactPackagingItemOutputState cached = item.getCachedOutputState();
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 (GenericCompilerProcessingItem<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 (GenericCompilerCacheState<String, VirtualFilePersistentState, ArtifactPackagingItemOutputState> item : obsoleteItems) {
for (Pair<String, Long> destination : item.getOutputState().myDestinations) {
pathToDelete.add(destination.getFirst());
}
}
@@ -40,7 +40,7 @@ public class CopyToDirectoryInstructionCreator extends IncrementalCompilerInstru
myContext.addDestination(file, new ExplodedDestinationInfo(myOutputPath + "/" + outputFileName, outputChild(outputFileName)));
}
public IncrementalCompilerInstructionCreator subFolder(@NotNull String directoryName) {
public CopyToDirectoryInstructionCreator subFolder(@NotNull String directoryName) {
return new CopyToDirectoryInstructionCreator(myContext, myOutputPath + "/" + directoryName, outputChild(directoryName));
}
@@ -15,11 +15,13 @@
*/
package com.intellij.packaging.impl.compiler;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.packaging.elements.PackagingFileFilter;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.elements.IncrementalCompilerInstructionCreator;
import com.intellij.packaging.elements.PackagingFileFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,23 +42,41 @@ public abstract class IncrementalCompilerInstructionCreatorBase implements Incre
}
public void addDirectoryCopyInstructions(@NotNull VirtualFile directory, @Nullable PackagingFileFilter filter) {
ProjectFileIndex index = ProjectRootManager.getInstance(myContext.getCompileContext().getProject()).getFileIndex();
final boolean copyExcluded = index.isIgnored(directory);
collectInstructionsRecursively(directory, filter, index, FileTypeManager.getInstance(), copyExcluded);
}
private void collectInstructionsRecursively(VirtualFile directory,
PackagingFileFilter filter,
ProjectFileIndex index,
final FileTypeManager fileTypeManager,
boolean copyExcluded) {
final VirtualFile[] children = directory.getChildren();
if (children != null) {
final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
for (VirtualFile child : children) {
if (!fileTypeManager.isFileIgnored(child.getName())
&& (filter == null || filter.accept(child, myContext.getCompileContext()))) {
if (copyExcluded) {
if (fileTypeManager.isFileIgnored(child.getName())) continue;
}
else {
if (index.isIgnored(child)) continue;
}
if ((filter == null || filter.accept(child, myContext.getCompileContext()))) {
if (!child.isDirectory()) {
addFileCopyInstruction(child, child.getName());
}
else {
subFolder(child.getName()).addDirectoryCopyInstructions(child, filter);
subFolder(child.getName()).collectInstructionsRecursively(child, filter, index, fileTypeManager, copyExcluded);
}
}
}
}
}
@Override
public abstract IncrementalCompilerInstructionCreatorBase subFolder(@NotNull String directoryName);
public IncrementalCompilerInstructionCreator subFolderByRelativePath(@NotNull String relativeDirectoryPath) {
final List<String> folders = StringUtil.split(relativeDirectoryPath, "/");
IncrementalCompilerInstructionCreator current = this;
@@ -49,7 +49,7 @@ public class PackIntoArchiveInstructionCreator extends IncrementalCompilerInstru
return myPathInJar.length() == 0 ? fileName : myPathInJar + "/" + fileName;
}
public IncrementalCompilerInstructionCreator subFolder(@NotNull String directoryName) {
public PackIntoArchiveInstructionCreator subFolder(@NotNull String directoryName) {
return new PackIntoArchiveInstructionCreator(myContext, myJarInfo, childPathInJar(directoryName), myJarDestination);
}
@@ -30,7 +30,7 @@ public class SkipAllInstructionCreator extends IncrementalCompilerInstructionCre
public void addFileCopyInstruction(@NotNull VirtualFile file, @NotNull String outputFileName) {
}
public IncrementalCompilerInstructionCreator subFolder(@NotNull String directoryName) {
public SkipAllInstructionCreator subFolder(@NotNull String directoryName) {
return this;
}
@@ -20,10 +20,11 @@ import com.intellij.openapi.fileChooser.FileChooserDialog;
import com.intellij.openapi.fileChooser.FileChooserFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.elements.PackagingElementFactory;
import com.intellij.packaging.elements.PackagingElementType;
import com.intellij.packaging.ui.ArtifactEditorContext;
import org.jetbrains.annotations.NotNull;
@@ -53,7 +54,7 @@ public class ExtractedDirectoryElementType extends PackagingElementType<Extracte
}
@NotNull
public List<? extends ExtractedDirectoryPackagingElement> chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact,
public List<? extends PackagingElement<?>> chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact,
@NotNull CompositePackagingElement<?> parent) {
final FileChooserDescriptor descriptor = new FileChooserDescriptor(false, true, true, false, true, true) {
@Override
@@ -64,11 +65,10 @@ public class ExtractedDirectoryElementType extends PackagingElementType<Extracte
};
final FileChooserDialog chooser = FileChooserFactory.getInstance().createFileChooser(descriptor, context.getProject());
final VirtualFile[] files = chooser.choose(null, context.getProject());
final List<ExtractedDirectoryPackagingElement> list = new ArrayList<ExtractedDirectoryPackagingElement>();
final List<PackagingElement<?>> list = new ArrayList<PackagingElement<?>>();
final PackagingElementFactory factory = PackagingElementFactory.getInstance();
for (VirtualFile file : files) {
final String fullPath = file.getPath();
final int jarEnd = fullPath.indexOf(JarFileSystem.JAR_SEPARATOR);
list.add(new ExtractedDirectoryPackagingElement(fullPath.substring(0, jarEnd), fullPath.substring(jarEnd + 1)));
list.add(factory.createExtractedDirectory(file));
}
return list;
}
@@ -63,6 +63,11 @@ public class ExtractedDirectoryPackagingElement extends FileOrDirectoryCopyPacka
return new ExtractedDirectoryPresentation(this);
}
@Override
public String toString() {
return "extracted:" + myFilePath + "!" + myPathInJar;
}
@Override
public VirtualFile findFile() {
final VirtualFile jarFile = super.findFile();
@@ -16,6 +16,9 @@
package com.intellij.packaging.impl.elements;
import com.intellij.CommonBundle;
import com.intellij.ide.util.TreeClassChooser;
import com.intellij.ide.util.TreeClassChooserFactory;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.compiler.make.ManifestBuilder;
@@ -24,9 +27,12 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -42,10 +48,16 @@ import com.intellij.packaging.impl.artifacts.PackagingElementPath;
import com.intellij.packaging.impl.artifacts.PackagingElementProcessor;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.packaging.ui.ManifestFileConfiguration;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiMethodUtil;
import com.intellij.util.PathUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -111,7 +123,18 @@ public class ManifestFileUtil {
}
@Nullable
private static VirtualFile suggestBaseDir(Project project, final @Nullable VirtualFile file) {
public static VirtualFile suggestManifestFileDirectory(@NotNull Project project, @Nullable Module module) {
OrderEnumerator enumerator = module != null ? OrderEnumerator.orderEntries(module) : OrderEnumerator.orderEntries(project);
final VirtualFile[] files = enumerator.withoutDepModules().withoutLibraries().withoutSdk().productionOnly().sources().getRoots();
if (files.length > 0) {
return files[0];
}
return suggestBaseDir(project, null);
}
@Nullable
private static VirtualFile suggestBaseDir(@NotNull Project project, final @Nullable VirtualFile file) {
final VirtualFile[] contentRoots = ProjectRootManager.getInstance(project).getContentRoots();
if (file == null && contentRoots.length > 0) {
return contentRoots[0];
@@ -145,7 +168,7 @@ public class ManifestFileUtil {
}
}
public static void updateManifest(VirtualFile file, final String mainClass, final List<String> classpath, final boolean replaceValues) {
public static void updateManifest(@NotNull VirtualFile file, final @Nullable String mainClass, final @Nullable List<String> classpath, final boolean replaceValues) {
final Manifest manifest = readManifest(file);
final Attributes mainAttributes = manifest.getMainAttributes();
@@ -235,18 +258,23 @@ public class ManifestFileUtil {
@Nullable
public static VirtualFile showDialogAndCreateManifest(final ArtifactEditorContext context, final CompositePackagingElement<?> element) {
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
descriptor.setTitle("Select Directory for META-INF/MANIFEST.MF file");
FileChooserDescriptor descriptor = createDescriptorForManifestDirectory();
final VirtualFile directory = suggestManifestFileDirectory(element, context, context.getArtifactType());
final VirtualFile[] files = FileChooser.chooseFiles(context.getProject(), descriptor, directory);
if (files.length != 1) {
return null;
}
return createManifestFile(files[0], context.getProject());
}
@Nullable
public static VirtualFile createManifestFile(final @NotNull VirtualFile directory, final @NotNull Project project) {
ApplicationManager.getApplication().assertIsDispatchThread();
final Ref<IOException> exc = Ref.create(null);
final VirtualFile file = new WriteAction<VirtualFile>() {
protected void run(final Result<VirtualFile> result) {
VirtualFile dir = files[0];
VirtualFile dir = directory;
try {
if (!dir.getName().equals(MANIFEST_DIR_NAME)) {
dir = VfsUtil.createDirectoryIfMissing(dir, MANIFEST_DIR_NAME);
@@ -272,12 +300,18 @@ public class ManifestFileUtil {
final IOException exception = exc.get();
if (exception != null) {
LOG.info(exception);
Messages.showErrorDialog(context.getProject(), exception.getMessage(), CommonBundle.getErrorTitle());
Messages.showErrorDialog(project, exception.getMessage(), CommonBundle.getErrorTitle());
return null;
}
return file;
}
public static FileChooserDescriptor createDescriptorForManifestDirectory() {
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
descriptor.setTitle("Select Directory for META-INF/MANIFEST.MF file");
return descriptor;
}
public static void addManifestFileToLayout(final @NotNull String path, final @NotNull ArtifactEditorContext context,
final @NotNull CompositePackagingElement<?> element) {
context.editLayout(context.getArtifact(), new Runnable() {
@@ -289,4 +323,32 @@ public class ManifestFileUtil {
}
});
}
@Nullable
public static PsiClass selectMainClass(Project project, final @Nullable String initialClassName) {
final TreeClassChooserFactory chooserFactory = TreeClassChooserFactory.getInstance(project);
final GlobalSearchScope searchScope = GlobalSearchScope.allScope(project);
final PsiClass aClass = initialClassName != null ? JavaPsiFacade.getInstance(project).findClass(initialClassName, searchScope) : null;
final TreeClassChooser chooser =
chooserFactory.createWithInnerClassesScopeChooser("Select Main Class", searchScope, new MainClassFilter(), aClass);
chooser.showDialog();
return chooser.getSelectedClass();
}
public static void setupMainClassField(final Project project, final TextFieldWithBrowseButton field) {
field.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final PsiClass selected = selectMainClass(project, field.getText());
if (selected != null) {
field.setText(selected.getQualifiedName());
}
}
});
}
private static class MainClassFilter implements TreeClassChooser.ClassFilter {
public boolean isAccepted(PsiClass aClass) {
return PsiMethodUtil.MAIN_CLASS.value(aClass) && PsiMethodUtil.hasMainMethod(aClass);
}
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.packaging.impl.elements;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModulePointer;
@@ -27,6 +28,7 @@ import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.artifacts.ArtifactPointer;
@@ -47,6 +49,7 @@ import java.util.List;
* @author nik
*/
public class PackagingElementFactoryImpl extends PackagingElementFactory {
private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.elements.PackagingElementFactoryImpl");
public static final PackagingElementType<DirectoryPackagingElement> DIRECTORY_ELEMENT_TYPE = new DirectoryElementType();
public static final PackagingElementType<ArchivePackagingElement> ARCHIVE_ELEMENT_TYPE = new ArchiveElementType();
public static final PackagingElementType<FileCopyPackagingElement> FILE_COPY_ELEMENT_TYPE = new FileCopyElementType();
@@ -261,6 +264,15 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory {
return createParentDirectories(relativeOutputPath, new ExtractedDirectoryPackagingElement(jarPath, pathInJar));
}
@NotNull
@Override
public PackagingElement<?> createExtractedDirectory(@NotNull VirtualFile jarEntry) {
LOG.assertTrue(jarEntry.getFileSystem() instanceof JarFileSystem, "Expected file from jar but file from " + jarEntry.getFileSystem() + " found");
final String fullPath = jarEntry.getPath();
final int jarEnd = fullPath.indexOf(JarFileSystem.JAR_SEPARATOR);
return new ExtractedDirectoryPackagingElement(fullPath.substring(0, jarEnd), fullPath.substring(jarEnd + 1));
}
@NotNull
@Override
public PackagingElement<?> createFileCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath) {
@@ -15,11 +15,8 @@
*/
package com.intellij.packaging.impl.ui.properties;
import com.intellij.ide.util.TreeClassChooser;
import com.intellij.ide.util.TreeClassChooserFactory;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Comparing;
@@ -31,10 +28,6 @@ import com.intellij.packaging.impl.elements.ManifestFileUtil;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.packaging.ui.ManifestFileConfiguration;
import com.intellij.packaging.ui.PackagingElementPropertiesPanel;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiMethodUtil;
import com.intellij.ui.DocumentAdapter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -67,21 +60,7 @@ public abstract class ElementWithManifestPropertiesPanel<E extends CompositeElem
myElement = element;
myContext = context;
myMainClassField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final Project project = context.getProject();
final TreeClassChooserFactory chooserFactory = TreeClassChooserFactory.getInstance(project);
final GlobalSearchScope searchScope = GlobalSearchScope.allScope(project);
final PsiClass aClass = JavaPsiFacade.getInstance(project).findClass(myMainClassField.getText(), searchScope);
final TreeClassChooser chooser =
chooserFactory.createWithInnerClassesScopeChooser("Select Main Class", searchScope, new MainClassFilter(), aClass);
chooser.showDialog();
final PsiClass selected = chooser.getSelectedClass();
if (selected != null) {
myMainClassField.setText(selected.getQualifiedName());
}
}
});
ManifestFileUtil.setupMainClassField(context.getProject(), myMainClassField);
myClasspathField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@@ -192,9 +171,4 @@ public abstract class ElementWithManifestPropertiesPanel<E extends CompositeElem
return className.length() != 0 ? className : null;
}
protected static class MainClassFilter implements TreeClassChooser.ClassFilter {
public boolean isAccepted(PsiClass aClass) {
return PsiMethodUtil.MAIN_CLASS.value(aClass) && PsiMethodUtil.hasMainMethod(aClass);
}
}
}
@@ -25,12 +25,9 @@ import java.util.ArrayList;
*/
public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcodes {
private boolean myIsModification = false;
private boolean myIsNotStaticInner = false;
private String myClassName;
private String mySuperName;
public static final String NOT_NULL = "org/jetbrains/annotations/NotNull";
public static final String NOT_NULL_ANNO = "L"+ NOT_NULL + ";";
private static final String ENUM_CLASS_NAME = "java/lang/Enum";
public static final String IAE_CLASS_NAME = "java/lang/IllegalArgumentException";
public static final String ISE_CLASS_NAME = "java/lang/IllegalStateException";
private static final String CONSTRUCTOR_NAME = "<init>";
@@ -51,14 +48,6 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode
final String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
myClassName = name;
mySuperName = superName;
}
public void visitInnerClass(final String name, final String outerName, final String innerName, final int access) {
super.visitInnerClass(name, outerName, innerName, access);
if (myClassName.equals(name)) {
myIsNotStaticInner = (access & ACC_STATIC) == 0;
}
}
public MethodVisitor visitMethod(
@@ -69,7 +58,6 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode
final String[] exceptions) {
final Type[] args = Type.getArgumentTypes(desc);
final Type returnType = Type.getReturnType(desc);
final int startParameter = getStartParameterIndex(name);
MethodVisitor v = cv.visitMethod(access,
name,
desc,
@@ -122,8 +110,8 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode
}
for (int p = 0; p < myNotNullParams.size(); ++p) {
int var = ((access & ACC_STATIC) == 0) ? 1 : 0;
int param = ((Integer)myNotNullParams.get(p)).intValue() - mySyntheticCount;
for (int i = 0; i < param + startParameter; ++i) {
int param = ((Integer)myNotNullParams.get(p)).intValue();
for (int i = 0; i < param; ++i) {
var += args[i].getSize();
}
mv.visitVarInsn(ALOAD, var);
@@ -132,7 +120,7 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode
mv.visitJumpInsn(IFNONNULL, end);
generateThrow(IAE_CLASS_NAME,
"Argument " + param + " for @NotNull parameter of " + myClassName + "." + name + " must not be null", end);
"Argument " + (param - mySyntheticCount) + " for @NotNull parameter of " + myClassName + "." + name + " must not be null", end);
}
}
@@ -192,16 +180,6 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode
};
}
private int getStartParameterIndex(final String name) {
int result = 0;
if (CONSTRUCTOR_NAME.equals(name)) {
if (myIsNotStaticInner) {
result += 1;
}
}
return result;
}
private static boolean isReferenceType(final Type type) {
return type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY;
}
@@ -48,16 +48,28 @@ public abstract class CompositePackagingElement<S> extends PackagingElement<S> i
}
}
myChildren.add(child);
myUnmodifiableChildren = null;
return child;
}
public void addFirstChild(@NotNull PackagingElement<?> child) {
myChildren.add(0, child);
for (int i = 1; i < myChildren.size(); i++) {
PackagingElement<?> element = myChildren.get(i);
if (element.isEqualTo(child)) {
if (element instanceof CompositePackagingElement<?>) {
((CompositePackagingElement<?>)child).addOrFindChildren(((CompositePackagingElement<?>)element).getChildren());
}
myChildren.remove(i);
break;
}
}
}
public List<? extends PackagingElement<?>> addOrFindChildren(Collection<? extends PackagingElement<?>> children) {
List<PackagingElement<?>> added = new ArrayList<PackagingElement<?>>();
for (PackagingElement<?> child : children) {
added.add(addOrFindChild(child));
}
myUnmodifiableChildren = null;
return added;
}
@@ -69,7 +81,6 @@ public abstract class CompositePackagingElement<S> extends PackagingElement<S> i
final PackagingElement<?> element2 = myChildren.get(target);
myChildren.set(index, element2);
myChildren.set(target, element1);
myUnmodifiableChildren = null;
return element1;
}
return null;
@@ -77,12 +88,10 @@ public abstract class CompositePackagingElement<S> extends PackagingElement<S> i
public void removeChild(@NotNull PackagingElement<?> child) {
myChildren.remove(child);
myUnmodifiableChildren = null;
}
public void removeChildren(@NotNull Collection<? extends PackagingElement<?>> children) {
myChildren.removeAll(children);
myUnmodifiableChildren = null;
}
@NotNull
@@ -117,6 +126,5 @@ public abstract class CompositePackagingElement<S> extends PackagingElement<S> i
public void removeAllChildren() {
myChildren.clear();
myUnmodifiableChildren = null;
}
}
@@ -17,8 +17,9 @@ package com.intellij.packaging.elements;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.artifacts.ArtifactPointer;
import org.jetbrains.annotations.NonNls;
@@ -71,6 +72,9 @@ public abstract class PackagingElementFactory {
public abstract PackagingElement<?> createExtractedDirectoryWithParentDirectories(@NotNull String jarPath, @NotNull String pathInJar,
@NotNull String relativeOutputPath);
@NotNull
public abstract PackagingElement<?> createExtractedDirectory(@NotNull VirtualFile jarEntry);
@NotNull
public abstract PackagingElement<?> createFileCopyWithParentDirectories(@NotNull String filePath, @NotNull String relativeOutputPath,
@Nullable String outputFileName);
@@ -189,7 +189,7 @@ public class NewProjectUtil {
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
if (openProjects.length > 0) {
int exitCode = Messages.showDialog(IdeBundle.message("prompt.open.project.in.new.frame"), IdeBundle.message("title.new.project"),
new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe")}, 1,
new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe")}, 1, 0,
Messages.getQuestionIcon());
if (exitCode == 1) { // "No" option
ProjectUtil.closeProject(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1]);
@@ -6,7 +6,7 @@
<xy x="20" y="20" width="487" height="400"/>
</constraints>
<properties/>
<border type="etched"/>
<border type="none"/>
<children>
<component id="8fe34" class="javax.swing.JLabel">
<constraints>
@@ -71,10 +71,7 @@ public class FrameworkSupportModelImpl extends UserDataHolderBase implements Fra
public void setFrameworkComponentEnabled(@NotNull @NonNls final String providerId, final boolean enable) {
final FrameworkSupportNode node = mySettingsMap.get(providerId);
if (node == null) {
throw new IllegalArgumentException("provider '" + providerId + " not found");
}
if (enable != node.isChecked()) {
if (node != null && enable != node.isChecked()) {
node.setChecked(enable);
}
}
@@ -276,11 +276,13 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
public int compare(final Object o1, final Object o2) {
final MyNode node1 = (MyNode)o1;
final MyNode node2 = (MyNode)o2;
final Object editableObject1 = node1.getConfigurable().getEditableObject();
final Object editableObject2 = node2.getConfigurable().getEditableObject();
if (editableObject1.getClass() == editableObject2.getClass()) {
final NamedConfigurable configurable1 = node1.getConfigurable();
final NamedConfigurable configurable2 = node2.getConfigurable();
if (configurable1.getClass() == configurable2.getClass()) {
return node1.getDisplayName().compareToIgnoreCase(node2.getDisplayName());
}
final Object editableObject1 = configurable1.getEditableObject();
final Object editableObject2 = configurable2.getEditableObject();
if (editableObject2 instanceof Module && editableObject1 instanceof ModuleGroup) return -1;
if (editableObject1 instanceof Module && editableObject2 instanceof ModuleGroup) return 1;
@@ -40,6 +40,8 @@ import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.projectRoots.SdkModificator;
@@ -51,6 +53,7 @@ import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -87,6 +90,7 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
private static final Logger LOG = Logger.getInstance("#" + ExternalAnnotationsManagerImpl.class.getName());
private final Map<VirtualFile, List<XmlFile>> myExternalAnotations = new ConcurrentWeakHashMap<VirtualFile, List<XmlFile>>();
private final Ref<Boolean> myHasAnyAnnotationsRoots = new Ref<Boolean>();
private static final List<XmlFile> NULL = new ArrayList<XmlFile>();
private final PsiManager myPsiManager;
@@ -99,10 +103,32 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
public void rootsChanged(ModuleRootEvent event) {
myExternalAnotations.clear();
synchronized (myHasAnyAnnotationsRoots) {
myHasAnyAnnotationsRoots.set(null);
}
}
});
}
private boolean hasAnyAnnotationsRoots() {
if (myHasAnyAnnotationsRoots.get() == null) {
synchronized (myHasAnyAnnotationsRoots) {
final Module[] modules = ModuleManager.getInstance(myPsiManager.getProject()).getModules();
for (Module module : modules) {
for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
final String[] urls = AnnotationOrderRootType.getUrls(entry);
if (urls.length > 0) {
myHasAnyAnnotationsRoots.set(Boolean.TRUE);
return true;
}
}
}
myHasAnyAnnotationsRoots.set(Boolean.FALSE);
}
}
return myHasAnyAnnotationsRoots.get();
}
@Nullable
public PsiAnnotation findExternalAnnotation(final PsiModifierListOwner listOwner, final String annotationFQN) {
return collectExternalAnnotations(listOwner).get(annotationFQN);
@@ -114,8 +140,10 @@ public class ExternalAnnotationsManagerImpl extends ExternalAnnotationsManager {
return result.isEmpty() ? null : result.values().toArray(new PsiAnnotation[result.size()]);
}
@NotNull
private Map<String, PsiAnnotation> collectExternalAnnotations(final PsiModifierListOwner listOwner) {
final Map<String, PsiAnnotation> result = new HashMap<String, PsiAnnotation>();
if (!hasAnyAnnotationsRoots()) return result;
final List<XmlFile> files = findExternalAnnotationsFile(listOwner);
if (files != null) {
for (XmlFile file : files) {
@@ -27,8 +27,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.PsiJavaPatterns;
import static com.intellij.patterns.PsiJavaPatterns.psiElement;
import static com.intellij.patterns.PsiJavaPatterns.psiMethod;
import com.intellij.patterns.PsiMethodPattern;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
@@ -51,6 +49,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.Set;
import static com.intellij.patterns.PsiJavaPatterns.psiElement;
import static com.intellij.patterns.PsiJavaPatterns.psiMethod;
/**
* @author peter
*/
@@ -378,12 +379,20 @@ public class ReferenceExpressionCompletionContributor {
return qualifier == null ? "" : qualifier.getText() + ".";
}
private static void addChainedCallVariants(final PsiElement place, final LookupElement qualifierItem,
private static void addChainedCallVariants(final PsiElement place, LookupElement qualifierItem,
final CompletionResultSet result,
PsiType qualifierType,
final PsiType expectedType, JavaSmartCompletionParameters parameters) throws IncorrectOperationException {
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(place.getProject()).getElementFactory();
final String typeText = qualifierType instanceof PsiEllipsisType ? ((PsiEllipsisType)qualifierType).getComponentType().getCanonicalText() + "[]" : qualifierType.getCanonicalText();
PsiType varType = qualifierType;
if (varType instanceof PsiEllipsisType) {
varType = ((PsiEllipsisType)varType).getComponentType();
}
if (varType instanceof PsiWildcardType) {
varType = TypeConversionUtil.erasure(expectedType);
}
final String typeText = varType.getCanonicalText();
final JavaCodeFragment block = elementFactory.createCodeBlockCodeFragment(typeText + " xxx;xxx.xxx;", place, false);
final PsiElement secondChild = block.getChildren()[1];
if (!(secondChild instanceof PsiExpressionStatement)) {
@@ -394,7 +403,7 @@ public class ReferenceExpressionCompletionContributor {
final ElementFilter filter = getReferenceFilter(place, true);
for (final LookupElement item : completeFinalReference(place, mockRef, filter, parameters)) {
if (shoudChain(place, qualifierType, expectedType, item)) {
if (shoudChain(place, varType, expectedType, item)) {
result.addElement(JavaChainLookupElement.chainElements(qualifierItem, item));
}
}
@@ -116,7 +116,7 @@ public class GenericsHighlightUtil {
final PsiTypeParameter[] typeParameters = typeParameterListOwner.getTypeParameters();
final int targetParametersNum = typeParameters.length;
final int refParametersNum = referenceParameterList == null ? 0 : referenceParameterList.getTypeParameterElements().length;
final int refParametersNum = referenceParameterList == null ? 0 : referenceParameterList.getTypeArguments().length;
if (targetParametersNum != refParametersNum && refParametersNum != 0) {
final String description;
if (targetParametersNum == 0) {
@@ -148,36 +148,18 @@ public class GenericsHighlightUtil {
// bounds check
if (targetParametersNum > 0 && refParametersNum != 0) {
final PsiTypeElement[] referenceElements = referenceParameterList.getTypeParameterElements();
for (int i = 0; i < typeParameters.length; i++) {
PsiTypeParameter classParameter = typeParameters[i];
final PsiTypeElement typeElement = referenceElements[i];
final PsiType type = typeElement.getType();
if (!(type instanceof PsiClassType)) continue;
final PsiClass referenceClass = ((PsiClassType)type).resolve();
if (referenceClass == null) continue;
final PsiClassType[] bounds = classParameter.getSuperTypes();
for (PsiClassType type1 : bounds) {
PsiType bound = substitutor.substitute(type1);
if (!TypeConversionUtil.isAssignable(bound, type, false)) {
PsiClass boundClass = bound instanceof PsiClassType ? ((PsiClassType)bound).resolve() : null;
@NonNls final String messageKey = boundClass == null || referenceClass.isInterface() == boundClass.isInterface()
? "generics.type.parameter.is.not.within.its.bound.extend"
: "generics.type.parameter.is.not.within.its.bound.implement";
String description = JavaErrorMessages.message(messageKey,
HighlightUtil.formatClass(referenceClass),
HighlightUtil.formatType(bound));
final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR,
typeElement,
description);
if (bound instanceof PsiClassType) {
QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createExtendsListFix(referenceClass, (PsiClassType)bound, true),
null);
}
return highlightInfo;
}
if (referenceElements.length == 1 && referenceElements[0].getType() instanceof PsiDiamondType) {
final PsiType[] types = ((PsiDiamondType)referenceElements[0].getType()).getInferredTypes();
for (int i = 0; i < typeParameters.length; i++) {
final PsiType type = types[i];
final HighlightInfo highlightInfo = checkTypeParameterWithinItsBound(typeParameters[i], substitutor, type, referenceElements[0]);
if (highlightInfo != null) return highlightInfo;
}
} else {
for (int i = 0; i < typeParameters.length; i++) {
final PsiTypeElement typeElement = referenceElements[i];
final HighlightInfo highlightInfo = checkTypeParameterWithinItsBound(typeParameters[i], substitutor, typeElement.getType(), typeElement);
if (highlightInfo != null) return highlightInfo;
}
}
}
@@ -185,6 +167,42 @@ public class GenericsHighlightUtil {
return null;
}
@Nullable
private static HighlightInfo checkTypeParameterWithinItsBound(final PsiTypeParameter classParameter,
final PsiSubstitutor substitutor,
final PsiType type,
final PsiElement typeElement2Highlight) {
if (!(type instanceof PsiClassType)) return null;
final PsiClass referenceClass = ((PsiClassType)type).resolve();
if (referenceClass == null) return null;
final PsiClassType[] bounds = classParameter.getSuperTypes();
for (PsiClassType type1 : bounds) {
PsiType bound = substitutor.substitute(type1);
if (!TypeConversionUtil.isAssignable(bound, type, false)) {
PsiClass boundClass = bound instanceof PsiClassType ? ((PsiClassType)bound).resolve() : null;
@NonNls final String messageKey = boundClass == null || referenceClass.isInterface() == boundClass.isInterface()
? "generics.type.parameter.is.not.within.its.bound.extend"
: "generics.type.parameter.is.not.within.its.bound.implement";
String description = JavaErrorMessages.message(messageKey,
HighlightUtil.formatClass(referenceClass),
HighlightUtil.formatType(bound));
final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR,
typeElement2Highlight,
description);
if (bound instanceof PsiClassType) {
QuickFixAction
.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createExtendsListFix(referenceClass, (PsiClassType)bound, true),
null);
}
return highlightInfo;
}
}
return null;
}
private static String typeParameterListOwnerDescription(final PsiTypeParameterListOwner typeParameterListOwner) {
if (typeParameterListOwner instanceof PsiClass) {
return HighlightUtil.formatClass((PsiClass)typeParameterListOwner);
@@ -417,7 +435,7 @@ public class GenericsHighlightUtil {
public static HighlightInfo checkReferenceTypeUsedAsTypeArgument(PsiTypeElement typeElement) {
final PsiType type = typeElement.getType();
if (type instanceof PsiPrimitiveType ||
if (type != PsiType.NULL && type instanceof PsiPrimitiveType ||
type instanceof PsiWildcardType && ((PsiWildcardType)type).getBound() instanceof PsiPrimitiveType) {
final PsiElement element = new PsiMatcherImpl(typeElement)
.parent(PsiMatchers.hasClass(PsiReferenceParameterList.class))
@@ -579,7 +579,30 @@ public class HighlightMethodUtil {
}
private static String esctrim(@NotNull String s) {
return XmlStringUtil.escapeString(StringUtil.first(s, 40, true));
return XmlStringUtil.escapeString(trimNicely(s));
}
private static String trimNicely(String s) {
if (s.length() <= 40) return s;
List<TextRange> wordIndices = StringUtil.getWordIndicesIn(s);
if (wordIndices.size() > 2) {
int firstWordEnd = wordIndices.get(0).getEndOffset();
// try firstWord...remainder
for (int i = 1; i<wordIndices.size();i++) {
int stringLength = firstWordEnd + s.length() - wordIndices.get(i).getStartOffset();
if (stringLength <= 40) {
return s.substring(0, firstWordEnd) + "..." + s.substring(wordIndices.get(i).getStartOffset());
}
}
}
// maybe one last word will fit?
if (!wordIndices.isEmpty() && s.length() - wordIndices.get(wordIndices.size()-1).getStartOffset() <= 40) {
return "..." + s.substring(wordIndices.get(wordIndices.size()-1).getStartOffset());
}
return StringUtil.last(s, 40, true).toString();
}
private static String createMismatchedArgumentsHtmlTooltip(PsiExpressionList list,
@@ -615,7 +638,8 @@ public class HighlightMethodUtil {
for (int i = 0; i < Math.max(parameters.length,expressions.length); i++) {
PsiParameter parameter = i < parameters.length ? parameters[i] : null;
PsiExpression expression = i < expressions.length ? expressions[i] : null;
@NonNls String mismatchColor = showShortType(i, parameters, expressions, substitutor) ? null : "red";
boolean showShort = showShortType(i, parameters, expressions, substitutor);
@NonNls String mismatchColor = showShort ? null : "red";
s += "<tr" + (i % 2 == 0 ? " style='background-color: #eeeeee'" : "") + ">";
s += "<td><b><nobr>";
@@ -631,9 +655,7 @@ public class HighlightMethodUtil {
if (parameter != null) {
PsiType type = substitutor.substitute(parameter.getType());
s += "<font " + (mismatchColor == null ? "" : "color=" + mismatchColor) + ">" +
esctrim(showShortType(i, parameters, expressions, substitutor)
? type.getPresentableText()
: HighlightUtil.formatType(type))
esctrim(showShort ? type.getPresentableText() : HighlightUtil.formatType(type))
+ "</font>"
;
}
@@ -666,12 +688,11 @@ public class HighlightMethodUtil {
PsiExpression expression = expressions[i];
PsiType type = expression.getType();
@NonNls String mismatchColor = showShortType(i, parameters, expressions, substitutor) ? null : "red";
boolean showShort = showShortType(i, parameters, expressions, substitutor);
@NonNls String mismatchColor = showShort ? null : "red";
ms += "<td> " + "<b><nobr>" + (i == 0 ? "(" : "")
+ "<font " + (mismatchColor == null ? "" : "color=" + mismatchColor) + ">" +
XmlStringUtil.escapeString(showShortType(i, parameters, expressions, substitutor)
? type.getPresentableText()
: HighlightUtil.formatType(type))
+ "<font " + (showShort ? "" : "color=" + mismatchColor) + ">" +
XmlStringUtil.escapeString(showShort ? type.getPresentableText() : HighlightUtil.formatType(type))
+ "</font>"
+ (i == expressions.length - 1 ? ")" : ",") + "</nobr></b></td>";
}
@@ -1263,9 +1284,12 @@ public class HighlightMethodUtil {
return;
}
highlightInfo = GenericsHighlightUtil.checkGenericCallWithRawArguments(result, (PsiCallExpression)constructorCall);
}
if (highlightInfo != null) {
holder.add(highlightInfo);
if (highlightInfo != null) {
holder.add(highlightInfo);
}
if (PsiUtil.isLanguageLevel7OrHigher(constructorCall)) {
//check if not diamand - apply corresponding fix
}
}
}
}
@@ -49,12 +49,13 @@ public class CreateClassFromUsageFix extends CreateClassFromUsageBaseFix {
assert element != null;
if (!CodeInsightUtilBase.preparePsiElementForWrite(element)) return;
final String superClassName = getSuperClassName(element);
final PsiClass aClass = CreateFromUsageUtils.createClass(element, myKind, superClassName);
if (aClass == null) return;
ApplicationManager.getApplication().runWriteAction(
new Runnable() {
public void run() {
PsiJavaCodeReferenceElement refElement = element;
final PsiClass aClass = CreateFromUsageUtils.createClass(refElement, myKind, superClassName);
if (aClass == null) return;
try {
refElement = (PsiJavaCodeReferenceElement)refElement.bindToElement(aClass);
}
@@ -31,6 +31,7 @@ import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.HashMap;
@@ -196,11 +197,10 @@ public class GenerateMembersUtil {
return null;
}
public static PsiMethod substituteGenericMethod(PsiMethod method, PsiSubstitutor substitutor) {
public static PsiMethod substituteGenericMethod(PsiMethod method, final PsiSubstitutor substitutor) {
Project project = method.getProject();
PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
final PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
PsiTypeParameter[] typeParams = method.getTypeParameters();
try {
PsiType returnType = method.getReturnType();
@@ -263,8 +263,20 @@ public class GenerateMembersUtil {
newMethod.getParameterList().add(newParameter);
}
for (PsiTypeParameter typeParam : typeParams) {
if (substitutor.substitute(typeParam) != null) newMethod.getTypeParameterList().add(typeParam);
for (PsiTypeParameter typeParam : method.getTypeParameters()) {
final PsiElement copy = typeParam.copy();
final Map<PsiElement, PsiElement> replacementMap = new HashMap<PsiElement, PsiElement>();
copy.accept(new JavaRecursiveElementWalkingVisitor(){
@Override
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
final PsiElement resolve = reference.resolve();
if (resolve instanceof PsiTypeParameter) {
replacementMap.put(reference, factory.createReferenceElementByType((PsiClassType)substitutor.substitute((PsiTypeParameter)resolve)));
}
}
});
newMethod.getTypeParameterList().add(RefactoringUtil.replaceElementsWithMap(copy, replacementMap));
}
PsiClassType[] thrownTypes = method.getThrowsList().getReferencedTypes();
@@ -110,7 +110,7 @@ public class CreateClassDialog extends DialogWrapper {
gbConstraints.weightx = 0;
gbConstraints.gridwidth = 1;
panel.add(myInformationLabel, gbConstraints);
panel.setBorder(IdeBorderFactory.createBorder());
panel.setBorder(IdeBorderFactory.createRoundedBorder());
gbConstraints.insets = new Insets(4, 8, 4, 8);
gbConstraints.gridx = 1;
gbConstraints.weightx = 1;
@@ -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);
}
}
@@ -103,15 +103,15 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool {
@NonNls private static final String COMMENT = "comment";
@NonNls private static final String [] HINTS = {COMMENT, DELETE};
public final UnusedCodeExtension[] myExtensions;
public final EntryPoint[] myExtensions;
public UnusedDeclarationInspection() {
ContainerUtil.addAll(ADDITIONAL_ANNOTATIONS, ADDITIONAL_ANNOS);
myQuickFixActions = new QuickFixAction[]{new PermanentDeleteAction(), new CommentOutBin(), new MoveToEntries()};
ExtensionPoint<UnusedCodeExtension> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.DEAD_CODE_TOOL);
final UnusedCodeExtension[] deadCodeAddins = point.getExtensions();
Arrays.sort(deadCodeAddins, new Comparator<UnusedCodeExtension>() {
public int compare(final UnusedCodeExtension o1, final UnusedCodeExtension o2) {
ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.DEAD_CODE_TOOL);
final EntryPoint[] deadCodeAddins = point.getExtensions();
Arrays.sort(deadCodeAddins, new Comparator<EntryPoint>() {
public int compare(final EntryPoint o1, final EntryPoint o2) {
return o1.getDisplayName().compareToIgnoreCase(o2.getDisplayName());
}
});
@@ -168,7 +168,7 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool {
gc.gridy++;
add(myServletToEntries, gc);
for (final UnusedCodeExtension extension : myExtensions) {
for (final EntryPoint extension : myExtensions) {
if (extension.showUI()) {
final JCheckBox extCheckbox = new JCheckBox(extension.getDisplayName());
extCheckbox.setSelected(extension.isSelected());
@@ -242,14 +242,14 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool {
public void readSettings(Element node) throws InvalidDataException {
super.readSettings(node);
for (UnusedCodeExtension extension : myExtensions) {
for (EntryPoint extension : myExtensions) {
extension.readExternal(node);
}
}
public void writeSettings(Element node) throws WriteExternalException {
super.writeSettings(node);
for (UnusedCodeExtension extension : myExtensions) {
for (EntryPoint extension : myExtensions) {
extension.writeExternal(node);
}
}
@@ -416,8 +416,8 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool {
&& AnnotationUtil.isAnnotated((PsiModifierListOwner)element, ADDITIONAL_ANNOTATIONS)) {
return true;
}
for (UnusedCodeExtension extension : myExtensions) {
if (extension.isEntryPoint(owner)) {
for (EntryPoint extension : myExtensions) {
if (extension.isEntryPoint(owner, element)) {
return true;
}
}
@@ -454,7 +454,7 @@ public class UnusedDeclarationInspection extends FilteringInspectionTool {
&& AnnotationUtil.checkAnnotatedUsingPatterns((PsiModifierListOwner)element, ADDITIONAL_ANNOTATIONS)) {
return true;
}
for (UnusedCodeExtension extension : myExtensions) {
for (EntryPoint extension : myExtensions) {
if (extension.isEntryPoint(element)) {
return true;
}
@@ -173,6 +173,7 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
final PsiClass applet = getRefJavaManager().getApplet();
setApplet(applet != null && psiClass.isInheritor(applet, true));
getRefManager().fireNodeInitialized(this);
getRefManager().getPsiManager().dropResolveCaches();
}
private void initializeSuperReferences(PsiClass psiClass) {
@@ -23,7 +23,7 @@ import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
import com.intellij.codeInspection.deadCode.UnusedCodeExtension;
import com.intellij.codeInspection.reference.EntryPoint;
import com.intellij.codeInspection.ex.UnfairLocalInspectionTool;
import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
import com.intellij.openapi.extensions.Extensions;
@@ -170,7 +170,7 @@ public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool imp
if (annotations == null) {
annotations = new ArrayList<String>();
for (Object extension : Extensions.getExtensions(ExtensionPoints.DEAD_CODE_TOOL)) {
final String[] ignoredAnnotations = ((UnusedCodeExtension)extension).getIgnoreAnnotations();
final String[] ignoredAnnotations = ((EntryPoint)extension).getIgnoreAnnotations();
if (ignoredAnnotations != null) {
ContainerUtil.addAll(annotations, ignoredAnnotations);
}
@@ -42,7 +42,6 @@ import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.VisibilityUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -60,6 +59,9 @@ public class VisibilityInspection extends GlobalJavaInspectionTool {
public boolean SUGGEST_PRIVATE_FOR_INNERS = false;
private static final String DISPLAY_NAME = InspectionsBundle.message("inspection.visibility.display.name");
@NonNls private static final String SHORT_NAME = "WeakerAccess";
private static final String CAN_BE_PRIVATE = InspectionsBundle.message("inspection.visibility.compose.suggestion", "private");
private static final String CAN_BE_PACKAGE_LOCAL = InspectionsBundle.message("inspection.visibility.compose.suggestion", "package local");
private static final String CAN_BE_PROTECTED = InspectionsBundle.message("inspection.visibility.compose.suggestion", "protected");
private class OptionsPanel extends JPanel {
private final JCheckBox myPackageLocalForMembersCheckbox;
@@ -174,11 +176,15 @@ public class VisibilityInspection extends GlobalJavaInspectionTool {
if (refClass.isInterface()) return null;
}
@Modifier String access = getPossibleAccess(refElement);
if (access != refElement.getAccessModifier()) {
if (access != refElement.getAccessModifier() && access != null) {
final PsiElement psiElement = HighlightUsagesHandler.getNameIdentifier(refElement.getElement());
if (psiElement != null) {
return new ProblemDescriptor[]{manager.createProblemDescriptor(psiElement,
InspectionsBundle.message("inspection.visibility.compose.suggestion", VisibilityUtil.toPresentableText(access)),
access.equals(PsiModifier.PRIVATE)
? CAN_BE_PRIVATE
: access.equals(PsiModifier.PACKAGE_LOCAL)
? CAN_BE_PACKAGE_LOCAL
: CAN_BE_PROTECTED,
new AcceptSuggestedAccess(globalContext.getRefManager(), access),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false)};
}
@@ -588,7 +588,8 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{
};
if (element instanceof PsiMethod) {
final boolean strictSignatureSearch = !((JavaMethodFindUsagesOptions)options).isIncludeOverloadUsages;
final boolean strictSignatureSearch = !(options instanceof JavaMethodFindUsagesOptions) || // field with getter
!((JavaMethodFindUsagesOptions)options).isIncludeOverloadUsages;
MethodReferencesSearch.search(new MethodReferencesSearch.SearchParameters((PsiMethod)element, searchScope, strictSignatureSearch, options.fastTrack)).forEach(consumer);
} else {
ReferencesSearch.search(new ReferencesSearch.SearchParameters(element, searchScope, false, options.fastTrack)).forEach(consumer);
@@ -84,20 +84,20 @@ public class TreeClassChooserDialog extends DialogWrapper implements TreeClassCh
this(title, project, null);
}
public TreeClassChooserDialog(String title, Project project, PsiClass initialClass) {
public TreeClassChooserDialog(String title, Project project, @Nullable PsiClass initialClass) {
this(title, project, GlobalSearchScope.projectScope(project), null, initialClass);
}
public TreeClassChooserDialog(String title, Project project, GlobalSearchScope scope, ClassFilter classFilter, PsiClass initialClass) {
public TreeClassChooserDialog(String title, Project project, GlobalSearchScope scope, @Nullable ClassFilter classFilter, @Nullable PsiClass initialClass) {
this(title, project, scope, classFilter, null, initialClass, PsiClassChildrenSource.NONE);
}
public TreeClassChooserDialog(String title,
Project project,
GlobalSearchScope scope,
ClassFilter classFilter,
@Nullable ClassFilter classFilter,
PsiClass baseClass,
PsiClass initialClass,
@Nullable PsiClass initialClass,
PsiClassChildrenSource classChildrens) {
super(project, true);
myScope = scope;
@@ -119,7 +119,7 @@ public class TreeClassChooserDialog extends DialogWrapper implements TreeClassCh
Project project,
GlobalSearchScope scope,
final ClassFilter classFilter,
PsiClass initialClass) {
@Nullable PsiClass initialClass) {
return new TreeClassChooserDialog(title, project, scope, classFilter, null, initialClass, new PsiClassChildrenSource() {
public void addChildren(PsiClass psiClass, List<PsiElement> children) {
ArrayList<PsiElement> innerClasses = new ArrayList<PsiElement>();
@@ -15,9 +15,12 @@
*/
package com.intellij.lang.java;
import com.intellij.lang.CodeDocumentationAwareCommenter;
import com.intellij.lang.ASTNode;
import com.intellij.lang.CodeDocumentationAwareCommenterEx;
import com.intellij.psi.JavaDocTokenType;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.JavaDocElementType;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.tree.IElementType;
@@ -26,7 +29,7 @@ import org.jetbrains.annotations.Nullable;
/**
* @author max
*/
public class JavaCommenter implements CodeDocumentationAwareCommenter {
public class JavaCommenter implements CodeDocumentationAwareCommenterEx {
public String getLineCommentPrefix() {
return "//";
@@ -78,4 +81,10 @@ public class JavaCommenter implements CodeDocumentationAwareCommenter {
public boolean isDocumentationComment(final PsiComment element) {
return element instanceof PsiDocComment;
}
public boolean isDocumentationCommentText(final PsiElement element) {
if (element == null) return false;
final ASTNode node = element.getNode();
return node != null && node.getElementType() == JavaDocTokenType.DOC_COMMENT_DATA;
}
}
@@ -64,7 +64,7 @@ public class DeclarationParser {
@Nullable
private static PsiBuilder.Marker parseClassFromKeyword(final PsiBuilder builder, final PsiBuilder.Marker declaration,
final boolean isAnnotation) {
final boolean isAnnotation, final Context context) {
final IElementType keywordTokenType = builder.getTokenType();
assert ElementType.CLASS_KEYWORD_BIT_SET.contains(keywordTokenType) : keywordTokenType;
builder.advanceLexer();
@@ -88,7 +88,33 @@ public class DeclarationParser {
error.error(JavaErrorMessages.message("expected.lbrace"));
}
parseClassBodyWithBraces(builder, isAnnotation, isEnum);
if (builder.getTokenType() == JavaTokenType.LBRACE) {
parseClassBodyWithBraces(builder, isAnnotation, isEnum);
}
if (context == Context.FILE) {
boolean declarationsAfterEnd = false;
while (builder.getTokenType() != null && builder.getTokenType() != JavaTokenType.RBRACE) {
final PsiBuilder.Marker position = builder.mark();
final PsiBuilder.Marker extra = parse(builder, Context.CLASS);
if (extra != null && AFTER_END_DECLARATION_SET.contains(exprType(extra))) {
if (!declarationsAfterEnd) {
error(builder, JavaErrorMessages.message("expected.class.or.interface"), extra);
}
declarationsAfterEnd = true;
position.drop();
}
else {
position.rollbackTo();
break;
}
}
if (declarationsAfterEnd) {
expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
}
}
declaration.done(JavaElementType.CLASS);
return declaration;
@@ -220,7 +246,8 @@ public class DeclarationParser {
if (expect(builder, JavaTokenType.AT)) {
if (builder.getTokenType() == JavaTokenType.INTERFACE_KEYWORD) {
return parseClassFromKeyword(builder, declaration, true);
final PsiBuilder.Marker result = parseClassFromKeyword(builder, declaration, true, context);
return result != null ? result : modList;
}
else {
declaration.rollbackTo();
@@ -228,32 +255,8 @@ public class DeclarationParser {
}
}
else if (ElementType.CLASS_KEYWORD_BIT_SET.contains(builder.getTokenType())) {
final PsiBuilder.Marker root = parseClassFromKeyword(builder, declaration, false);
if (context == Context.FILE) {
// todo: append following declarations to root (?)
boolean declarationsAfterEnd = false;
while (builder.getTokenType() != null && builder.getTokenType() != JavaTokenType.RBRACE) {
final PsiBuilder.Marker position = builder.mark();
final PsiBuilder.Marker element = parse(builder, Context.CLASS);
if (element != null && AFTER_END_DECLARATION_SET.contains(exprType(element))) {
if (!declarationsAfterEnd) {
element.precede().error(JavaErrorMessages.message("expected.class.or.interface"));
}
declarationsAfterEnd = true;
position.drop();
}
else {
position.rollbackTo();
break;
}
}
if (declarationsAfterEnd) {
expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
}
}
return root;
final PsiBuilder.Marker result = parseClassFromKeyword(builder, declaration, false, context);
return result != null ? result : modList;
}
PsiBuilder.Marker typeParams = null;
@@ -444,6 +447,7 @@ public class DeclarationParser {
builder.advanceLexer();
PsiBuilder.Marker invalidElements = null;
String errorMessage = null;
boolean commaExpected = false;
int paramCount = 0;
while (true) {
@@ -453,8 +457,19 @@ public class DeclarationParser {
if (noLastParam) {
error(builder, JavaErrorMessages.message("expected.identifier.or.type"));
}
if (!expect(builder, JavaTokenType.RPARENTH)) {
if (tokenType == JavaTokenType.RPARENTH) {
if (invalidElements != null) {
invalidElements.error(errorMessage);
}
invalidElements = null;
builder.advanceLexer();
}
else {
if (!noLastParam) {
if (invalidElements != null) {
invalidElements.error(errorMessage);
}
invalidElements = null;
error(builder, JavaErrorMessages.message("expected.rparen"));
}
}
@@ -465,7 +480,7 @@ public class DeclarationParser {
if (builder.getTokenType() == JavaTokenType.COMMA) {
commaExpected = false;
if (invalidElements != null) {
invalidElements.error(JavaErrorMessages.message("expected.parameter"));
invalidElements.error(errorMessage);
invalidElements = null;
}
builder.advanceLexer();
@@ -477,7 +492,7 @@ public class DeclarationParser {
if (param != null) {
commaExpected = true;
if (invalidElements != null) {
invalidElements.errorBefore(JavaErrorMessages.message("expected.comma"), param);
invalidElements.errorBefore(errorMessage, param);
invalidElements = null;
}
paramCount++;
@@ -493,6 +508,7 @@ public class DeclarationParser {
}
else {
invalidElements = builder.mark();
errorMessage = commaExpected ? JavaErrorMessages.message("expected.comma") : JavaErrorMessages.message("expected.parameter");
}
}
@@ -504,7 +520,7 @@ public class DeclarationParser {
}
if (invalidElements != null) {
invalidElements.error(commaExpected ? JavaErrorMessages.message("expected.comma") : JavaErrorMessages.message("expected.parameter"));
invalidElements.error(errorMessage);
}
paramList.done(JavaElementType.PARAMETER_LIST);
@@ -537,7 +553,7 @@ public class DeclarationParser {
else {
error(builder, JavaErrorMessages.message("expected.identifier"));
param.drop();
return type;
return modListInfo.first;
}
}
@@ -726,8 +742,8 @@ public class DeclarationParser {
PsiBuilder.Marker pair = builder.mark();
if (mayBeSimple) {
final PsiBuilder.Marker value = parseAnnotationValue(builder);
if (value != null && builder.getTokenType() != JavaTokenType.EQ) {
parseAnnotationValue(builder);
if (builder.getTokenType() != JavaTokenType.EQ) {
pair.done(JavaElementType.NAME_VALUE_PAIR);
return false;
}
@@ -747,9 +763,9 @@ public class DeclarationParser {
return hasName;
}
@Nullable
@NotNull
private static PsiBuilder.Marker parseAnnotationValue(final PsiBuilder builder) {
final PsiBuilder.Marker result;
PsiBuilder.Marker result;
final IElementType tokenType = builder.getTokenType();
if (tokenType == JavaTokenType.AT) {
@@ -763,8 +779,10 @@ public class DeclarationParser {
}
if (result == null) {
error(builder, JavaErrorMessages.message("expected.value"));
result = builder.mark();
result.error(JavaErrorMessages.message("expected.value"));
}
return result;
}
@@ -27,6 +27,7 @@ import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.lang.PsiBuilderUtil.expect;
import static com.intellij.lang.java.parser.JavaParserUtil.*;
@@ -216,7 +217,7 @@ public class ExpressionParser {
}
final PsiBuilder.Marker expression = left.precede();
builder.advanceLexer();
advanceGtToken(builder, tokenType);
final PsiBuilder.Marker right = parseExpression(builder, toParse);
if (right == null) {
@@ -502,7 +503,11 @@ public class ExpressionParser {
error(builder, JavaErrorMessages.message("expected.expression"));
}
JavaParserUtil.expectOrError(builder, JavaTokenType.RPARENTH, JavaErrorMessages.message("expected.rparen"));
if (!expect(builder, JavaTokenType.RPARENTH)) {
if (inner != null) {
error(builder, JavaErrorMessages.message("expected.rparen"));
}
}
parenth.done(JavaElementType.PARENTH_EXPRESSION);
return parenth;
@@ -801,6 +806,9 @@ public class ExpressionParser {
tokenType = JavaTokenType.GTGT;
}
}
else if (builder.getTokenType() == JavaTokenType.EQ) {
tokenType = JavaTokenType.GE;
}
}
sp.rollbackTo();
@@ -822,6 +830,9 @@ public class ExpressionParser {
else if (type == JavaTokenType.GTGT) {
PsiBuilderUtil.advance(builder, 2);
}
else if (type == JavaTokenType.GE) {
PsiBuilderUtil.advance(builder, 2);
}
else {
gtToken.drop();
builder.advanceLexer();
@@ -172,7 +172,9 @@ public class ReferenceParser {
parseReferenceParameterList(builder, true);
}
else {
emptyElement(builder, JavaElementType.REFERENCE_PARAMETER_LIST);
if (!isStaticImport || builder.getTokenType() == JavaTokenType.DOT) {
emptyElement(builder, JavaElementType.REFERENCE_PARAMETER_LIST);
}
}
boolean hasIdentifier;
@@ -210,6 +212,7 @@ public class ReferenceParser {
}
else {
error(builder, JavaErrorMessages.message("expected.identifier"));
emptyElement(builder, JavaElementType.REFERENCE_PARAMETER_LIST);
break;
}
}
@@ -27,6 +27,7 @@ import com.intellij.psi.search.NonClasspathDirectoryScope;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -158,12 +159,12 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder {
final VirtualFile dir = classRoot.findFileByRelativePath(qname.replace('.', '/'));
if (dir != null && dir.isDirectory()) {
final PsiDirectory psiDirectory = ApplicationManager.getApplication().runReadAction(new Computable<PsiDirectory>() {
@Nullable
public PsiDirectory compute() {
return psiManager.findDirectory(dir);
return dir.isValid() ? psiManager.findDirectory(dir) : null;
}
});
assert psiDirectory != null;
if (!consumer.process(psiDirectory)) {
if (psiDirectory != null && !consumer.process(psiDirectory)) {
return false;
}
}
@@ -47,9 +47,6 @@ class ConstantExpressionVisitor extends JavaElementVisitor implements PsiConstan
myResult = null;
element.accept(this);
store(element, myResult);
//for (PsiElement child : element.getChildren()) {
// store(child, null); //erase garbage
//}
return myResult;
}
private static final Key<Object> VALUE = Key.create("VALUE");
@@ -24,6 +24,7 @@ import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ConcurrentSoftHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,7 +38,7 @@ public class JavaConstantExpressionEvaluator extends JavaRecursiveElementWalking
private static final Key<CachedValue<ConcurrentMap<PsiElement,Object>>> CONSTANT_VALUE_WO_OVERFLOW_MAP_KEY = Key.create("CONSTANT_VALUE_WO_OVERFLOW_MAP_KEY");
private static final Key<CachedValue<ConcurrentMap<PsiElement,Object>>> CONSTANT_VALUE_WITH_OVERFLOW_MAP_KEY = Key.create("CONSTANT_VALUE_WITH_OVERFLOW_MAP_KEY");
private static final Object NO_VALUE = new Object();
private static final Object NO_VALUE = ObjectUtils.NULL;
private final ConstantExpressionVisitor myConstantExpressionVisitor;
private JavaConstantExpressionEvaluator(Set<PsiVariable> visitedVars, final boolean throwExceptionOnOverflow, final Project project, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) {
@@ -21,7 +21,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.impl.light.LightClassReference;
import com.intellij.psi.impl.source.PsiClassReferenceType;
@@ -193,6 +192,9 @@ public class PsiImplUtil {
for (int i = 0; i < types.length; i++) {
types[i] = typeElements[i].getType();
}
if (types.length == 1 && types[0] instanceof PsiDiamondType) {
return ((PsiDiamondType)types[0]).getInferredTypes();
}
return types;
}
@@ -25,15 +25,14 @@ import com.intellij.psi.impl.java.stubs.impl.PsiImportListStubImpl;
import com.intellij.psi.impl.source.PsiImportListImpl;
import com.intellij.psi.stubs.IndexSink;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.util.io.PersistentStringEnumerator;
import com.intellij.psi.stubs.StubOutputStream;
import java.io.IOException;
public class JavaImportListElementType extends JavaStubElementType<PsiImportListStub, PsiImportList> {
public JavaImportListElementType() {
super("IMPORT_LIST");
super("IMPORT_LIST", true);
}
public PsiImportList createPsi(final PsiImportListStub stub) {
@@ -60,4 +59,4 @@ public class JavaImportListElementType extends JavaStubElementType<PsiImportList
public void indexStub(final PsiImportListStub stub, final IndexSink sink) {
}
}
}
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
*/
public abstract class ImplicitVariableImpl extends LightVariableBase implements ImplicitVariable {
public ImplicitVariableImpl(PsiManager manager, PsiIdentifier nameIdentifier, @NotNull PsiType type, boolean writable, PsiElement scope) {
public ImplicitVariableImpl(PsiManager manager, PsiIdentifier nameIdentifier, PsiType type, boolean writable, PsiElement scope) {
super(manager, nameIdentifier, type, writable, scope);
}
@@ -37,7 +37,7 @@ public abstract class LightVariableBase extends LightElement implements PsiVaria
protected final PsiModifierList myModifierList;
protected boolean myWritable;
public LightVariableBase(PsiManager manager, PsiIdentifier nameIdentifier, @NotNull PsiType type, boolean writable, PsiElement scope) {
public LightVariableBase(PsiManager manager, PsiIdentifier nameIdentifier, PsiType type, boolean writable, PsiElement scope) {
super(manager, StdFileTypes.JAVA.getLanguage());
myModifierList = new LightModifierList(myManager);
myNameIdentifier = nameIdentifier;
@@ -107,6 +107,10 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
element = element.getTreeNext();
continue;
}
else if (elementType == JavaElementType.DIAMOND_TYPE) {
cachedType = new PsiDiamondType(getManager(), this);
break;
}
else {
LOG.error("Unknown element type: " + elementType);
}
@@ -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<PsiElement> nonImports = new ArrayList<PsiElement>();
// 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, nonImports));
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,31 @@ public class ImportHelper{
try {
StringBuilder text = buildImportListText(resultList, classesOrPackagesToImportOnDemand, classesToUseSingle);
for (PsiElement nonImport : nonImports) {
text.append("\n").append(nonImport.getText());
}
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;
if (!nonImports.isEmpty()) {
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 +628,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<PsiElement> 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 +649,19 @@ public class ImportHelper{
}
private static void collectNamesToImport(@NotNull final Set<Pair<String, Boolean>> names,
@NotNull List<PsiElement> 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<PsiElement> comments,
@NotNull PsiElement scope,
@NotNull String thisPackageName,
PsiFile context){
@@ -644,7 +671,24 @@ 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()) {
if (element == null) {
continue;
}
ASTNode node = element.getNode();
if (node == null) {
continue;
}
IElementType elementType = node.getElementType();
if (elementType != null &&!ElementType.IMPORT_STATEMENT_BASE_BIT_SET.contains(elementType)
&& !ElementType.WHITE_SPACE_BIT_SET.contains(elementType))
{
comments.add(element);
}
}
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));
}
@@ -172,7 +172,7 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo
}
private String[] getSignature() {
public String[] getSignature() {
PsiElement element = getNameElement().getNextSibling();
while (element != null && !(element instanceof PsiDocTagValue)) {
@@ -223,7 +223,7 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo
return JavaResolveUtil.getContextClass(this);
}
private class MyReference implements PsiJavaReference {
public class MyReference implements PsiJavaReference {
private final PsiElement myReferencee;
public MyReference(PsiElement referencee) {
@@ -345,16 +345,20 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo
}
newText.append("*/");
PsiComment comment =
JavaPsiFacade.getInstance(containingClass.getProject()).getElementFactory().createCommentFromText(newText.toString(), null);
PsiElement tag = PsiTreeUtil.getChildOfType(comment, PsiDocTag.class);
PsiElement ref = PsiTreeUtil.getChildOfType(tag, PsiDocMethodOrFieldRef.class);
return replace(ref);
return bindToText(containingClass, newText);
}
return PsiDocMethodOrFieldRef.this;
}
public PsiElement bindToText(PsiClass containingClass, StringBuffer newText) {
PsiComment comment =
JavaPsiFacade.getInstance(containingClass.getProject()).getElementFactory().createCommentFromText(newText.toString(), null);
PsiElement tag = PsiTreeUtil.getChildOfType(comment, PsiDocTag.class);
PsiElement ref = PsiTreeUtil.getChildOfType(tag, PsiDocMethodOrFieldRef.class);
return replace(ref);
}
public boolean isReferenceTo(PsiElement element) {
return getManager().areElementsEquivalent(resolve(), element);
}
@@ -100,7 +100,7 @@ public class ClassBodyParsing extends Parsing {
}
// adding a reference, not simple tokens allows "Browse .." to work well
CompositeElement ref = parseJavaCodeReference(filterLexer, true, true, false);
CompositeElement ref = parseJavaCodeReference(filterLexer, true, true, false, false);
if (ref != null){
invalidElementsGroup.rawAddChildren(ref);
continue;
@@ -490,7 +490,7 @@ public class DeclarationParsing extends Parsing {
annotation.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
lexer.advance();
TreeElement classReference = parseJavaCodeReference(lexer, true, false, false);
TreeElement classReference = parseJavaCodeReference(lexer, true, false, false, false);
if (classReference != null) {
annotation.rawAddChildren(classReference);
}
@@ -1004,7 +1004,7 @@ public class DeclarationParsing extends Parsing {
}
// adding a reference, not simple tokens allows "Browse .." to work well
CompositeElement ref = parseJavaCodeReference(lexer, true, true, false);
CompositeElement ref = parseJavaCodeReference(lexer, true, true, false, false);
if (ref != null){
invalidElementsGroup.rawAddChildren(ref);
}
@@ -1043,7 +1043,7 @@ public class DeclarationParsing extends Parsing {
lexer.advance();
while (true) {
TreeElement classReference = parseJavaCodeReference(lexer, true, true, true);
TreeElement classReference = parseJavaCodeReference(lexer, true, true, true, false);
if (classReference == null) {
classReference = Factory.createErrorElement(JavaErrorMessages.message("expected.identifier"));
}
@@ -457,7 +457,7 @@ public class ExpressionParsing extends Parsing {
IElementType tokenType = lexer.getTokenType();
if (tokenType == JavaTokenType.LT) {
final TreeElement referenceParameterList = parseReferenceParameterList(lexer, false);
final TreeElement referenceParameterList = parseReferenceParameterList(lexer, false, false);
CompositeElement element1 = ASTFactory.composite(JavaElementType.REFERENCE_EXPRESSION);
element1.rawAddChildren(element);
element1.rawAddChildren(dot);
@@ -494,7 +494,7 @@ public class ExpressionParsing extends Parsing {
&& element.getElementType() == JavaElementType.REFERENCE_EXPRESSION) {
lexer.restore(startPos);
CompositeElement element1 = parseJavaCodeReference(lexer, false, true, false); // don't eat the last dot before "this" or "super"!
CompositeElement element1 = parseJavaCodeReference(lexer, false, true, false, false); // don't eat the last dot before "this" or "super"!
if (element1 == null || lexer.getTokenType() != JavaTokenType.DOT || lexer.getTokenStart() != pos.getOffset()) {
lexer.restore(pos);
return element;
@@ -522,7 +522,7 @@ public class ExpressionParsing extends Parsing {
element = element1;
}
else {
final TreeElement referenceParameterList = parseReferenceParameterList(lexer, false);
final TreeElement referenceParameterList = parseReferenceParameterList(lexer, false, false);
CompositeElement element1 = ASTFactory.composite(JavaElementType.REFERENCE_EXPRESSION);
element1.rawAddChildren(element);
element1.rawAddChildren(dot);
@@ -731,6 +731,11 @@ public class ExpressionParsing extends Parsing {
return null;
}
protected boolean areDiamondsSupported() {
return myContext.getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_7);
}
private CompositeElement parseNewExpression(Lexer lexer,
TreeElement qualifier,
TreeElement dot) {
@@ -746,7 +751,7 @@ public class ExpressionParsing extends Parsing {
TreeElement newKeyword = ParseUtil.createTokenElement(lexer, myContext.getCharTable());
element.rawAddChildren(newKeyword);
lexer.advance();
element.rawAddChildren(parseReferenceParameterList(lexer, false));
element.rawAddChildren(parseReferenceParameterList(lexer, false, areDiamondsSupported()));
boolean isPrimitive;
TreeElement refOrType;
@@ -754,7 +759,7 @@ public class ExpressionParsing extends Parsing {
if (lexer.getTokenType() == JavaTokenType.IDENTIFIER || parseAnnotations) {
isPrimitive = false;
refOrType = parseJavaCodeReference(lexer, true, true, parseAnnotations);
refOrType = parseJavaCodeReference(lexer, true, true, parseAnnotations, areDiamondsSupported());
}
else if (lexer.getTokenType() != null && ElementType.PRIMITIVE_TYPE_BIT_SET.contains(lexer.getTokenType())) {
isPrimitive = true;
@@ -835,7 +840,7 @@ public class ExpressionParsing extends Parsing {
private CompositeElement parseClassObjectAccessExpression(Lexer lexer) {
final LexerPosition pos = lexer.getCurrentPosition();
CompositeElement type = parseType(lexer, false, false); // don't eat last dot before "class"!
CompositeElement type = parseType(lexer, false, false, false); // don't eat last dot before "class"!
if (type == null) return null;
if (lexer.getTokenType() != JavaTokenType.DOT) {
lexer.restore(pos);
@@ -116,7 +116,7 @@ public class FileTextParsing extends Parsing {
packageStatement.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
lexer.advance();
TreeElement packageReference = parseJavaCodeReference(lexer, true, false, false);
TreeElement packageReference = parseJavaCodeReference(lexer, true, false, false, false);
if (packageReference == null) {
lexer.restore(startPos);
return null;
@@ -90,7 +90,7 @@ public class ImportsTextParsing extends Parsing {
return statement;
}
CompositeElement refElement = parseJavaCodeReference(lexer, true, false, false);
CompositeElement refElement = parseJavaCodeReference(lexer, true, false, false, false);
final TreeElement refParameterList = refElement.getLastChildNode();
if (refParameterList.getTreePrev().getElementType() == TokenType.ERROR_ELEMENT){
final ASTNode qualifier = refElement.findChildByRole(ChildRole.QUALIFIER);
@@ -67,7 +67,7 @@ public class JavadocParsing extends Parsing {
element = parseTypeWithEllipsis(lexer, true, false);
}
else{
element = myContext.getStatementParsing().parseJavaCodeReference(lexer, true, true, false);
element = myContext.getStatementParsing().parseJavaCodeReference(lexer, true, true, false, false);
}
if (element != null){
@@ -29,8 +29,8 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.SmartList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class ParseUtil extends ParseUtilBase {
private ParseUtil() { }
@@ -57,8 +57,11 @@ public class ParseUtil extends ParseUtilBase {
}
private static class JavaMissingTokenInserter extends MissingTokenInserter {
public JavaMissingTokenInserter(final CompositeElement root, final Lexer lexer, final int startOffset, final int endOffset, final int state,
public JavaMissingTokenInserter(final CompositeElement root,
final Lexer lexer,
final int startOffset,
final int endOffset,
final int state,
final TokenProcessor processor,
final ParsingContext context) {
super(root, lexer, startOffset, endOffset, state, processor, context);
@@ -67,6 +70,7 @@ public class ParseUtil extends ParseUtilBase {
@Override
public void invoke() {
super.invoke();
moveEmptyImportList(myRoot);
bindComments(myRoot);
}
@@ -80,6 +84,26 @@ public class ParseUtil extends ParseUtilBase {
GTTokens.advance(next.getElementType(), myLexer);
}
protected boolean isInsertAfterElement(final TreeElement treeNext) {
return treeNext instanceof ModifierListElement;
}
private static void moveEmptyImportList(ASTNode root) {
TreeElement first = (TreeElement)root.getFirstChildNode();
TreeElement next = (TreeElement)TreeUtil.skipElements(first, ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET);
if (next == null) return;
if (next.getElementType() == JavaElementType.PACKAGE_STATEMENT) {
first = next.getTreeNext();
next = (TreeElement)TreeUtil.skipElements(first, ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET);
}
if (next != null && next != first && isEmptyImportList(next)) {
next.rawRemove();
first.rawInsertBeforeMe(next);
}
}
private static void bindComments(ASTNode root) {
if (TreeUtil.isLeafOrCollapsedChameleon(root)) return;
@@ -87,10 +111,7 @@ public class ParseUtil extends ParseUtilBase {
((TreeElement)root).acceptTree(new RecursiveTreeElementWalkingVisitor(false) {
@Override
protected void visitNode(TreeElement child) {
IElementType type = child.getElementType();
if (type == JavaDocElementType.DOC_COMMENT ||
type == JavaTokenType.END_OF_LINE_COMMENT ||
type == JavaTokenType.C_STYLE_COMMENT) {
if (ElementType.JAVA_COMMENT_BIT_SET.contains(child.getElementType())) {
comments.add(child);
}
if (TreeUtil.isLeafOrCollapsedChameleon(child)) return;
@@ -98,19 +119,15 @@ public class ParseUtil extends ParseUtilBase {
super.visitNode(child);
}
});
ListIterator<ASTNode> iterator;
// we'll only bind additional preceding comments in pass 2 when the declaration does not yet have a "doc comment"
boolean docCommentBound = false;
Iterator<ASTNode> iterator = comments.iterator();
iterator = comments.listIterator();
while (iterator.hasNext()) {
ASTNode child = iterator.next();
IElementType type = child.getElementType();
if (type == JavaDocElementType.DOC_COMMENT) {
if (bindDocComment((TreeElement)child)) {
iterator.remove();
docCommentBound = true;
}
if (bindDocComment((TreeElement)child)) iterator.remove();
}
// bind "trailing comments" (like "int a; // comment")
else if (type == JavaTokenType.END_OF_LINE_COMMENT || type == JavaTokenType.C_STYLE_COMMENT) {
@@ -119,13 +136,11 @@ public class ParseUtil extends ParseUtilBase {
}
// pass 2: bind preceding comments (like "// comment \n void f();")
if (!docCommentBound) {
for (ASTNode child : comments) {
if (child.getElementType() == JavaTokenType.END_OF_LINE_COMMENT || child.getElementType() == JavaTokenType.C_STYLE_COMMENT) {
TreeElement next = (TreeElement)TreeUtil.skipElements(child, PRECEDING_COMMENT_OR_SPACE_BIT_SET);
bindPrecedingComment((TreeElement)child, next);
}
}
iterator = comments.listIterator(comments.size());
while (iterator.hasPrevious()) {
ASTNode child = iterator.previous();
TreeElement next = (TreeElement)TreeUtil.skipElements(child.getTreeNext(), ElementType.JAVA_WHITESPACE_BIT_SET);
bindPrecedingComment((TreeElement)child, next);
}
}
@@ -136,21 +151,15 @@ public class ParseUtil extends ParseUtilBase {
TreeElement importList = null;
// bypass meaningless tokens and hold'em in hands
while (element.getElementType() == TokenType.WHITE_SPACE ||
element.getElementType() == JavaTokenType.C_STYLE_COMMENT ||
element.getElementType() == JavaTokenType.END_OF_LINE_COMMENT ||
element.getElementType() == JavaElementType.IMPORT_LIST && element.getTextLength() == 0) {
while (ElementType.JAVA_PLAIN_COMMENT_OR_WHITESPACE_BIT_SET.contains(element.getElementType()) ||
isEmptyImportList(element)) {
if (element.getElementType() == JavaElementType.IMPORT_LIST) importList = element;
if (startSpaces == null) startSpaces = element;
element = element.getTreeNext();
if (element == null) return false;
}
if (element.getElementType() == JavaElementType.CLASS ||
element.getElementType() == JavaElementType.FIELD ||
element.getElementType() == JavaElementType.METHOD ||
element.getElementType() == JavaElementType.ENUM_CONSTANT ||
element.getElementType() == JavaElementType.ANNOTATION_METHOD) {
if (ElementType.MEMBER_BIT_SET.contains(element.getElementType())) {
TreeElement first = element.getFirstChildNode();
if (startSpaces != null) {
docComment.rawRemoveUpTo(element);
@@ -172,9 +181,8 @@ public class ParseUtil extends ParseUtilBase {
}
private static final TokenSet BIND_TRAILING_COMMENT_BIT_SET = TokenSet.orSet(
TokenSet.create(JavaElementType.FIELD, JavaElementType.METHOD, JavaElementType.CLASS, JavaElementType.CLASS_INITIALIZER,
JavaElementType.IMPORT_STATEMENT, JavaElementType.IMPORT_STATIC_STATEMENT, JavaElementType.PACKAGE_STATEMENT),
ElementType.JAVA_STATEMENT_BIT_SET);
TokenSet.create(JavaElementType.PACKAGE_STATEMENT),
ElementType.IMPORT_STATEMENT_BASE_BIT_SET, ElementType.FULL_MEMBER_BIT_SET, ElementType.JAVA_STATEMENT_BIT_SET);
private static boolean bindTrailingComment(TreeElement comment) {
TreeElement element = comment.getTreePrev();
@@ -200,71 +208,40 @@ public class ParseUtil extends ParseUtilBase {
return false;
}
private static final TokenSet BIND_PRECEDING_COMMENT_BIT_SET = TokenSet.create(JavaElementType.FIELD, JavaElementType.METHOD,
JavaElementType.CLASS, JavaElementType.CLASS_INITIALIZER);
private static final TokenSet PRECEDING_COMMENT_OR_SPACE_BIT_SET = TokenSet.create(JavaTokenType.C_STYLE_COMMENT,
JavaTokenType.END_OF_LINE_COMMENT,
JavaDocElementType.DOC_COMMENT,
TokenType.WHITE_SPACE);
private static final TokenSet BIND_PRECEDING_COMMENT_BIT_SET = ElementType.FULL_MEMBER_BIT_SET;
private static void bindPrecedingComment(TreeElement comment, ASTNode bindTo) {
if (bindTo == null || bindTo.getFirstChildNode() != null && bindTo.getFirstChildNode().getElementType() == JavaDocElementType.DOC_COMMENT) return;
if (bindTo == null ||
!BIND_PRECEDING_COMMENT_BIT_SET.contains(bindTo.getElementType()) ||
(bindTo.getFirstChildNode() != null && bindTo.getFirstChildNode().getElementType() == JavaDocElementType.DOC_COMMENT) ||
!isBindingComment(comment)) return;
if (bindTo.getElementType() == JavaElementType.IMPORT_LIST && bindTo.getTextLength() == 0) {
bindTo = bindTo.getTreeNext();
}
ASTNode toStart = isBindingComment(comment) ? comment : null;
if (bindTo != null && BIND_PRECEDING_COMMENT_BIT_SET.contains(bindTo.getElementType())) {
for (ASTNode child = comment; child != bindTo; child = child.getTreeNext()) {
if (child.getElementType() == TokenType.WHITE_SPACE) {
int count = StringUtil.getLineBreakCount(child.getText());
if (count > 1) toStart = null;
}
else {
if (child.getTreePrev() != null && child.getTreePrev().getElementType() == TokenType.WHITE_SPACE) {
LeafElement prev = (LeafElement)child.getTreePrev();
char lastC = prev.charAt(prev.getTextLength() - 1);
if (lastC == '\n' || lastC == '\r') toStart = isBindingComment(child) ? child : null;
}
else {
return;
}
}
}
if (toStart == null) return;
TreeElement first = (TreeElement)bindTo.getFirstChildNode();
TreeElement child = (TreeElement)toStart;
while (child != bindTo) {
TreeElement next = child.getTreeNext();
if (child.getElementType() != JavaElementType.IMPORT_LIST) {
child.rawRemove();
first.rawInsertBeforeMe(child);
}
child = next;
}
final TreeElement first = (TreeElement)bindTo.getFirstChildNode();
TreeElement child = comment;
while (child != bindTo) {
final TreeElement next = child.getTreeNext();
child.rawRemove();
first.rawInsertBeforeMe(child);
child = next;
}
}
private static boolean isBindingComment(final ASTNode node) {
ASTNode prev = node.getTreePrev();
if (prev != null) {
if (prev.getElementType() != TokenType.WHITE_SPACE) {
return false;
}
else {
if (!prev.textContains('\n')) return false;
}
}
private static boolean isBindingComment(final ASTNode comment) {
ASTNode prev = comment.getTreePrev();
if (isEmptyImportList(prev)) prev = prev.getTreePrev();
final boolean prevOk = prev == null ||
(prev.getElementType() == TokenType.WHITE_SPACE && prev.textContains('\n'));
return true;
final ASTNode next = comment.getTreeNext();
final boolean nextOk = next != null &&
next.getElementType() == TokenType.WHITE_SPACE &&
StringUtil.getLineBreakCount(next.getText()) < 2;
return prevOk && nextOk;
}
protected boolean isInsertAfterElement(final TreeElement treeNext) {
return treeNext instanceof ModifierListElement;
private static boolean isEmptyImportList(final ASTNode node) {
return node != null && node.getElementType() == JavaElementType.IMPORT_LIST && node.getTextLength() == 0;
}
}
}
@@ -61,7 +61,7 @@ public class Parsing {
lexer.start(buffer, startOffset, endOffset);
JavaParsingContext context = new JavaParsingContext(table, LanguageLevelProjectExtension.getInstance(manager.getProject()).getLanguageLevel());
CompositeElement ref = context.getStatementParsing().parseJavaCodeReference(lexer, false, true, false);
CompositeElement ref = context.getStatementParsing().parseJavaCodeReference(lexer, false, true, false, false);
final FileElement dummyRoot = DummyHolderFactory.createHolder(manager, null, table).getTreeElement();
if (ref == null) {
if (!eatAll) return null;
@@ -85,7 +85,7 @@ public class Parsing {
}
public CompositeElement parseJavaCodeReference(Lexer lexer, boolean allowIncomplete, final boolean parseParameterList,
boolean parseAnnotations) {
boolean parseAnnotations, boolean parseNewExpression) {
CompositeElement refElement = ASTFactory.composite(JavaElementType.JAVA_CODE_REFERENCE);
LexerPosition beforeAnnos = lexer.getCurrentPosition();
if (parseAnnotations) {
@@ -102,7 +102,7 @@ public class Parsing {
refElement.rawAddChildren(identifier);
CompositeElement parameterList;
if (parseParameterList) {
parameterList = parseReferenceParameterList(lexer, true);
parameterList = parseReferenceParameterList(lexer, true, parseNewExpression);
}
else {
parameterList = ASTFactory.composite(JavaElementType.REFERENCE_PARAMETER_LIST);
@@ -136,7 +136,7 @@ public class Parsing {
refElement1.rawAddChildren(identifier);
CompositeElement parameterList1;
if (parseParameterList) {
parameterList1 = parseReferenceParameterList(lexer, true);
parameterList1 = parseReferenceParameterList(lexer, true, parseNewExpression);
}
else {
parameterList1 = ASTFactory.composite(JavaElementType.REFERENCE_PARAMETER_LIST);
@@ -148,14 +148,14 @@ public class Parsing {
return refElement;
}
public CompositeElement parseReferenceParameterList(Lexer lexer, boolean allowWildcard) {
public CompositeElement parseReferenceParameterList(Lexer lexer, boolean allowWildcard, boolean allowDiamonds) {
final CompositeElement list = ASTFactory.composite(JavaElementType.REFERENCE_PARAMETER_LIST);
if (lexer.getTokenType() != JavaTokenType.LT) return list;
final TreeElement lt = ParseUtil.createTokenElement(lexer, myContext.getCharTable());
list.rawAddChildren(lt);
lexer.advance();
while (true) {
final CompositeElement typeElement = parseType(lexer, true, allowWildcard);
final CompositeElement typeElement = parseType(lexer, true, allowWildcard, allowDiamonds);
if (typeElement != null) {
list.rawAddChildren(typeElement);
}
@@ -199,7 +199,7 @@ public class Parsing {
}
public CompositeElement parseTypeWithEllipsis(Lexer lexer, boolean eatLastDot, boolean allowWilcard) {
CompositeElement type = parseType(lexer, eatLastDot, allowWilcard);
CompositeElement type = parseType(lexer, eatLastDot, allowWilcard, false);
if (type == null) return null;
if (lexer.getTokenType() == JavaTokenType.ELLIPSIS) {
CompositeElement type1 = ASTFactory.composite(JavaElementType.TYPE);
@@ -217,7 +217,7 @@ public class Parsing {
}
public CompositeElement parseType(Lexer lexer){
return parseType(lexer, true, true);
return parseType(lexer, true, true, false);
}
protected void parseAnnotationListTo(@NotNull Lexer lexer, @Nullable CompositeElement element) {
@@ -229,7 +229,7 @@ public class Parsing {
}
}
public CompositeElement parseType(Lexer lexer, boolean eatLastDot, boolean allowWildcard){
public CompositeElement parseType(Lexer lexer, boolean eatLastDot, boolean allowWildcard, boolean allowDiamonds){
IElementType tokenType = lexer.getTokenType();
if (tokenType == null) {
return null;
@@ -244,11 +244,16 @@ public class Parsing {
lexer.advance();
}
else if (tokenType == JavaTokenType.IDENTIFIER){
refElement = parseJavaCodeReference(lexer, eatLastDot, true, false);
refElement = parseJavaCodeReference(lexer, eatLastDot, true, false, allowDiamonds);
}
else if (allowWildcard && lexer.getTokenType() == JavaTokenType.QUEST) {
return parseWildcardType(lexer);
}
else if (allowDiamonds && lexer.getTokenType() == JavaTokenType.GT) {
final CompositeElement typeElement = ASTFactory.composite(JavaElementType.TYPE);
typeElement.rawAddChildren(ASTFactory.composite(JavaElementType.DIAMOND_TYPE));
return typeElement;
}
else {
return null;
}
@@ -304,7 +309,7 @@ public class Parsing {
if (lexer.getTokenType() == JavaTokenType.SUPER_KEYWORD || lexer.getTokenType() == JavaTokenType.EXTENDS_KEYWORD) {
type.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
lexer.advance();
CompositeElement boundType = parseType(lexer, true, false);
CompositeElement boundType = parseType(lexer, true, false, false);
if (boundType != null) {
type.rawAddChildren(boundType);
}
@@ -358,7 +358,7 @@ public class StatementParsing extends Parsing {
declStatement.rawAddChildren(decl);
}
else {
final CompositeElement type = parseType(lexer, false, false);
final CompositeElement type = parseType(lexer, false, false, false);
if (type != null) declStatement.rawAddChildren(type);
final CompositeElement errorElement = Factory.createErrorElement(JavaErrorMessages.message("expected.identifier"));
declStatement.rawAddChildren(errorElement);
@@ -28,34 +28,42 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType,
JspElementType.JSP_TEMPLATE_EXPRESSION);
TokenSet JAVA_WHITESPACE_BIT_SET = TokenSet.create(WHITE_SPACE);
TokenSet JAVA_COMMENT_BIT_SET = TokenSet.create(END_OF_LINE_COMMENT, C_STYLE_COMMENT, JavaDocElementType.DOC_COMMENT);
TokenSet JAVA_PLAIN_COMMENT_BIT_SET = TokenSet.create(END_OF_LINE_COMMENT, C_STYLE_COMMENT);
TokenSet JAVA_COMMENT_BIT_SET = TokenSet.orSet(JAVA_PLAIN_COMMENT_BIT_SET, TokenSet.create(DOC_COMMENT));
TokenSet JAVA_PLAIN_COMMENT_OR_WHITESPACE_BIT_SET = TokenSet.orSet(JAVA_WHITESPACE_BIT_SET, JAVA_PLAIN_COMMENT_BIT_SET);
TokenSet JAVA_COMMENT_OR_WHITESPACE_BIT_SET = TokenSet.orSet(JAVA_WHITESPACE_BIT_SET, JAVA_COMMENT_BIT_SET);
TokenSet KEYWORD_BIT_SET = TokenSet.create(ABSTRACT_KEYWORD, ASSERT_KEYWORD, BOOLEAN_KEYWORD, BREAK_KEYWORD, BYTE_KEYWORD, CASE_KEYWORD, CATCH_KEYWORD, CHAR_KEYWORD, CLASS_KEYWORD,
CONST_KEYWORD, CONTINUE_KEYWORD, DEFAULT_KEYWORD, DO_KEYWORD, DOUBLE_KEYWORD, ELSE_KEYWORD, EXTENDS_KEYWORD, FINAL_KEYWORD,
FINALLY_KEYWORD, FLOAT_KEYWORD, FOR_KEYWORD, GOTO_KEYWORD, IF_KEYWORD, IMPLEMENTS_KEYWORD, IMPORT_KEYWORD, INSTANCEOF_KEYWORD,
INT_KEYWORD, INTERFACE_KEYWORD, LONG_KEYWORD, NATIVE_KEYWORD, NEW_KEYWORD, PACKAGE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD,
SHORT_KEYWORD, SUPER_KEYWORD, SWITCH_KEYWORD, STRICTFP_KEYWORD, SYNCHRONIZED_KEYWORD, THIS_KEYWORD, THROW_KEYWORD, PROTECTED_KEYWORD,
TRANSIENT_KEYWORD, RETURN_KEYWORD, VOID_KEYWORD, STATIC_KEYWORD, WHILE_KEYWORD, TRY_KEYWORD, VOLATILE_KEYWORD, THROWS_KEYWORD,
ENUM_KEYWORD);
TokenSet KEYWORD_BIT_SET = TokenSet.create(
ABSTRACT_KEYWORD, ASSERT_KEYWORD, BOOLEAN_KEYWORD, BREAK_KEYWORD, BYTE_KEYWORD, CASE_KEYWORD, CATCH_KEYWORD, CHAR_KEYWORD, CLASS_KEYWORD,
CONST_KEYWORD, CONTINUE_KEYWORD, DEFAULT_KEYWORD, DO_KEYWORD, DOUBLE_KEYWORD, ELSE_KEYWORD, EXTENDS_KEYWORD, FINAL_KEYWORD,
FINALLY_KEYWORD, FLOAT_KEYWORD, FOR_KEYWORD, GOTO_KEYWORD, IF_KEYWORD, IMPLEMENTS_KEYWORD, IMPORT_KEYWORD, INSTANCEOF_KEYWORD,
INT_KEYWORD, INTERFACE_KEYWORD, LONG_KEYWORD, NATIVE_KEYWORD, NEW_KEYWORD, PACKAGE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD,
SHORT_KEYWORD, SUPER_KEYWORD, SWITCH_KEYWORD, STRICTFP_KEYWORD, SYNCHRONIZED_KEYWORD, THIS_KEYWORD, THROW_KEYWORD, PROTECTED_KEYWORD,
TRANSIENT_KEYWORD, RETURN_KEYWORD, VOID_KEYWORD, STATIC_KEYWORD, WHILE_KEYWORD, TRY_KEYWORD, VOLATILE_KEYWORD, THROWS_KEYWORD,
ENUM_KEYWORD);
TokenSet MODIFIER_BIT_SET = TokenSet.create(PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, STATIC_KEYWORD, ABSTRACT_KEYWORD, FINAL_KEYWORD, NATIVE_KEYWORD, SYNCHRONIZED_KEYWORD,
STRICTFP_KEYWORD, TRANSIENT_KEYWORD, VOLATILE_KEYWORD);
TokenSet MODIFIER_BIT_SET = TokenSet.create(
PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, STATIC_KEYWORD, ABSTRACT_KEYWORD, FINAL_KEYWORD, NATIVE_KEYWORD, SYNCHRONIZED_KEYWORD,
STRICTFP_KEYWORD, TRANSIENT_KEYWORD, VOLATILE_KEYWORD);
TokenSet PRIMITIVE_TYPE_BIT_SET = TokenSet.create(BOOLEAN_KEYWORD, BYTE_KEYWORD, SHORT_KEYWORD, INT_KEYWORD, LONG_KEYWORD, CHAR_KEYWORD, FLOAT_KEYWORD, DOUBLE_KEYWORD, VOID_KEYWORD);
TokenSet PRIMITIVE_TYPE_BIT_SET = TokenSet.create(
BOOLEAN_KEYWORD, BYTE_KEYWORD, SHORT_KEYWORD, INT_KEYWORD, LONG_KEYWORD, CHAR_KEYWORD, FLOAT_KEYWORD, DOUBLE_KEYWORD, VOID_KEYWORD);
TokenSet EXPRESSION_BIT_SET = TokenSet.create(REFERENCE_EXPRESSION, LITERAL_EXPRESSION, THIS_EXPRESSION, SUPER_EXPRESSION, PARENTH_EXPRESSION, METHOD_CALL_EXPRESSION,
TYPE_CAST_EXPRESSION, PREFIX_EXPRESSION, POSTFIX_EXPRESSION, BINARY_EXPRESSION, CONDITIONAL_EXPRESSION, ASSIGNMENT_EXPRESSION,
NEW_EXPRESSION, ARRAY_ACCESS_EXPRESSION, ARRAY_INITIALIZER_EXPRESSION, INSTANCE_OF_EXPRESSION, CLASS_OBJECT_ACCESS_EXPRESSION,
EMPTY_EXPRESSION);
TokenSet EXPRESSION_BIT_SET = TokenSet.create(
REFERENCE_EXPRESSION, LITERAL_EXPRESSION, THIS_EXPRESSION, SUPER_EXPRESSION, PARENTH_EXPRESSION, METHOD_CALL_EXPRESSION,
TYPE_CAST_EXPRESSION, PREFIX_EXPRESSION, POSTFIX_EXPRESSION, BINARY_EXPRESSION, CONDITIONAL_EXPRESSION, ASSIGNMENT_EXPRESSION,
NEW_EXPRESSION, ARRAY_ACCESS_EXPRESSION, ARRAY_INITIALIZER_EXPRESSION, INSTANCE_OF_EXPRESSION, CLASS_OBJECT_ACCESS_EXPRESSION,
EMPTY_EXPRESSION);
TokenSet ANNOTATION_MEMBER_VALUE_BIT_SET = TokenSet.orSet(EXPRESSION_BIT_SET,
TokenSet.create(ANNOTATION, ANNOTATION_ARRAY_INITIALIZER));
TokenSet ARRAY_DIMENSION_BIT_SET = TokenSet.create(REFERENCE_EXPRESSION, LITERAL_EXPRESSION, THIS_EXPRESSION, SUPER_EXPRESSION, PARENTH_EXPRESSION, METHOD_CALL_EXPRESSION,
TYPE_CAST_EXPRESSION, PREFIX_EXPRESSION, POSTFIX_EXPRESSION, BINARY_EXPRESSION, CONDITIONAL_EXPRESSION, ASSIGNMENT_EXPRESSION,
NEW_EXPRESSION, ARRAY_ACCESS_EXPRESSION, INSTANCE_OF_EXPRESSION, CLASS_OBJECT_ACCESS_EXPRESSION, EMPTY_EXPRESSION);
TokenSet ARRAY_DIMENSION_BIT_SET = TokenSet.create(
REFERENCE_EXPRESSION, LITERAL_EXPRESSION, THIS_EXPRESSION, SUPER_EXPRESSION, PARENTH_EXPRESSION, METHOD_CALL_EXPRESSION,
TYPE_CAST_EXPRESSION, PREFIX_EXPRESSION, POSTFIX_EXPRESSION, BINARY_EXPRESSION, CONDITIONAL_EXPRESSION, ASSIGNMENT_EXPRESSION,
NEW_EXPRESSION, ARRAY_ACCESS_EXPRESSION, INSTANCE_OF_EXPRESSION, CLASS_OBJECT_ACCESS_EXPRESSION, EMPTY_EXPRESSION);
TokenSet JAVA_STATEMENT_BIT_SET = TokenSet.create(
EMPTY_STATEMENT, BLOCK_STATEMENT, EXPRESSION_STATEMENT, EXPRESSION_LIST_STATEMENT,
@@ -64,7 +72,9 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType,
CONTINUE_STATEMENT, RETURN_STATEMENT, THROW_STATEMENT, SYNCHRONIZED_STATEMENT,
TRY_STATEMENT, LABELED_STATEMENT, ASSERT_STATEMENT, JspElementType.JSP_EXPRESSION
);
TokenSet JSP_SYNTHETIC_STATEMENTS = TokenSet.create(JspElementType.JSP_WHILE_STATEMENT, JspElementType.JSP_BLOCK_STATEMENT, JspElementType.JSP_EXPRESSION, JspElementType.JSP_TEMPLATE_STATEMENT, JspElementType.JSP_CLASS_LEVEL_DECLARATION_STATEMENT);
TokenSet JSP_SYNTHETIC_STATEMENTS = TokenSet.create(
JspElementType.JSP_WHILE_STATEMENT, JspElementType.JSP_BLOCK_STATEMENT, JspElementType.JSP_EXPRESSION,
JspElementType.JSP_TEMPLATE_STATEMENT, JspElementType.JSP_CLASS_LEVEL_DECLARATION_STATEMENT);
TokenSet STATEMENT_BIT_SET = TokenSet.orSet(JAVA_STATEMENT_BIT_SET, JSP_SYNTHETIC_STATEMENTS);
TokenSet TYPES_BIT_SET = TokenSet.create(TYPE);
@@ -77,5 +87,7 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType,
TokenSet IMPORT_STATIC_STATEMENT_BIT_SET = TokenSet.create(IMPORT_STATIC_STATEMENT);
TokenSet IMPORT_STATEMENT_BASE_BIT_SET = TokenSet.create(IMPORT_STATEMENT, IMPORT_STATIC_STATEMENT);
TokenSet CLASS_KEYWORD_BIT_SET = TokenSet.create(CLASS_KEYWORD, INTERFACE_KEYWORD, ENUM_KEYWORD);
TokenSet MEMBER_BIT_SET = TokenSet.create(CLASS, FIELD, CLASS_INITIALIZER, METHOD);
TokenSet MEMBER_BIT_SET = TokenSet.create(CLASS, FIELD, ENUM_CONSTANT, METHOD, ANNOTATION_METHOD);
TokenSet FULL_MEMBER_BIT_SET = TokenSet.orSet(MEMBER_BIT_SET,
TokenSet.create(CLASS_INITIALIZER));
}
@@ -67,6 +67,7 @@ public interface JavaElementType {
IElementType IMPORT_STATIC_REFERENCE = new IJavaElementType("IMPORT_STATIC_REFERENCE");
IElementType TYPE = new IJavaElementType("TYPE");
IElementType DIAMOND_TYPE = new IJavaElementType("DIAMOND_TYPE");
IElementType REFERENCE_PARAMETER_LIST = new IJavaElementType("REFERENCE_PARAMETER_LIST", true);
IElementType JAVA_CODE_REFERENCE = new IJavaElementType("JAVA_CODE_REFERENCE");
IElementType PACKAGE_STATEMENT = new IJavaElementType("PACKAGE_STATEMENT");
@@ -604,13 +604,7 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
public PsiType[] getTypeParameters() {
final PsiReferenceParameterList parameterList = getParameterList();
if (parameterList == null) return PsiType.EMPTY_ARRAY;
PsiTypeElement[] typeElements = parameterList.getTypeParameterElements();
PsiType[] types = new PsiType[typeElements.length];
for (int i = 0; i < types.length; i++) {
types[i] = typeElements[i].getType();
}
return types;
return parameterList.getTypeArguments();
}
@@ -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();
@@ -111,16 +111,22 @@ public class JavaChangeSignatureHandler implements ChangeSignatureHandler {
return element.getParent();
}
final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class);
final PsiCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiCallExpression.class);
if (expression != null) {
assert element != null;
final PsiExpression qualifierExpression = expression.getMethodExpression().getQualifierExpression();
final PsiExpression qualifierExpression;
if (expression instanceof PsiMethodCallExpression) {
qualifierExpression = ((PsiMethodCallExpression)expression).getMethodExpression().getQualifierExpression();
} else if (expression instanceof PsiNewExpression) {
qualifierExpression = ((PsiNewExpression)expression).getQualifier();
} else {
qualifierExpression = null;
}
if (PsiTreeUtil.isAncestor(qualifierExpression, element, false)) {
final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(qualifierExpression, PsiExpressionList.class);
if (expressionList != null) {
final PsiElement parent = expressionList.getParent();
if (parent instanceof PsiMethodCallExpression) {
return ((PsiMethodCallExpression)parent).resolveMethod();
if (parent instanceof PsiCallExpression) {
return ((PsiCallExpression)parent).resolveMethod();
}
}
}
@@ -185,7 +185,7 @@ public abstract class CallerChooser extends DialogWrapper {
final JComponent calleeComponent = myCalleeEditor.getComponent();
calleeComponent.setBorder(IdeBorderFactory.createTitledBorder(RefactoringBundle.message("caller.chooser.callee.method")));
splitter.setSecondComponent(calleeComponent);
splitter.setBorder(IdeBorderFactory.createBorder());
splitter.setBorder(IdeBorderFactory.createRoundedBorder());
return splitter;
}
@@ -95,7 +95,7 @@ class CopyClassDialog extends DialogWrapper{
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbConstraints = new GridBagConstraints();
panel.setBorder(IdeBorderFactory.createBorder());
panel.setBorder(IdeBorderFactory.createRoundedBorder());
gbConstraints.insets = new Insets(4,8,4,8);
gbConstraints.weightx = 1;
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -136,16 +135,12 @@ public class ExtractMethodHandler implements RefactoringActionHandler {
public void run() {
PostprocessReformattingAspect.getInstance(project).postponeFormattingInside(new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
try {
processor.doRefactoring();
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
});
try {
processor.doRefactoring();
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
DuplicatesImpl.processDuplicates(processor, project, editor);
}
});
@@ -230,4 +225,4 @@ public class ExtractMethodHandler implements RefactoringActionHandler {
final OpenFileDescriptor fileDescriptor = new OpenFileDescriptor(project, virtualFile);
return FileEditorManager.getInstance(project).openTextEditor(fileDescriptor, false);
}
}
}
@@ -34,6 +34,7 @@ import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
@@ -542,15 +543,29 @@ public class ExtractMethodProcessor implements MatchProvider {
LogicalPosition pos = new LogicalPosition(0, 0);
myEditor.getCaretModel().moveToLogicalPosition(pos);
SearchScope processConflictsScope = myMethodVisibility.equals(PsiModifier.PRIVATE) ?
final SearchScope processConflictsScope = myMethodVisibility.equals(PsiModifier.PRIVATE) ?
new LocalSearchScope(myTargetClass) :
GlobalSearchScope.projectScope(myProject);
final Map<PsiMethodCallExpression, PsiMethod> overloadsResolveMap =
ExtractMethodUtil.encodeOverloadTargets(myTargetClass, processConflictsScope, myMethodName, myCodeFragmentMember);
doExtract();
ExtractMethodUtil.decodeOverloadTargets(overloadsResolveMap, myExtractedMethod, myCodeFragmentMember);
final Map<PsiMethodCallExpression, PsiMethod> overloadsResolveMap = new HashMap<PsiMethodCallExpression, PsiMethod>();
final Runnable collectOverloads = new Runnable() {
public void run() {
overloadsResolveMap.putAll(ExtractMethodUtil.encodeOverloadTargets(myTargetClass, processConflictsScope, myMethodName, myCodeFragmentMember));
}
};
final Runnable extract = new Runnable() {
public void run() {
doExtract();
ExtractMethodUtil.decodeOverloadTargets(overloadsResolveMap, myExtractedMethod, myCodeFragmentMember);
}
};
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
collectOverloads.run();
extract.run();
} else {
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(collectOverloads, "Collect overloads...", true, myProject)) return;
ApplicationManager.getApplication().runWriteAction(extract);
}
LogicalPosition pos1 = new LogicalPosition(line, col);
myEditor.getCaretModel().moveToLogicalPosition(pos1);
@@ -90,10 +90,14 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
query.forEach(new Processor<PsiReference>() {
public boolean process(final PsiReference psiReference) {
final PsiElement element = psiReference.getElement();
final PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
if (psiClass != containingClass) {
innerClassesWithUsages.add(psiClass);
innerClassUsages.add(element);
PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
while (psiClass != containingClass && psiClass != null) {
final PsiClass parentPsiClass = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true);
if (parentPsiClass == containingClass) {
innerClassesWithUsages.add(psiClass);
innerClassUsages.add(element);
}
psiClass = parentPsiClass;
}
return true;
}

Some files were not shown because too many files have changed in this diff Show More