Merge remote-tracking branch 'origin/master'

Conflicts:
	plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java
This commit is contained in:
Alexander Lobas
2012-02-22 23:38:25 +04:00
133 changed files with 1812 additions and 924 deletions
@@ -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
@@ -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;
}
@@ -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;
}
}
@@ -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");
@@ -0,0 +1,6 @@
// "Change to 'appendable.append(1)'" "true"
class Test {
void appendable(StringBuilder appendable) throws IOException {
appendable.append(1);
}
}
@@ -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(" ");
}
}
@@ -0,0 +1,6 @@
// "Change to 'appendable.append(1)'" "true"
class Test {
void appendable(StringBuilder appendable) throws IOException {
appendab<caret>le += 1;
}
}
@@ -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 + " ";
}
}
@@ -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();
}
@@ -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 {
@@ -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() {
@@ -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;
}
}
@@ -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
@@ -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
@@ -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\".*");
@@ -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";
}
}
@@ -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();
}
@@ -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
@@ -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)) {
@@ -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();
@@ -0,0 +1,8 @@
package com.siyeh.igfixes.performance.replace_with_isempty;
public class NullCheck {
void foo(String s) {
if (s != null && s.isEmpty()) {}
}
}
@@ -0,0 +1,8 @@
package com.siyeh.igfixes.performance.replace_with_isempty;
public class NullCheck {
void foo(String s) {
if ("".eq<caret>uals(s)) {}
}
}
@@ -0,0 +1,9 @@
package com.siyeh.igfixes.performance.replace_with_isempty;
public class Simple {
void foo(String s) {
if (s.isEmpty()) {}
}
}
@@ -0,0 +1,9 @@
package com.siyeh.igfixes.performance.replace_with_isempty;
public class Simple {
void foo(String s) {
if (s.eq<caret>uals("")) {}
}
}
@@ -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"));
}
*/
}
@@ -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 &lt;code&gt;StringBuffer.append()&lt;/code&gt; 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 &lt;code&gt;StringBuffer.append()&lt;/code&gt; 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 &lt;code&gt;StringBuilder.append()&lt;/code&gt; 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 &lt;code&gt;StringBuilder.append()&lt;/code&gt; call #loc</description>
</problem>
</problems>
@@ -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(); }
}
@@ -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());
}
}
@@ -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,
@@ -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;
@@ -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();
@@ -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);
}
}
@@ -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()) {
@@ -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);
}
@@ -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()) {
@@ -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;
}
}
@@ -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("&nbsp; &nbsp; &nbsp; &nbsp;").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("&nbsp; &nbsp; &nbsp; &nbsp;").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