mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -284,13 +284,7 @@ public class CompileServerManager implements ApplicationComponent{
|
||||
}
|
||||
try {
|
||||
for (RequestFuture future : futures) {
|
||||
try {
|
||||
future.get();
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
catch (java.util.concurrent.ExecutionException ignored) {
|
||||
}
|
||||
future.waitFor();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -447,7 +441,7 @@ public class CompileServerManager implements ApplicationComponent{
|
||||
connected = client.connect(NetUtils.getLocalHostString(), port);
|
||||
if (connected) {
|
||||
final RequestFuture setupFuture = sendSetupRequest(client);
|
||||
setupFuture.get();
|
||||
setupFuture.waitFor();
|
||||
myProcessHandler = processHandler;
|
||||
myClient = client;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ import org.jetbrains.jps.api.RequestFuture;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CompileDriver {
|
||||
|
||||
@@ -591,15 +591,10 @@ public class CompileDriver {
|
||||
final Set<Artifact> artifacts = ArtifactCompileScope.getArtifactsToBuild(myProject, compileContext.getCompileScope(), true);
|
||||
final RequestFuture future = compileOnServer(compileContext, modules, artifacts, paths, callback);
|
||||
if (future != null) {
|
||||
try {
|
||||
startCancelWatcher(indicator, future);
|
||||
future.get();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.error(e); // todo
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.error(e); // todo
|
||||
while (!future.waitFor(200L , TimeUnit.MILLISECONDS)) {
|
||||
if (indicator.isCanceled()) {
|
||||
future.cancel(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -686,27 +681,6 @@ public class CompileDriver {
|
||||
});
|
||||
}
|
||||
|
||||
private static void startCancelWatcher(final ProgressIndicator indicator, final RequestFuture future) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(200L);
|
||||
if (future.isDone() || future.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
if (indicator.isCanceled()) {
|
||||
future.cancel(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static List<String> fetchFiles(CompileContextImpl context) {
|
||||
if (context.isRebuild()) {
|
||||
return Collections.emptyList();
|
||||
|
||||
@@ -590,7 +590,7 @@ public class ExpectedTypesProvider {
|
||||
}
|
||||
return;
|
||||
}
|
||||
PsiExpression anotherExpr = index > 0 ? operands[0] : operands[1];
|
||||
PsiExpression anotherExpr = index > 0 ? operands[0] : index < operands.length ? operands[1] : null;
|
||||
PsiType anotherType = anotherExpr != null ? anotherExpr.getType() : null;
|
||||
IElementType i = expr.getOperationTokenType();
|
||||
if (i == JavaTokenType.MINUS ||
|
||||
|
||||
+33
@@ -28,6 +28,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -247,6 +248,38 @@ public class AnnotationsHighlightUtil {
|
||||
return highlightInfo;
|
||||
}
|
||||
|
||||
public static HighlightInfo checkForeignInnerClassesUsed(final PsiAnnotation annotation) {
|
||||
final HighlightInfo[] infos = new HighlightInfo[1];
|
||||
final PsiAnnotationOwner owner = annotation.getOwner();
|
||||
if (owner instanceof PsiModifierList) {
|
||||
final PsiElement parent = ((PsiModifierList)owner).getParent();
|
||||
if (parent instanceof PsiClass) {
|
||||
annotation.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitElement(PsiElement element) {
|
||||
if (infos[0] != null) return;
|
||||
super.visitElement(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
final PsiElement resolve = expression.resolve();
|
||||
if (resolve instanceof PsiField &&
|
||||
((PsiMember)resolve).hasModifierProperty(PsiModifier.PRIVATE) &&
|
||||
PsiTreeUtil.isAncestor(parent, resolve, true)) {
|
||||
String description = JavaErrorMessages.message("private.symbol",
|
||||
HighlightUtil.formatField((PsiField)resolve),
|
||||
HighlightUtil.formatClass((PsiClass)parent));
|
||||
infos[0] = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, description);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return infos[0];
|
||||
}
|
||||
|
||||
private static PsiField[] getFields(final PsiClass elementTypeClass, @NonNls final String... names) {
|
||||
PsiField[] result = new PsiField[names.length];
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
|
||||
+2
@@ -498,6 +498,7 @@ public class HighlightMethodUtil {
|
||||
AddTypeArgumentsFix.REGISTRAR.registerCastActions(methodCandidates, methodCall, highlightInfo, fixRange);
|
||||
registerMethodAccessLevelIntentions(methodCandidates, methodCall, list, highlightInfo);
|
||||
ChangeMethodSignatureFromUsageFix.registerIntentions(methodCandidates, list, highlightInfo, fixRange);
|
||||
ConvertDoubleToFloatFix.registerIntentions(methodCandidates, list, highlightInfo, fixRange);
|
||||
WrapExpressionFix.registerWrapAction(methodCandidates, list.getExpressions(), highlightInfo);
|
||||
ChangeParameterClassFix.registerQuickFixActions(methodCall, list, highlightInfo);
|
||||
if (methodCandidates.length == 0) {
|
||||
@@ -1273,6 +1274,7 @@ public class HighlightMethodUtil {
|
||||
if (classReference != null) {
|
||||
ConstructorParametersFixer.registerFixActions(classReference, constructorCall, info, getFixRange(infoElement));
|
||||
ChangeMethodSignatureFromUsageFix.registerIntentions(results, list, info, null);
|
||||
ConvertDoubleToFloatFix.registerIntentions(results, list, info, null);
|
||||
PermuteArgumentsFix.registerFix(info, constructorCall, toMethodCandidates(results), getFixRange(list));
|
||||
ChangeParameterClassFix.registerQuickFixActions(constructorCall, list, info);
|
||||
QuickFixAction.registerQuickFixAction(info, getFixRange(list), new SurroundWithArrayFix(constructorCall), null);
|
||||
|
||||
@@ -1014,7 +1014,7 @@ public class HighlightUtil {
|
||||
}
|
||||
|
||||
// true if floating point literal consists of zeros only
|
||||
private static boolean isFPZero(final String text) {
|
||||
public static boolean isFPZero(final String text) {
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
final char c = text.charAt(i);
|
||||
if (Character.isDigit(c) && c != '0') return false;
|
||||
|
||||
+1
@@ -184,6 +184,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkMissingAttributes(annotation));
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkTargetAnnotationDuplicates(annotation));
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkDuplicateAnnotations(annotation));
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkForeignInnerClassesUsed(annotation));
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationArrayInitializer(PsiArrayInitializerMemberValue initializer) {
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: 2/10/12
|
||||
*/
|
||||
public class ConvertDoubleToFloatFix implements IntentionAction {
|
||||
private final PsiExpression myExpression;
|
||||
|
||||
public ConvertDoubleToFloatFix(PsiExpression expression) {
|
||||
myExpression = expression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Convert '" + myExpression.getText() + "' to float";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
if (myExpression.isValid()) {
|
||||
if (!StringUtil.endsWithIgnoreCase(myExpression.getText(), "d")) {
|
||||
final PsiLiteralExpression expression = (PsiLiteralExpression)createFloatingPointExpression(project);
|
||||
final Object value = expression.getValue();
|
||||
return value instanceof Float && !((Float)value).isInfinite() && !(((Float)value).floatValue() == 0 && !HighlightUtil.isFPZero(expression.getText()));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
myExpression.replace(createFloatingPointExpression(project));
|
||||
}
|
||||
|
||||
private PsiExpression createFloatingPointExpression(Project project) {
|
||||
return JavaPsiFacade.getElementFactory(project).createExpressionFromText(myExpression.getText() + "f", myExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void registerIntentions(@NotNull JavaResolveResult[] candidates,
|
||||
@NotNull PsiExpressionList list,
|
||||
@NotNull HighlightInfo highlightInfo,
|
||||
TextRange fixRange) {
|
||||
if (candidates.length == 0) return;
|
||||
PsiExpression[] expressions = list.getExpressions();
|
||||
for (JavaResolveResult candidate : candidates) {
|
||||
registerIntention(expressions, highlightInfo, fixRange, candidate, list);
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerIntention(@NotNull PsiExpression[] expressions,
|
||||
@NotNull HighlightInfo highlightInfo,
|
||||
TextRange fixRange,
|
||||
@NotNull JavaResolveResult candidate,
|
||||
@NotNull PsiElement context) {
|
||||
if (!candidate.isStaticsScopeCorrect()) return;
|
||||
PsiMethod method = (PsiMethod)candidate.getElement();
|
||||
if (method != null && context.getManager().isInProject(method)) {
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (parameters.length == expressions.length) {
|
||||
for (int i = 0, length = parameters.length; i < length; i++) {
|
||||
PsiParameter parameter = parameters[i];
|
||||
final PsiExpression expression = expressions[i];
|
||||
if (expression instanceof PsiLiteralExpression && PsiType.FLOAT.equals(parameter.getType()) && PsiType.DOUBLE.equals(expression.getType())) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, new ConvertDoubleToFloatFix(expression), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,7 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
|
||||
}
|
||||
|
||||
//do not show lookup when typing varargs ellipsis
|
||||
final PsiElement prevSibling = lastElement.getPrevSibling();
|
||||
final PsiElement prevSibling = PsiTreeUtil.prevVisibleLeaf(lastElement);
|
||||
if (prevSibling == null || ".".equals(prevSibling.getText())) return false;
|
||||
PsiElement parent = prevSibling;
|
||||
do {
|
||||
|
||||
@@ -33,6 +33,8 @@ class PackageLookupItem extends LookupItem<PsiPackage> {
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context) {
|
||||
super.handleInsert(context);
|
||||
AutoPopupController.getInstance(context.getProject()).scheduleAutoPopup(context.getEditor(), null);
|
||||
if (getTailType() == TailType.DOT || context.getCompletionChar() == '.') {
|
||||
AutoPopupController.getInstance(context.getProject()).scheduleAutoPopup(context.getEditor(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,6 +334,9 @@ public class VisibilityInspection extends GlobalJavaInspectionTool {
|
||||
|
||||
if (accessModifier == PsiModifier.PRIVATE) {
|
||||
if (SUGGEST_PRIVATE_FOR_INNERS) {
|
||||
if (isInExtendsList(to, fromTopLevel.getElement().getExtendsList())) return false;
|
||||
if (isInExtendsList(to, fromTopLevel.getElement().getImplementsList())) return false;
|
||||
if (isInAnnotations(to, fromTopLevel)) return false;
|
||||
return fromTopLevel == toOwner || fromOwner == toTopLevel || toOwner != null && refUtil.getOwnerClass(toOwner) == from;
|
||||
}
|
||||
|
||||
@@ -354,6 +357,24 @@ public class VisibilityInspection extends GlobalJavaInspectionTool {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isInAnnotations(final RefJavaElement to, final RefClass fromTopLevel) {
|
||||
final PsiModifierList modifierList = fromTopLevel.getElement().getModifierList();
|
||||
if (modifierList == null) return false;
|
||||
final PsiElement toElement = to.getElement();
|
||||
|
||||
final boolean [] resolved = new boolean[] {false};
|
||||
modifierList.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
if (resolved[0]) return;
|
||||
super.visitReferenceExpression(expression);
|
||||
if (expression.resolve() == toElement) {
|
||||
resolved[0] = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
return resolved[0];
|
||||
}
|
||||
|
||||
private static boolean isInExtendsList(final RefJavaElement to, final PsiReferenceList extendsList) {
|
||||
if (extendsList != null) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.ide.fileTemplates;
|
||||
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
|
||||
@@ -108,6 +109,26 @@ public class JavaCreateFromTemplateHandler implements CreateFromTemplateHandler
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNameRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage() {
|
||||
return IdeBundle.message("title.cannot.create.class");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties prepareProperties(Properties props) {
|
||||
String packageName = props.getProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME);
|
||||
if(packageName == null || packageName.length() == 0){
|
||||
props = new Properties(props);
|
||||
props.setProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME, FileTemplate.ATTRIBUTE_PACKAGE_NAME);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
public static boolean canCreate(PsiDirectory dir) {
|
||||
return JavaDirectoryService.getInstance().getPackage(dir) != null;
|
||||
}
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
@SuppressWarnings(<error descr="'ThisClass.FOO' has private access in 'ThisClass'">ThisClass.FOO</error>)
|
||||
public class ThisClass {
|
||||
private static final String FOO = "foo";
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '1e1' to float" "true"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(1e1f);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '2.' to float" "true"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(2.f);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '.3' to float" "true"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(.3f);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '0.0' to float" "true"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(0.0f);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '3.14' to float" "true"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(3.14f);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '1e1' to float" "true"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(1e<caret>1);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '2.' to float" "true"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(2<caret>.);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '.3' to float" "true"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(.<caret>3);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '0.0' to float" "true"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(0<caret>.0);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '3.14' to float" "true"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(3<caret>.14);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '1e-9d' to float" "false"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(1e-9<caret>d);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Convert '1e137' to float" "false"
|
||||
class Test {
|
||||
void bar() {
|
||||
foo(1e1<caret>37);
|
||||
}
|
||||
void foo(float f){}
|
||||
}
|
||||
+7
@@ -4,3 +4,10 @@ End of files
|
||||
Compiling files:
|
||||
src/packageA/Base.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/OverrideAnnotatedAnonymousNotRecompile/packageA/Derived$1.class
|
||||
out/production/OverrideAnnotatedAnonymousNotRecompile/packageA/Derived.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/packageA/Derived.java
|
||||
End of files
|
||||
|
||||
+2
@@ -5,8 +5,10 @@ Compiling files:
|
||||
src/Base.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/DeleteMethodImplementation4/BaseImpl.class
|
||||
out/production/DeleteMethodImplementation4/BaseImplImpl.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/BaseImpl.java
|
||||
src/BaseImplImpl.java
|
||||
End of files
|
||||
|
||||
+6
@@ -4,3 +4,9 @@ End of files
|
||||
Compiling files:
|
||||
src/Base.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/DeleteMethodImplementation5/BaseImpl.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/BaseImpl.java
|
||||
End of files
|
||||
|
||||
+6
@@ -4,3 +4,9 @@ End of files
|
||||
Compiling files:
|
||||
src/BaseImpl.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/DeleteMethodImplementation6/BaseImplImpl.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/BaseImplImpl.java
|
||||
End of files
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
class SelectLeafFirst {
|
||||
void aaa(){}
|
||||
<caret>
|
||||
void bbb(){}
|
||||
void clear(){}
|
||||
void zzz(){}
|
||||
class ClearClass {
|
||||
void kkk(){}
|
||||
void www(){}
|
||||
void clear(){}
|
||||
void yyy(){}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
-SelectLeafFirst.java
|
||||
-SelectLeafFirst
|
||||
[clear():void]
|
||||
-ClearClass
|
||||
clear():void
|
||||
@@ -0,0 +1,13 @@
|
||||
class SelectLeafFirst2 {
|
||||
void aaa(){}
|
||||
void bbb(){}
|
||||
void clear(){}
|
||||
void zzz(){}
|
||||
class ClearClass {
|
||||
void kkk(){}
|
||||
<caret>
|
||||
void www(){}
|
||||
void clear(){}
|
||||
void yyy(){}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
-SelectLeafFirst2.java
|
||||
-SelectLeafFirst2
|
||||
clear():void
|
||||
-ClearClass
|
||||
[clear():void]
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>ThisClass.java</file>
|
||||
<line>5</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Declaration access can be weaker</problem_class>
|
||||
<hints>
|
||||
<hint value="packageLocal" />
|
||||
</hints>
|
||||
<description>Can be package local</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>ThisClass.java</file>
|
||||
<line>4</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Declaration access can be weaker</problem_class>
|
||||
<hints>
|
||||
<hint value="packageLocal" />
|
||||
</hints>
|
||||
<description>Can be package local</description>
|
||||
</problem>
|
||||
</problems>
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.util.ArrayList;
|
||||
@SuppressWarnings(ThisClass.PUBLICFINALNAME)
|
||||
public class ThisClass extends ArrayList<ThisClass.FF> {
|
||||
public static final String PUBLICFINALNAME = "stuff";
|
||||
public static class FF {}
|
||||
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
}
|
||||
+4
@@ -176,6 +176,10 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
public void testHighlightInaccessibleFromClassModifierList() throws Exception {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
public void testDynamicallyAddIgnoredAnnotations() throws Exception {
|
||||
ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.DEAD_CODE_TOOL);
|
||||
EntryPoint extension = new EntryPoint() {
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.codeInsight.daemon.quickFix;
|
||||
|
||||
/**
|
||||
* @author cdr
|
||||
*/
|
||||
public class ConvertDoubleToFloatFixTest extends LightQuickFix15TestCase {
|
||||
|
||||
public void test() throws Exception { doAllTests(); }
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/convertDoubleToFloat";
|
||||
}
|
||||
}
|
||||
@@ -102,4 +102,11 @@ public class VisibilityInspectionTest extends InspectionTestCase {
|
||||
myTool.SUGGEST_PRIVATE_FOR_INNERS = false;
|
||||
doTest("visibility/typeArguments", myTool, false, true);
|
||||
}
|
||||
|
||||
public void testUsedFromAnnotationsExtendsList() throws Exception {
|
||||
myTool.SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS = true;
|
||||
myTool.SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES = true;
|
||||
myTool.SUGGEST_PRIVATE_FOR_INNERS = true;
|
||||
doTest("visibility/usedFromAnnotationsExtendsList", myTool, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -29,5 +29,7 @@ public class JavaFileStructureFilteringTest extends JavaFileStructureTestCase {
|
||||
public void testAnonymousType()throws Exception{checkTree("point");}
|
||||
public void testCamel()throws Exception{checkTree("sohe");}
|
||||
public void testCamel2()throws Exception{checkTree("soHe");}
|
||||
public void testSelectLeafFirst()throws Exception{checkTree("clear");}
|
||||
public void testSelectLeafFirst2()throws Exception{checkTree("clear");}
|
||||
|
||||
}
|
||||
|
||||
@@ -79,17 +79,34 @@ public class RequestFuture<T> implements Future {
|
||||
return myDone.get();
|
||||
}
|
||||
|
||||
public Object get() throws InterruptedException, ExecutionException {
|
||||
while (!isDone()) {
|
||||
mySemaphore.tryAcquire(100L, TimeUnit.MILLISECONDS);
|
||||
public void waitFor() {
|
||||
try {
|
||||
while (!isDone()) {
|
||||
mySemaphore.tryAcquire(100L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean waitFor(long timeout, TimeUnit unit) {
|
||||
try {
|
||||
if (!isDone()) {
|
||||
mySemaphore.tryAcquire(timeout, unit);
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
return isDone();
|
||||
}
|
||||
|
||||
public Object get() throws InterruptedException, ExecutionException {
|
||||
waitFor();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
if (!isDone()) {
|
||||
mySemaphore.tryAcquire(timeout, unit);
|
||||
}
|
||||
waitFor(timeout, unit);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.*;
|
||||
* Date: 9/17/11
|
||||
*/
|
||||
public class CompileContext extends UserDataHolderBase implements MessageHandler{
|
||||
private static final String CANCELED_MESSAGE = "The build has been canceled";
|
||||
private final CompileScope myScope;
|
||||
private final boolean myIsMake;
|
||||
private final boolean myIsProjectRebuild;
|
||||
@@ -155,28 +156,39 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler
|
||||
return myCompilingTests;
|
||||
}
|
||||
|
||||
public CanceledStatus getCancelStatus() {
|
||||
public final CanceledStatus getCancelStatus() {
|
||||
return myCancelStatus;
|
||||
}
|
||||
|
||||
public final boolean isCanceled() {
|
||||
return getCancelStatus().isCanceled();
|
||||
}
|
||||
|
||||
public final void checkCanceled() throws ProjectBuildException {
|
||||
if (isCanceled()) {
|
||||
throw new ProjectBuildException(CANCELED_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
void setCompilingTests(boolean compilingTests) {
|
||||
myCompilingTests = compilingTests;
|
||||
}
|
||||
|
||||
void beforeCompileRound(@NotNull ModuleChunk chunk) {
|
||||
myFsState.beforeNextRoundStart();
|
||||
}
|
||||
|
||||
public void afterCompileRound() {
|
||||
myFsState.clearContextRoundData();
|
||||
}
|
||||
|
||||
public void onChunkBuildStart(ModuleChunk chunk) {
|
||||
myFsState.setContextChunk(chunk);
|
||||
}
|
||||
|
||||
void beforeNextCompileRound(@NotNull ModuleChunk chunk) {
|
||||
myFsState.beforeNextRoundStart();
|
||||
}
|
||||
|
||||
public void clearContextRoundData() {
|
||||
myFsState.clearContextRoundData();
|
||||
}
|
||||
|
||||
void onChunkBuildComplete(@NotNull ModuleChunk chunk) throws IOException {
|
||||
myDataManager.flush(true);
|
||||
myFsState.clearContextChunk();
|
||||
|
||||
if (!myErrorsFound && !myCancelStatus.isCanceled()) {
|
||||
final boolean compilingTests = isCompilingTests();
|
||||
|
||||
@@ -52,6 +52,10 @@ public class FSState {
|
||||
myContextModules.addAll(chunk.getModules());
|
||||
}
|
||||
|
||||
public void clearContextChunk() {
|
||||
myContextModules.clear();
|
||||
}
|
||||
|
||||
public void beforeNextRoundStart() {
|
||||
myLastRoundDelta = myCurrentRoundDelta;
|
||||
myCurrentRoundDelta = new FilesDelta();
|
||||
@@ -60,7 +64,6 @@ public class FSState {
|
||||
public void clearContextRoundData() {
|
||||
myCurrentRoundDelta = null;
|
||||
myLastRoundDelta = null;
|
||||
myContextModules.clear();
|
||||
}
|
||||
|
||||
public void clearRecompile(RootDescriptor rd) {
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -34,7 +34,6 @@ public class IncProjectBuilder {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.IncProjectBuilder");
|
||||
|
||||
public static final String COMPILE_SERVER_NAME = "COMPILE SERVER";
|
||||
private static final String CANCELED_MESSAGE = "The build has been canceled";
|
||||
|
||||
private final ProjectDescriptor myProjectDescriptor;
|
||||
private final BuilderRegistry myBuilderRegistry;
|
||||
@@ -119,11 +118,7 @@ public class IncProjectBuilder {
|
||||
if (descriptor != null) {
|
||||
try {
|
||||
final RequestFuture future = descriptor.client.sendShutdownRequest();
|
||||
future.get();
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
catch (ExecutionException ignored) {
|
||||
future.waitFor(500L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
finally {
|
||||
// ensure process is not running
|
||||
@@ -229,9 +224,7 @@ public class IncProjectBuilder {
|
||||
// check that output and source roots are not overlapping
|
||||
final List<File> filesToDelete = new ArrayList<File>();
|
||||
for (File outputRoot : rootsToDelete) {
|
||||
if (myCancelStatus.isCanceled()) {
|
||||
throw new ProjectBuildException(CANCELED_MESSAGE);
|
||||
}
|
||||
context.checkCanceled();
|
||||
boolean okToDelete = true;
|
||||
if (PathUtil.isUnder(allSourceRoots, outputRoot)) {
|
||||
okToDelete = false;
|
||||
@@ -389,7 +382,7 @@ public class IncProjectBuilder {
|
||||
boolean nextPassRequired;
|
||||
do {
|
||||
nextPassRequired = false;
|
||||
context.beforeNextCompileRound(chunk);
|
||||
context.beforeCompileRound(chunk);
|
||||
|
||||
if (!context.isProjectRebuild()) {
|
||||
syncOutputFiles(context, chunk);
|
||||
@@ -401,9 +394,7 @@ public class IncProjectBuilder {
|
||||
if (buildResult == ModuleLevelBuilder.ExitCode.ABORT) {
|
||||
throw new ProjectBuildException("Builder " + builder.getDescription() + " requested build stop");
|
||||
}
|
||||
if (myCancelStatus.isCanceled()) {
|
||||
throw new ProjectBuildException(CANCELED_MESSAGE);
|
||||
}
|
||||
context.checkCanceled();
|
||||
if (buildResult == ModuleLevelBuilder.ExitCode.ADDITIONAL_PASS_REQUIRED) {
|
||||
if (!nextPassRequired) {
|
||||
// recalculate basis
|
||||
@@ -440,16 +431,14 @@ public class IncProjectBuilder {
|
||||
}
|
||||
while (nextPassRequired);
|
||||
|
||||
context.clearContextRoundData();
|
||||
context.afterCompileRound();
|
||||
}
|
||||
}
|
||||
|
||||
private void runProjectLevelBuilders(CompileContext context) throws ProjectBuildException {
|
||||
for (ProjectLevelBuilder builder : myBuilderRegistry.getProjectLevelBuilders()) {
|
||||
builder.build(context);
|
||||
if (myCancelStatus.isCanceled()) {
|
||||
throw new ProjectBuildException(CANCELED_MESSAGE);
|
||||
}
|
||||
context.checkCanceled();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ import java.net.ServerSocket;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -257,14 +257,19 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
if (hasSourcesToCompile) {
|
||||
final Set<File> sourcePath = TEMPORARY_SOURCE_ROOTS_KEY.get(context, Collections.<File>emptySet());
|
||||
|
||||
final String chunkName = chunk.getName();
|
||||
final String chunkName = getChunkPresentableName(chunk);
|
||||
context.processMessage(new ProgressMessage("Compiling java [" + chunkName + "]"));
|
||||
|
||||
final boolean compiledOk = compileJava(chunk, files, classpath, platformCp, sourcePath, outs, context, diagnosticSink, outputSink);
|
||||
|
||||
final Map<File, String> chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk, context.isCompilingTests());
|
||||
|
||||
context.checkCanceled();
|
||||
|
||||
final ClassLoader compiledClassesLoader = createInstrumentationClassLoader(classpath, platformCp, chunkSourcePath, outputSink);
|
||||
|
||||
context.checkCanceled();
|
||||
|
||||
if (!forms.isEmpty()) {
|
||||
try {
|
||||
context.processMessage(new ProgressMessage("Instrumenting forms [" + chunkName + "]"));
|
||||
@@ -275,6 +280,8 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
context.checkCanceled();
|
||||
|
||||
if (addNotNullAssertions) {
|
||||
try {
|
||||
context.processMessage(new ProgressMessage("Adding NotNull assertions [" + chunkName + "]"));
|
||||
@@ -285,6 +292,8 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
context.checkCanceled();
|
||||
|
||||
if (!compiledOk && diagnosticSink.getErrorCount() == 0) {
|
||||
diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "Compilation failed: internal java compiler error"));
|
||||
}
|
||||
@@ -316,6 +325,24 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
private static String getChunkPresentableName(ModuleChunk chunk) {
|
||||
final Set<Module> modules = chunk.getModules();
|
||||
if (modules.isEmpty()) {
|
||||
return "<empty>";
|
||||
}
|
||||
if (modules.size() == 1) {
|
||||
return modules.iterator().next().getName();
|
||||
}
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
for (Module module : modules) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(",");
|
||||
}
|
||||
buf.append(module.getName());
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private boolean compileJava(ModuleChunk chunk, Collection<File> files,
|
||||
Collection<File> classpath,
|
||||
Collection<File> platformCp,
|
||||
@@ -338,14 +365,10 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
final RequestFuture<JavacServerResponseHandler> future = client.sendCompileRequest(
|
||||
options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer
|
||||
);
|
||||
try {
|
||||
future.get();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
e.printStackTrace(System.err);
|
||||
while (!future.waitFor(100L, TimeUnit.MILLISECONDS)) {
|
||||
if (context.isCanceled()) {
|
||||
future.cancel(true);
|
||||
}
|
||||
}
|
||||
rc = future.getResponseHandler().isTerminatedSuccessfully();
|
||||
}
|
||||
|
||||
@@ -66,6 +66,18 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
|
||||
return super.isSameFile(a, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
|
||||
checkCanceled();
|
||||
return super.getFileForInput(location, packageName, relativeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException {
|
||||
checkCanceled();
|
||||
return super.getJavaFileForInput(location, className, kind);
|
||||
}
|
||||
|
||||
public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
|
||||
if (kind != JavaFileObject.Kind.SOURCE && kind != JavaFileObject.Kind.CLASS) {
|
||||
throw new IllegalArgumentException("Invalid kind " + kind);
|
||||
@@ -86,6 +98,8 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
|
||||
}
|
||||
|
||||
private OutputFileObject getFileForOutput(Location location, JavaFileObject.Kind kind, String fileName, @Nullable String className, FileObject sibling) throws IOException {
|
||||
checkCanceled();
|
||||
|
||||
JavaFileObject src = null;
|
||||
if (sibling instanceof JavaFileObject) {
|
||||
final JavaFileObject javaFileObject = (JavaFileObject)sibling;
|
||||
@@ -190,4 +204,18 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
|
||||
return name.toString().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
private int myChecksCounter = 0;
|
||||
|
||||
private void checkCanceled() {
|
||||
final int counter = (myChecksCounter + 1) % 10;
|
||||
myChecksCounter = counter;
|
||||
if (counter == 0 && myContext.isCanceled()) {
|
||||
throw new RuntimeException("Compilation canceled") {
|
||||
@Override
|
||||
public Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.jetbrains.jps.javac;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.api.CanceledStatus;
|
||||
import org.jetbrains.jps.server.ClasspathBootstrap;
|
||||
|
||||
@@ -29,13 +28,14 @@ public class JavacMain {
|
||||
Collection<File> sourcePath,
|
||||
Map<File, Set<File>> outputDirToRoots,
|
||||
final DiagnosticOutputConsumer outConsumer,
|
||||
final OutputFileConsumer outputSink, @Nullable CanceledStatus canceledStatus) {
|
||||
final OutputFileConsumer outputSink,
|
||||
CanceledStatus canceledStatus) {
|
||||
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
|
||||
for (File outputDir : outputDirToRoots.keySet()) {
|
||||
outputDir.mkdirs();
|
||||
}
|
||||
final JavacFileManager fileManager = new JavacFileManager(new ContextImpl(compiler, outConsumer, outputSink));
|
||||
final JavacFileManager fileManager = new JavacFileManager(new ContextImpl(compiler, outConsumer, outputSink, canceledStatus));
|
||||
|
||||
fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff
|
||||
fileManager.handleOption("-extdirs", Collections.singleton("").iterator()); // this will clear cached stuff
|
||||
@@ -111,10 +111,15 @@ public class JavacMain {
|
||||
private final StandardJavaFileManager myStdManager;
|
||||
private final DiagnosticOutputConsumer myOutConsumer;
|
||||
private final OutputFileConsumer myOutputFileSink;
|
||||
private final CanceledStatus myCanceledStatus;
|
||||
|
||||
public ContextImpl(@NotNull JavaCompiler compiler, @NotNull DiagnosticOutputConsumer outConsumer, @NotNull OutputFileConsumer sink) {
|
||||
public ContextImpl(@NotNull JavaCompiler compiler,
|
||||
@NotNull DiagnosticOutputConsumer outConsumer,
|
||||
@NotNull OutputFileConsumer sink,
|
||||
CanceledStatus canceledStatus) {
|
||||
myOutConsumer = outConsumer;
|
||||
myOutputFileSink = sink;
|
||||
myCanceledStatus = canceledStatus;
|
||||
StandardJavaFileManager stdManager = null;
|
||||
final Class<StandardJavaFileManager> optimizedManagerClass = ClasspathBootstrap.getOptimizedFileManagerClass();
|
||||
if (optimizedManagerClass != null) {
|
||||
@@ -136,7 +141,7 @@ public class JavacMain {
|
||||
}
|
||||
|
||||
public boolean isCanceled() {
|
||||
return false; // todo
|
||||
return myCanceledStatus.isCanceled();
|
||||
}
|
||||
|
||||
public StandardJavaFileManager getStandardFileManager() {
|
||||
|
||||
@@ -11,9 +11,9 @@ import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.api.CanceledStatus;
|
||||
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.*;
|
||||
import java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
@@ -32,10 +32,11 @@ public class JavacServer {
|
||||
private final ChannelGroup myAllOpenChannels = new DefaultChannelGroup("javac-server");
|
||||
private final ChannelFactory myChannelFactory;
|
||||
private final ChannelPipelineFactory myPipelineFactory;
|
||||
private ExecutorService myThreadPool;
|
||||
|
||||
public JavacServer() {
|
||||
final ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||
myChannelFactory = new NioServerSocketChannelFactory(threadPool, threadPool, 1);
|
||||
myThreadPool = Executors.newCachedThreadPool();
|
||||
myChannelFactory = new NioServerSocketChannelFactory(myThreadPool, myThreadPool, 1);
|
||||
final ChannelRegistrar channelRegistrar = new ChannelRegistrar();
|
||||
final ChannelHandler compilationRequestsHandler = new CompilationRequestsHandler();
|
||||
myPipelineFactory = new ChannelPipelineFactory() {
|
||||
@@ -103,7 +104,15 @@ public class JavacServer {
|
||||
}
|
||||
|
||||
|
||||
public static JavacRemoteProto.Message compile(final ChannelHandlerContext ctx, final UUID sessionId, List<String> options, Collection<File> files, Collection<File> classpath, Collection<File> platformCp, Collection<File> sourcePath, Map<File, Set<File>> outs) {
|
||||
public static JavacRemoteProto.Message compile(final ChannelHandlerContext ctx,
|
||||
final UUID sessionId,
|
||||
List<String> options,
|
||||
Collection<File> files,
|
||||
Collection<File> classpath,
|
||||
Collection<File> platformCp,
|
||||
Collection<File> sourcePath,
|
||||
Map<File, Set<File>> outs,
|
||||
final CanceledStatus canceledStatus) {
|
||||
final DiagnosticOutputConsumer diagnostic = new DiagnosticOutputConsumer() {
|
||||
public void outputLineAvailable(String line) {
|
||||
Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createStdOutputResponse(line)));
|
||||
@@ -122,7 +131,7 @@ public class JavacServer {
|
||||
};
|
||||
|
||||
try {
|
||||
final boolean rc = JavacMain.compile(options, files, classpath, platformCp, sourcePath, outs, diagnostic, outputSink, null/*todo*/);
|
||||
final boolean rc = JavacMain.compile(options, files, classpath, platformCp, sourcePath, outs, diagnostic, outputSink, canceledStatus);
|
||||
return JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createBuildCompletedResponse(rc));
|
||||
}
|
||||
catch (Throwable e) {
|
||||
@@ -131,8 +140,14 @@ public class JavacServer {
|
||||
}
|
||||
}
|
||||
|
||||
public static void cancelBuild() {
|
||||
// todo
|
||||
private final Set<CancelHandler> myCancelHandlers = Collections.synchronizedSet(new HashSet<CancelHandler>());
|
||||
|
||||
public void cancelBuilds() {
|
||||
synchronized (myCancelHandlers) {
|
||||
for (CancelHandler handler : myCancelHandlers) {
|
||||
handler.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<File> toFiles(List<String> paths) {
|
||||
@@ -145,7 +160,7 @@ public class JavacServer {
|
||||
|
||||
private class CompilationRequestsHandler extends SimpleChannelHandler {
|
||||
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
public void messageReceived(final ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
final JavacRemoteProto.Message msg = (JavacRemoteProto.Message)e.getMessage();
|
||||
final UUID sessionId = JavacProtoUtil.fromProtoUUID(msg.getSessionId());
|
||||
final JavacRemoteProto.Message.Type messageType = msg.getMessageType();
|
||||
@@ -172,14 +187,26 @@ public class JavacServer {
|
||||
outs.put(new File(outputGroup.getOutputRoot()), srcRoots);
|
||||
}
|
||||
|
||||
reply = compile(ctx, sessionId, options, files, cp, platformCp, srcPath, outs);
|
||||
final CancelHandler cancelHandler = new CancelHandler();
|
||||
myCancelHandlers.add(cancelHandler);
|
||||
myThreadPool.submit(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
final JavacRemoteProto.Message exitMsg = compile(ctx, sessionId, options, files, cp, platformCp, srcPath, outs, cancelHandler);
|
||||
Channels.write(ctx.getChannel(), exitMsg);
|
||||
}
|
||||
finally {
|
||||
myCancelHandlers.remove(cancelHandler);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (requestType == JavacRemoteProto.Message.Request.Type.CANCEL){
|
||||
cancelBuild();
|
||||
cancelBuilds();
|
||||
reply = JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createRequestAckResponse());
|
||||
}
|
||||
else if (requestType == JavacRemoteProto.Message.Request.Type.SHUTDOWN){
|
||||
cancelBuild();
|
||||
cancelBuilds();
|
||||
new Thread("StopThread") {
|
||||
public void run() {
|
||||
JavacServer.this.stop();
|
||||
@@ -213,4 +240,19 @@ public class JavacServer {
|
||||
super.channelOpen(ctx, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CancelHandler implements CanceledStatus {
|
||||
private volatile boolean myIsCanceled = false;
|
||||
|
||||
private CancelHandler() {
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
myIsCanceled = true;
|
||||
}
|
||||
|
||||
public boolean isCanceled() {
|
||||
return myIsCanceled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ public class GenericTest extends IncrementalTestCase {
|
||||
public void testChangeToCovariantMethodInBase3() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
*/
|
||||
public void testChangeVarargSignature() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
@@ -80,7 +80,6 @@ public class GenericTest extends IncrementalTestCase {
|
||||
public void testChangeVarargSignature1() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
*/
|
||||
|
||||
public void testCovariance() throws Exception {
|
||||
doTest();
|
||||
@@ -114,7 +113,7 @@ public class GenericTest extends IncrementalTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
/* Not working yet
|
||||
/* Not working yet */
|
||||
public void testOverrideAnnotatedAnonymousNotRecompile() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
@@ -122,7 +121,6 @@ public class GenericTest extends IncrementalTestCase {
|
||||
public void testOverrideAnnotatedInner() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
*/
|
||||
|
||||
public void testParamTypes() throws Exception {
|
||||
doTest();
|
||||
|
||||
@@ -177,7 +177,7 @@ public abstract class IncrementalTestCase extends TestCase {
|
||||
finally {
|
||||
try {
|
||||
closeAppender();
|
||||
delete(new File(workDir));
|
||||
//delete(new File(workDir));
|
||||
}
|
||||
finally {
|
||||
Logger.setFactory(oldFactory);
|
||||
|
||||
@@ -116,11 +116,9 @@ public class MemberChangeTest extends IncrementalTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
/* Not working yet
|
||||
public void testDeleteMethodImplementation4() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
*/
|
||||
|
||||
public void testDeleteMethodImplementation5() throws Exception {
|
||||
doTest();
|
||||
|
||||
@@ -1103,47 +1103,55 @@ public class Mappings {
|
||||
}
|
||||
|
||||
if ((m.access & Opcodes.ACC_ABSTRACT) == 0) {
|
||||
final Collection<Pair<MethodRepr, ClassRepr>> overriding = u.findOverridingMethods(m, it, false);
|
||||
|
||||
for (final Pair<MethodRepr, ClassRepr> p : overriding) {
|
||||
final DependencyContext.S fName = myClassToSourceFile.get(p.second.name);
|
||||
affectedFiles.add(new File(myContext.getValue(fName)));
|
||||
}
|
||||
|
||||
for (DependencyContext.S p : propagated) {
|
||||
final ClassRepr s = u.reprByName(p);
|
||||
if (!p.equals(it.name)) {
|
||||
final ClassRepr s = u.reprByName(p);
|
||||
|
||||
if (s != null) {
|
||||
final Collection<Pair<MethodRepr, ClassRepr>> overridenInS = u.findOverridenMethods(m, s);
|
||||
if (s != null) {
|
||||
final Collection<Pair<MethodRepr, ClassRepr>> overridenInS = u.findOverridenMethods(m, s);
|
||||
|
||||
overridenInS.addAll(overridenMethods);
|
||||
overridenInS.addAll(overridenMethods);
|
||||
|
||||
boolean allAbstract = true;
|
||||
boolean visited = false;
|
||||
boolean allAbstract = true;
|
||||
boolean visited = false;
|
||||
|
||||
for (Pair<MethodRepr, ClassRepr> pp : overridenInS) {
|
||||
final ClassRepr cc = pp.second;
|
||||
for (Pair<MethodRepr, ClassRepr> pp : overridenInS) {
|
||||
final ClassRepr cc = pp.second;
|
||||
|
||||
if (cc == myMockClass) {
|
||||
visited = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cc.name.equals(it.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cc == myMockClass) {
|
||||
visited = true;
|
||||
continue;
|
||||
allAbstract = ((pp.first.access & Opcodes.ACC_ABSTRACT) > 0) || ((cc.access & Opcodes.ACC_INTERFACE) > 0);
|
||||
|
||||
if (!allAbstract) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cc.name.equals(it.name)) {
|
||||
continue;
|
||||
}
|
||||
if (allAbstract && visited) {
|
||||
final DependencyContext.S source = myClassToSourceFile.get(p);
|
||||
|
||||
visited = true;
|
||||
allAbstract = ((pp.first.access & Opcodes.ACC_ABSTRACT) > 0) || ((cc.access & Opcodes.ACC_INTERFACE) > 0);
|
||||
|
||||
if (!allAbstract) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allAbstract && visited) {
|
||||
final DependencyContext.S source = myClassToSourceFile.get(p);
|
||||
|
||||
if (source != null) {
|
||||
final String f = myContext.getValue(source);
|
||||
debug(
|
||||
"Removed method is not abstract & is overrides some abstract method which is not then over-overriden in subclass ",
|
||||
p);
|
||||
debug("Affecting subclass source file ", f);
|
||||
affectedFiles.add(new File(f));
|
||||
if (source != null) {
|
||||
final String f = myContext.getValue(source);
|
||||
debug("Removed method is not abstract & overrides some abstract method which is not then over-overriden in subclass ",
|
||||
p);
|
||||
debug("Affecting subclass source file ", f);
|
||||
affectedFiles.add(new File(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1597,19 +1605,19 @@ public class Mappings {
|
||||
for (DependencyContext.S f : delta.getChangedFiles()) {
|
||||
mySourceFileToClasses.remove(f);
|
||||
final Collection<ClassRepr> classes = delta.mySourceFileToClasses.get(f);
|
||||
if (classes != null){
|
||||
if (classes != null) {
|
||||
mySourceFileToClasses.put(f, classes);
|
||||
}
|
||||
|
||||
mySourceFileToUsages.remove(f);
|
||||
final Collection<UsageRepr.Cluster> clusters = delta.mySourceFileToUsages.get(f);
|
||||
if (clusters != null){
|
||||
if (clusters != null) {
|
||||
mySourceFileToUsages.put(f, clusters);
|
||||
}
|
||||
|
||||
mySourceFileToAnnotationUsages.remove(f);
|
||||
final Collection<UsageRepr.Usage> usages = delta.mySourceFileToAnnotationUsages.get(f);
|
||||
if (usages != null){
|
||||
if (usages != null) {
|
||||
mySourceFileToAnnotationUsages.put(f, usages);
|
||||
}
|
||||
}
|
||||
@@ -1637,7 +1645,7 @@ public class Mappings {
|
||||
|
||||
depClasses.retainAll(changedClasses);
|
||||
|
||||
if (! classChanged && depClasses.isEmpty()) {
|
||||
if (!classChanged && depClasses.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,17 +93,20 @@ public abstract class CachedValuesManager {
|
||||
}
|
||||
|
||||
public static class MemoizationKey<T> extends Key<T> {
|
||||
private final String myName;
|
||||
|
||||
public MemoizationKey(@NotNull @NonNls String name) {
|
||||
super(name);
|
||||
myName = name;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
return myName.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof MemoizationKey && toString().equals(obj.toString());
|
||||
return obj instanceof MemoizationKey && myName.equals(((MemoizationKey)obj).myName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
|
||||
protected synchronized Object createComponent(Class componentInterface) {
|
||||
final Object component = getPicoContainer().getComponentInstance(componentInterface.getName());
|
||||
assert component != null : "Can't instantiate component for: " + componentInterface;
|
||||
LOG.assertTrue(component != null, "Can't instantiate component for: " + componentInterface);
|
||||
return component;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -78,7 +78,8 @@ public abstract class TemplateInsertHandler implements InsertHandler {
|
||||
String lookupString = editor.getDocument().getCharsSequence().subSequence(startOffset, endOffset).toString();
|
||||
lookupItem.setLookupString(lookupString);
|
||||
|
||||
final OffsetMap offsetMap = context.getOffsetMap();
|
||||
final OffsetMap offsetMap = new OffsetMap(document);
|
||||
offsetMap.addOffset(CompletionInitializationContext.START_OFFSET, startOffset);
|
||||
offsetMap.addOffset(CompletionInitializationContext.SELECTION_END_OFFSET, endOffset);
|
||||
offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, endOffset);
|
||||
|
||||
|
||||
@@ -79,6 +79,10 @@ class ParameterInfoComponent extends JPanel{
|
||||
myCurrentParameterIndex = -1;
|
||||
}
|
||||
|
||||
public Object getHighlighted() {
|
||||
return myHighlighted;
|
||||
}
|
||||
|
||||
class MyParameterContext implements ParameterInfoUIContextEx {
|
||||
private int i;
|
||||
public void setupUIComponentPresentation(String text,
|
||||
|
||||
@@ -113,20 +113,33 @@ public class ParameterInfoController {
|
||||
int selectedParameterIndex = myComponent.getCurrentParameterIndex();
|
||||
List<Object> params = new ArrayList<Object>(objects.length);
|
||||
|
||||
final Object highlighted = myComponent.getHighlighted();
|
||||
for(Object o:objects) {
|
||||
final Object[] availableParams = myHandler.getParametersForDocumentation(o, context);
|
||||
if (highlighted != null && !o.equals(highlighted)) continue;
|
||||
collectParams(context, selectedParameterIndex, params, o);
|
||||
}
|
||||
|
||||
if (availableParams != null &&
|
||||
selectedParameterIndex < availableParams.length &&
|
||||
selectedParameterIndex >= 0
|
||||
) {
|
||||
params.add(availableParams[selectedParameterIndex]);
|
||||
//choose anything when highlighted is not applicable
|
||||
if (highlighted != null && params.isEmpty()) {
|
||||
for (Object o : objects) {
|
||||
collectParams(context, selectedParameterIndex, params, o);
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayUtil.toObjectArray(params);
|
||||
}
|
||||
|
||||
private void collectParams(ParameterInfoContext context, int selectedParameterIndex, List<Object> params, Object o) {
|
||||
final Object[] availableParams = myHandler.getParametersForDocumentation(o, context);
|
||||
|
||||
if (availableParams != null &&
|
||||
selectedParameterIndex < availableParams.length &&
|
||||
selectedParameterIndex >= 0
|
||||
) {
|
||||
params.add(availableParams[selectedParameterIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
private static ArrayList<ParameterInfoController> getAllControllers(Editor editor) {
|
||||
ArrayList<ParameterInfoController> array = editor.getUserData(ALL_CONTROLLERS_KEY);
|
||||
if (array == null){
|
||||
|
||||
@@ -64,7 +64,7 @@ public abstract class InspectionTool extends InspectionProfileEntry {
|
||||
}
|
||||
|
||||
public RefManager getRefManager() {
|
||||
return myContext.getRefManager();
|
||||
return getContext().getRefManager();
|
||||
}
|
||||
|
||||
public abstract void runInspection(@NotNull AnalysisScope scope, @NotNull InspectionManager manager);
|
||||
|
||||
@@ -339,6 +339,11 @@ public class InspectionToolRegistrar {
|
||||
getTool().runInspection(scope, manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(@NotNull GlobalInspectionContextImpl context) {
|
||||
getTool().initialize(context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JobDescriptor[] getJobDescriptors(GlobalInspectionContext globalInspectionContext) {
|
||||
|
||||
@@ -35,4 +35,8 @@ public interface CreateFromTemplateHandler {
|
||||
Properties props) throws IncorrectOperationException;
|
||||
|
||||
boolean canCreate(final PsiDirectory[] dirs);
|
||||
boolean isNameRequired();
|
||||
String getErrorMessage();
|
||||
|
||||
Properties prepareProperties(Properties props);
|
||||
}
|
||||
|
||||
+16
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.ide.fileTemplates;
|
||||
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
@@ -67,4 +68,19 @@ public class DefaultCreateFromTemplateHandler implements CreateFromTemplateHandl
|
||||
public boolean canCreate(final PsiDirectory[] dirs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNameRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage() {
|
||||
return IdeBundle.message("title.cannot.create.file");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties prepareProperties(Properties props) {
|
||||
return props;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public class FileTemplateUtil{
|
||||
}
|
||||
|
||||
public static String[] calculateAttributes(String templateContent, Properties properties, boolean includeDummies) throws ParseException {
|
||||
final Set<String> unsetAttributes = new HashSet<String>();
|
||||
final Set<String> unsetAttributes = new LinkedHashSet<String>();
|
||||
final Set<String> definedAttributes = new HashSet<String>();
|
||||
//noinspection HardCodedStringLiteral
|
||||
SimpleNode template = RuntimeSingleton.parse(new StringReader(templateContent), "MyTemplate");
|
||||
@@ -258,7 +258,7 @@ public class FileTemplateUtil{
|
||||
}
|
||||
|
||||
public static PsiElement createFromTemplate(@NotNull final FileTemplate template,
|
||||
@NonNls @Nullable final String fileName,
|
||||
@NonNls @Nullable String fileName,
|
||||
@Nullable Properties props,
|
||||
@NotNull final PsiDirectory directory,
|
||||
@Nullable ClassLoader classLoader) throws Exception {
|
||||
@@ -269,9 +269,16 @@ public class FileTemplateUtil{
|
||||
FileTemplateManager.getInstance().addRecentName(template.getName());
|
||||
fillDefaultProperties(props, directory);
|
||||
|
||||
final CreateFromTemplateHandler handler = findHandler(template);
|
||||
if (fileName != null && props.getProperty(FileTemplate.ATTRIBUTE_NAME) == null) {
|
||||
props.setProperty(FileTemplate.ATTRIBUTE_NAME, fileName);
|
||||
}
|
||||
else if (fileName == null && handler.isNameRequired()) {
|
||||
fileName = props.getProperty(FileTemplate.ATTRIBUTE_NAME);
|
||||
if (fileName == null) {
|
||||
throw new Exception("File name must be specified");
|
||||
}
|
||||
}
|
||||
|
||||
//Set escaped references to dummy values to remove leading "\" (if not already explicitely set)
|
||||
String[] dummyRefs = calculateAttributes(template.getText(), props, true);
|
||||
@@ -279,15 +286,10 @@ public class FileTemplateUtil{
|
||||
props.setProperty(dummyRef, "");
|
||||
}
|
||||
|
||||
if (template.isTemplateOfType(StdFileTypes.JAVA)){
|
||||
String packageName = props.getProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME);
|
||||
if(packageName == null || packageName.length() == 0){
|
||||
props = new Properties(props);
|
||||
props.setProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME, FileTemplate.ATTRIBUTE_PACKAGE_NAME);
|
||||
}
|
||||
}
|
||||
props = handler.prepareProperties(props);
|
||||
|
||||
final Properties props_ = props;
|
||||
final String fileName_ = fileName;
|
||||
String mergedText = ClassLoaderUtil.runWithClassLoader(classLoader != null ? classLoader : FileTemplateUtil.class.getClassLoader(),
|
||||
new ThrowableComputable<String, IOException>() {
|
||||
@Override
|
||||
@@ -304,8 +306,7 @@ public class FileTemplateUtil{
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable(){
|
||||
public void run(){
|
||||
try{
|
||||
CreateFromTemplateHandler handler = findHandler(template);
|
||||
result [0] = handler.createFromTemplate(project, directory, fileName, template, templateText, finalProps);
|
||||
result [0] = handler.createFromTemplate(project, directory, fileName_, template, templateText, finalProps);
|
||||
}
|
||||
catch (Exception ex){
|
||||
commandException[0] = ex;
|
||||
@@ -322,7 +323,7 @@ public class FileTemplateUtil{
|
||||
return result[0];
|
||||
}
|
||||
|
||||
private static CreateFromTemplateHandler findHandler(final FileTemplate template) {
|
||||
public static CreateFromTemplateHandler findHandler(final FileTemplate template) {
|
||||
for(CreateFromTemplateHandler handler: Extensions.getExtensions(CreateFromTemplateHandler.EP_NAME)) {
|
||||
if (handler.handlesTemplate(template)) {
|
||||
return handler;
|
||||
|
||||
@@ -32,6 +32,7 @@ public class AttributesDefaults {
|
||||
private final String myDefaultName;
|
||||
private final TextRange myDefaultRange;
|
||||
private final Map<String, Pair<String, TextRange>> myNamesToValueAndRangeMap = new HashMap<String, Pair<String, TextRange>>();
|
||||
private boolean myFixedName;
|
||||
|
||||
public AttributesDefaults(@NonNls @Nullable final String defaultName,
|
||||
@Nullable final TextRange defaultRange) {
|
||||
@@ -78,4 +79,13 @@ public class AttributesDefaults {
|
||||
final Pair<String, TextRange> valueAndRange = myNamesToValueAndRangeMap.get(attributeKey);
|
||||
return valueAndRange == null ? null : valueAndRange.first;
|
||||
}
|
||||
|
||||
public boolean isFixedName() {
|
||||
return myFixedName;
|
||||
}
|
||||
|
||||
public AttributesDefaults withFixedName(boolean fixedName) {
|
||||
myFixedName = fixedName;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -55,14 +55,18 @@ public abstract class CreateFromTemplateActionBase extends AnAction {
|
||||
}
|
||||
else {
|
||||
FileTemplateManager.getInstance().addRecentName(selectedTemplate.getName());
|
||||
PsiElement createdElement = new CreateFromTemplateDialog(project, dir, selectedTemplate, getAttributesDefaults()).create();
|
||||
final AttributesDefaults defaults = getAttributesDefaults(dataContext);
|
||||
final CreateFromTemplateDialog dialog = new CreateFromTemplateDialog(project, dir, selectedTemplate, defaults);
|
||||
PsiElement createdElement = dialog.create();
|
||||
if (createdElement != null) {
|
||||
elementCreated(dialog, createdElement);
|
||||
view.selectElement(createdElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected PsiDirectory getTargetDirectory(DataContext dataContext, IdeView view) {
|
||||
return DirectoryChooserUtil.getOrChooseDirectory(view);
|
||||
}
|
||||
@@ -73,7 +77,10 @@ public abstract class CreateFromTemplateActionBase extends AnAction {
|
||||
protected abstract FileTemplate getTemplate(final Project project, final PsiDirectory dir);
|
||||
|
||||
@Nullable
|
||||
public AttributesDefaults getAttributesDefaults() {
|
||||
public AttributesDefaults getAttributesDefaults(DataContext dataContext) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void elementCreated(CreateFromTemplateDialog dialog, PsiElement createdElement) {
|
||||
}
|
||||
}
|
||||
|
||||
+12
-4
@@ -22,7 +22,6 @@ import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateUtil;
|
||||
import com.intellij.ide.fileTemplates.actions.AttributesDefaults;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
@@ -65,6 +64,11 @@ public class CreateFromTemplateDialog extends DialogWrapper {
|
||||
|
||||
myDefaultProperties = defaultProperties == null ? FileTemplateManager.getInstance().getDefaultProperties() : defaultProperties;
|
||||
FileTemplateUtil.fillDefaultProperties(myDefaultProperties, directory);
|
||||
boolean mustEnterName = FileTemplateUtil.findHandler(template).isNameRequired();
|
||||
if (attributesDefaults != null && attributesDefaults.isFixedName()) {
|
||||
myDefaultProperties.setProperty(FileTemplate.ATTRIBUTE_NAME, attributesDefaults.getDefaultFileName());
|
||||
mustEnterName = false;
|
||||
}
|
||||
|
||||
String[] unsetAttributes = null;
|
||||
try {
|
||||
@@ -75,7 +79,7 @@ public class CreateFromTemplateDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
if (unsetAttributes != null) {
|
||||
myAttrPanel = new CreateFromTemplatePanel(unsetAttributes, !myTemplate.isTemplateOfType(StdFileTypes.JAVA), attributesDefaults);
|
||||
myAttrPanel = new CreateFromTemplatePanel(unsetAttributes, mustEnterName, attributesDefaults);
|
||||
myAttrComponent = myAttrPanel.getComponent();
|
||||
init();
|
||||
}
|
||||
@@ -110,7 +114,7 @@ public class CreateFromTemplateDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
private void doCreate(final String fileName) {
|
||||
private void doCreate(@Nullable final String fileName) {
|
||||
try {
|
||||
myCreatedElement = FileTemplateUtil.createFromTemplate(myTemplate, fileName, myAttrPanel.getProperties(myDefaultProperties),
|
||||
myDirectory);
|
||||
@@ -120,12 +124,16 @@ public class CreateFromTemplateDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
public Properties getEnteredProperties() {
|
||||
return myAttrPanel.getProperties(new Properties());
|
||||
}
|
||||
|
||||
private void showErrorDialog(final Exception e) {
|
||||
Messages.showMessageDialog(myProject, filterMessage(e.getMessage()), getErrorMessage(), Messages.getErrorIcon());
|
||||
}
|
||||
|
||||
private String getErrorMessage() {
|
||||
return myTemplate.isTemplateOfType(StdFileTypes.JAVA) ? IdeBundle.message("title.cannot.create.class") : IdeBundle.message("title.cannot.create.file");
|
||||
return FileTemplateUtil.findHandler(myTemplate).getErrorMessage();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+17
-20
@@ -19,8 +19,7 @@ package com.intellij.ide.fileTemplates.ui;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.actions.AttributesDefaults;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.ui.impl.DialogWrapperPeerImpl;
|
||||
import com.intellij.openapi.ui.DialogWrapperPeer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
@@ -37,8 +36,6 @@ import java.util.Properties;
|
||||
*/
|
||||
|
||||
public class CreateFromTemplatePanel{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.fileTemplates.ui.CreateFromTemplatePanel");
|
||||
|
||||
private JPanel myMainPanel;
|
||||
private JPanel myAttrPanel;
|
||||
private JTextField myFilenameField;
|
||||
@@ -47,7 +44,7 @@ public class CreateFromTemplatePanel{
|
||||
|
||||
private int myLastRow = 0;
|
||||
|
||||
private int myHorisontalMargin = -1;
|
||||
private int myHorizontalMargin = -1;
|
||||
private int myVerticalMargin = -1;
|
||||
private final boolean myMustEnterName;
|
||||
private final AttributesDefaults myAttributesDefaults;
|
||||
@@ -57,7 +54,6 @@ public class CreateFromTemplatePanel{
|
||||
myMustEnterName = mustEnterName;
|
||||
myUnsetAttributes = unsetAttributes;
|
||||
myAttributesDefaults = attributesDefaults;
|
||||
Arrays.sort(myUnsetAttributes);
|
||||
}
|
||||
|
||||
public boolean hasSomethingToAsk() {
|
||||
@@ -95,16 +91,16 @@ public class CreateFromTemplatePanel{
|
||||
return myMainPanel;
|
||||
}
|
||||
|
||||
public void ensureFitToScreen(int horisontalMargin, int verticalMargin){
|
||||
myHorisontalMargin = horisontalMargin;
|
||||
public void ensureFitToScreen(int horizontalMargin, int verticalMargin){
|
||||
myHorizontalMargin = horizontalMargin;
|
||||
myVerticalMargin = verticalMargin;
|
||||
}
|
||||
|
||||
private Dimension getMainPanelPreferredSize(Dimension superPreferredSize){
|
||||
if((myHorisontalMargin > 0) && (myVerticalMargin > 0)){
|
||||
if((myHorizontalMargin > 0) && (myVerticalMargin > 0)){
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
Dimension preferredSize = superPreferredSize;
|
||||
Dimension maxSize = new Dimension(screenSize.width - myHorisontalMargin, screenSize.height - myVerticalMargin);
|
||||
Dimension maxSize = new Dimension(screenSize.width - myHorizontalMargin, screenSize.height - myVerticalMargin);
|
||||
int width = Math.min(preferredSize.width, maxSize.width);
|
||||
int height = Math.min(preferredSize.height, maxSize.height);
|
||||
if(height < preferredSize.height){
|
||||
@@ -119,8 +115,7 @@ public class CreateFromTemplatePanel{
|
||||
}
|
||||
|
||||
private void updateShown() {
|
||||
final Insets insets = new Insets(2, 2, 2, 2);
|
||||
myAttrPanel.add(Box.createHorizontalStrut(200), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, insets, 0, 0));
|
||||
final Insets insets = new Insets(2, 4, 4, 2);
|
||||
if(myMustEnterName || Arrays.asList(myUnsetAttributes).contains(FileTemplate.ATTRIBUTE_NAME)){
|
||||
final JLabel filenameLabel = new JLabel(IdeBundle.message("label.file.name"));
|
||||
myAttrPanel.add(filenameLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, insets, 0, 0));
|
||||
@@ -134,7 +129,7 @@ public class CreateFromTemplatePanel{
|
||||
// set predefined file name value
|
||||
myFilenameField.setText(fileName);
|
||||
final TextRange selectionRange;
|
||||
// select range from default attrubutes or select file name without extension
|
||||
// select range from default attributes or select file name without extension
|
||||
if (myAttributesDefaults.getDefaultFileNameSelection() != null) {
|
||||
selectionRange = myAttributesDefaults.getDefaultFileNameSelection();
|
||||
} else {
|
||||
@@ -151,15 +146,17 @@ public class CreateFromTemplatePanel{
|
||||
}
|
||||
}
|
||||
}
|
||||
myAttrPanel.add(myFilenameField, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, insets, 0, 0));
|
||||
myAttrPanel.add(myFilenameField, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, insets, 0, 0));
|
||||
}
|
||||
|
||||
myLastRow = 2;
|
||||
for (String attribute : myUnsetAttributes) {
|
||||
if (attribute.equals(FileTemplate.ATTRIBUTE_NAME)) { // already asked above
|
||||
continue;
|
||||
}
|
||||
final JLabel label = new JLabel(attribute.replace('_', ' ') + ":");
|
||||
final JTextField field = new JTextField();
|
||||
field.setColumns(30);
|
||||
if (myAttributesDefaults != null) {
|
||||
final String defaultValue = myAttributesDefaults.getDefaultValueFor(attribute);
|
||||
final TextRange selectionRange = myAttributesDefaults.getRangeFor(attribute);
|
||||
@@ -172,9 +169,9 @@ public class CreateFromTemplatePanel{
|
||||
}
|
||||
}
|
||||
myAttributes.add(new Pair<String, JTextField>(attribute, field));
|
||||
myAttrPanel.add(label, new GridBagConstraints(0, myLastRow * 2 + 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,
|
||||
myAttrPanel.add(label, new GridBagConstraints(0, myLastRow, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE,
|
||||
insets, 0, 0));
|
||||
myAttrPanel.add(field, new GridBagConstraints(0, myLastRow * 2 + 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
|
||||
myAttrPanel.add(field, new GridBagConstraints(1, myLastRow, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
|
||||
GridBagConstraints.HORIZONTAL, insets, 0, 0));
|
||||
myLastRow++;
|
||||
}
|
||||
@@ -194,17 +191,17 @@ public class CreateFromTemplatePanel{
|
||||
}
|
||||
}
|
||||
|
||||
public Properties getProperties(Properties predefinedProperties){
|
||||
public Properties getProperties(Properties predefinedProperties) {
|
||||
Properties result = (Properties) predefinedProperties.clone();
|
||||
for (Pair<String, JTextField> pair : myAttributes) {
|
||||
result.put(pair.first, pair.second.getText());
|
||||
result.setProperty(pair.first, pair.second.getText());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void setPredefinedSelectionFor(final JTextField field, final TextRange selectionRange) {
|
||||
private static void setPredefinedSelectionFor(final JTextField field, final TextRange selectionRange) {
|
||||
field.select(selectionRange.getStartOffset(), selectionRange.getEndOffset());
|
||||
field.putClientProperty(DialogWrapperPeerImpl.HAVE_INITIAL_SELECTION, true);
|
||||
field.putClientProperty(DialogWrapperPeer.HAVE_INITIAL_SELECTION, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
myUpdateQueue = new MergingUpdateQueue("StructureView", Registry.intValue("structureView.coalesceTime"), false, myToolWindow.getComponent(), this, myToolWindow.getComponent(), true);
|
||||
myUpdateQueue.setRestartTimerOnAdd(true);
|
||||
|
||||
ActionManager.getInstance().addTimerListener(500, new TimerListener() {
|
||||
final TimerListener timerListener = new TimerListener() {
|
||||
public ModalityState getModalityState() {
|
||||
return ModalityState.stateForComponent(myToolWindow.getComponent());
|
||||
}
|
||||
@@ -95,6 +95,13 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl
|
||||
public void run() {
|
||||
checkUpdate();
|
||||
}
|
||||
};
|
||||
ActionManager.getInstance().addTimerListener(500, timerListener);
|
||||
Disposer.register(this, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
ActionManager.getInstance().removeTimerListener(timerListener);
|
||||
}
|
||||
});
|
||||
|
||||
myToolWindow.getComponent().addHierarchyListener(new HierarchyListener() {
|
||||
|
||||
@@ -818,11 +818,16 @@ public class FileStructurePopup implements Disposable {
|
||||
final Object object = ((DefaultMutableTreeNode)last).getUserObject();
|
||||
if (object instanceof FilteringTreeStructure.FilteringNode) {
|
||||
FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)object;
|
||||
FilteringTreeStructure.FilteringNode candidate = node;
|
||||
|
||||
while (node != null) {
|
||||
elements.add(getPsi(node));
|
||||
node = node.getParentNode();
|
||||
}
|
||||
final int size = ContainerUtil.intersection(parents, elements).size();
|
||||
if (size == elements.size() - 1 && size == parents.size() && candidate.children().isEmpty()) {
|
||||
return p.node;
|
||||
}
|
||||
if (size > max) {
|
||||
max = size;
|
||||
cur.clear();
|
||||
|
||||
+6
-3
@@ -28,6 +28,8 @@ import com.intellij.openapi.project.ex.ProjectEx;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Attribute;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -100,13 +102,13 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM
|
||||
public ModuleFileData(final String rootElementName, Module module) {
|
||||
super(rootElementName);
|
||||
myModule = module;
|
||||
myOptions = new TreeMap<String, String>();
|
||||
myOptions = new THashMap<String, String>(2);
|
||||
}
|
||||
|
||||
protected ModuleFileData(final ModuleFileData storageData) {
|
||||
super(storageData);
|
||||
|
||||
myOptions = new TreeMap<String, String>(storageData.myOptions);
|
||||
myOptions = new THashMap<String, String>(storageData.myOptions);
|
||||
myModule = storageData.myModule;
|
||||
}
|
||||
|
||||
@@ -130,7 +132,8 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM
|
||||
final Element root = super.save();
|
||||
|
||||
myOptions.put(VERSION_OPTION, Integer.toString(myVersion));
|
||||
Set<String> options = myOptions.keySet();
|
||||
String[] options = ArrayUtil.toStringArray(myOptions.keySet());
|
||||
Arrays.sort(options);
|
||||
for (String option : options) {
|
||||
root.setAttribute(option, myOptions.get(option));
|
||||
}
|
||||
|
||||
+3
-3
@@ -133,14 +133,14 @@ public class CodeStyleSchemeImpl implements JDOMExternalizable, CodeStyleScheme,
|
||||
public static CodeStyleSchemeImpl readScheme(Document document) throws InvalidDataException, JDOMException, IOException{
|
||||
Element root = document.getRootElement();
|
||||
if (root == null){
|
||||
throw new InvalidDataException();
|
||||
throw new InvalidDataException("No root element in code style scheme file");
|
||||
}
|
||||
|
||||
String schemeName = root.getAttributeValue(NAME);
|
||||
String parentName = root.getAttributeValue(PARENT);
|
||||
|
||||
if (schemeName == null){
|
||||
throw new InvalidDataException();
|
||||
if (schemeName == null) {
|
||||
throw new InvalidDataException("Name attribute missing in code style scheme file");
|
||||
}
|
||||
|
||||
return new CodeStyleSchemeImpl(schemeName, parentName, root);
|
||||
|
||||
+5
@@ -148,6 +148,11 @@ public abstract class InplaceVariableIntroducer<E extends PsiElement> extends In
|
||||
protected void collectAdditionalElementsToRename(List<Pair<PsiElement, TextRange>> stringUsages) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int restoreCaretOffset(int offset) {
|
||||
return myCaretRangeMarker.isValid() ? myCaretRangeMarker.getStartOffset() : offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCommandName() {
|
||||
return myTitle;
|
||||
|
||||
+6
-2
@@ -104,7 +104,7 @@ public abstract class InplaceRefactoring {
|
||||
protected StartMarkAction myMarkAction;
|
||||
protected PsiElement myScope;
|
||||
|
||||
private RangeMarker myCaretRangeMarker;
|
||||
protected RangeMarker myCaretRangeMarker;
|
||||
|
||||
public InplaceRefactoring(Editor editor, PsiNamedElement elementToRename, Project project) {
|
||||
this(editor, elementToRename, project, elementToRename != null ? elementToRename.getName() : null,
|
||||
@@ -245,6 +245,10 @@ public abstract class InplaceRefactoring {
|
||||
}
|
||||
else {
|
||||
revertState();
|
||||
final TemplateState templateState = TemplateManagerImpl.getTemplateState(InjectedLanguageUtil.getTopLevelEditor(myEditor));
|
||||
if (templateState != null) {
|
||||
templateState.gotoEnd(true);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -350,7 +354,7 @@ public abstract class InplaceRefactoring {
|
||||
}
|
||||
|
||||
protected int restoreCaretOffset(int offset) {
|
||||
return myCaretRangeMarker.isValid() ? myCaretRangeMarker.getStartOffset() : offset;
|
||||
return offset;
|
||||
}
|
||||
|
||||
protected void navigateToAlreadyStarted(Document oldDocument, int exitCode) {
|
||||
|
||||
@@ -44,6 +44,7 @@ import com.intellij.openapi.project.*;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.ex.VirtualFileManagerEx;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
@@ -280,6 +281,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
versionChanged |= registerIndexer(extension, currentVersionCorrupted);
|
||||
}
|
||||
FileUtil.delete(corruptionMarker);
|
||||
|
||||
String rebuildNotification = null;
|
||||
if (currentVersionCorrupted) {
|
||||
rebuildNotification = "Index files on disk are corrupted. Indices will be rebuilt.";
|
||||
@@ -287,10 +289,13 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
else if (versionChanged) {
|
||||
rebuildNotification = "Index file format has changed for some indices. These indices will be rebuilt.";
|
||||
}
|
||||
if (rebuildNotification != null && !ApplicationManager.getApplication().isHeadlessEnvironment()) {
|
||||
if (rebuildNotification != null
|
||||
&& !ApplicationManager.getApplication().isHeadlessEnvironment()
|
||||
&& Registry.is("ide.showIndexRebuildMessage")) {
|
||||
new NotificationGroup("Indexing", NotificationDisplayType.BALLOON, false)
|
||||
.createNotification("Index Rebuild", rebuildNotification, NotificationType.INFORMATION, null).notify(null);
|
||||
}
|
||||
|
||||
dropUnregisteredIndices();
|
||||
|
||||
// check if rebuild was requested for any index during registration
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.internal.statistic.connect;
|
||||
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -39,7 +40,7 @@ public class StatisticsHttpClientSender implements StatisticsDataSender {
|
||||
|
||||
post.setRequestBody(new NameValuePair[]{
|
||||
new NameValuePair("content", content),
|
||||
new NameValuePair("uuid", UpdateChecker.getInstallationUID()),
|
||||
new NameValuePair("uuid", UpdateChecker.getInstallationUID(PropertiesComponent.getInstance())),
|
||||
new NameValuePair("ide", ApplicationNamesInfo.getInstance().getProductName()),
|
||||
});
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ public class EventLog implements Notifications {
|
||||
content = title + (StringUtil.isNotEmpty(content) ? ": " + content : "");
|
||||
}
|
||||
|
||||
content = StringUtil.replace(StringUtil.convertLineSeparators(content), " ", " ");
|
||||
content = StringUtil.convertLineSeparators(content);
|
||||
boolean hasHtml = false;
|
||||
while (true) {
|
||||
Matcher tagMatcher = TAG_PATTERN.matcher(content);
|
||||
@@ -248,6 +248,9 @@ public class EventLog implements Notifications {
|
||||
}
|
||||
|
||||
private static void appendText(Document document, String text) {
|
||||
text = StringUtil.replace(text, " ", " ");
|
||||
text = StringUtil.replace(text, "»", ">>");
|
||||
text = StringUtil.replace(text, "«", "<<");
|
||||
document.insertString(document.getTextLength(), StringUtil.unescapeXml(text));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -154,7 +154,7 @@ public class NotificationsManagerImpl extends NotificationsManager implements No
|
||||
case BALLOON:
|
||||
default:
|
||||
Balloon balloon = notifyByBalloon(notification, type, project);
|
||||
if (!settings.isShouldLog()) {
|
||||
if (!settings.isShouldLog() || type == NotificationDisplayType.STICKY_BALLOON) {
|
||||
if (balloon == null) {
|
||||
notification.expire();
|
||||
} else {
|
||||
|
||||
+4
-2
@@ -32,6 +32,7 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ReflectionCache;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.io.fs.IFile;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -44,7 +45,7 @@ import java.util.*;
|
||||
abstract class ComponentStoreImpl implements IComponentStore {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.components.ComponentStoreImpl");
|
||||
private final Map<String, Object> myComponents = Collections.synchronizedMap(new TreeMap<String, Object>());
|
||||
private final Map<String, Object> myComponents = Collections.synchronizedMap(new THashMap<String, Object>());
|
||||
private final List<SettingsSavingComponent> mySettingsSavingComponents = Collections.synchronizedList(new ArrayList<SettingsSavingComponent>());
|
||||
@Nullable private SaveSessionImpl mySession;
|
||||
|
||||
@@ -470,7 +471,8 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
|
||||
final StateStorageManager.ExternalizationSession session = storageManager.startExternalization();
|
||||
|
||||
final String[] names = ArrayUtil.toStringArray(myComponents.keySet());
|
||||
String[] names = ArrayUtil.toStringArray(myComponents.keySet());
|
||||
Arrays.sort(names);
|
||||
|
||||
for (String name : names) {
|
||||
Object component = myComponents.get(name);
|
||||
|
||||
+2
-2
@@ -16,16 +16,16 @@
|
||||
package com.intellij.openapi.components.impl.stores;
|
||||
|
||||
import com.intellij.openapi.components.StateStorage;
|
||||
import gnu.trove.THashMap;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author mike
|
||||
*/
|
||||
public class CompoundExternalizationSession {
|
||||
private final Map<StateStorage, StateStorage.ExternalizationSession> mySessions = new HashMap<StateStorage, StateStorage.ExternalizationSession>();
|
||||
private final Map<StateStorage, StateStorage.ExternalizationSession> mySessions = new THashMap<StateStorage, StateStorage.ExternalizationSession>(1);
|
||||
|
||||
public StateStorage.ExternalizationSession getExternalizationSession(StateStorage stateStore) {
|
||||
StateStorage.ExternalizationSession session = mySessions.get(stateStore);
|
||||
|
||||
+7
-4
@@ -31,6 +31,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.io.fs.IFile;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Document;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.JDOMException;
|
||||
@@ -58,8 +59,8 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
|
||||
}
|
||||
|
||||
private final Map<String, String> myMacros = new HashMap<String, String>();
|
||||
private final Map<String, StateStorage> myStorages = new HashMap<String, StateStorage>();
|
||||
private final Map<String, StateStorage> myPathToStorage = new HashMap<String, StateStorage>();
|
||||
private final Map<String, StateStorage> myStorages = new THashMap<String, StateStorage>();
|
||||
private final Map<String, StateStorage> myPathToStorage = new THashMap<String, StateStorage>();
|
||||
private final TrackingPathMacroSubstitutor myPathMacroSubstitutor;
|
||||
private final String myRootTagName;
|
||||
private Object mySession;
|
||||
@@ -160,7 +161,7 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
|
||||
}
|
||||
|
||||
private Map<String, Long> loadVersions() {
|
||||
TreeMap<String, Long> result = new TreeMap<String, Long>();
|
||||
THashMap<String, Long> result = new THashMap<String, Long>();
|
||||
String filePath = getNotNullVersionsFilePath();
|
||||
if (filePath != null) {
|
||||
try {
|
||||
@@ -580,8 +581,10 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
|
||||
|
||||
public static Element createComponentVersionsXml(Map<String, Long> versions) {
|
||||
Element vers = new Element("versions");
|
||||
String[] componentNames = ArrayUtil.toStringArray(versions.keySet());
|
||||
Arrays.sort(componentNames);
|
||||
|
||||
for (String name : versions.keySet()) {
|
||||
for (String name : componentNames) {
|
||||
long version = versions.get(name);
|
||||
if (version != 0) {
|
||||
Element element = new Element("component");
|
||||
|
||||
+19
-26
@@ -26,8 +26,10 @@ import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.StringInterner;
|
||||
import com.intellij.util.io.fs.IFile;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Attribute;
|
||||
import org.jdom.Document;
|
||||
import org.jdom.Element;
|
||||
@@ -62,7 +64,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
protected Integer myProviderUpToDateHash;
|
||||
private boolean mySavingDisabled = false;
|
||||
|
||||
private final Map<String, Element> myStorageComponentStates = new TreeMap<String, Element>();
|
||||
private final Map<String, Object> myStorageComponentStates = new THashMap<String, Object>(); // at loading we store Element, on setState Integer of hash// at loading we store Element, on setState Integer of hash
|
||||
|
||||
private final ComponentVersionProvider myLocalVersionProvider;
|
||||
private final ComponentVersionProvider myRemoteVersionProvider;
|
||||
@@ -126,8 +128,6 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
final StorageData storageData = getStorageData(false);
|
||||
final Element state = storageData.getState(componentName);
|
||||
|
||||
|
||||
|
||||
if (state != null) {
|
||||
if (!myStorageComponentStates.containsKey(componentName)) {
|
||||
myStorageComponentStates.put(componentName, state);
|
||||
@@ -309,19 +309,20 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
if (element.getAttributes().isEmpty() && element.getChildren().isEmpty()) return;
|
||||
|
||||
myStorageData.setState(componentName, element);
|
||||
int hash = JDOMUtil.getTreeHash(element);
|
||||
|
||||
Element oldElement = myStorageComponentStates.get(componentName);
|
||||
try {
|
||||
if (oldElement != null && !JDOMUtil.areElementsEqual(oldElement, element)) {
|
||||
Object oldElementState = myStorageComponentStates.get(componentName);
|
||||
|
||||
if (oldElementState instanceof Element && !JDOMUtil.areElementsEqual((Element)oldElementState, element) ||
|
||||
oldElementState instanceof Integer && hash != (Integer)oldElementState
|
||||
) {
|
||||
myListener.componentStateChanged(componentName);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myStorageComponentStates.put(componentName, (Element)element.clone());
|
||||
myStorageComponentStates.put(componentName, hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,10 +397,6 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
|
||||
protected abstract void doSave() throws StateStorageException;
|
||||
|
||||
public void clearHash() {
|
||||
myUpToDateHash = null;
|
||||
}
|
||||
|
||||
protected Integer calcHash() {
|
||||
return null;
|
||||
}
|
||||
@@ -469,10 +466,6 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
return myUpToDateHash != null && myUpToDateHash.equals(hash);
|
||||
}
|
||||
|
||||
public boolean isHashUpToDate() {
|
||||
return isHashUpToDate(calcHash());
|
||||
}
|
||||
|
||||
protected Document getDocumentToSave() {
|
||||
if (myDocumentToSave != null) return myDocumentToSave;
|
||||
|
||||
@@ -520,8 +513,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
private Map<String, Long> loadVersions(Document copy) {
|
||||
|
||||
HashMap<String, Long> result = new HashMap<String, Long>();
|
||||
THashMap<String, Long> result = new THashMap<String, Long>();
|
||||
|
||||
List list = copy.getRootElement().getChildren(COMPONENT);
|
||||
for (Object o : list) {
|
||||
@@ -550,13 +542,13 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
private Integer myHash;
|
||||
|
||||
public StorageData(final String rootElementName) {
|
||||
myComponentStates = new TreeMap<String, Element>();
|
||||
myComponentStates = new THashMap<String, Element>();
|
||||
myRootElementName = rootElementName;
|
||||
}
|
||||
|
||||
protected StorageData(StorageData storageData) {
|
||||
myRootElementName = storageData.myRootElementName;
|
||||
myComponentStates = new TreeMap<String, Element>(storageData.myComponentStates);
|
||||
myComponentStates = new THashMap<String, Element>(storageData.myComponentStates);
|
||||
}
|
||||
|
||||
protected void load(@NotNull Element rootElement) throws IOException {
|
||||
@@ -603,8 +595,9 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
@NotNull
|
||||
protected Element save() {
|
||||
Element rootElement = new Element(myRootElementName);
|
||||
|
||||
for (String componentName : myComponentStates.keySet()) {
|
||||
String[] componentNames = ArrayUtil.toStringArray(myComponentStates.keySet());
|
||||
Arrays.sort(componentNames);
|
||||
for (String componentName : componentNames) {
|
||||
assert componentName != null;
|
||||
final Element element = myComponentStates.get(componentName);
|
||||
|
||||
@@ -617,7 +610,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Element getState(final String name) {
|
||||
private Element getState(final String name) {
|
||||
final Element e = myComponentStates.get(name);
|
||||
|
||||
if (e != null) {
|
||||
@@ -628,7 +621,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
return e;
|
||||
}
|
||||
|
||||
public void removeState(final String componentName) {
|
||||
private void removeState(final String componentName) {
|
||||
myComponentStates.remove(componentName);
|
||||
clearHash();
|
||||
}
|
||||
@@ -799,7 +792,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
private void loadProviderVersions() {
|
||||
myProviderVersions = new TreeMap<String, Long>();
|
||||
myProviderVersions = new THashMap<String, Long>();
|
||||
for (RoamingType type : RoamingType.values()) {
|
||||
Document doc = null;
|
||||
if (myStreamProvider.isEnabled()) {
|
||||
|
||||
+4
-1
@@ -16,6 +16,7 @@
|
||||
package com.intellij.openapi.updateSettings.impl;
|
||||
|
||||
import com.intellij.ide.plugins.PluginHostsConfigurable;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
@@ -46,7 +47,9 @@ public class CheckForUpdateAction extends AnAction implements DumbAware {
|
||||
ProgressManager.getInstance().run(new Task.Modal(project, "Checking for updates", false) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
final CheckForUpdateResult result = UpdateChecker.checkForUpdates(true);
|
||||
final CheckForUpdateResult result = UpdateChecker.checkForUpdates(UpdateSettings.getInstance(), PropertiesComponent.getInstance(),
|
||||
true
|
||||
);
|
||||
|
||||
final List<PluginDownloader> updatedPlugins = UpdateChecker.updatePlugins(true, hostsConfigurable);
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
|
||||
+17
-21
@@ -148,11 +148,12 @@ public final class UpdateChecker {
|
||||
public static ActionCallback updateAndShowResult() {
|
||||
final ActionCallback result = new ActionCallback();
|
||||
final Application app = ApplicationManager.getApplication();
|
||||
/*
|
||||
final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
|
||||
final UpdateSettings updateSettings = UpdateSettings.getInstance();
|
||||
app.executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final CheckForUpdateResult checkForUpdateResult = checkForUpdates();
|
||||
final CheckForUpdateResult checkForUpdateResult = checkForUpdates(updateSettings, propertiesComponent, false);
|
||||
|
||||
final List<PluginDownloader> updatedPlugins = updatePlugins(false, null);
|
||||
app.invokeLater(new Runnable() {
|
||||
@@ -164,7 +165,6 @@ public final class UpdateChecker {
|
||||
});
|
||||
}
|
||||
});
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -346,11 +346,11 @@ public final class UpdateChecker {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static CheckForUpdateResult doCheckForUpdates(final UpdateSettings settings) {
|
||||
public static CheckForUpdateResult doCheckForUpdates(final UpdateSettings settings, final PropertiesComponent instance) {
|
||||
ApplicationInfo appInfo = ApplicationInfo.getInstance();
|
||||
BuildNumber currentBuild = appInfo.getBuild();
|
||||
int majorVersion = Integer.parseInt(appInfo.getMajorVersion());
|
||||
final UpdatesXmlLoader loader = new UpdatesXmlLoader(getUpdateUrl(), getInstallationUID(), null);
|
||||
final UpdatesXmlLoader loader = new UpdatesXmlLoader(getUpdateUrl(), getInstallationUID(instance), null);
|
||||
final UpdatesInfo info;
|
||||
try {
|
||||
info = loader.loadUpdatesInfo();
|
||||
@@ -366,25 +366,21 @@ public final class UpdateChecker {
|
||||
return strategy.checkForUpdates();
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public static CheckForUpdateResult checkForUpdates() {
|
||||
return checkForUpdates(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static CheckForUpdateResult checkForUpdates(final boolean disregardIgnoredBuilds) {
|
||||
public static CheckForUpdateResult checkForUpdates(final UpdateSettings updateSettings,
|
||||
final PropertiesComponent propertiesComponent,
|
||||
final boolean disregardIgnoredBuilds) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("enter: auto checkForUpdates()");
|
||||
}
|
||||
|
||||
UserUpdateSettings settings = UpdateSettings.getInstance();
|
||||
UserUpdateSettings settings = updateSettings;
|
||||
if (disregardIgnoredBuilds) {
|
||||
settings = new UserUpdateSettings() {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getKnownChannelsIds() {
|
||||
return UpdateSettings.getInstance().getKnownChannelsIds();
|
||||
return updateSettings.getKnownChannelsIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -394,21 +390,21 @@ public final class UpdateChecker {
|
||||
|
||||
@Override
|
||||
public void setKnownChannelIds(List<String> ids) {
|
||||
UpdateSettings.getInstance().setKnownChannelIds(ids);
|
||||
updateSettings.setKnownChannelIds(ids);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ChannelStatus getSelectedChannelStatus() {
|
||||
return UpdateSettings.getInstance().getSelectedChannelStatus();
|
||||
return updateSettings.getSelectedChannelStatus();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
final CheckForUpdateResult result = doCheckForUpdates(UpdateSettings.getInstance());
|
||||
final CheckForUpdateResult result = doCheckForUpdates(updateSettings, propertiesComponent);
|
||||
|
||||
if (result.getState() == UpdateStrategy.State.LOADED) {
|
||||
UpdateSettings.getInstance().LAST_TIME_CHECKED = System.currentTimeMillis();
|
||||
updateSettings.LAST_TIME_CHECKED = System.currentTimeMillis();
|
||||
settings.setKnownChannelIds(result.getAllChannelsIds());
|
||||
}
|
||||
|
||||
@@ -444,12 +440,13 @@ public final class UpdateChecker {
|
||||
}
|
||||
final InputStream[] inputStreams = new InputStream[]{null};
|
||||
final Exception[] exception = new Exception[]{null};
|
||||
final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
|
||||
Future<?> downloadThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
HttpConfigurable.getInstance().prepareURL(url);
|
||||
|
||||
String uid = getInstallationUID();
|
||||
String uid = getInstallationUID(propertiesComponent);
|
||||
|
||||
final URL requestUrl =
|
||||
new URL(url + "?build=" + ApplicationInfo.getInstance().getBuild().asString() + "&uid=" + uid + ADDITIONAL_REQUEST_OPTIONS);
|
||||
@@ -477,8 +474,7 @@ public final class UpdateChecker {
|
||||
return inputStreams[0];
|
||||
}
|
||||
|
||||
public static String getInstallationUID() {
|
||||
final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
|
||||
public static String getInstallationUID(final PropertiesComponent propertiesComponent) {
|
||||
String uid = "";
|
||||
if (!propertiesComponent.isValueSet(INSTALLATION_UID)) {
|
||||
try {
|
||||
|
||||
@@ -200,7 +200,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
}
|
||||
|
||||
public void fileClosed(FileEditorManager source, VirtualFile file) {
|
||||
getFocusManagerImpl().doWhenFocusSettlesDown(new ExpirableRunnable.ForProject(myProject) {
|
||||
getFocusManagerImpl(myProject).doWhenFocusSettlesDown(new ExpirableRunnable.ForProject(myProject) {
|
||||
public void run() {
|
||||
if (!hasOpenEditorFiles()) {
|
||||
focusToolWinowByDefault(null);
|
||||
@@ -351,8 +351,8 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
return myFileEditorManager.getOpenFiles().length > 0;
|
||||
}
|
||||
|
||||
private static FocusManagerImpl getFocusManagerImpl() {
|
||||
return FocusManagerImpl.getInstance();
|
||||
private static IdeFocusManager getFocusManagerImpl(Project project) {
|
||||
return IdeFocusManager.getInstance(project);
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
@@ -619,7 +619,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
}).doWhenRejected(new Runnable() {
|
||||
public void run() {
|
||||
if (forced) {
|
||||
getFocusManagerImpl().requestFocus(new FocusCommand() {
|
||||
getFocusManagerImpl(myProject).requestFocus(new FocusCommand() {
|
||||
public ActionCallback run() {
|
||||
final ArrayList<FinalizableCommand> cmds = new ArrayList<FinalizableCommand>();
|
||||
|
||||
@@ -719,7 +719,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
final ArrayList<FinalizableCommand> commandList,
|
||||
boolean forced,
|
||||
boolean autoFocusContents) {
|
||||
if (!getFocusManagerImpl().isUnforcedRequestAllowed() && !forced) return;
|
||||
if (!FocusManagerImpl.getInstance().isUnforcedRequestAllowed() && !forced) return;
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("enter: activateToolWindowImpl(" + id + ")");
|
||||
@@ -2002,15 +2002,15 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
return;
|
||||
}
|
||||
final WindowInfoImpl info = getInfo(myId);
|
||||
getFocusManagerImpl().myFocusedComponentAlaram.cancelAllRequests();
|
||||
//getFocusManagerImpl(myProject)..cancelAllRequests();
|
||||
|
||||
if (!info.isActive()) {
|
||||
getFocusManagerImpl().myFocusedComponentAlaram.addRequest(new EdtRunnable() {
|
||||
getFocusManagerImpl(myProject).doWhenFocusSettlesDown(new EdtRunnable() {
|
||||
public void runEdt() {
|
||||
if (!myLayout.isToolWindowRegistered(myId)) return;
|
||||
activateToolWindow(myId, false, false);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2128,7 +2128,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
}
|
||||
|
||||
public ActionCallback requestDefaultFocus(final boolean forced) {
|
||||
return getFocusManagerImpl().requestFocus(new FocusCommand() {
|
||||
return getFocusManagerImpl(myProject).requestFocus(new FocusCommand() {
|
||||
public ActionCallback run() {
|
||||
return processDefaultFocusRequest(forced);
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ message.nothing.to.show.in.structure.view=Nothing to show in the Structure View
|
||||
error.license.collision=This license is being used elsewhere on the network by {0}.\nOnly one active computer at a time can use the license.\nWould you like to re-activate this computer?\nClick Yes to re-activate, or No to shutdown {1}.
|
||||
title.license.collision.detected=License Collision Detected
|
||||
message.licensed.to=Licensed to {0}
|
||||
title.enter.license.data=Enter License Data
|
||||
title.enter.license.data=Enter {0} License
|
||||
message.purchase.or.upgrade=For information on how to upgrade your evaluation software please go to {0}
|
||||
message.expiration.date=Expiration date: {0}
|
||||
message.educational.license=1-Year Educational License. {0}
|
||||
|
||||
@@ -99,6 +99,8 @@ editor.mouseSelectionStateResetDeadzone=4
|
||||
editor.use.new.tabs=true
|
||||
editor.smarterSelectionQuoting=true
|
||||
|
||||
ide.showIndexRebuildMessage=false
|
||||
|
||||
ide.tabbedPane.bufferedPaint=true
|
||||
ide.tabbedPane.dragOutMultiplier=1.2
|
||||
|
||||
@@ -108,6 +110,7 @@ ide.mac.message.dialogs.as.sheets=true
|
||||
ide.mac.inplaceDialogMnemonicsFix=true
|
||||
ide.mac.hide.cursor.when.typing=false
|
||||
ide.mac.show.native.help=false
|
||||
ide.mac.useNativeClipboard=false
|
||||
|
||||
debugger.valueTooltipAutoShow=true
|
||||
debugger.valueTooltipAutoShow.description=Auto show tooltip on mouse over
|
||||
@@ -171,8 +174,6 @@ projectView.hide.dot.idea=true
|
||||
show.live.templates.in.completion=false
|
||||
documentation.component.editor.font=false
|
||||
|
||||
ide.mac.useNativeClipboard=false
|
||||
|
||||
show.all.classes.on.first.completion=false
|
||||
ide.enable.toolwindow.stack=false
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ class EventLogTest extends LightPlatformTestCase {
|
||||
PlatformTestCase.initPlatformLangPrefix()
|
||||
}
|
||||
|
||||
public void testNbsp() {
|
||||
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "Hello world", NotificationType.ERROR))
|
||||
assert entry.message == 'Title: Hello world'
|
||||
public void testHtmlEntities() {
|
||||
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "Hello world«»", NotificationType.ERROR))
|
||||
assert entry.message == 'Title: Hello world<<>>'
|
||||
}
|
||||
|
||||
public void testParseMultilineText() {
|
||||
|
||||
@@ -68,6 +68,11 @@ class UsageViewTreeCellRenderer extends ColoredTreeCellRenderer {
|
||||
|
||||
if (userObject instanceof UsageTarget) {
|
||||
UsageTarget usageTarget = (UsageTarget)userObject;
|
||||
if (!usageTarget.isValid()) {
|
||||
append(UsageViewBundle.message("node.invalid"), ourInvalidAttributes);
|
||||
return;
|
||||
}
|
||||
|
||||
final ItemPresentation presentation = usageTarget.getPresentation();
|
||||
LOG.assertTrue(presentation != null);
|
||||
if (showAsReadOnly) {
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -47,17 +48,7 @@ import java.util.List;
|
||||
*/
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
public class JDOMUtil {
|
||||
private static final ThreadLocal<SAXBuilder> ourSaxBuilder = new ThreadLocal<SAXBuilder>(){
|
||||
protected SAXBuilder initialValue() {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
saxBuilder.setEntityResolver(new EntityResolver() {
|
||||
public InputSource resolveEntity(String publicId, String systemId) {
|
||||
return new InputSource(new CharArrayReader(ArrayUtil.EMPTY_CHAR_ARRAY));
|
||||
}
|
||||
});
|
||||
return saxBuilder;
|
||||
}
|
||||
};
|
||||
private static final ThreadLocal<SoftReference<SAXBuilder>> ourSaxBuilder = new ThreadLocal<SoftReference<SAXBuilder>>();
|
||||
|
||||
private JDOMUtil() { }
|
||||
|
||||
@@ -317,14 +308,27 @@ public class JDOMUtil {
|
||||
|
||||
@NotNull
|
||||
public static Document loadDocument(char[] chars, int length) throws IOException, JDOMException {
|
||||
SAXBuilder builder = ourSaxBuilder.get();
|
||||
return builder.build(new CharArrayReader(chars, 0, length));
|
||||
return getSaxBuilder().build(new CharArrayReader(chars, 0, length));
|
||||
}
|
||||
|
||||
private static SAXBuilder getSaxBuilder() {
|
||||
SoftReference<SAXBuilder> reference = ourSaxBuilder.get();
|
||||
SAXBuilder saxBuilder = reference != null ? reference.get() : null;
|
||||
if (saxBuilder == null) {
|
||||
saxBuilder = new SAXBuilder();
|
||||
saxBuilder.setEntityResolver(new EntityResolver() {
|
||||
public InputSource resolveEntity(String publicId, String systemId) {
|
||||
return new InputSource(new CharArrayReader(ArrayUtil.EMPTY_CHAR_ARRAY));
|
||||
}
|
||||
});
|
||||
ourSaxBuilder.set(new SoftReference<SAXBuilder>(saxBuilder));
|
||||
}
|
||||
return saxBuilder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Document loadDocument(CharSequence seq) throws IOException, JDOMException {
|
||||
SAXBuilder builder = ourSaxBuilder.get();
|
||||
return builder.build(new CharSequenceReader(seq));
|
||||
return getSaxBuilder().build(new CharSequenceReader(seq));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -351,10 +355,9 @@ public class JDOMUtil {
|
||||
|
||||
@NotNull
|
||||
public static Document loadDocument(@NotNull InputStream stream) throws JDOMException, IOException {
|
||||
SAXBuilder saxBuilder = ourSaxBuilder.get();
|
||||
InputStreamReader reader = new InputStreamReader(stream, ENCODING);
|
||||
try {
|
||||
return saxBuilder.build(reader);
|
||||
return getSaxBuilder().build(reader);
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
|
||||
@@ -151,5 +151,43 @@ public class StringHash {
|
||||
return h;
|
||||
}
|
||||
|
||||
public static int murmur(String data, int seed) {
|
||||
final int length = data.length();
|
||||
// 'm' and 'r' are mixing constants generated offline.
|
||||
// They're not really 'magic', they just happen to work well.
|
||||
final int m = 0x5bd1e995;
|
||||
final int r = 24;
|
||||
// Initialize the hash to a random value
|
||||
int h = seed ^ length;
|
||||
int length4 = length >> 2;
|
||||
|
||||
for (int i = 0; i < length4; i++) {
|
||||
final int i4 = i << 2;
|
||||
int k = data.charAt(i4) + (data.charAt(i4 + 1) << 8) +
|
||||
(data.charAt(i4 + 2) << 16) + (data.charAt(i4 + 3) << 24);
|
||||
k *= m;
|
||||
k ^= k >>> r;
|
||||
k *= m;
|
||||
h *= m;
|
||||
h ^= k;
|
||||
}
|
||||
|
||||
// Handle the last few bytes of the input array
|
||||
switch (length % 4) {
|
||||
case 3:
|
||||
h ^= data.charAt((length & ~3) + 2) << 16;
|
||||
case 2:
|
||||
h ^= data.charAt((length & ~3) + 1) << 8;
|
||||
case 1:
|
||||
h ^= data.charAt(length & ~3);
|
||||
h *= m;
|
||||
}
|
||||
|
||||
h ^= h >>> 13;
|
||||
h *= m;
|
||||
h ^= h >>> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.intellij.util.lang;
|
||||
|
||||
import com.intellij.openapi.util.text.StringHash;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
@@ -273,7 +274,7 @@ public class ClasspathCache {
|
||||
}
|
||||
|
||||
private boolean maybeContains(String name, Loader loader) {
|
||||
int hash = hashFromNameAndLoader(name, loader, murmur(name, SEED));
|
||||
int hash = hashFromNameAndLoader(name, loader, StringHash.murmur(name, SEED));
|
||||
int hash2 = hashFromNameAndLoader(name, loader, hash);
|
||||
|
||||
for (int i = 0; i < myHashFunctionCount; ++i) {
|
||||
@@ -283,7 +284,7 @@ public class ClasspathCache {
|
||||
}
|
||||
|
||||
public void add(String name, Loader loader) {
|
||||
int hash1 = hashFromNameAndLoader(name, loader, murmur(name, SEED));
|
||||
int hash1 = hashFromNameAndLoader(name, loader, StringHash.murmur(name, SEED));
|
||||
int hash2 = hashFromNameAndLoader(name, loader, hash1);
|
||||
|
||||
for (int i = 0; i < myHashFunctionCount; ++i) {
|
||||
@@ -292,7 +293,7 @@ public class ClasspathCache {
|
||||
}
|
||||
|
||||
private int hashFromNameAndLoader(String name, Loader loader, int n) {
|
||||
int hash = murmur(name, n);
|
||||
int hash = StringHash.murmur(name, n);
|
||||
int i = loader.getIndex();
|
||||
while (i > 0) {
|
||||
hash = hash * n + ((i % 10) + '0');
|
||||
@@ -300,45 +301,6 @@ public class ClasspathCache {
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
private static int murmur(String data, int seed) {
|
||||
final int length = data.length();
|
||||
// 'm' and 'r' are mixing constants generated offline.
|
||||
// They're not really 'magic', they just happen to work well.
|
||||
final int m = 0x5bd1e995;
|
||||
final int r = 24;
|
||||
// Initialize the hash to a random value
|
||||
int h = seed ^ length;
|
||||
int length4 = length >> 2;
|
||||
|
||||
for (int i = 0; i < length4; i++) {
|
||||
final int i4 = i << 2;
|
||||
int k = data.charAt(i4) + (data.charAt(i4 + 1) << 8) +
|
||||
(data.charAt(i4 + 2) << 16) + (data.charAt(i4 + 3) << 24);
|
||||
k *= m;
|
||||
k ^= k >>> r;
|
||||
k *= m;
|
||||
h *= m;
|
||||
h ^= k;
|
||||
}
|
||||
|
||||
// Handle the last few bytes of the input array
|
||||
switch (length % 4) {
|
||||
case 3:
|
||||
h ^= data.charAt((length & ~3) + 2) << 16;
|
||||
case 2:
|
||||
h ^= data.charAt((length & ~3) + 1) << 8;
|
||||
case 1:
|
||||
h ^= data.charAt(length & ~3);
|
||||
h *= m;
|
||||
}
|
||||
|
||||
h ^= h >>> 13;
|
||||
h *= m;
|
||||
h ^= h >>> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
static class DebugInfo {
|
||||
|
||||
+1
-1
@@ -564,7 +564,7 @@ public class PathsVerifier<BinaryType extends FilePatch> {
|
||||
public Collection<FilePatch> doDelayed() {
|
||||
final List<FilePatch> result = new LinkedList<FilePatch>();
|
||||
if (! myOverrideExisting.isEmpty()) {
|
||||
final String title = "Overwrite existing files";
|
||||
final String title = "Overwrite Existing Files";
|
||||
final Collection<FilePath> selected = AbstractVcsHelper.getInstance(myProject).selectFilePathsToProcess(
|
||||
new ArrayList<FilePath>(myOverrideExisting.keySet()), title,
|
||||
"\nThe following files should be created by patch, but they already exist.\nDo you want to overwrite them?\n", title,
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ProjectComponent;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.DumbAwareRunnable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -32,6 +33,7 @@ import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -40,6 +42,8 @@ import java.util.Collection;
|
||||
* @author max
|
||||
*/
|
||||
public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements ProjectComponent {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.VcsDirtyScopeManagerImpl");
|
||||
|
||||
private final Project myProject;
|
||||
private final ChangeListManager myChangeListManager;
|
||||
private final ProjectLevelVcsManager myVcsManager;
|
||||
@@ -100,6 +104,10 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
public void markEverythingDirty() {
|
||||
if ((! myProject.isOpen()) || myProject.isDisposed() || myVcsManager.getAllActiveVcss().length == 0) return;
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("everything dirty: " + Reflection.getCallerClass(1));
|
||||
}
|
||||
|
||||
final LifeDrop lifeDrop = myLife.doIfAlive(new Runnable() {
|
||||
public void run() {
|
||||
myDirtBuilder.everythingDirty();
|
||||
@@ -160,6 +168,10 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
|| dirsConverted != null && ! dirsConverted.isEmpty();
|
||||
if (! haveStuff) return;
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("paths dirty: " + filesConverted + "; " + dirsConverted + "; " + Reflection.getCallerClass(2));
|
||||
}
|
||||
|
||||
takeDirt(new Consumer<DirtBuilder>() {
|
||||
public void consume(final DirtBuilder dirt) {
|
||||
if (filesConverted != null) {
|
||||
@@ -218,6 +230,10 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
final boolean haveStuff = filesConverted != null && ! filesConverted.isEmpty() || dirsConverted != null && ! dirsConverted.isEmpty();
|
||||
if (! haveStuff) return;
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("files dirty: " + filesConverted + "; " + dirsConverted + "; " + Reflection.getCallerClass(2));
|
||||
}
|
||||
|
||||
takeDirt(new Consumer<DirtBuilder>() {
|
||||
public void consume(final DirtBuilder dirt) {
|
||||
if (filesConverted != null) {
|
||||
@@ -240,6 +256,9 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
try {
|
||||
final AbstractVcs vcs = myGuess.getVcsForDirty(file);
|
||||
if (vcs == null) return;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("file dirty: " + file + "; " + Reflection.getCallerClass(2));
|
||||
}
|
||||
final VcsRoot root = new VcsRoot(vcs, file);
|
||||
takeDirt(new Consumer<DirtBuilder>() {
|
||||
public void consume(DirtBuilder dirtBuilder) {
|
||||
@@ -254,6 +273,9 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
try {
|
||||
final AbstractVcs vcs = myGuess.getVcsForDirty(file);
|
||||
if (vcs == null) return;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("file dirty: " + file + "; " + Reflection.getCallerClass(1));
|
||||
}
|
||||
final FilePathUnderVcs root = new FilePathUnderVcs(file, vcs);
|
||||
takeDirt(new Consumer<DirtBuilder>() {
|
||||
public void consume(DirtBuilder dirtBuilder) {
|
||||
@@ -272,6 +294,9 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
try {
|
||||
final AbstractVcs vcs = myGuess.getVcsForDirty(dir);
|
||||
if (vcs == null) return;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("dir dirty recursively: " + dir + "; " + Reflection.getCallerClass(2));
|
||||
}
|
||||
final VcsRoot root = new VcsRoot(vcs, dir);
|
||||
takeDirt(new Consumer<DirtBuilder>() {
|
||||
public void consume(DirtBuilder dirtBuilder) {
|
||||
@@ -286,6 +311,9 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
try {
|
||||
final AbstractVcs vcs = myGuess.getVcsForDirty(path);
|
||||
if (vcs == null) return;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("dir dirty recursively: " + path + "; " + Reflection.getCallerClass(2));
|
||||
}
|
||||
final FilePathUnderVcs root = new FilePathUnderVcs(path, vcs);
|
||||
takeDirt(new Consumer<DirtBuilder>() {
|
||||
public void consume(DirtBuilder dirtBuilder) {
|
||||
|
||||
@@ -15,8 +15,12 @@
|
||||
*/
|
||||
package com.intellij.android.designer;
|
||||
|
||||
import com.intellij.android.designer.designSurface.AndroidDesignerEditorPanel;
|
||||
import com.intellij.designer.componentTree.TreeComponentDecorator;
|
||||
import com.intellij.designer.designSurface.DesignerEditorPanel;
|
||||
import com.intellij.openapi.fileEditor.FileEditorState;
|
||||
import com.intellij.openapi.fileEditor.FileEditorStateLevel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.designer.DesignerEditor;
|
||||
@@ -30,6 +34,11 @@ public final class AndroidDesignerEditor extends DesignerEditor {
|
||||
super(project, file);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DesignerEditorPanel createDesignerPanel(Module module, VirtualFile file) {
|
||||
return new AndroidDesignerEditorPanel(module, file);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.android.designer.componentTree;
|
||||
|
||||
import com.intellij.android.designer.model.RadViewComponent;
|
||||
import com.intellij.designer.componentTree.TreeComponentDecorator;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public final class AndroidTreeDecorator extends TreeComponentDecorator {
|
||||
@Override
|
||||
public void decorate(RadComponent component, ColoredTreeCellRenderer renderer) {
|
||||
RadViewComponent view = (RadViewComponent)component;
|
||||
renderer.append(view.getTitle());
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.android.designer.designSurface;
|
||||
|
||||
import com.intellij.android.designer.componentTree.AndroidTreeDecorator;
|
||||
import com.intellij.android.designer.model.RadViewComponent;
|
||||
import com.intellij.designer.componentTree.TreeComponentDecorator;
|
||||
import com.intellij.designer.designSurface.DesignerEditorPanel;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
|
||||
private final TreeComponentDecorator myTreeDecorator = new AndroidTreeDecorator();
|
||||
|
||||
public AndroidDesignerEditorPanel(@NotNull Module module, @NotNull VirtualFile file) {
|
||||
super(module, file);
|
||||
|
||||
// (temp code) TODO: use platform DOM
|
||||
|
||||
try {
|
||||
InputStream stream = file.getInputStream();
|
||||
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
|
||||
parser.parse(stream, new DefaultHandler() {
|
||||
RadViewComponent myComponent;
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
myComponent = new RadViewComponent(myComponent, qName);
|
||||
if (myRootComponent == null) {
|
||||
myRootComponent = myComponent;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
if (myComponent != null) {
|
||||
myComponent = (RadViewComponent)myComponent.getParent();
|
||||
}
|
||||
}
|
||||
});
|
||||
stream.close();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
e.printStackTrace(); // TODO
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeComponentDecorator getTreeDecorator() {
|
||||
return myTreeDecorator;
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.android.designer.model;
|
||||
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TODO: now dummy implementation for tests
|
||||
*
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public class RadViewComponent extends RadComponent {
|
||||
private final String myTitle;
|
||||
private final List<RadComponent> myChildren = new ArrayList<RadComponent>();
|
||||
|
||||
public RadViewComponent(RadViewComponent parent, String title) {
|
||||
myTitle = title;
|
||||
setParent(parent);
|
||||
if (parent != null) {
|
||||
parent.getChildren().add(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RadComponent> getChildren() {
|
||||
return myChildren;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return myTitle;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ package git4idea;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -91,11 +92,16 @@ public class GitBranch extends GitReference {
|
||||
*/
|
||||
@NotNull
|
||||
public String getShortName() {
|
||||
String name = getName();
|
||||
if (myRemote) {
|
||||
return name.substring(name.indexOf('/') + 1);
|
||||
}
|
||||
return name;
|
||||
return splitNameOfRemoteBranch(getName()).getSecond();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remote and the "local" name of a remote branch.
|
||||
* Expects branch in format "origin/master", i.e. remote/branch
|
||||
*/
|
||||
public static Pair<String, String> splitNameOfRemoteBranch(String branchName) {
|
||||
int firstSlash = branchName.indexOf('/');
|
||||
return Pair.create(branchName.substring(0, firstSlash), branchName.substring(firstSlash + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -37,6 +38,12 @@ public class NotificationManager {
|
||||
|
||||
public void notify(@NotNull NotificationGroup notificationGroup, @NotNull String title, @NotNull String message,
|
||||
@NotNull NotificationType type, @Nullable NotificationListener listener) {
|
||||
// title can be empty; description can't be neither null, nor empty
|
||||
if (StringUtil.isEmptyOrSpaces(message)) {
|
||||
message = title;
|
||||
title = "";
|
||||
}
|
||||
// if both title and description were empty, then it is a problem in the calling code => Notifications engine assertion will notify.
|
||||
createNotification(notificationGroup, title, message, type, listener).notify(myProject);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,18 +15,25 @@
|
||||
*/
|
||||
package git4idea.branch;
|
||||
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitExecutionException;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.NotificationManager;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
import git4idea.commands.GitCompoundResult;
|
||||
import git4idea.history.GitHistoryUtils;
|
||||
import git4idea.history.browser.GitCommit;
|
||||
import git4idea.repo.GitRepository;
|
||||
@@ -38,10 +45,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Executor of Git branching operations.
|
||||
@@ -168,13 +173,147 @@ public final class GitBranchOperationsProcessor {
|
||||
public void deleteBranch(final String branchName) {
|
||||
new CommonBackgroundTask(myProject, "Deleting " + branchName, myCallInAwtAfterExecution) {
|
||||
@Override public void execute(@NotNull ProgressIndicator indicator) {
|
||||
doDelete(branchName, indicator);
|
||||
new GitDeleteBranchOperation(myProject, myRepositories, branchName, getCurrentBranchOrRev(), indicator).execute();
|
||||
}
|
||||
}.runInBackground();
|
||||
}
|
||||
|
||||
private void doDelete(final String branchName, ProgressIndicator indicator) {
|
||||
new GitDeleteBranchOperation(myProject, myRepositories, branchName, getCurrentBranchOrRev(), indicator).execute();
|
||||
public void deleteRemoteBranch(@NotNull final String branchName) {
|
||||
final Collection<String> trackingBranches = findTrackingBranches(branchName);
|
||||
String currentBranch = getCurrentBranchOrRev();
|
||||
boolean currentBranchTracksBranchToDelete = false;
|
||||
if (trackingBranches.contains(currentBranch)) {
|
||||
currentBranchTracksBranchToDelete = true;
|
||||
trackingBranches.remove(currentBranch);
|
||||
}
|
||||
|
||||
final DeleteRemoteBranchDecision decision = confirmBranchDeletion(branchName, trackingBranches, currentBranchTracksBranchToDelete);
|
||||
|
||||
if (decision.delete()) {
|
||||
new CommonBackgroundTask(myProject, "Deleting " + branchName, myCallInAwtAfterExecution) {
|
||||
@Override public void execute(@NotNull ProgressIndicator indicator) {
|
||||
boolean deletedSuccessfully = doDeleteRemote(branchName);
|
||||
if (deletedSuccessfully) {
|
||||
final Collection<String> successfullyDeletedLocalBranches = new ArrayList<String>(1);
|
||||
if (decision.deleteTracking()) {
|
||||
for (final String branch : trackingBranches) {
|
||||
indicator.setText("Deleting " + branch);
|
||||
new GitDeleteBranchOperation(myProject, myRepositories, branch, getCurrentBranchOrRev(), indicator) {
|
||||
@Override
|
||||
protected void notifySuccess(@NotNull String message) {
|
||||
// do nothing - will display a combo notification for all deleted branches below
|
||||
successfullyDeletedLocalBranches.add(branch);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
notifySuccessfulDeletion(branchName, successfullyDeletedLocalBranches);
|
||||
}
|
||||
}
|
||||
}.runInBackground();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<String> findTrackingBranches(@NotNull String remoteBranch) {
|
||||
return new GitMultiRootBranchConfig(myRepositories).getTrackingBranches(remoteBranch);
|
||||
}
|
||||
|
||||
private boolean doDeleteRemote(String branchName) {
|
||||
GitCompoundResult result = new GitCompoundResult(myProject);
|
||||
for (GitRepository repository : myRepositories) {
|
||||
Pair<String, String> pair = GitBranch.splitNameOfRemoteBranch(branchName);
|
||||
GitCommandResult res = Git.push(repository, pair.getFirst(), ":" + pair.getSecond());
|
||||
result.append(repository, res);
|
||||
repository.update(GitRepository.TrackedTopic.BRANCHES);
|
||||
}
|
||||
if (!result.totalSuccess()) {
|
||||
NotificationManager.getInstance(myProject).notifyError("Failed to delete remote branch " + branchName,
|
||||
result.getErrorOutputWithReposIndication());
|
||||
}
|
||||
return result.totalSuccess();
|
||||
}
|
||||
|
||||
private void notifySuccessfulDeletion(@NotNull String remoteBranchName, @NotNull Collection<String> localBranches) {
|
||||
String message = "";
|
||||
if (!localBranches.isEmpty()) {
|
||||
message = "Also deleted local " + StringUtil.pluralize("branch", localBranches.size()) + ": " + StringUtil.join(localBranches, ", ");
|
||||
}
|
||||
NotificationManager.getInstance(myProject).notify(GitVcs.NOTIFICATION_GROUP_ID, "Deleted remote branch " + remoteBranchName,
|
||||
message, NotificationType.INFORMATION);
|
||||
}
|
||||
|
||||
private DeleteRemoteBranchDecision confirmBranchDeletion(@NotNull String branchName, @NotNull Collection<String> trackingBranches,
|
||||
boolean currentBranchTracksBranchToDelete) {
|
||||
String title = "Delete Remote Branch";
|
||||
String message = "Delete remote branch " + branchName;
|
||||
|
||||
boolean delete;
|
||||
final boolean deleteTracking;
|
||||
if (trackingBranches.isEmpty()) {
|
||||
delete = Messages.showYesNoDialog(myProject, message, title, "Delete", "Cancel", Messages.getQuestionIcon()) == Messages.OK;
|
||||
deleteTracking = false;
|
||||
}
|
||||
else {
|
||||
if (currentBranchTracksBranchToDelete) {
|
||||
message += "\n\nCurrent branch " + getCurrentBranchOrRev() + " tracks " + branchName + " but won't be deleted.";
|
||||
}
|
||||
final String checkboxMessage;
|
||||
if (trackingBranches.size() == 1) {
|
||||
checkboxMessage = "Delete tracking local branch " + trackingBranches.iterator().next() + " as well";
|
||||
}
|
||||
else {
|
||||
checkboxMessage = "Delete tracking local branches " + StringUtil.join(trackingBranches, ", ");
|
||||
}
|
||||
|
||||
final AtomicBoolean deleteChoice = new AtomicBoolean();
|
||||
delete = Messages.OK == Messages.showYesNoDialog(message, title, "Delete", "Cancel", Messages.getQuestionIcon(), new DialogWrapper.DoNotAskOption() {
|
||||
@Override
|
||||
public boolean isToBeShown() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setToBeShown(boolean value, int exitCode) {
|
||||
deleteChoice.set(!value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSaveOptionsOnCancel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDoNotShowMessage() {
|
||||
return checkboxMessage;
|
||||
}
|
||||
});
|
||||
deleteTracking = deleteChoice.get();
|
||||
}
|
||||
return new DeleteRemoteBranchDecision(delete, deleteTracking);
|
||||
}
|
||||
|
||||
private static class DeleteRemoteBranchDecision {
|
||||
private final boolean delete;
|
||||
private final boolean deleteTracking;
|
||||
|
||||
private DeleteRemoteBranchDecision(boolean delete, boolean deleteTracking) {
|
||||
this.delete = delete;
|
||||
this.deleteTracking = deleteTracking;
|
||||
}
|
||||
|
||||
public boolean delete() {
|
||||
return delete;
|
||||
}
|
||||
|
||||
public boolean deleteTracking() {
|
||||
return deleteTracking;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -256,19 +256,27 @@ public class Git {
|
||||
return run(h);
|
||||
}
|
||||
|
||||
public static GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec, @NotNull GitLineHandlerListener... listeners) {
|
||||
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(repository.getProject(), repository.getRoot(), GitCommand.PUSH);
|
||||
@NotNull
|
||||
public static GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @NotNull String spec,
|
||||
@NotNull GitLineHandlerListener... listeners) {
|
||||
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(repository.getProject(), repository.getRoot(),
|
||||
GitCommand.PUSH);
|
||||
h.setSilent(false);
|
||||
|
||||
for (GitLineHandlerListener listener : listeners) {
|
||||
h.addLineListener(listener);
|
||||
}
|
||||
h.addParameters(remote);
|
||||
h.addParameters(spec);
|
||||
return run(h, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec,
|
||||
@NotNull GitLineHandlerListener... listeners) {
|
||||
GitRemote remote = pushSpec.getRemote();
|
||||
h.addParameters(remote.getName());
|
||||
GitBranch remoteBranch = pushSpec.getDest();
|
||||
String destination = remoteBranch.getName().replaceFirst(remote.getName() + "/", "");
|
||||
h.addParameters(pushSpec.getSource().getName() + ":" + destination);
|
||||
return run(h, true);
|
||||
return push(repository, remote.getName(), pushSpec.getSource().getName() + ":" + destination);
|
||||
}
|
||||
|
||||
private static GitCommandResult run(@NotNull GitLineHandler handler) {
|
||||
|
||||
@@ -251,9 +251,6 @@ class GitBranchPopupActions {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to delete a branch.
|
||||
*/
|
||||
private static class DeleteAction extends DumbAwareAction {
|
||||
private final Project myProject;
|
||||
private final List<GitRepository> myRepositories;
|
||||
@@ -302,6 +299,7 @@ class GitBranchPopupActions {
|
||||
new CheckoutRemoteBranchAction(myProject, myRepositories, myBranchName, mySelectedRepository),
|
||||
new CompareAction(myProject, myRepositories, myBranchName, mySelectedRepository),
|
||||
new MergeAction(myProject, myRepositories, myBranchName, mySelectedRepository),
|
||||
new RemoteDeleteAction(myProject, myRepositories, myBranchName, mySelectedRepository)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -336,6 +334,28 @@ class GitBranchPopupActions {
|
||||
return myRemoteBranchName.substring(slashPosition+1);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RemoteDeleteAction extends DumbAwareAction {
|
||||
private final Project myProject;
|
||||
private final List<GitRepository> myRepositories;
|
||||
private final String myBranchName;
|
||||
private final GitRepository mySelectedRepository;
|
||||
|
||||
RemoteDeleteAction(@NotNull Project project, @NotNull List<GitRepository> repositories, @NotNull String branchName,
|
||||
@NotNull GitRepository selectedRepository) {
|
||||
super("Delete");
|
||||
myProject = project;
|
||||
myRepositories = repositories;
|
||||
myBranchName = branchName;
|
||||
mySelectedRepository = selectedRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
new GitBranchOperationsProcessor(myProject, myRepositories, mySelectedRepository).deleteRemoteBranch(myBranchName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class CompareAction extends DumbAwareAction {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user