Merge remote branch 'origin/master'

This commit is contained in:
irengrig
2011-12-21 15:57:11 +04:00
122 changed files with 1522 additions and 481 deletions
@@ -18,6 +18,7 @@ package com.intellij.debugger.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.sun.jdi.VMDisconnectedException;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.concurrent.*;
@@ -65,14 +66,14 @@ public abstract class InvokeThread<E extends PrioritizedTask> {
public boolean isInterrupted() {
assert myRequestFuture != null;
return myRequestFuture.isCancelled();
return myRequestFuture.isCancelled() || myRequestFuture.isDone();
}
public void join() throws InterruptedException, ExecutionException {
assert myRequestFuture != null;
try {
myRequestFuture.get();
}
}
catch(CancellationException ignored) {
}
}
@@ -101,7 +102,7 @@ public abstract class InvokeThread<E extends PrioritizedTask> {
public boolean isDone() {
assert myRequestFuture != null;
return myRequestFuture.isDone();
return myRequestFuture.isDone() && ourWorkerRequest.get() == null;
}
}
@@ -122,7 +123,7 @@ public abstract class InvokeThread<E extends PrioritizedTask> {
workerRequest.setRequestFuture( ApplicationManager.getApplication().executeOnPooledThread(workerRequest) );
}
public void run(WorkerThreadRequest threadRequest) {
private void run(@NotNull WorkerThreadRequest threadRequest) {
while(true) {
try {
if(threadRequest.isInterrupted()) {
@@ -75,6 +75,8 @@ public class DebuggerTreeBase extends DnDAwareTree implements Disposable {
}
});
Disposer.register(this, myTipManager);
UIUtil.setLineStyleAngled(this);
setRootVisible(false);
setShowsRootHandles(true);
@@ -388,7 +390,5 @@ public class DebuggerTreeBase extends DnDAwareTree implements Disposable {
}
myCurrentTooltip = null;
myCurrentTooltipNode = null;
Disposer.dispose(myTipManager);
}
}
@@ -544,7 +544,7 @@ public class HighlightMethodUtil {
PsiMethod method = methodCandidate.getElement();
PsiParameter[] parameters = method.getParameterList().getParameters();
PsiSubstitutor substitutor = methodCandidate.getSubstitutor();
@NonNls String ms = "<td><b>" + method.getName() + "</b></td>";
@NonNls @Language("HTML") String ms = "<td><b>" + method.getName() + "</b></td>";
for (int j = 0; j < parameters.length; j++) {
PsiParameter parameter = parameters[j];
@@ -120,7 +120,7 @@ public class AddMethodFix extends LocalQuickFixAndIntentionActionOnPsiElement {
}
PsiMethod method = (PsiMethod)myClass.add(myMethodPrototype);
method = (PsiMethod)method.replace(reformat(project, method));
if (editor != null) {
if (editor != null && method.getContainingFile() == file) {
GenerateMembersUtil.positionCaret(editor, method, true);
}
}
@@ -126,7 +126,9 @@ public class CreateConstructorMatchingSuperFix extends BaseIntentionAction {
}
}
derived.getNameIdentifier().replace(targetClass.getNameIdentifier());
final PsiIdentifier identifier = targetClass.getNameIdentifier();
LOG.assertTrue(identifier != null, targetClass);
derived.getNameIdentifier().replace(identifier);
@NonNls StringBuffer buffer = new StringBuffer();
buffer.append("void foo () {\nsuper(");
@@ -55,13 +55,23 @@ import java.util.regex.PatternSyntaxException;
public abstract class ImportClassFixBase<T extends PsiElement & PsiReference> implements HintAction, HighPriorityAction {
private final T myRef;
protected ImportClassFixBase(T ref) {
protected ImportClassFixBase(@NotNull T ref) {
myRef = ref;
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return myRef.isValid() && file.getManager().isInProject(file) && !getClassesToImport().isEmpty();
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiFile file) {
if (!myRef.isValid()) {
return false;
}
PsiManager manager = file.getManager();
if (!manager.isInProject(file)) {
return false;
}
if (getClassesToImport().isEmpty()) {
return false;
}
return true;
}
@Nullable
@@ -70,6 +80,7 @@ public abstract class ImportClassFixBase<T extends PsiElement & PsiReference> im
protected abstract boolean hasTypeParameters(T reference);
@NotNull
public List<PsiClass> getClassesToImport() {
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(myRef.getProject());
String name = getReferenceName(myRef);
@@ -36,7 +36,6 @@ public class SideEffectWarningDialog extends DialogWrapper {
private final String myBeforeText;
private final String myAfterText;
private final boolean myCanCopeWithSideEffects;
private AbstractAction myMakeStmtAction;
private AbstractAction myRemoveAllAction;
private AbstractAction myCancelAllAction;
public static final int MAKE_STATEMENT = 1;
@@ -71,7 +70,7 @@ public class SideEffectWarningDialog extends DialogWrapper {
};
actions.add(myRemoveAllAction);
if (myCanCopeWithSideEffects) {
myMakeStmtAction = new AbstractAction() {
AbstractAction makeStmtAction = new AbstractAction() {
{
UIUtil.setActionNameAndMnemonic(QuickFixBundle.message("side.effect.action.transform"), this);
}
@@ -80,9 +79,8 @@ public class SideEffectWarningDialog extends DialogWrapper {
public void actionPerformed(ActionEvent e) {
close(MAKE_STATEMENT);
}
};
actions.add(myMakeStmtAction);
actions.add(makeStmtAction);
}
myCancelAllAction = new AbstractAction() {
{
@@ -132,11 +132,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
}
if (isStringLiteral(token)) {
boolean escapeSlashes = true;
if (rawText != null && rawText.rawText != null) {
//is is assumed that all slashes are escaped in the raw text but some unescaped symbols can present (for example " copied from CharLiteral '"')
//so we should escape all needed symbols except slash.
escapeSlashes = false;
text = rawText.rawText;
}
@@ -144,7 +140,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
@NonNls String breaker = getLineBreaker(token);
final String[] lines = LineTokenizer.tokenize(text.toCharArray(), false, true);
for (int i = 0; i < lines.length; i++) {
buffer.append(escapeCharCharacters(lines[i], token, escapeSlashes));
buffer.append(escapeCharCharacters(lines[i], token));
if (i != lines.length - 1 || "\n".equals(breaker) && text.endsWith("\n")) {
buffer.append(breaker);
}
@@ -153,10 +149,10 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
}
else if (isCharLiteral(token)) {
if (rawText != null && rawText.rawText != null) {
return escapeCharCharacters(rawText.rawText, token, false);
return escapeCharCharacters(rawText.rawText, token);
}
else {
return escapeCharCharacters(text, token, true);
return escapeCharCharacters(text, token);
}
}
return text;
@@ -206,9 +202,9 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
}
@NotNull
protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token, boolean escapeSlashes) {
protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token) {
StringBuilder buffer = new StringBuilder();
StringUtil.escapeStringCharacters(s.length(), s, isStringLiteral(token) ? "\"" : "\'",escapeSlashes, buffer);
StringUtil.escapeStringCharacters(s.length(), s, isStringLiteral(token) ? "\"" : "\'", buffer);
return buffer.toString();
}
}
@@ -19,6 +19,7 @@
*/
package com.intellij.psi.impl.file;
import com.intellij.core.CoreJavaDirectoryService;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.fileTemplates.FileTemplateUtil;
@@ -39,14 +40,11 @@ import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class JavaDirectoryServiceImpl extends JavaDirectoryService {
public class JavaDirectoryServiceImpl extends CoreJavaDirectoryService {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.file.JavaDirectoryServiceImpl");
@Override
@@ -57,23 +55,6 @@ public class JavaDirectoryServiceImpl extends JavaDirectoryService {
return JavaPsiFacade.getInstance(dir.getProject()).findPackage(packageName);
}
@Override
@NotNull
public PsiClass[] getClasses(@NotNull PsiDirectory dir) {
LOG.assertTrue(dir.isValid());
List<PsiClass> classes = null;
for (PsiFile file : dir.getFiles()) {
if (file instanceof PsiClassOwner && file.getViewProvider().getLanguages().size() == 1) {
PsiClass[] psiClasses = ((PsiClassOwner)file).getClasses();
if (psiClasses.length == 0) continue;
if (classes == null) classes = new ArrayList<PsiClass>();
ContainerUtil.addAll(classes, psiClasses);
}
}
return classes == null ? PsiClass.EMPTY_ARRAY : classes.toArray(new PsiClass[classes.size()]);
}
@Override
@NotNull
public PsiClass createClass(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException {
@@ -789,7 +789,8 @@ public class ImportHelper{
}
private static void addUnresolvedImportNames(@NotNull final Set<Pair<String, Boolean>> namesToImport, @NotNull PsiJavaFile file) {
PsiImportStatementBase[] imports = file.getImportList().getAllImportStatements();
final PsiImportList importList = file.getImportList();
PsiImportStatementBase[] imports = importList == null ? PsiImportStatementBase.EMPTY_ARRAY : importList.getAllImportStatements();
final Map<String, Pair<String, Boolean>> unresolvedNames = new THashMap<String, Pair<String, Boolean>>();
@NotNull Set<Pair<String, Boolean>> unresolvedOnDemand = new THashSet<Pair<String, Boolean>>();
for (PsiImportStatementBase anImport : imports) {
@@ -34,6 +34,7 @@ import java.util.Set;
public class OptimizeImportsRefactoringHelper implements RefactoringHelper<Set<PsiJavaFile>> {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.OptimizeImportsRefactoringHelper");
@Override
public Set<PsiJavaFile> prepareOperation(final UsageInfo[] usages) {
Set<PsiJavaFile> javaFiles = new HashSet<PsiJavaFile>();
for (UsageInfo usage : usages) {
@@ -49,8 +50,10 @@ public class OptimizeImportsRefactoringHelper implements RefactoringHelper<Set<P
return javaFiles;
}
@Override
public void performOperation(final Project project, final Set<PsiJavaFile> javaFiles) {
CodeStyleManager.getInstance(project).performActionWithFormatterDisabled(new Runnable() {
@Override
public void run() {
PsiDocumentManager.getInstance(project).commitAllDocuments();
}
@@ -58,35 +61,42 @@ public class OptimizeImportsRefactoringHelper implements RefactoringHelper<Set<P
final Set<SmartPsiElementPointer<PsiImportStatementBase>> redundants = new HashSet<SmartPsiElementPointer<PsiImportStatementBase>>();
final Runnable findRedundantImports = new Runnable() {
@Override
public void run() {
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project);
final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
final SmartPointerManager pointerManager = SmartPointerManager.getInstance(project);
int i = 0;
final int fileCount = javaFiles.size();
for (PsiJavaFile file : javaFiles) {
if (file.isValid()) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile != null) {
if (progressIndicator != null) {
progressIndicator.setText2(virtualFile.getPresentableUrl());
progressIndicator.setFraction((double)i++/fileCount);
}
final Collection<PsiImportStatementBase> perFile = styleManager.findRedundantImports(file);
if (perFile != null) {
for (PsiImportStatementBase redundant : perFile) {
redundants.add(pointerManager.createSmartPsiElementPointer(redundant));
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project);
final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
final SmartPointerManager pointerManager = SmartPointerManager.getInstance(project);
int i = 0;
final int fileCount = javaFiles.size();
for (PsiJavaFile file : javaFiles) {
if (file.isValid()) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile != null) {
if (progressIndicator != null) {
progressIndicator.setText2(virtualFile.getPresentableUrl());
progressIndicator.setFraction((double)i++ / fileCount);
}
final Collection<PsiImportStatementBase> perFile = styleManager.findRedundantImports(file);
if (perFile != null) {
for (PsiImportStatementBase redundant : perFile) {
redundants.add(pointerManager.createSmartPsiElementPointer(redundant));
}
}
}
}
}
}
}
});
}
};
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(findRedundantImports, "Removing redundant imports", false, project)) return;
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
try {
for (final SmartPsiElementPointer<PsiImportStatementBase> pointer : redundants) {
@@ -23,6 +23,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.search.GlobalSearchScope;
@@ -114,8 +115,9 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
}
for (final PsiReference ref : ReferencesSearch.search(myTargetParameter, new LocalSearchScope(myMethod), false)) {
if (ref.getElement() instanceof PsiReferenceExpression) {
result.add(new ParameterUsageInfo((PsiReferenceExpression)ref));
final PsiElement element = ref.getElement();
if (element instanceof PsiReferenceExpression || element instanceof PsiDocParamRef) {
result.add(new ParameterUsageInfo(ref));
}
}
@@ -344,15 +346,23 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
}
private void processParameterUsage(ParameterUsageInfo usage) throws IncorrectOperationException {
final PsiJavaCodeReferenceElement referenceExpression = usage.getReferenceExpression();
if (referenceExpression.getParent() instanceof PsiReferenceExpression) {
// todo: check for correctness
referenceExpression.delete();
}
else {
final PsiExpression expression =
JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory().createExpressionFromText("this", null);
referenceExpression.replace(expression);
final PsiReference reference = usage.getReferenceExpression();
if (reference instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)reference;
if (referenceExpression.getParent() instanceof PsiReferenceExpression) {
// todo: check for correctness
referenceExpression.delete();
}
else {
final PsiExpression expression =
JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory().createExpressionFromText("this", null);
referenceExpression.replace(expression);
}
} else {
final PsiElement element = reference.getElement();
if (element instanceof PsiDocParamRef) {
element.getParent().delete();
}
}
}
@@ -15,22 +15,21 @@
*/
package com.intellij.refactoring.convertToInstanceMethod;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiReferenceExpression;
import com.intellij.psi.PsiReference;
import com.intellij.usageView.UsageInfo;
/**
* @author dsl
*/
class ParameterUsageInfo extends UsageInfo {
private final PsiReferenceExpression myReferenceExpression;
private final PsiReference myReferenceExpression;
public ParameterUsageInfo(PsiReferenceExpression refereneceElement) {
super(refereneceElement);
myReferenceExpression = refereneceElement;
public ParameterUsageInfo(PsiReference referenceElement) {
super(referenceElement);
myReferenceExpression = referenceElement;
}
public PsiJavaCodeReferenceElement getReferenceExpression() {
public PsiReference getReferenceExpression() {
return myReferenceExpression;
}
}
@@ -38,8 +38,8 @@ import com.intellij.refactoring.MoveDestination;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.move.MoveCallback;
import com.intellij.refactoring.move.MoveHandler;
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.usageView.UsageViewUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -170,6 +170,13 @@ public class MoveClassesOrPackagesToNewDirectoryDialog extends DialogWrapper {
return;
}
try {
MoveFilesOrDirectoriesUtil.checkIfMoveIntoSelf(myDirectory, directory);
}
catch (IncorrectOperationException e) {
Messages.showErrorDialog(project, e.getMessage(), RefactoringBundle.message("cannot.move"));
return;
}
super.doOKAction();
final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(directory);
@@ -37,6 +37,7 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class TypeMigrationProcessor extends BaseRefactoringProcessor {
@@ -132,7 +133,7 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
text = "method \'" + ((PsiMethod)myRoot[0]).getName() + "\' return";
}
else {
text = myRoot.toString();
text = Arrays.toString(myRoot);
}
Content content = UsageViewManager.getInstance(myProject)
.addContent("Migrate Type of " +
@@ -0,0 +1,110 @@
/*
* Copyright 2000-2011 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.core;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* @author yole
*/
public class CoreJavaDirectoryService extends JavaDirectoryService {
private static final Logger LOG = Logger.getInstance("#com.intellij.core.CoreJavaDirectoryService");
@Override
public PsiPackage getPackage(@NotNull PsiDirectory dir) {
return ServiceManager.getService(dir.getProject(), CoreJavaFileManager.class).getPackage(dir);
}
@NotNull
@Override
public PsiClass[] getClasses(@NotNull PsiDirectory dir) {
LOG.assertTrue(dir.isValid());
List<PsiClass> classes = null;
for (PsiFile file : dir.getFiles()) {
if (file instanceof PsiClassOwner && file.getViewProvider().getLanguages().size() == 1) {
PsiClass[] psiClasses = ((PsiClassOwner)file).getClasses();
if (psiClasses.length == 0) continue;
if (classes == null) classes = new ArrayList<PsiClass>();
ContainerUtil.addAll(classes, psiClasses);
}
}
return classes == null ? PsiClass.EMPTY_ARRAY : classes.toArray(new PsiClass[classes.size()]);
}
@NotNull
@Override
public PsiClass createClass(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public PsiClass createClass(@NotNull PsiDirectory dir, @NotNull String name, @NotNull String templateName)
throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public PsiClass createClass(@NotNull PsiDirectory dir,
@NotNull String name,
@NotNull String templateName,
boolean askForUndefinedVariables) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public void checkCreateClass(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public PsiClass createInterface(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public PsiClass createEnum(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public PsiClass createAnnotationType(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public boolean isSourceRoot(@NotNull PsiDirectory dir) {
return false;
}
@Override
public LanguageLevel getLanguageLevel(@NotNull PsiDirectory dir) {
return LanguageLevel.HIGHEST;
}
}
@@ -16,6 +16,7 @@
package com.intellij.core;
import com.intellij.openapi.roots.PackageIndex;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem;
import com.intellij.openapi.vfs.local.CoreLocalFileSystem;
@@ -70,6 +71,18 @@ public class CoreJavaFileManager extends PackageIndex implements JavaFileManager
return result;
}
@Nullable
public PsiPackage getPackage(PsiDirectory dir) {
final File ioFile = new File(dir.getVirtualFile().getPath());
for (File root : myClasspath) {
if (FileUtil.isAncestor(root, ioFile, false)) {
final String relativePath = FileUtil.getRelativePath(root.getPath(), ioFile.getPath(), '.');
return new PsiPackageImpl(myPsiManager, relativePath);
}
}
return null;
}
@Nullable
private VirtualFile findUnderClasspathEntry(File classpathEntry, String relativeName) {
if (classpathEntry.isFile()) {
@@ -27,6 +27,7 @@ import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.roots.PackageIndex;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.impl.EmptySubstitutorImpl;
import com.intellij.psi.impl.JavaPsiFacadeImpl;
import com.intellij.psi.impl.JavaPsiImplementationHelper;
@@ -60,10 +61,14 @@ public class JavaCoreEnvironment extends CoreEnvironment {
registerProjectExtensionPoint(PsiElementFinder.EP_NAME, PsiElementFinder.class);
registerExtensionPoint(Extensions.getRootArea(), ClsStubBuilderFactory.EP_NAME, ClsStubBuilderFactory.class);
registerExtensionPoint(Extensions.getRootArea(), PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
addExtension(ClsStubBuilderFactory.EP_NAME, new DefaultClsStubBuilderFactory());
myApplication.registerService(PsiPackageImplementationHelper.class, new CorePsiPackageImplementationHelper());
myFileManager = new CoreJavaFileManager(myPsiManager, getLocalFileSystem(), myJarFileSystem);
JavaPsiFacadeImpl javaPsiFacade = new JavaPsiFacadeImpl(myProject, myPsiManager, myFileManager, null);
myProject.registerService(CoreJavaFileManager.class, myFileManager);
registerComponentInstance(myProject.getPicoContainer(),
JavaPsiFacade.class,
javaPsiFacade);
@@ -72,10 +77,10 @@ public class JavaCoreEnvironment extends CoreEnvironment {
myProject.registerService(JavaPsiImplementationHelper.class, new CoreJavaPsiImplementationHelper());
myProject.registerService(PsiResolveHelper.class, new PsiResolveHelperImpl(myPsiManager));
myProject.registerService(LanguageLevelProjectExtension.class, new CoreLanguageLevelProjectExtension());
myProject.registerService(PsiPackageImplementationHelper.class, new CorePsiPackageImplementationHelper());
myProject.registerService(PackageIndex.class, myFileManager);
myApplication.registerService(EmptySubstitutor.class, new EmptySubstitutorImpl());
myApplication.registerService(JavaDirectoryService.class, new CoreJavaDirectoryService());
}
public void addToClasspath(File path) {
@@ -299,7 +299,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
@Override
@NotNull
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull final GlobalSearchScope scope) {
List<PsiClass> list = null;
String packageName = psiPackage.getQualifiedName();
for (PsiDirectory dir : psiPackage.getDirectories(scope)) {
@@ -315,9 +315,18 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
}
}
}
return list == null ? PsiClass.EMPTY_ARRAY : list.toArray(new PsiClass[list.size()]);
}
if (list == null) {
return PsiClass.EMPTY_ARRAY;
}
ContainerUtil.quickSort(list, new Comparator<PsiClass>() {
@Override
public int compare(PsiClass o1, PsiClass o2) {
return scope.compare(o2.getContainingFile().getVirtualFile(), o1.getContainingFile().getVirtualFile());
}
});
return list.toArray(new PsiClass[list.size()]);
}
@Override
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
@@ -0,0 +1,10 @@
class Test {
/**
* method description
* @param a description
*/
public static void ma<caret>in(A a) {
}
}
class A {}
@@ -0,0 +1,10 @@
class Test {
}
class A {
/**
* method description
*/
public void main() {
}
}
@@ -43,6 +43,8 @@ import com.intellij.openapi.progress.ProgressManager
import com.intellij.psi.PsiFile
import com.intellij.util.Consumer
import com.intellij.openapi.editor.LogicalPosition
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.util.Computable
/**
* @author peter
@@ -949,9 +951,15 @@ public class Bar {
myFixture.completeBasic()
}
myFixture.checkResult 'class Foo {pr<caret>}'
lookup.items.each {
lookup.list.cellRenderer.getListCellRendererComponent(lookup.list, it, 0, false, false)
}
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
void run() {
getLookup().items.each {
getLookup().list.cellRenderer.getListCellRendererComponent(getLookup().list, it, 0, false, false)
}
}
});
assert myFixture.lookupElementStrings.containsAll(['private', 'protected'])
}
@@ -1098,7 +1106,10 @@ class Foo {{
<caret>t;
t;
}}"""
def caret = myFixture.editor.offsetToLogicalPosition(myFixture.editor.caretModel.offset)
def caret = ApplicationManager.getApplication().runReadAction(new Computable<LogicalPosition>() {
public LogicalPosition compute() {
return myFixture.editor.offsetToLogicalPosition(myFixture.editor.caretModel.offset)
}});
edt { myFixture.editor.selectionModel.setBlockSelection(caret, new LogicalPosition(caret.line + 1, caret.column + 1)) }
type 'toStr'
assert lookup
@@ -30,6 +30,8 @@ public class ConvertToInstanceMethodTest extends LightRefactoringTestCase {
public void testInterfaceTypeParameter() throws Exception { doTest(0); }
public void testJavadocParameter() throws Exception { doTest(0); }
private void doTest(final int targetParameter) throws Exception {
final String filePath = "/refactoring/convertToInstanceMethod/" + getTestName(false) + ".java";
configureByFile(filePath);
@@ -43,11 +43,6 @@ public abstract class IdeaTestCase extends PlatformTestCase {
super.tearDown();
}
@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"})
protected IdeaTestCase() {
initPlatformPrefix();
}
public final JavaPsiFacadeEx getJavaFacade() {
return myJavaFacade;
}
@@ -15,8 +15,10 @@
*/
package com.intellij.testFramework.fixtures.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiModificationTrackerImpl;
@@ -51,17 +53,25 @@ public class JavaCodeInsightTestFixtureImpl extends CodeInsightTestFixtureImpl i
}
private PsiClass addClass(@NonNls final String rootPath, @NotNull @NonNls final String classText) {
final PsiClass aClass = ((PsiJavaFile)PsiFileFactory.getInstance(getProject()).createFileFromText("a.java", classText)).getClasses()[0];
final String qName = aClass.getQualifiedName();
final String qName =
ApplicationManager.getApplication().runReadAction(new Computable<String>() {
public String compute() {
final PsiClass aClass = ((PsiJavaFile)PsiFileFactory.getInstance(getProject()).createFileFromText("a.java", classText)).getClasses()[0];
return aClass.getQualifiedName();
}
});
assert qName != null;
final PsiFile psiFile = new WriteCommandAction<PsiFile>(getProject()) {
@Override
protected void run(Result<PsiFile> result) throws Throwable {
result.setResult(addFileToProject(rootPath, qName.replace('.', '/') + ".java", classText));
}
}.execute().getResultObject();
return ((PsiJavaFile)psiFile).getClasses()[0];
return ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
public PsiClass compute() {
return ((PsiJavaFile)psiFile).getClasses()[0];
}
});
}
@Override
@@ -194,6 +194,7 @@ public abstract class AbstractLayoutCodeProcessor {
final Runnable[] resultRunnable = new Runnable[1];
Runnable readAction = new Runnable() {
@Override
public void run() {
if (!checkFileWritable(file)) return;
try{
@@ -205,6 +206,7 @@ public abstract class AbstractLayoutCodeProcessor {
}
};
Runnable writeAction = new Runnable() {
@Override
public void run() {
if (resultRunnable[0] != null) {
resultRunnable[0].run();
@@ -261,6 +263,7 @@ public abstract class AbstractLayoutCodeProcessor {
}
return new Runnable() {
@Override
public void run() {
SequentialModalProgressTask progressTask = new SequentialModalProgressTask(myProject, myCommandName);
ReformatFilesTask reformatFilesTask = new ReformatFilesTask(tasks);
@@ -277,11 +280,13 @@ public abstract class AbstractLayoutCodeProcessor {
final Runnable[] resultRunnable = new Runnable[1];
runLayoutCodeProcess(
new Runnable() {
@Override
public void run() {
resultRunnable[0] = preprocessFiles(new ArrayList<PsiFile>(Arrays.asList(files)));
}
},
new Runnable() {
@Override
public void run() {
if (resultRunnable[0] != null){
resultRunnable[0].run();
@@ -352,10 +357,12 @@ public abstract class AbstractLayoutCodeProcessor {
final Runnable[] resultRunnable = new Runnable[1];
runLayoutCodeProcess(new Runnable() {
@Override
public void run() {
resultRunnable[0] = preprocessFiles(array);
}
}, new Runnable() {
@Override
public void run() {
if (resultRunnable[0] != null) {
resultRunnable[0].run();
@@ -450,12 +457,14 @@ public abstract class AbstractLayoutCodeProcessor {
final ModalityState modalityState = ModalityState.current();
final Runnable process = new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runReadAction(readAction);
}
};
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
//DaemonCodeAnalyzer.getInstance(myProject).setUpdateByTimerEnabled(false);
@@ -474,8 +483,10 @@ public abstract class AbstractLayoutCodeProcessor {
*/
final Runnable writeRunnable = new Runnable() {
@Override
public void run() {
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
@Override
public void run() {
if (globalAction) CommandProcessor.getInstance().markCurrentCommandAsGlobal(myProject);
try {
@@ -31,7 +31,6 @@ import com.intellij.ide.PowerSaveMode;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -696,16 +695,10 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx
// we'll restart when write action finish
return;
}
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
if (documentManager.hasUncommitedDocuments()) {
if (ModalityState.current() == ModalityState.NON_MODAL) {
((PsiDocumentManagerImpl)documentManager).cancelAndRunWhenAllCommitted("restart daemon when all committed", this);
return;
}
else {
// when modal dialog is open, DocumentCommitThread is not able to commit in background, so force commit here
documentManager.commitAllDocuments();
}
if (PsiDocumentManager.getInstance(myProject).hasUncommitedDocuments()) {
((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(myProject)).cancelAndRunWhenAllCommitted(
"restart daemon when all committed", this);
return;
}
Map<FileEditor, HighlightingPass[]> passes = new THashMap<FileEditor, HighlightingPass[]>(activeEditors.size());
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.NotNull;
*/
public class TemporaryRunConfigurationTypeUsagesCollector extends AbstractRunConfigurationTypeUsagesCollector {
private static final GroupDescriptor GROUP_ID = GroupDescriptor.create("run-configuration-type-temporary");
private static final GroupDescriptor GROUP_ID = GroupDescriptor.create("run-configuration-type-temp");
@NotNull
@Override
@@ -358,9 +358,9 @@ public class FindUsagesManager implements JDOMExternalizable {
private static UsageSearcher createUsageSearcher(final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor,
final FindUsagesHandler handler,
final FindUsagesOptions options,
FindUsagesOptions _options,
final PsiFile scopeFile) {
final FindUsagesOptions options = _options.clone();
return new UsageSearcher() {
@Override
public void generate(@NotNull final Processor<Usage> processor) {
@@ -30,6 +30,7 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
@@ -55,6 +56,7 @@ import java.util.Map;
public class DirectoryChooser extends DialogWrapper {
@NonNls private static final String FILTER_NON_EXISTING = "filter_non_existing";
private static final String DEFAULT_SELECTION = "last_directory_selection";
private final DirectoryChooserView myView;
private boolean myFilterExisting;
private PsiDirectory myDefaultSelection;
@@ -106,6 +108,13 @@ public class DirectoryChooser extends DialogWrapper {
if (myTabbedPaneWrapper.getSelectedIndex() == 1) {
setSelection(myChooseByNamePanel.getChosenElement());
}
final ItemWrapper item = myView.getSelectedItem();
if (item != null) {
final PsiDirectory directory = item.getDirectory();
if (directory != null) {
PropertiesComponent.getInstance(directory.getProject()).setValue(DEFAULT_SELECTION, directory.getVirtualFile().getPath());
}
}
super.doOKAction();
}
@@ -363,8 +372,11 @@ public class DirectoryChooser extends DialogWrapper {
if (myView.getItemsSize() > 0){
myView.clearItems();
}
if (defaultSelection == null && directories.length > 0) {
defaultSelection = directories[0];
if (defaultSelection == null) {
defaultSelection = getDefaultSelection(directories, project);
if (defaultSelection == null && directories.length > 0) {
defaultSelection = directories[0];
}
}
int selectionIndex = -1;
for(int i = 0; i < directories.length; i++){
@@ -437,6 +449,19 @@ public class DirectoryChooser extends DialogWrapper {
myView.getComponent().repaint();
}
@Nullable
private static PsiDirectory getDefaultSelection(PsiDirectory[] directories, Project project) {
final String defaultSelectionPath = PropertiesComponent.getInstance(project).getValue(DEFAULT_SELECTION);
if (defaultSelectionPath != null) {
final VirtualFile directoryByDefault = LocalFileSystem.getInstance().findFileByPath(defaultSelectionPath);
if (directoryByDefault != null) {
final PsiDirectory directory = PsiManager.getInstance(project).findDirectory(directoryByDefault);
return directory != null && ArrayUtil.find(directories, directory) > -1 ? directory : null;
}
}
return null;
}
private static boolean isParent(PsiDirectory directory, PsiDirectory parentCandidate) {
while (directory != null) {
if (directory.equals(parentCandidate)) return true;
@@ -36,6 +36,7 @@ import com.intellij.usages.UsageInfoToUsageConverter;
import com.intellij.util.Consumer;
import javax.swing.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -87,6 +88,7 @@ public class DependenciesUsagesPanel extends UsagesPanel {
elementsToSearch = searchFor;
usages = FindDependencyUtil.findDependencies(myBuilders, searchIn, searchFor);
}
assert !new HashSet<PsiFile>(elementsToSearch).contains(null);
}
catch (ProcessCanceledException e) {
}
@@ -18,7 +18,6 @@ package com.intellij.psi.impl;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -54,6 +53,7 @@ import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
import com.intellij.util.containers.Queue;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -318,7 +318,7 @@ public class DocumentCommitThread implements Runnable, Disposable {
}
if (success) {
assert !ApplicationManager.getApplication().isDispatchThread();
ApplicationManager.getApplication().invokeLater(finishRunnable, ModalityState.NON_MODAL); // do not commit while modal progress is running
UIUtil.invokeLaterIfNeeded(finishRunnable);
log("Invoked later finishRunnable", document, false, success, finishRunnable, indicator);
}
}
@@ -499,9 +499,6 @@ public class FileBasedIndex implements ApplicationComponent {
keyDescriptor.save(out, key);
}
}
catch (IOException e) {
throw e;
}
catch (IllegalArgumentException e) {
throw new IOException("Error saving data for index " + indexId, e);
}
@@ -517,9 +514,6 @@ public class FileBasedIndex implements ApplicationComponent {
}
return list;
}
catch (IOException e) {
throw e;
}
catch (IllegalArgumentException e) {
throw new IOException("Error reading data for index " + indexId, e);
}
@@ -23,6 +23,7 @@ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class RefreshQueue {
@@ -34,22 +35,23 @@ public abstract class RefreshQueue {
return createSession(async, recursive, finishRunnable, getDefaultModalityState());
}
public abstract RefreshSession createSession(boolean async, boolean recursive, @Nullable Runnable finishRunnable, ModalityState state);
public abstract RefreshSession createSession(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @NotNull ModalityState state);
public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, ModalityState state, VirtualFile... files) {
public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @NotNull ModalityState state, @NotNull VirtualFile... files) {
RefreshSession session = createSession(async, recursive, finishRunnable, state);
session.addAllFiles(files);
session.launch();
}
public abstract void refreshLocalRoots(boolean async, @Nullable Runnable postAction, ModalityState modalityState);
public abstract void refreshLocalRoots(boolean async, @Nullable Runnable postAction, @NotNull ModalityState modalityState);
public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, VirtualFile... files) {
public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @NotNull VirtualFile... files) {
refresh(async, recursive, finishRunnable, getDefaultModalityState(), files);
}
public abstract void processSingleEvent(VFileEvent event);
@NotNull
protected ModalityState getDefaultModalityState() {
return ModalityState.NON_MODAL;
}
@@ -31,7 +31,7 @@ public abstract class RefreshSession {
public abstract void addFile(@NotNull VirtualFile file);
public abstract void addAllFiles(Collection<VirtualFile> files);
public void addAllFiles(VirtualFile[] files) {
public void addAllFiles(@NotNull VirtualFile[] files) {
addAllFiles(Arrays.asList(files));
}
@@ -74,6 +74,10 @@ public class ActionInstallPlugin extends AnAction implements DumbAware {
}
public void actionPerformed(AnActionEvent e) {
install();
}
public void install() {
IdeaPluginDescriptor[] selection = getPluginTable().getSelectedObjects();
if (userConfirm(selection)) {
@@ -113,14 +117,14 @@ public class ActionInstallPlugin extends AnAction implements DumbAware {
}
catch (IOException e1) {
PluginManagerMain.LOG.error(e1);
IOExceptionDialog.showErrorDialog(IdeBundle.message("action.download.and.install.plugin"), IdeBundle.message("error.plugin.download.failed"));
IOExceptionDialog
.showErrorDialog(IdeBundle.message("action.download.and.install.plugin"), IdeBundle.message("error.plugin.download.failed"));
}
getPluginTable().updateUI();
}
}
public PluginTable getPluginTable() {
return host.getPluginTable();
}
@@ -16,7 +16,10 @@
package com.intellij.ide.plugins;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.DumbAware;
@@ -30,6 +33,8 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.LinkedHashSet;
@@ -87,6 +92,19 @@ public class AvailablePluginsManagerMain extends PluginManagerMain {
return ScrollPaneFactory.createScrollPane(pluginTable);
}
@Override
protected void installTableActions(final PluginTable pluginTable) {
super.installTableActions(pluginTable);
pluginTable.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() != 2) return;
if (pluginTable.columnAtPoint(e.getPoint()) < 0) return;
if (pluginTable.rowAtPoint(e.getPoint()) < 0) return;
new ActionInstallPlugin(AvailablePluginsManagerMain.this, installed).install();
}
});
}
@Override
public void reset() {
UiNotifyConnector.doWhenFirstShown(getPluginTable(), new Runnable() {
@@ -32,7 +32,7 @@ public class ModalityStateEx extends ModalityState {
this(EMPTY_REFS_ARRAY);
}
public ModalityStateEx(Object[] modalEntities) {
public ModalityStateEx(@NotNull Object[] modalEntities) {
if (modalEntities.length > 0) {
myModalEntities = new WeakReference[modalEntities.length];
for (int i = 0; i < modalEntities.length; i++) {
@@ -71,6 +71,7 @@ public class ModalityStateEx extends ModalityState {
return false;
}
@Override
public boolean dominates(@NotNull ModalityState anotherState){
if (anotherState == ModalityState.any()) return false;
@@ -192,8 +192,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private static final int MOUSE_SELECTION_STATE_WORD_SELECTED = 1;
private static final int MOUSE_SELECTION_STATE_LINE_SELECTED = 2;
private final MarkupModelListener myMarkupModelListener;
private EditorHighlighter myHighlighter;
private final TextDrawingCallback myTextDrawingCallback = new MyTextDrawingCallback();
@@ -306,7 +304,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
myMouseMotionListeners = ContainerUtil.createEmptyCOWList();
myMarkupModelListener = new MarkupModelListener() {
MarkupModelListener markupModelListener = new MarkupModelListener() {
@Override
public void afterAdded(@NotNull RangeHighlighterEx highlighter) {
attributesChanged(highlighter);
@@ -341,8 +339,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
};
((MarkupModelEx)DocumentMarkupModel.forDocument(myDocument, myProject, true)).addMarkupModelListener(myCaretModel, myMarkupModelListener);
((MarkupModelEx)getMarkupModel()).addMarkupModelListener(myCaretModel, myMarkupModelListener);
((MarkupModelEx)DocumentMarkupModel.forDocument(myDocument, myProject, true)).addMarkupModelListener(myCaretModel, markupModelListener);
((MarkupModelEx)getMarkupModel()).addMarkupModelListener(myCaretModel, markupModelListener);
myDocument.addDocumentListener(myFoldingModel,myCaretModel);
myDocument.addDocumentListener(myCaretModel,myCaretModel);
@@ -247,19 +247,26 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa
super.stop();
if (isDialogShowing()) {
if (myFocusTrackback != null) {
myFocusTrackback.setWillBeSheduledForRestore();
}
}
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
boolean wasShowing = myDialog != null && myDialog.getPanel() != null && myDialog.getPanel().isShowing();
boolean wasShowing = isDialogShowing();
if (myDialog != null) {
myDialog.hide();
}
if (wasShowing) {
myFocusTrackback.restoreFocus();
} else {
myFocusTrackback.consume();
if (myFocusTrackback != null) {
if (wasShowing) {
myFocusTrackback.restoreFocus();
} else {
myFocusTrackback.consume();
}
}
myStoppedAlready = true;
@@ -271,6 +278,10 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa
SwingUtilities.invokeLater(EmptyRunnable.INSTANCE); // Just to give blocking dispatching a chance to go out.
}
private boolean isDialogShowing() {
return myDialog != null && myDialog.getPanel() != null && myDialog.getPanel().isShowing();
}
public void cancel() {
super.cancel();
if (myDialog != null) {
@@ -121,6 +121,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
MessageBus messageBus = app.getMessageBus();
MessageBusConnection connection = messageBus.connect(app);
connection.subscribe(StateStorage.STORAGE_TOPIC, new StateStorage.Listener() {
@Override
public void storageFileChanged(final VirtualFileEvent event, @NotNull final StateStorage storage) {
VirtualFile file = event.getFile();
LOG.debug("[RELOAD] Storage file changed: " + file.getPath());
@@ -133,10 +134,12 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
addProjectManagerListener(
new ProjectManagerListener() {
@Override
public void projectOpened(final Project project) {
MessageBus messageBus = project.getMessageBus();
MessageBusConnection connection = messageBus.connect(project);
connection.subscribe(StateStorage.STORAGE_TOPIC, new StateStorage.Listener() {
@Override
public void storageFileChanged(final VirtualFileEvent event, @NotNull final StateStorage storage) {
VirtualFile file = event.getFile();
if (!file.isDirectory() && !(event.getRequestor() instanceof StateStorage.SaveSession)) {
@@ -151,6 +154,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
}
}
@Override
public void projectClosed(Project project) {
busPublisher.projectClosed(project);
for (ProjectManagerListener listener : getListeners(project)) {
@@ -158,6 +162,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
}
}
@Override
public boolean canCloseProject(Project project) {
for (ProjectManagerListener listener : getListeners(project)) {
if (!listener.canCloseProject(project)) {
@@ -167,6 +172,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
return true;
}
@Override
public void projectClosing(Project project) {
busPublisher.projectClosing(project);
for (ProjectManagerListener listener : getListeners(project)) {
@@ -179,10 +185,12 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
registerExternalProjectFileListener(virtualFileManagerEx);
}
@Override
public void disposeComponent() {
Disposer.dispose(myChangedFilesAlarm);
if (myDefaultProject != null) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
Disposer.dispose(myDefaultProject);
}
@@ -193,9 +201,11 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
}
}
@Override
public void initComponent() {
}
@Override
@Nullable
public Project newProject(final String projectName, String filePath, boolean useDefaultProjectSettings, boolean isDummy) {
filePath = canonicalize(filePath);
@@ -283,8 +293,10 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
private static void scheduleDispose(final ProjectImpl project) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
if (!project.isDisposed()) {
Disposer.dispose(project);
@@ -295,6 +307,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
});
}
@Override
@Nullable
public Project loadProject(String filePath) throws IOException, JDOMException, InvalidDataException {
try {
@@ -333,6 +346,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
public synchronized boolean isDefaultProjectInitialized() {
return myDefaultProject != null;
}
@Override
@NotNull
public synchronized Project getDefaultProject() {
LOG.assertTrue(!myDefaultProjectWasDisposed, "Default project has been already disposed!");
@@ -357,6 +371,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
return myDefaultProjectRootElement;
}
@Override
@NotNull
public Project[] getOpenProjects() {
if (myOpenProjectsArrayCache.length != myOpenProjects.size()) {
@@ -374,6 +389,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
return myOpenProjectsArrayCache;
}
@Override
public boolean isProjectOpened(Project project) {
if (ApplicationManager.getApplication().isUnitTestMode() && myCurrentTestProject != null) {
return project == myCurrentTestProject || myOpenProjects.contains(project);
@@ -381,6 +397,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
return myOpenProjects.contains(project);
}
@Override
public boolean openProject(final Project project) {
final Application application = ApplicationManager.getApplication();
@@ -403,6 +420,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
final StartupManagerImpl startupManager = (StartupManagerImpl)StartupManager.getInstance(project);
boolean ok = myProgressManager.runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
startupManager.runStartupActivities();
@@ -410,6 +428,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
// only when startCacheUpdate is called from UI thread, we can guarantee that
// when the method returns, the application has entered dumb mode
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
startupManager.startCacheUpdate();
}
@@ -418,6 +437,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
startupManager.runPostStartupActivitiesFromExtensions();
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
startupManager.runPostStartupActivities();
}
@@ -434,6 +454,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
if (!application.isHeadlessEnvironment() && !application.isUnitTestMode()) {
// should be invoked last
StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() {
@Override
public void run() {
final TrackingPathMacroSubstitutor macroSubstitutor =
((ProjectEx)project).getStateStore().getStateStorageManager().getMacroSubstitutor();
@@ -451,6 +472,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
myOpenProjectsArrayCache = myOpenProjects.toArray(new Project[myOpenProjects.size()]);
}
@Override
public Project loadAndOpenProject(@NotNull final String filePath) throws IOException {
final Project project = convertAndLoadProject(filePath);
@@ -462,6 +484,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
if (!openProject(project)) {
showWelcomeScreenIfNoProjectOpened();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
Disposer.dispose(project);
}
@@ -498,6 +521,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
if (!conversionResult.conversionNotNeeded()) {
StartupManager.getInstance(project).registerPostStartupActivity(new Runnable() {
@Override
public void run() {
conversionResult.postStartupActivity(project);
}
@@ -519,6 +543,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
final ProjectImpl project = createProject(null, canonicalize(filePath), false, false);
try {
myProgressManager.runProcessWithProgressSynchronously(new ThrowableComputable<Project, IOException>() {
@Override
@Nullable
public Project compute() throws IOException {
doLoadProject(filePath, project);
@@ -572,9 +597,11 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
private void registerExternalProjectFileListener(VirtualFileManagerEx virtualFileManager) {
virtualFileManager.addVirtualFileManagerListener(new VirtualFileManagerListener() {
@Override
public void beforeRefreshStart(boolean asynchonous) {
}
@Override
public void afterRefreshFinish(boolean asynchonous) {
scheduleReloadApplicationAndProject();
}
@@ -618,6 +645,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
final LinkedHashSet<String> components = new LinkedHashSet<String>();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
try {
reloadOk[0] = ((ApplicationImpl)app).getStateStore().reload(causes, components);
@@ -684,6 +712,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
final boolean[] reloadOk = {false};
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
try {
LOG.debug("[RELOAD] Reloading project/components...");
@@ -725,14 +754,17 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
Messages.getQuestionIcon()) == 0;
}
@Override
public boolean isFileSavedToBeReloaded(VirtualFile candidate) {
return mySavedCopies.containsKey(candidate);
}
@Override
public void blockReloadingProjectOnExternalChanges() {
myReloadBlockCount.incrementAndGet();
}
@Override
public void unblockReloadingProjectOnExternalChanges() {
if (myReloadBlockCount.decrementAndGet() == 0) scheduleReloadApplicationAndProject();
}
@@ -748,6 +780,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
// public void run() {
// IdeEventQueue.getInstance().removeIdleListener(this);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (!tryToReloadApplication()) return;
askToReloadProjectIfConfigFilesChangedExternally();
@@ -759,17 +792,20 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
//}, ModalityState.NON_MODAL);
}
@Override
public void setCurrentTestProject(@Nullable final Project project) {
assert ApplicationManager.getApplication().isUnitTestMode();
myCurrentTestProject = project;
}
@Override
@Nullable
public Project getCurrentTestProject() {
assert ApplicationManager.getApplication().isUnitTestMode();
return myCurrentTestProject;
}
@Override
public void saveChangedProjectFile(final VirtualFile file, final Project project) {
if (file.exists()) {
copyToTemp(file);
@@ -813,6 +849,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
myChangedFilesAlarm.cancelAllRequests();
myChangedFilesAlarm.addRequest(new Runnable() {
@Override
public void run() {
LOG.debug("[RELOAD] Scheduling reload application & project, myReloadBlockCount = " + myReloadBlockCount);
if (myReloadBlockCount.get() == 0) {
@@ -855,6 +892,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
}
}
@Override
public void reloadProject(@NotNull final Project p) {
reloadProjectImpl(p, true, false);
}
@@ -874,6 +912,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
final Application application = ApplicationManager.getApplication();
application.invokeLater(new Runnable() {
@Override
public void run() {
LOG.debug("Reloading project.");
ProjectImpl projectImpl = (ProjectImpl)project[0];
@@ -894,6 +933,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
if (project[0].isDisposed() || ProjectUtil.closeAndDispose(project[0])) {
application.runWriteAction(new Runnable() {
@Override
public void run() {
for (final IFile originalFile : original) {
restoreCopy(LocalFileSystem.getInstance().refreshAndFindFileByIoFile(originalFile));
@@ -915,6 +955,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
}
*/
@Override
public boolean closeProject(@NotNull final Project project) {
return closeProject(project, true, false);
}
@@ -940,6 +981,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
fireProjectClosing(project); // somebody can start progress here, do not wrap in write action
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
myOpenProjects.remove(project);
cacheOpenProjects();
@@ -982,6 +1024,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
}
}
@Override
public void addProjectManagerListener(@NotNull ProjectManagerListener listener) {
myListeners.add(listener);
}
@@ -997,11 +1040,13 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
});
}
@Override
public void removeProjectManagerListener(@NotNull ProjectManagerListener listener) {
boolean removed = myListeners.remove(listener);
LOG.assertTrue(removed);
}
@Override
public void addProjectManagerListener(@NotNull Project project, @NotNull ProjectManagerListener listener) {
List<ProjectManagerListener> listeners = project.getUserData(LISTENERS_IN_PROJECT_KEY);
if (listeners == null) {
@@ -1010,6 +1055,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
listeners.add(listener);
}
@Override
public void removeProjectManagerListener(@NotNull Project project, @NotNull ProjectManagerListener listener) {
List<ProjectManagerListener> listeners = project.getUserData(LISTENERS_IN_PROJECT_KEY);
if (listeners != null) {
@@ -1051,6 +1097,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
}
}
@Override
public boolean canClose(Project project) {
if (LOG.isDebugEnabled()) {
LOG.debug("enter: canClose()");
@@ -1080,6 +1127,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
Messages.getWarningIcon()) == 0;
}
@Override
public void writeExternal(Element parentNode) throws WriteExternalException {
if (myDefaultProject != null) {
myDefaultProject.save();
@@ -1098,6 +1146,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
myDefaultProjectRootElement = defaultProjectRootElement;
}
@Override
public void readExternal(Element parentNode) throws InvalidDataException {
myDefaultProjectRootElement = parentNode.getChild(ELEMENT_DEFAULT_PROJECT);
@@ -1108,20 +1157,24 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
myDefaultProjectRootElement.detach();
}
@Override
public String getExternalFileName() {
return "project.default";
}
@Override
@NotNull
public String getComponentName() {
return "ProjectManager";
}
@Override
@NotNull
public File[] getExportFiles() {
return new File[]{PathManager.getOptionsFile(this)};
}
@Override
@NotNull
public String getPresentableName() {
return ProjectBundle.message("project.default.settings");
@@ -30,6 +30,7 @@ import com.intellij.openapi.vfs.VfsBundle;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.io.storage.HeavyProcessLatch;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
@@ -41,22 +42,22 @@ public class RefreshQueueImpl extends RefreshQueue {
private final ExecutorService myQueue = ConcurrencyUtil.newSingleThreadExecutor("FS Synchronizer");
private final ProgressIndicator myRefreshIndicator = new RefreshProgress(VfsBundle.message("file.synchronize.progress"));
public void execute(final RefreshSessionImpl session) {
public void execute(@NotNull RefreshSessionImpl session) {
if (session.isAsynchronous()) {
ModalityState state = session.getModalityState();
queueSession(session, state != null ? state : ModalityState.NON_MODAL);
queueSession(session, state);
}
else {
final Application app = ApplicationManager.getApplication();
boolean isEDT = app.isDispatchThread();
final boolean hasWriteAction = app.isWriteAccessAllowed();
if (isEDT || hasWriteAction) {
final Application application = ApplicationManager.getApplication();
boolean isEDT = application.isDispatchThread();
if (isEDT) {
session.scan();
final boolean hasWriteAction = application.isWriteAccessAllowed();
session.fireEvents(hasWriteAction);
}
else {
if (((ApplicationEx)app).holdsReadLock()) {
LOG.error("Do not call synchronous refresh from inside read action except for event dispatch thread. This will eventually cause deadlock if there are events to fire");
if (((ApplicationEx)application).holdsReadLock()) {
LOG.error( "Do not call synchronous refresh from inside read action except for event dispatch thread. This will eventually cause deadlock if there are events to fire");
return;
}
@@ -66,7 +67,7 @@ public class RefreshQueueImpl extends RefreshQueue {
}
}
private void queueSession(final RefreshSessionImpl session, final ModalityState modality) {
private void queueSession(@NotNull final RefreshSessionImpl session, @NotNull final ModalityState modality) {
myQueue.submit(new Runnable() {
@Override
public void run() {
@@ -96,12 +97,12 @@ public class RefreshQueueImpl extends RefreshQueue {
}
@Override
public RefreshSession createSession(final boolean async, boolean recursively, @Nullable final Runnable finishRunnable, ModalityState state) {
public RefreshSession createSession(final boolean async, boolean recursively, @Nullable final Runnable finishRunnable, @NotNull ModalityState state) {
return new RefreshSessionImpl(async, recursively, finishRunnable, state);
}
@Override
public void refreshLocalRoots(boolean async, Runnable postAction, ModalityState modalityState) {
public void refreshLocalRoots(boolean async, @Nullable Runnable postAction, @NotNull ModalityState modalityState) {
RefreshQueue.getInstance().refresh(async, true, postAction, modalityState, ManagingFS.getInstance().getLocalRoots());
}
@@ -47,7 +47,7 @@ public class RefreshSessionImpl extends RefreshSession {
private final Semaphore mySemaphore = new Semaphore();
private volatile boolean iHaveEventsToFire;
private ModalityState myModalityState;
private final ModalityState myModalityState;
public RefreshSessionImpl(final boolean isAsync, final boolean recursively, final Runnable finishRunnable) {
this(isAsync, recursively, finishRunnable, ModalityState.NON_MODAL);
@@ -65,6 +65,7 @@ public class RefreshSessionImpl extends RefreshSession {
myIsRecursive = false;
myFinishRunnable = null;
myEvents = new ArrayList<VFileEvent>(events);
myModalityState = ModalityState.NON_MODAL;
}
@Override
@@ -167,6 +168,7 @@ public class RefreshSessionImpl extends RefreshSession {
return events;
}
@NotNull
public ModalityState getModalityState() {
return myModalityState;
}
@@ -145,7 +145,7 @@ class ComboContentLayout extends ContentLayout {
@Override
public void showContentPopup(ListPopup listPopup) {
listPopup.setMinimumSize(new Dimension(myComboLabel.getPreferredSize().width, 0));
listPopup.setMinimumSize(new Dimension(myComboLabel.getSize().width, 0));
listPopup.showUnderneathOf(myComboLabel);
}
@@ -425,7 +425,7 @@ public class ToolWindowContentUi extends JPanel implements ContentUI, PropertyCh
@NotNull
@Override
public String getTextFor(Content value) {
final String displayName = value.getDisplayName();
final String displayName = value.getTabName();
return displayName != null ? displayName : "";
}
@@ -42,7 +42,7 @@ class StatusPanel extends JPanel {
private boolean myLogMode;
private boolean myDirty;
private boolean myAfterClick;
private final Alarm myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
private Alarm myLogAlarm;
private final TextPanel myTextPanel = new TextPanel() {
@Override
protected String getTextForPreferredSize() {
@@ -103,6 +103,17 @@ class StatusPanel extends JPanel {
return null;
}
private Alarm getAlarm() {
if (myLogAlarm == null || myLogAlarm.isDisposed()) {
myLogAlarm = null; //Welcome screen
Project project = getActiveProject();
if (project != null) {
myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, project);
}
}
return myLogAlarm;
}
public void setLogMessage(String text) {
ApplicationManager.getApplication().assertIsDispatchThread();
@@ -117,26 +128,30 @@ class StatusPanel extends JPanel {
final Project project = getActiveProject();
final Pair<Notification, Long> statusMessage = EventLog.getStatusMessage(project);
myLogMode = logAllowed && StringUtil.isEmpty(nonLogText) && statusMessage != null;
myLogAlarm.cancelAllRequests();
final Alarm alarm = getAlarm();
if (myLogMode) {
myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
new Runnable() {
@Override
public void run() {
assert statusMessage != null;
String text = EventLog.formatForLog(statusMessage.first).status;
if (myDirty || System.currentTimeMillis() - statusMessage.second >= DateFormatUtil.MINUTE) {
text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.second)) + ")";
if (alarm != null) {
alarm.cancelAllRequests();
if (myLogMode) {
myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
new Runnable() {
@Override
public void run() {
assert statusMessage != null;
String text = EventLog.formatForLog(statusMessage.first).status;
if (myDirty || System.currentTimeMillis() - statusMessage.second >= DateFormatUtil.MINUTE) {
text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.second)) + ")";
}
setStatusText(text);
alarm.addRequest(this, 30000);
}
setStatusText(text);
myLogAlarm.addRequest(this, 30000);
}
}.run();
} else {
myTextPanel.setCursor(Cursor.getDefaultCursor());
myDirty = true;
setStatusText(nonLogText);
}.run();
} else {
myTextPanel.setCursor(Cursor.getDefaultCursor());
myDirty = true;
setStatusText(nonLogText);
}
}
return myLogMode;
}
@@ -155,15 +170,18 @@ class StatusPanel extends JPanel {
}
public void restoreLogIfNeeded() {
myLogAlarm.cancelAllRequests();
myLogAlarm.addRequest(new Runnable() {
@Override
public void run() {
if (StringUtil.isEmpty(myTextPanel.getText())) {
updateText(true, "");
Alarm alarm = getAlarm();
if (alarm != null) {
alarm.cancelAllRequests();
alarm.addRequest(new Runnable() {
@Override
public void run() {
if (StringUtil.isEmpty(myTextPanel.getText())) {
updateText(true, "");
}
}
}
}, 300);
}, 300);
}
}
public String getText() {
@@ -307,7 +307,12 @@ public class FocusTrackback {
if (mustBeLastInStack) {
for (int i = index + 1; i < stack.size(); i++) {
if (!stack.get(i).isConsumed()) {
if (!stack.get(i).isMustBeShown()) {
if ((stack.get(i).isSheduledForRestore() || stack.get(i).isWillBeSheduledForRestore()) && !stack.get(i).isConsumed()) {
toFocus = null;
break;
}
} else if (!stack.get(i).isConsumed()) {
toFocus = null;
break;
}
@@ -86,7 +86,7 @@ public class ExternalChangesAndRefreshingTest extends IntegrationTestCase {
@Override
protected void runBareRunnable(Runnable r) throws Throwable {
if (getName().equals("testRefreshingAsynchronously")) {
// this methods waits for another thread to finish, that leds
// this method waits for another thread to finish, that leads
// to deadlock in swing-thread. Therefore we have to run this test
// outside of swing-thread
r.run();
@@ -30,6 +30,7 @@ import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Clock;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.testFramework.PlatformTestCase;
@@ -143,8 +144,12 @@ public abstract class IntegrationTestCase extends PlatformTestCase {
return getRevisionsFor(f, null);
}
protected List<Revision> getRevisionsFor(VirtualFile f, String pattern) {
return LocalHistoryTestCase.collectRevisions(getVcs(), getRootEntry(), f.getPath(), myProject.getLocationHash(), pattern);
protected List<Revision> getRevisionsFor(final VirtualFile f, final String pattern) {
return ApplicationManager.getApplication().runReadAction(new Computable<List<Revision>>() {
public List<Revision> compute() {
return LocalHistoryTestCase.collectRevisions(getVcs(), getRootEntry(), f.getPath(), myProject.getLocationHash(), pattern);
}
});
}
protected RootEntry getRootEntry() {
@@ -41,7 +41,6 @@ import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.impl.ModuleManagerImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.project.impl.ProjectImpl;
import com.intellij.openapi.project.impl.TooManyProjectLeakedException;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModifiableRootModel;
@@ -68,7 +67,6 @@ import com.intellij.psi.impl.PsiDocumentManagerImpl;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
import com.intellij.util.PatchedWeakReference;
import com.intellij.util.Processor;
import com.intellij.util.indexing.IndexableSetContributor;
import com.intellij.util.indexing.IndexedRootsProvider;
import com.intellij.util.ui.UIUtil;
@@ -85,6 +83,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -127,6 +126,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
protected void initApplication() throws Exception {
boolean firstTime = ourApplication == null;
autodetectPlatformPrefix();
ourApplication = IdeaTestApplication.getInstance(getApplicationConfigDirPath());
ourApplication.setDataProvider(this);
@@ -135,6 +135,22 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
}
}
private static void autodetectPlatformPrefix() {
if (ourPlatformPrefixInitialized) {
return;
}
URL resource = PlatformTestCase.class.getClassLoader().getResource("idea/ApplicationInfo.xml");
if (resource == null) {
resource = PlatformTestCase.class.getClassLoader().getResource("idea/IdeaApplicationInfo.xml");
if (resource == null) {
System.setProperty("idea.platform.prefix", "PlatformLangXml");
}
else {
System.setProperty("idea.platform.prefix", "Idea");
}
}
}
private static void cleanPersistedVFSContent() {
((PersistentFS)ManagingFS.getInstance()).cleanPersistedContents();
}
@@ -429,7 +445,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
try {
LightPlatformTestCase.checkEditorsReleased();
}
catch (AssertionError error) {
catch (Throwable error) {
result.add(error);
}
}
@@ -617,7 +633,8 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
throw IdeaLogger.ourErrorsOccurred;
}
if (++LEAK_WALKS % 1000 == 0) {
/*
if (++LEAK_WALKS % 1 == 0) {
LeakHunter.checkLeak(ApplicationManager.getApplication(), ProjectImpl.class, new Processor<ProjectImpl>() {
@Override
public boolean process(ProjectImpl project) {
@@ -625,6 +642,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
}
});
}
*/
}
private static int LEAK_WALKS;
@@ -36,6 +36,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -236,6 +237,10 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu
VfsUtil.saveText(virtualFile[0], fileText);
}
}.execute();
return PsiManager.getInstance(getProject()).findFile(virtualFile[0]);
return ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
public PsiFile compute() {
return PsiManager.getInstance(getProject()).findFile(virtualFile[0]);
}
});
}
}
@@ -756,12 +756,12 @@ public class StringUtil {
return suggestion + "ren";
}
if (endsWithChar(suggestion, 's') || endsWithChar(suggestion, 'x') || suggestion.endsWith("ch")) {
if (endsWithIgnoreCase(suggestion, "s") || endsWithIgnoreCase(suggestion, "x") || endsWithIgnoreCase(suggestion, "ch")) {
return suggestion + "es";
}
int len = suggestion.length();
if (endsWithChar(suggestion, 'y') && len > 1 && !isVowel(suggestion.charAt(len - 2))) {
if (endsWithIgnoreCase(suggestion, "y") && len > 1 && !isVowel(toLowerCase(suggestion.charAt(len - 2)))) {
return suggestion.substring(0, len - 1) + "ies";
}
@@ -119,7 +119,7 @@ public abstract class XBreakpointType<B extends XBreakpoint<P>, P extends XBreak
}
/**
* @deprecated override {@link #getEditorsProvider(XBreakpoint)} instead
* @deprecated override {@link #getEditorsProvider(B, com.intellij.openapi.project.Project)} instead
*/
@Nullable
public XDebuggerEditorsProvider getEditorsProvider() {
@@ -127,7 +127,7 @@ public abstract class XBreakpointType<B extends XBreakpoint<P>, P extends XBreak
}
@Nullable
public XDebuggerEditorsProvider getEditorsProvider(@NotNull B breakpoint) {
public XDebuggerEditorsProvider getEditorsProvider(@NotNull B breakpoint, @NotNull Project project) {
return getEditorsProvider();
}
@@ -63,7 +63,7 @@ public class XBreakpointPropertiesPanel<B extends XBreakpoint<?>> {
mySuspendPolicyPanel.init(project, breakpointManager, breakpoint);
XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint);
XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint, project);
myBreakpointActionsPanel.init(project, breakpointManager, breakpoint, debuggerEditorsProvider);
@@ -105,7 +105,7 @@ public class XLightBreakpointPropertiesPanel<B extends XBreakpoint<?>> implement
mySubPanels.add(mySuspendPolicyPanel);
myMasterBreakpointPanel.init(project, breakpointManager, breakpoint);
mySubPanels.add(myMasterBreakpointPanel);
XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint);
XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint, project);
myActionsPanel.init(project, breakpointManager, breakpoint, debuggerEditorsProvider);
mySubPanels.add(myActionsPanel);
@@ -1,9 +1,25 @@
/*
* Copyright 2000-2011 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.testAssistant;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -22,14 +38,6 @@ import java.util.List;
*/
public class TestDataLineMarkerProvider implements LineMarkerProvider {
public LineMarkerInfo getLineMarkerInfo(PsiElement element) {
if (!(element instanceof PsiMethod)) {
return null;
}
final PsiMethod method = (PsiMethod)element;
if (isTestMethod(method)) {
return new LineMarkerInfo<PsiMethod>(method, method.getTextOffset(), PlatformIcons.TEST_SOURCE_FOLDER, Pass.UPDATE_ALL, null,
new TestDataNavigationHandler());
}
return null;
}
@@ -56,6 +64,20 @@ public class TestDataLineMarkerProvider implements LineMarkerProvider {
}
public void collectSlowLineMarkers(List<PsiElement> elements, Collection<LineMarkerInfo> result) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
return;
}
for (PsiElement element : elements) {
if (!(element instanceof PsiMethod)) {
continue;
}
final PsiMethod method = (PsiMethod)element;
if (isTestMethod(method)) {
result.add(new LineMarkerInfo<PsiMethod>(
method, method.getTextOffset(), PlatformIcons.TEST_SOURCE_FOLDER, Pass.UPDATE_ALL, null, new TestDataNavigationHandler()
));
}
}
}
@Nullable
@@ -69,13 +91,17 @@ public class TestDataLineMarkerProvider implements LineMarkerProvider {
final Object constantValue = evaluationHelper.computeConstantExpression(value, false);
if (constantValue instanceof String) {
String path = (String) constantValue;
if (path.indexOf("$CONTENT_ROOT") >= 0) {
if (path.contains("$CONTENT_ROOT")) {
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final VirtualFile contentRoot = fileIndex.getContentRootForFile(psiClass.getContainingFile().getVirtualFile());
final VirtualFile file = psiClass.getContainingFile().getVirtualFile();
if (file == null) {
return null;
}
final VirtualFile contentRoot = fileIndex.getContentRootForFile(file);
if (contentRoot == null) return null;
path = path.replace("$CONTENT_ROOT", contentRoot.getPath());
}
if (path.indexOf("$PROJECT_ROOT") >= 0) {
if (path.contains("$PROJECT_ROOT")) {
final VirtualFile baseDir = project.getBaseDir();
if (baseDir == null) {
return null;
@@ -930,9 +930,7 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, NonD
@Override
public boolean equals(final BaseInjection o1, final BaseInjection o2) {
if (!o1.sameLanguageParameters(o2)) return false;
if (!o1.getInjectionPlaces().equals(o2.getInjectionPlaces())) return false;
return true;
return o1.sameLanguageParameters(o2) && Arrays.equals(o1.getInjectionPlaces(), o2.getInjectionPlaces());
}
}
@@ -41,6 +41,7 @@ import com.intellij.openapi.vfs.*;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashSet;
@@ -51,6 +52,8 @@ import org.jetbrains.android.dom.resources.ResourceElement;
import org.jetbrains.android.dom.resources.Resources;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.fileTypes.AndroidIdlFileType;
import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
import org.jetbrains.android.resourceManagers.LocalResourceManager;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidUtils;
@@ -609,10 +612,15 @@ public class AndroidCompileUtil {
public static void createGenModulesAndSourceRoots(@NotNull final AndroidFacet facet) {
final Module module = facet.getModule();
String sourceRootPath;
String sourceRootPath = AndroidRootUtil.getRenderscriptGenSourceRootPath(module);
if (sourceRootPath != null) {
createSourceRootIfNotExist(sourceRootPath, module);
final GlobalSearchScope moduleScope = facet.getModule().getModuleScope();
if (FileTypeIndex.getFiles(AndroidRenderscriptFileType.INSTANCE, moduleScope).size() > 0) {
sourceRootPath = AndroidRootUtil.getRenderscriptGenSourceRootPath(module);
if (sourceRootPath != null) {
createSourceRootIfNotExist(sourceRootPath, module);
}
}
sourceRootPath = facet.getAptGenSourceRootPath();
@@ -620,9 +628,11 @@ public class AndroidCompileUtil {
createSourceRootIfNotExist(sourceRootPath, module);
}
sourceRootPath = facet.getAidlGenSourceRootPath();
if (sourceRootPath != null) {
createSourceRootIfNotExist(sourceRootPath, module);
if (FileTypeIndex.getFiles(AndroidIdlFileType.ourFileType, moduleScope).size() > 0) {
sourceRootPath = facet.getAidlGenSourceRootPath();
if (sourceRootPath != null) {
createSourceRootIfNotExist(sourceRootPath, module);
}
}
}
@@ -0,0 +1,17 @@
package org.jetbrains.android.dom;
import com.intellij.util.xml.ResolvingConverter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Eugene.Kudelevsky
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface AdditionalConverter {
Class<? extends ResolvingConverter> value();
}
@@ -0,0 +1,10 @@
package org.jetbrains.android.dom.converters;
/**
* @author Eugene.Kudelevsky
*/
public class QuietResourceReferenceConverter extends ResourceReferenceConverter {
public QuietResourceReferenceConverter() {
setQuiet(true);
}
}
@@ -18,6 +18,7 @@ package org.jetbrains.android.dom.converters;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.command.undo.UndoUtil;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
@@ -28,11 +29,9 @@ import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PsiNavigateUtil;
import com.intellij.util.xml.ConvertContext;
import com.intellij.util.xml.CustomReferenceConverter;
import com.intellij.util.xml.GenericDomValue;
import com.intellij.util.xml.ResolvingConverter;
import com.intellij.util.xml.*;
import org.jetbrains.android.dom.ResourceType;
import org.jetbrains.android.dom.AdditionalConverter;
import org.jetbrains.android.dom.resources.Item;
import org.jetbrains.android.dom.resources.ResourceElement;
import org.jetbrains.android.dom.resources.ResourceValue;
@@ -61,6 +60,7 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
private boolean myAdditionalConverterSoft = false;
private boolean myWithPrefix = true;
private boolean myWithExplicitResourceType = true;
private boolean myQuiet = false;
public ResourceReferenceConverter() {
this(new ArrayList<String>());
@@ -81,6 +81,10 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
myAdditionalConverterSoft = soft;
}
public void setQuiet(boolean quiet) {
myQuiet = quiet;
}
@NotNull
private String getPackagePrefix(@Nullable String resourcePackage) {
String prefix = myWithPrefix ? "@" : "";
@@ -117,32 +121,37 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
if (element == null) return result;
String value = getValue(element);
assert value != null;
String resourcePackage = null;
String systemPrefix = getPackagePrefix(SYSTEM_RESOURCE_PACKAGE);
if (value.startsWith(systemPrefix)) {
resourcePackage = SYSTEM_RESOURCE_PACKAGE;
}
else {
result.add(ResourceValue.literal(systemPrefix));
}
if (recommendedTypes.size() == 1) {
String type = recommendedTypes.iterator().next();
boolean explicitResourceType = value.startsWith(getTypePrefix(resourcePackage, type)) || myWithExplicitResourceType;
addResourceReferenceValuesWithDeps(facet, type, resourcePackage, result, explicitResourceType);
}
else {
for (String type : ResourceManager.REFERABLE_RESOURCE_TYPES) {
String typePrefix = getTypePrefix(resourcePackage, type);
if (value.startsWith(typePrefix)) {
addResourceReferenceValuesWithDeps(facet, type, resourcePackage, result, true);
}
else if (recommendedTypes.contains(type)) {
result.add(ResourceValue.literal(typePrefix));
if (!myQuiet || value.startsWith("@")) {
String resourcePackage = null;
String systemPrefix = getPackagePrefix(SYSTEM_RESOURCE_PACKAGE);
if (value.startsWith(systemPrefix)) {
resourcePackage = SYSTEM_RESOURCE_PACKAGE;
}
else {
result.add(ResourceValue.literal(systemPrefix));
}
if (recommendedTypes.size() == 1) {
String type = recommendedTypes.iterator().next();
boolean explicitResourceType = value.startsWith(getTypePrefix(resourcePackage, type)) || myWithExplicitResourceType;
addResourceReferenceValuesWithDeps(facet, type, resourcePackage, result, explicitResourceType);
}
else {
for (String type : ResourceManager.REFERABLE_RESOURCE_TYPES) {
String typePrefix = getTypePrefix(resourcePackage, type);
if (value.startsWith(typePrefix)) {
addResourceReferenceValuesWithDeps(facet, type, resourcePackage, result, true);
}
else if (recommendedTypes.contains(type)) {
result.add(ResourceValue.literal(typePrefix));
}
}
}
}
if (myAdditionalConverter != null) {
for (String variant : myAdditionalConverter.getVariants(context)) {
final ResolvingConverter<String> additionalConverter = getAdditionalConverter(context);
if (additionalConverter != null) {
for (String variant : additionalConverter.getVariants(context)) {
result.add(ResourceValue.literal(variant));
}
}
@@ -162,6 +171,9 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
String s = resourceType.value();
if (s != null) types.add(s);
}
if (types.size() == 0) {
types.addAll(ResourceManager.REFERABLE_RESOURCE_TYPES);
}
return types;
}
@@ -209,8 +221,10 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
public ResourceValue fromString(@Nullable @NonNls String s, ConvertContext context) {
if (s == null) return null;
ResourceValue parsed = ResourceValue.parse(s, true, myWithPrefix);
if ((parsed == null || !parsed.isReference()) && myAdditionalConverter != null) {
String value = myAdditionalConverter.fromString(s, context);
final ResolvingConverter<String> additionalConverter = getAdditionalConverter(context);
if ((parsed == null || !parsed.isReference()) && additionalConverter != null) {
String value = additionalConverter.fromString(s, context);
if (value != null) {
return ResourceValue.literal(value);
}
@@ -224,6 +238,27 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
return parsed;
}
@Nullable
private ResolvingConverter<String> getAdditionalConverter(ConvertContext context) {
if (myAdditionalConverter != null) {
return myAdditionalConverter;
}
final AdditionalConverter additionalConverterAnnotation =
context.getInvocationElement().getAnnotation(AdditionalConverter.class);
if (additionalConverterAnnotation != null) {
final Class<? extends ResolvingConverter> converterClass = additionalConverterAnnotation.value();
if (converterClass != null) {
final ConverterManager converterManager = ServiceManager.getService(ConverterManager.class);
//noinspection unchecked
return (ResolvingConverter<String>)converterManager.getConverterInstance(converterClass);
}
}
return null;
}
public String toString(@Nullable ResourceValue resourceElement, ConvertContext context) {
return resourceElement != null ? resourceElement.toString() : null;
}
@@ -232,22 +267,24 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
public LocalQuickFix[] getQuickFixes(ConvertContext context) {
AndroidFacet facet = AndroidFacet.getInstance(context);
if (facet != null) {
XmlElement element = context.getXmlElement();
if (element instanceof XmlAttribute) {
String value = ((XmlAttribute)element).getValue();
ResourceValue resourceValue = ResourceValue.parse(value, false, myWithPrefix);
if (resourceValue != null) {
String aPackage = resourceValue.getPackage();
String resourceType = resourceValue.getResourceType();
if (resourceType == null && myResourceTypes.size() == 1) {
resourceType = myResourceTypes.get(0);
}
final String resourceName = resourceValue.getResourceName();
if (aPackage == null && resourceType != null && resourceName != null) {
if (value != null &&
FIXABLE_RESOURCE_TYPES.contains(resourceType) &&
AndroidResourceUtil.isCorrectAndroidResourceName(resourceName)) {
return new LocalQuickFix[]{new MyLocalQuickFix(facet, resourceType, resourceName, element.getContainingFile())};
final DomElement domElement = context.getInvocationElement();
if (domElement instanceof GenericDomValue) {
final String value = ((GenericDomValue)domElement).getStringValue();
if (value != null) {
ResourceValue resourceValue = ResourceValue.parse(value, false, myWithPrefix);
if (resourceValue != null) {
String aPackage = resourceValue.getPackage();
String resourceType = resourceValue.getResourceType();
if (resourceType == null && myResourceTypes.size() == 1) {
resourceType = myResourceTypes.get(0);
}
final String resourceName = resourceValue.getResourceName();
if (aPackage == null && resourceType != null && resourceName != null) {
if (FIXABLE_RESOURCE_TYPES.contains(resourceType) && AndroidResourceUtil.isCorrectAndroidResourceName(resourceName)) {
return new LocalQuickFix[]{new MyLocalQuickFix(facet, resourceType, resourceName, context.getFile())};
}
}
}
}
@@ -0,0 +1,12 @@
package org.jetbrains.android.dom.resources;
import com.intellij.util.xml.Convert;
import com.intellij.util.xml.GenericDomValue;
import org.jetbrains.android.dom.converters.QuietResourceReferenceConverter;
/**
* @author Eugene.Kudelevsky
*/
@Convert(QuietResourceReferenceConverter.class)
public interface ArrayElement extends GenericDomValue {
}
@@ -16,11 +16,14 @@
package org.jetbrains.android.dom.resources;
import com.intellij.util.xml.Convert;
import org.jetbrains.android.dom.AdditionalConverter;
import org.jetbrains.android.dom.converters.AndroidBooleanValueConverter;
import org.jetbrains.android.dom.converters.QuietResourceReferenceConverter;
/**
* @author Eugene.Kudelevsky
*/
@Convert(AndroidBooleanValueConverter.class)
@Convert(QuietResourceReferenceConverter.class)
@AdditionalConverter(AndroidBooleanValueConverter.class)
public interface BoolElement extends ResourceElement {
}
@@ -17,11 +17,14 @@ package org.jetbrains.android.dom.resources;
import com.intellij.util.xml.Convert;
import com.intellij.util.xml.GenericDomValue;
import org.jetbrains.android.dom.AdditionalConverter;
import org.jetbrains.android.dom.converters.IntegerConverter;
import org.jetbrains.android.dom.converters.QuietResourceReferenceConverter;
/**
* @author Eugene.Kudelevsky
*/
@Convert(IntegerConverter.class)
@Convert(QuietResourceReferenceConverter.class)
@AdditionalConverter(IntegerConverter.class)
public interface IntegerArrayItem extends GenericDomValue {
}
@@ -16,11 +16,14 @@
package org.jetbrains.android.dom.resources;
import com.intellij.util.xml.Convert;
import org.jetbrains.android.dom.AdditionalConverter;
import org.jetbrains.android.dom.converters.IntegerConverter;
import org.jetbrains.android.dom.converters.QuietResourceReferenceConverter;
/**
* @author Eugene.Kudelevsky
*/
@Convert(IntegerConverter.class)
@Convert(QuietResourceReferenceConverter.class)
@AdditionalConverter(IntegerConverter.class)
public interface IntegerElement extends ResourceElement {
}
@@ -19,9 +19,10 @@ package org.jetbrains.android.dom.resources;
import com.intellij.util.ArrayUtil;
import com.intellij.util.xml.Convert;
import com.intellij.util.xml.GenericAttributeValue;
import org.jetbrains.android.dom.converters.StaticEnumConverter;
import org.jetbrains.android.dom.converters.FormatConverter;
import org.jetbrains.android.dom.attrs.AttributeFormat;
import org.jetbrains.android.dom.converters.FormatConverter;
import org.jetbrains.android.dom.converters.QuietResourceReferenceConverter;
import org.jetbrains.android.dom.converters.StaticEnumConverter;
import org.jetbrains.android.resourceManagers.ResourceManager;
import java.util.List;
@@ -33,6 +34,7 @@ import java.util.List;
* Time: 5:40:29 PM
* To change this template use File | Settings | File Templates.
*/
@Convert(QuietResourceReferenceConverter.class)
public interface Item extends ResourceElement {
class TypeConverter extends StaticEnumConverter {
public TypeConverter() {
@@ -28,14 +28,14 @@ public interface Resources extends AndroidDomElement {
List<StringElement> getStrings();
StringElement addString();
List<ResourceElement> getColors();
ResourceElement addColor();
List<ScalarResourceElement> getColors();
ScalarResourceElement addColor();
List<ResourceElement> getDrawables();
ResourceElement addDrawable();
List<ScalarResourceElement> getDrawables();
ScalarResourceElement addDrawable();
List<ResourceElement> getDimens();
ResourceElement addDimen();
List<ScalarResourceElement> getDimens();
ScalarResourceElement addDimen();
List<Style> getStyles();
Style addStyle();
@@ -0,0 +1,11 @@
package org.jetbrains.android.dom.resources;
import com.intellij.util.xml.Convert;
import org.jetbrains.android.dom.converters.QuietResourceReferenceConverter;
/**
* @author Eugene.Kudelevsky
*/
@Convert(QuietResourceReferenceConverter.class)
public interface ScalarResourceElement extends ResourceElement {
}
@@ -16,8 +16,6 @@
package org.jetbrains.android.dom.resources;
import com.intellij.util.xml.DomElement;
import java.util.List;
/**
@@ -28,5 +26,5 @@ import java.util.List;
* To change this template use File | Settings | File Templates.
*/
public interface StringArray extends ResourceElement {
List<DomElement> getItems();
List<ArrayElement> getItems();
}
@@ -16,6 +16,9 @@
package org.jetbrains.android.dom.resources;
import com.intellij.util.xml.Convert;
import org.jetbrains.android.dom.converters.QuietResourceReferenceConverter;
/**
* Created by IntelliJ IDEA.
* User: Eugene.Kudelevsky
@@ -23,5 +26,6 @@ package org.jetbrains.android.dom.resources;
* Time: 6:35:12 PM
* To change this template use File | Settings | File Templates.
*/
@Convert(QuietResourceReferenceConverter.class)
public interface StringElement extends ResourceElement, StyledText {
}
@@ -742,6 +742,7 @@ public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFace
@Override
public void collectExcludedFolders(MavenProject mavenProject, List<String> result) {
result.add(mavenProject.getGeneratedSourcesDirectory(false) + "/combined-resources");
result.add(mavenProject.getGeneratedSourcesDirectory(false) + "/combined-assets");
result.add(mavenProject.getGeneratedSourcesDirectory(false) + "/extracted-dependencies");
}
@@ -272,7 +272,7 @@ public class LocalResourceManager extends ResourceManager {
ResourceElement element = addValueResource(type, resources);
element.getName().setValue(name);
if (value != null) {
element.setValue(value);
element.setStringValue(value);
}
return element;
}
@@ -1,14 +1,19 @@
package org.jetbrains.android.sdk;
import com.android.resources.ResourceType;
import com.android.sdklib.IAndroidTarget;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.XmlRecursiveElementVisitor;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.dom.attrs.AttributeDefinitions;
import org.jetbrains.android.dom.resources.ResourceElement;
import org.jetbrains.android.resourceManagers.SystemResourceManager;
import org.jetbrains.android.uipreview.RenderServiceFactory;
import org.jetbrains.android.uipreview.RenderingException;
@@ -17,7 +22,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.List;
import java.util.Set;
/**
@@ -75,22 +79,46 @@ public class AndroidTargetData {
if (myThemes == null) {
myThemes = new HashSet<String>();
final SystemResourceManager systemResourceManager = new SystemResourceManager(module, new AndroidPlatform(mySdk, myTarget));
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
if (module.isDisposed() || module.getProject().isDisposed()) {
return;
}
final List<ResourceElement> styles = systemResourceManager.getValueResources(ResourceType.STYLE.getName());
for (ResourceElement style : styles) {
final String styleName = style.getName().getValue();
if (styleName != null && (styleName.equals("Theme") || styleName.startsWith("Theme."))) {
myThemes.add(styleName);
}
for (VirtualFile valueResourceDir : systemResourceManager.getResourceSubdirs("values")) {
for (final VirtualFile valueResourceFile : valueResourceDir.getChildren()) {
if (!valueResourceFile.isDirectory() && valueResourceFile.getFileType().equals(StdFileTypes.XML)) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
final Project project = module.getProject();
if (module.isDisposed() || project.isDisposed()) {
return;
}
final PsiManager psiManager = PsiManager.getInstance(project);
final PsiFile psiFile = psiManager.findFile(valueResourceFile);
if (psiFile instanceof XmlFile) {
psiFile.accept(new XmlRecursiveElementVisitor() {
@Override
public void visitXmlTag(XmlTag tag) {
super.visitXmlTag(tag);
if ("style".equals(tag.getName())) {
final String styleName = tag.getAttributeValue("name");
if (styleName != null && (styleName.equals("Theme") || styleName.startsWith("Theme."))) {
myThemes.add(styleName);
}
}
}
});
psiManager.dropResolveCaches();
InjectedLanguageManager.getInstance(project).dropFileCaches(psiFile);
}
}
});
}
}
});
}
}
return myThemes;
}
@@ -1,6 +1,7 @@
package org.jetbrains.android.uipreview;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.Disposer;
@@ -17,8 +18,10 @@
import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
/**
/**
* @author Eugene.Kudelevsky
*/
public class AndroidLayoutPreviewPanel extends JPanel implements Disposable {
@@ -35,6 +38,9 @@ public class AndroidLayoutPreviewPanel extends JPanel implements Disposable {
private double myZoomFactor = 1.0;
private boolean myZoomToFit = true;
private final List<ProgressIndicator> myProgressIndicators = new ArrayList<ProgressIndicator>();
private boolean myProgressVisible = false;
private final JPanel myImagePanel = new JPanel() {
@Override
@@ -110,16 +116,30 @@ public class AndroidLayoutPreviewPanel extends JPanel implements Disposable {
doRevalidate();
}
public void showProgress() {
((CardLayout)myProgressIconWrapper.getLayout()).show(myProgressIconWrapper, PROGRESS_ICON_CARD_NAME);
myProgressIcon.setVisible(true);
myProgressIcon.resume();
public synchronized void registerIndicator(@NotNull ProgressIndicator indicator) {
synchronized (myProgressIndicators) {
myProgressIndicators.add(indicator);
if (!myProgressVisible) {
myProgressVisible = true;
((CardLayout)myProgressIconWrapper.getLayout()).show(myProgressIconWrapper, PROGRESS_ICON_CARD_NAME);
myProgressIcon.setVisible(true);
myProgressIcon.resume();
}
}
}
public void hideProgress() {
myProgressIcon.suspend();
((CardLayout)myProgressIconWrapper.getLayout()).show(myProgressIconWrapper, EMPTY_CARD_NAME);
myProgressIcon.setVisible(false);
public void unregisterIndicator(@NotNull ProgressIndicator indicator) {
synchronized (myProgressIndicators) {
myProgressIndicators.remove(indicator);
if (myProgressIndicators.size() == 0 && myProgressVisible) {
myProgressVisible = false;
myProgressIcon.suspend();
((CardLayout)myProgressIconWrapper.getLayout()).show(myProgressIconWrapper, EMPTY_CARD_NAME);
myProgressIcon.setVisible(false);
}
}
}
private void doRevalidate() {
@@ -19,6 +19,7 @@ import com.intellij.openapi.actionSystem.ex.CheckboxAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootManager;
@@ -934,7 +935,14 @@ class AndroidLayoutPreviewToolWindowForm implements Disposable {
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
collectFrameworkThemes(themes, facet, finalTargetData, addedThemes);
ProgressManager.getInstance().runProcess(new Runnable() {
@Override
public void run() {
collectFrameworkThemes(themes, facet, finalTargetData, addedThemes);
}
}, new AndroidPreviewProgressIndicator(AndroidLayoutPreviewToolWindowForm.this, 0));
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
@@ -17,7 +17,6 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
@@ -43,7 +42,6 @@ import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentManager;
import com.intellij.util.containers.HashMap;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import org.jetbrains.android.dom.layout.LayoutDomFileDescription;
@@ -63,8 +61,6 @@ import org.jetbrains.annotations.Nullable;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
@@ -304,7 +300,7 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent {
DumbService.getInstance(myProject).waitForSmartMode();
doRender(facet, psiFile);
}
}, new MyProgressIndicator());
}, new AndroidPreviewProgressIndicator(myToolWindowForm, 1000));
}
@Override
@@ -628,45 +624,4 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent {
processFileEditorChange(layoutXmlEditor);
}
}
private class MyProgressIndicator extends ProgressIndicatorBase {
private final Object myLock = new Object();
@Override
public void start() {
super.start();
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
final Timer timer = UIUtil.createNamedTimer("Android rendering progress timer", 1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
synchronized (myLock) {
if (isRunning() && myToolWindowForm != null) {
myToolWindowForm.getPreviewPanel().showProgress();
}
}
}
});
timer.setRepeats(false);
timer.start();
}
});
}
@Override
public void stop() {
synchronized (myLock) {
super.stop();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (myToolWindowForm != null) {
myToolWindowForm.getPreviewPanel().hideProgress();
}
}
});
}
}
}
}
@@ -0,0 +1,61 @@
package org.jetbrains.android.uipreview;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* @author Eugene.Kudelevsky
*/
class AndroidPreviewProgressIndicator extends ProgressIndicatorBase {
private final Object myLock = new Object();
private final int myDelay;
private final AndroidLayoutPreviewToolWindowForm myForm;
AndroidPreviewProgressIndicator(@NotNull AndroidLayoutPreviewToolWindowForm form, int delay) {
myDelay = delay;
myForm = form;
}
@Override
public void start() {
super.start();
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
final Timer timer = UIUtil.createNamedTimer("Android rendering progress timer", myDelay, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
synchronized (myLock) {
if (isRunning() && myForm != null) {
myForm.getPreviewPanel().registerIndicator(AndroidPreviewProgressIndicator.this);
}
}
}
});
timer.setRepeats(false);
timer.start();
}
});
}
@Override
public void stop() {
synchronized (myLock) {
super.stop();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (myForm != null) {
myForm.getPreviewPanel().unregisterIndicator(AndroidPreviewProgressIndicator.this);
}
}
});
}
}
}
@@ -0,0 +1,9 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/unknownDrawabl<caret>e"
/>
</LinearLayout>
@@ -0,0 +1,3 @@
<resources>
<drawable name="unknownDrawable"></drawable>
</resources>
@@ -0,0 +1,3 @@
<resources>
<drawable name="d1">@drawable/dd<caret>2</drawable>
</resources>
@@ -0,0 +1,4 @@
<resources>
<drawable name="d1">@drawable/dd2</drawable>
<drawable name="dd2"></drawable>
</resources>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="res1">false</bool>
<color name="res2">#ffffff</color>
<string name="res3">str</string>
<integer name="res4">1</integer>
<string name="s1">@integer/r<caret></string>
</resources>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="res1">false</bool>
<color name="res2">#ffffff</color>
<string name="res3">str</string>
<integer name="res4">1</integer>
<string name="s1">@integer/res4</string>
</resources>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="res1">false</bool>
<color name="res2">#ffffff</color>
<string name="res3">str</string>
<integer name="res4">1</integer>
<string name="s1">@andr<caret></string>
</resources>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="res1">false</bool>
<color name="res2">#ffffff</color>
<string name="res3">str</string>
<integer name="res4">1</integer>
<string name="s1">@android:<caret></string>
</resources>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="res1">false</bool>
<color name="res2">#ffffff</color>
<string name="res3">str</string>
<integer name="res4">1</integer>
<bool name="s1"><caret></bool>
</resources>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="res1">false</bool>
<color name="res2">#ffffff</color>
<string name="res3">str</string>
<integer name="res4">1</integer>
<string name="s1"><caret></bool>
</resources>
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="res1">1</integer>
<bool name="res2">false</bool>
<color name="res3">#ffffff</color>
<string name="res4">str</string>
<string name="s1">@integer/res1</string>
<string name="s2">@bool/res2</string>
<string name="s3">@color/res3</string>
<string name="s4">@string/res4</string>
<string name="s5"><error>@string/err</error></string>
<color name="c1">@integer/res1</color>
<color name="c2">@bool/res2</color>
<color name="c3">@color/res3</color>
<color name="c4">@string/res4</color>
<color name="c5"><error>@string/err</error></color>
<drawable name="drawable1">@integer/res1</drawable>
<drawable name="drawable2">@bool/res2</drawable>
<drawable name="drawable3">@color/res3</drawable>
<drawable name="drawable4">@string/res4</drawable>
<drawable name="drawable5"><error>@string/err</error></drawable>
<dimen name="dimen1">@integer/res1</dimen>
<dimen name="dimen2">@bool/res2</dimen>
<dimen name="dimen3">@color/res3</dimen>
<dimen name="dimen4">@string/res4</dimen>
<dimen name="dimen5"><error>@string/err</error></dimen>
<array name="ar">
<item>@integer/res1</item>
<item>@bool/res2</item>
<item>@color/res3</item>
<item>@string/res4</item>
<item><error>@string/err</error></item>
</array>
<string-array name="sar">
<item>@integer/res1</item>
<item>@bool/res2</item>
<item>@color/res3</item>
<item>@string/res4</item>
<item><error>@string/err</error></item>
</string-array>
<bool name="bool1">@integer/res1</bool>
<bool name="bool2">@bool/res2</bool>
<bool name="bool3">@color/res3</bool>
<bool name="bool4">@string/res4</bool>
<bool name="bool5"><error>@string/err</error></bool>
<bool name="bool6">true</bool>
<bool name="bool7"><error>tru</error></bool>
<integer name="i1">@integer/res1</integer>
<integer name="i2">@bool/res2</integer>
<integer name="i3">@color/res3</integer>
<integer name="i4">@string/res4</integer>
<integer name="i5"><error>@string/err</error></integer>
<integer name="i6">10</integer>
<integer name="i7"><error>aba</error></integer>
<integer-array name="iar">
<item>@integer/res1</item>
<item>@bool/res2</item>
<item>@color/res3</item>
<item>@string/res4</item>
<item><error>@string/err</error></item>
</integer-array>
<item name="item1" type="string">@integer/res1</item>
<item name="item2" type="string">@bool/res2</item>
<item name="item3" type="string">@color/res3</item>
<item name="item4" type="string">@string/res4</item>
<item name="item5" type="string"><error>@string/err</error></item>
<item name="iitem1" type="bool">@integer/res1</item>
<item name="iitem2" type="bool">@bool/res2</item>
<item name="iitem3" type="bool">@color/res3</item>
<item name="iitem4" type="bool">@string/res4</item>
</resources>
@@ -2,11 +2,17 @@ package org.jetbrains.android.dom;
import com.android.sdklib.SdkConstants;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.util.ArrayUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
@@ -326,6 +332,33 @@ public class AndroidLayoutDomTest extends AndroidDomTest {
doTestCompletionVariants(getTestName(false) + ".xml", "@+id/", "@android:", "@id/idd1", "@id/idd2");
}
public void testCreateResourceFromUsage() throws Throwable {
final VirtualFile virtualFile = copyFileToProject(getTestName(true) + ".xml");
myFixture.configureFromExistingVirtualFile(virtualFile);
final List<HighlightInfo> infos = myFixture.doHighlighting();
final List<IntentionAction> actions = new ArrayList<IntentionAction>();
for (HighlightInfo info : infos) {
final List<Pair<HighlightInfo.IntentionActionDescriptor, TextRange>> ranges = info.quickFixActionRanges;
if (ranges != null) {
for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : ranges) {
actions.add(pair.getFirst().getAction());
}
}
}
assertEquals(1, actions.size());
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
actions.get(0).invoke(getProject(), myFixture.getEditor(), myFixture.getFile());
}
}.execute();
myFixture.checkResultByFile("res/values/drawables.xml", testFolder + '/' + getTestName(true) + "_drawable_after.xml", true);
}
private void copyOnClickClasses() throws IOException {
copyFileToProject("OnClick_Class1.java", "src/p1/p2/OnClick_Class1.java");
copyFileToProject("OnClick_Class2.java", "src/p1/p2/OnClick_Class2.java");
@@ -17,12 +17,20 @@
package org.jetbrains.android.dom;
import com.android.sdklib.SdkConstants;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.xml.XmlAttributeValue;
import java.util.ArrayList;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: Eugene.Kudelevsky
@@ -137,6 +145,26 @@ public class AndroidValueResourcesTest extends AndroidDomTest {
myFixture.testCompletion("res/layout/main.xml", testFolder + "/boolResReference_after.xml");
}
public void testResourceReferenceAsValueHighlighting() throws Throwable {
doTestHighlighting();
}
public void testResourceReferenceAsValueCompletion1() throws Throwable {
doTestCompletion();
}
public void testResourceReferenceAsValueCompletion2() throws Throwable {
doTestCompletion();
}
public void testResourceReferenceAsValueCompletion3() throws Throwable {
doTestCompletionVariants(getTestName(true) + ".xml", "true", "false");
}
public void testResourceReferenceAsValueCompletion4() throws Throwable {
doTestCompletionVariants(getTestName(true) + ".xml");
}
public void testParentStyleReference() throws Throwable {
VirtualFile file = myFixture.copyFileToProject(testFolder + "/psreference.xml", getPathToCopy("psreference.xml"));
myFixture.configureFromExistingVirtualFile(file);
@@ -153,4 +181,31 @@ public class AndroidValueResourcesTest extends AndroidDomTest {
public void testResOverlay() throws Throwable {
doTestCompletionVariants("styles1.xml", "@drawable/picture1", "@drawable/picture2", "@drawable/picture3");
}
public void testCreateResourceFromUsage() throws Throwable {
final VirtualFile virtualFile = copyFileToProject(getTestName(true) + ".xml", "res/values/drawables.xml");
myFixture.configureFromExistingVirtualFile(virtualFile);
final List<HighlightInfo> infos = myFixture.doHighlighting();
final List<IntentionAction> actions = new ArrayList<IntentionAction>();
for (HighlightInfo info : infos) {
final List<Pair<HighlightInfo.IntentionActionDescriptor, TextRange>> ranges = info.quickFixActionRanges;
if (ranges != null) {
for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : ranges) {
actions.add(pair.getFirst().getAction());
}
}
}
assertEquals(1, actions.size());
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
actions.get(0).invoke(getProject(), myFixture.getEditor(), myFixture.getFile());
}
}.execute();
myFixture.checkResultByFile(testFolder + '/' + getTestName(true) + "_after.xml", true);
}
}
@@ -156,9 +156,6 @@ public class IdeaJdk extends SdkType implements JavaSdkType {
else if (new File(sdkHome, "lib/webide.jar").exists()) {
productName = "WebStorm/PhpStorm ";
}
else if (new File(sdkHome, "lib/webide.jar").exists()) {
productName = "WebStorm/PhpStorm ";
}
else {
productName = "IDEA ";
}
+7 -2
View File
@@ -125,7 +125,7 @@ public class Git {
@NotNull
public static GitCommandResult clone(@NotNull Project project, @NotNull File parentDirectory, @NotNull String url, @NotNull String clonedDirectoryName) {
GitLineHandler handler = new GitLineHandler(project, parentDirectory, GitCommand.CLONE);
GitLineHandlerPasswordRequestAware handler = new GitLineHandlerPasswordRequestAware(project, parentDirectory, GitCommand.CLONE);
handler.addParameters(url);
handler.addParameters(clonedDirectoryName);
return run(handler, true);
@@ -221,7 +221,7 @@ public class Git {
}
public static GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec, @NotNull GitLineHandlerListener... listeners) {
final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.PUSH);
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(repository.getProject(), repository.getRoot(), GitCommand.PUSH);
h.setSilent(false);
for (GitLineHandlerListener listener : listeners) {
@@ -274,6 +274,11 @@ public class Git {
});
handler.runInCurrentThread(null);
if (handler instanceof GitLineHandlerPasswordRequestAware && ((GitLineHandlerPasswordRequestAware)handler).hadAuthRequest()) {
errorOutput.add("Authentication failed");
}
final boolean success = !startFailed.get() && errorOutput.isEmpty() && (handler.isIgnoredErrorCode(exitCode.get()) || exitCode.get() == 0);
return new GitCommandResult(success, exitCode.get(), errorOutput, output);
}
@@ -82,7 +82,7 @@ public class GitPull extends GitRepositoryAction {
return;
}
if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(url)) {
if (GitHttpAdapter.shouldUseJGit(url)) {
boolean fetchSuccessful = new GitFetcher(project, indicator).fetchRootsAndNotify(gitRoots, "Push failed", false);
if (!fetchSuccessful) {
return;
@@ -104,7 +104,7 @@ public class GitCheckoutProvider implements CheckoutProvider {
}
private static boolean doClone(@NotNull Project project, @NotNull String directoryName, @NotNull String parentDirectory, @NotNull String sourceRepositoryURL) {
if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(sourceRepositoryURL)) {
if (GitHttpAdapter.shouldUseJGit(sourceRepositoryURL)) {
GitFetchResult result = GitHttpAdapter.cloneRepository(project, new File(parentDirectory, directoryName), sourceRepositoryURL);
GitFetcher.displayFetchResult(project, result, "Clone failed", result.getErrors());
return result.isSuccess();
@@ -19,14 +19,15 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.*;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.EditorComboBox;
import com.intellij.util.ArrayUtil;
import git4idea.commands.*;
import git4idea.commands.GitCommand;
import git4idea.commands.GitLineHandlerPasswordRequestAware;
import git4idea.commands.GitTask;
import git4idea.commands.GitTaskResult;
import git4idea.i18n.GitBundle;
import git4idea.jgit.GitHttpAdapter;
import git4idea.remote.GitRememberedInputs;
import org.jetbrains.annotations.NonNls;
@@ -38,7 +39,6 @@ import java.awt.event.ActionListener;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
/**
@@ -141,7 +141,7 @@ public class GitCloneDialog extends DialogWrapper {
private void test() {
myTestURL = getCurrentUrlText();
boolean testResult = GitHttpAdapter.isHttpUrlWithoutUserCredentials(myTestURL) ? testHttp(myTestURL) : testNatively(myTestURL);
boolean testResult = test(myTestURL);
if (testResult) {
Messages.showInfoMessage(myTestButton, GitBundle.message("clone.test.success.message", myTestURL),
@@ -158,31 +158,13 @@ public class GitCloneDialog extends DialogWrapper {
* That way, we have a hack here: if http response asked for a password, then the url is at least valid and existant, and we consider
* that the test passed.
*/
private boolean testHttp(String url) {
final AtomicBoolean passwordRequested = new AtomicBoolean();
final GitLineHandler handler = new GitLineHandler(myProject, new File("."), GitCommand.LS_REMOTE);
handler.addParameters(url, "master");
handler.addLineListener(new GitLineHandlerAdapter() {
@Override
public void onLineAvailable(String line, Key outputType) {
String lowerCasedLine = line.toLowerCase();
if (lowerCasedLine.contains("password") || lowerCasedLine.contains("login") || lowerCasedLine.contains("username")) {
handler.cancel();
passwordRequested.set(true);
}
}
});
GitTask task = new GitTask(myProject, handler, GitBundle.message("clone.testing", url));
GitTaskResult result = task.executeModal();
return result.isOK() || passwordRequested.get();
}
private boolean testNatively(String url) {
GitSimpleHandler handler = new GitSimpleHandler(myProject, new File("."), GitCommand.LS_REMOTE);
private boolean test(String url) {
final GitLineHandlerPasswordRequestAware handler = new GitLineHandlerPasswordRequestAware(myProject, new File("."), GitCommand.LS_REMOTE);
handler.addParameters(url, "master");
GitTask task = new GitTask(myProject, handler, GitBundle.message("clone.testing", url));
GitTaskResult result = task.executeModal();
return result.isOK();
boolean authFailed = handler.hadAuthRequest();
return result.isOK() || authFailed;
}
/**
@@ -0,0 +1,55 @@
/*
* Copyright 2000-2011 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 git4idea.commands;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import java.io.File;
/**
* {@link GitLineHandler} that listens to Git output and kills itself if "username" or "password" is queried throughout the prompt.
* We can't pass the data to the prompt anyway, so better to kill the process and show an error message, than to hang the task.
*
* @author Kirill Likhodedov
*/
public class GitLineHandlerPasswordRequestAware extends GitLineHandler {
private boolean myAuthRequest;
public GitLineHandlerPasswordRequestAware(@NotNull Project project, @NotNull VirtualFile vcsRoot, @NotNull GitCommand command) {
super(project, vcsRoot, command);
}
public GitLineHandlerPasswordRequestAware(@NotNull Project project, @NotNull File directory, @NotNull GitCommand clone) {
super(project, directory, clone);
}
@Override
protected void onTextAvailable(String text, Key outputType) {
super.onTextAvailable(text, outputType);
if (text.toLowerCase().startsWith("password") || text.toLowerCase().startsWith("username")) {
myAuthRequest = true;
destroyProcess();
}
}
public boolean hadAuthRequest() {
return myAuthRequest;
}
}
@@ -65,11 +65,11 @@ public final class GitHttpAdapter {
private static final Pattern HTTP_URL_WITH_USERNAME_AND_PASSWORD = Pattern.compile("http(s?)://([^\\s^@:]+):([^\\s^@:]+)@.*");
public static boolean isHttpUrlWithoutUserCredentials(@NotNull String url) {
// if username & password are specified in the url, give it to the native Git
public static boolean shouldUseJGit(@NotNull String url) {
if (!url.startsWith("http")) {
return false;
}
// if username & password are specified in the url, give it to the native Git
if (HTTP_URL_WITH_USERNAME_AND_PASSWORD.matcher(url).matches()) {
return false;
}
@@ -79,11 +79,11 @@ public final class GitHttpAdapter {
return !netrcData.hasAuthDataForUrl(url);
}
catch (FileNotFoundException e) {
return false;
return true;
}
catch (IOException e) {
LOG.warn("Couldn't read netrc file", e);
return false;
return true;
}
}
@@ -182,7 +182,7 @@ public class GitPullDialog extends DialogWrapper {
@NotNull
private Collection<String> getRemoteBranches(@NotNull GitDeprecatedRemote remote) {
if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(remote.fetchUrl())) {
if (GitHttpAdapter.shouldUseJGit(remote.fetchUrl())) {
GitRepository repository = GitRepositoryManager.getInstance(myProject).getRepositoryForRoot(gitRoot());
if (repository == null) {
return Collections.emptyList();
@@ -332,7 +332,7 @@ public final class GitPusher {
return pushNatively(repository, pushSpec);
}
else {
return GitHttpAdapter.isHttpUrlWithoutUserCredentials(remoteUrl) ? GitHttpAdapter.push(repository, null, remoteUrl, null) : pushNatively(repository, pushSpec);
return GitHttpAdapter.shouldUseJGit(remoteUrl) ? GitHttpAdapter.push(repository, null, remoteUrl, null) : pushNatively(repository, pushSpec);
}
}
else {
@@ -340,7 +340,7 @@ public final class GitPusher {
assert remote != null : "Remote can't be null for pushSpec " + pushSpec;
String httpUrl = null;
for (String pushUrl : remote.getPushUrls()) {
if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(pushUrl)) {
if (GitHttpAdapter.shouldUseJGit(pushUrl)) {
httpUrl = pushUrl;
break; // TODO support http and ssh urls in one origin
}
@@ -19,6 +19,7 @@ import com.intellij.notification.NotificationType;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitVcs;
import git4idea.commands.*;
@@ -67,7 +68,7 @@ public class GitFetcher {
if (url == null) {
continue;
}
if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(url)) {
if (GitHttpAdapter.shouldUseJGit(url)) {
GitFetchResult res = GitHttpAdapter.fetch(repository, remote, url);
myErrors.addAll(res.getErrors());
if (!res.isSuccess()) {
@@ -86,7 +87,7 @@ public class GitFetcher {
}
private boolean fetchNatively(@NotNull VirtualFile root, @NotNull GitRemote remote) {
final GitLineHandler h = new GitLineHandler(myProject, root, GitCommand.FETCH);
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(myProject, root, GitCommand.FETCH);
h.addParameters(remote.getName());
final GitTask fetchTask = new GitTask(myProject, h, "Fetching...");
fetchTask.setProgressIndicator(myProgressIndicator);
@@ -102,11 +103,15 @@ public class GitFetcher {
protected void onCancel() {
LOG.info("Cancelled fetch.");
}
@Override
protected void onFailure() {
LOG.info("Error fetching: " + h.errors());
myErrors.addAll(h.errors());
if (!h.hadAuthRequest()) {
myErrors.addAll(h.errors());
} else {
myErrors.add(new VcsException("Authentication failed"));
}
}
});
return success.get();

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