mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -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*",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
-18
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -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()) {
|
||||
+1
-1
@@ -176,7 +176,7 @@ public class BackendCompilerWrapper {
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (fileToDelete != null) {
|
||||
if (fileToDelete != null && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
|
||||
FileUtil.asyncDelete(fileToDelete);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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();
|
||||
}
|
||||
+16
-16
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-5
@@ -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;
|
||||
}
|
||||
+48
@@ -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;
|
||||
}
|
||||
}
|
||||
+8
-7
@@ -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);
|
||||
}
|
||||
}
|
||||
+49
@@ -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;
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -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) {
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -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
|
||||
+51
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+88
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-9
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+101
@@ -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 &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="&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="&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="&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 &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>
|
||||
+152
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+179
@@ -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() {
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
|
||||
+4
-4
@@ -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;
|
||||
|
||||
+5
-6
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-15
@@ -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";
|
||||
|
||||
+25
-20
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
+26
-6
@@ -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;
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -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;
|
||||
}
|
||||
|
||||
+5
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -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) {
|
||||
|
||||
+1
-27
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-25
@@ -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;
|
||||
}
|
||||
|
||||
+14
-6
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -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]);
|
||||
|
||||
+1
-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>
|
||||
|
||||
+1
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -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) {
|
||||
|
||||
+14
-5
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+50
-32
@@ -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))
|
||||
|
||||
+37
-13
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -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) {
|
||||
|
||||
+2
-2
@@ -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());
|
||||
|
||||
|
||||
+2
-3
@@ -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));
|
||||
}
|
||||
|
||||
+11
-7
@@ -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");
|
||||
|
||||
+1
-7
@@ -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();
|
||||
|
||||
+11
-5
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+7
-12
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-6
@@ -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
Reference in New Issue
Block a user