mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
Conflicts: plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java
This commit is contained in:
+1
-1
@@ -584,7 +584,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
|
||||
}
|
||||
|
||||
private void initOutputRootsFile(File rootsFile) throws IOException {
|
||||
myOutputRootsStorage = new PersistentHashMap<Integer, TIntObjectHashMap<Pair<Integer, Integer>>>(rootsFile, new EnumeratorIntegerDescriptor(), new DataExternalizer<TIntObjectHashMap<Pair<Integer, Integer>>>() {
|
||||
myOutputRootsStorage = new PersistentHashMap<Integer, TIntObjectHashMap<Pair<Integer, Integer>>>(rootsFile, EnumeratorIntegerDescriptor.INSTANCE, new DataExternalizer<TIntObjectHashMap<Pair<Integer, Integer>>>() {
|
||||
public void save(DataOutput out, TIntObjectHashMap<Pair<Integer, Integer>> value) throws IOException {
|
||||
for (final TIntObjectIterator<Pair<Integer, Integer>> it = value.iterator(); it.hasNext();) {
|
||||
it.advance();
|
||||
|
||||
@@ -42,7 +42,7 @@ public class BackwardDependenciesStorage implements Flushable, Disposable {
|
||||
private static final int CLASS = 3;
|
||||
|
||||
public BackwardDependenciesStorage(File file, final int cacheSize) throws IOException {
|
||||
myMap = new PersistentHashMap<Integer, DependenciesSet>(file, new EnumeratorIntegerDescriptor(), new MyDataExternalizer());
|
||||
myMap = new PersistentHashMap<Integer, DependenciesSet>(file, EnumeratorIntegerDescriptor.INSTANCE, new MyDataExternalizer());
|
||||
|
||||
myCache = new SLRUCache<Integer, ReferencerSetHolder>(cacheSize * 2, cacheSize) {
|
||||
@NotNull
|
||||
|
||||
+2
-1
@@ -182,7 +182,8 @@ public class ApplicationConfiguration extends ModuleBasedConfiguration<JavaRunCo
|
||||
}
|
||||
|
||||
public void setEnvs(@NotNull final Map<String, String> envs) {
|
||||
this.myEnvs = envs;
|
||||
myEnvs.clear();
|
||||
myEnvs.putAll(envs);
|
||||
}
|
||||
|
||||
public boolean isPassParentEnvs() {
|
||||
|
||||
@@ -403,7 +403,7 @@ public class HighlightUtil {
|
||||
formatType(rType));
|
||||
|
||||
errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, assignment, message);
|
||||
QuickFixAction.registerQuickFixAction(errorResult, new ChangeToAppendFix(eqOpSign, lType, rType, assignment));
|
||||
QuickFixAction.registerQuickFixAction(errorResult, new ChangeToAppendFix(eqOpSign, lType, assignment));
|
||||
}
|
||||
return errorResult;
|
||||
}
|
||||
|
||||
+81
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -23,8 +23,11 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
@@ -33,13 +36,11 @@ public class ChangeToAppendFix implements IntentionAction {
|
||||
|
||||
private final IElementType myTokenType;
|
||||
private final PsiType myLhsType;
|
||||
private final PsiType myRhsType;
|
||||
private final PsiAssignmentExpression myAssignmentExpression;
|
||||
|
||||
public ChangeToAppendFix(IElementType eqOpSign, PsiType lType, PsiType rType, PsiAssignmentExpression assignmentExpression) {
|
||||
public ChangeToAppendFix(IElementType eqOpSign, PsiType lType, PsiAssignmentExpression assignmentExpression) {
|
||||
myTokenType = eqOpSign;
|
||||
myLhsType = lType;
|
||||
myRhsType = rType;
|
||||
myAssignmentExpression = assignmentExpression;
|
||||
}
|
||||
|
||||
@@ -47,8 +48,9 @@ public class ChangeToAppendFix implements IntentionAction {
|
||||
@Override
|
||||
public String getText() {
|
||||
return QuickFixBundle.message("change.to.append.text",
|
||||
myAssignmentExpression.getLExpression().getText(),
|
||||
myAssignmentExpression.getRExpression().getText());
|
||||
buildAppendExpression(myAssignmentExpression.getRExpression(),
|
||||
myLhsType.equalsToText("java.lang.Appendable"),
|
||||
new StringBuilder(myAssignmentExpression.getLExpression().getText())));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -61,9 +63,10 @@ public class ChangeToAppendFix implements IntentionAction {
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
return JavaTokenType.PLUSEQ == myTokenType &&
|
||||
myAssignmentExpression.isValid() &&
|
||||
myAssignmentExpression.getManager().isInProject(myAssignmentExpression) &&
|
||||
myRhsType.equalsToText(CommonClassNames.JAVA_LANG_STRING) &&
|
||||
(myLhsType.equalsToText(CommonClassNames.JAVA_LANG_STRING_BUILDER) || myLhsType.equalsToText(CommonClassNames.JAVA_LANG_STRING_BUFFER));
|
||||
PsiManager.getInstance(project).isInProject(myAssignmentExpression) &&
|
||||
(myLhsType.equalsToText(CommonClassNames.JAVA_LANG_STRING_BUILDER) ||
|
||||
myLhsType.equalsToText(CommonClassNames.JAVA_LANG_STRING_BUFFER) ||
|
||||
myLhsType.equalsToText("java.lang.Appendable"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,14 +77,78 @@ public class ChangeToAppendFix implements IntentionAction {
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
|
||||
final PsiExpression rExpression = myAssignmentExpression.getRExpression();
|
||||
if (rExpression == null) {
|
||||
final PsiExpression rhs = myAssignmentExpression.getRExpression();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final StringBuilder appendCallText = buildAppendExpression(rhs, myLhsType.equalsToText("java.lang.Appendable"),
|
||||
new StringBuilder(myAssignmentExpression.getLExpression().getText()));
|
||||
if (appendCallText == null) {
|
||||
return;
|
||||
}
|
||||
final String appendCallText =
|
||||
myAssignmentExpression.getLExpression().getText() + ".append(" + rExpression.getText() + ')';
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(myAssignmentExpression.getProject());
|
||||
final PsiExpression appendCall = factory.createExpressionFromText(appendCallText, myAssignmentExpression);
|
||||
final PsiExpression appendCall = factory.createExpressionFromText(appendCallText.toString(), myAssignmentExpression);
|
||||
myAssignmentExpression.replace(appendCall);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static StringBuilder buildAppendExpression(PsiExpression concatenation, boolean useStringValueOf, @NonNls StringBuilder out)
|
||||
throws IncorrectOperationException {
|
||||
final PsiType type = concatenation.getType();
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
if (concatenation instanceof PsiPolyadicExpression && type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
|
||||
PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)concatenation;
|
||||
final PsiExpression[] operands = polyadicExpression.getOperands();
|
||||
boolean isConstant = true;
|
||||
boolean isString = false;
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (PsiExpression operand : operands) {
|
||||
if (isConstant && PsiUtil.isConstantExpression(operand)) {
|
||||
if (builder.length() != 0) {
|
||||
builder.append('+');
|
||||
}
|
||||
final PsiType operandType = operand.getType();
|
||||
if (operandType != null && operandType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
|
||||
isString = true;
|
||||
}
|
||||
builder.append(operand.getText());
|
||||
}
|
||||
else {
|
||||
isConstant = false;
|
||||
if (builder.length() != 0) {
|
||||
append(builder, useStringValueOf && !isString, out);
|
||||
builder.setLength(0);
|
||||
}
|
||||
buildAppendExpression(operand, useStringValueOf, out);
|
||||
}
|
||||
}
|
||||
if (builder.length() != 0) {
|
||||
append(builder, false, out);
|
||||
}
|
||||
}
|
||||
else if (concatenation instanceof PsiParenthesizedExpression) {
|
||||
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)concatenation;
|
||||
final PsiExpression expression = parenthesizedExpression.getExpression();
|
||||
if (expression != null) {
|
||||
return buildAppendExpression(expression, useStringValueOf, out);
|
||||
}
|
||||
}
|
||||
else {
|
||||
append(concatenation.getText(), useStringValueOf && !type.equalsToText(CommonClassNames.JAVA_LANG_STRING), out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static void append(CharSequence text, boolean useStringValueOf, StringBuilder out) {
|
||||
out.append(".append(");
|
||||
if (useStringValueOf) {
|
||||
out.append("String.valueOf(").append(text).append(')');
|
||||
}
|
||||
else {
|
||||
out.append(text);
|
||||
}
|
||||
out.append(')');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ public class PsiTypeLookupItem extends LookupItem {
|
||||
PsiFile file = context.getFile();
|
||||
int newTail = JavaCompletionUtil.insertClassReference(aClass, file, context.getStartOffset(), context.getTailOffset());
|
||||
context.setTailOffset(newTail);
|
||||
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
|
||||
JavaCompletionUtil.shortenReference(file, context.getStartOffset());
|
||||
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,4 +60,6 @@ public interface DfaMemoryState {
|
||||
boolean isNotNull(DfaVariableValue dfaVar);
|
||||
|
||||
void flushVariableOutOfScope(DfaVariableValue variable);
|
||||
|
||||
void fieldReferenced();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
private Stack<DfaValue> myStack;
|
||||
private TIntStack myOffsetStack;
|
||||
private TLongHashSet myDistinctClasses;
|
||||
private Map<DfaVariableValue,DfaVariableState> myVariableStates;
|
||||
private THashMap<DfaVariableValue,DfaVariableState> myVariableStates;
|
||||
private boolean myHasDirtyFields = true;
|
||||
|
||||
public DfaMemoryStateImpl(final DfaValueFactory factory) {
|
||||
myFactory = factory;
|
||||
@@ -80,6 +81,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
newState.myStateSize = myStateSize;
|
||||
newState.myVariableStates = new THashMap<DfaVariableValue, DfaVariableState>();
|
||||
newState.myOffsetStack = new TIntStack(myOffsetStack);
|
||||
newState.myHasDirtyFields = myHasDirtyFields;
|
||||
|
||||
for (int i = 0; i < myEqClasses.size(); i++) {
|
||||
SortedIntSet aClass = myEqClasses.get(i);
|
||||
@@ -110,6 +112,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
if (!myStack.equals(that.myStack)) return false;
|
||||
if (!myOffsetStack.equals(that.myOffsetStack)) return false;
|
||||
if (!myVariableStates.equals(that.myVariableStates)) return false;
|
||||
if (myHasDirtyFields != that.myHasDirtyFields) return false;
|
||||
|
||||
int[] permutation = getPermutationToSortedState();
|
||||
int[] thatPermutation = that.getPermutationToSortedState();
|
||||
@@ -461,6 +464,11 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
myDistinctClasses.add(createPair(c1Index, c2Index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldReferenced() {
|
||||
myHasDirtyFields = true;
|
||||
}
|
||||
|
||||
public boolean isNull(DfaValue dfaValue) {
|
||||
if (dfaValue instanceof DfaNotNullValue) return false;
|
||||
|
||||
@@ -674,6 +682,9 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
|
||||
public void flushFields(DataFlowRunner runner) {
|
||||
if (!myHasDirtyFields) return;
|
||||
|
||||
myHasDirtyFields = false;
|
||||
DfaVariableValue[] fields = runner.getFields();
|
||||
for (DfaVariableValue field : fields) {
|
||||
boolean resetNullability = isNotNull(field);
|
||||
@@ -690,17 +701,19 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
|
||||
doFlash(variable);
|
||||
doFlash((DfaVariableValue)variable.createNegated());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushVariableOutOfScope(DfaVariableValue variable) {
|
||||
doFlash(variable);
|
||||
doFlash((DfaVariableValue)variable.createNegated());
|
||||
}
|
||||
|
||||
private void doFlash(DfaVariableValue variable) {
|
||||
final int id = variable.getID();
|
||||
private void doFlash(DfaVariableValue varPlain) {
|
||||
DfaVariableValue varNegated = (DfaVariableValue)varPlain.createNegated();
|
||||
|
||||
final int idPlain = varPlain.getID();
|
||||
final int idNegated = varNegated.getID();
|
||||
|
||||
int size = myEqClasses.size();
|
||||
int interruptCount = 0;
|
||||
for (int varClassIndex = 0; varClassIndex < size; varClassIndex++) {
|
||||
@@ -713,9 +726,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
int cl = varClass.get(i);
|
||||
DfaValue value = myFactory.getValue(cl);
|
||||
if (value != null && id == value.getID() ||
|
||||
value instanceof DfaBoxedValue && ((DfaBoxedValue)value).getWrappedValue().getID() == id ||
|
||||
value instanceof DfaUnboxedValue && ((DfaUnboxedValue)value).getVariable().getID() == id) {
|
||||
if (mine(idPlain, value) || mine(idNegated, value)) {
|
||||
varClass.remove(i);
|
||||
break;
|
||||
}
|
||||
@@ -733,6 +744,13 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
}
|
||||
|
||||
myVariableStates.remove(variable);
|
||||
myVariableStates.remove(varPlain);
|
||||
myVariableStates.remove(varNegated);
|
||||
}
|
||||
|
||||
private static boolean mine(int id, DfaValue value) {
|
||||
return value != null && id == value.getID() ||
|
||||
value instanceof DfaBoxedValue && ((DfaBoxedValue)value).getWrappedValue().getID() == id ||
|
||||
value instanceof DfaUnboxedValue && ((DfaUnboxedValue)value).getVariable().getID() == id;
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -119,6 +119,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
|
||||
@Override
|
||||
public DfaInstructionState[] visitFieldReference(FieldReferenceInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
|
||||
memState.fieldReferenced();
|
||||
final DfaValue qualifier = memState.pop();
|
||||
if (instruction.getExpression().isPhysical() && !memState.applyNotNull(qualifier)) {
|
||||
onInstructionProducesNPE(instruction, runner);
|
||||
|
||||
@@ -86,4 +86,5 @@ public interface CommonClassNames {
|
||||
|
||||
@NonNls String JAVA_LANG_INVOKE_MH_POLYMORPHIC = "java.lang.invoke.MethodHandle.PolymorphicSignature";
|
||||
String TARGET_ANNOTATION_FQ_NAME = "java.lang.annotation.Target";
|
||||
@NonNls String JAVA_LANG_RUNNABLE = "java.lang.Runnable";
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public class ElementPresentationUtil implements PlatformIcons {
|
||||
private static final int FLAGS_STATIC = 0x200;
|
||||
private static final int FLAGS_FINAL = 0x400;
|
||||
private static final int FLAGS_JUNIT_TEST = 0x2000;
|
||||
private static final int FLAGS_RUNNABLE = 0x4000;
|
||||
public static final int FLAGS_RUNNABLE = 0x4000;
|
||||
|
||||
private static final Key<CachedValue<Integer>> CLASS_KIND_KEY = new Key<CachedValue<Integer>>("CLASS_KIND_KEY");
|
||||
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Change to 'appendable.append(1)'" "true"
|
||||
class Test {
|
||||
void appendable(StringBuilder appendable) throws IOException {
|
||||
appendable.append(1);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Change to 'builder.append(1+1).append(s).append(" ")'" "true"
|
||||
class Test {
|
||||
String s;
|
||||
void bar(StringBuilder builder) {
|
||||
builder.append(1 + 1).append(s).append(" ");
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Change to 'appendable.append(1)'" "true"
|
||||
class Test {
|
||||
void appendable(StringBuilder appendable) throws IOException {
|
||||
appendab<caret>le += 1;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Change to 'builder.append(1+1).append(s).append(" ")'" "true"
|
||||
class Test {
|
||||
String s;
|
||||
void bar(StringBuilder builder) {
|
||||
buil<caret>der += 1 + 1 + s + " ";
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.intellij.codeInsight.daemon.quickFix;
|
||||
|
||||
public class ChangeToAppendTest extends LightQuickFixTestCase {
|
||||
|
||||
public void test() throws Exception { doAllTests(); }
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/changeToAppend";
|
||||
}
|
||||
}
|
||||
@@ -174,8 +174,8 @@ public class SrcRepositoryUseTest extends PsiTestCase{
|
||||
PsiClass aClass = classes[0];
|
||||
PsiClass[] superTypes = aClass.getSupers();
|
||||
LOG.assertTrue(superTypes.length == 2);
|
||||
LOG.assertTrue(superTypes[0].getQualifiedName().equals("java.lang.String"));
|
||||
LOG.assertTrue(superTypes[1].getQualifiedName().equals("java.lang.Runnable"));
|
||||
LOG.assertTrue(superTypes[0].getQualifiedName().equals(CommonClassNames.JAVA_LANG_STRING));
|
||||
LOG.assertTrue(superTypes[1].getQualifiedName().equals(CommonClassNames.JAVA_LANG_RUNNABLE));
|
||||
|
||||
teardownLoadingFilter();
|
||||
}
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ public class ExtendsBoundListTest extends LightCodeInsightTestCase {
|
||||
final PsiTypeParameter typeParameter = getTypeParameter();
|
||||
final PsiReferenceList extendsList = typeParameter.getExtendsList();
|
||||
final JavaPsiFacade manager = getJavaFacade();
|
||||
final PsiClass clonableClass = manager.findClass("java.lang.Runnable");
|
||||
final PsiClass clonableClass = manager.findClass(CommonClassNames.JAVA_LANG_RUNNABLE);
|
||||
assertNotNull(clonableClass);
|
||||
final PsiJavaCodeReferenceElement reference = manager.getElementFactory().createClassReferenceElement(clonableClass);
|
||||
extendsList.add(reference);
|
||||
|
||||
@@ -208,7 +208,7 @@ public class ChangeSignatureTest extends LightRefactoringTestCase {
|
||||
}
|
||||
|
||||
public void testCovariantReturnType() throws Exception {
|
||||
doTest("java.lang.Runnable", new ParameterInfoImpl[0], false);
|
||||
doTest(CommonClassNames.JAVA_LANG_RUNNABLE, new ParameterInfoImpl[0], false);
|
||||
}
|
||||
|
||||
public void testReorderExceptions() throws Exception {
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.intellij.refactoring;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiType;
|
||||
@@ -53,7 +54,7 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testAnonymousClass1() throws Exception {
|
||||
doTest(new MockIntroduceVariableHandler("runnable", false, false, false, "java.lang.Runnable"));
|
||||
doTest(new MockIntroduceVariableHandler("runnable", false, false, false, CommonClassNames.JAVA_LANG_RUNNABLE));
|
||||
}
|
||||
|
||||
public void testAnonymousClass2() throws Exception {
|
||||
|
||||
+2
-1
@@ -23,7 +23,8 @@ public abstract class AbstractRunConfiguration extends ModuleBasedConfiguration<
|
||||
}
|
||||
|
||||
public void setEnvs(final Map<String, String> envs) {
|
||||
myEnvs = envs;
|
||||
myEnvs.clear();
|
||||
myEnvs.putAll(envs);
|
||||
}
|
||||
|
||||
public boolean isPassParentEnvs() {
|
||||
|
||||
+2
-1
@@ -72,7 +72,8 @@ public class EnvironmentVariablesComponent extends LabeledComponent<TextFieldWit
|
||||
}
|
||||
|
||||
public void setEnvs(@NotNull Map<String, String> envs) {
|
||||
myEnvs = envs;
|
||||
myEnvs.clear();
|
||||
myEnvs.putAll(envs);
|
||||
@NonNls final StringBuilder buf = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
for (String variable : myEnvs.keySet()) {
|
||||
|
||||
@@ -35,6 +35,14 @@ public abstract class CustomFoldingProvider {
|
||||
public abstract boolean isCustomRegionStart(String elementText);
|
||||
public abstract boolean isCustomRegionEnd(String elementText);
|
||||
public abstract String getPlaceholderText(String elementText);
|
||||
|
||||
/**
|
||||
* @return A description string shown in "Surround With" action.
|
||||
*/
|
||||
public abstract String getDescription();
|
||||
|
||||
public abstract String getStartString();
|
||||
public abstract String getEndString();
|
||||
|
||||
public boolean isCollapsedByDefault(String text) {
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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.lang.folding;
|
||||
|
||||
import com.intellij.lang.Commenter;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LanguageCommenters;
|
||||
import com.intellij.lang.surroundWith.SurroundDescriptor;
|
||||
import com.intellij.lang.surroundWith.Surrounder;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Rustam Vishnyakov
|
||||
*/
|
||||
public class CustomFoldingSurroundDescriptor implements SurroundDescriptor {
|
||||
|
||||
public final static CustomFoldingSurroundDescriptor INSTANCE = new CustomFoldingSurroundDescriptor();
|
||||
public final static CustomFoldingRegionSurrounder[] SURROUNDERS;
|
||||
|
||||
private final static String DEFAULT_DESC_TEXT = "Description";
|
||||
|
||||
static {
|
||||
List<CustomFoldingRegionSurrounder> surrounderList = new ArrayList<CustomFoldingRegionSurrounder>();
|
||||
for (CustomFoldingProvider provider : CustomFoldingProvider.getAllProviders()) {
|
||||
surrounderList.add(new CustomFoldingRegionSurrounder(provider));
|
||||
}
|
||||
SURROUNDERS = surrounderList.toArray(new CustomFoldingRegionSurrounder[surrounderList.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) {
|
||||
if (startOffset >= endOffset - 1) return PsiElement.EMPTY_ARRAY;
|
||||
Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(file.getLanguage());
|
||||
if (commenter == null || commenter.getLineCommentPrefix() == null) return PsiElement.EMPTY_ARRAY;
|
||||
PsiElement startElement = file.findElementAt(startOffset);
|
||||
if (startElement instanceof PsiWhiteSpace) startElement = startElement.getNextSibling();
|
||||
PsiElement endElement = file.findElementAt(endOffset - 1);
|
||||
if (endElement instanceof PsiWhiteSpace) endElement = endElement.getPrevSibling();
|
||||
if (startElement != null && endElement != null) {
|
||||
if (startElement.getTextRange().getStartOffset() > endElement.getTextRange().getStartOffset()) return PsiElement.EMPTY_ARRAY;
|
||||
startElement = findClosestParentAfterLineBreak(startElement);
|
||||
if (startElement != null) {
|
||||
endElement = findClosestParentBeforeLineBreak(endElement);
|
||||
if (endElement != null) {
|
||||
PsiElement commonParent = startElement.getParent();
|
||||
if (endElement.getParent() == commonParent) {
|
||||
if (startElement == endElement) return new PsiElement[] {startElement};
|
||||
return new PsiElement[] {startElement, endElement};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement findClosestParentAfterLineBreak(PsiElement element) {
|
||||
PsiElement parent = element;
|
||||
while (parent != null) {
|
||||
PsiElement prev = parent.getPrevSibling();
|
||||
if (prev instanceof PsiWhiteSpace && prev.textContains('\n')) return parent;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement findClosestParentBeforeLineBreak(PsiElement element) {
|
||||
PsiElement parent = element;
|
||||
while (parent != null) {
|
||||
PsiElement next = parent.getNextSibling();
|
||||
if (next instanceof PsiWhiteSpace && next.textContains('\n')) return parent;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Surrounder[] getSurrounders() {
|
||||
return SURROUNDERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExclusive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class CustomFoldingRegionSurrounder implements Surrounder {
|
||||
|
||||
private CustomFoldingProvider myProvider;
|
||||
|
||||
public CustomFoldingRegionSurrounder(@NotNull CustomFoldingProvider provider) {
|
||||
myProvider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateDescription() {
|
||||
return myProvider.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement[] elements) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextRange surroundElements(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement[] elements)
|
||||
throws IncorrectOperationException {
|
||||
if (elements.length == 0) return null;
|
||||
PsiElement firstElement = elements[0];
|
||||
PsiElement lastElement = elements[elements.length - 1];
|
||||
PsiFile psiFile = firstElement.getContainingFile();
|
||||
Language language = psiFile.getLanguage();
|
||||
Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(language);
|
||||
if (commenter == null) return null;
|
||||
String linePrefix = commenter.getLineCommentPrefix();
|
||||
if (linePrefix == null) return null;
|
||||
int prefixLength = linePrefix.length();
|
||||
int startOffset = firstElement.getTextRange().getStartOffset();
|
||||
int endOffset = lastElement.getTextRange().getEndOffset();
|
||||
int delta = 0;
|
||||
TextRange rangeToSelect = new TextRange(startOffset, startOffset);
|
||||
String startText = myProvider.getStartString();
|
||||
int descPos = startText.indexOf("?");
|
||||
if (descPos >= 0) {
|
||||
startText = startText.replace("?", DEFAULT_DESC_TEXT);
|
||||
rangeToSelect = new TextRange(startOffset + descPos, startOffset + descPos + DEFAULT_DESC_TEXT.length());
|
||||
}
|
||||
String startString = linePrefix + startText + "\n";
|
||||
String endString = "\n" + linePrefix + myProvider.getEndString();
|
||||
editor.getDocument().insertString(endOffset, endString);
|
||||
delta += endString.length();
|
||||
editor.getDocument().insertString(startOffset, startString);
|
||||
delta += startString.length();
|
||||
rangeToSelect = rangeToSelect.shiftRight(prefixLength);
|
||||
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
|
||||
documentManager.commitDocument(documentManager.getDocument(psiFile));
|
||||
adjustLineIndent(project, psiFile, language,
|
||||
new TextRange(endOffset + delta - endString.length(), endOffset + delta));
|
||||
adjustLineIndent(project, psiFile, language,
|
||||
new TextRange(startOffset, startOffset + startString.length()));
|
||||
return rangeToSelect;
|
||||
}
|
||||
|
||||
private static void adjustLineIndent(@NotNull Project project, PsiFile file, Language language, TextRange range) {
|
||||
CommonCodeStyleSettings formatSettings = CodeStyleSettingsManager.getSettings(project).getCommonSettings(language);
|
||||
boolean keepAtFirstCol = formatSettings.KEEP_FIRST_COLUMN_COMMENT;
|
||||
formatSettings.KEEP_FIRST_COLUMN_COMMENT = false;
|
||||
CodeStyleManager.getInstance(project).adjustLineIndent(file, range);
|
||||
formatSettings.KEEP_FIRST_COLUMN_COMMENT = keepAtFirstCol;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,6 @@ public abstract class IntStubIndexExtension<Psi extends PsiElement> extends Abst
|
||||
}
|
||||
|
||||
public KeyDescriptor<Integer> getKeyDescriptor() {
|
||||
return new EnumeratorIntegerDescriptor();
|
||||
return EnumeratorIntegerDescriptor.INSTANCE;
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -33,8 +33,10 @@ import com.intellij.injected.editor.EditorWindow;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -442,7 +444,14 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
|
||||
void disposeIndicator() {
|
||||
Disposer.dispose(this);
|
||||
// our offset map should be disposed under write action, so that duringCompletion (read action) won't access it after disposing
|
||||
AccessToken token = WriteAction.start();
|
||||
try {
|
||||
Disposer.dispose(this);
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
|
||||
+8
-2
@@ -29,6 +29,7 @@ import com.intellij.codeInsight.template.impl.WrapWithCustomTemplateAction;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LanguageSurrounders;
|
||||
import com.intellij.lang.folding.CustomFoldingSurroundDescriptor;
|
||||
import com.intellij.lang.surroundWith.SurroundDescriptor;
|
||||
import com.intellij.lang.surroundWith.Surrounder;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
@@ -107,6 +108,7 @@ public class SurroundWithHandler implements CodeInsightActionHandler {
|
||||
|
||||
surroundDescriptors.addAll(LanguageSurrounders.INSTANCE.allForLanguage(l));
|
||||
if (l != baseLanguage) surroundDescriptors.addAll(LanguageSurrounders.INSTANCE.allForLanguage(baseLanguage));
|
||||
surroundDescriptors.add(CustomFoldingSurroundDescriptor.INSTANCE);
|
||||
|
||||
int exclusiveCount = 0;
|
||||
List<SurroundDescriptor> exclusiveSurroundDescriptors = new ArrayList<SurroundDescriptor>();
|
||||
@@ -152,8 +154,12 @@ public class SurroundWithHandler implements CodeInsightActionHandler {
|
||||
for (SurroundDescriptor descriptor : surroundDescriptors) {
|
||||
final PsiElement[] elements = descriptor.getElementsToSurround(file, startOffset, endOffset);
|
||||
if (elements.length > 0) {
|
||||
doSurround(project, editor, surrounder, elements);
|
||||
return;
|
||||
for (Surrounder descriptorSurrounder : descriptor.getSurrounders()) {
|
||||
if (surrounder.getClass().equals(descriptorSurrounder.getClass())) {
|
||||
doSurround(project, editor, surrounder, elements);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -784,7 +784,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
int bs = myEditor.logicalPositionToOffset(new LogicalPosition(line, blockStart.column));
|
||||
int start = bs - prefix.length();
|
||||
int end = myEditor.logicalPositionToOffset(new LogicalPosition(line, blockEnd.column));
|
||||
if (start >= end) {
|
||||
if (start > end) {
|
||||
LOG.error("bs=" + bs + "; start=" + start + "; end=" + end +
|
||||
"; blockStart=" + blockStart + "; blockEnd=" + blockEnd + "; line=" + line + "; len=" +
|
||||
(document.getLineEndOffset(line) - document.getLineStartOffset(line)));
|
||||
@@ -1275,7 +1275,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
public void hideLookup(boolean explicitly) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
|
||||
if (myDisposed) return;
|
||||
if (myHidden) return;
|
||||
|
||||
doHide(true, explicitly);
|
||||
}
|
||||
|
||||
@@ -763,7 +763,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
|
||||
myLivePreviewController.setReplaceListener(this);
|
||||
mySearchResults.addListener(this);
|
||||
|
||||
myLivePreviewController.updateInBackground(myFindModel, false);
|
||||
updateResults(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -76,7 +76,7 @@ public class TrigramIndex extends ScalarIndexExtension<Integer> {
|
||||
|
||||
@Override
|
||||
public KeyDescriptor<Integer> getKeyDescriptor() {
|
||||
return new EnumeratorIntegerDescriptor();
|
||||
return EnumeratorIntegerDescriptor.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+15
@@ -38,6 +38,21 @@ public class NetBeansCustomFoldingProvider extends CustomFoldingProvider {
|
||||
return customText.isEmpty() ? "..." : customText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "<editor-fold...> Comments";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStartString() {
|
||||
return "<editor-fold desc=\"?\">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEndString() {
|
||||
return "</editor-fold>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollapsedByDefault(String text) {
|
||||
return text.matches(".*defaultstate\\s*=\\s*\"collapsed\".*");
|
||||
|
||||
+14
@@ -37,4 +37,18 @@ public class VisualStudioCustomFoldingProvider extends CustomFoldingProvider {
|
||||
return elementText.replaceFirst("..?\\s*region(.*)","$1").trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "region...endregion Comments";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStartString() {
|
||||
return "region ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEndString() {
|
||||
return "endregion";
|
||||
}
|
||||
}
|
||||
|
||||
+12
-8
@@ -108,6 +108,11 @@ class ChangeTrackingValueContainer<Value> extends UpdatableValueContainer<Value>
|
||||
return getMergedData().isAssociated(value, inputId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntPredicate getValueAssociationPredicate(Value value) {
|
||||
return getMergedData().getValueAssociationPredicate(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntIterator getInputIdsIterator(final Value value) {
|
||||
return getMergedData().getInputIdsIterator(value);
|
||||
@@ -119,7 +124,7 @@ class ChangeTrackingValueContainer<Value> extends UpdatableValueContainer<Value>
|
||||
|
||||
// need 'synchronized' to ensure atomic initialization of merged data
|
||||
// because several threads that acquired read lock may simultaneously execute the method
|
||||
private ValueContainer<Value> getMergedData() {
|
||||
private ValueContainerImpl<Value> getMergedData() {
|
||||
ValueContainerImpl<Value> merged = myMerged;
|
||||
if (merged != null) {
|
||||
return merged;
|
||||
@@ -129,16 +134,15 @@ class ChangeTrackingValueContainer<Value> extends UpdatableValueContainer<Value>
|
||||
if (merged != null) {
|
||||
return merged;
|
||||
}
|
||||
final ValueContainerImpl<Value> newMerged = new ValueContainerImpl<Value>();
|
||||
|
||||
final ValueContainer<Value> fromDisk = myInitializer.compute();
|
||||
final ValueContainerImpl<Value> newMerged;
|
||||
|
||||
fromDisk.forEach(new ContainerAction<Value>() {
|
||||
@Override
|
||||
public void perform(final int id, final Value value) {
|
||||
newMerged.addValue(id, value);
|
||||
}
|
||||
});
|
||||
if (fromDisk instanceof ValueContainerImpl) {
|
||||
newMerged = ((ValueContainerImpl<Value>)fromDisk).clone();
|
||||
} else {
|
||||
newMerged = ((ChangeTrackingValueContainer<Value>)fromDisk).getMergedData().clone();
|
||||
}
|
||||
myInvalidated.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int inputId) {
|
||||
|
||||
@@ -63,8 +63,6 @@ import com.intellij.util.*;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.containers.ConcurrentHashSet;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.io.*;
|
||||
import com.intellij.util.io.DataOutputStream;
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch;
|
||||
@@ -171,7 +169,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
@Override
|
||||
public void beforeFileTypesChanged(final FileTypeEvent event) {
|
||||
cleanupProcessedFlag();
|
||||
myTypeToExtensionMap = new HashMap<FileType, Set<String>>();
|
||||
myTypeToExtensionMap = new THashMap<FileType, Set<String>>();
|
||||
for (FileType type : myFileTypeManager.getRegisteredFileTypes()) {
|
||||
myTypeToExtensionMap.put(type, getExtensions(type));
|
||||
}
|
||||
@@ -182,7 +180,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
final Map<FileType, Set<String>> oldExtensions = myTypeToExtensionMap;
|
||||
myTypeToExtensionMap = null;
|
||||
if (oldExtensions != null) {
|
||||
final Map<FileType, Set<String>> newExtensions = new HashMap<FileType, Set<String>>();
|
||||
final Map<FileType, Set<String>> newExtensions = new THashMap<FileType, Set<String>>();
|
||||
for (FileType type : myFileTypeManager.getRegisteredFileTypes()) {
|
||||
newExtensions.put(type, getExtensions(type));
|
||||
}
|
||||
@@ -204,7 +202,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
}
|
||||
|
||||
private Set<String> getExtensions(FileType type) {
|
||||
final Set<String> set = new HashSet<String>();
|
||||
final Set<String> set = new THashSet<String>();
|
||||
for (FileNameMatcher matcher : myFileTypeManager.getAssociations(type)) {
|
||||
set.add(matcher.getPresentableString());
|
||||
}
|
||||
@@ -434,7 +432,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
}
|
||||
|
||||
private static Set<String> readRegisteredIndexNames() {
|
||||
final Set<String> result = new HashSet<String>();
|
||||
final Set<String> result = new THashSet<String>();
|
||||
try {
|
||||
final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(getRegisteredIndicesFile())));
|
||||
try {
|
||||
@@ -493,7 +491,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
MemoryIndexStorage<K, ?> storage) throws IOException {
|
||||
final File indexStorageFile = IndexInfrastructure.getInputIndexStorageFile(indexId);
|
||||
final Ref<Boolean> isBufferingMode = new Ref<Boolean>(false);
|
||||
final Map<Integer, Collection<K>> tempMap = new HashMap<Integer, Collection<K>>();
|
||||
final TIntObjectHashMap<Collection<K>> tempMap = new TIntObjectHashMap<Collection<K>>();
|
||||
|
||||
final DataExternalizer<Collection<K>> dataExternalizer = new DataExternalizer<Collection<K>>() {
|
||||
@Override
|
||||
@@ -532,7 +530,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
// cleared properly before updating (removed data will still be present on disk). See IDEA-52223 for illustration of possible effects.
|
||||
|
||||
final PersistentHashMap<Integer, Collection<K>> map = new PersistentHashMap<Integer, Collection<K>>(
|
||||
indexStorageFile, new EnumeratorIntegerDescriptor(), dataExternalizer
|
||||
indexStorageFile, EnumeratorIntegerDescriptor.INSTANCE, dataExternalizer
|
||||
) {
|
||||
|
||||
@Override
|
||||
@@ -667,7 +665,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
*/
|
||||
@NotNull
|
||||
public <K> Collection<K> getAllKeys(final ID<K, ?> indexId, @NotNull Project project) {
|
||||
Set<K> allKeys = new HashSet<K>();
|
||||
Set<K> allKeys = new THashSet<K>();
|
||||
processAllKeys(indexId, new CommonProcessors.CollectProcessor<K>(allKeys), project);
|
||||
return allKeys;
|
||||
}
|
||||
@@ -829,7 +827,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
|
||||
@NotNull
|
||||
public <K, V> Collection<VirtualFile> getContainingFiles(final ID<K, V> indexId, @NotNull K dataKey, @NotNull final GlobalSearchScope filter) {
|
||||
final Set<VirtualFile> files = new HashSet<VirtualFile>();
|
||||
final Set<VirtualFile> files = new THashSet<VirtualFile>();
|
||||
processValuesImpl(indexId, dataKey, false, null, new ValueProcessor<V>() {
|
||||
@Override
|
||||
public boolean process(final VirtualFile file, final V value) {
|
||||
@@ -1021,7 +1019,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
|
||||
for (K dataKey : dataKeys) {
|
||||
ProgressManager.checkCanceled();
|
||||
TIntHashSet copy = new TIntHashSet();
|
||||
final TIntHashSet copy = new TIntHashSet();
|
||||
final ValueContainer<V> container = index.getData(dataKey);
|
||||
|
||||
for (final Iterator<V> valueIt = container.getValueIterator(); valueIt.hasNext(); ) {
|
||||
@@ -1029,12 +1027,27 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
if (valueChecker != null && !valueChecker.value(value)) {
|
||||
continue;
|
||||
}
|
||||
for (final ValueContainer.IntIterator inputIdsIterator = container.getInputIdsIterator(value); inputIdsIterator.hasNext(); ) {
|
||||
final int id = inputIdsIterator.next();
|
||||
if ((mainIntersection == null || mainIntersection.contains(id)) &&
|
||||
(projectFilesFilter == null || projectFilesFilter.contains(id))) {
|
||||
copy.add(id);
|
||||
|
||||
ValueContainer.IntIterator iterator = container.getInputIdsIterator(value);
|
||||
|
||||
if (mainIntersection == null || iterator.size() < mainIntersection.size()) {
|
||||
for (final ValueContainer.IntIterator inputIdsIterator = iterator; inputIdsIterator.hasNext(); ) {
|
||||
final int id = inputIdsIterator.next();
|
||||
if (mainIntersection == null && (projectFilesFilter == null || projectFilesFilter.contains(id)) ||
|
||||
mainIntersection != null && mainIntersection.contains(id)
|
||||
) {
|
||||
copy.add(id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mainIntersection.forEach(new TIntProcedure() {
|
||||
final ValueContainer.IntPredicate predicate = container.getValueAssociationPredicate(value);
|
||||
@Override
|
||||
public boolean execute(int id) {
|
||||
if (predicate.contains(id)) copy.add(id);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1249,7 +1262,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
}
|
||||
|
||||
private Set<Document> getUnsavedOrTransactedDocuments() {
|
||||
final Set<Document> docs = new HashSet<Document>(Arrays.asList(myFileDocumentManager.getUnsavedDocuments()));
|
||||
final Set<Document> docs = new THashSet<Document>(Arrays.asList(myFileDocumentManager.getUnsavedDocuments()));
|
||||
synchronized (myTransactionMap) {
|
||||
docs.addAll(myTransactionMap.keySet());
|
||||
}
|
||||
@@ -2161,7 +2174,7 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<VirtualFile> visitedRoots = new HashSet<VirtualFile>();
|
||||
Set<VirtualFile> visitedRoots = new THashSet<VirtualFile>();
|
||||
for (IndexedRootsProvider provider : Extensions.getExtensions(IndexedRootsProvider.EP_NAME)) {
|
||||
//important not to depend on project here, to support per-project background reindex
|
||||
// each client gives a project to FileBasedIndex
|
||||
|
||||
@@ -31,11 +31,17 @@ public abstract class ValueContainer<Value> {
|
||||
|
||||
int size();
|
||||
}
|
||||
|
||||
static abstract class IntPredicate {
|
||||
abstract boolean contains(int id);
|
||||
}
|
||||
|
||||
public abstract IntIterator getInputIdsIterator(Value value);
|
||||
|
||||
public abstract boolean isAssociated(Value value, int inputId);
|
||||
|
||||
|
||||
public abstract IntPredicate getValueAssociationPredicate(Value value);
|
||||
|
||||
public abstract Iterator<Value> getValueIterator();
|
||||
|
||||
public abstract List<Value> toValueList();
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
package com.intellij.util.indexing;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.containers.EmptyIterator;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import gnu.trove.TIntIterator;
|
||||
import gnu.trove.TObjectObjectProcedure;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -29,7 +31,6 @@ import java.util.*;
|
||||
*/
|
||||
class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implements Cloneable{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.indexing.ValueContainerImpl");
|
||||
|
||||
private THashMap<Value, Object> myInputIdMapping;
|
||||
|
||||
public ValueContainerImpl() {
|
||||
@@ -117,6 +118,10 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
|
||||
|
||||
@Override
|
||||
public Iterator<Value> getValueIterator() {
|
||||
if (myInputIdMapping.size() == 0) {
|
||||
return EmptyIterator.getInstance();
|
||||
}
|
||||
|
||||
final Set<Value> values = Collections.unmodifiableSet(myInputIdMapping.keySet());
|
||||
return new Iterator<Value>() {
|
||||
final Iterator<Value> iterator = values.iterator();
|
||||
@@ -161,6 +166,28 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntPredicate getValueAssociationPredicate(Value value) {
|
||||
final Object input = myInputIdMapping.get(value);
|
||||
if (input == null) return EMPTY_PREDICATE;
|
||||
if (input instanceof Integer) {
|
||||
return new IntPredicate() {
|
||||
final int myId = (Integer)input;
|
||||
@Override
|
||||
public boolean contains(int id) {
|
||||
return id == myId;
|
||||
}
|
||||
};
|
||||
}
|
||||
return new IntPredicate() {
|
||||
final TIntHashSet mySet = (TIntHashSet)input;
|
||||
@Override
|
||||
boolean contains(int id) {
|
||||
return mySet.contains(id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntIterator getInputIdsIterator(Value value) {
|
||||
value = maskNull(value);
|
||||
@@ -266,15 +293,26 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
|
||||
return null;
|
||||
}
|
||||
final THashMap<Value, Object> cloned = map.clone();
|
||||
for (Value key : cloned.keySet()) {
|
||||
final Object val = cloned.get(key);
|
||||
if (val instanceof TIntHashSet) {
|
||||
cloned.put(key, ((TIntHashSet)val).clone());
|
||||
cloned.forEachEntry(new TObjectObjectProcedure<Value, Object>() {
|
||||
@Override
|
||||
public boolean execute(Value key, Object val) {
|
||||
if (val instanceof TIntHashSet) {
|
||||
cloned.put(key, ((TIntHashSet)val).clone());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return cloned;
|
||||
}
|
||||
|
||||
private static final IntPredicate EMPTY_PREDICATE = new IntPredicate() {
|
||||
@Override
|
||||
public boolean contains(int id) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
private static class IdSet extends TIntHashSet {
|
||||
|
||||
private IdSet(final int initialCapacity, final float loadFactor) {
|
||||
|
||||
@@ -41,6 +41,15 @@ public class TableView<Item> extends BaseTableView implements ItemsProvider, Sel
|
||||
super.setModel(dataModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* use {@link #setModelAndUpdateColumns(com.intellij.util.ui.ListTableModel<Item>)} instead
|
||||
* @param model
|
||||
*/
|
||||
@Deprecated
|
||||
public void setModel(final ListTableModel<Item> model) {
|
||||
setModelAndUpdateColumns(model);
|
||||
}
|
||||
|
||||
public void setModelAndUpdateColumns(final ListTableModel<Item> model) {
|
||||
super.setModel(model);
|
||||
updateColumnSizes();
|
||||
|
||||
@@ -711,7 +711,27 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
|
||||
|
||||
addWindowListener(macFullScreenPatchListener);
|
||||
}
|
||||
if (SystemInfo.isMac && Registry.is("ide.mac.fix.dialog.showing")) {
|
||||
final Window owner = getOwner();
|
||||
if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow() != owner) {
|
||||
final Ref<WindowAdapter> dialogFixerRef = new Ref<WindowAdapter>();
|
||||
final WindowAdapter dialogFixer = new WindowAdapter() {
|
||||
@Override
|
||||
public void windowActivated(WindowEvent e) {
|
||||
owner.removeWindowListener(dialogFixerRef.get());
|
||||
superShow();
|
||||
}
|
||||
};
|
||||
dialogFixerRef.set(dialogFixer);
|
||||
owner.addWindowListener(dialogFixer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
superShow();
|
||||
}
|
||||
|
||||
private void superShow() {
|
||||
super.show();
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -379,6 +379,8 @@ public class ToolWindowContentUi extends JPanel implements ContentUI, PropertyCh
|
||||
hideWindow(e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hideWindow(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.openapi.wm.impl.status;
|
||||
import com.intellij.notification.EventLog;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
@@ -39,6 +40,7 @@ import java.awt.event.MouseEvent;
|
||||
* @author peter
|
||||
*/
|
||||
class StatusPanel extends JPanel {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.status.StatusPanel");
|
||||
private boolean myLogMode;
|
||||
private int myTimeStart;
|
||||
private boolean myDirty;
|
||||
@@ -58,6 +60,9 @@ class StatusPanel extends JPanel {
|
||||
@Override
|
||||
protected String truncateText(String text, Rectangle bounds, FontMetrics fm, Rectangle textR, Rectangle iconR, int maxWidth) {
|
||||
if (myTimeStart > 0) {
|
||||
if (myTimeStart >= text.length()) {
|
||||
LOG.error(myTimeStart + " " + text.length());
|
||||
}
|
||||
final String time = text.substring(myTimeStart);
|
||||
final int withoutTime = maxWidth - fm.stringWidth(time);
|
||||
|
||||
@@ -165,6 +170,8 @@ class StatusPanel extends JPanel {
|
||||
if (myDirty || System.currentTimeMillis() - statusMessage.second >= DateFormatUtil.MINUTE) {
|
||||
myTimeStart = text.length() + 1;
|
||||
text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.second)) + ")";
|
||||
} else {
|
||||
myTimeStart = -1;
|
||||
}
|
||||
setStatusText(text);
|
||||
alarm.addRequest(this, 30000);
|
||||
|
||||
@@ -108,6 +108,7 @@ ide.mac.filechooser.showhidden.files=false
|
||||
ide.mac.filechooser.native=true
|
||||
ide.mac.message.dialogs.as.sheets=true
|
||||
ide.mac.inplaceDialogMnemonicsFix=true
|
||||
ide.mac.fix.dialog.showing=false
|
||||
ide.mac.hide.cursor.when.typing=false
|
||||
ide.mac.show.native.help=false
|
||||
ide.mac.useNativeClipboard=false
|
||||
|
||||
@@ -1308,8 +1308,8 @@ string.buffer.replaceable.by.string.builder.replace.quickfix=Replace with 'Strin
|
||||
string.buffer.to.string.in.concatenation.remove.quickfix=Remove 'toString()'
|
||||
string.concatenation.in.loops.only.option=Only warn if string is repeatedly appended
|
||||
string.concatenation.inside.string.buffer.append.replace.quickfix=Replace with chained 'append()' calls
|
||||
string.equals.empty.string.replace.quickfix=Replace with 'length()==0'
|
||||
string.equals.empty.string.replace.quickfix2=Replace with 'isEmpty()'
|
||||
string.equals.empty.string.quickfix=Replace with 'length()==0'
|
||||
string.equals.empty.string.isempty.quickfix=Replace with 'isEmpty()'
|
||||
tail.recursion.replace.quickfix=Replace tail recursion with iteration
|
||||
if.statement.with.too.many.branches.max.option=Maximum number of branches:
|
||||
if.statement.with.too.many.branches.problem.descriptor='<code>#ref</code>' has too many branches ({0}) #loc
|
||||
|
||||
+85
-127
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
@@ -27,18 +28,14 @@ import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class StringConcatenationInsideStringBufferAppendInspection
|
||||
extends BaseInspection {
|
||||
public class StringConcatenationInsideStringBufferAppendInspection extends BaseInspection {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"string.concatenation.inside.string.buffer.append.display.name");
|
||||
return InspectionGadgetsBundle.message("string.concatenation.inside.string.buffer.append.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,9 +48,7 @@ public class StringConcatenationInsideStringBufferAppendInspection
|
||||
public String buildErrorString(Object... infos) {
|
||||
final PsiClass aClass = (PsiClass)infos[0];
|
||||
final String className = aClass.getName();
|
||||
return InspectionGadgetsBundle.message(
|
||||
"string.concatenation.inside.string.buffer.append.problem.descriptor",
|
||||
className);
|
||||
return InspectionGadgetsBundle.message("string.concatenation.inside.string.buffer.append.problem.descriptor", className);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,8 +61,7 @@ public class StringConcatenationInsideStringBufferAppendInspection
|
||||
return new ReplaceWithChainedAppendFix();
|
||||
}
|
||||
|
||||
private static class ReplaceWithChainedAppendFix
|
||||
extends InspectionGadgetsFix {
|
||||
private static class ReplaceWithChainedAppendFix extends InspectionGadgetsFix {
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
@@ -76,153 +70,115 @@ public class StringConcatenationInsideStringBufferAppendInspection
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
|
||||
final PsiElement methodNameElement = descriptor.getPsiElement();
|
||||
final PsiReferenceExpression methodExpression =
|
||||
(PsiReferenceExpression)methodNameElement.getParent();
|
||||
final PsiReferenceExpression methodExpression = (PsiReferenceExpression)methodNameElement.getParent();
|
||||
if (methodExpression == null) {
|
||||
return;
|
||||
}
|
||||
final PsiMethodCallExpression methodCallExpression =
|
||||
(PsiMethodCallExpression)methodExpression.getParent();
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)methodExpression.getParent();
|
||||
if (methodCallExpression == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpressionList argumentList =
|
||||
methodCallExpression.getArgumentList();
|
||||
final PsiExpression[] arguments = argumentList.getExpressions();
|
||||
final PsiExpression argument = arguments[0];
|
||||
final boolean useStringValueOf;
|
||||
final PsiMethod method = methodCallExpression.resolveMethod();
|
||||
if (method == null) {
|
||||
useStringValueOf = false;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
useStringValueOf = false;
|
||||
}
|
||||
else {
|
||||
final String qualifiedName = containingClass.getQualifiedName();
|
||||
if (qualifiedName == null) {
|
||||
useStringValueOf = false;
|
||||
}
|
||||
else {
|
||||
useStringValueOf = !qualifiedName.equals(
|
||||
CommonClassNames.JAVA_LANG_STRING_BUFFER) &&
|
||||
!qualifiedName.equals(CommonClassNames.JAVA_LANG_STRING_BUILDER);
|
||||
}
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
final List<String> expressions =
|
||||
findConcatenationComponents(argument, useStringValueOf);
|
||||
final PsiExpression qualifier =
|
||||
methodExpression.getQualifierExpression();
|
||||
final String qualifiedName = containingClass.getQualifiedName();
|
||||
if (qualifiedName == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
return;
|
||||
}
|
||||
@NonNls final StringBuffer newExpressionBuffer = new StringBuffer();
|
||||
newExpressionBuffer.append(qualifier.getText());
|
||||
for (String expression : expressions) {
|
||||
newExpressionBuffer.append(".append(");
|
||||
newExpressionBuffer.append(expression);
|
||||
newExpressionBuffer.append(')');
|
||||
final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
|
||||
final PsiExpression[] arguments = argumentList.getExpressions();
|
||||
final PsiExpression argument = arguments[0];
|
||||
final boolean useStringValueOf;
|
||||
useStringValueOf = !qualifiedName.equals(CommonClassNames.JAVA_LANG_STRING_BUFFER) &&
|
||||
!qualifiedName.equals(CommonClassNames.JAVA_LANG_STRING_BUILDER);
|
||||
@NonNls final StringBuilder newExpressionBuffer =
|
||||
buildAppendExpression(argument, useStringValueOf, new StringBuilder(qualifier.getText()));
|
||||
if (newExpressionBuffer == null) {
|
||||
return;
|
||||
}
|
||||
final String newExpression = newExpressionBuffer.toString();
|
||||
replaceExpression(methodCallExpression, newExpression);
|
||||
replaceExpression(methodCallExpression, newExpressionBuffer.toString());
|
||||
}
|
||||
|
||||
private static List<String> findConcatenationComponents(
|
||||
PsiExpression concatenation, boolean useStringValueOf)
|
||||
throws IncorrectOperationException {
|
||||
final List<String> out = new ArrayList<String>();
|
||||
findConcatenationComponents(concatenation, out, useStringValueOf);
|
||||
return out;
|
||||
}
|
||||
|
||||
private static void findConcatenationComponents(
|
||||
PsiExpression concatenation, @NonNls List<String> out,
|
||||
boolean useStringValueOf)
|
||||
@Nullable
|
||||
private static StringBuilder buildAppendExpression(PsiExpression concatenation, boolean useStringValueOf, @NonNls StringBuilder out)
|
||||
throws IncorrectOperationException {
|
||||
final PsiType type = concatenation.getType();
|
||||
if (concatenation instanceof PsiBinaryExpression) {
|
||||
if (type != null && type.equalsToText(
|
||||
CommonClassNames.JAVA_LANG_STRING)) {
|
||||
PsiBinaryExpression binaryExpression =
|
||||
(PsiBinaryExpression)concatenation;
|
||||
PsiExpression lhs = binaryExpression.getLOperand();
|
||||
PsiExpression rhs = binaryExpression.getROperand();
|
||||
assert rhs != null;
|
||||
if (!PsiUtil.isConstantExpression(rhs)) {
|
||||
findConcatenationComponents(lhs, out, useStringValueOf);
|
||||
findConcatenationComponents(rhs, out, useStringValueOf);
|
||||
return;
|
||||
}
|
||||
final StringBuffer builder =
|
||||
new StringBuffer(rhs.getText());
|
||||
while (lhs instanceof PsiBinaryExpression) {
|
||||
final PsiType lhsType = lhs.getType();
|
||||
if (lhsType == null ||
|
||||
!lhsType.equalsToText(
|
||||
CommonClassNames.JAVA_LANG_STRING)) {
|
||||
break;
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
if (concatenation instanceof PsiPolyadicExpression && type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
|
||||
PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)concatenation;
|
||||
final PsiExpression[] operands = polyadicExpression.getOperands();
|
||||
boolean isConstant = true;
|
||||
boolean isString = false;
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (PsiExpression operand : operands) {
|
||||
if (isConstant && PsiUtil.isConstantExpression(operand)) {
|
||||
if (builder.length() != 0) {
|
||||
builder.append('+');
|
||||
}
|
||||
binaryExpression = (PsiBinaryExpression)lhs;
|
||||
rhs = binaryExpression.getROperand();
|
||||
assert rhs != null;
|
||||
if (!PsiUtil.isConstantExpression(rhs)) {
|
||||
findConcatenationComponents(lhs, out, useStringValueOf);
|
||||
out.add(builder.toString());
|
||||
return;
|
||||
final PsiType operandType = operand.getType();
|
||||
if (operandType != null && operandType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
|
||||
isString = true;
|
||||
}
|
||||
lhs = binaryExpression.getLOperand();
|
||||
builder.insert(0, " + ");
|
||||
builder.insert(0, rhs.getText());
|
||||
}
|
||||
if (PsiUtil.isConstantExpression(lhs)) {
|
||||
builder.insert(0, " + ");
|
||||
builder.insert(0, lhs.getText());
|
||||
out.add(builder.toString());
|
||||
builder.append(operand.getText());
|
||||
}
|
||||
else {
|
||||
findConcatenationComponents(lhs, out, useStringValueOf);
|
||||
out.add(builder.toString());
|
||||
isConstant = false;
|
||||
if (builder.length() != 0) {
|
||||
append(builder, useStringValueOf && !isString, out);
|
||||
builder.setLength(0);
|
||||
}
|
||||
buildAppendExpression(operand, useStringValueOf, out);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (builder.length() != 0) {
|
||||
append(builder, false, out);
|
||||
}
|
||||
}
|
||||
else if (concatenation instanceof PsiParenthesizedExpression) {
|
||||
final PsiParenthesizedExpression parenthesizedExpression =
|
||||
(PsiParenthesizedExpression)concatenation;
|
||||
final PsiExpression expression =
|
||||
parenthesizedExpression.getExpression();
|
||||
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)concatenation;
|
||||
final PsiExpression expression = parenthesizedExpression.getExpression();
|
||||
if (expression != null) {
|
||||
out.add(expression.getText());
|
||||
return buildAppendExpression(expression, useStringValueOf, out);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (useStringValueOf && type != null &&
|
||||
!type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
|
||||
out.add("String.valueOf(" + concatenation.getText() + ')');
|
||||
}
|
||||
else {
|
||||
out.add(concatenation.getText());
|
||||
append(concatenation.getText(), useStringValueOf && !type.equalsToText(CommonClassNames.JAVA_LANG_STRING), out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static void append(CharSequence text, boolean useStringValueOf, StringBuilder out) {
|
||||
out.append(".append(");
|
||||
if (useStringValueOf) {
|
||||
out.append("String.valueOf(").append(text).append(')');
|
||||
}
|
||||
else {
|
||||
out.append(text);
|
||||
}
|
||||
out.append(')');
|
||||
}
|
||||
}
|
||||
|
||||
private static class StringConcatenationInsideStringBufferAppendVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
private static class StringConcatenationInsideStringBufferAppendVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitMethodCallExpression(
|
||||
PsiMethodCallExpression expression) {
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
final PsiReferenceExpression methodExpression =
|
||||
expression.getMethodExpression();
|
||||
@NonNls final String methodName =
|
||||
methodExpression.getReferenceName();
|
||||
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
|
||||
@NonNls final String methodName = methodExpression.getReferenceName();
|
||||
if (!"append".equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
@@ -251,20 +207,22 @@ public class StringConcatenationInsideStringBufferAppendInspection
|
||||
}
|
||||
final Project project = containingClass.getProject();
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
final PsiClass appendableClass =
|
||||
psiFacade.findClass("java.lang.Appendable",
|
||||
GlobalSearchScope.allScope(project));
|
||||
final PsiClass appendableClass = psiFacade.findClass("java.lang.Appendable", GlobalSearchScope.allScope(project));
|
||||
if (appendableClass == null) {
|
||||
return;
|
||||
}
|
||||
if (!containingClass.isInheritor(appendableClass, true)) {
|
||||
if (!InheritanceUtil.isInheritorOrSelf(containingClass, appendableClass, true)) {
|
||||
return;
|
||||
}
|
||||
registerMethodCallError(expression, containingClass);
|
||||
}
|
||||
|
||||
private static boolean isConcatenation(PsiExpression expression) {
|
||||
if (!(expression instanceof PsiBinaryExpression)) {
|
||||
if (expression instanceof PsiParenthesizedExpression) {
|
||||
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
|
||||
return isConcatenation(parenthesizedExpression.getExpression());
|
||||
}
|
||||
if (!(expression instanceof PsiPolyadicExpression)) {
|
||||
return false;
|
||||
}
|
||||
if (PsiUtil.isConstantExpression(expression)) {
|
||||
|
||||
+42
-48
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,8 +36,7 @@ public class StringEqualsEmptyStringInspection extends BaseInspection {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"string.equals.empty.string.display.name");
|
||||
return InspectionGadgetsBundle.message("string.equals.empty.string.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,8 +56,7 @@ public class StringEqualsEmptyStringInspection extends BaseInspection {
|
||||
return new StringEqualsEmptyStringFix(useIsEmpty);
|
||||
}
|
||||
|
||||
private static class StringEqualsEmptyStringFix
|
||||
extends InspectionGadgetsFix {
|
||||
private static class StringEqualsEmptyStringFix extends InspectionGadgetsFix {
|
||||
|
||||
private final boolean useIsEmpty;
|
||||
|
||||
@@ -69,27 +67,21 @@ public class StringEqualsEmptyStringInspection extends BaseInspection {
|
||||
@NotNull
|
||||
public String getName() {
|
||||
if (useIsEmpty) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"string.equals.empty.string.replace.quickfix2");
|
||||
return InspectionGadgetsBundle.message("string.equals.empty.string.isempty.quickfix");
|
||||
}
|
||||
else {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"string.equals.empty.string.replace.quickfix");
|
||||
return InspectionGadgetsBundle.message("string.equals.empty.string.quickfix");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
final PsiIdentifier name =
|
||||
(PsiIdentifier)descriptor.getPsiElement();
|
||||
final PsiReferenceExpression expression =
|
||||
(PsiReferenceExpression)name.getParent();
|
||||
public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
|
||||
final PsiIdentifier name = (PsiIdentifier)descriptor.getPsiElement();
|
||||
final PsiReferenceExpression expression = (PsiReferenceExpression)name.getParent();
|
||||
if (expression == null) {
|
||||
return;
|
||||
}
|
||||
final PsiMethodCallExpression call =
|
||||
(PsiMethodCallExpression)expression.getParent();
|
||||
final PsiMethodCallExpression call = (PsiMethodCallExpression)expression.getParent();
|
||||
final PsiExpressionList argumentList = call.getArgumentList();
|
||||
final PsiExpression[] arguments = argumentList.getExpressions();
|
||||
if (arguments.length == 0) {
|
||||
@@ -98,42 +90,55 @@ public class StringEqualsEmptyStringInspection extends BaseInspection {
|
||||
final PsiExpression qualifier = expression.getQualifierExpression();
|
||||
final PsiExpression argument = arguments[0];
|
||||
final String variableText;
|
||||
final boolean addNullCheck;
|
||||
if (ExpressionUtils.isEmptyStringLiteral(argument)) {
|
||||
variableText = getRemainingText(qualifier);
|
||||
addNullCheck = false;
|
||||
}
|
||||
else {
|
||||
variableText = getRemainingText(argument);
|
||||
addNullCheck = true;
|
||||
}
|
||||
StringBuilder newExpression;
|
||||
if (addNullCheck) {
|
||||
newExpression = new StringBuilder(variableText);
|
||||
newExpression.append("!=null&&");
|
||||
} else {
|
||||
newExpression = new StringBuilder("");
|
||||
}
|
||||
final PsiElement parent = call.getParent();
|
||||
final PsiExpression expressionToReplace;
|
||||
if (parent instanceof PsiExpression) {
|
||||
final PsiExpression parentExpression = (PsiExpression)parent;
|
||||
if (BoolUtils.isNegation(parentExpression)) {
|
||||
expressionToReplace = parentExpression;
|
||||
if (useIsEmpty) {
|
||||
replaceExpression(parentExpression,
|
||||
'!' + variableText + ".isEmpty()");
|
||||
newExpression.append('!').append(variableText).append(".isEmpty()");
|
||||
}
|
||||
else {
|
||||
replaceExpression(parentExpression,
|
||||
variableText + ".length()!=0");
|
||||
newExpression.append(variableText).append(".length()!=0");
|
||||
}
|
||||
}
|
||||
else {
|
||||
expressionToReplace = call;
|
||||
if (useIsEmpty) {
|
||||
replaceExpression(call, variableText + ".isEmpty()");
|
||||
newExpression.append(variableText).append(".isEmpty()");
|
||||
}
|
||||
else {
|
||||
replaceExpression(call, variableText + ".length()==0");
|
||||
newExpression.append(variableText).append(".length()==0");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
expressionToReplace = call;
|
||||
if (useIsEmpty) {
|
||||
replaceExpression(call, variableText + ".isEmpty()");
|
||||
newExpression.append(variableText).append(".isEmpty()");
|
||||
}
|
||||
else {
|
||||
replaceExpression(call, variableText + ".length()==0");
|
||||
newExpression.append(variableText).append(".length()==0");
|
||||
}
|
||||
}
|
||||
replaceExpression(expressionToReplace, newExpression.toString());
|
||||
}
|
||||
|
||||
private String getRemainingText(PsiExpression expression) {
|
||||
@@ -143,22 +148,16 @@ public class StringEqualsEmptyStringInspection extends BaseInspection {
|
||||
}
|
||||
// to replace stringBuffer.toString().equals("") with
|
||||
// stringBuffer.length() == 0
|
||||
final PsiMethodCallExpression callExpression =
|
||||
(PsiMethodCallExpression)expression;
|
||||
final PsiReferenceExpression methodExpression =
|
||||
callExpression.getMethodExpression();
|
||||
final String referenceName =
|
||||
methodExpression.getReferenceName();
|
||||
final PsiExpression qualifierExpression =
|
||||
methodExpression.getQualifierExpression();
|
||||
final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)expression;
|
||||
final PsiReferenceExpression methodExpression = callExpression.getMethodExpression();
|
||||
final String referenceName = methodExpression.getReferenceName();
|
||||
final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
|
||||
if (qualifierExpression == null) {
|
||||
return expression.getText();
|
||||
}
|
||||
final PsiType type = qualifierExpression.getType();
|
||||
if (HardcodedMethodConstants.TO_STRING.equals(referenceName) &&
|
||||
type != null && (type.equalsToText(
|
||||
CommonClassNames.JAVA_LANG_STRING_BUFFER) ||
|
||||
type.equalsToText(CommonClassNames.JAVA_LANG_STRING_BUILDER))) {
|
||||
if (HardcodedMethodConstants.TO_STRING.equals(referenceName) && type != null && (type.equalsToText(
|
||||
CommonClassNames.JAVA_LANG_STRING_BUFFER) || type.equalsToText(CommonClassNames.JAVA_LANG_STRING_BUILDER))) {
|
||||
return qualifierExpression.getText();
|
||||
}
|
||||
else {
|
||||
@@ -172,17 +171,13 @@ public class StringEqualsEmptyStringInspection extends BaseInspection {
|
||||
return new StringEqualsEmptyStringVisitor();
|
||||
}
|
||||
|
||||
private static class StringEqualsEmptyStringVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
private static class StringEqualsEmptyStringVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitMethodCallExpression(
|
||||
@NotNull PsiMethodCallExpression call) {
|
||||
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
|
||||
super.visitMethodCallExpression(call);
|
||||
final PsiReferenceExpression methodExpression =
|
||||
call.getMethodExpression();
|
||||
@NonNls final String methodName =
|
||||
methodExpression.getReferenceName();
|
||||
final PsiReferenceExpression methodExpression = call.getMethodExpression();
|
||||
@NonNls final String methodName = methodExpression.getReferenceName();
|
||||
if (!"equals".equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
@@ -194,13 +189,12 @@ public class StringEqualsEmptyStringInspection extends BaseInspection {
|
||||
final PsiElement context = call.getParent();
|
||||
final boolean useIsEmpty = PsiUtil.isLanguageLevel6OrHigher(call);
|
||||
if (!useIsEmpty && context instanceof PsiExpressionStatement) {
|
||||
//cheesy, but necessary, because otherwise the quickfix will
|
||||
// cheesy, but necessary, because otherwise the quickfix will
|
||||
// produce uncompilable code (out of merely incorrect code).
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiExpression qualifier =
|
||||
methodExpression.getQualifierExpression();
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
final PsiExpression argument = arguments[0];
|
||||
if (ExpressionUtils.isEmptyStringLiteral(qualifier)) {
|
||||
final PsiType type = argument.getType();
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package com.siyeh.igfixes.performance.replace_with_isempty;
|
||||
|
||||
public class NullCheck {
|
||||
|
||||
void foo(String s) {
|
||||
if (s != null && s.isEmpty()) {}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package com.siyeh.igfixes.performance.replace_with_isempty;
|
||||
|
||||
public class NullCheck {
|
||||
|
||||
void foo(String s) {
|
||||
if ("".eq<caret>uals(s)) {}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.siyeh.igfixes.performance.replace_with_isempty;
|
||||
|
||||
public class Simple {
|
||||
|
||||
void foo(String s) {
|
||||
if (s.isEmpty()) {}
|
||||
}
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.siyeh.igfixes.performance.replace_with_isempty;
|
||||
|
||||
public class Simple {
|
||||
|
||||
void foo(String s) {
|
||||
if (s.eq<caret>uals("")) {}
|
||||
}
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.siyeh.igtest.performance.string_concatenation_inside_string_buffer_append;
|
||||
|
||||
public class StringConcatenationInsideStringBufferAppend {
|
||||
|
||||
private String s;
|
||||
|
||||
void foo(StringBuffer buffer) {
|
||||
buffer.append("asdf" + s + "asdf");
|
||||
buffer.append("asdf" + s);
|
||||
buffer.append("asdf" + "asdf");
|
||||
}
|
||||
|
||||
void bar(StringBuilder builder) {
|
||||
builder.append("asdf" + s + "asdf");
|
||||
builder.append("asdf" + s);
|
||||
builder.append("asdf" + "asdf");
|
||||
}
|
||||
|
||||
/*
|
||||
// java.lang.Appendable not in mock jdk
|
||||
void appendable(Appendable appendable) throws IOException {
|
||||
appendable.append("asdf" + s);
|
||||
appendable.append((s + "asdf"));
|
||||
}
|
||||
*/
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>StringConcatenationInsideStringBufferAppend.java</file>
|
||||
<line>10</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">String concatenation as argument to 'StringBuffer.append()' call</problem_class>
|
||||
<description>String concatenation as argument to <code>StringBuffer.append()</code> call #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>StringConcatenationInsideStringBufferAppend.java</file>
|
||||
<line>11</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">String concatenation as argument to 'StringBuffer.append()' call</problem_class>
|
||||
<description>String concatenation as argument to <code>StringBuffer.append()</code> call #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>StringConcatenationInsideStringBufferAppend.java</file>
|
||||
<line>16</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">String concatenation as argument to 'StringBuffer.append()' call</problem_class>
|
||||
<description>String concatenation as argument to <code>StringBuilder.append()</code> call #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>StringConcatenationInsideStringBufferAppend.java</file>
|
||||
<line>17</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">String concatenation as argument to 'StringBuffer.append()' call</problem_class>
|
||||
<description>String concatenation as argument to <code>StringBuilder.append()</code> call #loc</description>
|
||||
</problem>
|
||||
|
||||
</problems>
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012 Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ig.fixes.performance;
|
||||
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.IGQuickFixesTestCase;
|
||||
import com.siyeh.ig.performance.StringEqualsEmptyStringInspection;
|
||||
|
||||
public class StringEqualsEmptyStringFixTest extends IGQuickFixesTestCase {
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFixture.enableInspections(new StringEqualsEmptyStringInspection());
|
||||
myRelativePath = "performance/replace_with_isempty";
|
||||
myDefaultHint = InspectionGadgetsBundle.message("string.equals.empty.string.isempty.quickfix");
|
||||
}
|
||||
|
||||
public void testSimple() { doTest(); }
|
||||
public void testNullCheck() { doTest(); }
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.siyeh.ig.performance;
|
||||
|
||||
import com.siyeh.ig.IGInspectionTestCase;
|
||||
|
||||
public class StringConcatenationInsideStringBufferAppendInspectionTest extends IGInspectionTestCase {
|
||||
|
||||
public void test() throws Exception {
|
||||
doTest("com/siyeh/igtest/performance/string_concatenation_inside_string_buffer_append",
|
||||
new StringConcatenationInsideStringBufferAppendInspection());
|
||||
}
|
||||
}
|
||||
-1
@@ -28,7 +28,6 @@ import com.intellij.designer.DesignerToolWindowManager;
|
||||
import com.intellij.designer.componentTree.TreeComponentDecorator;
|
||||
import com.intellij.designer.designSurface.*;
|
||||
import com.intellij.designer.designSurface.selection.DirectionResizePoint;
|
||||
import com.intellij.designer.designSurface.selection.NonResizeSelectionDecorator;
|
||||
import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator;
|
||||
import com.intellij.designer.designSurface.tools.ComponentCreationFactory;
|
||||
import com.intellij.designer.designSurface.tools.CreationTool;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package org.jetbrains.android;
|
||||
|
||||
import com.intellij.openapi.components.ApplicationComponent;
|
||||
import org.jetbrains.android.sdk.AndroidSdk;
|
||||
import org.jetbrains.android.sdk.AndroidSdkData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -33,6 +33,6 @@ public class AndroidPlugin implements ApplicationComponent {
|
||||
}
|
||||
|
||||
public void disposeComponent() {
|
||||
AndroidSdk.terminateDdmlib();
|
||||
AndroidSdkData.terminateDdmlib();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.logcat.AndroidLogcatToolWindowFactory;
|
||||
import org.jetbrains.android.sdk.AndroidSdk;
|
||||
import org.jetbrains.android.sdk.AndroidSdkData;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -72,7 +72,7 @@ public class AndroidEnableDdmsAction extends ToggleAction {
|
||||
hidden = true;
|
||||
toolWindow.hide(null);
|
||||
}
|
||||
AndroidSdk.terminateDdmlib();
|
||||
AndroidSdkData.terminateDdmlib();
|
||||
if (hidden) {
|
||||
toolWindow.show(null);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.sdk.AndroidSdk;
|
||||
import org.jetbrains.android.sdk.AndroidSdkData;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -39,9 +39,9 @@ public abstract class AndroidRunSdkToolAction extends AnAction {
|
||||
assert facets.size() > 0;
|
||||
Set<String> sdkSet = new HashSet<String>();
|
||||
for (AndroidFacet facet : facets) {
|
||||
AndroidSdk sdk = facet.getConfiguration().getAndroidSdk();
|
||||
if (sdk != null) {
|
||||
sdkSet.add(sdk.getLocation());
|
||||
AndroidSdkData sdkData = facet.getConfiguration().getAndroidSdk();
|
||||
if (sdkData != null) {
|
||||
sdkSet.add(sdkData.getLocation());
|
||||
}
|
||||
}
|
||||
if (sdkSet.size() == 0) {
|
||||
|
||||
@@ -223,7 +223,7 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler {
|
||||
}
|
||||
|
||||
final IAndroidTarget target = platform.getTarget();
|
||||
final int platformToolsRevision = platform.getSdk().getPlatformToolsRevision();
|
||||
final int platformToolsRevision = platform.getSdkData().getPlatformToolsRevision();
|
||||
|
||||
String[] resPaths = AndroidCompileUtil.collectResourceDirs(facet, false, myContext);
|
||||
if (resPaths.length <= 0) {
|
||||
|
||||
@@ -94,7 +94,7 @@ public class AndroidAutogenerator {
|
||||
}
|
||||
|
||||
final IAndroidTarget target = platform.getTarget();
|
||||
final int platformToolsRevision = platform.getSdk().getPlatformToolsRevision();
|
||||
final int platformToolsRevision = platform.getSdkData().getPlatformToolsRevision();
|
||||
final String[] resPaths = AndroidCompileUtil.collectResourceDirs(facet, false, context);
|
||||
|
||||
if (resPaths.length == 0) {
|
||||
@@ -419,7 +419,7 @@ public class AndroidAutogenerator {
|
||||
}
|
||||
|
||||
final IAndroidTarget target = platform.getTarget();
|
||||
final String sdkLocation = platform.getSdk().getLocation();
|
||||
final String sdkLocation = platform.getSdkData().getLocation();
|
||||
|
||||
final String packageName = AndroidUtils.computePackageName(module, file);
|
||||
if (packageName == null) {
|
||||
|
||||
@@ -530,7 +530,7 @@ public class AndroidCompileUtil {
|
||||
|
||||
if (collectResCacheDirs) {
|
||||
final AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform();
|
||||
final int platformToolsRevision = platform != null ? platform.getSdk().getPlatformToolsRevision() : -1;
|
||||
final int platformToolsRevision = platform != null ? platform.getSdkData().getPlatformToolsRevision() : -1;
|
||||
|
||||
if (platformToolsRevision < 0 || platformToolsRevision > 7) {
|
||||
// png cache is supported since platform-tools-r8
|
||||
|
||||
@@ -93,7 +93,7 @@ public class AndroidIncludingCompiler implements SourceGeneratingCompiler {
|
||||
for (AndroidFacet depFacet : AndroidSdkUtils.getAllAndroidDependencies(module, true)) {
|
||||
final AndroidPlatform platform = depFacet.getConfiguration().getAndroidPlatform();
|
||||
|
||||
final int platformToolsRevision = platform != null ? platform.getSdk().getPlatformToolsRevision() : -1;
|
||||
final int platformToolsRevision = platform != null ? platform.getSdkData().getPlatformToolsRevision() : -1;
|
||||
if (platformToolsRevision < 0 || platformToolsRevision > 7) {
|
||||
// "including" style building of library projects is deprecated since platform-tools-r8
|
||||
continue;
|
||||
|
||||
@@ -126,7 +126,7 @@ public class AndroidPackagingCompiler implements PackagingCompiler {
|
||||
AndroidBundle.message("android.compilation.error.specify.platform", module.getName()), null, -1, -1);
|
||||
continue;
|
||||
}
|
||||
String sdkPath = platform.getSdk().getLocation();
|
||||
String sdkPath = platform.getSdkData().getLocation();
|
||||
String outputPath = AndroidRootUtil.getApkPath(facet);
|
||||
if (outputPath == null) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR,
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class AndroidPngFilesCachingCompiler implements SourceGeneratingCompiler
|
||||
continue;
|
||||
}
|
||||
|
||||
final int platformToolsRevision = platform.getSdk().getPlatformToolsRevision();
|
||||
final int platformToolsRevision = platform.getSdkData().getPlatformToolsRevision();
|
||||
if (platformToolsRevision > 0 && platformToolsRevision <= 7) {
|
||||
// png files cache is supported since platform-tools-r8
|
||||
continue;
|
||||
|
||||
@@ -81,7 +81,7 @@ public class AndroidPrecompileTask implements CompileTask {
|
||||
}
|
||||
|
||||
final AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform();
|
||||
final int platformToolsRevision = platform != null ? platform.getSdk().getPlatformToolsRevision() : -1;
|
||||
final int platformToolsRevision = platform != null ? platform.getSdkData().getPlatformToolsRevision() : -1;
|
||||
|
||||
LOG.debug("Platform-tools revision for module " + module.getName() + " is " + platformToolsRevision);
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ public class AndroidProguardCompiler implements ClassPostProcessingCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
final String sdkPath = FileUtil.toSystemDependentName(platform.getSdk().getLocation());
|
||||
final String sdkPath = FileUtil.toSystemDependentName(platform.getSdkData().getLocation());
|
||||
|
||||
final VirtualFile outputDir = AndroidDexCompiler.getOutputDirectoryForDex(module);
|
||||
final String outputJarOsPath = FileUtil.toSystemDependentName(outputDir.getPath() + '/' + PROGUARD_OUTPUT_JAR_NAME);
|
||||
|
||||
@@ -87,7 +87,7 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
|
||||
}
|
||||
|
||||
final IAndroidTarget target = platform.getTarget();
|
||||
final String sdkLocation = platform.getSdk().getLocation();
|
||||
final String sdkLocation = platform.getSdkData().getLocation();
|
||||
|
||||
final String resourceDirPath = AndroidRootUtil.getResourceDirPath(facet);
|
||||
assert resourceDirPath != null;
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ public class AndroidResourcesPackagingCompiler implements ClassPostProcessingCom
|
||||
String assetsDirPath = assetsDir != null ? assetsDir.getPath() : null;
|
||||
String[] resourcesDirPaths = AndroidCompileUtil.collectResourceDirs(facet, true, context);
|
||||
final IAndroidTarget target = platform.getTarget();
|
||||
final int platformToolsRevision = platform.getSdk().getPlatformToolsRevision();
|
||||
final int platformToolsRevision = platform.getSdkData().getPlatformToolsRevision();
|
||||
|
||||
if (resourcesDirPaths.length == 0) {
|
||||
context.addMessage(CompilerMessageCategory.WARNING, "Resource directory not found for module " + module.getName(),
|
||||
|
||||
@@ -419,7 +419,7 @@ public class AndroidApkBuilder {
|
||||
}
|
||||
|
||||
// we exclude sources of library modules automatically for tools r7 or previous
|
||||
return platform.getSdk().getPlatformToolsRevision() > 7;
|
||||
return platform.getSdkData().getPlatformToolsRevision() > 7;
|
||||
}
|
||||
|
||||
private static void writeStandardSourceFolderResources(Collection<VirtualFile> resources,
|
||||
|
||||
@@ -71,10 +71,10 @@ public class AndroidModuleConverter1 extends ConversionProcessor<ModuleSettings>
|
||||
|
||||
if (androidPlatform != null) {
|
||||
|
||||
Sdk androidSdk = AndroidSdkUtils.findAppropriateAndroidPlatform(androidPlatform.getTarget(), androidPlatform.getSdk());
|
||||
Sdk androidSdk = AndroidSdkUtils.findAppropriateAndroidPlatform(androidPlatform.getTarget(), androidPlatform.getSdkData());
|
||||
|
||||
if (androidSdk == null) {
|
||||
androidSdk = AndroidSdkUtils.createNewAndroidPlatform(androidPlatform.getTarget(), androidPlatform.getSdk().getLocation(), false);
|
||||
androidSdk = AndroidSdkUtils.createNewAndroidPlatform(androidPlatform.getTarget(), androidPlatform.getSdkData().getLocation(), false);
|
||||
final SdkModificator modificator = androidSdk.getSdkModificator();
|
||||
|
||||
for (OrderRootType type : OrderRootType.getAllTypes()) {
|
||||
|
||||
@@ -195,7 +195,7 @@ class ApkStep extends ExportSignedPackageWizardStep {
|
||||
private void createAndAlignApk(final String apkPath) {
|
||||
AndroidPlatform platform = myWizard.getFacet().getConfiguration().getAndroidPlatform();
|
||||
assert platform != null;
|
||||
String sdkPath = platform.getSdk().getLocation();
|
||||
String sdkPath = platform.getSdkData().getLocation();
|
||||
String zipAlignPath = sdkPath + File.separatorChar + AndroidSdkUtils.toolPath(SdkConstants.FN_ZIPALIGN);
|
||||
File zipalign = new File(zipAlignPath);
|
||||
final boolean runZipAlign = zipalign.isFile();
|
||||
|
||||
@@ -211,7 +211,7 @@ public class AndroidFacet extends Facet<AndroidFacetConfiguration> {
|
||||
public AndroidDebugBridge getDebugBridge() {
|
||||
AndroidPlatform platform = getConfiguration().getAndroidPlatform();
|
||||
if (platform != null) {
|
||||
return platform.getSdk().getDebugBridge(getModule().getProject());
|
||||
return platform.getSdkData().getDebugBridge(getModule().getProject());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -376,10 +376,10 @@ public class AndroidFacet extends Facet<AndroidFacetConfiguration> {
|
||||
public AvdManager getAvdManager() throws AvdsNotSupportedException, AndroidLocation.AndroidLocationException {
|
||||
if (myAvdManager == null) {
|
||||
AndroidPlatform platform = getConfiguration().getAndroidPlatform();
|
||||
AndroidSdk sdk = platform != null ? platform.getSdk() : null;
|
||||
AndroidSdkData sdkData = platform != null ? platform.getSdkData() : null;
|
||||
Project project = getModule().getProject();
|
||||
if (sdk != null) {
|
||||
SdkManager sdkManager = sdk.getSdkManager();
|
||||
if (sdkData != null) {
|
||||
SdkManager sdkManager = sdkData.getSdkManager();
|
||||
myAvdManager = new AvdManager(sdkManager, AndroidSdkUtils.getSdkLog(project));
|
||||
}
|
||||
else {
|
||||
@@ -392,7 +392,7 @@ public class AndroidFacet extends Facet<AndroidFacetConfiguration> {
|
||||
public void launchEmulator(@Nullable final String avdName, @NotNull final String commands, @Nullable ProcessHandler handler) {
|
||||
AndroidPlatform platform = getConfiguration().getAndroidPlatform();
|
||||
if (platform != null) {
|
||||
final String emulatorPath = platform.getSdk().getLocation() + File.separator + AndroidSdkUtils.toolPath(SdkConstants.FN_EMULATOR);
|
||||
final String emulatorPath = platform.getSdkData().getLocation() + File.separator + AndroidSdkUtils.toolPath(SdkConstants.FN_EMULATOR);
|
||||
final GeneralCommandLine commandLine = new GeneralCommandLine();
|
||||
commandLine.setExePath(FileUtil.toSystemDependentName(emulatorPath));
|
||||
if (avdName != null) {
|
||||
|
||||
@@ -31,7 +31,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.android.sdk.AndroidPlatform;
|
||||
import org.jetbrains.android.sdk.AndroidSdk;
|
||||
import org.jetbrains.android.sdk.AndroidSdkData;
|
||||
import org.jetbrains.android.sdk.AndroidSdkAdditionalData;
|
||||
import org.jetbrains.android.sdk.AndroidSdkType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -122,9 +122,9 @@ public class AndroidFacetConfiguration implements FacetConfiguration {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AndroidSdk getAndroidSdk() {
|
||||
public AndroidSdkData getAndroidSdk() {
|
||||
AndroidPlatform platform = getAndroidPlatform();
|
||||
return platform != null ? platform.getSdk() : null;
|
||||
return platform != null ? platform.getSdkData() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -409,7 +409,7 @@ public abstract class AndroidLogcatToolWindowView implements Disposable {
|
||||
private void updateDevices() {
|
||||
AndroidPlatform platform = getAndroidPlatform(myProject);
|
||||
if (platform != null) {
|
||||
final AndroidDebugBridge debugBridge = platform.getSdk().getDebugBridge(myProject);
|
||||
final AndroidDebugBridge debugBridge = platform.getSdkData().getDebugBridge(myProject);
|
||||
if (debugBridge != null) {
|
||||
IDevice[] devices = debugBridge.getDevices();
|
||||
Object temp = myDeviceCombo.getSelectedItem();
|
||||
|
||||
@@ -618,11 +618,11 @@ public abstract class AndroidFacetImporterBase extends FacetImporter<AndroidFace
|
||||
return null;
|
||||
}
|
||||
|
||||
AndroidSdk sdk = AndroidSdk.parse(sdkPath, new EmptySdkLog());
|
||||
if (sdk != null) {
|
||||
IAndroidTarget target = sdk.findTargetByApiLevel(apiLevel);
|
||||
AndroidSdkData sdkData = AndroidSdkData.parse(sdkPath, new EmptySdkLog());
|
||||
if (sdkData != null) {
|
||||
IAndroidTarget target = sdkData.findTargetByApiLevel(apiLevel);
|
||||
if (target != null) {
|
||||
Sdk library = AndroidSdkUtils.findAppropriateAndroidPlatform(target, sdk);
|
||||
Sdk library = AndroidSdkUtils.findAppropriateAndroidPlatform(target, sdkData);
|
||||
if (library == null) {
|
||||
library = AndroidSdkUtils.createNewAndroidPlatform(target, sdkPath, true);
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ public class AndroidModuleBuilder extends JavaModuleBuilder {
|
||||
IAndroidTarget target = platform.getTarget();
|
||||
|
||||
final String androidToolPath =
|
||||
platform.getSdk().getLocation() + File.separator + AndroidSdkUtils.toolPath(SdkConstants.androidCmdName());
|
||||
platform.getSdkData().getLocation() + File.separator + AndroidSdkUtils.toolPath(SdkConstants.androidCmdName());
|
||||
|
||||
if (!new File(androidToolPath).exists()) {
|
||||
return false;
|
||||
|
||||
@@ -167,7 +167,7 @@ public class AndroidModuleWizardStep extends ModuleWizardStep {
|
||||
return;
|
||||
}
|
||||
|
||||
RunAndroidAvdManagerAction.runAvdManager(platform.getSdk().getLocation());
|
||||
RunAndroidAvdManagerAction.runAvdManager(platform.getSdkData().getLocation());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -390,8 +390,8 @@ public class AndroidModuleWizardStep extends ModuleWizardStep {
|
||||
|
||||
@NotNull
|
||||
private static String[] getAvds(@NotNull AndroidPlatform androidPlatform) {
|
||||
final AndroidSdk sdkObject = androidPlatform.getSdk();
|
||||
final SdkManager sdkManager = sdkObject.getSdkManager();
|
||||
final AndroidSdkData sdkData = androidPlatform.getSdkData();
|
||||
final SdkManager sdkManager = sdkData.getSdkManager();
|
||||
try {
|
||||
final AvdManager avdManager = new AvdManager(sdkManager, new MessageBuildingSdkLog());
|
||||
final AvdInfo[] validAvds = avdManager.getValidAvds();
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ public class SystemResourceManager extends ResourceManager {
|
||||
|
||||
@Nullable
|
||||
public synchronized AttributeDefinitions getAttributeDefinitions() {
|
||||
final AndroidTargetData targetData = myPlatform.getSdk().getTargetData(myPlatform.getTarget());
|
||||
final AndroidTargetData targetData = myPlatform.getSdkData().getTargetData(myPlatform.getTarget());
|
||||
return targetData != null ? targetData.getAttrDefs(myModule.getProject()) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ public abstract class AndroidRunConfigurationBase extends ModuleBasedConfigurati
|
||||
return null;
|
||||
}
|
||||
|
||||
if (platform.getSdk().getDebugBridge(getProject()) == null) return null;
|
||||
if (platform.getSdkData().getDebugBridge(getProject()) == null) return null;
|
||||
|
||||
boolean debug = DefaultDebugExecutor.EXECUTOR_ID.equals(executor.getId());
|
||||
if (debug) {
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.sdk.AndroidSdk;
|
||||
import org.jetbrains.android.sdk.AndroidSdkData;
|
||||
import org.jetbrains.android.sdk.AndroidSdkUtils;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
@@ -68,10 +68,10 @@ public class AvdChooser extends DialogWrapper {
|
||||
|
||||
@Nullable
|
||||
private static String getAndroidToolPath(@NotNull AndroidFacet facet) {
|
||||
AndroidSdk sdk = facet.getConfiguration().getAndroidSdk();
|
||||
if (sdk == null) return null;
|
||||
AndroidSdkData sdkData = facet.getConfiguration().getAndroidSdk();
|
||||
if (sdkData == null) return null;
|
||||
String androidCmd = SdkConstants.androidCmdName();
|
||||
return sdk.getLocation() + File.separator + AndroidSdkUtils.toolPath(androidCmd);
|
||||
return sdkData.getLocation() + File.separator + AndroidSdkUtils.toolPath(androidCmd);
|
||||
}
|
||||
|
||||
public AvdChooser(@NotNull final Project project,
|
||||
|
||||
@@ -60,7 +60,7 @@ public abstract class AvdComboBox extends ComboboxWithBrowseButton {
|
||||
return;
|
||||
}
|
||||
|
||||
RunAndroidAvdManagerAction.runAvdManager(platform.getSdk().getLocation());
|
||||
RunAndroidAvdManagerAction.runAvdManager(platform.getSdkData().getLocation());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.ui.CollectionComboBoxModel;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.sdk.AndroidSdk;
|
||||
import org.jetbrains.android.sdk.AndroidSdkData;
|
||||
import org.jetbrains.android.sdk.AndroidSdkUtils;
|
||||
import org.jetbrains.android.sdk.MessageBuildingSdkLog;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
@@ -163,9 +163,9 @@ public class CreateAvdDialog extends DialogWrapper {
|
||||
setTitle(AndroidBundle.message("create.avd.dialog.title"));
|
||||
init();
|
||||
myAvdManager = manager;
|
||||
final AndroidSdk sdk = facet.getConfiguration().getAndroidSdk();
|
||||
assert sdk != null;
|
||||
IAndroidTarget[] targets = sdk.getTargets();
|
||||
final AndroidSdkData sdkData = facet.getConfiguration().getAndroidSdk();
|
||||
assert sdkData != null;
|
||||
IAndroidTarget[] targets = sdkData.getTargets();
|
||||
myTargetBox.setModel(new DefaultComboBoxModel(targets));
|
||||
myTargetBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
@@ -41,11 +41,11 @@ import java.util.Set;
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public class AndroidPlatform {
|
||||
private final AndroidSdk mySdk;
|
||||
private final AndroidSdkData mySdkData;
|
||||
private final IAndroidTarget myTarget;
|
||||
|
||||
public AndroidPlatform(@NotNull AndroidSdk sdk, @NotNull IAndroidTarget target) {
|
||||
mySdk = sdk;
|
||||
public AndroidPlatform(@NotNull AndroidSdkData sdkData, @NotNull IAndroidTarget target) {
|
||||
mySdkData = sdkData;
|
||||
myTarget = target;
|
||||
}
|
||||
|
||||
@@ -64,8 +64,8 @@ public class AndroidPlatform {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public AndroidSdk getSdk() {
|
||||
return mySdk;
|
||||
public AndroidSdkData getSdkData() {
|
||||
return mySdkData;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -80,12 +80,12 @@ public class AndroidPlatform {
|
||||
}
|
||||
String sdkPath = sdk.getHomePath();
|
||||
if (sdkPath != null) {
|
||||
AndroidSdk sdkObject = AndroidSdk.parse(sdkPath, new EmptySdkLog());
|
||||
if (sdkObject != null) {
|
||||
AndroidSdkData sdkData = AndroidSdkData.parse(sdkPath, new EmptySdkLog());
|
||||
if (sdkData != null) {
|
||||
AndroidSdkAdditionalData data = (AndroidSdkAdditionalData)sdk.getSdkAdditionalData();
|
||||
IAndroidTarget target = data != null ? data.getBuildTarget(sdkObject) : null;
|
||||
IAndroidTarget target = data != null ? data.getBuildTarget(sdkData) : null;
|
||||
if (target != null) {
|
||||
return new AndroidPlatform(sdkObject, target);
|
||||
return new AndroidPlatform(sdkData, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class AndroidPlatform {
|
||||
@Deprecated
|
||||
public static AndroidPlatform parse(@NotNull Library library,
|
||||
@Nullable Library.ModifiableModel model,
|
||||
@Nullable Map<String, AndroidSdk> parsedSdks) {
|
||||
@Nullable Map<String, AndroidSdkData> parsedSdks) {
|
||||
VirtualFile[] files = model != null ? model.getFiles(OrderRootType.CLASSES) : library.getFiles(OrderRootType.CLASSES);
|
||||
Set<String> jarPaths = new HashSet<String>();
|
||||
VirtualFile frameworkLibrary = null;
|
||||
@@ -119,16 +119,16 @@ public class AndroidPlatform {
|
||||
if (sdkDir == null) return null;
|
||||
}
|
||||
String sdkPath = sdkDir.getPath();
|
||||
AndroidSdk sdk = parsedSdks != null ? parsedSdks.get(sdkPath) : null;
|
||||
if (sdk == null) {
|
||||
sdk = AndroidSdk.parse(sdkPath, new EmptySdkLog());
|
||||
if (sdk == null) return null;
|
||||
AndroidSdkData sdkData = parsedSdks != null ? parsedSdks.get(sdkPath) : null;
|
||||
if (sdkData == null) {
|
||||
sdkData = AndroidSdkData.parse(sdkPath, new EmptySdkLog());
|
||||
if (sdkData == null) return null;
|
||||
if (parsedSdks != null) {
|
||||
parsedSdks.put(sdkPath, sdk);
|
||||
parsedSdks.put(sdkPath, sdkData);
|
||||
}
|
||||
}
|
||||
IAndroidTarget resultTarget = null;
|
||||
for (IAndroidTarget target : sdk.getTargets()) {
|
||||
for (IAndroidTarget target : sdkData.getTargets()) {
|
||||
String targetsFrameworkLibPath = PathUtil.getCanonicalPath(target.getPath(IAndroidTarget.ANDROID_JAR));
|
||||
if (frameworkLibrary.getPath().equals(targetsFrameworkLibPath)) {
|
||||
if (target.isPlatform()) {
|
||||
@@ -153,7 +153,7 @@ public class AndroidPlatform {
|
||||
}
|
||||
}
|
||||
if (resultTarget != null) {
|
||||
return new AndroidPlatform(sdk, resultTarget);
|
||||
return new AndroidPlatform(sdkData, resultTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@ public class AndroidPlatform {
|
||||
|
||||
AndroidPlatform platform = (AndroidPlatform)o;
|
||||
|
||||
if (!mySdk.equals(platform.mySdk)) return false;
|
||||
if (!mySdkData.equals(platform.mySdkData)) return false;
|
||||
if (!myTarget.equals(platform.myTarget)) return false;
|
||||
|
||||
return true;
|
||||
@@ -175,7 +175,7 @@ public class AndroidPlatform {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = mySdk.hashCode();
|
||||
int result = mySdkData.hashCode();
|
||||
result = 31 * result + myTarget.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -109,8 +109,8 @@ public class AndroidSdkAdditionalData implements SdkAdditionalData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IAndroidTarget getBuildTarget(@NotNull AndroidSdk sdkObject) {
|
||||
return myBuildTarget != null ? sdkObject.findTargetByHashString(myBuildTarget) : null;
|
||||
public IAndroidTarget getBuildTarget(@NotNull AndroidSdkData sdkData) {
|
||||
return myBuildTarget != null ? sdkData.findTargetByHashString(myBuildTarget) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -106,7 +106,7 @@ public class AndroidSdkConfigurable implements AdditionalDataConfigurable {
|
||||
}
|
||||
final AndroidSdkAdditionalData androidData = (AndroidSdkAdditionalData)data;
|
||||
AndroidPlatform platform = androidData.getAndroidPlatform();
|
||||
myForm.init(androidData.getJavaSdk(), mySdk, platform != null ? androidData.getBuildTarget(platform.getSdk()) : null);
|
||||
myForm.init(androidData.getJavaSdk(), mySdk, platform != null ? androidData.getBuildTarget(platform.getSdkData()) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -134,8 +134,8 @@ class AndroidSdkConfigurableForm {
|
||||
}
|
||||
|
||||
mySdkLocation = androidSdk != null ? androidSdk.getHomePath() : null;
|
||||
AndroidSdk androidSdkObject = mySdkLocation != null ? AndroidSdk.parse(mySdkLocation, new EmptySdkLog()) : null;
|
||||
updateBuildTargets(androidSdkObject);
|
||||
AndroidSdkData androidSdkData = mySdkLocation != null ? AndroidSdkData.parse(mySdkLocation, new EmptySdkLog()) : null;
|
||||
updateBuildTargets(androidSdkData);
|
||||
|
||||
if (buildTarget != null) {
|
||||
for (int i = 0; i < myBuildTargetsModel.getSize(); i++) {
|
||||
@@ -157,11 +157,11 @@ class AndroidSdkConfigurableForm {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBuildTargets(AndroidSdk androidSdk) {
|
||||
private void updateBuildTargets(AndroidSdkData androidSdkData) {
|
||||
myBuildTargetsModel.removeAllElements();
|
||||
|
||||
if (androidSdk != null) {
|
||||
for (IAndroidTarget target : androidSdk.getTargets()) {
|
||||
if (androidSdkData != null) {
|
||||
for (IAndroidTarget target : androidSdkData.getTargets()) {
|
||||
myBuildTargetsModel.addElement(target);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -46,8 +46,8 @@ import java.util.Map;
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidSdk {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.sdk.AndroidSdk");
|
||||
public class AndroidSdkData {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.sdk.AndroidSdkData");
|
||||
|
||||
private static volatile boolean myDdmLibInitialized = false;
|
||||
|
||||
@@ -63,7 +63,7 @@ public class AndroidSdk {
|
||||
|
||||
private final int myPlatformToolsRevision;
|
||||
|
||||
public AndroidSdk(@NotNull SdkManager sdkManager, @NotNull String sdkDirOsPath) {
|
||||
public AndroidSdkData(@NotNull SdkManager sdkManager, @NotNull String sdkDirOsPath) {
|
||||
mySdkManager = sdkManager;
|
||||
|
||||
final File platformToolsPropFile =
|
||||
@@ -150,31 +150,31 @@ public class AndroidSdk {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AndroidSdk parse(@NotNull String path, @NotNull ISdkLog log) {
|
||||
public static AndroidSdkData parse(@NotNull String path, @NotNull ISdkLog log) {
|
||||
final SdkManager manager = AndroidCommonUtils.createSdkManager(path, log);
|
||||
return manager != null ? new AndroidSdk(manager, path) : null;
|
||||
return manager != null ? new AndroidSdkData(manager, path) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AndroidSdk parse(@NotNull String path, @NotNull final Component component) {
|
||||
public static AndroidSdkData parse(@NotNull String path, @NotNull final Component component) {
|
||||
MessageBuildingSdkLog log = new MessageBuildingSdkLog();
|
||||
AndroidSdk sdk = parse(path, log);
|
||||
if (sdk == null) {
|
||||
AndroidSdkData sdkData = parse(path, log);
|
||||
if (sdkData == null) {
|
||||
String message = log.getErrorMessage();
|
||||
if (message.length() > 0) {
|
||||
message = "Android SDK is parsed incorrectly. Parsing log:\n" + message;
|
||||
Messages.showInfoMessage(component, message, CommonBundle.getErrorTitle());
|
||||
}
|
||||
}
|
||||
return sdk;
|
||||
return sdkData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) return false;
|
||||
if (obj.getClass() != getClass()) return false;
|
||||
AndroidSdk sdk = (AndroidSdk)obj;
|
||||
return FileUtil.pathsEqual(getLocation(), sdk.getLocation());
|
||||
AndroidSdkData sdkData = (AndroidSdkData)obj;
|
||||
return FileUtil.pathsEqual(getLocation(), sdkData.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -114,15 +114,15 @@ public class AndroidSdkType extends SdkType implements JavaSdkType {
|
||||
final Sdk jdk = sdkModel.findSdk(name);
|
||||
|
||||
MessageBuildingSdkLog log = new MessageBuildingSdkLog();
|
||||
AndroidSdk sdkObject = AndroidSdk.parse(sdk.getHomePath(), log);
|
||||
AndroidSdkData sdkData = AndroidSdkData.parse(sdk.getHomePath(), log);
|
||||
|
||||
if (sdkObject == null) {
|
||||
if (sdkData == null) {
|
||||
String errorMessage = log.getErrorMessage().length() > 0 ? log.getErrorMessage() : AndroidBundle.message("cannot.parse.sdk.error");
|
||||
Messages.showErrorDialog(errorMessage, "SDK Parsing Error");
|
||||
return false;
|
||||
}
|
||||
|
||||
IAndroidTarget[] targets = sdkObject.getTargets();
|
||||
IAndroidTarget[] targets = sdkData.getTargets();
|
||||
|
||||
if (targets.length == 0) {
|
||||
Messages.showErrorDialog(AndroidBundle.message("no.android.targets.error"), CommonBundle.getErrorTitle());
|
||||
|
||||
@@ -257,7 +257,7 @@ public class AndroidSdkUtils {
|
||||
if (data != null) {
|
||||
final AndroidPlatform androidPlatform = data.getAndroidPlatform();
|
||||
if (androidPlatform != null) {
|
||||
result.add(FileUtil.toSystemIndependentName(androidPlatform.getSdk().getLocation()));
|
||||
result.add(FileUtil.toSystemIndependentName(androidPlatform.getSdkData().getLocation()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,7 +314,7 @@ public class AndroidSdkUtils {
|
||||
if (data != null) {
|
||||
final AndroidPlatform androidPlatform = data.getAndroidPlatform();
|
||||
if (androidPlatform != null) {
|
||||
final String baseDir = FileUtil.toSystemIndependentName(androidPlatform.getSdk().getLocation());
|
||||
final String baseDir = FileUtil.toSystemIndependentName(androidPlatform.getSdkData().getLocation());
|
||||
if ((sdkDir == null || FileUtil.pathsEqual(baseDir, sdkDir)) &&
|
||||
targetHashString.equals(androidPlatform.getTarget().hashString())) {
|
||||
return sdk;
|
||||
@@ -361,11 +361,11 @@ public class AndroidSdkUtils {
|
||||
}
|
||||
|
||||
private static boolean tryToCreateAndSetAndroidSdk(@NotNull Module module, @NotNull String baseDir, @NotNull String targetHashString) {
|
||||
final AndroidSdk sdkObject = AndroidSdk.parse(baseDir, new EmptySdkLog());
|
||||
if (sdkObject != null) {
|
||||
final IAndroidTarget target = sdkObject.findTargetByHashString(targetHashString);
|
||||
final AndroidSdkData sdkData = AndroidSdkData.parse(baseDir, new EmptySdkLog());
|
||||
if (sdkData != null) {
|
||||
final IAndroidTarget target = sdkData.findTargetByHashString(targetHashString);
|
||||
if (target != null) {
|
||||
final Sdk androidSdk = createNewAndroidPlatform(target, sdkObject.getLocation(), true);
|
||||
final Sdk androidSdk = createNewAndroidPlatform(target, sdkData.getLocation(), true);
|
||||
if (androidSdk != null) {
|
||||
setSdk(module, androidSdk);
|
||||
return true;
|
||||
@@ -428,18 +428,18 @@ public class AndroidSdkUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Sdk findAppropriateAndroidPlatform(@NotNull IAndroidTarget target, @NotNull AndroidSdk sdk) {
|
||||
public static Sdk findAppropriateAndroidPlatform(@NotNull IAndroidTarget target, @NotNull AndroidSdkData sdkData) {
|
||||
for (Sdk library : ProjectJdkTable.getInstance().getAllJdks()) {
|
||||
final String homePath = library.getHomePath();
|
||||
|
||||
if (homePath != null && library.getSdkType().equals(AndroidSdkType.getInstance())) {
|
||||
final AndroidSdk sdk1 = AndroidSdk.parse(homePath, new EmptySdkLog());
|
||||
final AndroidSdkData sdkData1 = AndroidSdkData.parse(homePath, new EmptySdkLog());
|
||||
|
||||
if (sdk1 != null && sdk1.equals(sdk)) {
|
||||
if (sdkData1 != null && sdkData1.equals(sdkData)) {
|
||||
final AndroidSdkAdditionalData data = (AndroidSdkAdditionalData)library.getSdkAdditionalData();
|
||||
|
||||
if (data != null) {
|
||||
final IAndroidTarget target1 = data.getBuildTarget(sdk1);
|
||||
final IAndroidTarget target1 = data.getBuildTarget(sdkData1);
|
||||
|
||||
if (target1 != null && target.hashString().equals(target1.hashString())) {
|
||||
return library;
|
||||
|
||||
@@ -33,15 +33,15 @@ import java.util.Set;
|
||||
public class AndroidTargetData {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.sdk.AndroidTargetData");
|
||||
|
||||
private final AndroidSdk mySdk;
|
||||
private final AndroidSdkData mySdkData;
|
||||
private final IAndroidTarget myTarget;
|
||||
|
||||
private volatile AttributeDefinitions myAttrDefs;
|
||||
private volatile RenderServiceFactory myRenderServiceFactory;
|
||||
private volatile Set<String> myThemes;
|
||||
|
||||
public AndroidTargetData(@NotNull AndroidSdk sdk, @NotNull IAndroidTarget target) {
|
||||
mySdk = sdk;
|
||||
public AndroidTargetData(@NotNull AndroidSdkData sdkData, @NotNull IAndroidTarget target) {
|
||||
mySdkData = sdkData;
|
||||
myTarget = target;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public class AndroidTargetData {
|
||||
if (myThemes == null) {
|
||||
myThemes = new HashSet<String>();
|
||||
final Module module = facet.getModule();
|
||||
final SystemResourceManager systemResourceManager = new SystemResourceManager(facet, new AndroidPlatform(mySdk, myTarget));
|
||||
final SystemResourceManager systemResourceManager = new SystemResourceManager(facet, new AndroidPlatform(mySdkData, myTarget));
|
||||
|
||||
for (VirtualFile valueResourceDir : systemResourceManager.getResourceSubdirs("values")) {
|
||||
for (final VirtualFile valueResourceFile : valueResourceDir.getChildren()) {
|
||||
|
||||
+90
-59
@@ -1,25 +1,27 @@
|
||||
package org.jetbrains.android.uipreview;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.ui.HyperlinkLabel;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.ui.AsyncProcessIcon;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.HyperlinkLabel;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.ui.AsyncProcessIcon;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
@@ -29,12 +31,11 @@ public class AndroidLayoutPreviewPanel extends JPanel implements Disposable {
|
||||
private static final double MAX_ZOOM_FACTOR = 2.0;
|
||||
private static final double ZOOM_STEP = 1.25;
|
||||
|
||||
private RenderingErrorMessage myErrorMessage;
|
||||
private String myWarnMessage;
|
||||
private FixableIssueMessage myErrorMessage;
|
||||
private List<FixableIssueMessage> myWarnMessages;
|
||||
private BufferedImage myImage;
|
||||
|
||||
private final HyperlinkLabel myHyperlinkMessageLabel = new HyperlinkLabel("", Color.BLUE, getBackground(), Color.BLUE);
|
||||
private final JBLabel myMessageLabel = new JBLabel();
|
||||
private final JPanel myMessagesPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
|
||||
|
||||
private double myZoomFactor = 1.0;
|
||||
private boolean myZoomToFit = true;
|
||||
@@ -70,16 +71,6 @@ public class AndroidLayoutPreviewPanel extends JPanel implements Disposable {
|
||||
setOpaque(true);
|
||||
myImagePanel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.GRAY));
|
||||
|
||||
myHyperlinkMessageLabel.addHyperlinkListener(new HyperlinkListener() {
|
||||
public void hyperlinkUpdate(final HyperlinkEvent e) {
|
||||
final Runnable quickFix = myErrorMessage.myQuickFix;
|
||||
if (quickFix != null && e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
quickFix.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
myHyperlinkMessageLabel.setOpaque(false);
|
||||
|
||||
myFileNameLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
myFileNameLabel.setBorder(new EmptyBorder(5, 0, 5, 0));
|
||||
|
||||
@@ -104,8 +95,10 @@ public class AndroidLayoutPreviewPanel extends JPanel implements Disposable {
|
||||
((CardLayout)myProgressIconWrapper.getLayout()).show(myProgressIconWrapper, EMPTY_CARD_NAME);
|
||||
|
||||
add(titlePanel);
|
||||
add(myHyperlinkMessageLabel);
|
||||
add(myMessageLabel);
|
||||
|
||||
myMessagesPanel.setBorder(IdeBorderFactory.createEmptyBorder(0, 5, 0, 5));
|
||||
myMessagesPanel.setOpaque(false);
|
||||
add(myMessagesPanel);
|
||||
|
||||
add(new MyImagePanelWrapper());
|
||||
}
|
||||
@@ -148,45 +141,83 @@ public class AndroidLayoutPreviewPanel extends JPanel implements Disposable {
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void setErrorMessage(@Nullable RenderingErrorMessage errorMessage) {
|
||||
public void setErrorMessage(@Nullable FixableIssueMessage errorMessage) {
|
||||
myErrorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public void setWarnMessage(String warnMessage) {
|
||||
myWarnMessage = warnMessage;
|
||||
public void setWarnMessages(@Nullable List<FixableIssueMessage> warnMessages) {
|
||||
myWarnMessages = warnMessages;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
myImagePanel.setVisible(true);
|
||||
|
||||
myHyperlinkMessageLabel.setVisible(false);
|
||||
myMessageLabel.setVisible(false);
|
||||
myMessagesPanel.removeAll();
|
||||
|
||||
if (myErrorMessage != null) {
|
||||
if (myErrorMessage.myLinkText.length() > 0 || myErrorMessage.myAfterLinkText.length() > 0) {
|
||||
myHyperlinkMessageLabel.setHyperlinkText(myErrorMessage.myBeforeLinkText,
|
||||
myErrorMessage.myLinkText,
|
||||
myErrorMessage.myAfterLinkText);
|
||||
myHyperlinkMessageLabel.setIcon(Messages.getErrorIcon());
|
||||
myHyperlinkMessageLabel.setVisible(true);
|
||||
}
|
||||
else {
|
||||
myMessageLabel.setText("<html><body>" + myErrorMessage.myBeforeLinkText.replace("\n", "<br>") + "</body></html>");
|
||||
myMessageLabel.setIcon(Messages.getErrorIcon());
|
||||
myMessageLabel.setVisible(true);
|
||||
showMessage(myErrorMessage, Messages.getErrorIcon());
|
||||
}
|
||||
if (myWarnMessages != null) {
|
||||
for (FixableIssueMessage warnMessage : myWarnMessages) {
|
||||
showMessage(warnMessage, Messages.getWarningIcon());
|
||||
}
|
||||
}
|
||||
|
||||
if (myErrorMessage == null && myWarnMessage != null && myWarnMessage.length() > 0) {
|
||||
myMessageLabel.setText("<html><body>" + myWarnMessage.replace("\n", "<br>") + "</body></html>");
|
||||
myMessageLabel.setIcon(Messages.getWarningIcon());
|
||||
myMessageLabel.setVisible(true);
|
||||
}
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void updateImageSize() {
|
||||
private void showMessage(final FixableIssueMessage message, Icon icon) {
|
||||
if (message.myLinkText.length() > 0 || message.myAfterLinkText.length() > 0) {
|
||||
final HyperlinkLabel warnLabel = new HyperlinkLabel();
|
||||
warnLabel.setOpaque(false);
|
||||
warnLabel.setHyperlinkText(message.myBeforeLinkText,
|
||||
message.myLinkText,
|
||||
message.myAfterLinkText);
|
||||
warnLabel.setIcon(icon);
|
||||
|
||||
warnLabel.addHyperlinkListener(new HyperlinkListener() {
|
||||
public void hyperlinkUpdate(final HyperlinkEvent e) {
|
||||
final Runnable quickFix = message.myQuickFix;
|
||||
if (quickFix != null && e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
quickFix.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
myMessagesPanel.add(warnLabel);
|
||||
}
|
||||
else {
|
||||
final JBLabel warnLabel = new JBLabel();
|
||||
warnLabel.setOpaque(false);
|
||||
warnLabel.setText("<html><body>" + message.myBeforeLinkText.replace("\n", "<br>") + "</body></html>");
|
||||
warnLabel.setIcon(icon);
|
||||
myMessagesPanel.add(warnLabel);
|
||||
}
|
||||
if (message.myAdditionalFixes.size() > 0) {
|
||||
final JPanel fixesPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
|
||||
fixesPanel.setBorder(IdeBorderFactory.createEmptyBorder(3, 0, 10, 0));
|
||||
fixesPanel.setOpaque(false);
|
||||
fixesPanel.add(Box.createHorizontalStrut(icon.getIconWidth()));
|
||||
|
||||
for (Pair<String, Runnable> pair : message.myAdditionalFixes) {
|
||||
final HyperlinkLabel fixLabel = new HyperlinkLabel();
|
||||
fixLabel.setOpaque(false);
|
||||
fixLabel.setHyperlinkText(pair.getFirst());
|
||||
final Runnable fix = pair.getSecond();
|
||||
|
||||
fixLabel.addHyperlinkListener(new HyperlinkListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(HyperlinkEvent e) {
|
||||
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
fix.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
fixesPanel.add(fixLabel);
|
||||
}
|
||||
myMessagesPanel.add(fixesPanel);
|
||||
}
|
||||
}
|
||||
|
||||
void updateImageSize() {
|
||||
if (myImage == null) {
|
||||
myImagePanel.setSize(0, 0);
|
||||
}
|
||||
|
||||
+10
-10
@@ -660,12 +660,12 @@ class AndroidLayoutPreviewToolWindowForm implements Disposable {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setErrorMessage(RenderingErrorMessage errorMessage) {
|
||||
public void setErrorMessage(FixableIssueMessage errorMessage) {
|
||||
myPreviewPanel.setErrorMessage(errorMessage);
|
||||
}
|
||||
|
||||
public void setWarnMessage(String warnMessage) {
|
||||
myPreviewPanel.setWarnMessage(warnMessage);
|
||||
public void setWarnMessage(List<FixableIssueMessage> warnMessages) {
|
||||
myPreviewPanel.setWarnMessages(warnMessages);
|
||||
}
|
||||
|
||||
public void setImage(@Nullable BufferedImage image, @NotNull String fileName) {
|
||||
@@ -682,13 +682,13 @@ class AndroidLayoutPreviewToolWindowForm implements Disposable {
|
||||
}
|
||||
|
||||
public void updateDevicesAndTargets(@Nullable AndroidPlatform platform) {
|
||||
final AndroidSdk sdkObject = platform != null ? platform.getSdk() : null;
|
||||
final AndroidSdkData sdkData = platform != null ? platform.getSdkData() : null;
|
||||
final LayoutDevice selectedDevice = getSelectedDevice();
|
||||
final String selectedDeviceName = selectedDevice != null ? selectedDevice.getName() : null;
|
||||
|
||||
final List<LayoutDevice> devices;
|
||||
if (sdkObject != null) {
|
||||
myLayoutDeviceManager.loadDevices(sdkObject);
|
||||
if (sdkData != null) {
|
||||
myLayoutDeviceManager.loadDevices(sdkData);
|
||||
devices = myLayoutDeviceManager.getCombinedList();
|
||||
}
|
||||
else {
|
||||
@@ -720,9 +720,9 @@ class AndroidLayoutPreviewToolWindowForm implements Disposable {
|
||||
IAndroidTarget newSelectedTarget = null;
|
||||
|
||||
final List<IAndroidTarget> targets;
|
||||
if (sdkObject != null) {
|
||||
if (sdkData != null) {
|
||||
targets = new ArrayList<IAndroidTarget>();
|
||||
for (IAndroidTarget target : sdkObject.getTargets()) {
|
||||
for (IAndroidTarget target : sdkData.getTargets()) {
|
||||
if (target.isPlatform()) {
|
||||
if (target.hashString().equals(selectedTargetHashString)) {
|
||||
newSelectedTarget = target;
|
||||
@@ -752,7 +752,7 @@ class AndroidLayoutPreviewToolWindowForm implements Disposable {
|
||||
}
|
||||
|
||||
if (modulePlatformHash != null) {
|
||||
targetFromModule = sdkObject.findTargetByHashString(modulePlatformHash);
|
||||
targetFromModule = sdkData.findTargetByHashString(modulePlatformHash);
|
||||
if (targetFromModule != null && targets.indexOf(targetFromModule) >= 0) {
|
||||
newSelectedTarget = targetFromModule;
|
||||
}
|
||||
@@ -917,7 +917,7 @@ class AndroidLayoutPreviewToolWindowForm implements Disposable {
|
||||
if (target == null) {
|
||||
target = androidPlatform.getTarget();
|
||||
}
|
||||
targetData = androidPlatform.getSdk().getTargetData(target);
|
||||
targetData = androidPlatform.getSdkData().getTargetData(target);
|
||||
}
|
||||
|
||||
if (targetData == null || targetData.areThemesCached()) {
|
||||
|
||||
+17
-15
@@ -66,6 +66,8 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -316,8 +318,8 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent {
|
||||
}
|
||||
|
||||
BufferedImage image = null;
|
||||
RenderingErrorMessage errorMessage = null;
|
||||
String warnMessage = null;
|
||||
FixableIssueMessage errorMessage = null;
|
||||
final List<FixableIssueMessage> warnMessages = new ArrayList<FixableIssueMessage>();
|
||||
|
||||
final String imgPath = FileUtil.getTempDirectory() + "/androidLayoutPreview.png";
|
||||
|
||||
@@ -358,14 +360,15 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent {
|
||||
final VirtualFile layoutXmlFile = psiFile.getVirtualFile();
|
||||
|
||||
synchronized (RENDERING_LOCK) {
|
||||
final StringBuilder warnBuilder = new StringBuilder();
|
||||
if (target != null && theme != null) {
|
||||
final RenderingResult result =
|
||||
RenderUtil.renderLayout(facet.getModule(), layoutXmlText, layoutXmlFile, imgPath, target, facet, config, xdpi, ydpi, theme);
|
||||
|
||||
if (target != null && theme != null &&
|
||||
RenderUtil.renderLayout(myProject, layoutXmlText, layoutXmlFile, imgPath,
|
||||
target, facet, config, xdpi, ydpi, theme, warnBuilder)) {
|
||||
warnMessage = warnBuilder.toString();
|
||||
if (result != null) {
|
||||
warnMessages.addAll(result.getWarnMessages());
|
||||
final File input = new File(imgPath);
|
||||
image = ImageIO.read(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,23 +377,23 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent {
|
||||
String message = e.getPresentableMessage();
|
||||
message = message != null ? message : AndroidBundle.message("android.layout.preview.default.error.message");
|
||||
final Throwable[] causes = e.getCauses();
|
||||
errorMessage = causes.length > 0 ? new RenderingErrorMessage(message + ' ', "Details", "", new Runnable() {
|
||||
errorMessage = causes.length > 0 ? new FixableIssueMessage(message + ' ', "Details", "", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showStackStace(causes);
|
||||
}
|
||||
}) : new RenderingErrorMessage(message);
|
||||
}) : new FixableIssueMessage(message);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
final String message = e.getMessage();
|
||||
errorMessage = new RenderingErrorMessage("I/O error" + (message != null ? ": " + message : ""));
|
||||
errorMessage = new FixableIssueMessage("I/O error" + (message != null ? ": " + message : ""));
|
||||
}
|
||||
catch (AndroidSdkNotConfiguredException e) {
|
||||
LOG.debug(e);
|
||||
|
||||
if (!AndroidMavenUtil.isMavenizedModule(facet.getModule())) {
|
||||
errorMessage = new RenderingErrorMessage("Please ", "configure", " Android SDK", new Runnable() {
|
||||
errorMessage = new FixableIssueMessage("Please ", "configure", " Android SDK", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
AndroidSdkUtils.openModuleDependenciesConfigurable(facet.getModule());
|
||||
@@ -398,13 +401,12 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent {
|
||||
});
|
||||
}
|
||||
else {
|
||||
errorMessage = new RenderingErrorMessage(AndroidBundle.message("android.maven.cannot.parse.android.sdk.error",
|
||||
errorMessage = new FixableIssueMessage(AndroidBundle.message("android.maven.cannot.parse.android.sdk.error",
|
||||
facet.getModule().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
final RenderingErrorMessage finalErrorMessage = errorMessage;
|
||||
final String finalWarnMessage = warnMessage;
|
||||
final FixableIssueMessage finalErrorMessage = errorMessage;
|
||||
final BufferedImage finalImage = image;
|
||||
|
||||
if (!myRenderingQueue.isEmpty()) {
|
||||
@@ -419,7 +421,7 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent {
|
||||
return;
|
||||
}
|
||||
myToolWindowForm.setErrorMessage(finalErrorMessage);
|
||||
myToolWindowForm.setWarnMessage(finalWarnMessage);
|
||||
myToolWindowForm.setWarnMessage(warnMessages);
|
||||
if (finalErrorMessage == null) {
|
||||
myToolWindowForm.setImage(finalImage, fileName);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.jetbrains.android.uipreview;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
class FixableIssueMessage {
|
||||
final String myBeforeLinkText;
|
||||
final String myLinkText;
|
||||
final String myAfterLinkText;
|
||||
final Runnable myQuickFix;
|
||||
final Collection<Pair<String, Runnable>> myAdditionalFixes;
|
||||
|
||||
FixableIssueMessage(@NotNull String beforeLinkText,
|
||||
@NotNull String linkText,
|
||||
@NotNull String afterLinkText,
|
||||
@Nullable Runnable quickFix) {
|
||||
myBeforeLinkText = beforeLinkText;
|
||||
myLinkText = linkText;
|
||||
myAfterLinkText = afterLinkText;
|
||||
myQuickFix = quickFix;
|
||||
myAdditionalFixes = Collections.emptyList();
|
||||
}
|
||||
|
||||
FixableIssueMessage(@NotNull String message) {
|
||||
this(message, "", "", null);
|
||||
}
|
||||
|
||||
FixableIssueMessage(@NotNull String message, @NotNull Collection<Pair<String, Runnable>> quickFixes) {
|
||||
myBeforeLinkText = message;
|
||||
myLinkText = "";
|
||||
myAfterLinkText = "";
|
||||
myQuickFix = null;
|
||||
myAdditionalFixes = quickFixes;
|
||||
}
|
||||
}
|
||||
+13
-1
@@ -1,7 +1,19 @@
|
||||
package org.jetbrains.android.uipreview;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class IncompatibleClassFileFormatException extends Exception {
|
||||
public class IncompatibleClassFileFormatException extends RuntimeException {
|
||||
private final String myClassName;
|
||||
|
||||
public IncompatibleClassFileFormatException(@NotNull String className) {
|
||||
myClassName = className;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getClassName() {
|
||||
return myClassName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import com.android.prefs.AndroidLocation.AndroidLocationException;
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.jetbrains.android.sdk.AndroidSdk;
|
||||
import org.jetbrains.android.sdk.AndroidSdkData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.w3c.dom.Document;
|
||||
@@ -149,13 +149,13 @@ public class LayoutDeviceManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void loadDevices(@NotNull AndroidSdk sdk) {
|
||||
loadDefaultAndUserDevices(sdk);
|
||||
loadAddOnLayoutDevices(sdk);
|
||||
public void loadDevices(@NotNull AndroidSdkData sdkData) {
|
||||
loadDefaultAndUserDevices(sdkData);
|
||||
loadAddOnLayoutDevices(sdkData);
|
||||
}
|
||||
|
||||
private void loadDefaultAndUserDevices(@NotNull AndroidSdk sdk) {
|
||||
loadDefaultLayoutDevices(sdk.getLocation());
|
||||
private void loadDefaultAndUserDevices(@NotNull AndroidSdkData sdkData) {
|
||||
loadDefaultLayoutDevices(sdkData.getLocation());
|
||||
|
||||
try {
|
||||
myUserLayoutDevices.clear();
|
||||
@@ -181,8 +181,8 @@ public class LayoutDeviceManager {
|
||||
combineLayoutDevices();
|
||||
}
|
||||
|
||||
private void loadAddOnLayoutDevices(@NotNull AndroidSdk sdk) {
|
||||
for (IAndroidTarget target : sdk.getTargets()) {
|
||||
private void loadAddOnLayoutDevices(@NotNull AndroidSdkData sdkData) {
|
||||
for (IAndroidTarget target : sdkData.getTargets()) {
|
||||
if (!target.isPlatform()) {
|
||||
File deviceXml = new File(target.getLocation(), SdkConstants.FN_DEVICES_XML);
|
||||
if (deviceXml.isFile()) {
|
||||
|
||||
@@ -23,14 +23,11 @@ import com.android.ide.common.resources.IntArrayWrapper;
|
||||
import com.android.resources.ResourceType;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.android.util.Pair;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import org.jetbrains.android.dom.manifest.Manifest;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -50,6 +47,7 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback {
|
||||
|
||||
private final Set<String> myMissingClasses = new TreeSet<String>();
|
||||
private final Map<String, Throwable> myBrokenClasses = new HashMap<String, Throwable>();
|
||||
private final Set<String> myClassesWithIncorrectFormat = new HashSet<String>();
|
||||
|
||||
private final Map<String, Class<?>> myLoadedClasses = new HashMap<String, Class<?>>();
|
||||
|
||||
@@ -113,9 +111,9 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback {
|
||||
return createNewInstance(aClass, constructorSignature, constructorArgs);
|
||||
}
|
||||
|
||||
aClass = loadClass(className);
|
||||
|
||||
try {
|
||||
aClass = loadClass(className);
|
||||
|
||||
if (aClass != null) {
|
||||
final Object viewObject = createNewInstance(aClass, constructorSignature, constructorArgs);
|
||||
myLoadedClasses.put(className, aClass);
|
||||
@@ -128,7 +126,14 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback {
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.info(e);
|
||||
myBrokenClasses.put(className, e.getCause());
|
||||
|
||||
final Throwable cause = e.getCause();
|
||||
if (cause instanceof IncompatibleClassFileFormatException) {
|
||||
myClassesWithIncorrectFormat.add(((IncompatibleClassFileFormatException)cause).getClassName());
|
||||
}
|
||||
else {
|
||||
myBrokenClasses.put(className, cause);
|
||||
}
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
LOG.info(e);
|
||||
@@ -142,6 +147,9 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback {
|
||||
LOG.info(e);
|
||||
myBrokenClasses.put(className, e.getCause());
|
||||
}
|
||||
catch (IncompatibleClassFileFormatException e) {
|
||||
myClassesWithIncorrectFormat.add(e.getClassName());
|
||||
}
|
||||
|
||||
try {
|
||||
return createMockView(className, constructorSignature, constructorArgs);
|
||||
@@ -167,7 +175,7 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Class<?> loadClass(String className) {
|
||||
private Class<?> loadClass(String className) throws IncompatibleClassFileFormatException {
|
||||
try {
|
||||
if (myProjectClassLoader == null) {
|
||||
myProjectClassLoader = new ProjectClassLoader(myParentClassLoader, myModule);
|
||||
@@ -181,11 +189,10 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (UnsupportedClassVersionError e) {
|
||||
LOG.info(e);
|
||||
myBrokenClasses.put(className, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasUnsupportedClassVersionProblem() {
|
||||
return myClassesWithIncorrectFormat.size() > 0;
|
||||
}
|
||||
|
||||
private Object createMockView(String className, Class[] constructorSignature, Object[] constructorArgs)
|
||||
@@ -221,6 +228,16 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback {
|
||||
return viewObject;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<String> getClassesWithIncorrectFormat() {
|
||||
return myClassesWithIncorrectFormat;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Module getModule() {
|
||||
return myModule;
|
||||
}
|
||||
|
||||
private static String getShortClassName(String fqcn) {
|
||||
if (fqcn.startsWith("android.")) {
|
||||
// android.foo.Name -> android...Name
|
||||
@@ -337,27 +354,21 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback {
|
||||
}
|
||||
|
||||
public void loadAndParseRClass() throws ClassNotFoundException, IncompatibleClassFileFormatException {
|
||||
final String className = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public String compute() {
|
||||
return getRClassName(myModule);
|
||||
}
|
||||
});
|
||||
if (className == null) {
|
||||
final String rClassName = RenderUtil.getRClassName(myModule);
|
||||
|
||||
if (rClassName == null) {
|
||||
LOG.info("loadAndParseRClass: failed to find manifest package for project %1$s");
|
||||
return;
|
||||
}
|
||||
loadAndParseRClass(rClassName);
|
||||
}
|
||||
|
||||
public void loadAndParseRClass(@NotNull String className) throws ClassNotFoundException, IncompatibleClassFileFormatException {
|
||||
Class<?> aClass = myLoadedClasses.get(className);
|
||||
if (aClass == null) {
|
||||
ProjectClassLoader loader = new ProjectClassLoader(null, myModule);
|
||||
try {
|
||||
aClass = loader.loadClass(className);
|
||||
}
|
||||
catch (UnsupportedClassVersionError e) {
|
||||
throw new IncompatibleClassFileFormatException();
|
||||
}
|
||||
aClass = loader.loadClass(className);
|
||||
|
||||
if (aClass != null) {
|
||||
myLoadedClasses.put(className, aClass);
|
||||
}
|
||||
@@ -414,20 +425,4 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getRClassName(Module module) {
|
||||
final AndroidFacet facet = AndroidFacet.getInstance(module);
|
||||
if (facet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Manifest manifest = facet.getManifest();
|
||||
if (manifest == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String aPackage = manifest.getPackage().getValue();
|
||||
return aPackage == null ? null : aPackage + ".R";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.roots.CompilerModuleExtension;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.android.facet.AndroidRootUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -17,6 +18,7 @@ import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
@@ -39,7 +41,26 @@ public final class ProjectClassLoader extends ClassLoader {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
|
||||
Class<?> aClass = loadClassFromModule(myModule, name);
|
||||
try {
|
||||
final Class<?> aClass = loadClassFromModuleOrDependency(myModule, name, new HashSet<Module>());
|
||||
if (aClass != null) {
|
||||
return aClass;
|
||||
}
|
||||
}
|
||||
catch (UnsupportedClassVersionError e) {
|
||||
throw new IncompatibleClassFileFormatException(name);
|
||||
}
|
||||
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Class<?> loadClassFromModuleOrDependency(Module module, String name, Set<Module> visited) {
|
||||
if (!visited.add(module)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> aClass = loadClassFromModule(module, name);
|
||||
if (aClass != null) {
|
||||
return aClass;
|
||||
}
|
||||
@@ -49,14 +70,13 @@ public final class ProjectClassLoader extends ClassLoader {
|
||||
return aClass;
|
||||
}
|
||||
|
||||
for (Module depModule : ModuleRootManager.getInstance(myModule).getDependencies(false)) {
|
||||
aClass = loadClassFromModule(depModule, name);
|
||||
for (Module depModule : ModuleRootManager.getInstance(module).getDependencies(false)) {
|
||||
aClass = loadClassFromModuleOrDependency(depModule, name, visited);
|
||||
if (aClass != null) {
|
||||
return aClass;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ClassNotFoundException(name);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -3,22 +3,41 @@ package org.jetbrains.android.uipreview;
|
||||
import com.android.ide.common.rendering.api.RenderResources;
|
||||
import com.android.ide.common.rendering.api.RenderSession;
|
||||
import com.android.ide.common.rendering.api.Result;
|
||||
import com.android.ide.common.resources.*;
|
||||
import com.android.ide.common.resources.ResourceDeltaKind;
|
||||
import com.android.ide.common.resources.ResourceFolder;
|
||||
import com.android.ide.common.resources.ResourceRepository;
|
||||
import com.android.ide.common.resources.ScanningContext;
|
||||
import com.android.ide.common.resources.configuration.FolderConfiguration;
|
||||
import com.android.ide.common.resources.configuration.VersionQualifier;
|
||||
import com.android.io.*;
|
||||
import com.android.io.IAbstractFile;
|
||||
import com.android.io.IAbstractFolder;
|
||||
import com.android.io.IAbstractResource;
|
||||
import com.android.io.StreamException;
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.intellij.compiler.impl.javaCompiler.javac.JavacSettings;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.CompilerManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ui.configuration.ClasspathEditor;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.android.dom.manifest.Application;
|
||||
import org.jetbrains.android.dom.manifest.Manifest;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
@@ -73,7 +92,7 @@ public class RenderUtil {
|
||||
|
||||
config.setVersionQualifier(new VersionQualifier(target.getVersion().getApiLevel()));
|
||||
|
||||
final RenderServiceFactory factory = platform.getSdk().getTargetData(target).getRenderServiceFactory(project);
|
||||
final RenderServiceFactory factory = platform.getSdkData().getTargetData(target).getRenderServiceFactory(project);
|
||||
if (factory == null) {
|
||||
throw new RenderingException(AndroidBundle.message("android.layout.preview.cannot.load.library.error"));
|
||||
}
|
||||
@@ -81,7 +100,7 @@ public class RenderUtil {
|
||||
final ProjectResources projectResources = new ProjectResources();
|
||||
|
||||
final VirtualFile[] resourceDirs = facet.getLocalResourceManager().getAllResourceDirs();
|
||||
final IAbstractFolder[] resFolders = toAbstractFolders(project, resourceDirs);
|
||||
final IAbstractFolder[] resFolders = toAbstractFolders(resourceDirs);
|
||||
|
||||
loadResources(projectResources, layoutXmlText, layoutXmlFile, resFolders);
|
||||
final int minSdkVersion = getMinSdkVersion(facet);
|
||||
@@ -109,18 +128,20 @@ public class RenderUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean renderLayout(@NotNull Project project,
|
||||
@NotNull String layoutXmlText,
|
||||
@Nullable VirtualFile layoutXmlFile,
|
||||
@NotNull String imgPath,
|
||||
@NotNull IAndroidTarget target,
|
||||
@NotNull AndroidFacet facet,
|
||||
@NotNull FolderConfiguration config,
|
||||
float xdpi,
|
||||
float ydpi,
|
||||
@NotNull ThemeData theme,
|
||||
StringBuilder warningBuilder)
|
||||
@Nullable
|
||||
public static RenderingResult renderLayout(@NotNull final Module module,
|
||||
@NotNull String layoutXmlText,
|
||||
@Nullable VirtualFile layoutXmlFile,
|
||||
@NotNull String imgPath,
|
||||
@NotNull IAndroidTarget target,
|
||||
@NotNull AndroidFacet facet,
|
||||
@NotNull FolderConfiguration config,
|
||||
float xdpi,
|
||||
float ydpi,
|
||||
@NotNull ThemeData theme)
|
||||
throws RenderingException, IOException, AndroidSdkNotConfiguredException {
|
||||
final Project project = module.getProject();
|
||||
|
||||
final Sdk sdk = ModuleRootManager.getInstance(facet.getModule()).getSdk();
|
||||
if (sdk == null || !(sdk.getSdkType() instanceof AndroidSdkType)) {
|
||||
throw new AndroidSdkNotConfiguredException();
|
||||
@@ -138,7 +159,7 @@ public class RenderUtil {
|
||||
|
||||
config.setVersionQualifier(new VersionQualifier(target.getVersion().getApiLevel()));
|
||||
|
||||
final RenderServiceFactory factory = platform.getSdk().getTargetData(target).getRenderServiceFactory(project);
|
||||
final RenderServiceFactory factory = platform.getSdkData().getTargetData(target).getRenderServiceFactory(project);
|
||||
if (factory == null) {
|
||||
throw new RenderingException(AndroidBundle.message("android.layout.preview.cannot.load.library.error"));
|
||||
}
|
||||
@@ -146,14 +167,17 @@ public class RenderUtil {
|
||||
final ProjectResources projectResources = new ProjectResources();
|
||||
|
||||
final VirtualFile[] resourceDirs = facet.getLocalResourceManager().getAllResourceDirs();
|
||||
final IAbstractFolder[] resFolders = toAbstractFolders(project, resourceDirs);
|
||||
final IAbstractFolder[] resFolders = toAbstractFolders(resourceDirs);
|
||||
|
||||
loadResources(projectResources, layoutXmlText, layoutXmlFile, resFolders);
|
||||
final int minSdkVersion = getMinSdkVersion(facet);
|
||||
String missingRClassMessage = null;
|
||||
boolean missingRClass = false;
|
||||
boolean incorrectRClassFormat = false;
|
||||
String rClassName = null;
|
||||
|
||||
final ProjectCallback callback = new ProjectCallback(factory.getLibrary(), facet.getModule(), projectResources);
|
||||
|
||||
try {
|
||||
callback.loadAndParseRClass();
|
||||
}
|
||||
@@ -164,8 +188,8 @@ public class RenderUtil {
|
||||
}
|
||||
catch (IncompatibleClassFileFormatException e) {
|
||||
LOG.debug(e);
|
||||
missingRClassMessage = "Incompatible R.class file format";
|
||||
missingRClass = true;
|
||||
incorrectRClassFormat = true;
|
||||
rClassName = e.getClassName();
|
||||
}
|
||||
|
||||
final RenderResources resolver =
|
||||
@@ -180,52 +204,34 @@ public class RenderUtil {
|
||||
throw new RenderingException(e);
|
||||
}
|
||||
if (session == null) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
final List<FixableIssueMessage> warnMessages = new ArrayList<FixableIssueMessage>();
|
||||
|
||||
if (callback.hasUnsupportedClassVersionProblem() || (incorrectRClassFormat && callback.hasLoadedClasses())) {
|
||||
reportIncorrectClassFormatWarning(callback, rClassName, incorrectRClassFormat, warnMessages);
|
||||
}
|
||||
|
||||
if (missingRClass && callback.hasLoadedClasses()) {
|
||||
warningBuilder.append(missingRClassMessage != null && missingRClassMessage.length() > 0
|
||||
? ("Class not found error: " + missingRClassMessage + ".")
|
||||
: "R class not found.")
|
||||
.append(" Try to build project\n");
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append(missingRClassMessage != null && missingRClassMessage.length() > 0
|
||||
? ("Class not found error: " + missingRClassMessage + ".")
|
||||
: "R class not found.")
|
||||
.append(" Try to build project");
|
||||
warnMessages.add(new FixableIssueMessage(builder.toString()));
|
||||
}
|
||||
|
||||
final Set<String> missingClasses = callback.getMissingClasses();
|
||||
if (missingClasses.size() > 0) {
|
||||
if (missingClasses.size() > 1) {
|
||||
warningBuilder.append("Missing classes:\n");
|
||||
for (String missingClass : missingClasses) {
|
||||
warningBuilder.append(" ").append(missingClass).append('\n');
|
||||
}
|
||||
}
|
||||
else {
|
||||
warningBuilder.append("Missing class ").append(missingClasses.iterator().next()).append('\n');
|
||||
}
|
||||
}
|
||||
reportMissingClassesWarning(warnMessages, callback.getMissingClasses());
|
||||
|
||||
final Map<String, Throwable> brokenClasses = callback.getBrokenClasses();
|
||||
if (brokenClasses.size() > 0) {
|
||||
if (brokenClasses.size() > 1) {
|
||||
warningBuilder.append("Unable to initialize:\n");
|
||||
for (String brokenClass : brokenClasses.keySet()) {
|
||||
warningBuilder.append(" ").append(brokenClass).append('\n');
|
||||
}
|
||||
}
|
||||
else {
|
||||
warningBuilder.append("Unable to initialize ").append(brokenClasses.keySet().iterator().next());
|
||||
}
|
||||
}
|
||||
|
||||
if (warningBuilder.length() > 0 && warningBuilder.charAt(warningBuilder.length() - 1) == '\n') {
|
||||
warningBuilder.deleteCharAt(warningBuilder.length() - 1);
|
||||
}
|
||||
reportBrokenClassesWarning(warnMessages, callback.getBrokenClasses());
|
||||
|
||||
final Result result = session.getResult();
|
||||
if (!result.isSuccess()) {
|
||||
final Throwable exception = result.getException();
|
||||
|
||||
if (exception != null) {
|
||||
final List<Throwable> exceptionsFromWarnings = getNonNullValues(brokenClasses);
|
||||
final List<Throwable> exceptionsFromWarnings = getNonNullValues(callback.getBrokenClasses());
|
||||
|
||||
if (exceptionsFromWarnings.size() > 0 &&
|
||||
exception instanceof ClassCastException &&
|
||||
@@ -240,13 +246,215 @@ public class RenderUtil {
|
||||
LOG.info(message);
|
||||
throw new RenderingException();
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
final String format = FileUtil.getExtension(imgPath);
|
||||
ImageIO.write(session.getImage(), format, new File(imgPath));
|
||||
|
||||
return true;
|
||||
return new RenderingResult(warnMessages);
|
||||
}
|
||||
|
||||
private static void reportBrokenClassesWarning(@NotNull List<FixableIssueMessage> warnMessages,
|
||||
@NotNull Map<String, Throwable> brokenClasses) {
|
||||
if (brokenClasses.size() > 0) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
if (brokenClasses.size() > 1) {
|
||||
builder.append("Unable to initialize:\n");
|
||||
for (String brokenClass : brokenClasses.keySet()) {
|
||||
builder.append(" ").append(brokenClass).append('\n');
|
||||
}
|
||||
}
|
||||
else {
|
||||
builder.append("Unable to initialize ").append(brokenClasses.keySet().iterator().next());
|
||||
}
|
||||
removeLastNewLineChar(builder);
|
||||
warnMessages.add(new FixableIssueMessage(builder.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportMissingClassesWarning(@NotNull List<FixableIssueMessage> warnMessages,
|
||||
@NotNull Set<String> missingClasses) {
|
||||
if (missingClasses.size() > 0) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
if (missingClasses.size() > 1) {
|
||||
builder.append("Missing classes:\n");
|
||||
for (String missingClass : missingClasses) {
|
||||
builder.append(" ").append(missingClass).append('\n');
|
||||
}
|
||||
}
|
||||
else {
|
||||
builder.append("Missing class ").append(missingClasses.iterator().next());
|
||||
}
|
||||
removeLastNewLineChar(builder);
|
||||
warnMessages.add(new FixableIssueMessage(builder.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportIncorrectClassFormatWarning(@NotNull ProjectCallback callback,
|
||||
@Nullable String rClassName,
|
||||
boolean incorrectRClassFormat,
|
||||
@NotNull List<FixableIssueMessage> warnMessages) {
|
||||
final Module module = callback.getModule();
|
||||
final Project project = module.getProject();
|
||||
final List<Module> problemModules = getProblemModules(module);
|
||||
final StringBuilder builder = new StringBuilder("Preview can be incorrect: unsupported classes version");
|
||||
final List<Pair<String, Runnable>> quickFixes = new ArrayList<Pair<String, Runnable>>();
|
||||
|
||||
if (problemModules.size() > 0) {
|
||||
quickFixes.add(new Pair<String, Runnable>("Rebuild project with '-target 1.6'", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final JavacSettings settings = JavacSettings.getInstance(project);
|
||||
if (settings.ADDITIONAL_OPTIONS_STRING.length() > 0) {
|
||||
settings.ADDITIONAL_OPTIONS_STRING += ' ';
|
||||
}
|
||||
settings.ADDITIONAL_OPTIONS_STRING += "-target 1.6";
|
||||
CompilerManager.getInstance(project).rebuild(null);
|
||||
}
|
||||
}));
|
||||
|
||||
quickFixes.add(new Pair<String, Runnable>("Change Java SDK to 1.5/1.6", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Set<String> sdkNames = getSdkNamesFromModules(problemModules);
|
||||
|
||||
if (sdkNames.size() == 1) {
|
||||
final Sdk sdk = ProjectJdkTable.getInstance().findJdk(sdkNames.iterator().next());
|
||||
|
||||
if (sdk != null && sdk.getSdkType() instanceof AndroidSdkType) {
|
||||
final ProjectStructureConfigurable config = ProjectStructureConfigurable.getInstance(project);
|
||||
|
||||
if (ShowSettingsUtil.getInstance().editConfigurable(project, config, new Runnable() {
|
||||
public void run() {
|
||||
config.select(sdk, true);
|
||||
}
|
||||
})) {
|
||||
askAndRebuild(project);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final String moduleToSelect = problemModules.size() > 0
|
||||
? problemModules.iterator().next().getName()
|
||||
: null;
|
||||
if (ModulesConfigurator.showDialog(project, moduleToSelect, ClasspathEditor.NAME)) {
|
||||
askAndRebuild(project);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
final Set<String> classesWithIncorrectFormat = new HashSet<String>(callback.getClassesWithIncorrectFormat());
|
||||
if (incorrectRClassFormat && rClassName != null) {
|
||||
classesWithIncorrectFormat.add(rClassName);
|
||||
}
|
||||
if (classesWithIncorrectFormat.size() > 0) {
|
||||
quickFixes.add(new Pair<String, Runnable>("Details", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showClassesWithIncorrectFormat(project, classesWithIncorrectFormat);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
builder.append("\nFollowing modules are built with incompatible JDK: ");
|
||||
|
||||
for (Iterator<Module> it = problemModules.iterator(); it.hasNext(); ) {
|
||||
Module problemModule = it.next();
|
||||
builder.append(problemModule.getName());
|
||||
if (it.hasNext()) {
|
||||
builder.append(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
warnMessages.add(new FixableIssueMessage(builder.toString(), quickFixes));
|
||||
}
|
||||
|
||||
private static void showClassesWithIncorrectFormat(@NotNull Project project, @NotNull Set<String> classesWithIncorrectFormat) {
|
||||
final StringBuilder builder = new StringBuilder("Classes with incompatible format:\n");
|
||||
|
||||
for (Iterator<String> it = classesWithIncorrectFormat.iterator(); it.hasNext(); ) {
|
||||
builder.append(" ").append(it.next());
|
||||
|
||||
if (it.hasNext()) {
|
||||
builder.append('\n');
|
||||
}
|
||||
}
|
||||
Messages.showInfoMessage(project, builder.toString(), "Unsupported class version");
|
||||
}
|
||||
|
||||
private static void askAndRebuild(Project project) {
|
||||
final int r =
|
||||
Messages.showYesNoDialog(project, "You have to rebuild project to see fixed preview. Would you like to do it?",
|
||||
"Rebuild project", Messages.getQuestionIcon());
|
||||
if (r == Messages.YES) {
|
||||
CompilerManager.getInstance(project).rebuild(null);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<String> getSdkNamesFromModules(@NotNull Collection<Module> modules) {
|
||||
final Set<String> result = new HashSet<String>();
|
||||
|
||||
for (Module module : modules) {
|
||||
final Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
|
||||
|
||||
if (sdk != null) {
|
||||
result.add(sdk.getName());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<Module> getProblemModules(@NotNull Module root) {
|
||||
final List<Module> result = new ArrayList<Module>();
|
||||
collectProblemModules(root, new HashSet<Module>(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void collectProblemModules(@NotNull Module module, @NotNull Set<Module> visited, @NotNull Collection<Module> result) {
|
||||
if (!visited.add(module)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBuiltByJdk7OrHigher(module)) {
|
||||
result.add(module);
|
||||
}
|
||||
|
||||
for (Module depModule : ModuleRootManager.getInstance(module).getDependencies(false)) {
|
||||
collectProblemModules(depModule, visited, result);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isBuiltByJdk7OrHigher(@NotNull Module module) {
|
||||
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
|
||||
|
||||
if (sdk == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sdk.getSdkType() instanceof AndroidSdkType) {
|
||||
final AndroidSdkAdditionalData data = (AndroidSdkAdditionalData)sdk.getSdkAdditionalData();
|
||||
|
||||
if (data != null) {
|
||||
final Sdk jdk = data.getJavaSdk();
|
||||
|
||||
if (jdk != null) {
|
||||
sdk = jdk;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sdk.getSdkType() instanceof JavaSdk &&
|
||||
JavaSdk.getInstance().isOfVersionOrHigher(sdk, JavaSdkVersion.JDK_1_7);
|
||||
}
|
||||
|
||||
private static void removeLastNewLineChar(StringBuilder builder) {
|
||||
if (builder.length() > 0 && builder.charAt(builder.length() - 1) == '\n') {
|
||||
builder.deleteCharAt(builder.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -283,6 +491,7 @@ public class RenderUtil {
|
||||
|
||||
private static int getMinSdkVersion(final AndroidFacet facet) {
|
||||
final XmlTag manifestTag = ApplicationManager.getApplication().runReadAction(new Computable<XmlTag>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public XmlTag compute() {
|
||||
final Manifest manifest = facet.getManifest();
|
||||
@@ -301,7 +510,7 @@ public class RenderUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static IAbstractFolder[] toAbstractFolders(@NotNull Project project, @NotNull VirtualFile[] folders) {
|
||||
private static IAbstractFolder[] toAbstractFolders(@NotNull VirtualFile[] folders) {
|
||||
final IAbstractFolder[] result = new IAbstractFolder[folders.length];
|
||||
|
||||
for (int i = 0; i < folders.length; i++) {
|
||||
@@ -329,15 +538,15 @@ public class RenderUtil {
|
||||
|
||||
if (resFolder != null) {
|
||||
for (final IAbstractResource childRes : folder.listMembers()) {
|
||||
|
||||
|
||||
if (childRes instanceof IAbstractFile) {
|
||||
final VirtualFile vFile;
|
||||
|
||||
if (childRes instanceof BufferingFileWrapper) {
|
||||
if (childRes instanceof BufferingFileWrapper) {
|
||||
final BufferingFileWrapper fileWrapper = (BufferingFileWrapper)childRes;
|
||||
final String filePath = FileUtil.toSystemIndependentName(fileWrapper.getOsLocation());
|
||||
vFile = LocalFileSystem.getInstance().findFileByPath(filePath);
|
||||
|
||||
|
||||
if (vFile != null && vFile == layoutXmlFile && layoutXmlFileText != null) {
|
||||
resFolder.processFile(new MyFileWrapper(layoutXmlFileText, childRes), ResourceDeltaKind.ADDED, scanningContext);
|
||||
}
|
||||
@@ -372,6 +581,28 @@ public class RenderUtil {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getRClassName(@NotNull final Module module) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public String compute() {
|
||||
final AndroidFacet facet = AndroidFacet.getInstance(module);
|
||||
if (facet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Manifest manifest = facet.getManifest();
|
||||
if (manifest == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String aPackage = manifest.getPackage().getValue();
|
||||
return aPackage == null ? null : aPackage + ".R";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class MyFileWrapper implements IAbstractFile {
|
||||
private final String myLayoutXmlFileText;
|
||||
private final IAbstractResource myChildRes;
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.jetbrains.android.uipreview;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
class RenderingErrorMessage {
|
||||
final String myBeforeLinkText;
|
||||
final String myLinkText;
|
||||
final String myAfterLinkText;
|
||||
final Runnable myQuickFix;
|
||||
|
||||
RenderingErrorMessage(@NotNull String beforeLinkText,
|
||||
@NotNull String linkText,
|
||||
@NotNull String afterLinkText,
|
||||
@Nullable Runnable quickFix) {
|
||||
myBeforeLinkText = beforeLinkText;
|
||||
myLinkText = linkText;
|
||||
myAfterLinkText = afterLinkText;
|
||||
myQuickFix = quickFix;
|
||||
}
|
||||
|
||||
RenderingErrorMessage(@NotNull String message) {
|
||||
this(message, "", "", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.jetbrains.android.uipreview;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class RenderingResult {
|
||||
private final List<FixableIssueMessage> myWarnMessages;
|
||||
|
||||
public RenderingResult(@NotNull List<FixableIssueMessage> warnMessages) {
|
||||
myWarnMessages = warnMessages;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<FixableIssueMessage> getWarnMessages() {
|
||||
return myWarnMessages;
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
import com.intellij.util.PathUtil;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.facet.AndroidFacetConfiguration;
|
||||
import org.jetbrains.android.sdk.AndroidSdk;
|
||||
import org.jetbrains.android.sdk.AndroidSdkData;
|
||||
import org.jetbrains.android.sdk.AndroidSdkAdditionalData;
|
||||
import org.jetbrains.android.sdk.AndroidSdkType;
|
||||
import org.jetbrains.android.sdk.EmptySdkLog;
|
||||
@@ -156,8 +156,8 @@ public abstract class AndroidTestCase extends JavaCodeInsightFixtureTestCase {
|
||||
sdkModificator.addRoot(resFolder, OrderRootType.CLASSES);
|
||||
|
||||
AndroidSdkAdditionalData data = new AndroidSdkAdditionalData(sdk);
|
||||
AndroidSdk sdkObject = AndroidSdk.parse(sdkPath, new EmptySdkLog());
|
||||
data.setBuildTarget(sdkObject.findTargetByName("Android 1.5"));
|
||||
AndroidSdkData sdkData = AndroidSdkData.parse(sdkPath, new EmptySdkLog());
|
||||
data.setBuildTarget(sdkData.findTargetByName("Android 1.5"));
|
||||
sdkModificator.setSdkAdditionalData(data);
|
||||
sdkModificator.commitChanges();
|
||||
return sdk;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user